diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index fb0727e4ce2ef28991704a7f62ad48fd1d3e1972..4100ee6b460656478ff43eca4ee500bb879987f7 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -30,8 +30,7 @@ const routes: ICustomRoute[] = [ ] }, {path: 'fdpsignin', component: SignupComponent, canActivate: [AuthGuardService]}, - { path: 'login', component: SigninComponent}, - { path: 'semantic', component: SemanticEnrichmentComponent} + { path: 'login', component: SigninComponent} ] @NgModule({ diff --git a/src/app/callback/callback.component.ts b/src/app/callback/callback.component.ts index 072e023daac82607b2f1a66f4fd9ef3b2317b925..2940c875570e2179d5cf03dbb6675b21d36588e7 100644 --- a/src/app/callback/callback.component.ts +++ b/src/app/callback/callback.component.ts @@ -16,8 +16,8 @@ export class CallbackComponent implements OnInit { this.authService.fetchToken(p.code, p.state).subscribe(data => { this.authService.updateToken(data.accessToken); this.router.navigate(['/dashboard']); - }) - }) + }); + }); } } diff --git a/src/app/datasets/datasets.component.ts b/src/app/datasets/datasets.component.ts index ccd15ad1fbf799ba85ab606af8cd45d5f1560519..6b38a7ad754411d9dca50458a731cde872decdb2 100644 --- a/src/app/datasets/datasets.component.ts +++ b/src/app/datasets/datasets.component.ts @@ -253,7 +253,7 @@ export class DatasetsComponent implements OnInit, AfterViewChecked, AfterContent switch (httpMethod.toLowerCase()) { case HttpMethod.GET: - if (this.openApi.info['x-result'] === 'xml' && this.getTagByPathName(pathName, httpMethod) == OpenApiTag.dataset) { + if (this.openApi.info['x-result'] === 'xml' && this.getTagByPathName(pathName, httpMethod) === OpenApiTag.dataset) { requestObs = this.httpClient.get(requestUrl, { headers, responseType: 'text' }); } else { requestObs = this.httpClient.get(requestUrl, { headers }); diff --git a/src/app/mapping/class/dataset.ts b/src/app/mapping/class/dataset.ts index f1e198cceed173236101d580a585bf7d57a7cb7f..250ed14799ffae5fefdd18914764d03b7f5bdc90 100644 --- a/src/app/mapping/class/dataset.ts +++ b/src/app/mapping/class/dataset.ts @@ -7,7 +7,7 @@ export class Property { public geodcat: boolean; public isDuplicated?: boolean = false; public dcatClass?: string; - + constructor(name: string, identifier: string, usageNote: string, isDuplicated: boolean, card: string, geodcat:boolean) { this.property = name; this.uri = identifier; @@ -24,13 +24,13 @@ export class OldProperty { public identifier: string; public usageNote: string; public isDuplicated?: boolean = false; - + constructor(name: string, identifier: string, usageNote: string, isDuplicated: boolean, card: string, geodcat:boolean) { this.name = name; this.identifier = identifier; this.usageNote = usageNote; this.isDuplicated = isDuplicated; - + } } export class DatasetPath { @@ -56,7 +56,7 @@ export class Distribution { public geodcat: boolean; public isDuplicated?: boolean = false; - + } export class ResponseFileTsv { @@ -67,4 +67,8 @@ export class ResponseFileTsv { public object_category: string; } +export class KeywordResponse { + public id: string; + public keywords: string[]; +} diff --git a/src/app/mapping/class/dataverse.ts b/src/app/mapping/class/dataverse.ts deleted file mode 100644 index af158a9f89ea35d8435773376bde79367b0d0e8c..0000000000000000000000000000000000000000 --- a/src/app/mapping/class/dataverse.ts +++ /dev/null @@ -1,52 +0,0 @@ -export interface Dataverse { - status: string, - data: Data -} - -export interface Data { - id: number, - identifier: string, - persistentUrl: string, - protocol : string, - authority: string, - publisher: string, - publicationDate: string, - storageIdentifier: string, - latestVersion: LatestVersion -} - -export interface LatestVersion { - id: number, - datasetId: number, - datasetPersistentId: string, - storageIdentifier: string, - versionNumber: number, - versionMinorNumber: number, - versionState: string, - distributionDate: string, - productionDate: string, - lastUpdateTime: string, - releaseTime: string, - createTime: string, - license: string, - termsOfUse: string, - fileAccessRequest: boolean, - metadataBlocks: MetadataBlock, - file: Array<string> -} - -export interface MetadataBlock { - citation: Citation -} - -export interface Citation { - displayName: string, - fields: Array<Field> -} - -export interface Field { - typeName: string, - multiple: boolean, - typeClass: string, - value: Field | string -} \ No newline at end of file diff --git a/src/app/mapping/mapping.component.html b/src/app/mapping/mapping.component.html index da877ae6197fa95109b19d03f1e6f2beca1714e9..c7c661d03cf452f2ae618d19af4cbba9052bf224 100644 --- a/src/app/mapping/mapping.component.html +++ b/src/app/mapping/mapping.component.html @@ -202,7 +202,7 @@ <input *ngIf="isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" required fullWidth name=" distri{{index}}" nbInput - (ngModelChange)="onModelChange($event)" + (ngModelChange)="onModelChange($event)" [(ngModel)]="distributionSelectedPaths[index]" [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" (focus)="reset()" /> @@ -210,7 +210,7 @@ <input *ngIf="!isMandatory(distribution.card) && distribution.uri !== 'dcat:distribution'" fullWidth name=" distri{{index}}" nbInput - (ngModelChange)="onModelChange($event)" + (ngModelChange)="onModelChange($event)" [(ngModel)]="distributionSelectedPaths[index]" [value]="distributionSelectedPaths[index]? distributionSelectedPaths[index] : ''" (focus)="reset()" /> @@ -371,9 +371,9 @@ </div> </div> - <div class="row"> + <div class="row"> <div class="button-center" *ngIf="!first "> - <button nbButton status="primary" (click)=" publishDataset()" [nbSpinner]="loading" + <button nbButton status="primary" (click)="getKeywords()" [nbSpinner]="loading" nbSpinnerStatus="basic">Publish</button> </div> </div> @@ -413,14 +413,14 @@ </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> -</ng-template> \ No newline at end of file +</ng-template> diff --git a/src/app/mapping/mapping.component.ts b/src/app/mapping/mapping.component.ts index a25b4f5c40ea5098c1868af8ab91f388845d27b7..eb2a5fc9b8bfc7bc0eb8b0f4159b55d8fdda818f 100644 --- a/src/app/mapping/mapping.component.ts +++ b/src/app/mapping/mapping.component.ts @@ -12,7 +12,7 @@ import { environment } from 'src/environments/environment'; import { TokenStorageService } from '../authentication/services/token-storage.service'; import { DatasetCrudService } from '../datasets/services/dataset-crud.service'; -import { Property, DatasetPath, Distribution, ResponseFileTsv, OldProperty } from './class/dataset'; +import {Property, DatasetPath, Distribution, ResponseFileTsv, OldProperty, KeywordResponse} from './class/dataset'; import { Path, RequestMapping } from './class/requestMapping'; import { FeedbackDialogComponent } from './dialog/feedback-dialog/feedback-dialog.component'; import { MappingService } from './service/mapping.service'; @@ -25,11 +25,14 @@ import { JSONPath } from 'jsonpath-plus'; }) export class MappingComponent implements OnInit { + /*@Output() + dataEvent = new EventEmitter<RequestMapping>(); + @Output() - pathsEvent = new EventEmitter<Path[]>(); + isJsonPathEvent = new EventEmitter();*/ @Output() - isJsonPathEvent = new EventEmitter(); + keywordsEvent = new EventEmitter<Observable<KeywordResponse[]>>(); paths: Path[]; addDistribution = false; @@ -58,7 +61,9 @@ export class MappingComponent implements OnInit { @Input() type: string; @Input() catalogId: any; - constructor(private ref: ChangeDetectorRef, private dataSetService: DatasetCrudService, private dialog: MatDialog, private route: Router, private tokenStorage: TokenStorageService, private mappingService: MappingService) { + constructor(private ref: ChangeDetectorRef, private dataSetService: DatasetCrudService, + private dialog: MatDialog, private route: Router, private tokenStorage: TokenStorageService, + private mappingService: MappingService) { ref.detach(); setInterval(() => { this.ref.detectChanges(); @@ -97,7 +102,8 @@ export class MappingComponent implements OnInit { (distributions: Distribution[]) => { this.distributions = this.ontology === 'dcat' ? distributions.filter(d => !d.geodcat) : distributions; this.distributions.forEach(distribution => distribution.dcatClass = 'dcat:distribution'); - this.vocabularies = this.vocabularies.concat(this.ontology === 'dcat' ? this.distributions.filter(d => !d.geodcat) : distributions); + this.vocabularies = this.vocabularies.concat(this.ontology === 'dcat' ? + this.distributions.filter(d => !d.geodcat) : distributions); this.distributionSelectedPaths = []; } ); @@ -134,7 +140,8 @@ export class MappingComponent implements OnInit { for (let i = 0; i < array.length; i++) { if (array[i] && array.length > 0) { const tab = array[i].split(' : '); - !this.isJsonPath ? mappedMetadata.set(i, this.getValueCustom(tab, item)) : mappedMetadata.set(i, this.getValueJsonPath(array[i], item)); + !this.isJsonPath ? mappedMetadata.set(i, this.getValueCustom(tab, item)) + : mappedMetadata.set(i, this.getValueJsonPath(array[i], item)); } } this.loadingCr = false; @@ -159,9 +166,8 @@ export class MappingComponent implements OnInit { } } - this.pathsEvent.emit(paths); - const data: RequestMapping = new RequestMapping(this.urls, paths, this.tokenStorage.getFDPToken()); - + const data: RequestMapping = new RequestMapping(this.ids, paths, this.tokenStorage.getFDPToken()); + // this.dataEvent.emit(data); const postedDatasets = []; const notPostedDatasets = []; this.loading = true; @@ -354,11 +360,11 @@ export class MappingComponent implements OnInit { private getValueCustom(tab: string[], item: Object) { let obj: Object; try { - if (tab.length == 1) { + if (tab.length === 1) { return item[tab[0]]; } else { for (let i = 0; i < tab.length; i++) { - if (i == 0) { + if (i === 0) { obj = item[tab[i]]; } else if (i < tab.length - 1 && obj[tab[i]]) { obj = obj[tab[i]]; @@ -416,10 +422,10 @@ export class MappingComponent implements OnInit { private getValueDataverse(tab: string[], item: Object): string { let obj: Object; for (let i = 0; i < tab.length; i++) { - if (tab.length == 1) { + if (tab.length === 1) { return item[tab[0]]; } else { - if (i == 0) { + if (i === 0) { obj = item[tab[i]]; } else if (i < tab.length - 1 && obj[tab[i]]) { obj = obj[tab[i]]; @@ -427,17 +433,17 @@ export class MappingComponent implements OnInit { if (obj[tab[i]] && typeof obj[tab[i]] !== 'object') { return obj[tab[i]]; } else { - if (i == tab.length - 2) { + if (i === tab.length - 2) { this.getKeysFromMetadataDataverse(item, ''); console.log(tab[i] + ' ' + i); this.keys.forEach(k => { const table = k.split(' : '); if (table[table.length - 2] === tab[i]) { for (let i = 0; i < tab.length; i++) { - if (table.length == 1) { + if (table.length === 1) { return item[tab[0]]; } else { - if (i == 0) { + if (i === 0) { obj = item[table[i]]; } else if (i < table.length - 1 && obj[table[i]]) { obj = obj[table[i]]; @@ -471,7 +477,9 @@ export class MappingComponent implements OnInit { this.datasetMappedMetadatas.push([this.createDataset(this.itemsdataset[i], 'dataset')]); if (this.distributionSelectedPaths.length > 0) { if (this.distributionSelectedPaths[0] !== '' && this.distributionSelectedPaths[0] !== null && this.distributionSelectedPaths[0]) { - const distributionItems: Object[] = (this.isJsonPath) ? this.getValueJsonPath(this.distributionSelectedPaths[0], this.itemsdataset[i]) : this.getDistributionItem(this.distributionSelectedPaths[0].split(' : '), this.itemsdataset[i]); + const distributionItems: Object[] = (this.isJsonPath) + ? this.getValueJsonPath(this.distributionSelectedPaths[0], this.itemsdataset[i]) + : this.getDistributionItem(this.distributionSelectedPaths[0].split(' : '), this.itemsdataset[i]); const distributionArray: Map<number, string>[] = []; for (let j = 0; j < distributionItems.length; j++) { const item = distributionItems[j]; @@ -511,7 +519,9 @@ export class MappingComponent implements OnInit { } for (let i = 0; i < this.distributions.length; i++) { if (this.distributionSelectedPaths[i]) { - datasetPathArray.push(new DatasetPath(this.distributions[i], this.distributionSelectedPaths[i], 'dcat:distribution', this.distributions[i].card)); + datasetPathArray.push( + new DatasetPath(this.distributions[i], this.distributionSelectedPaths[i], 'dcat:distribution', this.distributions[i].card) + ); } } return datasetPathArray; @@ -580,9 +590,11 @@ export class MappingComponent implements OnInit { this.selectedPaths.splice(i + 1, 0, paths[i].path); if (typeof paths[i].dcatProperty !== 'object') { - this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === paths[i].dcatProperty as string); + this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset') + .find(v => v.uri === paths[i].dcatProperty as string); } else { - this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === (paths[i].dcatProperty as unknown as OldProperty).identifier); + this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset') + .find(v => v.uri === (paths[i].dcatProperty as unknown as OldProperty).identifier); } } else { @@ -653,7 +665,7 @@ export class MappingComponent implements OnInit { toggleJsonPath(checked: boolean) { this.isJsonPath = checked; if (this.isJsonPath) { this.filteredOptions = of([]); } - this.isJsonPathEvent.emit(this.isJsonPath); + // this.isJsonPathEvent.emit(this.isJsonPath); } toggleDistri(checked: boolean) { @@ -672,6 +684,22 @@ export class MappingComponent implements OnInit { return this.vocabularies.find((vocabulary: Property) => vocabulary.uri === uri).card; } + getKeywords() { + + const paths: Path[] = []; + + for (let i = 0; i < this.datasets.length; i++) { + if (this.selectedPaths[i]) { + paths.push(new Path(this.datasets[i].uri, this.selectedPaths[i], this.datasets[i].card, this.datasets[i].dcatClass)); + } + } + 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([])) + )); + } + private getDistributionEmpty(properties: string, datasetId: string): string { return `@prefix dcat: <http://www.w3.org/ns/dcat#>. @prefix dct: <http://purl.org/dc/terms/>. diff --git a/src/app/mapping/service/mapping.service.ts b/src/app/mapping/service/mapping.service.ts index 3f95a4e70f22d57e33ca2f9e95c5ae85568ee6a1..061511ba6a06dd4bbc7e9594360f7695b7b66a17 100644 --- a/src/app/mapping/service/mapping.service.ts +++ b/src/app/mapping/service/mapping.service.ts @@ -3,8 +3,9 @@ import { Injectable } from '@angular/core'; import { TokenStorageService } from 'src/app/authentication/services/token-storage.service'; import { SmartHarvesterUser } from 'src/app/user/model/user'; import { environment } from 'src/environments/environment'; -import { DatasetPath } from '../class/dataset'; +import {DatasetPath, KeywordResponse} from '../class/dataset'; import { RequestMapping } from '../class/requestMapping'; +import {Observable} from 'rxjs'; @Injectable({ @@ -16,15 +17,11 @@ export class MappingService { smartHarvesterUrl = environment.smartharvesterUrl; fdpUrl = environment.fdpUrl; fds2Token: string = this.storageService.getToken(); - fdpToken: string = this.storageService.getFDPToken() + fdpToken: string = this.storageService.getFDPToken(); constructor(private storageService: TokenStorageService, private http: HttpClient) { } - postFile(objArray: DatasetPath[], catalogId: String) { - - - - + postFile(objArray: DatasetPath[], catalogId: string) { const body: Blob = new Blob(['\ufeff' + this.convertToTSV(objArray, [ 'subject_label', @@ -40,20 +37,17 @@ export class MappingService { data.append('file', body); const req = new HttpRequest('POST', `${this.smartHarvesterUrl}/harvester/api/storeMapping/upload/${catalogId}`, data, { headers: new HttpHeaders({ - - 'Authorization': 'Bearer ' + this.fds2Token - }), - reportProgress: true, - responseType: 'json' - }); - - return this.http.request(req); + + Authorization: 'Bearer ' + this.fds2Token + }), reportProgress: true, responseType: 'json'}); + + return this.http.request(req); } downloadFile(data: DatasetPath[], filename = 'dcatMapping') { - let tsvData = this.convertToTSV(data, [ + const tsvData = this.convertToTSV(data, [ 'subject_label', 'predicate_id', 'object_id', @@ -61,12 +55,12 @@ export class MappingService { 'object_category' ]); - let blob = new Blob(['\ufeff' + tsvData], { + const blob = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;', }); - let dwldLink = document.createElement('a'); - let url = URL.createObjectURL(blob); - let safariBrowser = navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1; + const dwldLink = document.createElement('a'); + const url = URL.createObjectURL(blob); + const safariBrowser = navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1; if (safariBrowser) { dwldLink.setAttribute('target', '_blank'); } @@ -79,13 +73,14 @@ export class MappingService { } convertToTSV(objArray: DatasetPath[], headerList: string[]): string { - let date = new Date(); - let user: SmartHarvesterUser = this.storageService.getUser(); - let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; - let str = `#mapping_date: ${date.getDate()}/${date.getMonth()}/${date.getFullYear()}\n#creator_label: ${user.firstName} ${user.lastName}\n#curie_map:\n# dcat: "http://www.w3.org/ns/dcat#"\n# dct: "http://purl.org/dc/terms/"\n# adms: "http://www.w3.org/ns/adms#\n# dqv: "http://www.w3.org/ns/dqv#"\n# geodcat: "http://data.europa.eu/930/"\n# prov: "http://www.w3.org/ns/prov#"\n# rdfs: "http://www.w3.org/2000/01/rdf-schema#"\n`; + const date = new Date(); + const user: SmartHarvesterUser = this.storageService.getUser(); + const array = typeof objArray !== 'object' ? JSON.parse(objArray) : objArray; + let str = + `#mapping_date: ${date.getDate()}/${date.getMonth()}/${date.getFullYear()}\n#creator_label: ${user.firstName} ${user.lastName}\n#curie_map:\n# dcat: "http://www.w3.org/ns/dcat#"\n# dct: "http://purl.org/dc/terms/"\n# adms: "http://www.w3.org/ns/adms#\n# dqv: "http://www.w3.org/ns/dqv#"\n# geodcat: "http://data.europa.eu/930/"\n# prov: "http://www.w3.org/ns/prov#"\n# rdfs: "http://www.w3.org/2000/01/rdf-schema#"\n`; let row = ''; - for (let index in headerList) { + for (const index in headerList) { row += headerList[index] + '\t'; } row = row.slice(0, -1); @@ -94,8 +89,8 @@ export class MappingService { if (array[i].path) { let line = ''; - for (let index in headerList) { - let head = headerList[index]; + for (const index in headerList) { + const head = headerList[index]; switch (head) { case 'subject_label': line += array[i].path + '\t'; @@ -113,7 +108,7 @@ export class MappingService { line += array[i].dcatClass + '\t'; } } - str += (i != array.length - 1) ? line + '\n' : line; + str += (i !== array.length - 1) ? line + '\n' : line; } @@ -123,29 +118,29 @@ export class MappingService { } tsvToJson(tsv: string): Object { - let lines: string[] = tsv.split('\n'); - let result = []; - console.table(lines) + const lines: string[] = tsv.split('\n'); + const result = []; + console.table(lines); while (lines[0].startsWith('#')) { lines.shift(); } - console.table(lines) - let headers = [ + console.table(lines); + const headers = [ 'subject_label', 'predicate_id', 'object_id', 'match_type', 'object_category' - ] + ]; - lines.shift() + lines.shift(); for (let i = 0; i < lines.length; i++) { - let obj = {}; - let currentLine = lines[i].split('\t'); + const obj = {}; + const currentLine = lines[i].split('\t'); - for (var j = 0; j < headers.length; j++) { + for (let j = 0; j < headers.length; j++) { obj[headers[j]] = currentLine[j]; } @@ -156,13 +151,14 @@ export class MappingService { } async postToFdpFropSmartharvester(catalogId: string, data: RequestMapping, isJsonpath: boolean): Promise<any> { - - if(this.fds2Token) { + + if (this.fds2Token) { const httpOptions = new Headers(); httpOptions.append('Content-Type', 'application/json'); httpOptions.append('Accept', 'application/json'); - httpOptions.append('Authorization', `Bearer ${this.fds2Token}`) - let url = `${this.smartHarvesterUrl}/harvester/api/transform/publish?fdpUrl=${this.fdpUrl}&catalogId=${catalogId}&isJsonpath=${isJsonpath}`; + httpOptions.append('Authorization', `Bearer ${this.fds2Token}`); + const url = + `${this.smartHarvesterUrl}/harvester/api/transform/publish?fdpUrl=${this.fdpUrl}&catalogId=${catalogId}&isJsonpath=${isJsonpath}`; const myInit = { method: 'POST', body: JSON.stringify(data), headers: httpOptions}; const myRequest = new Request(url, myInit); @@ -177,12 +173,28 @@ export class MappingService { const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Authorization': 'Bearer ' + this.fdpToken + Accept: 'application/json', + Authorization: 'Bearer ' + this.fdpToken }) }; return this.http.put(`${url}/meta/state`, { current: 'PUBLISHED' }, httpOptions).toPromise(); } } + + 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 ed5330bb283b80694272e94133aa3ac20240fa63..f907db6dfb715ea1c8657d92388497ff190a0941 100644 --- a/src/app/publishapi/publishapi.component.html +++ b/src/app/publishapi/publishapi.component.html @@ -315,17 +315,17 @@ <p class="lorem"> 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']" - (pathsEvent)="pathsEventHandler($event)" (isJsonPathEvent)="isJsonPathEventHandler($event)"> + <app-mapping *ngIf="initLabelThree && datasets.ready" [catalogId]="openApi.info['x-catalog-id']" + [type]="openApi.info['x-format']" (keywordsEvent)="keywordsEventHandler($event)" > </app-mapping> <button class="prev-button" nbButton nbStepperPrevious - (click)="initLabelThree=false; resetDataset(); datasets.ready = false"; getKeywords()>prev</button> - <button class="next-button" nbButton disabled nbStepperNext>next</button> + (click)="initLabelThree=false; resetDataset(); datasets.ready = false">prev</button> + <button class="next-button" nbButton nbStepperNext (click)="mappingComponent.getKeywords()">next</button> </nb-step> <nb-step [label]="labelFour"> <ng-template #labelFour>Fourth step</ng-template> <h4>Semantic Enrichment</h4> - <app-semantic-enrichment [paths]="paths"></app-semantic-enrichment> + <app-semantic-enrichment [keywords]="keywords"></app-semantic-enrichment> <button class="prev-button" nbButton nbStepperPrevious>prev</button> <button class="next-button" nbButton disabled nbStepperNext>next</button> </nb-step> diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts index 0e894729cf89ba6e2ddffa36624b1cdae95a48c9..fca06ce2125b51ace4d0c3b5b99ca251ffbc4024 100644 --- a/src/app/publishapi/publishapi.component.ts +++ b/src/app/publishapi/publishapi.component.ts @@ -10,8 +10,10 @@ import { OpenApiTag } 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'; -import {Path as PathReq} from '../mapping/class/requestMapping' ; -import {KeywordRequest} from './class/keywordRequest'; +import { RequestMapping} from '../mapping/class/requestMapping' ; +import {MappingComponent} from '../mapping/mapping.component'; +import {KeywordResponse} from '../mapping/class/dataset'; +import {Observable} from 'rxjs'; @Component({ selector: 'app-publishapi', @@ -24,9 +26,12 @@ export class PublishApiComponent implements OnInit { @ViewChild('catalogSelect') catalogSelect; @ViewChild('datasets') datasets; @ViewChild('stepper') stepper: NbStepperComponent; + @ViewChild(MappingComponent) + private mappingComponent: MappingComponent; - paths: PathReq[]; + data: RequestMapping; isJsonPath: boolean; + keywords: Observable<KeywordResponse[]>; constructor( private openApiService: OpenApiService, @@ -62,12 +67,16 @@ export class PublishApiComponent implements OnInit { this.datasetService.resetDataset(); } - pathsEventHandler($event: PathReq[]) { - this.paths = $event; - } + /*dataEventHandler($event: RequestMapping) { + this.data = $event; + }*/ - isJsonPathEventHandler($event: boolean) { + /* isJsonPathEventHandler($event: boolean) { this.isJsonPath = $event; + }*/ + + keywordsEventHandler($event: Observable<KeywordResponse[]>) { + this.keywords = $event; } getPrettyJson(): string { @@ -385,18 +394,9 @@ export class PublishApiComponent implements OnInit { this.datasets.openDatasetsSelectDialog(this.stepper); } - getKeywords() { - let keywordPaths: string[] = []; - if (this.paths !== null) { - for (const path of this.paths) { - if (path.dcatClass === 'dcat:keyword') { - keywordPaths.push(path.path); - } - } + /*getKeywords() { - const data = new KeywordRequest(this.isJsonPath, keywordPaths); - } - } + }*/ } diff --git a/src/app/semantic-enrichment/ESModel.ts b/src/app/semantic-enrichment/ESModel.ts new file mode 100644 index 0000000000000000000000000000000000000000..b47a68343a4d001d5fbded25d2c94aefcffcac25 --- /dev/null +++ b/src/app/semantic-enrichment/ESModel.ts @@ -0,0 +1,30 @@ +export class ESModel { + public search1: string; + public search2: string; + public count: number; + public best: number; + public results: Result[]; +} + +export class Result { + public score: number; + public source: Source; +} + +export class Source { + public document: Document; + public timestamp: Date; +} + +export class Document { + public iri: string; + public synonyms: string[]; + public label: string; + public resourceIri: string; + public resourceAcronym: string; + public resourceReusingAcronyms: string[]; + public resourceDate: Date; + public resourceName: string; + public resourceVersion: string; + public domains: string[]; +} diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.html b/src/app/semantic-enrichment/semantic-enrichment.component.html index 87756692f066a156ad6021584c8a36dadc210020..21411376b82f646323d18476eb0917161049d1c6 100644 --- a/src/app/semantic-enrichment/semantic-enrichment.component.html +++ b/src/app/semantic-enrichment/semantic-enrichment.component.html @@ -1,4 +1,4 @@ -<nb-layout> +<!--<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> @@ -9,14 +9,17 @@ </nb-layout-header> - <nb-layout-column> - - <nb-card size="small"> + <nb-layout-column>--> +<ng-template #loading> + <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 Location" + placeholder="enter a value with at least 4 characters" [formControl]="myControl" nbInput [nbAutocomplete]="auto"> @@ -24,17 +27,17 @@ <nb-option *ngFor="let option of filteredOptions | async" [value]="option"> - {{option.name}} + {{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-column> <nb-layout-footer>Contact us</nb-layout-footer> - +--> diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.ts b/src/app/semantic-enrichment/semantic-enrichment.component.ts index b15b368f8bf94be11a56bf59aa95532ee291ed0d..cd61efd4d546e6eea1d3b47b77fba74232e7fa17 100644 --- a/src/app/semantic-enrichment/semantic-enrichment.component.ts +++ b/src/app/semantic-enrichment/semantic-enrichment.component.ts @@ -1,10 +1,11 @@ import {Component, Input, OnInit} from '@angular/core'; -import {Path} from '../mapping/class/requestMapping'; -import {Observable} from 'rxjs'; +import {Observable, of} from 'rxjs'; import {debounceTime, distinctUntilChanged, map, startWith, switchMap} 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'; @Component({ selector: 'app-semantic-enrichment', @@ -14,43 +15,37 @@ import {FormControl} from '@angular/forms'; export class SemanticEnrichmentComponent implements OnInit { @Input() - paths: Path[]; + keywords: Observable<KeywordResponse[]>; myControl = new FormControl(); options = []; - filteredOptions: Observable<any>; + filteredOptions: Observable<Result[]>; constructor(private service: PostService) { - - this.filteredOptions = this.myControl.valueChanges.pipe( - startWith(''), - debounceTime(400), - distinctUntilChanged(), - switchMap(val => { - return this.filter(val || ''); - }) - ); + this.filteredOptions = this.myControl.valueChanges.pipe( + startWith(''), + debounceTime(400), + distinctUntilChanged(), + switchMap(val => this.filter(val || '')) + ); } ngOnInit(): void { - /*for ( let path of this.paths) { - if (path.property === 'dcat:keyword') { - - } - }*/ } - filter(val: any): Observable<any> { - return this.service.getData() - .pipe( - map(response => response.filter((option: any) => { - return option.name.toLowerCase().includes(val.toLowerCase()); - })) - ); + filter(val: string): Observable<any> { + if (val.length > 3) { + return this.service.getData(val) + .pipe( + map((response) => response.results )); + } + return of([]); + + } - viewHandle(value: any) { - return value.name; + viewHandle(value: Result) { + return value.source.document.label; } } diff --git a/src/app/semantic-enrichment/services/post.service.spec.ts b/src/app/semantic-enrichment/services/post.service.spec.ts deleted file mode 100644 index 913642b87e73bd219c4d1f0d2c6e6d161662583f..0000000000000000000000000000000000000000 --- a/src/app/semantic-enrichment/services/post.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { PostService } from './post.service'; - -describe('PostService', () => { - let service: PostService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(PostService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/semantic-enrichment/services/post.service.ts b/src/app/semantic-enrichment/services/post.service.ts index afb0b8d79f6ea3d34df0a3a44fec326c528299b7..39a02d5bde2aa5925cb285b8dc5ae128a66ea31f 100644 --- a/src/app/semantic-enrichment/services/post.service.ts +++ b/src/app/semantic-enrichment/services/post.service.ts @@ -1,23 +1,38 @@ -import { Injectable } from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import {of} from 'rxjs'; +import {Injectable} from '@angular/core'; +import {HttpClient, HttpHeaders} from '@angular/common/http'; +import {Observable, of} from 'rxjs'; import {tap} from 'rxjs/operators'; +import {ESModel} from '../ESModel'; +import {environment} from '../../../environments/environment'; +import {TokenStorageService} from '../../authentication/services/token-storage.service'; @Injectable({ providedIn: 'root' }) export class PostService { + smartHarvesterUrl = environment.smartharvesterUrl + '/harvester/api/es'; + fds2Token: string = this.storageService.getToken(); - constructor(private http: HttpClient) { } + constructor(private http: HttpClient, private storageService: TokenStorageService) { } opt = []; - getData() { - return this.opt.length ? - of(this.opt) : - this.http.get('https://jsonplaceholder.typicode.com/users').pipe( - tap((data: any) => this.opt = data) - ); + getData(value: string): Observable<ESModel> { + + if (this.fds2Token) { + const httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + this.fds2Token + }) + }; + return this.opt.length ? + of(this.opt) : + this.http.get<ESModel>(`${this.smartHarvesterUrl}/autocomplete?search1=${value}`, httpOptions).pipe( + tap((data: any) => this.opt = data) + ); + } } } diff --git a/src/app/services/parse-xml.service.ts b/src/app/services/parse-xml.service.ts index eebcb43b3771761db9d0df509388fa1df73283eb..9d199017f8b966992928afd869efbda0fffc5eb3 100644 --- a/src/app/services/parse-xml.service.ts +++ b/src/app/services/parse-xml.service.ts @@ -2,25 +2,34 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { environment } from 'src/environments/environment'; +import {TokenStorageService} from '../authentication/services/token-storage.service'; @Injectable({ providedIn: 'root' }) export class ParseXmlService { - - blazePath = environment.fdpUrl+ "/blazegraph/sparql"; - constructor(private http:HttpClient) { } - - + + token: string = this.storageService.getToken(); + + constructor(private http: HttpClient, private storageService: TokenStorageService) { } + getXmlResult(body): Observable<any> { + let blazePath: string; + if (!environment.production && !environment.staging) { + blazePath = environment.fdpUrl + ':8080/blazegraph/sparql'; + } else { + blazePath = environment.fdpUrl + '/blazegraph/sparql'; + } + const httpOptions = { - headers: new HttpHeaders({ - 'Content-Type': 'application/x-www-form-urlencoded', - 'responseType': 'application/sparql-results+xml' - }) - }; - return this.http.post(this.blazePath,body, httpOptions); + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: 'Bearer ' + this.token + }) + }; + return this.http.post(`${environment.smartharvesterUrl}/harvester/api/sparql?url=${(blazePath)}`, body, httpOptions); } } diff --git a/src/app/stats/stats.component.ts b/src/app/stats/stats.component.ts index 0b27976113fa4b1d82fc507173b1f657cbbeb6c2..673029ca7a7bec2dfcb01b39bdc86f4bef789fcb 100644 --- a/src/app/stats/stats.component.ts +++ b/src/app/stats/stats.component.ts @@ -11,32 +11,43 @@ import { environment } from 'src/environments/environment'; styleUrls: ['./stats.component.scss'] }) export class StatsComponent implements OnInit { - - public results: string[] = []; + + public results: string[] = []; public stats: string[] = []; constructor(private parserService: ParseXmlService) { } ngOnInit(): void { - let query1='query=prefix dct: <http://purl.org/dc/terms/>\n\ - SELECT (COUNT(?s) AS ?triples) \n\ - WHERE { ?s a <http://www.w3.org/ns/dcat#Catalog>;\n\ - dct:isPartOf <'+ environment.fdpUrl +'>\n\ - }' - this.parserService.getXmlResult(query1).subscribe(data=>{if (data){this.results = []; data.results.bindings.forEach(element => { this.results.push(element);}); - this.stats.push(this.results[0]["triples"].value) - - let query2='query=prefix dct: <http://purl.org/dc/terms/>\n\ - SELECT (COUNT(?s) AS ?triples) \n\ - WHERE { ?s a <http://www.w3.org/ns/dcat#Dataset>;\n\ - dct:isPartOf* <'+ environment.fdpUrl +'>\n\ - }' - this.parserService.getXmlResult(query2).subscribe(data=>{if (data){this.results = []; data.results.bindings.forEach(element => { this.results.push(element);}); - this.stats.push(this.results[0]["triples"].value); }}) - - console.log(this.stats); - }}) + const query1 = 'prefix dct: <http://purl.org/dc/terms/> ' + + 'SELECT (COUNT(?s) AS ?triples) ' + + 'WHERE { ?s a <http://www.w3.org/ns/dcat#Catalog>; ' + + 'dct:isPartOf <' + environment.fdpUrl + '>}'; + this.parserService.getXmlResult(query1) + .subscribe(data => { + if (data) { + this.results = []; data.results.bindings.forEach(element => { + this.results.push(element); + }); + this.stats.push(this.results[0]['triples'].value); + + const query2 = 'prefix dct: <http://purl.org/dc/terms/> ' + + 'SELECT (COUNT(?s) AS ?triples) ' + + 'WHERE { ?s a <http://www.w3.org/ns/dcat#Dataset>;' + + ' dct:isPartOf* <' + environment.fdpUrl + '> }'; + this.parserService.getXmlResult(query2) + .subscribe(data => { + if (data) { + this.results = []; + data.results.bindings.forEach(element => { + this.results.push(element); + }); + this.stats.push(this.results[0]['triples'].value); } + }); + + console.log(this.stats); + } + }); } diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 6b547d4efd3da0fe2ade884853be3b58de53d1ea..fd79f2409e5dfcb24afbc7f2451c6e3946c6d3e8 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,5 +1,6 @@ export const environment = { production: true, + staging: false, smartharvesterUrl: 'https://f2ds.eosc-pillar.eu', fdpUrl: 'https://f2ds.eosc-pillar.eu' }; diff --git a/src/environments/environment.staging.ts b/src/environments/environment.staging.ts index 1946fcc6f766811d8acde218cf3e38da8ed99720..93c94c2dfe2ba61a3f3c8af69e30a6a46ede0f43 100644 --- a/src/environments/environment.staging.ts +++ b/src/environments/environment.staging.ts @@ -1,5 +1,6 @@ export const environment = { production: false, + staging: true, smartharvesterUrl: 'https://f2ds-dev.eosc-pillar.eu', fdpUrl: 'https://f2ds-dev.eosc-pillar.eu' - }; \ No newline at end of file + }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 133ced8206075fbd06ec2d46aac09e74e8ce2abc..5ccf4091bdebc66aacd63923446f0deb391b469a 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -4,8 +4,9 @@ export const environment = { production: false, + staging: false, smartharvesterUrl: 'http://localhost:8080', - fdpUrl: 'http://10.6.10.97:8080' + fdpUrl: 'http://10.6.10.97' }; /*