feat(ssl): Add domain & certificate management, Cloudflare sync, SQLite cert manager, WebSocket realtime updates, and HTTP API SSL endpoints
This commit is contained in:
@@ -110,22 +110,26 @@ import { ApiService, SystemStatus } from '../../core/services/api.service';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nginx -->
|
||||
<!-- Reverse Proxy -->
|
||||
<div class="card">
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4">Nginx</h3>
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-4">Reverse Proxy</h3>
|
||||
<div class="space-y-2">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm text-gray-600">Status</span>
|
||||
<span [ngClass]="status()!.nginx.status === 'running' ? 'badge-success' : 'badge-danger'" class="badge">
|
||||
{{ status()!.nginx.status }}
|
||||
<span class="text-sm text-gray-600">HTTP (Port {{ status()!.reverseProxy.http.port }})</span>
|
||||
<span [ngClass]="status()!.reverseProxy.http.running ? 'badge-success' : 'badge-danger'" class="badge">
|
||||
{{ status()!.reverseProxy.http.running ? 'Running' : 'Stopped' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm text-gray-600">Installed</span>
|
||||
<span [ngClass]="status()!.nginx.installed ? 'badge-success' : 'badge-danger'" class="badge">
|
||||
{{ status()!.nginx.installed ? 'Yes' : 'No' }}
|
||||
<span class="text-sm text-gray-600">HTTPS (Port {{ status()!.reverseProxy.https.port }})</span>
|
||||
<span [ngClass]="status()!.reverseProxy.https.running ? 'badge-success' : 'badge-danger'" class="badge">
|
||||
{{ status()!.reverseProxy.https.running ? 'Running' : 'Stopped' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm text-gray-600">SSL Certificates</span>
|
||||
<span class="badge badge-info">{{ status()!.reverseProxy.https.certificates }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component, OnInit, inject, signal } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, inject, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { ApiService, Service } from '../../core/services/api.service';
|
||||
import { WebSocketService } from '../../core/services/websocket.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-services-list',
|
||||
@@ -89,14 +91,42 @@ import { ApiService, Service } from '../../core/services/api.service';
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class ServicesListComponent implements OnInit {
|
||||
export class ServicesListComponent implements OnInit, OnDestroy {
|
||||
private apiService = inject(ApiService);
|
||||
private wsService = inject(WebSocketService);
|
||||
private wsSubscription?: Subscription;
|
||||
|
||||
services = signal<Service[]>([]);
|
||||
loading = signal(true);
|
||||
|
||||
ngOnInit(): void {
|
||||
// Initial load
|
||||
this.loadServices();
|
||||
|
||||
// Subscribe to WebSocket updates
|
||||
this.wsSubscription = this.wsService.getMessages().subscribe((message) => {
|
||||
this.handleWebSocketMessage(message);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.wsSubscription?.unsubscribe();
|
||||
}
|
||||
|
||||
private handleWebSocketMessage(message: any): void {
|
||||
if (message.type === 'service_update') {
|
||||
// Reload the full service list on any service update
|
||||
this.loadServices();
|
||||
} else if (message.type === 'service_status') {
|
||||
// Update individual service status
|
||||
const currentServices = this.services();
|
||||
const updatedServices = currentServices.map(s =>
|
||||
s.name === message.serviceName
|
||||
? { ...s, status: message.status }
|
||||
: s
|
||||
);
|
||||
this.services.set(updatedServices);
|
||||
}
|
||||
}
|
||||
|
||||
loadServices(): void {
|
||||
@@ -117,7 +147,7 @@ export class ServicesListComponent implements OnInit {
|
||||
startService(service: Service): void {
|
||||
this.apiService.startService(service.name).subscribe({
|
||||
next: () => {
|
||||
this.loadServices();
|
||||
// WebSocket will handle the update
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -125,7 +155,7 @@ export class ServicesListComponent implements OnInit {
|
||||
stopService(service: Service): void {
|
||||
this.apiService.stopService(service.name).subscribe({
|
||||
next: () => {
|
||||
this.loadServices();
|
||||
// WebSocket will handle the update
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -133,7 +163,7 @@ export class ServicesListComponent implements OnInit {
|
||||
restartService(service: Service): void {
|
||||
this.apiService.restartService(service.name).subscribe({
|
||||
next: () => {
|
||||
this.loadServices();
|
||||
// WebSocket will handle the update
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -142,7 +172,7 @@ export class ServicesListComponent implements OnInit {
|
||||
if (confirm(`Are you sure you want to delete ${service.name}?`)) {
|
||||
this.apiService.deleteService(service.name).subscribe({
|
||||
next: () => {
|
||||
this.loadServices();
|
||||
// WebSocket will handle the update
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user