refs #1619.Refactor: update layout dimensions and styles for groups component
testing/ogGui-multibranch/pipeline/head This commit looks good Details

deb-pkg
Lucas Lara García 2025-02-27 16:12:13 +01:00
parent b29a3f58f1
commit 6fd741e7b4
5 changed files with 172 additions and 140 deletions

View File

@ -3,6 +3,7 @@
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
}
.header-container {
@ -18,6 +19,7 @@
flex-direction: row;
width: 100%;
height: 100%;
overflow: hidden;
}
.header-container-title {
@ -41,7 +43,10 @@
.clients-container {
flex-grow: 1;
box-sizing: border-box;
overflow-y: auto;
overflow: hidden;
display: flex;
flex-direction: column;
padding: 0rem 1rem 0rem 0.5rem;
}
.clients-view-header {
@ -52,7 +57,36 @@
margin-top: 0.5rem;
align-items: center;
padding-right: 1rem;
}
.clients-view {
flex-grow: 1;
overflow-y: auto;
}
.cards-view {
display: flex;
flex-grow: 1;
overflow-y: auto;
width: 100%;
}
.clients-table {
max-height: calc(100vh - 330px);
overflow: auto;
display: flex;
flex-direction: column;
}
.clients-table table {
flex-grow: 1;
overflow: auto;
}
.paginator-container {
display: flex;
justify-content: end;
margin-top: auto;
}
.actions mat-icon {
@ -234,7 +268,7 @@ mat-tree mat-tree-node.disabled:hover {
display: flex;
flex-direction: column;
justify-content: start;
padding: 1em;
padding: 1em 1em 0em 1em;
}
.chip-busy {
@ -311,9 +345,21 @@ mat-tree mat-tree-node.disabled:hover {
margin: 0 4px;
}
.filters-and-tree-container {
display: flex;
flex-direction: column;
height: 100%;
}
.filters-panel {
flex-shrink: 0;
}
.tree-container {
overflow-x: hidden;
flex-grow: 1;
overflow-y: auto;
max-height: calc(100% - var(--filters-panel-height));
margin-bottom: 1rem;
}
.client-item {
@ -527,11 +573,6 @@ mat-button-toggle-group {
background-color: #c7c7c7;
}
.cards-view {
display: flex;
width: 100%;
}
.clients-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));

View File

@ -198,7 +198,7 @@
<app-loading [isLoading]="isLoadingClients"></app-loading>
<!-- CLIENTS VIEWS-->
<div *ngIf="!isLoadingClients">
<div class="clients-view" *ngIf="!isLoadingClients">
<div *ngIf="hasClients; else noClientsTemplate">
<!-- Cards view -->
<div *ngIf="currentView === 'card'" class="cards-view">
@ -260,100 +260,102 @@
</div>
<!-- List view -->
<div class="clients-table" *ngIf="currentView === 'list'">
<table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? toggleAllRows() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()" (change)="toggleRow(row)"
[checked]="selection.isSelected(row)" [disabled]="row.status === 'busy'">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
<img [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
class="client-image" />
</td>
</ng-container>
<div *ngIf="currentView === 'list'" class="list-view">
<section class="clients-table" tabindex="0">
<table mat-table matSort [dataSource]="selectedClients">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? toggleAllRows() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()" (change)="toggleRow(row)"
[checked]="selection.isSelected(row)" [disabled]="row.status === 'busy'">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
<img [src]="'assets/images/ordenador_' + client.status + '.png'" alt="Client Icon"
class="client-image" />
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
{{ client.name }}
</td>
</ng-container>
<ng-container matColumnDef="ip">
<th mat-header-cell *matHeaderCellDef mat-sort-header>IP </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
{{ client.ip }}
</td>
</ng-container>
<ng-container matColumnDef="oglive">
<th mat-header-cell *matHeaderCellDef mat-sort-header> OG Live </th>
<td mat-cell *matCellDef="let client"> {{ client.ogLive?.date | date }} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
{{ client.name }}
</td>
</ng-container>
<ng-container matColumnDef="ip">
<th mat-header-cell *matHeaderCellDef mat-sort-header>IP </th>
<td mat-cell *matCellDef="let client" matTooltip="{{ getClientPath(client) }}"
matTooltipPosition="left" matTooltipShowDelay="500">
{{ client.ip }}
</td>
</ng-container>
<ng-container matColumnDef="oglive">
<th mat-header-cell *matHeaderCellDef mat-sort-header> OG Live </th>
<td mat-cell *matCellDef="let client"> {{ client.ogLive?.date | date }} </td>
</ng-container>
<ng-container matColumnDef="maintenace">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'maintenance' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.maintenance }} </td>
</ng-container>
<ng-container matColumnDef="subnet">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'subnet' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.subnet }} </td>
</ng-container>
<ng-container matColumnDef="pxeTemplate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'pxeTemplate' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.template?.name }} </td>
</ng-container>
<ng-container matColumnDef="maintenace">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'maintenance' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.maintenance }} </td>
</ng-container>
<ng-container matColumnDef="subnet">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'subnet' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.subnet }} </td>
</ng-container>
<ng-container matColumnDef="pxeTemplate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'pxeTemplate' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.template?.name }} </td>
</ng-container>
<ng-container matColumnDef="parentName">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'parent' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.parentName }} </td>
</ng-container>
<ng-container matColumnDef="parentName">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'parent' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.parentName }} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
<td mat-cell *matCellDef="let client">
<button
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"
mat-icon-button [matMenuTriggerFor]="clientMenu" color="primary">
<mat-icon>more_vert</mat-icon>
</button>
<app-execute-command [clientData]="[client]" [buttonType]="'icon'" [icon]="'terminal'"
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"></app-execute-command>
<mat-menu #clientMenu="matMenu">
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
<mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
<td mat-cell *matCellDef="let client">
<button
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"
mat-icon-button [matMenuTriggerFor]="clientMenu" color="primary">
<mat-icon>more_vert</mat-icon>
</button>
<button mat-menu-item (click)="onShowClientDetail($event, client)">
<mat-icon>visibility</mat-icon>
<span>{{ 'viewDetails' | translate }}</span>
</button>
<button mat-menu-item (click)="getStatus(client, selectedNode)">
<mat-icon>sync</mat-icon>
<span>{{ 'sync' | translate }}</span>
</button>
<button mat-menu-item (click)="onDeleteClick($event, client)">
<mat-icon>delete</mat-icon>
<span>{{ 'delete' | translate }}</span>
</button>
</mat-menu>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<app-execute-command [clientData]="[client]" [buttonType]="'icon'" [icon]="'terminal'"
[disabled]="selection.selected.length > 1 || (selection.selected.length === 1 && !selection.isSelected(client))"></app-execute-command>
<mat-menu #clientMenu="matMenu">
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
<mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span>
</button>
<button mat-menu-item (click)="onShowClientDetail($event, client)">
<mat-icon>visibility</mat-icon>
<span>{{ 'viewDetails' | translate }}</span>
</button>
<button mat-menu-item (click)="getStatus(client, selectedNode)">
<mat-icon>sync</mat-icon>
<span>{{ 'sync' | translate }}</span>
</button>
<button mat-menu-item (click)="onDeleteClick($event, client)">
<mat-icon>delete</mat-icon>
<span>{{ 'delete' | translate }}</span>
</button>
</mat-menu>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</section>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20, 50]" showFirstLastButtons></mat-paginator>
</div>
</div>

View File

@ -1,27 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef, MatDialog } from '@angular/material/dialog';
import { OperationResultDialogComponent } from './operation-result-dialog.component';
import {ShowClientsComponent} from "../show-clients/show-clients.component";
import {MatExpansionModule} from "@angular/material/expansion";
import {MatIconModule} from "@angular/material/icon";
import {MatDividerModule} from "@angular/material/divider";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatSelectModule} from "@angular/material/select";
import {MatPaginatorModule} from "@angular/material/paginator";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {FormsModule} from "@angular/forms";
import {MatInputModule} from "@angular/material/input";
import {MatDialog, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
import {MatTableModule} from "@angular/material/table";
import {TranslateModule} from "@ngx-translate/core";
import {JoyrideModule} from "ngx-joyride";
import {HttpClient} from "@angular/common/http";
import {ToastrService} from "ngx-toastr";
import {LoadingComponent} from "../../../shared/loading/loading.component";
import { MatExpansionModule } from "@angular/material/expansion";
import { MatIconModule } from "@angular/material/icon";
import { MatDividerModule } from "@angular/material/divider";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatSelectModule } from "@angular/material/select";
import { MatPaginatorModule } from "@angular/material/paginator";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { FormsModule } from "@angular/forms";
import { MatInputModule } from "@angular/material/input";
import { MatTableModule } from "@angular/material/table";
import { TranslateModule } from "@ngx-translate/core";
import { JoyrideModule } from "ngx-joyride";
import { HttpClient } from "@angular/common/http";
import { ToastrService } from "ngx-toastr";
import { LoadingComponent } from "../../../shared/loading/loading.component";
describe('OperationResultDialogComponent', () => {
let component: ShowClientsComponent;
let fixture: ComponentFixture<ShowClientsComponent>;
let component: OperationResultDialogComponent;
let fixture: ComponentFixture<OperationResultDialogComponent>;
let mockDialog: jasmine.SpyObj<MatDialog>;
let mockHttpClient: jasmine.SpyObj<HttpClient>;
let mockToastrService: jasmine.SpyObj<ToastrService>;
@ -29,17 +27,8 @@ describe('OperationResultDialogComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [OperationResultDialogComponent, LoadingComponent],
imports: [MatDialogModule],
providers: [
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: { success: [], errors: [] } }
]
})
.compileComponents();
await TestBed.configureTestingModule({
declarations: [ShowClientsComponent],
imports: [
MatDialogModule,
MatExpansionModule,
MatIconModule,
MatDividerModule,
@ -49,24 +38,21 @@ describe('OperationResultDialogComponent', () => {
BrowserAnimationsModule,
FormsModule,
MatInputModule,
MatDialogModule,
MatTableModule,
TranslateModule.forRoot(),
JoyrideModule.forRoot(),
],
providers: [
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: { success: [], errors: [] } },
{ provide: MatDialog, useValue: mockDialog },
{ provide: HttpClient, useValue: mockHttpClient },
{ provide: ToastrService, useValue: mockToastrService },
{
provide: MatDialogRef,
useValue: {}
},
],
})
.compileComponents();
fixture = TestBed.createComponent(ShowClientsComponent);
fixture = TestBed.createComponent(OperationResultDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
@ -74,4 +60,4 @@ describe('OperationResultDialogComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
});

View File

@ -13,10 +13,12 @@ import { MatTableModule } from "@angular/material/table";
import { TranslateModule } from "@ngx-translate/core";
import { JoyrideModule } from "ngx-joyride";
import { MatDialog, MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { HttpClient } from "@angular/common/http";
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';
import { ToastrService } from "ngx-toastr";
import { of } from "rxjs";
import { LoadingComponent } from '../../../shared/loading/loading.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; // Add this import
describe('ShowClientsComponent', () => {
let component: ShowClientsComponent;
@ -27,7 +29,6 @@ describe('ShowClientsComponent', () => {
beforeEach(async () => {
mockDialog = jasmine.createSpyObj('MatDialog', ['open']);
mockHttpClient = jasmine.createSpyObj('HttpClient', ['get', 'post', 'put', 'delete']);
mockToastrService = jasmine.createSpyObj('ToastrService', ['success', 'error']);
await TestBed.configureTestingModule({
@ -46,16 +47,17 @@ describe('ShowClientsComponent', () => {
MatTableModule,
TranslateModule.forRoot(),
JoyrideModule.forRoot(),
HttpClientTestingModule,
MatProgressSpinnerModule // Add this import
],
providers: [
{ provide: MatDialog, useValue: mockDialog },
{ provide: HttpClient, useValue: mockHttpClient },
{ provide: ToastrService, useValue: mockToastrService },
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: {} },
],
})
.compileComponents();
.compileComponents();
fixture = TestBed.createComponent(ShowClientsComponent);
component = fixture.componentInstance;
@ -65,4 +67,4 @@ describe('ShowClientsComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
});

View File

@ -1,5 +1,6 @@
mat-toolbar {
height: 7vh;
min-height: 60px;
background-color: #3f51b5;
color: white;
}