mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-23 18:05:09 +00:00
[AAE-35649] Viewer renderer wait until subsequent renderers will finish (#10924)
* [AAE-35649] Viewer renderer wait until particular renderers are done * [AAE-35649] Add docs and unit test coverage * [AAE-35649] Add missing space
This commit is contained in:
parent
0c7bf62097
commit
5d9acaec0d
@ -245,16 +245,17 @@ The Viewer supports dynamically-loaded viewer preview extensions, to know more a
|
||||
|
||||
You can define your own custom handler to override supported file formats or handle other file formats that are not yet supported by
|
||||
the component. Below is an example that shows how to use the `adf-viewer-extension`
|
||||
to handle 3D data files:
|
||||
to handle 3D data files. `contentLoaded` should be an `EventEmitter` that will emit as soon as the component responsible for rendering finishes.
|
||||
|
||||
```html
|
||||
<adf-alfresco-viewer [nodeId]="nodeId">
|
||||
<ng-template #viewerExtensions>
|
||||
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension" let-markAsLoaded="markAsLoaded">
|
||||
<threed-viewer
|
||||
[urlFile]="urlFileContent"
|
||||
[extension]="extension">
|
||||
[extension]="extension"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</threed-viewer>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
@ -270,17 +271,19 @@ You need to keep all instances of `adf-viewer-extension` inside `viewerExtension
|
||||
<adf-alfresco-viewer [nodeId]="nodeId">
|
||||
<ng-template #viewerExtensions>
|
||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent">
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded">
|
||||
<my-custom-xls-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-xls-component>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
|
||||
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent" >
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded">
|
||||
<my-custom-txt-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-txt-component>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
|
@ -206,22 +206,24 @@ The Viewer supports dynamically-loaded viewer preview extensions, to know more a
|
||||
#### Code extension mechanism
|
||||
|
||||
You can define your own custom handler to override supported file formats or handle other file formats that are not yet supported by
|
||||
the [Viewer render component](viewer.component.md). In order to do that first you need to define a template containing at least one `adf-viewer-extension`:
|
||||
the [Viewer render component](viewer.component.md). In order to do that first you need to define a template containing at least one `adf-viewer-extension`. `contentLoaded` should be an `EventEmitter` that will emit as soon as the component responsible for rendering finishes.
|
||||
|
||||
```html
|
||||
<ng-template #viewerExtensions>
|
||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent">
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded">
|
||||
<my-custom-xls-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-xls-component>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
|
||||
<adf-viewer-render-extension [supportedExtensions]="['txt']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent" >
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded">
|
||||
<my-custom-txt-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-txt-component>
|
||||
</ng-template>
|
||||
</adf-viewer-render-extension>
|
||||
|
@ -215,16 +215,17 @@ The Viewer supports dynamically-loaded viewer preview extensions, to know more a
|
||||
|
||||
You can define your own custom handler to override supported file formats or handle other file formats that are not yet supported by
|
||||
the [Viewer component](viewer.component.md). Below is an example that shows how to use the `adf-viewer-extension`
|
||||
to handle 3D data files:
|
||||
to handle 3D data files. `contentLoaded` should be an `EventEmitter` that will emit as soon as the component responsible for rendering finishes.
|
||||
|
||||
```html
|
||||
<adf-viewer [urlFile]="urlFile">
|
||||
<ng-template #viewerExtensions>
|
||||
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension" let-markAsLoaded="markAsLoaded">
|
||||
<threed-viewer
|
||||
[urlFile]="urlFileContent"
|
||||
[extension]="extension">
|
||||
[extension]="extension"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</threed-viewer>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
@ -239,17 +240,19 @@ You need to keep all instances of `adf-viewer-extension` inside `viewerExtension
|
||||
<adf-viewer [urlFile]="urlFile">
|
||||
<ng-template #viewerExtensions>
|
||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent">
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded">
|
||||
<my-custom-xls-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-xls-component>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
|
||||
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
||||
<ng-template let-urlFileContent="urlFileContent" >
|
||||
<ng-template let-urlFileContent="urlFileContent" let-markAsLoaded="markAsLoaded" >
|
||||
<my-custom-txt-component
|
||||
urlFileContent="urlFileContent">
|
||||
urlFileContent="urlFileContent"
|
||||
(contentLoaded)="markAsLoaded()">
|
||||
</my-custom-txt-component>
|
||||
</ng-template>
|
||||
</adf-viewer-extension>
|
||||
|
@ -42,6 +42,7 @@ describe('Text View component', () => {
|
||||
|
||||
describe('View', () => {
|
||||
it('Should text container be present with urlFile', async () => {
|
||||
spyOn(component.contentLoaded, 'emit');
|
||||
fixture.detectChanges();
|
||||
const urlFile = './fake-test-file.txt';
|
||||
const change = new SimpleChange(null, urlFile, true);
|
||||
@ -52,9 +53,11 @@ describe('Text View component', () => {
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(testingUtils.getByCSS('.adf-txt-viewer-content').nativeElement.textContent).toContain('example');
|
||||
expect(component.contentLoaded.emit).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should text container be present with Blob file', async () => {
|
||||
spyOn(component.contentLoaded, 'emit');
|
||||
const blobFile = new Blob(['text example'], { type: 'text/txt' });
|
||||
|
||||
const change = new SimpleChange(null, blobFile, true);
|
||||
@ -65,6 +68,7 @@ describe('Text View component', () => {
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(testingUtils.getByCSS('.adf-txt-viewer-content').nativeElement.textContent).toContain('example');
|
||||
expect(component.contentLoaded.emit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { AppConfigService } from '../../../app-config';
|
||||
|
||||
@Component({
|
||||
@ -34,6 +34,9 @@ export class TxtViewerComponent implements OnChanges {
|
||||
@Input()
|
||||
blobFile: Blob;
|
||||
|
||||
@Output()
|
||||
contentLoaded = new EventEmitter<void>();
|
||||
|
||||
content: string | ArrayBuffer;
|
||||
|
||||
constructor(private http: HttpClient, private appConfigService: AppConfigService) {}
|
||||
@ -67,6 +70,9 @@ export class TxtViewerComponent implements OnChanges {
|
||||
},
|
||||
(event) => {
|
||||
reject(event);
|
||||
},
|
||||
() => {
|
||||
this.contentLoaded.emit();
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -78,13 +84,17 @@ export class TxtViewerComponent implements OnChanges {
|
||||
|
||||
reader.onload = () => {
|
||||
this.content = reader.result;
|
||||
resolve();
|
||||
};
|
||||
|
||||
reader.onerror = (error: any) => {
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.onloadend = () => {
|
||||
this.contentLoaded.emit();
|
||||
resolve();
|
||||
};
|
||||
|
||||
reader.readAsText(blob);
|
||||
});
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
[extension]="externalViewer.fileExtension"
|
||||
[nodeId]="nodeId"
|
||||
[attr.data-automation-id]="externalViewer.component"
|
||||
(contentLoaded)="markAsLoaded()"
|
||||
/>
|
||||
</ng-container>
|
||||
|
||||
@ -68,7 +69,7 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'text'">
|
||||
<adf-txt-viewer [urlFile]="urlFile" [blobFile]="blobFile" />
|
||||
<adf-txt-viewer [urlFile]="urlFile" [blobFile]="blobFile" (contentLoaded)="markAsLoaded()" />
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'custom'">
|
||||
@ -80,6 +81,7 @@
|
||||
[extension]="extension"
|
||||
[nodeId]="nodeId"
|
||||
[attr.data-automation-id]="ext.component"
|
||||
(contentLoaded)="markAsLoaded()"
|
||||
/>
|
||||
</ng-container>
|
||||
|
||||
@ -87,7 +89,7 @@
|
||||
<span *ngIf="extensionTemplate.isVisible" class="adf-viewer-render-custom-content">
|
||||
<ng-template
|
||||
[ngTemplateOutlet]="extensionTemplate.template"
|
||||
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension }"
|
||||
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension, markAsLoaded: markAsLoaded.bind(this) }"
|
||||
/>
|
||||
</span>
|
||||
</ng-container>
|
||||
@ -101,5 +103,5 @@
|
||||
</div>
|
||||
}
|
||||
<ng-container *ngIf="viewerTemplateExtensions">
|
||||
<ng-template [ngTemplateOutlet]="viewerTemplateExtensions" [ngTemplateOutletInjector]="injector" />
|
||||
<ng-template [ngTemplateOutlet]="viewerTemplateExtensions" [ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension, markAsLoaded: markAsLoaded.bind(this) }" [ngTemplateOutletInjector]="injector" />
|
||||
</ng-container>
|
||||
|
@ -520,7 +520,8 @@ describe('ViewerComponent', () => {
|
||||
expect(component.viewerType).toBe('pdf');
|
||||
});
|
||||
|
||||
it('should show spinner until content is ready when viewerType is image', () => {
|
||||
it('should show spinner until renderer calls markAsLoaded', () => {
|
||||
spyOn(component, 'markAsLoaded').and.callThrough();
|
||||
component.isLoading = false;
|
||||
component.urlFile = 'some-url.png';
|
||||
|
||||
@ -534,16 +535,7 @@ describe('ViewerComponent', () => {
|
||||
|
||||
expect(getMainLoader()).toBeNull();
|
||||
expect(component.viewerType).toBe('image');
|
||||
});
|
||||
|
||||
it('should not show spinner when isLoading = false and isContentReady = false for other viewer types', () => {
|
||||
component.isLoading = false;
|
||||
component.urlFile = 'some-url.txt';
|
||||
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getMainLoader()).toBeNull();
|
||||
expect(component.markAsLoaded).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -178,10 +178,11 @@ export class ViewerRenderComponent implements OnChanges, OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
this.cacheTypeForContent = 'no-cache';
|
||||
this.setDefaultLoadingState();
|
||||
this.isLoading = true;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.isLoading = true;
|
||||
if (this.blobFile) {
|
||||
this.setUpBlobData();
|
||||
} else if (this.urlFile) {
|
||||
@ -196,6 +197,9 @@ export class ViewerRenderComponent implements OnChanges, OnInit {
|
||||
private setUpBlobData() {
|
||||
this.internalFileName = this.fileName;
|
||||
this.viewerType = this.viewUtilService.getViewerTypeByMimeType(this.blobFile.type);
|
||||
if (this.viewerType === 'unknown') {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
this.extensionChange.emit(this.blobFile.type);
|
||||
this.scrollTop();
|
||||
@ -205,6 +209,9 @@ export class ViewerRenderComponent implements OnChanges, OnInit {
|
||||
this.internalFileName = this.fileName ? this.fileName : this.viewUtilService.getFilenameFromUrl(this.urlFile);
|
||||
this.extension = this.viewUtilService.getFileExtension(this.internalFileName);
|
||||
this.viewerType = this.viewUtilService.getViewerType(this.extension, this.mimeType, this.extensionsSupportedByTemplates);
|
||||
if (this.viewerType === 'unknown') {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
this.extensionChange.emit(this.extension);
|
||||
this.scrollTop();
|
||||
@ -233,14 +240,4 @@ export class ViewerRenderComponent implements OnChanges, OnInit {
|
||||
onClose() {
|
||||
this.close.next(true);
|
||||
}
|
||||
|
||||
private canBePreviewed(): boolean {
|
||||
return this.viewerType === 'media' || this.viewerType === 'pdf' || this.viewerType === 'image';
|
||||
}
|
||||
|
||||
private setDefaultLoadingState() {
|
||||
if (this.canBePreviewed()) {
|
||||
this.isLoading = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Input, ComponentRef, OnInit, ViewChild, ViewContainerRef, OnDestroy, OnChanges } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
ComponentRef,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
OnDestroy,
|
||||
OnChanges,
|
||||
EventEmitter,
|
||||
Output,
|
||||
DestroyRef,
|
||||
inject
|
||||
} from '@angular/core';
|
||||
import { ExtensionService } from '../../services/extension.service';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-preview-extension',
|
||||
@ -43,6 +57,11 @@ export class PreviewExtensionComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@Input()
|
||||
extension: string;
|
||||
|
||||
@Output()
|
||||
contentLoaded = new EventEmitter<void>();
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
private componentRef: ComponentRef<any>;
|
||||
|
||||
constructor(private extensionService: ExtensionService) {}
|
||||
@ -73,11 +92,15 @@ export class PreviewExtensionComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
private updateInstance() {
|
||||
if (this.componentRef?.instance) {
|
||||
const instance = this.componentRef.instance;
|
||||
this.componentRef.setInput('url', this.url);
|
||||
this.componentRef.setInput('extension', this.extension);
|
||||
this.componentRef.setInput('nodeId', this.nodeId);
|
||||
|
||||
instance.url = this.url;
|
||||
instance.extension = this.extension;
|
||||
instance.nodeId = this.nodeId;
|
||||
if (this.componentRef.instance?.contentLoaded) {
|
||||
this.componentRef.instance.contentLoaded.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
||||
this.contentLoaded.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user