From 963f5d4ce05e2f6c768e005cd5456987834e6c7f Mon Sep 17 00:00:00 2001 From: August Andersen Date: Fri, 12 Nov 2021 11:02:53 +0100 Subject: [PATCH 1/3] Added message to prompt when attempting to delete application with SigFox device * Added message and functionality to check and to prompt when attempting to delete application with SigFox device --- .../applications-table.component.ts | 50 +++++++++++++++++-- src/assets/i18n/da.json | 1 + 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/app/applications/applications-list/applications-table/applications-table.component.ts b/src/app/applications/applications-list/applications-table/applications-table.component.ts index 4da38304..4286f5c9 100644 --- a/src/app/applications/applications-list/applications-table/applications-table.component.ts +++ b/src/app/applications/applications-list/applications-table/applications-table.component.ts @@ -1,4 +1,10 @@ -import { Component, ViewChild, AfterViewInit, Input, OnInit } from '@angular/core'; +import { + Component, + ViewChild, + AfterViewInit, + Input, + OnInit, +} from '@angular/core'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { Router } from '@angular/router'; @@ -10,6 +16,7 @@ import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dia import { MeService } from '@shared/services/me.service'; import { merge, Observable, of as observableOf } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; +import { DeviceType } from '@shared/enums/device-type'; /** * @title Table retrieving data through HTTP @@ -40,7 +47,7 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { private router: Router, private meService: MeService, private deleteDialogService: DeleteDialogService - ) { } + ) {} ngOnInit() { this.canEdit = this.meService.canWriteInTargetOrganization(); @@ -88,6 +95,11 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { deleteApplication(id: number) { let message: string; + + if (this.canBeDeleted(id)) { + return; + } + if (this.applicationHasDevices(id)) { message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); } @@ -110,10 +122,42 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { } applicationHasDevices(id: number): boolean { - const applicationToDelete = this.data?.find(app => app.id === id); + const applicationToDelete = this.data?.find((app) => app.id === id); return applicationToDelete && applicationToDelete.iotDevices.length > 0; } + applicationHasSigFoxDevices(id: number): boolean { + const applicationToDelete = this.data?.find((app) => app.id === id); + const checkForSigfox = applicationToDelete.iotDevices.find((device) => { + return device.type === DeviceType.SIGFOX; + }); + if (checkForSigfox) { + return true; + } else return false; + } + + canBeDeleted(id: number): boolean { + let message: string; + + if (this.applicationHasSigFoxDevices(id)) { + message = this.translate.instant( + 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' + ); + this.deleteDialogService + .showSimpleDialog( + message, + false, + true, + false, + this.translate.instant('APPLICATION.DELETE') + ) + .subscribe(); + return true; + } else { + return false; + } + } + navigateToEditPage(applicationId: string) { this.router.navigate(['applications', 'edit-application', applicationId]); } diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index 96c8b754..10f666f3 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -81,6 +81,7 @@ "SAVE": "Gem applikation", "DELETE": "Slet applikation", "DELETE-HAS-DEVICES-PROMPT": "Der er knyttet IoT-enheder til denne applikation. Disse vil også blive slettet. Slet alligevel?", + "DELETE-HAS-SIGFOX-DEVICES-PROMPT": "Applikationen kan ikke slettes, da der er knyttet Sigfox enheder til den", "NAME": "Applikationens navn", "DESCRIPTION": "Applikationens beskrivelse", "ATTACHED-IOT": "Tilknyttede IoT enheder", From 4b11b86c05887fcf05ba9fe31841a2d6db23f365 Mon Sep 17 00:00:00 2001 From: August Andersen Date: Fri, 19 Nov 2021 11:25:22 +0100 Subject: [PATCH 2/3] PR Changes. Also made the check for sigfox devices in detail page, which i missed before. --- .../application-detail.component.ts | 24 +++++- .../applications-table.component.ts | 73 +++++++------------ 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/app/applications/application-detail/application-detail.component.ts b/src/app/applications/application-detail/application-detail.component.ts index 009f3a63..77a56571 100644 --- a/src/app/applications/application-detail/application-detail.component.ts +++ b/src/app/applications/application-detail/application-detail.component.ts @@ -5,6 +5,7 @@ import { Application } from '@applications/application.model'; import { ApplicationService } from '@applications/application.service'; import { TranslateService } from '@ngx-translate/core'; import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dialog.service'; +import { DeviceType } from '@shared/enums/device-type'; import { BackButton } from '@shared/models/back-button.model'; import { DropdownButton } from '@shared/models/dropdown-button.model'; import { MeService } from '@shared/services/me.service'; @@ -59,12 +60,22 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy { } onDeleteApplication() { + let message: string; - if (this.applicationHasDevices()) { - message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); + let showAccept: boolean = true; + const hasSigfoxDevices: boolean = this.applicationHasSigFoxDevices(); + + if (hasSigfoxDevices) { + message = this.translate.instant( + 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' + ); + showAccept = false; + + } else if (this.applicationHasDevices()) { + message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); } - this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog(message).subscribe( + this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog(message, showAccept).subscribe( (response) => { if (response) { this.applicationService.deleteApplication(this.application.id).subscribe((response) => { @@ -86,6 +97,13 @@ export class ApplicationDetailComponent implements OnInit, OnDestroy { return this.application.iotDevices?.length > 0; } + applicationHasSigFoxDevices(): boolean { + const sigfoxDevice = this.application.iotDevices.find((device) => { + return device.type === DeviceType.SIGFOX; + }); + return sigfoxDevice !== undefined; + } + bindApplication(id: number): void { this.applicationsSubscription = this.applicationService.getApplication(id).subscribe((application) => { this.application = application; diff --git a/src/app/applications/applications-list/applications-table/applications-table.component.ts b/src/app/applications/applications-list/applications-table/applications-table.component.ts index 4286f5c9..bfdb8b3f 100644 --- a/src/app/applications/applications-list/applications-table/applications-table.component.ts +++ b/src/app/applications/applications-list/applications-table/applications-table.component.ts @@ -95,30 +95,37 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { deleteApplication(id: number) { let message: string; + let showAccept: boolean = true; + const hasSigfoxDevices: boolean = this.applicationHasSigFoxDevices(id); - if (this.canBeDeleted(id)) { - return; - } - - if (this.applicationHasDevices(id)) { + if (hasSigfoxDevices) { + message = this.translate.instant( + 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' + ); + showAccept = false; + } else if (this.applicationHasDevices(id)) { message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); } - this.deleteDialogService.showSimpleDialog(message).subscribe((response) => { - if (response) { - this.applicationService.deleteApplication(id).subscribe((response) => { - if (response.ok && response.body.affected > 0) { - this.paginator.page.emit({ - pageIndex: this.paginator.pageIndex, - pageSize: this.paginator.pageSize, - length: this.resultsLength, + this.deleteDialogService + .showSimpleDialog(message, showAccept) + .subscribe((response) => { + if (response) { + this.applicationService + .deleteApplication(id) + .subscribe((response) => { + if (response.ok && response.body.affected > 0) { + this.paginator.page.emit({ + pageIndex: this.paginator.pageIndex, + pageSize: this.paginator.pageSize, + length: this.resultsLength, + }); + } else { + this.errorMessage = response?.error?.message; + } }); - } else { - this.errorMessage = response?.error?.message; - } - }); - } - }); + } + }); } applicationHasDevices(id: number): boolean { @@ -128,34 +135,10 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { applicationHasSigFoxDevices(id: number): boolean { const applicationToDelete = this.data?.find((app) => app.id === id); - const checkForSigfox = applicationToDelete.iotDevices.find((device) => { + const sigfoxDevice = applicationToDelete.iotDevices.find((device) => { return device.type === DeviceType.SIGFOX; }); - if (checkForSigfox) { - return true; - } else return false; - } - - canBeDeleted(id: number): boolean { - let message: string; - - if (this.applicationHasSigFoxDevices(id)) { - message = this.translate.instant( - 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' - ); - this.deleteDialogService - .showSimpleDialog( - message, - false, - true, - false, - this.translate.instant('APPLICATION.DELETE') - ) - .subscribe(); - return true; - } else { - return false; - } + return sigfoxDevice !== undefined; } navigateToEditPage(applicationId: string) { From 0ca152605bde25be7fbea66498deb61505975d2d Mon Sep 17 00:00:00 2001 From: August Andersen Date: Mon, 22 Nov 2021 11:23:52 +0100 Subject: [PATCH 3/3] PR Changes + formatting --- .../application-detail.component.ts | 178 ++++++++---------- .../applications-table.component.ts | 29 +-- .../delete-dialog/delete-dialog.service.ts | 79 ++++++-- 3 files changed, 144 insertions(+), 142 deletions(-) diff --git a/src/app/applications/application-detail/application-detail.component.ts b/src/app/applications/application-detail/application-detail.component.ts index 77a56571..bd2c124d 100644 --- a/src/app/applications/application-detail/application-detail.component.ts +++ b/src/app/applications/application-detail/application-detail.component.ts @@ -1,4 +1,10 @@ -import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; +import { + Component, + EventEmitter, + OnDestroy, + OnInit, + Output, +} from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; import { Application } from '@applications/application.model'; @@ -12,110 +18,92 @@ import { MeService } from '@shared/services/me.service'; import { Subscription } from 'rxjs'; @Component({ - selector: 'app-application', - templateUrl: './application-detail.component.html', - styleUrls: ['./application-detail.component.scss'], + selector: 'app-application', + templateUrl: './application-detail.component.html', + styleUrls: ['./application-detail.component.scss'], }) export class ApplicationDetailComponent implements OnInit, OnDestroy { - @Output() deleteApplication = new EventEmitter(); - public applicationsSubscription: Subscription; - private deleteDialogSubscription: Subscription; - public application: Application; - public backButton: BackButton = { label: '', routerLink: '/applications' }; - public id: number; - public dropdownButton: DropdownButton; - public errorMessage: string; - public canEdit = false; + @Output() deleteApplication = new EventEmitter(); + public applicationsSubscription: Subscription; + public application: Application; + public backButton: BackButton = { label: '', routerLink: '/applications' }; + public id: number; + public dropdownButton: DropdownButton; + public errorMessage: string; + public canEdit = false; - constructor( - private applicationService: ApplicationService, - private route: ActivatedRoute, - public translate: TranslateService, - public router: Router, - private meService: MeService, - private titleService: Title, - private deleteDialogService: DeleteDialogService - ) { } + constructor( + private applicationService: ApplicationService, + private route: ActivatedRoute, + public translate: TranslateService, + public router: Router, + private meService: MeService, + private titleService: Title, + private deleteDialogService: DeleteDialogService + ) {} - ngOnInit(): void { - this.id = +this.route.snapshot.paramMap.get('id'); - if (this.id) { - this.bindApplication(this.id); - this.dropdownButton = { - label: '', - editRouterLink: '../../edit-application/' + this.id, - isErasable: true, - }; + ngOnInit(): void { + this.id = +this.route.snapshot.paramMap.get('id'); + if (this.id) { + this.bindApplication(this.id); + this.dropdownButton = { + label: '', + editRouterLink: '../../edit-application/' + this.id, + isErasable: true, + }; - console.log(this.id); - } - - this.translate.get(['NAV.APPLICATIONS', 'APPLICATION-TABLE-ROW.SHOW-OPTIONS', 'TITLE.APPLICATION']) - .subscribe(translations => { - this.backButton.label = translations['NAV.APPLICATIONS']; - this.dropdownButton.label = translations['APPLICATION-TABLE-ROW.SHOW-OPTIONS']; - this.titleService.setTitle(translations['TITLE.APPLICATION']); - }); - this.canEdit = this.meService.canWriteInTargetOrganization(); + console.log(this.id); } - onDeleteApplication() { - - let message: string; - let showAccept: boolean = true; - const hasSigfoxDevices: boolean = this.applicationHasSigFoxDevices(); - - if (hasSigfoxDevices) { - message = this.translate.instant( - 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' - ); - showAccept = false; + this.translate + .get([ + 'NAV.APPLICATIONS', + 'APPLICATION-TABLE-ROW.SHOW-OPTIONS', + 'TITLE.APPLICATION', + ]) + .subscribe((translations) => { + this.backButton.label = translations['NAV.APPLICATIONS']; + this.dropdownButton.label = + translations['APPLICATION-TABLE-ROW.SHOW-OPTIONS']; + this.titleService.setTitle(translations['TITLE.APPLICATION']); + }); + this.canEdit = this.meService.canWriteInTargetOrganization(); + } - } else if (this.applicationHasDevices()) { - message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); + onDeleteApplication() { + this.deleteDialogService + .showApplicationDialog(this.application) + .subscribe((response) => { + if (response) { + this.applicationService + .deleteApplication(this.application.id) + .subscribe((response) => { + if (response.ok && response.body.affected > 0) { + console.log( + 'delete application with id:' + this.application.id.toString() + ); + this.router.navigate(['applications']); + } else { + this.errorMessage = response?.error?.message; + } + }); + } else { + console.log(response); } + }); + } - this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog(message, showAccept).subscribe( - (response) => { - if (response) { - this.applicationService.deleteApplication(this.application.id).subscribe((response) => { - if (response.ok && response.body.affected > 0) { - console.log('delete application with id:' + this.application.id.toString()); - this.router.navigate(['applications']); - } else { - this.errorMessage = response?.error?.message; - } - }); - } else { - console.log(response); - } - } - ); - } - - applicationHasDevices(): boolean { - return this.application.iotDevices?.length > 0; - } - - applicationHasSigFoxDevices(): boolean { - const sigfoxDevice = this.application.iotDevices.find((device) => { - return device.type === DeviceType.SIGFOX; - }); - return sigfoxDevice !== undefined; - } + bindApplication(id: number): void { + this.applicationsSubscription = this.applicationService + .getApplication(id) + .subscribe((application) => { + this.application = application; + }); + } - bindApplication(id: number): void { - this.applicationsSubscription = this.applicationService.getApplication(id).subscribe((application) => { - this.application = application; - }); - } - - ngOnDestroy() { - if (this.applicationsSubscription) { - this.applicationsSubscription.unsubscribe(); - } - if (this.deleteDialogSubscription) { - this.deleteDialogSubscription.unsubscribe(); - } + ngOnDestroy() { + if (this.applicationsSubscription) { + this.applicationsSubscription.unsubscribe(); } + } } diff --git a/src/app/applications/applications-list/applications-table/applications-table.component.ts b/src/app/applications/applications-list/applications-table/applications-table.component.ts index bfdb8b3f..a459055d 100644 --- a/src/app/applications/applications-list/applications-table/applications-table.component.ts +++ b/src/app/applications/applications-list/applications-table/applications-table.component.ts @@ -94,21 +94,10 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { } deleteApplication(id: number) { - let message: string; - let showAccept: boolean = true; - const hasSigfoxDevices: boolean = this.applicationHasSigFoxDevices(id); - - if (hasSigfoxDevices) { - message = this.translate.instant( - 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' - ); - showAccept = false; - } else if (this.applicationHasDevices(id)) { - message = this.translate.instant('APPLICATION.DELETE-HAS-DEVICES-PROMPT'); - } + const applicationToDelete = this.data?.find((app) => app.id === id); this.deleteDialogService - .showSimpleDialog(message, showAccept) + .showApplicationDialog(applicationToDelete) .subscribe((response) => { if (response) { this.applicationService @@ -127,20 +116,6 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit { } }); } - - applicationHasDevices(id: number): boolean { - const applicationToDelete = this.data?.find((app) => app.id === id); - return applicationToDelete && applicationToDelete.iotDevices.length > 0; - } - - applicationHasSigFoxDevices(id: number): boolean { - const applicationToDelete = this.data?.find((app) => app.id === id); - const sigfoxDevice = applicationToDelete.iotDevices.find((device) => { - return device.type === DeviceType.SIGFOX; - }); - return sigfoxDevice !== undefined; - } - navigateToEditPage(applicationId: string) { this.router.navigate(['applications', 'edit-application', applicationId]); } diff --git a/src/app/shared/components/delete-dialog/delete-dialog.service.ts b/src/app/shared/components/delete-dialog/delete-dialog.service.ts index 6bb51bcc..90a6257a 100644 --- a/src/app/shared/components/delete-dialog/delete-dialog.service.ts +++ b/src/app/shared/components/delete-dialog/delete-dialog.service.ts @@ -1,33 +1,72 @@ import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { DeleteDialogComponent } from './delete-dialog.component'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; +import { Application } from '@applications/application.model'; +import { DeviceType } from '@shared/enums/device-type'; +import { TranslateService } from '@ngx-translate/core'; @Injectable({ providedIn: 'root', }) export class DeleteDialogService { - + private deleteDialogSubscription: Subscription; constructor( - private dialog: MatDialog - ) { } + private dialog: MatDialog, + public translate: TranslateService, + ) {} + + showSimpleDialog( + message?: string, + showAccept = true, + showCancel = true, + showOk = false, + infoTitle = '' + ): Observable { + return new Observable((observer) => { + const dialog = this.dialog.open(DeleteDialogComponent, { + data: { + infoTitle, + showOk, + showAccept, + showCancel, + message: message ? message : 'Er du sikker på at du vil slette?', + }, + }); + + dialog.afterClosed().subscribe((result) => { + observer.next(result); + }); + }); + } - showSimpleDialog(message?: string, showAccept = true, showCancel = true, showOk = false, infoTitle = ''): Observable { - return new Observable( - (observer) => { - const dialog = this.dialog.open(DeleteDialogComponent, { - data: { - infoTitle, - showOk, - showAccept, - showCancel, - message: message ? message : 'Er du sikker på at du vil slette?' - } - }); + showApplicationDialog(application: Application): Observable { + let message: string; + let showAccept: boolean = true; + const hasSigfoxDevices: boolean = this.applicationHasSigFoxDevices( + application + ); - dialog.afterClosed().subscribe((result) => { - observer.next(result); - }); + if (hasSigfoxDevices) { + message = this.translate.instant( + 'APPLICATION.DELETE-HAS-SIGFOX-DEVICES-PROMPT' + ); + showAccept = false; + } else if (this.applicationHasDevices(application)) { + message = this.translate.instant( + 'APPLICATION.DELETE-HAS-DEVICES-PROMPT' + ); } - ); + return this.showSimpleDialog(message, showAccept); + } + + applicationHasDevices(application: Application): boolean { + return application.iotDevices?.length > 0; + } + + applicationHasSigFoxDevices(application: Application): boolean { + const sigfoxDevice = application.iotDevices.find((device) => { + return device.type === DeviceType.SIGFOX; + }); + return sigfoxDevice !== undefined; } }