diff --git a/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.html b/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.html new file mode 100644 index 00000000000..bdef2c58c3a --- /dev/null +++ b/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.html @@ -0,0 +1,8 @@ + + + + {{ linkText || mdValue.value }} + + + + diff --git a/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.ts b/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.ts new file mode 100644 index 00000000000..bb2b001c24e --- /dev/null +++ b/src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component.ts @@ -0,0 +1,60 @@ +import { + NgForOf, + NgIf, +} from '@angular/common'; +import { + Component, + Input, +} from '@angular/core'; +import { TranslateModule } from '@ngx-translate/core'; + +import { MetadataValue } from '../../../core/shared/metadata.models'; +import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wrapper/metadata-field-wrapper.component'; +import { MetadataValuesComponent } from '../metadata-values/metadata-values.component'; + +/** + * This component renders DOIs into the `ds-metadata-field-wrapper` component as clickable links. + * Each DOI is transformed into a valid URL (e.g., `https://doi.org/...`) and displayed with custom text if provided. + */ +@Component({ + selector: 'ds-metadata-doi-values', + templateUrl: './metadata-doi-values.component.html', + imports: [ + MetadataFieldWrapperComponent, + TranslateModule, + NgForOf, + NgIf, + ], + standalone: true, +}) +export class MetadataDoiValuesComponent extends MetadataValuesComponent { + /** + * The metadata values (DOIs) to display + */ + @Input() mdValues: MetadataValue[]; + + /** + * The separator used between multiple DOIs + */ + @Input() separator: string; + + /** + * The label for this field + */ + @Input() label: string; + + /** + * Optional custom text for the DOI links + * If undefined, the raw DOI value is displayed + */ + @Input() linkText: string; + + /** + * Converts a raw DOI value into a full URL + * @param doi Raw DOI string (e.g., `10.1234/example.doi`) + * @returns Full URL for the DOI (e.g., `https://doi.org/10.1234/example.doi`) + */ + formatDoiUrl(doi: string): string { + return `https://doi.org/${doi}`; + } +} diff --git a/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.html b/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.html new file mode 100644 index 00000000000..2de3ac9a9b6 --- /dev/null +++ b/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.html @@ -0,0 +1,7 @@ +
+ + +
diff --git a/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.ts b/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.ts new file mode 100644 index 00000000000..e88571ec719 --- /dev/null +++ b/src/app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component.ts @@ -0,0 +1,49 @@ +import { + Component, + Input, +} from '@angular/core'; +import { MetadataDoiValuesComponent } from 'src/app/item-page/field-components/metadata-doi-values/metadata-doi-values.component'; + +import { Item } from '../../../../../core/shared/item.model'; +import { ItemPageFieldComponent } from '../item-page-field.component'; + +/** + * This component displays DOIs on a simple item page using the MetadataDoiValuesComponent. + * It converts DOIs into clickable links, separators, and labels. + */ +@Component({ + selector: 'ds-item-page-doi-field', + templateUrl: './item-page-doi-field.component.html', + standalone: true, + imports: [ + MetadataDoiValuesComponent, + ], +}) +export class ItemPageDoiFieldComponent extends ItemPageFieldComponent { + /** + * The item to display metadata for + */ + @Input() item: Item; + + /** + * Separator string between multiple DOIs + */ + @Input() separator = ', '; + + /** + * Metadata fields containing DOIs + */ + @Input() fields: string[] = ['dc.identifier.doi']; + + /** + * Label for the DOI field + */ + @Input() label = 'item.page.doi'; + + /** + * Get metadata values for the provided fields + */ + get doiValues() { + return this.item?.allMetadata(this.fields) || []; + } +} diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss index b810d2ddd4f..3575cae797d 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss @@ -1,2 +1 @@ @import '../../../../../styles/variables.scss'; - diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a82ba9a4716..6a7a13b3e57 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2762,6 +2762,8 @@ "item.page.uri": "URI", + "item.page.doi": "DOI", + "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.collapse": "Collapse", @@ -5584,7 +5586,7 @@ "thumbnail.person.placeholder": "No Profile Picture Available", - title: "DSpace", + "title": "DSpace", "vocabulary-treeview.header": "Hierarchical tree view", diff --git a/src/assets/i18n/hu.json5 b/src/assets/i18n/hu.json5 index ff79f985d0e..3316678d25e 100644 --- a/src/assets/i18n/hu.json5 +++ b/src/assets/i18n/hu.json5 @@ -4193,6 +4193,9 @@ // "item.page.uri": "URI", "item.page.uri": "URI", + //"item.page.doi": "DOI", + "item.page.doi": "DOI", + // "item.page.bitstreams.view-more": "Show more", "item.page.bitstreams.view-more": "Tovább", diff --git a/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.html new file mode 100644 index 00000000000..c22b7e6a1e2 --- /dev/null +++ b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -0,0 +1,99 @@ + +
+
+ + +
+
+ +
+ + + +
+
+
+ + + + + +
+ +
+ + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + {{"item.page.link.full" | translate}} + +
+
+
diff --git a/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss new file mode 100644 index 00000000000..902a64c4345 --- /dev/null +++ b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.scss @@ -0,0 +1 @@ +@import '../../../../../../../../src/styles/_variables.scss'; diff --git a/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts new file mode 100644 index 00000000000..8de5d723e35 --- /dev/null +++ b/src/themes/szerep/app/item-page/simple/item-types/untyped-item/untyped-item.component.ts @@ -0,0 +1,68 @@ +import { + AsyncPipe, + NgIf, +} from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, +} from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { Context } from 'src/app/core/shared/context.model'; +import { UntypedItemComponent as BaseComponent } from 'src/app/item-page/simple/item-types/untyped-item/untyped-item.component'; + +import { Item } from '../../../../../../../app/core/shared/item.model'; +import { ViewMode } from '../../../../../../../app/core/shared/view-mode.model'; +import { CollectionsComponent } from '../../../../../../../app/item-page/field-components/collections/collections.component'; +import { ThemedMediaViewerComponent } from '../../../../../../../app/item-page/media-viewer/themed-media-viewer.component'; +import { MiradorViewerComponent } from '../../../../../../../app/item-page/mirador-viewer/mirador-viewer.component'; +import { ThemedFileSectionComponent } from '../../../../../../../app/item-page/simple/field-components/file-section/themed-file-section.component'; +import { ItemPageAbstractFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/abstract/item-page-abstract-field.component'; +import { ItemPageCcLicenseFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/cc-license/item-page-cc-license-field.component'; +import { ItemPageDateFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/date/item-page-date-field.component'; +import { ItemPageDoiFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/doi/item-page-doi-field.component'; +import { GenericItemPageFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; +import { ThemedItemPageTitleFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/title/themed-item-page-field.component'; +import { ItemPageUriFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/uri/item-page-uri-field.component'; +import { ThemedMetadataRepresentationListComponent } from '../../../../../../../app/item-page/simple/metadata-representation-list/themed-metadata-representation-list.component'; +import { DsoEditMenuComponent } from '../../../../../../../app/shared/dso-page/dso-edit-menu/dso-edit-menu.component'; +import { MetadataFieldWrapperComponent } from '../../../../../../../app/shared/metadata-field-wrapper/metadata-field-wrapper.component'; +import { listableObjectComponent } from '../../../../../../../app/shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ThemedResultsBackButtonComponent } from '../../../../../../../app/shared/results-back-button/themed-results-back-button.component'; +import { ThemedThumbnailComponent } from '../../../../../../../app/thumbnail/themed-thumbnail.component'; + +/** + * Component that represents a publication Item page + */ + +@listableObjectComponent(Item, ViewMode.StandalonePage, Context.Any, 'szerep') +@Component({ + selector: 'ds-untyped-item', + styleUrls: ['./untyped-item.component.scss'], + templateUrl: './untyped-item.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [ + NgIf, + ThemedResultsBackButtonComponent, + MiradorViewerComponent, + ThemedItemPageTitleFieldComponent, + DsoEditMenuComponent, + MetadataFieldWrapperComponent, + ThemedThumbnailComponent, + ThemedMediaViewerComponent, + ThemedFileSectionComponent, + ItemPageDateFieldComponent, + ThemedMetadataRepresentationListComponent, + GenericItemPageFieldComponent, + ItemPageAbstractFieldComponent, + ItemPageUriFieldComponent, + CollectionsComponent, + RouterLink, + AsyncPipe, + TranslateModule, + ItemPageCcLicenseFieldComponent, + ItemPageDoiFieldComponent, + ], +}) +export class UntypedItemComponent extends BaseComponent {} diff --git a/src/themes/szerep/assets/i18n/en.json5 b/src/themes/szerep/assets/i18n/en.json5 index 4c8bdefcbdf..331e6a288c6 100644 --- a/src/themes/szerep/assets/i18n/en.json5 +++ b/src/themes/szerep/assets/i18n/en.json5 @@ -5,7 +5,7 @@ "home.top-level-communities.head": "Communities in SZERep", - "browse.search-form.placeholder": "Enter the first few characters", + "browse.search-form.placeholder": "Enter the first few characters", "qulto.home.welcome.title": "Welcome to the SZERep - Széchenyi István University Repository page!", diff --git a/src/themes/szerep/assets/i18n/hu.json5 b/src/themes/szerep/assets/i18n/hu.json5 index 31c501b80a7..d59dc8ddfd9 100644 --- a/src/themes/szerep/assets/i18n/hu.json5 +++ b/src/themes/szerep/assets/i18n/hu.json5 @@ -11,7 +11,7 @@ "item.truncatable-part.show-less": "Kevesebb", - "vocabulary-treeview.load-more": "Továbbiak", + "vocabulary-treeview.load-more": "Továbbiak", "qulto.home.welcome.title": "Köszöntjük a SZERep - Széchenyi István Egyetem Repozitórium oldalán!", diff --git a/src/themes/szerep/eager-theme.module.ts b/src/themes/szerep/eager-theme.module.ts index 8bbb469ad2e..02638b7348b 100644 --- a/src/themes/szerep/eager-theme.module.ts +++ b/src/themes/szerep/eager-theme.module.ts @@ -6,9 +6,10 @@ import { FooterComponent } from './app/footer/footer.component'; import { HeaderComponent } from './app/header/header.component'; import { HeaderNavbarWrapperComponent } from './app/header-nav-wrapper/header-navbar-wrapper.component'; import { HomeNewsComponent } from './app/home-page/home-news/home-news.component'; +import { UntypedItemComponent } from './app/item-page/simple/item-types/untyped-item/untyped-item.component'; import { NavbarComponent } from './app/navbar/navbar.component'; -import { CommunityListElementComponent } from './app/shared/object-list/community-list-element/community-list-element.component'; import { LangSwitchComponent } from './app/shared/lang-switch/lang-switch.component'; +import { CommunityListElementComponent } from './app/shared/object-list/community-list-element/community-list-element.component'; import { ItemSearchResultListElementComponent } from './app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component'; /** @@ -17,7 +18,7 @@ import { ItemSearchResultListElementComponent } from './app/shared/object-list/s */ const ENTRY_COMPONENTS = [ CommunityListElementComponent, - ItemSearchResultListElementComponent + ItemSearchResultListElementComponent, ]; const DECLARATIONS = [ @@ -27,7 +28,8 @@ const DECLARATIONS = [ HeaderNavbarWrapperComponent, NavbarComponent, FooterComponent, - LangSwitchComponent + LangSwitchComponent, + UntypedItemComponent, ]; @NgModule({ diff --git a/src/themes/szerep/lazy-theme.module.ts b/src/themes/szerep/lazy-theme.module.ts index 5df50404153..5493ac4ae41 100644 --- a/src/themes/szerep/lazy-theme.module.ts +++ b/src/themes/szerep/lazy-theme.module.ts @@ -14,12 +14,12 @@ import { ScrollToModule } from '@nicky-lenaers/ngx-scroll-to'; import { RootModule } from '../../app/root.module'; import { AdminSidebarComponent } from './app/admin/admin-sidebar/admin-sidebar.component'; import { HomePageComponent } from './app/home-page/home-page.component'; -import { LoginPageComponent } from './app/login-page/login-page.component'; -import { ObjectListComponent } from './app/shared/object-list/object-list.component'; -import { AuthNavMenuComponent } from './app/shared/auth-nav-menu/auth-nav-menu.component'; import { FullItemPageComponent } from './app/item-page/full/full-item-page.component'; +import { LoginPageComponent } from './app/login-page/login-page.component'; import { RegisterEmailFormComponent } from './app/register-email-form/register-email-form.component'; +import { AuthNavMenuComponent } from './app/shared/auth-nav-menu/auth-nav-menu.component'; import { AccessStatusBadgeComponent } from './app/shared/object-collection/shared/badges/access-status-badge/access-status-badge.component'; +import { ObjectListComponent } from './app/shared/object-list/object-list.component'; const DECLARATIONS = [ HomePageComponent, @@ -29,7 +29,7 @@ const DECLARATIONS = [ AuthNavMenuComponent, FullItemPageComponent, RegisterEmailFormComponent, - AccessStatusBadgeComponent + AccessStatusBadgeComponent, ]; @NgModule({