104 lines
3.9 KiB
TypeScript
104 lines
3.9 KiB
TypeScript
|
|
import { Component, OnInit, inject, signal } from '@angular/core';
|
||
|
|
import { CommonModule } from '@angular/common';
|
||
|
|
import { FormsModule } from '@angular/forms';
|
||
|
|
import { ApiService, Registry } from '../../core/services/api.service';
|
||
|
|
|
||
|
|
@Component({
|
||
|
|
selector: 'app-registries',
|
||
|
|
standalone: true,
|
||
|
|
imports: [CommonModule, FormsModule],
|
||
|
|
template: `
|
||
|
|
<div class="px-4 sm:px-0">
|
||
|
|
<h1 class="text-3xl font-bold text-gray-900 mb-8">Docker Registries</h1>
|
||
|
|
|
||
|
|
<!-- Add Registry Form -->
|
||
|
|
<div class="card mb-8 max-w-2xl">
|
||
|
|
<h2 class="text-lg font-medium text-gray-900 mb-4">Add Registry</h2>
|
||
|
|
<form (ngSubmit)="addRegistry()" class="space-y-4">
|
||
|
|
<div>
|
||
|
|
<label for="url" class="label">Registry URL</label>
|
||
|
|
<input type="text" id="url" [(ngModel)]="newRegistry.url" name="url" required placeholder="registry.example.com" class="input" />
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="username" class="label">Username</label>
|
||
|
|
<input type="text" id="username" [(ngModel)]="newRegistry.username" name="username" required class="input" />
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="password" class="label">Password</label>
|
||
|
|
<input type="password" id="password" [(ngModel)]="newRegistry.password" name="password" required class="input" />
|
||
|
|
</div>
|
||
|
|
<button type="submit" class="btn btn-primary">Add Registry</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Registries List -->
|
||
|
|
@if (registries().length > 0) {
|
||
|
|
<div class="card overflow-hidden p-0">
|
||
|
|
<table class="min-w-full divide-y divide-gray-200">
|
||
|
|
<thead class="bg-gray-50">
|
||
|
|
<tr>
|
||
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">URL</th>
|
||
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Username</th>
|
||
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Created</th>
|
||
|
|
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase">Actions</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
||
|
|
@for (registry of registries(); track registry.id) {
|
||
|
|
<tr>
|
||
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ registry.url }}</td>
|
||
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ registry.username }}</td>
|
||
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ formatDate(registry.createdAt) }}</td>
|
||
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm">
|
||
|
|
<button (click)="deleteRegistry(registry)" class="text-red-600 hover:text-red-900">Delete</button>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
`,
|
||
|
|
})
|
||
|
|
export class RegistriesComponent implements OnInit {
|
||
|
|
private apiService = inject(ApiService);
|
||
|
|
registries = signal<Registry[]>([]);
|
||
|
|
newRegistry = { url: '', username: '', password: '' };
|
||
|
|
|
||
|
|
ngOnInit(): void {
|
||
|
|
this.loadRegistries();
|
||
|
|
}
|
||
|
|
|
||
|
|
loadRegistries(): void {
|
||
|
|
this.apiService.getRegistries().subscribe({
|
||
|
|
next: (response) => {
|
||
|
|
if (response.success && response.data) {
|
||
|
|
this.registries.set(response.data);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
addRegistry(): void {
|
||
|
|
this.apiService.createRegistry(this.newRegistry).subscribe({
|
||
|
|
next: () => {
|
||
|
|
this.newRegistry = { url: '', username: '', password: '' };
|
||
|
|
this.loadRegistries();
|
||
|
|
},
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
deleteRegistry(registry: Registry): void {
|
||
|
|
if (confirm(`Delete registry ${registry.url}?`)) {
|
||
|
|
this.apiService.deleteRegistry(registry.url).subscribe({
|
||
|
|
next: () => this.loadRegistries(),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
formatDate(timestamp: number): string {
|
||
|
|
return new Date(timestamp).toLocaleDateString();
|
||
|
|
}
|
||
|
|
}
|