From e9b4411ea71191c841ca680d3004a54520d4f294 Mon Sep 17 00:00:00 2001 From: apuente Date: Thu, 5 Dec 2024 13:09:22 +0100 Subject: [PATCH] Refactor groups component to update filter option value and add sync functionality --- .../components/groups/groups.component.html | 85 ++++++----- .../app/components/groups/groups.component.ts | 141 +++++++++++------- .../src/app/components/groups/model/model.ts | 1 + ogWebconsole/src/locale/en.json | 3 +- ogWebconsole/src/locale/es.json | 18 ++- 5 files changed, 156 insertions(+), 92 deletions(-) diff --git a/ogWebconsole/src/app/components/groups/groups.component.html b/ogWebconsole/src/app/components/groups/groups.component.html index 85c1ad6..f7aa9d2 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.html +++ b/ogWebconsole/src/app/components/groups/groups.component.html @@ -22,33 +22,34 @@ - Filtros + {{ 'filters' | translate }}
- + {{ 'searchClient' | translate }} + + + + {{ savedFilter[0] }} - Buscar en el árbol - + {{ 'searchTree' | translate }} + - Filtrar por tipo - - Todos - Grupos de aulas - Aulas - Grupos de ordenadores + {{ 'filterByType' | translate }} + + {{ 'all' | translate }} + {{ 'classroomsGroup' | translate }} + {{ 'classrooms' | translate }} + {{ 'computerGroups' | translate }} - - Buscar cliente - - +
@@ -166,7 +167,7 @@ -
-

Clientes {{ selectedNode?.name ? 'del ' + selectedNode?.name : '' }}

+
+

{{ 'clients' | translate }} {{ selectedNode?.name ? ('del ' + selectedNode?.name) : '' }}

-
+
Client Icon
@@ -216,20 +217,20 @@
@@ -238,25 +239,25 @@
- +
- + - + - + - + - + + - + - + + + + + + + - + - - + +
Nombre Nombre {{ client.name }} IP IP {{ client.ip }} MAC MAC {{ client.mac }} OG Live OG Live {{ client.oglive }} Estado Estado - Mantenimiento Mantenimiento {{ client.mantenimiento }} Subred Subred {{ client.subnet }} Plantilla PXE Plantilla PXE {{ client.pxeTemplate }} Padre {{ client.parentName }} Acciones Acciones
diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index 96cf096..8f57a06 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -9,9 +9,8 @@ import { JoyrideService } from 'ngx-joyride'; import { FlatTreeControl } from '@angular/cdk/tree'; import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree'; import { Subscription } from 'rxjs'; - import { DataService } from './services/data.service'; -import { UnidadOrganizativa, Client, TreeNode, FlatNode, Command, Filter } from './model/model'; +import { UnidadOrganizativa, Client, TreeNode, FlatNode, Command } from './model/model'; import { CreateOrganizationalUnitComponent } from './shared/organizational-units/create-organizational-unit/create-organizational-unit.component'; import { CreateClientComponent } from './shared/clients/create-client/create-client.component'; import { EditOrganizationalUnitComponent } from './shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component'; @@ -23,6 +22,9 @@ import { ClientTabViewComponent } from './components/client-tab-view/client-tab- import { OrganizationalUnitTabViewComponent } from './components/organizational-unit-tab-view/organizational-unit-tab-view.component'; import { DeleteModalComponent } from '../../shared/delete_modal/delete-modal/delete-modal.component'; import { ClassroomViewDialogComponent } from './shared/classroom-view/classroom-view-modal'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { MatPaginator } from '@angular/material/paginator'; enum NodeType { OrganizationalUnit = 'organizational-unit', @@ -50,7 +52,7 @@ export class GroupsComponent implements OnInit, OnDestroy { selectedNode: TreeNode | null = null; commands: Command[] = []; commandsLoading = false; - selectedClients: Client[] = []; + selectedClients = new MatTableDataSource([]); cols = 4; selectedClientsOriginal: Client[] = []; currentView: 'card' | 'list' = 'list'; @@ -61,6 +63,28 @@ export class GroupsComponent implements OnInit, OnDestroy { syncingClientId: string | null = null; private originalTreeData: TreeNode[] = []; + + + displayedColumns: string[] = ['name', 'ip', 'mac', 'oglive', 'status', 'maintenace', 'subnet', 'pxeTemplate', 'parentName', 'actions']; + + private _sort!: MatSort; + private _paginator!: MatPaginator; + + @ViewChild(MatSort) + set matSort(ms: MatSort) { + this._sort = ms; + if (this.selectedClients) { + this.selectedClients.sort = this._sort; + } + } + + @ViewChild(MatPaginator) + set matPaginator(mp: MatPaginator) { + this._paginator = mp; + if (this.selectedClients) { + this.selectedClients.paginator = this._paginator; + } + } @ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent; @ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent; @@ -95,6 +119,16 @@ export class GroupsComponent implements OnInit, OnDestroy { this.getFilters(); this.updateGridCols(); window.addEventListener('resize', this.updateGridCols); + + this.selectedClients.filterPredicate = (client: Client, filter: string): boolean => { + const lowerTerm = filter.toLowerCase(); + return ( + client.name.toLowerCase().includes(lowerTerm) || + client.ip?.toLowerCase().includes(lowerTerm) || + client.status?.toLowerCase().includes(lowerTerm) || + client.mac?.toLowerCase().includes(lowerTerm) + ); + }; } ngOnDestroy(): void { @@ -124,7 +158,7 @@ export class GroupsComponent implements OnInit, OnDestroy { clearSelection(): void { this.selectedUnidad = null; this.selectedDetail = null; - this.selectedClients = []; + this.selectedClients.data = []; this.isTreeViewActive = false; } @@ -183,36 +217,46 @@ export class GroupsComponent implements OnInit, OnDestroy { onSelectUnidad(unidad: UnidadOrganizativa): void { this.selectedUnidad = unidad; this.selectedDetail = unidad; - this.selectedClients = this.collectAllClients(unidad); - this.selectedClientsOriginal = [...this.selectedClients]; + 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 || []; + let clients = (node.clients || []).map(client => ({ + ...client, + parentName: node.name + })); + if (node.children) { node.children.forEach((child) => { - clients = clients.concat(this.collectAllClients(child)); + clients = clients.concat(this.collectAllClients(child).map(client => ({ + ...client, + parentName: client.parentName || '' + }))); }); } return clients; } + private async loadChildrenAndClients(id: string): Promise { try { const childrenData = await this.dataService.getChildren(id).toPromise(); - + const processHierarchy = (nodes: UnidadOrganizativa[]): UnidadOrganizativa[] => { return nodes.map((node) => ({ ...node, children: node.children ? processHierarchy(node.children) : [], })); }; - + return { ...this.selectedUnidad!, children: childrenData ? processHierarchy(childrenData) : [], @@ -222,19 +266,19 @@ export class GroupsComponent implements OnInit, OnDestroy { return this.selectedUnidad!; } } - + private convertToTreeData(data: UnidadOrganizativa): TreeNode[] { - const processNode = (node: UnidadOrganizativa): TreeNode => ({ - name: node.name, - type: node.type, - '@id': node['@id'], - children: node.children?.map(processNode) || [], - hasClients: (node.clients?.length ?? 0) > 0, - }); - return [processNode(data)]; -} - + const processNode = (node: UnidadOrganizativa): TreeNode => ({ + name: node.name, + type: node.type, + '@id': node['@id'], + children: node.children?.map(processNode) || [], + hasClients: (node.clients?.length ?? 0) > 0, + }); + return [processNode(data)]; + } + onNodeClick(node: TreeNode): void { this.selectedNode = node; @@ -246,8 +290,15 @@ export class GroupsComponent implements OnInit, OnDestroy { this.subscriptions.add( this.http.get<{ clients: Client[] }>(`${this.baseUrl}${node['@id']}`).subscribe( (data) => { - this.selectedClientsOriginal = [...data.clients]; - this.selectedClients = data.clients || []; + const clientsWithParentName = (data.clients || []).map(client => ({ + ...client, + parentName: node.name + })); + this.selectedClients.data = clientsWithParentName; + this.selectedClients._updateChangeSubscription(); + if (this._paginator) { + this._paginator.firstPage(); + } }, (error) => { console.error('Error fetching clients:', error); @@ -255,11 +306,11 @@ export class GroupsComponent implements OnInit, OnDestroy { ) ); } else { - this.selectedClients = []; - this.selectedClientsOriginal = []; + this.selectedClients.data = []; + this.selectedClients._updateChangeSubscription(); } } - + getNodeIcon(node: TreeNode): string { switch (node.type) { case NodeType.OrganizationalUnit: @@ -309,11 +360,11 @@ export class GroupsComponent implements OnInit, OnDestroy { this.organizationalUnits = data; if (this.selectedUnidad) { this.loadChildrenAndClients(this.selectedUnidad?.id || '').then((updatedData) => { - this.selectedUnidad = updatedData; + this.selectedUnidad = updatedData; const treeData = this.convertToTreeData(updatedData); this.originalTreeData = treeData[0]?.children || []; this.treeDataSource.data = [...this.originalTreeData]; - }); + }); } }, (error) => console.error('Error fetching organizational units', error) @@ -333,9 +384,9 @@ export class GroupsComponent implements OnInit, OnDestroy { } } - onDeleteClick(event: MouseEvent, node: TreeNode | null, clientNode?: TreeNode | null): void{ + onDeleteClick(event: MouseEvent, node: TreeNode | null, clientNode?: TreeNode | null): void { event.stopPropagation(); - const uuid = node ? this.extractUuid(node['@id']) : null; + const uuid = node ? this.extractUuid(node['@id']) : null; if (!uuid) return; if (!node) return; @@ -371,7 +422,7 @@ export class GroupsComponent implements OnInit, OnDestroy { private refreshClientsForNode(node: TreeNode): void { if (!node['@id']) { - this.selectedClients = []; + this.selectedClients.data = []; return; } this.fetchClientsForNode(node); @@ -420,7 +471,7 @@ export class GroupsComponent implements OnInit, OnDestroy { } executeCommand(command: Command, selectedNode: TreeNode | null): void { - + if (!selectedNode) { this.toastr.error('No hay un nodo seleccionado.'); return; @@ -474,19 +525,19 @@ export class GroupsComponent implements OnInit, OnDestroy { const matchesName = node.name.toLowerCase().includes(searchTerm.toLowerCase()); const matchesType = filterType ? node.type.toLowerCase() === filterType.toLowerCase() : true; const filteredChildren = node.children ? filterNodes(node.children) : []; - + if ((matchesName && matchesType) || filteredChildren.length > 0) { filteredNodes.push({ ...node, children: filteredChildren }); } } return filteredNodes; }; - + const filteredData = filterNodes(this.originalTreeData); this.treeDataSource.data = filteredData; } - - + + onTreeFilterInput(event: Event): void { const input = event.target as HTMLInputElement; @@ -501,23 +552,11 @@ export class GroupsComponent implements OnInit, OnDestroy { } filterClients(searchTerm: string): void { - if (!searchTerm) { - this.selectedClients = [...this.selectedClientsOriginal]; - return; - } - - const lowerTerm = searchTerm.toLowerCase(); - - this.selectedClients = this.selectedClientsOriginal.filter((client) => { - return ( - client.name.toLowerCase().includes(lowerTerm) || - client.ip?.toLowerCase().includes(lowerTerm) || - client.status?.toLowerCase().includes(lowerTerm) || - client.mac?.toLowerCase().includes(lowerTerm) - ); - }); + this.searchTerm = searchTerm.trim().toLowerCase(); + this.selectedClients.filter = this.searchTerm; } + public setSelectedNode(node: TreeNode): void { this.selectedNode = node; } diff --git a/ogWebconsole/src/app/components/groups/model/model.ts b/ogWebconsole/src/app/components/groups/model/model.ts index 7789157..39f747a 100644 --- a/ogWebconsole/src/app/components/groups/model/model.ts +++ b/ogWebconsole/src/app/components/groups/model/model.ts @@ -44,6 +44,7 @@ export interface Client { createdAt: string; createdBy: string; uuid: string; + parentName?: string; } export interface ClientCollection { diff --git a/ogWebconsole/src/locale/en.json b/ogWebconsole/src/locale/en.json index 59fe4cd..d73f805 100644 --- a/ogWebconsole/src/locale/en.json +++ b/ogWebconsole/src/locale/en.json @@ -420,5 +420,6 @@ "TOOLTIP_MENUS": "Menu management (option disabled)", "search": "Search", "TOOLTIP_SEARCH": "Search function (option disabled)", - "detailsOf": "Details of" + "detailsOf": "Details of", + "filters": "Filters" } diff --git a/ogWebconsole/src/locale/es.json b/ogWebconsole/src/locale/es.json index b13e8b4..eec7c10 100644 --- a/ogWebconsole/src/locale/es.json +++ b/ogWebconsole/src/locale/es.json @@ -424,5 +424,21 @@ "detailsOf": "Detalles de", "editUnitMenu": "Editar", "addInternalUnitMenu": "Añadir", - "addClientMenu": "Añadir cliente" + "addClientMenu": "Añadir cliente", + "filters": "Filtros", + "searchClient": "Buscar cliente", + "searchTree": "Buscar en árbol", + "filterByType": "Filtrar por tipo", + "all": "Todos", + "classroomsGroup": "Grupos de aulas", + "classrooms": "Aulas", + "computerGroups": "Grupos de PCs", + "executeCommand": "Ejecutar comando", + "roomMap": "Plano de aula", + "addOrganizationalUnit": "Añadir unidad organizativa", + "edit": "Editar", + "delete": "Eliminar", + "clients": "Clientes", + "sync": "Sincronizar", + "viewDetails": "Ver detalles" }