diff --git a/src/app/shared/components/dialogs/shared-detail-dialog/shared-detail.dialog.scss b/src/app/shared/components/dialogs/shared-detail-dialog/shared-detail.dialog.scss index cc30606716e3bb14c223558ef279173c371c6a0b..8d11e5cd7421948405e3174dfb9da0289594839b 100644 --- a/src/app/shared/components/dialogs/shared-detail-dialog/shared-detail.dialog.scss +++ b/src/app/shared/components/dialogs/shared-detail-dialog/shared-detail.dialog.scss @@ -17,6 +17,19 @@ h2 { } .visualization { + + max-height: 100%; + height: 100%; + overflow-y: hidden; + + .visualization-mol { + + &.has-error-message { + height: 0 ! important; + display: none; + } + } + .warning-area { display: flex; flex-direction: column; diff --git a/src/app/shared/components/dialogs/shared-file-detail/shared-file-detail.dialog.html b/src/app/shared/components/dialogs/shared-file-detail/shared-file-detail.dialog.html index 56a3b6119ab6e8776384d07a634a37349dba3910..82f0d538650d1a4056c230f739d177fd7c1ff5cc 100644 --- a/src/app/shared/components/dialogs/shared-file-detail/shared-file-detail.dialog.html +++ b/src/app/shared/components/dialogs/shared-file-detail/shared-file-detail.dialog.html @@ -94,6 +94,8 @@ *ngIf="showPreviewTab.isActive" > <dlcm-file-visualizer + class="visualization-mol" + [class.has-error-message]="visualizationErrorMessage" [fileToVisualize]="getFileInput()" (errorMessageChange)="visualizationErrorMessage = $event" ></dlcm-file-visualizer> diff --git a/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.scss b/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.scss index b5be60976399d402fe035151245a797dc96923fd..d8951dd5e493e148485b568f814c8f312f83d6db 100644 --- a/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.scss +++ b/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.scss @@ -1,3 +1,7 @@ :host { - height: 500px; + + min-width: 300px; + width: 100%; + height: 100%; + } diff --git a/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.ts b/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.ts index 68a5dba776435cfbeeeaa81630920f49d08f97f4..3da99160aaa70ce8d7dccb4b60611690eee34c29 100644 --- a/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.ts +++ b/src/app/shared/components/dialogs/shared-preview/shared-preview.dialog.ts @@ -9,7 +9,6 @@ import { } from "@angular/material/dialog"; import {SharedAbstractContainer} from "@shared/components/containers/shared-abstract/shared-abstract.container"; import {SharedPreviewDialogData} from "@shared/components/dialogs/shared-preview/shared-preview-dialog-data.model"; -import {FileVisualizerPresentational} from "@shared/filevisualizer/components/file-visualizer.component"; @Component({ selector: "dlcm-preview-dialog", diff --git a/src/app/shared/filevisualizer/components/file-visualizer.component.html b/src/app/shared/filevisualizer/components/file-visualizer.component.html index a7eabd7a23ace2c8ed5cb3454b57e921896f090a..e487bc02ece68133c2f367702df94eee6398178b 100644 --- a/src/app/shared/filevisualizer/components/file-visualizer.component.html +++ b/src/app/shared/filevisualizer/components/file-visualizer.component.html @@ -1,3 +1,9 @@ -<div #visualizationContainer> +<div #visualizationContainer + class="visualization-container" +> <ng-template dlcmExternalPlugin></ng-template> + <div *ngIf="isLoadingVisualizationObs | async" + class="spinner-background" + [dlcmSpinner]="isLoadingVisualizationObs | async" + ></div> </div> diff --git a/src/app/shared/filevisualizer/components/file-visualizer.component.scss b/src/app/shared/filevisualizer/components/file-visualizer.component.scss index c12ab9d3fa0f03c232bb5ee875465fbd0ba7253c..e8868635a374ae83252bcd2ded0fcd49b72190c0 100644 --- a/src/app/shared/filevisualizer/components/file-visualizer.component.scss +++ b/src/app/shared/filevisualizer/components/file-visualizer.component.scss @@ -1,8 +1,31 @@ -.zoom-in { - cursor: zoom-in; -} +:host { + min-height: 300px; + width: 100%; + min-width: 300px; + height: 100%; + + .visualization-container { + height: 100%; + } + + .spinner-background { + background-color: rgba(255, 255, 255, 0.66); + height: 100%; + animation: from-transparent-background-color 0.5s ease-in-out; + } + + .zoom-in { + cursor: zoom-in; + overflow-y: auto; + max-height: 100%; + } + + .zoom-out { + cursor: zoom-out; + overflow-y: auto; + max-height: 100%; + } -.zoom-out { - cursor: zoom-out; } + diff --git a/src/app/shared/filevisualizer/components/file-visualizer.component.ts b/src/app/shared/filevisualizer/components/file-visualizer.component.ts index 62ee7a83a7d52915c607b7898d48940b1e0fab6a..1d70ce758156ec3b8d154a22e8ce10c30b0668b0 100644 --- a/src/app/shared/filevisualizer/components/file-visualizer.component.ts +++ b/src/app/shared/filevisualizer/components/file-visualizer.component.ts @@ -44,6 +44,8 @@ import { }) export class FileVisualizerPresentational extends CoreAbstractAngularElement implements AfterContentInit, OnDestroy { + isLoadingVisualizationObs: Observable<boolean> = MemoizedUtil.isLoading(this._store, VisualizationState); + previewFile: Observable<BlobElementModel> = MemoizedUtil.select(this._store, VisualizationState, state => ({ blob: state.blob, @@ -66,10 +68,10 @@ export class FileVisualizerPresentational extends CoreAbstractAngularElement imp @ViewChild(AddExternalComponentDirective, {static: true}) addExternalPlugin: AddExternalComponentDirective; - private readonly _closeBS: BehaviorSubject<boolean | undefined> = new BehaviorSubject<boolean | undefined>(undefined); + private readonly _closeBS: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); @Output("closeVisualizerChange") - readonly closeVisualizerObs: Observable<boolean | undefined> = ObservableUtil.asObservable(this._closeBS); + readonly closeVisualizerObs: Observable<boolean> = ObservableUtil.asObservable(this._closeBS); private readonly _errorMessageBS: BehaviorSubject<string> = new BehaviorSubject<string>(""); @@ -116,11 +118,11 @@ export class FileVisualizerPresentational extends CoreAbstractAngularElement imp this.closeVisualization(); if (!this.canHandleBySize(fileInfo)) { const sizeNotSupported = "notification.file.visualizer.file.toobig"; - this._notificationService.showInformation(TRANSLATE(sizeNotSupported), true); + this._notificationService.showInformation(TRANSLATE("notification.file.visualizer.file.toobig"), true); this._errorMessageBS.next(sizeNotSupported); } else { const notSupportedMessage = "notification.file.visualizer.file.notsupported"; - this._notificationService.showInformation(TRANSLATE(notSupportedMessage), true); + this._notificationService.showInformation(TRANSLATE("notification.file.visualizer.file.notsupported"), true); this._errorMessageBS.next(notSupportedMessage); } return; diff --git a/src/app/shared/filevisualizer/models/file-visualizer.constant.ts b/src/app/shared/filevisualizer/models/file-visualizer.constant.ts index 730d4c97ba7ba537fd2c17ce86380baae3fc97a9..dc288524cb9fd2b7cb85b3ba0b9c40f94044df76 100644 --- a/src/app/shared/filevisualizer/models/file-visualizer.constant.ts +++ b/src/app/shared/filevisualizer/models/file-visualizer.constant.ts @@ -19,7 +19,7 @@ export class FileVisualizerConstant { static readonly classicalMoviePronomId: string[] = ["fmt/199", "fmt/203", "fmt/944", "fmt/945", "fmt/946", "fmt/947", "fmt/948"]; // pdf constant - static readonly pdfExtensions: string[] = ["Office Open XML Document"]; + static readonly pdfExtensions: string[] = ["PDF/A", ".pdf"]; static readonly pdfContentType: string[] = []; static readonly pdfMimeType: string[] = ["application/pdf"]; static readonly pdfPronomId: string[] = ["fmt/95", "fmt/3", "fmt/476", "fmt/477", "fmt/479", "fmt/480", "fmt/18", "fmt/19", "fmt/20", "fmt/276"]; diff --git a/src/app/shared/filevisualizer/services/sound-file-visualizer.service.ts b/src/app/shared/filevisualizer/services/sound-file-visualizer.service.ts index 5a47925aa6fbd195b110b0644e1e039575e50e3a..b8b81b4fec80822ae50d8b243560bb4aa60095c8 100644 --- a/src/app/shared/filevisualizer/services/sound-file-visualizer.service.ts +++ b/src/app/shared/filevisualizer/services/sound-file-visualizer.service.ts @@ -34,6 +34,7 @@ export class SoundFileVisualizerService implements AbstractFileVisualizer { } isVisualizationOnGoing(fileInfo: FileInput, domElement: Element): boolean { + const test = isTruthyObject(this.wave); return isTruthyObject(this.wave); } @@ -54,22 +55,87 @@ export class SoundFileVisualizerService implements AbstractFileVisualizer { } closeVisualizer(fileInfo: FileInput, domElement: Element): void { + this.wave.unAll(); + this.wave.stop(); this.wave.destroy(); } openVisualizer(fileInfo: FileInput, domElement: Element): void { if (this.canHandle(fileInfo)) { + const divContainer = document.createElement("div"); + divContainer.style.display = "grid"; + divContainer.style.gridTemplateRows = "auto auto auto"; + const waveContainer = document.createElement("div"); + waveContainer.id = "wave"; + waveContainer.style.overflow = "hidden"; + divContainer.appendChild(waveContainer); + const timelineContainer = document.createElement("div"); + timelineContainer.style.display = "flex"; + timelineContainer.style.justifyContent = "center"; + const timeElement = document.createElement("span"); + timeElement.id = "time"; + timelineContainer.appendChild(timeElement); + const buttonContainer = document.createElement("div"); + buttonContainer.style.display = "flex"; + buttonContainer.style.alignItems = "center"; + buttonContainer.style.justifyContent = "center"; + const matButton = document.createElement("button"); + matButton.onclick = (ev => this.wave.playPause()); + matButton.textContent = "Play | Pause"; + matButton.classList.add("mat-button"); + matButton.classList.add("mat-focus-indicator"); + matButton.classList.add("mat-button-base"); + matButton.classList.add("mat-primary"); + buttonContainer.appendChild(matButton); + divContainer.appendChild(buttonContainer); + divContainer.appendChild(timelineContainer); + document.createElement("div"); + domElement.appendChild(divContainer); this.wave = WaveSurfer.create({ - container: domElement, + container: document.querySelector("#wave"), + barWidth: 2, + barHeight: 1, + overflow: "hidden ! important", waveColor: "violet", progressColor: "purple", }); + const url = URL.createObjectURL(fileInfo.blob); this.wave.load(url); this.wave.on("ready", () => { this.wave.play(); }); + + this.wave.on("audioprocess", () => { + const totalTime = this.wave.getDuration(); + const currentTime = this.wave.getCurrentTime(); + document.getElementById("time").innerText = this.getMiliSecondeDisplay(Math.round(currentTime * 1000)) + "/" + this.getMiliSecondeDisplay(Math.round(totalTime * 1000)); + }); + + this.wave.on("pause", () => { + const totalTime = this.wave.getDuration(); + const currentTime = this.wave.getCurrentTime(); + document.getElementById("time").innerText = this.getMiliSecondeDisplay(Math.round(currentTime * 1000)) + "/" + this.getMiliSecondeDisplay(Math.round(totalTime * 1000)); + }); + } + } + + private getMiliSecondeDisplay(millisec: number): string { + let seconds: any = (millisec / 1000).toFixed(0); + let minutes: any = Math.floor(seconds / 60); + let hours: any = ""; + if (minutes > 59) { + hours = Math.floor(minutes / 60); + hours = (hours >= 10) ? hours : "0" + hours; + minutes = minutes - (hours * 60); + minutes = (minutes >= 10) ? minutes : "0" + minutes; + } + seconds = Math.floor(seconds % 60); + seconds = (seconds >= 10) ? seconds : "0" + seconds; + if (hours !== "") { + return hours + ":" + minutes + ":" + seconds; } + return minutes + ":" + seconds; } doAction(fileInfo: FileInput, domElement: Element): void { diff --git a/src/app/shared/filevisualizer/services/video-classical-file-visualizer.service.ts b/src/app/shared/filevisualizer/services/video-classical-file-visualizer.service.ts index edfe853ae7184054acedcdba312d7fc43676b5a6..088db2ff480ed1bd9d226a8c95605e90cca27912 100644 --- a/src/app/shared/filevisualizer/services/video-classical-file-visualizer.service.ts +++ b/src/app/shared/filevisualizer/services/video-classical-file-visualizer.service.ts @@ -60,6 +60,7 @@ export class VideoClassicalFileVisualizerService implements AbstractFileVisualiz openVisualizer(fileInfo: FileInput, domElement: Element): void { const url = URL.createObjectURL(fileInfo.blob); this.video = document.createElement("video"); + this.video.style.backgroundColor = "black"; this.video.controls = true; this.video.autoplay = true; diff --git a/src/app/shared/filevisualizer/services/video-file-visualizer.service.ts b/src/app/shared/filevisualizer/services/video-file-visualizer.service.ts index f3bbaa10ba9fc10b139f5f866980e97e17b6d472..dcfb34b98bbaafc3f6e41560af319ab889607ec5 100644 --- a/src/app/shared/filevisualizer/services/video-file-visualizer.service.ts +++ b/src/app/shared/filevisualizer/services/video-file-visualizer.service.ts @@ -73,6 +73,7 @@ export class VideoFileVisualizerService implements AbstractFileVisualizer { this.video.src = url; this.video.height = 500; this.video.width = 500; + this.video.style.backgroundColor = "black"; domElement.appendChild(this.video); } diff --git a/src/app/shared/stores/visualization/visualization.state.ts b/src/app/shared/stores/visualization/visualization.state.ts index 9190153c5da78e72b16dee83ac15af553c37a48f..17b135f62352e7ae18aa4ec50b7f0a5abdcaaff4 100644 --- a/src/app/shared/stores/visualization/visualization.state.ts +++ b/src/app/shared/stores/visualization/visualization.state.ts @@ -56,6 +56,9 @@ export class VisualizationState extends BasicState<SharedVisualizationStateModel @Action(SharedVisualizationAction.Download) download(ctx: StateContext<SharedVisualizationStateModel>, action: SharedVisualizationAction.Download): Observable<Blob> { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + }); const url = `${this._urlResource}/${action.data.dataFile.packageId}/${ApiResourceNameEnum.DATAFILE}/${action.data.dataFile.resId}/${ApiActionEnum.DL}`; return this.downloadService.downloadInMemory(url, action.data.dataFile.fileName, false) .pipe( @@ -69,11 +72,17 @@ export class VisualizationState extends BasicState<SharedVisualizationStateModel @Action(SharedVisualizationAction.DownloadFailed) downloadFailed(ctx: StateContext<SharedVisualizationStateModel>, action: SharedVisualizationAction.DownloadFailed): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); this.notificationService.showError(TRANSLATE("deposit.notification.download.fail")); } @Action(SharedVisualizationAction.DownloadSucess) downloadSuccess(ctx: StateContext<SharedVisualizationStateModel>, action: SharedVisualizationAction.DownloadSucess): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); ctx.patchState({ blob: action.blob, blobId: action.blobId, diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 79bea18cc1e20c62ceed85c235d53e8859680bd6..9bbe0d6c47f336dff2e99d443ac025a5983a92d2 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -1869,6 +1869,14 @@ "joinOrgUnitRequest": "Join organizational unit request" } }, + "file": { + "visualizer": { + "file": { + "notsupported": "The file you try to open is not supported", + "toobig": "The file you try to open as a size not supported" + } + } + }, "metadataType": { "file": { "downloadInProgress": "File download started", @@ -2625,4 +2633,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 79bea18cc1e20c62ceed85c235d53e8859680bd6..9bbe0d6c47f336dff2e99d443ac025a5983a92d2 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1869,6 +1869,14 @@ "joinOrgUnitRequest": "Join organizational unit request" } }, + "file": { + "visualizer": { + "file": { + "notsupported": "The file you try to open is not supported", + "toobig": "The file you try to open as a size not supported" + } + } + }, "metadataType": { "file": { "downloadInProgress": "File download started", @@ -2625,4 +2633,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 2b8efaa13b5677cee1cbe5f44d31ab2c21408e5f..a8c0702177778daa0ecca2afd41138ffd7d93d16 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -1869,6 +1869,14 @@ "joinOrgUnitRequest": "Demande pour rejoindre une unité organisationnelle" } }, + "file": { + "visualizer": { + "file": { + "notsupported": "Le fichier que vous essayer d'ouvrir n'est pas supporté pour le moment.", + "toobig": "Le fichier que vous essayez d'ouvrir a une taille trop importante." + } + } + }, "metadataType": { "file": { "downloadInProgress": "Le téléchargement a démarré", @@ -2625,4 +2633,4 @@ } } } -} \ No newline at end of file +}