diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 67d2c4c1813afe7d6f71546589cba4d51b654b43..733dd5f712ff00e758d17d52d0fa326fc6056fad 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -47,6 +47,7 @@ import { CallbackComponent } from './callback/callback.component'; import { SemanticEnrichmentComponent } from './semantic-enrichment/semantic-enrichment.component'; import {MatAutocompleteModule} from '@angular/material/autocomplete'; import {MatFormFieldModule} from '@angular/material/form-field'; +import { OrderByScorePipe } from './semantic-enrichment/pipes/order-by-score.pipe'; @@ -67,6 +68,7 @@ import {MatFormFieldModule} from '@angular/material/form-field'; DatasetsDialogComponent, CallbackComponent, SemanticEnrichmentComponent, + OrderByScorePipe, ], imports: [ diff --git a/src/app/mapping/class/dataset.ts b/src/app/mapping/class/dataset.ts index 250ed14799ffae5fefdd18914764d03b7f5bdc90..808875f1def9bf3adeba1b4322164bc9559c2a8b 100644 --- a/src/app/mapping/class/dataset.ts +++ b/src/app/mapping/class/dataset.ts @@ -1,3 +1,5 @@ +import {ESModel} from '../../semantic-enrichment/ESModel'; + export class Property { public property: string; public uri: string; @@ -69,6 +71,8 @@ export class ResponseFileTsv { export class KeywordResponse { public id: string; + public url: string; public keywords: string[]; + public concepts: ESModel; } diff --git a/src/app/mapping/mapping.component.html b/src/app/mapping/mapping.component.html index c7c661d03cf452f2ae618d19af4cbba9052bf224..c86e88d44f03eec6ec096b09cd0c9757570e51f9 100644 --- a/src/app/mapping/mapping.component.html +++ b/src/app/mapping/mapping.component.html @@ -371,12 +371,12 @@ </div> </div> - <div class="row"> + <!-- <div class="row"> <div class="button-center" *ngIf="!first "> <button nbButton status="primary" (click)="getKeywords()" [nbSpinner]="loading" nbSpinnerStatus="basic">Publish</button> </div> - </div> + </div>--> </nb-card-footer> </nb-card> @@ -413,12 +413,12 @@ </div> </div> - <!--<div class="row"> + <div class="row"> <div class="button-center"> <button nbButton status="primary" (click)=" publishDatasetFromGeodcatApi()" [nbSpinner]="loading" nbSpinnerStatus="basic">Publish</button> </div> - </div>--> + </div> </nb-card-footer> </nb-card> diff --git a/src/app/mapping/mapping.component.ts b/src/app/mapping/mapping.component.ts index eb2a5fc9b8bfc7bc0eb8b0f4159b55d8fdda818f..b144ce4bae291215cb20a4b303fbe624af306b12 100644 --- a/src/app/mapping/mapping.component.ts +++ b/src/app/mapping/mapping.component.ts @@ -25,14 +25,13 @@ import { JSONPath } from 'jsonpath-plus'; }) export class MappingComponent implements OnInit { - /*@Output() + @Output() dataEvent = new EventEmitter<RequestMapping>(); @Output() - isJsonPathEvent = new EventEmitter();*/ + isJsonPathEvent = new EventEmitter(); + - @Output() - keywordsEvent = new EventEmitter<Observable<KeywordResponse[]>>(); paths: Path[]; addDistribution = false; @@ -168,7 +167,7 @@ export class MappingComponent implements OnInit { const data: RequestMapping = new RequestMapping(this.ids, paths, this.tokenStorage.getFDPToken()); // this.dataEvent.emit(data); - const postedDatasets = []; + /*const postedDatasets = []; const notPostedDatasets = []; this.loading = true; const requestPromises: Promise<any>[] = []; @@ -194,7 +193,7 @@ export class MappingComponent implements OnInit { } }).afterClosed().subscribe(); - }); + });*/ } buildRDF(vocabularies: Property[], array: Map<number, string>[], i: number): string { @@ -695,9 +694,8 @@ export class MappingComponent implements OnInit { } const data: RequestMapping = new RequestMapping(this.ids, paths, this.tokenStorage.getFDPToken()); - this.keywordsEvent.emit(this.mappingService.getKeywords(this.catalogId, this.isJsonPath, data).pipe( - catchError(err => of([])) - )); + this.dataEvent.emit(data); + this.isJsonPathEvent.emit(this.isJsonPath); } private getDistributionEmpty(properties: string, datasetId: string): string { diff --git a/src/app/mapping/service/mapping.service.ts b/src/app/mapping/service/mapping.service.ts index 061511ba6a06dd4bbc7e9594360f7695b7b66a17..32644e2c7bd6906fe725249ae28ff1206ffd868f 100644 --- a/src/app/mapping/service/mapping.service.ts +++ b/src/app/mapping/service/mapping.service.ts @@ -6,6 +6,7 @@ import { environment } from 'src/environments/environment'; import {DatasetPath, KeywordResponse} from '../class/dataset'; import { RequestMapping } from '../class/requestMapping'; import {Observable} from 'rxjs'; +import {ConceptsRequest} from '../../semantic-enrichment/ConceptsRequest'; @Injectable({ @@ -150,7 +151,8 @@ export class MappingService { return result; } - async postToFdpFropSmartharvester(catalogId: string, data: RequestMapping, isJsonpath: boolean): Promise<any> { + async postToFdpFropSmartharvester(catalogId: string, data: ConceptsRequest, isJsonpath: boolean): Promise<any> { + if (this.fds2Token) { const httpOptions = new Headers(); @@ -182,19 +184,5 @@ export class MappingService { } } - getKeywords(catalogId: string, isJsonPath: boolean, data: RequestMapping): Observable<KeywordResponse[]> { - if (this.fds2Token) { - const httpOptions = { - headers: new HttpHeaders({ - 'Content-Type': 'application/json', - Accept: 'application/json', - Authorization: 'Bearer ' + this.fds2Token - }) - }; - return this.http - .post<KeywordResponse[]>( - `${this.smartHarvesterUrl}/harvester/api/es/keywords?catalogId=${catalogId}&isJsonPath=${isJsonPath}`, data, httpOptions - ); - } - } + } diff --git a/src/app/publishapi/publishapi.component.html b/src/app/publishapi/publishapi.component.html index f907db6dfb715ea1c8657d92388497ff190a0941..e4286f892f82e10060a6783aec6888362869782d 100644 --- a/src/app/publishapi/publishapi.component.html +++ b/src/app/publishapi/publishapi.component.html @@ -4,7 +4,7 @@ <nb-card> <nb-card-body> - <nb-stepper #stepper orientation="horizontal" disableStepNavigation> + <nb-stepper #stepper orientation="horizontal" disableStepNavigation > <nb-step [label]="labelOne"> <ng-template #labelOne>First step</ng-template> <h4>Describe API</h4> @@ -316,17 +316,17 @@ Map your metadata schema with DCAT schema </p> <app-mapping *ngIf="initLabelThree && datasets.ready" [catalogId]="openApi.info['x-catalog-id']" - [type]="openApi.info['x-format']" (keywordsEvent)="keywordsEventHandler($event)" > + [type]="openApi.info['x-format']" (dataEvent)="dataEventHandler($event)" (isJsonPathEvent)="isJsonPathEventHandler($event)"> </app-mapping> <button class="prev-button" nbButton nbStepperPrevious (click)="initLabelThree=false; resetDataset(); datasets.ready = false">prev</button> - <button class="next-button" nbButton nbStepperNext (click)="mappingComponent.getKeywords()">next</button> + <button class="next-button" nbButton nbStepperNext (click)="initLabelFour = true; mappingComponent.getKeywords(); ">next</button> </nb-step> - <nb-step [label]="labelFour"> + <nb-step [label]="labelFour" > <ng-template #labelFour>Fourth step</ng-template> <h4>Semantic Enrichment</h4> - <app-semantic-enrichment [keywords]="keywords"></app-semantic-enrichment> - <button class="prev-button" nbButton nbStepperPrevious>prev</button> + <app-semantic-enrichment *ngIf="initLabelFour" [data]="data" [isJsonPath]="isJsonPath" [catalogId]="openApi.info['x-catalog-id']"></app-semantic-enrichment> + <button class="prev-button" nbButton nbStepperPrevious (click)="initLabelFour = false">prev</button> <button class="next-button" nbButton disabled nbStepperNext>next</button> </nb-step> </nb-stepper> diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts index fca06ce2125b51ace4d0c3b5b99ca251ffbc4024..fc157135f8ce84bdd8d11aee7bf740548209337e 100644 --- a/src/app/publishapi/publishapi.component.ts +++ b/src/app/publishapi/publishapi.component.ts @@ -14,6 +14,7 @@ import { RequestMapping} from '../mapping/class/requestMapping' ; import {MappingComponent} from '../mapping/mapping.component'; import {KeywordResponse} from '../mapping/class/dataset'; import {Observable} from 'rxjs'; +import {SemanticEnrichmentComponent} from '../semantic-enrichment/semantic-enrichment.component'; @Component({ selector: 'app-publishapi', @@ -29,9 +30,11 @@ export class PublishApiComponent implements OnInit { @ViewChild(MappingComponent) private mappingComponent: MappingComponent; + @ViewChild(SemanticEnrichmentComponent) + private semanticComponent: SemanticEnrichmentComponent; + data: RequestMapping; isJsonPath: boolean; - keywords: Observable<KeywordResponse[]>; constructor( private openApiService: OpenApiService, @@ -56,6 +59,7 @@ export class PublishApiComponent implements OnInit { canNext = false; type: string; initLabelThree = false; + initLabelFour = false; ngOnInit(): void { this.openApi = new OpenApi(null, null); @@ -67,18 +71,16 @@ export class PublishApiComponent implements OnInit { this.datasetService.resetDataset(); } - /*dataEventHandler($event: RequestMapping) { + dataEventHandler($event: RequestMapping) { this.data = $event; - }*/ + } - /* isJsonPathEventHandler($event: boolean) { + isJsonPathEventHandler($event: boolean) { this.isJsonPath = $event; - }*/ - - keywordsEventHandler($event: Observable<KeywordResponse[]>) { - this.keywords = $event; } + + getPrettyJson(): string { return this.openApiService.getPrettyJson(this.openApi); } diff --git a/src/app/publishapi/services/openapi-dto-mapping-service.ts b/src/app/publishapi/services/openapi-dto-mapping-service.ts index 29d4d04b401a3c55ff56a5ab7315e1fa21693ef2..7df332e9f627dc9f07f00c9c1e3eb1e57db6c1bc 100644 --- a/src/app/publishapi/services/openapi-dto-mapping-service.ts +++ b/src/app/publishapi/services/openapi-dto-mapping-service.ts @@ -13,21 +13,21 @@ export class OpenApiDTOMappingService { constructor() { } mapContentFromDTO(mimeTypeToContentMapDTO: MimeTypeToContentMapDTO, contentType: string) { - let contentDTO: ContentDTO = mimeTypeToContentMapDTO[contentType]; - let content: Content = {} as Content; + const contentDTO: ContentDTO = mimeTypeToContentMapDTO[contentType]; + const content: Content = {} as Content; content.contentType = contentType; content.example = contentDTO.example; return content; } mapResponseFromDTO(httpCodeToResponseMapDTO: HttpCodeToResponseMapDTO, httpStatusCodeToreponseDTOMap: string): Response { - let responseDTO: ResponseDTO = httpCodeToResponseMapDTO[httpStatusCodeToreponseDTOMap]; - let response: Response = {} as Response; + const responseDTO: ResponseDTO = httpCodeToResponseMapDTO[httpStatusCodeToreponseDTOMap]; + const response: Response = {} as Response; response.description = responseDTO.description; response.httpStatusCode = httpStatusCodeToreponseDTOMap as unknown as HttpStatusCode; response.contents = [] as Content[]; Object.keys(responseDTO.content).forEach((contentType) => { - let content: Content = this.mapContentFromDTO(responseDTO.content, contentType); + const content: Content = this.mapContentFromDTO(responseDTO.content, contentType); response.contents.push(content); }); return response; @@ -38,13 +38,13 @@ export class OpenApiDTOMappingService { } mapRequestFromDTO(methodToRequestMapDTO: MethodToRequestMapDTO, httpMethod: HttpMethod): Request { - let requestDTO: RequestDTO = methodToRequestMapDTO[httpMethod]; + const requestDTO: RequestDTO = methodToRequestMapDTO[httpMethod]; if (requestDTO == null) { return this.getEmptyRequest(OpenApiTag.other); } - let request: Request = {} as Request; + const request: Request = {} as Request; request.httpmethod = httpMethod; request.title = requestDTO.title; request.summary = requestDTO.summary; @@ -53,32 +53,32 @@ export class OpenApiDTOMappingService { request.responses = [] as Response[]; request.toggled = false; Object.keys(requestDTO.responses).forEach((HttpStatusCode) => { - let response: Response = this.mapResponseFromDTO(requestDTO.responses, HttpStatusCode); + const response: Response = this.mapResponseFromDTO(requestDTO.responses, HttpStatusCode); request.responses.push(response); }); return request; } mapPathFromDTO(pathMapDTO: PathMapDTO, pathName: string): Path { - let methodToRequestMapDTO: MethodToRequestMapDTO = pathMapDTO[pathName]; - let path: Path = {} as Path; + const methodToRequestMapDTO: MethodToRequestMapDTO = pathMapDTO[pathName]; + const path: Path = {} as Path; path.pathName = pathName.trim(); path.requests = [] as Request[]; Object.keys(methodToRequestMapDTO).forEach((httpMethod: HttpMethod) => { - let request: Request = this.mapRequestFromDTO(methodToRequestMapDTO, httpMethod); + const request: Request = this.mapRequestFromDTO(methodToRequestMapDTO, httpMethod); path.requests.push(request); }); return path; } 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); + const serverUrl = (openApiDTO.servers.length > 0) ? openApiDTO.servers[0].url : ''; + const openApi: OpenApi = new OpenApi(openApiDTO.info['x-catalog-id'], serverUrl); openApi.info = openApiDTO.info as InfoMap; openApi.openapi = openApiDTO.openapi; openApi.paths = [] as Path[]; Object.keys(openApiDTO.paths).forEach((pathName) => { - let path: Path = this.mapPathFromDTO(openApiDTO.paths, pathName); + const path: Path = this.mapPathFromDTO(openApiDTO.paths, pathName); openApi.paths.push(path); }); return openApi; @@ -88,7 +88,7 @@ export class OpenApiDTOMappingService { * @param openApi */ mapToDto(openApi: OpenApi): OpenApiDTO { - let openApiDTO: OpenApiDTO = {} as OpenApiDTO; + const openApiDTO: OpenApiDTO = {} as OpenApiDTO; openApiDTO.openapi = openApi.openapi; openApiDTO.info = openApi.info as InfoMapDTO; openApiDTO.servers = openApi.servers as ServerDTO[]; @@ -102,9 +102,10 @@ export class OpenApiDTOMappingService { 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()] = {}; openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].content = {}; - openApiDTO.paths[path.pathName][request.httpmethod].responses[response.httpStatusCode.toString()].description = response.description; + 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] = {}; diff --git a/src/app/semantic-enrichment/ConceptsRequest.ts b/src/app/semantic-enrichment/ConceptsRequest.ts new file mode 100644 index 0000000000000000000000000000000000000000..ebb2ed93f76cff32b4edf80c1b4d8db9edca4e05 --- /dev/null +++ b/src/app/semantic-enrichment/ConceptsRequest.ts @@ -0,0 +1,12 @@ +import {Path} from '../mapping/class/requestMapping'; + +export class ConceptsRequest { + dataConcepts: DataConcept[]; + paths: Path[]; + fdpToken: string; +} + +export class DataConcept { + iris: string[]; + id: string; +} diff --git a/src/app/semantic-enrichment/ESModel.ts b/src/app/semantic-enrichment/ESModel.ts index b47a68343a4d001d5fbded25d2c94aefcffcac25..1ac037e3a072036025ac0c0ed21cc77b88e40a18 100644 --- a/src/app/semantic-enrichment/ESModel.ts +++ b/src/app/semantic-enrichment/ESModel.ts @@ -4,11 +4,20 @@ export class ESModel { public count: number; public best: number; public results: Result[]; + } export class Result { + public checked: boolean; public score: number; public source: Source; + + constructor(result: Result, checked: boolean) { + this.source = result.source; + this.score = result.score; + this.checked = checked; + } + } export class Source { diff --git a/src/app/semantic-enrichment/pipes/order-by-score.pipe.ts b/src/app/semantic-enrichment/pipes/order-by-score.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..5bae7b4d3ef2fdeb702aec58a771abfbc6b08e69 --- /dev/null +++ b/src/app/semantic-enrichment/pipes/order-by-score.pipe.ts @@ -0,0 +1,23 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'orderByScore' +}) +export class OrderByScorePipe implements PipeTransform { + + transform(value: any, args?: any): any { + return value.sort((a: any, b: any) => { + const score1 = a.score; + const score2 = b.score; + + if (score1 > score2) { + return -1; + } else if (score1 < score2) { + return 1; + } else { + return 0; + } + }); + } + +} diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.html b/src/app/semantic-enrichment/semantic-enrichment.component.html index 21411376b82f646323d18476eb0917161049d1c6..3afc771272940d0d17c8998bb6b11f2454103c66 100644 --- a/src/app/semantic-enrichment/semantic-enrichment.component.html +++ b/src/app/semantic-enrichment/semantic-enrichment.component.html @@ -1,43 +1,94 @@ -<!--<nb-layout> - <nb-layout-header fixed> - <img width="80" alt="Angular Logo" src="assets/images/logo.png"/> - <h3 style="width: 100%;text-align: center;"><strong></strong></h3> - <div style="float: right;"> - <button (click)="login()" status="primary" nbButton>login</button> - </div> - - </nb-layout-header> +<ng-template #dialog let-data let-ref="dialogRef"> + <nb-card> + <nb-card-body>{{ errorMess }}</nb-card-body> + <nb-card-footer> + <button nbButton (click)="getConceptsByKeywords();ref.close()">Retry</button> + <button nbButton (click)="ref.close()">Close</button> + </nb-card-footer> + </nb-card> +</ng-template> - <nb-layout-column>--> -<ng-template #loading> +<ng-template #loading xmlns="http://www.w3.org/1999/html"> <nb-card size="small" [nbSpinner]="true" nbSpinnerStatus="primary" nbSpinnerSize="giant"></nb-card> </ng-template> -<p>{{ keywords | async | json}}</p> - <nb-card size="small" *ngIf="keywords | async; else loading"> - <nb-card-body> - <nb-form-field> - <input - type="text" - placeholder="enter a value with at least 4 characters" - [formControl]="myControl" - nbInput - [nbAutocomplete]="auto"> - <nb-autocomplete #auto [handleDisplayFn]="viewHandle"> - <nb-option - *ngFor="let option of filteredOptions | async" - [value]="option"> - {{option.source.document.label}} - </nb-option> - </nb-autocomplete> - </nb-form-field> - </nb-card-body> - </nb-card> - <p *ngIf="myControl.value !== null">{{ myControl.value | json }}</p> - <!--</nb-layout-column> - - - <nb-layout-footer>Contact us</nb-layout-footer> ---> +<ng-container *ngIf="!isLoading; else loading"> + <ng-container *ngFor="let keyword of response; let index = index"> + <nb-accordion> + <nb-accordion-item> + <nb-accordion-item-header>{{keyword.id}} - <a href="{{keyword.url}}" target="_blank">link to dataset</a></nb-accordion-item-header> + + <nb-accordion-item-body> + + <table> + <thead style="background-color: #3366ff"> + <th></th> + <th class="text-center">label</th> + <th class="text-center">iri</th> + <th class="text-center">synonyms</th> + <th class="text-center">score</th> + </thead> + <tbody> + <tr *ngFor="let objet of keyword.concepts.results | orderByScore"> + <td class="text-center"> + <nb-checkbox [(checked)]="objet.checked"></nb-checkbox> + </td> + <td class="text-center">{{ objet.source.document.label }}</td> + <td class="text-center">{{ objet.source.document.iri }}</td> + <td class="text-center">{{ objet.source.document.synonyms }}</td> + <td class="text-center">{{ objet.score | number: '2.2-2' }}</td> + </tr> + </tbody> + </table> + </nb-accordion-item-body> + </nb-accordion-item> + </nb-accordion> + + </ng-container> + <nb-card size="small"> + <nb-card-body> + <nb-form-field> + <input + type="text" + placeholder="enter a value with at least 4 characters" + [formControl]="myControl" + nbInput + [nbAutocomplete]="auto"> + <nb-autocomplete #auto [handleDisplayFn]="viewHandle"> + <nb-option + *ngFor="let option of filteredOptions | async" + [value]="option"> + {{option.source.document.label}} + </nb-option> + </nb-autocomplete> + </nb-form-field> + <!-- <div class="mt0-m"> + <table *ngIf="myControl.value !== null"> + <thead style="background-color: #3366ff"> + <th class="text-center">label</th> + <th class="text-center">iri</th> + </thead> + <tbody> + <tr > + <td class="text-center">{{ myControl.value.source.document.label }}</td> + <td class="text-center">{{ myControl.value.source.document.iri }}</td> + + </tr> + </tbody> + </table> + </div>--> + </nb-card-body> + </nb-card> + <p *ngIf="myControl.value !== null">{{ myControl.value | json }}</p> + + <div class="row"> + <div class="button-center" > + <button nbButton status="primary" (click)="onSubmit()" [nbSpinner]="loadingPublish" [disabled]="loadingPublish" + nbSpinnerStatus="basic">Publish</button> + </div> + </div> +</ng-container> + + diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.ts b/src/app/semantic-enrichment/semantic-enrichment.component.ts index cd61efd4d546e6eea1d3b47b77fba74232e7fa17..9e97a6fe848e8e2a588c3b196f97966ddb2d506c 100644 --- a/src/app/semantic-enrichment/semantic-enrichment.component.ts +++ b/src/app/semantic-enrichment/semantic-enrichment.component.ts @@ -1,11 +1,23 @@ -import {Component, Input, OnInit} from '@angular/core'; +import { + Component, + Input, + OnInit, + TemplateRef, + ViewChild +} from '@angular/core'; import {Observable, of} from 'rxjs'; -import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators'; +import {debounceTime, distinctUntilChanged, map, startWith, switchMap, tap} from 'rxjs/operators'; import {PostService} from './services/post.service'; import {FormControl} from '@angular/forms'; import {KeywordResponse} from '../mapping/class/dataset'; import {ESModel, Result} from './ESModel'; +import {ConceptsRequest, DataConcept} from './ConceptsRequest'; +import {RequestMapping} from '../mapping/class/requestMapping'; +import {NbDialogService} from '@nebular/theme'; +import {MappingService} from '../mapping/service/mapping.service'; +import {FeedbackDialogComponent} from '../mapping/dialog/feedback-dialog/feedback-dialog.component'; +import {MatDialog} from '@angular/material/dialog'; @Component({ selector: 'app-semantic-enrichment', @@ -15,22 +27,61 @@ import {ESModel, Result} from './ESModel'; export class SemanticEnrichmentComponent implements OnInit { @Input() - keywords: Observable<KeywordResponse[]>; + data: RequestMapping; + @Input() + isJsonPath: boolean; + + @Input() + catalogId: string; + @ViewChild('dialog') dialog: TemplateRef<any>; + isLoading: boolean; + errorMess: string; + + response: KeywordResponse[]; myControl = new FormControl(); - options = []; filteredOptions: Observable<Result[]>; + private loadingPublish: boolean; - constructor(private service: PostService) { - this.filteredOptions = this.myControl.valueChanges.pipe( - startWith(''), - debounceTime(400), - distinctUntilChanged(), - switchMap(val => this.filter(val || '')) - ); + constructor(private service: PostService, private dialogService: NbDialogService, + private mappingService: MappingService, private matDialog: MatDialog) { + this.filteredOptions = this.myControl.valueChanges.pipe( + startWith(''), + debounceTime(400), + distinctUntilChanged(), + switchMap(val => this.filter(val || '')) + ); } ngOnInit(): void { + this.getConceptsByKeywords(); + + } + + getConceptsByKeywords() { + this.errorMess = null; + this.isLoading = true; + this.service.getKeywords(this.catalogId, this.isJsonPath, this.data).subscribe( + (response: KeywordResponse[]) => { + this.response = response; + this.response.forEach((resp: KeywordResponse) => { + resp.concepts.results.forEach((result: Result) => { + if (resp.concepts.results.indexOf(result) === 0) { + result.checked = true; + } else { + result.checked = false; + } + }); + }); + }, + (error) => { + this.isLoading = false; + console.log(error.message); + this.errorMess = error.message; + this.openDialog(this.dialog); + }, + () => this.isLoading = false + ); } filter(val: string): Observable<any> { @@ -40,13 +91,69 @@ export class SemanticEnrichmentComponent implements OnInit { map((response) => response.results )); } return of([]); + } - + openDialog(dialog: TemplateRef<any>) { + this.dialogService.open(dialog, { + context: { + title: 'This is a title passed to the dialog component', + }, + }); } viewHandle(value: Result) { return value.source.document.label; } + onSubmit() { + const mappingData = new ConceptsRequest(); + mappingData.paths = this.data.paths; + mappingData.fdpToken = this.data.fdpToken; + mappingData.dataConcepts = []; + this.response.forEach((data: KeywordResponse) => { + const concepts = new DataConcept(); + concepts.id = data.id; + concepts.iris = []; + data.concepts.results.forEach((result: Result) => { + if (result.checked) { + concepts.iris.push(result.source.document.iri); + } + }); + mappingData.dataConcepts.push(concepts); + }); + + console.log(mappingData); + const postedDatasets = []; + const notPostedDatasets = []; + this.loadingPublish = true; + const requestPromises: Promise<any>[] = []; + + const requestPromise = this.mappingService.postToFdpFropSmartharvester(this.catalogId, mappingData, this.isJsonPath).then(resp => { + if (resp) { + resp.json().then((datas: any) => { + console.log(datas.message); + datas.publishedUrl.forEach(e => postedDatasets.push(e)); + datas.notPublishedUrl.forEach(e => notPostedDatasets.push(e)); + }); + } + }); + requestPromises.push(requestPromise); + + Promise.all(requestPromises).finally(() => { + this.loadingPublish = false; + this.matDialog.open(FeedbackDialogComponent, { + data: { + postedMetadatas: postedDatasets, + notPostedMetadatas: notPostedDatasets + } + }).afterClosed().subscribe(); + + }); + } + + + + + } diff --git a/src/app/semantic-enrichment/services/post.service.ts b/src/app/semantic-enrichment/services/post.service.ts index 39a02d5bde2aa5925cb285b8dc5ae128a66ea31f..d83ea9485f6608f03a8ead2ff005743d1848488d 100644 --- a/src/app/semantic-enrichment/services/post.service.ts +++ b/src/app/semantic-enrichment/services/post.service.ts @@ -5,6 +5,8 @@ import {tap} from 'rxjs/operators'; import {ESModel} from '../ESModel'; import {environment} from '../../../environments/environment'; import {TokenStorageService} from '../../authentication/services/token-storage.service'; +import {RequestMapping} from '../../mapping/class/requestMapping'; +import {KeywordResponse} from '../../mapping/class/dataset'; @Injectable({ providedIn: 'root' @@ -35,4 +37,20 @@ export class PostService { ); } } + + getKeywords(catalogId: string, isJsonPath: boolean, data: RequestMapping): Observable<KeywordResponse[]> { + if (this.fds2Token) { + const httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + this.fds2Token + }) + }; + return this.http + .post<KeywordResponse[]>( + `${this.smartHarvesterUrl}/keywords?catalogId=${catalogId}&isJsonPath=${isJsonPath}`, data, httpOptions + ); + } + } } diff --git a/src/app/services/catalog.service.ts b/src/app/services/catalog.service.ts index 2f0d632cbc7f44dfd29253ea8cf485e63bfeceb1..4e871c42e85c6a6c94609197e8c3abb2f6e1d72c 100644 --- a/src/app/services/catalog.service.ts +++ b/src/app/services/catalog.service.ts @@ -17,7 +17,7 @@ export interface FdpApiResponseItem { context: string; } -const FDP_URL = environment.fdpUrl; +let FDP_URL = environment.fdpUrl; @Injectable({ providedIn: 'root' @@ -51,6 +51,9 @@ export class CatalogService { } getCatalogContentById(catId: string) { + if (!environment.staging && !environment.production) { + FDP_URL = FDP_URL.replace(':8080', ''); + } return this.http.get<FdpApiResponseItem[]>(FDP_URL + '/catalog/' + catId, this.httpOptionsFDP); } diff --git a/src/app/services/parse-xml.service.ts b/src/app/services/parse-xml.service.ts index 9d199017f8b966992928afd869efbda0fffc5eb3..c2ca678f9b6eccdd73c64a0cd61e96f792d9cab9 100644 --- a/src/app/services/parse-xml.service.ts +++ b/src/app/services/parse-xml.service.ts @@ -17,7 +17,7 @@ export class ParseXmlService { getXmlResult(body): Observable<any> { let blazePath: string; if (!environment.production && !environment.staging) { - blazePath = environment.fdpUrl + ':8080/blazegraph/sparql'; + blazePath = environment.fdpUrl + '/blazegraph/sparql'; } else { blazePath = environment.fdpUrl + '/blazegraph/sparql'; } diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 5ccf4091bdebc66aacd63923446f0deb391b469a..17a2bd3453a01de97b35343fe4d807efd27dd341 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -6,7 +6,7 @@ export const environment = { production: false, staging: false, smartharvesterUrl: 'http://localhost:8080', - fdpUrl: 'http://10.6.10.97' + fdpUrl: 'http://10.6.10.97:8080' }; /*