-
-
-
-
-
-
{{ 'DATATARGET.DETAILS' | translate }}
-
-
-
{{ 'DATATARGET.URL' | translate }}{{datatarget.url}}
-
{{ 'DATATARGET.TIMEOUT' | translate }}{{datatarget.timeout}}
-
{{ 'DATATARGET.TYPE' | translate }}{{datatarget.type | translate}}
-
-
{{ 'DATATARGET.AUTHORIZATIONHEADER' | translate }}
-
{{datatarget.authorizationHeader}}
-
- {{ 'DATATARGET.NO-AUTHORIZATIONHEADER' | translate }}
-
-
-
-
-
-
-
{{ 'DATATARGET.OPENDATA-DK' | translate }}
-
-
- {{ 'DATATARGET.NO-OPENDATA-DK' | translate }}
-
-
-
-
-
-
-
+
+
\ No newline at end of file
diff --git a/src/app/applications/datatarget/datatarget-detail/datatarget-detail.component.ts b/src/app/applications/datatarget/datatarget-detail/datatarget-detail.component.ts
index af38e9d9..17970ff3 100644
--- a/src/app/applications/datatarget/datatarget-detail/datatarget-detail.component.ts
+++ b/src/app/applications/datatarget/datatarget-detail/datatarget-detail.component.ts
@@ -1,16 +1,11 @@
-import { Component, OnDestroy, OnInit } from '@angular/core';
-import { Subscription } from 'rxjs';
+import { Component, ComponentFactoryResolver, OnDestroy, OnInit, Type, ViewChild } 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 { DataTargetType } from '@shared/enums/datatarget-type';
+import { DatatargetTypesService } from '../datatarget-types.service';
import { Datatarget } from '../datatarget.model';
-import { DropdownButton } from '@shared/models/dropdown-button.model';
-import { faArrowsAltH } from '@fortawesome/free-solid-svg-icons';
+import { DatatargetService } from '../datatarget.service';
+import { DatatargetDetail } from './datatarget-detail';
+import { DatatargetDetailTypeSelectorDirective } from './datatarget-detail-type-selector.directive';
@Component({
selector: 'app-datatarget-detail',
@@ -19,79 +14,46 @@ import { faArrowsAltH } from '@fortawesome/free-solid-svg-icons';
})
export class DatatargetDetailComponent implements OnInit, OnDestroy {
- public datatargetSubscription: Subscription;
+ @ViewChild(DatatargetDetailTypeSelectorDirective, {static: true}) adHost!: DatatargetDetailTypeSelectorDirective;
+
public datatarget: Datatarget;
- public backButton: BackButton = { label: '', routerLink: '/datatarget-list' };
- public dataTargetRelations: PayloadDeviceDatatargetGetByDataTarget[];
- private deleteDialogSubscription: Subscription;
- public dropdownButton: DropdownButton;
- arrowsAltH = faArrowsAltH;
- private applicationName: string;
-
- constructor(
- private route: ActivatedRoute,
- private deleteDialogService: DeleteDialogService,
- private location: Location,
- private datatargetRelationServicer: PayloadDeviceDatatargetService,
- private datatargetService: DatatargetService,
- public translate: TranslateService) { }
+ private datatargetType: DataTargetType;
- ngOnInit(): void {
- const id: number = +this.route.snapshot.paramMap.get('datatargetId');
- this.applicationName = this.route.snapshot.paramMap.get('name');
- if (id) {
- this.getDatatarget(id);
- this.getDatatargetRelations(id);
- this.dropdownButton = {
- label: '',
- editRouterLink: '../../datatarget-edit/' + id,
- isErasable: true,
- }
- }
- 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']
- });
- }
+ constructor(private componentFactoryResolver: ComponentFactoryResolver,
+ private datatargetService: DatatargetService,
+ private route: ActivatedRoute,
+ private datatargetTypesService: DatatargetTypesService
+ ) { }
- getDatatarget(id: number) {
- this.datatargetService.get(id)
- .subscribe((dataTarget: Datatarget) => {
- this.datatarget = dataTarget;
- this.setBackButton(this.datatarget.applicationId);
- });
- }
- private setBackButton(applicationId: number) {
- this.backButton.routerLink = ['applications', applicationId.toString()]
- }
+ loadComponent(componentType: Type
) {
- 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);
- }
- }
- );
- }
+ const viewContainerRef = this.adHost.viewContainerRef;
- getDatatargetRelations(id: number) {
- this.datatargetRelationServicer.getByDataTarget(id)
- .subscribe((response) => {
- this.dataTargetRelations = response.data;
- });
+ viewContainerRef.clear();
+ const factory = this.componentFactoryResolver.resolveComponentFactory(componentType);
+ viewContainerRef.createComponent(factory);
}
- ngOnDestroy(): void {
- if (this.deleteDialogSubscription) {
- this.deleteDialogSubscription.unsubscribe();
- }
+ ngOnInit(): void {
+
+ const id: number = +this.route.snapshot.paramMap.get('datatargetId');
+
+ this.datatargetService.get(id)
+ .subscribe((dataTarget: Datatarget) => {
+ this.datatarget = dataTarget;
+ this.datatargetType = dataTarget.type;
+
+ const component = this.datatargetTypesService.getDetailComponent(this.datatargetType);
+
+ this.loadComponent(component);
+
+ });
+
+
}
+ ngOnDestroy() {
+
+ }
}
diff --git a/src/app/applications/datatarget/datatarget-detail/datatarget-detail.ts b/src/app/applications/datatarget/datatarget-detail/datatarget-detail.ts
new file mode 100644
index 00000000..4d5f7bfb
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-detail/datatarget-detail.ts
@@ -0,0 +1,2 @@
+export interface DatatargetDetail {
+}
diff --git a/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.spec.ts b/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.spec.ts
new file mode 100644
index 00000000..1c28242d
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.spec.ts
@@ -0,0 +1,11 @@
+/* tslint:disable:no-unused-variable */
+
+import { ViewContainerRef } from '@angular/core';
+import { DatatargetEditTypeSelectorDirective } from './datatarget-edit-type-selector.directive';
+let viewContainerRef: ViewContainerRef;
+describe('Directive: DatatargetEditTypeSelector', () => {
+ it('should create an instance', () => {
+ const directive = new DatatargetEditTypeSelectorDirective(viewContainerRef);
+ expect(directive).toBeTruthy();
+ });
+});
diff --git a/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.ts b/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.ts
new file mode 100644
index 00000000..03b06ddb
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit-type-selector.directive.ts
@@ -0,0 +1,10 @@
+import { Directive, ViewContainerRef } from '@angular/core';
+
+@Directive({
+ selector: '[edit-component]'
+})
+export class DatatargetEditTypeSelectorDirective {
+
+ constructor(public viewContainerRef: ViewContainerRef) { }
+
+}
diff --git a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.html b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.html
index 4d4df069..bb9f14e1 100644
--- a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.html
+++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.html
@@ -1,139 +1,3 @@
-
-
-
-
\ No newline at end of file
+
+
+
\ No newline at end of file
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 fa1f81f9..432a5e2b 100644
--- a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts
+++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.component.ts
@@ -1,26 +1,11 @@
-import { Component, OnInit, Input, OnDestroy } from '@angular/core';
-import { TranslateService } from '@ngx-translate/core';
-import { ActivatedRoute, Router } from '@angular/router';
+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';
import { Datatarget } from '../datatarget.model';
-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 { DatatargetService } from '../datatarget.service';
-import { ApplicationService } from '@applications/application.service';
-import { PayloadDecoderService } from '@payload-decoder/payload-decoder.service';
-import { PayloadDeviceDatatargetService } from '@payload-decoder/payload-device-datatarget.service';
-import { SnackService } from '@shared/services/snack.service';
-import { MatDialog } from '@angular/material/dialog';
-import { HttpErrorResponse } from '@angular/common/http';
-import { PayloadDecoderMappedResponse } from '@payload-decoder/payload-decoder.model';
-import { DeleteDialogComponent } from '@shared/components/delete-dialog/delete-dialog.component';
-import { ErrorMessageService } from '@shared/error-message.service';
-import { OpendatadkDialogService } from '@shared/components/opendatadk-dialog/opendatadk-dialog.service';
-import { OpendatadkService } from '@shared/services/opendatadk.service';
-import { ScrollToTopService } from '@shared/services/scroll-to-top.service';
-import { OpenDataDkDataset } from '../opendatadk/opendatadk-dataset.model';
+import { DatatargetEdit } from './datatarget-edit';
+import { DatatargetEditTypeSelectorDirective } from './datatarget-edit-type-selector.directive';
@Component({
selector: 'app-datatarget-edit',
@@ -28,364 +13,57 @@ import { OpenDataDkDataset } from '../opendatadk/opendatadk-dataset.model';
styleUrls: ['./datatarget-edit.component.scss']
})
export class DatatargetEditComponent implements OnInit, OnDestroy {
- public multiPage = false;
- public title = '';
- public sectionTitle = '';
- public backButtonTitle = '';
- @Input() submitButton: string;
- public datatarget: Datatarget = new Datatarget();
- faTimesCircle = faTimesCircle;
- public datatargetSubscription: Subscription;
- public relationSubscription: Subscription;
- public applicationSubscription: Subscription;
- public payloadDecoderSubscription: Subscription;
- public errorMessages: any;
- public errorFields: string[];
- public formFailedSubmit = false;
- public datatargetid: number;
- private applicationId: number;
- private applicationName: string;
- public application: Application;
- public devices: IotDevice[];
- public payloadDecoders = [];
- private counter: number;
- private dataSetExcists = false;
- private isMailDialogAlreadyShown = false;
- payloadDeviceDatatarget: PayloadDeviceDatatarget[];
- newDynamic: any = {};
+ @ViewChild(DatatargetEditTypeSelectorDirective, {static: true}) adHost!: DatatargetEditTypeSelectorDirective;
- constructor(
- public translate: TranslateService,
- private route: ActivatedRoute,
- private router: Router,
- private datatargetService: DatatargetService,
- private applicationService: ApplicationService,
- private payloadDecoderService: PayloadDecoderService,
- private payloadDeviceDataTargetService: PayloadDeviceDatatargetService,
- private saveSnackService: SnackService,
- private dialog: MatDialog,
- private errorMessageService: ErrorMessageService,
- private opendatadkService: OpendatadkService,
- private opendatadkDialogService: OpendatadkDialogService,
- private scrollToTopService: ScrollToTopService,
- ) {
- translate.use('da');
- }
-
- ngOnInit() {
- this.translate
- .get([
- 'FORM.CREATE-NEW-DATATARGET',
- 'FORM.EDIT-DATATARGET',
- 'DATATARGET.SAVE',
- 'NAV.DATATARGET',
- ])
- .subscribe((translations) => {
- const datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
- if (datatargetid !== 0) {
- this.title = translations['FORM.EDIT-DATATARGET'];
- } else {
- this.title = translations['FORM.CREATE-NEW-DATATARGET'];
- }
- this.submitButton = translations['DATATARGET.SAVE'];
- this.backButtonTitle = translations['NAV.DATATARGET'];
- });
+ public datatarget: Datatarget;
+ private datatargetType: DataTargetType;
- this.datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
- this.applicationId = +this.route.snapshot.paramMap.get('id');
- this.applicationName = this.route.snapshot.paramMap.get('name');
- if (this.datatargetid !== 0) {
- this.getDatatarget(this.datatargetid);
- this.getPayloadDeviceDatatarget(this.datatargetid);
- }
- if (this.applicationId !== 0) {
- this.getDevices();
- }
- this.getPayloadDecoders();
- this.setDataSetExcists();
- }
+ constructor(private componentFactoryResolver: ComponentFactoryResolver,
+ private datatargetService: DatatargetService,
+ private route: ActivatedRoute,
+ private datatargetTypesService: DatatargetTypesService
+ ) { }
- addRow() {
- if (!this.payloadDeviceDatatarget) {
- this.payloadDeviceDatatarget = [];
- }
- this.payloadDeviceDatatarget.push({ id: null, iotDeviceIds: [], payloadDecoderId: null, dataTargetId: this.datatargetid });
- }
- private deleteRow(index) {
- if (this.payloadDeviceDatatarget.length === 0) {
- } else if (this.payloadDeviceDatatarget[index]?.id === null) {
- this.payloadDeviceDatatarget.splice(index, 1);
- } else {
- this.payloadDeviceDataTargetService.delete(this.payloadDeviceDatatarget[index].id)
- .subscribe((response) => {
- this.payloadDeviceDatatarget.splice(index, 1);
- });
- }
+ loadComponent(componentType: Type) {
+ const viewContainerRef = this.adHost.viewContainerRef;
+ viewContainerRef.clear();
+ const factory = this.componentFactoryResolver.resolveComponentFactory(componentType);
+ viewContainerRef.createComponent(factory);
}
- openDeleteDialog(index) {
- const dialog = this.dialog.open(DeleteDialogComponent, {
- data: {
- showAccept: true,
- showCancel: true,
- message: 'Er du sikker på at du vil slette?'
- }
- });
-
- dialog.afterClosed().subscribe((result) => {
- if (result === true) {
- this.deleteRow(index);
- }
- });
- }
-
- onSubmit(): void {
- this.counter = 0;
- if (this.datatargetid) {
- this.updateDatatarget();
- this.addPayloadDeviceDatatarget();
- } else {
- this.createDatatarget();
- }
- }
-
- public compare(o1: any, o2: any): boolean {
- return o1 === o2;
- }
+ ngOnInit(): void {
- updateDatatarget() {
- this.resetErrors();
- this.counter = 1 + (this.payloadDeviceDatatarget?.length ? this.payloadDeviceDatatarget?.length : 0);
- this.datatargetService.update(this.datatarget)
- .subscribe(
- (response: Datatarget) => {
- this.datatarget = response;
- if (this.datatarget.openDataDkDataset != null) {
- this.datatarget.openDataDkDataset.acceptTerms = true;
- }
- this.shouldShowMailDialog().subscribe(
- (response) => {
- this.countToRedirect();
- }
- );
- },
- (error: HttpErrorResponse) => {
- this.checkDataTargetModelOpendatadkdatasaet();
- this.handleError(error);
- this.formFailedSubmit = true;
- }
- );
- }
+ const id: number = +this.route.snapshot.paramMap.get('datatargetId');
- addPayloadDeviceDatatarget() {
- this.payloadDeviceDatatarget.map(
- pdd => {
- if (pdd.payloadDecoderId === 0) {
- pdd.payloadDecoderId = null;
- }
- }
- );
- this.payloadDeviceDatatarget.forEach((relation) => {
- if (relation.id) {
- this.payloadDeviceDataTargetService.put(relation).subscribe(
- (response) => {
- this.countToRedirect();
- },
- (error) => {
- this.handleError(error);
- }
- );
+ 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 {
- this.payloadDeviceDataTargetService.post(relation).subscribe(
- (res: any) => {
- this.countToRedirect();
- },
- (error) => {
- this.handleError(error);
- }
- );
- }
- });
- }
-
- countToRedirect() {
- this.counter -= 1;
- if (this.counter <= 0 && !this.formFailedSubmit) {
- this.showSavedSnack();
- this.routeToDatatargets();
- }
- }
-
- getPayloadDeviceDatatarget(id: number) {
- this.relationSubscription = this.payloadDeviceDataTargetService
- .getByDataTarget(id)
- .subscribe((response: PayloadDeviceDatatargetGetByDataTargetResponse) => {
- this.mapToDatatargetDevicePayload(response);
- });
- }
-
- createDatatarget() {
- this.resetErrors();
- this.datatarget.applicationId = this.applicationId;
- this.datatargetService.create(this.datatarget)
- .subscribe((response: Datatarget) => {
- this.datatargetid = response.id;
- this.datatarget = response;
- if (this.datatarget.openDataDkDataset != null) {
- this.datatarget.openDataDkDataset.acceptTerms = true;
+ 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);
}
- this.showSavedSnack();
- this.routeToDatatargets();
- },
- (error: HttpErrorResponse) => {
- this.checkDataTargetModelOpendatadkdatasaet();
- this.handleError(error);
- this.formFailedSubmit = true;
- });
-
- }
-
- private resetErrors() {
- this.errorFields = [];
- this.errorMessages = undefined;
- this.formFailedSubmit = false;
- }
-
- checkDataTargetModelOpendatadkdatasaet() {
- if (!this.datatarget.openDataDkDataset) {
- this.datatarget.openDataDkDataset = new OpenDataDkDataset();
- }
- }
-
- getDevices(): void {
- 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);
- }
-
- public deSelectAllDevices(index: number) {
- this.payloadDeviceDatatarget[index].iotDeviceIds = [];
- }
-
- getPayloadDecoders() {
- this.payloadDecoderSubscription = this.payloadDecoderService.getMultiple(1000, 0, 'id', 'ASC')
- .subscribe((response: PayloadDecoderMappedResponse) => {
- this.payloadDecoders = response.data;
- });
- }
-
- handleError(error: HttpErrorResponse) {
- const errors = this.errorMessageService.handleErrorMessageWithFields(error);
- this.errorFields = errors.errorFields;
- this.errorMessages = errors.errorMessages;
- this.scrollToTopService.scrollToTop();
- }
-
- routeToDatatargets(): void {
- this.router.navigate(['applications',this.applicationId.toString()])
- }
-
- onCoordinateKey(event: any) {
- if (event.target.value.length > event.target.maxLength) {
- event.target.value = event.target.value.slice(
- 0,
- event.target.maxLength
- );
- }
- }
-
- getDatatarget(id: number) {
- this.datatargetSubscription = this.datatargetService
- .get(id)
- .subscribe((response: Datatarget) => {
- this.datatarget = response;
- });
- }
-
- showSavedSnack() {
- this.saveSnackService.showSavedSnack();
- }
-
- private setDataSetExcists() {
- this.opendatadkService.get().subscribe(
- (response) => {
- this.dataSetExcists = response.dataset.length === 0 ? false : true;
}
- );
- }
- private shouldShowMailDialog(): Observable {
- return new Observable(
- (observer) => {
- if (!this.dataSetExcists && this.datatarget.setToOpendataDk && !this.isMailDialogAlreadyShown) {
- this.isMailDialogAlreadyShown = true;
- this.opendatadkDialogService.showDialog().subscribe(
- response => {
- if (response) {
- this.showMailClient();
- }
- observer.next(response);
- }
- );
- } else {
- observer.next(true);
- }
- }
- )
- }
- private showMailClient() {
- if (!this.datatarget.openDataDkDataset.url) {
- this.datatarget.openDataDkDataset.url = this.datatargetService.getOpendataSharingApiUrl()
- }
- window.location.href = 'mailto:FG2V@kk.dk?subject=Oprettelse%20af%20datas%C3%A6t%20i%20OpenDataDK&body=K%C3%A6re%20Frans%0D%0A%0D%0AHermed%20fremsendes%20linket%20til%20DCAT%20kataloget%20%2C%20du%20bedes%20registrere%20p%C3%A5%20Open%20Data%20DK%20platformen.%0D%0A%0D%0ALink%3A ' + this.datatarget.openDataDkDataset.url;
}
- disableSaveButton(): boolean {
- let disable = true;
- if (!this.datatarget.setToOpendataDk) {
- disable = false;
- } else if (this.datatarget.openDataDkDataset?.acceptTerms) {
- disable = false;
- } else {
- disable = true;
- }
- return disable;
+ 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(): void {
- if (this.relationSubscription) {
- this.relationSubscription.unsubscribe();
- }
- if (this.applicationSubscription) {
- this.applicationSubscription.unsubscribe();
- }
- if (this.datatargetSubscription) {
- this.datatargetSubscription.unsubscribe();
- }
- if (this.payloadDecoderSubscription) {
- this.payloadDecoderSubscription.unsubscribe();
- }
- }
+ ngOnDestroy() {
- 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
- });
- }
- );
- }
+ }
}
diff --git a/src/app/applications/datatarget/datatarget-edit/datatarget-edit.ts b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.ts
new file mode 100644
index 00000000..16def301
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-edit/datatarget-edit.ts
@@ -0,0 +1,2 @@
+export interface DatatargetEdit {
+}
diff --git a/src/app/applications/datatarget/datatarget-new/datatarget-new.component.html b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.html
new file mode 100644
index 00000000..6d654898
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{dataTargetType.name}}
+
+
+ {{dataTargetType.provider}}
+
+
+
+ {{ dataTargetType.description }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/applications/datatarget/datatarget-new/datatarget-new.component.scss b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.scss
new file mode 100644
index 00000000..71485bcb
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.scss
@@ -0,0 +1,44 @@
+.data-component {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin-left: 10px;
+}
+
+.mat-card{
+ display:flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ width: 300px;
+ min-width: 300px;
+ max-width: 400px;
+ height: 320px;
+ margin: 10px;
+}
+
+.mat-card-header {
+ flex-shrink: 1;
+
+}
+
+.mat-card-content{
+ flex-grow: 1;
+ overflow: auto;
+ margin-left: 10px;
+}
+
+
+mat-card img{
+ object-fit: contain; /*this makes the image in src fit to the size specified below*/
+ object-position: left;
+ width: 50%; /* Here you can use wherever you want to specify the width and also the height of the
*/
+ height: 20px;
+ margin-left: 3px;
+ margin-top: 3px;
+ margin-bottom: 3px;
+}
+
+.img-placeholder{
+ height: 26px;
+ clear: both;
+}
diff --git a/src/app/applications/datatarget/datatarget-new/datatarget-new.component.spec.ts b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.spec.ts
new file mode 100644
index 00000000..4f1f6508
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.spec.ts
@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { DatatargetNewComponent } from './datatarget-new.component';
+
+describe('DatatargetNewComponent', () => {
+ let component: DatatargetNewComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatargetNewComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatargetNewComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/applications/datatarget/datatarget-new/datatarget-new.component.ts b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.ts
new file mode 100644
index 00000000..d3f90b12
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-new/datatarget-new.component.ts
@@ -0,0 +1,63 @@
+import { Component, OnInit } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { DatatargetTypeDescriptor } from '../datatarget.model';
+import { DatatargetTypesService } from '../datatarget-types.service';
+
+
+
+@Component({
+ selector: 'app-datatarget-new',
+ templateUrl: './datatarget-new.component.html',
+ styleUrls: ['./datatarget-new.component.scss']
+})
+export class DatatargetNewComponent implements OnInit {
+
+ public title = '';
+ public sectionTitle = '';
+ public backButtonTitle = '';
+ public submitButton = '';
+ public avaiableDataTargetTypes : DatatargetTypeDescriptor[];
+
+ constructor(
+ public translate: TranslateService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private dataTargetTypesService: DatatargetTypesService
+ ) {
+ translate.use('da');
+ }
+
+ ngOnInit() {
+
+ this.translate
+ .get([
+ 'FORM.CREATE-NEW-DATATARGET',
+ 'FORM.EDIT-DATATARGET',
+ 'DATATARGET.SAVE',
+ 'NAV.DATATARGET',
+ ])
+ .subscribe((translations) => {
+ const datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
+ if (datatargetid !== 0) {
+ this.title = translations['FORM.EDIT-DATATARGET'];
+ } else {
+ this.title = translations['FORM.CREATE-NEW-DATATARGET'];
+ }
+ this.submitButton = translations['DATATARGET.SAVE'];
+ this.backButtonTitle = translations['NAV.DATATARGET'];
+ });
+
+ this.avaiableDataTargetTypes = this.dataTargetTypesService.getAvailableDataTargetTypes();
+
+ }
+
+ public createNewOf(typeDescriptor: DatatargetTypeDescriptor)
+ {
+ this.router.navigate(['../datatarget-edit', {datatargetType: typeDescriptor.type}], {relativeTo:this. route});
+ }
+ public showReadMe(typeDescriptor: DatatargetTypeDescriptor)
+ {
+ window.open(typeDescriptor.readMoreUrl, "_blank");
+ }
+}
diff --git a/src/app/applications/datatarget/datatarget-response.model.ts b/src/app/applications/datatarget/datatarget-response.model.ts
index 1d6b809d..fcb40286 100644
--- a/src/app/applications/datatarget/datatarget-response.model.ts
+++ b/src/app/applications/datatarget/datatarget-response.model.ts
@@ -9,6 +9,8 @@ export class DatatargetResponse {
timeout: number;
type: DataTargetType;
url: string;
+ tenant: string;
+ context: string;
authorizationHeader: string;
openDataDkDataset: OpenDataDkDataset;
createdAt: string;
diff --git a/src/app/applications/datatarget/datatarget-table/datatarget-table.component.html b/src/app/applications/datatarget/datatarget-table/datatarget-table.component.html
index c839d784..d2b4aca8 100644
--- a/src/app/applications/datatarget/datatarget-table/datatarget-table.component.html
+++ b/src/app/applications/datatarget/datatarget-table/datatarget-table.component.html
@@ -21,7 +21,7 @@
{{ 'DATATARGET-TABLE.TYPE' | translate }}
- {{element.type | translate}} |
+ {{'DATATARGET.' + element.type | translate}}
diff --git a/src/app/applications/datatarget/datatarget-table/datatarget-table.component.ts b/src/app/applications/datatarget/datatarget-table/datatarget-table.component.ts
index fa4eb35d..65c04906 100644
--- a/src/app/applications/datatarget/datatarget-table/datatarget-table.component.ts
+++ b/src/app/applications/datatarget/datatarget-table/datatarget-table.component.ts
@@ -46,8 +46,7 @@ export class DatatargetTableComponent implements OnInit, AfterViewInit, OnDestro
}
ngOnInit(): void {
- this.applicationId = +Number(this.route.parent.snapshot.paramMap.get('id'));
- console.log(this.applicationId);
+ this.applicationId = +Number(this.route.parent.snapshot.paramMap.get('id'));
this.getDatatarget();
this.canEdit = this.meService.canWriteInTargetOrganization()
}
diff --git a/src/app/applications/datatarget/datatarget-types.service.spec.ts b/src/app/applications/datatarget/datatarget-types.service.spec.ts
new file mode 100644
index 00000000..d5ef25d5
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-types.service.spec.ts
@@ -0,0 +1,16 @@
+/* tslint:disable:no-unused-variable */
+
+import { TestBed, async, inject } from '@angular/core/testing';
+import { DatatargetTypesService } from './datatarget-types.service';
+
+describe('Service: DatatargetTypesService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [DatatargetTypesService]
+ });
+ });
+
+ it('should ...', inject([DatatargetTypesService], (service: DatatargetTypesService) => {
+ expect(service).toBeTruthy();
+ }));
+});
diff --git a/src/app/applications/datatarget/datatarget-types.service.ts b/src/app/applications/datatarget/datatarget-types.service.ts
new file mode 100644
index 00000000..581788cf
--- /dev/null
+++ b/src/app/applications/datatarget/datatarget-types.service.ts
@@ -0,0 +1,84 @@
+import { Injectable, Type } from '@angular/core';
+import { DataTargetType } from '@shared/enums/datatarget-type';
+import { DatatargetDetail } from './datatarget-detail/datatarget-detail';
+import { DatatargetEdit } from './datatarget-edit/datatarget-edit';
+import { DatatargetTypeDescriptor } from './datatarget.model';
+import { FiwareDetailComponent } from './fiware/fiware-detail/fiware-detail.component';
+import { FiwareEditComponent } from './fiware/fiware-edit/fiware-edit.component';
+import { HttppushDetailComponent } from './httppush/httppush-detail/httppush-detail.component';
+import { HttppushEditComponent } from './httppush/httppush-edit/httppush-edit.component';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class DatatargetTypesService {
+
+constructor() { }
+
+ getAvailableDataTargetTypes() : DatatargetTypeDescriptor[]
+ {
+ return [
+ { name: 'Generisk HTTP Push',
+ type: DataTargetType.HTTPPUSH,
+ icon: null,
+ description: 'Send data med HTTP POST requests til et HTTP URL endpoint',
+ readMoreUrl: '',
+ provider: 'OS2'
+
+ },
+ { name: 'Open Data DK',
+ type: DataTargetType.OPENDATADK,
+ icon: '/assets/images/logo_opendatadk.svg',
+ description: 'Offentliggør datasæt i Open Data DK\'s åbne dataportal.',
+ readMoreUrl: 'https://www.opendata.dk/',
+ provider: 'OS2'
+
+ },
+ { name: 'FIWARE connection',
+ type: DataTargetType.FIWARE,
+ icon: '/assets/images/logo_FIWARE.png',
+ description: 'En integration til FIWARE Context Broker' ,
+ readMoreUrl: 'https://www.kmd.dk',
+ provider: 'KMD A/S'
+ }
+ ]
+ }
+
+ getDetailComponent(dataTargetType: DataTargetType): Type
+ {
+ if (dataTargetType === DataTargetType.HTTPPUSH)
+ {
+ return HttppushDetailComponent;
+ }
+
+ if (dataTargetType === DataTargetType.OPENDATADK)
+ {
+ return HttppushDetailComponent;
+ }
+
+ if (dataTargetType === DataTargetType.FIWARE)
+ {
+ return FiwareDetailComponent;
+ }
+ }
+
+ getEditComponent(dataTargetType: DataTargetType): Type
+ {
+ if (dataTargetType === DataTargetType.HTTPPUSH)
+ {
+ return HttppushEditComponent;
+ }
+
+ if (dataTargetType === DataTargetType.OPENDATADK)
+ {
+ return HttppushEditComponent;
+ }
+
+ if (dataTargetType === DataTargetType.FIWARE)
+ {
+ return FiwareEditComponent;
+ }
+ }
+
+}
+
diff --git a/src/app/applications/datatarget/datatarget.model.ts b/src/app/applications/datatarget/datatarget.model.ts
index 03fba64b..12e846c9 100644
--- a/src/app/applications/datatarget/datatarget.model.ts
+++ b/src/app/applications/datatarget/datatarget.model.ts
@@ -7,6 +7,8 @@ export class Datatarget {
applicationId: number;
type: DataTargetType = DataTargetType.HTTPPUSH;
url: string;
+ tenant: string;
+ context: string;
//default 30 sec
timeout: number = 30000;
authorizationHeader: string;
@@ -24,4 +26,14 @@ export class DatatargetData {
data: Datatarget[];
ok?: boolean;
count?: number;
+}
+
+export class DatatargetTypeDescriptor
+{
+ name: string;
+ type: DataTargetType;
+ icon: string;
+ description: string;
+ readMoreUrl: string;
+ provider: string;
}
\ No newline at end of file
diff --git a/src/app/applications/datatarget/datatarget.module.ts b/src/app/applications/datatarget/datatarget.module.ts
index 46be0a33..ac65cbea 100644
--- a/src/app/applications/datatarget/datatarget.module.ts
+++ b/src/app/applications/datatarget/datatarget.module.ts
@@ -14,15 +14,29 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
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 { 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';
+import { DatatargetDetailTypeSelectorDirective } from './datatarget-detail/datatarget-detail-type-selector.directive';
+import { DatatargetEditTypeSelectorDirective } from './datatarget-edit/datatarget-edit-type-selector.directive';
@NgModule({
- declarations: [
+ declarations: [
DatatargetTableComponent,
DatatargetEditComponent,
+ DatatargetNewComponent,
DatatargetDetailComponent,
+ FiwareDetailComponent,
+ FiwareEditComponent,
+ HttppushDetailComponent,
+ HttppushEditComponent,
OpendatadkComponent,
OpendatadkEditComponent,
- OpendatadkDetailComponent],
+ OpendatadkDetailComponent,
+ DatatargetDetailTypeSelectorDirective,
+ DatatargetEditTypeSelectorDirective],
imports: [
CommonModule,
RouterModule,
@@ -38,7 +52,12 @@ import { PipesModule } from '@shared/pipes/pipes.module';
exports: [
DatatargetTableComponent,
DatatargetEditComponent,
- DatatargetDetailComponent,
+ DatatargetNewComponent,
+ DatatargetDetailComponent,
+ FiwareDetailComponent,
+ FiwareEditComponent,
+ HttppushDetailComponent,
+ HttppushEditComponent,
NGMaterialModule
]
})
diff --git a/src/app/applications/datatarget/datatarget.service.ts b/src/app/applications/datatarget/datatarget.service.ts
index 74e3688c..6647ed30 100644
--- a/src/app/applications/datatarget/datatarget.service.ts
+++ b/src/app/applications/datatarget/datatarget.service.ts
@@ -90,6 +90,8 @@ export class DatatargetService {
timeout: dataTargetResponse.timeout,
type: dataTargetResponse.type,
url: dataTargetResponse.url,
+ tenant: dataTargetResponse.tenant,
+ context: dataTargetResponse.context,
authorizationHeader: dataTargetResponse.authorizationHeader,
applicationId: dataTargetResponse.application.id,
setToOpendataDk: dataTargetResponse?.openDataDkDataset ? true : false,
diff --git a/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.html b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.html
new file mode 100644
index 00000000..8e895d9c
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
{{ 'DATATARGET.DETAILS' | translate }}
+
+
+
Context Broker{{datatarget.url}}
+
{{ 'DATATARGET.TIMEOUT' | translate }}{{datatarget.timeout}}
+
{{ 'DATATARGET.TYPE' | translate }}{{'DATATARGET.' + datatarget.type | translate}}
+
+
+
{{ 'DATATARGET.TENANT' | translate }}
+
{{datatarget.tenant}}
+
+ {{ 'DATATARGET.NO-TENANT' | translate }}
+
+
+
{{ 'DATATARGET.CONTEXT' | translate }}
+
{{datatarget.context}}
+
+ {{ 'DATATARGET.NO-CONTEXT' | translate }}
+
+
+
{{ 'DATATARGET.AUTHORIZATIONHEADER' | translate }}
+
{{datatarget.authorizationHeader}}
+
+ {{ 'DATATARGET.NO-AUTHORIZATIONHEADER' | translate }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.scss b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.spec.ts b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.spec.ts
new file mode 100644
index 00000000..7f5198d9
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.spec.ts
@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { FiwareDetailComponent } from './fiware-detail.component';
+
+describe('FiwareDetailComponent', () => {
+ let component: FiwareDetailComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FiwareDetailComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FiwareDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.ts b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.ts
new file mode 100644
index 00000000..d56148e6
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-detail/fiware-detail.component.ts
@@ -0,0 +1,98 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs';
+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';
+
+
+@Component({
+ selector: 'app-fiware-detail',
+ templateUrl: './fiware-detail.component.html',
+ styleUrls: ['./fiware-detail.component.scss']
+})
+export class FiwareDetailComponent implements DatatargetDetail, OnInit, OnDestroy {
+
+ public datatargetSubscription: Subscription;
+ public datatarget: Datatarget;
+ public backButton: BackButton = { label: '', routerLink: '' };
+ public dataTargetRelations: PayloadDeviceDatatargetGetByDataTarget[];
+ private deleteDialogSubscription: Subscription;
+ public dropdownButton: DropdownButton;
+ arrowsAltH = faArrowsAltH;
+
+ constructor(
+ private route: ActivatedRoute,
+ private deleteDialogService: DeleteDialogService,
+ private location: Location,
+ private datatargetRelationServicer: PayloadDeviceDatatargetService,
+ private datatargetService: DatatargetService,
+ public translate: TranslateService) { }
+
+ ngOnInit(): void {
+ const id: number = +this.route.snapshot.paramMap.get('datatargetId');
+
+ if (id) {
+ this.getDatatarget(id);
+ this.getDatatargetRelations(id);
+ this.dropdownButton = {
+ label: '',
+ editRouterLink: '../../datatarget-edit/' + id,
+ isErasable: true,
+ };
+ }
+ 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'];
+ });
+ }
+
+ getDatatarget(id: number) {
+ this.datatargetService.get(id)
+ .subscribe((dataTarget: Datatarget) => {
+ this.datatarget = dataTarget;
+ this.setBackButton(this.datatarget.applicationId);
+ });
+ }
+
+ private setBackButton(applicationId: number) {
+ this.backButton.routerLink = ['applications', applicationId.toString() ];
+ }
+
+ 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) {
+ this.datatargetRelationServicer.getByDataTarget(id)
+ .subscribe((response) => {
+ this.dataTargetRelations = response.data;
+ });
+ }
+
+ ngOnDestroy(): void {
+ if (this.deleteDialogSubscription) {
+ this.deleteDialogSubscription.unsubscribe();
+ }
+ }
+
+}
diff --git a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.html b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.html
new file mode 100644
index 00000000..02ec7529
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.html
@@ -0,0 +1,167 @@
+
+
+
+
diff --git a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.scss b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.scss
new file mode 100644
index 00000000..bb96f657
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.scss
@@ -0,0 +1,4 @@
+.form-info-icon {
+ margin-left: 5px;
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.spec.ts b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.spec.ts
new file mode 100644
index 00000000..6a58e7f6
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.spec.ts
@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { FiwareEditComponent } from './fiware-edit.component';
+
+describe('FiwareEditComponent', () => {
+ let component: FiwareEditComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ FiwareEditComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FiwareEditComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
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
new file mode 100644
index 00000000..b52a823b
--- /dev/null
+++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts
@@ -0,0 +1,336 @@
+import { Component, OnInit, Input, OnDestroy } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { Datatarget } from '../../datatarget.model';
+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 { DatatargetService } from '../../datatarget.service';
+import { ApplicationService } from '@applications/application.service';
+import { PayloadDecoderService } from '@payload-decoder/payload-decoder.service';
+import { PayloadDeviceDatatargetService } from '@payload-decoder/payload-device-datatarget.service';
+import { SnackService } from '@shared/services/snack.service';
+import { MatDialog } from '@angular/material/dialog';
+import { HttpErrorResponse } from '@angular/common/http';
+import { PayloadDecoderMappedResponse } from '@payload-decoder/payload-decoder.model';
+import { DeleteDialogComponent } from '@shared/components/delete-dialog/delete-dialog.component';
+import { ErrorMessageService } from '@shared/error-message.service';
+import { ScrollToTopService } from '@shared/services/scroll-to-top.service';
+import { DataTargetType } from '@shared/enums/datatarget-type';
+import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
+import { DatatargetEdit } from '@applications/datatarget/datatarget-edit/datatarget-edit';
+
+@Component({
+ selector: 'app-fiware-edit',
+ templateUrl: './fiware-edit.component.html',
+ styleUrls: ['./fiware-edit.component.scss']
+})
+export class FiwareEditComponent implements DatatargetEdit, OnInit, OnDestroy {
+
+
+ public multiPage = false;
+ public title = '';
+ public sectionTitle = '';
+ public backButtonTitle = '';
+ @Input() submitButton: string;
+ public datatarget: Datatarget = new Datatarget();
+ faTimesCircle = faTimesCircle;
+ public datatargetSubscription: Subscription;
+ public relationSubscription: Subscription;
+ public applicationSubscription: Subscription;
+ public payloadDecoderSubscription: Subscription;
+ public errorMessages: any;
+ public errorFields: string[];
+ public formFailedSubmit = false;
+ public datatargetid: number;
+ private applicationId: number;
+ public application: Application;
+ public devices: IotDevice[];
+ public payloadDecoders = [];
+ private counter: number;
+ payloadDeviceDatatarget: PayloadDeviceDatatarget[];
+ newDynamic: any = {};
+ faQuestionCircle = faQuestionCircle;
+
+
+ constructor(
+ public translate: TranslateService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private datatargetService: DatatargetService,
+ private applicationService: ApplicationService,
+ private payloadDecoderService: PayloadDecoderService,
+ private payloadDeviceDataTargetService: PayloadDeviceDatatargetService,
+ private snackService: SnackService,
+ private dialog: MatDialog,
+ private errorMessageService: ErrorMessageService,
+ private scrollToTopService: ScrollToTopService,
+ ) {
+ translate.use('da');
+ }
+
+
+
+ ngOnInit() {
+ this.translate
+ .get([
+ 'FORM.CREATE-NEW-DATATARGET',
+ 'FORM.EDIT-DATATARGET',
+ 'DATATARGET.SAVE',
+ 'NAV.DATATARGET',
+ ])
+ .subscribe((translations) => {
+ const datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
+ if (datatargetid !== 0) {
+ this.title = translations['FORM.EDIT-DATATARGET'];
+ } else {
+ this.title = translations['FORM.CREATE-NEW-DATATARGET'];
+ }
+ this.submitButton = translations['DATATARGET.SAVE'];
+ this.backButtonTitle = translations['NAV.DATATARGET'];
+ });
+
+ this.datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
+ this.applicationId = +this.route.snapshot.paramMap.get('id');
+
+ this.datatarget.type = DataTargetType.FIWARE;
+
+ if (this.datatargetid !== 0) {
+ this.getDatatarget(this.datatargetid);
+ this.getPayloadDeviceDatatarget(this.datatargetid);
+ }
+ if (this.applicationId !== 0) {
+ this.getDevices();
+ }
+ this.getPayloadDecoders();
+
+ }
+
+
+ addRow() {
+ if (!this.payloadDeviceDatatarget) {
+ this.payloadDeviceDatatarget = [];
+ }
+ this.payloadDeviceDatatarget.push({ id: null, iotDeviceIds: [], payloadDecoderId: null, dataTargetId: this.datatargetid });
+ }
+
+ private deleteRow(index) {
+ if (this.payloadDeviceDatatarget.length === 0) {
+ } else if (this.payloadDeviceDatatarget[index]?.id === null) {
+ this.payloadDeviceDatatarget.splice(index, 1);
+ } else {
+ this.payloadDeviceDataTargetService.delete(this.payloadDeviceDatatarget[index].id)
+ .subscribe((response) => {
+ this.payloadDeviceDatatarget.splice(index, 1);
+ });
+ }
+ }
+
+ openDeleteDialog(index) {
+ const dialog = this.dialog.open(DeleteDialogComponent, {
+ data: {
+ showAccept: true,
+ showCancel: true,
+ message: 'Er du sikker på at du vil slette?'
+ }
+ });
+
+ dialog.afterClosed().subscribe((result) => {
+ if (result === true) {
+ this.deleteRow(index);
+ }
+ });
+ }
+
+ onSubmit(): void {
+ this.counter = 0;
+ if (this.datatargetid) {
+ this.updateDatatarget();
+ this.addPayloadDeviceDatatarget();
+ } else {
+ this.createDatatarget();
+ }
+ }
+
+ public compare(o1: any, o2: any): boolean {
+ return o1 === o2;
+ }
+
+ 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;
+ }
+ );
+ }
+
+ addPayloadDeviceDatatarget() {
+ this.payloadDeviceDatatarget.map(
+ pdd => {
+ if (pdd.payloadDecoderId === 0) {
+ pdd.payloadDecoderId = null;
+ }
+ }
+ );
+ this.payloadDeviceDatatarget.forEach((relation) => {
+ if (relation.id) {
+ this.payloadDeviceDataTargetService.put(relation).subscribe(
+ (response) => {
+ this.countToRedirect();
+ },
+ (error) => {
+ this.handleError(error);
+ }
+ );
+ } else {
+ this.payloadDeviceDataTargetService.post(relation).subscribe(
+ (res: any) => {
+ this.countToRedirect();
+ },
+ (error) => {
+ this.handleError(error);
+ }
+ );
+ }
+ });
+ }
+
+ countToRedirect() {
+ this.counter -= 1;
+ if (this.counter <= 0 && !this.formFailedSubmit) {
+ this.showSavedSnack();
+ this.routeToDatatargets();
+ }
+ }
+
+ getPayloadDeviceDatatarget(id: number) {
+ this.relationSubscription = this.payloadDeviceDataTargetService
+ .getByDataTarget(id)
+ .subscribe((response: PayloadDeviceDatatargetGetByDataTargetResponse) => {
+ this.mapToDatatargetDevicePayload(response);
+ });
+ }
+
+ createDatatarget() {
+ this.resetErrors();
+ this.datatarget.applicationId = this.applicationId;
+ 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;
+ });
+
+ }
+
+ private resetErrors() {
+ this.errorFields = [];
+ this.errorMessages = undefined;
+ this.formFailedSubmit = false;
+ }
+
+
+
+ getDevices(): void {
+ 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);
+ }
+
+ public deSelectAllDevices(index: number) {
+ this.payloadDeviceDatatarget[index].iotDeviceIds = [];
+ }
+
+ getPayloadDecoders() {
+ this.payloadDecoderSubscription = this.payloadDecoderService.getMultiple(1000, 0, 'id', 'ASC')
+ .subscribe((response: PayloadDecoderMappedResponse) => {
+ this.payloadDecoders = response.data;
+ });
+ }
+
+ handleError(error: HttpErrorResponse) {
+ const errors = this.errorMessageService.handleErrorMessageWithFields(error);
+ this.errorFields = errors.errorFields;
+ this.errorMessages = errors.errorMessages;
+ this.scrollToTopService.scrollToTop();
+ }
+
+ routeToDatatargets(): void {
+ this.router.navigate(['applications', this.applicationId.toString()]);
+ }
+
+ onCoordinateKey(event: any) {
+ if (event.target.value.length > event.target.maxLength) {
+ event.target.value = event.target.value.slice(
+ 0,
+ event.target.maxLength
+ );
+ }
+ }
+
+ getDatatarget(id: number) {
+ this.datatargetSubscription = this.datatargetService
+ .get(id)
+ .subscribe((response: Datatarget) => {
+ this.datatarget = response;
+ });
+ }
+
+ showSavedSnack() {
+ this.snackService.showSavedSnack();
+ }
+
+ disableSaveButton(): boolean {
+ const disable = false;
+
+ return disable;
+ }
+
+ ngOnDestroy(): void {
+ if (this.relationSubscription) {
+ this.relationSubscription.unsubscribe();
+ }
+ if (this.applicationSubscription) {
+ this.applicationSubscription.unsubscribe();
+ }
+ if (this.datatargetSubscription) {
+ this.datatargetSubscription.unsubscribe();
+ }
+ if (this.payloadDecoderSubscription) {
+ this.payloadDecoderSubscription.unsubscribe();
+ }
+ }
+
+ 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
+ });
+ }
+ );
+ }
+}
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
new file mode 100644
index 00000000..42cf6d1f
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
{{ 'DATATARGET.DETAILS' | translate }}
+
+
+
{{ 'DATATARGET.URL' | translate }}{{datatarget.url}}
+
{{ 'DATATARGET.TIMEOUT' | translate }}{{datatarget.timeout}}
+
{{ 'DATATARGET.TYPE' | translate }}{{'DATATARGET.' + datatarget.type | translate}}
+
+
{{ 'DATATARGET.AUTHORIZATIONHEADER' | translate }}
+
{{datatarget.authorizationHeader}}
+
+ {{ 'DATATARGET.NO-AUTHORIZATIONHEADER' | translate }}
+
+
+
+
+
+
+
{{ 'DATATARGET.OPENDATA-DK' | translate }}
+
+
+ {{ 'DATATARGET.NO-OPENDATA-DK' | translate }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.scss b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.scss
new file mode 100644
index 00000000..e5e49dff
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.scss
@@ -0,0 +1,3 @@
+pre {
+ word-wrap: break-word;
+ }
\ No newline at end of file
diff --git a/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.spec.ts b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.spec.ts
new file mode 100644
index 00000000..a212025a
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.spec.ts
@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { HttppushDetailComponent } from './httppush-detail.component';
+
+describe('HttppushDetailComponent', () => {
+ let component: HttppushDetailComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ HttppushDetailComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HttppushDetailComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
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
new file mode 100644
index 00000000..179aebcf
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-detail/httppush-detail.component.ts
@@ -0,0 +1,98 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs';
+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';
+
+@Component({
+ selector: 'app-httppush-detail',
+ templateUrl: './httppush-detail.component.html',
+ styleUrls: ['./httppush-detail.component.scss']
+})
+export class HttppushDetailComponent implements DatatargetDetail, OnInit, OnDestroy {
+
+ public datatargetSubscription: Subscription;
+ public datatarget: Datatarget;
+ public backButton: BackButton = { label: '', routerLink: '' };
+ public dataTargetRelations: PayloadDeviceDatatargetGetByDataTarget[];
+ private deleteDialogSubscription: Subscription;
+ public dropdownButton: DropdownButton;
+ arrowsAltH = faArrowsAltH;
+ private applicationName: string;
+
+ constructor(
+ private route: ActivatedRoute,
+ private deleteDialogService: DeleteDialogService,
+ private location: Location,
+ private datatargetRelationServicer: PayloadDeviceDatatargetService,
+ private datatargetService: DatatargetService,
+ public translate: TranslateService) { }
+
+ ngOnInit(): void {
+ const id: number = +this.route.snapshot.paramMap.get('datatargetId');
+ this.applicationName = this.route.snapshot.paramMap.get('name');
+ if (id) {
+ this.getDatatarget(id);
+ this.getDatatargetRelations(id);
+ this.dropdownButton = {
+ label: '',
+ editRouterLink: '../../datatarget-edit/' + id,
+ isErasable: true,
+ };
+ }
+ 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'];
+ });
+ }
+
+ getDatatarget(id: number) {
+ this.datatargetService.get(id)
+ .subscribe((dataTarget: Datatarget) => {
+ this.datatarget = dataTarget;
+ this.setBackButton(this.datatarget.applicationId);
+ });
+ }
+
+ private setBackButton(applicationId: number) {
+ this.backButton.routerLink = ['applications', applicationId.toString()];
+ }
+
+ 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) {
+ this.datatargetRelationServicer.getByDataTarget(id)
+ .subscribe((response) => {
+ this.dataTargetRelations = response.data;
+ });
+ }
+
+ ngOnDestroy(): void {
+ if (this.deleteDialogSubscription) {
+ this.deleteDialogSubscription.unsubscribe();
+ }
+ }
+
+}
diff --git a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.html b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.html
new file mode 100644
index 00000000..4d4df069
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.html
@@ -0,0 +1,139 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.scss b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.spec.ts b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.spec.ts
new file mode 100644
index 00000000..1ff864db
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.spec.ts
@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { HttppushEditComponent } from './httppush-edit.component';
+
+describe('HttppushEditComponent', () => {
+ let component: HttppushEditComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ HttppushEditComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HttppushEditComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
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
new file mode 100644
index 00000000..d192c2a6
--- /dev/null
+++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts
@@ -0,0 +1,406 @@
+import { Component, OnInit, Input, OnDestroy } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { Datatarget } from '../../datatarget.model';
+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 { DatatargetService } from '../../datatarget.service';
+import { ApplicationService } from '@applications/application.service';
+import { PayloadDecoderService } from '@payload-decoder/payload-decoder.service';
+import { PayloadDeviceDatatargetService } from '@payload-decoder/payload-device-datatarget.service';
+import { SnackService } from '@shared/services/snack.service';
+import { MatDialog } from '@angular/material/dialog';
+import { HttpErrorResponse } from '@angular/common/http';
+import { PayloadDecoderMappedResponse } from '@payload-decoder/payload-decoder.model';
+import { DeleteDialogComponent } from '@shared/components/delete-dialog/delete-dialog.component';
+import { ErrorMessageService } from '@shared/error-message.service';
+import { OpendatadkDialogService } from '@shared/components/opendatadk-dialog/opendatadk-dialog.service';
+import { OpendatadkService } from '@shared/services/opendatadk.service';
+import { ScrollToTopService } from '@shared/services/scroll-to-top.service';
+import { OpenDataDkDataset } from '../../opendatadk/opendatadk-dataset.model';
+import { DataTargetType } from '@shared/enums/datatarget-type';
+import { DatatargetEdit } from '@applications/datatarget/datatarget-edit/datatarget-edit';
+
+@Component({
+ selector: 'app-httppush-edit',
+ templateUrl: './httppush-edit.component.html',
+ styleUrls: ['./httppush-edit.component.scss'],
+})
+export class HttppushEditComponent
+ implements DatatargetEdit, OnInit, OnDestroy {
+ public multiPage = false;
+ public title = '';
+ public sectionTitle = '';
+ public backButtonTitle = '';
+ @Input() submitButton: string;
+ public datatarget: Datatarget = new Datatarget();
+ faTimesCircle = faTimesCircle;
+ public datatargetSubscription: Subscription;
+ public relationSubscription: Subscription;
+ public applicationSubscription: Subscription;
+ public payloadDecoderSubscription: Subscription;
+ public errorMessages: any;
+ public errorFields: string[];
+ public formFailedSubmit = false;
+ public datatargetid: number;
+ private applicationId: number;
+ private applicationName: string;
+ public application: Application;
+ public devices: IotDevice[];
+ public payloadDecoders = [];
+ private counter: number;
+ private dataSetExcists = false;
+ private isMailDialogAlreadyShown = false;
+
+ payloadDeviceDatatarget: PayloadDeviceDatatarget[];
+ newDynamic: any = {};
+
+ constructor(
+ public translate: TranslateService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private datatargetService: DatatargetService,
+ private applicationService: ApplicationService,
+ private payloadDecoderService: PayloadDecoderService,
+ private payloadDeviceDataTargetService: PayloadDeviceDatatargetService,
+ private saveSnackService: SnackService,
+ private dialog: MatDialog,
+ private errorMessageService: ErrorMessageService,
+ private opendatadkService: OpendatadkService,
+ private opendatadkDialogService: OpendatadkDialogService,
+ private scrollToTopService: ScrollToTopService
+ ) {
+ translate.use('da');
+ }
+
+ ngOnInit() {
+ this.translate
+ .get([
+ 'FORM.CREATE-NEW-DATATARGET',
+ 'FORM.EDIT-DATATARGET',
+ 'DATATARGET.SAVE',
+ 'NAV.DATATARGET',
+ ])
+ .subscribe((translations) => {
+ const datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
+ if (datatargetid !== 0) {
+ this.title = translations['FORM.EDIT-DATATARGET'];
+ } else {
+ this.title = translations['FORM.CREATE-NEW-DATATARGET'];
+ }
+ this.submitButton = translations['DATATARGET.SAVE'];
+ this.backButtonTitle = translations['NAV.DATATARGET'];
+ });
+
+ this.datatargetid = +this.route.snapshot.paramMap.get('datatargetId');
+ this.applicationId = +this.route.snapshot.paramMap.get('id');
+ this.applicationName = this.route.snapshot.paramMap.get('name');
+ if (this.datatargetid !== 0) {
+ this.getDatatarget(this.datatargetid);
+ this.getPayloadDeviceDatatarget(this.datatargetid);
+ }
+ if (this.applicationId !== 0) {
+ this.getDevices();
+ }
+ this.getPayloadDecoders();
+ this.setDataSetExcists();
+ }
+
+ addRow() {
+ if (!this.payloadDeviceDatatarget) {
+ this.payloadDeviceDatatarget = [];
+ }
+ this.payloadDeviceDatatarget.push({
+ id: null,
+ iotDeviceIds: [],
+ payloadDecoderId: null,
+ dataTargetId: this.datatargetid,
+ });
+ }
+
+ private deleteRow(index) {
+ if (this.payloadDeviceDatatarget.length === 0) {
+ } else if (this.payloadDeviceDatatarget[index]?.id === null) {
+ this.payloadDeviceDatatarget.splice(index, 1);
+ } else {
+ this.payloadDeviceDataTargetService
+ .delete(this.payloadDeviceDatatarget[index].id)
+ .subscribe((response) => {
+ this.payloadDeviceDatatarget.splice(index, 1);
+ });
+ }
+ }
+
+ openDeleteDialog(index) {
+ const dialog = this.dialog.open(DeleteDialogComponent, {
+ data: {
+ showAccept: true,
+ showCancel: true,
+ message: 'Er du sikker på at du vil slette?',
+ },
+ });
+
+ dialog.afterClosed().subscribe((result) => {
+ if (result === true) {
+ this.deleteRow(index);
+ }
+ });
+ }
+
+ onSubmit(): void {
+ this.counter = 0;
+ if (this.datatargetid) {
+ this.updateDatatarget();
+ this.addPayloadDeviceDatatarget();
+ } else {
+ this.createDatatarget();
+ }
+ }
+
+ public compare(o1: any, o2: any): boolean {
+ return o1 === o2;
+ }
+
+ updateDatatarget() {
+ this.resetErrors();
+ this.counter =
+ 1 +
+ (this.payloadDeviceDatatarget?.length
+ ? this.payloadDeviceDatatarget?.length
+ : 0);
+ this.datatargetService.update(this.datatarget).subscribe(
+ (response: Datatarget) => {
+ this.datatarget = response;
+ if (this.datatarget.openDataDkDataset != null) {
+ this.datatarget.openDataDkDataset.acceptTerms = true;
+ }
+ this.shouldShowMailDialog().subscribe((response) => {
+ this.countToRedirect();
+ });
+ },
+ (error: HttpErrorResponse) => {
+ this.checkDataTargetModelOpendatadkdatasaet();
+ this.handleError(error);
+ this.formFailedSubmit = true;
+ }
+ );
+ }
+
+ addPayloadDeviceDatatarget() {
+ this.payloadDeviceDatatarget.map((pdd) => {
+ if (pdd.payloadDecoderId === 0) {
+ pdd.payloadDecoderId = null;
+ }
+ });
+ this.payloadDeviceDatatarget.forEach((relation) => {
+ if (relation.id) {
+ this.payloadDeviceDataTargetService.put(relation).subscribe(
+ (response) => {
+ this.countToRedirect();
+ },
+ (error) => {
+ this.handleError(error);
+ }
+ );
+ } else {
+ this.payloadDeviceDataTargetService.post(relation).subscribe(
+ (res: any) => {
+ this.countToRedirect();
+ },
+ (error) => {
+ this.handleError(error);
+ }
+ );
+ }
+ });
+ }
+
+ countToRedirect() {
+ this.counter -= 1;
+ if (this.counter <= 0 && !this.formFailedSubmit) {
+ this.showSavedSnack();
+ this.routeToDatatargets();
+ }
+ }
+
+ getPayloadDeviceDatatarget(id: number) {
+ this.relationSubscription = this.payloadDeviceDataTargetService
+ .getByDataTarget(id)
+ .subscribe((response: PayloadDeviceDatatargetGetByDataTargetResponse) => {
+ this.mapToDatatargetDevicePayload(response);
+ });
+ }
+
+ createDatatarget() {
+ this.resetErrors();
+ this.datatarget.applicationId = this.applicationId;
+ this.datatargetService.create(this.datatarget).subscribe(
+ (response: Datatarget) => {
+ this.datatargetid = response.id;
+ this.datatarget = response;
+ if (this.datatarget.openDataDkDataset != null) {
+ this.datatarget.openDataDkDataset.acceptTerms = true;
+ }
+ this.showSavedSnack();
+ this.routeToDatatargets();
+ },
+ (error: HttpErrorResponse) => {
+ this.checkDataTargetModelOpendatadkdatasaet();
+ this.handleError(error);
+ this.formFailedSubmit = true;
+ }
+ );
+ }
+
+ private resetErrors() {
+ this.errorFields = [];
+ this.errorMessages = undefined;
+ this.formFailedSubmit = false;
+ }
+
+ checkDataTargetModelOpendatadkdatasaet() {
+ if (!this.datatarget.openDataDkDataset) {
+ this.datatarget.openDataDkDataset = new OpenDataDkDataset();
+ }
+ }
+
+ getDevices(): void {
+ 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
+ );
+ }
+
+ public deSelectAllDevices(index: number) {
+ this.payloadDeviceDatatarget[index].iotDeviceIds = [];
+ }
+
+ getPayloadDecoders() {
+ this.payloadDecoderSubscription = this.payloadDecoderService
+ .getMultiple(1000, 0, 'id', 'ASC')
+ .subscribe((response: PayloadDecoderMappedResponse) => {
+ this.payloadDecoders = response.data;
+ });
+ }
+
+ handleError(error: HttpErrorResponse) {
+ const errors = this.errorMessageService.handleErrorMessageWithFields(error);
+ this.errorFields = errors.errorFields;
+ this.errorMessages = errors.errorMessages;
+ this.scrollToTopService.scrollToTop();
+ }
+
+ routeToDatatargets(): void {
+ this.router.navigate(['applications', this.applicationId.toString()]);
+ }
+
+ onCoordinateKey(event: any) {
+ if (event.target.value.length > event.target.maxLength) {
+ event.target.value = event.target.value.slice(0, event.target.maxLength);
+ }
+ }
+
+ getDatatarget(id: number) {
+ this.datatargetSubscription = this.datatargetService
+ .get(id)
+ .subscribe((response: Datatarget) => {
+ this.datatarget = response;
+ });
+ }
+
+ showSavedSnack() {
+ this.saveSnackService.showSavedSnack();
+ }
+
+ private setDataSetExcists() {
+ this.opendatadkService.get().subscribe((response) => {
+ this.dataSetExcists = response.dataset.length === 0 ? false : true;
+ });
+ }
+
+ private shouldShowMailDialog(): Observable {
+ return new Observable((observer) => {
+ if (
+ !this.dataSetExcists &&
+ this.datatarget.setToOpendataDk &&
+ !this.isMailDialogAlreadyShown
+ ) {
+ this.isMailDialogAlreadyShown = true;
+ this.opendatadkDialogService.showDialog().subscribe((response) => {
+ if (response) {
+ this.showMailClient();
+ }
+ observer.next(response);
+ });
+ } else {
+ observer.next(true);
+ }
+ });
+ }
+
+ private showMailClient() {
+ if (!this.datatarget.openDataDkDataset.url) {
+ this.datatarget.openDataDkDataset.url = this.datatargetService.getOpendataSharingApiUrl();
+ }
+ window.location.href =
+ 'mailto:FG2V@kk.dk?subject=Oprettelse%20af%20datas%C3%A6t%20i%20OpenDataDK&body=K%C3%A6re%20Frans%0D%0A%0D%0AHermed%20fremsendes%20linket%20til%20DCAT%20kataloget%20%2C%20du%20bedes%20registrere%20p%C3%A5%20Open%20Data%20DK%20platformen.%0D%0A%0D%0ALink%3A ' +
+ this.datatarget.openDataDkDataset.url;
+ }
+
+ disableSaveButton(): boolean {
+ let disable = true;
+ if (!this.datatarget.setToOpendataDk) {
+ disable = false;
+ } else if (this.datatarget.openDataDkDataset?.acceptTerms) {
+ disable = false;
+ } else {
+ disable = true;
+ }
+ return disable;
+ }
+
+ ngOnDestroy(): void {
+ if (this.relationSubscription) {
+ this.relationSubscription.unsubscribe();
+ }
+ if (this.applicationSubscription) {
+ this.applicationSubscription.unsubscribe();
+ }
+ if (this.datatargetSubscription) {
+ this.datatargetSubscription.unsubscribe();
+ }
+ if (this.payloadDecoderSubscription) {
+ this.payloadDecoderSubscription.unsubscribe();
+ }
+ }
+
+ 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,
+ });
+ });
+ }
+}
diff --git a/src/app/shared/components/snack-bar/snack-bar.component.html b/src/app/shared/components/snack-bar/snack-bar.component.html
new file mode 100644
index 00000000..aa504cd5
--- /dev/null
+++ b/src/app/shared/components/snack-bar/snack-bar.component.html
@@ -0,0 +1,9 @@
+
+ {{data.title}}
+
+
+ {{data.message}}
+
+
+
+
\ No newline at end of file
diff --git a/src/app/shared/components/snack-bar/snack-bar.component.scss b/src/app/shared/components/snack-bar/snack-bar.component.scss
new file mode 100644
index 00000000..29916f9b
--- /dev/null
+++ b/src/app/shared/components/snack-bar/snack-bar.component.scss
@@ -0,0 +1,21 @@
+.snackbar-title-style {
+ font-weight: 500;
+ letter-spacing: 0.5px;
+}
+.snackbar-content-style {
+ letter-spacing: 0.5px;
+ border: none;
+ padding: 0 10px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.snackbar-button-div-style {
+ text-align: center;
+
+ .button-style {
+ letter-spacing: 0.5px;
+ border: 1px solid #000;
+ border-radius: 5px;
+ padding: 5px 15px;
+ }
+}
diff --git a/src/app/shared/components/snack-bar/snack-bar.component.ts b/src/app/shared/components/snack-bar/snack-bar.component.ts
new file mode 100644
index 00000000..2bf27e0b
--- /dev/null
+++ b/src/app/shared/components/snack-bar/snack-bar.component.ts
@@ -0,0 +1,18 @@
+import { Component, OnInit, Inject } from "@angular/core";
+import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from "@angular/material/snack-bar";
+
+
+@Component({
+ selector: 'app-snackbar',
+ templateUrl: './snack-bar.component.html',
+ styleUrls: ['./snack-bar.component.scss']
+})
+export class SnackBarComponent implements OnInit {
+
+ constructor(
+ @Inject(MAT_SNACK_BAR_DATA) public data: any,
+ public snackBarRef: MatSnackBarRef) {}
+
+ ngOnInit(): void {
+ }
+}
diff --git a/src/app/shared/enums/datatarget-type.ts b/src/app/shared/enums/datatarget-type.ts
index 5dea3827..795c317d 100644
--- a/src/app/shared/enums/datatarget-type.ts
+++ b/src/app/shared/enums/datatarget-type.ts
@@ -1,4 +1,5 @@
export enum DataTargetType {
HTTPPUSH = 'HTTP_PUSH',
- OPENDATADK = 'OPENDATADK'
+ OPENDATADK = 'OPENDATADK',
+ FIWARE = 'FIWARE'
}
diff --git a/src/app/shared/services/snack.service.ts b/src/app/shared/services/snack.service.ts
index d5831815..f759968f 100644
--- a/src/app/shared/services/snack.service.ts
+++ b/src/app/shared/services/snack.service.ts
@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { TranslateService } from '@ngx-translate/core';
+import { SnackBarComponent } from '@shared/components/snack-bar/snack-bar.component';
+
@Injectable({
providedIn: 'root',
@@ -41,4 +43,18 @@ export class SnackService {
duration: 10000,
});
}
+
+ public showSnackBar(title: string, displayMessage: string, buttonText: string) {
+ this.snackBar.openFromComponent(SnackBarComponent, {
+ data: {
+ title: title,
+ message: displayMessage,
+ buttonText: buttonText
+ },
+ duration: 5000,
+ horizontalPosition: 'right',
+ verticalPosition: 'top',
+ panelClass: 'snackBar'
+ });
+ }
}
diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json
index bf9a16d8..af3bc49c 100644
--- a/src/assets/i18n/da.json
+++ b/src/assets/i18n/da.json
@@ -151,6 +151,8 @@
"DATATARGET": {
"DETAILS": "Detaljer",
"SAVE": "Gem datatarget",
+ "CREATE": "Opret",
+ "READMORE": "Læs mere",
"DESCRIPTION": "Beskrivelse",
"URL": "URL",
"TIMEOUT": "Timeout",
@@ -163,11 +165,17 @@
"NO-PAYLOADDECODER": "Ingen payload decoder",
"IOTDEVICE": "IoT enhed(er)",
"NO-RELATIONS": "ingen tilknyttede relationer",
+ "TENANT": "Tenant",
+ "NO-TENANT": "Ingen Tenant angivet",
+ "CONTEXT": "Context",
+ "NO-CONTEXT": "Ingen Context angivet",
"AUTHORIZATIONHEADER": "Authorization header",
"NO-AUTHORIZATIONHEADER": "Ingen Authorization header angivet",
"ADD-TO-OPENDATADK": "Send data til OpenDataDK",
- "OPENDATA-DK": "OpenDataDK",
- "NO-OPENDATA-DK": "Der er ikke oprettet nogen datadeling med Open Data DK endnu"
+ "OPENDATA-DK": "OpenDataDK",
+ "NO-OPENDATA-DK": "Der er ikke oprettet nogen datadeling med Open Data DK endnu",
+ "HTTP_PUSH": "HTTP Push",
+ "FIWARE": "FIWARE"
},
"MULTICAST": {
"SAVE": "Gem multicast",
@@ -945,5 +953,19 @@
"DELETE": "Slet"
}
},
- "NoUsersAdded": "Ingen brugergrupper er tilføjet"
+ "NoUsersAdded": "Ingen brugergrupper er tilføjet",
+
+ "FIWARE": {
+ "QUESTION": {
+ "GIVE-DATATARGET-CONTEXTBROKER-URL": "Angiv datatargets 'context broker' URL",
+ "GIVE-DATATARGET-CONTEXTBROKER-URL-PLACEHOLDER": "https://contextBroker.dk/",
+ "GIVE-DATATARGET-TENANT": "Angiv 'tenant'",
+ "GIVE-DATATARGET-TENANT-INFO": "hvis tom, vil default tenant blive brugt",
+ "GIVE-DATATARGET-TENANT-PLACEHOLDER": "Tenant's navn",
+ "GIVE-DATATARGET-CONTEXT": "Angiv 'context'",
+ "GIVE-DATATARGET-CONTEXT-INFO": "hvis tom, skal den angives i 'payload'",
+ "GIVE-DATATARGET-CONTEXT-PLACEHOLDER": "https://os2iot/context-file.json"
+ }
+
+ }
}
diff --git a/src/assets/images/logo_FIWARE.png b/src/assets/images/logo_FIWARE.png
new file mode 100644
index 00000000..beb19973
Binary files /dev/null and b/src/assets/images/logo_FIWARE.png differ
diff --git a/src/assets/images/logo_opendatadk.svg b/src/assets/images/logo_opendatadk.svg
new file mode 100644
index 00000000..37964dfc
--- /dev/null
+++ b/src/assets/images/logo_opendatadk.svg
@@ -0,0 +1 @@
+
diff --git a/src/styles.scss b/src/styles.scss
index 91b964e8..4455b654 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -53,3 +53,38 @@
font-family: 'roboto-bold';
src: url('./assets/fonts/Roboto-Bold.ttf') format('truetype');
}
+
+body {
+ // For Google Chrome
+ &::-webkit-scrollbar {
+ width: 5px;
+ height: 5px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: rgba($color: #000000, $alpha: 0.5);
+ }
+
+ &::-webkit-scrollbar-track {
+ background: rgba($color: #000000, $alpha: 0.4);
+ }
+
+ // For FireFox
+ scrollbar-width: 5px;
+
+ // For Internet Explorer
+ & {
+ scrollbar-face-color: rgba($color: #000000, $alpha: 0.5);
+ scrollbar-track-color: rgba($color: #000000, $alpha: 0.4);
+ }
+}
+
+.snackBar.mat-snack-bar-container{
+ background: #f4f4f4;
+ color: #000;
+}
+
+.mat-tooltip {
+ font-size: 1rem !important;
+}
+