From d8311c33e4ae30af01d8a127b474ec81fb1b1a31 Mon Sep 17 00:00:00 2001
From: Charly <maeder@cines.fr>
Date: Wed, 30 Jun 2021 12:56:58 +0200
Subject: [PATCH 1/5] Add catalog list with name, get and save open api
 description in mongodb

---
 src/app/publishapi/class/openapi-dto.ts       |  22 +-
 src/app/publishapi/class/openapi.ts           |  23 +-
 src/app/publishapi/publishapi.component.html  | 457 +++++++++---------
 src/app/publishapi/publishapi.component.ts    |  85 +++-
 .../services/openapi-dto-mapping-service.ts   |  31 +-
 .../publishapi/services/openapi-service.ts    |  16 +
 src/app/services/catalog.service.spec.ts      |  16 +
 src/app/services/catalog.service.ts           |  27 ++
 8 files changed, 416 insertions(+), 261 deletions(-)
 create mode 100644 src/app/services/catalog.service.spec.ts
 create mode 100644 src/app/services/catalog.service.ts

diff --git a/src/app/publishapi/class/openapi-dto.ts b/src/app/publishapi/class/openapi-dto.ts
index 69ed5c5e3..ae152b627 100644
--- a/src/app/publishapi/class/openapi-dto.ts
+++ b/src/app/publishapi/class/openapi-dto.ts
@@ -27,35 +27,47 @@ export interface ResponseSchemaDTO {
 }
 
 export interface ContentDTO {
-    schema: ResponseSchemaDTO
+    schema: ResponseSchemaDTO;
+    contentType: string;
 }
 
 export type MimeTypeToContentMapDTO = Map<string,ContentDTO>;
 
 export interface ResponseDTO {
     description: string,
-    content: MimeTypeToContentMapDTO
+    content: any;
+    httpStatusCode: string;
 }
 
 export type HttpCodeToResponseMapDTO = Map<HttpStatusCode,ResponseDTO>;
 
 export interface RequestDTO {
+    httpmethod: string;
     description: string,
     tags: string[]
     parameters: ParameterDTO[],
-    responses : HttpCodeToResponseMapDTO,
+    responses : any;
 }
 
 export type MethodToRequestMapDTO = Map<HttpMethod,RequestDTO>;
 
 export type PathMapDTO = Map<string,MethodToRequestMapDTO>;
 
-export type InfoMapDTO = Map<string,string>;
+export type InfoMapDTO = {
+    title: string;
+    version: string;
+    description: string;
+    'x-catalog-id': string;
+    'x-format': string;
+    'x-page-param': string;
+    'x-result': string;
+    'x-start-param': string;
+};
 
 export interface OpenApiDTO {
     openapi: string;
     info: InfoMapDTO;
     servers: ServerDTO[];
-    paths: PathMapDTO;
+    paths: any;
 }
 
diff --git a/src/app/publishapi/class/openapi.ts b/src/app/publishapi/class/openapi.ts
index 2baff9632..275f8bee9 100644
--- a/src/app/publishapi/class/openapi.ts
+++ b/src/app/publishapi/class/openapi.ts
@@ -51,12 +51,31 @@ export interface Path {
     requests: Request[]
 }
 
-export type InfoMap = Map<string,string>;
+export class InfoMap {
+    title: string;
+    version: string;
+    description: string;
+    'x-catalog-id': string;
+    'x-format': string;
+    'x-page-param': string;
+    'x-result': string;
+    'x-start-param': string;
 
-export interface OpenApi {
+    constructor(catId: string) {
+        this['x-catalog-id'] = catId;
+    }
+};
+
+export class OpenApi {
     openapi: string;
     info: InfoMap;
     servers: Server[];
     paths: Path[];
+
+    constructor(catId: string) {
+        this.info = new InfoMap(catId);
+        this.servers = [];
+        this.paths = [];
+    }
 }
 
diff --git a/src/app/publishapi/publishapi.component.html b/src/app/publishapi/publishapi.component.html
index 952801a18..5c095fc9f 100644
--- a/src/app/publishapi/publishapi.component.html
+++ b/src/app/publishapi/publishapi.component.html
@@ -1,268 +1,283 @@
-
 <!--<button class="next-step-button" routerLink="/datasets" routerLinkActive="active" >Next step</button>-->
 
 <!--Nebula example-->
 
 <nb-card>
-    <nb-card-body>
-      <nb-stepper orientation="horizontal" disableStepNavigation>
-        <nb-step [label]="labelOne">
-          <ng-template #labelOne>First step</ng-template>
-          <h4>Describe API</h4>
-          <nb-card>
-            <nb-card-body>
-              <nb-tabset>
-                <nb-tab class="repository" tabTitle="Repository" tabIcon="hard-drive-outline">
-                  <label>Choose your Repository</label>  
-                  <nb-select class="form-control" required>
-                    <nb-option value="1">Inrae</nb-option>
-                    <nb-option value="2">Inrae-2</nb-option>
-                  </nb-select>  
-                </nb-tab>
-                <nb-tab class="header" tabTitle="Headers" tabIcon="file-text-outline">
-                  <div class="field">
-                    <label class="" for="title">Title</label>
-                    <div>
-                      <input name="title" [(ngModel)]="openApi.info.title" fullWidth nbInput/>
-                    </div>
+  <nb-card-body>
+    <nb-stepper orientation="horizontal" disableStepNavigation>
+      <nb-step [label]="labelOne">
+        <ng-template #labelOne>First step</ng-template>
+        <h4>Describe API</h4>
+        <nb-card>
+          <nb-card-body>
+            <nb-tabset>
+
+              <!-- Repository tab -->
+              <nb-tab class="repository" tabTitle="Repository" tabIcon="hard-drive-outline">
+                <label>Choose your Repository</label>
+                <nb-select #catalogSelect class="form-control" [(ngModel)]="openApi.info['x-catalog-id']" (selectedChange)="onChangeRepository($event)" required>
+                  <nb-option *ngFor="let catalog of catalogList" [value]="catalog.catId">{{catalog.title}}</nb-option>
+                </nb-select>
+              </nb-tab>
+
+
+              <nb-tab class="header" tabTitle="Headers" tabIcon="file-text-outline">
+                <div class="field">
+                  <label class="" for="title">Title</label>
+                  <div>
+                    <input name="title" [(ngModel)]="openApi.info.title" fullWidth nbInput />
                   </div>
-                  <div class="field">
-                    <label for="description">Description</label>
-                    <div>
-                      <textarea name="description " [(ngModel)]="openApi.info.description" placeholder="Textarea" fullWidth  nbInput></textarea>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="description">Description</label>
+                  <div>
+                    <textarea name="description " [(ngModel)]="openApi.info.description" placeholder="Textarea"
+                      fullWidth nbInput></textarea>
                   </div>
-                  <div class="field">
-                    <label for="version">version</label>
-                    <div>
-                      <input name="version" [(ngModel)]="openApi.info.version" fullWidth  nbInput/>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="version">version</label>
+                  <div>
+                    <input name="version" [(ngModel)]="openApi.info.version" fullWidth nbInput />
                   </div>
-                  <div class="field">
-                    <label for="x-format">x-format</label>
-                    <div>
-                      <input name="x-format" [(ngModel)]="openApi.info['x-format']" fullWidth  nbInput/>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="x-format">x-format</label>
+                  <div>
+                    <input name="x-format" [(ngModel)]="openApi.info['x-format']" fullWidth nbInput />
                   </div>
-                  <div class="field">
-                    <label for="x-result">x-result</label>
-                    <div>
-                      <input name="x-result" [(ngModel)]="openApi.info['x-result']" fullWidth  nbInput/>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="x-result">x-result</label>
+                  <div>
+                    <input name="x-result" [(ngModel)]="openApi.info['x-result']" fullWidth nbInput />
                   </div>
-                  <div class="field">
-                    <label for="x-start-param">x-start-param</label>
-                    <div>
-                      <input name="x-start-param" [(ngModel)]="openApi.info['x-start-param']" fullWidth  nbInput/>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="x-start-param">x-start-param</label>
+                  <div>
+                    <input name="x-start-param" [(ngModel)]="openApi.info['x-start-param']" fullWidth nbInput />
                   </div>
-                  <div class="field">
-                    <label for="x-page-param">x-page-param</label>
-                    <div>
-                      <input name="x-page-param" [(ngModel)]="openApi.info['x-page-param']" fullWidth  nbInput/>
-                    </div>
+                </div>
+                <div class="field">
+                  <label for="x-page-param">x-page-param</label>
+                  <div>
+                    <input name="x-page-param" [(ngModel)]="openApi.info['x-page-param']" fullWidth nbInput />
                   </div>
-                </nb-tab>
-                <nb-tab class="main" tabTitle="Main" tabIcon="edit-2-outline">
-                  <div *ngFor="let path of openApi.paths">
-                    <nb-card>
-                      <nb-card-body>
-                        <!-- <nb-icon icon="plus-outline" nbTooltip="Add path" (click)="addPath()"></nb-icon>
+                </div>
+              </nb-tab>
+              <nb-tab class="main" tabTitle="Main" tabIcon="edit-2-outline">
+                <div *ngFor="let path of openApi.paths">
+                  <nb-card>
+                    <nb-card-body>
+                      <!-- <nb-icon icon="plus-outline" nbTooltip="Add path" (click)="addPath()"></nb-icon>
                         <nb-icon icon="copy-outline" nbTooltip="Duplicate path"(click)="duplicatePath()"></nb-icon>
                         <nb-icon icon="edit-2-outline" nbTooltip="Edit path description"(click)="editDescriptionPath()"></nb-icon>
                         <ng-container *ngIf="openApi.paths.length>1">
                           <nb-icon icon="trash-2-outline" nbTooltip="Delete path" (click)="deletePath(path)"></nb-icon>
                         </ng-container> -->
-                        <h5 *ngIf="path.requests[0].tags[0]=='datasetlist'">Get list of datasets</h5>
-                        <h5 *ngIf="path.requests[0].tags[0]=='dataset'">Get dataset</h5>
-                        <label for="Path">Path</label>
-                        <input name="path" [(ngModel)]="path.pathName" nbInput/>
-                        <div *ngFor="let request of path.requests">
-                          <nb-card>
-                            <nb-card-body>
-                              <div class="request">
-                                <label>Request</label><br/>
-                                <!-- <nb-icon icon="menu-outline" nbTooltip="Toggle Request" (click)="togglRequest(request)"></nb-icon>
+                      <h5 *ngIf="path.requests[0].tags[0]=='datasetlist'">Get list of datasets</h5>
+                      <h5 *ngIf="path.requests[0].tags[0]=='dataset'">Get dataset</h5>
+                      <label for="Path">Path</label>
+                      <input name="path" [(ngModel)]="path.pathName" nbInput />
+                      <div *ngFor="let request of path.requests">
+                        <nb-card>
+                          <nb-card-body>
+                            <div class="request">
+                              <label>Request</label><br />
+                              <!-- <nb-icon icon="menu-outline" nbTooltip="Toggle Request" (click)="togglRequest(request)"></nb-icon>
                                  <nb-icon icon="plus-outline" nbTooltip="Add Request" (click)="addRequest(path)"></nb-icon>
                                 <nb-icon icon="copy-outline" nbTooltip="Duplicate Request" (click)="DuplicateRequest(path)"></nb-icon>
                                 <ng-container *ngIf="path.requests.length>1">
                                   <nb-icon icon="trash-2-outline" nbTooltip="Delete Request" (click)="deleteRequest(path, request)"></nb-icon>
                                 </ng-container> -->
-                                <span class="title">{{request.httpmethod}}</span>
-                                <span class="title">{{request.description}}</span>
-                                <div class="requestbody">
-                                  <nb-tabset>
-                                    <nb-tab tabTitle="Main" tabIcon="settings-2-outline">
+                              <span class="title">{{request.httpmethod}}</span>
+                              <span class="title">{{request.description}}</span>
+                              <div class="requestbody">
+                                <nb-tabset>
+                                  <nb-tab tabTitle="Main" tabIcon="settings-2-outline">
+                                    <nb-card>
+                                      <nb-card-body>
+                                        <table>
+                                          <thead>
+                                            <tr>
+                                              <th>Method</th>
+                                              <th>Description</th>
+                                            </tr>
+                                          </thead>
+                                          <tbody>
+                                            <tr>
+                                              <td>
+                                                <nb-select [(ngModel)]="request.httpmethod">
+                                                  <nb-option value="get">GET</nb-option>
+                                                  <nb-option value="post">POST</nb-option>
+                                                  <nb-option value="put">PUT</nb-option>
+                                                  <nb-option value="patch">PATCH</nb-option>
+                                                  <nb-option value="delete">DELETE</nb-option>
+                                                  <nb-option value="head">HEAD</nb-option>
+                                                  <nb-option value="options">OPTIONS</nb-option>
+                                                </nb-select>
+                                              </td>
+                                              <td>
+                                                <input name="description" [(ngModel)]="request.description" nbInput />
+                                              </td>
+                                            </tr>
+                                          </tbody>
+                                        </table>
+                                      </nb-card-body>
+                                    </nb-card>
+                                  </nb-tab>
+                                  <nb-tab tabTitle="Parameters" tabIcon="list-outline">
+                                    <nb-card>
+                                      <nb-card-body>
+                                        <label>Parameters</label>
+                                        <table>
+                                          <thead>
+                                            <tr>
+                                              <th>Name</th>
+                                              <th>Location</th>
+                                              <th>Type</th>
+                                              <th>Default value</th>
+                                              <th></th>
+                                            </tr>
+                                          </thead>
+                                          <tbody>
+                                            <tr *ngFor="let parameter of request.parameters">
+                                              <td>
+                                                <input [(ngModel)]="parameter.name" nbInput />
+                                              </td>
+                                              <td>
+                                                <nb-select [(ngModel)]="parameter.in">
+                                                  <nb-option *ngFor="let type of parametersTypes" value="{{type}}">
+                                                    {{type}}</nb-option>
+                                                </nb-select>
+                                              </td>
+                                              <td>
+                                                <nb-select [(ngModel)]="parameter.schema.type">
+                                                  <nb-option *ngFor="let type of shemaTypes" value="{{type}}">{{type}}
+                                                  </nb-option>
+                                                </nb-select>
+                                              </td>
+                                              <td>
+                                                <input name="default" [(ngModel)]="parameter.schema.default" nbInput />
+                                              </td>
+                                              <td>
+                                                <nb-icon icon="plus-outline" nbTooltip="Add parameter"
+                                                  (click)="addParameter(request)"></nb-icon>
+                                                <nb-icon icon="copy-outline" nbTooltip="Duplicate parameter"
+                                                  (click)="duplicateParameter(request, parameter)"></nb-icon>
+                                                <ng-container *ngIf="request.parameters.length>1">
+                                                  <nb-icon icon="trash-2-outline" nbTooltip="Delete parameter"
+                                                    (click)="deleteParameter(request, parameter)"></nb-icon>
+                                                </ng-container>
+                                              </td>
+                                            </tr>
+                                          </tbody>
+                                        </table>
+                                      </nb-card-body>
+                                    </nb-card>
+                                  </nb-tab>
+                                  <nb-tab tabTitle="Response" tabIcon="checkmark-circle-2-outline">
+                                    <div *ngFor="let response of request.responses">
                                       <nb-card>
                                         <nb-card-body>
+                                          <label>Reponse</label><br />
+                                          <!-- <nb-icon icon="plus-outline" nbTooltip="Add Response" (click)="addResponse(request)"></nb-icon>
+                                            <nb-icon icon="copy-outline" nbTooltip="Duplicate Response" (click)="duplicateResponse(request)"></nb-icon>
+                                            <ng-container *ngIf="request.responses.length>1">
+                                              <nb-icon icon="trash-2-outline" nbTooltip="Delete Response" (click)="deleteResponse(request, response)"></nb-icon>
+                                            </ng-container> -->
                                           <table>
                                             <thead>
                                               <tr>
-                                                <th>Method</th>
+                                                <th>Http Status Code</th>
+                                                <th>Media-Type</th>
                                                 <th>Description</th>
                                               </tr>
                                             </thead>
                                             <tbody>
                                               <tr>
                                                 <td>
-                                                  <nb-select [(ngModel)]="request.httpmethod">
-                                                    <nb-option value="get">GET</nb-option>
-                                                    <nb-option value="post">POST</nb-option>
-                                                    <nb-option value="put">PUT</nb-option>
-                                                    <nb-option value="patch">PATCH</nb-option>
-                                                    <nb-option value="delete">DELETE</nb-option>
-                                                    <nb-option value="head">HEAD</nb-option>
-                                                    <nb-option value="options">OPTIONS</nb-option>
-                                                  </nb-select>
-                                                </td>
-                                                <td>
-                                                  <input name="description" [(ngModel)]="request.description" nbInput/>
-                                                </td>
-                                              </tr>
-                                            </tbody>
-                                          </table>
-                                        </nb-card-body>
-                                      </nb-card>
-                                    </nb-tab>
-                                    <nb-tab tabTitle="Parameters" tabIcon="list-outline">
-                                      <nb-card>
-                                        <nb-card-body>
-                                          <label>Parameters</label>
-                                          <table>
-                                            <thead>
-                                              <tr>
-                                                <th>Name</th>
-                                                <th>Location</th>
-                                                <th>Type</th>
-                                                <th>Default value</th>
-                                                <th></th>
-                                              </tr>
-                                            </thead>
-                                            <tbody>
-                                              <tr *ngFor="let parameter of request.parameters">
-                                                <td>
-                                                  <input [(ngModel)]="parameter.name" nbInput/>
-                                                </td>
-                                                <td>
-                                                  <nb-select [(ngModel)]="parameter.in">
-                                                    <nb-option *ngFor="let type of parametersTypes" value="{{type}}">{{type}}</nb-option>
+                                                  <nb-select>
+                                                    <nb-option *ngFor="let code of httpStatusCodes" value="{{code}}">
+                                                      {{code}}</nb-option>
                                                   </nb-select>
                                                 </td>
                                                 <td>
-                                                  <nb-select [(ngModel)]="parameter.schema.type">
-                                                    <nb-option *ngFor="let type of shemaTypes" value="{{type}}">{{type}}</nb-option>
-                                                  </nb-select>
-                                                </td>
-                                                <td>
-                                                  <input name="default" [(ngModel)]="parameter.schema.default" nbInput/>
+                                                  <div *ngFor="let content of response.contents">
+                                                    <input name="default" [(ngModel)]="content.contentType" nbInput />
+                                                  </div>
                                                 </td>
                                                 <td>
-                                                  <nb-icon icon="plus-outline" nbTooltip="Add parameter" (click)="addParameter(request)"></nb-icon>
-                                                  <nb-icon icon="copy-outline" nbTooltip="Duplicate parameter" (click)="duplicateParameter(request, parameter)"></nb-icon>
-                                                  <ng-container *ngIf="request.parameters.length>1">
-                                                    <nb-icon icon="trash-2-outline" nbTooltip="Delete parameter" (click)="deleteParameter(request, parameter)"></nb-icon>
-                                                  </ng-container>
+                                                  <input name="default" [(ngModel)]="response.description" nbInput />
                                                 </td>
                                               </tr>
                                             </tbody>
                                           </table>
                                         </nb-card-body>
                                       </nb-card>
-                                    </nb-tab>
-                                    <nb-tab tabTitle="Response" tabIcon="checkmark-circle-2-outline">
-                                      <div *ngFor="let response of request.responses">
-                                        <nb-card>
-                                          <nb-card-body>
-                                            <label>Reponse</label><br/>
-                                            <!-- <nb-icon icon="plus-outline" nbTooltip="Add Response" (click)="addResponse(request)"></nb-icon>
-                                            <nb-icon icon="copy-outline" nbTooltip="Duplicate Response" (click)="duplicateResponse(request)"></nb-icon>
-                                            <ng-container *ngIf="request.responses.length>1">
-                                              <nb-icon icon="trash-2-outline" nbTooltip="Delete Response" (click)="deleteResponse(request, response)"></nb-icon>
-                                            </ng-container> -->
-                                            <table>
-                                              <thead>
-                                                <tr>
-                                                  <th>Http Status Code</th>
-                                                  <th>Media-Type</th>
-                                                  <th>Description</th>
-                                                </tr>
-                                              </thead>
-                                              <tbody>
-                                                <tr>
-                                                  <td>
-                                                    <nb-select>
-                                                      <nb-option *ngFor="let code of httpStatusCodes" value="{{code}}">{{code}}</nb-option>
-                                                    </nb-select>
-                                                  </td>
-                                                  <td>
-                                                    <div *ngFor="let content of response.contents">
-                                                      <input name="default" [(ngModel)]="content.contentType" nbInput/>
-                                                    </div>
-                                                  </td>
-                                                  <td>
-                                                    <input name="default" [(ngModel)]="response.description" nbInput/>
-                                                  </td>
-                                                </tr>
-                                              </tbody>
-                                            </table>
-                                          </nb-card-body>
-                                        </nb-card>
-                                      </div>
-                                    </nb-tab>
-                                  </nb-tabset>
-                                </div>
+                                    </div>
+                                  </nb-tab>
+                                </nb-tabset>
                               </div>
-                            </nb-card-body>
-                          </nb-card>
-                        </div>
-                      </nb-card-body>
-                    </nb-card>
-                  </div>
-                </nb-tab>
-                <nb-tab class="json" tabTitle="JSON" tabIcon="file-text-outline">
-                  <nb-card>
-                    <nb-card-body>
-                      <button nbButton type="button" (click)="selectAllJson()"><nb-icon icon="copy-outline"></nb-icon>Select all</button>
-                      <button nbButton type="button" (click)="downloadJson()"><nb-icon icon="download-outline"></nb-icon>Download</button>
-                      <button nbButton type="button" (click)="openFileInputDialog()"><nb-icon icon="upload-outline"></nb-icon>Import</button>
-                      <input id="jsonfileinput" type="file" (change)="importJson($event)" />
-                      <pre id="json">{{getPrettyJson()}}</pre>
+                            </div>
+                          </nb-card-body>
+                        </nb-card>
+                      </div>
                     </nb-card-body>
                   </nb-card>
-                </nb-tab>
-              </nb-tabset>
-            </nb-card-body>
-          </nb-card>
-          <button class="prev-button" nbButton disabled nbStepperNext>prev</button>
-          <button class="next-button" nbButton nbStepperNext>next</button>
-        </nb-step>
-        <nb-step [label]="labelTwo">
-          <ng-template #labelTwo>Second step</ng-template>
-          <h4>Use parameters & launch request</h4>
-          <p class="lorem">
-            Use parameters & launch request
-          </p>
-          <button class="prev-button" nbButton nbStepperPrevious>prev</button>
-          <button class="next-button" nbButton nbStepperNext>next</button>
-        </nb-step>
-        <nb-step [label]="labelThree">
-          <ng-template #labelThree>Third step</ng-template>
-          <h4>Map DCAT Schema </h4>
-          <p class="lorem">
-            Map your metadata schema with DCAT schema
-          </p>
-          <button class="prev-button" nbButton nbStepperPrevious>prev</button>
-          <button class="next-button" nbButton nbStepperNext>next</button>
-        </nb-step>
-        <nb-step [label]="labelFour">
-          <ng-template #labelFour>Fourth step</ng-template>
-          <h4>Populate FDP</h4>
-          <p class="lorem">
-            Populate FDP with datasets metadata
-          </p>
-          <button class="prev-button" nbButton nbStepperPrevious>prev</button>
-          <button class="next-button" nbButton disabled nbStepperNext>next</button>
-        </nb-step>
-      </nb-stepper>
-    </nb-card-body>
-  </nb-card>
+                </div>
+              </nb-tab>
+              <nb-tab class="json" tabTitle="JSON" tabIcon="file-text-outline">
+                <nb-card>
+                  <nb-card-body>
+                    <button nbButton type="button" (click)="selectAllJson()">
+                      <nb-icon icon="copy-outline"></nb-icon>Select all
+                    </button>
+                    <button nbButton type="button" (click)="downloadJson()">
+                      <nb-icon icon="download-outline"></nb-icon>Download
+                    </button>
+                    <button nbButton type="button" (click)="openFileInputDialog()">
+                      <nb-icon icon="upload-outline"></nb-icon>Import
+                    </button>
+                    <input id="jsonfileinput" type="file" (change)="importJson($event)" />
+                    <pre id="json">{{getPrettyJson()}}</pre>
+                  </nb-card-body>
+                </nb-card>
+              </nb-tab>
+            </nb-tabset>
+          </nb-card-body>
+        </nb-card>
+        <button class="prev-button" nbButton disabled nbStepperNext>prev</button>
+        <button class="next-button" nbButton nbStepperNext [disabled]="openApi.info['x-catalog-id'] == null" (click)="savePublication()">next</button>
+      </nb-step>
+      <nb-step [label]="labelTwo">
+        <ng-template #labelTwo>Second step</ng-template>
+        <h4>Use parameters & launch request</h4>
+        <p class="lorem">
+          Use parameters & launch request
+        </p>
+        <button class="prev-button" nbButton nbStepperPrevious>prev</button>
+        <button class="next-button" nbButton nbStepperNext>next</button>
+      </nb-step>
+      <nb-step [label]="labelThree">
+        <ng-template #labelThree>Third step</ng-template>
+        <h4>Map DCAT Schema </h4>
+        <p class="lorem">
+          Map your metadata schema with DCAT schema
+        </p>
+        <button class="prev-button" nbButton nbStepperPrevious>prev</button>
+        <button class="next-button" nbButton nbStepperNext>next</button>
+      </nb-step>
+      <nb-step [label]="labelFour">
+        <ng-template #labelFour>Fourth step</ng-template>
+        <h4>Populate FDP</h4>
+        <p class="lorem">
+          Populate FDP with datasets metadata
+        </p>
+        <button class="prev-button" nbButton nbStepperPrevious>prev</button>
+        <button class="next-button" nbButton disabled nbStepperNext>next</button>
+      </nb-step>
+    </nb-stepper>
+  </nb-card-body>
+</nb-card>
\ No newline at end of file
diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts
index 5520c04bb..50e2da041 100644
--- a/src/app/publishapi/publishapi.component.ts
+++ b/src/app/publishapi/publishapi.component.ts
@@ -1,12 +1,11 @@
-import { ComponentFactoryResolver, OnDestroy, ViewChild } from '@angular/core';
-import { Component,  Input, OnInit, TemplateRef } from '@angular/core';
-import { Directive, ViewContainerRef } from '@angular/core';
-import { FormControl } from '@angular/forms';
+import { ViewChild } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { cloneDeep } from 'lodash';
+import { CatalogService } from '../services/catalog.service';
 import HttpStatusCode from './class/http-enum';
 import { OpenApi, Parameter, Path, Request, Response } from './class/openapi';
-import { OpenApiDTO } from './class/openapi-dto';
 import { ParameterType, ShemaType } from './class/openapi-enum';
+import { OpenApiDTOMappingService } from './services/openapi-dto-mapping-service';
 import { OpenApiService } from './services/openapi-service';
 
 @Component({
@@ -17,12 +16,19 @@ import { OpenApiService } from './services/openapi-service';
 
 export class PublishApiComponent implements OnInit {
 
-  constructor(private openApiService:OpenApiService) {}
+  @ViewChild('catalogSelect') catalogSelect;
+
+  constructor(
+    private openApiService: OpenApiService,
+    private catalogService: CatalogService,
+    private openApiDTOMappingService: OpenApiDTOMappingService
+  ) { }
 
   openApi: OpenApi;
   parametersTypes: string[];
   shemaTypes: string[];
   httpStatusCodes: string[];
+  catalogList: { title: string, catId: string }[] = [];
 
   ngOnInit(): void {
     this.openApi = this.openApiService.getFromJson();
@@ -30,12 +36,59 @@ export class PublishApiComponent implements OnInit {
     this.shemaTypes = Object.keys(ShemaType);
     const httpStatusCodeskeys = Object.keys(HttpStatusCode).filter(k => typeof HttpStatusCode[k as any] === "number");
     this.httpStatusCodes = httpStatusCodeskeys.map(k => HttpStatusCode[k as any]);
+    this.initCatalogList();
   }
 
   getPrettyJson(): string {
     return this.openApiService.getPrettyJson(this.openApi);
   }
 
+  initCatalogList() {
+    this.catalogService.getAllCatalogId().subscribe({
+      next: (response) => {
+        const titlePromises: Promise<any>[] = [];
+        response.forEach((catalog) => {
+          titlePromises.push(
+            this.catalogService.getCatalogContentById(catalog.catId).toPromise().then(
+              (response) => {
+                this.catalogList.push({ catId: catalog.catId, title: response[18].object.label });
+              }));
+        });
+        Promise.all(titlePromises).finally(() => {
+          if (this.catalogList.length > 0) {
+            this.updateCurrentOpenApi(this.catalogList[0].catId);
+          }
+        });
+      },
+      error: (error) => {
+        if (error.staus === 404) { /* Ignore */ }
+      }
+    });
+  }
+
+  onChangeRepository(catId: string) {
+    this.openApiService.getByCatalogId(catId).subscribe({
+      next: (response) => {
+        this.openApi = this.openApiDTOMappingService.mapOpenApiFromDTO(response);
+        this.openApi.info['x-catalog-id'] = catId;
+      },
+      error: () => {
+        this.openApi = this.openApiService.getFromJson();
+        this.openApi.info['x-catalog-id'] = catId;
+      }
+    })
+  }
+
+  updateCurrentOpenApi(catId: string) {
+    this.openApi.info['x-catalog-id'] = catId;
+    this.catalogSelect.selected = catId;
+    this.onChangeRepository(catId);
+  }
+
+  savePublication() {
+    this.openApiService.publishOpenApi(this.openApi).subscribe();
+  }
+
   selectAllJson(): void {
     var range = document.createRange();
     range.selectNodeContents(document.getElementById('json'));
@@ -47,8 +100,8 @@ export class PublishApiComponent implements OnInit {
   downloadJson(): void {
     const newBlob = new Blob([this.openApiService.getPrettyJson(this.openApi)], { type: 'application/json' });
     if (window.navigator && window.navigator.msSaveOrOpenBlob) {
-        window.navigator.msSaveOrOpenBlob(newBlob);
-        return;
+      window.navigator.msSaveOrOpenBlob(newBlob);
+      return;
     }
     const data = window.URL.createObjectURL(newBlob);
     const link = document.createElement('a');
@@ -56,10 +109,10 @@ export class PublishApiComponent implements OnInit {
     link.download = 'openAPI.json';
     // this is necessary as link.click() does not work on the latest firefox
     link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
-    setTimeout( () => {
-        // For Firefox it is necessary to delay revoking the ObjectURL
-        window.URL.revokeObjectURL(data);
-        link.remove();
+    setTimeout(() => {
+      // For Firefox it is necessary to delay revoking the ObjectURL
+      window.URL.revokeObjectURL(data);
+      link.remove();
     }, 100);
   }
 
@@ -123,20 +176,20 @@ export class PublishApiComponent implements OnInit {
     document.getElementById('jsonfileinput').click();
   }
 
-  importJson(event:Event): void {
+  importJson(event: Event): void {
     const files: FileList = (event.target as HTMLInputElement).files;
     const jsonFile: File = files[0];
     var reader = new FileReader();
 
-    reader.onload = ()=> {
+    reader.onload = () => {
       console.log(reader.result as string);
       this.openApi = this.openApiService.getFromString(reader.result as string);
     };
 
-    reader.readAsText(jsonFile);    
+    reader.readAsText(jsonFile);
   }
 
-  goToLink()  {
+  goToLink() {
     window.open("/swaggerapi");
   }
 
diff --git a/src/app/publishapi/services/openapi-dto-mapping-service.ts b/src/app/publishapi/services/openapi-dto-mapping-service.ts
index 35ca0498a..0aadbacc6 100644
--- a/src/app/publishapi/services/openapi-dto-mapping-service.ts
+++ b/src/app/publishapi/services/openapi-dto-mapping-service.ts
@@ -85,31 +85,28 @@ export class OpenApiDTOMappingService {
         openApiDTO.openapi = openApi.openapi;
         openApiDTO.info = openApi.info as InfoMapDTO;
         openApiDTO.servers = openApi.servers as ServerDTO[];
-        openApiDTO.paths = new Map<string,MethodToRequestMapDTO>();
+        openApiDTO.paths = {};
         openApi.paths.forEach(path=>{
-            let methodToRequestMapDTO: MethodToRequestMapDTO = new Map<HttpMethod, RequestDTO>();
+            openApiDTO.paths[path.pathName] = {};
             path.requests.forEach(request=>{
-                let requestDTO: RequestDTO = {} as RequestDTO;
-                requestDTO.tags = request.tags;
-                requestDTO.description = request.description;
-                requestDTO.parameters = request.parameters as ParameterDTO[];
-                requestDTO.responses = {} as HttpCodeToResponseMapDTO;
+                openApiDTO.paths[path.pathName][request.httpmethod] = {};
+                openApiDTO.paths[path.pathName][request.httpmethod].tags = request.tags;
+                openApiDTO.paths[path.pathName][request.httpmethod].description = request.description;
+                openApiDTO.paths[path.pathName][request.httpmethod].parameters = request.parameters as ParameterDTO[];
+                openApiDTO.paths[path.pathName][request.httpmethod].responses = {};
                 request.responses.forEach(response=>{
-                    let httpCodeToResponseMapDTO: HttpCodeToResponseMapDTO = new Map<HttpStatusCode, ResponseDTO>();
                     let responseDTO: ResponseDTO = {} as ResponseDTO;
-                    responseDTO.content = new Map<string, ContentDTO>();
-                    responseDTO.description = response.description;
+                    openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()] = {}
+                    openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content = {};
+                    openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].description = response.description;
                     response.contents.forEach(content=>{
-                        let contentDTO: ContentDTO = {} as ContentDTO;
-                        contentDTO.schema = content.schema as ResponseSchemaDTO;
-                        responseDTO.content.set(content.contentType, contentDTO);
+                        if (openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content[content.contentType] == null) {
+                            openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content[content.contentType] = {};
+                        }
+                        openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content[content.contentType].schema = content.schema as ResponseSchemaDTO;
                     });
-                    httpCodeToResponseMapDTO.set(response.httpStatusCode,responseDTO);
-                    requestDTO.responses=httpCodeToResponseMapDTO;
                 });
-                methodToRequestMapDTO.set(request.httpmethod, requestDTO);
             });
-            openApiDTO.paths.set(path.pathName, methodToRequestMapDTO);
         });
         return openApiDTO;
     }
diff --git a/src/app/publishapi/services/openapi-service.ts b/src/app/publishapi/services/openapi-service.ts
index 140a1bf96..c8dffd47d 100644
--- a/src/app/publishapi/services/openapi-service.ts
+++ b/src/app/publishapi/services/openapi-service.ts
@@ -13,6 +13,11 @@ import { OpenApiDTOMappingService } from './openapi-dto-mapping-service';
 export class OpenApiService {
     constructor(private http: HttpClient, private openApiDTOMappingService: OpenApiDTOMappingService) {}
 
+    get smartApiUrl(): string {
+        return 'http://localhost:8080/harvester/publication'; // TO-DO
+        //return this.appConfig.smartapiurl + '/harvester/publication'
+      }
+
     getFromRepository(repositoryId:string): Observable<OpenApiDTO> {
         return this.http.get<OpenApiDTO>('/openapi/' + repositoryId);
     }
@@ -83,6 +88,17 @@ export class OpenApiService {
         return responses[0];
     }
 
+    getByCatalogId(catId: string): Observable<OpenApiDTO> {
+        return this.http.get<OpenApiDTO>(this.smartApiUrl + '/catalogs/' + catId);
+    }
+
+    publishOpenApi(openApi: OpenApi) {
+        const openApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
+        console.log(openApi);
+        console.log(openApiDTO);
+        return this.http.post(this.smartApiUrl + '/publish', openApiDTO);
+    }
+
     private jsonFull =
     '{' +
     '    "openapi" : "3.0.0",' +
diff --git a/src/app/services/catalog.service.spec.ts b/src/app/services/catalog.service.spec.ts
new file mode 100644
index 000000000..21b1429f3
--- /dev/null
+++ b/src/app/services/catalog.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { CatalogService } from './catalog.service';
+
+describe('CatalogService', () => {
+  let service: CatalogService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(CatalogService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/src/app/services/catalog.service.ts b/src/app/services/catalog.service.ts
new file mode 100644
index 000000000..30822325b
--- /dev/null
+++ b/src/app/services/catalog.service.ts
@@ -0,0 +1,27 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { AppConfiguration } from '../AppConfiguration';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class CatalogService {
+
+  constructor(
+    private appConfig: AppConfiguration,
+    private http: HttpClient
+  ) { }
+
+  get smartApiUrl(): string {
+    return 'http://localhost:8080/harvester/api'; // TO-DO
+    //return this.appConfig.smartapiurl + '/harvester/api'
+  }
+
+  getAllCatalogId() {
+    return this.http.get<{ catId: string, uuid: string }[]>(this.smartApiUrl + '/user/' + this.appConfig.fdpemail + '/catalogs');
+  }
+
+  getCatalogContentById(catId: string) {
+    return this.http.get<any>(this.appConfig.fdpurl + '/catalog/' + catId);
+  }
+}
-- 
GitLab


From 9305cd5063d842feebad557e36cee4fdcbbb9f78 Mon Sep 17 00:00:00 2001
From: Charly <maeder@cines.fr>
Date: Fri, 2 Jul 2021 17:51:15 +0200
Subject: [PATCH 2/5] Can publish complete api for catalog

---
 src/app/publishapi/class/openapi-dto.ts       |   5 +-
 src/app/publishapi/class/openapi.ts           |  13 +--
 src/app/publishapi/publishapi.component.html  | 102 +++++++++++-------
 src/app/publishapi/publishapi.component.scss  |  11 +-
 src/app/publishapi/publishapi.component.ts    |  67 ++++++++++--
 .../services/openapi-dto-mapping-service.ts   | 100 +++++++++++++----
 .../publishapi/services/openapi-service.ts    |  42 +-------
 src/app/services/catalog.service.ts           |  15 ++-
 8 files changed, 233 insertions(+), 122 deletions(-)

diff --git a/src/app/publishapi/class/openapi-dto.ts b/src/app/publishapi/class/openapi-dto.ts
index ae152b627..cd18e39eb 100644
--- a/src/app/publishapi/class/openapi-dto.ts
+++ b/src/app/publishapi/class/openapi-dto.ts
@@ -8,7 +8,7 @@ export interface ServerDTO {
 
 export interface SchemaDTO {
     type: ShemaType,
-    default: string
+    defaultValue: string
 }
 
 export interface ParameterDTO {
@@ -23,7 +23,7 @@ export interface ItemDTO {
 }
 export interface ResponseSchemaDTO {
     type: string,
-    items: ItemDTO[]
+    items: ItemDTO
 }
 
 export interface ContentDTO {
@@ -43,6 +43,7 @@ export type HttpCodeToResponseMapDTO = Map<HttpStatusCode,ResponseDTO>;
 
 export interface RequestDTO {
     httpmethod: string;
+    title: string;
     description: string,
     tags: string[]
     parameters: ParameterDTO[],
diff --git a/src/app/publishapi/class/openapi.ts b/src/app/publishapi/class/openapi.ts
index 275f8bee9..2e07b3635 100644
--- a/src/app/publishapi/class/openapi.ts
+++ b/src/app/publishapi/class/openapi.ts
@@ -2,12 +2,12 @@ import HttpStatusCode, { HttpMethod } from './http-enum'
 import { ParameterType } from './openapi-enum';
 
 export interface Server {
-    url:string;
+    url: string;
 }
 
 export interface Schema {
     type: string,
-    default: string
+    defaultValue: string
 }
 
 export interface Parameter {
@@ -23,7 +23,7 @@ export interface Item {
 
 export interface ResponseSchema {
     type: string,
-    items: Item[]
+    items: Item
 }
 
 export interface Content {
@@ -38,6 +38,7 @@ export interface Response {
 }
 
 export interface Request {
+    title: string,
     description: string,
     tags: string[]
     parameters: Parameter[],
@@ -48,7 +49,7 @@ export interface Request {
 
 export interface Path {
     pathName: string,
-    requests: Request[]
+    requests: Request[],
 }
 
 export class InfoMap {
@@ -72,9 +73,9 @@ export class OpenApi {
     servers: Server[];
     paths: Path[];
 
-    constructor(catId: string) {
+    constructor(catId: string, server: string) {
         this.info = new InfoMap(catId);
-        this.servers = [];
+        this.servers = [{ url: server }];
         this.paths = [];
     }
 }
diff --git a/src/app/publishapi/publishapi.component.html b/src/app/publishapi/publishapi.component.html
index 5c095fc9f..7d2d37c64 100644
--- a/src/app/publishapi/publishapi.component.html
+++ b/src/app/publishapi/publishapi.component.html
@@ -12,11 +12,13 @@
           <nb-card-body>
             <nb-tabset>
 
-              <!-- Repository tab -->
+              <!-- Repository tab ------------------------------------------------------------->
               <nb-tab class="repository" tabTitle="Repository" tabIcon="hard-drive-outline">
                 <label>Choose your Repository</label>
-                <nb-select #catalogSelect class="form-control" [(ngModel)]="openApi.info['x-catalog-id']" (selectedChange)="onChangeRepository($event)" required>
-                  <nb-option *ngFor="let catalog of catalogList" [value]="catalog.catId">{{catalog.title}}</nb-option>
+                <nb-select #catalogSelect class="form-control" [(ngModel)]="openApi.info['x-catalog-id']"
+                  (selectedChange)="onChangeRepository($event)" required>
+                  <nb-option *ngFor="let catalog of catalogList" [value]="catalog.catId" [title]="catalog.catId">
+                    {{catalog.title?.length > 0 ? catalog.title : catalog.catId}}</nb-option>
                 </nb-select>
               </nb-tab>
 
@@ -66,34 +68,46 @@
                   </div>
                 </div>
               </nb-tab>
+
+              <!-- Main tab ------------------------------------------------------------->
+
               <nb-tab class="main" tabTitle="Main" tabIcon="edit-2-outline">
-                <div *ngFor="let path of openApi.paths">
+                <button class="margin-bottom" nbTooltip="Add path" (click)="addPath()">
+                  <nb-icon icon="plus-outline"></nb-icon>Add path
+                </button>
+                <ng-container *ngFor="let path of openApi.paths">
                   <nb-card>
                     <nb-card-body>
-                      <!-- <nb-icon icon="plus-outline" nbTooltip="Add path" (click)="addPath()"></nb-icon>
-                        <nb-icon icon="copy-outline" nbTooltip="Duplicate path"(click)="duplicatePath()"></nb-icon>
-                        <nb-icon icon="edit-2-outline" nbTooltip="Edit path description"(click)="editDescriptionPath()"></nb-icon>
-                        <ng-container *ngIf="openApi.paths.length>1">
-                          <nb-icon icon="trash-2-outline" nbTooltip="Delete path" (click)="deletePath(path)"></nb-icon>
-                        </ng-container> -->
-                      <h5 *ngIf="path.requests[0].tags[0]=='datasetlist'">Get list of datasets</h5>
-                      <h5 *ngIf="path.requests[0].tags[0]=='dataset'">Get dataset</h5>
-                      <label for="Path">Path</label>
-                      <input name="path" [(ngModel)]="path.pathName" nbInput />
+                      <nb-icon icon="copy-outline" nbTooltip="Duplicate path" (click)="duplicatePath(path)"></nb-icon>
+                      <!-- <nb-icon icon="edit-2-outline" nbTooltip="Edit path description"(click)="editDescriptionPath()"></nb-icon> -->
+                      <ng-container *ngIf="openApi.paths.length>1">
+                        <nb-icon icon="trash-2-outline" nbTooltip="Delete path" (click)="deletePath(path)"></nb-icon>
+                      </ng-container>
+                      <div>
+                        <label for="Path">Path</label>
+                        <input name="path" [(ngModel)]="path.pathName" nbInput />
+                      </div>
+                      <div>
+                        <button class="margin-bottom" nbTooltip="Add Request" (click)="addRequest(path)">
+                          <nb-icon icon="plus-outline"></nb-icon>Add request
+                        </button>
+                      </div>
                       <div *ngFor="let request of path.requests">
                         <nb-card>
                           <nb-card-body>
                             <div class="request">
-                              <label>Request</label><br />
-                              <!-- <nb-icon icon="menu-outline" nbTooltip="Toggle Request" (click)="togglRequest(request)"></nb-icon>
-                                 <nb-icon icon="plus-outline" nbTooltip="Add Request" (click)="addRequest(path)"></nb-icon>
-                                <nb-icon icon="copy-outline" nbTooltip="Duplicate Request" (click)="DuplicateRequest(path)"></nb-icon>
-                                <ng-container *ngIf="path.requests.length>1">
-                                  <nb-icon icon="trash-2-outline" nbTooltip="Delete Request" (click)="deleteRequest(path, request)"></nb-icon>
-                                </ng-container> -->
-                              <span class="title">{{request.httpmethod}}</span>
-                              <span class="title">{{request.description}}</span>
-                              <div class="requestbody">
+                              <label>Request</label>
+                              <nb-icon icon="menu-outline" nbTooltip="Toggle Request" (click)="togglRequest(request)">
+                              </nb-icon>
+                              <nb-icon icon="copy-outline" nbTooltip="Duplicate Request"
+                                (click)="duplicateRequest(path, request)"></nb-icon>
+                              <nb-icon *ngIf="path.requests.length > 1" icon="trash-2-outline"
+                                nbTooltip="Delete Request" (click)="deleteRequest(path, request)"></nb-icon>
+                              <div>
+                                <strong class="title">{{request.httpmethod|uppercase}}</strong>
+                                <span>{{request.description}}</span>
+                              </div>
+                              <div class="requestbody" *ngIf="!request.toggled">
                                 <nb-tabset>
                                   <nb-tab tabTitle="Main" tabIcon="settings-2-outline">
                                     <nb-card>
@@ -131,6 +145,8 @@
                                     <nb-card>
                                       <nb-card-body>
                                         <label>Parameters</label>
+                                        <nb-icon icon="plus-outline" nbTooltip="Add parameter"
+                                          (click)="addParameter(request)"></nb-icon>
                                         <table>
                                           <thead>
                                             <tr>
@@ -159,17 +175,15 @@
                                                 </nb-select>
                                               </td>
                                               <td>
-                                                <input name="default" [(ngModel)]="parameter.schema.default" nbInput />
+                                                <input name="default" [(ngModel)]="parameter.schema.defaultValue"
+                                                  nbInput />
                                               </td>
                                               <td>
-                                                <nb-icon icon="plus-outline" nbTooltip="Add parameter"
-                                                  (click)="addParameter(request)"></nb-icon>
                                                 <nb-icon icon="copy-outline" nbTooltip="Duplicate parameter"
                                                   (click)="duplicateParameter(request, parameter)"></nb-icon>
-                                                <ng-container *ngIf="request.parameters.length>1">
-                                                  <nb-icon icon="trash-2-outline" nbTooltip="Delete parameter"
-                                                    (click)="deleteParameter(request, parameter)"></nb-icon>
-                                                </ng-container>
+                                                <nb-icon icon="trash-2-outline" nbTooltip="Delete parameter"
+                                                  (click)="deleteParameter(request, parameter)"
+                                                  *ngIf="request.parameters.length > 1"></nb-icon>
                                               </td>
                                             </tr>
                                           </tbody>
@@ -178,15 +192,19 @@
                                     </nb-card>
                                   </nb-tab>
                                   <nb-tab tabTitle="Response" tabIcon="checkmark-circle-2-outline">
+                                    <button nbTooltip="Add Response" (click)="addResponse(request)">
+                                      <nb-icon icon="plus-outline"></nb-icon>Add response
+                                    </button>
                                     <div *ngFor="let response of request.responses">
                                       <nb-card>
                                         <nb-card-body>
-                                          <label>Reponse</label><br />
-                                          <!-- <nb-icon icon="plus-outline" nbTooltip="Add Response" (click)="addResponse(request)"></nb-icon>
-                                            <nb-icon icon="copy-outline" nbTooltip="Duplicate Response" (click)="duplicateResponse(request)"></nb-icon>
-                                            <ng-container *ngIf="request.responses.length>1">
-                                              <nb-icon icon="trash-2-outline" nbTooltip="Delete Response" (click)="deleteResponse(request, response)"></nb-icon>
-                                            </ng-container> -->
+                                          <label>Reponse</label>
+                                          <nb-icon icon="copy-outline" nbTooltip="Duplicate Response"
+                                            (click)="duplicateResponse(request, response)"></nb-icon>
+                                          <ng-container *ngIf="request.responses.length>1">
+                                            <nb-icon icon="trash-2-outline" nbTooltip="Delete Response"
+                                              (click)="deleteResponse(request, response)"></nb-icon>
+                                          </ng-container>
                                           <table>
                                             <thead>
                                               <tr>
@@ -198,7 +216,7 @@
                                             <tbody>
                                               <tr>
                                                 <td>
-                                                  <nb-select>
+                                                  <nb-select [(ngModel)]="response.httpStatusCode">
                                                     <nb-option *ngFor="let code of httpStatusCodes" value="{{code}}">
                                                       {{code}}</nb-option>
                                                   </nb-select>
@@ -226,8 +244,11 @@
                       </div>
                     </nb-card-body>
                   </nb-card>
-                </div>
+                </ng-container>
               </nb-tab>
+
+              <!-- JSON tab ------------------------------------------------------------->
+
               <nb-tab class="json" tabTitle="JSON" tabIcon="file-text-outline">
                 <nb-card>
                   <nb-card-body>
@@ -249,7 +270,8 @@
           </nb-card-body>
         </nb-card>
         <button class="prev-button" nbButton disabled nbStepperNext>prev</button>
-        <button class="next-button" nbButton nbStepperNext [disabled]="openApi.info['x-catalog-id'] == null" (click)="savePublication()">next</button>
+        <button class="next-button" nbButton nbStepperNext [disabled]="openApi.info['x-catalog-id'] == null"
+          (click)="savePublication()">next</button>
       </nb-step>
       <nb-step [label]="labelTwo">
         <ng-template #labelTwo>Second step</ng-template>
diff --git a/src/app/publishapi/publishapi.component.scss b/src/app/publishapi/publishapi.component.scss
index c4758be30..931e6621b 100644
--- a/src/app/publishapi/publishapi.component.scss
+++ b/src/app/publishapi/publishapi.component.scss
@@ -3,6 +3,13 @@
     margin-right: 1rem;
 }
 
+.margin-bottom {
+  margin-bottom: 5px;
+}
+
+.block {
+  display: block;
+}
 
 /**
 HEADER TAB
@@ -60,7 +67,7 @@ MAIN TAB
   background: rgba(0, 0, 0, 0.030);
 }
 
-.main div.request span.title {
+.main div.request strong.title {
   margin-right: 0.32em;
 }
 
@@ -83,4 +90,4 @@ SWAGGER TAB
 #swaggereditor{
   height: 600px;
   position: relative;
-}
\ No newline at end of file
+}
diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts
index 50e2da041..f6cfb6b56 100644
--- a/src/app/publishapi/publishapi.component.ts
+++ b/src/app/publishapi/publishapi.component.ts
@@ -1,7 +1,7 @@
 import { ViewChild } from '@angular/core';
 import { Component, OnInit } from '@angular/core';
 import { cloneDeep } from 'lodash';
-import { CatalogService } from '../services/catalog.service';
+import { CatalogService, FdpApiResponseItem } from '../services/catalog.service';
 import HttpStatusCode from './class/http-enum';
 import { OpenApi, Parameter, Path, Request, Response } from './class/openapi';
 import { ParameterType, ShemaType } from './class/openapi-enum';
@@ -28,10 +28,10 @@ export class PublishApiComponent implements OnInit {
   parametersTypes: string[];
   shemaTypes: string[];
   httpStatusCodes: string[];
-  catalogList: { title: string, catId: string }[] = [];
+  catalogList: { title: string, catId: string, server: string }[] = [];
 
   ngOnInit(): void {
-    this.openApi = this.openApiService.getFromJson();
+    this.openApi = new OpenApi(null, null);
     this.parametersTypes = Object.keys(ParameterType);
     this.shemaTypes = Object.keys(ShemaType);
     const httpStatusCodeskeys = Object.keys(HttpStatusCode).filter(k => typeof HttpStatusCode[k as any] === "number");
@@ -51,11 +51,14 @@ export class PublishApiComponent implements OnInit {
           titlePromises.push(
             this.catalogService.getCatalogContentById(catalog.catId).toPromise().then(
               (response) => {
-                this.catalogList.push({ catId: catalog.catId, title: response[18].object.label });
-              }));
+                this.catalogList.push({ catId: catalog.catId, title: this.getTitleFromFdpApi(response), server: this.getServerFromFdpApi(response) });
+              }).catch(
+                () => this.catalogList.push({ catId: catalog.catId, title: catalog.catId, server: null }))
+          );
         });
         Promise.all(titlePromises).finally(() => {
           if (this.catalogList.length > 0) {
+            this.catalogList.sort((a, b) => a.catId.localeCompare(b.catId));
             this.updateCurrentOpenApi(this.catalogList[0].catId);
           }
         });
@@ -71,10 +74,10 @@ export class PublishApiComponent implements OnInit {
       next: (response) => {
         this.openApi = this.openApiDTOMappingService.mapOpenApiFromDTO(response);
         this.openApi.info['x-catalog-id'] = catId;
+        this.openApi.servers.push({ url: this.getServer(catId) });
       },
       error: () => {
-        this.openApi = this.openApiService.getFromJson();
-        this.openApi.info['x-catalog-id'] = catId;
+        this.openApi = new OpenApi(catId, this.getServer(catId));
       }
     })
   }
@@ -85,6 +88,33 @@ export class PublishApiComponent implements OnInit {
     this.onChangeRepository(catId);
   }
 
+  getTitleFromFdpApi(fdpApiResponse: FdpApiResponseItem[]): string {
+    for (const item of fdpApiResponse) {
+      if (item.predicate.localName === 'title') {
+        return item.object.label;
+      }
+    }
+    return '';
+  }
+
+  getServerFromFdpApi(fdpApiResponse: FdpApiResponseItem[]): string {
+    for (const item of fdpApiResponse) {
+      if (item.predicate.localName === 'homepage') {
+        return item.object.namespace + item.object.localName;
+      }
+    }
+    return '';
+  }
+
+  getServer(catId: string): string {
+    for (const catalog of this.catalogList) {
+      if (catalog.catId === catId) {
+        return catalog.server;
+      }
+    }
+    return null;
+  }
+
   savePublication() {
     this.openApiService.publishOpenApi(this.openApi).subscribe();
   }
@@ -117,7 +147,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addPath(): void {
-    let emptyPath: Path = this.openApiService.getEmptyPath();
+    let emptyPath: Path = this.openApiDTOMappingService.getEmptyPath()
     this.openApi.paths.unshift(emptyPath);
   }
 
@@ -129,7 +159,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addRequest(path: Path): void {
-    let emptyRequest: Request = this.openApiService.getEmptyRequest();
+    let emptyRequest: Request = this.openApiDTOMappingService.getEmptyRequest();
     path.requests.unshift(emptyRequest);
   }
 
@@ -145,7 +175,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addParameter(request: Request): void {
-    let emptyParameter: Parameter = this.openApiService.getEmptyParameter();
+    let emptyParameter: Parameter = this.openApiDTOMappingService.getEmptyParameter();
     request.parameters.unshift(emptyParameter);
   }
 
@@ -161,7 +191,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addResponse(request: Request): void {
-    let emptyResponse: Response = this.openApiService.getEmptyResponse();
+    let emptyResponse: Response = this.openApiDTOMappingService.getEmptyResponse();
     request.responses.unshift(emptyResponse);
   }
 
@@ -193,4 +223,19 @@ export class PublishApiComponent implements OnInit {
     window.open("/swaggerapi");
   }
 
+  duplicatePath(path: Path) {
+    const newPath = cloneDeep(path);
+    this.openApi.paths.unshift(newPath);
+  }
+
+  duplicateRequest(path: Path, request: Request) {
+    const newRequest = cloneDeep(request);
+    path.requests.unshift(newRequest);
+  }
+
+  duplicateResponse(request: Request, response: Response) {
+    const newResponse = cloneDeep(response);
+    request.responses.unshift(newResponse);
+  }
+
 }
diff --git a/src/app/publishapi/services/openapi-dto-mapping-service.ts b/src/app/publishapi/services/openapi-dto-mapping-service.ts
index 0aadbacc6..f70751b91 100644
--- a/src/app/publishapi/services/openapi-dto-mapping-service.ts
+++ b/src/app/publishapi/services/openapi-dto-mapping-service.ts
@@ -1,17 +1,18 @@
-import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import HttpStatusCode, { HttpMethod } from '../class/http-enum';
 import { InfoMap, OpenApi, Path, Server, Request, Parameter, Response, Content, ResponseSchema } from '../class/openapi';
 import { ContentDTO, HttpCodeToResponseMapDTO, InfoMapDTO, MethodToRequestMapDTO, MimeTypeToContentMapDTO, OpenApiDTO, ParameterDTO, PathMapDTO, RequestDTO, ResponseDTO, ResponseSchemaDTO, ServerDTO } from '../class/openapi-dto';
+import { ParameterType } from '../class/openapi-enum';
 
 @Injectable({
     providedIn: 'root'
-  })
+})
 
 export class OpenApiDTOMappingService {
-    constructor() {}
 
-    mapContentFromDTO(mimeTypeToContentMapDTO: MimeTypeToContentMapDTO, contentType: string){
+    constructor() { }
+
+    mapContentFromDTO(mimeTypeToContentMapDTO: MimeTypeToContentMapDTO, contentType: string) {
         let contentDTO: ContentDTO = mimeTypeToContentMapDTO[contentType];
         let content: Content = {} as Content;
         content.contentType = contentType;
@@ -25,7 +26,7 @@ export class OpenApiDTOMappingService {
         response.description = responseDTO.description;
         response.httpStatusCode = httpStatusCodeToreponseDTOMap as unknown as HttpStatusCode;
         response.contents = [] as Content[];
-        Object.keys(responseDTO.content).forEach((contentType)=>{
+        Object.keys(responseDTO.content).forEach((contentType) => {
             let content: Content = this.mapContentFromDTO(responseDTO.content, contentType);
             response.contents.push(content);
         });
@@ -36,41 +37,47 @@ export class OpenApiDTOMappingService {
         return parameterDTO as Parameter[];
     }
 
-    mapRequestFromDTO(methodToRequestMapDTO: MethodToRequestMapDTO, httpMethod: HttpMethod): Request{
+    mapRequestFromDTO(methodToRequestMapDTO: MethodToRequestMapDTO, httpMethod: HttpMethod): Request {
         let requestDTO: RequestDTO = methodToRequestMapDTO[httpMethod];
+
+        if (requestDTO == null) {
+            return this.getEmptyRequest();
+        }
+
         let request: Request = {} as Request;
         request.httpmethod = httpMethod;
+        request.title = requestDTO.title;
         request.description = requestDTO.description;
         request.tags = requestDTO.tags as string[];
         request.parameters = this.mapParametersFromDTO(requestDTO.parameters);
         request.responses = [] as Response[];
         request.toggled = false;
-        Object.keys(requestDTO.responses).forEach((HttpStatusCode)=>{
+        Object.keys(requestDTO.responses).forEach((HttpStatusCode) => {
             let response: Response = this.mapResponseFromDTO(requestDTO.responses, HttpStatusCode);
             request.responses.push(response);
         });
         return request;
     }
 
-    mapPathFromDTO(pathMapDTO: PathMapDTO, pathName: string): Path{
+    mapPathFromDTO(pathMapDTO: PathMapDTO, pathName: string): Path {
         let methodToRequestMapDTO: MethodToRequestMapDTO = pathMapDTO[pathName];
-        let path:Path = {} as Path;
+        let path: Path = {} as Path;
         path.pathName = pathName.trim();
         path.requests = [] as Request[];
-        Object.keys(methodToRequestMapDTO).forEach((httpMethod:HttpMethod)=>{
+        Object.keys(methodToRequestMapDTO).forEach((httpMethod: HttpMethod) => {
             let request: Request = this.mapRequestFromDTO(methodToRequestMapDTO, httpMethod);
             path.requests.push(request);
         });
         return path;
     }
 
-    mapOpenApiFromDTO(openApiDTO:OpenApiDTO): OpenApi {
-        let openApi:OpenApi = {} as OpenApi;
+    mapOpenApiFromDTO(openApiDTO: OpenApiDTO): OpenApi {
+        let openApi: OpenApi = {} as OpenApi;
         openApi.info = openApiDTO.info as InfoMap;
         openApi.openapi = openApiDTO.openapi;
         openApi.servers = openApiDTO.servers as Server[];
         openApi.paths = [] as Path[];
-        Object.keys(openApiDTO.paths).forEach((pathName)=>{
+        Object.keys(openApiDTO.paths).forEach((pathName) => {
             let path: Path = this.mapPathFromDTO(openApiDTO.paths, pathName);
             openApi.paths.push(path);
         });
@@ -80,26 +87,25 @@ export class OpenApiDTOMappingService {
     /**
      * @param openApi
      */
-    mapToDto(openApi:OpenApi): OpenApiDTO {
-        let openApiDTO:OpenApiDTO = {} as OpenApiDTO;
+    mapToDto(openApi: OpenApi): OpenApiDTO {
+        let openApiDTO: OpenApiDTO = {} as OpenApiDTO;
         openApiDTO.openapi = openApi.openapi;
         openApiDTO.info = openApi.info as InfoMapDTO;
         openApiDTO.servers = openApi.servers as ServerDTO[];
         openApiDTO.paths = {};
-        openApi.paths.forEach(path=>{
-            openApiDTO.paths[path.pathName] = {};
-            path.requests.forEach(request=>{
+        openApi.paths.forEach(path => {
+            openApiDTO.paths[path.pathName] = { };
+            path.requests.forEach(request => {
                 openApiDTO.paths[path.pathName][request.httpmethod] = {};
                 openApiDTO.paths[path.pathName][request.httpmethod].tags = request.tags;
                 openApiDTO.paths[path.pathName][request.httpmethod].description = request.description;
                 openApiDTO.paths[path.pathName][request.httpmethod].parameters = request.parameters as ParameterDTO[];
                 openApiDTO.paths[path.pathName][request.httpmethod].responses = {};
-                request.responses.forEach(response=>{
-                    let responseDTO: ResponseDTO = {} as ResponseDTO;
+                request.responses.forEach(response => {
                     openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()] = {}
                     openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content = {};
                     openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].description = response.description;
-                    response.contents.forEach(content=>{
+                    response.contents.forEach(content => {
                         if (openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content[content.contentType] == null) {
                             openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content[content.contentType] = {};
                         }
@@ -111,4 +117,56 @@ export class OpenApiDTOMappingService {
         return openApiDTO;
     }
 
+    getEmptyPath(): Path {
+        return {
+            pathName: '',
+            requests: [
+                this.getEmptyRequest()
+            ]
+        };
+    }
+
+    getEmptyRequest(): Request {
+        return {
+            description: '',
+            httpmethod: HttpMethod.GET,
+            tags: [],
+            title: '',
+            parameters: [
+                this.getEmptyParameter()
+            ],
+            responses: [
+                this.getEmptyResponse()
+            ],
+            toggled: false
+        };
+    }
+
+    getEmptyParameter(): Parameter {
+        return {
+            name: '',
+            in: ParameterType.query,
+            schema: {
+                type: 'string',
+                defaultValue: ''
+            },
+            required: true
+        };
+    }
+
+    getEmptyResponse(): Response {
+        return {
+            httpStatusCode: HttpStatusCode.ACCEPTED,
+            description: '',
+            contents: [{
+                contentType: 'application/json',
+                schema: {
+                    type: 'array',
+                    items: {
+                        type: 'string'
+                    }
+                }
+            }]
+        };
+    }
 }
diff --git a/src/app/publishapi/services/openapi-service.ts b/src/app/publishapi/services/openapi-service.ts
index c8dffd47d..415fdffd8 100644
--- a/src/app/publishapi/services/openapi-service.ts
+++ b/src/app/publishapi/services/openapi-service.ts
@@ -1,9 +1,8 @@
 import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
-import HttpStatusCode, { HttpMethod } from '../class/http-enum';
-import { OpenApi, Parameter, Path, Request, Response } from '../class/openapi';
-import { HttpCodeToResponseMapDTO, MethodToRequestMapDTO, OpenApiDTO, ParameterDTO, PathMapDTO } from '../class/openapi-dto';
+import { OpenApi } from '../class/openapi';
+import { OpenApiDTO } from '../class/openapi-dto';
 import { OpenApiDTOMappingService } from './openapi-dto-mapping-service';
 
 @Injectable({
@@ -53,41 +52,6 @@ export class OpenApiService {
         return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO);
     }
 
-    getEmptyPath(): Path {
-        let pathDTO: PathMapDTO = <PathMapDTO>JSON.parse(this.emptyPathJson);
-        let paths = [] as Path[];
-        Object.keys(pathDTO).forEach((pathName)=>{
-            let path: Path = this.openApiDTOMappingService.mapPathFromDTO(pathDTO, pathName);
-            paths.push(path);
-        });
-        return paths[0];
-    }
-
-    getEmptyRequest(): Request {
-        let methodToRequestMapDTO: MethodToRequestMapDTO = <MethodToRequestMapDTO>JSON.parse('{' + this.emptyMethodJson + '}');
-        let requests = [] as Request[];
-        Object.keys(methodToRequestMapDTO).forEach((httpMethod:HttpMethod)=>{
-            let request: Request = this.openApiDTOMappingService.mapRequestFromDTO(methodToRequestMapDTO, httpMethod);
-            requests.push(request);
-        });
-        return requests[0];
-    }
-
-    getEmptyParameter(): Parameter {
-        let parameterDTO: ParameterDTO[] = <ParameterDTO[]>JSON.parse(this.emptyParameter);
-        return this.openApiDTOMappingService.mapParametersFromDTO(parameterDTO)[0];
-    }
-
-    getEmptyResponse(): Response {
-        let httpCodeToResponseMapDTO : HttpCodeToResponseMapDTO = <HttpCodeToResponseMapDTO>JSON.parse('{' + this.emptyResponse + '}');
-        let responses = [] as Response[];
-        Object.keys(httpCodeToResponseMapDTO).forEach((httpStatusCode:string)=>{
-            let response: Response = this.openApiDTOMappingService.mapResponseFromDTO(httpCodeToResponseMapDTO, httpStatusCode);
-            responses.push(response);
-        });
-        return responses[0];
-    }
-
     getByCatalogId(catId: string): Observable<OpenApiDTO> {
         return this.http.get<OpenApiDTO>(this.smartApiUrl + '/catalogs/' + catId);
     }
@@ -106,7 +70,7 @@ export class OpenApiService {
     '        "title" : "inrae list datasets",' +
     '        "version" : "0",' +
     '        "x-format" : "dataverse",' +
-    '        "x-catalog-id" : "09de0761-f1b5-4dc1-8c5c-92e5e782cb2c",' +
+    '        "x-catalog-id" : null,' +
     '        "x-result" : "json",' +
     '        "x-start-param" : "start",' +
     '        "x-page-param" : "per_page"' +
diff --git a/src/app/services/catalog.service.ts b/src/app/services/catalog.service.ts
index 30822325b..87c1806df 100644
--- a/src/app/services/catalog.service.ts
+++ b/src/app/services/catalog.service.ts
@@ -2,6 +2,19 @@ import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { AppConfiguration } from '../AppConfiguration';
 
+export interface FdpApiResponseItem {
+  subject: {
+    namespace: string,
+    localName: string
+  },
+  predicate: {
+    namespace: string,
+    localName: string
+  },
+  object: any,
+  context: string
+}
+
 @Injectable({
   providedIn: 'root'
 })
@@ -22,6 +35,6 @@ export class CatalogService {
   }
 
   getCatalogContentById(catId: string) {
-    return this.http.get<any>(this.appConfig.fdpurl + '/catalog/' + catId);
+    return this.http.get<FdpApiResponseItem[]>(this.appConfig.fdpurl + '/catalog/' + catId);
   }
 }
-- 
GitLab


From 6421a147b88fc7f0f523dd200a893154c7765527 Mon Sep 17 00:00:00 2001
From: Charly <maeder@cines.fr>
Date: Mon, 5 Jul 2021 17:36:17 +0200
Subject: [PATCH 3/5] Rename defaultValue to default and description to
 summary. Add openapiversion. Use enironment for api url

---
 src/app/publishapi/class/openapi-dto.ts       |   4 +-
 src/app/publishapi/class/openapi.ts           |  15 ++-
 src/app/publishapi/publishapi.component.html  |   8 +-
 src/app/publishapi/publishapi.component.ts    |   1 +
 .../services/openapi-dto-mapping-service.ts   |   8 +-
 .../publishapi/services/openapi-service.ts    | 111 +++++++++---------
 .../services/publish-repository.service.ts    |   6 +-
 src/app/services/catalog.service.ts           |   4 +-
 8 files changed, 85 insertions(+), 72 deletions(-)

diff --git a/src/app/publishapi/class/openapi-dto.ts b/src/app/publishapi/class/openapi-dto.ts
index cd18e39eb..60c5c41b9 100644
--- a/src/app/publishapi/class/openapi-dto.ts
+++ b/src/app/publishapi/class/openapi-dto.ts
@@ -8,7 +8,7 @@ export interface ServerDTO {
 
 export interface SchemaDTO {
     type: ShemaType,
-    defaultValue: string
+    default: string
 }
 
 export interface ParameterDTO {
@@ -44,7 +44,7 @@ export type HttpCodeToResponseMapDTO = Map<HttpStatusCode,ResponseDTO>;
 export interface RequestDTO {
     httpmethod: string;
     title: string;
-    description: string,
+    summary: string,
     tags: string[]
     parameters: ParameterDTO[],
     responses : any;
diff --git a/src/app/publishapi/class/openapi.ts b/src/app/publishapi/class/openapi.ts
index 2e07b3635..698bd757e 100644
--- a/src/app/publishapi/class/openapi.ts
+++ b/src/app/publishapi/class/openapi.ts
@@ -7,7 +7,7 @@ export interface Server {
 
 export interface Schema {
     type: string,
-    defaultValue: string
+    default: string
 }
 
 export interface Parameter {
@@ -39,7 +39,7 @@ export interface Response {
 
 export interface Request {
     title: string,
-    description: string,
+    summary: string,
     tags: string[]
     parameters: Parameter[],
     responses: Response[],
@@ -68,7 +68,7 @@ export class InfoMap {
 };
 
 export class OpenApi {
-    openapi: string;
+    openapi = '3.0.0';
     info: InfoMap;
     servers: Server[];
     paths: Path[];
@@ -78,5 +78,14 @@ export class OpenApi {
         this.servers = [{ url: server }];
         this.paths = [];
     }
+
+    addServers(serverUrl: string) {
+        for (const server of this.servers) {
+            if (server.url === serverUrl) {
+                return;
+            }
+        }
+        this.servers.push({ url: serverUrl });
+    }
 }
 
diff --git a/src/app/publishapi/publishapi.component.html b/src/app/publishapi/publishapi.component.html
index d56263322..c0bcd2fa7 100644
--- a/src/app/publishapi/publishapi.component.html
+++ b/src/app/publishapi/publishapi.component.html
@@ -3,7 +3,7 @@
 <!--Nebula example-->
 
 <nb-card>
-  <<<<<<< HEAD <nb-card-body>
+  <nb-card-body>
     <nb-stepper orientation="horizontal" disableStepNavigation>
       <nb-step [label]="labelOne">
         <ng-template #labelOne>First step</ng-template>
@@ -133,7 +133,7 @@
                                                 </nb-select>
                                               </td>
                                               <td>
-                                                <input name="description" [(ngModel)]="request.description" nbInput />
+                                                <input name="description" [(ngModel)]="request.summary" nbInput />
                                               </td>
                                             </tr>
                                           </tbody>
@@ -175,7 +175,7 @@
                                                 </nb-select>
                                               </td>
                                               <td>
-                                                <input name="default" [(ngModel)]="parameter.schema.defaultValue"
+                                                <input name="default" [(ngModel)]="parameter.schema.default"
                                                   nbInput />
                                               </td>
                                               <td>
@@ -301,5 +301,5 @@
         <button class="next-button" nbButton disabled nbStepperNext>next</button>
       </nb-step>
     </nb-stepper>
-    </nb-card-body>
+  </nb-card-body>
 </nb-card>
\ No newline at end of file
diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts
index f6cfb6b56..5edfdecf2 100644
--- a/src/app/publishapi/publishapi.component.ts
+++ b/src/app/publishapi/publishapi.component.ts
@@ -78,6 +78,7 @@ export class PublishApiComponent implements OnInit {
       },
       error: () => {
         this.openApi = new OpenApi(catId, this.getServer(catId));
+        this.openApi.paths.push(this.openApiDTOMappingService.getEmptyPath());
       }
     })
   }
diff --git a/src/app/publishapi/services/openapi-dto-mapping-service.ts b/src/app/publishapi/services/openapi-dto-mapping-service.ts
index f70751b91..2d8bb303d 100644
--- a/src/app/publishapi/services/openapi-dto-mapping-service.ts
+++ b/src/app/publishapi/services/openapi-dto-mapping-service.ts
@@ -47,7 +47,7 @@ export class OpenApiDTOMappingService {
         let request: Request = {} as Request;
         request.httpmethod = httpMethod;
         request.title = requestDTO.title;
-        request.description = requestDTO.description;
+        request.summary = requestDTO.summary;
         request.tags = requestDTO.tags as string[];
         request.parameters = this.mapParametersFromDTO(requestDTO.parameters);
         request.responses = [] as Response[];
@@ -98,7 +98,7 @@ export class OpenApiDTOMappingService {
             path.requests.forEach(request => {
                 openApiDTO.paths[path.pathName][request.httpmethod] = {};
                 openApiDTO.paths[path.pathName][request.httpmethod].tags = request.tags;
-                openApiDTO.paths[path.pathName][request.httpmethod].description = request.description;
+                openApiDTO.paths[path.pathName][request.httpmethod].summary = request.summary;
                 openApiDTO.paths[path.pathName][request.httpmethod].parameters = request.parameters as ParameterDTO[];
                 openApiDTO.paths[path.pathName][request.httpmethod].responses = {};
                 request.responses.forEach(response => {
@@ -128,7 +128,7 @@ export class OpenApiDTOMappingService {
 
     getEmptyRequest(): Request {
         return {
-            description: '',
+            summary: '',
             httpmethod: HttpMethod.GET,
             tags: [],
             title: '',
@@ -148,7 +148,7 @@ export class OpenApiDTOMappingService {
             in: ParameterType.query,
             schema: {
                 type: 'string',
-                defaultValue: ''
+                default: ''
             },
             required: true
         };
diff --git a/src/app/publishapi/services/openapi-service.ts b/src/app/publishapi/services/openapi-service.ts
index 415fdffd8..f61dc5934 100644
--- a/src/app/publishapi/services/openapi-service.ts
+++ b/src/app/publishapi/services/openapi-service.ts
@@ -4,66 +4,69 @@ import { Observable } from 'rxjs';
 import { OpenApi } from '../class/openapi';
 import { OpenApiDTO } from '../class/openapi-dto';
 import { OpenApiDTOMappingService } from './openapi-dto-mapping-service';
+import { environment } from 'src/environments/environment';
 
 @Injectable({
-    providedIn: 'root'
-  })
+  providedIn: 'root'
+})
 
 export class OpenApiService {
-    constructor(private http: HttpClient, private openApiDTOMappingService: OpenApiDTOMappingService) {}
+  constructor(
+    private http: HttpClient,
+    private openApiDTOMappingService: OpenApiDTOMappingService,
+  ) { }
 
-    get smartApiUrl(): string {
-        return 'http://localhost:8080/harvester/publication'; // TO-DO
-        //return this.appConfig.smartapiurl + '/harvester/publication'
-      }
+  get smartApiUrl(): string {
+    return environment.smartharvesterUrl + '/harvester/publication'
+  }
 
-    getFromRepository(repositoryId:string): Observable<OpenApiDTO> {
-        return this.http.get<OpenApiDTO>('/openapi/' + repositoryId);
-    }
+  getFromRepository(repositoryId: string): Observable<OpenApiDTO> {
+    return this.http.get<OpenApiDTO>('/openapi/' + repositoryId);
+  }
 
-    /**
-     * Replacer for JSON.stringify
-     * 
-     * Allows to serialize Map
-     * @param key 
-     * @param value 
-     */
-    private replacer(key, value) {
-        const originalObject = this[key];
-        if(originalObject instanceof Map) {
-          return [...originalObject].reduce((o, [key, value]) => (o[key] = value, o), {});
-        } else {
-          return value;
-        }
-      }
-    
-    getPrettyJson(openApi: OpenApi): string {
-        let openApiDTO: OpenApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
-        return JSON.stringify(openApiDTO, this.replacer, 2);
+  /**
+   * Replacer for JSON.stringify
+   * 
+   * Allows to serialize Map
+   * @param key 
+   * @param value 
+   */
+  private replacer(key, value) {
+    const originalObject = this[key];
+    if (originalObject instanceof Map) {
+      return [...originalObject].reduce((o, [key, value]) => (o[key] = value, o), {});
+    } else {
+      return value;
     }
+  }
 
-    getFromJson(): OpenApi {
-        let openApiDTO:OpenApiDTO = <OpenApiDTO>JSON.parse(this.jsonFull);
-        return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO);
-    }
+  getPrettyJson(openApi: OpenApi): string {
+    let openApiDTO: OpenApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
+    return JSON.stringify(openApiDTO, this.replacer, 2);
+  }
 
-    getFromString(json: string): OpenApi {
-        let openApiDTO:OpenApiDTO = <OpenApiDTO>JSON.parse(json);
-        return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO);
-    }
+  getFromJson(): OpenApi {
+    let openApiDTO: OpenApiDTO = <OpenApiDTO>JSON.parse(this.jsonFull);
+    return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO);
+  }
 
-    getByCatalogId(catId: string): Observable<OpenApiDTO> {
-        return this.http.get<OpenApiDTO>(this.smartApiUrl + '/catalogs/' + catId);
-    }
+  getFromString(json: string): OpenApi {
+    let openApiDTO: OpenApiDTO = <OpenApiDTO>JSON.parse(json);
+    return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO);
+  }
 
-    publishOpenApi(openApi: OpenApi) {
-        const openApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
-        console.log(openApi);
-        console.log(openApiDTO);
-        return this.http.post(this.smartApiUrl + '/publish', openApiDTO);
-    }
+  getByCatalogId(catId: string): Observable<OpenApiDTO> {
+    return this.http.get<OpenApiDTO>(this.smartApiUrl + '/catalogs/' + catId);
+  }
+
+  publishOpenApi(openApi: OpenApi) {
+    const openApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
+    console.log(openApi);
+    console.log(openApiDTO);
+    return this.http.post(this.smartApiUrl + '/publish', openApiDTO);
+  }
 
-    private jsonFull =
+  private jsonFull =
     '{' +
     '    "openapi" : "3.0.0",' +
     '    "info" : {' +
@@ -204,7 +207,7 @@ export class OpenApiService {
     '    }' +
     '}';
 
-    private jsonEmpty =
+  private jsonEmpty =
     '{' +
     '    "openapi" : "3.0.0",' +
     '    "info" : {' +
@@ -293,7 +296,7 @@ export class OpenApiService {
     '    }' +
     '}';
 
-    private emptyResponse =
+  private emptyResponse =
     '"200" : {' +
     '    "description" : "",' +
     '    "content" : {' +
@@ -308,7 +311,7 @@ export class OpenApiService {
     '    }' +
     '}';
 
-    private emptyParameter =
+  private emptyParameter =
     '[' +
     '   {' +
     '      "name" : "",' +
@@ -323,14 +326,14 @@ export class OpenApiService {
     ']';
 
 
-    private emptyMethodJson =
+  private emptyMethodJson =
     '   "get" : {' +
     '       "description" : "",' +
     '       "tags" : [ ' +
     '           "datasetlist"' +
     '       ],' +
     '       "parameters" : ' +
-                this.emptyParameter +
+    this.emptyParameter +
     '       ,' +
     '       "responses" : {' +
     '           "200" : {' +
@@ -349,9 +352,9 @@ export class OpenApiService {
     '       }' +
     '   }';
 
-    private emptyPathJson = '{' +
+  private emptyPathJson = '{' +
     '   " " : {' +
-        this.emptyMethodJson +
+    this.emptyMethodJson +
     '   }' +
     '}';
 
diff --git a/src/app/repository/services/publish-repository.service.ts b/src/app/repository/services/publish-repository.service.ts
index e00d695ba..c1e69d873 100644
--- a/src/app/repository/services/publish-repository.service.ts
+++ b/src/app/repository/services/publish-repository.service.ts
@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
 import { AppConfiguration } from 'src/app/AppConfiguration';
 import { AuthService } from 'src/app/authentication/services/auth.service';
+import { environment } from 'src/environments/environment';
 
 interface PersistentUrlResponse {
   persistentUrl: string;
@@ -21,8 +22,7 @@ export class PublishRepositoryService {
   ) { }
 
   get smartApiUrl(): string {
-    return 'http://localhost:8080/harvester/api'; // TO-DO
-    //return this.appConfig.smartapiurl + '/harvester/api'
+    return environment.smartharvesterUrl + '/harvester/api'
   }
 
   publishRepository(data: string) {
@@ -55,7 +55,7 @@ export class PublishRepositoryService {
   }
 
   getPersistentUrl(): Observable<PersistentUrlResponse> {
-    return this.http.get<PersistentUrlResponse>(/* // TO-DO : this.appConfig.fdpurl*/ 'http://localhost:8084' + '/configs/bootstrap');
+    return this.http.get<PersistentUrlResponse>(environment.fdpUrl + '/configs/bootstrap');
   }
 
   async addUserCatalog(catId: string): Promise<any> {
diff --git a/src/app/services/catalog.service.ts b/src/app/services/catalog.service.ts
index 87c1806df..012b628bb 100644
--- a/src/app/services/catalog.service.ts
+++ b/src/app/services/catalog.service.ts
@@ -1,6 +1,7 @@
 import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { AppConfiguration } from '../AppConfiguration';
+import { environment } from 'src/environments/environment';
 
 export interface FdpApiResponseItem {
   subject: {
@@ -26,8 +27,7 @@ export class CatalogService {
   ) { }
 
   get smartApiUrl(): string {
-    return 'http://localhost:8080/harvester/api'; // TO-DO
-    //return this.appConfig.smartapiurl + '/harvester/api'
+    return environment.smartharvesterUrl + '/harvester/api'
   }
 
   getAllCatalogId() {
-- 
GitLab


From 60b707d15d7585e4cd1f4f05bbfb2a0ea2e47941 Mon Sep 17 00:00:00 2001
From: Charly <maeder@cines.fr>
Date: Tue, 6 Jul 2021 14:19:00 +0200
Subject: [PATCH 4/5] Fix bug : duplicate server url for openapi description

---
 src/app/publishapi/class/openapi.ts            | 12 ++++++++----
 src/app/publishapi/publishapi.component.ts     |  2 +-
 src/app/publishapi/services/openapi-service.ts |  2 --
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/app/publishapi/class/openapi.ts b/src/app/publishapi/class/openapi.ts
index 698bd757e..9376b0fdc 100644
--- a/src/app/publishapi/class/openapi.ts
+++ b/src/app/publishapi/class/openapi.ts
@@ -70,22 +70,26 @@ export class InfoMap {
 export class OpenApi {
     openapi = '3.0.0';
     info: InfoMap;
-    servers: Server[];
+    private _servers: Server[];
     paths: Path[];
 
+    get servers() {
+        return this._servers;
+    }
+
     constructor(catId: string, server: string) {
         this.info = new InfoMap(catId);
-        this.servers = [{ url: server }];
+        this._servers = [{ url: server }];
         this.paths = [];
     }
 
     addServers(serverUrl: string) {
-        for (const server of this.servers) {
+        for (const server of this._servers) {
             if (server.url === serverUrl) {
                 return;
             }
         }
-        this.servers.push({ url: serverUrl });
+        this._servers.push({ url: serverUrl });
     }
 }
 
diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts
index 5edfdecf2..96cc35acb 100644
--- a/src/app/publishapi/publishapi.component.ts
+++ b/src/app/publishapi/publishapi.component.ts
@@ -74,7 +74,7 @@ export class PublishApiComponent implements OnInit {
       next: (response) => {
         this.openApi = this.openApiDTOMappingService.mapOpenApiFromDTO(response);
         this.openApi.info['x-catalog-id'] = catId;
-        this.openApi.servers.push({ url: this.getServer(catId) });
+        this.openApi.addServers(this.getServer(catId));
       },
       error: () => {
         this.openApi = new OpenApi(catId, this.getServer(catId));
diff --git a/src/app/publishapi/services/openapi-service.ts b/src/app/publishapi/services/openapi-service.ts
index f61dc5934..491b8399d 100644
--- a/src/app/publishapi/services/openapi-service.ts
+++ b/src/app/publishapi/services/openapi-service.ts
@@ -61,8 +61,6 @@ export class OpenApiService {
 
   publishOpenApi(openApi: OpenApi) {
     const openApiDTO = this.openApiDTOMappingService.mapToDto(openApi);
-    console.log(openApi);
-    console.log(openApiDTO);
     return this.http.post(this.smartApiUrl + '/publish', openApiDTO);
   }
 
-- 
GitLab


From 77e0bca783f04f8e56fec270ba57374db7b41d68 Mon Sep 17 00:00:00 2001
From: Charly <maeder@cines.fr>
Date: Tue, 6 Jul 2021 15:02:31 +0200
Subject: [PATCH 5/5] Fix compilation error

---
 src/app/publishapi/class/openapi.ts                        | 5 +++++
 src/app/publishapi/services/openapi-dto-mapping-service.ts | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/app/publishapi/class/openapi.ts b/src/app/publishapi/class/openapi.ts
index 9376b0fdc..ed9941e51 100644
--- a/src/app/publishapi/class/openapi.ts
+++ b/src/app/publishapi/class/openapi.ts
@@ -1,4 +1,5 @@
 import HttpStatusCode, { HttpMethod } from './http-enum'
+import { ServerDTO } from './openapi-dto';
 import { ParameterType } from './openapi-enum';
 
 export interface Server {
@@ -84,6 +85,10 @@ export class OpenApi {
     }
 
     addServers(serverUrl: string) {
+        if (serverUrl == null || serverUrl.length === 0 || typeof(serverUrl !== 'string')) {
+            return;
+        }
+
         for (const server of this._servers) {
             if (server.url === serverUrl) {
                 return;
diff --git a/src/app/publishapi/services/openapi-dto-mapping-service.ts b/src/app/publishapi/services/openapi-dto-mapping-service.ts
index 2d8bb303d..c4ccb5310 100644
--- a/src/app/publishapi/services/openapi-dto-mapping-service.ts
+++ b/src/app/publishapi/services/openapi-dto-mapping-service.ts
@@ -72,10 +72,10 @@ export class OpenApiDTOMappingService {
     }
 
     mapOpenApiFromDTO(openApiDTO: OpenApiDTO): OpenApi {
-        let openApi: OpenApi = {} as OpenApi;
+        const serverUrl = (openApiDTO.servers.length > 0) ? openApiDTO.servers[0].url : ''; 
+        let openApi: OpenApi = new OpenApi(openApiDTO.info['x-catalog-id'], serverUrl);
         openApi.info = openApiDTO.info as InfoMap;
         openApi.openapi = openApiDTO.openapi;
-        openApi.servers = openApiDTO.servers as Server[];
         openApi.paths = [] as Path[];
         Object.keys(openApiDTO.paths).forEach((pathName) => {
             let path: Path = this.mapPathFromDTO(openApiDTO.paths, pathName);
-- 
GitLab