From f1305274ca6506cff922b5f8ea92ee77e805c48a Mon Sep 17 00:00:00 2001 From: msutya Date: Thu, 4 Sep 2025 21:56:35 +0200 Subject: [PATCH 1/4] ELTETANREP-41 create new generic-item-metadata-list-element.component for new entity types --- ...-item-metadata-list-element.component.html | 12 +++ ...ic-item-metadata-list-element.component.ts | 86 +++++++++++++++++++ .../metadata-representation.decorator.ts | 64 +++++++++++++- 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html create mode 100644 src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts diff --git a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html new file mode 100644 index 00000000000..24a3fab6123 --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts new file mode 100644 index 00000000000..64ee767712b --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts @@ -0,0 +1,86 @@ +import { + Component, + Input, + OnDestroy, + OnInit, + ChangeDetectionStrategy, +} from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; + +import { MetadataValue } from '../../../../core/shared/metadata.models'; +import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; +import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths'; + +import { MetadataRepresentationListElementComponent } from 'src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component'; +import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component'; + +@Component({ + selector: 'ds-item-metadata-representation-list-element', + templateUrl: './generic-item-metadata-list-element.component.html', + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + CommonModule, + RouterModule, + NgbTooltipModule, + TruncatableComponent, + ], +}) +export class GenericItemMetadataListElementComponent extends MetadataRepresentationListElementComponent implements OnInit, OnDestroy { + + @Input() mdRepresentation!: ItemMetadataRepresentation; + + itemPageRoute = ''; + titleForUiLang = ''; + descriptionForUiLang = ''; + + private subs: Subscription[] = []; + + constructor(private translate: TranslateService) { + super(); + } + + ngOnInit(): void { + this.itemPageRoute = getItemPageRoute(this.mdRepresentation); + this.localizeTexts(this.translate.currentLang); + + this.subs.push( + this.translate.onLangChange.subscribe(e => this.localizeTexts(e.lang)) + ); + } + + ngOnDestroy(): void { + this.subs.forEach(s => s?.unsubscribe()); + } + + private localizeTexts(lang: string): void { + this.titleForUiLang = this.pickByLang(['dc.title'], lang) ?? ''; + this.descriptionForUiLang = this.pickByLang(['dc.description'], lang) ?? ''; + } + + private pickByLang(keys: string[], uiLanguage: string): string | undefined { + const metadataValues = this.mdRepresentation.allMetadata(keys) as MetadataValue[] | undefined; + if (!metadataValues?.length) return undefined; + + const normalizeLanguage = (s?: string) => (s ?? '').toLowerCase(); + const getLanguageBase = (s?: string) => normalizeLanguage(s).split(/[_-]/)[0]; + + const currentLocale = normalizeLanguage(uiLanguage); + const currentLangBase = getLanguageBase(uiLanguage); + + const exactMatch = metadataValues.find(v => normalizeLanguage(v.language) === currentLocale); + if (exactMatch) return exactMatch.value; + + const baseLangMatch = metadataValues.find(v => getLanguageBase(v.language) === currentLangBase); + if (baseLangMatch) return baseLangMatch.value; + + const languageAgnostic = metadataValues.find(v => !v.language); + if (languageAgnostic) return languageAgnostic.value; + + return metadataValues[0]?.value; + } +} diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.ts index c34eb0d2191..1defb9de94f 100644 --- a/src/app/shared/metadata-representation/metadata-representation.decorator.ts +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.ts @@ -18,6 +18,7 @@ import { import { BrowseLinkMetadataListElementComponent } from '../object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component'; import { ItemMetadataListElementComponent } from '../object-list/metadata-representation-list-element/item/item-metadata-list-element.component'; import { PlainTextMetadataListElementComponent } from '../object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component'; +import { GenericItemMetadataListElementComponent } from 'src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component'; export const METADATA_REPRESENTATION_COMPONENT_FACTORY = new InjectionToken<(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context, theme: string) => GenericConstructor>('getMetadataRepresentationComponent', { providedIn: 'root', @@ -34,7 +35,8 @@ export type MetadataRepresentationComponent = typeof ItemMetadataListElementComponent | typeof OrgUnitItemMetadataListElementComponent | typeof PersonItemMetadataListElementComponent | - typeof ProjectItemMetadataListElementComponent; + typeof ProjectItemMetadataListElementComponent | + typeof GenericItemMetadataListElementComponent; export const METADATA_REPRESENTATION_COMPONENT_DECORATOR_MAP = new Map>>>([ @@ -52,6 +54,66 @@ export const METADATA_REPRESENTATION_COMPONENT_DECORATOR_MAP = [MetadataRepresentationType.Item, new Map([ [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, PersonItemMetadataListElementComponent]])]])], ])], + ['LearningObject', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Language', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['EducationLevel', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Type', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Format', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['TeachingMethod', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['License', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['FieldOfScience', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Course', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['DoctoralSchool', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Faculty', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Department', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['Institute', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['SchoolSubject', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], + ['AccessLevel', new Map([ + [MetadataRepresentationType.Item, new Map([ + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + ])], ['OrgUnit', new Map([ [MetadataRepresentationType.Item, new Map([ [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, OrgUnitItemMetadataListElementComponent]])]])], From d8aa38f5f9718bfde8db3e9b0ab7c871a8f51c6f Mon Sep 17 00:00:00 2001 From: msutya Date: Thu, 4 Sep 2025 22:00:33 +0200 Subject: [PATCH 2/4] ELTETANREP-41 add missing new line --- .../generic-item-metadata-list-element.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html index 24a3fab6123..1c44c860c85 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.html @@ -9,4 +9,4 @@ - \ No newline at end of file + From 7d42b0c27957223289d9b385d8dc2be4210837d4 Mon Sep 17 00:00:00 2001 From: msutya Date: Mon, 8 Sep 2025 09:38:03 +0200 Subject: [PATCH 3/4] ELTETANREP-41 add missing trailing commas, refactor --- ...ic-item-metadata-list-element.component.ts | 22 +++++++++----- .../metadata-representation.decorator.ts | 30 +++++++++---------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts index 64ee767712b..1e60020ebab 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts @@ -5,6 +5,7 @@ import { OnInit, ChangeDetectionStrategy, } from '@angular/core'; + import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { Subscription } from 'rxjs'; @@ -49,7 +50,7 @@ export class GenericItemMetadataListElementComponent extends MetadataRepresentat this.localizeTexts(this.translate.currentLang); this.subs.push( - this.translate.onLangChange.subscribe(e => this.localizeTexts(e.lang)) + this.translate.onLangChange.subscribe(e => this.localizeTexts(e.lang)), ); } @@ -64,7 +65,9 @@ export class GenericItemMetadataListElementComponent extends MetadataRepresentat private pickByLang(keys: string[], uiLanguage: string): string | undefined { const metadataValues = this.mdRepresentation.allMetadata(keys) as MetadataValue[] | undefined; - if (!metadataValues?.length) return undefined; + if (!metadataValues?.length){ + return undefined; + } const normalizeLanguage = (s?: string) => (s ?? '').toLowerCase(); const getLanguageBase = (s?: string) => normalizeLanguage(s).split(/[_-]/)[0]; @@ -73,14 +76,17 @@ export class GenericItemMetadataListElementComponent extends MetadataRepresentat const currentLangBase = getLanguageBase(uiLanguage); const exactMatch = metadataValues.find(v => normalizeLanguage(v.language) === currentLocale); - if (exactMatch) return exactMatch.value; - + if (exactMatch) { + return exactMatch.value; + } const baseLangMatch = metadataValues.find(v => getLanguageBase(v.language) === currentLangBase); - if (baseLangMatch) return baseLangMatch.value; - + if (baseLangMatch) { + return baseLangMatch.value; + } const languageAgnostic = metadataValues.find(v => !v.language); - if (languageAgnostic) return languageAgnostic.value; - + if (languageAgnostic) { + return languageAgnostic.value; + } return metadataValues[0]?.value; } } diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.ts index 1defb9de94f..32b7b877023 100644 --- a/src/app/shared/metadata-representation/metadata-representation.decorator.ts +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.ts @@ -56,63 +56,63 @@ export const METADATA_REPRESENTATION_COMPONENT_DECORATOR_MAP = ])], ['LearningObject', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Language', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['EducationLevel', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Type', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Format', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['TeachingMethod', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['License', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['FieldOfScience', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Course', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['DoctoralSchool', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Faculty', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Department', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['Institute', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['SchoolSubject', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['AccessLevel', new Map([ [MetadataRepresentationType.Item, new Map([ - [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])] + [DEFAULT_CONTEXT, new Map([[DEFAULT_THEME, GenericItemMetadataListElementComponent]])]])], ])], ['OrgUnit', new Map([ [MetadataRepresentationType.Item, new Map([ From 5cc388222993bf3fff79a81d337ae1df64c61a0a Mon Sep 17 00:00:00 2001 From: msutya Date: Mon, 8 Sep 2025 10:22:21 +0200 Subject: [PATCH 4/4] ELTETANREP-41 refactor imports --- ...generic-item-metadata-list-element.component.ts | 14 ++++++-------- .../metadata-representation.decorator.ts | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts index 1e60020ebab..d27c9e0facf 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts +++ b/src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component.ts @@ -1,24 +1,22 @@ +import { CommonModule } from '@angular/common'; import { + ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit, - ChangeDetectionStrategy, } from '@angular/core'; - -import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; -import { Subscription } from 'rxjs'; -import { TranslateService } from '@ngx-translate/core'; import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { Subscription } from 'rxjs'; +import { MetadataRepresentationListElementComponent } from 'src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component'; +import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component'; import { MetadataValue } from '../../../../core/shared/metadata.models'; import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths'; -import { MetadataRepresentationListElementComponent } from 'src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component'; -import { TruncatableComponent } from 'src/app/shared/truncatable/truncatable.component'; - @Component({ selector: 'ds-item-metadata-representation-list-element', templateUrl: './generic-item-metadata-list-element.component.html', diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.ts index 32b7b877023..93a0801c865 100644 --- a/src/app/shared/metadata-representation/metadata-representation.decorator.ts +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.ts @@ -1,4 +1,5 @@ import { InjectionToken } from '@angular/core'; +import { GenericItemMetadataListElementComponent } from 'src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component'; import { Context } from '../../core/shared/context.model'; import { GenericConstructor } from '../../core/shared/generic-constructor'; @@ -18,7 +19,6 @@ import { import { BrowseLinkMetadataListElementComponent } from '../object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component'; import { ItemMetadataListElementComponent } from '../object-list/metadata-representation-list-element/item/item-metadata-list-element.component'; import { PlainTextMetadataListElementComponent } from '../object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component'; -import { GenericItemMetadataListElementComponent } from 'src/app/entity-groups/research-entities/metadata-representations/generic-item/generic-item-metadata-list-element.component'; export const METADATA_REPRESENTATION_COMPONENT_FACTORY = new InjectionToken<(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context, theme: string) => GenericConstructor>('getMetadataRepresentationComponent', { providedIn: 'root',