From 52ae1a24bc0cc5341e4776afca09678799caef4a Mon Sep 17 00:00:00 2001 From: Frederik Christ Vestergaard Date: Mon, 20 Feb 2023 11:33:26 +0100 Subject: [PATCH 1/2] Updated most dropdowns to sort by name --- .../permission-edit.component.ts | 36 +- .../awaiting-users-table.component.html | 2 +- .../user-table/user-table.component.html | 2 +- .../user-table/user-table.component.ts | 229 +++++----- .../datatarget-edit.component.ts | 96 ++-- .../fiware-edit/fiware-edit.component.ts | 125 +++--- .../httppush-edit/httppush-edit.component.ts | 10 +- .../mqtt-edit/mqtt-edit.component.ts | 2 +- .../device-model-table.component.ts | 20 +- .../gateway-list/gateway-list.component.ts | 416 +++++++++--------- .../organisation-dropdown.component.html | 2 +- .../organisation-dropdown.component.ts | 1 + .../payload-decoder-edit.component.ts | 188 +++++--- .../payload-decoder-table.component.ts | 8 +- .../sigfox-device-type-table.component.ts | 18 +- src/assets/i18n/da.json | 2 +- 16 files changed, 619 insertions(+), 538 deletions(-) diff --git a/src/app/admin/permission/permission-edit/permission-edit.component.ts b/src/app/admin/permission/permission-edit/permission-edit.component.ts index 180d85f0d..ed0d4a864 100644 --- a/src/app/admin/permission/permission-edit/permission-edit.component.ts +++ b/src/app/admin/permission/permission-edit/permission-edit.component.ts @@ -6,7 +6,11 @@ import { TranslateService } from '@ngx-translate/core'; import { ReplaySubject, Subject, Subscription } from 'rxjs'; import { Location } from '@angular/common'; import { PermissionService } from '../permission.service'; -import { PermissionRequest, PermissionType, PermissionTypes } from '../permission.model'; +import { + PermissionRequest, + PermissionType, + PermissionTypes, +} from '../permission.model'; import { OrganisationResponse } from '../../organisation/organisation.model'; import { OrganisationService } from '../../organisation/organisation.service'; import { UserService } from '../../users/user.service'; @@ -80,8 +84,7 @@ export class PermissionEditComponent implements OnInit, OnDestroy { private location: Location, private errormEssageService: ErrorMessageService, private meService: MeService - ) { - } + ) {} ngOnInit(): void { this.getOrganizations(); @@ -167,7 +170,7 @@ export class PermissionEditComponent implements OnInit, OnDestroy { private getOrganizations() { this.organisationSubscription = this.organisationService - .getMultiple() + .getMultiple(1000, 0, 'name', 'asc') .subscribe( (orgs) => { this.organisations = orgs.data; @@ -179,15 +182,17 @@ export class PermissionEditComponent implements OnInit, OnDestroy { } private getUsers() { - this.userSubscription = this.userService.getMultiple().subscribe( - (users) => { - this.users = users.data; - this.filteredUsersMulti.next(this.users.slice()); - }, - (error: HttpErrorResponse) => { - this.showError(error); - } - ); + this.userSubscription = this.userService + .getMultiple(1000, 0, 'name', 'asc') + .subscribe( + (users) => { + this.users = users.data; + this.filteredUsersMulti.next(this.users.slice()); + }, + (error: HttpErrorResponse) => { + this.showError(error); + } + ); } public compare(o1: any, o2: any): boolean { @@ -207,7 +212,9 @@ export class PermissionEditComponent implements OnInit, OnDestroy { .getApplicationsByOrganizationId(organizationId) .subscribe( (res) => { - this.applications = res.data; + this.applications = res.data.sort((a, b) => + a.name.localeCompare(b.name, 'en', { numeric: true }) + ); this.filteredApplicationsMulti.next(this.applications.slice()); }, (error: HttpErrorResponse) => { @@ -251,7 +258,6 @@ export class PermissionEditComponent implements OnInit, OnDestroy { ); this.applicationMultiCtrl.setValue(this.permission.applicationIds); } - }, (error: HttpErrorResponse) => { this.showError(error); diff --git a/src/app/admin/users/user-list/awaiting-users-table/awaiting-users-table.component.html b/src/app/admin/users/user-list/awaiting-users-table/awaiting-users-table.component.html index 35f0e2638..88817e562 100644 --- a/src/app/admin/users/user-list/awaiting-users-table/awaiting-users-table.component.html +++ b/src/app/admin/users/user-list/awaiting-users-table/awaiting-users-table.component.html @@ -9,7 +9,7 @@ mat-table [dataSource]="users" matSort - matSortActive="id" + matSortActive="name" matSortDirection="asc" matSortDisableClear > diff --git a/src/app/admin/users/user-list/user-table/user-table.component.html b/src/app/admin/users/user-list/user-table/user-table.component.html index d729f65e0..56fe30c4f 100644 --- a/src/app/admin/users/user-list/user-table/user-table.component.html +++ b/src/app/admin/users/user-list/user-table/user-table.component.html @@ -2,7 +2,7 @@
- +
diff --git a/src/app/admin/users/user-list/user-table/user-table.component.ts b/src/app/admin/users/user-list/user-table/user-table.component.ts index baac24d7e..fe7009695 100644 --- a/src/app/admin/users/user-list/user-table/user-table.component.ts +++ b/src/app/admin/users/user-list/user-table/user-table.component.ts @@ -1,117 +1,112 @@ -import { - AfterViewInit, - Component, - Input, - ViewChild, -} from '@angular/core'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort } from '@angular/material/sort'; -import { TranslateService } from '@ngx-translate/core'; -import { startWith, switchMap, map, catchError } from 'rxjs/operators'; -import { UserGetManyResponse, UserResponse } from '../../user.model'; -import { UserService } from '../../user.service'; -import { merge, Observable, of as observableOf } from 'rxjs'; -import { environment } from '@environments/environment'; -import { DefaultPageSizeOptions } from '@shared/constants/page.constants'; -import { ActivatedRoute } from '@angular/router'; -import { MeService } from '@shared/services/me.service'; - -@Component({ - selector: 'app-user-table', - templateUrl: './user-table.component.html', - styleUrls: ['./user-table.component.scss'], -}) -export class UserTableComponent implements AfterViewInit { - displayedColumns: string[] = [ - 'name', - 'email', - 'global', - 'status', - 'lastLogin', - 'menu', - ]; - data: UserResponse[]; - - public pageSize = environment.tablePageSize; - pageSizeOptions = DefaultPageSizeOptions; - resultsLength = 0; - isLoadingResults = true; - @ViewChild(MatPaginator) paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; - - // If supplied, users will only be retrieved for the specified organization - // If supplied, permissionId will ignored, even if supplied - @Input() organizationId?: number; - - // If supplied, users will be retrieved on the permissionId (userGroup/brugerGruppe) - @Input() permissionId?: number; - - @Input() canSort = true; - isGlobalAdmin: boolean; - - constructor( - public translate: TranslateService, - private userService: UserService, - private meService: MeService - ) { - this.isGlobalAdmin = this.meService.hasGlobalAdmin(); - } - - getUsers( - orderByColumn: string, - orderByDirection: string - ): Observable { - if (this.organizationId !== null && this.organizationId !== undefined) { - if (this.isGlobalAdmin) { - return this.userService.getMultiple( - this.paginator.pageSize, - this.paginator.pageIndex * this.paginator.pageSize, - orderByColumn, - orderByDirection - ); - } else { - return this.userService.getMultipleByOrganization( - this.paginator.pageSize, - this.paginator.pageIndex * this.paginator.pageSize, - orderByColumn, - orderByDirection, - this.organizationId - ); - } - } else { - return this.userService.getMultiple( - this.paginator.pageSize, - this.paginator.pageIndex * this.paginator.pageSize, - orderByColumn, - orderByDirection, - this.permissionId - ); - } - } - - ngAfterViewInit() { - // If the user changes the sort order, reset back to the first page. - this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0)); - - merge(this.sort.sortChange, this.paginator.page) - .pipe( - startWith({}), - switchMap(() => { - this.isLoadingResults = true; - return this.getUsers(this.sort.active, this.sort.direction); - }), - map((data) => { - // Flip flag to show that loading has finished. - this.isLoadingResults = false; - this.resultsLength = data.count; - - return data.data; - }), - catchError(() => { - this.isLoadingResults = false; - return observableOf([]); - }) - ) - .subscribe((data) => (this.data = data)); - } -} +import { AfterViewInit, Component, Input, ViewChild } from '@angular/core'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { TranslateService } from '@ngx-translate/core'; +import { catchError, map, startWith, switchMap } from 'rxjs/operators'; +import { UserGetManyResponse, UserResponse } from '../../user.model'; +import { UserService } from '../../user.service'; +import { merge, Observable, of as observableOf } from 'rxjs'; +import { environment } from '@environments/environment'; +import { DefaultPageSizeOptions } from '@shared/constants/page.constants'; +import { MeService } from '@shared/services/me.service'; + +@Component({ + selector: 'app-user-table', + templateUrl: './user-table.component.html', + styleUrls: ['./user-table.component.scss'], +}) +export class UserTableComponent implements AfterViewInit { + displayedColumns: string[] = [ + 'name', + 'email', + 'global', + 'status', + 'lastLogin', + 'menu', + ]; + data: UserResponse[]; + + public pageSize = environment.tablePageSize; + pageSizeOptions = DefaultPageSizeOptions; + resultsLength = 0; + isLoadingResults = true; + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + // If supplied, users will only be retrieved for the specified organization + // If supplied, permissionId will ignored, even if supplied + @Input() organizationId?: number; + + // If supplied, users will be retrieved on the permissionId (userGroup/brugerGruppe) + @Input() permissionId?: number; + + @Input() canSort = true; + isGlobalAdmin: boolean; + + constructor( + public translate: TranslateService, + private userService: UserService, + private meService: MeService + ) { + this.isGlobalAdmin = this.meService.hasGlobalAdmin(); + } + + getUsers( + orderByColumn: string, + orderByDirection: string + ): Observable { + if (this.organizationId !== null && this.organizationId !== undefined) { + if (this.isGlobalAdmin) { + return this.userService.getMultiple( + this.paginator.pageSize, + this.paginator.pageIndex * this.paginator.pageSize, + orderByColumn, + orderByDirection + ); + } else { + return this.userService.getMultipleByOrganization( + this.paginator.pageSize, + this.paginator.pageIndex * this.paginator.pageSize, + orderByColumn, + orderByDirection, + this.organizationId + ); + } + } else { + return this.userService.getMultiple( + this.paginator.pageSize, + this.paginator.pageIndex * this.paginator.pageSize, + orderByColumn, + orderByDirection, + this.permissionId + ); + } + } + + ngAfterViewInit() { + console.log(this.sort.active); + // If the user changes the sort order, reset back to the first page. + this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0)); + + merge(this.sort.sortChange, this.paginator.page) + .pipe( + startWith({}), + switchMap(() => { + this.isLoadingResults = true; + return this.getUsers(this.sort.active, this.sort.direction); + }), + map((data) => { + // Flip flag to show that loading has finished. + this.isLoadingResults = false; + this.resultsLength = data.count; + + return data.data; + }), + catchError(() => { + this.isLoadingResults = false; + return observableOf([]); + }) + ) + .subscribe((data) => (this.data = data)); + } +} diff --git a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts index 432a5e2b4..903f2dcfd 100644 --- a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts +++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts @@ -1,4 +1,14 @@ -import { AfterViewInit, Component, ComponentFactoryResolver, OnDestroy, OnInit, QueryList, Type, ViewChild, ViewChildren } from '@angular/core'; +import { + AfterViewInit, + Component, + ComponentFactoryResolver, + OnDestroy, + OnInit, + QueryList, + Type, + ViewChild, + ViewChildren, +} from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { DataTargetType } from '@shared/enums/datatarget-type'; import { DatatargetTypesService } from '../datatarget-types.service'; @@ -10,60 +20,68 @@ import { DatatargetEditTypeSelectorDirective } from './datatarget-edit-type-sele @Component({ selector: 'app-datatarget-edit', templateUrl: './datatarget-edit.component.html', - styleUrls: ['./datatarget-edit.component.scss'] + styleUrls: ['./datatarget-edit.component.scss'], }) export class DatatargetEditComponent implements OnInit, OnDestroy { - - @ViewChild(DatatargetEditTypeSelectorDirective, {static: true}) adHost!: DatatargetEditTypeSelectorDirective; + @ViewChild(DatatargetEditTypeSelectorDirective, { static: true }) + adHost!: DatatargetEditTypeSelectorDirective; public datatarget: Datatarget; private datatargetType: DataTargetType; - constructor(private componentFactoryResolver: ComponentFactoryResolver, - private datatargetService: DatatargetService, - private route: ActivatedRoute, - private datatargetTypesService: DatatargetTypesService - ) { } - + constructor( + private componentFactoryResolver: ComponentFactoryResolver, + private datatargetService: DatatargetService, + private route: ActivatedRoute, + private datatargetTypesService: DatatargetTypesService + ) {} loadComponent(componentType: Type) { - const viewContainerRef = this.adHost.viewContainerRef; - viewContainerRef.clear(); - const factory = this.componentFactoryResolver.resolveComponentFactory(componentType); - viewContainerRef.createComponent(factory); + const viewContainerRef = this.adHost.viewContainerRef; + viewContainerRef.clear(); + const factory = this.componentFactoryResolver.resolveComponentFactory( + componentType + ); + viewContainerRef.createComponent(factory); } ngOnInit(): void { + const id: number = +this.route.snapshot.paramMap.get('datatargetId'); - const id: number = +this.route.snapshot.paramMap.get('datatargetId'); - - if (id > 0) { - this.datatargetService.get(id) - .subscribe((dataTarget: Datatarget) => { - this.datatarget = dataTarget; - this.datatargetType = dataTarget.type; - const component = this.datatargetTypesService.getEditComponent(this.datatargetType); - this.loadComponent(component); - }); - } else { - let datatargetTypeParam = this.route.snapshot.paramMap.get('datatargetType'); - this.datatargetType = this.enumFromStringValue(DataTargetType, datatargetTypeParam); - if (this.datatargetType) { - const component = this.datatargetTypesService.getEditComponent(this.datatargetType); - this.loadComponent(component); - } + if (id > 0) { + this.datatargetService.get(id).subscribe((dataTarget: Datatarget) => { + this.datatarget = dataTarget; + this.datatargetType = dataTarget.type; + const component = this.datatargetTypesService.getEditComponent( + this.datatargetType + ); + this.loadComponent(component); + }); + } else { + let datatargetTypeParam = this.route.snapshot.paramMap.get( + 'datatargetType' + ); + this.datatargetType = this.enumFromStringValue( + DataTargetType, + datatargetTypeParam + ); + if (this.datatargetType) { + const component = this.datatargetTypesService.getEditComponent( + this.datatargetType + ); + this.loadComponent(component); } - - + } } - enumFromStringValue(enm: { [s: string]: T}, value: string): T | undefined { - return (Object.values(enm) as unknown as string[]).includes(value) - ? value as unknown as T + enumFromStringValue( + enm: { [s: string]: T }, + value: string + ): T | undefined { + return ((Object.values(enm) as unknown) as string[]).includes(value) + ? ((value as unknown) as T) : undefined; } - ngOnDestroy() { - - } + ngOnDestroy() {} } diff --git a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts index 92567fe66..1b7a53179 100644 --- a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts +++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts @@ -6,7 +6,10 @@ import { Observable, Subscription } from 'rxjs'; import { Application } from '@applications/application.model'; import { IotDevice } from '@applications/iot-devices/iot-device.model'; import { faTimesCircle } from '@fortawesome/free-solid-svg-icons'; -import { PayloadDeviceDatatarget, PayloadDeviceDatatargetGetByDataTargetResponse } from '@payload-decoder/payload-device-data.model'; +import { + PayloadDeviceDatatarget, + PayloadDeviceDatatargetGetByDataTargetResponse, +} from '@payload-decoder/payload-device-data.model'; import { DatatargetService } from '../../datatarget.service'; import { ApplicationService } from '@applications/application.service'; import { PayloadDecoderService } from '@payload-decoder/payload-decoder.service'; @@ -27,11 +30,9 @@ import { OrganizationAccessScope } from '@shared/enums/access-scopes'; @Component({ selector: 'app-fiware-edit', templateUrl: './fiware-edit.component.html', - styleUrls: ['./fiware-edit.component.scss'] + styleUrls: ['./fiware-edit.component.scss'], }) export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { - - public multiPage = false; public title = ''; public sectionTitle = ''; @@ -69,13 +70,11 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { private dialog: MatDialog, private errorMessageService: ErrorMessageService, private scrollToTopService: ScrollToTopService, - private meService: MeService, + private meService: MeService ) { translate.use('da'); } - - ngOnInit() { this.translate .get([ @@ -108,15 +107,21 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { this.getDevices(); } this.getPayloadDecoders(); - this.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite); + this.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.ApplicationWrite + ); } - addRow() { if (!this.payloadDeviceDatatarget) { this.payloadDeviceDatatarget = []; } - this.payloadDeviceDatatarget.push({ id: null, iotDeviceIds: [], payloadDecoderId: null, dataTargetId: this.datatargetid }); + this.payloadDeviceDatatarget.push({ + id: null, + iotDeviceIds: [], + payloadDecoderId: null, + dataTargetId: this.datatargetid, + }); } private deleteRow(index) { @@ -124,7 +129,8 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { } else if (this.payloadDeviceDatatarget[index]?.id === null) { this.payloadDeviceDatatarget.splice(index, 1); } else { - this.payloadDeviceDataTargetService.delete(this.payloadDeviceDatatarget[index].id) + this.payloadDeviceDataTargetService + .delete(this.payloadDeviceDatatarget[index].id) .subscribe((response) => { this.payloadDeviceDatatarget.splice(index, 1); }); @@ -136,8 +142,8 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { data: { showAccept: true, showCancel: true, - message: 'Er du sikker på at du vil slette?' - } + message: 'Er du sikker på at du vil slette?', + }, }); dialog.afterClosed().subscribe((result) => { @@ -163,28 +169,29 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { updateDatatarget() { this.resetErrors(); - this.counter = 1 + (this.payloadDeviceDatatarget?.length ? this.payloadDeviceDatatarget?.length : 0); - this.datatargetService.update(this.datatarget) - .subscribe( - (response: Datatarget) => { - this.datatarget = response; - this.countToRedirect(); - }, - (error: HttpErrorResponse) => { - this.handleError(error); - this.formFailedSubmit = true; - } - ); + this.counter = + 1 + + (this.payloadDeviceDatatarget?.length + ? this.payloadDeviceDatatarget?.length + : 0); + this.datatargetService.update(this.datatarget).subscribe( + (response: Datatarget) => { + this.datatarget = response; + this.countToRedirect(); + }, + (error: HttpErrorResponse) => { + this.handleError(error); + this.formFailedSubmit = true; + } + ); } addPayloadDeviceDatatarget() { - this.payloadDeviceDatatarget.map( - pdd => { - if (pdd.payloadDecoderId === 0) { - pdd.payloadDecoderId = null; - } + this.payloadDeviceDatatarget.map((pdd) => { + if (pdd.payloadDecoderId === 0) { + pdd.payloadDecoderId = null; } - ); + }); this.payloadDeviceDatatarget.forEach((relation) => { if (relation.id) { this.payloadDeviceDataTargetService.put(relation).subscribe( @@ -227,17 +234,17 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { createDatatarget() { this.resetErrors(); this.datatarget.applicationId = this.applicationId; - this.datatargetService.create(this.datatarget) - .subscribe((response: Datatarget) => { + this.datatargetService.create(this.datatarget).subscribe( + (response: Datatarget) => { this.datatargetid = response.id; this.datatarget = response; this.showSavedSnack(); }, - (error: HttpErrorResponse) => { - this.handleError(error); - this.formFailedSubmit = true; - }); - + (error: HttpErrorResponse) => { + this.handleError(error); + this.formFailedSubmit = true; + } + ); } private resetErrors() { @@ -246,17 +253,18 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { this.formFailedSubmit = false; } - - getDevices(): void { - this.applicationSubscription = this.applicationService.getApplication(this.applicationId) + this.applicationSubscription = this.applicationService + .getApplication(this.applicationId) .subscribe((application: Application) => { this.devices = application.iotDevices; }); } public selectAllDevices(index: number) { - this.payloadDeviceDatatarget[index].iotDeviceIds = this.devices.map(device => device.id); + this.payloadDeviceDatatarget[index].iotDeviceIds = this.devices.map( + (device) => device.id + ); } public deSelectAllDevices(index: number) { @@ -264,7 +272,8 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { } getPayloadDecoders() { - this.payloadDecoderSubscription = this.payloadDecoderService.getMultiple(1000, 0, 'id', 'ASC') + this.payloadDecoderSubscription = this.payloadDecoderService + .getMultiple(1000, 0, 'name', 'ASC') .subscribe((response: PayloadDecoderMappedResponse) => { this.payloadDecoders = response.data; }); @@ -283,10 +292,7 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { onCoordinateKey(event: any) { if (event.target.value.length > event.target.maxLength) { - event.target.value = event.target.value.slice( - 0, - event.target.maxLength - ); + event.target.value = event.target.value.slice(0, event.target.maxLength); } } @@ -323,17 +329,20 @@ export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy { } } - private mapToDatatargetDevicePayload(dto: PayloadDeviceDatatargetGetByDataTargetResponse) { + private mapToDatatargetDevicePayload( + dto: PayloadDeviceDatatargetGetByDataTargetResponse + ) { this.payloadDeviceDatatarget = []; - dto.data.forEach( - (element) => { - this.payloadDeviceDatatarget.push({ - id: element.id, - iotDeviceIds: element.iotDevices.map((x) => x.id), - payloadDecoderId: element.payloadDecoder?.id === undefined ? 0 : element.payloadDecoder?.id, - dataTargetId: element.dataTarget.id - }); - } - ); + dto.data.forEach((element) => { + this.payloadDeviceDatatarget.push({ + id: element.id, + iotDeviceIds: element.iotDevices.map((x) => x.id), + payloadDecoderId: + element.payloadDecoder?.id === undefined + ? 0 + : element.payloadDecoder?.id, + dataTargetId: element.dataTarget.id, + }); + }); } } diff --git a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts index c68dc4304..e28bb6903 100644 --- a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts +++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts @@ -78,7 +78,7 @@ export class HttppushEditComponent private opendatadkService: OpendatadkService, private opendatadkDialogService: OpendatadkDialogService, private scrollToTopService: ScrollToTopService, - private meService: MeService, + private meService: MeService ) { translate.use('da'); } @@ -114,7 +114,11 @@ export class HttppushEditComponent } this.getPayloadDecoders(); this.setDataSetExcists(); - this.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite, undefined, this.applicationId); + this.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.ApplicationWrite, + undefined, + this.applicationId + ); } addRow() { @@ -295,7 +299,7 @@ export class HttppushEditComponent getPayloadDecoders() { this.payloadDecoderSubscription = this.payloadDecoderService - .getMultiple(1000, 0, 'id', 'ASC') + .getMultiple(1000, 0, 'name', 'ASC') .subscribe((response: PayloadDecoderMappedResponse) => { this.payloadDecoders = response.data; }); diff --git a/src/app/applications/datatarget/mqtt-edit/mqtt-edit.component.ts b/src/app/applications/datatarget/mqtt-edit/mqtt-edit.component.ts index 7d3e8f62d..5114238a4 100644 --- a/src/app/applications/datatarget/mqtt-edit/mqtt-edit.component.ts +++ b/src/app/applications/datatarget/mqtt-edit/mqtt-edit.component.ts @@ -84,7 +84,7 @@ export class MqttEditComponent implements DatatargetEdit, OnInit, OnDestroy { private getPayloadDecoders() { this.payloadDecoderSubscription = this.payloadDecoderService - .getMultiple(1000, 0, 'id', 'ASC') + .getMultiple(1000, 0, 'name', 'ASC') .subscribe((response: PayloadDecoderMappedResponse) => { this.payloadDecoders = response.data; }); diff --git a/src/app/device-model/device-model-table/device-model-table.component.ts b/src/app/device-model/device-model-table/device-model-table.component.ts index 18d575ef8..f997a1ef6 100644 --- a/src/app/device-model/device-model-table/device-model-table.component.ts +++ b/src/app/device-model/device-model-table/device-model-table.component.ts @@ -1,21 +1,13 @@ -import { Location } from '@angular/common'; -import { - AfterViewInit, - Component, - OnDestroy, - OnInit, - ViewChild, -} from '@angular/core'; +import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; import { environment } from '@environments/environment'; import { TranslateService } from '@ngx-translate/core'; import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dialog.service'; import { MeService } from '@shared/services/me.service'; import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; import { merge, Observable, of as observableOf, Subscription } from 'rxjs'; -import { startWith, switchMap, map, catchError } from 'rxjs/operators'; +import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { DeviceModelService } from '../device-model.service'; import { DeviceModel, DeviceModelResponse } from '../device.model'; import { OrganizationAccessScope } from '@shared/enums/access-scopes'; @@ -48,7 +40,9 @@ export class DeviceModelTableComponent implements OnInit, AfterViewInit { ) {} ngOnInit(): void { - this.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite); + this.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.ApplicationWrite + ); this.translateService .get(['DEVICE-MODEL.DELETE-FAILED']) .subscribe((translations) => { @@ -72,7 +66,9 @@ export class DeviceModelTableComponent implements OnInit, AfterViewInit { this.isLoadingResults = false; this.resultsLength = data.count; - return data.data; + return data.data.sort((a, b) => + a.body.name.localeCompare(b.body.name, 'en', { numeric: true }) + ); }), catchError(() => { this.isLoadingResults = false; diff --git a/src/app/gateway/gateway-list/gateway-list.component.ts b/src/app/gateway/gateway-list/gateway-list.component.ts index ba7b67a7b..9c4d0f9e4 100644 --- a/src/app/gateway/gateway-list/gateway-list.component.ts +++ b/src/app/gateway/gateway-list/gateway-list.component.ts @@ -1,207 +1,209 @@ -import { Component, OnChanges, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { Organisation } from '@app/admin/organisation/organisation.model'; -import { TranslateService } from '@ngx-translate/core'; -import { Sort } from '@shared/models/sort.model'; -import { ChirpstackGatewayService } from '@shared/services/chirpstack-gateway.service'; -import moment from 'moment'; -import { Subject, Subscription } from 'rxjs'; -import { Gateway, GatewayResponseMany } from '../gateway.model'; -import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dialog.service'; -import { MeService } from '@shared/services/me.service'; -import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; -import { environment } from '@environments/environment'; -import { Title } from '@angular/platform-browser'; -import { OrganizationAccessScope } from '@shared/enums/access-scopes'; -import { MatTabChangeEvent } from '@angular/material/tabs'; - -const gatewayStatusTabIndex = 2; - -@Component({ - selector: 'app-gateway-list', - templateUrl: './gateway-list.component.html', - styleUrls: ['./gateway-list.component.scss'] -}) -export class GatewayListComponent implements OnInit, OnChanges, OnDestroy { - isLoadingResults = true; - selectedOrg: number; - - public coordinateList = []; - public showmap = false; - public pageLimit = environment.tablePageSize; - public selectedSortId = 1; - public gateways: Gateway[]; - private gatewaySubscription: Subscription; - public selectedSortObject: Sort = { - id: 1, - dir: 'ASC', - col: 'name', - label: 'SORT.NAME-ASCENDING', - }; - organisations: Organisation[]; - orgSubscribtion: Subscription; - - private deleteDialogSubscription: Subscription; - public pageOffset = 0; - public pageTotal: number; - organisationId: number; - canEdit: boolean; - tabIndex = 0; - organisationChangeSubject: Subject = new Subject(); - isGatewayStatusVisibleSubject: Subject = new Subject(); - - constructor( - public translate: TranslateService, - private chirpstackGatewayService: ChirpstackGatewayService, - private deleteDialogService: DeleteDialogService, - private meService: MeService, - private titleService: Title, - private sharedVariableService: SharedVariableService, - ) { - translate.use('da'); - moment.locale('da'); - } - - ngOnInit(): void { - this.getGateways(); - this.organisations = this.sharedVariableService.getOrganizationInfo(); - this.translate.get(['TITLE.LORAWAN-GATEWAY']) - .subscribe(translations => { - this.titleService.setTitle(translations['TITLE.LORAWAN-GATEWAY']); - }); - this.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.GatewayWrite); - } - - ngOnChanges() { - } - - public filterGatewayByOrgId(event: number) { - this.selectedOrg = event; - if (event) { - this.getGatewayWith(event); - } else { - this.getGateways(); - } - } - - setOrgIdFilter(orgId: number) { - this.organisationId = orgId; - this.organisationChangeSubject.next(orgId); - - if (this.tabIndex === gatewayStatusTabIndex) { - this.isGatewayStatusVisibleSubject.next(); - } - - this.filterGatewayByOrgId(orgId); - } - - private getGateways(): void { - this.gatewaySubscription = this.chirpstackGatewayService.getMultiple( - { - limit: this.pageLimit, - offset: this.pageOffset * this.pageLimit, - sort: this.selectedSortObject.dir, - orderOn: this.selectedSortObject.col, - } - ) - .subscribe( - (gateways: GatewayResponseMany) => { - this.gateways = gateways.result; - this.mapToCoordinateList(); - this.setCanEdit(); - this.isLoadingResults = false; - } - ); - } - - private getGatewayWith(orgId: number): void { - this.gatewaySubscription = this.chirpstackGatewayService.getMultiple( - { - limit: this.pageLimit, - offset: this.pageOffset * this.pageLimit, - sort: this.selectedSortObject.dir, - orderOn: this.selectedSortObject.col, - organizationId: orgId, - } - ) - .subscribe( - (gateways: GatewayResponseMany) => { - this.gateways = gateways.result; - this.mapToCoordinateList(); - this.setCanEdit(); - this.isLoadingResults = false; - } - ); - } - - selectedTabChange({index}: MatTabChangeEvent) { - this.tabIndex = index; - - if (index === 1) { - if (this.selectedOrg) { - this.getGatewayWith(this.selectedOrg); - } else { - this.getGateways(); - } - this.showmap = true; - } else if (index === gatewayStatusTabIndex) { - this.isGatewayStatusVisibleSubject.next(); - } - } - - private mapToCoordinateList() { - const tempcoordinateList = []; - this.gateways.map( - gateway => tempcoordinateList.push( - { - longitude: gateway.location.longitude, - latitude: gateway.location.latitude, - draggable: false, - editEnabled: false, - useGeolocation: false, - markerInfo: { - name: gateway.name, - active: this.gatewayStatus(gateway), - id: gateway.id, - internalOrganizationId: gateway.internalOrganizationId, - internalOrganizationName: gateway.internalOrganizationName - } - } - ), - ); - this.coordinateList = tempcoordinateList; - } - - gatewayStatus(gateway: Gateway): boolean { - return this.chirpstackGatewayService.isGatewayActive(gateway); - } - - deleteGateway(id: string) { - this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog().subscribe( - (response) => { - if (response) { - this.chirpstackGatewayService.delete(id).subscribe((response) => { - if (response.ok && response.body.success === true) { - this.getGateways(); - } - }); - } else { - console.log(response); - } - } - ); - } - - setCanEdit() { - this.gateways.forEach( - (gateway) => { - gateway.canEdit = this.meService.hasAccessToTargetOrganization(OrganizationAccessScope.GatewayWrite, gateway.internalOrganizationId); - } - ); - } - - ngOnDestroy() { - // prevent memory leak by unsubscribing - this.gatewaySubscription?.unsubscribe(); - this.deleteDialogSubscription?.unsubscribe(); - } -} +import { + Component, + OnChanges, + OnDestroy, + OnInit, + ViewChild, +} from '@angular/core'; +import { Organisation } from '@app/admin/organisation/organisation.model'; +import { TranslateService } from '@ngx-translate/core'; +import { Sort } from '@shared/models/sort.model'; +import { ChirpstackGatewayService } from '@shared/services/chirpstack-gateway.service'; +import moment from 'moment'; +import { Subject, Subscription } from 'rxjs'; +import { Gateway, GatewayResponseMany } from '../gateway.model'; +import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dialog.service'; +import { MeService } from '@shared/services/me.service'; +import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; +import { environment } from '@environments/environment'; +import { Title } from '@angular/platform-browser'; +import { OrganizationAccessScope } from '@shared/enums/access-scopes'; +import { MatTabChangeEvent } from '@angular/material/tabs'; + +const gatewayStatusTabIndex = 2; + +@Component({ + selector: 'app-gateway-list', + templateUrl: './gateway-list.component.html', + styleUrls: ['./gateway-list.component.scss'], +}) +export class GatewayListComponent implements OnInit, OnChanges, OnDestroy { + isLoadingResults = true; + selectedOrg: number; + + public coordinateList = []; + public showmap = false; + public pageLimit = environment.tablePageSize; + public selectedSortId = 1; + public gateways: Gateway[]; + private gatewaySubscription: Subscription; + public selectedSortObject: Sort = { + id: 1, + dir: 'ASC', + col: 'name', + label: 'SORT.NAME-ASCENDING', + }; + organisations: Organisation[]; + orgSubscribtion: Subscription; + + private deleteDialogSubscription: Subscription; + public pageOffset = 0; + public pageTotal: number; + organisationId: number; + canEdit: boolean; + tabIndex = 0; + organisationChangeSubject: Subject = new Subject(); + isGatewayStatusVisibleSubject: Subject = new Subject(); + + constructor( + public translate: TranslateService, + private chirpstackGatewayService: ChirpstackGatewayService, + private deleteDialogService: DeleteDialogService, + private meService: MeService, + private titleService: Title, + private sharedVariableService: SharedVariableService + ) { + translate.use('da'); + moment.locale('da'); + } + + ngOnInit(): void { + this.getGateways(); + this.organisations = this.sharedVariableService.getOrganizationInfo(); + this.organisations.sort((a, b) => + a.name.localeCompare(b.name, 'en', { numeric: true }) + ); + this.translate.get(['TITLE.LORAWAN-GATEWAY']).subscribe((translations) => { + this.titleService.setTitle(translations['TITLE.LORAWAN-GATEWAY']); + }); + this.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.GatewayWrite + ); + } + + ngOnChanges() {} + + public filterGatewayByOrgId(event: number) { + this.selectedOrg = event; + if (event) { + this.getGatewayWith(event); + } else { + this.getGateways(); + } + } + + setOrgIdFilter(orgId: number) { + this.organisationId = orgId; + this.organisationChangeSubject.next(orgId); + + if (this.tabIndex === gatewayStatusTabIndex) { + this.isGatewayStatusVisibleSubject.next(); + } + + this.filterGatewayByOrgId(orgId); + } + + private getGateways(): void { + this.gatewaySubscription = this.chirpstackGatewayService + .getMultiple({ + limit: this.pageLimit, + offset: this.pageOffset * this.pageLimit, + sort: this.selectedSortObject.dir, + orderOn: this.selectedSortObject.col, + }) + .subscribe((gateways: GatewayResponseMany) => { + this.gateways = gateways.result; + this.mapToCoordinateList(); + this.setCanEdit(); + this.isLoadingResults = false; + }); + } + + private getGatewayWith(orgId: number): void { + this.gatewaySubscription = this.chirpstackGatewayService + .getMultiple({ + limit: this.pageLimit, + offset: this.pageOffset * this.pageLimit, + sort: this.selectedSortObject.dir, + orderOn: this.selectedSortObject.col, + organizationId: orgId, + }) + .subscribe((gateways: GatewayResponseMany) => { + this.gateways = gateways.result; + this.mapToCoordinateList(); + this.setCanEdit(); + this.isLoadingResults = false; + }); + } + + selectedTabChange({ index }: MatTabChangeEvent) { + this.tabIndex = index; + + if (index === 1) { + if (this.selectedOrg) { + this.getGatewayWith(this.selectedOrg); + } else { + this.getGateways(); + } + this.showmap = true; + } else if (index === gatewayStatusTabIndex) { + this.isGatewayStatusVisibleSubject.next(); + } + } + + private mapToCoordinateList() { + const tempcoordinateList = []; + this.gateways.map((gateway) => + tempcoordinateList.push({ + longitude: gateway.location.longitude, + latitude: gateway.location.latitude, + draggable: false, + editEnabled: false, + useGeolocation: false, + markerInfo: { + name: gateway.name, + active: this.gatewayStatus(gateway), + id: gateway.id, + internalOrganizationId: gateway.internalOrganizationId, + internalOrganizationName: gateway.internalOrganizationName, + }, + }) + ); + this.coordinateList = tempcoordinateList; + } + + gatewayStatus(gateway: Gateway): boolean { + return this.chirpstackGatewayService.isGatewayActive(gateway); + } + + deleteGateway(id: string) { + this.deleteDialogSubscription = this.deleteDialogService + .showSimpleDialog() + .subscribe((response) => { + if (response) { + this.chirpstackGatewayService.delete(id).subscribe((response) => { + if (response.ok && response.body.success === true) { + this.getGateways(); + } + }); + } else { + console.log(response); + } + }); + } + + setCanEdit() { + this.gateways.forEach((gateway) => { + gateway.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.GatewayWrite, + gateway.internalOrganizationId + ); + }); + } + + ngOnDestroy() { + // prevent memory leak by unsubscribing + this.gatewaySubscription?.unsubscribe(); + this.deleteDialogSubscription?.unsubscribe(); + } +} diff --git a/src/app/navbar/organisation-dropdown/organisation-dropdown.component.html b/src/app/navbar/organisation-dropdown/organisation-dropdown.component.html index 7e1dccfea..4f97fad63 100644 --- a/src/app/navbar/organisation-dropdown/organisation-dropdown.component.html +++ b/src/app/navbar/organisation-dropdown/organisation-dropdown.component.html @@ -26,7 +26,7 @@ - +