[ADF-1750] content projection for viewer menus (#2524)

* content projection for viewer menus

* unit tests

* remove old file
This commit is contained in:
Denys Vuika 2017-10-23 21:57:00 +01:00 committed by Eugenio Romano
parent f1812fd123
commit b174cea07c
9 changed files with 204 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -51,13 +51,11 @@ Using with file url:
| showToolbar | boolean | true | Hide or show the toolbars | | showToolbar | boolean | true | Hide or show the toolbars |
| displayName | string | | You can specify the name of the file | | displayName | string | | You can specify the name of the file |
| allowGoBack | boolean | true | Allow `back` navigation | | allowGoBack | boolean | true | Allow `back` navigation |
| allowOpenWith | boolean | false | Toggle `Open With` options |
| allowDownload | boolean | true | Toggle download feature | | allowDownload | boolean | true | Toggle download feature |
| allowPrint | boolean | false | Toggle printing feature | | allowPrint | boolean | false | Toggle printing feature |
| allowShare | boolean | false | Toggle sharing feature | | allowShare | boolean | false | Toggle sharing feature |
| allowInfoDrawer | boolean |false | Toogle info drawer feature | | allowInfoDrawer | boolean |false | Toogle info drawer feature |
| showInfoDrawer | boolean | false | Toggles info drawer visibility. Requires `allowInfoDrawer` to be set to `true`. | | showInfoDrawer | boolean | false | Toggles info drawer visibility. Requires `allowInfoDrawer` to be set to `true`. |
| allowMoreActions | boolean | false | Toggles `More actions` feature |
## Details ## Details
@ -139,6 +137,60 @@ The `allowInfoDrawer` property should be set to `true` to enable Info Drawer fea
Everything you put inside the "adf-viewer-info-drawer" tags is going to be rendered instead of the default info drawer. Everything you put inside the "adf-viewer-info-drawer" tags is going to be rendered instead of the default info drawer.
### Custom "Open With" menu
You can enable custom "Open With" menu by providing at least one action inside the "adf-viewer-open-with" tag:
```html
<adf-viewer [fileNodeId]="nodeId">
<adf-viewer-open-with>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Option 1</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Option 2</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Option 3</span>
</button>
</adf-viewer-open-with>
</adv-viewer>
```
![Open with](docassets/images/viewer-open-with.png)
### Custom "More actions" menu
You can enable custom "More actions" menu by providing at least one action indide the "adf-viewer-more-actions" tag:
```html
<adf-viewer [fileNodeId]="nodeId">
<adf-viewer-more-actions>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Action One</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Action Two</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Action Three</span>
</button>
</adf-viewer-more-actions>
</adv-viewer>
```
![More actions](docassets/images/viewer-more-actions.png)
### Custom extension handler ### Custom extension handler
If you want to handle other file formats that are not yet supported by the ng2-alfresco-viewer you can define your own custom handler. If you want to handle other file formats that are not yet supported by the ng2-alfresco-viewer you can define your own custom handler.

View File

@ -25,6 +25,8 @@ import { PdfViewerComponent } from './src/components/pdfViewer.component';
import { TxtViewerComponent } from './src/components/txtViewer.component'; import { TxtViewerComponent } from './src/components/txtViewer.component';
import { UnknownFormatComponent } from './src/components/unknown-format/unknown-format.component'; import { UnknownFormatComponent } from './src/components/unknown-format/unknown-format.component';
import { ViewerInfoDrawerComponent } from './src/components/viewer-info-drawer.component'; import { ViewerInfoDrawerComponent } from './src/components/viewer-info-drawer.component';
import { ViewerMoreActionsComponent } from './src/components/viewer-more-actions.component';
import { ViewerOpenWithComponent } from './src/components/viewer-open-with.component';
import { ViewerToolbarComponent } from './src/components/viewer-toolbar.component'; import { ViewerToolbarComponent } from './src/components/viewer-toolbar.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';
@ -42,7 +44,9 @@ export function declarations() {
ExtensionViewerDirective, ExtensionViewerDirective,
UnknownFormatComponent, UnknownFormatComponent,
ViewerToolbarComponent, ViewerToolbarComponent,
ViewerInfoDrawerComponent ViewerInfoDrawerComponent,
ViewerOpenWithComponent,
ViewerMoreActionsComponent
]; ];
} }

View File

@ -0,0 +1,28 @@
/*!
* @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 { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'adf-viewer-more-actions',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'adf-viewer-more-actions' },
template: `<ng-content></ng-content>`
})
export class ViewerMoreActionsComponent {
}

View File

@ -0,0 +1,28 @@
/*!
* @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 { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'adf-viewer-open-with',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'adf-viewer-open-with' },
template: `<ng-content></ng-content>`
})
export class ViewerOpenWithComponent {
}

View File

@ -20,24 +20,13 @@
<span>{{ displayName }}</span> <span>{{ displayName }}</span>
</adf-toolbar-title> </adf-toolbar-title>
<ng-container *ngIf="allowOpenWith"> <ng-container *ngIf="mnuOpenWith">
<button mat-button [matMenuTriggerFor]="mnuOpenWith"> <button mat-button [matMenuTriggerFor]="mnuOpenWith">
<span>{{ 'ADF_VIEWER.ACTIONS.OPEN_WITH' | translate }}</span> <span>{{ 'ADF_VIEWER.ACTIONS.OPEN_WITH' | translate }}</span>
<mat-icon>arrow_drop_down</mat-icon> <mat-icon>arrow_drop_down</mat-icon>
</button> </button>
<mat-menu #mnuOpenWith="matMenu" [overlapTrigger]="false"> <mat-menu #mnuOpenWith="matMenu" [overlapTrigger]="false">
<button mat-menu-item> <ng-content select="adf-viewer-open-with"></ng-content>
<mat-icon>dialpad</mat-icon>
<span>Option 1</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Option 2</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Option 3</span>
</button>
</mat-menu> </mat-menu>
</ng-container> </ng-container>
@ -55,23 +44,12 @@
<mat-icon>share</mat-icon> <mat-icon>share</mat-icon>
</button> </button>
<ng-container *ngIf="allowMoreActions"> <ng-container *ngIf="mnuMoreActions">
<button mat-icon-button [matMenuTriggerFor]="mnuMoreActions" matTooltip="{{ 'ADF_VIEWER.ACTIONS.MORE_ACTIONS' | translate }}"> <button mat-icon-button [matMenuTriggerFor]="mnuMoreActions" matTooltip="{{ 'ADF_VIEWER.ACTIONS.MORE_ACTIONS' | translate }}">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
<mat-menu #mnuMoreActions="matMenu"> <mat-menu #mnuMoreActions="matMenu" [overlapTrigger]="false">
<button mat-menu-item> <ng-content select="adf-viewer-more-actions"></ng-content>
<mat-icon>dialpad</mat-icon>
<span>Action One</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Action Two</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Action Three</span>
</button>
</mat-menu> </mat-menu>
</ng-container> </ng-container>

View File

@ -31,6 +31,8 @@ import { PdfViewerComponent } from './pdfViewer.component';
import { TxtViewerComponent } from './txtViewer.component'; import { TxtViewerComponent } from './txtViewer.component';
import { UnknownFormatComponent } from './unknown-format/unknown-format.component'; import { UnknownFormatComponent } from './unknown-format/unknown-format.component';
import { ViewerInfoDrawerComponent } from './viewer-info-drawer.component'; import { ViewerInfoDrawerComponent } from './viewer-info-drawer.component';
import { ViewerMoreActionsComponent } from './viewer-more-actions.component';
import { ViewerOpenWithComponent } from './viewer-open-with.component';
import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { ViewerToolbarComponent } from './viewer-toolbar.component';
import { ViewerComponent } from './viewer.component'; import { ViewerComponent } from './viewer.component';
@ -60,6 +62,52 @@ class ViewerWithCustomToolbarComponent {}
}) })
class ViewerWithCustomInfoDrawerComponent {} class ViewerWithCustomInfoDrawerComponent {}
@Component({
selector: 'adf-viewer-container-open-with',
template: `
<adf-viewer>
<adf-viewer-open-with>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Option 1</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Option 2</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Option 3</span>
</button>
</adf-viewer-open-with>
</adf-viewer>
`
})
class ViewerWithCustomOpenWithComponent {}
@Component({
selector: 'adf-viewer-container-more-actions',
template: `
<adf-viewer>
<adf-viewer-more-actions>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Action One</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Action Two</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Action Three</span>
</button>
</adf-viewer-more-actions>
</adf-viewer>
`
})
class ViewerWithCustomMoreActionsComponent {}
describe('ViewerComponent', () => { describe('ViewerComponent', () => {
let component: ViewerComponent; let component: ViewerComponent;
@ -82,8 +130,12 @@ describe('ViewerComponent', () => {
UnknownFormatComponent, UnknownFormatComponent,
ViewerInfoDrawerComponent, ViewerInfoDrawerComponent,
ViewerToolbarComponent, ViewerToolbarComponent,
ViewerOpenWithComponent,
ViewerMoreActionsComponent,
ViewerWithCustomToolbarComponent, ViewerWithCustomToolbarComponent,
ViewerWithCustomInfoDrawerComponent ViewerWithCustomInfoDrawerComponent,
ViewerWithCustomOpenWithComponent,
ViewerWithCustomMoreActionsComponent
], ],
providers: [ providers: [
RenderingQueueServices, RenderingQueueServices,
@ -128,6 +180,22 @@ describe('ViewerComponent', () => {
expect(customElement.querySelector('.custom-info-drawer-element')).toBeDefined(); expect(customElement.querySelector('.custom-info-drawer-element')).toBeDefined();
}); });
it('should use custom open with menu', () => {
let customFixture = TestBed.createComponent(ViewerWithCustomOpenWithComponent);
let customElement: HTMLElement = customFixture.nativeElement;
customFixture.detectChanges();
expect(customElement.querySelector('.adf-viewer-container-open-with')).toBeDefined();
});
it('should use custom more actions menu', () => {
let customFixture = TestBed.createComponent(ViewerWithCustomMoreActionsComponent);
let customElement: HTMLElement = customFixture.nativeElement;
customFixture.detectChanges();
expect(customElement.querySelector('.adf-viewer-container-more-actions')).toBeDefined();
});
describe('View', () => { describe('View', () => {
describe('Overlay mode true', () => { describe('Overlay mode true', () => {

View File

@ -24,6 +24,8 @@ import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { AlfrescoApiService, BaseEvent, LogService, RenditionsService } from 'ng2-alfresco-core'; import { AlfrescoApiService, BaseEvent, LogService, RenditionsService } from 'ng2-alfresco-core';
import { ViewerInfoDrawerComponent } from './viewer-info-drawer.component'; import { ViewerInfoDrawerComponent } from './viewer-info-drawer.component';
import { ViewerMoreActionsComponent } from './viewer-more-actions.component';
import { ViewerOpenWithComponent } from './viewer-open-with.component';
import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { ViewerToolbarComponent } from './viewer-toolbar.component';
@Component({ @Component({
@ -41,8 +43,14 @@ export class ViewerComponent implements OnDestroy, OnChanges {
@ContentChild(ViewerInfoDrawerComponent) @ContentChild(ViewerInfoDrawerComponent)
infoDrawer: ViewerInfoDrawerComponent; infoDrawer: ViewerInfoDrawerComponent;
@ContentChild(ViewerOpenWithComponent)
mnuOpenWith: ViewerOpenWithComponent;
@ContentChild(ViewerMoreActionsComponent)
mnuMoreActions: ViewerMoreActionsComponent;
@Input() @Input()
urlFile: string = ''; urlFile = '';
@Input() @Input()
blobFile: Blob; blobFile: Blob;
@ -51,23 +59,20 @@ export class ViewerComponent implements OnDestroy, OnChanges {
fileNodeId: string = null; fileNodeId: string = null;
@Input() @Input()
overlayMode: boolean = false; overlayMode = false;
@Input() @Input()
showViewer: boolean = true; showViewer = true;
@Input() @Input()
showToolbar = true; showToolbar = true;
@Input() @Input()
displayName: string = 'Unknown'; displayName = 'Unknown';
@Input() @Input()
allowGoBack = true; allowGoBack = true;
@Input()
allowOpenWith = false;
@Input() @Input()
allowDownload = true; allowDownload = true;
@ -83,9 +88,6 @@ export class ViewerComponent implements OnDestroy, OnChanges {
@Input() @Input()
showInfoDrawer = false; showInfoDrawer = false;
@Input()
allowMoreActions = false;
@Output() @Output()
goBack = new EventEmitter<BaseEvent<any>>(); goBack = new EventEmitter<BaseEvent<any>>();
@ -95,10 +97,10 @@ export class ViewerComponent implements OnDestroy, OnChanges {
@Output() @Output()
extensionChange = new EventEmitter<string>(); extensionChange = new EventEmitter<string>();
viewerType: string = 'unknown'; viewerType = 'unknown';
downloadUrl: string = null; downloadUrl: string = null;
fileName: string = 'document'; fileName = 'document';
isLoading: boolean = false; isLoading = false;
extensionTemplates: { template: TemplateRef<any>, isVisible: boolean }[] = []; extensionTemplates: { template: TemplateRef<any>, isVisible: boolean }[] = [];
externalExtensions: string[] = []; externalExtensions: string[] = [];