From 786ee3effe5a8c1dce414dc1cb33cad6b9aa8ff1 Mon Sep 17 00:00:00 2001 From: Matus Kasak Date: Wed, 1 Apr 2026 13:36:49 +0200 Subject: [PATCH 1/2] Fixed ORCID badge --- .env.mendelu | 45 ++++++++++ .env.ufal | 36 ++++++++ ...-text-metadata-list-element.component.html | 5 +- ...xt-metadata-list-element.component.spec.ts | 12 --- ...in-text-metadata-list-element.component.ts | 89 ++++++++++++++----- 5 files changed, 153 insertions(+), 34 deletions(-) create mode 100644 .env.mendelu create mode 100644 .env.ufal diff --git a/.env.mendelu b/.env.mendelu new file mode 100644 index 00000000000..c3e7d5f8d05 --- /dev/null +++ b/.env.mendelu @@ -0,0 +1,45 @@ +INSTANCE=8 +DSPACE_HOST=localhost +DSPACE_VER=customer-mendelu +DSPACE_SSL=false + +FE_CMD=yarn start:dev + +#please do not edit the following variables unless you know what you are doing +DOCKER_OWNER=dataquest +DSPACE_UI_IMAGE=${DOCKER_OWNER}/dspace-angular:$DSPACE_VER +# DSPACE_REST_IMAGE=${DOCKER_OWNER}/dspace:$DSPACE_VER na DSPACE_REST_IMAGE=nazov-buildu +DSPACE_REST_IMAGE=mendelu + +DSPACE_REST_PORT=808${INSTANCE} +UI_PORT=400${INSTANCE} + +TRUST_IP_RANGE=${INSTANCE} +DSPACE_DOCKER_REST_PORT=808${INSTANCE} +DSPACE_DEBUG_PORT=800${INSTANCE} +DSPACE_HANDLE_PORT=264${INSTANCE} +DSPACE_HANDLE_PORT_HTTP=801${INSTANCE} +DSPACE_PORT=${INSTANCE} +PG_PORT=543${INSTANCE} +SOLR_PORT=898${INSTANCE} + +DSPACE_REST_NAMESPACE=/server +DSPACE_UI_NAMESPACE=/ + +REST_URL=http://${DSPACE_HOST}:${DSPACE_REST_PORT}${DSPACE_REST_NAMESPACE} +UI_URL=http://${DSPACE_HOST}:${UI_PORT}${DSPACE_UI_NAMESPACE} + +# ===== S3 Storage ===== +#diable s3 storage +#S3_STORAGE=1 +#S3_ENABLED=true +S3_STORAGE=0 +S3_ENABLED=false +S3_BUCKET=YOUR_BUCKET_NAME # replace with your S3 bucket +S3_SUBFOLDER=assetstore +S3_ACCESS=YOUR_ACCESS_KEY # replace with your S3 access key +S3_SECRET=YOUR_SECRET_KEY # replace with your S3 secret key +S3_ENDPOINT=YOUR_S3_ENDPOINT_URL # replace with your S3 endpoint URL +S3_RELATIVE_PATH=true +S3_PATH_STYLE_ACCESS=false +S3_REGION_NAME= \ No newline at end of file diff --git a/.env.ufal b/.env.ufal new file mode 100644 index 00000000000..a386a92e047 --- /dev/null +++ b/.env.ufal @@ -0,0 +1,36 @@ +INSTANCE=8 +DSPACE_HOST=localhost +DSPACE_VER=dspace-7_x +DSPACE_SSL=false + +FE_CMD=yarn start:dev + +#please do not edit the following variables unless you know what you are doing +DOCKER_OWNER=dataquest +DSPACE_UI_IMAGE=${DOCKER_OWNER}/dspace-angular:$DSPACE_VER +# DSPACE_REST_IMAGE=${DOCKER_OWNER}/dspace:$DSPACE_VER na DSPACE_REST_IMAGE=nazov-buildu +DSPACE_REST_IMAGE=ufal + +DSPACE_REST_PORT=808${INSTANCE} +UI_PORT=400${INSTANCE} + +DSPACE_REST_NAMESPACE=/server +DSPACE_UI_NAMESPACE=/ + +REST_URL=http://${DSPACE_HOST}:${DSPACE_REST_PORT}${DSPACE_REST_NAMESPACE} +UI_URL=http://${DSPACE_HOST}:${UI_PORT}${DSPACE_UI_NAMESPACE} + +# ===== S3 Storage ===== +#diable s3 storage +#S3_STORAGE=1 +#S3_ENABLED=true +S3_STORAGE=0 +S3_ENABLED=false +S3_BUCKET=YOUR_BUCKET_NAME # replace with your S3 bucket +S3_SUBFOLDER=assetstore +S3_ACCESS=YOUR_ACCESS_KEY # replace with your S3 access key +S3_SECRET=YOUR_SECRET_KEY # replace with your S3 secret key +S3_ENDPOINT=YOUR_S3_ENDPOINT_URL # replace with your S3 endpoint URL +S3_RELATIVE_PATH=true +S3_PATH_STYLE_ACCESS=false +S3_REGION_NAME= \ No newline at end of file diff --git a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html index 59f9fa2e862..9cd2b781eb0 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html +++ b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html @@ -12,9 +12,10 @@ } @if ((mdRepresentation.representationType==='authority_controlled')) { - @let isOrcid = isOrcidAuthority(); + @let orcidDomainUrl = orcidDomainUrl$ | async; + @let isOrcid = isOrcidAuthority(orcidDomainUrl); @if (isOrcid) { - + {{mdRepresentation.getValue()}} diff --git a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts index aa0f80de8fe..3861e46df07 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts @@ -42,18 +42,6 @@ const mockOrcidWithWhitespaceRepresentation = Object.assign(new MetadatumReprese authority: ' 1234-5678-9012-3456 ', }); -const mockOrcidFullUrlRepresentation = Object.assign(new MetadatumRepresentation('type'), { - key: 'dc.contributor.author', - value: 'Doe, John', - authority: 'https://orcid.org/1234-5678-9012-3456', -}); - -const mockOrcidFullUrlSandboxRepresentation = Object.assign(new MetadatumRepresentation('type'), { - key: 'dc.contributor.author', - value: 'Smith, Jane', - authority: 'https://sandbox.orcid.org/1234-5678-9012-345X', -}); - const mockConfigurationDataService = { findByPropertyName: jasmine.createSpy('findByPropertyName').and.returnValue( createSuccessfulRemoteDataObject$({ values: ['https://orcid.org'] }), diff --git a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts index 6c22cbec1a2..aede056a21c 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts @@ -1,15 +1,26 @@ -import { Component } from '@angular/core'; +import { + AsyncPipe, +} from '@angular/common'; +import { + Component, + OnInit, +} from '@angular/core'; import { RouterLink } from '@angular/router'; +import { BehaviorSubject } from 'rxjs'; + +import { ConfigurationDataService } from '../../../../core/data/configuration-data.service'; import { MetadatumRepresentation } from '../../../../core/shared/metadata-representation/metadatum/metadatum-representation.model'; +import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; import { VALUE_LIST_BROWSE_DEFINITION } from '../../../../core/shared/value-list-browse-definition.resource-type'; import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component'; /** - * Regex pattern for full ORCID URL authority values stored by the backend - * (e.g. https://orcid.org/0000-0001-2345-6789 or https://sandbox.orcid.org/0000-0001-2345-678X). + * Regex pattern for ORCID identifiers: four groups of four digits separated by hyphens. + * The last group may end with an X (checksum digit). + * Example: 0000-0001-2345-6789 or 0000-0001-2345-678X */ -const ORCID_URL_PATTERN = /^https?:\/\/[^/]+\/((\d{4}-){3}(\d{3}X|\d{4}))$/i; +const ORCID_PATTERN = /^\d{4}-\d{4}-\d{4}-(\d{3}X|\d{4})$/; @Component({ selector: 'ds-plain-text-metadata-list-element', @@ -17,6 +28,7 @@ const ORCID_URL_PATTERN = /^https?:\/\/[^/]+\/((\d{4}-){3}(\d{3}X|\d{4}))$/i; styleUrls: ['./plain-text-metadata-list-element.component.scss'], standalone: true, imports: [ + AsyncPipe, RouterLink, ], }) @@ -24,7 +36,38 @@ const ORCID_URL_PATTERN = /^https?:\/\/[^/]+\/((\d{4}-){3}(\d{3}X|\d{4}))$/i; * A component for displaying MetadataRepresentation objects in the form of plain text * It will simply use the value retrieved from MetadataRepresentation.getValue() to display as plain text */ -export class PlainTextMetadataListElementComponent extends MetadataRepresentationListElementComponent { +export class PlainTextMetadataListElementComponent extends MetadataRepresentationListElementComponent implements OnInit { + + /** + * The base ORCID domain URL fetched from backend configuration. + * Remains null until successfully loaded — ORCID linking is disabled when null. + */ + orcidDomainUrl$ = new BehaviorSubject(null); + + constructor(private configurationService: ConfigurationDataService) { + super(); + } + + ngOnInit(): void { + this.configurationService.findByPropertyName('orcid.domain-url').pipe( + getFirstCompletedRemoteData(), + ).subscribe(rd => { + if (rd.hasFailed) { + console.error('PlainTextMetadataListElementComponent: failed to fetch backend config property "orcid.domain-url". ORCID author linking will be disabled.'); + return; + } + if (!rd.hasSucceeded || !rd.payload?.values?.length) { + console.error('PlainTextMetadataListElementComponent: backend config property "orcid.domain-url" returned no values. ORCID author linking will be disabled.'); + return; + } + const url = rd.payload.values[0].trim(); + if (!url || !/^https?:\/\//i.test(url)) { + console.error(`PlainTextMetadataListElementComponent: backend config property "orcid.domain-url" has invalid value "${url}". ORCID author linking will be disabled.`); + return; + } + this.orcidDomainUrl$.next(url); + }); + } /** * Get the appropriate query parameters for this browse link, depending on whether the browse definition @@ -41,30 +84,36 @@ export class PlainTextMetadataListElementComponent extends MetadataRepresentatio } /** - * Check if the authority value of this metadata is a full ORCID URL. - * The backend OrcidAuthorityAssign script stores authority as full URLs - * (e.g. https://orcid.org/0000-0001-2345-6789). + * Check if the authority value of this metadata is an ORCID identifier. + * Authority is expected to be a bare ORCID ID (e.g. 0000-0001-2345-6789). + * Requires the orcidDomainUrl to be loaded from backend configuration. */ - isOrcidAuthority(): boolean { + isOrcidAuthority(orcidDomainUrl: string | null): boolean { + if (orcidDomainUrl === null) { + return false; + } if (this.mdRepresentation instanceof MetadatumRepresentation) { const authority = this.mdRepresentation.authority?.trim(); - return !!authority && ORCID_URL_PATTERN.test(authority); + return !!authority && ORCID_PATTERN.test(authority); } return false; } /** - * Return the full ORCID profile URL from the authority value. - * Since the backend stores authority as a full URL, this simply returns it. - * Returns an empty string if the authority is not a valid ORCID URL. + * Build the full ORCID profile URL by combining the configured domain URL with the authority ORCID ID. + * Returns an empty string if preconditions are not met (no domain URL or no valid authority). */ - getOrcidUrl(): string { - if (this.mdRepresentation instanceof MetadatumRepresentation) { - const authority = this.mdRepresentation.authority?.trim(); - if (authority && ORCID_URL_PATTERN.test(authority)) { - return authority; - } + getOrcidUrl(orcidDomainUrl: string | null): string { + if (orcidDomainUrl === null) { + return ''; + } + const authority = this.mdRepresentation instanceof MetadatumRepresentation + ? this.mdRepresentation.authority?.trim() + : undefined; + if (!authority) { + return ''; } - return ''; + const base = orcidDomainUrl.endsWith('/') ? orcidDomainUrl : orcidDomainUrl + '/'; + return `${base}${authority}`; } } From aeb1489a0bce17b92556f9d07b80d8a33e3493a9 Mon Sep 17 00:00:00 2001 From: Matus Kasak Date: Wed, 1 Apr 2026 13:39:32 +0200 Subject: [PATCH 2/2] Removed envs --- .env.mendelu | 45 --------------------------------------------- .env.ufal | 36 ------------------------------------ 2 files changed, 81 deletions(-) delete mode 100644 .env.mendelu delete mode 100644 .env.ufal diff --git a/.env.mendelu b/.env.mendelu deleted file mode 100644 index c3e7d5f8d05..00000000000 --- a/.env.mendelu +++ /dev/null @@ -1,45 +0,0 @@ -INSTANCE=8 -DSPACE_HOST=localhost -DSPACE_VER=customer-mendelu -DSPACE_SSL=false - -FE_CMD=yarn start:dev - -#please do not edit the following variables unless you know what you are doing -DOCKER_OWNER=dataquest -DSPACE_UI_IMAGE=${DOCKER_OWNER}/dspace-angular:$DSPACE_VER -# DSPACE_REST_IMAGE=${DOCKER_OWNER}/dspace:$DSPACE_VER na DSPACE_REST_IMAGE=nazov-buildu -DSPACE_REST_IMAGE=mendelu - -DSPACE_REST_PORT=808${INSTANCE} -UI_PORT=400${INSTANCE} - -TRUST_IP_RANGE=${INSTANCE} -DSPACE_DOCKER_REST_PORT=808${INSTANCE} -DSPACE_DEBUG_PORT=800${INSTANCE} -DSPACE_HANDLE_PORT=264${INSTANCE} -DSPACE_HANDLE_PORT_HTTP=801${INSTANCE} -DSPACE_PORT=${INSTANCE} -PG_PORT=543${INSTANCE} -SOLR_PORT=898${INSTANCE} - -DSPACE_REST_NAMESPACE=/server -DSPACE_UI_NAMESPACE=/ - -REST_URL=http://${DSPACE_HOST}:${DSPACE_REST_PORT}${DSPACE_REST_NAMESPACE} -UI_URL=http://${DSPACE_HOST}:${UI_PORT}${DSPACE_UI_NAMESPACE} - -# ===== S3 Storage ===== -#diable s3 storage -#S3_STORAGE=1 -#S3_ENABLED=true -S3_STORAGE=0 -S3_ENABLED=false -S3_BUCKET=YOUR_BUCKET_NAME # replace with your S3 bucket -S3_SUBFOLDER=assetstore -S3_ACCESS=YOUR_ACCESS_KEY # replace with your S3 access key -S3_SECRET=YOUR_SECRET_KEY # replace with your S3 secret key -S3_ENDPOINT=YOUR_S3_ENDPOINT_URL # replace with your S3 endpoint URL -S3_RELATIVE_PATH=true -S3_PATH_STYLE_ACCESS=false -S3_REGION_NAME= \ No newline at end of file diff --git a/.env.ufal b/.env.ufal deleted file mode 100644 index a386a92e047..00000000000 --- a/.env.ufal +++ /dev/null @@ -1,36 +0,0 @@ -INSTANCE=8 -DSPACE_HOST=localhost -DSPACE_VER=dspace-7_x -DSPACE_SSL=false - -FE_CMD=yarn start:dev - -#please do not edit the following variables unless you know what you are doing -DOCKER_OWNER=dataquest -DSPACE_UI_IMAGE=${DOCKER_OWNER}/dspace-angular:$DSPACE_VER -# DSPACE_REST_IMAGE=${DOCKER_OWNER}/dspace:$DSPACE_VER na DSPACE_REST_IMAGE=nazov-buildu -DSPACE_REST_IMAGE=ufal - -DSPACE_REST_PORT=808${INSTANCE} -UI_PORT=400${INSTANCE} - -DSPACE_REST_NAMESPACE=/server -DSPACE_UI_NAMESPACE=/ - -REST_URL=http://${DSPACE_HOST}:${DSPACE_REST_PORT}${DSPACE_REST_NAMESPACE} -UI_URL=http://${DSPACE_HOST}:${UI_PORT}${DSPACE_UI_NAMESPACE} - -# ===== S3 Storage ===== -#diable s3 storage -#S3_STORAGE=1 -#S3_ENABLED=true -S3_STORAGE=0 -S3_ENABLED=false -S3_BUCKET=YOUR_BUCKET_NAME # replace with your S3 bucket -S3_SUBFOLDER=assetstore -S3_ACCESS=YOUR_ACCESS_KEY # replace with your S3 access key -S3_SECRET=YOUR_SECRET_KEY # replace with your S3 secret key -S3_ENDPOINT=YOUR_S3_ENDPOINT_URL # replace with your S3 endpoint URL -S3_RELATIVE_PATH=true -S3_PATH_STYLE_ACCESS=false -S3_REGION_NAME= \ No newline at end of file