Files
dspace-angular/src/app/core/breadcrumbs/dso-name.service.ts
2023-01-10 19:37:06 +05:30

113 lines
3.8 KiB
TypeScript

import { Injectable } from '@angular/core';
import { hasValue, isEmpty } from '../../shared/empty.util';
import { DSpaceObject } from '../shared/dspace-object.model';
import { TranslateService } from '@ngx-translate/core';
import { Metadata } from '../shared/metadata.utils';
/**
* Returns a name for a {@link DSpaceObject} based
* on its render types.
*/
@Injectable({
providedIn: 'root'
})
export class DSONameService {
constructor(private translateService: TranslateService) {
}
/**
* Functions to generate the specific names.
*
* If this list ever expands it will probably be worth it to
* refactor this using decorators for specific entity types,
* or perhaps by using a dedicated model for each entity type
*
* With only two exceptions those solutions seem overkill for now.
*/
private readonly factories = {
Person: (dso: DSpaceObject): string => {
const familyName = dso.firstMetadataValue('person.familyName');
const givenName = dso.firstMetadataValue('person.givenName');
if (isEmpty(familyName) && isEmpty(givenName)) {
return dso.firstMetadataValue('dc.title') || dso.name;
} else if (isEmpty(familyName) || isEmpty(givenName)) {
return familyName || givenName;
} else {
return `${familyName}, ${givenName}`;
}
},
OrgUnit: (dso: DSpaceObject): string => {
return dso.firstMetadataValue('organization.legalName');
},
Default: (dso: DSpaceObject): string => {
// If object doesn't have dc.title metadata use name property
return dso.firstMetadataValue('dc.title') || dso.name || this.translateService.instant('dso.name.untitled');
}
};
/**
* Get the name for the given {@link DSpaceObject}
*
* @param dso The {@link DSpaceObject} you want a name for
*/
getName(dso: DSpaceObject): string {
const types = dso.getRenderTypes();
const match = types
.filter((type) => typeof type === 'string')
.find((type: string) => Object.keys(this.factories).includes(type)) as string;
let name;
if (hasValue(match)) {
name = this.factories[match](dso);
}
if (isEmpty(name)) {
name = this.factories.Default(dso);
}
return name;
}
/**
* Gets the Hit highlight
*
* @param object
* @param dso
*
* @returns {string} html embedded hit highlight.
*/
getHitHighlights(object: any, dso: DSpaceObject): string {
const types = dso.getRenderTypes();
const entityType = types
.filter((type) => typeof type === 'string')
.find((type: string) => (['Person', 'OrgUnit']).includes(type)) as string;
if (entityType === 'Person') {
const familyName = this.firstMetadataValue(object, dso, 'person.familyName');
const givenName = this.firstMetadataValue(object, dso, 'person.givenName');
if (isEmpty(familyName) && isEmpty(givenName)) {
return this.firstMetadataValue(object, dso, 'dc.title') || dso.name;
} else if (isEmpty(familyName) || isEmpty(givenName)) {
return familyName || givenName;
}
return `${familyName}, ${givenName}`;
} else if (entityType === 'OrgUnit') {
return this.firstMetadataValue(object, dso, 'organization.legalName');
}
return this.firstMetadataValue(object, dso, 'dc.title') || dso.name || this.translateService.instant('dso.name.untitled');
}
/**
* Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights.
*
* @param object
* @param dso
* @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]].
*
* @returns {string} the first matching string value, or `undefined`.
*/
firstMetadataValue(object: any, dso: DSpaceObject, keyOrKeys: string | string[]): string {
return Metadata.firstValue([object.hitHighlights, dso.metadata], keyOrKeys);
}
}