diff --git a/ogWebconsole/src/app/app-routing.module.ts b/ogWebconsole/src/app/app-routing.module.ts
index dbb8779..e1f456c 100644
--- a/ogWebconsole/src/app/app-routing.module.ts
+++ b/ogWebconsole/src/app/app-routing.module.ts
@@ -15,6 +15,7 @@ import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-bo
import {OgbootStatusComponent} from "./components/ogboot/ogboot-status/ogboot-status.component";
import { OgdhcpComponent } from './components/ogdhcp/ogdhcp.component';
import { OgDhcpSubnetsComponent } from './components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component';
+import { CalendarComponent } from "./components/calendar/calendar.component";
import { CommandsComponent } from './components/commands/main-commands/commands.component';
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
@@ -36,8 +37,7 @@ const routes: Routes = [
{ path: 'dhcp', component: OgdhcpComponent },
{ path: 'dhcp-subnets', component: OgDhcpSubnetsComponent },
{ path: 'commands', component: CommandsComponent },
- { path: 'commands-groups', component: CommandsGroupsComponent },
- { path: 'commands-task', component: CommandsTaskComponent },
+ { path: 'calendars', component: CalendarComponent },
],
},
{
diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts
index a201d9e..abfb8b6 100644
--- a/ogWebconsole/src/app/app.module.ts
+++ b/ogWebconsole/src/app/app.module.ts
@@ -1,5 +1,3 @@
-// @ts-ignore
-
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
@@ -88,6 +86,11 @@ import { CommandDetailComponent } from './components/commands/main-commands/deta
import { CreateCommandComponent } from './components/commands/main-commands/create-command/create-command.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
+import { CalendarComponent } from './components/calendar/calendar.component';
+import { CreateCalendarComponent } from './components/calendar/create-calendar/create-calendar.component';
+import {MatRadioButton, MatRadioGroup} from "@angular/material/radio";
+import { CreateCalendarRuleComponent } from './components/calendar/create-calendar-rule/create-calendar-rule.component';
+
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
import { CreateCommandGroupComponent } from './components/commands/commands-groups/create-command-group/create-command-group.component';
@@ -140,6 +143,9 @@ import { ClientTabViewComponent } from './components/groups/client-tab-view/clie
CommandsComponent,
CommandDetailComponent,
CreateCommandComponent,
+ CalendarComponent,
+ CreateCalendarComponent,
+ CreateCalendarRuleComponent
CommandsGroupsComponent,
CommandsTaskComponent,
CreateCommandGroupComponent,
@@ -183,7 +189,7 @@ import { ClientTabViewComponent } from './components/groups/client-tab-view/clie
progressAnimation: 'increasing',
closeButton: true
}
- ), MatGridList, MatTree, MatTreeNode, MatNestedTreeNode, MatTreeNodeToggle, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeOutlet, MatPaginator, MatGridTile, MatExpansionPanel, MatExpansionPanelTitle, MatExpansionPanelDescription
+ ), MatGridList, MatTree, MatTreeNode, MatNestedTreeNode, MatTreeNodeToggle, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeOutlet, MatPaginator, MatGridTile, MatExpansionPanel, MatExpansionPanelTitle, MatExpansionPanelDescription, MatRadioGroup, MatRadioButton
],
schemas: [
CUSTOM_ELEMENTS_SCHEMA,
diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.css b/ogWebconsole/src/app/components/calendar/calendar.component.css
new file mode 100644
index 0000000..16117cb
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/calendar.component.css
@@ -0,0 +1,102 @@
+.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;
+}
+
+.example-headers-align .mat-expansion-panel-header-description {
+ justify-content: space-between;
+ align-items: center;
+}
+
+.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field {
+ margin-left: 8px;
+}
+
+.example-button-row {
+ display: table-cell;
+ max-width: 600px;
+}
+
+.example-button-row .mat-mdc-button-base {
+ margin: 8px 8px 8px 0;
+}
+
diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.html b/ogWebconsole/src/app/components/calendar/calendar.component.html
new file mode 100644
index 0000000..990232f
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/calendar.component.html
@@ -0,0 +1,58 @@
+
+
+
+
+ Buscar nombre de calendario
+
+ search
+ Pulsar 'enter' para buscar
+
+
+
+
+ {{ column.header }} |
+
+
+
+ {{ image[column.columnDef] ? 'check_circle' : 'cancel' }}
+
+
+
+
+
+ {{ image.downloadUrl ? image.downloadUrl.substring(0, 20) + '...' : '' }}
+
+
+
+
+ {{ column.cell(image) }}
+
+
+ |
+
+
+
+ Acciones |
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.spec.ts b/ogWebconsole/src/app/components/calendar/calendar.component.spec.ts
new file mode 100644
index 0000000..43d63ca
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/calendar.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CalendarComponent } from './calendar.component';
+
+describe('CalendarComponent', () => {
+ let component: CalendarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [CalendarComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(CalendarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ogWebconsole/src/app/components/calendar/calendar.component.ts b/ogWebconsole/src/app/components/calendar/calendar.component.ts
new file mode 100644
index 0000000..0a1671d
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/calendar.component.ts
@@ -0,0 +1,149 @@
+import {Component, OnInit, signal} 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 {DataService} from "./data.service";
+import {ToastrService} from "ngx-toastr";
+import {InfoImageComponent} from "../ogboot/images/info-image/info-image/info-image.component";
+import {PageEvent} from "@angular/material/paginator";
+import {CreateCalendarComponent} from "./create-calendar/create-calendar.component";
+import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component";
+
+@Component({
+ selector: 'app-calendar',
+ templateUrl: './calendar.component.html',
+ styleUrl: './calendar.component.css'
+})
+export class CalendarComponent implements OnInit {
+ baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
+ images: { downloadUrl: string; name: string; uuid: string }[] = [];
+ dataSource = new MatTableDataSource();
+ length: number = 0;
+ itemsPerPage: number = 10;
+ page: number = 1;
+ pageSizeOptions: number[] = [5, 10, 20, 40, 100];
+ selectedElements: string[] = [];
+ loading:boolean = false;
+ filters: { [key: string]: string } = {};
+ alertMessage: string | null = null;
+ readonly panelOpenState = signal(false);
+ datePipe: DatePipe = new DatePipe('es-ES');
+ columns = [
+ {
+ columnDef: 'id',
+ header: 'ID',
+ cell: (user: any) => `${user.id}`,
+ },
+ {
+ columnDef: 'name',
+ header: 'Nombre',
+ cell: (user: any) => `${user.name}`
+ },
+ {
+ columnDef: 'createdAt',
+ header: 'Fecha de creación',
+ cell: (user: any) => `${this.datePipe.transform(user.createdAt, 'dd/MM/yyyy hh:mm:ss')}`,
+ }
+ ];
+ displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
+
+ private apiUrl = `${this.baseUrl}/remote-calendars`;
+
+ constructor(
+ public dialog: MatDialog,
+ private http: HttpClient,
+ private dataService: DataService,
+ private toastService: ToastrService
+ ) {}
+
+ ngOnInit(): void {
+ this.search();
+ }
+
+ addImage(): void {
+ const dialogRef = this.dialog.open(CreateCalendarComponent, {
+ width: '400px'
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ console.log('The dialog was closed');
+ this.search();
+ });
+ }
+
+ search(): void {
+ this.loading = true;
+ this.dataService.getRemoteCalendars(this.filters).subscribe(
+ data => {
+ this.dataSource.data = data;
+ this.loading = false;
+ },
+ error => {
+ console.error('Error fetching og lives', error);
+ this.loading = false;
+ }
+ );
+ }
+
+ sync(calendar: any): void {
+ console.log('Syncing calendars');
+ }
+
+ editCalendar(calendar: any): void {
+ const dialogRef = this.dialog.open(CreateCalendarComponent, {
+ width: '700px',
+ data: calendar['@id']
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ this.search();
+ }
+ });
+ }
+
+ deleteCalendar(calendar: any): void {
+ const dialogRef = this.dialog.open(DeleteModalComponent, {
+ width: '400px',
+ data: { name: calendar.name }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ const apiUrl = `${this.baseUrl}${calendar['@id']}`;
+
+ this.http.delete(apiUrl).subscribe({
+ next: () => {
+ console.log('Calendar deleted successfully');
+ this.search();
+ this.toastService.success('Calendar deleted successfully');
+ },
+ error: (error) => {
+ this.toastService.error('Error deleting calendar');
+ }
+ });
+ } else {
+ console.log('calendar deletion cancelled');
+ }
+ });
+ }
+
+ applyFilter() {
+ this.http.get(`${this.apiUrl}?page=${this.page}&itemsPerPage=${this.itemsPerPage}`).subscribe({
+ next: (response) => {
+ this.dataSource.data = response['hydra:member'];
+ this.length = response['hydra:totalItems'];
+ },
+ error: (error) => {
+ console.error('Error al cargar las imágenes:', error);
+ }
+ });
+ }
+
+ onPageChange(event: PageEvent) {
+ this.page = event.pageIndex;
+ this.itemsPerPage = event.pageSize;
+ this.applyFilter();
+ }
+}
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.css b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.css
new file mode 100644
index 0000000..13e2689
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.css
@@ -0,0 +1,30 @@
+.full-width {
+ width: 100%;
+}
+.form-container {
+ padding: 40px;
+}
+
+.form-group {
+ margin-top: 20px;
+ margin-bottom: 26px;
+}
+
+.full-width {
+ width: 100%;
+ margin-bottom: 16px;
+}
+
+.checkbox-group {
+ margin: 15px 0;
+ align-items: flex-start;
+}
+
+.time-fields {
+ display: flex;
+ gap: 15px; /* Espacio entre los campos */
+}
+
+.time-field {
+ flex: 1;
+}
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.html b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.html
new file mode 100644
index 0000000..8249a20
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.html
@@ -0,0 +1,61 @@
+{{ isEditMode ? 'Editar' : 'Añadir' }} calendario
+
+ ¿Disponibilidad remoto?
+
+
+
+
+
+
+
+
+
+
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.spec.ts b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.spec.ts
new file mode 100644
index 0000000..607fb50
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateCalendarRuleComponent } from './create-calendar-rule.component';
+
+describe('CreateCalendarRuleComponent', () => {
+ let component: CreateCalendarRuleComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [CreateCalendarRuleComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(CreateCalendarRuleComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts
new file mode 100644
index 0000000..6711779
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar-rule/create-calendar-rule.component.ts
@@ -0,0 +1,115 @@
+import {Component, Inject} from '@angular/core';
+import {ToastrService} from "ngx-toastr";
+import {HttpClient} from "@angular/common/http";
+import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
+
+@Component({
+ selector: 'app-create-calendar-rule',
+ templateUrl: './create-calendar-rule.component.html',
+ styleUrl: './create-calendar-rule.component.css'
+})
+export class CreateCalendarRuleComponent {
+ baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
+ name: string = '';
+ remoteCalendarRules: any[] = [];
+ weekDays: string[] = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo'];
+ busyWeekDays: { [key: string]: boolean } = {};
+ busyFromHour: any = null;
+ busyToHour: any = null;
+ availableFromDate: any = null;
+ availableToDate: any = null;
+ isRemoteAvailable: boolean = false;
+ showAdditionalForm: boolean = false;
+ availableReason: any = null;
+ isEditMode: boolean = false;
+ ruleId: string | null = null;
+ calendarId: string | null = null;
+ selectedDaysIndices: number[] = [];
+
+ constructor(
+ private toastService: ToastrService,
+ private http: HttpClient,
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public data: any,
+) { }
+
+ ngOnInit(): void {
+ this.calendarId = this.data.calendar
+ if (this.data) {
+ this.isEditMode = true;
+ this.availableFromDate = this.data.rule.availableFromDate;
+ this.availableToDate = this.data.rule.availableToDate;
+ this.isRemoteAvailable = this.data.rule.isRemoteAvailable;
+ this.availableReason = this.data.rule.availableReason;
+ this.busyFromHour = this.data.rule.busyFromHour;
+ this.busyToHour = this.data.rule.busyToHour;
+ if (this.data.rule.busyWeekDays) {
+ this.busyWeekDays = this.data.rule.busyWeekDays.reduce((acc: {
+ [x: string]: boolean;
+ }, day: string | number) => {
+ // @ts-ignore
+ acc[this.weekDays[day]] = true;
+ return acc;
+ }, {});
+ }
+ this.ruleId = this.data.rule['@id']
+ }
+ }
+
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+
+ toggleAdditionalForm(): void {
+ this.showAdditionalForm = !this.showAdditionalForm;
+ }
+
+ getSelectedDaysIndices() {
+ this.selectedDaysIndices = this.weekDays
+ .map((day, index) => this.busyWeekDays[day] ? index : -1)
+ .filter(index => index !== -1);
+ }
+
+ submitRule(): void {
+ this.getSelectedDaysIndices()
+ const selectedDaysArray = Object.keys(this.busyWeekDays).map((day, index) => this.busyWeekDays[index]);
+
+ const formData = {
+ remoteCalendar: this.calendarId,
+ busyWeekDays: this.selectedDaysIndices,
+ busyFromHour: this.busyFromHour,
+ busyToHour: this.busyToHour,
+ availableFromDate: this.availableFromDate,
+ availableToDate: this.availableToDate,
+ isRemoteAvailable: this.isRemoteAvailable,
+ availableReason: this.availableReason
+ };
+
+ if (this.isEditMode && this.ruleId) {
+ this.http.put(`${this.baseUrl}${this.ruleId}`, formData)
+ .subscribe({
+ next: (response) => {
+ this.toastService.success('Calendar updated successfully');
+ this.dialogRef.close(true);
+ },
+ error: (error) => {
+ console.error('Error:', error);
+ this.toastService.error(error.error['hydra:description']);
+ }
+ });
+ } else {
+ this.http.post(`${this.baseUrl}/remote-calendar-rules`, formData)
+ .subscribe({
+ next: (response) => {
+ this.toastService.success('Calendar created successfully');
+ this.dialogRef.close(true);
+ },
+ error: (error) => {
+ console.error('Error:', error);
+ this.toastService.error(error.error['hydra:description']);
+ }
+ });
+ }
+ console.log(formData);
+ }
+}
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.css b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.css
new file mode 100644
index 0000000..722ef4f
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.css
@@ -0,0 +1,60 @@
+.full-width {
+ width: 100%;
+}
+.form-container {
+ padding: 40px;
+}
+
+.form-group {
+ margin-top: 20px;
+ margin-bottom: 26px;
+}
+
+.full-width {
+ width: 100%;
+ margin-bottom: 16px;
+}
+
+.additional-form {
+ margin-top: 20px;
+}
+
+.checkbox-group {
+ display: flex;
+ flex-direction: column;
+ margin: 15px 0;
+ align-items: flex-start;
+}
+
+.time-fields {
+ display: flex;
+ gap: 15px; /* Espacio entre los campos */
+}
+
+.time-field {
+ flex: 1;
+}
+
+.list-item-content {
+ display: flex;
+ align-items: flex-start; /* Alinea el contenido al inicio */
+ justify-content: space-between; /* Espacio entre los textos y los íconos */
+ width: 100%; /* Asegúrate de que el contenido ocupe todo el ancho */
+}
+
+.text-content {
+ flex-grow: 1; /* Permite que este contenedor ocupe el espacio disponible */
+ margin-right: 16px; /* Espaciado a la derecha para separar de los íconos */
+ margin-left: 10px;
+}
+
+.icon-container {
+ display: flex;
+ align-items: center; /* Alinea los íconos verticalmente */
+}
+
+.right-icon {
+ margin-left: 8px; /* Espaciado entre los íconos */
+ cursor: pointer;
+}
+
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.html b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.html
new file mode 100644
index 0000000..c90baeb
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.html
@@ -0,0 +1,45 @@
+{{ isEditMode ? 'Editar' : 'Añadir' }} calendario
+
+
+
+ Nombre
+
+ mode_edit
+
+
+
Reglas
+
+
+
+
+
+
+
+
+
+
event_available
+
+
{{ rule.isRemoteAvailable ? 'Disponible' : 'No disponible ( periodo presencial )' }}
+
{{ rule.busyFromHour }} - {{ rule.busyToHour }}
+
{{ rule.availableReason }} | {{ rule.busyFromHour }} - {{ rule.busyToHour }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.spec.ts b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.spec.ts
new file mode 100644
index 0000000..ce6a69c
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateCalendarComponent } from './create-calendar.component';
+
+describe('CreateCalendarComponent', () => {
+ let component: CreateCalendarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [CreateCalendarComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(CreateCalendarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts
new file mode 100644
index 0000000..5e7254e
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/create-calendar/create-calendar.component.ts
@@ -0,0 +1,128 @@
+import {Component, Inject, OnInit} from '@angular/core';
+import {ToastrService} from "ngx-toastr";
+import {HttpClient} from "@angular/common/http";
+import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
+import {CreateCalendarRuleComponent} from "../create-calendar-rule/create-calendar-rule.component";
+import {DataService} from "../data.service";
+import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/delete-modal.component";
+
+@Component({
+ selector: 'app-create-calendar',
+ templateUrl: './create-calendar.component.html',
+ styleUrl: './create-calendar.component.css'
+})
+export class CreateCalendarComponent implements OnInit {
+ baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
+ name: string = '';
+ remoteCalendarRules: any[] = [];
+ isEditMode: boolean = false;
+ calendarId: string | null = null;
+
+ constructor(
+ private toastService: ToastrService,
+ private http: HttpClient,
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public data: any,
+ public dialog: MatDialog,
+ private dataService: DataService,
+ ) { }
+
+ ngOnInit(): void {
+ if (this.data) {
+ this.load()
+ }
+ }
+
+ load(): void {
+ this.dataService.getRemoteCalendar(this.data).subscribe({
+ next: (response) => {
+ this.isEditMode = true;
+ this.name = response.name;
+ this.remoteCalendarRules = response.remoteCalendarRules;
+ this.calendarId = this.data;
+ },
+ error: (err) => {
+ console.error('Error fetching remote calendar:', err);
+ }
+ });
+ }
+
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+
+ submitForm(): void {
+ const payload = {
+ name: this.name
+ };
+
+ if (this.isEditMode && this.calendarId) {
+ this.http.patch(`${this.baseUrl}${this.calendarId}`, payload)
+ .subscribe({
+ next: (response) => {
+ this.toastService.success('Calendar updated successfully');
+ this.dialogRef.close(true);
+ this.load()
+ },
+ error: (error) => {
+ console.error('Error:', error);
+ this.toastService.error(error.error['hydra:description']);
+ }
+ });
+ } else {
+ this.http.post(`${this.baseUrl}/remote-calendars`, payload)
+ .subscribe({
+ next: (response) => {
+ this.toastService.success('Calendar created successfully');
+ this.dialogRef.close(true);
+ this.load()
+ },
+ error: (error) => {
+ console.error('Error:', error);
+ this.toastService.error(error.error['hydra:description']);
+ }
+ });
+ }
+ }
+
+ createRule(rule: any = null): void {
+ const dialogRef = this.dialog.open(CreateCalendarRuleComponent, {
+ width: '700px',
+ data: {
+ calendar: this.calendarId,
+ rule: rule
+ },
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ this.load()
+ }
+ });
+ }
+
+ deleteCalendarRule(rule: any): void {
+ const dialogRef = this.dialog.open(DeleteModalComponent, {
+ width: '400px',
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ const apiUrl = `${this.baseUrl}${rule['@id']}`;
+
+ this.http.delete(apiUrl).subscribe({
+ next: () => {
+ console.log('Calendar deleted successfully');
+ this.load();
+ this.toastService.success('Calendar deleted successfully');
+ },
+ error: (error) => {
+ this.toastService.error('Error deleting calendar');
+ }
+ });
+ } else {
+ console.log('calendar deletion cancelled');
+ }
+ });
+ }
+}
diff --git a/ogWebconsole/src/app/components/calendar/data.service.ts b/ogWebconsole/src/app/components/calendar/data.service.ts
new file mode 100644
index 0000000..ba9b568
--- /dev/null
+++ b/ogWebconsole/src/app/components/calendar/data.service.ts
@@ -0,0 +1,48 @@
+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}/remote-calendars?page=1&itemsPerPage=1000`;
+
+ constructor(private http: HttpClient) {}
+
+ getRemoteCalendars(filters: { [key: string]: string }): Observable {
+ const params = new HttpParams({ fromObject: filters });
+
+ return this.http.get(this.apiUrl, { params }).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 remote calendars', error);
+ return throwError(error);
+ })
+ );
+ }
+
+ getRemoteCalendar(id: string): Observable {
+ return this.http.get(`${this.baseUrl}${id}`).pipe(
+ map(response => {
+ if (response.name && response.remoteCalendarRules) {
+ return response;
+ } else {
+ throw new Error('Unexpected response format');
+ }
+ }),
+ catchError(error => {
+ console.error('Error fetching calendar', error);
+ return throwError(error);
+ })
+ );
+ }
+}
diff --git a/ogWebconsole/src/app/components/groups/client-view/client-view.component.html b/ogWebconsole/src/app/components/groups/client-view/client-view.component.html
index d60e173..7cbdd4d 100644
--- a/ogWebconsole/src/app/components/groups/client-view/client-view.component.html
+++ b/ogWebconsole/src/app/components/groups/client-view/client-view.component.html
@@ -44,7 +44,7 @@
-
+
diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts
index 184aa3e..5cd48ea 100644
--- a/ogWebconsole/src/app/components/groups/groups.component.ts
+++ b/ogWebconsole/src/app/components/groups/groups.component.ts
@@ -126,7 +126,6 @@ export class GroupsComponent implements OnInit {
this.loadingChildren = true
this.dataService.getChildren(id).subscribe(
childrenData => {
- console.log('Children data:', childrenData);
this.dataService.getClients(id).subscribe(
clientsData => {
this.clientsData = clientsData;
diff --git a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html
index 55ea6fc..19cce7f 100644
--- a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html
+++ b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.html
@@ -49,6 +49,17 @@
Aforo
+
+
+
+ Calendario Asociado
+
+
+ {{ calendar.name }}
+
+
+
+
@@ -83,7 +94,7 @@
bootFileName
-
+
Url servidor Proxy
@@ -107,9 +118,7 @@
Modo P2P
-
+
{{ option.name }}
@@ -133,9 +142,7 @@
Modo Multicast
-
+
{{ option.name }}
@@ -147,7 +154,7 @@
Perfil de Hardware
- {{ unit.description }}
+ {{ unit.description }}
Formato de URL inválido.
diff --git a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts
index 2e7f363..4d55383 100644
--- a/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts
+++ b/ogWebconsole/src/app/components/groups/organizational-units/create-organizational-unit/create-organizational-unit.component.ts
@@ -1,9 +1,9 @@
-import {Component, OnInit, Output, EventEmitter, Inject} from '@angular/core';
+import { Component, OnInit, Output, EventEmitter, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { HttpClient, HttpHeaders } from '@angular/common/http';
-import {ToastrService} from "ngx-toastr";
-import {DataService} from "../../data.service";
+import { ToastrService } from 'ngx-toastr';
+import { DataService } from '../../data.service';
@Component({
selector: 'app-create-organizational-unit',
@@ -24,17 +24,21 @@ export class CreateOrganizationalUnitComponent implements OnInit {
'classroom': 'Aula',
'clients-group': 'Grupo de clientes'
};
+ protected p2pModeOptions = [
+ { name: 'Leecher', value: 'p2p-mode-leecher' },
+ { name: 'Peer', value: 'p2p-mode-peer' },
+ { name: 'Seeder', value: 'p2p-mode-seeder' },
+ ];
+ multicastModeOptions: { name: string, value: string }[] = [
+ { name: 'Modo 1', value: 'mode1' },
+ { name: 'Modo 2', value: 'mode2' },
+ { name: 'Modo 3', value: 'mode3' },
+ ];
parentUnits: any[] = [];
hardwareProfiles: any[] = [];
- protected p2pModeOptions = [
- {"name": 'Leecher', "value": "p2p-mode-leecher"},
- {"name": 'Peer', "value": "p2p-mode-peer"},
- {"name": 'Seeder', "value": "p2p-mode-seeder"},
- ];
- protected multicastModeOptions = [
- {"name": 'Half duplex', "value": "half-duplex"},
- {"name": 'Full duplex', "value": "full-duplex"},
- ];
+ calendars: any[] = [];
+ selectedCalendarUuid: string | null = null;
+
@Output() unitAdded = new EventEmitter();
constructor(
@@ -70,7 +74,8 @@ export class CreateOrganizationalUnitComponent implements OnInit {
mcastMode: [''],
menu: [''],
hardwareProfile: [''],
- validation: [false]
+ validation: [false],
+ remoteCalendar: ['']
});
this.classroomInfoFormGroup = this._formBuilder.group({
location: [''],
@@ -83,28 +88,31 @@ export class CreateOrganizationalUnitComponent implements OnInit {
ngOnInit() {
this.loadParentUnits();
this.loadHardwareProfiles();
+ this.loadCalendars();
}
loadParentUnits() {
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
-
this.http.get(url).subscribe(
- response => {
- this.parentUnits = response['hydra:member'];
- },
- error => {
- console.error('Error fetching parent units:', error);
- }
+ response => this.parentUnits = response['hydra:member'],
+ error => console.error('Error fetching parent units:', error)
);
}
loadHardwareProfiles(): void {
this.dataService.getHardwareProfiles().subscribe(
- (data: any[]) => {
- this.hardwareProfiles = data;
- },
- (error: any) => {
- console.error('Error fetching hardware profiles', error);
+ (data: any[]) => this.hardwareProfiles = data,
+ error => console.error('Error fetching hardware profiles', error)
+ );
+ }
+
+ loadCalendars() {
+ const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
+ this.http.get(apiUrl).subscribe(
+ response => this.calendars = response['hydra:member'],
+ error => {
+ console.error('Error loading calendars', error);
+ this.openSnackBar(true, 'Error loading calendars');
}
);
}
@@ -121,26 +129,13 @@ export class CreateOrganizationalUnitComponent implements OnInit {
}
onSubmit() {
- if (this.generalFormGroup.valid && this.additionalInfoFormGroup.valid && this.networkSettingsFormGroup.valid && (this.generalFormGroup.value.type !== 'classroom' || this.classroomInfoFormGroup.valid)) {
- const generalFormValues = this.cleanFormValues(this.generalFormGroup);
- const additionalInfoFormValues = this.cleanFormValues(this.additionalInfoFormGroup);
- const networkSettingsFormValues = this.cleanFormValues(this.networkSettingsFormGroup);
- const classroomInfoFormValues = this.cleanFormValues(this.classroomInfoFormGroup);
-
- const formData: any = {
- ...generalFormValues,
- ...classroomInfoFormValues,
- comments: additionalInfoFormValues.comments,
- networkSettings: { ...networkSettingsFormValues }
- };
-
- console.log('POST data:', formData);
+ if (this.isFormValid()) {
+ const formData: any = this.buildPayload();
const postUrl = `${this.baseUrl}/organizational-units`;
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
this.http.post(postUrl, formData, { headers }).subscribe(
response => {
- console.log('POST successful:', response);
this.unitAdded.emit();
this.dialogRef.close();
this.openSnackBar(false, 'Cliente creado exitosamente');
@@ -153,14 +148,43 @@ export class CreateOrganizationalUnitComponent implements OnInit {
}
}
+ private isFormValid(): boolean {
+ return this.generalFormGroup.valid &&
+ this.additionalInfoFormGroup.valid &&
+ this.networkSettingsFormGroup.valid &&
+ (this.generalFormGroup.value.type !== 'classroom' || this.classroomInfoFormGroup.valid);
+ }
+
+ private buildPayload(): any {
+ const generalFormValues = this.cleanFormValues(this.generalFormGroup);
+ const additionalInfoFormValues = this.cleanFormValues(this.additionalInfoFormGroup);
+ const networkSettingsFormValues = this.cleanFormValues(this.networkSettingsFormGroup);
+ const classroomInfoFormValues = this.cleanFormValues(this.classroomInfoFormGroup);
+
+ return {
+ ...generalFormValues,
+ ...classroomInfoFormValues,
+ comments: additionalInfoFormValues.comments,
+ networkSettings: { ...networkSettingsFormValues },
+ remoteCalendar: this.selectedCalendarUuid ? `/remote-calendars/${this.selectedCalendarUuid}` : null,
+ menu: networkSettingsFormValues.menu || null,
+ hardwareProfile: networkSettingsFormValues.hardwareProfile || null,
+ };
+ }
+
+ onCalendarChange(event: any) {
+ this.selectedCalendarUuid = event.value;
+ }
+
onNoClick(): void {
this.dialogRef.close();
}
openSnackBar(isError: boolean, message: string) {
if (isError) {
- this.toastService.error(' Error al crear el cliente: ' + message, 'Error');
- } else
+ this.toastService.error('Error al crear el cliente: ' + message, 'Error');
+ } else {
this.toastService.success('Cliente creado exitosamente', 'Éxito');
+ }
}
}
diff --git a/ogWebconsole/src/app/components/groups/organizational-units/show-organizational-unit/show-organizational-unit.component.html b/ogWebconsole/src/app/components/groups/organizational-units/show-organizational-unit/show-organizational-unit.component.html
index 93406cd..8cf3f5e 100644
--- a/ogWebconsole/src/app/components/groups/organizational-units/show-organizational-unit/show-organizational-unit.component.html
+++ b/ogWebconsole/src/app/components/groups/organizational-units/show-organizational-unit/show-organizational-unit.component.html
@@ -29,15 +29,5 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/ogWebconsole/src/app/layout/sidebar/sidebar.component.html b/ogWebconsole/src/app/layout/sidebar/sidebar.component.html
index bb4e55d..60cbd81 100644
--- a/ogWebconsole/src/app/layout/sidebar/sidebar.component.html
+++ b/ogWebconsole/src/app/layout/sidebar/sidebar.component.html
@@ -128,7 +128,7 @@
-
+
calendar_month
Calendarios