import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import {Observable, Subject} from 'rxjs'; import { GlobalConstants } from '../global-constants'; import SockJS from 'sockjs-client'; import { Client, IMessage } from '@stomp/stompjs'; // Унифицируем название интерфейса для списка контейнеров export interface DockerContainer { id: string; name: string; image: string; state: string; // running, exited, etc. status: string; // Up 2 hours, etc. } // Интерфейс Project в соответствии с Project.java[cite: 3] export interface Project { id: string; name: string; user?: any; // Соответствует полю private User user в Java[cite: 3] status: string; localPath: string; createdAt: Date; containers?: DockerContainer[]; } export interface ProjectCreateRequest { name: string; rawComposeContent: string; } export interface ProjectDetailResponse { project: Project; config: { projectId: string; rawComposeContent: string; envVariables: { [key: string]: string }; }; } @Injectable({ providedIn: 'root' }) export class ProjectService { // Используем baseUrl, как определено в начале класса private baseUrl = GlobalConstants.API_URL; private stompClient: Client | null = null; constructor(private http: HttpClient) {} // Создание нового проекта[cite: 4, 5] createProject(request: ProjectCreateRequest): Observable { return this.http.post(`${this.baseUrl}/user/projects`, request); } // Методы для Dashboard[cite: 4, 5] getUserProjects(): Observable { return this.http.get(`${this.baseUrl}/user/projects`); } getProjectDetails(id: string): Observable { return this.http.get(`${this.baseUrl}/user/projects/${id}/details`); } // Управление жизненным циклом (Docker Compose)[cite: 3, 4] deployProject(id: string): Observable { return this.http.post(`${this.baseUrl}/user/projects/${id}/deploy`, {}, { responseType: 'text' }); } stopProject(id: string): Observable { return this.http.post(`${this.baseUrl}/user/projects/${id}/stop`, {}, { responseType: 'text' }); } deleteProject(id: string): Observable { return this.http.delete(`${this.baseUrl}/user/projects/${id}`); } // Администрирование[cite: 4] getAllProjectsAdmin(): Observable { return this.http.get(`${this.baseUrl}/admin/projects/all`); } // WebSocket для трансляции логов в реальном времени[cite: 3, 5] public connectToDockerLogs(containerId: string): Observable { const logSubject = new Subject(); // Твой эндпоинт из WebSocketConfig.java const socket = new SockJS(`${this.baseUrl}/ws-jambotron`); this.stompClient = new Client({ webSocketFactory: () => socket, debug: (str) => console.log(str), onConnect: () => { // 1. Подписываемся на логи конкретного контейнера this.stompClient?.subscribe(`/topic/logs/${containerId}`, (message: IMessage) => { logSubject.next(message.body); }); // 2. Отправляем сигнал бэкенду начать стриминг (согласно LogController) this.stompClient?.publish({ destination: '/app/start-logs', body: containerId }); }, onStompError: (frame) => { logSubject.error('Broker error: ' + frame.headers['message']); } }); this.stompClient.activate(); return logSubject.asObservable(); } public disconnectLogs(): void { if (this.stompClient) { this.stompClient.deactivate(); } } // ИСПРАВЛЕНО: возвращаем DockerContainer и используем правильный baseUrl[cite: 5] getProjectContainers(projectId: string): Observable { return this.http.get(`${this.baseUrl}/user/projects/${projectId}/containers`); } }