diff --git a/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.html b/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.html
new file mode 100644
index 00000000000..c09c23f8651
--- /dev/null
+++ b/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{value}}
+
+
+
+
+
+
+
+ {{value}}
+
+
+
+
+
+ {{value}}
+
+
+
+
+ {{value}}
+
diff --git a/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.scss b/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.scss
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.ts b/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.ts
new file mode 100644
index 00000000000..a8e93bf2b42
--- /dev/null
+++ b/src/themes/qulto/app/item-page/simple/field-components/metadata-values/metadata-values.component.ts
@@ -0,0 +1,166 @@
+import {
+ AsyncPipe,
+ NgFor,
+ NgIf,
+ NgTemplateOutlet,
+} from '@angular/common';
+import {
+ Component,
+ Inject,
+ Input,
+ OnChanges,
+ SimpleChanges,
+} from '@angular/core';
+import { RouterLink } from '@angular/router';
+import { TranslateModule } from '@ngx-translate/core';
+
+import {
+ APP_CONFIG,
+ AppConfig,
+} from '../../../../../../../config/app-config.interface';
+import { environment } from '../../../../../../../environments/environment';
+import { BrowseDefinition } from 'src/app/core/shared/browse-definition.model';
+import { MetadataValue } from 'src/app/core/shared/metadata.models';
+import { hasValue } from 'src/app/shared/empty.util';
+import { MetadataFieldWrapperComponent } from 'src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component';
+import { MarkdownDirective } from 'src/app/shared/utils/markdown.directive';
+import { ImageField } from 'src/app/item-page/simple/field-components/specific-field/image-field';
+import { ResourceType } from 'src/app/core/shared/resource-type';
+import { listableObjectComponent } from 'src/app/shared/object-collection/shared/listable-object/listable-object.decorator';
+import { ViewMode } from 'src/app/core/shared/view-mode.model';
+import { Context } from 'src/app/core/shared/context.model';
+
+/**
+ * This component renders the configured 'values' into the ds-metadata-field-wrapper component.
+ * It puts the given 'separator' between each two values.
+ */
+@listableObjectComponent('MetadataValuesComponent', ViewMode.ListElement, Context.Any, 'qulto')
+@Component({
+ selector: 'ds-metadata-values',
+ styleUrls: ['./metadata-values.component.scss'],
+ templateUrl: './metadata-values.component.html',
+ standalone: true,
+ imports: [MetadataFieldWrapperComponent, NgFor, NgTemplateOutlet, NgIf, RouterLink, AsyncPipe, TranslateModule, MarkdownDirective],
+})
+export class MetadataValuesComponent implements OnChanges {
+
+ constructor(
+ @Inject(APP_CONFIG) private appConfig: AppConfig,
+ ) {
+ }
+
+ /**
+ * The metadata values to display
+ */
+ @Input() mdValues: MetadataValue[];
+
+ /**
+ * The seperator used to split the metadata values (can contain HTML)
+ */
+ @Input() separator: string;
+
+ /**
+ * The label for this iteration of metadata values
+ */
+ @Input() label: string;
+
+ /**
+ * Whether the {@link MarkdownDirective} should be used to render these metadata values.
+ * This will only have effect if {@link MarkdownConfig#enabled} is true.
+ * Mathjax will only be rendered if {@link MarkdownConfig#mathjax} is true.
+ */
+ @Input() enableMarkdown = false;
+
+ /**
+ * Whether any valid HTTP(S) URL should be rendered as a link
+ */
+ @Input() urlRegex?;
+
+ /**
+ * This variable will be true if both {@link environment.markdown.enabled} and {@link enableMarkdown} are true.
+ */
+ renderMarkdown;
+
+
+ @Input() browseDefinition?: BrowseDefinition;
+
+ /**
+ * Optional {@code ImageField} reference that represents an image to be displayed inline.
+ */
+ @Input() img?: ImageField;
+
+ hasValue = hasValue;
+
+ ngOnChanges(changes: SimpleChanges): void {
+ this.renderMarkdown = !!this.appConfig.markdown.enabled && this.enableMarkdown;
+ }
+
+ /**
+ * Does this metadata value have a configured link to a browse definition?
+ */
+ hasBrowseDefinition(): boolean {
+ console.log('hasBrowseDefinition');
+ return hasValue(this.browseDefinition);
+ }
+
+ /**
+ * Does this metadata value have a valid URL that should be rendered as a link?
+ * @param value A MetadataValue being displayed
+ */
+ hasLink(value: MetadataValue): boolean {
+ console.log('hasLink');
+ if (hasValue(this.urlRegex)) {
+ const pattern = new RegExp(this.urlRegex);
+ return pattern.test(value.value);
+ }
+ return false;
+ }
+
+ /**
+ * Return a queryparams object for use in a link, with the key dependent on whether this browse
+ * definition is metadata browse, or item browse
+ * @param value the specific metadata value being linked
+ */
+ getQueryParams(value) {
+ console.log('getQueryParams');
+ const queryParams = { value: value };
+ // todo: should compare with type instead?
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
+ if (this.browseDefinition.getRenderType() === new ResourceType("startsWith").value) {
+ return { startsWith: value };
+ }
+ return queryParams;
+ }
+
+ getBrowseRouteSegment(): string {
+ console.log('getBrowseRouteSegment');
+ if (this.browseDefinition?.id === 'srsc') {
+ return 'subject';
+ }
+ return this.browseDefinition?.id;
+ }
+
+
+ /**
+ * Checks if the given link value is an internal link.
+ * @param linkValue - The link value to check.
+ * @returns True if the link value starts with the base URL defined in the environment configuration, false otherwise.
+ */
+ hasInternalLink(linkValue: string): boolean {
+ console.log('hasInternalLink');
+ return linkValue.startsWith(environment.ui.baseUrl);
+ }
+
+ /**
+ * This method performs a validation and determines the target of the url.
+ * @returns - Returns the target url.
+ */
+ getLinkAttributes(urlValue: string): { target: string, rel: string } {
+ console.log('getLinkAttributes');
+ if (this.hasInternalLink(urlValue)) {
+ return { target: '_self', rel: '' };
+ } else {
+ return { target: '_blank', rel: 'noopener noreferrer' };
+ }
+ }
+}
diff --git a/src/themes/qulto/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts b/src/themes/qulto/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts
new file mode 100644
index 00000000000..3a55e599691
--- /dev/null
+++ b/src/themes/qulto/app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts
@@ -0,0 +1,56 @@
+import { AsyncPipe } from '@angular/common';
+import {
+ Component,
+ Input,
+} from '@angular/core';
+
+import { Item } from 'src/app/core/shared/item.model';
+import { MetadataValuesComponent } from '../../metadata-values/metadata-values.component';
+import { ItemPageFieldComponent } from 'src/app/item-page/simple/field-components/specific-field/item-page-field.component';
+
+@Component({
+ selector: 'ds-generic-item-page-field',
+ templateUrl: '../item-page-field.component.html',
+ standalone: true,
+ imports: [MetadataValuesComponent, AsyncPipe],
+})
+/**
+ * This component can be used to represent metadata on a simple item page.
+ * It is the most generic way of displaying metadata values
+ * It expects 4 parameters: The item, a separator, the metadata keys and an i18n key
+ */
+export class GenericItemPageFieldComponent extends ItemPageFieldComponent {
+
+ /**
+ * The item to display metadata for
+ */
+ @Input() item: Item;
+
+ /**
+ * Separator string between multiple values of the metadata fields defined
+ * @type {string}
+ */
+ @Input() separator: string;
+
+ /**
+ * Fields (schema.element.qualifier) used to render their values.
+ */
+ @Input() fields: string[];
+
+ /**
+ * Label i18n key for the rendered metadata
+ */
+ @Input() label: string;
+
+ /**
+ * Whether the {@link MarkdownDirective} should be used to render this metadata.
+ */
+ @Input() enableMarkdown = false;
+
+ /**
+ * Whether any valid HTTP(S) URL should be rendered as a link
+ */
+ @Input() urlRegex?: string;
+
+
+}
diff --git a/src/themes/qulto/app/item-page/simple/field-components/specific-field/item-page-field.component.html b/src/themes/qulto/app/item-page/simple/field-components/specific-field/item-page-field.component.html
new file mode 100644
index 00000000000..f45d4657a46
--- /dev/null
+++ b/src/themes/qulto/app/item-page/simple/field-components/specific-field/item-page-field.component.html
@@ -0,0 +1,11 @@
+
+
+
diff --git a/src/themes/qulto/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.spec.ts b/src/themes/qulto/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.spec.ts
index c8165c6f871..7e3e24d650e 100644
--- a/src/themes/qulto/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.spec.ts
+++ b/src/themes/qulto/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.spec.ts
@@ -13,7 +13,7 @@ import {
} from '@ngx-translate/core';
import { TranslateLoaderMock } from '../../../../../../../../app/shared/testing/translate-loader.mock';
-import { MetadataValuesComponent } from '../../../../../../../../app/item-page/field-components/metadata-values/metadata-values.component';
+import { MetadataValuesComponent } from '../../metadata-values/metadata-values.component';
import { mockItemWithMetadataFieldsAndValue } from '../../../../../../../../app/item-page/simple/field-components/specific-field/item-page-field.component.spec';
import { ItemPageTitleFieldComponent } from './item-page-title-field.component';
diff --git a/src/themes/qulto/app/item-page/simple/item-types/publication/publication.component.ts b/src/themes/qulto/app/item-page/simple/item-types/publication/publication.component.ts
index 6f2f1482e8b..5291e9d9786 100644
--- a/src/themes/qulto/app/item-page/simple/item-types/publication/publication.component.ts
+++ b/src/themes/qulto/app/item-page/simple/item-types/publication/publication.component.ts
@@ -22,7 +22,7 @@ import { MiradorViewerComponent } from '../../../../../../../app/item-page/mirad
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 { ItemPageDateFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/date/item-page-date-field.component';
-import { GenericItemPageFieldComponent } from '../../../../../../../app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component';
+import { GenericItemPageFieldComponent } from '../../field-components/specific-field/generic/generic-item-page-field.component';
import { ThemedItemPageTitleFieldComponent } from '../../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';
diff --git a/src/themes/qulto/eager-theme.module.ts b/src/themes/qulto/eager-theme.module.ts
index ad263eeb32e..0d31e90bec2 100644
--- a/src/themes/qulto/eager-theme.module.ts
+++ b/src/themes/qulto/eager-theme.module.ts
@@ -10,6 +10,7 @@ import { NavbarComponent } from './app/navbar/navbar.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 { PublicationComponent } from './app/item-page/simple/item-types/publication/publication.component';
+import { MetadataValuesComponent } from './app/item-page/simple/field-components/metadata-values/metadata-values.component';
/**
@@ -28,7 +29,8 @@ const DECLARATIONS = [
NavbarComponent,
FooterComponent,
LangSwitchComponent,
- PublicationComponent
+ PublicationComponent,
+ MetadataValuesComponent
];
@NgModule({
@@ -36,6 +38,7 @@ const DECLARATIONS = [
CommonModule,
RootModule,
PublicationComponent,
+ MetadataValuesComponent,
...DECLARATIONS,
],
providers: [
diff --git a/src/themes/qulto/lazy-theme.module.ts b/src/themes/qulto/lazy-theme.module.ts
index 3172f900cc4..56428c061f8 100644
--- a/src/themes/qulto/lazy-theme.module.ts
+++ b/src/themes/qulto/lazy-theme.module.ts
@@ -17,6 +17,8 @@ import { HomePageComponent } from './app/home-page/home-page.component';
import { FullItemPageComponent } from './app/item-page/full/full-item-page.component';
import { PublicationComponent } from './app/item-page/simple/item-types/publication/publication.component';
import { ThemedItemPageTitleFieldComponent } from './app/item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
+import { MetadataValuesComponent } from './app/item-page/simple/field-components/metadata-values/metadata-values.component';
+import { GenericItemPageFieldComponent } from './app/item-page/simple/field-components/specific-field/generic/generic-item-page-field.component';
import { LoginPageComponent } from './app/login-page/login-page.component';
import { AuthNavMenuComponent } from './app/shared/auth-nav-menu/auth-nav-menu.component';
import { ObjectListComponent } from './app/shared/object-list/object-list.component';
@@ -48,6 +50,8 @@ const DECLARATIONS = [
NgxGalleryModule,
PublicationComponent,
ThemedItemPageTitleFieldComponent,
+ GenericItemPageFieldComponent,
+ MetadataValuesComponent,
...DECLARATIONS,
],
})