-
Настройка шлюза
-
-
-
}
diff --git a/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.scss b/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.scss
index 0efe77b..ba6a14e 100644
--- a/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.scss
+++ b/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.scss
@@ -104,3 +104,19 @@
overflow-y: auto;
}
}
+
+.mat-mdc-form-field {
+ width: 100%;
+ --mdc-outlined-text-field-container-shape: 6px;
+ --mdc-outlined-text-field-input-text-color: #e5e7eb;
+ --mdc-outlined-text-field-focus-input-text-color: #ffffff;
+ --mdc-outlined-text-field-label-text-color: #6b7280;
+ --mdc-outlined-text-field-focus-label-text-color: #3b82f6;
+ --mdc-outlined-text-field-outline-color: #1f2937;
+ --mdc-outlined-text-field-focus-outline-color: #2563eb;
+
+ .mat-mdc-text-field-wrapper {
+ background-color: rgba(3, 7, 18, 0.6) !important; // Глубокий тёмный фон bg-gray-950
+ }
+}
+
diff --git a/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.ts b/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.ts
index fd38113..5d638ef 100644
--- a/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.ts
+++ b/jambotron-ui/src/app/modules/user-module/project-details.component/project-details.component.ts
@@ -16,6 +16,8 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatDividerModule } from '@angular/material/divider';
import { MatCard, MatCardContent } from '@angular/material/card';
import {FormsModule} from '@angular/forms';
+import {MatInputModule} from '@angular/material/input';
+import {MatFormFieldModule} from '@angular/material/form-field';
@Component({
selector: 'app-project-details',
@@ -28,7 +30,9 @@ import {FormsModule} from '@angular/forms';
MatProgressSpinnerModule,
MatDividerModule,
MatCard,
- MatCardContent
+ MatCardContent,
+ MatFormFieldModule, // <-- Включаем в сборку созидания
+ MatInputModule // <-- Включаем в сборку созидания
],
templateUrl: './project-details.component.html',
styleUrls: ['./project-details.component.scss']
@@ -252,19 +256,18 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
// Хранит состояние редактирования для каждого контейнера: { [containerId]: boolean }
editingDomains: { [key: string]: boolean } = {};
- // Временные переменные для хранения ввода пользователя во время редактирования
+ // Временные переменные для хранения ввода пользователя во время инлайн-редактирования
tempSubdomain: string = '';
tempPort: number = 80;
/**
- * Извлекает имя сервиса (например, 'web') из полного имени Docker-контейнера
+ * Безопасно извлекает имя сервиса (например, 'web') из имени Docker-контейнера.
+ * Проверяет префиксы как по ID, так и по Name проекта.
*/
getServiceName(containerName: string): string | null {
- if (!containerName || !this.project?.id) return null;
+ if (!containerName || !this.project) return null;
- // Проверяем префикс по ID проекта
const prefixId = `jambotron-${this.project.id}-`;
- // Резервный префикс по имени проекта (на случай, если бэкенд использует его)
const prefixName = `jambotron-${this.project.name}-`;
let servicePart = '';
@@ -274,7 +277,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
} else if (containerName.startsWith(prefixName)) {
servicePart = containerName.substring(prefixName.length);
} else {
- // Фолбэк-разбор для коротких имён, если префиксы не подошли
+ // Резервный разбор по токенам (jambotron-проект-сервис)
const parts = containerName.split('-');
if (parts.length >= 3 && parts[0] === 'jambotron') {
servicePart = parts.slice(2).join('-');
@@ -283,7 +286,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
}
}
- // Отрезаем индекс реплики Compose (например, "-1")
+ // Отрезаем индекс реплики Docker Compose (например, "-1")
if (servicePart.endsWith('-1')) {
servicePart = servicePart.substring(0, servicePart.length - 2);
}
@@ -291,7 +294,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
}
/**
- * Возвращает текущий сформированный домен для отображения
+ * Возвращает текущий сформированный домен для вывода в UI
*/
getContainerDomain(containerName: string): string | null {
const serviceName = this.getServiceName(containerName);
@@ -302,7 +305,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
}
/**
- * Возвращает текущий порт сервиса
+ * Возвращает порт сервиса из конфигурации MongoDB
*/
getContainerPort(containerName: string): number {
const serviceName = this.getServiceName(containerName);
@@ -313,28 +316,31 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
}
/**
- * Вход в режим редактирования плашки
+ * Активация режима редактирования. Теперь полностью безопасна.
*/
startEditDomain(container: any) {
const serviceName = this.getServiceName(container.name);
- if (!serviceName) return;
+ if (!serviceName) {
+ console.warn(`[Jambotron] Не удалось определить имя сервиса для: ${container.name}`);
+ return;
+ }
+ // Переключаем реактивный флаг видимости формы в шаблоне
this.editingDomains[container.id] = true;
- // Инициализируем временные переменные текущими значениями из Mongo конфигурации
+ // Подтягиваем текущие сохранённые значения из локального объекта конфигурации config
const currentConfig = this.config?.serviceConfigs?.[serviceName];
this.tempSubdomain = currentConfig?.subdomain || '';
this.tempPort = currentConfig?.port || 80;
}
/**
- * Сохранение изменённого домена и порта на бэкенд
+ * Сохранение изменённого поддомена и порта в MongoDB базы данных
*/
saveDomainConfig(container: any) {
const serviceName = this.getServiceName(container.name);
if (!serviceName || !this.project?.id || !this.config) return;
- // Гарантируем существование мапы конфигураций
if (!this.config.serviceConfigs) {
this.config.serviceConfigs = {};
}
@@ -342,7 +348,7 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
const subdomainClean = this.tempSubdomain.trim().toLowerCase();
if (!subdomainClean) {
- // Если поддомен стёрли — удаляем настройку проксирования для этого сервиса
+ // Если поле очищено — удаляем проксирование
delete this.config.serviceConfigs[serviceName];
} else {
this.config.serviceConfigs[serviceName] = {
@@ -351,15 +357,16 @@ export class ProjectDetailsComponent implements OnInit, OnDestroy, AfterViewChec
};
}
- // Отправляем монолитный конфиг в базу MongoDB через твой сохранённый сервис
+ // Отправка монолитного конфига на бэкенд через твой рабочий ProjectService
this.projectService.updateProjectConfig(this.project.id, this.config).subscribe({
next: (updatedConfig) => {
this.config = updatedConfig;
this.editingDomains[container.id] = false;
- console.log(`Конфигурация Caddy для ${serviceName} успешно зафиксирована.`);
+ console.log(`[Caddy] Маршрут для сервиса ${serviceName} успешно сохранён.`);
},
error: (err) => {
- alert(err.error?.message || 'Ошибка валидации доменного имени.');
+ console.error('Ошибка обновления конфигурации проекта:', err);
+ alert(err.error?.message || 'Не удалось применить конфигурацию шлюза.');
}
});
}
diff --git a/src/main/java/com/jambotronGroup/jambotron/projects/ProjectService.java b/src/main/java/com/jambotronGroup/jambotron/projects/ProjectService.java
index 3b438a0..201c8a7 100644
--- a/src/main/java/com/jambotronGroup/jambotron/projects/ProjectService.java
+++ b/src/main/java/com/jambotronGroup/jambotron/projects/ProjectService.java
@@ -155,12 +155,13 @@ public class ProjectService {
try {
Files.createDirectories(projectPath);
- // Записываем уже модифицированный файл со всеми доменами
+ // Записываем модифицированный файл со всеми доменами
Files.writeString(projectPath.resolve("docker-compose.yml"), finalComposeContent);
logToConsole(projectId, "Конфигурация Caddy подготовлена. Запуск контейнеров...");
- ProcessBuilder pb = new ProcessBuilder("docker", "compose", "up", "-d", "--remove-orphans");
+ // Добавляем --force-recreate, чтобы Docker гарантированно применил новые labels!
+ ProcessBuilder pb = new ProcessBuilder("docker", "compose", "up", "-d", "--force-recreate", "--remove-orphans");
pb.directory(projectPath.toFile());
Process process = pb.start();