mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-16 06:23:03 +00:00
add DSONameService
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
|
||||
import { BreadcrumbsService } from './breadcrumbs.service';
|
||||
import { DSONameService } from './dso-name.service';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { ChildHALResource } from '../shared/child-hal-resource.model';
|
||||
import { LinkService } from '../cache/builders/link.service';
|
||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||
import { followLink } from '../../shared/utils/follow-link-config.model';
|
||||
import { filter, find, map, switchMap } from 'rxjs/operators';
|
||||
import { find, map, switchMap } from 'rxjs/operators';
|
||||
import { getDSOPath } from '../../app-routing.module';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
@@ -13,12 +14,16 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class DSOBreadcrumbsService implements BreadcrumbsService<ChildHALResource & DSpaceObject> {
|
||||
constructor(private linkService: LinkService) {
|
||||
constructor(
|
||||
private linkService: LinkService,
|
||||
private dsoNameService: DSONameService
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
getBreadcrumbs(key: ChildHALResource & DSpaceObject, url: string): Observable<Breadcrumb[]> {
|
||||
const crumb = new Breadcrumb(key.name, url);
|
||||
const label = this.dsoNameService.getName(key);
|
||||
const crumb = new Breadcrumb(label, url);
|
||||
const propertyName = key.getParentLinkKey();
|
||||
return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe(
|
||||
find((childRD: RemoteData<ChildHALResource & DSpaceObject>) => childRD.hasSucceeded || childRD.statusCode === 204),
|
||||
|
116
src/app/core/breadcrumbs/dso-name.service.spec.ts
Normal file
116
src/app/core/breadcrumbs/dso-name.service.spec.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||
import { GenericConstructor } from '../shared/generic-constructor';
|
||||
import { Item } from '../shared/item.model';
|
||||
import { MetadataValueFilter } from '../shared/metadata.models';
|
||||
import { DSONameService } from './dso-name.service';
|
||||
|
||||
describe(`DSONameService`, () => {
|
||||
let service: DSONameService;
|
||||
let mockPersonName: string;
|
||||
let mockPerson: DSpaceObject;
|
||||
let mockOrgUnitName: string;
|
||||
let mockOrgUnit: DSpaceObject;
|
||||
let mockDSOName: string;
|
||||
let mockDSO: DSpaceObject;
|
||||
|
||||
beforeEach(() => {
|
||||
mockPersonName = 'Doe, John';
|
||||
mockPerson = Object.assign(new DSpaceObject(), {
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return mockPersonName
|
||||
},
|
||||
getRenderTypes(): Array<string | GenericConstructor<ListableObject>> {
|
||||
return ['Person', Item, DSpaceObject];
|
||||
}
|
||||
});
|
||||
|
||||
mockOrgUnitName = 'Molecular Spectroscopy';
|
||||
mockOrgUnit = Object.assign(new DSpaceObject(), {
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return mockOrgUnitName
|
||||
},
|
||||
getRenderTypes(): Array<string | GenericConstructor<ListableObject>> {
|
||||
return ['OrgUnit', Item, DSpaceObject];
|
||||
}
|
||||
});
|
||||
|
||||
mockDSOName = 'Lorem Ipsum';
|
||||
mockDSO = Object.assign(new DSpaceObject(), {
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return mockDSOName
|
||||
},
|
||||
getRenderTypes(): Array<string | GenericConstructor<ListableObject>> {
|
||||
return [DSpaceObject];
|
||||
}
|
||||
});
|
||||
|
||||
service = new DSONameService();
|
||||
});
|
||||
|
||||
describe(`getName`, () => {
|
||||
it(`should use the Person factory for Person entities`, () => {
|
||||
spyOn((service as any).factories, 'Person').and.returnValue('Bingo!');
|
||||
|
||||
const result = service.getName(mockPerson);
|
||||
|
||||
expect((service as any).factories.Person).toHaveBeenCalledWith(mockPerson);
|
||||
expect(result).toBe('Bingo!');
|
||||
});
|
||||
|
||||
it(`should use the OrgUnit factory for OrgUnit entities`, () => {
|
||||
spyOn((service as any).factories, 'OrgUnit').and.returnValue('Bingo!');
|
||||
|
||||
const result = service.getName(mockOrgUnit);
|
||||
|
||||
expect((service as any).factories.OrgUnit).toHaveBeenCalledWith(mockOrgUnit);
|
||||
expect(result).toBe('Bingo!');
|
||||
});
|
||||
|
||||
it(`should use the Default factory for regular DSpaceObjects`, () => {
|
||||
spyOn((service as any).factories, 'Default').and.returnValue('Bingo!');
|
||||
|
||||
const result = service.getName(mockDSO);
|
||||
|
||||
expect((service as any).factories.Default).toHaveBeenCalledWith(mockDSO);
|
||||
expect(result).toBe('Bingo!');
|
||||
});
|
||||
});
|
||||
|
||||
describe(`factories.Person`, () => {
|
||||
beforeEach(() => {
|
||||
spyOn(mockPerson, 'firstMetadataValue').and.returnValues(...mockPersonName.split(', '));
|
||||
});
|
||||
|
||||
it(`should return 'person.familyName, person.givenName'`, () => {
|
||||
const result = (service as any).factories.Person(mockPerson);
|
||||
expect(result).toBe(mockPersonName);
|
||||
expect(mockPerson.firstMetadataValue).toHaveBeenCalledWith('person.familyName');
|
||||
expect(mockPerson.firstMetadataValue).toHaveBeenCalledWith('person.givenName');
|
||||
});
|
||||
});
|
||||
|
||||
describe(`factories.OrgUnit`, () => {
|
||||
beforeEach(() => {
|
||||
spyOn(mockOrgUnit, 'firstMetadataValue').and.callThrough();
|
||||
});
|
||||
|
||||
it(`should return 'organization.legalName'`, () => {
|
||||
const result = (service as any).factories.OrgUnit(mockOrgUnit);
|
||||
expect(result).toBe(mockOrgUnitName);
|
||||
expect(mockOrgUnit.firstMetadataValue).toHaveBeenCalledWith('organization.legalName');
|
||||
});
|
||||
});
|
||||
|
||||
describe(`factories.Default`, () => {
|
||||
beforeEach(() => {
|
||||
spyOn(mockDSO, 'firstMetadataValue').and.callThrough();
|
||||
});
|
||||
|
||||
it(`should return 'dc.title'`, () => {
|
||||
const result = (service as any).factories.Default(mockDSO);
|
||||
expect(result).toBe(mockDSOName);
|
||||
expect(mockDSO.firstMetadataValue).toHaveBeenCalledWith('dc.title');
|
||||
});
|
||||
});
|
||||
});
|
53
src/app/core/breadcrumbs/dso-name.service.ts
Normal file
53
src/app/core/breadcrumbs/dso-name.service.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||
|
||||
/**
|
||||
* Returns a name for a {@link DSpaceObject} based
|
||||
* on its render types.
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DSONameService {
|
||||
|
||||
/**
|
||||
* 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 factories = {
|
||||
Person: (dso: DSpaceObject): string => {
|
||||
return `${dso.firstMetadataValue('person.familyName')}, ${dso.firstMetadataValue('person.givenName')}`;
|
||||
},
|
||||
OrgUnit: (dso: DSpaceObject): string => {
|
||||
return dso.firstMetadataValue('organization.legalName');
|
||||
},
|
||||
Default: (dso: DSpaceObject): string => {
|
||||
return dso.firstMetadataValue('dc.title');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if (hasValue(match)) {
|
||||
return this.factories[match](dso);
|
||||
} else {
|
||||
return this.factories.Default(dso);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
6
src/app/core/cache/builders/link.service.ts
vendored
6
src/app/core/cache/builders/link.service.ts
vendored
@@ -55,7 +55,10 @@ export class LinkService {
|
||||
parent: this.parentInjector
|
||||
}).get(provider);
|
||||
|
||||
const href = model._links[matchingLinkDef.linkName].href;
|
||||
const link = model._links[matchingLinkDef.linkName];
|
||||
|
||||
if (hasValue(link)) {
|
||||
const href = link.href;
|
||||
|
||||
try {
|
||||
if (matchingLinkDef.isList) {
|
||||
@@ -67,6 +70,7 @@ export class LinkService {
|
||||
throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import { catchError, distinctUntilKeyChanged, filter, first, map, take } from 'r
|
||||
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||
import { DSONameService } from '../breadcrumbs/dso-name.service';
|
||||
import { CacheableObject } from '../cache/object-cache.reducer';
|
||||
import { BitstreamDataService } from '../data/bitstream-data.service';
|
||||
import { BitstreamFormatDataService } from '../data/bitstream-format-data.service';
|
||||
@@ -35,6 +36,7 @@ export class MetadataService {
|
||||
private translate: TranslateService,
|
||||
private meta: Meta,
|
||||
private title: Title,
|
||||
private dsoNameService: DSONameService,
|
||||
private bitstreamDataService: BitstreamDataService,
|
||||
private bitstreamFormatDataService: BitstreamFormatDataService,
|
||||
@Inject(GLOBAL_CONFIG) private envConfig: GlobalConfig
|
||||
@@ -154,7 +156,7 @@ export class MetadataService {
|
||||
* Add <meta name="title" ... > to the <head>
|
||||
*/
|
||||
private setTitleTag(): void {
|
||||
const value = this.getMetaTagValue('dc.title');
|
||||
const value = this.dsoNameService.getName(this.currentObject.getValue());
|
||||
this.addMetaTag('title', value);
|
||||
this.title.setTitle(value);
|
||||
}
|
||||
|
@@ -69,6 +69,7 @@ export class DSpaceObject extends ListableObject implements CacheableObject {
|
||||
|
||||
/**
|
||||
* The name for this DSpaceObject
|
||||
* @deprecated use {@link DSONameService} instead
|
||||
*/
|
||||
get name(): string {
|
||||
return (isUndefined(this._name)) ? this.firstMetadataValue('dc.title') : this._name;
|
||||
|
Reference in New Issue
Block a user