- | {{ column.header }} |
-
-
-
- {{ column.cell(schedule) }}
-
-
+
-
-
-
-
-
+
+ | {{ 'executionOrder' | translate }} |
+
+
+ {{ item.order }}
+
+ |
+
-
- {{ column.cell(schedule) }}
-
+
+ {{ 'actionType' | translate }} |
+
+
+ {{ getTypeDisplay(item.type).icon }}
+ {{ getTypeDisplay(item.type).label }}
+
+ |
+
+
+
+ {{ 'scriptLabel' | translate }} |
+
+
+ {{ item.content }}
+
+
+ ({{ 'viewParameters' | translate }})
+
+ |
+
+
+
+ {{ 'viewParameters' | translate }} |
+
+
+ —
|
- Acciones |
-
- |
-
+
@@ -74,5 +92,5 @@
- Cerrar
+ {{ 'close' | translate }}
diff --git a/ogWebconsole/src/app/components/commands/commands-task/show-task-script/show-task-script.component.ts b/ogWebconsole/src/app/components/commands/commands-task/show-task-script/show-task-script.component.ts
index 9be4dc7..7622307 100644
--- a/ogWebconsole/src/app/components/commands/commands-task/show-task-script/show-task-script.component.ts
+++ b/ogWebconsole/src/app/components/commands/commands-task/show-task-script/show-task-script.component.ts
@@ -25,14 +25,31 @@ export class ShowTaskScriptComponent implements OnInit{
filters: { [key: string]: string } = {};
columns = [
- { columnDef: 'id', header: 'ID', cell: (client: any) => client.id },
- { columnDef: 'order', header: 'Orden', cell: (client: any) => client.order },
- { columnDef: 'content', header: 'Script', cell: (client: any) => client.content },
- { columnDef: 'type', header: 'Tipo', cell: (client: any) => client.type },
- { columnDef: 'parameters', header: 'Parámetros', cell: (client: any) => client.parameters },
+ { columnDef: 'id', header: 'ID', cell: (item: any) => item.id },
+ { columnDef: 'order', header: 'Orden', cell: (item: any) => item.order },
+ { columnDef: 'type', header: 'Tipo', cell: (item: any) => item.type },
+ { columnDef: 'parameters', header: 'Parámetros', cell: (item: any) => item.parameters },
+ { columnDef: 'content', header: 'Contenido', cell: (item: any) => item.content },
];
- displayedColumns: string[] = ['id', 'order', 'type', 'parameters', 'content', 'actions'];
+ displayedColumns: string[] = ['order', 'type', 'content', 'parameters', 'actions'];
+
+ typeLabels: { [key: string]: { label: string, icon: string } } = {
+ 'partition-and-format': { label: 'Particionar y formatear', icon: 'storage' },
+ 'partition-assistant': { label: 'Asistente de particionado', icon: 'storage' },
+ 'deploy-image': { label: 'Desplegar imagen', icon: 'cloud_download' },
+ 'create-image': { label: 'Crear imagen', icon: 'cloud_upload' },
+ 'run-script': { label: 'Ejecutar script', icon: 'code' },
+ 'reboot': { label: 'Reiniciar', icon: 'restart_alt' },
+ 'shutdown': { label: 'Apagar', icon: 'power_off' },
+ 'poweron': { label: 'Encender', icon: 'power' },
+ 'power-on': { label: 'Encender', icon: 'power' },
+ 'login': { label: 'Iniciar sesión', icon: 'login' },
+ };
+
+ getTypeDisplay(type: string): { label: string, icon: string } {
+ return this.typeLabels[type] || { label: type, icon: 'play_arrow' };
+ }
constructor(
private toastService: ToastrService,
@@ -53,9 +70,11 @@ export class ShowTaskScriptComponent implements OnInit{
loadData() {
this.loading = true;
- this.http.get (`${this.baseUrl}/command-task-scripts?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}&commandTask.id=${this.data.commandTask?.id}`, { params: this.filters }).subscribe(
+ this.http.get(`${this.baseUrl}/command-task-scripts?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}&commandTask.id=${this.data.commandTask?.id}&order[order]=ASC`, { params: this.filters }).subscribe(
(data) => {
- this.dataSource.data = data['hydra:member'];
+ const items = data['hydra:member'];
+ items.sort((a: any, b: any) => (a.order ?? 0) - (b.order ?? 0));
+ this.dataSource.data = items;
this.length = data['hydra:totalItems'];
this.loading = false;
},
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.css b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.css
index cf41b39..2154a9a 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.css
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.css
@@ -10,6 +10,26 @@
align-items: center;
}
+/* Layout compacto: tipo + configuración en una fila */
+.compact-config-row {
+ display: flex;
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+.compact-section {
+ padding: 20px !important;
+ margin-bottom: 0 !important;
+}
+
+.type-section {
+ flex: 0 0 280px;
+}
+
+.config-section {
+ flex: 1;
+}
+
/* Secciones del formulario */
.form-section {
background: white !important;
@@ -249,6 +269,14 @@ mat-form-field {
/* Responsive design */
@media (max-width: 768px) {
+ .compact-config-row {
+ flex-direction: column;
+ }
+
+ .type-section {
+ flex: none;
+ }
+
.select-container {
padding: 16px;
}
@@ -879,8 +907,8 @@ mat-form-field {
.git-info-grid {
display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- gap: 16px;
+ grid-template-columns: 1fr;
+ gap: 12px;
}
.git-info-item {
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.html b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.html
index d28e1b6..62861a4 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.html
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.html
@@ -33,14 +33,13 @@
|
@@ -92,15 +98,17 @@
edit
-
- delete
+
+ {{ image.status === 'trash' ? 'delete_forever' : 'delete' }}
menu
Obtener ficheros auxiliares
- Eliminar permanentemente
Recuperar imagen de la papelera
diff --git a/ogWebconsole/src/app/components/repositories/show-monolitic-images/show-monolitic-images.component.ts b/ogWebconsole/src/app/components/repositories/show-monolitic-images/show-monolitic-images.component.ts
index 8a6e185..4ca9eab 100644
--- a/ogWebconsole/src/app/components/repositories/show-monolitic-images/show-monolitic-images.component.ts
+++ b/ogWebconsole/src/app/components/repositories/show-monolitic-images/show-monolitic-images.component.ts
@@ -61,6 +61,11 @@ export class ShowMonoliticImagesComponent implements OnInit {
header: 'Estado',
cell: (image: any) => image.status
},
+ {
+ columnDef: 'datasize',
+ header: 'Tamaño',
+ cell: (image: any) => this.formatSize(image.datasize)
+ },
{
columnDef: 'description',
header: 'Descripción',
@@ -144,17 +149,19 @@ export class ShowMonoliticImagesComponent implements OnInit {
showImageInfo(event: MouseEvent, image:any) {
event.stopPropagation();
+ this.loading = true;
this.loadImageAlert(image).subscribe(
response => {
this.alertMessage = response;
+ this.loading = false;
+ this.loadData();
this.dialog.open(ServerInfoDialogComponent, {
width: '800px',
data: {
message: this.alertMessage
}
});
- this.loading = false;
},
error => {
this.toastService.error(error.error['hydra:description']);
@@ -407,7 +414,7 @@ export class ShowMonoliticImagesComponent implements OnInit {
this.loading = true;
this.loadAlert().subscribe(
response => {
- this.alertMessage = response.output;
+ this.alertMessage = response.details;
this.dialog.open(ServerInfoDialogComponent, {
width: '800px',
@@ -427,5 +434,19 @@ export class ShowMonoliticImagesComponent implements OnInit {
this.dialogRef.close();
}
+ formatSize(bytes: string | number | null | undefined): string {
+ if (bytes === null || bytes === undefined || bytes === '') return '-';
+ const n = Number(bytes);
+ if (isNaN(n) || n === 0) return '-';
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
+ let i = 0;
+ let value = n;
+ while (value >= 1024 && i < units.length - 1) {
+ value /= 1024;
+ i++;
+ }
+ return `${value.toFixed(2)} ${units[i]}`;
+ }
+
protected readonly isDevMode = isDevMode;
}
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.css b/ogWebconsole/src/app/components/task-logs/task-logs.component.css
index f2077a2..81763a6 100644
--- a/ogWebconsole/src/app/components/task-logs/task-logs.component.css
+++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.css
@@ -2,7 +2,7 @@
display: flex;
justify-content: space-between;
align-items: center;
- padding: 10px 10px;
+ padding: 6px 10px;
border-bottom: 1px solid #ddd;
background: white;
color: #333;
@@ -56,10 +56,10 @@
}
.stats-container {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 15px;
- margin: 20px 0;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ margin: 10px 0;
padding: 0 10px;
position: relative;
}
@@ -119,12 +119,16 @@
.stat-card {
background: white;
- border-radius: 12px;
- padding: 20px;
+ border-radius: 20px;
+ padding: 8px 16px;
text-align: center;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
- transition: transform 0.3s ease, box-shadow 0.3s ease;
- border-left: 4px solid #667eea;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+ border-left: none;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ min-width: 0;
}
.stat-card.clickable {
@@ -149,8 +153,8 @@
}
.stat-card.clickable:hover {
- transform: translateY(-3px);
- box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.stat-card.clickable:active {
@@ -238,6 +242,28 @@
color: #212529;
}
+.stat-pending {
+ border-left-color: #ff9800;
+ background: #ff9800;
+ color: white;
+}
+
+.stat-pending .stat-number,
+.stat-pending .stat-label {
+ color: white;
+}
+
+.stat-cancelled {
+ border-left-color: #9e9e9e;
+ background: #9e9e9e;
+ color: white;
+}
+
+.stat-cancelled .stat-number,
+.stat-cancelled .stat-label {
+ color: white;
+}
+
.stat-sent {
border-left-color: #b19cd9;
background: #b19cd9;
@@ -250,23 +276,25 @@
}
.stat-number {
- font-size: 2rem;
- font-weight: bold;
+ font-size: 1.25rem;
+ font-weight: 700;
color: #667eea;
- margin-bottom: 5px;
+ margin-bottom: 0;
+ line-height: 1;
}
.stat-label {
- font-size: 0.9rem;
+ font-size: 0.75rem;
color: #666;
font-weight: 500;
+ white-space: nowrap;
}
.filters-section {
background: #f8f9fa;
border-radius: 8px;
- margin: 20px 0;
- padding: 20px;
+ margin: 8px 0;
+ padding: 10px 16px;
border: 1px solid #e9ecef;
}
@@ -274,7 +302,7 @@
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 15px;
+ margin-bottom: 6px;
}
.filters-header-actions {
@@ -315,25 +343,25 @@
.search-container {
display: flex;
flex-direction: column;
- gap: 15px;
+ gap: 4px;
transition: all 0.3s ease;
}
.search-container.expanded {
- gap: 20px;
+ gap: 8px;
}
.filter-row {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
- gap: 15px;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 8px;
align-items: end;
}
.advanced-filters {
border-top: 1px solid #dee2e6;
- padding-top: 15px;
- margin-top: 10px;
+ padding-top: 8px;
+ margin-top: 4px;
}
.calendar-button-row {
@@ -360,22 +388,22 @@ table {
.search-string {
flex: 1;
- padding: 5px;
+ padding: 0;
}
.search-boolean {
flex: 1;
- padding: 5px;
+ padding: 0;
}
.search-select {
flex: 2;
- padding: 5px;
+ padding: 0;
}
.search-date {
flex: 1;
- padding: 5px;
+ padding: 0;
}
.mat-elevation-z8 {
@@ -395,7 +423,7 @@ table {
display: flex;
justify-content: space-between;
align-items: center;
- padding: 15px 20px;
+ padding: 6px 16px;
background: #f8f9fa;
border-bottom: 1px solid #dee2e6;
}
@@ -505,8 +533,8 @@ table {
.paginator-container {
display: flex;
- justify-content: end;
- margin: 20px 0;
+ justify-content: flex-end;
+ margin: 8px 0;
padding: 0 10px;
}
@@ -667,7 +695,7 @@ button.cancel-button {
}
.stats-container {
- grid-template-columns: repeat(2, 1fr);
+ gap: 6px;
}
.filter-row {
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.html b/ogWebconsole/src/app/components/task-logs/task-logs.component.html
index b2df6d8..798a273 100644
--- a/ogWebconsole/src/app/components/task-logs/task-logs.component.html
+++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.html
@@ -57,6 +57,20 @@
{{ getStatusCount('in-progress') }}
{{ 'inProgress' | translate }}
+
+
{{ getStatusCount('pending') }}
+
{{ 'pending' | translate }}
+
+
+
{{ getStatusCount('cancelled') }}
+
{{ 'cancelled' | translate }}
+
close
-
{{ 'enterClientName' | translate }}
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts
index 1326dec..a8012e2 100644
--- a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts
+++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts
@@ -116,6 +116,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy {
filteredCommands!: Observable;
commandControl = new FormControl();
activeFilter: string = '';
+ private eventSource: EventSource | null = null;
constructor(private http: HttpClient,
private joyrideService: JoyrideService,
@@ -145,10 +146,10 @@ export class TaskLogsComponent implements OnInit, OnDestroy {
map(name => (name ? this._filterClients(name) : this.clients.slice()))
);
- const eventSource = new EventSource(`${this.mercureUrl}?topic=`
+ this.eventSource = new EventSource(`${this.mercureUrl}?topic=`
+ encodeURIComponent(`traces`));
- eventSource.onmessage = (event) => {
+ this.eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data && data['@id']) {
this.updateTracesStatus(data['@id'], data.status, data.progress);
@@ -157,6 +158,9 @@ export class TaskLogsComponent implements OnInit, OnDestroy {
}
ngOnDestroy(): void {
+ if (this.eventSource) {
+ this.eventSource.close();
+ }
}
toggleFilters(): void {
@@ -693,6 +697,20 @@ export class TaskLogsComponent implements OnInit, OnDestroy {
this.loadTraces();
}
+ filterByPending(): void {
+ this.resetAllFilters();
+ this.filters['status'] = 'pending';
+ this.activeFilter = 'pending';
+ this.loadTraces();
+ }
+
+ filterByCancelled(): void {
+ this.resetAllFilters();
+ this.filters['status'] = 'cancelled';
+ this.activeFilter = 'cancelled';
+ this.loadTraces();
+ }
+
filterBySent(): void {
this.resetAllFilters();
this.filters['status'] = 'sent';
@@ -716,6 +734,10 @@ export class TaskLogsComponent implements OnInit, OnDestroy {
return 'Trazas fallidas';
case 'in-progress':
return 'Trazas en progreso';
+ case 'pending':
+ return 'Trazas pendientes';
+ case 'cancelled':
+ return 'Trazas canceladas';
case 'sent':
return 'Trazas enviadas';
default:
diff --git a/ogWebconsole/src/app/layout/header/header.component.css b/ogWebconsole/src/app/layout/header/header.component.css
index 7e7c1dd..e186ef8 100644
--- a/ogWebconsole/src/app/layout/header/header.component.css
+++ b/ogWebconsole/src/app/layout/header/header.component.css
@@ -1,15 +1,16 @@
+:host {
+ display: block;
+}
+
mat-toolbar {
- /*height: 7vh;*/
min-height: 65px;
min-width: 375px;
background: rgba(226, 232, 240, 0.8);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
color: black;
- position: fixed;
+ position: sticky;
top: 0;
- left: 0;
- right: 0;
z-index: 1000;
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
@@ -20,6 +21,15 @@ mat-toolbar {
padding: 0 16px;
}
+.sidebar-toggle-button {
+ flex-shrink: 0;
+ color: #3f51b5 !important;
+}
+
+.sidebar-toggle-button .navbar-icon {
+ color: #3f51b5 !important;
+}
+
/* Estilos específicos para el botón del sidebar */
.navbar-icon {
color: #3f51b5;
@@ -67,6 +77,26 @@ mat-toolbar button[mat-icon-button]:hover {
cursor: pointer;
}
+.download-agent-button {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ text-decoration: none;
+ color: inherit;
+ padding: 4px 10px !important;
+ font-size: 13px !important;
+ line-height: 1;
+ font-family: Roboto, "Helvetica Neue", sans-serif;
+ font-weight: 400;
+}
+
+.download-icon {
+ font-size: 14px !important;
+ width: 14px !important;
+ height: 14px !important;
+ line-height: 14px !important;
+}
+
.logout-button {
background-color: #f00e0e;
color: white;
diff --git a/ogWebconsole/src/app/layout/header/header.component.html b/ogWebconsole/src/app/layout/header/header.component.html
index 353e3da..b520422 100644
--- a/ogWebconsole/src/app/layout/header/header.component.html
+++ b/ogWebconsole/src/app/layout/header/header.component.html
@@ -1,18 +1,25 @@
+
+