diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8ec74..f4e8cfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog -## [0.6.0] - 2024-11-21 +## [0.6.1] - 2024-11-19 + +### Improved +- Introduced a new automatic sync mode for the ogdhcp and ogBoot components. +- Improve test coverage. +- New view for clients inside the classroom on the main page. + + +## [0.6.0] - 2024-11-19 ### Added - Added functionality to execute actions from the menu in the general groups screen. @@ -30,3 +38,4 @@ --- + diff --git a/ogWebconsole/src/app/app.component.spec.ts b/ogWebconsole/src/app/app.component.spec.ts index 25ab0ad..c77f097 100644 --- a/ogWebconsole/src/app/app.component.spec.ts +++ b/ogWebconsole/src/app/app.component.spec.ts @@ -1,19 +1,23 @@ import { TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { TranslateModule } from '@ngx-translate/core'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { AppComponent } from './app.component'; describe('AppComponent', () => { + let translateService: TranslateService; + beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ RouterTestingModule, - TranslateModule.forRoot() + TranslateModule.forRoot() ], declarations: [ AppComponent ], }).compileComponents(); + + translateService = TestBed.inject(TranslateService); }); it('should create the app', () => { @@ -21,4 +25,42 @@ describe('AppComponent', () => { const app = fixture.componentInstance; expect(app).toBeTruthy(); }); + + it(`should have as title 'ogWebconsole'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('ogWebconsole'); + }); + + it('should set the language from localStorage on creation', () => { + spyOn(localStorage, 'getItem').and.returnValue('en'); // Simula que el idioma guardado es "en" + spyOn(translateService, 'use'); + + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + + expect(localStorage.getItem).toHaveBeenCalledWith('language'); + expect(translateService.use).toHaveBeenCalledWith('en'); + }); + + it('should default to Spanish if no language is saved in localStorage', () => { + spyOn(localStorage, 'getItem').and.returnValue(null); // Simula que no hay idioma guardado + spyOn(translateService, 'use'); + + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + + expect(localStorage.getItem).toHaveBeenCalledWith('language'); + expect(translateService.use).toHaveBeenCalledWith('es'); + }); + + it('should set language to Spanish in sessionStorage on ngOnInit', () => { + spyOn(sessionStorage, 'setItem'); + + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + + app.ngOnInit(); + expect(sessionStorage.setItem).toHaveBeenCalledWith('language', 'es'); + }); }); diff --git a/ogWebconsole/src/app/components/groups/groups.component.css b/ogWebconsole/src/app/components/groups/groups.component.css index 7f0db7c..b2923f7 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.css +++ b/ogWebconsole/src/app/components/groups/groups.component.css @@ -218,17 +218,75 @@ mat-card { .classroom-grid { display: flex; flex-wrap: wrap; - gap: 16px; /* Espacio entre elementos */ - justify-content: flex-start; /* Alinea los elementos a la izquierda */ + gap: 16px; + justify-content: flex-start; /* Opcional: para alinear a la izquierda */ } .classroom-item { - flex: 0 1 calc(16.66% - 16px); /* 6 columnas (para pantallas grandes) */ - box-sizing: border-box; /* Incluye padding y borde en el cálculo del ancho */ + flex: 0 1 calc(16.66% - 16px); /* 6 columnas */ + max-width: calc(16.66% - 16px); + text-align: center; + box-sizing: border-box; } -.classroom-card { - width: 100%; /* Asegura que el card ocupe todo el espacio del item */ +.classroom-pc { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + padding: 8px; + background-color: #f4f4f4; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.pc-image { + width: 80px; + height: 80px; +} + +.pc-details { + margin-top: 8px; + font-size: 12px; +} + +.client-name { + font-weight: bold; + display: block; +} + +.client-ip, +.client-mac { + color: #666; + font-size: 10px; + display: block; +} + +.pc-actions { + margin-top: 8px; + display: flex; + justify-content: center; + gap: 8px; +} + +.pc-og-live { + border: 2px solid #4caf50; +} + +.pc-busy { + border: 2px solid #ff9800; +} + +.pc-off { + border: 2px solid #f44336; +} + +.pc-linux { + border: 2px solid #9c27b0; +} + +.pc-windows { + border: 2px solid #2196f3; } /* Pantallas medianas: 4 columnas */ @@ -261,33 +319,3 @@ mat-card { font-size: 0.9rem; text-align: center; } - -.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; -} diff --git a/ogWebconsole/src/app/components/groups/groups.component.html b/ogWebconsole/src/app/components/groups/groups.component.html index 5745561..2de059a 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.html +++ b/ogWebconsole/src/app/components/groups/groups.component.html @@ -111,32 +111,32 @@
- - - {{ pc.name }} - - -

{{ pc.ip }}

-

{{ pc.mac }}

-
- +
+ PC Icon +
+ {{ pc.name }} + {{ pc.ip }} + {{ pc.mac }} +
+
- - - +
+
+ diff --git a/ogWebconsole/src/app/components/groups/groups.component.spec.ts b/ogWebconsole/src/app/components/groups/groups.component.spec.ts new file mode 100644 index 0000000..5fb654f --- /dev/null +++ b/ogWebconsole/src/app/components/groups/groups.component.spec.ts @@ -0,0 +1,243 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { GroupsComponent } from './groups.component'; +import { MatInputModule } from '@angular/material/input'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatOptionModule } from '@angular/material/core'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTableModule } from '@angular/material/table'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ToastrModule } from 'ngx-toastr'; +import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatListModule } from '@angular/material/list'; +import { MatTabsModule } from '@angular/material/tabs'; +import { MatCardModule } from '@angular/material/card'; +import { TranslateModule } from '@ngx-translate/core'; +import { JoyrideModule } from 'ngx-joyride'; +import { AdvancedSearchComponent } from './components/advanced-search/advanced-search.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 { MatMenuModule } from '@angular/material/menu'; + +describe('GroupsComponent', () => { + let component: GroupsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [GroupsComponent, AdvancedSearchComponent, ClientTabViewComponent, OrganizationalUnitTabViewComponent], + imports: [ + HttpClientTestingModule, + ToastrModule.forRoot(), + BrowserAnimationsModule, + MatDividerModule, + MatFormFieldModule, + MatInputModule, + MatIconModule, + MatButtonModule, + MatTableModule, + MatPaginatorModule, + MatTooltipModule, + FormsModule, + ReactiveFormsModule, + MatProgressSpinnerModule, + MatDialogModule, + MatSelectModule, + MatTabsModule, + MatAutocompleteModule, + MatListModule, + MatCardModule, + MatMenuModule, + TranslateModule.forRoot(), + JoyrideModule.forRoot(), + ], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { provide: MAT_DIALOG_DATA, useValue: { data: { id: 123 } } } + ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GroupsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call search on ngOnInit', () => { + spyOn(component, 'search'); + component.ngOnInit(); + expect(component.search).toHaveBeenCalled(); + }); + + it('should call getFilters on ngOnInit', () => { + spyOn(component, 'getFilters'); + component.ngOnInit(); + expect(component.getFilters).toHaveBeenCalled(); + }); + + it('should call search method', () => { + spyOn(component, 'search'); + component.search(); + expect(component.search).toHaveBeenCalled(); + }); + + it('should call getFilters method', () => { + spyOn(component, 'getFilters'); + component.getFilters(); + expect(component.getFilters).toHaveBeenCalled(); + }); + + it('should call onTabChange method', () => { + spyOn(component, 'onTabChange'); + const event = { index: 2 } as any; + component.onTabChange(event); + expect(component.onTabChange).toHaveBeenCalledWith(event); + }); + + it('should call onSelectUnidad method', () => { + spyOn(component, 'onSelectUnidad'); + const unidad = { id: '1', name: 'Test' } as any; + component.onSelectUnidad(unidad); + expect(component.onSelectUnidad).toHaveBeenCalledWith(unidad); + }); + + it('should call onSelectChild method', () => { + spyOn(component, 'onSelectChild'); + const child = { id: '1', name: 'Test', type: 'unit' } as any; + component.onSelectChild(child); + expect(component.onSelectChild).toHaveBeenCalledWith(child); + }); + + it('should call navigateToBreadcrumb method', () => { + spyOn(component, 'navigateToBreadcrumb'); + component.navigateToBreadcrumb(1); + expect(component.navigateToBreadcrumb).toHaveBeenCalledWith(1); + }); + + it('should call loadChildrenAndClients method', () => { + spyOn(component, 'loadChildrenAndClients'); + component.loadChildrenAndClients('1'); + expect(component.loadChildrenAndClients).toHaveBeenCalledWith('1'); + }); + + it('should call onDeleteClick method', () => { + spyOn(component, 'onDeleteClick'); + const event = new MouseEvent('click'); + component.onDeleteClick(event, 'uuid', 'name', 'client'); + expect(component.onDeleteClick).toHaveBeenCalledWith(event, 'uuid', 'name', 'client'); + }); + + it('should call onEditClick method', () => { + spyOn(component, 'onEditClick'); + const event = new MouseEvent('click'); + component.onEditClick(event, 'client', 'uuid'); + expect(component.onEditClick).toHaveBeenCalledWith(event, 'client', 'uuid'); + }); + + it('should call onShowClick method', () => { + spyOn(component, 'onShowClick'); + const event = new MouseEvent('click'); + component.onShowClick(event, { type: 'unit' }); + expect(component.onShowClick).toHaveBeenCalledWith(event, { type: 'unit' }); + }); + + it('should call onTreeClick method', () => { + spyOn(component, 'onTreeClick'); + const event = new MouseEvent('click'); + component.onTreeClick(event, { type: 'unit' }); + expect(component.onTreeClick).toHaveBeenCalledWith(event, { type: 'unit' }); + }); + + it('should call onExecuteCommand method', () => { + spyOn(component, 'onExecuteCommand'); + const event = new MouseEvent('click'); + component.onExecuteCommand(event, 'child', 'name', 'type'); + expect(component.onExecuteCommand).toHaveBeenCalledWith(event, 'child', 'name', 'type'); + }); + + it('should call openSnackBar method', () => { + spyOn(component, 'openSnackBar'); + component.openSnackBar(true, 'message'); + expect(component.openSnackBar).toHaveBeenCalledWith(true, 'message'); + }); + + it('should call openBottomSheet method', () => { + spyOn(component, 'openBottomSheet'); + component.openBottomSheet(); + expect(component.openBottomSheet).toHaveBeenCalled(); + }); + + it('should call roomMap method', () => { + spyOn(component, 'roomMap'); + component.roomMap(); + expect(component.roomMap).toHaveBeenCalled(); + }); + + it('should call applyFilter method', () => { + spyOn(component, 'applyFilter'); + component.applyFilter(); + expect(component.applyFilter).toHaveBeenCalled(); + }); + + it('should call onPageChange method', () => { + spyOn(component, 'onPageChange'); + const event = { pageIndex: 1, pageSize: 10 } as any; + component.onPageChange(event); + expect(component.onPageChange).toHaveBeenCalledWith(event); + }); + + it('should call saveFilters method', () => { + spyOn(component, 'saveFilters'); + component.saveFilters(); + expect(component.saveFilters).toHaveBeenCalled(); + }); + + it('should call loadSelectedFilter method', () => { + spyOn(component, 'loadSelectedFilter'); + component.loadSelectedFilter(['name', 'uuid']); + expect(component.loadSelectedFilter).toHaveBeenCalledWith(['name', 'uuid']); + }); + + it('should call onCheckboxChange method', () => { + spyOn(component, 'onCheckboxChange'); + const event = { checked: true } as any; + component.onCheckboxChange(event, 'name', 'uuid'); + expect(component.onCheckboxChange).toHaveBeenCalledWith(event, 'name', 'uuid'); + }); + + it('should call toggleSelectAll method', () => { + spyOn(component, 'toggleSelectAll'); + component.toggleSelectAll(); + expect(component.toggleSelectAll).toHaveBeenCalled(); + }); + + it('should call isSelected method', () => { + spyOn(component, 'isSelected'); + component.isSelected('name'); + expect(component.isSelected).toHaveBeenCalledWith('name'); + }); + + it('should call sendActions method', () => { + spyOn(component, 'sendActions'); + component.sendActions(); + expect(component.sendActions).toHaveBeenCalled(); + }); + + it('should call iniciarTour method', () => { + spyOn(component, 'iniciarTour'); + component.iniciarTour(); + expect(component.iniciarTour).toHaveBeenCalled(); + }); +}); diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.css b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.css index 897597c..2239479 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.css +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.css @@ -1,17 +1,22 @@ .loading-container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100px; - } - - mat-form-field { - width: 100%; - } - - mat-dialog-actions { - display: flex; - justify-content: flex-end; - } - \ No newline at end of file + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100px; +} + +mat-form-field { + width: 100%; +} + +mat-dialog-actions { + display: flex; + justify-content: flex-end; +} + +.checkbox-group { + display: flex; + flex-direction: column; + gap: 10px; +} diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.html b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.html index 44ec007..87ed097 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.html +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.html @@ -2,23 +2,16 @@ - Unidad Organizativa - + Seleccione aula + {{ unit.name }} - - Subunidad Organizativa - - {{ child.name }} - - -
- {{ client.name }} diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts index 33dbecd..6b7bd34 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts @@ -12,7 +12,6 @@ import { ToastrService } from 'ngx-toastr'; export class AddClientsToSubnetComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; units: any[] = []; - childUnits: any[] = []; clients: any[] = []; selectedClients: string[] = []; loading: boolean = true; @@ -32,38 +31,22 @@ export class AddClientsToSubnetComponent implements OnInit { } loadUnits() { - this.http.get(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=50`).subscribe( + this.http.get(`${this.baseUrl}/organizational-units?type=classroom&page=1&itemsPerPage=50`).subscribe( response => { - this.units = response['hydra:member'].filter((unit: { type: string; }) => unit.type === 'organizational-unit'); + this.units = response['hydra:member']; this.loading = false; }, error => console.error('Error fetching organizational units:', error) ); } - onUnitChange(unitId: string): void { - const unit = this.units.find(unit => unit.uuid === unitId); - this.childUnits = unit ? this.getAllChildren(unit) : []; - this.clients = []; - this.childUnitControl.setValue(null); - this.selectedClients = []; - } - - getAllChildren(unit: any): any[] { - let allChildren = []; - if (unit.children && unit.children.length > 0) { - for (const child of unit.children) { - allChildren.push(child); - allChildren = allChildren.concat(this.getAllChildren(child)); - } - } - return allChildren; - } - - onChildUnitChange(childUnitId: string): void { - const childUnit = this.childUnits.find(unit => unit.uuid === childUnitId); - this.clients = childUnit && childUnit.clients ? childUnit.clients : []; - this.selectedClients = []; + loadChildUnits(unitId: string) { + this.http.get(`${this.baseUrl}/clients?parent.id${unitId}`).subscribe( + response => { + this.clients = response['hydra:member']; + }, + error => console.error('Error fetching child units:', error) + ); } toggleClientSelection(clientId: string): void { @@ -75,18 +58,6 @@ export class AddClientsToSubnetComponent implements OnInit { } } - toggleSelectAll(): void { - if (this.areAllClientsSelected()) { - this.selectedClients = []; - } else { - this.selectedClients = this.clients.map(client => client.uuid); - } - } - - areAllClientsSelected(): boolean { - return this.selectedClients.length === this.clients.length; - } - save() { this.selectedClients.forEach(clientId => { const postData = { client: `/clients/${clientId}` }; diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.css b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.css index 27f82b3..f01f981 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.css +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.css @@ -38,7 +38,6 @@ table { } .header-container { - margin-top: 16px; display: flex; justify-content: space-between; align-items: center; @@ -58,20 +57,14 @@ table { margin-bottom: 30px; } -.example-headers-align .mat-expansion-panel-header-description { - justify-content: space-between; - align-items: center; +mat-spinner { + margin: 0 auto; + align-self: 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; +.subnets-button-row { + display: flex; + justify-content: flex-end; + margin-bottom: 20px; + gap: 10px; } diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html index 3641600..903ebd5 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html @@ -1,23 +1,10 @@ - - - - Información en servidor ogDHCP - -
- -
-
- -
-
-
-

Administrar Subredes

+
@@ -52,8 +39,8 @@
- - + +
diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.spec.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.spec.ts index e53bcb7..199d47c 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.spec.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.spec.ts @@ -4,9 +4,9 @@ import { MatDialog } from '@angular/material/dialog'; import { HttpClient } from '@angular/common/http'; import { ToastrService } from 'ngx-toastr'; import { of } from 'rxjs'; -import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionPanelDescription } from '@angular/material/expansion'; -import { MatIcon } from '@angular/material/icon'; -import { MatDivider } from '@angular/material/divider'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatIconModule } from '@angular/material/icon'; +import { MatDividerModule } from '@angular/material/divider'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatSelectModule } from '@angular/material/select'; import { MatPaginatorModule } from '@angular/material/paginator'; @@ -28,22 +28,18 @@ describe('OgDhcpSubnetsComponent', () => { mockDialog = jasmine.createSpyObj('MatDialog', ['open']); mockHttpClient = jasmine.createSpyObj('HttpClient', ['get', 'post', 'put', 'delete']); mockToastrService = jasmine.createSpyObj('ToastrService', ['success', 'error']); - - mockHttpClient.get.and.returnValue(of([])); + mockHttpClient.get.and.returnValue(of({ 'hydra:member': [], 'hydra:totalItems': 0 })); + mockHttpClient.post.and.returnValue(of({})); await TestBed.configureTestingModule({ declarations: [OgDhcpSubnetsComponent], - imports: [ - MatAccordion, - MatExpansionPanel, - MatExpansionPanelHeader, - MatExpansionPanelTitle, - MatExpansionPanelDescription, - MatIcon, - MatDivider, - MatFormFieldModule, - MatSelectModule, - MatPaginatorModule, + imports: [ + MatExpansionModule, + MatIconModule, + MatDividerModule, + MatFormFieldModule, + MatSelectModule, + MatPaginatorModule, BrowserAnimationsModule, FormsModule, MatInputModule, @@ -54,8 +50,8 @@ describe('OgDhcpSubnetsComponent', () => { providers: [ { provide: MatDialog, useValue: mockDialog }, { provide: HttpClient, useValue: mockHttpClient }, - { provide: ToastrService, useValue: mockToastrService } - ] + { provide: ToastrService, useValue: mockToastrService }, + ], }).compileComponents(); }); @@ -69,4 +65,10 @@ describe('OgDhcpSubnetsComponent', () => { expect(component).toBeTruthy(); }); + it('should call syncSubnets and handle success', () => { + component.syncSubnets(); + expect(mockHttpClient.post).toHaveBeenCalledWith(`${component.baseUrl}/subnets/sync`, {}); + expect(mockToastrService.success).toHaveBeenCalledWith('Sincronización con componente DHCP exitosa'); + }); + }); diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts index 3d49acd..dfec859 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts @@ -35,7 +35,7 @@ export interface Subnet { }) export class OgDhcpSubnetsComponent { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; - displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'nextServer', 'bootFileName', 'synchronized', 'serverId', 'clients', 'actions']; + displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'synchronized', 'serverId', 'clients', 'actions']; dataSource = new MatTableDataSource([]); length = 0; itemsPerPage: number = 10; @@ -43,6 +43,7 @@ export class OgDhcpSubnetsComponent { filters: { [key: string]: string } = {}; pageSizeOptions: number[] = [5, 10, 20]; alertMessage: string | null = null; + loading:boolean = false; @ViewChild(MatPaginator) paginator: MatPaginator | undefined; @@ -51,8 +52,6 @@ export class OgDhcpSubnetsComponent { { columnDef: 'name', header: 'Name', cell: (subnet: Subnet) => subnet.name }, { columnDef: 'netmask', header: 'Netmask', cell: (subnet: Subnet) => subnet.netmask }, { columnDef: 'ipAddress', header: 'IP Address', cell: (subnet: Subnet) => subnet.ipAddress }, - { columnDef: 'nextServer', header: 'Next Server', cell: (subnet: Subnet) => subnet.nextServer }, - { columnDef: 'bootFileName', header: 'Boot File Name', cell: (subnet: Subnet) => subnet.bootFileName }, { columnDef: 'synchronized', header: 'Sincronizado', cell: (subnet: Subnet) => `${subnet.synchronized}` }, { columnDef: 'serverId', header: 'Id Servidor DHCP', cell: (subnet: Subnet) => subnet.serverId }, { columnDef: 'clients', header: 'Lista de clientes', cell: (subnet: Subnet) => `${subnet.clients}` }, @@ -64,8 +63,11 @@ export class OgDhcpSubnetsComponent { private joyrideService: JoyrideService) { } ngOnInit() { + this.loading = true; this.loadSubnets(); this.loadAlert() + this.syncSubnets() + this.loading = false; } loadSubnets() { @@ -87,7 +89,7 @@ export class OgDhcpSubnetsComponent { syncSubnets() { this.http.post(`${this.apiUrl}/sync`, {}) .subscribe(response => { - this.toastService.success('Sincronización completada'); + this.toastService.success('Sincronización con componente DHCP exitosa'); this.loadSubnets() }, error => { console.error('Error al sincronizar', error); @@ -224,9 +226,6 @@ export class OgDhcpSubnetsComponent { iniciarTour(): void { this.joyrideService.startTour({ steps: [ - 'serverInfoStep', - 'syncDbStep', - 'viewInfoStep', 'titleStep', 'addSubnetStep', 'searchNameStep',
{{ column.header }} @@ -84,15 +71,8 @@ + - - - - - -