Merge branch 'develop' of ssh://ognproject.evlt.uma.es:21987/opengnsys/oggui into develop
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
commit
70319d718f
|
@ -258,11 +258,11 @@ mat-tree mat-tree-node.disabled:hover {
|
||||||
|
|
||||||
.client-name {
|
.client-name {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 16px;
|
font-weight: 500;
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filters-container {
|
.filters-container {
|
||||||
|
@ -319,11 +319,26 @@ mat-tree mat-tree-node.disabled:hover {
|
||||||
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.client-image {
|
.client-details {
|
||||||
width: 35px;
|
flex-grow: 1;
|
||||||
height: 35px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-icons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 8px;
|
}
|
||||||
|
|
||||||
|
.client-status-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.client-ip {
|
.client-ip {
|
||||||
|
@ -338,11 +353,9 @@ mat-tree mat-tree-node.disabled:hover {
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-icons {
|
.sync-spinner {
|
||||||
display: flex;
|
margin-left: 1em;
|
||||||
justify-content: center;
|
margin-right: 1em;
|
||||||
gap: 1px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-elevation-z8 {
|
.mat-elevation-z8 {
|
||||||
|
@ -360,10 +373,6 @@ mat-tree mat-tree-node.disabled:hover {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.client-details {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1560px) {
|
@media (max-width: 1560px) {
|
||||||
.clients-view-header {
|
.clients-view-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -60,12 +60,14 @@
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field class="form-field search-select" appearance="outline">
|
<mat-form-field class="form-field search-select" appearance="outline">
|
||||||
<mat-select placeholder="Buscar por estado..." #clientSearchStatusInput (selectionChange)="onClientFilterStatusInput($event.value)">
|
<mat-select placeholder="Buscar por estado..." #clientSearchStatusInput
|
||||||
|
(selectionChange)="onClientFilterStatusInput($event.value)">
|
||||||
<mat-option *ngFor="let option of status" [value]="option.value">
|
<mat-option *ngFor="let option of status" [value]="option.value">
|
||||||
{{ option.name }}
|
{{ option.name }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<button *ngIf="clientSearchStatusInput.value" mat-icon-button matSuffix aria-label="Clear tree search" (click)="clearStatusFilter($event, clientSearchStatusInput)">
|
<button *ngIf="clientSearchStatusInput.value" mat-icon-button matSuffix aria-label="Clear tree search"
|
||||||
|
(click)="clearStatusFilter($event, clientSearchStatusInput)">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@ -226,7 +228,7 @@
|
||||||
<mat-checkbox (click)="$event.stopPropagation()" (change)="toggleRow(client)"
|
<mat-checkbox (click)="$event.stopPropagation()" (change)="toggleRow(client)"
|
||||||
[checked]="selection.isSelected(client)" [disabled]="client.status === 'busy'">
|
[checked]="selection.isSelected(client)" [disabled]="client.status === 'busy'">
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<img [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
|
<img style="margin-top: 0.5em;" [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
|
||||||
class="client-image" />
|
class="client-image" />
|
||||||
|
|
||||||
<div class="client-details">
|
<div class="client-details">
|
||||||
|
@ -234,14 +236,6 @@
|
||||||
<span class="client-ip">{{ client.ip }}</span>
|
<span class="client-ip">{{ client.ip }}</span>
|
||||||
<span class="client-ip">{{ client.mac }}</span>
|
<span class="client-ip">{{ client.mac }}</span>
|
||||||
<div class="action-icons">
|
<div class="action-icons">
|
||||||
<button *ngIf="(!syncStatus || syncingClientId !== client.uuid)" mat-icon-button
|
|
||||||
color="primary" (click)="getStatus(client, selectedNode)">
|
|
||||||
<mat-icon>sync</mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button *ngIf="syncStatus && syncingClientId === client.uuid" mat-icon-button color="primary">
|
|
||||||
<mat-spinner diameter="24"></mat-spinner>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<app-execute-command [clientData]="[client]" [buttonType]="'icon'" [icon]="'terminal'"
|
<app-execute-command [clientData]="[client]" [buttonType]="'icon'" [icon]="'terminal'"
|
||||||
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"></app-execute-command>
|
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"></app-execute-command>
|
||||||
|
@ -252,6 +246,10 @@
|
||||||
<mat-icon>more_vert</mat-icon>
|
<mat-icon>more_vert</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<span class="sync-spinner" *ngIf="syncStatus && syncingClientId === client.uuid">
|
||||||
|
<mat-spinner diameter="24"></mat-spinner>
|
||||||
|
</span>
|
||||||
|
|
||||||
<mat-menu #clientMenu="matMenu">
|
<mat-menu #clientMenu="matMenu">
|
||||||
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
|
@ -261,6 +259,11 @@
|
||||||
<mat-icon>visibility</mat-icon>
|
<mat-icon>visibility</mat-icon>
|
||||||
<span>{{ 'viewDetails' | translate }}</span>
|
<span>{{ 'viewDetails' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-menu-item *ngIf="(!syncStatus || syncingClientId !== client.uuid)"
|
||||||
|
(click)="getStatus(client, selectedNode)">
|
||||||
|
<mat-icon>sync</mat-icon>
|
||||||
|
<span>{{ 'sync' | translate }}</span>
|
||||||
|
</button>
|
||||||
<button mat-menu-item (click)="onDeleteClick($event, client)">
|
<button mat-menu-item (click)="onDeleteClick($event, client)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>{{ 'delete' | translate }}</span>
|
<span>{{ 'delete' | translate }}</span>
|
||||||
|
@ -300,8 +303,13 @@
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
|
||||||
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
|
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
|
||||||
matTooltipPosition="left" matTooltipShowDelay="500">
|
matTooltipPosition="left" matTooltipShowDelay="500">
|
||||||
<img [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
|
<div class="client-status-container">
|
||||||
class="client-image" />
|
<img [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
|
||||||
|
class="client-image" />
|
||||||
|
<span *ngIf="syncStatus && syncingClientId === client.uuid">
|
||||||
|
<mat-spinner diameter="24"></mat-spinner>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
@ -372,7 +380,8 @@
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<tr mat-header-row style="background-color: #f3f3f3;" *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
<tr mat-header-row style="background-color: #f3f3f3;"
|
||||||
|
*matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,8 +1,25 @@
|
||||||
.dialog-content {
|
.create-image-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
padding: 1rem;
|
||||||
/* Espacio entre los elementos del formulario */
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-dialog-content.loading {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-dialog-content {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
padding-right: 1.5em;
|
||||||
|
padding-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-form {
|
.image-form {
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
<app-loading [isLoading]="loading"></app-loading>
|
<div class="create-image-container">
|
||||||
|
<h2 mat-dialog-title>{{ isEditMode ? 'Editar' : 'Crear' }} imagen</h2>
|
||||||
|
<div class="mat-dialog-content" [ngClass]="{'loading': loading}">
|
||||||
|
<mat-spinner class="loading-spinner" *ngIf="loading"></mat-spinner>
|
||||||
|
<form *ngIf="!loading" [formGroup]="imageForm" (ngSubmit)="saveImage()" class="image-form">
|
||||||
|
<mat-card *ngIf="showWarning" class="warning-card">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-icon color="warn">warning</mat-icon>
|
||||||
|
Ha marcado la casilla <strong>"Imagen Global"</strong>. Se transferirá la imagen al resto de repositorios en
|
||||||
|
el
|
||||||
|
caso de que no exista previamente.
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
<mat-form-field appearance="fill" class="form-field">
|
||||||
|
<mat-label>{{ 'imageNameLabel' | translate }}</mat-label>
|
||||||
|
<input matInput formControlName="name" required>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<h2 mat-dialog-title>{{ imageId ? 'Editar' : 'Crear' }} imagen</h2>
|
<mat-form-field appearance="fill" class="form-field" *ngIf="!imageId">
|
||||||
|
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
|
||||||
|
<mat-select formControlName="imageRepositories" required multiple>
|
||||||
|
<mat-option *ngFor="let imageRepository of repositories" [value]="imageRepository['@id']">
|
||||||
|
{{ imageRepository.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-dialog-content class="dialog-content">
|
<mat-form-field appearance="fill" class="form-field">
|
||||||
<form [formGroup]="imageForm" (ngSubmit)="saveImage()" class="image-form">
|
<mat-label>{{ 'descriptionLabel' | translate }}</mat-label>
|
||||||
<mat-card *ngIf="showWarning" class="warning-card">
|
<input matInput formControlName="description" name="description">
|
||||||
<mat-card-content>
|
</mat-form-field>
|
||||||
<mat-icon color="warn">warning</mat-icon>
|
|
||||||
Ha marcado la casilla <strong>"Imagen Global"</strong>. Se transferirá la imagen al resto de repositorios en el
|
|
||||||
caso de que no exista previamente.
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
<mat-form-field appearance="fill" class="form-field">
|
|
||||||
<mat-label>{{ 'imageNameLabel' | translate }}</mat-label>
|
|
||||||
<input matInput formControlName="name" required>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="fill" class="form-field" *ngIf="!imageId">
|
<mat-form-field appearance="fill" class="form-field">
|
||||||
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
|
<mat-label>{{ 'commentsLabel' | translate }}</mat-label>
|
||||||
<mat-select formControlName="imageRepositories" required multiple>
|
<input matInput formControlName="comments" name="comments">
|
||||||
<mat-option *ngFor="let imageRepository of repositories" [value]="imageRepository['@id']">
|
</mat-form-field>
|
||||||
{{ imageRepository.name }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="fill" class="form-field">
|
<mat-form-field appearance="fill" class="form-field">
|
||||||
<mat-label>{{ 'descriptionLabel' | translate }}</mat-label>
|
<mat-label>Perfil de software</mat-label>
|
||||||
<input matInput formControlName="description" name="description">
|
<mat-select formControlName="softwareProfile">
|
||||||
</mat-form-field>
|
<mat-option *ngFor="let profile of softwareProfiles" [value]="profile['@id']">
|
||||||
|
{{ profile.description }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="fill" class="form-field">
|
<mat-checkbox formControlName="remotePc">
|
||||||
<mat-label>{{ 'commentsLabel' | translate }}</mat-label>
|
{{ 'remotePcLabel' | translate }}
|
||||||
<input matInput formControlName="comments" name="comments">
|
</mat-checkbox>
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field appearance="fill" class="form-field">
|
<mat-checkbox formControlName="isGlobal" (click)="changeIsGlobal()">
|
||||||
<mat-label>Perfil de software</mat-label>
|
{{ 'globalImageLabel' | translate }}
|
||||||
<mat-select formControlName="softwareProfile">
|
</mat-checkbox>
|
||||||
<mat-option *ngFor="let profile of softwareProfiles" [value]="profile['@id']">
|
|
||||||
{{ profile.description }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-checkbox formControlName="remotePc">
|
<mat-divider *ngIf="imageId && partitionInfo"></mat-divider>
|
||||||
{{ 'remotePcLabel' | translate }}
|
|
||||||
</mat-checkbox>
|
|
||||||
|
|
||||||
<mat-checkbox formControlName="isGlobal" (click)="changeIsGlobal()">
|
<div *ngIf="imageId && partitionInfo" class="partition-info-container">
|
||||||
{{ 'globalImageLabel' | translate }}
|
<h3>Información de Partición de origen</h3>
|
||||||
</mat-checkbox>
|
<p>Sistema de archivos: {{ partitionInfo['filesystem'] }}</p>
|
||||||
|
<p>Disco: {{ partitionInfo['numDisk'] }}</p>
|
||||||
|
<p>Particion: {{ partitionInfo['numPartition'] }}</p>
|
||||||
|
<p>Nombre del SO: {{ partitionInfo['osName'] }}</p>
|
||||||
|
<p>Código de partición: {{ partitionInfo['partitionCode'] }}</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<mat-divider *ngIf="imageId && partitionInfo"></mat-divider>
|
<mat-dialog-actions class="action-container">
|
||||||
|
<button class="ordinary-button" (click)="close()">{{ 'cancelButton' | translate }}</button>
|
||||||
<div *ngIf="imageId && partitionInfo" class="partition-info-container">
|
<button class="submit-button" (click)="saveImage()" [disabled]="loading">{{ 'saveButton' | translate }}</button>
|
||||||
<h3>Información de Partición de origen</h3>
|
</mat-dialog-actions>
|
||||||
<p>Sistema de archivos: {{ partitionInfo['filesystem'] }}</p>
|
</div>
|
||||||
<p>Disco: {{ partitionInfo['numDisk'] }}</p>
|
|
||||||
<p>Particion: {{ partitionInfo['numPartition'] }}</p>
|
|
||||||
<p>Nombre del SO: {{ partitionInfo['osName'] }}</p>
|
|
||||||
<p>Código de partición: {{ partitionInfo['partitionCode'] }}</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</mat-dialog-content>
|
|
||||||
|
|
||||||
<mat-dialog-actions class="action-container">
|
|
||||||
<button class="ordinary-button" (click)="close()">{{ 'cancelButton' | translate }}</button>
|
|
||||||
<button class="submit-button" (click)="saveImage()">{{ 'saveButton' | translate }}</button>
|
|
||||||
</mat-dialog-actions>
|
|
|
@ -17,6 +17,7 @@ export class CreateImageComponent implements OnInit {
|
||||||
softwareProfiles: any[] = [];
|
softwareProfiles: any[] = [];
|
||||||
repositories: any[] = [];
|
repositories: any[] = [];
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
|
isEditMode: boolean = false;
|
||||||
partitionInfo: { [key: string]: string } = {};
|
partitionInfo: { [key: string]: string } = {};
|
||||||
showWarning: boolean = false;
|
showWarning: boolean = false;
|
||||||
|
|
||||||
|
@ -42,30 +43,34 @@ export class CreateImageComponent implements OnInit {
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
if (this.data) {
|
if (this.data) {
|
||||||
this.load()
|
this.isEditMode = true;
|
||||||
|
this.load();
|
||||||
|
} else {
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
this.fetchSoftwareProfiles();
|
this.fetchSoftwareProfiles();
|
||||||
this.fetchRepositories();
|
this.fetchRepositories();
|
||||||
this.loading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load(): void {
|
load(): void {
|
||||||
this.dataService.getImage(this.data).subscribe({
|
this.dataService.getImage(this.data).subscribe({
|
||||||
next: (response) => {
|
next: (response) => {
|
||||||
this.imageForm = this.fb.group({
|
this.imageForm.patchValue({
|
||||||
name: [response.name, Validators.required],
|
name: response.name,
|
||||||
description: [response.description],
|
description: response.description,
|
||||||
comments: [response.comments],
|
comments: response.comments,
|
||||||
remotePc: [response.remotePc],
|
remotePc: response.remotePc,
|
||||||
isGlobal: [response.isGlobal],
|
isGlobal: response.isGlobal,
|
||||||
softwareProfile: [response.softwareProfile ? response.softwareProfile['@id'] : null, Validators.required],
|
softwareProfile: response.softwareProfile ? response.softwareProfile['@id'] : null,
|
||||||
imageRepositories: [response.imageRepositories ? response.imageRepositories.map((r: any) => r.imageRepository['@id']) : [], Validators.required],
|
imageRepositories: response.imageRepositories ? response.imageRepositories.map((r: any) => r.imageRepository['@id']) : [],
|
||||||
});
|
});
|
||||||
this.imageId = response['@id'];
|
this.imageId = response['@id'];
|
||||||
this.partitionInfo = response.partitionInfo;
|
this.partitionInfo = response.partitionInfo;
|
||||||
|
this.loading = false;
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
console.error('Error fetching remote calendar:', err);
|
console.error('Error fetching remote calendar:', err);
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue