refs #1321 Unit's view discarded. Tree view becomes main view.

pull/10/head
Lucas Lara García 2025-01-13 11:29:16 +01:00
parent d689583b56
commit 87f436624c
3 changed files with 268 additions and 305 deletions

View File

@ -487,12 +487,6 @@ button[mat-raised-button] {
flex-direction: column;
}
.view-toggle-container {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
}
.clients-grid {
display: flex;
flex-wrap: wrap;
@ -518,23 +512,10 @@ button[mat-raised-button] {
margin-bottom: 0.5rem;
}
.header-actions-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.back-button {
flex-shrink: 0;
}
.view-toggle-container {
display: flex;
gap: 1rem;
align-items: center;
}
.filters-container {
display: flex;
flex-wrap: wrap;
@ -595,10 +576,17 @@ button[mat-raised-button] {
margin-top: 4px;
}
.clients-view-header {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
align-items: center;
}
.clients-title-name {
font-size: x-large;
display: block;
margin-bottom: 1.5rem;
padding: 1rem 1rem 1rem 15px;
}
.no-clients-info {

View File

@ -56,214 +56,124 @@
</div>
</mat-expansion-panel>
<!-- Main units cards -->
<div *ngIf="!selectedUnidad; else detailsTemplate" class="card-container" joyrideStep="organizationalUnitsStep" text="{{ 'organizationalUnitsStepText' | translate }}">
<mat-card *ngFor="let unidad of organizationalUnits"
[ngClass]="{'selected-item': unidad === selectedUnidad, 'clickable-item': true}"
(click)="onSelectUnidad(unidad)" class="unidad-card small-card">
<mat-card-header>
<mat-card-title>
<mat-icon>apartment</mat-icon> {{ unidad.name }}
</mat-card-title>
</mat-card-header>
<mat-card-actions>
<div class="button-container">
<button mat-raised-button color="primary" [matMenuTriggerFor]="menu" (click)="$event.stopPropagation()">
<mat-icon>menu</mat-icon>
{{ 'Menu' | translate }}
<!-- Unit details view-->
<div class="main-container">
<!-- Tree view -->
<div class="tree-container">
<mat-tree [dataSource]="treeDataSource" [treeControl]="treeControl">
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding (click)="onNodeClick(node)">
<button mat-icon-button matTreeNodeToggle [disabled]="!node.expandable" [ngClass]="{'disabled-toggle': !node.expandable}">
<mat-icon>{{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}</mat-icon>
</button>
<mat-icon class="node-icon {{ node.type }}">
{{
node.type === 'organizational-unit' ? 'apartment'
: node.type === 'classrooms-group' ? 'meeting_room'
: node.type === 'classroom' ? 'school'
: node.type === 'clients-group' ? 'lan'
: node.type === 'client' ? 'computer'
: 'group'
}}
</mat-icon>
<span>{{ node.name }}</span>
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="onNodeClick(node)">
<mat-icon>more_vert</mat-icon>
</button>
</mat-tree-node>
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: isLeafNode" matTreeNodePadding (click)="onNodeClick(node)">
<button mat-icon-button matTreeNodeToggle [disabled]="true" class="disabled-toggle"></button>
<mat-icon style="color: green;">
{{
node.type === 'organizational-unit' ? 'apartment'
: node.type === 'classrooms-group' ? 'meeting_room'
: node.type === 'classroom' ? 'school'
: node.type === 'clients-group' ? 'lan'
: node.type === 'client' ? 'computer'
: 'group'
}}
</mat-icon>
<span>{{ node.name }}</span>
<ng-container *ngIf="node.type === 'client'">
<span> - IP: {{ node.ip }}</span>
</ng-container>
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="onNodeClick(node)">
<mat-icon>more_vert</mat-icon>
</button>
</mat-tree-node>
</mat-tree>
</div>
<mat-divider [vertical]="true"></mat-divider>
<!-- Tree node actions -->
<mat-menu restoreFocus=false #commandMenu="matMenu">
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)">
<span>{{ command.name }}</span>
</button>
</mat-menu>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onShowDetailsClick($event, selectedNode)">
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
<span>{{ 'viewUnitMenu' | translate }}</span>
</button>
<button *ngIf="selectedNode?.type === 'classroom'" mat-menu-item (click)="onRoomMap(selectedNode)">
<mat-icon>map</mat-icon>
<span>{{ 'roomMap' | translate }}</span>
</button>
<button mat-menu-item (click)="addClient($event, selectedNode)">
<mat-icon>add</mat-icon>
<span>{{ 'addClientMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="addOU($event, selectedNode)">
<mat-icon>playlist_add</mat-icon>
<span>{{ 'addOrganizationalUnit' | translate }}</span>
</button>
<button mat-menu-item (click)="onEditNode($event, selectedNode)">
<mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span>
</button>
<button mat-menu-item (click)="selectedNode && onTreeClick($event, selectedNode)">
<mat-icon matTooltip="{{ 'viewTreeTooltip' | translate }}" matTooltipHideDelay="0">account_tree</mat-icon>
<span>{{ 'viewTreeMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)">
<mat-icon>delete</mat-icon>
<span>{{ 'delete' | translate }}</span>
</button>
</mat-menu>
<!-- Clients view -->
<div class="clients-container">
<div class="clients-view-header">
<span class="clients-title-name">{{ 'clients' | translate }}
<strong>{{ selectedNode?.name }}</strong>
</span>
<div class="view-type-container">
<button mat-button color="primary" (click)="toggleView('card')" [disabled]="currentView === 'card'">
<mat-icon>grid_view</mat-icon> {{ 'Vista Tarjeta' | translate }}
</button>
<button mat-button color="primary" (click)="toggleView('list')" [disabled]="currentView === 'list'">
<mat-icon>list</mat-icon> {{ 'Vista Lista' | translate }}
</button>
</div>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onEditClick($event, unidad.type, unidad.uuid)">
<mat-icon matTooltip="{{ 'editUnitTooltip' | translate }}" matTooltipHideDelay="0">edit</mat-icon>
<span>{{ 'editUnitMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="onShowDetailsClick($event, unidad)">
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
<span>{{ 'viewUnitMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="addOU($event, unidad)">
<mat-icon matTooltip="{{ 'addInternalUnitTooltip' | translate }}" matTooltipHideDelay="0">add_home_work</mat-icon>
<span>{{ 'addInternalUnitMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="addClient($event, unidad)">
<mat-icon matTooltip="{{ 'addClientTooltip' | translate }}" matTooltipHideDelay="0">devices</mat-icon>
<span>{{ 'addClientMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="onTreeClick($event, unidad)">
<mat-icon matTooltip="{{ 'viewTreeTooltip' | translate }}" matTooltipHideDelay="0">account_tree</mat-icon>
<span>{{ 'viewTreeMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="onDeleteClick($event, unidad)">
<mat-icon>delete</mat-icon>
<span>{{ 'delete' | translate }}</span>
</button>
</mat-menu>
</mat-card-actions>
</mat-card>
</div>
<!-- Unit details view-->
<ng-template #detailsTemplate>
<!-- Header -->
<div class="header-actions-container">
<button mat-raised-button color="primary" (click)="clearSelection()" class="back-button">
<mat-icon>arrow_back</mat-icon>
{{ 'Back' | translate }}
</button>
<div class="view-toggle-container" *ngIf="selectedDetail">
<button mat-button color="primary" (click)="toggleView('card')" [disabled]="currentView === 'card'">
<mat-icon>grid_view</mat-icon> {{ 'Vista Tarjeta' | translate }}
</button>
<button mat-button color="primary" (click)="toggleView('list')" [disabled]="currentView === 'list'">
<mat-icon>list</mat-icon> {{ 'Vista Lista' | translate }}
</button>
</div>
</div>
<div class="main-container">
<!-- Tree view -->
<div class="tree-container">
<h2>{{ selectedUnidad?.name }}</h2>
<mat-tree [dataSource]="treeDataSource" [treeControl]="treeControl">
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding (click)="onNodeClick(node)">
<button mat-icon-button matTreeNodeToggle [disabled]="!node.expandable" [ngClass]="{'disabled-toggle': !node.expandable}">
<mat-icon>{{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}</mat-icon>
</button>
<mat-icon class="node-icon {{ node.type }}">
{{
node.type === 'organizational-unit' ? 'apartment'
: node.type === 'classrooms-group' ? 'meeting_room'
: node.type === 'classroom' ? 'school'
: node.type === 'clients-group' ? 'lan'
: node.type === 'client' ? 'computer'
: 'group'
}}
</mat-icon>
<span>{{ node.name }}</span>
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="onNodeClick(node)">
<mat-icon>more_vert</mat-icon>
</button>
</mat-tree-node>
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: isLeafNode" matTreeNodePadding (click)="onNodeClick(node)">
<button mat-icon-button matTreeNodeToggle [disabled]="true" class="disabled-toggle"></button>
<mat-icon style="color: green;">
{{
node.type === 'organizational-unit' ? 'apartment'
: node.type === 'classrooms-group' ? 'meeting_room'
: node.type === 'classroom' ? 'school'
: node.type === 'clients-group' ? 'lan'
: node.type === 'client' ? 'computer'
: 'group'
}}
</mat-icon>
<span>{{ node.name }}</span>
<ng-container *ngIf="node.type === 'client'">
<span> - IP: {{ node.ip }}</span>
</ng-container>
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="onNodeClick(node)">
<mat-icon>more_vert</mat-icon>
</button>
</mat-tree-node>
</mat-tree>
</div>
<mat-divider [vertical]="true"></mat-divider>
<div *ngIf="(selectedClients.data?.length || 0) > 0; else noClientsTemplate">
<!-- Cards view -->
<div class="clients-grid" *ngIf="currentView === 'card'">
<div *ngFor="let client of selectedClients.data" class="client-item">
<div class="client-card">
<img
[src]="'assets/images/ordenador_' + client.status + '.png'"
alt="Client Icon"
class="client-image" />
<!-- Tree node actions -->
<mat-menu restoreFocus=false #commandMenu="matMenu">
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)">
<span>{{ command.name }}</span>
</button>
</mat-menu>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="onShowDetailsClick($event, selectedNode)">
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
<span>{{ 'viewUnitMenu' | translate }}</span>
</button>
<button *ngIf="selectedNode?.type === 'classroom'" mat-menu-item (click)="onRoomMap(selectedNode)">
<mat-icon>map</mat-icon>
<span>{{ 'roomMap' | translate }}</span>
</button>
<button mat-menu-item (click)="addClient($event, selectedNode)">
<mat-icon>add</mat-icon>
<span>{{ 'addClientMenu' | translate }}</span>
</button>
<button mat-menu-item (click)="addOU($event, selectedNode)">
<mat-icon>playlist_add</mat-icon>
<span>{{ 'addOrganizationalUnit' | translate }}</span>
</button>
<button mat-menu-item (click)="onEditNode($event, selectedNode)">
<mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span>
</button>
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)">
<mat-icon>delete</mat-icon>
<span>{{ 'delete' | translate }}</span>
</button>
</mat-menu>
<div class="client-details">
<span class="client-name">{{ client.name }}</span>
<span class="client-ip">{{ client.ip }}</span>
<span class="client-ip">{{ client.mac }}</span>
<!-- Clients view -->
<div class="clients-container">
<span class="clients-title-name">{{ 'clients' | translate }}
<strong>{{ selectedNode?.name ? ' ' + selectedNode?.name : ' ' + selectedUnidad?.name }}</strong>
</span>
<mat-divider></mat-divider>
<div *ngIf="(selectedClients.data?.length || 0) > 0; else noClientsTemplate">
<!-- Cards view -->
<div class="clients-grid" *ngIf="currentView === 'card'">
<div *ngFor="let client of selectedClients.data" class="client-item">
<div class="client-card">
<img
[src]="'assets/images/ordenador_' + client.status + '.png'"
alt="Client Icon"
class="client-image" />
<div class="client-details">
<span class="client-name">{{ client.name }}</span>
<span class="client-ip">{{ client.ip }}</span>
<span class="client-ip">{{ client.mac }}</span>
<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>
<button mat-icon-button color="primary" (click)="onShowClientDetail($event, client)">
<mat-icon>visibility</mat-icon>
</button>
<app-execute-command [clientData]="client['@id']"></app-execute-command>
</div>
</div>
</div>
</div>
</div>
<!-- List view -->
<div class="clients-table" *ngIf="currentView === 'list'">
<table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8">
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
<td mat-cell *matCellDef="let client">
<img
[src]="'assets/images/ordenador_' + client.status + '.png'"
alt="Client Icon"
class="client-image" />
</td>
</ng-container>
<ng-container matColumnDef="sync">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'sync' | translate }} </th>
<td mat-cell *matCellDef="let client">
<div class="action-icons">
<button
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
mat-icon-button color="primary"
@ -276,78 +186,120 @@
mat-icon-button color="primary">
<mat-spinner diameter="24"></mat-spinner>
</button>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
<td mat-cell *matCellDef="let client">
<div class="client-info">
<div class="client-name">{{ client.name }}</div>
<div class="client-ip">{{ client.ip }}</div>
<div class="client-ip">{{ client.mac }}</div>
</div>
</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?.filename || '').slice(0, 15) }}{{ (client.ogLive?.filename?.length > 15) ? '...' : '' }} </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="actions" >
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
<td mat-cell *matCellDef="let client">
<button mat-icon-button [matMenuTriggerFor]="clientMenu">
<mat-icon>more_vert</mat-icon>
<button mat-icon-button color="primary" (click)="onShowClientDetail($event, client)">
<mat-icon>visibility</mat-icon>
</button>
<app-execute-command [clientData]="client['@id']"></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)="onDeleteClick($event, client, selectedNode)">
<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>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- List view -->
<div class="clients-table" *ngIf="currentView === 'list'">
<table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8">
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
<td mat-cell *matCellDef="let client">
<img
[src]="'assets/images/ordenador_' + client.status + '.png'"
alt="Client Icon"
class="client-image" />
</td>
</ng-container>
<!-- No clients view -->
<ng-template #noClientsTemplate>
<div class="no-clients-info">
<mat-icon>error_outline</mat-icon>
<span>{{ 'noClients' | translate }}</span>
<ng-container matColumnDef="sync">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'sync' | translate }} </th>
<td mat-cell *matCellDef="let client">
<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>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
<td mat-cell *matCellDef="let client">
<div class="client-info">
<div class="client-name">{{ client.name }}</div>
<div class="client-ip">{{ client.ip }}</div>
<div class="client-ip">{{ client.mac }}</div>
</div>
</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?.filename || '').slice(0, 15) }}{{ (client.ogLive?.filename?.length > 15) ? '...' : '' }} </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="actions" >
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
<td mat-cell *matCellDef="let client">
<button mat-icon-button [matMenuTriggerFor]="clientMenu">
<mat-icon>more_vert</mat-icon>
</button>
<app-execute-command [clientData]="client['@id']"></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)="onDeleteClick($event, client, selectedNode)">
<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>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
</ng-template>
</div>
</div>
<!-- No clients view -->
<ng-template #noClientsTemplate>
<div *ngIf="isLoadingClients" class="loading-container">
<mat-spinner></mat-spinner>
</div>
<div *ngIf="!isLoadingClients" class="no-clients-info">
<mat-icon>error_outline</mat-icon>
<span>{{ 'noClients' | translate }}</span>
</div>
</ng-template>
</div>

View File

@ -43,6 +43,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
selectedUnidad: UnidadOrganizativa | null = null;
selectedDetail: UnidadOrganizativa | null = null;
loading = false;
isLoadingClients: boolean = false;
searchTerm = '';
treeControl: FlatTreeControl<FlatNode>;
treeFlattener: MatTreeFlattener<TreeNode, FlatNode>;
@ -112,6 +113,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
this.search();
this.getFilters();
this.updateGridCols();
this.loadOrganizationalUnits();
window.addEventListener('resize', this.updateGridCols);
this.selectedClients.filterPredicate = (client: Client, filter: string): boolean => {
@ -141,6 +143,40 @@ export class GroupsComponent implements OnInit, OnDestroy {
'@id': node['@id'],
});
private loadOrganizationalUnits(): void {
this.loading = true;
this.isLoadingClients = true;
this.dataService.getOrganizationalUnits().subscribe(
(data) => {
this.organizationalUnits = data;
this.loading = false;
if (this.organizationalUnits.length > 0) {
const treeData = this.organizationalUnits.map((unidad) => this.convertToTreeData(unidad));
this.treeDataSource.data = treeData.flat();
this.isTreeViewActive = true;
const firstNode = this.treeDataSource.data[0];
if (firstNode) {
this.selectedNode = firstNode;
this.fetchClientsForNode(firstNode);
}
} else {
this.toastr.info('No existen unidades organizativas');
this.isTreeViewActive = false;
this.isLoadingClients = false;
return;
}
},
(error) => {
console.error('Error fetching organizational units', error);
this.loading = false;
}
);
}
toggleView(view: 'card' | 'list'): void {
this.currentView = view;
}
@ -202,20 +238,6 @@ export class GroupsComponent implements OnInit, OnDestroy {
);
}
onSelectUnidad(unidad: UnidadOrganizativa): void {
this.selectedUnidad = unidad;
this.selectedDetail = unidad;
this.selectedClients.data = this.collectAllClients(unidad);
this.selectedClientsOriginal = [...this.selectedClients.data];
this.loadChildrenAndClients(unidad.id).then((fullData) => {
const treeData = this.convertToTreeData(fullData);
this.treeDataSource.data = treeData[0]?.children || [];
});
this.isTreeViewActive = true;
console.log('Selected unidad:', unidad);
}
private collectAllClients(node: UnidadOrganizativa): Client[] {
let clients = (node.clients || []).map(client => ({
...client,
@ -277,13 +299,14 @@ export class GroupsComponent implements OnInit, OnDestroy {
private fetchClientsForNode(node: TreeNode): void {
console.log('Node:', node);
this.isLoadingClients = true;
this.http.get<any>(`${this.baseUrl}/clients?organizationalUnit.id=${node.id}`).subscribe({
next: (response) => {
this.selectedClients.data = response['hydra:member'];
this.loading = false;
this.isLoadingClients = false;
},
error: () => {
this.loading = false;
this.isLoadingClients = false;
}
});
}
@ -502,7 +525,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
iniciarTour(): void {
this.joyrideService.startTour({
steps: ['groupsTitleStepText', 'filtersPanelStep', 'organizationalUnitsStep', 'addStep', 'keyStep', 'unitStep', 'elementsStep', 'tabsStep'],
steps: ['groupsTitleStepText', 'filtersPanelStep', 'addStep', 'keyStep', 'tabsStep'],
showPrevButton: true,
themeColor: '#3f51b5',
});