diff --git a/src/app/publishapi/class/openapi-dto.ts b/src/app/publishapi/class/openapi-dto.ts index 69ed5c5e379aa176e12ff88ca57a2d81b4f39bcb..60c5c41b9b147fbf598dd834e5fd607c509d588d 100644 --- a/src/app/publishapi/class/openapi-dto.ts +++ b/src/app/publishapi/class/openapi-dto.ts @@ -23,39 +23,52 @@ export interface ItemDTO { } export interface ResponseSchemaDTO { type: string, - items: ItemDTO[] + items: ItemDTO } 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 { - description: string, + httpmethod: string; + title: string; + summary: 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 2baff963205ea4dd5f42b6a622ff17f78d34f290..ed9941e51697597733fe2a53918b4b6b034b8136 100644 --- a/src/app/publishapi/class/openapi.ts +++ b/src/app/publishapi/class/openapi.ts @@ -1,8 +1,9 @@ import HttpStatusCode, { HttpMethod } from './http-enum' +import { ServerDTO } from './openapi-dto'; import { ParameterType } from './openapi-enum'; export interface Server { - url:string; + url: string; } export interface Schema { @@ -23,7 +24,7 @@ export interface Item { export interface ResponseSchema { type: string, - items: Item[] + items: Item } export interface Content { @@ -38,7 +39,8 @@ export interface Response { } export interface Request { - description: string, + title: string, + summary: string, tags: string[] parameters: Parameter[], responses: Response[], @@ -48,15 +50,51 @@ export interface Request { export interface Path { pathName: string, - requests: Request[] + 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; + + constructor(catId: string) { + this['x-catalog-id'] = catId; + } +}; -export interface OpenApi { - openapi: string; +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.paths = []; + } + + addServers(serverUrl: string) { + if (serverUrl == null || serverUrl.length === 0 || typeof(serverUrl !== 'string')) { + return; + } + + 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 bccccb7c511fea781dbc0ccc09b4614a3d0aa832..c0bcd2fa7f0c8002628d20eb7117af6da5a7fff1 100644 --- a/src/app/publishapi/publishapi.component.html +++ b/src/app/publishapi/publishapi.component.html @@ -1,268 +1,305 @@ - <!--<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" [title]="catalog.catId"> + {{catalog.title?.length > 0 ? catalog.title : catalog.catId}}</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> - <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> + </div> + </nb-tab> + + <!-- Main tab -------------------------------------------------------------> + + <nb-tab class="main" tabTitle="Main" tabIcon="edit-2-outline"> + <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="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 *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"> + <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> + <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> + <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.summary" 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> + <nb-icon icon="plus-outline" nbTooltip="Add parameter" + (click)="addParameter(request)"></nb-icon> + <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="copy-outline" nbTooltip="Duplicate parameter" + (click)="duplicateParameter(request, parameter)"></nb-icon> + <nb-icon icon="trash-2-outline" nbTooltip="Delete parameter" + (click)="deleteParameter(request, parameter)" + *ngIf="request.parameters.length > 1"></nb-icon> + </td> + </tr> + </tbody> + </table> + </nb-card-body> + </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> + <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> - <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 [(ngModel)]="response.httpStatusCode"> + <nb-option *ngFor="let code of httpStatusCodes" value="{{code}}"> + {{code}}</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> + <div *ngFor="let content of response.contents"> + <input name="default" [(ngModel)]="content.contentType" nbInput /> + </div> </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> + <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> + </ng-container> + </nb-tab> + + <!-- JSON 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.scss b/src/app/publishapi/publishapi.component.scss index c4758be30d2e47fa0406ac67c2a6ac22b2635bf8..931e6621b564140ddb90f5c37f571764a749fe8a 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 5520c04bb0386e7a7d13c87fef3cd95fa9e66974..96cc35acb30c303640922178cc6a2fbf39942b59 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, FdpApiResponseItem } 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,25 +16,110 @@ 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, 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"); 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: 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); + } + }); + }, + 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; + this.openApi.addServers(this.getServer(catId)); + }, + error: () => { + this.openApi = new OpenApi(catId, this.getServer(catId)); + this.openApi.paths.push(this.openApiDTOMappingService.getEmptyPath()); + } + }) + } + + updateCurrentOpenApi(catId: string) { + this.openApi.info['x-catalog-id'] = catId; + this.catalogSelect.selected = catId; + 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(); + } + selectAllJson(): void { var range = document.createRange(); range.selectNodeContents(document.getElementById('json')); @@ -47,8 +131,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,15 +140,15 @@ 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); } addPath(): void { - let emptyPath: Path = this.openApiService.getEmptyPath(); + let emptyPath: Path = this.openApiDTOMappingService.getEmptyPath() this.openApi.paths.unshift(emptyPath); } @@ -76,7 +160,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); } @@ -92,7 +176,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); } @@ -108,7 +192,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); } @@ -123,21 +207,36 @@ 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"); } + 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 35ca0498a6bfe5f7d74296b914419eae6766ae1c..c4ccb53104974f6cab29433adf4f2ba8305b0c39 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.description = requestDTO.description; + request.title = requestDTO.title; + request.summary = requestDTO.summary; 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 { + 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)=>{ + Object.keys(openApiDTO.paths).forEach((pathName) => { let path: Path = this.mapPathFromDTO(openApiDTO.paths, pathName); openApi.paths.push(path); }); @@ -80,38 +87,86 @@ 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 = new Map<string,MethodToRequestMapDTO>(); - openApi.paths.forEach(path=>{ - let methodToRequestMapDTO: MethodToRequestMapDTO = new Map<HttpMethod, RequestDTO>(); - 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; - 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; - response.contents.forEach(content=>{ - let contentDTO: ContentDTO = {} as ContentDTO; - contentDTO.schema = content.schema as ResponseSchemaDTO; - responseDTO.content.set(content.contentType, contentDTO); + openApiDTO.paths = {}; + 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].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 => { + 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 => { + 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; } + getEmptyPath(): Path { + return { + pathName: '', + requests: [ + this.getEmptyRequest() + ] + }; + } + + getEmptyRequest(): Request { + return { + summary: '', + httpmethod: HttpMethod.GET, + tags: [], + title: '', + parameters: [ + this.getEmptyParameter() + ], + responses: [ + this.getEmptyResponse() + ], + toggled: false + }; + } + + getEmptyParameter(): Parameter { + return { + name: '', + in: ParameterType.query, + schema: { + type: 'string', + default: '' + }, + 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 140a1bf96ee09d3078f37ec394b2291d68a9c7f3..491b8399dccc0b924f13ccffb20cfec578e82e1c 100644 --- a/src/app/publishapi/services/openapi-service.ts +++ b/src/app/publishapi/services/openapi-service.ts @@ -1,96 +1,77 @@ 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'; +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, + ) { } - getFromRepository(repositoryId:string): Observable<OpenApiDTO> { - return this.http.get<OpenApiDTO>('/openapi/' + repositoryId); - } + get smartApiUrl(): string { + return environment.smartharvesterUrl + '/harvester/publication' + } - /** - * 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); - } + getFromRepository(repositoryId: string): Observable<OpenApiDTO> { + return this.http.get<OpenApiDTO>('/openapi/' + repositoryId); + } - getFromJson(): OpenApi { - let openApiDTO:OpenApiDTO = <OpenApiDTO>JSON.parse(this.jsonFull); - return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO); + /** + * 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; } + } - getFromString(json: string): OpenApi { - let openApiDTO:OpenApiDTO = <OpenApiDTO>JSON.parse(json); - return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO); - } + getPrettyJson(openApi: OpenApi): string { + let openApiDTO: OpenApiDTO = this.openApiDTOMappingService.mapToDto(openApi); + return JSON.stringify(openApiDTO, this.replacer, 2); + } - 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]; - } + getFromJson(): OpenApi { + let openApiDTO: OpenApiDTO = <OpenApiDTO>JSON.parse(this.jsonFull); + return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO); + } - 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]; - } + getFromString(json: string): OpenApi { + let openApiDTO: OpenApiDTO = <OpenApiDTO>JSON.parse(json); + return this.openApiDTOMappingService.mapOpenApiFromDTO(openApiDTO); + } - getEmptyParameter(): Parameter { - let parameterDTO: ParameterDTO[] = <ParameterDTO[]>JSON.parse(this.emptyParameter); - return this.openApiDTOMappingService.mapParametersFromDTO(parameterDTO)[0]; - } + getByCatalogId(catId: string): Observable<OpenApiDTO> { + return this.http.get<OpenApiDTO>(this.smartApiUrl + '/catalogs/' + catId); + } - 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]; - } + publishOpenApi(openApi: OpenApi) { + const openApiDTO = this.openApiDTOMappingService.mapToDto(openApi); + return this.http.post(this.smartApiUrl + '/publish', openApiDTO); + } - private jsonFull = + private jsonFull = '{' + ' "openapi" : "3.0.0",' + ' "info" : {' + ' "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"' + @@ -224,7 +205,7 @@ export class OpenApiService { ' }' + '}'; - private jsonEmpty = + private jsonEmpty = '{' + ' "openapi" : "3.0.0",' + ' "info" : {' + @@ -313,7 +294,7 @@ export class OpenApiService { ' }' + '}'; - private emptyResponse = + private emptyResponse = '"200" : {' + ' "description" : "",' + ' "content" : {' + @@ -328,7 +309,7 @@ export class OpenApiService { ' }' + '}'; - private emptyParameter = + private emptyParameter = '[' + ' {' + ' "name" : "",' + @@ -343,14 +324,14 @@ export class OpenApiService { ']'; - private emptyMethodJson = + private emptyMethodJson = ' "get" : {' + ' "description" : "",' + ' "tags" : [ ' + ' "datasetlist"' + ' ],' + ' "parameters" : ' + - this.emptyParameter + + this.emptyParameter + ' ,' + ' "responses" : {' + ' "200" : {' + @@ -369,9 +350,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 e00d695bac2757205eaed58ee4ef1a04e9e19eff..c1e69d8736eb7dbdc4719d949880c4bade91d09d 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.spec.ts b/src/app/services/catalog.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..21b1429f3f88c2b69dfb6701be2598a966146387 --- /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 0000000000000000000000000000000000000000..012b628bb9604b3f2c5b099d40e1a0a07a267ffc --- /dev/null +++ b/src/app/services/catalog.service.ts @@ -0,0 +1,40 @@ +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: { + namespace: string, + localName: string + }, + predicate: { + namespace: string, + localName: string + }, + object: any, + context: string +} + +@Injectable({ + providedIn: 'root' +}) +export class CatalogService { + + constructor( + private appConfig: AppConfiguration, + private http: HttpClient + ) { } + + get smartApiUrl(): string { + return environment.smartharvesterUrl + '/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<FdpApiResponseItem[]>(this.appConfig.fdpurl + '/catalog/' + catId); + } +}