Skip to content

Commit 59c88d8

Browse files
Merge branch 'ux-plus-2023_02_x' into UXP-34-carousel-pagination
2 parents f30973c + 57c536b commit 59c88d8

33 files changed

Lines changed: 409 additions & 157 deletions

src/app/core/shared/client-math.service.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
import { Injectable } from '@angular/core';
1+
import { DOCUMENT } from '@angular/common';
2+
import {
3+
Inject,
4+
Injectable,
5+
} from '@angular/core';
26
import { Observable, ReplaySubject, Subject } from 'rxjs';
37
import { environment } from 'src/environments/environment';
4-
import { MathJaxConfig, MathService } from './math.service';
8+
import {
9+
NativeWindowRef,
10+
NativeWindowService,
11+
} from '../services/window.service';import { MathJaxConfig, MathService } from './math.service';
512

613
@Injectable({
714
providedIn: 'root'
815
})
16+
/**
17+
* Provide the MathService for CSR
18+
*/
919
export class ClientMathService extends MathService {
1020

1121
protected isReady$: Subject<boolean>;
@@ -31,7 +41,10 @@ export class ClientMathService extends MathService {
3141
id: 'MathJaxBackupScript'
3242
};
3343

34-
constructor() {
44+
constructor(
45+
@Inject(DOCUMENT) private _document: Document,
46+
@Inject(NativeWindowService) protected _window: NativeWindowRef,
47+
) {
3548
super();
3649

3750
this.isReady$ = new ReplaySubject<boolean>();
@@ -44,36 +57,49 @@ export class ClientMathService extends MathService {
4457
});
4558
}
4659

60+
/**
61+
* Register the specified MathJax script in the document
62+
*
63+
* @param config The configuration object for the script
64+
*/
4765
protected async registerMathJaxAsync(config: MathJaxConfig): Promise<any> {
4866
if (environment.markdown.mathjax) {
4967
return new Promise<void>((resolve, reject) => {
5068

51-
const optionsScript: HTMLScriptElement = document.createElement('script');
69+
const optionsScript: HTMLScriptElement = this._document.createElement('script');
5270
optionsScript.type = 'text/javascript';
5371
optionsScript.text = `MathJax = ${JSON.stringify(this.mathJaxOptions)};`;
54-
document.head.appendChild(optionsScript);
72+
this._document.head.appendChild(optionsScript);
5573

56-
const script: HTMLScriptElement = document.createElement('script');
74+
const script: HTMLScriptElement = this._document.createElement('script');
5775
script.id = config.id;
5876
script.type = 'text/javascript';
5977
script.src = config.source;
6078
script.crossOrigin = 'anonymous';
6179
script.async = true;
6280
script.onload = () => resolve();
6381
script.onerror = error => reject(error);
64-
document.head.appendChild(script);
82+
this._document.head.appendChild(script);
6583
});
6684
}
6785
return Promise.resolve();
6886
}
6987

88+
/**
89+
* Return the status of the script registration
90+
*/
7091
ready(): Observable<boolean> {
7192
return this.isReady$;
7293
}
7394

95+
/**
96+
* Render the specified element using the MathJax JavaScript
97+
*
98+
* @param element The element to render with MathJax
99+
*/
74100
render(element: HTMLElement) {
75101
if (environment.markdown.mathjax) {
76-
(window as any).MathJax.typesetPromise([element]);
102+
this._window.nativeWindow.MathJax.typesetPromise([element]);
77103
}
78104
}
79105
}

src/app/core/shared/math.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export interface MathJaxConfig {
55
id: string;
66
}
77

8+
/**
9+
* This service is used to provide the MathJax library with the ability to render markdown code
10+
*/
811
export abstract class MathService {
912
protected abstract mathJaxOptions: any;
1013
protected abstract mathJax: MathJaxConfig;

src/app/core/shared/server-math.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { MathJaxConfig, MathService } from './math.service';
55
@Injectable({
66
providedIn: 'root'
77
})
8+
/**
9+
* Provide the MathService for SSR
10+
*/
811
export class ServerMathService extends MathService {
912

1013
protected signal: Subject<boolean>;

src/app/cris-layout/enums/layout-box.enum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ export enum LayoutBox {
1616
IIIFTOOLBAR = 'IIIFTOOLBAR',
1717
VIDEOVIEWER = 'VIDEOVIEWER',
1818
COLLECTIONS = 'COLLECTIONS',
19+
VERSIONING = 'VERSIONING',
1920
}

src/app/item-page/item-page.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ import { ThemedItemAlertsComponent } from './alerts/themed-item-alerts.component
6161
import {
6262
ThemedFullFileSectionComponent
6363
} from './full/field-components/file-section/themed-full-file-section.component';
64-
import { UnpaywallVersionsComponent } from './unpaywall-versions/unpaywall-versions.component';
6564
import { MarkdownViewerModule } from '../shared/markdown-viewer/markdown-viewer.module';
65+
import { UnpaywallVersionsComponent } from './unpaywall-versions/unpaywall-versions.component';
6666

6767

6868
const ENTRY_COMPONENTS = [

src/app/item-page/simple/item-page.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
<div
33
[ngClass]="{'container': (itemRD?.hasSucceeded && !itemRD?.hasNoContent) && tabsRD?.payload?.pageInfo?.totalElements < 1}"
44
*ngVar="(itemRD$ | async) as itemRD">
5+
<div class="py-1" [ngClass]="{'container': (itemRD?.hasSucceeded && !itemRD?.hasNoContent) && tabsRD?.payload?.pageInfo?.totalElements > 0}">
6+
<ds-item-versions-notice [item]="itemRD?.payload" ></ds-item-versions-notice>
7+
</div>
58
<div class="item-page" *ngIf="(itemRD?.hasSucceeded && !itemRD?.hasNoContent) && tabsRD?.payload?.pageInfo?.totalElements < 1" @fadeInOut>
69
<div *ngIf="itemRD?.payload as item">
710
<ds-themed-item-alerts [item]="item"></ds-themed-item-alerts>

src/app/item-page/versions/item-versions.component.spec.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Version } from '../../core/shared/version.model';
1010
import { VersionHistory } from '../../core/shared/version-history.model';
1111
import { VersionHistoryDataService } from '../../core/data/version-history-data.service';
1212
import { BrowserModule, By } from '@angular/platform-browser';
13-
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
13+
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
1414
import { createPaginatedList } from '../../shared/testing/utils.test';
1515
import { EMPTY, of, of as observableOf } from 'rxjs';
1616
import { PaginationService } from '../../core/pagination/pagination.service';
@@ -26,7 +26,7 @@ import { FeatureID } from '../../core/data/feature-authorization/feature-id';
2626
import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service';
2727
import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service';
2828
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
29-
import { Router } from '@angular/router';
29+
import { ActivatedRoute, Router } from '@angular/router';
3030
import { CommonModule } from '@angular/common';
3131
import { ItemSharedModule } from '../item-shared.module';
3232
import { UUIDService } from '../../core/shared/uuid.service';
@@ -135,6 +135,25 @@ describe('ItemVersionsComponent', () => {
135135
navigateByUrl: null,
136136
});
137137

138+
const mockItem = Object.assign(new Item(), {
139+
id: 'fake-id',
140+
uuid: 'fake-id',
141+
handle: 'fake/handle',
142+
lastModified: '2018',
143+
_links: {
144+
self: {
145+
href: 'https://localhost:8000/items/fake-id'
146+
}
147+
}
148+
});
149+
150+
const routeStub = {
151+
data: observableOf({
152+
dso: createSuccessfulRemoteDataObject(mockItem)
153+
}),
154+
children: []
155+
};
156+
138157
beforeEach(waitForAsync(() => {
139158

140159
TestBed.configureTestingModule({
@@ -153,7 +172,8 @@ describe('ItemVersionsComponent', () => {
153172
{provide: WorkflowItemDataService, useValue: workflowItemDataServiceSpy},
154173
{provide: ConfigurationDataService, useValue: configurationServiceSpy},
155174
{ provide: Router, useValue: routerSpy },
156-
{ provide: UUIDService, useValue: getMockUUIDService() }
175+
{ provide: UUIDService, useValue: getMockUUIDService() },
176+
{ provide: ActivatedRoute, useValue: routeStub },
157177
],
158178
schemas: [NO_ERRORS_SCHEMA]
159179
}).compileComponents();

src/app/item-page/versions/item-versions.component.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { TranslateService } from '@ngx-translate/core';
4040
import { ItemVersionsDeleteModalComponent } from './item-versions-delete-modal/item-versions-delete-modal.component';
4141
import { VersionDataService } from '../../core/data/version-data.service';
4242
import { ItemDataService } from '../../core/data/item-data.service';
43-
import { Router } from '@angular/router';
43+
import { ActivatedRoute, Router } from '@angular/router';
4444
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
4545
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
4646
import { ItemVersionsSharedService } from './item-versions-shared.service';
@@ -49,7 +49,11 @@ import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-da
4949
import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service';
5050
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
5151
import { UUIDService } from '../../core/shared/uuid.service';
52+
import { RenderCrisLayoutBoxFor } from '../../cris-layout/decorators/cris-layout-box.decorator';
53+
import { LayoutBox } from '../../cris-layout/enums/layout-box.enum';
5254

55+
56+
@RenderCrisLayoutBoxFor(LayoutBox.VERSIONING)
5357
@Component({
5458
selector: 'ds-item-versions',
5559
templateUrl: './item-versions.component.html',
@@ -182,7 +186,8 @@ export class ItemVersionsComponent implements OnDestroy, OnInit {
182186
private workspaceItemDataService: WorkspaceitemDataService,
183187
private workflowItemDataService: WorkflowItemDataService,
184188
private configurationService: ConfigurationDataService,
185-
private uuidService: UUIDService
189+
private uuidService: UUIDService,
190+
private route: ActivatedRoute,
186191
) {
187192
}
188193

@@ -488,6 +493,21 @@ export class ItemVersionsComponent implements OnDestroy, OnInit {
488493
* Initialize all observables
489494
*/
490495
ngOnInit(): void {
496+
if (!hasValue(this.item)) {
497+
this.subs.push(this.route.data.pipe(
498+
map((data) => {
499+
return data.dso as RemoteData<Item>;
500+
}),
501+
getFirstCompletedRemoteData(),
502+
map(data => data.payload)
503+
).subscribe((item) => {
504+
this.item = item;
505+
this.ngOnInit();
506+
}));
507+
508+
return;
509+
}
510+
491511
if (hasValue(this.item.version)) {
492512
this.versionRD$ = this.item.version;
493513
this.versionHistoryRD$ = this.versionRD$.pipe(
Lines changed: 33 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,41 @@
1-
<div *ngIf="!(isLoading$ | async) && itemList?.length > 0">
2-
<ngb-carousel #carousel [interval]="2000" (slide)="onSlide($event)" class="ds-carousel">
3-
<ng-template ngbSlide [id]="'slide_' + i" *ngFor="let item of currentPageItems(); let i = index; let last = last">
4-
<ng-container *ngIf="getItemLink(item.indexableObject); let currentLink; else carouselContent">
5-
<a *ngIf="isLinkInternal(currentLink)" [routerLink]="currentLink">
6-
<ng-container *ngTemplateOutlet="carouselContent"></ng-container>
7-
</a>
8-
<a *ngIf="!isLinkInternal(currentLink)" [href]="currentLink" [target]="carouselOptions.targetBlank ? '_blank' : null">
9-
<ng-container *ngTemplateOutlet="carouselContent"></ng-container>
10-
</a>
11-
</ng-container>
12-
<ng-template #carouselContent>
13-
<div class="carousel-content-wrapper"
14-
[ngStyle]="{
1+
<ngb-carousel #carousel [interval]="2000" (slide)="onSlide($event)" class="ds-carousel">
2+
<ng-template ngbSlide *ngFor="let item of items; let i = index; let last = last">
3+
<ng-container *ngIf="getItemLink(item.indexableObject); let currentLink; else carouselContent">
4+
<a *ngIf="internalLinkService.isLinkInternal(currentLink)" [routerLink]="internalLinkService.getRelativePath(currentLink)">
5+
<ng-container *ngTemplateOutlet="carouselContent"></ng-container>
6+
</a>
7+
<a *ngIf="!internalLinkService.isLinkInternal(currentLink)" [href]="currentLink" [target]="carouselOptions.targetBlank ? '_blank' : null">
8+
<ng-container *ngTemplateOutlet="carouselContent"></ng-container>
9+
</a>
10+
</ng-container>
11+
<ng-template #carouselContent>
12+
<div class="carousel-content-wrapper"
13+
[ngStyle]="{
1514
'height': carouselOptions.keepAspectRatio ? null : carouselOptions.carouselHeightPx + 'px',
1615
'aspect-ratio': carouselOptions.keepAspectRatio ? carouselOptions.aspectRatio : null
1716
}">
18-
<div class="picsum-img-wrapper" *ngIf="(itemToImageHrefMap$ | async).get(item.indexableObject.uuid); let href">
19-
<img [src]="href" [alt]="item.indexableObject.metadata[title][0].value" class="img-fluid"
20-
[ngClass]="{'w-100': carouselOptions.fitWidth, 'h-100': carouselOptions.fitHeight}">
21-
</div>
22-
<div class="carousel-caption">
23-
<div class="carousel-caption-inner">
24-
<h3 data-test="carouselObjTitle" [class]="carouselOptions.titleStyle"
25-
*ngIf="item.indexableObject.metadata[title]">
26-
{{item.indexableObject.metadata[title][0].value}}</h3>
27-
<div data-test="carouselObjDesc" class="carousel-caption-text pr-3 pl-2" [class]="carouselOptions.captionStyle"
28-
*ngIf="item.indexableObject.metadata[description]; let descriptionObj">
29-
{{descriptionObj[0].value}}
30-
</div>
17+
<div class="picsum-img-wrapper" *ngIf="(itemToImageHrefMap$ | async).get(item.indexableObject.uuid); let href">
18+
<img [src]="href" [alt]="item.indexableObject.metadata[title][0].value" class="img-fluid"
19+
[ngClass]="{'w-100': carouselOptions.fitWidth, 'h-100': carouselOptions.fitHeight}">
20+
</div>
21+
<div class="carousel-caption">
22+
<div class="carousel-caption-inner">
23+
<h3 data-test="carouselObjTitle" [class]="carouselOptions.titleStyle"
24+
*ngIf="item.indexableObject.metadata[title]">
25+
{{item.indexableObject.metadata[title][0].value}}</h3>
26+
<div data-test="carouselObjDesc" class="carousel-caption-text pr-3 pl-2" [class]="carouselOptions.captionStyle"
27+
*ngIf="item.indexableObject.metadata[description]; let descriptionObj">
28+
{{descriptionObj[0].value}}
3129
</div>
3230
</div>
3331
</div>
34-
</ng-template>
32+
</div>
3533
</ng-template>
36-
</ngb-carousel>
37-
<div class="text-center play-pause-button">
38-
<button type="button" class="btn btn-sm toggle-paused" (click)="togglePaused()">
39-
<i class="fas fa-play" *ngIf="paused"></i>
40-
<i class="fas fa-pause" *ngIf="!paused"></i>
41-
</button>
42-
</div>
43-
<div class="mt-4 w-100 d-flex justify-content-center align-items-center" *ngIf="totalPages > 1">
44-
<button (click)="previousPage()" [disabled]="currentPage === 1" class="prev border-0 bg-transparent">
45-
<i class="fa fa-arrow-left"></i>
46-
</button>
47-
<button
48-
*ngFor="let page of pages()"
49-
class="number"
50-
(click)="changePage(page)"
51-
style="border: none; background: none; margin: 0 5px"
52-
[style.color]="page === currentPage ? '#000000' : '#7c7c7c'">
53-
{{ page < 10 ? '0' + page : page }}
54-
</button>
55-
<button (click)="nextPage()" [disabled]="currentPage === pages().length" class="next border-0 bg-transparent">
56-
<i class="fa fa-arrow-right"></i>
57-
</button>
58-
</div>
59-
</div>
60-
61-
62-
<div
63-
class="carousel-content-wrapper"
64-
[ngStyle]="{
65-
'height': carouselOptions.keepAspectRatio ? null : carouselOptions.carouselHeightPx + 'px',
66-
'aspect-ratio': carouselOptions.keepAspectRatio ? carouselOptions.aspectRatio : null
67-
}"
68-
*ngIf="(isLoading$ | async)"
69-
>
70-
<a
71-
href="#"
72-
target="_blank"
73-
class="img-container-el">
74-
<div class="picsum-img-wrapper flex-column">
75-
<img class="img-fluid" src="assets/images/replacement_image.svg">
76-
{{'loading.default' | translate}}
77-
</div>
78-
</a>
34+
</ng-template>
35+
</ngb-carousel>
36+
<div class="text-center play-pause-button">
37+
<button type="button" class="btn btn-sm toggle-paused" (click)="togglePaused()">
38+
<i class="fas fa-play" *ngIf="paused"></i>
39+
<i class="fas fa-pause" *ngIf="!paused"></i>
40+
</button>
7941
</div>

src/app/shared/explore/explore.module.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ import { ThemedSearchSectionComponent } from './section-component/search-section
2020
import { TextSectionComponent } from './section-component/text-section/text-section.component';
2121
import { ThemedTextSectionComponent } from './section-component/text-section/themed-text-section.component';
2222
import { SharedModule } from '../shared.module';
23+
import { MarkdownViewerModule } from '../markdown-viewer/markdown-viewer.module';
2324
import { CarouselSectionComponent } from './section-component/carousel-section/carousel-section.component';
2425
import { ThemedCarouselSectionComponent } from './section-component/carousel-section/themed-carousel-section.component';
2526
import { CarouselModule } from '../carousel/carousel.module';
26-
import { MarkdownViewerModule } from '../markdown-viewer/markdown-viewer.module';
2727
import { GridSectionComponent } from './section-component/grid-section/grid-section.component';
2828
import { ThemedGridSectionComponent } from './section-component/grid-section/themed-grid-section.component';
2929
import { TwitterSectionComponent } from './section-component/twitter-section/twitter-section.component';
@@ -56,12 +56,12 @@ const COMPONENTS = [
5656
declarations: [
5757
...COMPONENTS
5858
],
59-
imports: [
60-
CommonModule,
61-
SharedModule,
62-
CarouselModule,
63-
MarkdownViewerModule
64-
],
59+
imports: [
60+
CommonModule,
61+
SharedModule,
62+
MarkdownViewerModule,
63+
CarouselModule,
64+
],
6565
exports: [
6666
...COMPONENTS
6767
]

0 commit comments

Comments
 (0)