Refactor group component and remove unused code
parent
4c45e51493
commit
98491bc3c8
|
@ -95,10 +95,7 @@ import { CreateCommandGroupComponent } from './components/commands/commands-grou
|
|||
import { DetailCommandGroupComponent } from './components/commands/commands-groups/detail-command-group/detail-command-group.component';
|
||||
import { CreateTaskComponent } from './components/commands/commands-task/create-task/create-task.component';
|
||||
import { DetailTaskComponent } from './components/commands/commands-task/detail-task/detail-task.component';
|
||||
import { ClientTabViewComponent } from './components/groups/components/client-tab-view/client-tab-view.component';
|
||||
import { AdvancedSearchComponent } from './components/groups/components/advanced-search/advanced-search.component';
|
||||
import { TaskLogsComponent } from './components/commands/commands-task/task-logs/task-logs.component';
|
||||
import { OrganizationalUnitTabViewComponent } from './components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component';
|
||||
import { ServerInfoDialogComponent } from './components/ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component';
|
||||
import { StatusComponent } from './components/ogdhcp/og-dhcp-subnets/status/status.component';
|
||||
import {MatSliderModule} from '@angular/material/slider';
|
||||
|
@ -183,10 +180,7 @@ export function HttpLoaderFactory(http: HttpClient) {
|
|||
DetailCommandGroupComponent,
|
||||
CreateTaskComponent,
|
||||
DetailTaskComponent,
|
||||
ClientTabViewComponent,
|
||||
AdvancedSearchComponent,
|
||||
TaskLogsComponent,
|
||||
OrganizationalUnitTabViewComponent,
|
||||
ServerInfoDialogComponent,
|
||||
StatusComponent,
|
||||
ClientMainViewComponent,
|
||||
|
|
|
@ -1,333 +0,0 @@
|
|||
.groupLists-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
flex-grow: 1;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.header mat-form-field {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.filters {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.results {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.result-card {
|
||||
width: 100%;
|
||||
max-width: 250px;
|
||||
height: auto;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 15px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
|
||||
.result-card.small-card {
|
||||
width: 100%;
|
||||
max-width: 180px;
|
||||
padding: 10px;
|
||||
margin: 10px 10px 10px 10px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.result-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
background-color: #fff;
|
||||
max-width: 300px;
|
||||
margin: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.result-card {
|
||||
&.card-og-live {
|
||||
background-color: yellow; /* Verde */
|
||||
color: white;
|
||||
}
|
||||
&.card-busy {
|
||||
background-color: indianred; /* Naranja */
|
||||
color: white;
|
||||
}
|
||||
&.card-windows {
|
||||
background-color: cornflowerblue; /* Azul */
|
||||
color: white;
|
||||
}
|
||||
&.card-linux {
|
||||
background-color: mediumpurple; /* Púrpura */
|
||||
color: white;
|
||||
}
|
||||
&.card-macos {
|
||||
background-color: cornflowerblue; /* Rojo */
|
||||
color: white;
|
||||
}
|
||||
&.card-off {
|
||||
background-color: #9e9e9e; /* Gris */
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.result-container:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
margin: 8px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.result-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.result-type,
|
||||
.result-ip,
|
||||
.result-mac,
|
||||
.result-status,
|
||||
.result-internal-units,
|
||||
.result-clients {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.result-checkbox {
|
||||
margin-bottom: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card-og-live {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-busy {
|
||||
background-color: #f44336;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-windows {
|
||||
background-color: #2196f3;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-linux {
|
||||
background-color: #9c27b0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-macos {
|
||||
background-color: #ff9800;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-off {
|
||||
background-color: #9e9e9e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-group button {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.red-card {
|
||||
background-color: #f35f53;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.green-card {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.view-mode-buttons {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.view-mode-buttons button.active {
|
||||
font-weight: bold;
|
||||
color: #3f51b5;
|
||||
}
|
||||
|
||||
.result-card-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
margin-bottom: 2px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.result-card-list mat-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.result-card-list .result-title {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.result-card-list mat-card-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%; /* Ajusta según el contenedor padre */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-results p {
|
||||
font-size: 1.5rem; /* Tamaño de fuente más grande */
|
||||
font-weight: bold; /* Negrita para mejor visibilidad */
|
||||
color: #555; /* Cambia el color según tu diseño */
|
||||
}
|
||||
|
||||
.result-card-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.result-list {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.result-container {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Estilo general para la tarjeta */
|
||||
.result-card {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.result-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Centrar contenido para clientes */
|
||||
.centered-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.client-info p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.client-info .client-name {
|
||||
font-size: 0.9rem;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.client-info .client-text {
|
||||
font-size: 0.8rem;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.client-info strong {
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.client-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
<h2 class="title" i18n="@@searchTitle">Búsqueda avanzada</h2>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<mat-form-field>
|
||||
<mat-label i18n="@@selectFilterLabel">Seleccione filtro</mat-label>
|
||||
<mat-select (selectionChange)="loadSelectedFilter($event.value)">
|
||||
<mat-option *ngFor="let savedFilter of savedFilterNames" [value]="savedFilter">
|
||||
{{ savedFilter[0] }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
||||
<div class="view-mode-buttons" joyrideStep="viewModeStep" text="Elige cómo quieres ver los resultados: en cuadrícula o en lista.">
|
||||
<button mat-button (click)="changeViewMode('grid')" [class.active]="viewMode === 'grid'">
|
||||
<mat-icon>grid_view</mat-icon> Cuadrícula
|
||||
</button>
|
||||
<button mat-button (click)="changeViewMode('list')" [class.active]="viewMode === 'list'">
|
||||
<mat-icon>list</mat-icon> Lista
|
||||
</button>
|
||||
<button mat-button (click)="toggleSelectAll()">
|
||||
<mat-icon>checkbox</mat-icon> Seleccionar/Deseleccionar Todos
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<div class="filters">
|
||||
<mat-form-field>
|
||||
<mat-label i18n="@@selectOptionLabel">Selecciona una opción</mat-label>
|
||||
<mat-select [(value)]="selectedFilter1" (selectionChange)="applyFilter()">
|
||||
<mat-option value="ou" i18n="@@organizationalUnitsOption">Unidades organizativas</mat-option>
|
||||
<mat-option value="client" i18n="@@clientsOption">Clientes</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label i18n="@@nameLabel">Nombre</mat-label>
|
||||
<input matInput placeholder="Unidad organizativa" (input)="applyFilter()" [(ngModel)]="filterName"
|
||||
i18n-placeholder="@@namePlaceholder">
|
||||
</mat-form-field>
|
||||
|
||||
<ng-container *ngIf="selectedFilter1 === 'ou'">
|
||||
|
||||
<mat-form-field [disabled]="selectedFilter1 === 'ou'">
|
||||
<mat-label i18n="@@unitTypeLabel">Tipo de unidad</mat-label>
|
||||
<mat-select [(value)]="selectedFilter2" (selectionChange)="applyFilter()">
|
||||
<mat-option value="organizational-unit" i18n="@@organizationalUnitOption">Unidad organizativa</mat-option>
|
||||
<mat-option value="classroom-group" i18n="@@classroomsGroupOption">Grupos de aulas</mat-option>
|
||||
<mat-option value="classroom" i18n="@@classroomOption">Aulas</mat-option>
|
||||
<mat-option value="client-group" i18n="@@clientGroupOption">Grupos de clientes</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label i18n="@@floorLabel" class="temp_filter">Planta</mat-label>
|
||||
<mat-select [(value)]="selectedFilter1">
|
||||
<mat-option value="none" i18n="@@noneOption">Ninguno</mat-option>
|
||||
<mat-option value="option1" i18n="@@option1">Planta 1</mat-option>
|
||||
<mat-option value="option2" i18n="@@option2">Planta 2</mat-option>
|
||||
<mat-option value="option3" i18n="@@option3">Planta 3</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<!-- FILTROS CLIENTES -->
|
||||
|
||||
<ng-container *ngIf="selectedFilter1 === 'client'">
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label i18n="@@selectAnotherOptionLabel" class="temp_filter">Sistema Operativo</mat-label>
|
||||
<mat-select multiple [(value)]="selectedFilterOS">
|
||||
<mat-option value="none" i18n="@@noneOption">Ninguno</mat-option>
|
||||
<mat-option value="Windows 10 Education 1803 64 bits">Windows 10 Education 1803 64 bits</mat-option>
|
||||
<mat-option value="Ubuntu 18.04.1 LTS 64 bits">Ubuntu 18.04.1 LTS 64 bits</mat-option>
|
||||
<mat-option value="Ubuntu 16.04.4 LTS 64 bits">Ubuntu 16.04.4 LTS 64 bits</mat-option>
|
||||
<mat-option value="DATA">RESTO DE OPCIONES TBI</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label i18n="@@selectStateLabel" class="temp_filter">Estado</mat-label>
|
||||
<mat-select multiple [(value)]="selectedFilterStatus">
|
||||
<mat-option value="off" i18n="@@offOption">off</mat-option>
|
||||
<mat-option value="initializing" i18n="@@initializingOption">initializing</mat-option>
|
||||
<mat-option value="oglive" i18n="@@ogliveOption">oglive</mat-option>
|
||||
<mat-option value="busy" i18n="@@busyOption">busy</mat-option>
|
||||
<mat-option value="linux" i18n="@@linuxOption">linux</mat-option>
|
||||
<mat-option value="linux_session" i18n="@@linuxSessionOption">linux_session</mat-option>
|
||||
<mat-option value="macos" i18n="@@macosOption">macos</mat-option>
|
||||
<mat-option value="windows" i18n="@@windowsOption">windows</mat-option>
|
||||
<mat-option value="windows_session" i18n="@@windowsSessionOption">windows_session</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label class="temp_filter">IP</mat-label>
|
||||
<input matInput placeholder="Dírección IP" (input)="applyFilter()" i18n [(ngModel)]="filterIP">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label class="temp_filter">MAC</mat-label>
|
||||
<input matInput placeholder="Dírección IP" (input)="applyFilter()" i18n [(ngModel)]="filterMAC">
|
||||
</mat-form-field>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<div class="button-group">
|
||||
<button mat-raised-button color="primary" (click)="saveFilters()" i18n="@@saveFiltersButton" joyrideStep="saveFiltersStep" text="Guarda tus filtros seleccionados para usarlos en el futuro.">Guardar Filtros</button>
|
||||
<button mat-raised-button color="accent" (click)="sendActions()" i18n="@@sendFiltersButton" [disabled]="selectedElements.length === 0" joyrideStep="sendActionStep" text="Envía una acción a los elementos seleccionados.">Enviar Acción</button>
|
||||
<button mat-flat-button color="primary" [disabled]="selectedElements.length === 0" (click)="onPxeBootFile()" joyrideStep="addPxeStep" text="Añade un archivo PXE a los elementos seleccionados.">Añadir fichero PXE</button>
|
||||
<button mat-raised-button color="primary" [matMenuTriggerFor]="menu" [disabled]="selectedFilter1 === 'ou'">
|
||||
Asistentes
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item [disabled]="selectedElements.length > 1 || !selectedElements.length" (click)="onCommandSelect('partition')">Asistente de particionado</button>
|
||||
<button mat-menu-item [disabled]="selectedElements.length > 1 || !selectedElements.length" (click)="onCommandSelect('create-image')">Crear una imagen</button>
|
||||
<button mat-menu-item [disabled]="selectedElements.length > 1 || !selectedElements.length" (click)="onCommandSelect('deploy-image')">Desplegar una imagen</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="results">
|
||||
<ng-container *ngIf="filteredResults && filteredResults.length > 0; else noResults">
|
||||
<ng-container *ngIf="viewMode === 'grid'">
|
||||
<mat-grid-list cols="7" rowHeight="1:1">
|
||||
<mat-grid-tile *ngFor="let result of filteredResults">
|
||||
<mat-card class="result-card small-card" [ngClass]="{
|
||||
'card-og-live': result.status === 'og-live',
|
||||
'card-busy': result.status === 'busy',
|
||||
'card-windows': result.status === 'windows' || result.status === 'windows-session',
|
||||
'card-linux': result.status === 'linux' || result.status === 'linux-session',
|
||||
'card-macos': result.status === 'macos',
|
||||
'card-off': result.status === 'off'
|
||||
}">
|
||||
<mat-checkbox
|
||||
[(ngModel)]="result.selected"
|
||||
(change)="onCheckboxChange($event, result.name, result['@id'])"
|
||||
class="result-checkbox">
|
||||
</mat-checkbox>
|
||||
<mat-card-title *ngIf="result.type !== 'client'" class="result-title">{{ result.name }}</mat-card-title>
|
||||
<mat-card-content *ngIf="result.type === 'client'" class="result-content centered-content" >
|
||||
<div class="client-info">
|
||||
<p class="client-name">{{ result.name }}</p>
|
||||
<p class="client-text">{{ result.ip }}</p>
|
||||
<p class="client-text"> {{ result.mac }}</p>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-card-content *ngIf="result.type !== 'client'" class="result-content">
|
||||
<p i18n="@@internalUnits" class="result-internal-units">Unidades internas: {{ result.children.length }}</p>
|
||||
<p i18n="@@clients" class="result-clients">Clientes: {{ result.clients.length }}</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="viewMode === 'list'">
|
||||
<div class="result-list" *ngFor="let result of filteredResults">
|
||||
<mat-card class="result-card-list">
|
||||
<mat-checkbox [(ngModel)]="result.selected" (change)="onCheckboxChange($event, result.name, result['@id'])" class="result-checkbox"></mat-checkbox>
|
||||
<mat-card-title class="result-title">{{ result.name }}</mat-card-title>
|
||||
<mat-card-content class="result-content">
|
||||
<p class="result-type">{{ result.type !== 'client' ? result.type : '' }}</p>
|
||||
<p class="result-ip" *ngIf="result.type === 'client'">{{ result.ip }}</p>
|
||||
<p class="result-mac" *ngIf="result.type === 'client'">{{ result.mac }}</p>
|
||||
<p class="result-status" *ngIf="result.type === 'client'">{{ result.status }}</p>
|
||||
<p *ngIf="result.type !== 'client'" i18n="@@internalUnits" class="result-internal-units">
|
||||
Unidades internas: {{ result.children.length }}
|
||||
</p>
|
||||
<p *ngIf="result.type !== 'client'" i18n="@@clients" class="result-clients">
|
||||
Clientes: {{ result.clients.length }}
|
||||
</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="paginator-container">
|
||||
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page"
|
||||
[pageSizeOptions]="pageSizeOptions" (page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #noResults>
|
||||
<div class="no-results">
|
||||
<p i18n="@@noResultsMessage">No hay resultados para mostrar.</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,502 +0,0 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { DataService } from '../../services/data.service';
|
||||
import { ClientCollection, UnidadOrganizativa } from '../../model/model';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { CreateOrganizationalUnitComponent } from '../../shared/organizational-units/create-organizational-unit/create-organizational-unit.component';
|
||||
import { DeleteModalComponent } from '../../../../shared/delete_modal/delete-modal/delete-modal.component';
|
||||
import { CreateClientComponent } from '../../shared/clients/create-client/create-client.component';
|
||||
import { EditOrganizationalUnitComponent } from '../../shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component';
|
||||
import { EditClientComponent } from '../../shared/clients/edit-client/edit-client.component';
|
||||
import { ShowOrganizationalUnitComponent} from "../../shared/organizational-units/show-organizational-unit/show-organizational-unit.component";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {TreeViewComponent} from "../../shared/tree-view/tree-view.component";
|
||||
import {MatBottomSheet} from "@angular/material/bottom-sheet";
|
||||
import {LegendComponent} from "../../shared/legend/legend.component";
|
||||
import { ClassroomViewDialogComponent } from '../../shared/classroom-view/classroom-view-modal';
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {PageEvent} from "@angular/material/paginator";
|
||||
import { SaveFiltersDialogComponent } from '../../shared/save-filters-dialog/save-filters-dialog.component';
|
||||
import { AcctionsModalComponent } from '../../shared/acctions-modal/acctions-modal.component';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import { Router } from '@angular/router';
|
||||
import {
|
||||
CreatePxeBootFileComponent
|
||||
} from "../../../ogboot/pxe-boot-files/create-pxeBootFile/create-pxe-boot-file/create-pxe-boot-file.component";
|
||||
import { JoyrideService } from 'ngx-joyride';
|
||||
|
||||
@Component({
|
||||
selector: 'app-advanced-search',
|
||||
templateUrl: './advanced-search.component.html',
|
||||
styleUrl: './advanced-search.component.css'
|
||||
})
|
||||
export class AdvancedSearchComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
organizationalUnits: UnidadOrganizativa[] = [];
|
||||
selectedUnidad: UnidadOrganizativa | null = null;
|
||||
selectedDetail: any | null = null;
|
||||
children: any[] = [];
|
||||
breadcrumb: string[] = [];
|
||||
clientsData: any[] = [];
|
||||
breadcrumbData: any[] = [];
|
||||
loading:boolean = false;
|
||||
loadingChildren:boolean = false;
|
||||
searchTerm: string = '';
|
||||
selectedFilter1: string = 'none';
|
||||
selectedFilter2: string = 'none';
|
||||
selectedFilterOS: string[] = [];
|
||||
selectedFilterStatus: string[] = [];
|
||||
filterIP: string = '';
|
||||
filterMAC: string = '';
|
||||
filterName: string = '';
|
||||
filteredResults: any[] = [];
|
||||
savedFilterNames: any[] = [];
|
||||
length: number = 0;
|
||||
itemsPerPage: number = 10;
|
||||
page: number = 0;
|
||||
pageSizeOptions: number[] = [5, 10, 25, 100];
|
||||
selectedElements: any[] = [];
|
||||
isAllSelected: boolean = false;
|
||||
filters: { [key: string]: string } = {};
|
||||
datePipe: DatePipe = new DatePipe('es-ES');
|
||||
|
||||
viewMode: 'grid' | 'list' = 'grid';
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
public dialog: MatDialog,
|
||||
private toastService: ToastrService,
|
||||
private _bottomSheet: MatBottomSheet,
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
private joyrideService: JoyrideService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.search();
|
||||
this.getFilters();
|
||||
}
|
||||
|
||||
changeViewMode(mode: 'grid' | 'list'): void {
|
||||
this.viewMode = mode;
|
||||
}
|
||||
|
||||
getFilters(): void {
|
||||
this.dataService.getFilters().subscribe(
|
||||
data => {
|
||||
this.savedFilterNames = data.map((filter: any) => [filter.name, filter.uuid]);
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching filters:', 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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onSelectUnidad(unidad: UnidadOrganizativa): void {
|
||||
this.selectedUnidad = unidad;
|
||||
this.selectedDetail = unidad;
|
||||
this.breadcrumb = [unidad.name];
|
||||
this.breadcrumbData = [unidad];
|
||||
this.loadChildrenAndClients(unidad.id);
|
||||
}
|
||||
|
||||
onSelectChild(child: any): void {
|
||||
this.selectedDetail = child;
|
||||
if (child.type !== 'client' && child.uuid && child.id) {
|
||||
this.breadcrumb.push(child.name || child.name);
|
||||
this.breadcrumbData.push(child);
|
||||
this.loadChildrenAndClients(child.id);
|
||||
}
|
||||
}
|
||||
|
||||
navigateToBreadcrumb(index: number): void {
|
||||
this.breadcrumb = this.breadcrumb.slice(0, index + 1);
|
||||
const target = this.breadcrumbData[index];
|
||||
this.breadcrumbData = this.breadcrumbData.slice(0, index + 1);
|
||||
if (target.type === 'client') {
|
||||
this.selectedDetail = target;
|
||||
} else {
|
||||
this.loadChildrenAndClients(target.id);
|
||||
}
|
||||
}
|
||||
|
||||
loadChildrenAndClients(id: string): void {
|
||||
this.loadingChildren = true
|
||||
this.dataService.getChildren(id).subscribe(
|
||||
childrenData => {
|
||||
this.dataService.getClients(id).subscribe(
|
||||
clientsData => {
|
||||
this.clientsData = clientsData;
|
||||
const newChildren = [...childrenData, ...clientsData];
|
||||
|
||||
if (newChildren.length > 0) {
|
||||
this.children = newChildren;
|
||||
} else {
|
||||
this.children = [];
|
||||
}
|
||||
this.loadingChildren = false
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching clients', error);
|
||||
this.clientsData = [];
|
||||
this.children = [];
|
||||
this.loadingChildren = false
|
||||
}
|
||||
);
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching children', error);
|
||||
this.children = [];
|
||||
this.loadingChildren = false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
addOU(event: MouseEvent, parent:any = null): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent, { data: { parent }, width: '900px'});
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data
|
||||
this.loadChildrenAndClients(parent.id);
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
addClient(event: MouseEvent, organizationalUnit:any = null): void {
|
||||
event.stopPropagation();
|
||||
|
||||
const dialogRef = this.dialog.open(CreateClientComponent, { data: { organizationalUnit }, width: '900px'});
|
||||
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data
|
||||
this.loadChildrenAndClients(organizationalUnit.id);
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
});
|
||||
}
|
||||
onDeleteClick(event: MouseEvent, uuid: string, name: string, type: string): void {
|
||||
event.stopPropagation();
|
||||
if (type === 'client') {
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: { name }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.dataService.deleteElement(uuid, type).subscribe(
|
||||
() => {
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '');
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => this.organizationalUnits = data,
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
this.openSnackBar(false, 'Entidad eliminada exitosamente')
|
||||
},
|
||||
error => {
|
||||
console.error('Error deleting element', error)
|
||||
this.openSnackBar(true, error.error['hydra:description'])
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const dialogDeleteGroupRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: { name }
|
||||
});
|
||||
|
||||
dialogDeleteGroupRef.afterClosed().subscribe(result => {
|
||||
if (result && result === 'delete') {
|
||||
this.dataService.deleteElement(uuid, type).subscribe(
|
||||
() => {
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '');
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => this.organizationalUnits = data,
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
this.openSnackBar(false, 'Entidad eliminada exitosamente')
|
||||
},
|
||||
error => {
|
||||
console.error('Error deleting element', error)
|
||||
this.openSnackBar(true, error.error['hydra:description'])
|
||||
}
|
||||
);
|
||||
} else if (result && result === 'change') {
|
||||
this.dataService.changeParent(uuid).subscribe(
|
||||
() => {
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '');
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => this.organizationalUnits = data,
|
||||
error => console.error('Error fetching unidades organizativas', error)
|
||||
);
|
||||
this.openSnackBar(false, 'Entidad eliminada exitosamente')
|
||||
},
|
||||
error => {
|
||||
console.error('Error deleting element', error)
|
||||
this.openSnackBar(true, error.error['hydra:description'])
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onEditClick(event: MouseEvent, type: any, uuid: string): void {
|
||||
event.stopPropagation();
|
||||
if (type != "client") {
|
||||
const dialogRef = this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '900px'});
|
||||
} else {
|
||||
console.log('Editar cliente');
|
||||
const dialogRef = this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' } );
|
||||
}
|
||||
}
|
||||
|
||||
onShowClick(event: MouseEvent, data: any): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != "client") {
|
||||
const dialogRef = this.dialog.open(ShowOrganizationalUnitComponent, { data: { data }, width: '700px'});
|
||||
}
|
||||
}
|
||||
|
||||
onTreeClick(event: MouseEvent, data: any): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != "client") {
|
||||
const dialogRef = this.dialog.open(TreeViewComponent, { data: { data }, width: '800px'});
|
||||
}
|
||||
}
|
||||
|
||||
openSnackBar(isError: boolean, message: string) {
|
||||
if (isError) {
|
||||
this.toastService.error(' Error al eliminar la entidad: ' + message, 'Error');
|
||||
} else
|
||||
this.toastService.success(message, 'Éxito');
|
||||
}
|
||||
|
||||
openBottomSheet(): void {
|
||||
this._bottomSheet.open(LegendComponent);
|
||||
}
|
||||
|
||||
roomMap(): void {
|
||||
if (this.selectedDetail && this.selectedDetail.type === 'classroom') {
|
||||
const dialogRef = this.dialog.open(ClassroomViewDialogComponent, {
|
||||
width: '90vw',
|
||||
data: { clients: this.clientsData }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
applyFilter() {
|
||||
this.dataService.getFilteredResults(this.selectedFilter1, this.selectedFilter2, this.filterName, this.filterIP, this.filterMAC, this.page + 1, this.itemsPerPage)
|
||||
.subscribe(
|
||||
response => {
|
||||
this.filteredResults = response.results;
|
||||
this.length = response.total;
|
||||
},
|
||||
error => {
|
||||
console.error('Error al obtener los resultados filtrados', error);
|
||||
this.filteredResults = [];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onPageChange(event: PageEvent) {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.length = event.length;
|
||||
this.applyFilter();
|
||||
}
|
||||
|
||||
saveFilters() {
|
||||
const dialogRef = this.dialog.open(SaveFiltersDialogComponent);
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
const filters = {
|
||||
name: result,
|
||||
favourite: true,
|
||||
filters: {
|
||||
filter0: this.filterName,
|
||||
filter1: this.selectedFilter1,
|
||||
filter2: this.selectedFilter2,
|
||||
filter3: this.selectedFilterOS,
|
||||
filter4: this.selectedFilterStatus,
|
||||
filter5: this.filterIP,
|
||||
filter6: this.filterMAC,
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
this.http.post(`${this.baseUrl}/views`, filters).subscribe(response => {
|
||||
console.log('Response from server:', response);
|
||||
this.toastService.success('Se ha guardado el filtro correctamente');
|
||||
}, error => {
|
||||
console.error('Error:', error);
|
||||
this.toastService.error(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);
|
||||
this.filterName = response.filters.filter0 || '';
|
||||
this.selectedFilter1 = response.filters.filter1 || null;
|
||||
this.selectedFilter2 = response.filters.filter2 || '';
|
||||
|
||||
this.selectedFilterOS = response.filters.filter3 || [];
|
||||
this.selectedFilterStatus = response.filters.filter4 || [];
|
||||
this.filterIP = response.filters.filter5 || '';
|
||||
this.filterMAC = response.filters.filter6 || '';
|
||||
|
||||
this.applyFilter();
|
||||
}
|
||||
}, error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onCheckboxChange(event: any, name: string, uuid: string) {
|
||||
if (event.checked) {
|
||||
if (!this.selectedElements.includes(uuid)) {
|
||||
this.selectedElements.push(uuid);
|
||||
}
|
||||
} else {
|
||||
const index = this.selectedElements.indexOf(uuid);
|
||||
if (index > -1) {
|
||||
this.selectedElements.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.isAllSelected = this.filteredResults.every(result =>
|
||||
this.selectedElements.includes(result['@id'])
|
||||
);
|
||||
}
|
||||
|
||||
toggleSelectAll() {
|
||||
this.isAllSelected = !this.isAllSelected;
|
||||
|
||||
if (this.isAllSelected) {
|
||||
this.selectedElements = this.filteredResults.map(result => result['@id']);
|
||||
} else {
|
||||
this.selectedElements = [];
|
||||
}
|
||||
|
||||
this.filteredResults.forEach(result => {
|
||||
result.selected = this.isAllSelected;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
isSelected(name: string): boolean {
|
||||
return this.selectedElements.includes(name);
|
||||
|
||||
}
|
||||
|
||||
sendActions() {
|
||||
const dialogRef = this.dialog.open(AcctionsModalComponent, { data: { selectedElements: this.selectedElements }, width: '700px'});
|
||||
}
|
||||
|
||||
onPxeBootFile(): void {
|
||||
const dialog = this.dialog.open(CreatePxeBootFileComponent, { data: this.selectedElements, width: '400px' });
|
||||
dialog.afterClosed().subscribe(() => {
|
||||
this.dialog.closeAll();
|
||||
});
|
||||
}
|
||||
|
||||
onCommandSelect(action: any): void {
|
||||
if (action === 'partition') {
|
||||
this.openPartitionAssistant();
|
||||
}
|
||||
|
||||
if (action === 'create-image') {
|
||||
this.openCreateImageAssistant();
|
||||
}
|
||||
|
||||
if (action === 'deploy-image') {
|
||||
this.openDeployImageAssistant();
|
||||
}
|
||||
}
|
||||
|
||||
openPartitionAssistant(): void {
|
||||
const client = this.selectedElements[0];
|
||||
console.log(client)
|
||||
this.router.navigate([`${client}/partition-assistant`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
openCreateImageAssistant(): void {
|
||||
const client = this.selectedElements[0];
|
||||
this.router.navigate([`${client}/create-image`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
openDeployImageAssistant(): void {
|
||||
const client = this.selectedElements[0];
|
||||
this.router.navigate([`${client}/deploy-image`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
onDobleClick(event: MouseEvent, data: any, type: string): void {
|
||||
if (type === 'client') {
|
||||
this.router.navigate(['client', data]);
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'title2Step',
|
||||
'filterSelectionStep',
|
||||
'viewModeStep',
|
||||
'filtersStep',
|
||||
'selectAllStep',
|
||||
'saveFiltersStep',
|
||||
'sendActionStep',
|
||||
'addPxeStep',
|
||||
'resultsStep'
|
||||
],
|
||||
showPrevButton: true,
|
||||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
padding: 10px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.search-string {
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.mat-elevation-z8 {
|
||||
margin-top: 30px;
|
||||
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.search-boolean {
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.search-select {
|
||||
flex: 2;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
button{
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.client-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.client-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.client-ip,
|
||||
.client-mac {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.chip-busy {
|
||||
background-color: indianred !important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.chip-og-live {
|
||||
background-color: yellow !important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.chip-windows,
|
||||
.chip-windows-session,
|
||||
.chip-macos {
|
||||
background-color: cornflowerblue !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.chip-linux,
|
||||
.chip-linux-session {
|
||||
background-color: mediumpurple !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.chip-off {
|
||||
background-color: darkgrey !important;
|
||||
color: white;
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
<div class="header-container">
|
||||
<button mat-icon-button color="primary" (click)="iniciarTour()">
|
||||
<mat-icon>help</mat-icon>
|
||||
</button>
|
||||
<h2 class="title" i18n="@@adminImagesTitle" joyrideStep="clientTabtitleStep" text="En esta pantalla se podran administrar todos los clientes del sistema sin jerarquias.">{{ 'adminImagesTitle' | translate }}</h2>
|
||||
<div class="images-button-row">
|
||||
<button mat-flat-button color="primary" (click)="resetFilters()" joyrideStep="clientTabResetFiltersStep" text="Reinicia los filtros aplicados para mostrar todos los clientes.">{{ 'resetFiltersButton' | translate }}</button>
|
||||
<button mat-flat-button color="primary" (click)="addClient($event)" joyrideStep="clientTabaddClientStep" text="Añade un nuevo cliente a la lista.">{{ 'addClientButton' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
||||
<div class="search-container" joyrideStep="clientTabsearchContainerStep" text="Filtra los clientes por nombre, IP, MAC o unidad organizativa.">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">{{ 'searchClientNameLabel' | translate }}</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">{{ 'searchHint' | translate }}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">{{ 'searchIPLabel' | translate }}</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['ip']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">{{ 'searchHint' | translate }}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">{{ 'searchMACLabel' | translate }}</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['mac']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">{{ 'searchHint' | translate }}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="search-select" >
|
||||
<mat-label i18n="@@organizational-unit-label">{{ 'organizationalUnitLabel' | translate }}</mat-label>
|
||||
<mat-select [(ngModel)]="filters['organizationalUnit.id']" (selectionChange)="search()">
|
||||
<mat-option *ngFor="let unit of organizationalUnits" [value]="unit.id" >
|
||||
{{ unit.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loading" class="loading-container">
|
||||
<mat-spinner></mat-spinner>
|
||||
</div>
|
||||
|
||||
<div *ngIf="loading">
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" joyrideStep="clientTabtableStep" text="Lista de clientes filtrados por tus criterios de búsqueda.">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let client" >
|
||||
<ng-container *ngIf="column.columnDef === 'name'">
|
||||
<div class="client-info">
|
||||
<div class="client-name">{{ client.name }}</div>
|
||||
<div class="client-ip">{{ client.ip }}</div>
|
||||
<div class="client-mac">{{ client.mac }}</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'status'">
|
||||
<mat-chip [ngClass]="{
|
||||
'chip-og-live': client.status === 'og-live',
|
||||
'chip-busy': client.status === 'busy',
|
||||
'chip-windows': client.status === 'windows' || client.status === 'windows-session',
|
||||
'chip-linux': client.status === 'linux' || client.status === 'linux-session',
|
||||
'chip-macos': client.status === 'macos',
|
||||
'chip-off': client.status === 'off'
|
||||
}">
|
||||
{{ client.status }}
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef !== 'status' && column.columnDef !== 'name'">
|
||||
{{ column.cell(client) }}
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">
|
||||
{{ 'columnActions' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let client" style="text-align: center;" joyrideStep="clientTabactionsStep"
|
||||
text="Acciones disponibles para cada cliente, como ver, editar o eliminar.">
|
||||
|
||||
<button
|
||||
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
|
||||
mat-icon-button color="primary"
|
||||
(click)="getStatus(client)">
|
||||
<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="info" (click)="handleClientClick($event, client)">
|
||||
<mat-icon i18n="@@deleteElementTooltip">visibility</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="primary" (click)="onEditClick($event, client.uuid)" i18n="@@editImage">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="onDeleteClick($event, client)">
|
||||
<mat-icon i18n="@@deleteElementTooltip">delete</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<div class="paginator-container" joyrideStep="clientTabpaginationStep" text="Navega entre las páginas de resultados utilizando el paginador.">
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageIndex]="page"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
|
@ -1,216 +0,0 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {PageEvent} from "@angular/material/paginator";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {DataService} from "./data.service";
|
||||
import {EditClientComponent} from "../../shared/clients/edit-client/edit-client.component";
|
||||
import {CreateClientComponent} from "../../shared/clients/create-client/create-client.component";
|
||||
import {DeleteModalComponent} from "../../../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||
import { throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import {ClientViewComponent} from "../../shared/client-view/client-view.component";
|
||||
import { Router } from '@angular/router';
|
||||
import { JoyrideService } from 'ngx-joyride';
|
||||
|
||||
@Component({
|
||||
selector: 'app-client-tab-view',
|
||||
templateUrl: './client-tab-view.component.html',
|
||||
styleUrl: './client-tab-view.component.css'
|
||||
})
|
||||
export class ClientTabViewComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
length: number = 0;
|
||||
loading:boolean = false;
|
||||
syncStatus: boolean = false;
|
||||
itemsPerPage: number = 10;
|
||||
pageSizeOptions: number[] = [5, 10, 25, 100];
|
||||
page: number = 0;
|
||||
filters: { [key: string]: string } = {};
|
||||
organizationalUnits: any[] = [];
|
||||
datePipe: DatePipe = new DatePipe('es-ES');
|
||||
syncingClientId: number | null = null;
|
||||
|
||||
private apiUrl = `${this.baseUrl}/clients`;
|
||||
|
||||
columns = [
|
||||
{
|
||||
columnDef: 'id',
|
||||
header: 'ID',
|
||||
cell: (client: any) => `${client.id}`
|
||||
},
|
||||
{
|
||||
columnDef: 'name',
|
||||
header: 'Nombre del cliente',
|
||||
cell: (client: any) => `${client.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'status',
|
||||
header: 'Estado',
|
||||
cell: (client: any) => `${client.status}`
|
||||
},
|
||||
{
|
||||
columnDef: 'organizationalUnit',
|
||||
header: 'Pertenece a',
|
||||
cell: (client: any) => `${client.organizationalUnit?.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'ogLive',
|
||||
header: 'OgLive',
|
||||
cell: (client: any) => `${client.ogLive?.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'subnet',
|
||||
header: 'Subred',
|
||||
cell: (client: any) => `${client.subnet}`
|
||||
},
|
||||
{
|
||||
columnDef: 'template',
|
||||
header: 'Plantilla PXE',
|
||||
cell: (client: any) => `${client.template?.name}`
|
||||
},
|
||||
];
|
||||
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
public dialog: MatDialog,
|
||||
private toastService: ToastrService,
|
||||
private http: HttpClient,
|
||||
private router: Router,
|
||||
private joyrideService: JoyrideService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getClients();
|
||||
this.loadOrganizationalUnits();
|
||||
}
|
||||
|
||||
getClients() {
|
||||
this.http.get<any>(`${this.apiUrl}?&page=${this.page + 1 }&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe(
|
||||
(data) => {
|
||||
this.dataSource.data = data['hydra:member'];
|
||||
this.length = data['hydra:totalItems'];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching commands', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onEditClick(event: MouseEvent, uuid: string): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' } );
|
||||
dialogRef.afterClosed().subscribe(() => this.getClients());
|
||||
}
|
||||
|
||||
addClient(event: MouseEvent, organizationalUnit:any = null): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(CreateClientComponent, { data: { organizationalUnit }, width: '900px'});
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.getClients();
|
||||
});
|
||||
}
|
||||
|
||||
onDeleteClick(event: MouseEvent, client: any): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px'
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.http.delete<void>(`${this.apiUrl}/${client.uuid}`).pipe(
|
||||
catchError(error => {
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
return throwError(error);
|
||||
})
|
||||
).subscribe(() => {
|
||||
this.toastService.success('Elemento eliminado correctamente');
|
||||
this.getClients();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getStatus(client: any): void {
|
||||
this.syncingClientId = client.uuid;
|
||||
this.syncStatus = true;
|
||||
|
||||
this.http.post(`${this.baseUrl}${client['@id']}/agent/status`, {}).subscribe(
|
||||
response => {
|
||||
this.toastService.success('Cliente actualizado correctamente');
|
||||
this.search();
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
},
|
||||
error => {
|
||||
this.toastService.error('Error de conexión con el cliente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
handleClientClick(event: MouseEvent, client: any): void {
|
||||
event.stopPropagation();
|
||||
this.router.navigate(['clients', client.uuid], { state: { clientData: client } });
|
||||
|
||||
}
|
||||
|
||||
resetFilters() {
|
||||
this.loading = true;
|
||||
this.filters = {};
|
||||
this.getClients();
|
||||
}
|
||||
|
||||
loadOrganizationalUnits() {
|
||||
this.loading = true;
|
||||
this.http.get<any>( `${this.baseUrl}/organizational-units?&page=1&itemsPerPage=10000`, {
|
||||
params: {
|
||||
'groups[]': ['organizational-unit:read:collection:short']
|
||||
}
|
||||
}).subscribe(
|
||||
response => {
|
||||
this.organizationalUnits = response['hydra:member'];
|
||||
this.loading = false;
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching parent units:', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
search(): void {
|
||||
this.loading = true;
|
||||
this.getClients()
|
||||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.length = event.length;
|
||||
this.getClients();
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'clientTabtitleStep',
|
||||
'clientTabResetFiltersStep',
|
||||
'clientTabaddClientStep',
|
||||
'clientTabsearchContainerStep',
|
||||
'clientTabtableStep',
|
||||
'clientTabactionsStep',
|
||||
'clientTabpaginationStep'
|
||||
],
|
||||
showPrevButton: true,
|
||||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import {HttpClient, HttpParams} from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DataService {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
|
||||
private apiUrl = `${this.baseUrl}/organizational-units`;
|
||||
private clientsUrl = `${this.baseUrl}/clients`;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getClients(itemsPerPage: number = 10, page: number = 1): Observable<any> {
|
||||
return this.http.get<any>(this.clientsUrl, {
|
||||
params: new HttpParams().set('itemsPerPage', itemsPerPage.toString()).set('page', page.toString())
|
||||
})
|
||||
.pipe(
|
||||
map(response => {
|
||||
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
|
||||
return response['hydra:member']
|
||||
} else {
|
||||
throw new Error('Unexpected response format');
|
||||
}
|
||||
}),
|
||||
catchError(error => {
|
||||
console.error('Error fetching clients', error);
|
||||
return throwError(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
padding: 10px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.search-string {
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.search-boolean {
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.mat-elevation-z8 {
|
||||
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.search-select {
|
||||
flex: 2;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.mat-chip-success {
|
||||
background-color: #4CAF50 !important;
|
||||
color: white !important;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
.button-row{
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.calendar-ico{
|
||||
margin-top: 5px;
|
||||
color: gray;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
<div class="header-container">
|
||||
<button mat-icon-button color="primary" (click)="iniciarTour()">
|
||||
<mat-icon>help</mat-icon>
|
||||
</button>
|
||||
<h2 class="title" i18n="@@adminImagesTitle" joyrideStep="titleS4tep" text="Gestiona las unidades organizativas desde esta pantalla.">{{ 'resetFiltersButton' | translate }}</h2>
|
||||
<div class="button-row">
|
||||
<button mat-flat-button color="primary" (click)="resetFilters()" joyrideStep="resetFiltersStep" text="Reinicia los filtros aplicados para mostrar todas las unidades organizativas.">Reiniciar filtros</button>
|
||||
<button mat-flat-button color="primary" (click)="addOrganizationalUnit($event)" joyrideStep="addOUStep" text="Añade una nueva unidad organizativa.">{{ 'addOUButton' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
||||
<div class="search-container" joyrideStep="searchContainerStep" text="Filtra las unidades organizativas por nombre o tipo.">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">{{ 'searchLabelOu' | translate }}</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">{{ 'searchHint' | translate }}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="search-boolean">
|
||||
<mat-label i18n="@@searchLabel">{{ 'typeLabel' | translate }}</mat-label>
|
||||
<mat-select [(ngModel)]="filters['type']" (selectionChange)="search()" placeholder="Seleccionar opción">
|
||||
<mat-option [value]="''">{{ 'allOption' | translate }}</mat-option>
|
||||
<mat-option [value]="'organizational-unit'">{{ 'centerOption' | translate }}</mat-option>
|
||||
<mat-option [value]="'classrooms-group'">{{ 'classroomsGroupOption' | translate }}</mat-option>
|
||||
<mat-option [value]="'classroom'">{{ 'classroomOption' | translate }}</mat-option>
|
||||
<mat-option [value]="'clients-group'">{{ 'clientsGroupOption' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" joyrideStep="tableStep" text="Aquí se muestran las unidades organizativas según los filtros aplicados.">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let ou">
|
||||
<ng-container *ngIf="column.columnDef !== 'available' && column.columnDef !== 'type'">
|
||||
{{ column.cell(ou) }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'available'">
|
||||
<mat-chip *ngIf="ou.available" class="mat-chip-success"><mat-icon class="calendar-ico">event_available</mat-icon></mat-chip>
|
||||
<mat-chip *ngIf="!ou.available" class="mat-chip-error"><mat-icon class="calendar-ico">event_busy</mat-icon></mat-chip>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'type'">
|
||||
<mat-chip>{{ ou.type }}</mat-chip>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">{{ 'columnActions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let ou" style="text-align: center;" joyrideStep="actionsStep" text="Usa estas opciones para ver, editar o eliminar una unidad organizativa.">
|
||||
<button mat-icon-button color="info" (click)="onShowClick($event, ou)"><mat-icon i18n="@@deleteElementTooltip">visibility</mat-icon></button>
|
||||
<button mat-icon-button color="primary" (click)="onEditClick($event, ou.uuid)" i18n="@@editImage"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="onDeleteClick($event, ou)"><mat-icon>delete</mat-icon></button>
|
||||
<button mat-icon-button color="info" [matMenuTriggerFor]="menu">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item [disabled]="ou.type !== 'classroom'" (click)="roomMap(ou)">
|
||||
<span i18n="@@viewTreeMenu"> {{ 'roomMapOption' | translate }}</span>
|
||||
</button>
|
||||
<button mat-menu-item [disabled]="ou.type !== 'organizational-unit'" (click)="onTreeClick(ou)">
|
||||
<span i18n="@@viewTreeMenu">{{ 'viewTreeMenu' | 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>
|
||||
|
||||
<div class="paginator-container" joyrideStep="paginationStep" text="Navega entre las páginas de unidades organizativas con el paginador.">
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageIndex]="page"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
|
@ -1,191 +0,0 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import {DataService} from "../client-tab-view/data.service";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {EditClientComponent} from "../../shared/clients/edit-client/edit-client.component";
|
||||
import {CreateClientComponent} from "../../shared/clients/create-client/create-client.component";
|
||||
import {DeleteModalComponent} from "../../../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||
import {catchError} from "rxjs/operators";
|
||||
import {throwError} from "rxjs";
|
||||
import {
|
||||
CreateOrganizationalUnitComponent
|
||||
} from "../../shared/organizational-units/create-organizational-unit/create-organizational-unit.component";
|
||||
import {
|
||||
ShowOrganizationalUnitComponent
|
||||
} from "../../shared/organizational-units/show-organizational-unit/show-organizational-unit.component";
|
||||
import {
|
||||
EditOrganizationalUnitComponent
|
||||
} from "../../shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component";
|
||||
import {ClassroomViewDialogComponent} from "../../shared/classroom-view/classroom-view-modal";
|
||||
import {TreeViewComponent} from "../../shared/tree-view/tree-view.component";
|
||||
import { JoyrideService } from 'ngx-joyride';
|
||||
|
||||
@Component({
|
||||
selector: 'app-organizational-unit-tab-view',
|
||||
templateUrl: './organizational-unit-tab-view.component.html',
|
||||
styleUrl: './organizational-unit-tab-view.component.css'
|
||||
})
|
||||
export class OrganizationalUnitTabViewComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
length: number = 0;
|
||||
loading:boolean = false;
|
||||
itemsPerPage: number = 10;
|
||||
pageSizeOptions: number[] = [5, 10, 25, 100];
|
||||
page: number = 0;
|
||||
filters: { [key: string]: string } = {};
|
||||
organizationalUnits: any[] = [];
|
||||
datePipe: DatePipe = new DatePipe('es-ES');
|
||||
|
||||
private apiUrl = `${this.baseUrl}/organizational-units`;
|
||||
|
||||
columns = [
|
||||
{
|
||||
columnDef: 'id',
|
||||
header: 'ID',
|
||||
cell: (ou: any) => `${ou.id}`
|
||||
},
|
||||
{
|
||||
columnDef: 'name',
|
||||
header: 'Nombre',
|
||||
cell: (ou: any) => `${ou.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'type',
|
||||
header: 'Tipo',
|
||||
cell: (ou: any) => `${ou.type}`
|
||||
},
|
||||
{
|
||||
columnDef: 'remoteCalendar',
|
||||
header: 'Calendario',
|
||||
cell: (ou: any) => `${ou.remoteCalendar ? ou.remoteCalendar.name : '-'}`
|
||||
},
|
||||
{
|
||||
columnDef: 'available',
|
||||
header: 'Disponible remotePC',
|
||||
cell: (ou: any) => `${ou.available ? 'No' : 'Si'}`
|
||||
},
|
||||
{
|
||||
columnDef: 'createdAt',
|
||||
header: 'Fecha de creación',
|
||||
cell: (ou: any) => `${this.datePipe.transform(ou.createdAt, 'dd/MM/yyyy hh:mm:ss')}`
|
||||
}
|
||||
];
|
||||
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||
|
||||
constructor(
|
||||
private dataService: DataService,
|
||||
public dialog: MatDialog,
|
||||
private toastService: ToastrService,
|
||||
private http: HttpClient,
|
||||
private joyrideService: JoyrideService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getOrganizationalUnits();
|
||||
}
|
||||
|
||||
roomMap(room: any): void {
|
||||
console.log(room)
|
||||
const dialogRef = this.dialog.open(ClassroomViewDialogComponent, {
|
||||
width: '90vw',
|
||||
data: { clients: room.clients }
|
||||
});
|
||||
}
|
||||
|
||||
onTreeClick(data: any): void {
|
||||
const dialogRef = this.dialog.open(TreeViewComponent, { data: { data }, width: '800px'});
|
||||
}
|
||||
|
||||
getOrganizationalUnits() {
|
||||
this.http.get<any>(`${this.apiUrl}?&page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe(
|
||||
(data) => {
|
||||
this.dataSource.data = data['hydra:member'];
|
||||
this.length = data['hydra:totalItems'];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching ou', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onShowClick(event: MouseEvent, data: any): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != "client") {
|
||||
const dialogRef = this.dialog.open(ShowOrganizationalUnitComponent, { data: { data }, width: '700px'});
|
||||
}
|
||||
}
|
||||
|
||||
onEditClick(event: MouseEvent, uuid: string): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(EditOrganizationalUnitComponent, { data: { uuid }, width: '700px'});
|
||||
dialogRef.afterClosed().subscribe(() => this.getOrganizationalUnits());
|
||||
}
|
||||
|
||||
addOrganizationalUnit(event: MouseEvent, organizationalUnit:any = null): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(CreateOrganizationalUnitComponent, { data: { organizationalUnit }, width: '900px'});
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.getOrganizationalUnits();
|
||||
});
|
||||
}
|
||||
|
||||
onDeleteClick(event: MouseEvent, client: any): void {
|
||||
event.stopPropagation();
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px'
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.http.delete<void>(`${this.apiUrl}/${client.uuid}`).pipe(
|
||||
catchError(error => {
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
return throwError(error);
|
||||
})
|
||||
).subscribe(() => {
|
||||
this.toastService.success('Elemento eliminado correctamente');
|
||||
this.getOrganizationalUnits();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
resetFilters() {
|
||||
this.loading = true;
|
||||
this.filters = {};
|
||||
this.getOrganizationalUnits();
|
||||
}
|
||||
|
||||
search(): void {
|
||||
this.loading = true;
|
||||
this.getOrganizationalUnits()
|
||||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.length = event.length;
|
||||
this.getOrganizationalUnits();
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'titleS4tep',
|
||||
'resetFiltersStep',
|
||||
'addOUStep',
|
||||
'searchContainerStep',
|
||||
'tableStep',
|
||||
'actionsStep',
|
||||
'paginationStep'
|
||||
],
|
||||
showPrevButton: true,
|
||||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -18,8 +18,6 @@ import { EditClientComponent } from './shared/clients/edit-client/edit-client.co
|
|||
import { ShowOrganizationalUnitComponent } from './shared/organizational-units/show-organizational-unit/show-organizational-unit.component';
|
||||
import { TreeViewComponent } from './shared/tree-view/tree-view.component';
|
||||
import { LegendComponent } from './shared/legend/legend.component';
|
||||
import { ClientTabViewComponent } from './components/client-tab-view/client-tab-view.component';
|
||||
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';
|
||||
|
@ -83,8 +81,6 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
this.selectedClients.paginator = this._paginator;
|
||||
}
|
||||
}
|
||||
@ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent;
|
||||
@ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent;
|
||||
|
||||
private subscriptions: Subscription = new Subscription();
|
||||
|
||||
|
@ -160,14 +156,6 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
this.isTreeViewActive = false;
|
||||
}
|
||||
|
||||
onTabChange(event: MatTabChangeEvent): void {
|
||||
if (event.index === 2) {
|
||||
this.clientTabComponent.search();
|
||||
} else if (event.index === 3) {
|
||||
this.organizationalUnitTabComponent.search();
|
||||
}
|
||||
}
|
||||
|
||||
getFilters(): void {
|
||||
this.subscriptions.add(
|
||||
this.dataService.getFilters().subscribe(
|
||||
|
|
Loading…
Reference in New Issue