Merge remote-tracking branch 'upstream/main' into media-viewer-thumbnail-width_contribute-main

# Conflicts:
#	src/app/item-page/simple/item-types/publication/publication.component.html
#	src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html
This commit is contained in:
Alexandre Vryghem
2023-03-24 00:18:33 +01:00
51 changed files with 6027 additions and 2165 deletions

View File

@@ -198,7 +198,7 @@
"sass-resources-loader": "^2.1.1", "sass-resources-loader": "^2.1.1",
"ts-node": "^8.10.2", "ts-node": "^8.10.2",
"typescript": "~4.5.5", "typescript": "~4.5.5",
"webpack": "^5.69.1", "webpack": "^5.76.0",
"webpack-bundle-analyzer": "^4.4.0", "webpack-bundle-analyzer": "^4.4.0",
"webpack-cli": "^4.2.0", "webpack-cli": "^4.2.0",
"webpack-dev-server": "^4.5.0" "webpack-dev-server": "^4.5.0"

View File

@@ -13,12 +13,13 @@
[formGroup]="formGroup" [formGroup]="formGroup"
[formLayout]="formLayout" [formLayout]="formLayout"
[displayCancel]="false" [displayCancel]="false"
[submitLabel]="submitLabel"
(submitForm)="onSubmit()"> (submitForm)="onSubmit()">
<div before class="btn-group"> <div before class="btn-group">
<button (click)="onCancel()" <button (click)="onCancel()"
class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}</button> class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}</button>
</div> </div>
<div between class="btn-group"> <div *ngIf="displayResetPassword" between class="btn-group">
<button class="btn btn-primary" [disabled]="!(canReset$ | async)" (click)="resetPassword()"> <button class="btn btn-primary" [disabled]="!(canReset$ | async)" (click)="resetPassword()">
<i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}} <i class="fa fa-key"></i> {{'admin.access-control.epeople.actions.reset' | translate}}
</button> </button>

View File

@@ -165,6 +165,15 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
*/ */
isImpersonated = false; isImpersonated = false;
/**
* A boolean that indicate if to display EPersonForm's Rest password button
*/
displayResetPassword = false;
/**
* A string that indicate the label of Submit button
*/
submitLabel = 'form.create';
/** /**
* Subscription to email field value change * Subscription to email field value change
*/ */
@@ -188,6 +197,8 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
this.epersonInitial = eperson; this.epersonInitial = eperson;
if (hasValue(eperson)) { if (hasValue(eperson)) {
this.isImpersonated = this.authService.isImpersonatingUser(eperson.id); this.isImpersonated = this.authService.isImpersonatingUser(eperson.id);
this.displayResetPassword = true;
this.submitLabel = 'form.submit';
} }
})); }));
} }

View File

@@ -218,7 +218,8 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone
{ {
path: 'statistics', path: 'statistics',
loadChildren: () => import('./statistics-page/statistics-page-routing.module') loadChildren: () => import('./statistics-page/statistics-page-routing.module')
.then((m) => m.StatisticsPageRoutingModule) .then((m) => m.StatisticsPageRoutingModule),
canActivate: [EndUserAgreementCurrentUserGuard],
}, },
{ {
path: HEALTH_PAGE_PATH, path: HEALTH_PAGE_PATH,
@@ -228,7 +229,7 @@ import { ThemedPageErrorComponent } from './page-error/themed-page-error.compone
{ {
path: ACCESS_CONTROL_MODULE_PATH, path: ACCESS_CONTROL_MODULE_PATH,
loadChildren: () => import('./access-control/access-control.module').then((m) => m.AccessControlModule), loadChildren: () => import('./access-control/access-control.module').then((m) => m.AccessControlModule),
canActivate: [GroupAdministratorGuard], canActivate: [GroupAdministratorGuard, EndUserAgreementCurrentUserGuard],
}, },
{ {
path: 'subscriptions', path: 'subscriptions',

View File

@@ -151,8 +151,15 @@ export class BrowseByMetadataPageComponent implements OnInit, OnDestroy {
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => { ).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
this.browseId = params.id || this.defaultBrowseId; this.browseId = params.id || this.defaultBrowseId;
this.authority = params.authority; this.authority = params.authority;
this.value = +params.value || params.value || '';
this.startsWith = +params.startsWith || params.startsWith; if (typeof params.value === 'string'){
this.value = params.value.trim();
}
if (typeof params.startsWith === 'string'){
this.startsWith = params.startsWith.trim();
}
if (isNotEmpty(this.value)) { if (isNotEmpty(this.value)) {
this.updatePageWithItems( this.updatePageWithItems(
browseParamsToOptions(params, currentPage, currentSort, this.browseId, this.fetchThumbnails), this.value, this.authority); browseParamsToOptions(params, currentPage, currentSort, this.browseId, this.fetchThumbnails), this.value, this.authority);
@@ -305,7 +312,7 @@ export function browseParamsToOptions(params: any,
metadata, metadata,
paginationConfig, paginationConfig,
sortConfig, sortConfig,
+params.startsWith || params.startsWith, params.startsWith,
params.scope, params.scope,
fetchThumbnail fetchThumbnail
); );

View File

@@ -62,25 +62,33 @@ describe('LocaleService test suite', () => {
}); });
describe('getCurrentLanguageCode', () => { describe('getCurrentLanguageCode', () => {
it('should return language saved on cookie', () => { beforeEach(() => {
spyOn(translateService, 'getLangs').and.returnValue(langList);
});
it('should return the language saved on cookie if it\'s a valid & active language', () => {
spyOnGet.and.returnValue('de'); spyOnGet.and.returnValue('de');
expect(service.getCurrentLanguageCode()).toBe('de'); expect(service.getCurrentLanguageCode()).toBe('de');
}); });
describe('', () => { it('should return the default language if the cookie language is disabled', () => {
beforeEach(() => { spyOnGet.and.returnValue('disabled');
spyOn(translateService, 'getLangs').and.returnValue(langList); expect(service.getCurrentLanguageCode()).toBe('en');
}); });
it('should return language from browser setting', () => { it('should return the default language if the cookie language does not exist', () => {
spyOn(translateService, 'getBrowserLang').and.returnValue('it'); spyOnGet.and.returnValue('does-not-exist');
expect(service.getCurrentLanguageCode()).toBe('it'); expect(service.getCurrentLanguageCode()).toBe('en');
}); });
it('should return default language from config', () => { it('should return language from browser setting', () => {
spyOn(translateService, 'getBrowserLang').and.returnValue('fr'); spyOn(translateService, 'getBrowserLang').and.returnValue('it');
expect(service.getCurrentLanguageCode()).toBe('en'); expect(service.getCurrentLanguageCode()).toBe('it');
}); });
it('should return default language from config', () => {
spyOn(translateService, 'getBrowserLang').and.returnValue('fr');
expect(service.getCurrentLanguageCode()).toBe('en');
}); });
}); });

View File

@@ -11,6 +11,7 @@ import { map, mergeMap, take } from 'rxjs/operators';
import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { NativeWindowRef, NativeWindowService } from '../services/window.service';
import { RouteService } from '../services/route.service'; import { RouteService } from '../services/route.service';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { LangConfig } from '../../../config/lang-config.interface';
export const LANG_COOKIE = 'dsLanguage'; export const LANG_COOKIE = 'dsLanguage';
@@ -52,8 +53,7 @@ export class LocaleService {
getCurrentLanguageCode(): string { getCurrentLanguageCode(): string {
// Attempt to get the language from a cookie // Attempt to get the language from a cookie
let lang = this.getLanguageCodeFromCookie(); let lang = this.getLanguageCodeFromCookie();
if (isEmpty(lang)) { if (isEmpty(lang) || environment.languages.find((langConfig: LangConfig) => langConfig.code === lang && langConfig.active) === undefined) {
// Cookie not found
// Attempt to get the browser language from the user // Attempt to get the browser language from the user
if (this.translate.getLangs().includes(this.translate.getBrowserLang())) { if (this.translate.getLangs().includes(this.translate.getBrowserLang())) {
lang = this.translate.getBrowserLang(); lang = this.translate.getBrowserLang();

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field class="mr-auto" [item]="object"> <ds-themed-item-page-title-field class="mr-auto" [item]="object">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -1,7 +1,7 @@
<ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button> <ds-themed-results-back-button *ngIf="showBackButton | async" [back]="back"></ds-themed-results-back-button>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">

View File

@@ -0,0 +1,27 @@
import { Component } from '@angular/core';
import { ThemedComponent } from '../../../shared/theme-support/themed.component';
import { FeedbackFormComponent } from './feedback-form.component';
/**
* Themed wrapper for {@link FeedbackFormComponent}
*/
@Component({
selector: 'ds-themed-feedback-form',
styleUrls: [],
templateUrl: '../../../shared/theme-support/themed.component.html',
})
export class ThemedFeedbackFormComponent extends ThemedComponent<FeedbackFormComponent> {
protected getComponentName(): string {
return 'FeedbackFormComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../../themes/${themeName}/app/info/feedback/feedback-form/feedback-form.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./feedback-form.component');
}
}

View File

@@ -1,3 +1,3 @@
<div class="container"> <div class="container">
<ds-feedback-form></ds-feedback-form> <ds-themed-feedback-form></ds-themed-feedback-form>
</div> </div>

View File

@@ -10,6 +10,7 @@ import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end
import { ThemedPrivacyComponent } from './privacy/themed-privacy.component'; import { ThemedPrivacyComponent } from './privacy/themed-privacy.component';
import { FeedbackComponent } from './feedback/feedback.component'; import { FeedbackComponent } from './feedback/feedback.component';
import { FeedbackFormComponent } from './feedback/feedback-form/feedback-form.component'; import { FeedbackFormComponent } from './feedback/feedback-form/feedback-form.component';
import { ThemedFeedbackFormComponent } from './feedback/feedback-form/themed-feedback-form.component';
import { ThemedFeedbackComponent } from './feedback/themed-feedback.component'; import { ThemedFeedbackComponent } from './feedback/themed-feedback.component';
import { FeedbackGuard } from '../core/feedback/feedback.guard'; import { FeedbackGuard } from '../core/feedback/feedback.guard';
@@ -23,6 +24,7 @@ const DECLARATIONS = [
ThemedPrivacyComponent, ThemedPrivacyComponent,
FeedbackComponent, FeedbackComponent,
FeedbackFormComponent, FeedbackFormComponent,
ThemedFeedbackFormComponent,
ThemedFeedbackComponent ThemedFeedbackComponent
]; ];

View File

@@ -6,9 +6,8 @@
<ds-view-tracker [object]="item"></ds-view-tracker> <ds-view-tracker [object]="item"></ds-view-tracker>
<div *ngIf="!item.isWithdrawn || (isAdmin$|async)" class="full-item-info"> <div *ngIf="!item.isWithdrawn || (isAdmin$|async)" class="full-item-info">
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field class="mr-auto" [item]="item"></ds-item-page-title-field> <ds-themed-item-page-title-field class="mr-auto" [item]="item"></ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="simple-view-link my-3" *ngIf="!fromSubmissionObject"> <div class="simple-view-link my-3" *ngIf="!fromSubmissionObject">
<a class="btn btn-outline-primary" [routerLink]="[(itemPageRoute$ | async)]"> <a class="btn btn-outline-primary" [routerLink]="[(itemPageRoute$ | async)]">

View File

@@ -34,8 +34,11 @@ import { ResearchEntitiesModule } from '../entity-groups/research-entities/resea
import { ThemedItemPageComponent } from './simple/themed-item-page.component'; import { ThemedItemPageComponent } from './simple/themed-item-page.component';
import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component'; import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component';
import { MediaViewerComponent } from './media-viewer/media-viewer.component'; import { MediaViewerComponent } from './media-viewer/media-viewer.component';
import { ThemedMediaViewerComponent } from './media-viewer/themed-media-viewer.component';
import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component'; import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component';
import { ThemedMediaViewerVideoComponent } from './media-viewer/media-viewer-video/themed-media-viewer-video.component';
import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component'; import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component';
import { ThemedMediaViewerImageComponent } from './media-viewer/media-viewer-image/themed-media-viewer-image.component';
import { NgxGalleryModule } from '@kolkov/ngx-gallery'; import { NgxGalleryModule } from '@kolkov/ngx-gallery';
import { MiradorViewerComponent } from './mirador-viewer/mirador-viewer.component'; import { MiradorViewerComponent } from './mirador-viewer/mirador-viewer.component';
import { VersionPageComponent } from './version-page/version-page/version-page.component'; import { VersionPageComponent } from './version-page/version-page/version-page.component';
@@ -58,7 +61,6 @@ import {
ThemedFullFileSectionComponent ThemedFullFileSectionComponent
} from './full/field-components/file-section/themed-full-file-section.component'; } from './full/field-components/file-section/themed-full-file-section.component';
const ENTRY_COMPONENTS = [ const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator // put only entry components that use custom decorator
PublicationComponent, PublicationComponent,
@@ -87,8 +89,11 @@ const DECLARATIONS = [
UploadBitstreamComponent, UploadBitstreamComponent,
AbstractIncrementalListComponent, AbstractIncrementalListComponent,
MediaViewerComponent, MediaViewerComponent,
ThemedMediaViewerComponent,
MediaViewerVideoComponent, MediaViewerVideoComponent,
ThemedMediaViewerVideoComponent,
MediaViewerImageComponent, MediaViewerImageComponent,
ThemedMediaViewerImageComponent,
MiradorViewerComponent, MiradorViewerComponent,
VersionPageComponent, VersionPageComponent,
OrcidPageComponent, OrcidPageComponent,

View File

@@ -18,7 +18,7 @@ export class MediaViewerImageComponent implements OnInit {
@Input() preview?: boolean; @Input() preview?: boolean;
@Input() image?: string; @Input() image?: string;
loggedin: boolean; thumbnailPlaceholder = './assets/images/replacement_image.svg';
galleryOptions: NgxGalleryOptions[]; galleryOptions: NgxGalleryOptions[];
galleryImages: NgxGalleryImage[]; galleryImages: NgxGalleryImage[];
@@ -28,7 +28,10 @@ export class MediaViewerImageComponent implements OnInit {
*/ */
isAuthenticated$: Observable<boolean>; isAuthenticated$: Observable<boolean>;
constructor(private authService: AuthService) {} constructor(
protected authService: AuthService,
) {
}
/** /**
* Thi method sets up the gallery settings and data * Thi method sets up the gallery settings and data
@@ -69,20 +72,20 @@ export class MediaViewerImageComponent implements OnInit {
* @param medias input NgxGalleryImage array * @param medias input NgxGalleryImage array
*/ */
convertToGalleryImage(medias: MediaViewerItem[]): NgxGalleryImage[] { convertToGalleryImage(medias: MediaViewerItem[]): NgxGalleryImage[] {
const mappadImages = []; const mappedImages = [];
for (const image of medias) { for (const image of medias) {
if (image.format === 'image') { if (image.format === 'image') {
mappadImages.push({ mappedImages.push({
small: image.thumbnail small: image.thumbnail
? image.thumbnail ? image.thumbnail
: './assets/images/replacement_image.svg', : this.thumbnailPlaceholder,
medium: image.thumbnail medium: image.thumbnail
? image.thumbnail ? image.thumbnail
: './assets/images/replacement_image.svg', : this.thumbnailPlaceholder,
big: image.bitstream._links.content.href, big: image.bitstream._links.content.href,
}); });
} }
} }
return mappadImages; return mappedImages;
} }
} }

View File

@@ -0,0 +1,38 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../../../shared/theme-support/themed.component';
import { MediaViewerImageComponent } from './media-viewer-image.component';
import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
/**
* Themed wrapper for {@link MediaViewerImageComponent}.
*/
@Component({
selector: 'ds-themed-media-viewer-image',
styleUrls: [],
templateUrl: '../../../shared/theme-support/themed.component.html',
})
export class ThemedMediaViewerImageComponent extends ThemedComponent<MediaViewerImageComponent> {
@Input() images: MediaViewerItem[];
@Input() preview?: boolean;
@Input() image?: string;
protected inAndOutputNames: (keyof MediaViewerImageComponent & keyof this)[] = [
'images',
'preview',
'image',
];
protected getComponentName(): string {
return 'MediaViewerImageComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../../themes/${themeName}/app/item-page/media-viewer/media-viewer-image/media-viewer-image.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./media-viewer-image.component');
}
}

View File

@@ -4,7 +4,7 @@ import { languageHelper } from './language-helper';
import { CaptionInfo} from './caption-info'; import { CaptionInfo} from './caption-info';
/** /**
* This componenet renders a video viewer and playlist for the media viewer * This component renders a video viewer and playlist for the media viewer
*/ */
@Component({ @Component({
selector: 'ds-media-viewer-video', selector: 'ds-media-viewer-video',
@@ -24,8 +24,6 @@ export class MediaViewerVideoComponent implements OnInit {
audio: './assets/images/replacement_audio.svg', audio: './assets/images/replacement_audio.svg',
}; };
replacementThumbnail: string;
ngOnInit() { ngOnInit() {
this.isCollapsed = false; this.isCollapsed = false;
this.filteredMedias = this.medias.filter((media) => media.format === 'audio' || media.format === 'video'); this.filteredMedias = this.medias.filter((media) => media.format === 'audio' || media.format === 'video');

View File

@@ -0,0 +1,34 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../../../shared/theme-support/themed.component';
import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
import { MediaViewerVideoComponent } from './media-viewer-video.component';
/**
* Themed wrapper for {@link MediaViewerVideoComponent}.
*/
@Component({
selector: 'ds-themed-media-viewer-video',
styleUrls: [],
templateUrl: '../../../shared/theme-support/themed.component.html',
})
export class ThemedMediaViewerVideoComponent extends ThemedComponent<MediaViewerVideoComponent> {
@Input() medias: MediaViewerItem[];
protected inAndOutputNames: (keyof MediaViewerVideoComponent & keyof this)[] = [
'medias',
];
protected getComponentName(): string {
return 'MediaViewerVideoComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../../themes/${themeName}/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./media-viewer-video.component');
}
}

View File

@@ -12,11 +12,11 @@
mediaList[0]?.format === 'video' || mediaList[0]?.format === 'audio' mediaList[0]?.format === 'video' || mediaList[0]?.format === 'audio'
" "
> >
<ds-media-viewer-video [medias]="mediaList"></ds-media-viewer-video> <ds-themed-media-viewer-video [medias]="mediaList"></ds-themed-media-viewer-video>
</ng-container> </ng-container>
</ng-container> </ng-container>
<ng-container *ngIf="mediaList[0]?.format === 'image'"> <ng-container *ngIf="mediaList[0]?.format === 'image'">
<ds-media-viewer-image [images]="mediaList"></ds-media-viewer-image> <ds-themed-media-viewer-image [images]="mediaList"></ds-themed-media-viewer-image>
</ng-container> </ng-container>
</ng-container> </ng-container>
<ng-container <ng-container
@@ -27,10 +27,10 @@
mediaList.length === 0 mediaList.length === 0
" "
> >
<ds-media-viewer-image <ds-themed-media-viewer-image
[image]="mediaList[0]?.thumbnail || thumbnailPlaceholder" [image]="mediaList[0]?.thumbnail || thumbnailPlaceholder"
[preview]="false" [preview]="false"
></ds-media-viewer-image> ></ds-themed-media-viewer-image>
</ng-container> </ng-container>
</div> </div>
</ng-container> </ng-container>

View File

@@ -135,7 +135,7 @@ describe('MediaViewerComponent', () => {
it('should display a default, thumbnail', () => { it('should display a default, thumbnail', () => {
const defaultThumbnail = fixture.debugElement.query( const defaultThumbnail = fixture.debugElement.query(
By.css('ds-media-viewer-image') By.css('ds-themed-media-viewer-image')
); );
expect(defaultThumbnail.nativeElement).toBeDefined(); expect(defaultThumbnail.nativeElement).toBeDefined();
}); });

View File

@@ -13,9 +13,8 @@ import { hasValue } from '../../shared/empty.util';
import { followLink } from '../../shared/utils/follow-link-config.model'; import { followLink } from '../../shared/utils/follow-link-config.model';
/** /**
* This componenet renders the media viewers * This component renders the media viewers
*/ */
@Component({ @Component({
selector: 'ds-media-viewer', selector: 'ds-media-viewer',
templateUrl: './media-viewer.component.html', templateUrl: './media-viewer.component.html',

View File

@@ -0,0 +1,36 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { MediaViewerComponent } from './media-viewer.component';
import { Item } from '../../core/shared/item.model';
/**
* Themed wrapper for {@link MediaViewerComponent}.
*/
@Component({
selector: 'ds-themed-media-viewer',
styleUrls: [],
templateUrl: '../../shared/theme-support/themed.component.html',
})
export class ThemedMediaViewerComponent extends ThemedComponent<MediaViewerComponent> {
@Input() item: Item;
@Input() videoOptions: boolean;
protected inAndOutputNames: (keyof MediaViewerComponent & keyof this)[] = [
'item',
'videoOptions',
];
protected getComponentName(): string {
return 'MediaViewerComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/item-page/media-viewer/media-viewer.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./media-viewer.component');
}
}

View File

@@ -0,0 +1,33 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../../../../../shared/theme-support/themed.component';
import { ItemPageTitleFieldComponent } from './item-page-title-field.component';
import { Item } from '../../../../../core/shared/item.model';
/**
* Themed wrapper for {@link ItemPageTitleFieldComponent}
*/
@Component({
selector: 'ds-themed-item-page-title-field',
styleUrls: [],
templateUrl: '../../../../../shared/theme-support/themed.component.html',
})
export class ThemedItemPageTitleFieldComponent extends ThemedComponent<ItemPageTitleFieldComponent> {
protected inAndOutputNames: (keyof ItemPageTitleFieldComponent & keyof this)[] = [
'item',
];
@Input() item: Item;
protected getComponentName(): string {
return 'ItemPageTitleFieldComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../../../../themes/${themeName}/app/item-page/simple/field-components/specific-field/title/item-page-title-field.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./item-page-title-field.component');
}
}

View File

@@ -9,9 +9,9 @@
</div> </div>
</div> </div>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-4"> <div class="col-xs-12 col-md-4">
@@ -21,7 +21,7 @@
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>
</ng-container> </ng-container>
<div *ngIf="mediaViewer.image" class="mb-2"> <div *ngIf="mediaViewer.image" class="mb-2">
<ds-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-media-viewer> <ds-themed-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-themed-media-viewer>
</div> </div>
<ds-themed-item-page-file-section [item]="object"></ds-themed-item-page-file-section> <ds-themed-item-page-file-section [item]="object"></ds-themed-item-page-file-section>
<ds-item-page-date-field [item]="object"></ds-item-page-date-field> <ds-item-page-date-field [item]="object"></ds-item-page-date-field>

View File

@@ -10,8 +10,8 @@
</div> </div>
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<ds-item-page-title-field [item]="object" class="mr-auto"> <ds-themed-item-page-title-field [item]="object" class="mr-auto">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<ds-dso-edit-menu></ds-dso-edit-menu> <ds-dso-edit-menu></ds-dso-edit-menu>
</div> </div>
<div class="row"> <div class="row">
@@ -22,7 +22,7 @@
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>
</ng-container> </ng-container>
<div *ngIf="mediaViewer.image" class="mb-2"> <div *ngIf="mediaViewer.image" class="mb-2">
<ds-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-media-viewer> <ds-themed-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-themed-media-viewer>
</div> </div>
<ds-themed-item-page-file-section [item]="object"></ds-themed-item-page-file-section> <ds-themed-item-page-file-section [item]="object"></ds-themed-item-page-file-section>
<ds-item-page-date-field [item]="object"></ds-item-page-date-field> <ds-item-page-date-field [item]="object"></ds-item-page-date-field>

View File

@@ -3,8 +3,8 @@
<ds-mydspace-item-status [status]="status"></ds-mydspace-item-status> <ds-mydspace-item-status [status]="status"></ds-mydspace-item-status>
</ng-container> </ng-container>
<div *ngIf="item"> <div *ngIf="item">
<ds-item-page-title-field [item]="item"> <ds-themed-item-page-title-field [item]="item">
</ds-item-page-title-field> </ds-themed-item-page-title-field>
<div class="row mb-1"> <div class="row mb-1">
<div class="col-xs-12 col-md-4"> <div class="col-xs-12 col-md-4">
<ds-metadata-field-wrapper [hideIfNoTextContent]="false"> <ds-metadata-field-wrapper [hideIfNoTextContent]="false">

View File

@@ -32,7 +32,7 @@ import { RemoteData } from '../../core/data/remote-data';
}) })
export class RSSComponent implements OnInit, OnDestroy { export class RSSComponent implements OnInit, OnDestroy {
route$: BehaviorSubject<string>; route$: BehaviorSubject<string> = new BehaviorSubject<string>('');
isEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null); isEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
@@ -99,7 +99,7 @@ export class RSSComponent implements OnInit, OnDestroy {
rel: 'search', rel: 'search',
title: 'Dspace' title: 'Dspace'
}); });
this.route$ = new BehaviorSubject<string>(route); this.route$.next(route);
})); }));
} }

View File

@@ -268,6 +268,9 @@ import {
import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-list.component'; import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-list.component';
import { EpersonSearchBoxComponent } from './eperson-group-list/eperson-search-box/eperson-search-box.component'; import { EpersonSearchBoxComponent } from './eperson-group-list/eperson-search-box/eperson-search-box.component';
import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/group-search-box.component'; import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/group-search-box.component';
import {
ThemedItemPageTitleFieldComponent
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
const MODULES = [ const MODULES = [
CommonModule, CommonModule,
@@ -373,7 +376,8 @@ const COMPONENTS = [
ContextHelpWrapperComponent, ContextHelpWrapperComponent,
EpersonGroupListComponent, EpersonGroupListComponent,
EpersonSearchBoxComponent, EpersonSearchBoxComponent,
GroupSearchBoxComponent GroupSearchBoxComponent,
ThemedItemPageTitleFieldComponent,
]; ];
const ENTRY_COMPONENTS = [ const ENTRY_COMPONENTS = [

View File

@@ -1751,6 +1751,8 @@
"form.submit": "Save", "form.submit": "Save",
"form.create": "Create",
"form.repeatable.sort.tip": "Drop the item in the new position", "form.repeatable.sort.tip": "Drop the item in the new position",

File diff suppressed because it is too large Load Diff

View File

@@ -209,6 +209,10 @@ export const environment: BuildConfig = {
code: 'el', code: 'el',
label: 'Ελληνικά', label: 'Ελληνικά',
active: true, active: true,
}, {
code: 'disabled',
label: 'Disabled',
active: false,
}], }],
// Browse-By Pages // Browse-By Pages

View File

@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import {
FeedbackFormComponent as BaseComponent
} from '../../../../../../app/info/feedback/feedback-form/feedback-form.component';
@Component({
selector: 'ds-feedback-form',
// templateUrl: './feedback-form.component.html',
templateUrl: '../../../../../../app/info/feedback/feedback-form/feedback-form.component.html',
// styleUrls: ['./feedback-form.component.scss'],
styleUrls: ['../../../../../../app/info/feedback/feedback-form/feedback-form.component.scss'],
})
export class FeedbackFormComponent extends BaseComponent {
}

View File

@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import {
MediaViewerImageComponent as BaseComponent
} from '../../../../../../app/item-page/media-viewer/media-viewer-image/media-viewer-image.component';
@Component({
selector: 'ds-media-viewer-image',
// templateUrl: './media-viewer-image.component.html',
templateUrl: '../../../../../../app/item-page/media-viewer/media-viewer-image/media-viewer-image.component.html',
// styleUrls: ['./media-viewer-image.component.scss'],
styleUrls: ['../../../../../../app/item-page/media-viewer/media-viewer-image/media-viewer-image.component.scss'],
})
export class MediaViewerImageComponent extends BaseComponent {
}

View File

@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import {
MediaViewerVideoComponent as BaseComponent
} from '../../../../../../app/item-page/media-viewer/media-viewer-video/media-viewer-video.component';
@Component({
selector: 'ds-media-viewer-video',
// templateUrl: './media-viewer-video.component.html',
templateUrl: '../../../../../../app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html',
// styleUrls: ['./media-viewer-video.component.scss'],
styleUrls: ['../../../../../../app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.scss'],
})
export class MediaViewerVideoComponent extends BaseComponent {
}

View File

@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import {
MediaViewerComponent as BaseComponent
} from '../../../../../app/item-page/media-viewer/media-viewer.component';
@Component({
selector: 'ds-media-viewer',
// templateUrl: './media-viewer.component.html',
templateUrl: '../../../../../app/item-page/media-viewer/media-viewer.component.html',
// styleUrls: ['./media-viewer.component.scss'],
styleUrls: ['../../../../../app/item-page/media-viewer/media-viewer.component.scss'],
})
export class MediaViewerComponent extends BaseComponent {
}

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
import {
ItemPageTitleFieldComponent as BaseComponent
} from '../../../../../../../../app/item-page/simple/field-components/specific-field/title/item-page-title-field.component';
@Component({
selector: 'ds-item-page-title-field',
// templateUrl: './item-page-title-field.component.html',
templateUrl: '../../../../../../../../app/item-page/simple/field-components/specific-field/title/item-page-title-field.component.html',
})
export class ItemPageTitleFieldComponent extends BaseComponent {
}

View File

@@ -133,6 +133,18 @@ import {
import { MetadataRepresentationListComponent } from './app/item-page/simple/metadata-representation-list/metadata-representation-list.component'; import { MetadataRepresentationListComponent } from './app/item-page/simple/metadata-representation-list/metadata-representation-list.component';
import { DsDynamicLookupRelationSearchTabComponent } from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component'; import { DsDynamicLookupRelationSearchTabComponent } from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component';
import { DsDynamicLookupRelationExternalSourceTabComponent } from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component'; import { DsDynamicLookupRelationExternalSourceTabComponent } from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component';
import { FeedbackFormComponent } from './app/info/feedback/feedback-form/feedback-form.component';
import {
ItemPageTitleFieldComponent
} from './app/item-page/simple/field-components/specific-field/title/item-page-title-field.component';
import { MediaViewerComponent } from './app/item-page/media-viewer/media-viewer.component';
import {
MediaViewerImageComponent
} from './app/item-page/media-viewer/media-viewer-image/media-viewer-image.component';
import {
MediaViewerVideoComponent
} from './app/item-page/media-viewer/media-viewer-video/media-viewer-video.component';
import { NgxGalleryModule } from '@kolkov/ngx-gallery';
const DECLARATIONS = [ const DECLARATIONS = [
FileSectionComponent, FileSectionComponent,
@@ -173,6 +185,7 @@ const DECLARATIONS = [
WorkflowItemSendBackComponent, WorkflowItemSendBackComponent,
BreadcrumbsComponent, BreadcrumbsComponent,
FeedbackComponent, FeedbackComponent,
FeedbackFormComponent,
CommunityListComponent, CommunityListComponent,
ComcolPageHandleComponent, ComcolPageHandleComponent,
AuthNavMenuComponent, AuthNavMenuComponent,
@@ -195,6 +208,10 @@ const DECLARATIONS = [
MetadataRepresentationListComponent, MetadataRepresentationListComponent,
DsDynamicLookupRelationSearchTabComponent, DsDynamicLookupRelationSearchTabComponent,
DsDynamicLookupRelationExternalSourceTabComponent, DsDynamicLookupRelationExternalSourceTabComponent,
ItemPageTitleFieldComponent,
MediaViewerComponent,
MediaViewerImageComponent,
MediaViewerVideoComponent,
]; ];
@NgModule({ @NgModule({
@@ -251,7 +268,8 @@ const DECLARATIONS = [
ResourcePoliciesModule, ResourcePoliciesModule,
ComcolModule, ComcolModule,
DsoSharedModule, DsoSharedModule,
SystemWideAlertModule SystemWideAlertModule,
NgxGalleryModule,
], ],
declarations: DECLARATIONS, declarations: DECLARATIONS,
exports: [ exports: [

View File

@@ -11520,10 +11520,10 @@ webpack@5.70.0:
watchpack "^2.3.1" watchpack "^2.3.1"
webpack-sources "^3.2.3" webpack-sources "^3.2.3"
webpack@^5.69.1: webpack@^5.76.0:
version "5.75.0" version "5.76.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c"
integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==
dependencies: dependencies:
"@types/eslint-scope" "^3.7.3" "@types/eslint-scope" "^3.7.3"
"@types/estree" "^0.0.51" "@types/estree" "^0.0.51"