refs #1288. Added Menu CRUD
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
parent
d9d8eddc1d
commit
f51b255209
|
@ -40,6 +40,7 @@ import {
|
|||
MainRepositoryViewComponent
|
||||
} from "./components/repositories/main-repository-view/main-repository-view.component";
|
||||
import {EnvVarsComponent} from "./components/admin/env-vars/env-vars.component";
|
||||
import {MenusComponent} from "./components/menus/menus.component";
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
||||
{
|
||||
|
@ -74,6 +75,7 @@ const routes: Routes = [
|
|||
{ path: 'software', component: SoftwareComponent },
|
||||
{ path: 'software-profiles', component: SoftwareProfileComponent },
|
||||
{ path: 'operative-systems', component: OperativeSystemComponent },
|
||||
{ path: 'menus', component: MenusComponent },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -124,6 +124,8 @@ 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';
|
||||
import { MenusComponent } from './components/menus/menus.component';
|
||||
import { CreateMenuComponent } from './components/menus/create-menu/create-menu.component';
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
}
|
||||
|
@ -206,6 +208,8 @@ export function HttpLoaderFactory(http: HttpClient) {
|
|||
MainRepositoryViewComponent,
|
||||
ExecuteCommandOuComponent,
|
||||
EnvVarsComponent,
|
||||
MenusComponent,
|
||||
CreateMenuComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [BrowserModule,
|
||||
|
|
|
@ -183,10 +183,6 @@ mat-tree {
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
mat-tree mat-tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
<mat-option value="group">{{ 'computerGroups' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
|
|
|
@ -130,7 +130,16 @@
|
|||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'menuLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu">
|
||||
<mat-option *ngFor="let menu of menus" [value]="menu['@id']">
|
||||
{{ menu.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error>{{ 'menuError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@ export class CreateClientComponent implements OnInit {
|
|||
parentUnits: any[] = [];
|
||||
hardwareProfiles: any[] = [];
|
||||
ogLives: any[] = [];
|
||||
menus: any[] = [];
|
||||
templates: any[] = [];
|
||||
uploadedClients: any[] = [];
|
||||
repositories: any[] = [];
|
||||
|
@ -51,6 +52,7 @@ export class CreateClientComponent implements OnInit {
|
|||
this.loadOgLives();
|
||||
this.loadPxeTemplates();
|
||||
this.loadRepositories();
|
||||
this.loadMenus()
|
||||
}
|
||||
|
||||
initForm(): void {
|
||||
|
@ -71,6 +73,7 @@ export class CreateClientComponent implements OnInit {
|
|||
],
|
||||
ogLive: [null],
|
||||
repository: [null],
|
||||
menu: [null]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -129,6 +132,19 @@ export class CreateClientComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
loadMenus(): void {
|
||||
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
response => {
|
||||
this.menus = response['hydra:member'];
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching menus:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadRepositories(): void {
|
||||
const url = `${this.baseUrl}/image-repositories?page=1&itemsPerPage=10000`;
|
||||
|
||||
|
@ -146,13 +162,13 @@ export class CreateClientComponent implements OnInit {
|
|||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
|
||||
|
||||
reader.onload = (e: any) => {
|
||||
const textData = e.target.result;
|
||||
const regex = /host\s+(\S+)\s+\{\s+hardware\s+ethernet\s+([\da-fA-F:]+);\s+fixed-address\s+([\d.]+);\s+\}/g;
|
||||
let match;
|
||||
const clients = [];
|
||||
|
||||
|
||||
while ((match = regex.exec(textData)) !== null) {
|
||||
clients.push({
|
||||
name: match[1],
|
||||
|
@ -160,7 +176,7 @@ export class CreateClientComponent implements OnInit {
|
|||
ip: match[3]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (clients.length > 0) {
|
||||
this.uploadedClients = clients;
|
||||
this.toastService.success('Archivo cargado correctamente, los datos están listos para enviarse.', 'Éxito');
|
||||
|
@ -170,16 +186,16 @@ export class CreateClientComponent implements OnInit {
|
|||
this.showTextarea = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onTextarea(text: string): void {
|
||||
const regex = /host\s+(\S+)\s+\{\s+hardware\s+ethernet\s+([\da-fA-F:]+);\s+fixed-address\s+([\d.]+);\s+\}/g;
|
||||
let match;
|
||||
const clients = [];
|
||||
|
||||
|
||||
while ((match = regex.exec(text)) !== null) {
|
||||
clients.push({
|
||||
name: match[1],
|
||||
|
@ -187,7 +203,7 @@ export class CreateClientComponent implements OnInit {
|
|||
ip: match[3]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (clients.length > 0) {
|
||||
this.uploadedClients = clients;
|
||||
this.toastService.success('Datos cargados correctamente, los datos están listos para enviarse.', 'Éxito');
|
||||
|
@ -197,7 +213,7 @@ export class CreateClientComponent implements OnInit {
|
|||
this.showTextarea = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onSubmit(): void {
|
||||
if (this.isSingleClientForm) {
|
||||
if (this.clientForm.valid) {
|
||||
|
@ -230,7 +246,7 @@ export class CreateClientComponent implements OnInit {
|
|||
netiface: null,
|
||||
netDriver: null
|
||||
};
|
||||
|
||||
|
||||
this.http.post(`${this.baseUrl}/clients`, formData).subscribe(
|
||||
response => {
|
||||
this.toastService.success(`Cliente ${client.name} creado exitosamente`, 'Éxito');
|
||||
|
@ -241,7 +257,7 @@ export class CreateClientComponent implements OnInit {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
this.uploadedClients = [];
|
||||
this.dialogRef.close();
|
||||
} else {
|
||||
|
@ -249,11 +265,11 @@ export class CreateClientComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
toggleClientForm(): void {
|
||||
this.isSingleClientForm = !this.isSingleClientForm;
|
||||
}
|
||||
|
||||
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
|
|
@ -88,6 +88,15 @@
|
|||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'menuLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu">
|
||||
<mat-option *ngFor="let menu of menus" [value]="menu['@id']">
|
||||
{{ menu.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error>{{ 'menuError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ export class EditClientComponent {
|
|||
repositories: any[] = [];
|
||||
ogLives: any[] = [];
|
||||
templates: any[] = [];
|
||||
menus: any[] = [];
|
||||
isEditMode: boolean;
|
||||
protected netifaceTypes = [
|
||||
{ "name": 'Eth0', "value": "eth0" },
|
||||
|
@ -50,6 +51,7 @@ export class EditClientComponent {
|
|||
this.loadOgLives();
|
||||
this.loadPxeTemplates()
|
||||
this.loadRepositories();
|
||||
this.loadMenus()
|
||||
this.clientForm = this.fb.group({
|
||||
organizationalUnit: [null, Validators.required],
|
||||
name: ['', Validators.required],
|
||||
|
@ -62,6 +64,7 @@ export class EditClientComponent {
|
|||
hardwareProfile: null,
|
||||
ogLive: null,
|
||||
repository: null,
|
||||
menu: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -102,6 +105,19 @@ export class EditClientComponent {
|
|||
);
|
||||
}
|
||||
|
||||
loadMenus(): void {
|
||||
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
response => {
|
||||
this.menus = response['hydra:member'];
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching menus:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadRepositories(): void {
|
||||
const url = `${this.baseUrl}/image-repositories?page=1&itemsPerPage=10000`;
|
||||
|
||||
|
@ -146,6 +162,7 @@ export class EditClientComponent {
|
|||
repository: data.repository ? data.repository['@id'] : null,
|
||||
ogLive: data.ogLive ? data.ogLive['@id'] : null,
|
||||
template: data.template ? data.template['@id'] : null,
|
||||
menu: data.menu ? data.menu['@id'] : null,
|
||||
});
|
||||
this.loading = false;
|
||||
},
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
.dialog-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.menu-form {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.dialog-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dialog-actions {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<h2 mat-dialog-title> {{ menuId ? 'Editar' : 'Añadir' }} menú</h2>
|
||||
|
||||
<mat-dialog-content class="dialog-content">
|
||||
<form [formGroup]="menuForm" (ngSubmit)="save()" class="menu-form">
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Nombre del menú</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Url pública</mat-label>
|
||||
<input matInput formControlName="publicUrl" name="description">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Resolución</mat-label>
|
||||
<input matInput formControlName="resolution" name="comments">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Comentarios</mat-label>
|
||||
<input matInput formControlName="comments" name="comments">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end" class="dialog-actions">
|
||||
<button mat-button (click)="close()">Cancelar</button>
|
||||
<button mat-button color="primary" (click)="save()">Guardar</button>
|
||||
</mat-dialog-actions>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CreateMenuComponent } from './create-menu.component';
|
||||
|
||||
describe('CreateMenuComponent', () => {
|
||||
let component: CreateMenuComponent;
|
||||
let fixture: ComponentFixture<CreateMenuComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [CreateMenuComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CreateMenuComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,94 @@
|
|||
import {Component, Inject} from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {DataService} from "../../images/data.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-create-menu',
|
||||
templateUrl: './create-menu.component.html',
|
||||
styleUrl: './create-menu.component.css'
|
||||
})
|
||||
export class CreateMenuComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
menuForm: FormGroup<any>;
|
||||
menuId: string | null = null;
|
||||
softwareProfiles: any[] = [];
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private http: HttpClient,
|
||||
public dialogRef: MatDialogRef<CreateMenuComponent>,
|
||||
private toastService: ToastrService,
|
||||
private dataService: DataService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) {
|
||||
this.menuForm = this.fb.group({
|
||||
name: ['', Validators.required],
|
||||
publicUrl: ['', Validators.required],
|
||||
resolution: ['', Validators.required],
|
||||
comments: [''],
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.data) {
|
||||
this.load()
|
||||
}
|
||||
}
|
||||
|
||||
load(): void {
|
||||
this.dataService.getImage(this.data).subscribe({
|
||||
next: (response) => {
|
||||
this.menuForm = this.fb.group({
|
||||
name: [response.name, Validators.required],
|
||||
publicUrl: [response.publicUrl, Validators.required],
|
||||
resolution: [response.resolution, Validators.required],
|
||||
comments: [response.comments],
|
||||
});
|
||||
this.menuId = response['@id'];
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error fetching remote calendar:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
save(): void {
|
||||
const payload = {
|
||||
name: this.menuForm.value.name,
|
||||
publicUrl: this.menuForm.value.publicUrl,
|
||||
resolution: this.menuForm.value.resolution,
|
||||
comments: this.menuForm.value.comments,
|
||||
};
|
||||
|
||||
if (this.menuId) {
|
||||
this.http.put(`${this.baseUrl}${this.menuId}`, payload).subscribe(
|
||||
(response) => {
|
||||
this.toastService.success('Menu editado correctamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
(error) => {
|
||||
this.toastService.error(error['error']['hydra:description']);
|
||||
console.error('Error al editar la imagen', error);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.http.post(`${this.baseUrl}/menus`, payload).subscribe(
|
||||
(response) => {
|
||||
this.toastService.success('Menu añadido correctamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
(error) => {
|
||||
this.toastService.error(error['error']['hydra:description']);
|
||||
console.error('Error al añadir el menu', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.images-button-row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.lists-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.imagesLists-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card.unidad-card {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: 1px solid rgba(122, 122, 122, 0.555);
|
||||
}
|
||||
|
||||
.image-container h4 {
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.image-name{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.search-string {
|
||||
flex: 2;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.search-boolean {
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.mat-elevation-z8 {
|
||||
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.paginator-container {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
margin-bottom: 30px;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<div class="header-container">
|
||||
<button mat-icon-button color="primary" (click)="iniciarTour()">
|
||||
<mat-icon>help</mat-icon>
|
||||
</button>
|
||||
<h2 class="title" joyrideStep="titleStep" text="Desde esta pantalla podrás ver y administrar los menus exitentes.">Administrar menús</h2>
|
||||
<div class="images-button-row">
|
||||
<button mat-flat-button color="primary" (click)="addImage()" joyrideStep="addStep" text="Utiliza este botón para añadir un nuevo menu.">Añadir menú</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
||||
<div class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label>Buscar nombre de menú</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="search()" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint>Pulsar 'enter' para buscar</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let menu" >
|
||||
<ng-container>
|
||||
{{ column.cell(menu) }}
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
|
||||
<td mat-cell *matCellDef="let client" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" (click)="editMenu($event, client)" i18n="@@editImage"> <mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="deleteMenu($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">
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageIndex]="page"
|
||||
[pageSizeOptions]="[5, 10, 20, 40, 100]"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MenusComponent } from './menus.component';
|
||||
|
||||
describe('MenusComponent', () => {
|
||||
let component: MenusComponent;
|
||||
let fixture: ComponentFixture<MenusComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [MenusComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MenusComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,141 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {JoyrideService} from "ngx-joyride";
|
||||
import {Router} from "@angular/router";
|
||||
import {CreateRepositoryComponent} from "../repositories/create-repository/create-repository.component";
|
||||
import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||
import {CreateMenuComponent} from "./create-menu/create-menu.component";
|
||||
import {CreateImageComponent} from "../images/create-image/create-image.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-menus',
|
||||
templateUrl: './menus.component.html',
|
||||
styleUrl: './menus.component.css'
|
||||
})
|
||||
export class MenusComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
length: number = 0;
|
||||
itemsPerPage: number = 10;
|
||||
page: number = 0;
|
||||
loading: boolean = false;
|
||||
filters: { [key: string]: string } = {};
|
||||
datePipe: DatePipe = new DatePipe('es-ES');
|
||||
columns = [
|
||||
{
|
||||
columnDef: 'id',
|
||||
header: 'Id',
|
||||
cell: (repository: any) => `${repository.id}`
|
||||
},
|
||||
{
|
||||
columnDef: 'name',
|
||||
header: 'Nombre de menú',
|
||||
cell: (repository: any) => `${repository.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'publicUrl',
|
||||
header: 'Url pública',
|
||||
cell: (repository: any) => `${repository.publicUrl}`
|
||||
},
|
||||
{
|
||||
columnDef: 'resolution',
|
||||
header: 'Resolución',
|
||||
cell: (repository: any) => `${repository.resolution}`
|
||||
},
|
||||
{
|
||||
columnDef: 'createdAt',
|
||||
header: 'Fecha de creación',
|
||||
cell: (repository: any) => `${this.datePipe.transform(repository.createdAt, 'dd/MM/yyyy hh:mm:ss')}`
|
||||
}
|
||||
];
|
||||
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||
|
||||
private apiUrl = `${this.baseUrl}/menus`;
|
||||
|
||||
constructor(
|
||||
public dialog: MatDialog,
|
||||
private http: HttpClient,
|
||||
private toastService: ToastrService,
|
||||
private joyrideService: JoyrideService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.search();
|
||||
}
|
||||
|
||||
addImage(): void {
|
||||
const dialogRef = this.dialog.open(CreateMenuComponent, {
|
||||
width: '600px'
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
|
||||
search(): void {
|
||||
this.loading = true;
|
||||
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'];
|
||||
this.loading = false;
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching images', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
editMenu(event: MouseEvent, menu: any): void {
|
||||
event.stopPropagation();
|
||||
this.dialog.open(CreateMenuComponent, {
|
||||
width: '800px',
|
||||
data: menu['@id']
|
||||
}).afterClosed().subscribe(() => this.search());
|
||||
}
|
||||
|
||||
deleteMenu(event: MouseEvent,menu: any): void {
|
||||
event.stopPropagation();
|
||||
this.dialog.open(DeleteModalComponent, {
|
||||
width: '300px',
|
||||
data: { name: menu.name },
|
||||
}).afterClosed().subscribe((result) => {
|
||||
if (result) {
|
||||
this.http.delete(`${this.apiUrl}/${menu.uuid}`).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Menu eliminado con éxito');
|
||||
this.search();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al eliminar el menú:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.length = event.length;
|
||||
this.search();
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'titleStep',
|
||||
'addStep',
|
||||
],
|
||||
showPrevButton: true,
|
||||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
}
|
|
@ -128,5 +128,4 @@ export class RepositoriesComponent {
|
|||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -151,17 +151,10 @@
|
|||
</span>
|
||||
</mat-list-item>
|
||||
|
||||
<mat-list-item class="disabled" matTooltip="{{ 'TOOLTIP_MENUS' | translate }}" matTooltipShowDelay="1000">
|
||||
<mat-list-item routerLink="/menus" matTooltip="{{ 'TOOLTIP_MENUS' | translate }}" matTooltipShowDelay="1000">
|
||||
<span class="entry">
|
||||
<mat-icon class="icon">list</mat-icon>
|
||||
<span>{{ 'menus' | translate }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
|
||||
<mat-list-item class="disabled" matTooltip="{{ 'TOOLTIP_SEARCH' | translate }}" matTooltipShowDelay="1000">
|
||||
<span class="entry">
|
||||
<mat-icon class="icon">search</mat-icon>
|
||||
<span>{{ 'search' | translate }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
|
|
|
@ -211,6 +211,7 @@
|
|||
"mcastPortLabel": "Multicast Port",
|
||||
"mcastModeLabel": "Multicast Mode",
|
||||
"menuUrlLabel": "Menu URL",
|
||||
"menuLabel": "Menu",
|
||||
"hardwareProfileLabel": "Hardware Profile",
|
||||
"urlFormatError": "Invalid URL format.",
|
||||
"validationToggle": "Validation",
|
||||
|
|
|
@ -363,6 +363,7 @@
|
|||
"selectOptionPlaceholder": "Selecciona una opción",
|
||||
"yesOption": "Sí",
|
||||
"noOption": "No",
|
||||
"menuLabel": "Menu",
|
||||
"actionsColumn": "Acciones",
|
||||
"createServerButton": "Crear servidor",
|
||||
"labelName": "Nombre",
|
||||
|
|
Loading…
Reference in New Issue