diff --git a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.html b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.html index 2ae5e2a851..0dd37bead0 100644 --- a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.html +++ b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.html @@ -178,13 +178,16 @@ + [tracks]="tracks" + [readOnly]="readOnly"> + diff --git a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.scss b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.scss index 963c5500c5..d6ec2ab599 100644 --- a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.scss +++ b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.scss @@ -58,10 +58,6 @@ @extend .adf-full-screen; } - &-custom-content { - width: 100vw; - } - &__sidebar { width: 350px; display: block; diff --git a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.ts b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.ts index 34a3e3b089..9ea38e8b0b 100644 --- a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.ts +++ b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.ts @@ -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 { 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, diff --git a/lib/core/src/lib/viewer/components/media-player.component.ts b/lib/core/src/lib/viewer/components/media-player.component.ts index 59f757111d..1052adeecd 100644 --- a/lib/core/src/lib/viewer/components/media-player.component.ts +++ b/lib/core/src/lib/viewer/components/media-player.component.ts @@ -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'); } diff --git a/lib/core/src/lib/viewer/components/pdf-viewer.component.ts b/lib/core/src/lib/viewer/components/pdf-viewer.component.ts index a8392d2849..0a30ac33b5 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer.component.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer.component.ts @@ -80,6 +80,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { @Output() error = new EventEmitter(); + @Output() + close = new EventEmitter(); + 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(); } }); } diff --git a/lib/core/src/lib/viewer/components/viewer-render.component.html b/lib/core/src/lib/viewer/components/viewer-render.component.html index 0885137321..2cbfc82da8 100644 --- a/lib/core/src/lib/viewer/components/viewer-render.component.html +++ b/lib/core/src/lib/viewer/components/viewer-render.component.html @@ -1,5 +1,7 @@
+ class="adf-viewer-render-main" + fxFlexOrder="1" + fxFlex="1 1 auto">
@@ -17,7 +19,9 @@
+ class="adf-viewer-render-main" + fxFlexOrder="1" + fxFlex="1 1 auto">
@@ -37,6 +41,7 @@ [urlFile]="urlFile" [fileName]="fileName" [cacheType]="cacheTypeForContent" + (close)="onClose()" (error)="onUnsupportedFile()"> @@ -44,6 +49,7 @@ (); @@ -107,6 +106,10 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy { @Output() submitFile = new EventEmitter(); + /** Emitted when the img is submitted in the img viewer. */ + @Output() + close = new EventEmitter(); + extensionTemplates: { template: TemplateRef; isVisible: boolean }[] = []; extension: string; @@ -200,4 +203,8 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy { this.viewerType = 'unknown'; } + onClose() { + this.close.next(true); + } + } diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.html new file mode 100644 index 0000000000..00c6489b02 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.html @@ -0,0 +1,7 @@ +
+ + + +
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.scss b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.scss new file mode 100644 index 0000000000..4af97c452d --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.scss @@ -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; + } + } + } + } +} diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.spec.ts new file mode 100644 index 0000000000..01f77baa19 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.spec.ts @@ -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; + let fixture: ComponentFixture; + + 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(); + }); + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.ts new file mode 100644 index 0000000000..b0b1b672aa --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/widgets/file-viewer/file-viewer.widget.ts @@ -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; + } + } +}