autocomit

This commit is contained in:
2026-02-09 19:33:55 +01:00
parent 16b8ae0b8e
commit fd356019d7
22 changed files with 1595 additions and 0 deletions
@@ -0,0 +1,81 @@
<div class="dependencies-container">
<div class="header">
<h3>External Dependencies</h3>
<button (click)="createNew()" class="btn-primary">Add Dependency</button>
</div>
<div class="filters">
<div class="filter-group">
<label>Filter by Type:</label>
<select [(ngModel)]="selectedTypeId" (ngModelChange)="onFilterChange()" class="filter-select">
<option value="">All Types</option>
<option *ngFor="let type of dependencyTypes" [value]="type.id">
{{ type.typeName }}
</option>
</select>
</div>
<div class="filter-group">
<label>Filter by Status:</label>
<select [(ngModel)]="selectedStatus" (ngModelChange)="onFilterChange()" class="filter-select">
<option *ngFor="let opt of statusOptions" [value]="opt.value">
{{ opt.label }}
</option>
</select>
</div>
</div>
<div *ngIf="loading" class="loading">Loading dependencies...</div>
<div *ngIf="error" class="error">{{ error }}</div>
<div *ngIf="!loading && dependencies.length > 0" class="dependencies-table">
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Status</th>
<th>Validity Period</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let dep of dependencies">
<td><strong>{{ dep.name }}</strong></td>
<td>{{ dep.dependencyType.typeName }}</td>
<td>
<span class="status-badge" [ngClass]="getStatusClass(dep.status)">
{{ getStatusLabel(dep.status) }}
<span *ngIf="dep.daysUntilExpiration !== null && dep.daysUntilExpiration !== undefined">
({{ dep.daysUntilExpiration }} days)
</span>
</span>
</td>
<td>
<div *ngIf="dep.validityStartDate || dep.validityEndDate">
{{ dep.validityStartDate ? (dep.validityStartDate | date:'mediumDate') : '-' }}
{{ dep.validityEndDate ? (dep.validityEndDate | date:'mediumDate') : 'Indefinite' }}
</div>
<div *ngIf="!dep.validityStartDate && !dep.validityEndDate">-</div>
</td>
<td class="actions">
<button (click)="viewDetails(dep.id)" class="btn-sm">View</button>
<button (click)="edit(dep.id)" class="btn-sm">Edit</button>
<button (click)="delete(dep.id)" class="btn-sm btn-danger">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<div *ngIf="!loading && dependencies.length === 0" class="empty">
No external dependencies found for this application.
</div>
<div *ngIf="totalPages > 1" class="pagination">
<button (click)="previousPage()" [disabled]="page === 0">Previous</button>
<span>Page {{ page + 1 }} of {{ totalPages }}</span>
<button (click)="nextPage()" [disabled]="page >= totalPages - 1">Next</button>
</div>
</div>
@@ -0,0 +1,181 @@
.dependencies-container {
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
h3 {
margin: 0;
}
}
}
.btn-primary {
background-color: #3f51b5;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: #303f9f;
}
}
.filters {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
padding: 1rem;
background: #f9f9f9;
border-radius: 8px;
.filter-group {
flex: 1;
min-width: 200px;
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #555;
}
.filter-select {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 0.95rem;
&:focus {
outline: none;
border-color: #3f51b5;
}
}
}
}
.loading, .error, .empty {
text-align: center;
padding: 2rem;
color: #666;
}
.error {
color: #f44336;
}
.dependencies-table {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
table {
width: 100%;
border-collapse: collapse;
th, td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid #f5f5f5;
}
th {
background-color: #f9f9f9;
font-weight: 600;
color: #555;
}
tbody tr:hover {
background-color: #fafafa;
}
}
}
.status-badge {
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.875rem;
font-weight: 500;
display: inline-block;
&.status-active {
background-color: #e8f5e9;
color: #388e3c;
}
&.status-expiring {
background-color: #fff3e0;
color: #f57c00;
}
&.status-expired {
background-color: #ffebee;
color: #c62828;
}
&.status-not-valid {
background-color: #f5f5f5;
color: #616161;
}
}
.actions {
display: flex;
gap: 0.5rem;
}
.btn-sm {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: #2196f3;
color: white;
font-size: 0.875rem;
&:hover {
background-color: #1976d2;
}
&.btn-danger {
background-color: #f44336;
&:hover {
background-color: #d32f2f;
}
}
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
margin-top: 1.5rem;
button {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
cursor: pointer;
&:hover:not(:disabled) {
background-color: #f5f5f5;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
span {
color: #666;
}
}
@@ -0,0 +1,152 @@
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { DependencyService } from '../../dependencies/dependency.service';
import { ExternalDependency, DependencyType } from '../../../shared/models/dependency.model';
import { Page } from '../../../shared/models/environment.model';
@Component({
selector: 'app-application-dependencies',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './application-dependencies.component.html',
styleUrls: ['./application-dependencies.component.scss']
})
export class ApplicationDependenciesComponent implements OnInit {
@Input() applicationId!: string;
@Input() applicationName!: string;
dependencies: ExternalDependency[] = [];
dependencyTypes: DependencyType[] = [];
loading = false;
error = '';
page = 0;
size = 10;
totalPages = 0;
selectedTypeId = '';
selectedStatus = '';
statusOptions = [
{ value: '', label: 'All Statuses' },
{ value: 'ACTIVE', label: 'Active' },
{ value: 'EXPIRING', label: 'Expiring Soon' },
{ value: 'EXPIRED', label: 'Expired' },
{ value: 'NOT_YET_VALID', label: 'Not Yet Valid' }
];
constructor(
private dependencyService: DependencyService,
private router: Router
) {}
ngOnInit(): void {
if (this.applicationId) {
this.loadDependencyTypes();
this.loadDependencies();
}
}
loadDependencyTypes(): void {
this.dependencyService.getDependencyTypes().subscribe({
next: (types) => {
this.dependencyTypes = types;
},
error: (err) => {
console.error('Failed to load dependency types', err);
}
});
}
loadDependencies(): void {
this.loading = true;
const filters: any = { applicationId: this.applicationId };
if (this.selectedTypeId) {
filters.dependencyTypeId = this.selectedTypeId;
}
if (this.selectedStatus) {
filters.status = this.selectedStatus;
}
this.dependencyService.getDependencies(filters, this.page, this.size).subscribe({
next: (data: Page<ExternalDependency>) => {
this.dependencies = data.content;
this.totalPages = data.totalPages;
this.loading = false;
},
error: (err) => {
this.error = 'Failed to load dependencies';
this.loading = false;
}
});
}
onFilterChange(): void {
this.page = 0;
this.loadDependencies();
}
createNew(): void {
this.router.navigate(['/dependencies/new'], {
queryParams: { applicationId: this.applicationId }
});
}
viewDetails(id: string): void {
this.router.navigate(['/dependencies', id]);
}
edit(id: string): void {
this.router.navigate(['/dependencies', id, 'edit']);
}
delete(id: string): void {
if (confirm('Are you sure you want to delete this dependency?')) {
this.dependencyService.deleteDependency(id).subscribe({
next: () => {
this.loadDependencies();
},
error: (err) => {
this.error = 'Failed to delete dependency';
}
});
}
}
getStatusClass(status: string): string {
const classes: Record<string, string> = {
'ACTIVE': 'status-active',
'EXPIRING': 'status-expiring',
'EXPIRED': 'status-expired',
'NOT_YET_VALID': 'status-not-valid'
};
return classes[status] || '';
}
getStatusLabel(status: string): string {
const labels: Record<string, string> = {
'ACTIVE': 'Active',
'EXPIRING': 'Expiring Soon',
'EXPIRED': 'Expired',
'NOT_YET_VALID': 'Not Yet Valid'
};
return labels[status] || status;
}
nextPage(): void {
if (this.page < this.totalPages - 1) {
this.page++;
this.loadDependencies();
}
}
previousPage(): void {
if (this.page > 0) {
this.page--;
this.loadDependencies();
}
}
}