Refactor groups component
parent
a6797f8f77
commit
21078a8ab0
|
@ -593,3 +593,16 @@ button[mat-raised-button] {
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filters-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap; /* Permite que los elementos pasen a la siguiente línea si no caben */
|
||||||
|
gap: 16px; /* Espaciado entre los elementos */
|
||||||
|
margin: 16px 0; /* Separación con otros elementos */
|
||||||
|
padding: 0 16px; /* Opcional, para añadir un poco de espacio interno */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters-container mat-form-field {
|
||||||
|
flex: 1 1 300px; /* Toma todo el ancho disponible hasta 300px por elemento */
|
||||||
|
max-width: 300px; /* Limita el ancho máximo */
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<mat-tab-group (selectedTabChange)="onTabChange($event)">
|
<!-- <mat-tab-group (selectedTabChange)="onTabChange($event)">
|
||||||
<mat-tab label="{{ 'generalTabLabel' | translate }}">
|
<mat-tab label="{{ 'generalTabLabel' | translate }}"> -->
|
||||||
|
|
||||||
<!-- HEADER -->
|
<!-- HEADER -->
|
||||||
<div class="header-container" joyrideStep="tabsStep" text="{{ 'tabsStepText' | translate }}">
|
<div class="header-container" joyrideStep="tabsStep" text="{{ 'tabsStepText' | translate }}">
|
||||||
|
@ -23,7 +23,51 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
</div>
|
</div>
|
||||||
|
<mat-expansion-panel *ngIf="isTreeViewActive" class="filters-panel">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
Filtros
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<!-- Contenedor de filtros -->
|
||||||
|
<div class="filters-container">
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-select (selectionChange)="loadSelectedFilter($event.value)" placeholder="Cargar filtro">
|
||||||
|
<mat-option *ngFor="let savedFilter of savedFilterNames" [value]="savedFilter">
|
||||||
|
{{ savedFilter[0] }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Buscar en el árbol</mat-label>
|
||||||
|
<input matInput (input)="onTreeFilterInput($event)" placeholder="Buscar nombre o tipo">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Filtrar por tipo</mat-label>
|
||||||
|
<mat-select [(value)]="selectedTreeFilter" (selectionChange)="filterTree(searchTerm, $event.value)">
|
||||||
|
<mat-option [value]="">Todos</mat-option>
|
||||||
|
<mat-option value="organizational-unit">Unidades Organizativas</mat-option>
|
||||||
|
<mat-option value="classroom">Aulas</mat-option>
|
||||||
|
<mat-option value="client">Clientes</mat-option>
|
||||||
|
<mat-option value="group">Grupos</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>Buscar cliente</mat-label>
|
||||||
|
<input matInput (input)="onClientFilterInput($event)" placeholder="Buscar nombre, IP, estado o MAC">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- LAS CARDS DE LAS FACULTADES -->
|
<!-- LAS CARDS DE LAS FACULTADES -->
|
||||||
|
|
||||||
|
@ -44,10 +88,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<mat-menu #menu="matMenu">
|
<mat-menu #menu="matMenu">
|
||||||
<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)="onEditClick($event, unidad.type, unidad.uuid)">
|
<button mat-menu-item (click)="onEditClick($event, unidad.type, unidad.uuid)">
|
||||||
<mat-icon matTooltip="{{ 'editUnitTooltip' | translate }}" matTooltipHideDelay="0">edit</mat-icon>
|
<mat-icon matTooltip="{{ 'editUnitTooltip' | translate }}" matTooltipHideDelay="0">edit</mat-icon>
|
||||||
<span>{{ 'editUnitMenu' | translate }}</span>
|
<span>{{ 'editUnitMenu' | translate }}</span>
|
||||||
|
@ -65,7 +106,10 @@
|
||||||
<mat-icon matTooltip="{{ 'addClientTooltip' | translate }}" matTooltipHideDelay="0">devices</mat-icon>
|
<mat-icon matTooltip="{{ 'addClientTooltip' | translate }}" matTooltipHideDelay="0">devices</mat-icon>
|
||||||
<span>{{ 'addClientMenu' | translate }}</span>
|
<span>{{ 'addClientMenu' | translate }}</span>
|
||||||
</button>
|
</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)">
|
<button mat-menu-item (click)="onDeleteClick($event, unidad)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>Delete</span>
|
<span>Delete</span>
|
||||||
|
@ -86,7 +130,7 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Botones de alternancia -->
|
<!-- Botones de alternancia -->
|
||||||
<div class="view-toggle-container">
|
<div class="view-toggle-container" *ngIf="selectedDetail">
|
||||||
<button mat-button color="primary" (click)="toggleView('card')" [disabled]="currentView === 'card'">
|
<button mat-button color="primary" (click)="toggleView('card')" [disabled]="currentView === 'card'">
|
||||||
<mat-icon>grid_view</mat-icon> {{ 'Vista Tarjeta' | translate }}
|
<mat-icon>grid_view</mat-icon> {{ 'Vista Tarjeta' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -112,12 +156,11 @@
|
||||||
</button>
|
</button>
|
||||||
<mat-icon class="node-icon {{ node.type }}">
|
<mat-icon class="node-icon {{ node.type }}">
|
||||||
{{
|
{{
|
||||||
node.type === 'organizational-unit'
|
node.type === 'organizational-unit' ? 'apartment'
|
||||||
? 'apartment'
|
: node.type === 'classrooms-group' ? 'meeting_room'
|
||||||
: node.type === 'classroom'
|
: node.type === 'classroom' ? 'school'
|
||||||
? 'school'
|
: node.type === 'clients-group' ? 'lan'
|
||||||
: node.type === 'client'
|
: node.type === 'client' ? 'computer'
|
||||||
? 'computer'
|
|
||||||
: 'group'
|
: 'group'
|
||||||
}}
|
}}
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
|
@ -140,14 +183,14 @@
|
||||||
'pc-off': node.type === 'client' && node.status === 'off'
|
'pc-off': node.type === 'client' && node.status === 'off'
|
||||||
}">
|
}">
|
||||||
{{
|
{{
|
||||||
node.type === 'organizational-unit'
|
node.type === 'organizational-unit' ? 'apartment'
|
||||||
? 'apartment'
|
: node.type === 'classrooms-group' ? 'meeting_room'
|
||||||
: node.type === 'classroom'
|
: node.type === 'classroom' ? 'school'
|
||||||
? 'school'
|
: node.type === 'clients-group' ? 'lan'
|
||||||
: node.type === 'client'
|
: node.type === 'client' ? 'computer'
|
||||||
? 'computer'
|
|
||||||
: 'group'
|
: 'group'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
<span>{{ node.name }}</span>
|
<span>{{ node.name }}</span>
|
||||||
<ng-container *ngIf="node.type === 'client'">
|
<ng-container *ngIf="node.type === 'client'">
|
||||||
|
@ -331,7 +374,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<!-- FIN DEL TAB -->
|
<!-- FIN DEL TAB -->
|
||||||
</mat-tab>
|
<!-- </mat-tab>
|
||||||
|
|
||||||
<mat-tab label="{{ 'advancedSearchTabLabel' | translate }}">
|
<mat-tab label="{{ 'advancedSearchTabLabel' | translate }}">
|
||||||
<app-advanced-search></app-advanced-search>
|
<app-advanced-search></app-advanced-search>
|
||||||
|
@ -344,4 +387,4 @@
|
||||||
<mat-tab label="{{ 'organizationalUnitsTabLabel' | translate }}">
|
<mat-tab label="{{ 'organizationalUnitsTabLabel' | translate }}">
|
||||||
<app-organizational-unit-tab-view #organizationalUnitTab></app-organizational-unit-tab-view>
|
<app-organizational-unit-tab-view #organizationalUnitTab></app-organizational-unit-tab-view>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group> -->
|
|
@ -64,8 +64,10 @@ export class GroupsComponent implements OnInit {
|
||||||
commandsLoading: boolean = false;
|
commandsLoading: boolean = false;
|
||||||
selectedClients: any[] = [];
|
selectedClients: any[] = [];
|
||||||
cols: number = 4;
|
cols: number = 4;
|
||||||
|
selectedClientsOriginal: any[] = [];
|
||||||
currentView: 'card' | 'list' = 'list';
|
currentView: 'card' | 'list' = 'list';
|
||||||
|
isTreeViewActive: boolean = false;
|
||||||
|
savedFilterNames: any[] = [];
|
||||||
|
|
||||||
@ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent;
|
@ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent;
|
||||||
@ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent;
|
@ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent;
|
||||||
|
@ -121,6 +123,7 @@ export class GroupsComponent implements OnInit {
|
||||||
this.selectedUnidad = null;
|
this.selectedUnidad = null;
|
||||||
this.selectedDetail = null;
|
this.selectedDetail = null;
|
||||||
this.selectedClients = [];
|
this.selectedClients = [];
|
||||||
|
this.isTreeViewActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onTabChange(event: MatTabChangeEvent): void {
|
onTabChange(event: MatTabChangeEvent): void {
|
||||||
|
@ -133,11 +136,30 @@ export class GroupsComponent implements OnInit {
|
||||||
|
|
||||||
getFilters(): void {
|
getFilters(): void {
|
||||||
this.dataService.getFilters().subscribe(
|
this.dataService.getFilters().subscribe(
|
||||||
data => {},
|
data => {
|
||||||
error => console.error('Error fetching filters:', error)
|
this.savedFilterNames = data.map((filter: any) => [filter.name, filter.uuid]);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.error('Error fetching filters:', error);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadSelectedFilter(savedFilter: any) {
|
||||||
|
const url = `${this.baseUrl}/views/` + savedFilter[1];
|
||||||
|
console.log('llamando a:', url);
|
||||||
|
|
||||||
|
this.dataService.getFilter(savedFilter[1]).subscribe(response => {
|
||||||
|
console.log('Response from server:', response.filters);
|
||||||
|
if (response) {
|
||||||
|
console.log('Filter1:', response.filters);
|
||||||
|
}
|
||||||
|
}, error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
search(): void {
|
search(): void {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.dataService.getOrganizationalUnits(this.searchTerm).subscribe(
|
this.dataService.getOrganizationalUnits(this.searchTerm).subscribe(
|
||||||
|
@ -160,6 +182,7 @@ export class GroupsComponent implements OnInit {
|
||||||
const treeData = this.convertToTreeData(fullData);
|
const treeData = this.convertToTreeData(fullData);
|
||||||
this.treeDataSource.data = treeData[0]?.children || [];
|
this.treeDataSource.data = treeData[0]?.children || [];
|
||||||
});
|
});
|
||||||
|
this.isTreeViewActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadChildrenAndClients(id: string): Promise<any> {
|
async loadChildrenAndClients(id: string): Promise<any> {
|
||||||
|
@ -204,6 +227,7 @@ export class GroupsComponent implements OnInit {
|
||||||
const url = `${this.baseUrl}${node['@id']}`;
|
const url = `${this.baseUrl}${node['@id']}`;
|
||||||
this.http.get(url).subscribe(
|
this.http.get(url).subscribe(
|
||||||
(data: any) => {
|
(data: any) => {
|
||||||
|
this.selectedClientsOriginal = [...data.clients];
|
||||||
this.selectedClients = data.clients || [];
|
this.selectedClients = data.clients || [];
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
@ -212,13 +236,17 @@ export class GroupsComponent implements OnInit {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.selectedClients = [];
|
this.selectedClients = [];
|
||||||
|
this.selectedClientsOriginal = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getNodeIcon(node: any): string {
|
getNodeIcon(node: any): string {
|
||||||
|
console.log('Node:', node);
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'organizational-unit': return 'apartment';
|
case 'organizational-unit': return 'apartment';
|
||||||
|
case 'classrooms-group': return 'doors';
|
||||||
case 'classroom': return 'school';
|
case 'classroom': return 'school';
|
||||||
|
case 'clients-group': return 'lan';
|
||||||
case 'client': return 'computer';
|
case 'client': return 'computer';
|
||||||
default: return 'group';
|
default: return 'group';
|
||||||
}
|
}
|
||||||
|
@ -437,4 +465,66 @@ export class GroupsComponent implements OnInit {
|
||||||
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
|
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
|
||||||
isLeafNode = (_: number, node: FlatNode): boolean => !node.expandable;
|
isLeafNode = (_: number, node: FlatNode): boolean => !node.expandable;
|
||||||
|
|
||||||
|
/* filtros */
|
||||||
|
selectedTreeFilter: string = '';
|
||||||
|
filterTree(searchTerm: string, filterType: string): void {
|
||||||
|
const filterNodes = (nodes: any[]): any[] => {
|
||||||
|
return nodes
|
||||||
|
.map(node => {
|
||||||
|
const matchesName = node.name.toLowerCase().includes(searchTerm.toLowerCase());
|
||||||
|
const matchesType = filterType ? node.type.toLowerCase() === filterType.toLowerCase() : true;
|
||||||
|
|
||||||
|
// Filtrar hijos recursivamente
|
||||||
|
const filteredChildren = node.children ? filterNodes(node.children) : [];
|
||||||
|
|
||||||
|
// Si el nodo o algún hijo coincide, incluirlo
|
||||||
|
if (matchesName && matchesType || filteredChildren.length > 0) {
|
||||||
|
return { ...node, children: filteredChildren };
|
||||||
|
}
|
||||||
|
return null; // Excluir nodos que no coinciden
|
||||||
|
})
|
||||||
|
.filter(node => node !== null); // Eliminar nodos excluidos
|
||||||
|
};
|
||||||
|
|
||||||
|
// Aplicar filtro sobre el árbol completo
|
||||||
|
const filteredData = filterNodes(this.treeDataSource.data);
|
||||||
|
|
||||||
|
// Actualizar el origen de datos del árbol
|
||||||
|
this.treeDataSource.data = filteredData;
|
||||||
|
}
|
||||||
|
|
||||||
|
onTreeFilterInput(event: Event): void {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
const searchTerm = input?.value || ''; // Maneja el caso de nulo o indefinido
|
||||||
|
this.filterTree(searchTerm, this.selectedTreeFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClientFilterInput(event: Event): void {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
const searchTerm = input?.value || ''; // Maneja valores nulos o indefinidos
|
||||||
|
this.filterClients(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filterClients(searchTerm: string): void {
|
||||||
|
if (!searchTerm) {
|
||||||
|
// Restaurar los datos originales si no hay filtro
|
||||||
|
this.selectedClients = [...this.selectedClientsOriginal];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lowerTerm = searchTerm.toLowerCase();
|
||||||
|
|
||||||
|
this.selectedClients = this.selectedClientsOriginal.filter(client => {
|
||||||
|
const matchesName = client.name.toLowerCase().includes(lowerTerm);
|
||||||
|
const matchesIP = client.ip?.toLowerCase().includes(lowerTerm) || false;
|
||||||
|
const matchesStatus = client.status?.toLowerCase().includes(lowerTerm) || false;
|
||||||
|
const matchesMac = client.mac?.toLowerCase().includes(lowerTerm) || false;
|
||||||
|
|
||||||
|
return matchesName || matchesIP || matchesStatus || matchesMac;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,5 +421,8 @@
|
||||||
"TOOLTIP_MENUS": "Gestión de menús (opción deshabilitada)",
|
"TOOLTIP_MENUS": "Gestión de menús (opción deshabilitada)",
|
||||||
"search": "Buscar",
|
"search": "Buscar",
|
||||||
"TOOLTIP_SEARCH": "Función de búsqueda (opción deshabilitada)",
|
"TOOLTIP_SEARCH": "Función de búsqueda (opción deshabilitada)",
|
||||||
"detailsOf": "Detalles de"
|
"detailsOf": "Detalles de",
|
||||||
|
"editUnitMenu": "Editar",
|
||||||
|
"addInternalUnitMenu": "Añadir",
|
||||||
|
"addClientMenu": "Añadir cliente"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue