Refactor groups component to update filter option value
testing/ogGui-multibranch/pipeline/head This commit is unstable
Details
testing/ogGui-multibranch/pipeline/head This commit is unstable
Details
parent
aa9b82cda5
commit
aecc16c332
|
@ -123,7 +123,7 @@ import { JoyrideModule } from 'ngx-joyride';
|
|||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { EnvVarsComponent } from './components/admin/env-vars/env-vars.component';
|
||||
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
}
|
||||
|
@ -234,6 +234,7 @@ export function HttpLoaderFactory(http: HttpClient) {
|
|||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
MatSliderModule,
|
||||
MatSortModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<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">Grupos de aulas</mat-option>
|
||||
<mat-option value="classrooms-group">Grupos de aulas</mat-option>
|
||||
<mat-option value="classroom">Aulas</mat-option>
|
||||
<mat-option value="group">Grupos de ordenadores</mat-option>
|
||||
</mat-select>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
@ -8,8 +8,10 @@ import { ToastrService } from 'ngx-toastr';
|
|||
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 } from './model/model';
|
||||
import { UnidadOrganizativa, Client, TreeNode, FlatNode, Command, Filter } 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';
|
||||
|
@ -22,86 +24,67 @@ import { OrganizationalUnitTabViewComponent } from './components/organizational-
|
|||
import { DeleteModalComponent } from '../../shared/delete_modal/delete-modal/delete-modal.component';
|
||||
import { ClassroomViewDialogComponent } from './shared/classroom-view/classroom-view-modal';
|
||||
|
||||
interface TreeNode {
|
||||
clients?: any[];
|
||||
name: string;
|
||||
type: string;
|
||||
children?: TreeNode[];
|
||||
ip?: string;
|
||||
'@id'?: string;
|
||||
hasClients?: boolean;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
interface FlatNode {
|
||||
name: string;
|
||||
type: string;
|
||||
level: number;
|
||||
expandable: boolean;
|
||||
ip?: string;
|
||||
hasClients?: boolean;
|
||||
enum NodeType {
|
||||
OrganizationalUnit = 'organizational-unit',
|
||||
ClassroomsGroup = 'classrooms-group',
|
||||
Classroom = 'classroom',
|
||||
ClientsGroup = 'clients-group',
|
||||
Client = 'client',
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-groups',
|
||||
templateUrl: './groups.component.html',
|
||||
styleUrls: ['./groups.component.css']
|
||||
styleUrls: ['./groups.component.css'],
|
||||
})
|
||||
export class GroupsComponent implements OnInit {
|
||||
export class GroupsComponent implements OnInit, OnDestroy {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
organizationalUnits: UnidadOrganizativa[] = [];
|
||||
selectedUnidad: UnidadOrganizativa | null = null;
|
||||
selectedDetail: any | null = null;
|
||||
loading: boolean = false;
|
||||
loadingChildren: boolean = false;
|
||||
searchTerm: string = '';
|
||||
selectedDetail: UnidadOrganizativa | null = null;
|
||||
loading = false;
|
||||
searchTerm = '';
|
||||
treeControl: FlatTreeControl<FlatNode>;
|
||||
treeFlattener: MatTreeFlattener<TreeNode, FlatNode>;
|
||||
treeDataSource: MatTreeFlatDataSource<TreeNode, FlatNode>;
|
||||
selectedNode: TreeNode | null = null;
|
||||
commands: any[] = [];
|
||||
commandsLoading: boolean = false;
|
||||
selectedClients: any[] = [];
|
||||
cols: number = 4;
|
||||
selectedClientsOriginal: any[] = [];
|
||||
commands: Command[] = [];
|
||||
commandsLoading = false;
|
||||
selectedClients: Client[] = [];
|
||||
cols = 4;
|
||||
selectedClientsOriginal: Client[] = [];
|
||||
currentView: 'card' | 'list' = 'list';
|
||||
isTreeViewActive: boolean = false;
|
||||
savedFilterNames: any[] = [];
|
||||
selectedTreeFilter: string = '';
|
||||
|
||||
syncStatus: boolean = false;
|
||||
syncingClientId: number | null = null;
|
||||
isTreeViewActive = false;
|
||||
savedFilterNames: [string, string][] = [];
|
||||
selectedTreeFilter = '';
|
||||
syncStatus = false;
|
||||
syncingClientId: string | null = null;
|
||||
private originalTreeData: TreeNode[] = [];
|
||||
|
||||
@ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent;
|
||||
@ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent;
|
||||
|
||||
private subscriptions: Subscription = new Subscription();
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
private dataService: DataService,
|
||||
public dialog: MatDialog,
|
||||
private _bottomSheet: MatBottomSheet,
|
||||
private bottomSheet: MatBottomSheet,
|
||||
private joyrideService: JoyrideService,
|
||||
private toastr: ToastrService
|
||||
) {
|
||||
this.treeFlattener = new MatTreeFlattener<TreeNode, FlatNode>(
|
||||
(node: TreeNode, level: number) => ({
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
level,
|
||||
expandable: !!node.children?.length,
|
||||
hasClients: node.hasClients,
|
||||
ip: node.ip,
|
||||
['@id']: node['@id']
|
||||
}),
|
||||
node => node.level,
|
||||
node => node.expandable,
|
||||
node => node.children
|
||||
this.transformer,
|
||||
(node) => node.level,
|
||||
(node) => node.expandable,
|
||||
(node) => node.children
|
||||
);
|
||||
|
||||
this.treeControl = new FlatTreeControl<FlatNode>(
|
||||
node => node.level,
|
||||
node => node.expandable
|
||||
(node) => node.level,
|
||||
(node) => node.expandable
|
||||
);
|
||||
|
||||
this.treeDataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
|
||||
|
@ -111,17 +94,32 @@ export class GroupsComponent implements OnInit {
|
|||
this.search();
|
||||
this.getFilters();
|
||||
this.updateGridCols();
|
||||
window.addEventListener('resize', () => this.updateGridCols());
|
||||
window.addEventListener('resize', this.updateGridCols);
|
||||
}
|
||||
|
||||
toggleView(view: 'card' | 'list') {
|
||||
ngOnDestroy(): void {
|
||||
window.removeEventListener('resize', this.updateGridCols);
|
||||
this.subscriptions.unsubscribe();
|
||||
}
|
||||
|
||||
private transformer = (node: TreeNode, level: number): FlatNode => ({
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
level,
|
||||
expandable: !!node.children?.length,
|
||||
hasClients: node.hasClients,
|
||||
ip: node.ip,
|
||||
'@id': node['@id'],
|
||||
});
|
||||
|
||||
toggleView(view: 'card' | 'list'): void {
|
||||
this.currentView = view;
|
||||
}
|
||||
|
||||
updateGridCols(): void {
|
||||
updateGridCols = (): void => {
|
||||
const width = window.innerWidth;
|
||||
this.cols = width <= 600 ? 1 : width <= 960 ? 2 : width <= 1280 ? 3 : 4;
|
||||
}
|
||||
};
|
||||
|
||||
clearSelection(): void {
|
||||
this.selectedUnidad = null;
|
||||
|
@ -139,112 +137,122 @@ export class GroupsComponent implements OnInit {
|
|||
}
|
||||
|
||||
getFilters(): void {
|
||||
this.dataService.getFilters().subscribe(
|
||||
data => {
|
||||
this.savedFilterNames = data.map((filter: any) => [filter.name, filter.uuid]);
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching filters:', error);
|
||||
}
|
||||
this.subscriptions.add(
|
||||
this.dataService.getFilters().subscribe(
|
||||
(data) => {
|
||||
this.savedFilterNames = data.map((filter: { name: string; uuid: string; }) => [filter.name, filter.uuid]);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching filters:', error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
loadSelectedFilter(savedFilter: any) {
|
||||
const url = `${this.baseUrl}/views/` + savedFilter[1];
|
||||
this.dataService.getFilter(savedFilter[1]).subscribe(response => {
|
||||
if (response) {
|
||||
console.log('Filter1:', response.filters);
|
||||
}
|
||||
}, error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
loadSelectedFilter(savedFilter: [string, string]): void {
|
||||
this.subscriptions.add(
|
||||
this.dataService.getFilter(savedFilter[1]).subscribe(
|
||||
(response) => {
|
||||
if (response) {
|
||||
console.log('Filter:', response.filters);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
search(): void {
|
||||
this.loading = true;
|
||||
this.dataService.getOrganizationalUnits(this.searchTerm).subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data;
|
||||
this.loading = false;
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching unidades organizativas', error);
|
||||
this.loading = false;
|
||||
}
|
||||
this.subscriptions.add(
|
||||
this.dataService.getOrganizationalUnits(this.searchTerm).subscribe(
|
||||
(data) => {
|
||||
this.organizationalUnits = data;
|
||||
this.loading = false;
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching organizational units', error);
|
||||
this.loading = false;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
onSelectUnidad(unidad: any): void {
|
||||
onSelectUnidad(unidad: UnidadOrganizativa): void {
|
||||
this.selectedUnidad = unidad;
|
||||
this.selectedDetail = unidad;
|
||||
this.selectedClients = this.collectAllClients(unidad);
|
||||
this.selectedClientsOriginal = [...this.selectedClients];
|
||||
this.loadChildrenAndClients(unidad.id).then(fullData => {
|
||||
this.loadChildrenAndClients(unidad.id).then((fullData) => {
|
||||
const treeData = this.convertToTreeData(fullData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
});
|
||||
this.isTreeViewActive = true;
|
||||
}
|
||||
|
||||
private collectAllClients(node: any): any[] {
|
||||
private collectAllClients(node: UnidadOrganizativa): Client[] {
|
||||
let clients = node.clients || [];
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach((child: any) => {
|
||||
if (node.children) {
|
||||
node.children.forEach((child) => {
|
||||
clients = clients.concat(this.collectAllClients(child));
|
||||
});
|
||||
}
|
||||
return clients;
|
||||
}
|
||||
|
||||
async loadChildrenAndClients(id: string): Promise<any> {
|
||||
private async loadChildrenAndClients(id: string): Promise<UnidadOrganizativa> {
|
||||
try {
|
||||
const childrenData = await this.dataService.getChildren(id).toPromise();
|
||||
const processHierarchy = (nodes: UnidadOrganizativa[]): TreeNode[] => {
|
||||
return nodes.map(node => ({
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
'@id': node['@id'],
|
||||
|
||||
const processHierarchy = (nodes: UnidadOrganizativa[]): UnidadOrganizativa[] => {
|
||||
return nodes.map((node) => ({
|
||||
...node,
|
||||
children: node.children ? processHierarchy(node.children) : [],
|
||||
clients: node.clients || []
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
...this.selectedUnidad,
|
||||
children: childrenData ? processHierarchy(childrenData) : []
|
||||
...this.selectedUnidad!,
|
||||
children: childrenData ? processHierarchy(childrenData) : [],
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error loading children:', error);
|
||||
return this.selectedUnidad;
|
||||
return this.selectedUnidad!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
convertToTreeData(data: any): TreeNode[] {
|
||||
const processNode = (node: UnidadOrganizativa): TreeNode => ({
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
'@id': node['@id'],
|
||||
children: node.children?.map(processNode) || [],
|
||||
hasClients: node.clients && node.clients.length > 0,
|
||||
});
|
||||
|
||||
return [processNode(data)];
|
||||
}
|
||||
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)];
|
||||
}
|
||||
|
||||
|
||||
onNodeClick(node: TreeNode): void {
|
||||
this.selectedNode = node;
|
||||
this.selectedClients = node.clients || [];
|
||||
this.selectedClientsOriginal = [...this.selectedClients];
|
||||
if (node.hasClients) {
|
||||
const url = `${this.baseUrl}${node['@id']}`;
|
||||
this.http.get(url).subscribe(
|
||||
(data: any) => {
|
||||
this.selectedClientsOriginal = [...data.clients];
|
||||
this.selectedClients = data.clients || [];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching clients:', error);
|
||||
}
|
||||
this.fetchClientsForNode(node);
|
||||
}
|
||||
|
||||
private fetchClientsForNode(node: TreeNode): void {
|
||||
if (node.hasClients && node['@id']) {
|
||||
this.subscriptions.add(
|
||||
this.http.get<{ clients: Client[] }>(`${this.baseUrl}${node['@id']}`).subscribe(
|
||||
(data) => {
|
||||
this.selectedClientsOriginal = [...data.clients];
|
||||
this.selectedClients = data.clients || [];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching clients:', error);
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.selectedClients = [];
|
||||
|
@ -252,222 +260,207 @@ export class GroupsComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
getNodeIcon(node: any): string {
|
||||
getNodeIcon(node: TreeNode): string {
|
||||
switch (node.type) {
|
||||
case 'organizational-unit': return 'apartment';
|
||||
case 'classrooms-group': return 'doors';
|
||||
case 'classroom': return 'school';
|
||||
case 'clients-group': return 'lan';
|
||||
case 'client': return 'computer';
|
||||
default: return 'group';
|
||||
case NodeType.OrganizationalUnit:
|
||||
return 'apartment';
|
||||
case NodeType.ClassroomsGroup:
|
||||
return 'doors';
|
||||
case NodeType.Classroom:
|
||||
return 'school';
|
||||
case NodeType.ClientsGroup:
|
||||
return 'lan';
|
||||
case NodeType.Client:
|
||||
return 'computer';
|
||||
default:
|
||||
return 'group';
|
||||
}
|
||||
}
|
||||
|
||||
addOU(event: MouseEvent, parent: any = null): void {
|
||||
addOU(event: MouseEvent, parent: TreeNode | null = null): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent, { data: { parent }, width: '900px' });
|
||||
const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent, {
|
||||
data: { parent },
|
||||
width: '900px',
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data;
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '').then(updatedData => {
|
||||
const treeData = this.convertToTreeData(updatedData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
});
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
this.refreshOrganizationalUnits();
|
||||
});
|
||||
}
|
||||
|
||||
addClient(event: MouseEvent, organizationalUnit: any = null): void {
|
||||
addClient(event: MouseEvent, organizationalUnit: TreeNode | null = null): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(CreateClientComponent, { data: { organizationalUnit }, width: '900px' });
|
||||
const dialogRef = this.dialog.open(CreateClientComponent, {
|
||||
data: { organizationalUnit },
|
||||
width: '900px',
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.refreshOrganizationalUnits();
|
||||
if (organizationalUnit && organizationalUnit['@id']) {
|
||||
this.refreshClientsForNode(organizationalUnit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private refreshOrganizationalUnits(): void {
|
||||
this.subscriptions.add(
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
(data) => {
|
||||
this.organizationalUnits = data;
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '').then(updatedData => {
|
||||
const treeData = this.convertToTreeData(updatedData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
});
|
||||
if (organizationalUnit && organizationalUnit.id) {
|
||||
this.loadChildrenAndClients(organizationalUnit.id);
|
||||
this.refreshClients(organizationalUnit);
|
||||
}
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
setSelectedNode(node: TreeNode): void {
|
||||
this.selectedNode = node;
|
||||
}
|
||||
|
||||
onEditNode(event: MouseEvent, node: TreeNode | null): void {
|
||||
if (!node) return;
|
||||
|
||||
const uuid = node['@id'] ? node['@id'].split('/').pop() : '';
|
||||
const type = node.type;
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
if (type !== 'client') {
|
||||
this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '900px' });
|
||||
} else {
|
||||
this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' });
|
||||
}
|
||||
}
|
||||
|
||||
onDelete(node: TreeNode | null): void {
|
||||
console.log('Deleting node:', node);
|
||||
}
|
||||
|
||||
onDeleteClick(event: MouseEvent, node: TreeNode | null, clientNode?: TreeNode | null): void {
|
||||
const uuid = node && node['@id'] ? node['@id'].split('/').pop() || '' : '';
|
||||
const name = node?.name || 'Elemento desconocido';
|
||||
const type = node?.type || '';
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: { name }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result === true) {
|
||||
this.dataService.deleteElement(uuid, type).subscribe(
|
||||
() => {
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '').then(updatedData => {
|
||||
if (this.selectedUnidad) {
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '').then((updatedData) => {
|
||||
this.selectedUnidad = updatedData;
|
||||
const treeData = this.convertToTreeData(updatedData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
});
|
||||
|
||||
if (type === 'client' && clientNode) {
|
||||
this.refreshClients(clientNode);
|
||||
}
|
||||
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data;
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
|
||||
this.toastr.success('Entidad eliminada exitosamente');
|
||||
},
|
||||
error => {
|
||||
console.error('Error deleting entity:', error);
|
||||
this.toastr.error('Error al eliminar la entidad', error.message);
|
||||
this.originalTreeData = treeData[0]?.children || [];
|
||||
this.treeDataSource.data = [...this.originalTreeData];
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private refreshClients(node: TreeNode): void {
|
||||
if (!node || !node['@id']) {
|
||||
this.selectedClients = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}${node['@id']}`;
|
||||
this.http.get(url).subscribe(
|
||||
(data: any) => {
|
||||
if (data && Array.isArray(data.clients)) {
|
||||
this.selectedClients = data.clients;
|
||||
} else {
|
||||
this.selectedClients = [];
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error('Error refreshing clients:', error);
|
||||
const errorMessage = error.status === 404
|
||||
? 'No se encontraron clientes para este nodo.'
|
||||
: 'Error al comunicarse con el servidor.';
|
||||
this.toastr.error(errorMessage);
|
||||
}
|
||||
},
|
||||
(error) => console.error('Error fetching organizational units', error)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
onEditClick(event: MouseEvent, type: any, uuid: string): void {
|
||||
onEditNode(event: MouseEvent, node: TreeNode | null): void {
|
||||
event.stopPropagation();
|
||||
if (type != 'client') {
|
||||
const uuid = node ? this.extractUuid(node['@id']) : null;
|
||||
if (!uuid) return;
|
||||
|
||||
if (node && node.type !== NodeType.Client) {
|
||||
this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '900px' });
|
||||
} else {
|
||||
this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' });
|
||||
}
|
||||
}
|
||||
|
||||
onRoomMap(room: any): void {
|
||||
this.http.get(`${this.baseUrl}`+ room['@id']).subscribe(
|
||||
(response: any) => {
|
||||
this.dialog.open(ClassroomViewDialogComponent, {
|
||||
width: '90vw',
|
||||
data: { clients: response.clients }
|
||||
});
|
||||
},
|
||||
(error: any) => {
|
||||
console.error('Error en la solicitud HTTP:', error);
|
||||
onDeleteClick(event: MouseEvent, node: TreeNode | null, clientNode?: TreeNode | null): void{
|
||||
event.stopPropagation();
|
||||
const uuid = node ? this.extractUuid(node['@id']) : null;
|
||||
if (!uuid) return;
|
||||
|
||||
if (!node) return;
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: { name: node.name },
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
if (result === true) {
|
||||
this.deleteEntity(uuid, node.type, node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private deleteEntity(uuid: string, type: string, node: TreeNode): void {
|
||||
this.subscriptions.add(
|
||||
this.dataService.deleteElement(uuid, type).subscribe(
|
||||
() => {
|
||||
this.refreshOrganizationalUnits();
|
||||
if (type === NodeType.Client) {
|
||||
this.refreshClientsForNode(node);
|
||||
}
|
||||
this.toastr.success('Entidad eliminada exitosamente');
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error deleting entity:', error);
|
||||
this.toastr.error('Error al eliminar la entidad', error.message);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private refreshClientsForNode(node: TreeNode): void {
|
||||
if (!node['@id']) {
|
||||
this.selectedClients = [];
|
||||
return;
|
||||
}
|
||||
this.fetchClientsForNode(node);
|
||||
}
|
||||
|
||||
onEditClick(event: MouseEvent, type: string, uuid: string): void {
|
||||
event.stopPropagation();
|
||||
if (type !== NodeType.Client) {
|
||||
this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '900px' });
|
||||
} else {
|
||||
this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' });
|
||||
}
|
||||
}
|
||||
|
||||
onRoomMap(room: TreeNode | null): void {
|
||||
if (!room || !room['@id']) return;
|
||||
this.subscriptions.add(
|
||||
this.http.get<{ clients: Client[] }>(`${this.baseUrl}${room['@id']}`).subscribe(
|
||||
(response) => {
|
||||
this.dialog.open(ClassroomViewDialogComponent, {
|
||||
width: '90vw',
|
||||
data: { clients: response.clients },
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching room data:', error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fetchCommands(): void {
|
||||
this.commandsLoading = true;
|
||||
this.http.get(`${this.baseUrl}`+'/commands?page=1&itemsPerPage=30').subscribe(
|
||||
(response: any) => {
|
||||
this.commands = response['hydra:member'];
|
||||
this.commandsLoading = false;
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching commands:', error);
|
||||
this.commandsLoading = false;
|
||||
}
|
||||
this.subscriptions.add(
|
||||
this.http.get<{ 'hydra:member': Command[] }>(`${this.baseUrl}/commands?page=1&itemsPerPage=30`).subscribe(
|
||||
(response) => {
|
||||
this.commands = response['hydra:member'];
|
||||
this.commandsLoading = false;
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching commands:', error);
|
||||
this.commandsLoading = false;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
executeCommand(command: any, selectedNode: any): void {
|
||||
this.toastr.success('Ejecutando comando: ' + command.name + " en " + selectedNode.name);
|
||||
executeCommand(command: Command, selectedNode: TreeNode | null): void {
|
||||
|
||||
if (!selectedNode) {
|
||||
this.toastr.error('No hay un nodo seleccionado.');
|
||||
return;
|
||||
} else {
|
||||
this.toastr.success(`Ejecutando comando: ${command.name} en ${selectedNode.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
onClientActions(client: any): void {
|
||||
console.log('Client actions:', client);
|
||||
}
|
||||
|
||||
onShowClientDetail(event: MouseEvent, client: any): void {
|
||||
onShowClientDetail(event: MouseEvent, client: Client): void {
|
||||
event.stopPropagation();
|
||||
this.router.navigate(['clients', client.uuid], { state: { clientData: client } });
|
||||
}
|
||||
|
||||
onShowDetailsClick(event: MouseEvent, data: any): void {
|
||||
onShowDetailsClick(event: MouseEvent, data: TreeNode | null): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != 'client') {
|
||||
if (data && data.type !== NodeType.Client) {
|
||||
this.dialog.open(ShowOrganizationalUnitComponent, { data: { data }, width: '700px' });
|
||||
}
|
||||
if (data.type == 'client') {
|
||||
this.router.navigate(['clients', data['@id'].split('/').pop()], { state: { clientData: data } });
|
||||
} else {
|
||||
if (data) {
|
||||
this.router.navigate(['clients', this.extractUuid(data['@id'])], { state: { clientData: data } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onTreeClick(event: MouseEvent, data: any): void {
|
||||
onTreeClick(event: MouseEvent, data: TreeNode): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != 'client') {
|
||||
if (data.type !== NodeType.Client) {
|
||||
this.dialog.open(TreeViewComponent, { data: { data }, width: '800px' });
|
||||
}
|
||||
}
|
||||
|
||||
openBottomSheet(): void {
|
||||
this._bottomSheet.open(LegendComponent);
|
||||
this.bottomSheet.open(LegendComponent);
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: ['groupsTitleStepText', 'addStep', 'keyStep', 'unitStep', 'elementsStep', 'tabsStep'],
|
||||
showPrevButton: true,
|
||||
themeColor: '#3f51b5'
|
||||
themeColor: '#3f51b5',
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -475,23 +468,25 @@ export class GroupsComponent implements OnInit {
|
|||
isLeafNode = (_: number, node: FlatNode): boolean => !node.expandable;
|
||||
|
||||
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;
|
||||
const filteredChildren = node.children ? filterNodes(node.children) : [];
|
||||
if (matchesName && matchesType || filteredChildren.length > 0) {
|
||||
return { ...node, children: filteredChildren };
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(node => node !== null);
|
||||
const filterNodes = (nodes: TreeNode[]): TreeNode[] => {
|
||||
const filteredNodes: TreeNode[] = [];
|
||||
for (const node of nodes) {
|
||||
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.treeDataSource.data);
|
||||
|
||||
const filteredData = filterNodes(this.originalTreeData);
|
||||
this.treeDataSource.data = filteredData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
onTreeFilterInput(event: Event): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
|
@ -513,32 +508,44 @@ export class GroupsComponent implements OnInit {
|
|||
|
||||
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;
|
||||
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)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getStatus(client: any): void {
|
||||
public setSelectedNode(node: TreeNode): void {
|
||||
this.selectedNode = node;
|
||||
}
|
||||
|
||||
getStatus(client: Client): void {
|
||||
if (!client.uuid || !client['@id']) return;
|
||||
|
||||
this.syncingClientId = client.uuid;
|
||||
this.syncStatus = true;
|
||||
|
||||
this.http.post(`${this.baseUrl}${client['@id']}/agent/status`, {}).subscribe(
|
||||
response => {
|
||||
this.toastr.success('Cliente actualizado correctamente');
|
||||
this.search();
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
},
|
||||
error => {
|
||||
this.toastr.error('Error de conexión con el cliente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
}
|
||||
this.subscriptions.add(
|
||||
this.http.post(`${this.baseUrl}${client['@id']}/agent/status`, {}).subscribe(
|
||||
() => {
|
||||
this.toastr.success('Cliente actualizado correctamente');
|
||||
this.search();
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
},
|
||||
() => {
|
||||
this.toastr.error('Error de conexión con el cliente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private extractUuid(idPath: string | undefined): string | null {
|
||||
return idPath ? idPath.split('/').pop() || null : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ export interface Aula {
|
|||
}
|
||||
|
||||
export interface UnidadOrganizativa {
|
||||
clients: any[];
|
||||
children: UnidadOrganizativa[];
|
||||
'@id'?: string;
|
||||
id: string;
|
||||
name: string;
|
||||
uuid: string;
|
||||
name: string;
|
||||
type: string;
|
||||
parent: UnidadOrganizativa[];
|
||||
'@id': string;
|
||||
clients?: Client[];
|
||||
children?: UnidadOrganizativa[];
|
||||
parent?: UnidadOrganizativa;
|
||||
}
|
||||
|
||||
export interface OrganizationalUnit {
|
||||
|
@ -29,6 +29,9 @@ export interface OrganizationalUnit {
|
|||
}
|
||||
|
||||
export interface Client {
|
||||
mac: any;
|
||||
status: any;
|
||||
ip: any;
|
||||
"@id": string;
|
||||
"@type": string;
|
||||
id: number;
|
||||
|
@ -54,3 +57,35 @@ export interface ClientCollection {
|
|||
"@type": string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TreeNode {
|
||||
name: string;
|
||||
type: string;
|
||||
'@id'?: string;
|
||||
children?: TreeNode[];
|
||||
hasClients?: boolean;
|
||||
clients?: Client[];
|
||||
ip?: string;
|
||||
}
|
||||
|
||||
export interface FlatNode {
|
||||
name: string;
|
||||
type: string;
|
||||
level: number;
|
||||
expandable: boolean;
|
||||
hasClients?: boolean;
|
||||
ip?: string;
|
||||
'@id'?: string;
|
||||
}
|
||||
|
||||
|
||||
export interface Command {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface Filter {
|
||||
name: string;
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue