mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ADF-2137] Document Thumbnail Pane (#2943)
* pdf thumbnails * update TestBed declarations * add PdfViewerService to TestBed * content projection * update TestBed declaration * update TestBed * update TestBed * docs * pristine * added doc component image * use global PDFJS instance fro tests
This commit is contained in:
parent
5955cc567d
commit
28ca71a5f9
BIN
docs/docassets/images/pdf-thumbnails.png
Normal file
BIN
docs/docassets/images/pdf-thumbnails.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 400 KiB |
@ -69,6 +69,8 @@ Using with file url:
|
||||
| showSidebar | `boolean` | `false` | Toggles sidebar visibility. Requires `allowSidebar` to be set to `true`. |
|
||||
| sidebarPosition | `string` | `'right'` | The position of the sidebar. Can be `left` or `right`. |
|
||||
| sidebarTemplate | `TemplateRef<any>` | `null` | The template for the sidebar. The template context contains the loaded node data. |
|
||||
| allowThumbnails | `boolean` | `true` | Enables pdf viewer thumbnails. |
|
||||
| thumbnailsTemplate | `TemplateRef<any>` | `null` | Custom template content for thumbnails. |
|
||||
| mimeType | `string` | | MIME type of the file content (when not determined by the filename extension). |
|
||||
| fileName | `string` | | Content filename. |
|
||||
| downloadUrl | `string` | `null` | URL to download. |
|
||||
@ -279,6 +281,38 @@ Everything you put inside the "adf-viewer-sidebar" tags is going to be rendered.
|
||||
<adf-viewer [allowSidebar]="true" [sidebarTemplate]="sidebarTemplate"></adf-viewer>
|
||||
```
|
||||
|
||||
### Custom thumbnails
|
||||
|
||||
By default, the pdf viewer comes with its own thumbnails list but this can be replaced
|
||||
by providing a custom template and binding to context property `viewer` to access PDFJS.PDFViewer
|
||||
instance.
|
||||
|
||||

|
||||
|
||||
#### Using template injection
|
||||
|
||||
```javascript
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'custom-thumbnails',
|
||||
template: '<p> Custom Thumbnails Component </p>'
|
||||
})
|
||||
export class CustomThumbnailsComponent {
|
||||
@Input() pdfViewer: any;
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<ng-template let-pdfViewer="viewer" #customThumbnailsTemplate>
|
||||
<custom-thumbnails [pdfViewer]="pdfViewer"></custom-thumbnails>
|
||||
</ng-template>
|
||||
|
||||
<adf-viewer [thumbnailsTemplate]="customThumbnailsTemplate"></adf-viewer>
|
||||
```
|
||||
|
||||
### Custom "Open With" menu
|
||||
|
||||
You can enable custom "Open With" menu by providing at least one action inside the "adf-viewer-open-with" tag:
|
||||
|
@ -210,6 +210,9 @@
|
||||
"LOADING": "Loading",
|
||||
"UNKNOWN_FORMAT": "Couldn't load preview",
|
||||
"SIDEBAR": {
|
||||
"THUMBNAILS": {
|
||||
"PAGE": "Page {{ pageNum }}"
|
||||
},
|
||||
"METADATA": {
|
||||
"MORE_INFORMATION": "More information",
|
||||
"LESS_INFORMATION": "Less information"
|
||||
|
@ -18,6 +18,7 @@
|
||||
@import '../userinfo/components/user-info.component';
|
||||
@import '../viewer/components/viewer.component';
|
||||
@import '../viewer/components/pdfViewer.component';
|
||||
@import '../viewer/components/pdfViewer-thumbnails.component';
|
||||
@import '../viewer/components/txtViewer.component';
|
||||
@import '../viewer/components/imgViewer.component';
|
||||
@import '../form/components/form.component';
|
||||
@ -42,6 +43,7 @@
|
||||
@include adf-userinfo-theme($theme);
|
||||
@include adf-viewer-theme($theme);
|
||||
@include adf-pdf-viewer-theme($theme);
|
||||
@include adf-pdf-thumbnails-theme($theme);
|
||||
@include adf-image-viewer-theme($theme);
|
||||
@include adf-text-viewer-theme($theme);
|
||||
@include adf-form-component-theme($theme);
|
||||
|
@ -0,0 +1,4 @@
|
||||
<ng-container *ngIf="image$ | async as image">
|
||||
<img [src]="image"
|
||||
title="{{ 'ADF_VIEWER.SIDEBAR.THUMBNAILS.PAGE' | translate: { pageNum: page.id } }}">
|
||||
</ng-container>
|
62
lib/core/viewer/components/pdfViewer-thumb.component.spec.ts
Normal file
62
lib/core/viewer/components/pdfViewer-thumb.component.spec.ts
Normal file
@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { PdfThumbComponent } from './pdfViewer-thumb.component';
|
||||
|
||||
describe('PdfThumbComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<PdfThumbComponent>;
|
||||
let component: PdfThumbComponent;
|
||||
const domSanitizer = {
|
||||
bypassSecurityTrustUrl: () => 'image-data'
|
||||
};
|
||||
const page = {
|
||||
id: 'pageId',
|
||||
getPage: jasmine.createSpy('getPage').and.returnValue(Promise.resolve({
|
||||
getViewport: () => ({ height: 0, width: 0 }),
|
||||
render: jasmine.createSpy('render').and.returnValue(Promise.resolve())
|
||||
}))
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
PdfThumbComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: DomSanitizer, useValue: domSanitizer }
|
||||
]
|
||||
}).compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(PdfThumbComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
}));
|
||||
|
||||
it('should have resolve image data', (done) => {
|
||||
component.page = page;
|
||||
fixture.detectChanges();
|
||||
|
||||
component.image$.then((result) => {
|
||||
expect(result).toBe('image-data');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
62
lib/core/viewer/components/pdfViewer-thumb.component.ts
Normal file
62
lib/core/viewer/components/pdfViewer-thumb.component.ts
Normal file
@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit, ElementRef, ViewEncapsulation } from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-pdf-thumb',
|
||||
templateUrl: './pdfViewer-thumb.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class PdfThumbComponent implements OnInit {
|
||||
@Input('page') page: any = null;
|
||||
|
||||
image$: Promise<string>;
|
||||
|
||||
constructor(
|
||||
private element: ElementRef, private sanitizer: DomSanitizer) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.image$ = this.page.getPage().then((page) => this.getThumb(page));
|
||||
}
|
||||
|
||||
private getThumb(page): Promise<string> {
|
||||
const canvas = this.getCanvas();
|
||||
const viewport = page.getViewport(1);
|
||||
const scale = Math.min((canvas.height / viewport.height), (canvas.width / viewport.width));
|
||||
|
||||
return page.render({
|
||||
canvasContext: canvas.getContext('2d'),
|
||||
viewport: page.getViewport(scale)
|
||||
})
|
||||
.then(() => {
|
||||
const imageSource = canvas.toDataURL();
|
||||
return this.sanitizer.bypassSecurityTrustUrl(imageSource);
|
||||
});
|
||||
}
|
||||
|
||||
private getCanvas(): HTMLCanvasElement {
|
||||
const elementRect = this.element.nativeElement.getBoundingClientRect();
|
||||
const canvas = document.createElement('canvas');
|
||||
|
||||
canvas.width = elementRect.width;
|
||||
canvas.height = elementRect.height;
|
||||
|
||||
return canvas;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<div class="pdf-thumbnails__content"
|
||||
[style.height.px]="virtualHeight"
|
||||
[style.transform]="'translate(-50%, ' + translateY + 'px)'">
|
||||
<adf-pdf-thumb *ngFor="let page of renderItems; trackBy: trackByFn"
|
||||
class="pdf-thumbnails__thumb"
|
||||
[ngClass]="{'pdf-thumbnails__thumb--selected' : isSelected(page.id)}"
|
||||
[page]="page"
|
||||
(click)="goTo(page.id)">
|
||||
</adf-pdf-thumb>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
@mixin adf-pdf-thumbnails-theme($theme) {
|
||||
$background: map-get($theme, background);
|
||||
|
||||
.pdf-thumbnails {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
&__content {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&__thumb:first-child {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
&__thumb {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 140px;
|
||||
width: 100px;
|
||||
background: mat-color($background, background);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
&__thumb:hover {
|
||||
box-shadow: 0px 0px 5px 0px $black-87-opacity;
|
||||
}
|
||||
|
||||
&__thumb--selected:not(:hover) {
|
||||
box-shadow: 0px 0px 5px 0px $black-87-opacity;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*!
|
||||
* @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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { PdfThumbListComponent } from './pdfViewer-thumbnails.component';
|
||||
import { PdfThumbComponent } from './pdfViewer-thumb.component';
|
||||
|
||||
declare let PDFJS: any;
|
||||
|
||||
describe('PdfThumbListComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<PdfThumbListComponent>;
|
||||
let component: PdfThumbListComponent;
|
||||
|
||||
const page = (id) => {
|
||||
return {
|
||||
id,
|
||||
getPage: () => Promise.resolve()
|
||||
};
|
||||
};
|
||||
|
||||
const viewerMock = {
|
||||
_currentPageNumber: null,
|
||||
set currentPageNumber(pageNum) {
|
||||
this._currentPageNumber = pageNum;
|
||||
this.eventBus.dispatch('pagechange', { pageNumber: pageNum });
|
||||
},
|
||||
get currentPageNumber() { return this._currentPageNumber; },
|
||||
pdfDocument: {
|
||||
getPage: (pageNum) => Promise.resolve({})
|
||||
},
|
||||
_pages: [
|
||||
page(1), page(2), page(3), page(4),
|
||||
page(5), page(6), page(7), page(8),
|
||||
page(9), page(10), page(11), page(12),
|
||||
page(13), page(14), page(15), page(16)
|
||||
],
|
||||
eventBus: new PDFJS.EventBus()
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
PdfThumbListComponent,
|
||||
PdfThumbComponent
|
||||
]
|
||||
})
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(PdfThumbListComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
component.pdfViewer = viewerMock;
|
||||
|
||||
// provide scrollable container
|
||||
fixture.nativeElement.style.display = 'block';
|
||||
fixture.nativeElement.style.height = '700px';
|
||||
fixture.nativeElement.style.overflow = 'scroll';
|
||||
fixture.debugElement.query(By.css('.pdf-thumbnails__content'))
|
||||
.nativeElement.style.height = '2000px';
|
||||
});
|
||||
}));
|
||||
|
||||
it('should render initial rage of items', () => {
|
||||
fixture.nativeElement.scrollTop = 0;
|
||||
fixture.detectChanges();
|
||||
|
||||
const renderedIds = component.renderItems.map(item => item.id);
|
||||
const rangeIds = viewerMock._pages.slice(0, 5).map(item => item.id);
|
||||
|
||||
expect(renderedIds).toEqual(rangeIds);
|
||||
});
|
||||
|
||||
it('should render next range on scroll', () => {
|
||||
fixture.nativeElement.scrollTop = 700;
|
||||
fixture.detectChanges();
|
||||
|
||||
const renderedIds = component.renderItems.map(item => item.id);
|
||||
const rangeIds = viewerMock._pages.slice(5, 10).map(item => item.id);
|
||||
|
||||
expect(renderedIds).toEqual(rangeIds);
|
||||
});
|
||||
|
||||
it('should render items containing current document page', () => {
|
||||
fixture.nativeElement.scrollTop = 1700;
|
||||
fixture.detectChanges();
|
||||
|
||||
const renderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(renderedIds).not.toContain(3);
|
||||
|
||||
viewerMock.eventBus.dispatch('pagechange', { pageNumber: 3 });
|
||||
|
||||
const newRenderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(newRenderedIds).toContain(3);
|
||||
});
|
||||
|
||||
it('should not change items if range contains current document page', () => {
|
||||
fixture.nativeElement.scrollTop = 1700;
|
||||
fixture.detectChanges();
|
||||
|
||||
const renderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(renderedIds).toContain(12);
|
||||
|
||||
viewerMock.eventBus.dispatch('pagechange', { pageNumber: 12 });
|
||||
|
||||
const newRenderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(newRenderedIds).toContain(12);
|
||||
});
|
||||
|
||||
it('should return current viewed page as selected', () => {
|
||||
fixture.nativeElement.scrollTop = 0;
|
||||
fixture.detectChanges();
|
||||
|
||||
viewerMock.currentPageNumber = 2;
|
||||
|
||||
expect(component.isSelected(2)).toBe(true);
|
||||
});
|
||||
|
||||
it('should go to selected page', () => {
|
||||
fixture.nativeElement.scrollTop = 0;
|
||||
fixture.detectChanges();
|
||||
|
||||
const renderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(renderedIds).not.toContain(12);
|
||||
|
||||
component.goTo(12);
|
||||
|
||||
const newRenderedIds = component.renderItems.map(item => item.id);
|
||||
|
||||
expect(newRenderedIds).toContain(12);
|
||||
});
|
||||
});
|
137
lib/core/viewer/components/pdfViewer-thumbnails.component.ts
Normal file
137
lib/core/viewer/components/pdfViewer-thumbnails.component.ts
Normal file
@ -0,0 +1,137 @@
|
||||
/*!
|
||||
* @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, ContentChild, TemplateRef, HostListener, OnInit,
|
||||
AfterViewInit, ElementRef, OnDestroy, ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-pdf-thumbnails',
|
||||
templateUrl: './pdfViewer-thumbnails.component.html',
|
||||
styleUrls: ['./pdfViewer-thumbnails.component.scss'],
|
||||
host: { 'class': 'pdf-thumbnails' },
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
@Input() pdfViewer: any;
|
||||
|
||||
virtualHeight: number = 0;
|
||||
translateY: number = 0;
|
||||
renderItems = [];
|
||||
|
||||
private items = [];
|
||||
private itemHeight: number = 140;
|
||||
|
||||
@ContentChild(TemplateRef)
|
||||
template: any;
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(event) {
|
||||
this.calculateItems();
|
||||
}
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.calculateItems = this.calculateItems.bind(this);
|
||||
this.onPageChange = this.onPageChange.bind(this);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.element.nativeElement.addEventListener('scroll', this.calculateItems, true);
|
||||
this.pdfViewer.eventBus.on('pagechange', this.onPageChange);
|
||||
|
||||
this.items = this.getPages();
|
||||
this.calculateItems();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => this.scrollInto(this.pdfViewer.currentPageNumber), 0);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.element.nativeElement.removeEventListener('scroll', this.calculateItems, true);
|
||||
this.pdfViewer.eventBus.off('pagechange', this.onPageChange);
|
||||
}
|
||||
|
||||
trackByFn(index: number, item: any): number {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
isSelected(pageNum: number) {
|
||||
return this.pdfViewer.currentPageNumber === pageNum;
|
||||
}
|
||||
|
||||
goTo(pageNum: number) {
|
||||
this.pdfViewer.currentPageNumber = pageNum;
|
||||
}
|
||||
|
||||
scrollInto(item: any) {
|
||||
if (this.items.length) {
|
||||
const index: number = this.items.findIndex((element) => element.id === item);
|
||||
|
||||
if (index < 0 || index >= this.items.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.nativeElement.scrollTop = Math.floor(index - 1 ) * this.itemHeight;
|
||||
|
||||
this.calculateItems();
|
||||
}
|
||||
}
|
||||
|
||||
getPages() {
|
||||
return this.pdfViewer._pages.map((page) => ({
|
||||
id: page.id,
|
||||
getPage: () => this.pdfViewer.pdfDocument.getPage(page.id)
|
||||
}));
|
||||
}
|
||||
|
||||
private calculateItems() {
|
||||
const { element, viewPort, itemsInView } = this.getContainerSetup();
|
||||
|
||||
const indexByScrollTop = element.scrollTop / viewPort * this.items.length / itemsInView;
|
||||
|
||||
const start = Math.floor(indexByScrollTop);
|
||||
|
||||
const end = Math.ceil(indexByScrollTop) + (itemsInView);
|
||||
|
||||
this.translateY = this.itemHeight * Math.ceil(start);
|
||||
this.virtualHeight = this.itemHeight * this.items.length - this.translateY;
|
||||
this.renderItems = this.items.slice(start, end);
|
||||
}
|
||||
|
||||
private getContainerSetup() {
|
||||
const element = this.element.nativeElement;
|
||||
const elementRec = element.getBoundingClientRect();
|
||||
const itemsInView = Math.ceil(elementRec.height / this.itemHeight);
|
||||
const viewPort = (this.itemHeight * this.items.length) / itemsInView;
|
||||
|
||||
return {
|
||||
element,
|
||||
viewPort,
|
||||
itemsInView
|
||||
};
|
||||
}
|
||||
|
||||
private onPageChange(event) {
|
||||
const index = this.renderItems.findIndex((element) => element.id === event.pageNumber);
|
||||
|
||||
if (index < 0) {
|
||||
this.scrollInto(event.pageNumber);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,17 @@
|
||||
<div id="viewer-pdf-container" class="viewer-pdf-container" (window:resize)="onResize()">
|
||||
<div class="adf-pdf-viewer__container">
|
||||
<ng-container *ngIf="showThumbnails">
|
||||
<div class="adf-pdf-viewer__thumbnails">
|
||||
<ng-container *ngIf="thumbnailsTemplate">
|
||||
<ng-container *ngTemplateOutlet="thumbnailsTemplate;context:pdfThumbnailsContext"></ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!thumbnailsTemplate">
|
||||
<adf-pdf-thumbnails [pdfViewer]="pdfViewer"></adf-pdf-thumbnails>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div class="adf-pdf-viewer__content">
|
||||
<div id="viewer-pdf-viewer" class="viewer-pdf-viewer" (window:resize)="onResize()">
|
||||
<div id="viewer-viewerPdf" class="pdfViewer">
|
||||
<div id="loader-container" class="loader-container">
|
||||
<div class="loader-item">
|
||||
@ -6,13 +19,16 @@
|
||||
</div >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="adf-pdf-viewer__toolbar" *ngIf="showToolbar">
|
||||
<adf-toolbar>
|
||||
|
||||
<ng-container *ngIf="allowThumbnails">
|
||||
<button mat-icon-button>
|
||||
<button mat-icon-button
|
||||
(click)="toggleThumbnails()">
|
||||
<mat-icon>dashboard</mat-icon>
|
||||
</button>
|
||||
<adf-toolbar-divider></adf-toolbar-divider>
|
||||
|
@ -1,7 +1,14 @@
|
||||
@mixin adf-pdf-viewer-theme($theme) {
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.adf-viewer-content-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.adf-pdf-viewer {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
.loader-container {
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
@ -14,6 +21,18 @@
|
||||
height:100%;
|
||||
}
|
||||
|
||||
&__thumbnails {
|
||||
position: relative; height: 100%; width: 140px; background-color: rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
&__container {
|
||||
display: flex; height: 100%;
|
||||
}
|
||||
|
||||
&__content {
|
||||
flex: 1 1 auto; position: relative;
|
||||
}
|
||||
|
||||
.loader-item {
|
||||
margin: auto;
|
||||
max-height:100px;
|
||||
|
@ -26,6 +26,8 @@ import { ToolbarModule } from '../../toolbar/toolbar.module';
|
||||
import { EventMock } from '../../mock/event.mock';
|
||||
import { RenderingQueueServices } from '../services/rendering-queue.services';
|
||||
import { PdfViewerComponent } from './pdfViewer.component';
|
||||
import { PdfThumbListComponent } from './pdfViewer-thumbnails.component';
|
||||
import { PdfThumbComponent } from './pdfViewer-thumb.component';
|
||||
|
||||
declare var require: any;
|
||||
|
||||
@ -41,7 +43,11 @@ describe('Test PdfViewer component', () => {
|
||||
ToolbarModule,
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [PdfViewerComponent],
|
||||
declarations: [
|
||||
PdfViewerComponent,
|
||||
PdfThumbListComponent,
|
||||
PdfThumbComponent
|
||||
],
|
||||
providers: [
|
||||
SettingsService,
|
||||
AuthenticationService,
|
||||
@ -97,7 +103,7 @@ describe('Test PdfViewer component', () => {
|
||||
|
||||
it('should Canvas be present', () => {
|
||||
expect(element.querySelector('.pdfViewer')).not.toBeNull();
|
||||
expect(element.querySelector('.viewer-pdf-container')).not.toBeNull();
|
||||
expect(element.querySelector('.viewer-pdf-viewer')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should Loader be present', () => {
|
||||
@ -145,7 +151,7 @@ describe('Test PdfViewer component', () => {
|
||||
|
||||
it('should Canvas be present', () => {
|
||||
expect(element.querySelector('.pdfViewer')).not.toBeNull();
|
||||
expect(element.querySelector('.viewer-pdf-container')).not.toBeNull();
|
||||
expect(element.querySelector('.viewer-pdf-viewer')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should Loader be present', () => {
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, HostListener, Input, OnChanges, OnDestroy, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, TemplateRef, HostListener, Input, OnChanges, OnDestroy, ViewEncapsulation } from '@angular/core';
|
||||
import { LogService } from '../../services/log.service';
|
||||
import { RenderingQueueServices } from '../services/rendering-queue.services';
|
||||
|
||||
@ -49,6 +49,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
@Input()
|
||||
allowThumbnails = false;
|
||||
|
||||
@Input()
|
||||
thumbnailsTemplate: TemplateRef<any> = null;
|
||||
|
||||
currentPdfDocument: any;
|
||||
page: number;
|
||||
displayPage: number;
|
||||
@ -64,6 +67,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
MIN_SCALE: number = 0.25;
|
||||
MAX_SCALE: number = 10.0;
|
||||
|
||||
showThumbnails = false;
|
||||
pdfThumbnailsContext: { viewer: any } = { viewer: null };
|
||||
|
||||
get currentScaleText(): string {
|
||||
return Math.round(this.currentScale * 100) + '%';
|
||||
}
|
||||
@ -134,7 +140,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
|
||||
const viewer: any = document.getElementById('viewer-viewerPdf');
|
||||
|
||||
this.documentContainer = document.getElementById('viewer-pdf-container');
|
||||
this.documentContainer = document.getElementById('viewer-pdf-viewer');
|
||||
this.documentContainer.addEventListener('pagechange', this.onPageChange, true);
|
||||
|
||||
this.pdfViewer = new PDFJS.PDFViewer({
|
||||
@ -146,6 +152,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
this.renderingQueueServices.setViewer(this.pdfViewer);
|
||||
|
||||
this.pdfViewer.setDocument(pdfDocument);
|
||||
|
||||
this.pdfThumbnailsContext.viewer = this.pdfViewer;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -154,6 +162,10 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
toggleThumbnails() {
|
||||
this.showThumbnails = !this.showThumbnails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to scale the page current support implementation
|
||||
*
|
||||
@ -165,7 +177,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
if (this.pdfViewer) {
|
||||
|
||||
let viewerContainer = document.getElementById('viewer-main-container');
|
||||
let documentContainer = document.getElementById('viewer-pdf-container');
|
||||
let documentContainer = document.getElementById('viewer-pdf-viewer');
|
||||
|
||||
let widthContainer;
|
||||
let heightContainer;
|
||||
|
@ -235,7 +235,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.viewer-pdf-container {
|
||||
.viewer-pdf-viewer {
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
position: absolute;
|
||||
@ -245,9 +245,9 @@
|
||||
left: 0;
|
||||
outline: none;
|
||||
}
|
||||
html[dir='ltr'] .viewer-pdf-container {
|
||||
html[dir='ltr'] .viewer-pdf-viewer {
|
||||
box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
|
||||
}
|
||||
html[dir='rtl'] .viewer-pdf-container {
|
||||
html[dir='rtl'] .viewer-pdf-viewer {
|
||||
box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05);
|
||||
}
|
||||
|
@ -144,7 +144,7 @@
|
||||
<div class="adf-viewer-layout-content adf-viewer__fullscreen-container">
|
||||
<div class="adf-viewer-content-container" [ngSwitch]="viewerType">
|
||||
<ng-container *ngSwitchCase="'pdf'">
|
||||
<adf-pdf-viewer [blobFile]="blobFile" [urlFile]="urlFileContent" [nameFile]="displayName"></adf-pdf-viewer>
|
||||
<adf-pdf-viewer [thumbnailsTemplate]="thumbnailsTemplate" [allowThumbnails]="allowThumbnails" [blobFile]="blobFile" [urlFile]="urlFileContent" [nameFile]="displayName"></adf-pdf-viewer>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'image'">
|
||||
|
@ -130,6 +130,39 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&__thumbnails {
|
||||
width: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
background: #e6e6e6;
|
||||
|
||||
.adf-info-drawer-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
background: #e6e6e6;
|
||||
}
|
||||
|
||||
.adf-info-drawer-layout-header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.adf-info-drawer-layout-content {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.info-drawer-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.adf-info-drawer-layout-content > *:last-child {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&__toolbar {
|
||||
&-page-scale {
|
||||
cursor: default;
|
||||
|
@ -30,6 +30,8 @@ import { RenderingQueueServices } from '../services/rendering-queue.services';
|
||||
import { ImgViewerComponent } from './imgViewer.component';
|
||||
import { MediaPlayerComponent } from './mediaPlayer.component';
|
||||
import { PdfViewerComponent } from './pdfViewer.component';
|
||||
import { PdfThumbListComponent } from './pdfViewer-thumbnails.component';
|
||||
import { PdfThumbComponent } from './pdfViewer-thumb.component';
|
||||
import { TxtViewerComponent } from './txtViewer.component';
|
||||
import { UnknownFormatComponent } from './unknown-format/unknown-format.component';
|
||||
import { ViewerMoreActionsComponent } from './viewer-more-actions.component';
|
||||
@ -129,6 +131,8 @@ describe('ViewerComponent', () => {
|
||||
declarations: [
|
||||
ViewerComponent,
|
||||
PdfViewerComponent,
|
||||
PdfThumbListComponent,
|
||||
PdfThumbComponent,
|
||||
TxtViewerComponent,
|
||||
MediaPlayerComponent,
|
||||
ImgViewerComponent,
|
||||
|
@ -18,7 +18,8 @@
|
||||
import { Location } from '@angular/common';
|
||||
import {
|
||||
Component, ContentChild, EventEmitter, HostListener, ElementRef,
|
||||
Input, OnChanges, Output, SimpleChanges, TemplateRef, ViewEncapsulation
|
||||
Input, OnChanges, Output, SimpleChanges, TemplateRef,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { MinimalNodeEntryEntity, RenditionEntry } from 'alfresco-js-api';
|
||||
import { BaseEvent } from '../../events';
|
||||
@ -130,6 +131,10 @@ export class ViewerComponent implements OnChanges {
|
||||
@Input()
|
||||
allowSidebar = false;
|
||||
|
||||
/** Toggles PDF thumbnails. */
|
||||
@Input()
|
||||
allowThumbnails = true;
|
||||
|
||||
/** Toggles sidebar visibility. Requires `allowSidebar` to be set to `true`. */
|
||||
@Input()
|
||||
showSidebar = false;
|
||||
@ -142,6 +147,10 @@ export class ViewerComponent implements OnChanges {
|
||||
@Input()
|
||||
sidebarTemplate: TemplateRef<any> = null;
|
||||
|
||||
/** The template for the pdf thumbnails. */
|
||||
@Input()
|
||||
thumbnailsTemplate: TemplateRef<any> = null;
|
||||
|
||||
/** MIME type of the file content (when not determined by the filename extension). */
|
||||
@Input()
|
||||
mimeType: string;
|
||||
@ -192,6 +201,7 @@ export class ViewerComponent implements OnChanges {
|
||||
@Output()
|
||||
navigateNext = new EventEmitter();
|
||||
|
||||
showPdfThumbnails: boolean = false;
|
||||
viewerType = 'unknown';
|
||||
isLoading = false;
|
||||
node: MinimalNodeEntryEntity;
|
||||
|
@ -19,6 +19,8 @@ export * from './components/viewer.component';
|
||||
export * from './components/imgViewer.component';
|
||||
export * from './components/mediaPlayer.component';
|
||||
export * from './components/pdfViewer.component';
|
||||
export * from './components/pdfViewer-thumbnails.component';
|
||||
export * from './components/pdfViewer-thumb.component';
|
||||
export * from './components/txtViewer.component';
|
||||
export * from './components/unknown-format/unknown-format.component';
|
||||
export * from './components/viewer-more-actions.component';
|
||||
|
@ -25,6 +25,8 @@ import { PipeModule } from '../pipes/pipe.module';
|
||||
import { ImgViewerComponent } from './components/imgViewer.component';
|
||||
import { MediaPlayerComponent } from './components/mediaPlayer.component';
|
||||
import { PdfViewerComponent } from './components/pdfViewer.component';
|
||||
import { PdfThumbComponent } from './components/pdfViewer-thumb.component';
|
||||
import { PdfThumbListComponent } from './components/pdfViewer-thumbnails.component';
|
||||
import { TxtViewerComponent } from './components/txtViewer.component';
|
||||
import { UnknownFormatComponent } from './components/unknown-format/unknown-format.component';
|
||||
import { ViewerMoreActionsComponent } from './components/viewer-more-actions.component';
|
||||
@ -50,6 +52,8 @@ import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
TxtViewerComponent,
|
||||
MediaPlayerComponent,
|
||||
PdfViewerComponent,
|
||||
PdfThumbComponent,
|
||||
PdfThumbListComponent,
|
||||
ViewerExtensionDirective,
|
||||
UnknownFormatComponent,
|
||||
ViewerToolbarComponent,
|
||||
@ -63,6 +67,8 @@ import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
TxtViewerComponent,
|
||||
MediaPlayerComponent,
|
||||
PdfViewerComponent,
|
||||
PdfThumbComponent,
|
||||
PdfThumbListComponent,
|
||||
ViewerExtensionDirective,
|
||||
UnknownFormatComponent,
|
||||
ViewerToolbarComponent,
|
||||
|
Loading…
x
Reference in New Issue
Block a user