mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACS-6620] Proper viewer extension template projection to viewer renderer (#9273)
* [ACS-6620] Proper viewer extension template projection to viewer renderer * [ACS-6620] Use extensions instead of content for viewer config * [ACS-6620] Lint fix
This commit is contained in:
parent
5ec8228504
commit
2c627f1166
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
"features": {
|
"features": {
|
||||||
"viewer": {
|
"viewer": {
|
||||||
"content": []
|
"extensions": []
|
||||||
},
|
},
|
||||||
|
|
||||||
"documentList": {
|
"documentList": {
|
||||||
|
@ -237,47 +237,48 @@ The Viewer supports dynamically-loaded viewer preview extensions, to know more a
|
|||||||
|
|
||||||
#### Code extension mechanism]
|
#### Code extension mechanism]
|
||||||
|
|
||||||
You can define your own custom handler to handle other file formats that are not yet supported by
|
You can define your own custom handler to override supported file formats or handle other file formats that are not yet supported by
|
||||||
the [Alfresco Viewer component](viewer.component.md). Below is an example that shows how to use the `adf-viewer-extension`
|
the [Alfresco 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:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<adf-alfresco-viewer [nodeId]="nodeId">
|
<adf-alfresco-viewer [nodeId]="nodeId">
|
||||||
|
<ng-template #viewerExtensions>
|
||||||
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
||||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
||||||
<threed-viewer
|
<threed-viewer
|
||||||
[urlFile]="urlFileContent"
|
[urlFile]="urlFileContent"
|
||||||
[extension]="extension">
|
[extension]="extension">
|
||||||
</threed-viewer>
|
</threed-viewer>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</adf-viewer-extension>
|
</adf-viewer-extension>
|
||||||
|
</ng-template>
|
||||||
</adf-alfresco-viewer>
|
</adf-alfresco-viewer>
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: you need to add the `ng2-3d-editor` dependency to your `package.json` file to make the example above work.
|
Note: you need to add the `ng2-3d-editor` dependency to your `package.json` file to make the example above work.
|
||||||
|
|
||||||
You can define multiple `adf-viewer-extension` templates if required:
|
You need to keep all instances of `adf-viewer-extension` inside `viewerExtensions` template, also you can define multiple `adf-viewer-extension` templates if required:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<adf-alfresco-viewer [nodeId]="nodeId">
|
<adf-alfresco-viewer [nodeId]="nodeId">
|
||||||
|
<ng-template #viewerExtensions>
|
||||||
|
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||||
|
<ng-template let-urlFileContent="urlFileContent">
|
||||||
|
<my-custom-xls-component
|
||||||
|
urlFileContent="urlFileContent">
|
||||||
|
</my-custom-xls-component>
|
||||||
|
</ng-template>
|
||||||
|
</adf-viewer-extension>
|
||||||
|
|
||||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
||||||
<ng-template let-urlFileContent="urlFileContent">
|
<ng-template let-urlFileContent="urlFileContent" >
|
||||||
<my-custom-xls-component
|
<my-custom-txt-component
|
||||||
urlFileContent="urlFileContent">
|
urlFileContent="urlFileContent">
|
||||||
</my-custom-xls-component>
|
</my-custom-txt-component>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</adf-viewer-extension>
|
</adf-viewer-extension>
|
||||||
|
</ng-template>
|
||||||
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
|
||||||
<ng-template let-urlFileContent="urlFileContent" >
|
|
||||||
<my-custom-txt-component
|
|
||||||
urlFileContent="urlFileContent">
|
|
||||||
</my-custom-txt-component>
|
|
||||||
</ng-template>
|
|
||||||
</adf-viewer-extension>
|
|
||||||
</adf-alfresco-viewer>
|
</adf-alfresco-viewer>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ Using with file [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob):
|
|||||||
| thumbnailsTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the pdf thumbnails. |
|
| thumbnailsTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the pdf thumbnails. |
|
||||||
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
|
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
|
||||||
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
|
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
|
||||||
|
| viewerTemplateExtensions | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
@ -200,34 +201,13 @@ The [Viewer render component](viewer.component.md) should now be able to display
|
|||||||
|
|
||||||
The Viewer supports dynamically-loaded viewer preview extensions, to know more about it [Preview Extension component](../../extensions/components/preview-extension.component.md). This
|
The Viewer supports dynamically-loaded viewer preview extensions, to know more about it [Preview Extension component](../../extensions/components/preview-extension.component.md). This
|
||||||
|
|
||||||
#### Code extension mechanism]
|
#### Code extension mechanism
|
||||||
|
|
||||||
You can define your own custom handler to handle other file formats that are not yet supported by
|
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). Below is an example that shows how to use the `adf-viewer-render-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`:
|
||||||
to handle 3D data files:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<adf-viewer-render [nodeId]="nodeId">
|
|
||||||
|
|
||||||
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
|
||||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
|
||||||
<threed-viewer
|
|
||||||
[urlFile]="urlFileContent"
|
|
||||||
[extension]="extension">
|
|
||||||
</threed-viewer>
|
|
||||||
</ng-template>
|
|
||||||
</adf-viewer-extension>
|
|
||||||
|
|
||||||
</adf-viewer-render>
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: you need to add the `ng2-3d-editor` dependency to your `package.json` file to make the example above work.
|
|
||||||
|
|
||||||
You can define multiple `adf-viewer-render-extension` templates if required:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<adf-viewer-render [nodeId]="nodeId">
|
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ng-template #viewerExtensions>
|
||||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||||
<ng-template let-urlFileContent="urlFileContent">
|
<ng-template let-urlFileContent="urlFileContent">
|
||||||
<my-custom-xls-component
|
<my-custom-xls-component
|
||||||
@ -243,6 +223,22 @@ You can define multiple `adf-viewer-render-extension` templates if required:
|
|||||||
</my-custom-txt-component>
|
</my-custom-txt-component>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</adf-viewer-render-extension>
|
</adf-viewer-render-extension>
|
||||||
|
</ng-template>
|
||||||
|
```
|
||||||
|
|
||||||
|
Next in your component you need to get a reference of created template
|
||||||
|
|
||||||
|
```ts
|
||||||
|
@ViewChild('viewerExtensions')
|
||||||
|
viewerTemplateExtensions: TemplateRef<any>;
|
||||||
|
```
|
||||||
|
|
||||||
|
and pass it via `viewerTemplateExtensions` input:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<adf-viewer-render>
|
||||||
|
...
|
||||||
|
[viewerTemplateExtensions]="viewerTemplateExtensions"
|
||||||
</adf-viewer-render>
|
</adf-viewer-render>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
|
|||||||
| sidebarRightTemplateContext | | null | Context object available for binding by the local sidebarRightTemplate with let declarations. |
|
| sidebarRightTemplateContext | | null | Context object available for binding by the local sidebarRightTemplate with let declarations. |
|
||||||
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
|
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
|
||||||
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
|
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
|
||||||
|
| viewerExtensions | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
@ -209,47 +210,47 @@ The Viewer supports dynamically-loaded viewer preview extensions, to know more a
|
|||||||
|
|
||||||
#### Code extension mechanism]
|
#### Code extension mechanism]
|
||||||
|
|
||||||
You can define your own custom handler to handle other file formats that are not yet supported by
|
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`
|
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:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<adf-viewer [urlFile]="urlFile">
|
<adf-viewer [urlFile]="urlFile">
|
||||||
|
<ng-template #viewerExtensions>
|
||||||
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
<adf-viewer-extension [supportedExtensions]="['obj','3ds']" #extension>
|
||||||
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
<ng-template let-urlFileContent="urlFileContent" let-extension="extension">
|
||||||
<threed-viewer
|
<threed-viewer
|
||||||
[urlFile]="urlFileContent"
|
[urlFile]="urlFileContent"
|
||||||
[extension]="extension">
|
[extension]="extension">
|
||||||
</threed-viewer>
|
</threed-viewer>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</adf-viewer-extension>
|
</adf-viewer-extension>
|
||||||
|
</ng-template>
|
||||||
</adf-viewer>
|
</adf-viewer>
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: you need to add the `ng2-3d-editor` dependency to your `package.json` file to make the example above work.
|
Note: you need to add the `ng2-3d-editor` dependency to your `package.json` file to make the example above work.
|
||||||
|
|
||||||
You can define multiple `adf-viewer-extension` templates if required:
|
You need to keep all instances of `adf-viewer-extension` inside `viewerExtensions` template, also you can define multiple `adf-viewer-extension` templates if required:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<adf-viewer [urlFile]="urlFile">
|
<adf-viewer [urlFile]="urlFile">
|
||||||
|
<ng-template #viewerExtensions>
|
||||||
|
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
||||||
|
<ng-template let-urlFileContent="urlFileContent">
|
||||||
|
<my-custom-xls-component
|
||||||
|
urlFileContent="urlFileContent">
|
||||||
|
</my-custom-xls-component>
|
||||||
|
</ng-template>
|
||||||
|
</adf-viewer-extension>
|
||||||
|
|
||||||
<adf-viewer-extension [supportedExtensions]="['xls','xlsx']" #extension>
|
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
||||||
<ng-template let-urlFileContent="urlFileContent">
|
<ng-template let-urlFileContent="urlFileContent" >
|
||||||
<my-custom-xls-component
|
<my-custom-txt-component
|
||||||
urlFileContent="urlFileContent">
|
urlFileContent="urlFileContent">
|
||||||
</my-custom-xls-component>
|
</my-custom-txt-component>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</adf-viewer-extension>
|
</adf-viewer-extension>
|
||||||
|
</ng-template>
|
||||||
<adf-viewer-extension [supportedExtensions]="['txt']" #extension>
|
|
||||||
<ng-template let-urlFileContent="urlFileContent" >
|
|
||||||
<my-custom-txt-component
|
|
||||||
urlFileContent="urlFileContent">
|
|
||||||
</my-custom-txt-component>
|
|
||||||
</ng-template>
|
|
||||||
</adf-viewer-extension>
|
|
||||||
</adf-viewer>
|
</adf-viewer>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
[urlFile]="urlFileContent"
|
[urlFile]="urlFileContent"
|
||||||
[tracks]="tracks"
|
[tracks]="tracks"
|
||||||
[readOnly]="readOnly"
|
[readOnly]="readOnly"
|
||||||
|
[viewerExtensions]="viewerExtensions"
|
||||||
(downloadFile)="onDownloadFile()"
|
(downloadFile)="onDownloadFile()"
|
||||||
(navigateBefore)="onNavigateBeforeClick($event)"
|
(navigateBefore)="onNavigateBeforeClick($event)"
|
||||||
(navigateNext)="onNavigateNextClick($event)"
|
(navigateNext)="onNavigateNextClick($event)"
|
||||||
|
@ -80,6 +80,9 @@ export class AlfrescoViewerComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
@ContentChild(ViewerOpenWithComponent)
|
@ContentChild(ViewerOpenWithComponent)
|
||||||
openWith: ViewerOpenWithComponent;
|
openWith: ViewerOpenWithComponent;
|
||||||
|
|
||||||
|
@ContentChild('viewerExtensions', { static: false })
|
||||||
|
viewerExtensions: TemplateRef<any>;
|
||||||
|
|
||||||
/** Node Id of the file to load. */
|
/** Node Id of the file to load. */
|
||||||
@Input()
|
@Input()
|
||||||
nodeId: string = null;
|
nodeId: string = null;
|
||||||
|
@ -79,13 +79,13 @@
|
|||||||
</adf-preview-extension>
|
</adf-preview-extension>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<span class="adf-viewer-render-custom-content"
|
<ng-container *ngFor="let extensionTemplate of extensionTemplates">
|
||||||
*ngFor="let extensionTemplate of extensionTemplates">
|
<span *ngIf="extensionTemplate.isVisible" class="adf-viewer-render-custom-content">
|
||||||
<ng-template *ngIf="extensionTemplate.isVisible"
|
<ng-template [ngTemplateOutlet]="extensionTemplate.template"
|
||||||
[ngTemplateOutlet]="extensionTemplate.template"
|
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension }">
|
||||||
[ngTemplateOutletContext]="{ urlFile: urlFile, extension:extension }">
|
</ng-template>
|
||||||
</ng-template>
|
</span>
|
||||||
</span>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngSwitchDefault>
|
<ng-container *ngSwitchDefault>
|
||||||
@ -94,3 +94,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ng-container *ngIf="viewerTemplateExtensions">
|
||||||
|
<ng-template [ngTemplateOutlet]="viewerTemplateExtensions" [ngTemplateOutletInjector]="injector"></ng-template>
|
||||||
|
</ng-container>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { SpyLocation } from '@angular/common/testing';
|
import { SpyLocation } from '@angular/common/testing';
|
||||||
import { Component, ViewChild } from '@angular/core';
|
import { Component, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { RenderingQueueServices } from '../services/rendering-queue.services';
|
import { RenderingQueueServices } from '../services/rendering-queue.services';
|
||||||
import { ViewerRenderComponent } from './viewer-render.component';
|
import { ViewerRenderComponent } from './viewer-render.component';
|
||||||
@ -33,8 +33,20 @@ import { By } from '@angular/platform-browser';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-double-viewer',
|
selector: 'adf-double-viewer',
|
||||||
template: `
|
template: `
|
||||||
<adf-viewer-render [urlFile]="urlFileViewer1" #viewer1></adf-viewer-render>
|
<adf-viewer-render [urlFile]="urlFileViewer1" [viewerTemplateExtensions]="viewerTemplateExtensions" #viewer1></adf-viewer-render>
|
||||||
<adf-viewer-render [urlFile]="urlFileViewer2" #viewer2></adf-viewer-render>
|
<adf-viewer-render [urlFile]="urlFileViewer2" #viewer2></adf-viewer-render>
|
||||||
|
<ng-template #viewerExtension>
|
||||||
|
<adf-viewer-extension [supportedExtensions]="['json']">
|
||||||
|
<ng-template>
|
||||||
|
<h1>JSON Viewer</h1>
|
||||||
|
</ng-template>
|
||||||
|
</adf-viewer-extension>
|
||||||
|
<adf-viewer-extension [supportedExtensions]="['test']">
|
||||||
|
<ng-template>
|
||||||
|
<h1>Test Viewer</h1>
|
||||||
|
</ng-template>
|
||||||
|
</adf-viewer-extension>
|
||||||
|
</ng-template>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
class DoubleViewerComponent {
|
class DoubleViewerComponent {
|
||||||
@ -44,6 +56,9 @@ class DoubleViewerComponent {
|
|||||||
@ViewChild('viewer2')
|
@ViewChild('viewer2')
|
||||||
viewer2: ViewerRenderComponent;
|
viewer2: ViewerRenderComponent;
|
||||||
|
|
||||||
|
@ViewChild('viewerExtension', { static: true })
|
||||||
|
viewerTemplateExtensions: TemplateRef<any>;
|
||||||
|
|
||||||
urlFileViewer1: string;
|
urlFileViewer1: string;
|
||||||
urlFileViewer2: string;
|
urlFileViewer2: string;
|
||||||
|
|
||||||
@ -261,6 +276,42 @@ describe('ViewerComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Custom viewer extension template', () => {
|
||||||
|
const getCustomViewerContent = (customFixture: ComponentFixture<DoubleViewerComponent>): HTMLHeadingElement =>
|
||||||
|
customFixture.debugElement.query(By.css('.adf-viewer-render-custom-content h1')).nativeElement;
|
||||||
|
|
||||||
|
it('should render provided custom template when file type matches supported extensions', async () => {
|
||||||
|
const fixtureCustom = TestBed.createComponent(DoubleViewerComponent);
|
||||||
|
fixtureCustom.detectChanges();
|
||||||
|
await fixtureCustom.whenStable();
|
||||||
|
|
||||||
|
const customComponent = fixtureCustom.componentInstance.viewer1;
|
||||||
|
fixtureCustom.componentInstance.urlFileViewer1 = 'fake-url-file.json';
|
||||||
|
customComponent.ngOnChanges();
|
||||||
|
|
||||||
|
fixtureCustom.detectChanges();
|
||||||
|
await fixtureCustom.whenStable();
|
||||||
|
|
||||||
|
let customContent = getCustomViewerContent(fixtureCustom);
|
||||||
|
expect(customComponent.extensionsSupportedByTemplates).toEqual(['json', 'test']);
|
||||||
|
expect(customComponent.extensionTemplates.length).toBe(2);
|
||||||
|
expect(customComponent.extensionTemplates[0].isVisible).toBeTrue();
|
||||||
|
expect(customComponent.extensionTemplates[1].isVisible).toBeFalse();
|
||||||
|
expect(customContent.innerText).toBe('JSON Viewer');
|
||||||
|
|
||||||
|
fixtureCustom.componentInstance.urlFileViewer1 = 'fake-url-file.test';
|
||||||
|
customComponent.ngOnChanges();
|
||||||
|
|
||||||
|
fixtureCustom.detectChanges();
|
||||||
|
await fixtureCustom.whenStable();
|
||||||
|
|
||||||
|
customContent = getCustomViewerContent(fixtureCustom);
|
||||||
|
expect(customComponent.extensionTemplates[0].isVisible).toBeFalse();
|
||||||
|
expect(customComponent.extensionTemplates[1].isVisible).toBeTrue();
|
||||||
|
expect(customContent.innerText).toBe('Test Viewer');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('MimeType handling', () => {
|
describe('MimeType handling', () => {
|
||||||
it('should display an image file identified by mimetype when the filename has no extension', (done) => {
|
it('should display an image file identified by mimetype when the filename has no extension', (done) => {
|
||||||
component.urlFile = 'fake-content-img';
|
component.urlFile = 'fake-content-img';
|
||||||
@ -338,7 +389,6 @@ describe('ViewerComponent', () => {
|
|||||||
expect(element.querySelector('adf-pdf-viewer')).not.toBeNull();
|
expect(element.querySelector('adf-pdf-viewer')).not.toBeNull();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
}, 25000);
|
}, 25000);
|
||||||
|
|
||||||
it('should display a PDF file identified by mimetype when the file extension is wrong', (done) => {
|
it('should display a PDF file identified by mimetype when the file extension is wrong', (done) => {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
import {
|
import {
|
||||||
Component, EventEmitter,
|
Component, EventEmitter,
|
||||||
Input, OnChanges, Output, TemplateRef,
|
Input, OnChanges, Output, TemplateRef,
|
||||||
ViewEncapsulation, OnInit, OnDestroy
|
ViewEncapsulation, OnInit, OnDestroy, Injector
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { ViewUtilService } from '../services/view-util.service';
|
import { ViewUtilService } from '../services/view-util.service';
|
||||||
@ -79,6 +79,10 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
@Input()
|
@Input()
|
||||||
tracks: Track[] = [];
|
tracks: Track[] = [];
|
||||||
|
|
||||||
|
/** Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. */
|
||||||
|
@Input()
|
||||||
|
viewerTemplateExtensions: TemplateRef<any>;
|
||||||
|
|
||||||
/** Emitted when the filename extension changes. */
|
/** Emitted when the filename extension changes. */
|
||||||
@Output()
|
@Output()
|
||||||
extensionChange = new EventEmitter<string>();
|
extensionChange = new EventEmitter<string>();
|
||||||
@ -96,6 +100,7 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
isSaving = new EventEmitter<boolean>();
|
isSaving = new EventEmitter<boolean>();
|
||||||
|
|
||||||
extensionTemplates: { template: TemplateRef<any>; isVisible: boolean }[] = [];
|
extensionTemplates: { template: TemplateRef<any>; isVisible: boolean }[] = [];
|
||||||
|
extensionsSupportedByTemplates: string[] = [];
|
||||||
extension: string;
|
extension: string;
|
||||||
internalFileName: string;
|
internalFileName: string;
|
||||||
viewerType: string = 'unknown';
|
viewerType: string = 'unknown';
|
||||||
@ -133,7 +138,8 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(private viewUtilService: ViewUtilService,
|
constructor(private viewUtilService: ViewUtilService,
|
||||||
private extensionService: AppExtensionService,
|
private extensionService: AppExtensionService,
|
||||||
public dialog: MatDialog) {
|
public dialog: MatDialog,
|
||||||
|
public readonly injector: Injector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -166,7 +172,7 @@ export class ViewerRenderComponent implements OnChanges, OnInit, OnDestroy {
|
|||||||
private setUpUrlFile() {
|
private setUpUrlFile() {
|
||||||
this.internalFileName = this.fileName ? this.fileName : this.viewUtilService.getFilenameFromUrl(this.urlFile);
|
this.internalFileName = this.fileName ? this.fileName : this.viewUtilService.getFilenameFromUrl(this.urlFile);
|
||||||
this.extension = this.viewUtilService.getFileExtension(this.internalFileName);
|
this.extension = this.viewUtilService.getFileExtension(this.internalFileName);
|
||||||
this.viewerType = this.viewUtilService.getViewerType(this.extension, this.mimeType);
|
this.viewerType = this.viewUtilService.getViewerType(this.extension, this.mimeType, this.extensionsSupportedByTemplates);
|
||||||
|
|
||||||
this.extensionChange.emit(this.extension);
|
this.extensionChange.emit(this.extension);
|
||||||
this.scrollTop();
|
this.scrollTop();
|
||||||
|
@ -171,7 +171,8 @@
|
|||||||
(submitFile)="onSubmitFile($event)"
|
(submitFile)="onSubmitFile($event)"
|
||||||
[urlFile]="urlFile"
|
[urlFile]="urlFile"
|
||||||
(isSaving)="allowNavigate = !$event"
|
(isSaving)="allowNavigate = !$event"
|
||||||
[tracks]="tracks">
|
[tracks]="tracks"
|
||||||
|
[viewerTemplateExtensions]="viewerExtensions ?? viewerTemplateExtensions">
|
||||||
</adf-viewer-render>
|
</adf-viewer-render>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -71,6 +71,9 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
|||||||
@ContentChild(ViewerMoreActionsComponent)
|
@ContentChild(ViewerMoreActionsComponent)
|
||||||
mnuMoreActions: ViewerMoreActionsComponent;
|
mnuMoreActions: ViewerMoreActionsComponent;
|
||||||
|
|
||||||
|
@ContentChild('viewerExtensions', { static: false })
|
||||||
|
viewerTemplateExtensions: TemplateRef<any>;
|
||||||
|
|
||||||
get CloseButtonPosition() {
|
get CloseButtonPosition() {
|
||||||
return CloseButtonPosition;
|
return CloseButtonPosition;
|
||||||
}
|
}
|
||||||
@ -190,6 +193,10 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
hideInfoButton = false;
|
hideInfoButton = false;
|
||||||
|
|
||||||
|
/** Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. */
|
||||||
|
@Input()
|
||||||
|
viewerExtensions: TemplateRef<any>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable dialog box to allow user to download the previewed file, in case the preview is not responding for a set period of time.
|
* Enable dialog box to allow user to download the previewed file, in case the preview is not responding for a set period of time.
|
||||||
*/
|
*/
|
||||||
|
@ -26,6 +26,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
|
|
||||||
describe('ExtensionViewerDirective', () => {
|
describe('ExtensionViewerDirective', () => {
|
||||||
let extensionViewerDirective: ViewerExtensionDirective;
|
let extensionViewerDirective: ViewerExtensionDirective;
|
||||||
|
let viewerRenderer: ViewerRenderComponent;
|
||||||
|
|
||||||
class MockElementRef extends ElementRef {
|
class MockElementRef extends ElementRef {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -42,12 +43,13 @@ describe('ExtensionViewerDirective', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: Location, useClass: SpyLocation },
|
{ provide: Location, useClass: SpyLocation },
|
||||||
ViewerExtensionDirective,
|
ViewerExtensionDirective,
|
||||||
{provide: ElementRef, useClass: MockElementRef},
|
{ provide: ElementRef, useClass: MockElementRef },
|
||||||
ViewerRenderComponent,
|
ViewerRenderComponent,
|
||||||
{ provide: ChangeDetectorRef, useValue: { detectChanges: () => {} } }
|
{ provide: ChangeDetectorRef, useValue: { detectChanges: () => {} } }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
extensionViewerDirective = TestBed.inject(ViewerExtensionDirective);
|
extensionViewerDirective = TestBed.inject(ViewerExtensionDirective);
|
||||||
|
viewerRenderer = TestBed.inject(ViewerRenderComponent);
|
||||||
extensionViewerDirective.templateModel = {template: '', isVisible: false};
|
extensionViewerDirective.templateModel = {template: '', isVisible: false};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,4 +66,12 @@ describe('ExtensionViewerDirective', () => {
|
|||||||
extensionViewerDirective.supportedExtensions = ['xls', 'sts'];
|
extensionViewerDirective.supportedExtensions = ['xls', 'sts'];
|
||||||
expect(extensionViewerDirective.isVisible('png')).not.toBeTruthy();
|
expect(extensionViewerDirective.isVisible('png')).not.toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set correct template and supported extensions in viewer renderer component', () => {
|
||||||
|
extensionViewerDirective.supportedExtensions = ['png', 'txt'];
|
||||||
|
extensionViewerDirective.ngAfterContentInit();
|
||||||
|
expect(viewerRenderer.extensionTemplates.length).toBe(1);
|
||||||
|
expect(viewerRenderer.extensionTemplates[0]).toEqual(extensionViewerDirective.templateModel);
|
||||||
|
expect(viewerRenderer.extensionsSupportedByTemplates).toEqual(extensionViewerDirective.supportedExtensions);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -46,7 +46,7 @@ export class ViewerExtensionDirective implements AfterContentInit, OnDestroy {
|
|||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
this.templateModel = { template: this.template, isVisible: false };
|
this.templateModel = { template: this.template, isVisible: false };
|
||||||
|
this.viewerComponent.extensionsSupportedByTemplates.push(...this.supportedExtensions);
|
||||||
this.viewerComponent.extensionTemplates.push(this.templateModel);
|
this.viewerComponent.extensionTemplates.push(this.templateModel);
|
||||||
|
|
||||||
this.viewerComponent.extensionChange
|
this.viewerComponent.extensionChange
|
||||||
@ -54,12 +54,6 @@ export class ViewerExtensionDirective implements AfterContentInit, OnDestroy {
|
|||||||
.subscribe(fileExtension => {
|
.subscribe(fileExtension => {
|
||||||
this.templateModel.isVisible = this.isVisible(fileExtension);
|
this.templateModel.isVisible = this.isVisible(fileExtension);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.supportedExtensions instanceof Array) {
|
|
||||||
this.supportedExtensions.forEach((extension) => {
|
|
||||||
this.viewerComponent.externalExtensions.push(extension);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
78
lib/core/src/lib/viewer/services/view-util.service.spec.ts
Normal file
78
lib/core/src/lib/viewer/services/view-util.service.spec.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 { AppExtensionService } from '@alfresco/adf-extensions';
|
||||||
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { ViewUtilService } from './view-util.service';
|
||||||
|
|
||||||
|
describe('ViewUtilService', () => {
|
||||||
|
let viewUtilService: ViewUtilService;
|
||||||
|
let appExtensionService: AppExtensionService;
|
||||||
|
const extensionsSupportedByTemplates = ['dmn', 'txt'];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [HttpClientTestingModule],
|
||||||
|
providers: [AppExtensionService]
|
||||||
|
});
|
||||||
|
|
||||||
|
viewUtilService = TestBed.inject(ViewUtilService);
|
||||||
|
appExtensionService = TestBed.inject(AppExtensionService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extract file name from url', () => {
|
||||||
|
expect(viewUtilService.getFilenameFromUrl('http://localhost/test.jpg?cache=1000')).toBe('test.jpg');
|
||||||
|
expect(viewUtilService.getFilenameFromUrl('http://localhost:4200/test-path/test2.json#cache=1000')).toBe('test2.json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extract file extension from url', () => {
|
||||||
|
expect(viewUtilService.getFileExtension('http://localhost/test.jpg?cache=1000')).toBe('jpg');
|
||||||
|
expect(viewUtilService.getFileExtension('http://localhost:4200/test-path/test2.json#cache=1000')).toBe('json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct viewer type based on file mime type', () => {
|
||||||
|
expect(viewUtilService.getViewerTypeByMimeType('text/plain')).toBe('text');
|
||||||
|
expect(viewUtilService.getViewerTypeByMimeType('application/pdf')).toBe('pdf');
|
||||||
|
expect(viewUtilService.getViewerTypeByMimeType('image/gif')).toBe('image');
|
||||||
|
expect(viewUtilService.getViewerTypeByMimeType('video/webm')).toBe('media');
|
||||||
|
expect(viewUtilService.getViewerTypeByMimeType('image/test')).toBe('unknown');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check if extension is custom one added either by extension service or by a template in viewer renderer', () => {
|
||||||
|
spyOn(appExtensionService, 'getViewerExtensions').and.returnValue([{ fileExtension: 'json', component: 'test', id: 'test' }]);
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('pdf')).toBeFalse();
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('txt')).toBeFalse();
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('json')).toBeTrue();
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('docx', extensionsSupportedByTemplates)).toBeFalse();
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('dmn', extensionsSupportedByTemplates)).toBeTrue();
|
||||||
|
expect(viewUtilService.isCustomViewerExtension('txt', extensionsSupportedByTemplates)).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct viewer type based on extension and mime type', () => {
|
||||||
|
spyOn(appExtensionService, 'getViewerExtensions').and.returnValue([{ fileExtension: '*', component: 'test', id: 'test' }]);
|
||||||
|
expect(viewUtilService.getViewerType('pdf', 'application/pdf')).toBe('external');
|
||||||
|
|
||||||
|
appExtensionService.getViewerExtensions = jasmine.createSpy().and.returnValue([{ fileExtension: 'json', component: 'test', id: 'test' }]);
|
||||||
|
expect(viewUtilService.getViewerType('json', '')).toBe('custom');
|
||||||
|
expect(viewUtilService.getViewerType('dmn', '')).toBe('unknown');
|
||||||
|
expect(viewUtilService.getViewerType('dmn', '', extensionsSupportedByTemplates)).toBe('custom');
|
||||||
|
|
||||||
|
expect(viewUtilService.getViewerType('pdf', '')).toBe('pdf');
|
||||||
|
expect(viewUtilService.getViewerType('', 'application/pdf')).toBe('pdf');
|
||||||
|
});
|
||||||
|
});
|
@ -88,8 +88,8 @@ export class ViewUtilService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getViewerType(extension: string, mimeType: string): string {
|
getViewerType(extension: string, mimeType: string, extensionsSupportedByTemplates?: string[]): string {
|
||||||
let viewerType = this.getViewerTypeByExtension(extension);
|
let viewerType = this.getViewerTypeByExtension(extension, extensionsSupportedByTemplates);
|
||||||
|
|
||||||
if (viewerType === 'unknown') {
|
if (viewerType === 'unknown') {
|
||||||
viewerType = this.getViewerTypeByMimeType(mimeType);
|
viewerType = this.getViewerTypeByMimeType(mimeType);
|
||||||
@ -112,7 +112,7 @@ export class ViewUtilService {
|
|||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
private getViewerTypeByExtension(extension: string): string {
|
private getViewerTypeByExtension(extension: string, extensionsSupportedByTemplates?: string[]): string {
|
||||||
if (extension) {
|
if (extension) {
|
||||||
extension = extension.toLowerCase();
|
extension = extension.toLowerCase();
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ export class ViewUtilService {
|
|||||||
return 'external';
|
return 'external';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isCustomViewerExtension(extension)) {
|
if (this.isCustomViewerExtension(extension, extensionsSupportedByTemplates)) {
|
||||||
return 'custom';
|
return 'custom';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +148,11 @@ export class ViewUtilService {
|
|||||||
return !!this.viewerExtensions.find((ext) => ext.fileExtension === '*');
|
return !!this.viewerExtensions.find((ext) => ext.fileExtension === '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
isCustomViewerExtension(extension: string): boolean {
|
isCustomViewerExtension(extension: string, extensionsSupportedByTemplates?: string[]): boolean {
|
||||||
const extensions = this.externalExtensions || [];
|
const extensions = this.externalExtensions || [];
|
||||||
|
if (extensionsSupportedByTemplates) {
|
||||||
|
extensions.push(...extensionsSupportedByTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
if (extension && extensions.length > 0) {
|
if (extension && extensions.length > 0) {
|
||||||
extension = extension.toLowerCase();
|
extension = extension.toLowerCase();
|
||||||
|
@ -72,7 +72,7 @@ export class AppExtensionService {
|
|||||||
*/
|
*/
|
||||||
getViewerExtensions(): ViewerExtensionRef[] {
|
getViewerExtensions(): ViewerExtensionRef[] {
|
||||||
return this.extensionService
|
return this.extensionService
|
||||||
.getElements<ViewerExtensionRef>('features.viewer.content')
|
.getElements<ViewerExtensionRef>('features.viewer.extensions')
|
||||||
.filter((extension) => !this.isViewerExtensionDisabled(extension));
|
.filter((extension) => !this.isViewerExtensionDisabled(extension));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ export class ExtensionLoaderService {
|
|||||||
* Retrieves configuration elements.
|
* Retrieves configuration elements.
|
||||||
* Filters element by **enabled** and **order** attributes.
|
* Filters element by **enabled** and **order** attributes.
|
||||||
* Example:
|
* Example:
|
||||||
* `getElements<ViewerExtensionRef>(config, 'features.viewer.content')`
|
* `getElements<ViewerExtensionRef>(config, 'features.viewer.extensions')`
|
||||||
*
|
*
|
||||||
* @param config configuration settings
|
* @param config configuration settings
|
||||||
* @param key element key
|
* @param key element key
|
||||||
|
Loading…
x
Reference in New Issue
Block a user