refactor part 2

This commit is contained in:
eromano
2022-11-22 22:38:53 +01:00
committed by Amedeo Lepore
parent 36ee8c8e34
commit 9b6daeedb7
12 changed files with 306 additions and 108 deletions

View File

@@ -178,13 +178,16 @@
<adf-viewer-render
fxFlexOrder="1"
fxFlex="1 1 auto"
(close)="onClose()"
(submitFile)="onSubmitFile($event)"
[viewerType]="viewerType"
[fileName]="fileName"
[isLoading]="isLoading"
[allowGoBack]="allowGoBack"
[urlFile]="urlFileContent"
></adf-viewer-render>
[tracks]="tracks"
[readOnly]="readOnly">
</adf-viewer-render>
</div>
</div>

View File

@@ -58,10 +58,6 @@
@extend .adf-full-screen;
}
&-custom-content {
width: 100vw;
}
&__sidebar {
width: 350px;
display: block;

View File

@@ -1,30 +1,58 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
ChangeDetectorRef,
Component, ContentChild,
EventEmitter, HostListener,
Component,
ContentChild,
ElementRef,
EventEmitter,
HostListener,
Input,
Output,
ViewEncapsulation,
ElementRef,
TemplateRef
} from "@angular/core";
import { ViewUtilService } from "../../../../../core/src/lib/viewer/services/view-util.service";
TemplateRef,
ViewEncapsulation
} from '@angular/core';
import {
ContentApi, Node,
AlfrescoApiService, ContentService,
FileModel,
LogService, Track,
UploadService,
ViewerMoreActionsComponent,
ViewerOpenWithComponent,
ViewerSidebarComponent,
ViewerToolbarComponent,
ViewUtilService
} from "@alfresco/adf-core";
import { fromEvent, Subject } from "rxjs";
import {
ContentApi,
Node,
NodeEntry,
NodesApi, RenditionEntry,
SharedLinkEntry,
SharedlinksApi, Version,
NodesApi,
RenditionEntry,
SharedlinksApi,
Version,
VersionEntry,
VersionsApi
} from "@alfresco/js-api";
import { AlfrescoApiService, LogService, UploadService } from "../../../../../core/src/lib/services";
import { RenditionViewerService } from "../services/rendition-viewer.service";
import { MatDialog } from "@angular/material/dialog";
import { filter, skipWhile, takeUntil } from "rxjs/operators";
import { FileModel } from "../../../../../core/src/lib/models";
import { fromEvent, Subject } from "rxjs";
import { RenditionViewerService } from "../services/rendition-viewer.service";
import { ViewerToolbarComponent,ViewerSidebarComponent, ViewerOpenWithComponent,ViewerMoreActionsComponent } from "@alfresco/adf-core";
@Component({
selector: 'adf-alfresco-viewer',
@@ -159,6 +187,8 @@ export class AlfrescoViewerComponent {
fileName: string;
mimeType: string;
nodeEntry: NodeEntry;
tracks: Track[] = [];
readOnly: boolean = true;
sidebarRightTemplateContext: { node: Node } = {node: null};
sidebarLeftTemplateContext: { node: Node } = {node: null};
@@ -191,6 +221,7 @@ export class AlfrescoViewerComponent {
private renditionViewerService: RenditionViewerService,
private viewUtilService: ViewUtilService,
private logService: LogService,
private contentService: ContentService,
private el: ElementRef,
private uploadService: UploadService,
public dialog: MatDialog,
@@ -199,14 +230,6 @@ export class AlfrescoViewerComponent {
}
onNavigateBeforeClick(event: MouseEvent | KeyboardEvent) {
this.navigateBefore.next(event);
}
onNavigateNextClick(event: MouseEvent | KeyboardEvent) {
this.navigateNext.next(event);
}
ngOnInit() {
this.apiService.nodeUpdated.pipe(
filter((node) => node && node.id === this.nodeId &&
@@ -241,22 +264,13 @@ export class AlfrescoViewerComponent {
});
}
/**
* close the viewer
*/
onClose() {
this.showViewer = false;
this.close.emit(this.showViewer);
}
private onNodeUpdated(node: Node) {
private async onNodeUpdated(node: Node) {
if (node && node.id === this.nodeId) {
// this.cacheTypeForContent = 'no-cache';
this.generateCacheBusterNumber();
this.isLoading = true;
this.setUpNodeFile(node).then(() => {
this.isLoading = false;
});
await this.setUpNodeFile(node)
this.isLoading = false;
}
}
@@ -264,52 +278,42 @@ export class AlfrescoViewerComponent {
return node?.properties['cm:versionLabel'] ?? '';
}
private setupSharedLink() {
private async setupSharedLink() {
this.allowGoBack = false;
this.sharedLinksApi.getSharedLink(this.sharedLinkId).then(
(sharedLinkEntry: SharedLinkEntry) => {
this.setUpSharedLinkFile(sharedLinkEntry);
this.isLoading = false;
},
() => {
this.isLoading = false;
this.logService.error('This sharedLink does not exist');
this.invalidSharedLink.next();
});
try {
const sharedLinkEntry = await this.sharedLinksApi.getSharedLink(this.sharedLinkId);
await this.setUpSharedLinkFile(sharedLinkEntry);
this.isLoading = false;
} catch (error) {
this.isLoading = false;
this.logService.error('This sharedLink does not exist');
this.invalidSharedLink.next();
}
}
private setupNode() {
this.nodesApi.getNode(this.nodeId, {include: ['allowableOperations']}).then(
(node: NodeEntry) => {
this.nodeEntry = node;
if (this.versionId) {
this.versionsApi.getVersion(this.nodeId, this.versionId).then(
(version: VersionEntry) => {
this.versionEntry = version;
this.setUpNodeFile(node.entry, version.entry).then(() => {
this.isLoading = false;
});
}
);
} else {
this.setUpNodeFile(node.entry).then(() => {
this.isLoading = false;
this.cdr.detectChanges();
});
}
},
() => {
private async setupNode() {
try {
this.nodeEntry = await this.nodesApi.getNode(this.nodeId, {include: ['allowableOperations']});
if (this.versionId) {
this.versionEntry = await this.versionsApi.getVersion(this.nodeId, this.versionId);
await this.setUpNodeFile(this.nodeEntry.entry, this.versionEntry.entry);
this.isLoading = false;
this.logService.error('This node does not exist');
} else {
await this.setUpNodeFile(this.nodeEntry.entry);
this.isLoading = false;
this.cdr.detectChanges();
}
);
} catch (error) {
this.isLoading = false;
this.logService.error('This node does not exist');
}
}
private async setUpNodeFile(nodeData: Node, versionData?: Version): Promise<void> {
this.isLoading = true;
// this.readOnly = !this.contentService.hasAllowableOperations(nodeData, 'update');
this.readOnly = !this.contentService.hasAllowableOperations(nodeData, 'update');
if (versionData && versionData.content) {
this.mimeType = versionData.content.mimeType;
@@ -341,7 +345,10 @@ export class AlfrescoViewerComponent {
viewerType: this.viewerType
} = await this.renditionViewerService.getNodeRendition(nodeData.id));
}
} else if (this.viewerType === 'media') {
this.tracks = await this.renditionViewerService.generateMediaTracksRendition(this.nodeId);
}
this.isLoading = false;
this.sidebarRightTemplateContext.node = nodeData;
@@ -363,14 +370,6 @@ export class AlfrescoViewerComponent {
}
}
onPrintContent(event: MouseEvent) {
if (this.allowPrint) {
if (!event.defaultPrevented) {
this.viewUtilService.printFileGeneric(this.nodeId, this.mimeType);
}
}
}
private async getSharedLinkRendition(sharedId: string): Promise<{ url: string, viewerType: string }> {
try {
const rendition: RenditionEntry = await this.sharedLinksApi.getSharedLinkRendition(sharedId, 'pdf');
@@ -400,8 +399,32 @@ export class AlfrescoViewerComponent {
this.cacheBusterNumber = Date.now();
}
onNavigateBeforeClick(event: MouseEvent | KeyboardEvent) {
this.navigateBefore.next(event);
}
onNavigateNextClick(event: MouseEvent | KeyboardEvent) {
this.navigateNext.next(event);
}
/**
* close the viewer
*/
onClose() {
this.showViewer = false;
this.close.emit(this.showViewer);
}
onPrintContent(event: MouseEvent) {
if (this.allowPrint) {
if (!event.defaultPrevented) {
this.viewUtilService.printFileGeneric(this.nodeId, this.mimeType);
}
}
}
onSubmitFile(newImageBlob: Blob) {
if (this?.nodeEntry?.entry?.id) { // && !this.readOnly) {
if (this?.nodeEntry?.entry?.id && !this.readOnly) {
const newImageFile: File = new File([newImageBlob], this?.nodeEntry?.entry?.name, {type: this?.nodeEntry?.entry?.content?.mimeType});
const newFile = new FileModel(
newImageFile,

View File

@@ -39,10 +39,8 @@ export class MediaPlayerComponent implements OnChanges {
@Input()
fileName: string;
//
// @Input()
// nodeId: string;
/** media subtitles for the media player*/
@Input()
tracks: Track[] = [];
@@ -54,17 +52,12 @@ export class MediaPlayerComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges) {
const blobFile = changes['blobFile'];
// const nodeId = changes['nodeId'];
if (blobFile && blobFile.currentValue) {
this.urlFile = this.contentService.createTrustedUrl(this.blobFile);
return;
}
// if (nodeId && nodeId.currentValue) {
// this.viewUtils.generateMediaTracksRendition(this.nodeId).then((tracks) => this.tracks = tracks);
// }
if (!this.urlFile && !this.blobFile) {
throw new Error('Attribute urlFile or blobFile is required');
}

View File

@@ -80,6 +80,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
@Output()
error = new EventEmitter<any>();
@Output()
close = new EventEmitter<any>();
page: number;
displayPage: number;
totalPages: number;
@@ -511,6 +514,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
.afterClosed().subscribe((password) => {
if (password) {
callback(password);
} else {
this.close.emit();
}
});
}

View File

@@ -1,5 +1,7 @@
<div *ngIf="isLoading"
class="adf-viewer-main">
class="adf-viewer-render-main"
fxFlexOrder="1"
fxFlex="1 1 auto">
<div class="adf-viewer-render-layout-content adf-viewer__fullscreen-container">
<div class="adf-viewer-render-content-container">
<ng-container *ngIf="isLoading">
@@ -17,7 +19,9 @@
</div>
<div *ngIf="!isLoading"
class="adf-viewer-main">
class="adf-viewer-render-main"
fxFlexOrder="1"
fxFlex="1 1 auto">
<div class="adf-viewer-render-layout-content adf-viewer__fullscreen-container">
<div class="adf-viewer-render-content-container" [ngSwitch]="viewerType">
<ng-container *ngSwitchCase="'external'">
@@ -37,6 +41,7 @@
[urlFile]="urlFile"
[fileName]="fileName"
[cacheType]="cacheTypeForContent"
(close)="onClose()"
(error)="onUnsupportedFile()">
</adf-pdf-viewer>
@@ -44,6 +49,7 @@
<ng-container *ngSwitchCase="'image'">
<adf-img-viewer [urlFile]="urlFile"
[readOnly]="readOnly"
[fileName]="fileName"
[blobFile]="blobFile"
(error)="onUnsupportedFile()"
@@ -54,6 +60,7 @@
<ng-container *ngSwitchCase="'media'">
<adf-media-player id="adf-mdedia-player"
[urlFile]="urlFile"
[tracks]="tracks"
[mimeType]="mimeType"
[blobFile]="blobFile"
[fileName]="fileName"

View File

@@ -16,7 +16,7 @@
justify-content: center;
}
.adf-viewer-render-layout-content {
&-layout-content {
@extend .adf-full-screen;
position: relative;

View File

@@ -15,18 +15,8 @@
* limitations under the License.
*/
//TODO BETTER APPROACH FOR IMG EXTENSION submit
//TODO uncomment readOnly
//TODO TO UNDERSTAND THE LEFT AND RIGHT SIDEBAR
//TODO uncomment media load subtitle
//TODO rename allowGoBack allow close button
//TODO prevent momentous unknown format
//TODO null propagation
//TODO viewer widget specialization in process service cloud
//TODO Test close dialog password scenario
//TODO Remove unused CSS
//TODO FIX documentation
//TODO Fix core viewer widget
//TODO FIX unit test
import {
Component, EventEmitter,
@@ -37,6 +27,7 @@ import { Subject } from 'rxjs';
import { ViewUtilService } from '../services/view-util.service';
import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions';
import { MatDialog } from '@angular/material/dialog';
import { Track } from "../models/viewer.model";
@Component({
selector: 'adf-viewer-render',
@@ -99,6 +90,14 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
@Input()
isLoading = false;
/** Enable when where is possible the editing functionalities */
@Input()
readOnly = true;
/** media subtitles for the media player*/
@Input()
tracks: Track[] = [];
/** Emitted when the filename extension changes. */
@Output()
extensionChange = new EventEmitter<string>();
@@ -107,6 +106,10 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
@Output()
submitFile = new EventEmitter<Blob>();
/** Emitted when the img is submitted in the img viewer. */
@Output()
close = new EventEmitter<boolean>();
extensionTemplates: { template: TemplateRef<any>; isVisible: boolean }[] = [];
extension: string;
@@ -200,4 +203,8 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
this.viewerType = 'unknown';
}
onClose() {
this.close.next(true);
}
}

View File

@@ -0,0 +1,7 @@
<div class="adf-file-viewer-widget {{field.className}}" [class.adf-invalid]="!field.isValid"
[class.adf-readonly]="field.readOnly">
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span></label>
<adf-viewer [overlayMode]="false" [nodeId]="field.value" [showViewer]="field.value" [allowGoBack]="false"></adf-viewer>
<error-widget [error]="field.validationSummary"></error-widget>
</div>

View File

@@ -0,0 +1,19 @@
file-viewer-widget {
height: 100%;
width: 100%;
.adf-file-viewer-widget {
height: 100%;
width: 100%;
adf-viewer.adf-viewer {
position: relative;
.adf-viewer-container {
.adf-viewer-content > div {
height: 90vh;
}
}
}
}
}

View File

@@ -0,0 +1,83 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FormModel } from '../core/form.model';
import { TranslateModule } from '@ngx-translate/core';
import { FormFieldModel } from '../core/form-field.model';
import { FormService } from '../../../services/form.service';
import { FileViewerWidgetComponent } from './file-viewer.widget';
import { ComponentFixture, TestBed } from '@angular/core/testing';
describe('FileViewerWidgetComponent', () => {
const fakeForm = new FormModel();
let widget: FileViewerWidgetComponent;
let formServiceStub: Partial<FormService>;
let fixture: ComponentFixture<FileViewerWidgetComponent>;
const fakePngAnswer: any = {
id: '1933',
link: false,
isExternal: false,
relatedContent: false,
contentAvailable: true,
name: 'a_png_file.png',
simpleType: 'image',
mimeType: 'image/png',
previewStatus: 'queued',
thumbnailStatus: 'queued',
created: '2022-10-14T17:17:37.099Z',
createdBy: { id: 1001, firstName: 'Admin', lastName: 'admin', email: 'admin@example.com' }
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot()
],
declarations: [ FileViewerWidgetComponent ],
providers: [ { provide: FormService, useValue: formServiceStub } ]
});
formServiceStub = TestBed.inject(FormService);
fixture = TestBed.createComponent(FileViewerWidgetComponent);
widget = fixture.componentInstance;
});
it('should set the file id corretly when the field value is an array', (done) => {
const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: [fakePngAnswer] });
widget.field = fakeField;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(widget.field.value).toBe('1933');
done();
});
});
it('should set the file id corretly when the field value is a string', (done) => {
const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: 'fakeValue' });
widget.field = fakeField;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(widget.field.value).toBe('fakeValue');
done();
});
});
});

View File

@@ -0,0 +1,55 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'file-viewer-widget',
templateUrl: './file-viewer.widget.html',
styleUrls: ['./file-viewer.widget.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
'(change)': 'event($event)',
'(focus)': 'event($event)',
'(focusin)': 'event($event)',
'(focusout)': 'event($event)',
'(input)': 'event($event)',
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
encapsulation: ViewEncapsulation.None
})
export class FileViewerWidgetComponent extends WidgetComponent implements OnInit {
constructor(formService: FormService) {
super(formService);
}
ngOnInit(): void {
if (this.field &&
this.field.value &&
Array.isArray(this.field.value) &&
this.field.value.length) {
const file = this.field.value[0];
this.field.value = file.id;
}
}
}