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