diff --git a/demo-shell-ng2/app/app.component.html b/demo-shell-ng2/app/app.component.html index 6ecf0aadbc..0680b43f9c 100644 --- a/demo-shell-ng2/app/app.component.html +++ b/demo-shell-ng2/app/app.component.html @@ -1,97 +1 @@ - - - - - ADF Demo Application - -
- - - - Home - Content Services - Process Services - Login - - - - - - - - - - - - - - home - Home - - - folder_open - Content Services - - - device_hub - Process Services - - - vpn_key - Login - - - extension - DL: Custom Sources - - - view_module - DataTable - - - poll - Form - - - library_books - Form List - - - file_upload - Uploader - - - extension - Webscript - - - local_offer - Tag - - - thumb_up - Social - - - settings - Settings - - - info_outline - About - - - -
- diff --git a/demo-shell-ng2/app/app.component.ts b/demo-shell-ng2/app/app.component.ts index 3ad93d556f..f1747695ce 100644 --- a/demo-shell-ng2/app/app.component.ts +++ b/demo-shell-ng2/app/app.component.ts @@ -16,33 +16,24 @@ */ import { Component, ViewEncapsulation } from '@angular/core'; -import { AlfrescoSettingsService, AlfrescoTranslationService, PageTitle, StorageService } from 'ng2-alfresco-core'; +import { AlfrescoSettingsService, PageTitle, StorageService } from 'ng2-alfresco-core'; @Component({ selector: 'adf-app', templateUrl: './app.component.html', - styleUrls: ['./app.component.scss', './theme.scss'], + styleUrls: ['./theme.scss'], encapsulation: ViewEncapsulation.None }) export class AppComponent { searchTerm: string = ''; constructor(private settingsService: AlfrescoSettingsService, - private translateService: AlfrescoTranslationService, private storage: StorageService, pageTitle: PageTitle) { this.setProvider(); pageTitle.setTitle(); } - isAPageWithHeaderBar(): boolean { - return location.pathname === '/login' || location.pathname === '/settings'; - } - - changeLanguage(lang: string) { - this.translateService.use(lang); - } - private setProvider() { if (this.storage.hasItem(`providers`)) { this.settingsService.setProviders(this.storage.getItem(`providers`)); diff --git a/demo-shell-ng2/app/app.module.ts b/demo-shell-ng2/app/app.module.ts index e01a6ca653..fcafb18ef4 100644 --- a/demo-shell-ng2/app/app.module.ts +++ b/demo-shell-ng2/app/app.module.ts @@ -41,6 +41,8 @@ import { ChartsModule } from 'ng2-charts'; import { AppComponent } from './app.component'; import { routing } from './app.routes'; import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component'; +import { AppMenuComponent } from './components/app-menu/app-menu.component'; +import { FileViewComponent } from './components/file-view/file-view.component'; import { FormListDemoComponent } from './components/form/form-list-demo.component'; import { ThemePickerModule } from './components/theme-picker/theme-picker'; import { MaterialModule } from './material.module'; @@ -119,7 +121,9 @@ import { SettingsComponent, FormDemoComponent, FormListDemoComponent, - CustomSourcesComponent + CustomSourcesComponent, + FileViewComponent, + AppMenuComponent ], providers: [ { provide: AppConfigService, useClass: DebugAppConfigService }, diff --git a/demo-shell-ng2/app/app.routes.ts b/demo-shell-ng2/app/app.routes.ts index ecc6bea0a9..c23380ae81 100644 --- a/demo-shell-ng2/app/app.routes.ts +++ b/demo-shell-ng2/app/app.routes.ts @@ -39,6 +39,7 @@ import { } from './components/index'; import { UploadButtonComponent } from 'ng2-alfresco-upload'; +import { FileViewComponent } from './components/file-view/file-view.component'; import { CustomSourcesComponent } from './components/files/custom-sources.component'; import { FormListDemoComponent } from './components/form/form-list-demo.component'; @@ -64,6 +65,11 @@ export const appRoutes: Routes = [ component: FilesComponent, canActivate: [AuthGuardEcm] }, + { + path: 'files/:nodeId/view', + component: FileViewComponent, + canActivate: [ AuthGuardEcm ] + }, { path: 'dl-custom-sources', component: CustomSourcesComponent, diff --git a/demo-shell-ng2/app/components/about/about.component.html b/demo-shell-ng2/app/components/about/about.component.html index 132925dfc1..213a40fbb0 100644 --- a/demo-shell-ng2/app/components/about/about.component.html +++ b/demo-shell-ng2/app/components/about/about.component.html @@ -1,3 +1,5 @@ + +

Server settings

diff --git a/demo-shell-ng2/app/components/about/about.component.ts b/demo-shell-ng2/app/components/about/about.component.ts index 7fb556da91..e62061e748 100644 --- a/demo-shell-ng2/app/components/about/about.component.ts +++ b/demo-shell-ng2/app/components/about/about.component.ts @@ -17,7 +17,7 @@ import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; -import { AlfrescoAuthenticationService, AppConfigService, BpmProductVersionModel, DiscoveryApiService, EcmProductVersionModel, LogService } from 'ng2-alfresco-core'; +import { AlfrescoAuthenticationService, AppConfigService, BpmProductVersionModel, DiscoveryApiService, EcmProductVersionModel } from 'ng2-alfresco-core'; import { ObjectDataTableAdapter } from 'ng2-alfresco-datatable'; @Component({ @@ -40,7 +40,6 @@ export class AboutComponent implements OnInit { constructor(private http: Http, private appConfig: AppConfigService, private authService: AlfrescoAuthenticationService, - private logService: LogService, private discovery: DiscoveryApiService) { } @@ -62,13 +61,11 @@ export class AboutComponent implements OnInit { let regexp = new RegExp('^(ng2-activiti|ng2-alfresco|alfresco-)'); let alfrescoPackages = Object.keys(response.json().dependencies).filter((val) => { - this.logService.log(val); return regexp.test(val); }); let alfrescoPackagesTableRepresentation = []; alfrescoPackages.forEach((val) => { - this.logService.log(response.json().dependencies[val]); alfrescoPackagesTableRepresentation.push({ name: val, version: response.json().dependencies[val].version @@ -77,8 +74,6 @@ export class AboutComponent implements OnInit { this.gitHubLinkCreation(alfrescoPackagesTableRepresentation); - this.logService.log(alfrescoPackagesTableRepresentation); - this.data = new ObjectDataTableAdapter(alfrescoPackagesTableRepresentation, [ {type: 'text', key: 'name', title: 'Name', sortable: true}, {type: 'text', key: 'version', title: 'Version', sortable: true} diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html index 0d551a24e6..f84f4435b9 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -1,3 +1,5 @@ + +
diff --git a/demo-shell-ng2/app/components/activiti/apps.view.ts b/demo-shell-ng2/app/components/activiti/apps.view.ts index 04898acd6d..b73ae25f3e 100644 --- a/demo-shell-ng2/app/components/activiti/apps.view.ts +++ b/demo-shell-ng2/app/components/activiti/apps.view.ts @@ -22,6 +22,7 @@ import { AppDefinitionRepresentationModel } from 'ng2-activiti-tasklist'; @Component({ selector: 'activiti-apps-view', template: ` + ` }) diff --git a/demo-shell-ng2/app/components/app-menu/app-menu.component.html b/demo-shell-ng2/app/components/app-menu/app-menu.component.html new file mode 100644 index 0000000000..4bfcb76628 --- /dev/null +++ b/demo-shell-ng2/app/components/app-menu/app-menu.component.html @@ -0,0 +1,96 @@ + + + + ADF Demo Application + +
+ + + + Home + Content Services + Process Services + Login + + + + + + + + + + + + + + + home + Home + + + folder_open + Content Services + + + device_hub + Process Services + + + vpn_key + Login + + + extension + DL: Custom Sources + + + view_module + DataTable + + + poll + Form + + + library_books + Form List + + + file_upload + Uploader + + + extension + Webscript + + + local_offer + Tag + + + thumb_up + Social + + + settings + Settings + + + info_outline + About + + + +
diff --git a/demo-shell-ng2/app/app.component.scss b/demo-shell-ng2/app/components/app-menu/app-menu.component.scss similarity index 99% rename from demo-shell-ng2/app/app.component.scss rename to demo-shell-ng2/app/components/app-menu/app-menu.component.scss index 35a7d0c51f..016d5d4a01 100644 --- a/demo-shell-ng2/app/app.component.scss +++ b/demo-shell-ng2/app/components/app-menu/app-menu.component.scss @@ -1,6 +1,5 @@ @import '~@angular/material/theming'; - .adf-app-user-profile { margin-right: 10px; } diff --git a/demo-shell-ng2/app/components/app-menu/app-menu.component.ts b/demo-shell-ng2/app/components/app-menu/app-menu.component.ts new file mode 100644 index 0000000000..278d336db5 --- /dev/null +++ b/demo-shell-ng2/app/components/app-menu/app-menu.component.ts @@ -0,0 +1,34 @@ +/*! + * @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 { Component } from '@angular/core'; +import { AlfrescoTranslationService } from 'ng2-alfresco-core'; + +@Component({ + selector: 'adf-app-menu', + templateUrl: 'app-menu.component.html', + styleUrls: ['app-menu.component.scss'] +}) +export class AppMenuComponent { + + constructor(private translateService: AlfrescoTranslationService) { + } + + changeLanguage(lang: string) { + this.translateService.use(lang); + } +} diff --git a/demo-shell-ng2/app/components/datatable/datatable-demo.component.html b/demo-shell-ng2/app/components/datatable/datatable-demo.component.html index 1feceb707b..813816fe34 100644 --- a/demo-shell-ng2/app/components/datatable/datatable-demo.component.html +++ b/demo-shell-ng2/app/components/datatable/datatable-demo.component.html @@ -1,3 +1,5 @@ + +
+ + + + + + + + diff --git a/demo-shell-ng2/app/components/file-view/file-view.component.ts b/demo-shell-ng2/app/components/file-view/file-view.component.ts new file mode 100644 index 0000000000..ba713f6aaf --- /dev/null +++ b/demo-shell-ng2/app/components/file-view/file-view.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { AlfrescoApiService } from 'ng2-alfresco-core'; + +@Component({ + selector: 'adf-file-view', + templateUrl: 'file-view.component.html' +}) +export class FileViewComponent implements OnInit { + + nodeId: string = null; + + constructor( + private router: Router, + private route: ActivatedRoute, + private apiService: AlfrescoApiService) {} + + ngOnInit() { + this.route.params.subscribe(params => { + const id = params.nodeId; + if (id) { + this.apiService.getInstance().nodes.getNodeInfo(id).then( + (node) => { + if (node && node.isFile) { + this.nodeId = id; + return; + } + this.router.navigate(['/files', id]); + }, + () => this.router.navigate(['/files', id]) + ); + } + }); + } + +} diff --git a/demo-shell-ng2/app/components/files/custom-sources.component.html b/demo-shell-ng2/app/components/files/custom-sources.component.html index cff8d59ede..7996cc2bc4 100644 --- a/demo-shell-ng2/app/components/files/custom-sources.component.html +++ b/demo-shell-ng2/app/components/files/custom-sources.component.html @@ -1,3 +1,4 @@ + diff --git a/demo-shell-ng2/app/components/files/files.component.html b/demo-shell-ng2/app/components/files/files.component.html index 14450ea3b6..fa1edea705 100644 --- a/demo-shell-ng2/app/components/files/files.component.html +++ b/demo-shell-ng2/app/components/files/files.component.html @@ -1,3 +1,5 @@ + +
@@ -225,14 +227,6 @@
-
- Use inline viewer (no overlay) -
- -
- Use File Viewer dialog -
-
Multiselect (with checkboxes)
@@ -309,29 +303,3 @@
- -
- - - - - - - - - - - - - -
- - -
-
-
diff --git a/demo-shell-ng2/app/components/files/files.component.ts b/demo-shell-ng2/app/components/files/files.component.ts index d6c40ce37c..a74bcdef67 100644 --- a/demo-shell-ng2/app/components/files/files.component.ts +++ b/demo-shell-ng2/app/components/files/files.component.ts @@ -27,8 +27,6 @@ import { import { DataColumn, DataRow } from 'ng2-alfresco-datatable'; import { DocumentListComponent, PermissionStyleModel } from 'ng2-alfresco-documentlist'; -import { ViewerService } from 'ng2-alfresco-viewer'; - const DEFAULT_FOLDER_TO_SHOW = '-my-'; @Component({ @@ -46,8 +44,6 @@ export class FilesComponent implements OnInit { toolbarColor = 'default'; useDropdownBreadcrumb = false; - useViewerDialog = true; - useInlineViewer = false; selectionModes = [ { value: 'none', viewValue: 'None' }, @@ -91,27 +87,14 @@ export class FilesComponent implements OnInit { private contentService: AlfrescoContentService, private dialog: MdDialog, private translateService: AlfrescoTranslationService, - private viewerService: ViewerService, private router: Router, @Optional() private route: ActivatedRoute) { } showFile(event) { - if (this.useViewerDialog) { - if (event.value.entry.isFile) { - this.viewerService - .showViewerForNode(event.value.entry) - .then(result => { - console.log(result); - }); - } - } else { - if (event.value.entry.isFile) { - this.fileNodeId = event.value.entry.id; - this.showViewer = true; - } else { - this.showViewer = false; - } + const entry = event.value.entry; + if (entry && entry.isFile) { + this.router.navigate(['/files', entry.id, 'view']); } } diff --git a/demo-shell-ng2/app/components/form/form-demo.component.html b/demo-shell-ng2/app/components/form/form-demo.component.html index 8b41dfbe7c..973f8b78f7 100644 --- a/demo-shell-ng2/app/components/form/form-demo.component.html +++ b/demo-shell-ng2/app/components/form/form-demo.component.html @@ -1,3 +1,5 @@ + +
diff --git a/demo-shell-ng2/app/components/form/form-list-demo.component.ts b/demo-shell-ng2/app/components/form/form-list-demo.component.ts index 162b04084b..8ace89ac05 100644 --- a/demo-shell-ng2/app/components/form/form-list-demo.component.ts +++ b/demo-shell-ng2/app/components/form/form-list-demo.component.ts @@ -22,6 +22,7 @@ import { ActivitiForm } from 'ng2-activiti-form'; @Component({ selector: 'form-list-demo', template: ` +
diff --git a/demo-shell-ng2/app/components/home/home.component.html b/demo-shell-ng2/app/components/home/home.component.html index af4342dcdc..cf97241a9c 100644 --- a/demo-shell-ng2/app/components/home/home.component.html +++ b/demo-shell-ng2/app/components/home/home.component.html @@ -1,3 +1,5 @@ + + diff --git a/demo-shell-ng2/app/components/social/social.component.html b/demo-shell-ng2/app/components/social/social.component.html index 7bd1e17bff..0b727f6cd0 100644 --- a/demo-shell-ng2/app/components/social/social.component.html +++ b/demo-shell-ng2/app/components/social/social.component.html @@ -1,3 +1,5 @@ + +

diff --git a/demo-shell-ng2/app/components/tag/tag.component.html b/demo-shell-ng2/app/components/tag/tag.component.html index 11d44c424a..1099f23c7a 100644 --- a/demo-shell-ng2/app/components/tag/tag.component.html +++ b/demo-shell-ng2/app/components/tag/tag.component.html @@ -1,3 +1,5 @@ + +

diff --git a/demo-shell-ng2/app/components/webscript/webscript.component.ts b/demo-shell-ng2/app/components/webscript/webscript.component.ts index 4587498c80..bd4296d559 100644 --- a/demo-shell-ng2/app/components/webscript/webscript.component.ts +++ b/demo-shell-ng2/app/components/webscript/webscript.component.ts @@ -21,6 +21,7 @@ import { LogService } from 'ng2-alfresco-core'; @Component({ selector: 'alfresco-webscript-demo', template: ` +


diff --git a/docs/docassets/images/renditions.png b/docs/docassets/images/renditions.png deleted file mode 100644 index 02198cbf85..0000000000 Binary files a/docs/docassets/images/renditions.png and /dev/null differ diff --git a/docs/viewer.component.md b/docs/viewer.component.md index 82169a7dcb..96bfa555ff 100644 --- a/docs/viewer.component.md +++ b/docs/viewer.component.md @@ -7,7 +7,7 @@ See it live: [Viewer Quickstart](https://embed.plnkr.co/iTuG1lFIXfsP95l6bDW6/) - [Basic usage](#basic-usage) - * [Properties](#properties) +- [Properties](#properties) - [Details](#details) * [Supported file formats](#supported-file-formats) * [PDF Conversion](#pdf-conversion) @@ -39,9 +39,9 @@ Using with file url: ``` -### Properties +## Properties -| Attribute | Options | Default | Description | +| Name | Type | Default | Description | | --- | --- | --- | --- | | fileNodeId | string | | Node Id of the file to load | | urlFile | string | | If you want to load an external file that does not come from ECM you can use this Url where to load the file | @@ -50,6 +50,13 @@ Using with file url: | showViewer | boolean | true | Hide or show the viewer | | showToolbar | boolean | true | Hide or show the toolbars | | displayName | string | | You can specify the name of the file | +| allowGoBack | boolean | true | Allow `back` navigation | +| allowOpenWith | boolean | true | Toggle `Open With` options | +| allowDownload | boolean | true | Toggle download feature | +| allowPrint | boolean | true | Toggle printing feature | +| allowShare | boolean | true | Toggle sharing feature | +| allowInfoDrawer | boolean | true | Toogle info drawer feature | +| showInfoDrawer | boolean | false | Toggles info drawer visibility. Requires `allowInfoDrawer` to be set to `true`. | ## Details @@ -63,9 +70,7 @@ Using with file url: ### PDF Conversion -![Rendition](docassets/images/renditions.png) - -Note for unsupported extensions the viewer will offer the possibility to convert to PDF if that kind of extension is supported by the [content service renditions service](https://community.alfresco.com/docs/DOC-5879-rendition-service) +For unsupported extensions or mime types the viewer will try to fetch PDF rendition utilising the [renditions service api](https://community.alfresco.com/docs/DOC-5879-rendition-service) ### Configuring PDF.js library diff --git a/ng2-components/ng2-alfresco-viewer/index.ts b/ng2-components/ng2-alfresco-viewer/index.ts index 276bee5c2f..8aa27e7eb6 100644 --- a/ng2-components/ng2-alfresco-viewer/index.ts +++ b/ng2-components/ng2-alfresco-viewer/index.ts @@ -23,12 +23,13 @@ import { MaterialModule } from './src/material.module'; export { ViewerComponent } from './src/components/viewer.component'; import { ImgViewerComponent } from './src/components/imgViewer.component'; import { MediaPlayerComponent } from './src/components/mediaPlayer.component'; -import { NotSupportedFormatComponent } from './src/components/notSupportedFormat.component'; import { PdfViewerComponent } from './src/components/pdfViewer.component'; import { TxtViewerComponent } from './src/components/txtViewer.component'; +import { UnknownFormatComponent } from './src/components/unknown-format/unknown-format.component'; import { PdfViewComponent } from './src/components/viewer-dialog/pdf-view/pdf-view.component'; import { ViewerDialogComponent } from './src/components/viewer-dialog/viewer-dialog.component'; import { ViewerComponent } from './src/components/viewer.component'; + import { ExtensionViewerDirective } from './src/directives/extension-viewer.directive'; import { RenderingQueueServices } from './src/services/rendering-queue.services'; @@ -38,33 +39,33 @@ export { ViewerDialogComponent } from './src/components/viewer-dialog/viewer-dia export { ViewerDialogSettings } from './src/components/viewer-dialog/viewer-dialog.settings'; export { ViewerService } from './src/services/viewer.service'; -export const VIEWER_DIRECTIVES: any[] = [ - ViewerComponent, - ImgViewerComponent, - TxtViewerComponent, - MediaPlayerComponent, - NotSupportedFormatComponent, - PdfViewerComponent, - ExtensionViewerDirective, - ViewerDialogComponent, - PdfViewComponent -]; +export function declarations() { + return [ + ViewerComponent, + ImgViewerComponent, + TxtViewerComponent, + MediaPlayerComponent, + PdfViewerComponent, + ExtensionViewerDirective, + ViewerDialogComponent, + PdfViewComponent, + UnknownFormatComponent + ]; +} @NgModule({ imports: [ CoreModule, MaterialModule ], - declarations: [ - ...VIEWER_DIRECTIVES - ], + declarations: declarations(), providers: [ RenderingQueueServices, ViewerService ], exports: [ MaterialModule, - ...VIEWER_DIRECTIVES + ...declarations() ], entryComponents: [ ViewerDialogComponent diff --git a/ng2-components/ng2-alfresco-viewer/src/components/imgViewer.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/imgViewer.component.scss index b62e87f509..3c78ff223c 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/imgViewer.component.scss +++ b/ng2-components/ng2-alfresco-viewer/src/components/imgViewer.component.scss @@ -7,6 +7,7 @@ justify-content: center; height: 90vh; img { + width: 100%; object-fit: contain; } } diff --git a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.html b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.html deleted file mode 100644 index 01d5009114..0000000000 --- a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.html +++ /dev/null @@ -1,47 +0,0 @@ - - - Unknown format - - -

File '{{nameFile}}' is of an unsupported format

- - -
- - - - - -
- - - diff --git a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.scss deleted file mode 100644 index b6bae84645..0000000000 --- a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.scss +++ /dev/null @@ -1,5 +0,0 @@ -.adf-not-supported-format { - .mat-card { - max-width: 400px; - } -} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.spec.ts b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.spec.ts deleted file mode 100644 index 5670e79a9b..0000000000 --- a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.spec.ts +++ /dev/null @@ -1,271 +0,0 @@ -/*! - * @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 { DebugElement } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ContentService, CoreModule, RenditionsService } from 'ng2-alfresco-core'; -import { Subject } from 'rxjs/Subject'; -import { MaterialModule } from './../material.module'; -import { NotSupportedFormatComponent } from './notSupportedFormat.component'; -import { PdfViewerComponent } from './pdfViewer.component'; - -interface RenditionResponse { - entry: { - status: string - }; -} - -describe('NotSupportedFormatComponent', () => { - - const nodeId = 'not-supported-node-id'; - - let component: NotSupportedFormatComponent; - let service: ContentService; - let fixture: ComponentFixture; - let debug: DebugElement; - let element: HTMLElement; - let renditionsService: RenditionsService; - - let renditionSubject: Subject; - let conversionSubject: Subject; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [ - CoreModule, - MaterialModule - ], - declarations: [ - NotSupportedFormatComponent, - PdfViewerComponent - ] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(NotSupportedFormatComponent); - service = fixture.debugElement.injector.get(ContentService); - debug = fixture.debugElement; - element = fixture.nativeElement; - component = fixture.componentInstance; - component.nodeId = nodeId; - - renditionSubject = new Subject(); - conversionSubject = new Subject(); - renditionsService = TestBed.get(RenditionsService); - spyOn(renditionsService, 'getRendition').and.returnValue(renditionSubject); - spyOn(renditionsService, 'convert').and.returnValue(conversionSubject); - }); - - describe('View', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - it('should display the Download button', () => { - expect(element.querySelector('[data-automation-id="viewer-download-button"]')).not.toBeNull(); - }); - - it('should display the name of the file', () => { - component.nameFile = 'Example Content.xls'; - fixture.detectChanges(); - expect(element.querySelector('h4 span').innerHTML).toEqual('Example Content.xls'); - }); - - it('should NOT show loading spinner by default', () => { - expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).toBeNull('Conversion spinner should NOT be shown by default'); - }); - }); - - describe('Convertibility to pdf', () => { - - it('should not show the "Convert to PDF" button by default', () => { - fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull(); - }); - - it('should be checked on ngInit', () => { - fixture.detectChanges(); - expect(renditionsService.getRendition).toHaveBeenCalledWith(nodeId, 'pdf'); - }); - - it('should NOT be checked on ngInit if nodeId is not set', () => { - component.nodeId = null; - fixture.detectChanges(); - expect(renditionsService.getRendition).not.toHaveBeenCalled(); - }); - - it('should show the "Convert to PDF" button if the node is convertible', async(() => { - fixture.detectChanges(); - renditionSubject.next({ entry: { status: 'NOT_CREATED' } }); - - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).not.toBeNull(); - }); - })); - - it('should NOT show the "Convert to PDF" button if the node is NOT convertible', async(() => { - component.convertible = true; - fixture.detectChanges(); - renditionSubject.error(new Error('Mocked error')); - - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull(); - }); - })); - - it('should NOT show the "Convert to PDF" button if the node is already converted', async(() => { - renditionSubject.next({ entry: { status: 'CREATED' } }); - - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull(); - }); - })); - - it('should start the conversion when clicking on the "Convert to PDF" button', () => { - component.convertible = true; - fixture.detectChanges(); - - const convertButton = debug.query(By.css('[data-automation-id="viewer-convert-button"]')); - convertButton.triggerEventHandler('click', null); - fixture.detectChanges(); - - const conversionSpinner = debug.query(By.css('[data-automation-id="viewer-conversion-spinner"]')); - expect(renditionsService.convert).toHaveBeenCalled(); - expect(conversionSpinner).not.toBeNull(); - }); - - it('should remove the spinner if an error happens during conversion', () => { - component.convertToPdf(); - - conversionSubject.error('whatever'); - fixture.detectChanges(); - - const conversionSpinner = debug.query(By.css('[data-automation-id="viewer-conversion-spinner"]')); - expect(conversionSpinner).toBeNull(); - }); - - it('should remove the spinner and show the pdf if conversion has finished', () => { - component.convertToPdf(); - - conversionSubject.complete(); - fixture.detectChanges(); - - const conversionSpinner = debug.query(By.css('[data-automation-id="viewer-conversion-spinner"]')); - const pdfRenditionViewer = debug.query(By.css('[data-automation-id="pdf-rendition-viewer"]')); - expect(conversionSpinner).toBeNull(); - expect(pdfRenditionViewer).not.toBeNull(); - }); - - it('should unsubscribe from the conversion subscription on ngOnDestroy', () => { - component.convertToPdf(); - - component.ngOnDestroy(); - conversionSubject.complete(); - fixture.detectChanges(); - - const pdfRenditionViewer = debug.query(By.css('[data-automation-id="pdf-rendition-viewer"]')); - expect(pdfRenditionViewer).toBeNull(); - }); - - it('should not throw error on ngOnDestroy if the conversion hasn\'t started at all' , () => { - const callNgOnDestroy = () => { - component.ngOnDestroy(); - }; - - expect(callNgOnDestroy).not.toThrowError(); - }); - }); - - describe('User Interaction', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - describe('Download', () => { - - it('should call download method if Click on Download button', () => { - spyOn(window, 'open'); - component.urlFile = 'test'; - - let downloadButton: any = element.querySelector('[data-automation-id="viewer-download-button"]'); - downloadButton.click(); - - expect(window.open).toHaveBeenCalled(); - }); - - it('should call content service download method if Click on Download button', () => { - spyOn(service, 'downloadBlob'); - - component.blobFile = new Blob(); - - let downloadButton: any = element.querySelector('[data-automation-id="viewer-download-button"]'); - downloadButton.click(); - - expect(service.downloadBlob).toHaveBeenCalled(); - }); - }); - - describe('Conversion', () => { - - function clickOnConvertButton() { - renditionSubject.next({ entry: { status: 'NOT_CREATED' } }); - fixture.detectChanges(); - - let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]'); - convertButton.click(); - fixture.detectChanges(); - } - - it('should show loading spinner and disable the "Convert to PDF button" after the button was clicked', () => { - clickOnConvertButton(); - - let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]'); - expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).not.toBeNull('Conversion spinner should be shown'); - expect(convertButton.disabled).toBe(true); - }); - - it('should re-enable the "Convert to PDF button" and hide spinner after unsuccessful conversion and hide loading spinner', () => { - clickOnConvertButton(); - - conversionSubject.error(new Error()); - fixture.detectChanges(); - - let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]'); - expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).toBeNull('Conversion spinner should be shown'); - expect(convertButton.disabled).toBe(false); - }); - - it('should show the pdf rendition after successful conversion', () => { - clickOnConvertButton(); - - conversionSubject.next(); - conversionSubject.complete(); - fixture.detectChanges(); - fixture.detectChanges(); - - expect(element.querySelector('[data-automation-id="pdf-rendition-viewer"]')).not.toBeNull('Pdf rendition should be shown.'); - }); - }); - }); -}); diff --git a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts b/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts deleted file mode 100644 index 0560f52d23..0000000000 --- a/ng2-components/ng2-alfresco-viewer/src/components/notSupportedFormat.component.ts +++ /dev/null @@ -1,133 +0,0 @@ -/*! - * @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 { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; -import { ContentService, RenditionsService } from 'ng2-alfresco-core'; - -const DEFAULT_CONVERSION_ENCODING = 'pdf'; - -@Component({ - selector: 'adf-not-supported-format', - templateUrl: './notSupportedFormat.component.html', - styleUrls: ['./notSupportedFormat.component.scss'], - host: { 'class': 'adf-not-supported-format' }, - encapsulation: ViewEncapsulation.None -}) -export class NotSupportedFormatComponent implements OnInit, OnDestroy { - - @Input() - nameFile: string; - - @Input() - urlFile: string; - - @Input() - blobFile: Blob; - - @Input() - nodeId: string|null = null; - - @Input() - showToolbar: boolean = true; - - convertible: boolean = false; - displayable: boolean = false; - isConversionStarted: boolean = false; - isConversionFinished: boolean = false; - renditionUrl: string|null = null; - conversionsubscription: any = null; - - constructor( - private contentService: ContentService, - private renditionsService: RenditionsService) {} - - /** - * Checks for available renditions if the nodeId is present - */ - ngOnInit() { - if (this.nodeId) { - this.checkRendition(); - } - } - - /** - * Download file opening it in a new window - */ - download() { - if (this.urlFile) { - window.open(this.urlFile); - } else { - this.contentService.downloadBlob(this.blobFile, this.nameFile); - } - } - - /** - * Update component's button according to the given rendition's availability - * - * @param {string} encoding - the rendition id - */ - checkRendition(encoding: string = DEFAULT_CONVERSION_ENCODING): void { - this.renditionsService.getRendition(this.nodeId, encoding) - .subscribe( - (response) => { - const status = response.entry.status.toString(); - if (status === 'NOT_CREATED') { - this.convertible = true; - this.displayable = false; - } else if (status === 'CREATED') { - this.convertible = false; - this.displayable = true; - } - }, - () => { - this.convertible = false; - this.displayable = false; - } - ); - } - - /** - * Set the component to loading state and send the conversion starting signal to parent component - */ - convertToPdf(): void { - this.isConversionStarted = true; - - this.conversionsubscription = this.renditionsService.convert(this.nodeId, DEFAULT_CONVERSION_ENCODING) - .subscribe({ - error: (error) => { this.isConversionStarted = false; }, - complete: () => { this.showPDF(); } - }); - } - - /** - * Show the PDF rendition of the node - */ - showPDF(): void { - this.renditionUrl = this.renditionsService.getRenditionUrl(this.nodeId, DEFAULT_CONVERSION_ENCODING); - this.isConversionStarted = false; - this.isConversionFinished = true; - } - - /** - * Kills the subscription polling if it has been started - */ - ngOnDestroy(): void { - if (this.isConversionStarted) { - this.conversionsubscription.unsubscribe(); - } - } -} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/pdfViewerHost.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/pdfViewerHost.component.scss index 17684164df..20817fce7c 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/pdfViewerHost.component.scss +++ b/ng2-components/ng2-alfresco-viewer/src/components/pdfViewerHost.component.scss @@ -8,6 +8,7 @@ overflow: hidden; opacity: 0.2; line-height: 1.0; + border: 1px solid gray; & > div { color: transparent; diff --git a/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.html b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.html new file mode 100644 index 0000000000..74de545144 --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.html @@ -0,0 +1,6 @@ +
+
+ wifi_tethering +
Document preview could not be loaded.
+
+
diff --git a/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.scss new file mode 100644 index 0000000000..8499afb75f --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.scss @@ -0,0 +1,8 @@ +.adf-viewer__unknown-format-view { + height: 90vh; + text-align: center; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; +} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.ts b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.ts new file mode 100644 index 0000000000..95c2af1199 --- /dev/null +++ b/ng2-components/ng2-alfresco-viewer/src/components/unknown-format/unknown-format.component.ts @@ -0,0 +1,26 @@ +/*! + * @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 { Component } from '@angular/core'; + +@Component({ + selector: 'adf-viewer-unknown-format', + templateUrl: 'unknown-format.component.html', + styleUrls: ['unknown-format.component.scss'] +}) +export class UnknownFormatComponent { +} diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.html b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.html index d3dd4a5c74..37bc165ef7 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.html +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.html @@ -4,80 +4,151 @@ [class.adf-viewer-inline-container]="!overlayMode">
- + + - {{ displayName }} + + + {{ displayName }} - + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
+ +
+

Loading

+
+ +
+
+
+ +
-
-
+
+
- - - + + - - - + + - - - + + - + - - - - + + + + + + -
- - -
+ + +
+
+ +
+ + + + DETAILS + + + + + Activity + + + +
+
diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.scss b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.scss index ea3471a69c..84750c3812 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.scss +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.scss @@ -1,4 +1,4 @@ -$adf-viewer-background-color: #515151; +$adf-viewer-background-color: #f5f5f5; @mixin full-screen() { width: 100%; @@ -33,7 +33,7 @@ $adf-viewer-background-color: #515151; @include full-screen(); display: flex; - flex-direction: column; + flex-direction: row; overflow-y: auto; overflow-x: hidden; position: relative; @@ -41,6 +41,7 @@ $adf-viewer-background-color: #515151; .adf-viewer-content { @include full-screen(); + flex: 1; } } @@ -66,4 +67,33 @@ $adf-viewer-background-color: #515151; align-items: center; display: flex; } + + &__loading-screen { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + height: 85vh; + + .md-spinner { + margin: 0 auto; + } + } + + &__info-drawer { + width: 350px; + display: block; + padding: 8px 0; + background-color: #fafafa; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.27); + border-left: 1px solid rgba(0, 0, 0, 0.07); + + .mat-tab-label { + text-transform: uppercase; + } + + .mat-card { + margin: 6px; + } + } } diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.spec.ts b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.spec.ts index 3a159eac6c..cc04ae154b 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.spec.ts +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.spec.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { Location } from '@angular/common'; +import { SpyLocation } from '@angular/common/testing'; import { DebugElement } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; @@ -25,9 +27,9 @@ import { EventMock } from '../assets/event.mock'; import { RenderingQueueServices } from '../services/rendering-queue.services'; import { ImgViewerComponent } from './imgViewer.component'; import { MediaPlayerComponent } from './mediaPlayer.component'; -import { NotSupportedFormatComponent } from './notSupportedFormat.component'; import { PdfViewerComponent } from './pdfViewer.component'; import { TxtViewerComponent } from './txtViewer.component'; +import { UnknownFormatComponent } from './unknown-format/unknown-format.component'; import { ViewerComponent } from './viewer.component'; declare let jasmine: any; @@ -49,12 +51,13 @@ describe('ViewerComponent', () => { ViewerComponent, PdfViewerComponent, TxtViewerComponent, - NotSupportedFormatComponent, MediaPlayerComponent, - ImgViewerComponent + ImgViewerComponent, + UnknownFormatComponent ], providers: [ - RenderingQueueServices + RenderingQueueServices, + { provide: Location, useClass: SpyLocation } ] }).compileComponents(); })); @@ -128,10 +131,6 @@ describe('ViewerComponent', () => { expect(element.querySelector('header')).toBeNull(); }); - it('should Close button be not present if is not overlay mode', () => { - expect(element.querySelector('.adf-viewer-close-button')).toBeNull(); - }); - it('should Esc button not hide the viewer if is not overlay mode', () => { EventMock.keyDown(27); fixture.detectChanges(); @@ -182,7 +181,7 @@ describe('ViewerComponent', () => { }); }); - describe('Exteznsion Type Test', () => { + describe('Extension Type Test', () => { it('should extension file pdf be loaded', (done) => { component.urlFile = 'base/src/assets/fake-test-file.pdf'; @@ -243,13 +242,13 @@ describe('ViewerComponent', () => { }); }); - it('should the not supported div be loaded if the file is a not supported extension', (done) => { + it('should display [unknown format] for unsupported extensions', (done) => { component.urlFile = 'fake-url-file.unsupported'; component.mimeType = ''; component.ngOnChanges(null).then(() => { fixture.detectChanges(); - expect(element.querySelector('adf-not-supported-format')).not.toBeNull(); + expect(element.querySelector('adf-viewer-unknown-format')).toBeDefined(); done(); }); }); @@ -333,17 +332,6 @@ describe('ViewerComponent', () => { done(); }); }); - - it('should not display the media player if the file identified by mimetype is a media but with not supported extension', (done) => { - component.urlFile = 'content'; - component.mimeType = 'video/avi'; - - component.ngOnChanges(null).then(() => { - fixture.detectChanges(); - expect(element.querySelector('adf-media-player')).toBeNull(); - done(); - }); - }); }); describe('Events', () => { diff --git a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.ts b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.ts index 4e087bd1c6..7f14a7e7e7 100644 --- a/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.ts +++ b/ng2-components/ng2-alfresco-viewer/src/components/viewer.component.ts @@ -15,9 +15,10 @@ * limitations under the License. */ +import { Location } from '@angular/common'; import { Component, EventEmitter, HostListener, Input, OnChanges, OnDestroy, Output, TemplateRef, ViewEncapsulation } from '@angular/core'; import { MinimalNodeEntryEntity } from 'alfresco-js-api'; -import { AlfrescoApiService, LogService } from 'ng2-alfresco-core'; +import { AlfrescoApiService, BaseEvent, LogService, RenditionsService } from 'ng2-alfresco-core'; @Component({ selector: 'adf-viewer, alfresco-viewer', @@ -44,30 +45,70 @@ export class ViewerComponent implements OnDestroy, OnChanges { showViewer: boolean = true; @Input() - showToolbar: boolean = true; + showToolbar = true; @Input() - displayName: string; + displayName: string = 'Unknown'; + + @Input() + allowGoBack = true; + + @Input() + allowOpenWith = true; + + @Input() + allowDownload = true; + + @Input() + allowPrint = true; + + @Input() + allowShare = true; + + @Input() + allowInfoDrawer = true; + + @Input() + showInfoDrawer = false; @Output() - showViewerChange: EventEmitter = new EventEmitter(); + goBack = new EventEmitter>(); @Output() - extensionChange: EventEmitter = new EventEmitter(); + showViewerChange = new EventEmitter(); + + @Output() + extensionChange = new EventEmitter(); + + viewerType: string = 'unknown'; + downloadUrl: string = null; + fileName: string = 'document'; + isLoading: boolean = false; extensionTemplates: { template: TemplateRef, isVisible: boolean }[] = []; - externalExtensions: string[] = []; - urlFileContent: string; otherMenu: any; extension: string; mimeType: string; - loaded: boolean = false; - constructor(private apiService: AlfrescoApiService, - private logService: LogService) { - } + private extensions = { + image: ['png', 'jpg', 'jpeg', 'gif', 'bpm'], + media: ['wav', 'mp4', 'mp3', 'webm', 'ogg'], + text: ['txt', 'xml', 'js', 'html'], + pdf: ['pdf'] + }; + + private mimeTypes = [ + { mimeType: 'application/x-javascript', type: 'text' }, + { mimeType: 'application/pdf', type: 'pdf' } + ]; + + constructor( + private apiService: AlfrescoApiService, + private logService: LogService, + private location: Location, + private renditionService: RenditionsService) {} ngOnChanges(changes) { if (this.showViewer) { @@ -77,28 +118,66 @@ export class ViewerComponent implements OnDestroy, OnChanges { return new Promise((resolve, reject) => { if (this.blobFile) { + this.isLoading = true; + this.mimeType = this.blobFile.type; + this.viewerType = this.getViewerTypeByMimeType(this.mimeType); + + this.allowDownload = false; + // TODO: wrap blob into the data url and allow downloading + this.extensionChange.emit(this.mimeType); + this.isLoading = false; + this.scrollTop(); resolve(); } else if (this.urlFile) { + this.isLoading = true; let filenameFromUrl = this.getFilenameFromUrl(this.urlFile); - this.displayName = filenameFromUrl ? filenameFromUrl : ''; + this.displayName = filenameFromUrl || 'Unknown'; this.extension = this.getFileExtension(filenameFromUrl); - this.extensionChange.emit(this.extension); this.urlFileContent = this.urlFile; + + this.downloadUrl = this.urlFile; + this.fileName = this.displayName; + + this.viewerType = this.getViewerTypeByExtension(this.extension); + if (this.viewerType === 'unknown') { + this.viewerType = this.getViewerTypeByMimeType(this.mimeType); + } + + this.extensionChange.emit(this.extension); + this.isLoading = false; + this.scrollTop(); resolve(); } else if (this.fileNodeId) { + this.isLoading = true; this.apiService.getInstance().nodes.getNodeInfo(this.fileNodeId).then( (data: MinimalNodeEntryEntity) => { this.mimeType = data.content.mimeType; this.displayName = data.name; this.urlFileContent = this.apiService.getInstance().content.getContentUrl(data.id); this.extension = this.getFileExtension(data.name); + + this.fileName = data.name; + this.downloadUrl = this.apiService.getInstance().content.getContentUrl(data.id, true); + + this.viewerType = this.getViewerTypeByExtension(this.extension); + if (this.viewerType === 'unknown') { + this.viewerType = this.getViewerTypeByMimeType(this.mimeType); + } + + if (this.viewerType === 'unknown') { + this.displayAsPdf(data.id); + } else { + this.isLoading = false; + } + this.extensionChange.emit(this.extension); - this.loaded = true; + this.scrollTop(); resolve(); }, (error) => { + this.isLoading = false; reject(error); this.logService.error('This node does not exist'); } @@ -108,6 +187,79 @@ export class ViewerComponent implements OnDestroy, OnChanges { } } + scrollTop() { + window.scrollTo(0, 1); + } + + getViewerTypeByMimeType(mimeType: string) { + if (mimeType) { + mimeType = mimeType.toLowerCase(); + + if (mimeType.startsWith('image/')) { + return 'image'; + } + + if (mimeType.startsWith('text/')) { + return 'text'; + } + + if (mimeType.startsWith('video/')) { + return 'media'; + } + + if (mimeType.startsWith('audio/')) { + return 'media'; + } + + const registered = this.mimeTypes.find(t => t.mimeType === mimeType); + if (registered) { + return registered.type; + } + } + return 'unknown'; + } + + getViewerTypeByExtension(extension: string) { + if (extension) { + extension = extension.toLowerCase(); + } + + if (this.isCustomViewerExtension(extension)) { + return 'custom'; + } + + if (this.extensions.image.indexOf(extension) >= 0) { + return 'image'; + } + + if (this.extensions.media.indexOf(extension) >= 0) { + return 'media'; + } + + if (this.extensions.text.indexOf(extension) >= 0) { + return 'text'; + } + + if (this.extensions.pdf.indexOf(extension) >= 0) { + return 'pdf'; + } + + return 'unknown'; + } + + onBackButtonClick() { + if (this.overlayMode) { + this.close(); + } else { + const event = new BaseEvent(); + this.goBack.next(event); + + if (!event.defaultPrevented) { + this.location.back(); + } + } + } + /** * close the viewer */ @@ -127,7 +279,6 @@ export class ViewerComponent implements OnDestroy, OnChanges { this.urlFileContent = ''; this.displayName = ''; this.fileNodeId = null; - this.loaded = false; this.extension = null; this.mimeType = null; } @@ -157,113 +308,19 @@ export class ViewerComponent implements OnDestroy, OnChanges { * @param {string} fileName - file name * @returns {string} file name extension */ - private getFileExtension(fileName: string): string { + getFileExtension(fileName: string): string { return fileName.split('.').pop().toLowerCase(); } - /** - * Check if the content is an image through the extension or mime type - * - * @returns {boolean} - */ - public isImage(): boolean { - return this.isImageExtension() || this.isImageMimeType(); - } + isCustomViewerExtension(extension: string): boolean { + const extensions = this.externalExtensions || []; - /** - * Check if the content is a media through the extension or mime type - * - * @returns {boolean} - */ - public isMedia(): boolean { - return this.isMediaExtension(this.extension) || this.isMediaMimeType(); - } - - /** - * check if the current file is a supported image extension - * - * @returns {boolean} - */ - private isImageExtension(): boolean { - return this.extension === 'png' || this.extension === 'jpg' || - this.extension === 'jpeg' || this.extension === 'gif' || this.extension === 'bmp'; - } - - /** - * check if the current file has an image-based mimetype - * - * @returns {boolean} - */ - private isMediaMimeType(): boolean { - let mimeExtension; - if (this.mimeType && this.mimeType.indexOf('/')) { - mimeExtension = this.mimeType.substr(this.mimeType.indexOf('/') + 1, this.mimeType.length); - } - return (this.mimeType && (this.mimeType.indexOf('video/') === 0 || this.mimeType.indexOf('audio/') === 0)) && this.isMediaExtension(mimeExtension); - } - - /** - * check if the current file is a supported media extension - * @param {string} extension - * - * @returns {boolean} - */ - private isMediaExtension(extension: string): boolean { - return extension === 'wav' || extension === 'mp4' || extension === 'mp3' || extension === 'WebM' || extension === 'Ogg'; - } - - /** - * check if the current file has an image-based mimetype - * - * @returns {boolean} - */ - private isImageMimeType(): boolean { - return this.mimeType && this.mimeType.indexOf('image/') === 0; - } - - /** - * check if the current file is a supported pdf extension - * - * @returns {boolean} - */ - public isPdf(): boolean { - return this.extension === 'pdf' || this.mimeType === 'application/pdf'; - } - - /** - * check if the current file is a supported txt extension - * - * @returns {boolean} - */ - public isText(): boolean { - return this.extension === 'txt' || this.mimeType === 'text/txt' || this.mimeType === 'text/plain'; - } - - /** - * check if the current file is a supported extension - * - * @returns {boolean} - */ - supportedExtension(): boolean { - return this.isImage() || this.isPdf() || this.isMedia() || this.isText() || this.isExternalSupportedExtension(); - } - - /** - * Check if the file is compatible with one of the extension - * - * @returns {boolean} - */ - isExternalSupportedExtension(): boolean { - let externalType: string; - - if (this.externalExtensions && (this.externalExtensions instanceof Array)) { - externalType = this.externalExtensions.find((externalExtension) => { - return externalExtension.toLowerCase() === this.extension; - - }); + if (extension && extensions.length > 0) { + extension = extension.toLowerCase(); + return extensions.indexOf(extension) >= 0; } - return !!externalType; + return false; } /** @@ -278,12 +335,56 @@ export class ViewerComponent implements OnDestroy, OnChanges { } } - /** - * return true if the data about the node in the ecm are loaded - * - * @returns {boolean} - */ - isLoaded(): boolean { - return this.fileNodeId ? this.loaded : true; + download() { + if (this.allowDownload && this.downloadUrl && this.fileName) { + const link = document.createElement('a'); + + link.style.display = 'none'; + link.download = this.fileName; + link.href = this.downloadUrl; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + } + + private displayAsPdf(nodeId: string) { + this.isLoading = true; + + this.renditionService.getRendition(nodeId, 'pdf').subscribe( + (response) => { + const status = response.entry.status.toString(); + + if (status === 'CREATED') { + this.isLoading = false; + this.showPdfRendition(nodeId); + } else if (status === 'NOT_CREATED') { + this.renditionService.convert(nodeId, 'pdf').subscribe({ + complete: () => { + this.isLoading = false; + this.showPdfRendition(nodeId); + }, + error: (error) => { + this.isLoading = false; + console.log(error); + } + }); + } else { + this.isLoading = false; + } + }, + (err) => { + this.isLoading = false; + console.log(err); + } + ); + } + + private showPdfRendition(nodeId: string) { + if (nodeId) { + this.viewerType = 'pdf'; + this.urlFileContent = this.renditionService.getRenditionUrl(nodeId, 'pdf'); + } } } diff --git a/ng2-components/ng2-alfresco-viewer/src/directives/extension-viewer.directive.spec.ts b/ng2-components/ng2-alfresco-viewer/src/directives/extension-viewer.directive.spec.ts index 398406e3ce..0dfa24656c 100644 --- a/ng2-components/ng2-alfresco-viewer/src/directives/extension-viewer.directive.spec.ts +++ b/ng2-components/ng2-alfresco-viewer/src/directives/extension-viewer.directive.spec.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { Location } from '@angular/common'; +import { SpyLocation } from '@angular/common/testing'; import { ElementRef } from '@angular/core'; import { Injector } from '@angular/core'; import { async, getTestBed, TestBed } from '@angular/core/testing'; @@ -28,7 +30,7 @@ export class MockElementRef extends ElementRef { } } -describe('ExtensionViewerComponent', () => { +describe('ExtensionViewerDirective', () => { let injector: Injector; let extensionViewerDirective: ExtensionViewerDirective; let viewerComponent: ViewerComponent; @@ -37,6 +39,7 @@ describe('ExtensionViewerComponent', () => { TestBed.configureTestingModule({ imports: [CoreModule], providers: [ + { provide: Location, useClass: SpyLocation }, ExtensionViewerDirective, {provide: ElementRef, useClass: MockElementRef}, ViewerComponent