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