Skip to content

Commit 8ca81ed

Browse files
author
Andrea Barbasso
committed
[CST-19328] add lang attribute in representation components
1 parent 5203ffa commit 8ca81ed

10 files changed

Lines changed: 101 additions & 7 deletions

src/app/core/shared/metadata-representation/item/item-metadata-representation.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,11 @@ export class ItemMetadataRepresentation extends Item implements MetadataRepresen
4141
return this.virtualMetadata.value;
4242
}
4343

44+
/**
45+
* Get the language of the value to display
46+
*/
47+
getLanguage(): string {
48+
return this.virtualMetadata.language || null;
49+
}
50+
4451
}

src/app/core/shared/metadata-representation/metadata-representation.model.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,9 @@ export interface MetadataRepresentation {
3737
*/
3838
getValue(): string;
3939

40+
/**
41+
* Fetches the language of the metadata
42+
*/
43+
getLanguage(): string;
44+
4045
}

src/app/core/shared/metadata-representation/metadatum/metadatum-representation.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,11 @@ export class MetadatumRepresentation extends MetadataValue implements MetadataRe
4747
return this.value;
4848
}
4949

50+
/**
51+
* Get the value language
52+
*/
53+
getLanguage(): string {
54+
return this.language || null;
55+
}
56+
5057
}

src/app/shared/metadata-representation/metadata-representation-loader.component.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class TestType implements MetadataRepresentation {
3636
getValue(): string {
3737
return '';
3838
}
39+
40+
getLanguage(): string {
41+
return '';
42+
}
3943
}
4044

4145
describe('MetadataRepresentationLoaderComponent', () => {

src/app/shared/metadata.directive.spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ describe('MetadataDirective', () => {
2626
let span: HTMLSpanElement;
2727

2828
function createMetadata(value?: string, language?: string): MetadataValue {
29-
return { uuid: '123', value: value as any, language: language as any, place: undefined as any, authority: undefined as any, confidence: undefined as any } as MetadataValue;
29+
return {
30+
uuid: '123',
31+
value: value,
32+
language: language,
33+
place: undefined,
34+
authority: undefined,
35+
confidence: undefined,
36+
} as MetadataValue;
3037
}
3138

3239
beforeEach(async () => {
@@ -71,14 +78,14 @@ describe('MetadataDirective', () => {
7178
});
7279

7380
it('removes lang attribute when language missing', () => {
74-
host.mv = createMetadata('Value', undefined as any);
81+
host.mv = createMetadata('Value', undefined);
7582
fixture.detectChanges();
7683
expect(span.innerHTML).toBe('Value');
7784
expect(span.hasAttribute('lang')).toBeFalse();
7885
});
7986

8087
it('renders empty string when value is undefined', () => {
81-
host.mv = createMetadata(undefined as any, 'en');
88+
host.mv = createMetadata(undefined, 'en');
8289
fixture.detectChanges();
8390
expect(span.innerHTML).toBe('');
8491
expect(span.getAttribute('lang')).toBe('en');

src/app/shared/metadata.directive.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,54 @@ import {
88

99
import { MetadataValue } from '../core/shared/metadata.models';
1010

11+
/**
12+
* A directive that sets the innerHTML and lang attribute of the host element
13+
* based on the provided `MetadataValue`.
14+
*
15+
* - The `innerHTML` is set to the `value` property of the `MetadataValue`.
16+
* - The `lang` attribute is set to the `language` property of the `MetadataValue`.
17+
* - If the `MetadataValue` is null or undefined, the `innerHTML` is cleared and the `lang` attribute is removed.
18+
*/
1119
@Directive({
1220
selector: '[dsMetadata]',
1321
standalone: true,
1422
})
1523
export class MetadataDirective {
24+
/**
25+
* Stores the current `MetadataValue` provided to the directive.
26+
*/
1627
private _metadataValue?: MetadataValue;
1728

29+
/**
30+
* Reference to the host DOM element.
31+
*/
1832
private el = inject(ElementRef);
33+
34+
/**
35+
* Angular Renderer2 instance for safely manipulating the DOM.
36+
*/
1937
private renderer = inject(Renderer2);
2038

2139
/**
22-
* Accepts a MetadataValue. Sets the host element's innerHTML to the metadata value and the lang attribute to the metadata language.
40+
* Input property for the directive. Accepts a `MetadataValue` object.
41+
* When set, it updates the host element's `innerHTML` and `lang` attribute.
42+
*
43+
* @param value - The `MetadataValue` object containing the `value` and `language`.
2344
*/
2445
@Input() set dsMetadata(value: MetadataValue | null | undefined) {
2546
this._metadataValue = value ?? undefined;
2647
this.updateHost();
2748
}
2849

50+
/**
51+
* Updates the host element's `innerHTML` and `lang` attribute based on the current `MetadataValue`.
52+
* - If `MetadataValue` is provided:
53+
* - Sets `innerHTML` to `MetadataValue.value` (or an empty string if `value` is null/undefined).
54+
* - Sets the `lang` attribute to `MetadataValue.language` (or removes it if `language` is null/undefined).
55+
* - If `MetadataValue` is null/undefined:
56+
* - Clears the `innerHTML`.
57+
* - Removes the `lang` attribute.
58+
*/
2959
private updateHost(): void {
3060
if (this._metadataValue) {
3161
const val = this._metadataValue.value ?? '';
@@ -41,4 +71,3 @@ export class MetadataDirective {
4171
}
4272
}
4373
}
44-

src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<a
44
target="_blank" class="dont-break-out"
55
[routerLink]="['/browse/', mdRepresentation.browseDefinition.id]"
6+
[attr.lang]="mdRepresentation.getLanguage()"
67
[queryParams]="getQueryParams()">
78
{{mdRepresentation.getValue()}}
89
</a>

src/app/shared/object-list/metadata-representation-list-element/browse-link/browse-link-metadata-list-element.component.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ describe('BrowseLinkMetadataListElementComponent', () => {
6666
it('should NOT match isLink', () => {
6767
expect(comp.isLink()).toBe(false);
6868
});
69+
70+
it('should set lang attribute when language is provided', () => {
71+
(comp.mdRepresentation as any).language = 'en';
72+
fixture.detectChanges();
73+
const anchor: HTMLAnchorElement = fixture.debugElement.nativeElement.querySelector('a');
74+
expect(anchor.getAttribute('lang')).toBe('en');
75+
});
76+
77+
it('should remove lang attribute when language becomes undefined', () => {
78+
(comp.mdRepresentation as any).language = 'fr';
79+
fixture.detectChanges();
80+
(comp.mdRepresentation as any).language = undefined;
81+
fixture.detectChanges();
82+
const anchor: HTMLAnchorElement = fixture.debugElement.nativeElement.querySelector('a');
83+
expect(anchor.getAttribute('lang')).toBeNull();
84+
});
6985
});
7086

7187
describe('with metadata with an url', () => {

src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
<div>
22
<!-- Because this template is used by default, we will additionally test for representation type and display accordingly -->
33
@if ((mdRepresentation.representationType==='plain_text') && !isLink()) {
4-
<span class="dont-break-out">
4+
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage()">
55
{{mdRepresentation.getValue()}}
66
</span>
77
}
88
@if ((mdRepresentation.representationType==='plain_text') && isLink()) {
99
<a class="dont-break-out"
10+
[attr.lang]="mdRepresentation.getLanguage()"
1011
target="_blank" [href]="mdRepresentation.getValue()" role="link" tabindex="0">
1112
{{mdRepresentation.getValue()}}
1213
</a>
1314
}
1415
@if ((mdRepresentation.representationType==='authority_controlled')) {
15-
<span class="dont-break-out">{{mdRepresentation.getValue()}}</span>
16+
<span class="dont-break-out" [attr.lang]="mdRepresentation.getLanguage()">{{mdRepresentation.getValue()}}</span>
1617
}
1718
@if ((mdRepresentation.representationType==='browse_link')) {
1819
<a
1920
class="dont-break-out ds-browse-link"
2021
[routerLink]="['/browse/', mdRepresentation.browseDefinition.id]"
2122
[queryParams]="getQueryParams()"
2223
role="link"
24+
[attr.lang]="mdRepresentation.getLanguage()"
2325
tabindex="0">
2426
{{mdRepresentation.getValue()}}
2527
</a>

src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,20 @@ describe('PlainTextMetadataListElementComponent', () => {
5151
expect(fixture.debugElement.query(By.css('a.ds-browse-link')).nativeElement.innerHTML).toContain(mockMetadataRepresentation.value);
5252
});
5353

54+
it('should set lang attribute when language is provided', () => {
55+
(comp.mdRepresentation as any).language = 'en';
56+
fixture.detectChanges();
57+
const el: HTMLElement = fixture.debugElement.nativeElement.querySelector('.dont-break-out');
58+
expect(el.getAttribute('lang')).toBe('en');
59+
});
60+
61+
it('should remove lang attribute when language becomes undefined', () => {
62+
(comp.mdRepresentation as any).language = 'fr';
63+
fixture.detectChanges();
64+
(comp.mdRepresentation as any).language = undefined;
65+
fixture.detectChanges();
66+
const el: HTMLElement = fixture.debugElement.nativeElement.querySelector('.dont-break-out');
67+
expect(el.getAttribute('lang')).toBeNull();
68+
});
69+
5470
});

0 commit comments

Comments
 (0)