From dd9ee8c6714fb6c877c4d7ed37751fb80f9587aa Mon Sep 17 00:00:00 2001 From: Baptiste Toulemonde <toulemonde@cines.fr> Date: Tue, 1 Mar 2022 09:30:24 +0100 Subject: [PATCH] fix distrib publishing --- src/app/mapping/mapping.component.html | 213 +++++++++++++++---------- src/app/mapping/mapping.component.ts | 127 +++++++++------ src/assets/distribution.json | 7 + src/assets/geodcat.json | 7 - 4 files changed, 215 insertions(+), 139 deletions(-) diff --git a/src/app/mapping/mapping.component.html b/src/app/mapping/mapping.component.html index 986828b76..da877ae61 100644 --- a/src/app/mapping/mapping.component.html +++ b/src/app/mapping/mapping.component.html @@ -10,20 +10,21 @@ </nb-card-body> </nb-card> - + <form #form="ngForm" *ngIf="ontology"> <div class="row"> <p>Upload Or fill out the form with the path corresponding to the dcat property and save a new file for next mappings:</p> - + <button class="button-center" nbButton status="primary" (click)="openFileInputDialog()"> <nb-icon icon="upload-outline"></nb-icon>Import file </button> <input type="file" id="file" (change)="importJson($event)" accept=".json, .tsv" /> </div> <div class="row"> - <nb-checkbox (checkedChange)="toggleJsonPath($event)">Use jsonpath to describe the mapping</nb-checkbox> + <nb-checkbox (checkedChange)="toggleJsonPath($event)">Use jsonpath to describe the mapping (more information + about jsonpath <a href="https://github.com/json-path/JsonPath" target="_blank">here</a>)</nb-checkbox> </div> <div class="card-row"> <div class="card-col"> @@ -52,38 +53,45 @@ <div class="col-7"> <nb-form-field *ngIf="!isJsonPath; else blockJsonPath"> - <input *ngIf="isMandatory(dataset.card)" required fullWidth + <input *ngIf="isMandatory(dataset.card)" required fullWidth name=" data{{index}}" nbInput (ngModelChange)="onModelChange($event)" - [nbAutocomplete]="auto" [(ngModel)]="selectedPaths[index]" [value]="selectedPaths[index]? selectedPaths[index] : ''" + [nbAutocomplete]="auto" [(ngModel)]="selectedPaths[index]" + [value]="selectedPaths[index]? selectedPaths[index] : ''" (focus)="reset()" /> <input *ngIf="!isMandatory(dataset.card)" fullWidth name=" data{{index}}" nbInput (ngModelChange)="onModelChange($event)" [nbAutocomplete]="auto" - [(ngModel)]="selectedPaths[index]" [value]="selectedPaths[index]? selectedPaths[index] : ''" (focus)="reset()" /> - - <nb-autocomplete #auto > - <nb-option *ngFor="let option of filteredOptions | async" + [(ngModel)]="selectedPaths[index]" + [value]="selectedPaths[index]? selectedPaths[index] : ''" + (focus)="reset()" /> + + <nb-autocomplete #auto> + <nb-option *ngFor="let option of filteredOptions | async" [value]="option"> {{ option }} </nb-option> </nb-autocomplete> </nb-form-field> <ng-template #blockJsonPath> - - <input *ngIf="isMandatory(dataset.card)" required fullWidth - name=" data{{index}}" nbInput (ngModelChange)="onModelChange($event)" - [(ngModel)]="selectedPaths[index]" [value]="selectedPaths[index]? selectedPaths[index] : ''" - (focus)="reset()" /> - - <input *ngIf="!isMandatory(dataset.card)" fullWidth name=" data{{index}}" - nbInput (ngModelChange)="onModelChange($event)" - [(ngModel)]="selectedPaths[index]" [value]="selectedPaths[index]? selectedPaths[index] : ''" (focus)="reset()" /> - + + <input *ngIf="isMandatory(dataset.card)" required fullWidth + name=" data{{index}}" nbInput (ngModelChange)="onModelChange($event)" + [(ngModel)]="selectedPaths[index]" + [value]="selectedPaths[index]? selectedPaths[index] : ''" + (focus)="reset()" /> + + <input *ngIf="!isMandatory(dataset.card)" fullWidth name=" data{{index}}" + nbInput (ngModelChange)="onModelChange($event)" + [(ngModel)]="selectedPaths[index]" + [value]="selectedPaths[index]? selectedPaths[index] : ''" + (focus)="reset()" /> + </ng-template> </div> <div class="col-2" *ngIf="isReplicable(dataset.card) " style="margin-left: 10px;"> - <button nbButton ghost (click)="addField(index, datasets, selectedPaths)" *ngIf="dataset.uri !== datasets[index - 1].uri"> + <button nbButton ghost (click)="addField(index, datasets, selectedPaths)" + *ngIf="dataset.uri !== datasets[index - 1].uri"> <nb-icon icon="plus-outline" status="primary"> </nb-icon> </button> @@ -115,42 +123,61 @@ <div class="row"> Distribution </div> - <div class="row"> - <input [(ngModel)]="distributionValues" [ngModelOptions]="{standalone: true}"> - </div> </nb-card-header> <nb-card-body> - <ng-container *ngFor="let distribution of distributions; let index = index; trackBy: trackByIndex" > + <ng-container + *ngFor="let distribution of distributions; let index = index; trackBy: trackByIndex"> <nb-form-field> <div class="row"> <div class="col-3" style="margin-right: 10px;"> <nb-form-field> - <input *ngIf="!isMandatory(distribution.card)" nbInput fullWidth type="text" - value="{{distribution.uri}} " disabled style="color: black;" /> - <input *ngIf="isMandatory(distribution.card)" nbInput fullWidth type="text" - value="{{distribution.uri}} *" disabled style="color: black;" /> + <input *ngIf="distribution.uri === 'dcat:distribution'" nbInput fullWidth + type="text" value="{{distribution.uri}} " disabled + style="color: black;" /> + + <input + *ngIf="!isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + nbInput fullWidth type="text" value="{{distribution.uri}} " disabled + style="color: black;" /> + <input + *ngIf="isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + nbInput fullWidth type="text" value="{{distribution.uri}} *" disabled + style="color: black;" /> <button nbSuffix nbTooltip="{{distribution.property}}: {{distribution.usageNote}}" nbTooltipStatus="info" nbButton status="basic" ghost> <nb-icon [icon]=" 'question-mark-circle-outline' " pack="eva"> </nb-icon> </button> + + </nb-form-field> </div> <div class="col-7"> - <nb-form-field> - <input *ngIf="isMandatory(distribution.card)" required fullWidth + <nb-form-field *ngIf="!isJsonPath; else blockJsonPathDistri"> + <input *ngIf="distribution.uri === 'dcat:distribution'" fullWidth name=" distri{{index}}" nbInput (ngModelChange)="onModelChange($event)" - [nbAutocomplete]="auto" [(ngModel)]="distributionSelectedPaths[index]" [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" + [nbAutocomplete]="auto" [(ngModel)]="distributionSelectedPaths[index]" + [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" (focus)="reset()" /> - <input *ngIf="!isMandatory(distribution.card)" fullWidth - name=" distri{{index}}" nbInput (ngModelChange)="onModelChange($event)" - [nbAutocomplete]="auto" [(ngModel)]="distributionSelectedPaths[index]" + <input + *ngIf="isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + required fullWidth name=" distri{{index}}" nbInput + (ngModelChange)="onModelChange($event)" [nbAutocomplete]="auto" + [(ngModel)]="distributionSelectedPaths[index]" + [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" + (focus)="reset()" /> + + <input + *ngIf="!isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + fullWidth name=" distri{{index}}" nbInput + (ngModelChange)="onModelChange($event)" [nbAutocomplete]="auto" + [(ngModel)]="distributionSelectedPaths[index]" [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" (focus)="reset()" /> @@ -162,11 +189,37 @@ </nb-option> </nb-autocomplete> + </nb-form-field> + + <ng-template #blockJsonPathDistri> + <input *ngIf="distribution.uri === 'dcat:distribution'" fullWidth + name=" distri{{index}}" nbInput (ngModelChange)="onModelChange($event)" + [(ngModel)]="distributionSelectedPaths[index]" + [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" + (focus)="reset()" /> + + <input + *ngIf="isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + required fullWidth name=" distri{{index}}" nbInput + (ngModelChange)="onModelChange($event)" + [(ngModel)]="distributionSelectedPaths[index]" + [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" + (focus)="reset()" /> + + <input + *ngIf="!isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" + fullWidth name=" distri{{index}}" nbInput + (ngModelChange)="onModelChange($event)" + [(ngModel)]="distributionSelectedPaths[index]" + [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" + (focus)="reset()" /> + </ng-template> </div> <div class="col-2" *ngIf="isReplicable(distribution.card)" style="margin-left: 10px;"> - <button nbButton ghost (click)="addField(index, distributions, distributionSelectedPaths)" + <button nbButton ghost + (click)="addField(index, distributions, distributionSelectedPaths)" *ngIf="distribution.uri !== distributions[index - 1].uri"> <nb-icon icon="plus-outline" status="primary"> </nb-icon> @@ -206,8 +259,7 @@ <nb-list-item *ngFor="let data of datasetMappedMetadatas[index][0] | keyvalue; trackBy:trackByIndex; "> <div class="row"> - <div class="col-3"><label - for="{{data.key}}">{{datasets[data.key].uri}}</label> + <div class="col-3"><label for="{{data.key}}">{{datasets[data.key].uri}}</label> </div> <div class="col-7"> <ng-template #normal> @@ -225,8 +277,7 @@ <li> <div class="row"> <div class="col-3"> - <label - for="{{data.key}}">{{datasets[data.key].uri}}</label> + <label for="{{data.key}}">{{datasets[data.key].uri}}</label> </div> <div class="col-7"> <input nbInput [ngModel]="val" @@ -253,52 +304,52 @@ </nb-list> </nb-card> - <nb-card *ngFor="let distrib of distributionMappedMetadatas[index]; trackBy:trackByIndex; let i = index"> + <nb-card + *ngFor="let distrib of distributionMappedMetadatas[index]; trackBy:trackByIndex; let i = index"> <nb-card-header> Distribution {{i + 1}}</nb-card-header> - <nb-list > - <nb-list-item - *ngFor="let data of distrib| keyvalue ; trackBy:trackByIndex;"> - <div class="row"> - <div class="col-3"><label - for="{{data.key}}">{{distributions[data.key].uri}}</label> - </div> - <div class="col-7"> - <ng-container> - <input nbInput [ngModel]="data.value" - (ngModelChange)="data[index].set(data.key, $event)" /> - </ng-container> - <ng-container - *ngIf="isArray(data.value) "> - <ul *ngFor="let val of data.value" style="margin-left: -100px;"> - <li> - <div class="row"> - <div class="col-3"> - <label - for="{{data.key}}">{{distributions[data.key].uri}}</label> - </div> - <div class="col-7"> - <input nbInput [ngModel]="val" - (ngModelChange)="data[index].set(data.key, $event)" /> - </div> - <div class="col-2"> - + <nb-list> + <nb-list-item *ngFor="let data of distrib| keyvalue ; trackBy:trackByIndex;"> + <ng-container *ngIf="distributions[data.key].uri !== 'dcat:distribution'"> + <div class="row"> + <div class="col-3"><label + for="{{data.key}}">{{distributions[data.key].uri}}</label> + </div> + <div class="col-7"> + <ng-container> + <input nbInput [ngModel]="data.value" + (ngModelChange)="data[index].set(data.key, $event) " /> + </ng-container> + <ng-container *ngIf="isArray(data.value) "> + <ul *ngFor="let val of data.value" style="margin-left: -100px;"> + <li> + <div class="row"> + <div class="col-3"> + <label + for="{{data.key}}">{{distributions[data.key].uri}}</label> + </div> + <div class="col-7"> + <input nbInput [ngModel]="val" + (ngModelChange)="data[index].set(data.key, $event)" /> + </div> + <div class="col-2"> + + </div> </div> - </div> - </li> - </ul> - </ng-container> - - </div> - <div class="col-2"> - <button nbButton ghost> - <nb-icon icon="trash-2-outline" status="danger" - (click)="deleteProperty(data.key, data)"> - </nb-icon> - </button> + </li> + </ul> + </ng-container> + + </div> + <div class="col-2"> + <button nbButton ghost> + <nb-icon icon="trash-2-outline" status="danger" + (click)="deleteProperty(data.key, data)"> + </nb-icon> + </button> + </div> </div> - </div> + </ng-container> </nb-list-item> - </nb-list> </nb-card> <div class="row"> diff --git a/src/app/mapping/mapping.component.ts b/src/app/mapping/mapping.component.ts index fc9f429d1..152445461 100644 --- a/src/app/mapping/mapping.component.ts +++ b/src/app/mapping/mapping.component.ts @@ -7,7 +7,7 @@ import { Router } from '@angular/router'; import { Observable, of } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { catchError, map } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; import { TokenStorageService } from '../authentication/services/token-storage.service'; import { DatasetCrudService } from '../datasets/services/dataset-crud.service'; @@ -25,7 +25,6 @@ import { JSONPath } from 'jsonpath-plus'; }) export class MappingComponent implements OnInit { - distributionValues: string = ''; addDistribution = false check = false; distributions: Property[] = []; @@ -124,7 +123,7 @@ export class MappingComponent implements OnInit { createDataset(item: Object, classDcat: string): Map<number, string> { let mappedMetadata: Map<number, string> = new Map() - const array: string[] = (classDcat === "dataset") ? this.selectedPaths : this.distributionSelectedPaths + const array: string[] = (classDcat === "dataset") ? this.selectedPaths : this.distributionSelectedPaths; for (let i = 0; i < array.length; i++) { if (array[i] && array.length > 0) { let tab = array[i].split(' : '); @@ -329,60 +328,82 @@ export class MappingComponent implements OnInit { } }); } -private getValueJsonPath(jsonPath: string, item: Object) { - let value = JSONPath({ - path: jsonPath, - json: item - }) + private getValueJsonPath(jsonPath: string, item: Object) { + let value = JSONPath({ + path: jsonPath, + json: item + }) + + if (value === null || value === "") { + value = "undefined"; + } - if (value === null || value === "") { - value = "undefined"; + return value; } - - return value; -} private getValueCustom(tab: string[], item: Object) { let obj: Object; - if (tab.length == 1) { - return item[tab[0]]; - } else { - for (let i = 0; i < tab.length; i++) { - if (i == 0) { - obj = item[tab[i]] - } else if (i < tab.length - 1 && obj[tab[i]]) { - obj = obj[tab[i]]; - } else { - if (Array.isArray(obj) && obj.some(e => typeof e === 'object')) { - let array = []; - obj.forEach(e => { - if (e[tab[i]]) { - array.push(e[tab[i]]); - } - }); - return array; - } else if (typeof obj === 'object' && Object.values(obj).every(e => Array.isArray(e))) { - let array = []; - for (let element in obj) { - obj[element].forEach(e => { + try { + if (tab.length == 1) { + return item[tab[0]]; + } else { + for (let i = 0; i < tab.length; i++) { + if (i == 0) { + obj = item[tab[i]] + } else if (i < tab.length - 1 && obj[tab[i]]) { + obj = obj[tab[i]]; + } else { + if (Array.isArray(obj) && obj.some(e => typeof e === 'object')) { + let array = []; + obj.forEach(e => { if (e[tab[i]]) { array.push(e[tab[i]]); } - }) + }); + return array; + } else if (typeof obj === 'object' && Object.values(obj).every(e => Array.isArray(e))) { + let array = []; + for (let element in obj) { + obj[element].forEach(e => { + if (e[tab[i]]) { + array.push(e[tab[i]]); + } + }) + } + return array; + } else if (Array.isArray(obj[tab[i]])) { + return Object.values(obj[tab[i]]); + } else { + return obj[tab[i]]; } - return array; - } else if (Array.isArray(obj[tab[i]])) { - return Object.values(obj[tab[i]]); - } else { - return obj[tab[i]]; } } } + } catch { + return "undefined" + } + + + + } + private getDistributionItem(tab: string[], item: Object) { + if (tab.length === 0) { + return []; + } + let currentPath = tab[0]; + if (!item.hasOwnProperty(currentPath) || item[currentPath] == null) { + return []; + } + + if (tab.length === 1 ) { + return item[currentPath]; + } else { + return this.getDistributionItem(tab.slice(1), item[currentPath]); } } private getValueDataverse(tab: string[], item: Object): string { - let obj: Object + let obj: Object for (let i = 0; i < tab.length; i++) { if (tab.length == 1) { return item[tab[0]]; @@ -437,15 +458,18 @@ private getValueJsonPath(jsonPath: string, item: Object) { this.distributionMappedMetadatas = new Array<Array<Map<number, string>>>() for (let i = 0; i < this.itemsdataset.length; i++) { this.datasetMappedMetadatas.push([this.createDataset(this.itemsdataset[i], "dataset")]); - if (this.distributionValues !== '') { - let distributionItems: Object[] = (this.isJsonPath) ? this.getValueJsonPath(this.distributionValues, this.itemsdataset[i]) : this.getValueCustom(this.distributionValues.split(' : '), this.itemsdataset[i]); - let distributionArray: Map<number, string>[] = [] - for (let j = 0; j < distributionItems.length; j++) { - distributionArray.push(this.createDataset(distributionItems[j], "distribution")); + if (this.distributionSelectedPaths.length > 0) { + if (this.distributionSelectedPaths[0] !== '' && this.distributionSelectedPaths[0] !== null && this.distributionSelectedPaths[0]) { + let distributionItems: Object[] = (this.isJsonPath) ? this.getValueJsonPath(this.distributionSelectedPaths[0], this.itemsdataset[i]) : this.getDistributionItem(this.distributionSelectedPaths[0].split(' : '), this.itemsdataset[i]); + let distributionArray: Map<number, string>[] = [] + for (let j = 0; j < distributionItems.length; j++) { + let item = distributionItems[j] + distributionArray.push(this.createDataset(distributionItems[j], "distribution")); + } + this.distributionMappedMetadatas.push(distributionArray); + } else { + this.distributionMappedMetadatas.push([this.createDataset(this.itemsdataset[i], "distribution")]) } - this.distributionMappedMetadatas.push(distributionArray); - } else { - this.distributionMappedMetadatas.push([this.createDataset(this.itemsdataset[i], "distribution")]) } } this.first = false; @@ -517,7 +541,8 @@ private getValueJsonPath(jsonPath: string, item: Object) { const files: FileList = (event.target as HTMLInputElement).files; const jsonFile = files[0]; const reader = new FileReader(); - + this.selectedPaths = []; + this.distributionSelectedPaths = []; reader.onloadend = () => { if (jsonFile.name.split('.')[1] === "tsv") { let paths: ResponseFileTsv[] = <ResponseFileTsv[]>this.mappingService.tsvToJson(reader.result as string); @@ -574,7 +599,7 @@ private getValueJsonPath(jsonPath: string, item: Object) { paths.splice(index + 1, 0, ''); - + } deleteField(index: number, properties: Property[], paths: string[]) { diff --git a/src/assets/distribution.json b/src/assets/distribution.json index eef15addc..50031f570 100644 --- a/src/assets/distribution.json +++ b/src/assets/distribution.json @@ -1,4 +1,11 @@ [ + { + "property": "distribution", + "uri": "dcat:distribution", + "usageNote": "fill the path to access to the distribution values if they are contained in an array ", + "card": "0..1", + "geodcat": false + }, { "property": "media type", "uri": "dcat:mediaType", diff --git a/src/assets/geodcat.json b/src/assets/geodcat.json index 0c50b926a..b39da5a18 100644 --- a/src/assets/geodcat.json +++ b/src/assets/geodcat.json @@ -41,13 +41,6 @@ "card": "0..1", "geodcat": false }, - { - "property": "dataset distribution", - "uri": "dcat:distribution", - "usageNote": "Recommended property. This property links the Dataset to an available Distribution.", - "card": "0..n", - "geodcat": false - }, { "property": "keyword/ tag", "uri": "dcat:keyword", -- GitLab