From 3f4db59c6d616bf3dbae00806d756340aec3ae84 Mon Sep 17 00:00:00 2001 From: Chris Dons Johansen Date: Fri, 13 Sep 2024 13:47:25 +0200 Subject: [PATCH 1/9] Initial restructure of UI-code to allow having tabs under datatarget-details.. --- .../applications-routing.module.ts | 4 + .../datatarget/datatarget-types.service.ts | 3 + .../datatarget/datatarget.module.ts | 2 + .../httppush-detail-tabs.component.html | 15 ++ .../httppush-detail-tabs.component.scss | 0 .../httppush-detail-tabs.component.spec.ts | 23 +++ .../httppush-detail-tabs.component.ts | 111 +++++++++++++ .../httppush-detail.component.html | 155 ++++++++---------- .../httppush-detail.component.ts | 93 +++-------- .../components/top-bar/top-bar.component.html | 4 +- src/app/shared/types/nav-tabs.type.ts | 5 + src/assets/i18n/da.json | 1 + src/assets/i18n/en.json | 1 + 13 files changed, 265 insertions(+), 152 deletions(-) create mode 100644 src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.html create mode 100644 src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.scss create mode 100644 src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.spec.ts create mode 100644 src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.ts create mode 100644 src/app/shared/types/nav-tabs.type.ts diff --git a/src/app/applications/applications-routing.module.ts b/src/app/applications/applications-routing.module.ts index 5542be8df..869156091 100644 --- a/src/app/applications/applications-routing.module.ts +++ b/src/app/applications/applications-routing.module.ts @@ -19,6 +19,7 @@ import { IotDeviceDetailsTabComponent } from "@applications/iot-devices/iot-devi import { IotDeviceHistoryTabComponent } from "@applications/iot-devices/iot-device-detail/iot-device-history-tab/iot-device-history-tab.component"; import { IotDeviceDataPacketsTabComponent } from "@applications/iot-devices/iot-device-detail/iot-device-data-packets-tab/iot-device-data-packets-tab.component"; import { IotDeviceDownlinkTabComponent } from "@applications/iot-devices/iot-device-detail/iot-device-downlink-tab/iot-device-downlink-tab.component"; +import { HttppushDetailComponent } from "./datatarget/httppush/httppush-detail/httppush-detail.component"; const applicationRoutes: Routes = [ { @@ -70,6 +71,9 @@ const applicationRoutes: Routes = [ { path: "datatarget/:datatargetId", component: DatatargetDetailComponent, + children: [ + {path: "httppush-detail", component: HttppushDetailComponent } + ] }, { path: "multicast-edit", component: MulticastEditComponent }, { diff --git a/src/app/applications/datatarget/datatarget-types.service.ts b/src/app/applications/datatarget/datatarget-types.service.ts index de53fe079..68006dfcb 100644 --- a/src/app/applications/datatarget/datatarget-types.service.ts +++ b/src/app/applications/datatarget/datatarget-types.service.ts @@ -10,6 +10,7 @@ import { HttppushEditComponent } from "./httppush/httppush-edit/httppush-edit.co import { MqttDetailComponent } from "./mqtt-detail/mqtt-detail.component"; import { MqttEditComponent } from "./mqtt-edit/mqtt-edit.component"; import { OpendatadkEditComponent } from "./opendatadk/opendatadk-edit/opendatadk-edit.component"; +import { HttppushDetailTabsComponent } from "./httppush/httppush-detail-tabs/httppush-detail-tabs.component"; @Injectable({ providedIn: "root", @@ -56,10 +57,12 @@ export class DatatargetTypesService { getDetailComponent(dataTargetType: DataTargetType): Type { if (dataTargetType === DataTargetType.HTTPPUSH) { + return HttppushDetailTabsComponent; return HttppushDetailComponent; } if (dataTargetType === DataTargetType.OPENDATADK) { + return HttppushDetailTabsComponent; return HttppushDetailComponent; } diff --git a/src/app/applications/datatarget/datatarget.module.ts b/src/app/applications/datatarget/datatarget.module.ts index ea0361994..8bcb804b8 100644 --- a/src/app/applications/datatarget/datatarget.module.ts +++ b/src/app/applications/datatarget/datatarget.module.ts @@ -16,6 +16,7 @@ import { SharedModule } from "@shared/shared.module"; import { PipesModule } from "@shared/pipes/pipes.module"; import { DatatargetNewComponent } from "./datatarget-new/datatarget-new.component"; import { FiwareEditComponent } from "./fiware/fiware-edit/fiware-edit.component"; +import { HttppushDetailTabsComponent } from "./httppush/httppush-detail-tabs/httppush-detail-tabs.component"; import { FiwareDetailComponent } from "./fiware/fiware-detail/fiware-detail.component"; import { HttppushDetailComponent } from "./httppush/httppush-detail/httppush-detail.component"; import { HttppushEditComponent } from "./httppush/httppush-edit/httppush-edit.component"; @@ -35,6 +36,7 @@ import { OpenDataDkWarningDialogComponent } from "./opendatadk/opendatadk-edit/o DatatargetDetailComponent, FiwareDetailComponent, FiwareEditComponent, + HttppushDetailTabsComponent, HttppushDetailComponent, HttppushEditComponent, OpendatadkComponent, diff --git a/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.html b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.html new file mode 100644 index 000000000..77bbde6cc --- /dev/null +++ b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.html @@ -0,0 +1,15 @@ + + + +
+ + + +
+ + diff --git a/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.scss b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.spec.ts b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.spec.ts new file mode 100644 index 000000000..ced4a7a5d --- /dev/null +++ b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HttppushDetailTabsComponent } from './httppush-detail-tabs.component'; + +describe('HttppushDetailTabsComponent', () => { + let component: HttppushDetailTabsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [HttppushDetailTabsComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(HttppushDetailTabsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.ts b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.ts new file mode 100644 index 000000000..7e4970317 --- /dev/null +++ b/src/app/applications/datatarget/httppush/httppush-detail-tabs/httppush-detail-tabs.component.ts @@ -0,0 +1,111 @@ +import { Location } from "@angular/common"; +import { HttpResponse } from "@angular/common/http"; +import { Component, OnDestroy } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { DatatargetDetail } from "@applications/datatarget/datatarget-detail/datatarget-detail"; +import { Datatarget } from "@applications/datatarget/datatarget.model"; +import { DatatargetService } from "@applications/datatarget/datatarget.service"; +import { TranslateService } from "@ngx-translate/core"; +import { DeleteDialogService } from "@shared/components/delete-dialog/delete-dialog.service"; +import { OrganizationAccessScope } from "@shared/enums/access-scopes"; +import { DataTargetType } from "@shared/enums/datatarget-type"; +import { BackButton } from "@shared/models/back-button.model"; +import { DropdownButton } from "@shared/models/dropdown-button.model"; +import { MeService } from "@shared/services/me.service"; +import { NavTab } from "@shared/types/nav-tabs.type"; +import { Subscription } from "rxjs"; + +@Component({ + selector: "app-httppush-detail-tabs", + templateUrl: "./httppush-detail-tabs.component.html", + styleUrl: "./httppush-detail-tabs.component.scss", +}) +export class HttppushDetailTabsComponent implements DatatargetDetail, OnDestroy { + dataTargetType = DataTargetType; + + navTabs: NavTab[] = [ + { + label: "APPLICATION.DETAILS", + link: "httppush-detail", + index: 0, + }, + { + label: "IOTDEVICE.HISTORY", + link: "datatarget-log", + index: 1, + }, + ]; + + datatarget: Datatarget; + dropdownButton: DropdownButton; + backButton: BackButton = { label: "", routerLink: undefined }; + canEdit: boolean; + + private subscriptions: Subscription[] = []; + private deleteDialogSubscription: Subscription; + + constructor( + route: ActivatedRoute, + router: Router, + translate: TranslateService, + meService: MeService, + private location: Location, + private datatargetService: DatatargetService, + public deleteDialogService: DeleteDialogService + ) { + // Load first tab if none was selected + const path = this.location.path(); + if (!this.navTabs.some(tab => path.includes(tab.link))) { + router.navigate([path, this.navTabs[0].link], { replaceUrl: true }); + } + // URL params + const paramMap = route.snapshot.paramMap; + const id: number = +paramMap.get("datatargetId"); + const appId: number = +paramMap.get("id"); + if (id) { + this.subscriptions.push(this.getDatatarget(id)); + this.dropdownButton = { + label: "", + editRouterLink: "../../datatarget-edit/" + id, + isErasable: true, + }; + } + + this.subscriptions.push( + translate.get(["NAV.MY-DATATARGET", "DATATARGET.SHOW-OPTIONS"]).subscribe(translations => { + this.backButton.label = translations["NAV.MY-DATATARGET"]; + this.dropdownButton.label = translations["DATATARGET.SHOW-OPTIONS"]; + }) + ); + + this.canEdit = meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite, undefined, appId); + } + + ngOnDestroy(): void { + this.subscriptions?.forEach(s => s?.unsubscribe()); + this.deleteDialogSubscription?.unsubscribe(); + } + + getDatatarget = (id: number) => + this.datatargetService.get(id).subscribe((dataTarget: Datatarget) => { + this.datatarget = dataTarget; + }); + + onDeleteDatatarget() { + this.deleteDialogSubscription?.unsubscribe(); + this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog().subscribe(response => { + // Do nothing if user cancels + if (!response) return; + this.subscriptions.push( + this.datatargetService.delete(this.datatarget.id).subscribe((deleteResponse: HttpResponse) => { + if (deleteResponse?.ok) { + this.location.back(); + } else { + // TODO: Show error / snackbar?? + console.log("Delete failed", deleteResponse); + } + }) + ); + }); + } +} diff --git a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.html b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.html index e298c88ee..d79dbb70b 100644 --- a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.html +++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.html @@ -1,101 +1,88 @@ -
- -
-
-
-
-

{{ "DATATARGET.DETAILS" | translate }}

- +
+
+
+
+

{{ "DATATARGET.DETAILS" | translate }}

+ + + +

+ {{ "DATATARGET.URL" | translate }}{{ datatarget.url }} +

+

+ {{ "DATATARGET.TIMEOUT" | translate }}{{ datatarget.timeout }} +

+
+

+ {{ "DATATARGET.TYPE" | translate }}{{ "DATATARGET." + datatarget.type + ".TYPE" | translate + }} +

+ - -

- {{ "DATATARGET.URL" | translate }}{{ datatarget.url }} -

-

- {{ "DATATARGET.TIMEOUT" | translate }}{{ datatarget.timeout }} -

-

- {{ "DATATARGET.TYPE" | translate }}{{ "DATATARGET." + datatarget.type + ".TYPE" | translate }} + {{ "DATATARGET.AUTHORIZATIONHEADER" | translate }}

- - -

- {{ "DATATARGET.AUTHORIZATIONHEADER" | translate }} -

- +
{{
                 datatarget.authorizationHeader
               }}
- -

{{ "DATATARGET.NO-AUTHORIZATIONHEADER" | translate }}

-
-
-
-
-
-
-

{{ "DATATARGET.OPENDATA-DK.TYPE" | translate }}

-
- -
- -

{{ "DATATARGET.NO-OPENDATA-DK" | translate }}

+ +

{{ "DATATARGET.NO-AUTHORIZATIONHEADER" | translate }}

+ +
+
+
+
+

{{ "DATATARGET.OPENDATA-DK.TYPE" | translate }}

+
+
+ +

{{ "DATATARGET.NO-OPENDATA-DK" | translate }}

+
+
-
-
-
-
-

{{ "DATATARGET.RELATIONS" | translate }}

-
-

{{ "DATATARGET.NO-RELATIONS" | translate }}

-
-
-
- \ No newline at end of file diff --git a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.ts b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.ts index 7c2f9f146..3fce32cff 100644 --- a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.ts +++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.ts @@ -1,97 +1,58 @@ -import { Component, OnDestroy, OnInit } from "@angular/core"; -import { Subscription } from "rxjs"; +import { Component, OnDestroy } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; -import { TranslateService } from "@ngx-translate/core"; import { PayloadDeviceDatatargetGetByDataTarget } from "@app/payload-decoder/payload-device-data.model"; import { PayloadDeviceDatatargetService } from "@app/payload-decoder/payload-device-datatarget.service"; -import { BackButton } from "@shared/models/back-button.model"; -import { DatatargetService } from "../../datatarget.service"; -import { Location } from "@angular/common"; -import { DeleteDialogService } from "@shared/components/delete-dialog/delete-dialog.service"; -import { Datatarget } from "../../datatarget.model"; -import { DropdownButton } from "@shared/models/dropdown-button.model"; -import { faArrowsAltH } from "@fortawesome/free-solid-svg-icons"; import { DatatargetDetail } from "@applications/datatarget/datatarget-detail/datatarget-detail"; -import { MeService } from "@shared/services/me.service"; +import { faArrowsAltH } from "@fortawesome/free-solid-svg-icons"; import { OrganizationAccessScope } from "@shared/enums/access-scopes"; import { DataTargetType } from "@shared/enums/datatarget-type"; +import { MeService } from "@shared/services/me.service"; +import { Subscription } from "rxjs"; +import { Datatarget } from "../../datatarget.model"; +import { DatatargetService } from "../../datatarget.service"; @Component({ selector: "app-httppush-detail", templateUrl: "./httppush-detail.component.html", styleUrls: ["./httppush-detail.component.scss"], }) -export class HttppushDetailComponent implements DatatargetDetail, OnInit, OnDestroy { +export class HttppushDetailComponent implements DatatargetDetail, OnDestroy { dataTargetType = DataTargetType; - - public datatargetSubscription: Subscription; - public datatarget: Datatarget; - public backButton: BackButton = { label: "", routerLink: undefined }; - public dataTargetRelations: PayloadDeviceDatatargetGetByDataTarget[]; - private deleteDialogSubscription: Subscription; - public dropdownButton: DropdownButton; arrowsAltH = faArrowsAltH; + + datatarget: Datatarget; + dataTargetRelations: PayloadDeviceDatatargetGetByDataTarget[]; canEdit: boolean; + private subscriptions: Subscription[]; + constructor( - private route: ActivatedRoute, - private deleteDialogService: DeleteDialogService, - private location: Location, - private datatargetRelationServicer: PayloadDeviceDatatargetService, + route: ActivatedRoute, + meService: MeService, private datatargetService: DatatargetService, - public translate: TranslateService, - private meService: MeService - ) {} + private datatargetRelationServicer: PayloadDeviceDatatargetService + ) { + const paramMap = route.parent.snapshot.paramMap; + const id: number = +paramMap.get("datatargetId"); + const appId: number = +paramMap.get("id"); - ngOnInit(): void { - const id: number = +this.route.snapshot.paramMap.get("datatargetId"); - const appId: number = +this.route.snapshot.paramMap.get("id"); if (id) { - this.getDatatarget(id); - this.getDatatargetRelations(id); - this.dropdownButton = { - label: "", - editRouterLink: "../../datatarget-edit/" + id, - isErasable: true, - }; + this.subscriptions = [this.getDatatarget(id), this.getDatatargetRelations(id)]; } - this.translate.get(["NAV.MY-DATATARGET", "DATATARGET.SHOW-OPTIONS"]).subscribe(translations => { - this.backButton.label = translations["NAV.MY-DATATARGET"]; - this.dropdownButton.label = translations["DATATARGET.SHOW-OPTIONS"]; - }); - this.canEdit = this.meService.hasAccessToTargetOrganization( - OrganizationAccessScope.ApplicationWrite, - undefined, - appId - ); + this.canEdit = meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite, undefined, appId); + } + + ngOnDestroy(): void { + this.subscriptions?.forEach(s => s?.unsubscribe()); } - getDatatarget(id: number) { + private getDatatarget = (id: number) => this.datatargetService.get(id).subscribe((dataTarget: Datatarget) => { this.datatarget = dataTarget; }); - } - onDeleteDatatarget() { - this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog().subscribe(response => { - if (response) { - this.datatargetService.delete(this.datatarget.id).subscribe(response => {}); - this.location.back(); - } else { - console.log(response); - } - }); - } - - getDatatargetRelations(id: number) { + private getDatatargetRelations = (id: number) => this.datatargetRelationServicer.getByDataTarget(id).subscribe(response => { this.dataTargetRelations = response.data; }); - } - - ngOnDestroy(): void { - if (this.deleteDialogSubscription) { - this.deleteDialogSubscription.unsubscribe(); - } - } } diff --git a/src/app/shared/components/top-bar/top-bar.component.html b/src/app/shared/components/top-bar/top-bar.component.html index 0d1fdf0b5..9bcc122f6 100644 --- a/src/app/shared/components/top-bar/top-bar.component.html +++ b/src/app/shared/components/top-bar/top-bar.component.html @@ -61,7 +61,7 @@

{{ title || staticTitle }}

> -