Made it possible to only enable video media viewer

Also:
- Filtered out non-supported media file types from the mediaViewers mediaList
- Fixed thumbnails not displaying with 0 ORIGINAL bitstreams
This commit is contained in:
Alexandre Vryghem
2023-03-19 11:42:09 +01:00
parent e4f483c308
commit aa4d56e2cf
9 changed files with 89 additions and 90 deletions

View File

@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery';
import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
import { NgxGalleryAnimation } from '@kolkov/ngx-gallery'; import { NgxGalleryAnimation } from '@kolkov/ngx-gallery';
@@ -13,7 +13,7 @@ import { AuthService } from '../../../core/auth/auth.service';
templateUrl: './media-viewer-image.component.html', templateUrl: './media-viewer-image.component.html',
styleUrls: ['./media-viewer-image.component.scss'], styleUrls: ['./media-viewer-image.component.scss'],
}) })
export class MediaViewerImageComponent implements OnInit { export class MediaViewerImageComponent implements OnChanges, OnInit {
@Input() images: MediaViewerItem[]; @Input() images: MediaViewerItem[];
@Input() preview?: boolean; @Input() preview?: boolean;
@Input() image?: string; @Input() image?: string;
@@ -30,11 +30,9 @@ export class MediaViewerImageComponent implements OnInit {
constructor(private authService: AuthService) {} constructor(private authService: AuthService) {}
/** ngOnChanges(changes: SimpleChanges): void {
* Thi method sets up the gallery settings and data this.image = changes.image.currentValue;
*/ this.preview = changes.preview.currentValue;
ngOnInit(): void {
this.isAuthenticated$ = this.authService.isAuthenticated();
this.galleryOptions = [ this.galleryOptions = [
{ {
preview: this.preview !== undefined ? this.preview : true, preview: this.preview !== undefined ? this.preview : true,
@@ -50,7 +48,6 @@ export class MediaViewerImageComponent implements OnInit {
previewFullscreen: true, previewFullscreen: true,
}, },
]; ];
if (this.image) { if (this.image) {
this.galleryImages = [ this.galleryImages = [
{ {
@@ -64,6 +61,10 @@ export class MediaViewerImageComponent implements OnInit {
} }
} }
ngOnInit(): void {
this.isAuthenticated$ = this.authService.isAuthenticated();
}
/** /**
* This method convert an array of MediaViewerItem into NgxGalleryImage array * This method convert an array of MediaViewerItem into NgxGalleryImage array
* @param medias input NgxGalleryImage array * @param medias input NgxGalleryImage array

View File

@@ -1,15 +1,14 @@
<video <video
#media [src]="medias[currentIndex].bitstream._links.content.href"
[src]="filteredMedias[currentIndex].bitstream._links.content.href"
id="singleVideo" id="singleVideo"
[poster]=" [poster]="
filteredMedias[currentIndex].thumbnail || medias[currentIndex].thumbnail ||
replacements[filteredMedias[currentIndex].format] replacements[medias[currentIndex].format]
" "
preload="none" preload="none"
controls controls
></video> ></video>
<div class="buttons" *ngIf="filteredMedias?.length > 1"> <div class="buttons" *ngIf="medias?.length > 1">
<button <button
class="btn btn-primary previous" class="btn btn-primary previous"
[disabled]="currentIndex === 0" [disabled]="currentIndex === 0"
@@ -20,7 +19,7 @@
<button <button
class="btn btn-primary next" class="btn btn-primary next"
[disabled]="currentIndex === filteredMedias.length - 1" [disabled]="currentIndex === medias.length - 1"
(click)="nextMedia()" (click)="nextMedia()"
> >
{{ "media-viewer.next" | translate }} {{ "media-viewer.next" | translate }}
@@ -36,7 +35,7 @@
<div ngbDropdownMenu aria-labelledby="dropdownBasic1"> <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<button <button
ngbDropdownItem ngbDropdownItem
*ngFor="let item of filteredMedias; index as indexOfelement" *ngFor="let item of medias; index as indexOfelement"
class="list-element" class="list-element"
(click)="selectedMedia(indexOfelement)" (click)="selectedMedia(indexOfelement)"
> >

View File

@@ -83,7 +83,6 @@ describe('MediaViewerVideoComponent', () => {
fixture = TestBed.createComponent(MediaViewerVideoComponent); fixture = TestBed.createComponent(MediaViewerVideoComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
component.medias = mockMediaViewerItem; component.medias = mockMediaViewerItem;
component.filteredMedias = mockMediaViewerItem;
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -94,7 +93,6 @@ describe('MediaViewerVideoComponent', () => {
describe('should show controller buttons when the having mode then one video', () => { describe('should show controller buttons when the having mode then one video', () => {
beforeEach(() => { beforeEach(() => {
component.medias = mockMediaViewerItems; component.medias = mockMediaViewerItems;
component.filteredMedias = mockMediaViewerItems;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input } from '@angular/core';
import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
/** /**
@@ -9,12 +9,11 @@ import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
templateUrl: './media-viewer-video.component.html', templateUrl: './media-viewer-video.component.html',
styleUrls: ['./media-viewer-video.component.scss'], styleUrls: ['./media-viewer-video.component.scss'],
}) })
export class MediaViewerVideoComponent implements OnInit { export class MediaViewerVideoComponent {
@Input() medias: MediaViewerItem[]; @Input() medias: MediaViewerItem[];
filteredMedias: MediaViewerItem[]; isCollapsed = false;
isCollapsed: boolean;
currentIndex = 0; currentIndex = 0;
replacements = { replacements = {
@@ -24,15 +23,8 @@ export class MediaViewerVideoComponent implements OnInit {
replacementThumbnail: string; replacementThumbnail: string;
ngOnInit() {
this.isCollapsed = false;
this.filteredMedias = this.medias.filter(
(media) => media.format === 'audio' || media.format === 'video'
);
}
/** /**
* This method sets the reviced index into currentIndex * This method sets the received index into currentIndex
* @param index Selected index * @param index Selected index
*/ */
selectedMedia(index: number) { selectedMedia(index: number) {
@@ -40,14 +32,14 @@ export class MediaViewerVideoComponent implements OnInit {
} }
/** /**
* This method increade the number of the currentIndex * This method increases the number of the currentIndex
*/ */
nextMedia() { nextMedia() {
this.currentIndex++; this.currentIndex++;
} }
/** /**
* This method decrese the number of the currentIndex * This method decreases the number of the currentIndex
*/ */
prevMedia() { prevMedia() {
this.currentIndex--; this.currentIndex--;

View File

@@ -5,32 +5,20 @@
[showMessage]="false" [showMessage]="false"
></ds-loading> ></ds-loading>
<div class="media-viewer" *ngIf="!isLoading"> <div class="media-viewer" *ngIf="!isLoading">
<ng-container *ngIf="mediaList.length > 0"> <ng-container *ngIf="mediaList.length > 0; else showThumbnail">
<ng-container *ngIf="videoOptions"> <ng-container *ngVar="mediaOptions.video && ['audio', 'video'].includes(mediaList[0]?.format) as showVideo">
<ng-container <ng-container *ngVar="mediaOptions.image && mediaList[0]?.format === 'image' as showImage">
*ngIf=" <ds-media-viewer-video *ngIf="showVideo" [medias]="mediaList"></ds-media-viewer-video>
mediaList[0]?.format === 'video' || mediaList[0]?.format === 'audio' <ds-media-viewer-image *ngIf="showImage" [images]="mediaList"></ds-media-viewer-image>
" <ng-container *ngIf="showImage || showVideo; else showThumbnail"></ng-container>
>
<ds-media-viewer-video [medias]="mediaList"></ds-media-viewer-video>
</ng-container> </ng-container>
</ng-container> </ng-container>
<ng-container *ngIf="mediaList[0]?.format === 'image'">
<ds-media-viewer-image [images]="mediaList"></ds-media-viewer-image>
</ng-container>
</ng-container>
<ng-container
*ngIf="
((mediaList[0]?.format !== 'image') &&
(!videoOptions || mediaList[0]?.format !== 'video') &&
(!videoOptions || mediaList[0]?.format !== 'audio')) ||
mediaList.length === 0
"
>
<ds-media-viewer-image
[image]="mediaList[0]?.thumbnail || thumbnailPlaceholder"
[preview]="false"
></ds-media-viewer-image>
</ng-container> </ng-container>
</div> </div>
<ng-template #showThumbnail>
<ds-media-viewer-image
[image]="(thumbnailsRD$ | async)?.payload?.page[0]?._links.content.href || thumbnailPlaceholder"
[preview]="false"
></ds-media-viewer-image>
</ng-template>
</ng-container> </ng-container>

View File

@@ -61,7 +61,7 @@ describe('MediaViewerComponent', () => {
); );
beforeEach(waitForAsync(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ return TestBed.configureTestingModule({
imports: [ imports: [
TranslateModule.forRoot({ TranslateModule.forRoot({
loader: { loader: {
@@ -94,7 +94,10 @@ describe('MediaViewerComponent', () => {
describe('when the bitstreams are loading', () => { describe('when the bitstreams are loading', () => {
beforeEach(() => { beforeEach(() => {
comp.mediaList$.next([mockMediaViewerItem]); comp.mediaList$.next([mockMediaViewerItem]);
comp.videoOptions = true; comp.mediaOptions = {
image: true,
video: true,
};
comp.isLoading = true; comp.isLoading = true;
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -118,7 +121,10 @@ describe('MediaViewerComponent', () => {
describe('when the bitstreams loading is failed', () => { describe('when the bitstreams loading is failed', () => {
beforeEach(() => { beforeEach(() => {
comp.mediaList$.next([]); comp.mediaList$.next([]);
comp.videoOptions = true; comp.mediaOptions = {
image: true,
video: true,
};
comp.isLoading = false; comp.isLoading = false;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { filter, take } from 'rxjs/operators'; import { filter, take } from 'rxjs/operators';
import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { BitstreamDataService } from '../../core/data/bitstream-data.service';
@@ -11,6 +11,9 @@ import { MediaViewerItem } from '../../core/shared/media-viewer-item.model';
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { followLink } from '../../shared/utils/follow-link-config.model'; import { followLink } from '../../shared/utils/follow-link-config.model';
import { MediaViewerConfig } from '../../../config/media-viewer-config.interface';
import { environment } from '../../../environments/environment';
import { Subscription } from 'rxjs/internal/Subscription';
/** /**
* This componenet renders the media viewers * This componenet renders the media viewers
@@ -21,51 +24,67 @@ import { followLink } from '../../shared/utils/follow-link-config.model';
templateUrl: './media-viewer.component.html', templateUrl: './media-viewer.component.html',
styleUrls: ['./media-viewer.component.scss'], styleUrls: ['./media-viewer.component.scss'],
}) })
export class MediaViewerComponent implements OnInit { export class MediaViewerComponent implements OnDestroy, OnInit {
@Input() item: Item; @Input() item: Item;
@Input() videoOptions: boolean;
mediaList$: BehaviorSubject<MediaViewerItem[]>; @Input() mediaOptions: MediaViewerConfig = environment.mediaViewer;
isLoading: boolean; mediaList$: BehaviorSubject<MediaViewerItem[]> = new BehaviorSubject([]);
isLoading = true;
thumbnailPlaceholder = './assets/images/replacement_document.svg'; thumbnailPlaceholder = './assets/images/replacement_document.svg';
constructor(protected bitstreamDataService: BitstreamDataService) {} thumbnailsRD$: Observable<RemoteData<PaginatedList<Bitstream>>>;
subs: Subscription[] = [];
constructor(
protected bitstreamDataService: BitstreamDataService,
) {
}
ngOnDestroy(): void {
this.subs.forEach((subscription: Subscription) => subscription.unsubscribe());
}
/** /**
* This metod loads all the Bitstreams and Thumbnails and contert it to media item * This method loads all the Bitstreams and Thumbnails and converts it to {@link MediaViewerItem}s
*/ */
ngOnInit(): void { ngOnInit(): void {
this.mediaList$ = new BehaviorSubject([]); const types: string[] = [
this.isLoading = true; ...(this.mediaOptions.image ? ['image'] : []),
this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD) => { ...(this.mediaOptions.video ? ['audio', 'video'] : []),
];
this.thumbnailsRD$ = this.loadRemoteData('THUMBNAIL');
this.subs.push(this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => {
if (bitstreamsRD.payload.page.length === 0) { if (bitstreamsRD.payload.page.length === 0) {
this.isLoading = false; this.isLoading = false;
this.mediaList$.next([]); this.mediaList$.next([]);
} else { } else {
this.loadRemoteData('THUMBNAIL').subscribe((thumbnailsRD) => { this.subs.push(this.thumbnailsRD$.subscribe((thumbnailsRD: RemoteData<PaginatedList<Bitstream>>) => {
for ( for (
let index = 0; let index = 0;
index < bitstreamsRD.payload.page.length; index < bitstreamsRD.payload.page.length;
index++ index++
) { ) {
bitstreamsRD.payload.page[index].format this.subs.push(bitstreamsRD.payload.page[index].format
.pipe(getFirstSucceededRemoteDataPayload()) .pipe(getFirstSucceededRemoteDataPayload())
.subscribe((format) => { .subscribe((format: BitstreamFormat) => {
const current = this.mediaList$.getValue();
const mediaItem = this.createMediaViewerItem( const mediaItem = this.createMediaViewerItem(
bitstreamsRD.payload.page[index], bitstreamsRD.payload.page[index],
format, format,
thumbnailsRD.payload && thumbnailsRD.payload.page[index] thumbnailsRD.payload && thumbnailsRD.payload.page[index]
); );
this.mediaList$.next([...current, mediaItem]); if (types.includes(mediaItem.format)) {
}); this.mediaList$.next([...this.mediaList$.getValue(), mediaItem]);
}
}));
} }
this.isLoading = false; this.isLoading = false;
}); }));
} }
}); }));
} }
/** /**
@@ -95,16 +114,12 @@ export class MediaViewerComponent implements OnInit {
} }
/** /**
* This method create MediaViewerItem from incoming bitstreams * This method creates a {@link MediaViewerItem} from incoming {@link Bitstream}s
* @param original original remote data bitstream * @param original original bitstream
* @param format original bitstream format * @param format original bitstream format
* @param thumbnail trunbnail remote data bitstream * @param thumbnail thumbnail bitstream
*/ */
createMediaViewerItem( createMediaViewerItem(original: Bitstream, format: BitstreamFormat, thumbnail: Bitstream): MediaViewerItem {
original: Bitstream,
format: BitstreamFormat,
thumbnail: Bitstream
): MediaViewerItem {
const mediaItem = new MediaViewerItem(); const mediaItem = new MediaViewerItem();
mediaItem.bitstream = original; mediaItem.bitstream = original;
mediaItem.format = format.mimetype.split('/')[0]; mediaItem.format = format.mimetype.split('/')[0];

View File

@@ -17,13 +17,13 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-4"> <div class="col-xs-12 col-md-4">
<ng-container *ngIf="!mediaViewer.image"> <ng-container *ngIf="!(mediaViewer.image || mediaViewer.video)">
<ds-metadata-field-wrapper [hideIfNoTextContent]="false"> <ds-metadata-field-wrapper [hideIfNoTextContent]="false">
<ds-thumbnail [thumbnail]="object?.thumbnail | async"></ds-thumbnail> <ds-thumbnail [thumbnail]="object?.thumbnail | async"></ds-thumbnail>
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>
</ng-container> </ng-container>
<ng-container *ngIf="mediaViewer.image"> <ng-container *ngIf="mediaViewer.image || mediaViewer.video">
<ds-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-media-viewer> <ds-media-viewer [item]="object"></ds-media-viewer>
</ng-container> </ng-container>
<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

@@ -20,13 +20,13 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-4"> <div class="col-xs-12 col-md-4">
<ng-container *ngIf="!mediaViewer.image"> <ng-container *ngIf="!(mediaViewer.image || mediaViewer.video)">
<ds-metadata-field-wrapper [hideIfNoTextContent]="false"> <ds-metadata-field-wrapper [hideIfNoTextContent]="false">
<ds-thumbnail [thumbnail]="object?.thumbnail | async"></ds-thumbnail> <ds-thumbnail [thumbnail]="object?.thumbnail | async"></ds-thumbnail>
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>
</ng-container> </ng-container>
<ng-container *ngIf="mediaViewer.image"> <ng-container *ngIf="mediaViewer.image || mediaViewer.video">
<ds-media-viewer [item]="object" [videoOptions]="mediaViewer.video"></ds-media-viewer> <ds-media-viewer [item]="object"></ds-media-viewer>
</ng-container> </ng-container>
<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>