Viewer enhancements and Viewer Dialog prototype (#2200)

* viewer dialog scaffold

* toolbar divider component

* simple error screen

* material module and tooltips

* show file name in the title

* improved settings, simple image viewer

* flex-based image viewer, minor fixes

* ability to switch between viewers

* single viewer for images

* remove MDL from the Viewer component

* remove hardcoded demo shell layout

remove harcoded assumptions on "header" and "main" elements

* rework text viewer, remove MDL dependency

* upgrade 'unknown format' view, remove MDL

* simplify media viewer layout

* simplify image viewer

* clean pdf viewer

* migrate pdf viewer styles to scss

* rewrite pdf viewer host styles in scss

* fix unit tests and cleanup layout

* file viewer service

* viewer dialog supports downloads if url provided
This commit is contained in:
Denys Vuika
2017-08-11 10:15:13 +01:00
committed by Mario Romano
parent d460824df4
commit bb53844f92
43 changed files with 1139 additions and 965 deletions

View File

@@ -29,6 +29,8 @@
</adf-dropdown-breadcrumb> </adf-dropdown-breadcrumb>
</adf-toolbar-title> </adf-toolbar-title>
<adf-toolbar-divider></adf-toolbar-divider>
<button md-icon-button <button md-icon-button
(click)="onCreateFolderClicked($event)"> (click)="onCreateFolderClicked($event)">
<md-icon>create_new_folder</md-icon> <md-icon>create_new_folder</md-icon>
@@ -56,6 +58,8 @@
<button md-menu-item (click)="toolbarColor = 'warn'">Warn</button> <button md-menu-item (click)="toolbarColor = 'warn'">Warn</button>
</md-menu> </md-menu>
<adf-toolbar-divider></adf-toolbar-divider>
<button md-icon-button [mdMenuTriggerFor]="menu"> <button md-icon-button [mdMenuTriggerFor]="menu">
<md-icon>more_vert</md-icon> <md-icon>more_vert</md-icon>
</button> </button>
@@ -210,6 +214,14 @@
</div> </div>
<div class="container"> <div class="container">
<section *ngIf="!useViewerDialog">
<md-slide-toggle [(ngModel)]="useInlineViewer">Use inline viewer (no overlay)</md-slide-toggle>
</section>
<section>
<md-slide-toggle [(ngModel)]="useViewerDialog">Use File Viewer dialog</md-slide-toggle>
</section>
<section> <section>
<md-slide-toggle [(ngModel)]="multiselect">Multiselect (with checkboxes)</md-slide-toggle> <md-slide-toggle [(ngModel)]="multiselect">Multiselect (with checkboxes)</md-slide-toggle>
</section> </section>
@@ -291,26 +303,28 @@
<file-uploading-dialog #fileDialog></file-uploading-dialog> <file-uploading-dialog #fileDialog></file-uploading-dialog>
<div *ngIf="fileShowed"> <div *ngIf="showViewer">
<alfresco-viewer [(showViewer)]="fileShowed" <ng-container *ngIf="!useInlineViewer">
[fileNodeId]="fileNodeId" <alfresco-viewer
[overlayMode]="true"> [(showViewer)]="showViewer"
[fileNodeId]="fileNodeId"
[overlayMode]="true">
<extension-viewer [supportedExtensions]="['obj','3DS']" #extension> <extension-viewer [supportedExtensions]="['obj','3DS']" #extension>
<ng-template let-urlFileContent="urlFileContent" let-extension="extension" > <ng-template let-urlFileContent="urlFileContent" let-extension="extension" >
<threed-viewer [urlFile]="urlFileContent" [extension]="extension" ></threed-viewer> <threed-viewer [urlFile]="urlFileContent" [extension]="extension" ></threed-viewer>
</ng-template> </ng-template>
</extension-viewer> </extension-viewer>
</alfresco-viewer> </alfresco-viewer>
</ng-container>
<!-- Comment the viewer above and uncomment that one below if you want test the overlay false viewer-->
<!--<div *ngIf="fileShowed" class="adf-not-overlay-viewer">-->
<!--<alfresco-viewer [(showViewer)]="fileShowed"-->
<!--[fileNodeId]="fileNodeId"-->
<!--[overlayMode]="false">-->
<!--</alfresco-viewer>-->
<!--</div>-->
<ng-container *ngIf="useInlineViewer">
<div class="adf-not-overlay-viewer">
<alfresco-viewer
[(showViewer)]="showViewer"
[fileNodeId]="fileNodeId">
</alfresco-viewer>
</div>
</ng-container>
</div> </div>

View File

@@ -28,6 +28,8 @@ import { DocumentListComponent, PermissionStyleModel } from 'ng2-alfresco-docume
import { CreateFolderDialogComponent } from '../../dialogs/create-folder.dialog'; import { CreateFolderDialogComponent } from '../../dialogs/create-folder.dialog';
import { DownloadZipDialogComponent } from './../../dialogs/download-zip.dialog'; import { DownloadZipDialogComponent } from './../../dialogs/download-zip.dialog';
import { ViewerDialogComponent, ViewerDialogSettings, ViewerService } from 'ng2-alfresco-viewer';
@Component({ @Component({
selector: 'adf-files-component', selector: 'adf-files-component',
templateUrl: './files.component.html', templateUrl: './files.component.html',
@@ -39,11 +41,13 @@ export class FilesComponent implements OnInit {
errorMessage: string = null; errorMessage: string = null;
fileNodeId: any; fileNodeId: any;
fileShowed: boolean = false; showViewer: boolean = false;
useCustomToolbar = true; useCustomToolbar = true;
toolbarColor = 'default'; toolbarColor = 'default';
useDropdownBreadcrumb = false; useDropdownBreadcrumb = false;
useViewerDialog = true;
useInlineViewer = false;
selectionModes = [ selectionModes = [
{ value: 'none', viewValue: 'None' }, { value: 'none', viewValue: 'None' },
@@ -90,16 +94,27 @@ export class FilesComponent implements OnInit {
private contentService: AlfrescoContentService, private contentService: AlfrescoContentService,
private dialog: MdDialog, private dialog: MdDialog,
private translateService: AlfrescoTranslationService, private translateService: AlfrescoTranslationService,
private viewerService: ViewerService,
private router: Router, private router: Router,
@Optional() private route: ActivatedRoute) { @Optional() private route: ActivatedRoute) {
} }
showFile(event) { showFile(event) {
if (event.value.entry.isFile) { if (this.useViewerDialog) {
this.fileNodeId = event.value.entry.id; if (event.value.entry.isFile) {
this.fileShowed = true; this.viewerService
.showViewerForNode(event.value.entry)
.then(result => {
console.log(result);
});
}
} else { } else {
this.fileShowed = false; if (event.value.entry.isFile) {
this.fileNodeId = event.value.entry.id;
this.showViewer = true;
} else {
this.showViewer = false;
}
} }
} }

View File

@@ -0,0 +1,35 @@
/*!
* @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, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'adf-toolbar-divider',
template: '<div></div>',
host: { 'class': 'adf-toolbar-divider' },
styles: [`
.adf-toolbar-divider > div {
height: 24px;
width: 1px;
background: rgba(0, 0, 0, 0.26);
margin-left: 5px;
margin-right: 5px;
}
`],
encapsulation: ViewEncapsulation.None
})
export class ToolbarDividerComponent {}

View File

@@ -41,6 +41,19 @@ The toolbar should now look similar to the following:
![](docs/adf-toolbar-02.png) ![](docs/adf-toolbar-02.png)
## Divider
You can divide groups of elements with a visual separator `<adf-toolbar-divider>`:
```html
<adf-toolbar>
<button></button>
<button></button>
<adf-toolbar-divider></adf-toolbar-divider>
<button></button>
</adf-toolbar>
```
## Dropdown menu ## Dropdown menu
You can use the following example to create a dropdown menu: You can use the following example to create a dropdown menu:

View File

@@ -19,6 +19,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MdToolbarModule } from '@angular/material'; import { MdToolbarModule } from '@angular/material';
import { ToolbarDividerComponent } from './toolbar-divider.component';
import { ToolbarTitleComponent } from './toolbar-title.component'; import { ToolbarTitleComponent } from './toolbar-title.component';
import { ToolbarComponent } from './toolbar.component'; import { ToolbarComponent } from './toolbar.component';
@@ -29,12 +30,14 @@ import { ToolbarComponent } from './toolbar.component';
], ],
declarations: [ declarations: [
ToolbarComponent, ToolbarComponent,
ToolbarTitleComponent ToolbarTitleComponent,
ToolbarDividerComponent
], ],
exports: [ exports: [
MdToolbarModule, MdToolbarModule,
ToolbarComponent, ToolbarComponent,
ToolbarTitleComponent ToolbarTitleComponent,
ToolbarDividerComponent
] ]
}) })
export class ToolbarModule {} export class ToolbarModule {}

View File

@@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;;;;;;;;;;;;AAWH,sCAA8D;AAC9D,uDAA+C;AAE/C,sEAAoE;AACpE,oFAAiF;AACjF,4EAA0E;AAC1E,gFAA8E;AAC9E,8FAAmF;AACnF,4EAA0E;AAC1E,0FAAuF;AAEvF,uDAAkD;AAClD,6DAAwD;AACxD,0DAAqD;AACrD,4DAAuD;AACvD,mEAA8D;AAC9D,0DAAqD;AAExC,QAAA,iBAAiB,GAAU;IACpC,kCAAe;IACf,wCAAkB;IAClB,4CAAoB;IACpB,iDAAkB;IAClB,wCAAkB;IAClB,qDAAwB;CAC3B,CAAC;AAEW,QAAA,gBAAgB,GAAU;IACnC,iDAAsB;CACzB,CAAC;AAgBF,IAAa,YAAY;IAAzB;IASA,CAAC;IARU,oBAAO,GAAd;QACI,MAAM,CAAC;YACH,QAAQ,EAAE,cAAY;YACtB,SAAS,EACF,wBAAgB,QACtB;SACJ,CAAC;IACN,CAAC;IACL,mBAAC;AAAD,CAAC,AATD,IASC;AATY,YAAY;IAdxB,eAAQ,CAAC;QACN,OAAO,EAAE;YACL,8BAAU;SACb;QACD,YAAY,EACL,yBAAiB,QACvB;QACD,SAAS,EACF,wBAAgB,QACtB;QACD,OAAO,EACA,yBAAiB,QACvB;KACJ,CAAC;GACW,YAAY,CASxB;AATY,oCAAY"}

View File

@@ -15,35 +15,27 @@
* limitations under the License. * limitations under the License.
*/ */
/**
* ng2-alfresco-viewer, provide components to view files.
*
* Components provided:
* <alfresco-viewer [urlFile]="'localTestFile.pdf'">
* <div class="mdl-spinner mdl-js-spinner is-active"></div>
* </alfresco-viewer>
*/
import { ModuleWithProviders, NgModule } from '@angular/core'; import { ModuleWithProviders, NgModule } from '@angular/core';
import { CoreModule } from 'ng2-alfresco-core'; import { CoreModule } from 'ng2-alfresco-core';
import { MdButtonModule, MdIconModule, MdProgressSpinnerModule } from '@angular/material'; import { MaterialModule } from './src/material.module';
export { ViewerComponent } from './src/components/viewer.component';
import { ImgViewerComponent } from './src/components/imgViewer.component'; import { ImgViewerComponent } from './src/components/imgViewer.component';
import { MediaPlayerComponent } from './src/components/mediaPlayer.component'; import { MediaPlayerComponent } from './src/components/mediaPlayer.component';
import { NotSupportedFormatComponent } from './src/components/notSupportedFormat.component'; import { NotSupportedFormatComponent } from './src/components/notSupportedFormat.component';
import { PdfViewerComponent } from './src/components/pdfViewer.component'; import { PdfViewerComponent } from './src/components/pdfViewer.component';
import { TxtViewerComponent } from './src/components/txtViewer.component'; import { TxtViewerComponent } from './src/components/txtViewer.component';
import { ViewerDialogComponent } from './src/components/viewer-dialog.component';
import { ViewerComponent } from './src/components/viewer.component'; import { ViewerComponent } from './src/components/viewer.component';
import { ExtensionViewerDirective } from './src/directives/extension-viewer.directive'; import { ExtensionViewerDirective } from './src/directives/extension-viewer.directive';
import { RenderingQueueServices } from './src/services/rendering-queue.services';
export * from './src/components/viewer.component'; import { RenderingQueueServices } from './src/services/rendering-queue.services';
export * from './src/services/rendering-queue.services'; import { ViewerService } from './src/services/viewer.service';
export * from './src/components/imgViewer.component';
export * from './src/components/mediaPlayer.component'; export { ViewerDialogComponent } from './src/components/viewer-dialog.component';
export * from './src/components/notSupportedFormat.component'; export { ViewerDialogSettings } from './src/components/viewer-dialog.settings';
export * from './src/components/pdfViewer.component'; export { ViewerService } from './src/services/viewer.service';
export * from './src/components/txtViewer.component';
export const VIEWER_DIRECTIVES: any[] = [ export const VIEWER_DIRECTIVES: any[] = [
ViewerComponent, ViewerComponent,
@@ -52,36 +44,38 @@ export const VIEWER_DIRECTIVES: any[] = [
MediaPlayerComponent, MediaPlayerComponent,
NotSupportedFormatComponent, NotSupportedFormatComponent,
PdfViewerComponent, PdfViewerComponent,
ExtensionViewerDirective ExtensionViewerDirective,
]; ViewerDialogComponent
export const VIEWER_PROVIDERS: any[] = [
RenderingQueueServices
]; ];
@NgModule({ @NgModule({
imports: [ imports: [
CoreModule, CoreModule,
MdIconModule, MaterialModule
MdButtonModule,
MdProgressSpinnerModule
], ],
declarations: [ declarations: [
...VIEWER_DIRECTIVES ...VIEWER_DIRECTIVES
], ],
providers: [ providers: [
...VIEWER_PROVIDERS RenderingQueueServices,
ViewerService
], ],
exports: [ exports: [
...VIEWER_DIRECTIVES ...VIEWER_DIRECTIVES
],
entryComponents: [
ViewerDialogComponent
] ]
}) })
export class ViewerModule { export class ViewerModule {
/** @deprecated in 1.8.0 */
static forRoot(): ModuleWithProviders { static forRoot(): ModuleWithProviders {
console.log('ViewerModule.forRoot is deprecated and will be removed in future versions');
return { return {
ngModule: ViewerModule, ngModule: ViewerModule,
providers: [ providers: [
...VIEWER_PROVIDERS RenderingQueueServices,
ViewerService
] ]
}; };
} }

View File

@@ -1,40 +0,0 @@
.viewer-image-row {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
box-orient: horizontal;
flex-direction: row;
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
justify-content: center;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
align-items: center;
}
.viewer-image-cell {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
padding: 10px;
margin: 10px;
text-align: center;
}
.viewer-image {
height: 80vh;
max-width:100%;
}

View File

@@ -1,7 +1,3 @@
<div class="viewer-image-content"> <div class="image-container">
<div class="viewer-image-row"> <img id="viewer-image" [src]="urlFile" [alt]="nameFile" />
<div class="viewer-image-cell">
<img id="viewer-image" [src]="urlFile" [alt]="nameFile" class="center-element viewer-image"/>
</div>
</div>
</div> </div>

View File

@@ -0,0 +1,13 @@
.adf-img-viewer {
.image-container {
display: flex;
flex: 1;
text-align: center;
flex-direction: row;
justify-content: center;
height: 90vh;
img {
object-fit: contain;
}
}
}

View File

@@ -15,15 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
/* tslint:disable:component-selector */ import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { ContentService } from 'ng2-alfresco-core'; import { ContentService } from 'ng2-alfresco-core';
@Component({ @Component({
selector: 'img-viewer', selector: 'adf-img-viewer',
templateUrl: './imgViewer.component.html', templateUrl: './imgViewer.component.html',
styleUrls: ['./imgViewer.component.css'] styleUrls: ['./imgViewer.component.scss'],
host: { 'class': 'adf-img-viewer' },
encapsulation: ViewEncapsulation.None
}) })
export class ImgViewerComponent implements OnChanges { export class ImgViewerComponent implements OnChanges {

View File

@@ -1,48 +0,0 @@
.viewer-video-row {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
box-orient: horizontal;
flex-direction: row;
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
justify-content: center;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
align-items: center;
}
.viewer-video-cell {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
padding: 10px;
margin: 10px;
text-align: center;
}
video {
max-height: 80vh;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
align-content: center;
max-width: 100%;
margin-left: auto;
margin-right: auto;
}

View File

@@ -1,10 +1,3 @@
<div class="viewer-video-content"> <video controls>
<div class="viewer-video-row"> <source [src]="urlFile" [type]="mimeType" />
<div class="viewer-video-cell"> </video>
<video controls >
<source [src]="urlFile" [type]="mimeType" />
</video>
</div>
</div>
</div>

View File

@@ -0,0 +1,7 @@
.adf-media-player {
video {
display: flex;
flex: 1;
max-height: 90vh;
}
}

View File

@@ -15,15 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
/* tslint:disable:component-selector */ import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { ContentService } from 'ng2-alfresco-core'; import { ContentService } from 'ng2-alfresco-core';
@Component({ @Component({
selector: 'media-player', selector: 'adf-media-player',
templateUrl: './mediaPlayer.component.html', templateUrl: './mediaPlayer.component.html',
styleUrls: ['./mediaPlayer.component.css'] styleUrls: ['./mediaPlayer.component.scss'],
host: { 'class': 'adf-media-player' },
encapsulation: ViewEncapsulation.None
}) })
export class MediaPlayerComponent implements OnChanges { export class MediaPlayerComponent implements OnChanges {

View File

@@ -1,48 +0,0 @@
.unsupported-container {
width: 600px;
}
.viewer-margin {
margin: auto !important;
padding: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.viewer-download-text {
text-align: center;
word-wrap: break-word;
min-height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
.viewer-download-text h4 {
margin: 0;
}
.adf-conversion-spinner {
margin: 16px 0;
}
.viewer-margin >>> .adf-conversion-spinner.mat-spinner path {
stroke: #00BFD4;
}
.button-container {
display: flex;
align-items: center;
justify-content: space-around;
}
.button-container button {
line-height: 40px;
}
.viewer-button-icon {
margin-right: 10px;
margin-top: -5px;
}

View File

@@ -1,39 +1,47 @@
<section *ngIf="!isConversionFinished" class="unsupported-container"> <md-card *ngIf="!isConversionFinished">
<div class="viewer-margin mdl-card mdl-cell mdl-cell--9-col-desktop mdl-cell--6-col-tablet mdl-cell--4-col-phone mdl-shadow--2dp"> <md-card-title>
<div *ngIf="!isConversionStarted" class="viewer-download-text mdl-card__supporting-text"> Unknown format
<h4>File '<span>{{nameFile}}</span>' is of an unsupported format</h4> </md-card-title>
</div> <md-card-content>
<h4>File '<span>{{nameFile}}</span>' is of an unsupported format</h4>
<md-spinner *ngIf="isConversionStarted" <md-progress-bar
id="conversion-spinner" *ngIf="isConversionStarted"
class="adf-conversion-spinner" mode="indeterminate"
color="primary" data-automation-id="viewer-conversion-spinner">
data-automation-id="viewer-conversion-spinner"></md-spinner> </md-progress-bar>
</md-card-content>
<md-card-actions>
<button
md-button
data-automation-id="viewer-download-button"
(click)="download()">
<md-icon>cloud_download</md-icon>
Download
</button>
<button
md-button
*ngIf="convertible"
[disabled]="isConversionStarted"
data-automation-id="viewer-convert-button"
(click)="convertToPdf()">
<md-icon>insert_drive_file</md-icon>
Convert to PDF
</button>
<button
md-button
*ngIf="displayable"
data-automation-id="viewer-display-button"
(click)="showPDF()">
<md-icon>insert_drive_file</md-icon>
Show PDF
</button>
</md-card-actions>
</md-card>
<div class="button-container mdl-card__actions"> <adf-pdf-viewer
<button md-button id="viewer-download-button" aria-label="Download" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent" (click)="download()"> *ngIf="isConversionFinished"
<md-icon class="viewer-button-icon">cloud_download</md-icon> Download [showToolbar]="showToolbar"
</button> [urlFile]="renditionUrl"
<button *ngIf="convertible"
md-button
id="viewer-convert-button"
aria-label="Convert to PDF"
class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary"
[disabled]="isConversionStarted"
(click)="convertToPdf()"
data-automation-id="viewer-convert-button">
<md-icon class="viewer-button-icon">insert_drive_file</md-icon> Convert to PDF
</button>
<button md-button *ngIf="displayable" id="viewer-display-button" aria-label="Show PDF" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" (click)="showPDF()">
<md-icon class="viewer-button-icon">insert_drive_file</md-icon> Show PDF
</button>
</div>
</div>
</section>
<pdf-viewer *ngIf="isConversionFinished"
id="pdf-rendition-viewer"
[showToolbar]="showToolbar"
[urlFile]="renditionUrl"
[nameFile]="nameFile" [nameFile]="nameFile"
data-automation-id="pdf-rendition-viewer"></pdf-viewer> data-automation-id="pdf-rendition-viewer">
</adf-pdf-viewer>

View File

@@ -0,0 +1,5 @@
.adf-not-supported-format {
.mat-card {
max-width: 400px;
}
}

View File

@@ -17,18 +17,10 @@
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MdButtonModule, MdIconModule, MdProgressSpinnerModule } from '@angular/material';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { import { ContentService, CoreModule, RenditionsService } from 'ng2-alfresco-core';
AlfrescoApiService,
AlfrescoAuthenticationService,
AlfrescoSettingsService,
ContentService,
CoreModule,
LogService,
RenditionsService
} from 'ng2-alfresco-core';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
import { MaterialModule } from './../material.module';
import { NotSupportedFormatComponent } from './notSupportedFormat.component'; import { NotSupportedFormatComponent } from './notSupportedFormat.component';
import { PdfViewerComponent } from './pdfViewer.component'; import { PdfViewerComponent } from './pdfViewer.component';
@@ -49,28 +41,18 @@ describe('NotSupportedFormatComponent', () => {
let element: HTMLElement; let element: HTMLElement;
let renditionsService: RenditionsService; let renditionsService: RenditionsService;
let renditionSubject: Subject<RenditionResponse>, let renditionSubject: Subject<RenditionResponse>;
conversionSubject: Subject<any>; let conversionSubject: Subject<any>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
CoreModule, CoreModule,
MdIconModule, MaterialModule
MdButtonModule,
MdProgressSpinnerModule
], ],
declarations: [ declarations: [
NotSupportedFormatComponent, NotSupportedFormatComponent,
PdfViewerComponent PdfViewerComponent
],
providers: [
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoApiService,
ContentService,
RenditionsService,
LogService
] ]
}).compileComponents(); }).compileComponents();
})); }));
@@ -96,8 +78,8 @@ describe('NotSupportedFormatComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should be present Download button', () => { it('should display the Download button', () => {
expect(element.querySelector('#viewer-download-button')).not.toBeNull(); expect(element.querySelector('[data-automation-id="viewer-download-button"]')).not.toBeNull();
}); });
it('should display the name of the file', () => { it('should display the name of the file', () => {
@@ -107,7 +89,7 @@ describe('NotSupportedFormatComponent', () => {
}); });
it('should NOT show loading spinner by default', () => { it('should NOT show loading spinner by default', () => {
expect(element.querySelector('#conversion-spinner')).toBeNull('Conversion spinner should NOT be shown by default'); expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).toBeNull('Conversion spinner should NOT be shown by default');
}); });
}); });
@@ -115,7 +97,7 @@ describe('NotSupportedFormatComponent', () => {
it('should not show the "Convert to PDF" button by default', () => { it('should not show the "Convert to PDF" button by default', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-convert-button')).toBeNull(); expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull();
}); });
it('should be checked on ngInit', () => { it('should be checked on ngInit', () => {
@@ -135,7 +117,7 @@ describe('NotSupportedFormatComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-convert-button')).not.toBeNull(); expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).not.toBeNull();
}); });
})); }));
@@ -146,7 +128,7 @@ describe('NotSupportedFormatComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-convert-button')).toBeNull(); expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull();
}); });
})); }));
@@ -155,7 +137,7 @@ describe('NotSupportedFormatComponent', () => {
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-convert-button')).toBeNull(); expect(element.querySelector('[data-automation-id="viewer-convert-button"]')).toBeNull();
}); });
})); }));
@@ -226,7 +208,7 @@ describe('NotSupportedFormatComponent', () => {
spyOn(window, 'open'); spyOn(window, 'open');
component.urlFile = 'test'; component.urlFile = 'test';
let downloadButton: any = element.querySelector('#viewer-download-button'); let downloadButton: any = element.querySelector('[data-automation-id="viewer-download-button"]');
downloadButton.click(); downloadButton.click();
expect(window.open).toHaveBeenCalled(); expect(window.open).toHaveBeenCalled();
@@ -237,7 +219,7 @@ describe('NotSupportedFormatComponent', () => {
component.blobFile = new Blob(); component.blobFile = new Blob();
let downloadButton: any = element.querySelector('#viewer-download-button'); let downloadButton: any = element.querySelector('[data-automation-id="viewer-download-button"]');
downloadButton.click(); downloadButton.click();
expect(service.downloadBlob).toHaveBeenCalled(); expect(service.downloadBlob).toHaveBeenCalled();
@@ -250,7 +232,7 @@ describe('NotSupportedFormatComponent', () => {
renditionSubject.next({ entry: { status: 'NOT_CREATED' } }); renditionSubject.next({ entry: { status: 'NOT_CREATED' } });
fixture.detectChanges(); fixture.detectChanges();
let convertButton: any = element.querySelector('#viewer-convert-button'); let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]');
convertButton.click(); convertButton.click();
fixture.detectChanges(); fixture.detectChanges();
} }
@@ -258,8 +240,8 @@ describe('NotSupportedFormatComponent', () => {
it('should show loading spinner and disable the "Convert to PDF button" after the button was clicked', () => { it('should show loading spinner and disable the "Convert to PDF button" after the button was clicked', () => {
clickOnConvertButton(); clickOnConvertButton();
let convertButton: any = element.querySelector('#viewer-convert-button'); let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]');
expect(element.querySelector('#conversion-spinner')).not.toBeNull('Conversion spinner should be shown'); expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).not.toBeNull('Conversion spinner should be shown');
expect(convertButton.disabled).toBe(true); expect(convertButton.disabled).toBe(true);
}); });
@@ -269,8 +251,8 @@ describe('NotSupportedFormatComponent', () => {
conversionSubject.error(new Error()); conversionSubject.error(new Error());
fixture.detectChanges(); fixture.detectChanges();
let convertButton: any = element.querySelector('#viewer-convert-button'); let convertButton: any = element.querySelector('[data-automation-id="viewer-convert-button"]');
expect(element.querySelector('#conversion-spinner')).toBeNull('Conversion spinner should be shown'); expect(element.querySelector('[data-automation-id="viewer-conversion-spinner"]')).toBeNull('Conversion spinner should be shown');
expect(convertButton.disabled).toBe(false); expect(convertButton.disabled).toBe(false);
}); });
@@ -282,7 +264,7 @@ describe('NotSupportedFormatComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#pdf-rendition-viewer')).not.toBeNull('Pdf rendition should be shown.'); expect(element.querySelector('[data-automation-id="pdf-rendition-viewer"]')).not.toBeNull('Pdf rendition should be shown.');
}); });
}); });
}); });

View File

@@ -15,18 +15,18 @@
* limitations under the License. * limitations under the License.
*/ */
/* tslint:disable:component-selector */ import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ContentService, RenditionsService } from 'ng2-alfresco-core'; import { ContentService, RenditionsService } from 'ng2-alfresco-core';
import { AlfrescoApiService } from 'ng2-alfresco-core'; import { AlfrescoApiService } from 'ng2-alfresco-core';
const DEFAULT_CONVERSION_ENCODING = 'pdf'; const DEFAULT_CONVERSION_ENCODING = 'pdf';
@Component({ @Component({
selector: 'not-supported-format', selector: 'adf-not-supported-format',
templateUrl: './notSupportedFormat.component.html', templateUrl: './notSupportedFormat.component.html',
styleUrls: ['./notSupportedFormat.component.css'] styleUrls: ['./notSupportedFormat.component.scss'],
host: { 'class': 'adf-not-supported-format' },
encapsulation: ViewEncapsulation.None
}) })
export class NotSupportedFormatComponent implements OnInit, OnDestroy { export class NotSupportedFormatComponent implements OnInit, OnDestroy {

View File

@@ -1,96 +0,0 @@
.loader-container {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
-webkit-box-flex-direction: row;
-moz-box-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
height:100%;
}
.loader-item {
margin: auto;
max-height:100px;
max-width:300px;
}
.loader-text{
white-space: nowrap;
text-align: center;
position: relative;
color : #fff;
}
.left {
float: left;
}
.viewer-toolbar-pagination{
padding-top: 4px;
top: 80px;
right:35px;
width:auto;
position:absolute;
border-radius: 10px;
background: #3E3E3E;
color: white;
}
.viewer-toolbar-command{
height: 30px;
padding-top: 4px;
top: 80px;
left:35px;
width:auto;
position:absolute;
border-radius: 10px;
background: #3E3E3E;
color: white;
}
.viewer-pagenumber-input {
border: none;
display: block;
font-size: 16px;
padding: 4px 0;
background: 0 0;
text-align: right;
color: inherit;
width: 33px;
margin-right: 4px;
height: 20px;
}
.viewer-total-pages {
border: medium none;
display: flex;
font-size: 16px;
padding: 4px 0px;
background: transparent none repeat scroll 0px 0px;
text-align: right;
color: inherit;
margin-right: 4px;
height: 20px;
align-items: center;
justify-content: center;
}
.viewer-page-counter {
margin-right: 20px;
}
.button-page {
margin-right: 4px;
height: 24px;
width: 24px;
margin-left: 4px;
cursor: pointer;
}
.button-page:hover {
cursor: pointer;
background: grey;
border-radius: 24px;
}

View File

@@ -3,8 +3,7 @@
<div id="viewer-viewerPdf" class="pdfViewer"> <div id="viewer-viewerPdf" class="pdfViewer">
<div id="loader-container" class="loader-container"> <div id="loader-container" class="loader-container">
<div class="loader-item"> <div class="loader-item">
<div id="loader-spin" class="mdl-progress mdl-js-progress mdl-progress__indeterminate"></div> <md-progress-bar mode="indeterminate"></md-progress-bar>
<div id="loader-text" class="loader-text">Loading <span>{{nameFile}}</span> {{laodingPercent}}%</div>
</div > </div >
</div> </div>
</div> </div>
@@ -13,33 +12,62 @@
<!-- Pagination toolbar start --> <!-- Pagination toolbar start -->
<div *ngIf="showToolbar" id="viewer-toolbar-pagination" class="viewer-toolbar-pagination mdl-cell--hide-tablet mdl-cell--hide-phone"> <div *ngIf="showToolbar" class="viewer-toolbar-pagination">
<div id="viewer-previous-page-button" aria-label="arrow left" class="button-page left" (click)="previousPage()" tabindex="0"> <div
<i class="icon material-icons">keyboard_arrow_left</i> id="viewer-previous-page-button"
aria-label="arrow left"
class="button-page left"
tabindex="0"
(click)="previousPage()">
<md-icon>keyboard_arrow_left</md-icon>
</div> </div>
<div class="viewer-page-counter left" > <div class="viewer-page-counter left" >
<input id="viewer-pagenumber-input" #page <input #page
(keyup.enter)="inputPage(page.value)" class="viewer-pagenumber-input left" type="text" pattern="-?[0-9]*(\.[0-9]+)?" value="{{displayPage}}"> class="viewer-pagenumber-input left"
<div id="viewer-total-pages" class="left viewer-total-pages">/ {{totalPages}}</div> type="text"
pattern="-?[0-9]*(\.[0-9]+)?"
value="{{ displayPage }}"
(keyup.enter)="inputPage(page.value)">
<div class="left viewer-total-pages">/ {{ totalPages }}</div>
</div> </div>
<div id="viewer-next-page-button" aria-label="arrow right" class="button-page left" (click)="nextPage()" tabindex="0"> <div
<i class="icon material-icons" >keyboard_arrow_right</i> id="viewer-next-page-button"
aria-label="arrow right"
class="button-page left"
tabindex="0"
(click)="nextPage()">
<md-icon>keyboard_arrow_right</md-icon>
</div> </div>
</div> </div>
<!-- Pagination toolbar end --> <!-- Pagination toolbar end -->
<!-- Command toolbar start --> <!-- Command toolbar start -->
<div *ngIf="showToolbar" id="viewer-toolbar-command" class="viewer-toolbar-command"> <div *ngIf="showToolbar" class="viewer-toolbar-command">
<div id="viewer-scale-page-button" aria-label="zoom out map" class="button-page left" (click)="pageFit()" tabindex="0"> <div
<i class="icon material-icons">zoom_out_map</i> id="viewer-scale-page-button"
aria-label="zoom out map"
class="button-page left"
tabindex="0"
(click)="pageFit()">
<md-icon>zoom_out_map</md-icon>
</div> </div>
<div id="viewer-zoom-in-button" aria-label="zoom in" class="button-page left" (click)="zoomIn()" tabindex="0"> <div
<i class="icon material-icons">zoom_in</i> id="viewer-zoom-in-button"
aria-label="zoom in"
class="button-page left"
tabindex="0"
(click)="zoomIn()">
<md-icon>zoom_in</md-icon>
</div> </div>
<div id="viewer-zoom-out-button" aria-label="zoom out" class="button-page left" (click)="zoomOut()" tabindex="0"> <div
<i class="icon material-icons">zoom_out</i> id="viewer-zoom-out-button"
aria-label="zoom out"
class="button-page left"
tabindex="0"
(click)="zoomOut()">
<md-icon>zoom_out</md-icon>
</div> </div>
</div> </div>
<!-- Command toolbar end --> <!-- Command toolbar end -->

View File

@@ -0,0 +1,91 @@
.adf-pdf-viewer {
.loader-container {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
-webkit-box-flex-direction: row;
-moz-box-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
height:100%;
}
.loader-item {
margin: auto;
max-height:100px;
max-width:300px;
}
.left {
float: left;
}
.viewer-toolbar-pagination{
padding-top: 4px;
top: 80px;
right:35px;
width:auto;
position:absolute;
border-radius: 10px;
background: #3E3E3E;
color: white;
}
.viewer-toolbar-command{
height: 30px;
padding-top: 4px;
top: 80px;
left:35px;
width:auto;
position:absolute;
border-radius: 10px;
background: #3E3E3E;
color: white;
}
.viewer-pagenumber-input {
border: none;
display: block;
font-size: 16px;
padding: 4px 0;
background: 0 0;
text-align: right;
color: inherit;
width: 33px;
margin-right: 4px;
height: 20px;
}
.viewer-total-pages {
border: medium none;
display: flex;
font-size: 16px;
padding: 4px 0px;
background: transparent none repeat scroll 0px 0px;
text-align: right;
color: inherit;
margin-right: 4px;
height: 20px;
align-items: center;
justify-content: center;
}
.viewer-page-counter {
margin-right: 20px;
}
.button-page {
margin-right: 4px;
height: 24px;
width: 24px;
margin-left: 4px;
cursor: pointer;
}
.button-page:hover {
cursor: pointer;
background: grey;
border-radius: 24px;
}
}

View File

@@ -95,12 +95,12 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('should Canvas be present', () => { it('should Canvas be present', () => {
expect(element.querySelector('#viewer-viewerPdf')).not.toBeNull(); expect(element.querySelector('.pdfViewer')).not.toBeNull();
expect(element.querySelector('#viewer-pdf-container')).not.toBeNull(); expect(element.querySelector('.viewer-pdf-container')).not.toBeNull();
}); });
it('should Loader be present', () => { it('should Loader be present', () => {
expect(element.querySelector('#loader-container')).not.toBeNull(); expect(element.querySelector('.loader-container')).not.toBeNull();
}); });
it('should Next an Previous Buttons be present', () => { it('should Next an Previous Buttons be present', () => {
@@ -109,8 +109,8 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('should Input Page elements be present', () => { it('should Input Page elements be present', () => {
expect(element.querySelector('#viewer-pagenumber-input')).toBeDefined(); expect(element.querySelector('.viewer-pagenumber-input')).toBeDefined();
expect(element.querySelector('#viewer-total-pages')).toBeDefined(); expect(element.querySelector('.viewer-total-pages')).toBeDefined();
expect(element.querySelector('#viewer-previous-page-button')).not.toBeNull(); expect(element.querySelector('#viewer-previous-page-button')).not.toBeNull();
expect(element.querySelector('#viewer-next-page-button')).not.toBeNull(); expect(element.querySelector('#viewer-next-page-button')).not.toBeNull();
@@ -121,8 +121,8 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-toolbar-command')).toBeNull(); expect(element.querySelector('.viewer-toolbar-command')).toBeNull();
expect(element.querySelector('#viewer-toolbar-pagination')).toBeNull(); expect(element.querySelector('.viewer-toolbar-pagination')).toBeNull();
}); });
}); });
@@ -143,12 +143,12 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('should Canvas be present', () => { it('should Canvas be present', () => {
expect(element.querySelector('#viewer-viewerPdf')).not.toBeNull(); expect(element.querySelector('.pdfViewer')).not.toBeNull();
expect(element.querySelector('#viewer-pdf-container')).not.toBeNull(); expect(element.querySelector('.viewer-pdf-container')).not.toBeNull();
}); });
it('should Loader be present', () => { it('should Loader be present', () => {
expect(element.querySelector('#loader-container')).not.toBeNull(); expect(element.querySelector('.loader-container')).not.toBeNull();
}); });
it('should Next an Previous Buttons be present', () => { it('should Next an Previous Buttons be present', () => {
@@ -157,8 +157,8 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
}); });
it('should Input Page elements be present', () => { it('should Input Page elements be present', () => {
expect(element.querySelector('#viewer-pagenumber-input')).toBeDefined(); expect(element.querySelector('.viewer-pagenumber-input')).toBeDefined();
expect(element.querySelector('#viewer-total-pages')).toBeDefined(); expect(element.querySelector('.viewer-total-pages')).toBeDefined();
expect(element.querySelector('#viewer-previous-page-button')).not.toBeNull(); expect(element.querySelector('#viewer-previous-page-button')).not.toBeNull();
expect(element.querySelector('#viewer-next-page-button')).not.toBeNull(); expect(element.querySelector('#viewer-next-page-button')).not.toBeNull();
@@ -169,8 +169,8 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-toolbar-command')).toBeNull(); expect(element.querySelector('.viewer-toolbar-command')).toBeNull();
expect(element.querySelector('#viewer-toolbar-pagination')).toBeNull(); expect(element.querySelector('.viewer-toolbar-pagination')).toBeNull();
}); });
}); });
@@ -370,7 +370,7 @@ describe('Test ng2-alfresco-viewer PdfViewer component', () => {
component.inputPage('2'); component.inputPage('2');
fixture.detectChanges(); fixture.detectChanges();
expect(component.displayPage).toBe(2); expect(component.displayPage).toBe(2);
let documentContainer = element.querySelector('#viewer-pdf-container'); let documentContainer = element.querySelector('.viewer-pdf-container');
documentContainer.scrollTop = 100000; documentContainer.scrollTop = 100000;
component.watchScroll(documentContainer); component.watchScroll(documentContainer);
fixture.detectChanges(); fixture.detectChanges();

View File

@@ -15,19 +15,22 @@
* limitations under the License. * limitations under the License.
*/ */
/* tslint:disable:component-selector */ import { Component, HostListener, Input, OnChanges, ViewEncapsulation } from '@angular/core';
import { Component, HostListener, Input, OnChanges } from '@angular/core';
import { LogService } from 'ng2-alfresco-core'; import { LogService } from 'ng2-alfresco-core';
import { RenderingQueueServices } from '../services/rendering-queue.services'; import { RenderingQueueServices } from '../services/rendering-queue.services';
declare let PDFJS: any; declare let PDFJS: any;
@Component({ @Component({
selector: 'pdf-viewer', selector: 'adf-pdf-viewer',
templateUrl: './pdfViewer.component.html', templateUrl: './pdfViewer.component.html',
styleUrls: ['./pdfViewer.component.css', './pdfViewerHost.component.css'], styleUrls: [
providers: [RenderingQueueServices] './pdfViewer.component.scss',
'./pdfViewerHost.component.scss'
],
providers: [ RenderingQueueServices ],
host: { 'class': 'adf-pdf-viewer' },
encapsulation: ViewEncapsulation.None
}) })
export class PdfViewerComponent implements OnChanges { export class PdfViewerComponent implements OnChanges {
@@ -47,7 +50,7 @@ export class PdfViewerComponent implements OnChanges {
page: number; page: number;
displayPage: number; displayPage: number;
totalPages: number; totalPages: number;
laodingPercent: number; loadingPercent: number;
pdfViewer: any; pdfViewer: any;
currentScaleMode: string = 'auto'; currentScaleMode: string = 'auto';
currentScale: number; currentScale: number;
@@ -86,7 +89,7 @@ export class PdfViewerComponent implements OnChanges {
loadingTask.onProgress = (progressData) => { loadingTask.onProgress = (progressData) => {
let level = progressData.loaded / progressData.total; let level = progressData.loaded / progressData.total;
this.laodingPercent = Math.round(level * 100); this.loadingPercent = Math.round(level * 100);
}; };
loadingTask.then((pdfDocument) => { loadingTask.then((pdfDocument) => {

View File

@@ -1,264 +0,0 @@
:host >>> .textLayer {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
opacity: 0.2;
line-height: 1.0;
}
:host >>> .textLayer > div {
color: transparent;
position: absolute;
white-space: pre;
cursor: text;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-o-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
}
:host >>> .textLayer .highlight {
margin: -1px;
padding: 1px;
background-color: rgb(180, 0, 170);
border-radius: 4px;
}
:host >>> .textLayer .highlight.begin {
border-radius: 4px 0px 0px 4px;
}
:host >>> .textLayer .highlight.end {
border-radius: 0px 4px 4px 0px;
}
:host >>> .textLayer .highlight.middle {
border-radius: 0px;
}
:host >>> .textLayer .highlight.selected {
background-color: rgb(0, 100, 0);
}
:host >>> .textLayer ::selection { background: rgb(0,0,255); }
:host >>> .textLayer ::-moz-selection { background: rgb(0,0,255); }
:host >>> .textLayer .endOfContent {
display: block;
position: absolute;
left: 0px;
top: 100%;
right: 0px;
bottom: 0px;
z-index: -1;
cursor: default;
-webkit-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
}
:host >>> .textLayer .endOfContent.active {
top: 0px;
}
:host >>> .annotationLayer section {
position: absolute;
}
:host >>> .annotationLayer .linkAnnotation > a {
position: absolute;
font-size: 1em;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
:host >>> .annotationLayer .linkAnnotation > a /* -ms-a */ {
background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
}
:host >>> .annotationLayer .linkAnnotation > a:hover {
opacity: 0.2;
background: #ff0;
box-shadow: 0px 2px 10px #ff0;
}
:host >>> .annotationLayer .textAnnotation img {
position: absolute;
cursor: pointer;
}
:host >>> .annotationLayer .popupWrapper {
position: absolute;
width: 20em;
}
:host >>> .annotationLayer .popup {
position: absolute;
z-index: 200;
max-width: 20em;
background-color: #FFFF99;
box-shadow: 0px 2px 5px #333;
border-radius: 2px;
padding: 0.6em;
margin-left: 5px;
cursor: pointer;
word-wrap: break-word;
}
:host >>> .annotationLayer .popup h1 {
font-size: 1em;
border-bottom: 1px solid #000000;
padding-bottom: 0.2em;
}
:host >>> .annotationLayer .popup p {
padding-top: 0.2em;
}
:host >>> .annotationLayer .highlightAnnotation,
.annotationLayer .underlineAnnotation,
.annotationLayer .squigglyAnnotation,
.annotationLayer .strikeoutAnnotation,
.annotationLayer .fileAttachmentAnnotation {
cursor: pointer;
}
:host >>> .pdfViewer .canvasWrapper {
overflow: hidden;
}
:host >>> .pdfViewer .page {
direction: ltr;
width: 816px;
height: 1056px;
margin: 1px auto -8px auto;
position: relative;
overflow: visible;
border: 9px solid transparent;
background-clip: content-box;
background-color: white;
}
:host >>> .pdfViewer.removePageBorders .page {
margin: 0px auto 10px auto;
border: none;
}
:host >>> .pdfViewer .page canvas {
margin: 0;
display: block;
}
:host >>> .pdfViewer .page .loadingIcon {
position: absolute;
display: block;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
:host >>> .loadingIcon {
width: 100px;
height: 100px;
left: 50% !important;
top: 50% !important;
margin-top: -50px;
margin-left: -50px;
font-size: 5px;
text-indent: -9999em;
border-top: 1.1em solid rgba(3,0,2, 0.2);
border-right: 1.1em solid rgba(3,0,2, 0.2);
border-bottom: 1.1em solid rgba(3,0,2, 0.2);
border-left: 1.1em solid #030002;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
:host >>> .loadingIcon,
:host >>> .loadingIcon:after {
border-radius: 50%;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
:host >>> * {
padding: 0;
margin: 0;
}
:host >>> html {
height: 100%;
width: 100%;
/* Font size is needed to make the activity bar the correct size. */
font-size: 10px;
}
:host >>> body {
height: 100%;
width: 100%;
background-color: #404040;
}
:host >>> body,
input,
button,
select {
font: message-box;
outline: none;
}
:host >>> .hidden {
display: none !important;
}
:host >>> [hidden] {
display: none !important;
}
#viewer-pdf-container {
overflow: auto;
-webkit-overflow-scrolling: touch;
position: absolute;
top: 32px;
right: 0;
bottom: 0;
left: 0;
outline: none;
}
html[dir='ltr'] #viewer-pdf-container {
box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
}
html[dir='rtl'] #viewer-pdf-container {
box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05);
}

View File

@@ -0,0 +1,250 @@
.adf-pdf-viewer {
.textLayer {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
opacity: 0.2;
line-height: 1.0;
& > div {
color: transparent;
position: absolute;
white-space: pre;
cursor: text;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-o-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
}
.highlight {
margin: -1px;
padding: 1px;
background-color: rgb(180, 0, 170);
border-radius: 4px;
&.begin {
border-radius: 4px 0px 0px 4px;
}
&.end {
border-radius: 0px 4px 4px 0px;
}
&.middle {
border-radius: 0px;
}
&.selected {
background-color: rgb(0, 100, 0);
}
}
&::selection { background: rgb(0,0,255); }
&::-moz-selection { background: rgb(0,0,255); }
.endOfContent {
display: block;
position: absolute;
left: 0px;
top: 100%;
right: 0px;
bottom: 0px;
z-index: -1;
cursor: default;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
&.active {
top: 0px;
}
}
}
.annotationLayer {
section {
position: absolute;
}
.linkAnnotation {
& > a {
position: absolute;
font-size: 1em;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") 0 0 repeat;
&:hover {
opacity: 0.2;
background: #ff0;
box-shadow: 0px 2px 10px #ff0;
}
}
}
.textAnnotation {
img {
position: absolute;
cursor: pointer;
}
}
.popupWrapper {
position: absolute;
width: 20em;
}
.popup {
position: absolute;
z-index: 200;
max-width: 20em;
background-color: #FFFF99;
box-shadow: 0px 2px 5px #333;
border-radius: 2px;
padding: 0.6em;
margin-left: 5px;
cursor: pointer;
word-wrap: break-word;
h1 {
font-size: 1em;
border-bottom: 1px solid #000000;
padding-bottom: 0.2em;
}
p {
padding-top: 0.2em;
}
}
.highlightAnnotation,
.underlineAnnotation,
.squigglyAnnotation,
.strikeoutAnnotation,
.fileAttachmentAnnotation {
cursor: pointer;
}
}
.pdfViewer {
canvasWrapper {
overflow: hidden;
}
.page {
direction: ltr;
width: 816px;
height: 1056px;
margin: 1px auto -8px auto;
position: relative;
overflow: visible;
border: 9px solid transparent;
background-clip: content-box;
background-color: white;
canvas {
margin: 0;
display: block;
}
.loadingIcon {
position: absolute;
display: block;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
}
&.removePageBorders {
.page {
margin: 0px auto 10px auto;
border: none;
}
}
.loadingIcon {
width: 100px;
height: 100px;
left: 50% !important;
top: 50% !important;
margin-top: -50px;
margin-left: -50px;
font-size: 5px;
text-indent: -9999em;
border-top: 1.1em solid rgba(3,0,2, 0.2);
border-right: 1.1em solid rgba(3,0,2, 0.2);
border-bottom: 1.1em solid rgba(3,0,2, 0.2);
border-left: 1.1em solid #030002;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
border-radius: 50%;
&:after {
border-radius: 50%;
}
}
}
* {
padding: 0;
margin: 0;
}
.hidden, [hidden] {
display: none !important;
}
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.viewer-pdf-container {
overflow: auto;
-webkit-overflow-scrolling: touch;
position: absolute;
top: 32px;
right: 0;
bottom: 0;
left: 0;
outline: none;
}
html[dir='ltr'] .viewer-pdf-container {
box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
}
html[dir='rtl'] .viewer-pdf-container {
box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05);
}

View File

@@ -1,11 +0,0 @@
.adf-txt-viewer-margin {
margin: auto !important;
overflow: auto;
font-size: 1em;
padding: 20px;
max-width: 70%;
}
.full_width{
width :95% !important;
}

View File

@@ -1,6 +1,3 @@
<section class="section--center mdl-grid mdl-grid--no-spacing"> <pre class="adf-txt-viewer-content">
<pre id="adf-viewer-text-container"class="adf-txt-viewer-margin mdl-card mdl-cell mdl-cell--12-col-desktop mdl-cell--12-col-tablet mdl-cell--2-col-phone mdl-shadow--2dp"> {{content}}
{{content}} </pre>
</pre>
</section>

View File

@@ -0,0 +1,7 @@
.adf-txt-viewer {
background-color: white;
width: 100vw;
overflow: hidden;
overflow-y: scroll;
margin-bottom: 42px;
}

View File

@@ -64,7 +64,7 @@ describe('Test ng2-alfresco-viewer Text View component', () => {
component.ngOnChanges({ 'urlFile': change }).then(() => { component.ngOnChanges({ 'urlFile': change }).then(() => {
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
expect(element.querySelector('#adf-viewer-text-container').textContent).toContain('example'); expect(element.querySelector('.adf-txt-viewer-content').textContent).toContain('example');
done(); done();
}); });
}); });
@@ -78,7 +78,7 @@ describe('Test ng2-alfresco-viewer Text View component', () => {
component.ngOnChanges({ 'blobFile': change }).then(() => { component.ngOnChanges({ 'blobFile': change }).then(() => {
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
expect(element.querySelector('#adf-viewer-text-container').textContent).toContain('example'); expect(element.querySelector('.adf-txt-viewer-content').textContent).toContain('example');
done(); done();
}); });
}); });

View File

@@ -15,17 +15,17 @@
* limitations under the License. * limitations under the License.
*/ */
/* tslint:disable:component-selector */ import { Component, Input, OnChanges, ViewEncapsulation } from '@angular/core';
import { Component, Input, OnChanges } from '@angular/core';
import { SimpleChanges } from '@angular/core'; import { SimpleChanges } from '@angular/core';
import { Http, RequestOptions, Response, ResponseContentType } from '@angular/http'; import { Http, RequestOptions, Response, ResponseContentType } from '@angular/http';
import 'rxjs/add/operator/toPromise'; import 'rxjs/add/operator/toPromise';
@Component({ @Component({
selector: 'txt-viewer', selector: 'adf-txt-viewer',
templateUrl: './txtViewer.component.html', templateUrl: './txtViewer.component.html',
styleUrls: ['./txtViewer.component.css'] styleUrls: ['./txtViewer.component.scss'],
host: { 'class': 'adf-txt-viewer' },
encapsulation: ViewEncapsulation.None
}) })
export class TxtViewerComponent implements OnChanges { export class TxtViewerComponent implements OnChanges {

View File

@@ -0,0 +1,66 @@
<adf-toolbar color="default">
<adf-toolbar-title>
<button md-icon-button [md-dialog-close]="true" mdTooltip="Close and go back">
<md-icon>arrow_back</md-icon>
</button>
<span>{{ fileName }}</span>
</adf-toolbar-title>
<adf-toolbar-divider></adf-toolbar-divider>
<button
*ngIf="downloadUrl"
md-icon-button
mdTooltip="Download"
(click)="download()">
<md-icon>file_download</md-icon>
</button>
<button md-icon-button mdTooltip="Print">
<md-icon>print</md-icon>
</button>
<button md-icon-button mdTooltip="Share">
<md-icon>share</md-icon>
</button>
<button md-icon-button mdTooltip="Info">
<md-icon>info_outline</md-icon>
</button>
<adf-toolbar-divider></adf-toolbar-divider>
<button md-icon-button [mdMenuTriggerFor]="menu">
<md-icon>more_vert</md-icon>
</button>
<md-menu #menu="mdMenu">
<button md-menu-item>
<md-icon>dialpad</md-icon>
<span>Redial</span>
</button>
<button md-menu-item disabled>
<md-icon>voicemail</md-icon>
<span>Check voicemail</span>
</button>
<button md-menu-item>
<md-icon>notifications_off</md-icon>
<span>Disable alerts</span>
</button>
</md-menu>
</adf-toolbar>
<md-dialog-content>
<ng-container [ngSwitch]="viewerType">
<ng-container *ngSwitchCase="'image'">
<div class="adf-viewer-dialog-image-view">
<img *ngIf="fileUrl" [src]="fileUrl">
</div>
</ng-container>
<ng-container *ngSwitchDefault>
<div class="adf-viewer-dialog-unknown-view">
<div>
<md-icon class="icon">{{ unknownFormatIcon }}</md-icon>
<div class="label">{{ unknownFormatText | translate }}</div>
</div>
</div>
</ng-container>
</ng-container>
</md-dialog-content>

View File

@@ -0,0 +1,36 @@
.adf-viewer-dialog-panel {
.mat-dialog-container {
padding: 0;
max-width: none;
width: 99vw;
height: 99vh;
}
}
.adf-viewer-dialog {
.mat-dialog-content {
display: flex;
max-height: 90vh;
}
&-unknown-view {
height: 90vh;
text-align: center;
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
}
&-image-view {
display: flex;
flex: 1;
text-align: center;
flex-direction: row;
justify-content: center;
height: 90vh;
img {
object-fit: contain;
}
}
}

View File

@@ -0,0 +1,81 @@
/*!
* @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, Inject, OnInit, ViewEncapsulation } from '@angular/core';
import { MD_DIALOG_DATA, MdDialogRef } from '@angular/material';
import { ViewerDialogSettings } from './viewer-dialog.settings';
@Component({
selector: 'adf-viewer-dialog',
templateUrl: 'viewer-dialog.component.html',
styleUrls: ['viewer-dialog.component.scss'],
encapsulation: ViewEncapsulation.None,
host: { 'class': 'adf-viewer-dialog' }
})
export class ViewerDialogComponent implements OnInit {
fileName: string = 'Unknown file';
fileUrl: string = null;
fileMimeType: string = null;
downloadUrl: string = null;
unknownFormatIcon = 'wifi_tethering';
unknownFormatText = 'Document preview could not be loaded.';
viewerType: string = null;
constructor(private dialogRef: MdDialogRef<ViewerDialogComponent>,
@Inject(MD_DIALOG_DATA) settings: ViewerDialogSettings) {
this.fileUrl = settings.fileUrl;
this.fileName = settings.fileName;
this.fileMimeType = settings.fileMimeType;
this.downloadUrl = settings.downloadUrl;
}
ngOnInit() {
this.viewerType = this.detectViewerType(this.fileMimeType);
}
private detectViewerType(mimeType: string) {
if (mimeType) {
mimeType = mimeType.toLowerCase();
if (mimeType.startsWith('image/')) {
return 'image';
}
}
return 'unknown';
}
download() {
if (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);
}
}
close() {
this.dialogRef.close(true);
}
}

View File

@@ -0,0 +1,23 @@
/*!
* @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.
*/
export interface ViewerDialogSettings {
fileUrl?: string;
fileMimeType?: string;
fileName?: string;
downloadUrl?: string;
}

View File

@@ -1,63 +0,0 @@
.button-container {
padding: 0 40px;
}
.left {
float: left;
}
#page-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
}
.mdl-grid {
width: 100vw;
padding: 0px !important;
}
.viewer-name-file {
width: 100%;
height: 21px;
overflow: hidden !important;
text-overflow: ellipsis;
white-space: nowrap;
padding-right: 60px;
margin-right: -40px;
}
.viewer-shadow-transparent {
z-index: 1000;
background-color: #3E3E3E;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
opacity: .90;
}
.viewer-overlay-view {
position: fixed;
top: 0px;
left: 0px;
z-index: 1000;
}
img-viewer {
height: 100%;
}
.center-element {
display: flex;
align-items: center;
justify-content: center;
}
.all-space{
width: 100%;
height: 100%;
background-color: #515151;
}

View File

@@ -1,59 +1,60 @@
<div id="viewer" *ngIf="showViewer" [ngClass]="{'all-space': !overlayMode }"> <div *ngIf="showViewer"
<div *ngIf="overlayMode"> class="adf-viewer-container"
<div id="viewer-shadow-transparent" class="viewer-shadow-transparent"></div> [class.adf-viewer-overlay-container]="overlayMode"
</div> [class.adf-viewer-inline-container]="!overlayMode">
<div id="viewer-main-container" class="all-space" [ngClass]="{'viewer-overlay-view': overlayMode }"> <div class="adf-viewer-content">
<ng-container *ngIf="overlayMode">
<adf-toolbar color="default" class="adf-viewer-toolbar">
<adf-toolbar-title>
<span class="adf-viewer-filename">{{ displayName }}</span>
</adf-toolbar-title>
<button
md-icon-button
class="adf-viewer-close-button"
mdTooltip="Close and go back"
mdTooltipPosition="before"
(click)="close()"
aria-label="Close">
<md-icon>close</md-icon>
</button>
</adf-toolbar>
</ng-container>
<!-- Start Layout --> <div class="adf-viewer-layout">
<div [ngClass]="{'mdl-layout mdl-js-layout mdl-layout--fixed-header': overlayMode, 'all-space': !overlayMode}"> <div class="adf-viewer-layout-content">
<div *ngIf="isLoaded()">
<div class="adf-viewer-content-container">
<header *ngIf="overlayMode" class="mdl-layout__header"> <ng-container *ngIf="isPdf()">
<div class="mdl-layout__header-row"> <adf-pdf-viewer
[showToolbar]="showToolbar"
[blobFile]="blobFile"
[urlFile]="urlFileContent"
[nameFile]="displayName">
</adf-pdf-viewer>
</ng-container>
<!-- File Title --> <ng-container *ngIf="isImage()">
<span id="viewer-name-file" class="mdl-layout-title viewer-name-file">{{displayName}}</span> <adf-img-viewer
[urlFile]="urlFileContent"
[nameFile]="displayName"
[blobFile]="blobFile">
</adf-img-viewer>
</ng-container>
<span class="vertical-divider"></span> <ng-container *ngIf="isMedia()">
<adf-media-player
[urlFile]="urlFileContent"
[mimeType]="mimeType"
[blobFile]="blobFile"
[nameFile]="displayName">
</adf-media-player>
</ng-container>
<div class="mdl-layout-spacer"></div> <ng-container *ngIf="isText()">
<adf-txt-viewer [urlFile]="urlFileContent" [blobFile]="blobFile" ></adf-txt-viewer>
<!-- Start Navigation --> </ng-container>
<nav class="mdl-navigation">
<div id="viewer-toolbar-view-options">
<button *ngIf="overlayMode"
class="mdl-color--black mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored"
(click)="close()" aria-label="Close">
<i id="viewer-close-button" class="icon material-icons">close</i>
</button>
</div>
</nav>
<!-- End Navigation -->
</div>
</header>
<main id="page-content" class="mdl-layout__content" [ngClass]="{'all-space': !overlayMode }">
<div class="mdl-grid">
<div id="viewer-content-container" *ngIf="isLoaded()"
class="center-element mdl-cell mdl-cell--12-col">
<!-- Start View Switch-->
<div *ngIf="isPdf()">
<pdf-viewer [showToolbar]="showToolbar" [blobFile]="blobFile" [urlFile]="urlFileContent"
[nameFile]="displayName"></pdf-viewer>
</div>
<div class="center-element" *ngIf="isImage()">
<img-viewer [urlFile]="urlFileContent" [nameFile]="displayName" [blobFile]="blobFile"></img-viewer>
</div>
<div class="center-element" *ngIf="isMedia()">
<media-player [urlFile]="urlFileContent" [mimeType]="mimeType" [blobFile]="blobFile"
[nameFile]="displayName"></media-player>
</div>
<div class="center-element" *ngIf="isText()">
<txt-viewer [urlFile]="urlFileContent" [blobFile]="blobFile" ></txt-viewer>
</div>
<span *ngFor="let extensionTemplate of extensionTemplates"> <span *ngFor="let extensionTemplate of extensionTemplates">
<ng-template <ng-template
@@ -63,22 +64,20 @@
</ng-template> </ng-template>
</span> </span>
<div *ngIf="!supportedExtension()"> <div *ngIf="!supportedExtension()" class="adf-viewer-unknown-content">
<not-supported-format *ngIf="!extensionTemplate" <adf-not-supported-format
[urlFile]="urlFileContent" *ngIf="!extensionTemplate"
[blobFile]="blobFile" [urlFile]="urlFileContent"
[nameFile]="displayName" [blobFile]="blobFile"
[showToolbar]="showToolbar" [nameFile]="displayName"
[nodeId]="fileNodeId"> [showToolbar]="showToolbar"
</not-supported-format> [nodeId]="fileNodeId">
</adf-not-supported-format>
</div> </div>
<!-- End View Switch -->
</div> </div>
</div> </div>
</main> </div>
</div> </div>
<!-- End Layout -->
</div> </div>
</div> </div>

View File

@@ -0,0 +1,69 @@
$adf-viewer-background-color: #515151;
@mixin full-screen() {
width: 100%;
height: 100%;
background-color: $adf-viewer-background-color;
}
.adf-viewer {
&-container {
.adf-viewer-layout-content {
@include full-screen();
position: relative;
overflow-y: auto;
overflow-x: hidden;
z-index: 1;
display: flex;
flex-direction: row;
flex-wrap: wrap;
flex: 1;
& > div {
display: flex;
flex-flow: row wrap;
margin: 0 auto;
align-items: stretch;
}
}
.adf-viewer-layout {
@include full-screen();
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: hidden;
position: relative;
}
.adf-viewer-content {
@include full-screen();
}
}
&-overlay-container {
.adf-viewer-content {
position: fixed;
top: 0px;
left: 0px;
z-index: 1000;
}
}
&-inline-container {
@include full-screen();
}
&-content-container {
display: flex;
justify-content: center;
}
&-unknown-content {
align-items: center;
display: flex;
}
}

View File

@@ -17,13 +17,10 @@
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {
AlfrescoApiService, import { CoreModule } from 'ng2-alfresco-core';
AlfrescoAuthenticationService, import { MaterialModule } from './../material.module';
AlfrescoSettingsService,
CoreModule,
RenditionsService
} from 'ng2-alfresco-core';
import { EventMock } from '../assets/event.mock'; import { EventMock } from '../assets/event.mock';
import { RenderingQueueServices } from '../services/rendering-queue.services'; import { RenderingQueueServices } from '../services/rendering-queue.services';
import { ImgViewerComponent } from './imgViewer.component'; import { ImgViewerComponent } from './imgViewer.component';
@@ -35,7 +32,7 @@ import { ViewerComponent } from './viewer.component';
declare let jasmine: any; declare let jasmine: any;
describe('Test ng2-alfresco-viewer ViewerComponent', () => { describe('ViewerComponent', () => {
let component: ViewerComponent; let component: ViewerComponent;
let fixture: ComponentFixture<ViewerComponent>; let fixture: ComponentFixture<ViewerComponent>;
@@ -45,7 +42,8 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
CoreModule CoreModule,
MaterialModule
], ],
declarations: [ declarations: [
ViewerComponent, ViewerComponent,
@@ -56,11 +54,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
ImgViewerComponent ImgViewerComponent
], ],
providers: [ providers: [
AlfrescoSettingsService, RenderingQueueServices
AlfrescoAuthenticationService,
AlfrescoApiService,
RenderingQueueServices,
RenditionsService
] ]
}).compileComponents(); }).compileComponents();
})); }));
@@ -94,40 +88,32 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
it('should shadow overlay be present if is overlay mode', () => {
expect(element.querySelector('#viewer-shadow-transparent')).not.toBeNull();
});
it('should header be present if is overlay mode', () => { it('should header be present if is overlay mode', () => {
expect(element.querySelector('header')).not.toBeNull(); expect(element.querySelector('.adf-viewer-toolbar')).not.toBeNull();
}); });
it('should Name File be present if is overlay mode ', () => { it('should Name File be present if is overlay mode ', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-name-file').innerHTML).toEqual('fake-test-file.pdf'); expect(element.querySelector('.adf-viewer-filename').innerHTML).toEqual('fake-test-file.pdf');
}); });
}); });
it('should Close button be present if overlay mode', () => { it('should Close button be present if overlay mode', () => {
expect(element.querySelector('#viewer-close-button')).not.toBeNull(); expect(element.querySelector('.adf-viewer-close-button')).not.toBeNull();
}); });
it('should Click on close button hide the viewer', () => { it('should Click on close button hide the viewer', () => {
let closebutton: any = element.querySelector('#viewer-close-button'); let closebutton: any = element.querySelector('.adf-viewer-close-button');
closebutton.click(); closebutton.click();
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-main-container')).toBeNull(); expect(element.querySelector('.adf-viewer-content')).toBeNull();
}); });
it('should Esc button hide the viewer', () => { it('should Esc button hide the viewer', () => {
EventMock.keyDown(27); EventMock.keyDown(27);
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-main-container')).toBeNull(); expect(element.querySelector('.adf-viewer-content')).toBeNull();
});
it('should all-space class not be present if is in overlay mode', () => {
expect(element.querySelector('#viewer').getAttribute('class')).toEqual('');
}); });
}); });
@@ -143,17 +129,13 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
}); });
it('should Close button be not present if is not overlay mode', () => { it('should Close button be not present if is not overlay mode', () => {
expect(element.querySelector('#viewer-close-button')).toBeNull(); expect(element.querySelector('.adf-viewer-close-button')).toBeNull();
}); });
it('should Esc button not hide the viewer if is not overlay mode', () => { it('should Esc button not hide the viewer if is not overlay mode', () => {
EventMock.keyDown(27); EventMock.keyDown(27);
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-main-container')).not.toBeNull(); expect(element.querySelector('.adf-viewer-content')).not.toBeNull();
});
it('all-space class should be present if is not overlay mode', () => {
expect(element.querySelector('#viewer').getAttribute('class')).toEqual('all-space');
}); });
}); });
}); });
@@ -196,7 +178,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.showViewer = false; component.showViewer = false;
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('#viewer-main-container')).toBeNull(); expect(element.querySelector('.adf-viewer-content')).toBeNull();
}); });
}); });
@@ -206,7 +188,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('adf-pdf-viewer')).not.toBeNull();
done(); done();
}); });
}); });
@@ -226,7 +208,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('adf-media-player')).not.toBeNull();
done(); done();
}); });
}); });
@@ -236,7 +218,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('adf-media-player')).not.toBeNull();
done(); done();
}); });
}); });
@@ -246,7 +228,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('adf-media-player')).not.toBeNull();
done(); done();
}); });
}); });
@@ -256,7 +238,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('txt-viewer')).not.toBeNull(); expect(element.querySelector('adf-txt-viewer')).not.toBeNull();
done(); done();
}); });
}); });
@@ -267,7 +249,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('not-supported-format')).not.toBeNull(); expect(element.querySelector('adf-not-supported-format')).not.toBeNull();
done(); done();
}); });
}); });
@@ -280,7 +262,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('adf-pdf-viewer')).not.toBeNull();
done(); done();
}); });
@@ -292,7 +274,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('pdf-viewer')).not.toBeNull(); expect(element.querySelector('adf-pdf-viewer')).not.toBeNull();
done(); done();
}); });
}); });
@@ -325,7 +307,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('adf-media-player')).not.toBeNull();
done(); done();
}); });
}); });
@@ -336,7 +318,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('txt-viewer')).not.toBeNull(); expect(element.querySelector('adf-txt-viewer')).not.toBeNull();
done(); done();
}); });
}); });
@@ -347,7 +329,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).not.toBeNull(); expect(element.querySelector('adf-media-player')).not.toBeNull();
done(); done();
}); });
}); });
@@ -358,7 +340,7 @@ describe('Test ng2-alfresco-viewer ViewerComponent', () => {
component.ngOnChanges(null).then(() => { component.ngOnChanges(null).then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(element.querySelector('media-player')).toBeNull(); expect(element.querySelector('adf-media-player')).toBeNull();
done(); done();
}); });
}); });

View File

@@ -15,15 +15,16 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, ElementRef, EventEmitter, HostListener, Inject, Input, OnChanges, OnDestroy, Output, TemplateRef } from '@angular/core'; import { Component, EventEmitter, HostListener, Input, OnChanges, OnDestroy, Output, TemplateRef, ViewEncapsulation } from '@angular/core';
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';
@Component({ @Component({
selector: 'adf-viewer, alfresco-viewer', selector: 'adf-viewer, alfresco-viewer',
templateUrl: './viewer.component.html', templateUrl: './viewer.component.html',
styleUrls: ['./viewer.component.css'] styleUrls: ['./viewer.component.scss'],
host: { 'class': 'adf-viewer' },
encapsulation: ViewEncapsulation.None
}) })
export class ViewerComponent implements OnDestroy, OnChanges { export class ViewerComponent implements OnDestroy, OnChanges {
@@ -65,17 +66,11 @@ export class ViewerComponent implements OnDestroy, OnChanges {
loaded: boolean = false; loaded: boolean = false;
constructor(private apiService: AlfrescoApiService, constructor(private apiService: AlfrescoApiService,
private element: ElementRef,
@Inject(DOCUMENT) private document,
private logService: LogService) { private logService: LogService) {
} }
ngOnChanges(changes) { ngOnChanges(changes) {
if (this.showViewer) { if (this.showViewer) {
if (this.overlayMode) {
this.hideOtherHeaderBar();
this.blockOtherScrollBar();
}
if (!this.urlFile && !this.blobFile && !this.fileNodeId) { if (!this.urlFile && !this.blobFile && !this.fileNodeId) {
throw new Error('Attribute urlFile or fileNodeId or blobFile is required'); throw new Error('Attribute urlFile or fileNodeId or blobFile is required');
} }
@@ -117,7 +112,6 @@ export class ViewerComponent implements OnDestroy, OnChanges {
* close the viewer * close the viewer
*/ */
close() { close() {
this.unblockOtherScrollBar();
if (this.otherMenu) { if (this.otherMenu) {
this.otherMenu.hidden = false; this.otherMenu.hidden = false;
} }
@@ -284,68 +278,6 @@ export class ViewerComponent implements OnDestroy, OnChanges {
} }
} }
/**
* Check if in the document there are scrollable main area and disable it
*/
private blockOtherScrollBar() {
let mainElements: any = this.document.getElementsByTagName('main');
for (let i = 0; i < mainElements.length; i++) {
mainElements[i].style.overflow = 'hidden';
}
}
/**
* Check if in the document there are scrollable main area and re-enable it
*/
private unblockOtherScrollBar() {
let mainElements: any = this.document.getElementsByTagName('main');
for (let i = 0; i < mainElements.length; i++) {
mainElements[i].style.overflow = '';
}
}
/**
* Check if the viewer is used inside and header element
*
* @returns {boolean}
*/
private isParentElementHeaderBar(): boolean {
return !!this.closestElement(this.element.nativeElement, 'header');
}
/**
* Check if the viewer is used inside and header element
* @param {HTMLElement} elelemnt
* @param {string} nodeName
* @returns {HTMLElement}
*/
private closestElement(element: HTMLElement, nodeName: string): HTMLElement {
let parent = element.parentElement;
if (parent) {
if (parent.nodeName.toLowerCase() === nodeName) {
return parent;
} else {
return this.closestElement(parent, nodeName);
}
} else {
return null;
}
}
/**
* Hide the other possible menu in the application
*/
private hideOtherHeaderBar() {
if (this.overlayMode && !this.isParentElementHeaderBar()) {
this.otherMenu = this.document.querySelector('header');
if (this.otherMenu) {
this.otherMenu.hidden = true;
}
}
}
/** /**
* return true if the data about the node in the ecm are loaded * return true if the data about the node in the ecm are loaded
* *

View File

@@ -0,0 +1,47 @@
/*!
* @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 { NgModule } from '@angular/core';
import {
MdButtonModule,
MdCardModule,
MdDialogModule,
MdIconModule,
MdMenuModule,
MdProgressBarModule,
MdProgressSpinnerModule,
MdTooltipModule
} from '@angular/material';
export function modules() {
return [
MdButtonModule,
MdCardModule,
MdDialogModule,
MdIconModule,
MdMenuModule,
MdProgressBarModule,
MdProgressSpinnerModule,
MdTooltipModule
];
}
@NgModule({
imports: modules(),
exports: modules()
})
export class MaterialModule {}

View File

@@ -0,0 +1,56 @@
/*!
* @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 { Injectable } from '@angular/core';
import { MdDialog } from '@angular/material';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { AlfrescoApiService } from 'ng2-alfresco-core';
import { ViewerDialogComponent } from './../components/viewer-dialog.component';
import { ViewerDialogSettings } from './../components/viewer-dialog.settings';
@Injectable()
export class ViewerService {
constructor(private dialog: MdDialog,
private apiService: AlfrescoApiService) {
}
private get contentApi() {
return this.apiService.getInstance().content;
}
showViewerForNode(node: MinimalNodeEntryEntity): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
const settings: ViewerDialogSettings = {
fileName: node.name,
fileMimeType: node.content.mimeType,
fileUrl: this.contentApi.getContentUrl(node.id, false),
downloadUrl: this.contentApi.getContentUrl(node.id, true)
};
const dialogRef = this.dialog.open(ViewerDialogComponent, {
panelClass: 'adf-viewer-dialog-panel',
data: settings
});
dialogRef.afterClosed().subscribe(result => {
resolve(result);
});
});
}
}