diff --git a/src/app/admin/organisation/organisation.model.ts b/src/app/admin/organisation/organisation.model.ts index f07c0a528..fdf05791f 100644 --- a/src/app/admin/organisation/organisation.model.ts +++ b/src/app/admin/organisation/organisation.model.ts @@ -16,6 +16,7 @@ export interface OrganisationResponse { createdByName: string; updatedByName: string; name: string; + openDataDkRegistered: boolean; payloadDecoders: PayloadDecoder[]; applications: Application[]; diff --git a/src/app/applications/datatarget/datatarget-types.service.ts b/src/app/applications/datatarget/datatarget-types.service.ts index 67e7f9592..a1ef01684 100644 --- a/src/app/applications/datatarget/datatarget-types.service.ts +++ b/src/app/applications/datatarget/datatarget-types.service.ts @@ -9,6 +9,7 @@ import { HttppushDetailComponent } from './httppush/httppush-detail/httppush-det import { HttppushEditComponent } from './httppush/httppush-edit/httppush-edit.component'; 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'; @Injectable({ providedIn: 'root', @@ -77,7 +78,7 @@ export class DatatargetTypesService { } if (dataTargetType === DataTargetType.OPENDATADK) { - return HttppushEditComponent; + return OpendatadkEditComponent; } if (dataTargetType === DataTargetType.FIWARE) { diff --git a/src/app/applications/datatarget/datatarget.model.ts b/src/app/applications/datatarget/datatarget.model.ts index 6021d01f4..f66c885ad 100644 --- a/src/app/applications/datatarget/datatarget.model.ts +++ b/src/app/applications/datatarget/datatarget.model.ts @@ -44,3 +44,10 @@ export class DatatargetTypeDescriptor { readMoreUrl: string; provider: string; } + +export class OddkMailInfo { + organizationId?: number; + organizationOddkAlias: string; + comment?: string; + sharingUrl?: 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 8355b03e7..2a8518acc 100644 --- a/src/app/applications/datatarget/datatarget.module.ts +++ b/src/app/applications/datatarget/datatarget.module.ts @@ -24,6 +24,8 @@ import { DatatargetEditTypeSelectorDirective } from './datatarget-edit/datatarge import { MqttEditComponent } from './mqtt-edit/mqtt-edit.component'; import { MqttDetailComponent } from './mqtt-detail/mqtt-detail.component'; import { DatatargetTabComponent } from './datatarget-tab/datatarget-tab.component'; +import { OpenDataDkMailDialogComponent } from './opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog'; +import { OpenDataDkWarningDialogComponent } from './opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog'; @NgModule({ declarations: [ @@ -38,11 +40,14 @@ import { DatatargetTabComponent } from './datatarget-tab/datatarget-tab.componen OpendatadkComponent, OpendatadkEditComponent, OpendatadkDetailComponent, + OpenDataDkMailDialogComponent, + OpenDataDkWarningDialogComponent, MqttDetailComponent, MqttEditComponent, DatatargetDetailTypeSelectorDirective, DatatargetEditTypeSelectorDirective, - DatatargetTabComponent], + DatatargetTabComponent, + ], imports: [ CommonModule, RouterModule, @@ -64,7 +69,7 @@ import { DatatargetTabComponent } from './datatarget-tab/datatarget-tab.componen FiwareEditComponent, HttppushDetailComponent, HttppushEditComponent, - NGMaterialModule - ] + NGMaterialModule, + ], }) -export class DatatargetModule { } +export class DatatargetModule {} diff --git a/src/app/applications/datatarget/datatarget.service.ts b/src/app/applications/datatarget/datatarget.service.ts index e803524f3..1efcb30eb 100644 --- a/src/app/applications/datatarget/datatarget.service.ts +++ b/src/app/applications/datatarget/datatarget.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { DatatargetResponse } from '@applications/datatarget/datatarget-response.model'; import { RestService } from '@shared/services/rest.service'; -import { DatatargetData, Datatarget } from './datatarget.model'; +import { DatatargetData, Datatarget, OddkMailInfo } from './datatarget.model'; import { map } from 'rxjs/operators'; import { OpenDataDkDataset } from './opendatadk/opendatadk-dataset.model'; import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; @@ -77,10 +77,6 @@ export class DatatargetService { if (!datatarget.setToOpendataDk) { datatarget.openDataDkDataset = null; } - if (datatarget.setToOpendataDk) { - datatarget.openDataDkDataset.keywords = datatarget.openDataDkDataset?.keywordsInput?.split(','); - datatarget.openDataDkDataset.keywordsInput = undefined; - } } private mapToDatatarget(dataTargetResponse: DatatargetResponse): Datatarget { @@ -120,4 +116,14 @@ export class DatatargetService { return this.restService.createResourceUrl('open-data-dk-sharing', this.sharedVariableService.getSelectedOrganisationId()); } + getOpenDataDkRegistered(organizationId: number): Observable { + return this.restService.get(this.dataTargetURL + '/getOpenDataDkRegistered', undefined, organizationId); + } + updateOpenDataDkRegistered(organizationId: number): Observable { + return this.restService.put(this.dataTargetURL + '/updateOpenDataDkRegistered', undefined, organizationId); + } + sendOpenDataDkMail(mailDto: OddkMailInfo): Observable { + mailDto.sharingUrl = this.getOpendataSharingApiUrl(); + return this.restService.post(this.dataTargetURL + '/sendOpenDataDkMail', mailDto); + } } diff --git a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts index afc7d21c9..32fb4fb4d 100644 --- a/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts +++ b/src/app/applications/datatarget/fiware/fiware-edit/fiware-edit.component.ts @@ -2,7 +2,7 @@ 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 { 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'; 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 ad21eba71..37b36bcf1 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 @@ -8,19 +8,23 @@

{{ 'DATATARGET.DETAILS' | translate }}

-

{{ 'DATATARGET.URL' | translate }}{{datatarget.url}}

-

{{ 'DATATARGET.TIMEOUT' | translate }}{{datatarget.timeout}}

+ +

{{ 'DATATARGET.URL' | translate }}{{datatarget.url}}

+

{{ 'DATATARGET.TIMEOUT' | translate }}{{datatarget.timeout}}

+

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

- -

{{ 'DATATARGET.AUTHORIZATIONHEADER' | translate }}

-
{{datatarget.authorizationHeader}}
- -

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

-
+ + +

{{ 'DATATARGET.AUTHORIZATIONHEADER' | translate }}

+
{{datatarget.authorizationHeader}}
+ +

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

+
+
-
+

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

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 844f9c3a3..47878a841 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 @@ -14,6 +14,7 @@ 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 { OrganizationAccessScope } from '@shared/enums/access-scopes'; +import { DataTargetType } from '@shared/enums/datatarget-type'; @Component({ selector: 'app-httppush-detail', @@ -22,6 +23,8 @@ import { OrganizationAccessScope } from '@shared/enums/access-scopes'; }) export class HttppushDetailComponent implements DatatargetDetail, OnInit, OnDestroy { + dataTargetType = DataTargetType; + public datatargetSubscription: Subscription; public datatarget: Datatarget; public backButton: BackButton = { label: '', routerLink: undefined }; @@ -29,7 +32,6 @@ export class HttppushDetailComponent private deleteDialogSubscription: Subscription; public dropdownButton: DropdownButton; arrowsAltH = faArrowsAltH; - private applicationName: string; canEdit: boolean; constructor( @@ -45,7 +47,6 @@ export class HttppushDetailComponent ngOnInit(): void { const id: number = +this.route.snapshot.paramMap.get('datatargetId'); const appId: number = +this.route.snapshot.paramMap.get('id'); - this.applicationName = this.route.snapshot.paramMap.get('name'); if (id) { this.getDatatarget(id); this.getDatatargetRelations(id); 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 index 73725f599..96bbe9365 100644 --- a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.html +++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.html @@ -12,14 +12,8 @@
- - {{'DATATARGET.ADD-TO-OPENDATADK' | translate}} -
-
+
*
-
- -
+
{{'QUESTION.DATATARGET.RELATIONS' | translate}}
@@ -135,6 +127,6 @@
{{'QUESTION.DATATARGET.RELATIONS' | translate}}
- +
diff --git a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts index 0ee5bac9a..3bf2d40e4 100644 --- a/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts +++ b/src/app/applications/datatarget/httppush/httppush-edit/httppush-edit.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit, Input, OnDestroy } from '@angular/core'; +import { Component, OnInit, 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 { 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'; @@ -20,11 +20,7 @@ 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'; import { MeService } from '@shared/services/me.service'; import { OrganizationAccessScope } from '@shared/enums/access-scopes'; @@ -52,13 +48,10 @@ export class HttppushEditComponent 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 = {}; @@ -75,8 +68,6 @@ export class HttppushEditComponent private saveSnackService: SnackService, private dialog: MatDialog, private errorMessageService: ErrorMessageService, - private opendatadkService: OpendatadkService, - private opendatadkDialogService: OpendatadkDialogService, private scrollToTopService: ScrollToTopService, private meService: MeService ) { @@ -104,7 +95,6 @@ export class HttppushEditComponent 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); @@ -113,7 +103,6 @@ export class HttppushEditComponent this.getDevices(); } this.getPayloadDecoders(); - this.setDataSetExcists(); this.canEdit = this.meService.hasAccessToTargetOrganization( OrganizationAccessScope.ApplicationWrite, undefined, @@ -186,15 +175,8 @@ export class HttppushEditComponent 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; } @@ -253,14 +235,10 @@ export class HttppushEditComponent (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; } @@ -273,12 +251,6 @@ export class HttppushEditComponent this.formFailedSubmit = false; } - checkDataTargetModelOpendatadkdatasaet() { - if (!this.datatarget.openDataDkDataset) { - this.datatarget.openDataDkDataset = new OpenDataDkDataset(); - } - } - getDevices(): void { this.applicationSubscription = this.applicationService .getApplication(this.applicationId) @@ -338,53 +310,6 @@ export class HttppushEditComponent 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(); diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-dataset.model.ts b/src/app/applications/datatarget/opendatadk/opendatadk-dataset.model.ts index 36fe3b5cb..031f23095 100644 --- a/src/app/applications/datatarget/opendatadk/opendatadk-dataset.model.ts +++ b/src/app/applications/datatarget/opendatadk/opendatadk-dataset.model.ts @@ -5,7 +5,7 @@ export class OpenDataDkDataset { description: string; keywords: string[]; keywordsInput: string; - license = 'http://portal.opendata.dk/dataset/open-data-dk-licens'; + license = 'https://creativecommons.org/publicdomain/zero/1.0/'; authorName: string; //required authorEmail: string; //reqired url: string; // autogenerated with orgid as input diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-detail/opendatadk-detail.component.html b/src/app/applications/datatarget/opendatadk/opendatadk-detail/opendatadk-detail.component.html index e2beb2af0..cfe1e7049 100644 --- a/src/app/applications/datatarget/opendatadk/opendatadk-detail/opendatadk-detail.component.html +++ b/src/app/applications/datatarget/opendatadk/opendatadk-detail/opendatadk-detail.component.html @@ -18,11 +18,6 @@ {{openDataDkDataset.keywords ? openDataDkDataset.keywords : ('OPENDATADK.DETAILS.NA' | translate) }}

-

- {{ 'OPENDATADK.DETAILS.LICENSE' | translate }} - {{openDataDkDataset.license}} -

-

{{ 'OPENDATADK.DETAILS.AUTHORNAME' | translate }} {{openDataDkDataset.authorName}} diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.html b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.html index 9030bc5a8..f7ff73556 100644 --- a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.html +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.html @@ -1,86 +1,384 @@ -

-

- OpenDataDK datasæt -

-
-
+ + + +
+
+
    +
  • {{ error | translate }}
  • +
+
+ + + + + +

+ {{ 'OPENDATADK.INTRO.GUIDE_HEADER' | translate }} +

+
+
+

+ {{ 'OPENDATADK.INTRO.GUIDE1' | translate }} +

+ {{ 'OPENDATADK.INTRO.GUIDE2' | translate }} +

+ {{ 'OPENDATADK.INTRO.GUIDE3' | translate }} +

+ {{ 'OPENDATADK.INTRO.GUIDE4' | translate }} + {{ 'OPENDATADK.INTRO.GUIDE5' | translate }} +

+

+
+ + + + +

+ {{ 'OPENDATADK.INTRO.PROCEDURE_HEADER' | translate }} +

+
+
+
    +
  1. + {{ 'OPENDATADK.INTRO.PROCEDURE1' | translate }} + https://www.opendata.dk/ +

  2. +
  3. {{ 'OPENDATADK.INTRO.PROCEDURE2' | translate }}

  4. +
  5. {{ 'OPENDATADK.INTRO.PROCEDURE3' | translate }}

  6. +
  7. + {{ 'OPENDATADK.INTRO.PROCEDURE4' | translate }} + {{ 'OPENDATADK.INTRO.PROCEDURE4_LINK' | translate }} +

  8. +
+
+ + +
+
+ + + + +
+
+ + +
- * - + + + +
-
+
-
+ +
- - + + + +
-
+
-
+ +
- * - + +
-
+
-
+ +
- * - + + + +
-
+
-
+ +
- - + +
-
+
-
+ +
- - + + + {{kw}} +
-
+
-
+ +
- -

- {{'OPENDATADK.QUESTION.ACCEPT-TERMS-PART-ONE' | translate}} - - {{'OPENDATADK.QUESTION.TERMS-AND-CONDITIONS' | translate}} - -

-

- {{'OPENDATADK.QUESTION.ACCEPT-TERMS-PART-TWO' | translate}} -

-
+ +

+ {{ 'OPENDATADK.QUESTION.ACCEPT-TERMS-PART-ONE' | translate }} + + {{ 'OPENDATADK.QUESTION.TERMS-AND-CONDITIONS' | translate }} + +

+
-
\ No newline at end of file +
+ + +
{{ 'QUESTION.DATATARGET.RELATIONS' | translate }}
+ + + +
+ + {{'QUESTION.ADD-RELATIONS' | translate}} + + + + + + + + + + +
+
+ + {{'QUESTION.DATATARGET.SELECT-DEVICES' | translate}} + + + + + + {{ device.name }} + + +
+
+
+ + {{ + 'QUESTION.DATATARGET.SELECT-PAYLOADDECODER' | translate + }} + + + {{ + 'QUESTION.DATATARGET.NO-PAYLOAD-DECODER-SELECTED' + | translate + }} + + + {{ payloadDecoder.name }} + + + +
+
+ +
+ +

{{ 'DATATARGET.DELETE' | translate }}

+
+
+
+
+
+ + +
+ + +
+ diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.scss b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.scss index e69de29bb..9e1cdf180 100644 --- a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.scss +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.scss @@ -0,0 +1,15 @@ +@import 'src/assets/scss/setup/fonts'; + +:host { + .form-info-icon { + margin-left: 5px; + cursor: pointer; + } + mat-expansion-panel ol { + padding-left: 20px; + li { + font-family: $font-name, system; + display: list-item; + } + } +} diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.ts b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.ts index 8ec2e7a2b..3d3cbe732 100644 --- a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.ts +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-edit.component.ts @@ -1,21 +1,389 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { OpenDataDkDataset } from '../opendatadk-dataset.model'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Component, OnDestroy } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Application } from '@applications/application.model'; +import { ApplicationService } from '@applications/application.service'; +import { DatatargetEdit } from '@applications/datatarget/datatarget-edit/datatarget-edit'; +import { IotDevice } from '@applications/iot-devices/iot-device.model'; +import { + faQuestionCircle, + faTimesCircle, +} from '@fortawesome/free-solid-svg-icons'; +import { TranslateService } from '@ngx-translate/core'; +import { PayloadDecoderMappedResponse } from '@payload-decoder/payload-decoder.model'; +import { PayloadDecoderService } from '@payload-decoder/payload-decoder.service'; +import { + PayloadDeviceDatatarget, + PayloadDeviceDatatargetGetByDataTargetResponse, +} from '@payload-decoder/payload-device-data.model'; +import { PayloadDeviceDatatargetService } from '@payload-decoder/payload-device-datatarget.service'; +import { DeleteDialogComponent } from '@shared/components/delete-dialog/delete-dialog.component'; +import { OrganizationAccessScope } from '@shared/enums/access-scopes'; +import { DataTargetType } from '@shared/enums/datatarget-type'; +import { ErrorMessageService } from '@shared/error-message.service'; +import { MeService } from '@shared/services/me.service'; +import { ScrollToTopService } from '@shared/services/scroll-to-top.service'; +import { SnackService } from '@shared/services/snack.service'; +import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; +import { first } from 'rxjs/operators'; +import { Datatarget, OddkMailInfo } from '../../datatarget.model'; +import { DatatargetService } from '../../datatarget.service'; +import { OpenDataDkDataset } from '../../opendatadk/opendatadk-dataset.model'; +import { OpenDataDkMailDialogComponent } from './opendatadk-mail-dialog/opendatadk-mail-dialog'; +import { OpenDataDkWarningDialogComponent } from './opendatadk-warning-dialog/opendatadk-warning-dialog'; @Component({ selector: 'app-opendatadk-edit', templateUrl: './opendatadk-edit.component.html', styleUrls: ['./opendatadk-edit.component.scss'], }) -export class OpendatadkEditComponent implements OnInit { - public errorMessages: any; - @Input() errorFields: string[]; - @Input() formFailedSubmit = false; - @Input() openDataDk: OpenDataDkDataset; +export class OpendatadkEditComponent implements DatatargetEdit, OnDestroy { + faQuestionCircle = faQuestionCircle; + faTimesCircle = faTimesCircle; - constructor() {} + title = 'FORM.CREATE-NEW-DATATARGET'; - ngOnInit(): void { - // Set box to checked, if this already exists. - this.openDataDk.acceptTerms = this.openDataDk.id != null; + selectableKeyword = [ + 'Befolkning og samfund', + 'Energi', + 'Internationale spørgsmål', + 'Landbrug, fiskeri, skovbrug og fødevarer', + 'Midlertidige data', + 'Miljø', + 'Regeringen og den offentlige sektor', + 'Regioner og byer', + 'Retfærdighed, retssystem og offentlig sikkerhed', + 'Sundhed', + 'Transport', + 'Uddannelse, kultur og sport', + 'Videnskab og teknologi', + 'Økonomi og finanser', + ]; + + errorMessages: any[]; + errorFields: string[]; + + datatarget: Datatarget = new Datatarget(); + private subscriptions = []; + + formFailedSubmit = false; + datatargetId: number; + private applicationId: number; + devices: IotDevice[]; + payloadDecoders = []; + private pendingRequestsCounter: number; + + payloadDeviceDatatarget: PayloadDeviceDatatarget[]; + canEdit: boolean; + + private alreadySentOddkMail: boolean = false; + + constructor( + 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 scrollToTopService: ScrollToTopService, + private meService: MeService, + private sharedVariableService: SharedVariableService + ) { + translate.use('da'); + + this.datatarget.type = DataTargetType.OPENDATADK; + this.datatarget.setToOpendataDk = true; + + this.datatargetId = +this.route.snapshot.paramMap.get('datatargetId'); + this.applicationId = +this.route.snapshot.paramMap.get('id'); + if (this.applicationId !== 0) { + this.getDevices(); + this.getPayloadDecoders(); + } + if (this.datatargetId !== 0) { + this.title = 'FORM.EDIT-DATATARGET'; + this.getDatatarget(this.datatargetId); + this.getPayloadDeviceDatatarget(this.datatargetId); + } + this.getAlreadySentOddkMail(); + + this.canEdit = this.meService.hasAccessToTargetOrganization( + OrganizationAccessScope.ApplicationWrite, + undefined, + this.applicationId + ); + } + + ngOnDestroy(): void { + this.subscriptions.forEach((s) => s?.unsubscribe()); + } + + private getPayloadDeviceDatatarget(id: number) { + this.subscriptions.push( + this.payloadDeviceDataTargetService + .getByDataTarget(id) + .subscribe((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, + }); + }); + }) + ); + } + + private getDatatarget(id: number) { + this.subscriptions.push( + this.datatargetService.get(id).subscribe((response: Datatarget) => { + this.datatarget = response; + if (this.datatarget.openDataDkDataset != null) { + this.datatarget.openDataDkDataset.acceptTerms = true; + } + }) + ); + } + + onSubmit(): void { + this.resetErrors(); + if (this.datatargetId) { + this.pendingRequestsCounter = + 1 + (this.payloadDeviceDatatarget?.length ?? 0); + this.updateDatatarget(); + this.addPayloadDeviceDatatarget(); + } else { + this.createDatatarget(); + } + } + private updateDatatarget() { + this.subscriptions.push( + this.datatargetService.update(this.datatarget).subscribe( + (response: Datatarget) => { + this.datatarget = response; + if (this.datatarget.openDataDkDataset != null) { + this.datatarget.openDataDkDataset.acceptTerms = true; + } + this.countToRedirect(); + }, + (error: HttpErrorResponse) => { + this.checkDataTargetModelOpendatadkdatasaet(); + this.handleError(error); + this.formFailedSubmit = true; + } + ) + ); + } + private addPayloadDeviceDatatarget() { + this.payloadDeviceDatatarget.forEach((relation) => { + if (relation.payloadDecoderId === 0) { + relation.payloadDecoderId = null; + } + if (relation.id) { + this.subscriptions.push( + this.payloadDeviceDataTargetService.put(relation).subscribe( + () => this.countToRedirect(), + (error) => this.handleError(error) + ) + ); + } else { + this.subscriptions.push( + this.payloadDeviceDataTargetService.post(relation).subscribe( + () => this.countToRedirect(), + (error) => this.handleError(error) + ) + ); + } + }); + } + private createDatatarget() { + this.pendingRequestsCounter = 0; + this.datatarget.applicationId = this.applicationId; + this.subscriptions.push( + 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.saveSnackService.showSavedSnack(); + this.showMailOrRedirect(); + }, + (error: HttpErrorResponse) => { + this.checkDataTargetModelOpendatadkdatasaet(); + this.handleError(error); + this.formFailedSubmit = true; + } + ) + ); + } + private showMailOrRedirect = () => { + if (!this.alreadySentOddkMail) { + this.openMailDialog(); + } else { + this.routeToDatatargets(); + } + }; + // Note: When updating, we send multiple async request, and use this counter to know when everything is done, so we can redirect + private countToRedirect() { + this.pendingRequestsCounter -= 1; + if (this.pendingRequestsCounter <= 0 && !this.formFailedSubmit) { + this.saveSnackService.showSavedSnack(); + this.showMailOrRedirect(); + } + } + private resetErrors() { + this.errorFields = []; + this.errorMessages = undefined; + this.formFailedSubmit = false; + } + private checkDataTargetModelOpendatadkdatasaet() { + this.datatarget.setToOpendataDk = true; + if (!this.datatarget.openDataDkDataset) { + this.datatarget.openDataDkDataset = new OpenDataDkDataset(); + } + } + private 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(), 'data-targets']); + } + + // For mail dialog + private getAlreadySentOddkMail = () => { + const orgId = this.sharedVariableService.getSelectedOrganisationId(); + this.subscriptions.push( + this.datatargetService + .getOpenDataDkRegistered(orgId) + .subscribe((response) => { + this.alreadySentOddkMail = !!response; + }) + ); + }; + private setAlreadySentOddkMail = async () => { + const orgId = this.sharedVariableService.getSelectedOrganisationId(); + await this.datatargetService + .updateOpenDataDkRegistered(orgId) + .pipe(first()) + .toPromise(); + }; + private openMailDialog = () => { + const dialog = this.dialog.open(OpenDataDkMailDialogComponent); + dialog.afterClosed().subscribe(async (result: OddkMailInfo) => { + if (result) { + // User accepted -> Send mail and continue + await this.datatargetService + .sendOpenDataDkMail(result) + .pipe(first()) + .toPromise(); + this.routeToDatatargets(); + } else { + // User cancelled -> Show the warning + this.openMailWarningDialog(); + } + }); + }; + private openMailWarningDialog = () => { + const dialog = this.dialog.open(OpenDataDkWarningDialogComponent); + dialog.afterClosed().subscribe(async (result) => { + if (result) { + // User accepted -> Save if 'never again' was checked, then continue + if (result.neverAgain) { + await this.setAlreadySentOddkMail(); + } + this.routeToDatatargets(); + } else { + // User cancelled -> Show the mail-dialog again + this.openMailDialog(); + } + }); + }; + + // For list of devices / payload-decoders + private getDevices(): void { + this.subscriptions.push( + this.applicationService + .getApplication(this.applicationId) + .subscribe((application: Application) => { + this.devices = application.iotDevices.sort((a, b) => + a.name.localeCompare(b.name, 'en', { numeric: true }) + ); + }) + ); + } + private getPayloadDecoders() { + this.subscriptions.push( + this.payloadDecoderService + .getMultiple(1000, 0, 'id', 'ASC') + .subscribe((response: PayloadDecoderMappedResponse) => { + this.payloadDecoders = response.data.sort((a, b) => + a.name.localeCompare(b.name, 'en', { numeric: true }) + ); + }) + ); + } + 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.subscriptions.push( + 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); + } + }); + } + payloadDevicesDropdownCompare = (o1: any, o2: any): boolean => o1 === o2; + selectAllDevices(index: number) { + this.payloadDeviceDatatarget[index].iotDeviceIds = this.devices.map( + (device) => device.id + ); + } + deSelectAllDevices(index: number) { + this.payloadDeviceDatatarget[index].iotDeviceIds = []; } } diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.html b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.html new file mode 100644 index 000000000..3a60ee7ab --- /dev/null +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.html @@ -0,0 +1,37 @@ +

{{'OPENDATADK.MAIL.DIALOG_TITLE' | translate}}

+
+

+ {{'OPENDATADK.MAIL.DIALOG_TEXT1' | translate}} + {{selectedOrganizationName ?? ('OPENDATADK.MAIL.SELECTED_ORG_FALLBACK' | translate)}}{{'OPENDATADK.MAIL.DIALOG_TEXT2' | translate}} +

+

+ +
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
\ No newline at end of file diff --git a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.scss b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.scss similarity index 100% rename from src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.scss rename to src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.scss diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.ts b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.ts new file mode 100644 index 000000000..6eb667ffe --- /dev/null +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-mail-dialog/opendatadk-mail-dialog.ts @@ -0,0 +1,38 @@ +import { Component } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; +import { OddkMailInfo } from '@applications/datatarget/datatarget.model'; +import { SharedVariableService } from '@shared/shared-variable/shared-variable.service'; + +@Component({ + selector: 'app-opendatadk-mail-dialog', + templateUrl: './opendatadk-mail-dialog.html', + styleUrls: ['./opendatadk-mail-dialog.scss'], +}) +export class OpenDataDkMailDialogComponent { + sendAttempted: boolean = false; + organizationInput: string = ''; + commentInput: string = ''; + + selectedOrganizationName: string; + + constructor( + public dialog: MatDialogRef, + private sharedVariableService: SharedVariableService + ) { + const selectedOrganisationId = sharedVariableService.getSelectedOrganisationId(); + this.selectedOrganizationName = sharedVariableService + .getOrganizationInfo() + ?.find((o) => o.id === selectedOrganisationId)?.name; + } + + send() { + this.sendAttempted = true; + if (this.organizationInput) { + this.dialog.close({ + organizationId: this.sharedVariableService.getSelectedOrganisationId(), + organizationOddkAlias: this.organizationInput, + comment: this.commentInput || undefined, + }); + } + } +} diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.html b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.html new file mode 100644 index 000000000..698444655 --- /dev/null +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.html @@ -0,0 +1,24 @@ +

{{'OPENDATADK.MAIL.WARNING' | translate}}

+
+

+ {{'OPENDATADK.MAIL.WARNING-TEXT' | translate}} +
+

+ +
+
+ + {{ 'OPENDATADK.MAIL.NEVER-AGAIN' | translate }} + +
+
+ +
+
+ + +
\ No newline at end of file diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.scss b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.ts b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.ts new file mode 100644 index 000000000..a79b5fd1d --- /dev/null +++ b/src/app/applications/datatarget/opendatadk/opendatadk-edit/opendatadk-warning-dialog/opendatadk-warning-dialog.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; + +@Component({ + selector: 'app-opendatadk-warning-dialog', + templateUrl: './opendatadk-warning-dialog.html', + styleUrls: ['./opendatadk-warning-dialog.scss'], +}) +export class OpenDataDkWarningDialogComponent { + neverAgain: boolean = false; + + constructor(public dialog: MatDialogRef) {} + + ok() { + this.dialog.close({ neverAgain: this.neverAgain }); + } +} diff --git a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.html b/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.html deleted file mode 100644 index aab0d2948..000000000 --- a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.html +++ /dev/null @@ -1,20 +0,0 @@ -

{{'DIALOG.OPENDATADK.TITLE' | translate}}

-
- {{'DIALOG.OPENDATADK.MESSAGE' | translate}} -
-
- - -
\ No newline at end of file diff --git a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.spec.ts b/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.spec.ts deleted file mode 100644 index 5c35447d5..000000000 --- a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { OpendatadkDialogComponent } from './opendatadk-dialog.component'; - -describe('OpendatadkDialogComponent', () => { - let component: OpendatadkDialogComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ OpendatadkDialogComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(OpendatadkDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.ts b/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.ts deleted file mode 100644 index 0c2d965b2..000000000 --- a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { TranslateService } from '@ngx-translate/core'; - -@Component({ - selector: 'app-opendatadk-dialog', - templateUrl: './opendatadk-dialog.component.html', - styleUrls: ['./opendatadk-dialog.component.scss'] -}) -export class OpendatadkDialogComponent implements OnInit { - - constructor( - private translate: TranslateService, - public dialog: MatDialogRef) { - this.translate.use('da'); - } - - ngOnInit(): void { - } - - close() { - this.dialog.close(); - } - -} diff --git a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.service.ts b/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.service.ts deleted file mode 100644 index d4e074872..000000000 --- a/src/app/shared/components/opendatadk-dialog/opendatadk-dialog.service.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Injectable } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { Observable } from 'rxjs'; -import { OpendatadkDialogComponent } from './opendatadk-dialog.component'; -@Injectable({ - providedIn: 'root', -}) -export class OpendatadkDialogService { - - constructor( - private dialog: MatDialog - ) {} - - showDialog(): Observable { - return new Observable( - (observer) => { - const dialog = this.dialog.open(OpendatadkDialogComponent); - - dialog.afterClosed().subscribe((result) => { - observer.next(result); - }); - } - ); - } - -} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 5045e60d7..4d52159ed 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -10,7 +10,6 @@ import { BatteriStatusComponent } from './components/batteri-status/batteri-stat import { MapComponent } from './components/map/map.component'; import { NGMaterialModule } from './Modules/materiale.module'; import { DeleteDialogComponent } from './components/delete-dialog/delete-dialog.component'; -import { OpendatadkDialogComponent } from './components/opendatadk-dialog/opendatadk-dialog.component'; import { FormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; @@ -28,7 +27,6 @@ import { MetadataDetailsComponent } from './components/metadata-details/metadata BatteriStatusComponent, MapComponent, DeleteDialogComponent, - OpendatadkDialogComponent, TopBarComponent, TopBarTableComponent, GeneralDetailsComponent, @@ -52,7 +50,6 @@ import { MetadataDetailsComponent } from './components/metadata-details/metadata BatteriStatusComponent, MapComponent, DeleteDialogComponent, - OpendatadkDialogComponent, TopBarComponent, TopBarTableComponent, GeneralDetailsComponent, diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index 580da59ab..8a22efb27 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -237,6 +237,9 @@ "QOS": "QoS", "USERNAME": "Brugernavn", "PASSWORD": "Adgangskode" + }, + "OPENDATADK": { + "TYPE": "OpenDataDK" } }, "MULTICAST": { @@ -260,33 +263,63 @@ } }, "OPENDATADK": { + "INTRO": { + "GUIDE_HEADER": "Guide til Open Data DK-data target", + "GUIDE1": "Det er nemt at sende data fra OS2iot til Open Data DK (ODDK). Første gange der oprettes et ODDK-data target, bliver det muligt for ODDK at høste oplysninger om jeres datasæt til opendata.dk. Når først høstningen er sat op, vil alle jeres ODDK-data targets automatisk blive oprettet og opdateret på opendata.dk.", + "GUIDE2": "Senest modtagede datapakke udstilles via OS2iots API og kan hentes via en URL angivet på det enkelte ODDK-data target og på jeres datasæt på opendata.dk. Der opsamles og udstilles altså ikke historisk data i hverken OS2iot eller på opendata.dk.", + "GUIDE3": "Nye ODDK-data targets høstes automatisk, og I behøver ikke gøre noget aktivt for at gøre dem tilgængelige på opendata.dk. Hvis I sletter et ODDK-data target forsvinder det af sig selv fra opendata.dk.", + "GUIDE4": "Datasæt fra OS2iot publiceres under licensen", + "GUIDE5": "Open DATA DK Licens.", + "PROCEDURE_HEADER": "Procedure ved oprettelse af første data target", + "PROCEDURE1": "Bliv medlem af Open Data DK, hvis jeres myndighed ikke allerede er det:", + "PROCEDURE2": "Opret første ODDK-data target i OS2iot", + "PROCEDURE3": "Ved oprettelsen tilbyder OS2iot at sende en mail til Open Data DK's administrator, som sætter høstningen op. I må forvente op til 2-3 ugers behandlingstid.", + "PROCEDURE4": "Når høstningen er aktiv, kan datasæt findes og beriges på", + "PROCEDURE4_LINK": "ODDK administrationsmodulet" + }, "QUESTION": { "GIVE-OPENDATADK-NAME": "Datasæt titel", "GIVE-OPENDATADK-NAME-PLACEHOLDER": "Datasæt titel", - "GIVE-OPENDATADK-RESOURCETITLE": "Datakilde titel", + "GIVE-OPENDATADK-NAME-INFO": "Overordnet titel på datasættet på opendata.dk", + "GIVE-OPENDATADK-RESOURCETITLE": "Data ressource titel", "GIVE-OPENDATADK-RESOURCETITLE-PLACEHOLDER": "Kloaksensorer - Aarhus kommune", + "GIVE-OPENDATADK-RESOURCETITLE-INFO": "Titel på den ressource, der vises i datasættet på opendata.dk", "GIVE-OPENDATADK-DESCRIPTION": "Beskrivelse", "GIVE-OPENDATADK-DESCRIPTION-PLACEHOLDER": "Beskrivelse", - "GIVE-OPENDATADK-KEYWORDS": "Angiv kommasepareret nøgleord", - "GIVE-OPENDATADK-KEYWORDS-PLACEHOLDER": "IOT, sensor, LoRaWAN, temeratur", - "GIVE-OPENDATADK-AUTHORNAME": "Forfatter", + "GIVE-OPENDATADK-KEYWORDS": "Angiv emneord", + "GIVE-OPENDATADK-KEYWORDS-PLACEHOLDER": "Vælg nøgleord fra drop-down", + "GIVE-OPENDATADK-AUTHORNAME": "Dataejer", "GIVE-OPENDATADK-AUTHORNAME-PLACEHOLDER": "Jens Jensen", - "GIVE-OPENDATADK-AUTHOR-EMAIL": "Forfatterens e-mail", + "GIVE-OPENDATADK-AUTHORNAME-INFO": "Ansvarlig afdeling eller person", + "GIVE-OPENDATADK-AUTHOR-EMAIL": "Dataejers e-mail", "GIVE-OPENDATADK-AUTHOR-EMAIL-PLACEHOLDER": "jens@jensen.dk", - "ACCEPT-TERMS-PART-ONE": "Jeg accepterer hermed de", - "ACCEPT-TERMS-PART-TWO": "Heriblandt at data ikke indeholder følsomme personoplysninger eller personhenførbare informationer.", - "TERMS-AND-CONDITIONS": "Gældende vilkår og betingelser for OpenDataDK" + "ACCEPT-TERMS-PART-ONE": "Jeg accepterer hermed, at datasættet udgives under en", + "TERMS-AND-CONDITIONS": "Creative Commons CC0 1.0 Universel (CC0 1.0) licens" }, "DETAILS": { "NAME": "Datasæt titel", "RESOURCETITLE": "Datakilde titel", "DESCRIPTION": "Beskrivelse", - "KEYWORDS": "Keywords", + "KEYWORDS": "Emneord", "LICENSE": "Licens", "AUTHORNAME": "Forfatterens navn", "AUTHOREMAIL": "Forfatterens email", "URL": "Endpoint til hentning af data", "NA": "Intet angivet" + }, + "MAIL": { + "DIALOG_TITLE": "Anmod Open Data DK om høstning af data", + "DIALOG_TEXT1": "For at få", + "DIALOG_TEXT2": "s ODDK datatargets gjort synlige på opendata.dk, skal Open Data DK have en anmodning om at begynde at høste jeres oplysninger fra OS2iot. Hvis du udfylder oplysningerne herunder, sender OS2iot automatisk en mail til Open Data DK", + "DIALOG_CONFIRM": "Send mail", + "GIVE-OPENDATADK-ORGNAME": "Organisation (i Open Data DK)", + "GIVE-OPENDATADK-ORGNAME-PLACEHOLDER": "Organisation", + "GIVE-OPENDATADK-COMMENT": "Eventuel kommentar", + "GIVE-OPENDATADK-COMMENT-PLACEHOLDER": "Kort kommentar", + "SELECTED_ORG_FALLBACK": "organisationen", + "WARNING": "Advarsel", + "WARNING-TEXT": "Hvis Open Data DK ikke får besked om integrationen, vises datasættet ikke på opendata.dk", + "NEVER-AGAIN": "Vis ikke igen. Open Data DK høster allerede denne organisation fra OS2iot." } }, "APPLICATION-TABLE": { @@ -537,6 +570,7 @@ "RELATION-APPLICATION": "Tilknyttet applikation: ", "GIVE-DATATARGET-NAME": "Navngiv datatarget", "GIVE-DATATARGET-NAME-PLACEHOLDER": "Datatarget's navn", + "GIVE-DATATARGET-NAME-INFO": "Benyttes kun i OS2iot", "GIVE-DATATARGET-TIMEOUT": "Timeout i millisekunder", "GIVE-DATATARGET-AUTHORIZATIONHEADER": "Angiv authorization header", "GIVE-DATATARGET-URL": "Angiv datatargets URL",