Skip to content

Commit df8318e

Browse files
Mattia VianelliAndrea Barbasso
authored andcommitted
Merged in task/dspace-cris-2025_02_x/DSC-2458 (pull request DSpace#4591)
Task/dspace cris 2025 02 x/DSC-2458 Approved-by: Andrea Barbasso
2 parents 2b16910 + 8b649a1 commit df8318e

10 files changed

Lines changed: 415 additions & 87 deletions
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<div class="container">
2+
3+
@if (headLabel$ | async; as headLabel) {
4+
<h2>{{ headLabel | translate }}</h2>
5+
}
6+
7+
@if (metadataLoaded$ | async) {
8+
@if (cmsMetadataValue$ | async; as value) {
9+
<ds-markdown-viewer [value]="value"></ds-markdown-viewer>
10+
} @else {
11+
<div>{{ 'info.empty-cms-metadata-error' | translate }}</div>
12+
}
13+
}
14+
</div>

src/app/info/cms-info/cms-info.component.scss

Whitespace-only changes.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import {
2+
ComponentFixture,
3+
TestBed,
4+
} from '@angular/core/testing';
5+
import { ActivatedRoute } from '@angular/router';
6+
import { TranslateModule } from '@ngx-translate/core';
7+
import { MockComponent } from 'ng-mocks';
8+
import {
9+
Observable,
10+
of,
11+
} from 'rxjs';
12+
import { SiteDataService } from 'src/app/core/data/site-data.service';
13+
import { LocaleService } from 'src/app/core/locale/locale.service';
14+
import { Site } from 'src/app/core/shared/site.model';
15+
16+
import { MarkdownViewerComponent } from '../../shared/markdown-viewer/markdown-viewer.component';
17+
import { CmsInfoComponent } from './cms-info.component';
18+
19+
describe('CmsInfoComponent', () => {
20+
let component: CmsInfoComponent;
21+
let fixture: ComponentFixture<CmsInfoComponent>;
22+
let localeServiceSpy: jasmine.SpyObj<LocaleService>;
23+
let activatedRouteStub: any;
24+
let siteServiceStub: any;
25+
26+
const site: Site = Object.assign(new Site(), {
27+
metadata: {
28+
'dc.rights' : [{
29+
value: 'English text',
30+
language: 'en',
31+
},
32+
{
33+
value: 'German text',
34+
language: 'de',
35+
}],
36+
},
37+
});
38+
39+
beforeEach(async () => {
40+
localeServiceSpy = jasmine.createSpyObj('LocaleService', ['getCurrentLanguageCode']);
41+
localeServiceSpy.getCurrentLanguageCode.and.returnValue(of('en'));
42+
activatedRouteStub = {
43+
data: of({ schema: 'cris', qualifier: 'testQualifier' }),
44+
queryParamMap: of({}),
45+
};
46+
siteServiceStub = {
47+
find(): Observable<Site> {
48+
return of(site);
49+
},
50+
};
51+
await TestBed.configureTestingModule({
52+
imports: [
53+
TranslateModule.forRoot(),
54+
CmsInfoComponent,
55+
MockComponent(MarkdownViewerComponent),
56+
],
57+
providers: [
58+
{ provide: SiteDataService, useValue: siteServiceStub },
59+
{ provide: LocaleService, useValue: localeServiceSpy },
60+
{ provide: ActivatedRoute, useValue: activatedRouteStub },
61+
],
62+
})
63+
.compileComponents();
64+
65+
fixture = TestBed.createComponent(CmsInfoComponent);
66+
component = fixture.componentInstance;
67+
fixture.detectChanges();
68+
});
69+
70+
it('should create', () => {
71+
expect(component).toBeTruthy();
72+
});
73+
74+
it('should set headLabel$ when data is successfully retrieved', () => {
75+
const headLabelSpy = spyOn(component.headLabel$, 'next');
76+
77+
component.ngOnInit();
78+
79+
expect(headLabelSpy).toHaveBeenCalledOnceWith('info.testQualifier.head');
80+
});
81+
82+
it('should log a warning to console if metadata content is missing', () => {
83+
spyOn(console, 'warn');
84+
site.metadata['cris.cms.testQualifier'] = undefined;
85+
86+
component.ngOnInit();
87+
88+
expect(console.warn).toHaveBeenCalledWith('Metadata cris.cms.testQualifier has no content');
89+
});
90+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { AsyncPipe } from '@angular/common';
2+
import {
3+
Component,
4+
OnInit,
5+
} from '@angular/core';
6+
import { ActivatedRoute } from '@angular/router';
7+
import { TranslateModule } from '@ngx-translate/core';
8+
import {
9+
BehaviorSubject,
10+
combineLatest,
11+
} from 'rxjs';
12+
import { take } from 'rxjs/operators';
13+
14+
import { SiteDataService } from '../../core/data/site-data.service';
15+
import { LocaleService } from '../../core/locale/locale.service';
16+
import { hasValue } from '../../shared/empty.util';
17+
import { MarkdownViewerComponent } from '../../shared/markdown-viewer/markdown-viewer.component';
18+
19+
@Component({
20+
selector: 'ds-cms-info',
21+
templateUrl: './cms-info.component.html',
22+
styleUrls: ['./cms-info.component.scss'],
23+
imports: [
24+
AsyncPipe,
25+
MarkdownViewerComponent,
26+
TranslateModule,
27+
],
28+
})
29+
export class CmsInfoComponent implements OnInit {
30+
31+
/**
32+
* The i18n label for the page title
33+
*/
34+
headLabel$ = new BehaviorSubject<string>('');
35+
36+
/**
37+
* The content of the CMS metadata
38+
*/
39+
cmsMetadataValue$ = new BehaviorSubject<string>('');
40+
41+
/**
42+
* True if the metadata content is being loaded
43+
*/
44+
metadataLoaded$ = new BehaviorSubject<boolean>(false);
45+
46+
constructor(
47+
private siteService: SiteDataService,
48+
private locale: LocaleService,
49+
private route: ActivatedRoute,
50+
) {
51+
}
52+
53+
ngOnInit() {
54+
55+
const data$ = this.route.data.pipe(
56+
take(1),
57+
);
58+
59+
const site$ = this.siteService.find().pipe(take(1));
60+
const lang$ = this.locale.getCurrentLanguageCode().pipe(take(1));
61+
62+
combineLatest([data$, site$, lang$]).subscribe(([data, site, lang]) => {
63+
this.headLabel$.next(`info.${data.qualifier}.head`);
64+
const mdValue = site?.firstMetadataValue(`${data.schema}.cms.${data.qualifier}`, { language: lang });
65+
if (hasValue(mdValue)) {
66+
this.cmsMetadataValue$.next(mdValue);
67+
} else {
68+
console.warn(`Metadata ${data.schema}.cms.${data.qualifier} has no content`);
69+
}
70+
this.metadataLoaded$.next(true);
71+
});
72+
73+
}
74+
75+
}

src/app/info/info-routes.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { notifyInfoGuard } from '../core/coar-notify/notify-info/notify-info.gua
99
import { feedbackGuard } from '../core/feedback/feedback.guard';
1010
import { hasValue } from '../shared/empty.util';
1111
import { AccessibilitySettingsComponent } from './accessibility-settings/accessibility-settings.component';
12+
import { CmsInfoComponent } from './cms-info/cms-info.component';
1213
import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end-user-agreement.component';
1314
import { ThemedFeedbackComponent } from './feedback/themed-feedback.component';
1415
import {
@@ -21,6 +22,19 @@ import {
2122
import { NotifyInfoComponent } from './notify-info/notify-info.component';
2223
import { ThemedPrivacyComponent } from './privacy/themed-privacy.component';
2324

25+
function cmsInfoRoute(qualifier: string, schema: string): Route {
26+
return {
27+
path: qualifier,
28+
component: CmsInfoComponent,
29+
resolve: { breadcrumb: i18nBreadcrumbResolver },
30+
data: {
31+
title: `info.${qualifier}.title`,
32+
breadcrumbKey: `info.${qualifier}`,
33+
schema: schema,
34+
qualifier: qualifier,
35+
},
36+
};
37+
}
2438

2539
export const ROUTES: Routes = [
2640
{
@@ -60,4 +74,5 @@ export const ROUTES: Routes = [
6074
breadcrumbKey: 'info.coar-notify-support',
6175
},
6276
} : undefined,
77+
cmsInfoRoute(PRIVACY_PATH, 'cris'),
6378
].filter((route: Route) => hasValue(route));

0 commit comments

Comments
 (0)