diff --git a/projects/admin/src/app/app.module.ts b/projects/admin/src/app/app.module.ts index b0321f4f5..555be25c6 100644 --- a/projects/admin/src/app/app.module.ts +++ b/projects/admin/src/app/app.module.ts @@ -117,6 +117,7 @@ import { OtherEditionComponent } from './record/detail-view/document-detail-view/document-description/other-edition/other-edition.component'; import { DocumentDetailViewComponent } from './record/detail-view/document-detail-view/document-detail-view.component'; +import { EntitiesRelatedComponent } from './record/detail-view/document-detail-view/entities-related/entities-related.component'; import { HoldingDetailComponent } from './record/detail-view/document-detail-view/holding-detail/holding-detail.component'; import { HoldingOrganisationComponent @@ -332,6 +333,7 @@ export function appInitFactory(appInitializerService: AppInitializerService): () StatisticsCfgDetailViewComponent, ReportDataComponent, ReportsListComponent, + EntitiesRelatedComponent ], imports: [ AppRoutingModule, diff --git a/projects/admin/src/app/record/brief-view/documents-brief-view/documents-brief-view.component.ts b/projects/admin/src/app/record/brief-view/documents-brief-view/documents-brief-view.component.ts index 8fb3d9fc5..e1d60c8e4 100644 --- a/projects/admin/src/app/record/brief-view/documents-brief-view/documents-brief-view.component.ts +++ b/projects/admin/src/app/record/brief-view/documents-brief-view/documents-brief-view.component.ts @@ -53,22 +53,6 @@ export class DocumentsBriefViewComponent implements ResultItem { */ constructor(public documentApiService: DocumentApiService) {} - /** - * Contribution type parameter - * @param contribution - object - * @return string - type of agent - */ - contributionTypeParam(contribution: any) { - switch (contribution.type) { - case 'bf:Person': - return 'persons'; - case 'bf:Organisation': - return 'corporate-bodies'; - default: - return 'missing-contribution-type'; - } - } - /** process provision activity publications */ private processProvisionActivityPublications() { const { provisionActivity } = this.record.metadata; diff --git a/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.html b/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.html index ada65580e..27b6fc5de 100644 --- a/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.html +++ b/projects/admin/src/app/record/detail-view/document-detail-view/document-detail-view.component.html @@ -67,8 +67,7 @@

{{ altgr_title }}

+ [activateLink]="activateLink"> @@ -180,7 +179,12 @@

{{ altgr_title }}

- + + @@ -188,7 +192,11 @@

{{ altgr_title }}

- + +
@@ -234,6 +242,16 @@

{{ altgr_title }}

+ + + + {{ 'Related Entities' | translate }} + +
+ +
+
+ . +--> +
+
+
+ {{ field.key | translate |ucfirst }} +
+ +
+
diff --git a/projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.component.ts b/projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.component.ts new file mode 100644 index 000000000..048070d56 --- /dev/null +++ b/projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.component.ts @@ -0,0 +1,63 @@ +/* + * RERO ILS UI + * Copyright (C) 2019-2023 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 + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import { Component, Input, OnInit } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Entity } from '@rero/shared'; +import { IEntityRelated } from './entities-related.interface'; + +@Component({ + selector: 'admin-entities-related', + templateUrl: './entities-related.component.html' +}) +export class EntitiesRelatedComponent implements OnInit { + + /** Record metadata */ + @Input() record: any; + + /** Entities processed */ + entities: {[key: string]: IEntityRelated[]} = {}; + + /** + * Constructor + * @param translateService - TranslateService + */ + constructor(private translateService: TranslateService) {} + + /** OnInit hook */ + ngOnInit(): void { + const language = this.translateService.currentLang; + const { metadata } = this.record; + Entity.FIELDS_WITH_REF.forEach((field: string) => { + if (field in metadata && metadata[field].length > 0) { + metadata[field].forEach((entity: any) => { + if (entity.entity.resource_type) { + if (!Object.keys(this.entities).includes(field)) { + this.entities[field] = []; + } + this.entities[field].push({ + authorized_access_point: entity.entity[`authorized_access_point_${language}`], + pid: entity.entity.pid, + resource_type: entity.entity.resource_type, + type: entity.entity.type, + icon: Entity.getIcon(entity.entity.type) + }); + } + }); + } + }); + } +} diff --git a/projects/admin/src/app/utils/tools.spec.ts b/projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.interface.ts similarity index 64% rename from projects/admin/src/app/utils/tools.spec.ts rename to projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.interface.ts index b3c238359..55856335d 100644 --- a/projects/admin/src/app/utils/tools.spec.ts +++ b/projects/admin/src/app/record/detail-view/document-detail-view/entities-related/entities-related.interface.ts @@ -1,7 +1,6 @@ /* * RERO ILS UI * Copyright (C) 2019-2023 RERO - * Copyright (C) 2019-2023 UCLouvain * * 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 @@ -15,17 +14,10 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { Tools } from "./tools"; - -describe('Tools', () => { - - it('should return a query', () => { - const query = [ - 'contribution.entity.pids.foo:x11', - 'subjects.entity.pids.foo:x11', - 'genreForm.entity.pids.foo:x11' - ].join(' OR '); - expect(Tools.generateEntitySearchQuery('foo', 'x11')).toEqual(query); - }); - -}); +export interface IEntityRelated { + authorized_access_point: string; + pid: string; + resource_type: string; + type: string; + icon: string; +} diff --git a/projects/admin/src/app/record/detail-view/entities-detail-view/local/entities-local-detail-view.component.ts b/projects/admin/src/app/record/detail-view/entities-detail-view/local/entities-local-detail-view.component.ts index 32cde9ace..88f8c825d 100644 --- a/projects/admin/src/app/record/detail-view/entities-detail-view/local/entities-local-detail-view.component.ts +++ b/projects/admin/src/app/record/detail-view/entities-detail-view/local/entities-local-detail-view.component.ts @@ -18,10 +18,9 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { OperationLogsService } from '@app/admin/service/operation-logs.service'; -import { Tools } from '@app/admin/utils/tools'; import { TranslateService } from '@ngx-translate/core'; import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record'; -import { EntityType, EntityTypeIcon } from '@rero/shared'; +import { Entity, EntityType, EntityTypeIcon } from '@rero/shared'; @Component({ selector: 'admin-entities-local-detail-view', @@ -90,7 +89,7 @@ export class EntitiesLocalDetailViewComponent implements OnInit, DetailRecord { this._router.navigate( ['/records', 'documents'], { - queryParams: { q: Tools.generateEntitySearchQuery('local', metadata.pid), simple: '0'}, + queryParams: { q: Entity.generateEntitySearchQuery(metadata.type, 'local', metadata.pid), simple: '0' }, skipLocationChange: true }, ); diff --git a/projects/admin/src/app/record/detail-view/entities-detail-view/remote/entities-remote-detail-view.component.ts b/projects/admin/src/app/record/detail-view/entities-detail-view/remote/entities-remote-detail-view.component.ts index 3436931ec..323424342 100644 --- a/projects/admin/src/app/record/detail-view/entities-detail-view/remote/entities-remote-detail-view.component.ts +++ b/projects/admin/src/app/record/detail-view/entities-detail-view/remote/entities-remote-detail-view.component.ts @@ -18,10 +18,9 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; -import { Tools } from '@app/admin/utils/tools'; import { TranslateService } from '@ngx-translate/core'; import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record'; -import { AppSettingsService, EntityType, EntityTypeIcon } from '@rero/shared'; +import { AppSettingsService, Entity, EntityType, EntityTypeIcon } from '@rero/shared'; @Component({ selector: 'admin-remote-entities-remote-detail-view', @@ -109,7 +108,7 @@ export class RemoteEntitiesDetailViewComponent implements DetailRecord { this._router.navigate( ['/records', 'documents'], { - queryParams: { q: Tools.generateEntitySearchQuery(catalogKey, catalogPid), simple: '0' }, + queryParams: { q: Entity.generateEntitySearchQuery(metadata.type, catalogKey, catalogPid), simple: '0' }, skipLocationChange: true } ); diff --git a/projects/admin/src/app/utils/tools.ts b/projects/admin/src/app/utils/tools.ts deleted file mode 100644 index 9eabcf645..000000000 --- a/projects/admin/src/app/utils/tools.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * RERO ILS UI - * Copyright (C) 2019-2023 RERO - * Copyright (C) 2019-2023 UCLouvain - * - * 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 - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -export class Tools { - /** - * Generate entity search query - * @param catalogKey - Catalog key (Ex: idref, gnd, rero) - * @param catalogPid - Entity catalog pid - * @returns The string representing the query - */ - static generateEntitySearchQuery(catalogKey: string, catalogPid: string): string { - const queries = []; - ['contribution', 'subjects', 'genreForm'].every( - (field: string) => queries.push(`${field}.entity.pids.${catalogKey}:${catalogPid}`) - ); - - return queries.join(' OR '); - } -} diff --git a/projects/shared/src/lib/class/entities.ts b/projects/shared/src/lib/class/entities.ts deleted file mode 100644 index 3532f7b46..000000000 --- a/projects/shared/src/lib/class/entities.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * RERO ILS UI - * Copyright (C) 2019-2023 RERO - * Copyright (C) 2019-2023 UCLouvain - * - * 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 - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -export enum EntityType { - ORGANISATION = 'bf:Organisation', - PERSON = 'bf:Person', - PLACE = 'bf:Place', - TEMPORAL = 'bf:Temporal', - TOPIC = 'bf:Topic', - WORK = 'bf:Work', -} - -export enum EntityTypeIcon { - ORGANISATION = 'fa-building-o', - PERSON = 'fa-user-o', - PLACE = 'fa-map-marker', - TEMPORAL = 'fa-calendar', - TOPIC = 'fa-tag', - WORK = 'fa-book', -} - -export class Entity { - /** - * Get Entity icon - * @param resourceType type of entity - * @returns the icon class name - */ - static getIcon(resourceType: string): string { - const icons = new Map([ - [EntityType.ORGANISATION, EntityTypeIcon.ORGANISATION], - [EntityType.PERSON, EntityTypeIcon.PERSON], - [EntityType.TEMPORAL, EntityTypeIcon.TEMPORAL], - [EntityType.PLACE, EntityTypeIcon.PLACE], - [EntityType.TOPIC, EntityTypeIcon.TOPIC], - [EntityType.WORK, EntityTypeIcon.WORK] - ]); - if (!icons.has(resourceType)) { - return 'fa-question-circle'; - } - return icons.get(resourceType); - } -} diff --git a/projects/shared/src/lib/class/entity.spec.ts b/projects/shared/src/lib/class/entity.spec.ts new file mode 100644 index 000000000..f202b0aff --- /dev/null +++ b/projects/shared/src/lib/class/entity.spec.ts @@ -0,0 +1,98 @@ +/* + * RERO ILS UI + * Copyright (C) 2023 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 + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import { EntityTypeIcon } from '@rero/shared'; +import { Entity, EntityField$ref, EntityType } from './entity'; + +describe('Entity', () => { + it('should return the icon\'s class', () => { + expect(Entity.getIcon(EntityType.ORGANISATION)).toEqual(EntityTypeIcon.ORGANISATION); + expect(Entity.getIcon(EntityType.PERSON)).toEqual(EntityTypeIcon.PERSON); + expect(Entity.getIcon(EntityType.PLACE)).toEqual(EntityTypeIcon.PLACE); + expect(Entity.getIcon(EntityType.TEMPORAL)).toEqual(EntityTypeIcon.TEMPORAL); + expect(Entity.getIcon(EntityType.TOPIC)).toEqual(EntityTypeIcon.TOPIC); + expect(Entity.getIcon(EntityType.WORK)).toEqual(EntityTypeIcon.WORK); + expect(Entity.getIcon('foo')).toEqual(EntityTypeIcon.MISSING); + }); + + it('should return search fields based on the type', () => { + expect(Entity.getFieldsSearch(EntityType.ORGANISATION)).toEqual([ + EntityField$ref.CONTRIBUTION, + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch(EntityType.PERSON)).toEqual([ + EntityField$ref.CONTRIBUTION, + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch(EntityType.PLACE)).toEqual([ + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch(EntityType.TEMPORAL)).toEqual([ + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch(EntityType.TOPIC)).toEqual([ + EntityField$ref.GENRE_FORM, + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch(EntityType.WORK)).toEqual([ + EntityField$ref.SUBJECTS + ]); + expect(Entity.getFieldsSearch('foo')).toEqual([ + EntityField$ref.CONTRIBUTION, + EntityField$ref.GENRE_FORM, + EntityField$ref.SUBJECTS + ]); + }); + + it('should return a query for bf:Organisation', () => { + const query = [ + 'contribution.entity.pids.foo:x11', + 'subjects.entity.pids.foo:x11' + ].join(' OR '); + expect(Entity.generateEntitySearchQuery(EntityType.ORGANISATION, 'foo', 'x11')).toEqual(query); + }); + + it('should return a query for bf:Topic', () => { + const query = [ + 'genreForm.entity.pids.foo:x11', + 'subjects.entity.pids.foo:x11' + ].join(' OR '); + expect(Entity.generateEntitySearchQuery(EntityType.TOPIC, 'foo', 'x11')).toEqual(query); + }); + + it('should return a query with all fields if the type is missing', () => { + const query = [ + 'contribution.entity.pids.foo:x11', + 'genreForm.entity.pids.foo:x11', + 'subjects.entity.pids.foo:x11' + ].join(' OR '); + expect(Entity.generateEntitySearchQuery('bf:foo', 'foo', 'x11')).toEqual(query); + }); + + it('should return the search string for an external link', () => { + const routerLink = ['/records', 'documents']; + const queryParams = { + q: 'entity.pid:100', + page: '1', + size: '10', + sort: 'bestmatch', + simple: '0', + + } + const link = '/records/documents?q=entity.pid:100&page=1&size=10&sort=bestmatch&simple=0'; + expect(Entity.generateHrefLink(routerLink, queryParams)).toEqual(link); + }); +}); diff --git a/projects/shared/src/lib/class/entity.ts b/projects/shared/src/lib/class/entity.ts new file mode 100644 index 000000000..1293e7d09 --- /dev/null +++ b/projects/shared/src/lib/class/entity.ts @@ -0,0 +1,133 @@ +/* + * RERO ILS UI + * Copyright (C) 2019-2023 RERO + * Copyright (C) 2019-2023 UCLouvain + * + * 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 + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export enum EntityField$ref { + CONTRIBUTION = 'contribution', + GENRE_FORM = 'genreForm', + SUBJECTS = 'subjects' +} + +export enum EntityType { + ORGANISATION = 'bf:Organisation', + PERSON = 'bf:Person', + PLACE = 'bf:Place', + TEMPORAL = 'bf:Temporal', + TOPIC = 'bf:Topic', + WORK = 'bf:Work', +} + +export enum EntityTypeIcon { + MISSING = 'fa-question-circle', + ORGANISATION = 'fa-building-o', + PERSON = 'fa-user-o', + PLACE = 'fa-map-marker', + TEMPORAL = 'fa-calendar', + TOPIC = 'fa-tag', + WORK = 'fa-book', +} + +export class Entity { + + /** Available fields with entity ref */ + static FIELDS_WITH_REF = [ + EntityField$ref.CONTRIBUTION, + EntityField$ref.GENRE_FORM, + EntityField$ref.SUBJECTS + ]; + + /** Map of types => fields */ + private static TYPES_FIELDS = new Map([ + [EntityType.ORGANISATION, [EntityField$ref.CONTRIBUTION, EntityField$ref.SUBJECTS]], + [EntityType.PERSON, [EntityField$ref.CONTRIBUTION, EntityField$ref.SUBJECTS]], + [EntityType.PLACE, [EntityField$ref.SUBJECTS]], + [EntityType.TEMPORAL, [EntityField$ref.SUBJECTS]], + [EntityType.TOPIC, [EntityField$ref.GENRE_FORM, EntityField$ref.SUBJECTS]], + [EntityType.WORK, [EntityField$ref.SUBJECTS]] + ]); + + /** Map entity type => icon class */ + private static ICONS = new Map([ + [EntityType.ORGANISATION, EntityTypeIcon.ORGANISATION], + [EntityType.PERSON, EntityTypeIcon.PERSON], + [EntityType.PLACE, EntityTypeIcon.PLACE], + [EntityType.TEMPORAL, EntityTypeIcon.TEMPORAL], + [EntityType.TOPIC, EntityTypeIcon.TOPIC], + [EntityType.WORK, EntityTypeIcon.WORK] + ]); + + /** + * Get Entity icon + * @param resourceType type of entity + * @returns the icon class name + */ + static getIcon(resourceType: string): string { + if (!Entity.ICONS.has(resourceType)) { + return EntityTypeIcon.MISSING; + } + return Entity.ICONS.get(resourceType); + } + + /** + * Get Fields search + * @param type - type of entity + * @returns the array of field(s) + */ + static getFieldsSearch(resourceType: string): string[] { + if (!Entity.TYPES_FIELDS.has(resourceType)) { + return Entity.FIELDS_WITH_REF; + } + return Entity.TYPES_FIELDS.get(resourceType); + } + + /** + * Generate the advanced search query + * @param resourceType - type of entity + * @param catalogKey - Catalog key + * @param catalogPid - Catalog pid + * @returns the search string + */ + static generateEntitySearchQuery(resourceType: string, catalogKey: string, catalogPid: string): string { + const queries = []; + const fields = Entity.getFieldsSearch(resourceType); + fields.every( + (field: string) => queries.push(`${field}.entity.pids.${catalogKey}:${catalogPid}`) + ); + return queries.join(' OR '); + } + + /** + * Generate external link for public view + * @param routerLink - Array of url path + * @param queryParams - Object of parameters + * @return the link string + */ + static generateHrefLink(routerLink: string[], queryParams: object): string { + let link = routerLink.join('/'); + const params = []; + if (link.startsWith('//')) { + link = link.substring(1); + } + const keyQueryParams = Object.keys(queryParams); + if (keyQueryParams.length > 0) { + link += '?'; + keyQueryParams.forEach((param: string) => params.push(`${param}=${queryParams[param]}`)); + link += params.join('&'); + } + return link; + } +} diff --git a/projects/shared/src/lib/component/entities/entity-brief-view/entity-brief-view.component.ts b/projects/shared/src/lib/component/entities/entity-brief-view/entity-brief-view.component.ts index 89e816dd6..b2fe16465 100644 --- a/projects/shared/src/lib/component/entities/entity-brief-view/entity-brief-view.component.ts +++ b/projects/shared/src/lib/component/entities/entity-brief-view/entity-brief-view.component.ts @@ -18,7 +18,7 @@ import { AfterViewInit, Component, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; import { ResultItem } from '@rero/ng-core'; -import { Entity, EntityType } from '../../../class/entities'; +import { Entity, EntityType } from '../../../class/entity'; import { ExtractSourceFieldPipe } from '../../../pipe/extract-source-field.pipe'; import { BriefViewTag } from '../../core/brief-view/brief-view.component'; import { EntityBriefViewRemoteOrganisationComponent } from './entity-brief-view.organisation'; diff --git a/projects/shared/src/lib/service/search-bar-config.service.ts b/projects/shared/src/lib/service/search-bar-config.service.ts index bd6823ce2..7ef51604f 100644 --- a/projects/shared/src/lib/service/search-bar-config.service.ts +++ b/projects/shared/src/lib/service/search-bar-config.service.ts @@ -21,7 +21,7 @@ import { TranslateService } from '@ngx-translate/core'; import { TruncateTextPipe } from '@rero/ng-core'; import { MainTitlePipe } from '../pipe/main-title.pipe'; import { AppSettingsService } from './app-settings.service'; -import { EntityType, EntityTypeIcon } from '../class/entities'; +import { Entity } from '../class/entity'; @Injectable({ providedIn: 'root' @@ -136,7 +136,7 @@ export class SearchBarConfigService { query: '', category: this._translateService.instant('authors/subjects'), href: this.generateEntityLink(hit.metadata), - iconCssClass: `fa ${this.findIconByType(hit.metadata.type)}` + iconCssClass: `fa ${Entity.getIcon(hit.metadata.type)}` }); }); return values; @@ -170,23 +170,6 @@ export class SearchBarConfigService { } } - /** - * Find icon by type - * @param type - entity type (Ex: bf:Organisation) - * @returns The class icon - */ - private findIconByType(type: string): string { - switch(type) { - case EntityType.ORGANISATION : return EntityTypeIcon.ORGANISATION; - case EntityType.PERSON : return EntityTypeIcon.PERSON; - case EntityType.PLACE : return EntityTypeIcon.PLACE; - case EntityType.TEMPORAL : return EntityTypeIcon.TEMPORAL; - case EntityType.TOPIC : return EntityTypeIcon.TOPIC; - case EntityType.WORK : return EntityTypeIcon.WORK; - default: return 'fa-question-circle'; - } - } - /** * Escape RegExp * @param data - string diff --git a/projects/shared/src/lib/shared.module.ts b/projects/shared/src/lib/shared.module.ts index 71bf56ae6..f7bc142bd 100644 --- a/projects/shared/src/lib/shared.module.ts +++ b/projects/shared/src/lib/shared.module.ts @@ -52,6 +52,7 @@ import { PartOfComponent } from './view/brief/part-of/part-of.component'; import { InheritedCallNumberComponent } from './view/inherited-call-number/inherited-call-number.component'; import { ThumbnailComponent } from './view/thumbnail/thumbnail.component'; import { AvailabilityComponent } from './view/availability/availability.component'; +import { EntityLinkComponent } from './view/entity-link.component'; @NgModule({ declarations: [ @@ -85,6 +86,7 @@ import { AvailabilityComponent } from './view/availability/availability.componen ContributionComponent, NoContentDirective, AvailabilityComponent, + EntityLinkComponent, ], exports: [ CommonModule, @@ -114,6 +116,7 @@ import { AvailabilityComponent } from './view/availability/availability.componen ContributionComponent, NoContentDirective, AvailabilityComponent, + EntityLinkComponent ], imports: [ CommonModule, diff --git a/projects/shared/src/lib/view/contribution/contribution.component.html b/projects/shared/src/lib/view/contribution/contribution.component.html index fda358c82..1fa2bd88f 100644 --- a/projects/shared/src/lib/view/contribution/contribution.component.html +++ b/projects/shared/src/lib/view/contribution/contribution.component.html @@ -33,7 +33,7 @@ - + @@ -43,10 +43,18 @@ - {{ entity | entityLabel }} + - {{ entity | entityLabel }} + diff --git a/projects/shared/src/lib/view/contribution/contribution.component.ts b/projects/shared/src/lib/view/contribution/contribution.component.ts index 3cbacff71..68660f117 100644 --- a/projects/shared/src/lib/view/contribution/contribution.component.ts +++ b/projects/shared/src/lib/view/contribution/contribution.component.ts @@ -16,7 +16,6 @@ * along with this program. If not, see . */ import { Component, Input, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'shared-contribution', @@ -44,13 +43,6 @@ export class ContributionComponent implements OnInit { /** If the limit is activated, we add 3 dots at the end of the contribution line. */ limit: boolean = false; - // CONSTRUCTORS & HOOKS ===================================================== - /** - * Constructor - * @param _translateService - TranslateService - */ - constructor(private _translateService: TranslateService) {} - /** OnInit hook */ ngOnInit() { this.contributions = this.contributions || []; @@ -61,18 +53,5 @@ export class ContributionComponent implements OnInit { this.contributions = this.contributions.slice(0, this.limitRecord); this.limit = true; } - - this.contributions.forEach(contributor => { - if (contributor.entity?.pid) { - // Linked entity - const type = contributor.entity.resource_type; - contributor.entity.target = `contribution.entity.pids.${type}:${contributor.entity.pids[type]}`; - } else { - // Textual entity - const field = `authorized_access_point_${this._translateService.currentLang}`; - const fieldData = (field in contributor.entity) ? field : 'authorized_access_point'; - contributor.entity.target = `contribution.entity.${field}:"${contributor.entity[fieldData]}"`; - } - }); } } diff --git a/projects/shared/src/lib/view/entity-link.component.ts b/projects/shared/src/lib/view/entity-link.component.ts new file mode 100644 index 000000000..f6e26655a --- /dev/null +++ b/projects/shared/src/lib/view/entity-link.component.ts @@ -0,0 +1,93 @@ +/* + * RERO ILS UI + * Copyright (C) 2019-2023 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 + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import { Component, Input, OnInit } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Entity } from '../class/entity'; + +@Component({ + selector: 'shared-entity-link', + template: ` + {{ linkName }} + + {{ linkName }} + + ` +}) +export class EntityLinkComponent implements OnInit { + + /** Entity field metadata */ + @Input() entity: any; + + /** Entity field name */ + @Input() resourceName: string; + + /** Link class */ + @Input() class: string; + + /** Router link parameters */ + @Input() routerLinkParams = ['/records', 'documents']; + + /** Make link external */ + @Input() external: boolean = false; + + /** Link label name */ + linkName: string; + + /** External link href */ + externalHrefLink: string; + + /** Query params */ + queryParams: object = {}; + + /** + * Constructor + * @param translateService - TranslateService + */ + constructor(private translateService: TranslateService) {} + + /** OnInit hook */ + ngOnInit(): void { + const lang = this.translateService.currentLang; + this.linkName = `authorized_access_point_${lang}` in this.entity + ? this.entity[`authorized_access_point_${lang}`] + : this.entity.authorized_access_point; + if ('resource_type' in this.entity) { + const pid = this.entity.pids[this.entity.resource_type]; + this.queryParams = { + q: `${this.resourceName}.entity.pids.${this.entity.resource_type}:${pid}`, + simple: '0', + }; + } else { + this.queryParams = { + q: `${this.resourceName}.entity.authorized_access_point_${lang}:"${this.linkName}"`, + simple: '0', + } + } + if (this.external) { + // This link is used to redirect to the jinja view of the entity. + this.externalHrefLink = Entity.generateHrefLink(this.routerLinkParams, this.queryParams); + } + } +} diff --git a/projects/shared/src/public-api.ts b/projects/shared/src/public-api.ts index 372015be7..da8d791fa 100644 --- a/projects/shared/src/public-api.ts +++ b/projects/shared/src/public-api.ts @@ -22,7 +22,7 @@ export * from './lib/api/base-api'; export * from './lib/api/user-api.service'; export * from './lib/class/core'; -export * from './lib/class/entities'; +export * from './lib/class/entity'; export * from './lib/class/holdings'; export * from './lib/class/item-status'; export * from './lib/class/user'; @@ -31,6 +31,7 @@ export * from './lib/component/action-button/action-button.component'; export * from './lib/component/core/brief-view/brief-view.component'; export * from './lib/component/entities/entity-brief-view/entity-brief-view.component'; export * from './lib/view/contribution/contribution.component'; +export * from './lib/view/entity-link.component'; export * from './lib/directive/link-permissions.directive'; export * from './lib/directive/no-content.directive'; @@ -72,3 +73,4 @@ export * from './lib/view/brief/part-of/part-of.component'; export * from './lib/view/inherited-call-number/inherited-call-number.component'; export * from './lib/view/thumbnail/thumbnail.component'; export * from './tests/user'; +