Dev eromano external viewer (#1636)

* add extensibility point to add a custom viewer

* documentation and tests

* add example in document list
This commit is contained in:
Eugenio Romano
2017-02-16 09:50:12 +00:00
committed by Mario Romano
parent e3ce65880f
commit 59cbbcbe4d
30 changed files with 309 additions and 83 deletions

View File

@@ -35,6 +35,7 @@ import { AnalyticsModule } from 'ng2-activiti-analytics';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { routing } from './app.routes'; import { routing } from './app.routes';
import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component'; import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component';
import { Editor3DModule } from 'ng2-3d-editor';
import { import {
HomeComponent, HomeComponent,
@@ -71,7 +72,8 @@ import {
ActivitiProcessListModule.forRoot(), ActivitiProcessListModule.forRoot(),
UserInfoComponentModule.forRoot(), UserInfoComponentModule.forRoot(),
AnalyticsModule.forRoot(), AnalyticsModule.forRoot(),
CustomEditorsModule CustomEditorsModule,
Editor3DModule.forRoot()
], ],
declarations: [ declarations: [
AppComponent, AppComponent,

View File

@@ -174,7 +174,13 @@
<alfresco-viewer [(showViewer)]="fileShowed" <alfresco-viewer [(showViewer)]="fileShowed"
[fileNodeId]="fileNodeId" [fileNodeId]="fileNodeId"
[overlayMode]="true"> [overlayMode]="true">
<div class="mdl-spinner mdl-js-spinner is-active"></div>
<extension-viewer [supportedExtensions]="['obj','3DS']" #extension>
<template let-urlFileContent="urlFileContent" let-extension="extension" >
<threed-viewer [urlFile]="urlFileContent" [extension]="extension" ></threed-viewer>
</template>
</extension-viewer>
</alfresco-viewer> </alfresco-viewer>
</div> </div>

View File

@@ -62,3 +62,4 @@ if (process.env.ENV === 'production') {
} }
require('pdfjs-dist/web/pdf_viewer.js'); require('pdfjs-dist/web/pdf_viewer.js');
require('three/build/three.min.js');

View File

@@ -79,6 +79,7 @@
"raphael": "^2.2.6", "raphael": "^2.2.6",
"md-date-time-picker": "^2.2.0", "md-date-time-picker": "^2.2.0",
"alfresco-js-api": "~1.1.0", "alfresco-js-api": "~1.1.0",
"ng2-3d-editor": "0.0.15",
"ng2-activiti-analytics": "1.1.0", "ng2-activiti-analytics": "1.1.0",
"ng2-alfresco-core": "1.1.0", "ng2-alfresco-core": "1.1.0",
"ng2-alfresco-datatable": "1.1.0", "ng2-alfresco-datatable": "1.1.0",
@@ -97,8 +98,8 @@
"element.scrollintoviewifneeded-polyfill": "^1.0.1" "element.scrollintoviewifneeded-polyfill": "^1.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jasmine": "^2.5.35", "@types/jasmine": "2.5.35",
"@types/node": "^6.0.45", "@types/node": "6.0.45",
"angular2-template-loader": "^0.6.0", "angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "^2.2.4", "awesome-typescript-loader": "^2.2.4",
"classlist-polyfill": "^1.0.3", "classlist-polyfill": "^1.0.3",

View File

@@ -71,7 +71,7 @@ export class AlfrescoLoginComponent implements OnInit {
formError: { [id: string]: string }; formError: { [id: string]: string };
minLenght: number = 2; minLength: number = 2;
footerTemplate: TemplateRef<any>; footerTemplate: TemplateRef<any>;
@@ -299,14 +299,14 @@ export class AlfrescoLoginComponent implements OnInit {
} }
}; };
this.translateService.get('LOGIN.MESSAGES.USERNAME-MIN', {minLenght: this.minLenght}).subscribe((res: string) => { this.translateService.get('LOGIN.MESSAGES.USERNAME-MIN', {minLength: this.minLength}).subscribe((res: string) => {
this._message['username']['minlength'] = res; this._message['username']['minlength'] = res;
}); });
} }
private initFormFieldsDefault() { private initFormFieldsDefault() {
this.form = this._fb.group({ this.form = this._fb.group({
username: ['', Validators.compose([Validators.required, Validators.minLength(this.minLenght)])], username: ['', Validators.compose([Validators.required, Validators.minLength(this.minLength)])],
password: ['', Validators.required] password: ['', Validators.required]
}); });
} }

View File

@@ -223,7 +223,44 @@ Media | Mp4, WebM, Ogv
Images | png, jpg, jpeg, gif, bmp Images | png, jpg, jpeg, gif, bmp
Text | pdf Text | pdf
# Custom extension handler
If you want handle other file formats that are not yet supported by the ng2-alfresco-viewer you can define your own custom handler.
Above you can find an example where with the use of ``` extension-viewer ``` if you can handle 3d files
```html
<alfresco-viewer [(showViewer)]="fileShowed"
[fileNodeId]="fileNodeId"
[overlayMode]="true">
<extension-viewer [supportedExtensions]="['obj','3ds']" #extension>
<template let-urlFileContent="urlFileContent" let-extension="extension" >
<threed-viewer [urlFile]="urlFileContent" [extension]="extension" ></threed-viewer>
</template>
</extension-viewer>
</alfresco-viewer>
```
Note: In order to make the example above works you need to add in your package.json the dependency to ng2-3d-editor.
Is possible define multiple ``` extension-viewer ```
```html
<alfresco-viewer [(showViewer)]="fileShowed"
[fileNodeId]="fileNodeId"
[overlayMode]="true">
<extension-viewer [supportedExtensions]="['xls','xlsx']" #extension>
<template let-urlFileContent="urlFileContent" >
<my-custom-xls-component urlFileContent="urlFileContent"></my-custom-xls-component>
</template>
</extension-viewer>
<extension-viewer [supportedExtensions]="['txt']" #extension>
<template let-urlFileContent="urlFileContent" >
<my-custom-txt-component urlFileContent="urlFileContent"></my-custom-txt-component>
</template>
</extension-viewer>
</alfresco-viewer>
```
## Build from sources ## Build from sources

View File

@@ -27,26 +27,28 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { CoreModule } from 'ng2-alfresco-core'; import { CoreModule } from 'ng2-alfresco-core';
import { ViewerComponent } from './src/componets/viewer.component'; import { ViewerComponent } from './src/components/viewer.component';
import { RenderingQueueServices } from './src/services/rendering-queue.services'; import { RenderingQueueServices } from './src/services/rendering-queue.services';
import { ImgViewerComponent } from './src/componets/imgViewer.component'; import { ImgViewerComponent } from './src/components/imgViewer.component';
import { MediaPlayerComponent } from './src/componets/mediaPlayer.component'; import { MediaPlayerComponent } from './src/components/mediaPlayer.component';
import { NotSupportedFormat } from './src/componets/notSupportedFormat.component'; import { NotSupportedFormat } from './src/components/notSupportedFormat.component';
import { PdfViewerComponent } from './src/componets/pdfViewer.component'; import { PdfViewerComponent } from './src/components/pdfViewer.component';
import { ExtensionViewerDirective } from './src/directives/extension-viewer.directive';
export * from './src/componets/viewer.component'; export * from './src/components/viewer.component';
export * from './src/services/rendering-queue.services'; export * from './src/services/rendering-queue.services';
export * from './src/componets/imgViewer.component'; export * from './src/components/imgViewer.component';
export * from './src/componets/mediaPlayer.component'; export * from './src/components/mediaPlayer.component';
export * from './src/componets/notSupportedFormat.component'; export * from './src/components/notSupportedFormat.component';
export * from './src/componets/pdfViewer.component'; export * from './src/components/pdfViewer.component';
export const VIEWER_DIRECTIVES: any[] = [ export const VIEWER_DIRECTIVES: any[] = [
ViewerComponent, ViewerComponent,
ImgViewerComponent, ImgViewerComponent,
MediaPlayerComponent, MediaPlayerComponent,
NotSupportedFormat, NotSupportedFormat,
PdfViewerComponent PdfViewerComponent,
ExtensionViewerDirective
]; ];
export const VIEWER_PROVIDERS: any[] = [ export const VIEWER_PROVIDERS: any[] = [

View File

@@ -27,7 +27,7 @@ import {
describe('Test ng2-alfresco-viewer Img viewer component ', () => { describe('Test ng2-alfresco-viewer Img viewer component ', () => {
let component: any; let component: ImgViewerComponent;
let fixture: ComponentFixture<ImgViewerComponent>; let fixture: ComponentFixture<ImgViewerComponent>;
let debug: DebugElement; let debug: DebugElement;
let element: HTMLElement; let element: HTMLElement;
@@ -57,14 +57,14 @@ describe('Test ng2-alfresco-viewer Img viewer component ', () => {
it('If no url is passed should thrown an error', () => { it('If no url is passed should thrown an error', () => {
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).toThrow(new Error('Attribute urlFile is required')); }).toThrow(new Error('Attribute urlFile is required'));
}); });
it('If url is passed should not thrown an error', () => { it('If url is passed should not thrown an error', () => {
component.urlFile = 'fake-url'; component.urlFile = 'fake-url';
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).not.toThrow(new Error('Attribute urlFile is required')); }).not.toThrow(new Error('Attribute urlFile is required'));
}); });

View File

@@ -27,7 +27,7 @@ import {
describe('Test ng2-alfresco-viewer Media player component ', () => { describe('Test ng2-alfresco-viewer Media player component ', () => {
let component: any; let component: MediaPlayerComponent;
let fixture: ComponentFixture<MediaPlayerComponent>; let fixture: ComponentFixture<MediaPlayerComponent>;
let debug: DebugElement; let debug: DebugElement;
let element: HTMLElement; let element: HTMLElement;
@@ -57,21 +57,21 @@ describe('Test ng2-alfresco-viewer Media player component ', () => {
it('If no url is passed should thrown an error', () => { it('If no url is passed should thrown an error', () => {
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).toThrow(new Error('Attribute urlFile is required')); }).toThrow(new Error('Attribute urlFile is required'));
}); });
it('If url is passed should not thrown an error', () => { it('If url is passed should not thrown an error', () => {
component.urlFile = 'fake-url'; component.urlFile = 'fake-url';
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).not.toThrow(new Error('Attribute urlFile is required')); }).not.toThrow(new Error('Attribute urlFile is required'));
}); });
it('If url is passed should not thrown an error', () => { it('If url is passed should not thrown an error', () => {
component.urlFile = 'fake-url'; component.urlFile = 'fake-url';
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).not.toThrow(new Error('Attribute urlFile is required')); }).not.toThrow(new Error('Attribute urlFile is required'));
}); });
}); });

View File

@@ -27,7 +27,7 @@ import {
describe('Test ng2-alfresco-viewer Not Supported Format View component', () => { describe('Test ng2-alfresco-viewer Not Supported Format View component', () => {
let component: any; let component: NotSupportedFormat;
let fixture: ComponentFixture<NotSupportedFormat>; let fixture: ComponentFixture<NotSupportedFormat>;
let debug: DebugElement; let debug: DebugElement;
let element: HTMLElement; let element: HTMLElement;

View File

@@ -29,7 +29,7 @@ import {
describe('Test ng2-alfresco-viewer PdfViewer component', () => { describe('Test ng2-alfresco-viewer PdfViewer component', () => {
let component: any; let component: PdfViewerComponent;
let fixture: ComponentFixture<PdfViewerComponent>; let fixture: ComponentFixture<PdfViewerComponent>;
let debug: DebugElement; let debug: DebugElement;
let element: HTMLElement; let element: HTMLElement;
@@ -70,7 +70,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).toThrow(); }).toThrow();
}); });
@@ -109,11 +109,11 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
describe('User interaction', () => { describe('User interaction', () => {
beforeEach(() => { beforeEach(() => {
component.inputPage(1); component.inputPage('1');
}); });
it('Total number of pages should be loaded', (done) => { it('Total number of pages should be loaded', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.totalPages).toEqual(6); expect(component.totalPages).toEqual(6);
done(); done();
@@ -121,7 +121,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}, 5000); }, 5000);
it('right arrow should move to the next page', (done) => { it('right arrow should move to the next page', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
EventMock.keyDown(39); EventMock.keyDown(39);
@@ -134,7 +134,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
it('nextPage should move to the next page', (done) => { it('nextPage should move to the next page', (done) => {
let nextPageButton: any = element.querySelector('#viewer-next-page-button'); let nextPageButton: any = element.querySelector('#viewer-next-page-button');
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
nextPageButton.click(); nextPageButton.click();
@@ -145,7 +145,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('left arrow should move to the previous page', (done) => { it('left arrow should move to the previous page', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
EventMock.keyDown(39); EventMock.keyDown(39);
@@ -161,7 +161,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
let previousPageButton: any = element.querySelector('#viewer-previous-page-button'); let previousPageButton: any = element.querySelector('#viewer-previous-page-button');
let nextPageButton: any = element.querySelector('#viewer-next-page-button'); let nextPageButton: any = element.querySelector('#viewer-next-page-button');
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
nextPageButton.click(); nextPageButton.click();
@@ -174,7 +174,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('previous page should not move to the previous page if is page 1', (done) => { it('previous page should not move to the previous page if is page 1', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
component.previousPage(); component.previousPage();
@@ -185,7 +185,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('Input page should move to the inserted page', (done) => { it('Input page should move to the inserted page', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
component.inputPage('2'); component.inputPage('2');
@@ -205,7 +205,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
it('In should increment the scale value', (done) => { it('In should increment the scale value', (done) => {
let zoomInButton: any = element.querySelector('#viewer-zoom-in-button'); let zoomInButton: any = element.querySelector('#viewer-zoom-in-button');
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
let zoomBefore = component.currentScale; let zoomBefore = component.currentScale;
zoomInButton.click(); zoomInButton.click();
expect(component.currentScaleMode).toBe('auto'); expect(component.currentScaleMode).toBe('auto');
@@ -218,7 +218,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
it('Out should decrement the scale value', (done) => { it('Out should decrement the scale value', (done) => {
let zoomOutButton: any = element.querySelector('#viewer-zoom-out-button'); let zoomOutButton: any = element.querySelector('#viewer-zoom-out-button');
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
let zoomBefore = component.currentScale; let zoomBefore = component.currentScale;
zoomOutButton.click(); zoomOutButton.click();
expect(component.currentScaleMode).toBe('auto'); expect(component.currentScaleMode).toBe('auto');
@@ -231,7 +231,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
it('fit-in button should toggle page-fit and auto scale mode', (done) => { it('fit-in button should toggle page-fit and auto scale mode', (done) => {
let fitPage: any = element.querySelector('#viewer-scale-page-button'); let fitPage: any = element.querySelector('#viewer-scale-page-button');
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
expect(component.currentScaleMode).toBe('auto'); expect(component.currentScaleMode).toBe('auto');
fitPage.click(); fitPage.click();
expect(component.currentScaleMode).toBe('page-fit'); expect(component.currentScaleMode).toBe('page-fit');
@@ -245,20 +245,19 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
describe('Resize interaction', () => { describe('Resize interaction', () => {
it('resize event should trigger setScaleUpdatePages', (done) => { it('resize event should trigger setScaleUpdatePages', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
spyOn(component, 'onResize'); spyOn(component, 'onResize');
component.documentContainer = element.querySelector('#viewer-pdf-container');
EventMock.resizeMobileView(); EventMock.resizeMobileView();
expect(component.onResize).toHaveBeenCalled(); expect(component.onResize).toHaveBeenCalled();
done(); done();
}, 5000); });
}); });
}); });
describe('scroll interaction', () => { describe('scroll interaction', () => {
it('scroll page should return the current page', (done) => { it('scroll page should return the current page', (done) => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(1); expect(component.displayPage).toBe(1);
component.inputPage('2'); component.inputPage('2');

View File

@@ -31,19 +31,10 @@
<!-- End Navigation --> <!-- End Navigation -->
</div> </div>
</header> </header>
<!--<div class="mdl-layout__drawer">-->
<!--<span class="mdl-layout-title">Thumbnail</span>-->
<!--</div>-->
<main id="page-content" class="mdl-layout__content" [ngClass]="{'all-space': !overlayMode }"> <main id="page-content" class="mdl-layout__content" [ngClass]="{'all-space': !overlayMode }">
<div class="mdl-grid"> <div class="mdl-grid">
<!--<div id="viewer-previous-file-button" class="center-element mdl-cell mdl-cell&#45;&#45;2-col mdl-cell&#45;&#45;hide-tablet mdl-cell&#45;&#45;hide-phone">-->
<!--<button *ngIf="false"-->
<!--class="center-element mdl-color&#45;&#45;black mdl-button mdl-js-button mdl-button&#45;&#45;fab mdl-button&#45;&#45;mini-fab mdl-button&#45;&#45;colored"-->
<!--(click)="previousFile()">-->
<!--<i class="icon material-icons ">keyboard_arrow_left</i>-->
<!--</button>-->
<!--</div>-->
<div id="viewer-content-container" *ngIf="isLoaded()" <div id="viewer-content-container" *ngIf="isLoaded()"
class="center-element mdl-cell mdl-cell--12-col"> class="center-element mdl-cell mdl-cell--12-col">
@@ -60,22 +51,19 @@
<media-player [urlFile]="urlFileContent" [mimeType]="mimeType" <media-player [urlFile]="urlFileContent" [mimeType]="mimeType"
[nameFile]="displayName"></media-player> [nameFile]="displayName"></media-player>
</div> </div>
<span *ngFor="let extensionTemplate of extensionTemplates">
<template [ngTemplateOutlet]="extensionTemplate.template" *ngIf="extensionTemplate.isVisible"
[ngOutletContext]="{ urlFileContent: urlFileContent, extension:extension }"></template>
</span>
<div *ngIf="!supportedExtension()"> <div *ngIf="!supportedExtension()">
<not-supported-format [urlFile]="urlFileContent" <not-supported-format *ngIf="!extensionTemplate" [urlFile]="urlFileContent" [nameFile]="displayName"></not-supported-format>
[nameFile]="displayName"></not-supported-format>
</div> </div>
<!-- End View Switch --> <!-- End View Switch -->
</div> </div>
<!--<div id="viewer-next-file-button" class="center-element mdl-cell mdl-cell&#45;&#45;2-col mdl-cell&#45;&#45;hide-tablet mdl-cell&#45;&#45;hide-phone">-->
<!--<button *ngIf="false"-->
<!--class="center-element mdl-color&#45;&#45;black mdl-button mdl-js-button mdl-button&#45;&#45;fab mdl-button&#45;&#45;mini-fab mdl-button&#45;&#45;colored"-->
<!--(click)="nextFile()">-->
<!--<i class="icon material-icons">keyboard_arrow_right</i>-->
<!--</button>-->
<!--</div>-->
</div> </div>
</main> </main>
</div> </div>

View File

@@ -35,7 +35,7 @@ declare let jasmine: any;
describe('Test ng2-alfresco-viewer ViewerComponent', () => { describe('Test ng2-alfresco-viewer ViewerComponent', () => {
let component: any; let component: ViewerComponent;
let fixture: ComponentFixture<ViewerComponent>; let fixture: ComponentFixture<ViewerComponent>;
let debug: DebugElement; let debug: DebugElement;
let element: HTMLElement; let element: HTMLElement;
@@ -99,7 +99,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
}); });
it('Name File should be present if is overlay mode ', () => { it('Name File should be present if is overlay mode ', () => {
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-name-file').innerHTML).toEqual('fake-test-file.pdf'); expect(element.querySelector('#viewer-name-file').innerHTML).toEqual('fake-test-file.pdf');
}); });
@@ -161,7 +161,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = undefined; component.urlFile = undefined;
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).toThrow(); }).toThrow();
}); });
@@ -171,7 +171,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = undefined; component.urlFile = undefined;
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).not.toThrow(); }).not.toThrow();
}); });
@@ -180,7 +180,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.fileNodeId = undefined; component.fileNodeId = undefined;
expect(() => { expect(() => {
component.ngOnChanges(); component.ngOnChanges(null);
}).not.toThrow(); }).not.toThrow();
}); });
@@ -200,7 +200,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
it('if extension file is a pdf the pdf viewer should be loaded', (done) => { it('if extension file is a pdf the pdf viewer should be loaded', (done) => {
component.urlFile = 'base/src/assets/fake-test-file.pdf'; component.urlFile = 'base/src/assets/fake-test-file.pdf';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('pdf-viewer')).not.toBeNull();
done(); done();
@@ -210,7 +210,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
it('if extension file is a image the img viewer should be loaded', (done) => { it('if extension file is a image the img viewer should be loaded', (done) => {
component.urlFile = 'fake-url-file.png'; component.urlFile = 'fake-url-file.png';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-image')).not.toBeNull(); expect(element.querySelector('#viewer-image')).not.toBeNull();
done(); done();
@@ -220,7 +220,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
it('if extension file is a video the the media player should be loaded', (done) => { it('if extension file is a video the the media player should be loaded', (done) => {
component.urlFile = 'fake-url-file.mp4'; component.urlFile = 'fake-url-file.mp4';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('media-player')).not.toBeNull();
done(); done();
@@ -230,7 +230,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
it('if extension file is a not supported the not supported div should be loaded', (done) => { it('if extension file is a not supported the not supported div should be loaded', (done) => {
component.urlFile = 'fake-url-file.unsupported'; component.urlFile = 'fake-url-file.unsupported';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('not-supported-format')).not.toBeNull(); expect(element.querySelector('not-supported-format')).not.toBeNull();
done(); done();
@@ -243,7 +243,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content'; component.urlFile = 'content';
component.mimeType = 'application/pdf'; component.mimeType = 'application/pdf';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('pdf-viewer')).not.toBeNull();
done(); done();
@@ -255,7 +255,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content.bin'; component.urlFile = 'content.bin';
component.mimeType = 'application/pdf'; component.mimeType = 'application/pdf';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('pdf-viewer')).not.toBeNull();
done(); done();
@@ -266,7 +266,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content'; component.urlFile = 'content';
component.mimeType = 'image/png'; component.mimeType = 'image/png';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-image')).not.toBeNull(); expect(element.querySelector('#viewer-image')).not.toBeNull();
done(); done();
@@ -277,7 +277,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content.bin'; component.urlFile = 'content.bin';
component.mimeType = 'image/png'; component.mimeType = 'image/png';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-image')).not.toBeNull(); expect(element.querySelector('#viewer-image')).not.toBeNull();
done(); done();
@@ -288,7 +288,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content.bin'; component.urlFile = 'content.bin';
component.mimeType = 'video/mp4'; component.mimeType = 'video/mp4';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('media-player')).not.toBeNull();
done(); done();
@@ -299,7 +299,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content'; component.urlFile = 'content';
component.mimeType = 'video/mp4'; component.mimeType = 'video/mp4';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('media-player')).not.toBeNull();
done(); done();
@@ -310,11 +310,25 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.urlFile = 'content'; component.urlFile = 'content';
component.mimeType = 'video/avi'; component.mimeType = 'video/avi';
component.ngOnChanges().then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).toBeNull(); expect(element.querySelector('media-player')).toBeNull();
done(); done();
}); });
}); });
}); });
describe('Events', () => {
it('if extension change exextensionChange event should be fired ', (done) => {
component.extensionChange.subscribe((fileExtension) => {
expect(fileExtension).toEqual('png');
done();
});
component.urlFile = 'fake-url-file.png';
component.ngOnChanges(null);
});
});
}); });

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, ElementRef, Input, Output, HostListener, EventEmitter, Inject } from '@angular/core'; import { Component, ElementRef, Input, Output, HostListener, EventEmitter, Inject, TemplateRef } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser'; import { DOCUMENT } from '@angular/platform-browser';
import { MinimalNodeEntryEntity } from 'alfresco-js-api'; import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { AlfrescoApiService, LogService } from 'ng2-alfresco-core'; import { AlfrescoApiService, LogService } from 'ng2-alfresco-core';
@@ -46,6 +46,13 @@ export class ViewerComponent {
@Output() @Output()
showViewerChange: EventEmitter<boolean> = new EventEmitter<boolean>(); showViewerChange: EventEmitter<boolean> = new EventEmitter<boolean>();
@Output()
extensionChange: EventEmitter<String> = new EventEmitter<String>();
extensionTemplates: { template: TemplateRef<any>, isVisible: boolean }[] = [];
externalExtensions: string[] = [];
urlFileContent: string; urlFileContent: string;
otherMenu: any; otherMenu: any;
displayName: string; displayName: string;
@@ -72,6 +79,7 @@ export class ViewerComponent {
let filenameFromUrl = this.getFilenameFromUrl(this.urlFile); let filenameFromUrl = this.getFilenameFromUrl(this.urlFile);
this.displayName = filenameFromUrl ? filenameFromUrl : ''; this.displayName = filenameFromUrl ? filenameFromUrl : '';
this.extension = this.getFileExtension(filenameFromUrl); this.extension = this.getFileExtension(filenameFromUrl);
this.extensionChange.emit(this.extension);
this.urlFileContent = this.urlFile; this.urlFileContent = this.urlFile;
resolve(); resolve();
} else if (this.fileNodeId) { } else if (this.fileNodeId) {
@@ -79,6 +87,8 @@ export class ViewerComponent {
this.mimeType = data.content.mimeType; this.mimeType = data.content.mimeType;
this.displayName = data.name; this.displayName = data.name;
this.urlFileContent = alfrescoApi.content.getContentUrl(data.id); this.urlFileContent = alfrescoApi.content.getContentUrl(data.id);
this.extension = this.getFileExtension(data.name);
this.extensionChange.emit(this.extension);
this.loaded = true; this.loaded = true;
resolve(); resolve();
}, function (error) { }, function (error) {
@@ -103,6 +113,9 @@ export class ViewerComponent {
this.showViewerChange.emit(this.showViewer); this.showViewerChange.emit(this.showViewer);
} }
/**
* cleanup before the close
*/
cleanup() { cleanup() {
this.urlFileContent = ''; this.urlFileContent = '';
this.displayName = ''; this.displayName = '';
@@ -216,7 +229,25 @@ export class ViewerComponent {
* @returns {boolean} * @returns {boolean}
*/ */
supportedExtension() { supportedExtension() {
return this.isImage() || this.isPdf() || this.isMedia(); return this.isImage() || this.isPdf() || this.isMedia() || this.isExternalSupportedExtension();
}
/**
* Check if the file is compatible with one of the extension
*
* @returns {boolean}
*/
isExternalSupportedExtension() {
let externalType: string;
if (this.externalExtensions && (this.externalExtensions instanceof Array)) {
externalType = this.externalExtensions.find((externalExtension) => {
return externalExtension.toLowerCase() === this.extension;
});
}
return !!externalType;
} }
/** /**
@@ -272,8 +303,8 @@ export class ViewerComponent {
* @param {string} nodeName * @param {string} nodeName
* @returns {HTMLElement} * @returns {HTMLElement}
*/ */
private closestElement(elelemnt: HTMLElement, nodeName: string) { private closestElement(element: HTMLElement, nodeName: string) {
let parent = elelemnt.parentElement; let parent = element.parentElement;
if (parent) { if (parent) {
if (parent.nodeName.toLowerCase() === nodeName) { if (parent.nodeName.toLowerCase() === nodeName) {
return parent; return parent;

View File

@@ -0,0 +1,62 @@
/*!
* @license
* Copyright 2016 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 { ElementRef } from '@angular/core';
import { CoreModule } from 'ng2-alfresco-core';
import { ExtensionViewerDirective } from './extension-viewer.directive';
import { ViewerComponent } from '../components/viewer.component';
import { getTestBed, TestBed, async } from '@angular/core/testing';
import { Injector } from '@angular/core';
export class MockElementRef extends ElementRef {
}
describe('ExtensionViewerComponent', () => {
let injector: Injector;
let extensionViewerDirective: ExtensionViewerDirective;
let viewerComponent: ViewerComponent;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [CoreModule.forRoot()],
providers: [
ExtensionViewerDirective,
{provide: ElementRef, useClass: MockElementRef},
ViewerComponent
]
});
injector = getTestBed();
extensionViewerDirective = injector.get(ExtensionViewerDirective);
viewerComponent = injector.get(ViewerComponent);
extensionViewerDirective.templateModel = {template: '', isVisible: false};
}));
it('is defined', () => {
expect(extensionViewerDirective).toBeDefined();
});
it('if the file in the viewer has an extension handled by this extension isVisible should be true', () => {
extensionViewerDirective.supportedExtensions = ['xls', 'sts'];
expect(extensionViewerDirective.isVisible('xls')).toBeTruthy();
});
it('if the file in the viewer not has an extension handled by this extension isVisible should be false', () => {
extensionViewerDirective.supportedExtensions = ['xls', 'sts'];
expect(extensionViewerDirective.isVisible('png')).not.toBeTruthy();
});
});

View File

@@ -0,0 +1,83 @@
/*!
* @license
* Copyright 2016 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 {
Directive,
ContentChild,
TemplateRef,
AfterContentInit,
Input
} from '@angular/core';
import { ViewerComponent } from '../components/viewer.component';
@Directive({
selector: 'extension-viewer'
})
export class ExtensionViewerDirective implements AfterContentInit {
@ContentChild(TemplateRef)
template: any;
@Input()
urlFileContent: string;
@Input()
extension: string;
@Input()
supportedExtensions: string[];
templateModel: any;
constructor(private viewerComponent: ViewerComponent) {
}
ngAfterContentInit() {
this.templateModel = {template: this.template, isVisible: false};
this.viewerComponent.extensionTemplates.push(this.templateModel);
this.viewerComponent.extensionChange.subscribe((fileExtension) => {
this.templateModel.isVisible = this.isVisible(fileExtension);
});
if (this.supportedExtensions instanceof Array) {
this.supportedExtensions.forEach((extension) => {
this.viewerComponent.externalExtensions.push(extension);
});
}
}
/**
* check if the current extension in the viewer is compatible with this extension checking against supportedExtensions
*
* @returns {boolean}
*/
isVisible(fileExtension) {
let supportedExtension: string;
if (this.supportedExtensions && (this.supportedExtensions instanceof Array)) {
supportedExtension = this.supportedExtensions.find((extension) => {
return extension.toLowerCase() === fileExtension;
});
}
return !!supportedExtension;
}
}