diff --git a/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.ts b/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.ts index 228ca2f0d..6826d09fa 100644 --- a/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.ts +++ b/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.ts @@ -1,6 +1,6 @@ /* * RERO ILS UI - * Copyright (C) 2019 RERO + * Copyright (C) 2019-2022 RERO * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -22,7 +22,7 @@ import { Record, RecordService } from '@rero/ng-core'; import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record'; import { cloneDeep } from 'lodash-es'; import { BsModalService } from 'ngx-bootstrap/modal'; -import { forkJoin, Observable, of, Subscription } from 'rxjs'; +import { Observable, of, Subscription } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { DocumentApiService } from '../../../api/document-api.service'; import { OperationLogsService } from '../../../service/operation-logs.service'; @@ -72,6 +72,54 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest return this._operationLogsService.isLogVisible('documents'); } + /** Source for imported record. */ + get source() { + if (this._activatedRouter.snapshot && this._activatedRouter.snapshot.params && this._activatedRouter.snapshot.params.type !== null) { + return this._activatedRouter.snapshot.params.type.replace('import_', ''); + } + return null; + } + + /** External identifier for imported record. */ + get pid(): string | null { + if (this._activatedRouter.snapshot && this._activatedRouter.snapshot.params && this._activatedRouter.snapshot.params.pid !== null) { + return this._activatedRouter.snapshot.params.pid; + } + return null; + } + + /** + * Related resources to display below 'Subjects' + */ + get relatedResources() { + if (this.record.metadata.electronicLocator) { + return this.record.metadata.electronicLocator.filter( + (electronicLocator: any) => [ + 'hiddenUrl', 'noInfo', 'resource', 'relatedResource', 'versionOfResource' + ].some(t => t === electronicLocator.type && electronicLocator.content !== 'coverImage') + ); + } + } + + /** + * Resources to display like a holding + */ + get resources() { + if (this.record.metadata.electronicLocator) { + return this.record.metadata.electronicLocator.filter( + (electronicLocator: any) => ['resource', 'versionOfResource'].some(t => t === electronicLocator.type) + ); + } + } + + /** + * Get Current language interface + * @return string - language + */ + get currentLanguage(): string { + return this._translateService.currentLang; + } + /** * Constructor * @param _translateService - TranslateService to translate some strings. @@ -93,7 +141,7 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest ) { } /** On init hook */ - ngOnInit() { + ngOnInit(): void { this._recordObs = this.record$.pipe( switchMap((record: any) => { this.record = record; @@ -114,6 +162,20 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest }); } + /** On destroy hook */ + ngOnDestroy(): void { + this._recordObs.unsubscribe(); + } + + /** + * Allow to filter provisionActivity keeping only activities that are 'Publication' + * @param element: the element to check + * @return True if element is a 'Publication', False otherwise + */ + filterPublicationProvisionActivity(element: any): boolean { + return ('key' in element && element.key === 'bf:Publication'); + } + /** * Import Document * @param event - Event @@ -125,8 +187,10 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest const keysTypes = Object.keys(this.mappingtypes); const rec = record.metadata; const route = ['/records', 'documents', 'new']; + const queryParams = []; + // If we have identifiers if (rec.identifiedBy) { - const queryParams = []; + // We select only a defined part of the identifier rec.identifiedBy.forEach((identifier: any) => { if (['bf:Isbn', 'bf:Issn', 'bf:Doi', 'bf:Lccn', 'bf:IssnL', 'bf:Ean'].includes(identifier.type)) { queryParams.push(this._extractAndFormatQueryParams(identifier)); @@ -135,8 +199,28 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest cidentifier.type = this.mappingtypes[cidentifier.type]; queryParams.push(this._extractAndFormatQueryParams(cidentifier)); } - } + } }); + } + + // If we do not have a identifier and we have a title + // TODO: Nice to have - create an backend API entrypoint to detect the duplicate resource. + // https://github.com/rero/rero-ils/issues/2900 (Generalize to all resources) + if (queryParams.length === 0 && rec.title) { + // We extract the title + const titles = rec.title.filter((rtitle: any) => rtitle.type === 'bf:Title' && '_text' in rtitle); + if (titles.length > 0) { + // We clean the text string by deleting some characters + const regex = /["\[\]]/gi; + queryParams.push(`title._text:"${titles[0]._text.replace(regex, '')}"`); + } + } + + // No identifier and no title, we redirect to the add form. + if (queryParams.length === 0) { + this._router.navigate(route, { queryParams: data }); + } else { + // Find documents(s) with query params const query = queryParams.join(' OR '); this._recordService.getRecords( 'documents', query, 1, undefined, undefined, undefined, { accept: 'application/rero+json' } @@ -157,70 +241,6 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest }); } }); - } else { - this._router.navigate(route, { queryParams: data }); - } - } - - /** Source for imported record. */ - get source() { - if (this._activatedRouter.snapshot && this._activatedRouter.snapshot.params && this._activatedRouter.snapshot.params.type !== null) { - return this._activatedRouter.snapshot.params.type.replace('import_', ''); - } - return null; - } - - /** External identifier for imported record. */ - get pid() { - if (this._activatedRouter.snapshot && this._activatedRouter.snapshot.params && this._activatedRouter.snapshot.params.pid !== null) { - return this._activatedRouter.snapshot.params.pid; - } - return null; - } - - /** On destroy hook */ - ngOnDestroy(): void { - this._recordObs.unsubscribe(); - } - - /** - * Get Current language interface - * @return string - language - */ - get currentLanguage() { - return this._translateService.currentLang; - } - - /** - * Allow to filter provisionActivity keeping only activities that are 'Publication' - * @param element: the element to check - * @return True if element is a 'Publication', False otherwise - */ - filterPublicationProvisionActivity(element: any): boolean { - return ('key' in element && element.key === 'bf:Publication'); - } - - /** - * Related resources to display below 'Subjects' - */ - get relatedResources() { - if (this.record.metadata.electronicLocator) { - return this.record.metadata.electronicLocator.filter( - (electronicLocator: any) => [ - 'hiddenUrl', 'noInfo', 'resource', 'relatedResource', 'versionOfResource' - ].some(t => t === electronicLocator.type && electronicLocator.content !== 'coverImage') - ); - } - } - - /** - * Resources to display like a holding - */ - get resources() { - if (this.record.metadata.electronicLocator) { - return this.record.metadata.electronicLocator.filter( - (electronicLocator: any) => ['resource', 'versionOfResource'].some(t => t === electronicLocator.type) - ); } } @@ -258,15 +278,20 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest getPartOfLabel(hostDocument: any) { switch (hostDocument.metadata.issuance.subtype) { case 'periodical': - return this._translateService.instant('Journal'); + return this._translateService.instant('Journal'); case 'monographicSeries': - return this._translateService.instant('Series'); + return this._translateService.instant('Series'); default: - return this._translateService.instant('Published in'); + return this._translateService.instant('Published in'); } } - contributionTypeParam(contribution: any) { + /** + * Translate the type of the contribution for url + * @param contribution - document contribution + * @returns string, the translated type + */ + contributionTypeParam(contribution: any): string { switch (contribution.type) { case 'bf:Person': return 'persons'; @@ -282,14 +307,11 @@ export class DocumentDetailViewComponent implements DetailRecord, OnInit, OnDest * @param identifier - IdentifiedBy object * @return string, query formatted */ - private _extractAndFormatQueryParams(identifier: any): string { + private _extractAndFormatQueryParams(identifier: any): string { const query = []; - /* const type = identifier.type.replace(/:/g, '\\:'); - const value = identifier.value.replace(/:/g, '\\:'); */ query.push(`identifiedBy.type:"${identifier.type}"`); query.push(`identifiedBy.value:"${identifier.value}"`); if (identifier.source) { - /* const source = identifier.source.replace(/:/g, '\\:'); */ query.push(`identifiedBy.source:"${identifier.source}"`); } return `(${query.join(' AND ')})`;