diff --git a/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.html b/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.html
index 9c205dce27a..407f1963e93 100644
--- a/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.html
+++ b/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.html
@@ -15,7 +15,7 @@
{{citationText + ', '}}
{{itemNameText + ', '}}
{{repositoryNameText + ', '}}
- {{identifierURI}}
+ {{prettifiedIdentifier | async}}
diff --git a/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.ts b/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.ts
index ee24711cd5e..37edb07f702 100644
--- a/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.ts
+++ b/src/app/item-page/clarin-ref-citation/clarin-ref-citation.component.ts
@@ -10,6 +10,11 @@ import { GetRequest } from '../../core/data/request.models';
import { RequestService } from '../../core/data/request.service';
import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service';
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
+import { BehaviorSubject } from 'rxjs';
+import {
+ DOI_METADATA_FIELD, HANDLE_METADATA_FIELD,
+} from '../simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component';
+import { ItemIdentifierService } from '../../shared/item-identifier.service';
/**
* If the item has more authors do not add all authors to the citation but add there a shortcut.
@@ -57,6 +62,14 @@ export class ClarinRefCitationComponent implements OnInit {
* The nam of the organization which provides the repository
*/
repositoryNameText: string;
+ /**
+ * BehaviorSubject to store the prettified identifier.
+ */
+ prettifiedIdentifier: BehaviorSubject = new BehaviorSubject(null);
+ /**
+ * The item has DOI or not.
+ */
+ hasDoi = false;
constructor(private configurationService: ConfigurationDataService,
private clipboard: Clipboard,
@@ -64,7 +77,8 @@ export class ClarinRefCitationComponent implements OnInit {
private modalService: NgbModal,
private requestService: RequestService,
protected rdbService: RemoteDataBuildService,
- protected halService: HALEndpointService,) {
+ protected halService: HALEndpointService,
+ private itemIdentifierService: ItemIdentifierService) {
// Configure the tooltip to show on click - `Copied` message
config.triggers = 'click';
}
@@ -79,10 +93,15 @@ export class ClarinRefCitationComponent implements OnInit {
return textValue !== null;
});
+ this.hasDoi = this.hasItemDoi();
this.citationText = citationArray.join(', ');
this.itemNameText = this.getTitle();
- this.identifierURI = this.getIdentifierUri();
- this.getRepositoryName().then(res => {
+ this.identifierURI = this.getIdentifierUri(this.whichIdentifierMetadataField());
+ void this.itemIdentifierService.prettifyIdentifier(this.identifierURI, [this.whichIdentifierMetadataField()])
+ .then((value: string) => {
+ this.prettifiedIdentifier.next(value);
+ });
+ void this.getRepositoryName().then(res => {
this.repositoryNameText = res?.payload?.values?.[0];
});
}
@@ -104,18 +123,30 @@ export class ClarinRefCitationComponent implements OnInit {
.pipe(getFirstSucceededRemoteData()).toPromise();
}
- getIdentifierUri() {
- const handleMetadata = this.item.metadata['dc.identifier.uri'];
- if (isUndefined(handleMetadata) || isNull(handleMetadata)) {
- return null;
- }
+ /**
+ * Get the identifier URI from the item metadata. If the item has DOI, return the DOI, otherwise return the handle.
+ */
+ getIdentifierUri(identifierMetadataField) {
+ return this.item.firstMetadataValue(identifierMetadataField);
+ }
+
+ /**
+ * Check if the item has DOI.
+ */
+ hasItemDoi() {
+ return this.item?.allMetadata(DOI_METADATA_FIELD)?.length > 0;
+ }
- return handleMetadata?.[0]?.value;
+ /**
+ * If the item has DOI, return the DOI metadata field, otherwise return the handle metadata field.
+ */
+ whichIdentifierMetadataField() {
+ return this.hasDoi ? DOI_METADATA_FIELD : HANDLE_METADATA_FIELD;
}
getHandle() {
// Separate the handle from the full URI
- const fullUri = this.getIdentifierUri();
+ const fullUri = this.getIdentifierUri(this.whichIdentifierMetadataField());
const handleWord = 'handle/';
const startHandleIndex = fullUri.indexOf('handle/') + handleWord.length;
return fullUri.substr(startHandleIndex);
diff --git a/src/app/item-page/simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component.ts b/src/app/item-page/simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component.ts
index ec73516b638..e8174206450 100644
--- a/src/app/item-page/simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component.ts
+++ b/src/app/item-page/simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component.ts
@@ -10,8 +10,8 @@ import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/oper
import { map } from 'rxjs/operators';
export const DOI_METADATA_FIELD = 'dc.identifier.doi';
+export const HANDLE_METADATA_FIELD = 'dc.identifier.uri';
const SHOW_HANDLE_AND_DOI_PROPERTY_NAME = 'item-page.show-handle-and-doi';
-const HANDLE_METADATA_FIELD = 'dc.identifier.uri';
@Component({
selector: 'ds-clarin-generic-item-field',
diff --git a/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.spec.ts b/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.spec.ts
index 31cde074d2b..70269c8bedf 100644
--- a/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.spec.ts
+++ b/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.spec.ts
@@ -1,16 +1,16 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ClarinIdentifierItemFieldComponent } from './clarin-identifier-item-field.component';
-import { ConfigurationDataService } from '../../../../core/data/configuration-data.service';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
-import { ConfigurationProperty } from '../../../../core/shared/configuration-property.model';
import { Item } from '../../../../core/shared/item.model';
import { createPaginatedList } from '../../../../shared/testing/utils.test';
import { DOI_METADATA_FIELD } from '../clarin-generic-item-field/clarin-generic-item-field.component';
+import { ItemIdentifierService } from '../../../../shared/item-identifier.service';
describe('ClarinIdentifierItemFieldComponent', () => {
let component: ClarinIdentifierItemFieldComponent;
let fixture: ComponentFixture;
+ let itemIdentifierService: ItemIdentifierService;
const mockItem: Item = Object.assign(new Item(), {
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
@@ -25,13 +25,8 @@ describe('ClarinIdentifierItemFieldComponent', () => {
});
beforeEach(async () => {
- const configurationServiceSpy = jasmine.createSpyObj('configurationService', {
- findByPropertyName: createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), {
- name: 'test',
- values: [
- true
- ]
- })),
+ itemIdentifierService = jasmine.createSpyObj('itemIdentifierService', {
+ prettifyIdentifier: new Promise((res, rej) => { return 'awesome identifier'; }),
});
await TestBed.configureTestingModule({
@@ -40,7 +35,7 @@ describe('ClarinIdentifierItemFieldComponent', () => {
],
declarations: [ ClarinIdentifierItemFieldComponent ],
providers: [
- { provide: ConfigurationDataService, useValue: configurationServiceSpy }
+ { provide: ItemIdentifierService, useValue: itemIdentifierService }
]
})
.compileComponents();
diff --git a/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.ts b/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.ts
index a75eae240b6..13964247b13 100644
--- a/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.ts
+++ b/src/app/item-page/simple/field-components/clarin-identifier-item-field/clarin-identifier-item-field.component.ts
@@ -1,16 +1,10 @@
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { Item } from '../../../../core/shared/item.model';
-import { BehaviorSubject, firstValueFrom } from 'rxjs';
+import { BehaviorSubject } from 'rxjs';
import { Clipboard } from '@angular/cdk/clipboard';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
-import { ConfigurationDataService } from '../../../../core/data/configuration-data.service';
-import { isEmpty, isNotEmpty } from '../../../../shared/empty.util';
-import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
-import { map } from 'rxjs/operators';
-import { DOI_METADATA_FIELD } from '../clarin-generic-item-field/clarin-generic-item-field.component';
+import { ItemIdentifierService } from '../../../../shared/item-identifier.service';
-const DEFAULT_DOI_RESOLVER = 'https://doi.org/';
-const DOI_RESOLVER_CFG_PROPERTY = 'identifier.doi.resolver';
@Component({
selector: 'ds-clarin-identifier-item-field',
@@ -34,11 +28,6 @@ export class ClarinIdentifierItemFieldComponent implements OnInit {
*/
@Input() fields: string[];
- /**
- * The DOI resolver URL. It is a `identifier.doi.resolver` property or the default resolver (constant).
- */
- doiResolver: string;
-
/**
* The identifier of the item. DOI or handle.
*/
@@ -49,16 +38,18 @@ export class ClarinIdentifierItemFieldComponent implements OnInit {
*/
prettifiedIdentifier: BehaviorSubject = new BehaviorSubject(null);
- constructor(private configurationService: ConfigurationDataService,
+ constructor(private itemIdentifierService: ItemIdentifierService,
private clipboard: Clipboard) {
}
ngOnInit(): void {
this.identifier = this.item?.firstMetadataValue(this.fields);
- void this.prettifyIdentifier(this.identifier);
+ void this.itemIdentifierService.prettifyIdentifier(this.identifier, this.fields)
+ .then((value: string) => {
+ this.prettifiedIdentifier.next(value);
+ });
}
-
/**
* Copy the metadata value to the clipboard. After clicking on the `Copy` icon the message `Copied` is popped up.
*
@@ -70,56 +61,4 @@ export class ClarinIdentifierItemFieldComponent implements OnInit {
this.copyButtonRef.close();
}, 700);
}
-
- /**
- * Prettify the identifier. If the identifier is DOI, remove the DOI resolver from it.
- *
- * @param identifier
- */
- async prettifyIdentifier(identifier: string) {
- if (isEmpty(identifier)) {
- this.prettifiedIdentifier.next(null);
- return;
- }
-
- // Do not prettify the identifier if it is not DOI.
- if (!this.fields.includes(DOI_METADATA_FIELD)) {
- this.prettifiedIdentifier.next(identifier);
- return;
- }
-
- // If the DOI resolver is set, use it. It is not set by default.
- if (isNotEmpty(this.doiResolver)) {
- this.removeDoiResolverFromIdentifier(identifier);
- return;
- }
-
- // Get the DOI resolver from the configuration.
- const cfgDoiResolver = await firstValueFrom(this.loadDoiResolverConfiguration());
-
- // If the configuration is not set, use the default resolver.
- this.doiResolver = isEmpty(cfgDoiResolver) ? DEFAULT_DOI_RESOLVER : cfgDoiResolver;
-
- // Remove the DOI resolver from the identifier.
- this.removeDoiResolverFromIdentifier(identifier);
- }
-
- /**
- * Remove the DOI resolver from the identifier.
- *
- * @param identifier
- */
- removeDoiResolverFromIdentifier(identifier: string) {
- this.prettifiedIdentifier.next(identifier.replace(this.doiResolver, ''));
- }
-
- /**
- * Load the DOI resolver from the configuration. It is a `identifier.doi.resolver` property.
- */
- loadDoiResolverConfiguration() {
- return this.configurationService.findByPropertyName(DOI_RESOLVER_CFG_PROPERTY)
- .pipe(
- getFirstCompletedRemoteData(),
- map((config) => config?.payload?.values?.[0]));
- }
}
diff --git a/src/app/shared/item-identifier.service.ts b/src/app/shared/item-identifier.service.ts
new file mode 100644
index 00000000000..3a040bb7615
--- /dev/null
+++ b/src/app/shared/item-identifier.service.ts
@@ -0,0 +1,68 @@
+import { Injectable } from '@angular/core';
+import { ConfigurationDataService } from '../core/data/configuration-data.service';
+import { isEmpty } from './empty.util';
+import { firstValueFrom } from 'rxjs';
+import {
+ DOI_METADATA_FIELD
+} from '../item-page/simple/field-components/clarin-generic-item-field/clarin-generic-item-field.component';
+import { getFirstCompletedRemoteData } from '../core/shared/operators';
+import { map } from 'rxjs/operators';
+
+export const DEFAULT_DOI_RESOLVER = 'https://doi.org/';
+export const DOI_RESOLVER_CFG_PROPERTY = 'identifier.doi.resolver';
+
+/**
+ * Service to handle the item identifier. It prettifies the identifier and removes the DOI resolver from it.
+ */
+@Injectable()
+export class ItemIdentifierService {
+ constructor(private configurationService: ConfigurationDataService) {
+ }
+
+ /**
+ * Prettify the identifier. If the identifier is DOI, remove the DOI resolver from it.
+ *
+ * @param identifier
+ * @param metadataFields
+ */
+ async prettifyIdentifier(identifier: string, metadataFields: string[] = []) {
+ let prettifiedIdentifier = identifier;
+ if (isEmpty(identifier)) {
+ return prettifiedIdentifier;
+ }
+
+ // Do not prettify the identifier if it is not DOI.
+ if (!metadataFields?.includes(DOI_METADATA_FIELD)) {
+ return prettifiedIdentifier;
+ }
+
+ // Get the DOI resolver from the configuration.
+ const cfgDoiResolver = await firstValueFrom(this.loadDoiResolverConfiguration());
+
+ // If the configuration is not set, use the default resolver.
+ const doiResolver = isEmpty(cfgDoiResolver) ? DEFAULT_DOI_RESOLVER : cfgDoiResolver;
+
+ // Remove the DOI resolver from the identifier.
+ return this.removeDoiResolverFromIdentifier(identifier, doiResolver);
+ }
+
+ /**
+ * Remove the DOI resolver from the identifier.
+ *
+ * @param identifier
+ * @param doiResolver
+ */
+ removeDoiResolverFromIdentifier(identifier: string, doiResolver: string) {
+ return identifier.replace(doiResolver, '');
+ }
+
+ /**
+ * Load the DOI resolver from the configuration. It is a `identifier.doi.resolver` property.
+ */
+ loadDoiResolverConfiguration() {
+ return this.configurationService.findByPropertyName(DOI_RESOLVER_CFG_PROPERTY)
+ .pipe(
+ getFirstCompletedRemoteData(),
+ map((config) => config?.payload?.values?.[0]));
+ }
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 2f5a4c9f154..b8ee124f70a 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -295,6 +295,7 @@ import { HtmlContentService } from './html-content.service';
import { ClarinSafeHtmlPipe } from './utils/clarin-safehtml.pipe';
import { ReplacePipe } from './utils/replace.pipe';
import { ClarinDateService } from './clarin-date.service';
+import { ItemIdentifierService } from './item-identifier.service';
const MODULES = [
CommonModule,
@@ -495,7 +496,8 @@ const PROVIDERS = [
MockAdminGuard,
AbstractTrackableComponent,
HtmlContentService,
- ClarinDateService
+ ClarinDateService,
+ ItemIdentifierService
];
const DIRECTIVES = [