extensibility docs update (#571)

* docs: custom sidebar tabs

* update docs

* docs update, simplify extension schema

* test fixes
This commit is contained in:
Denys Vuika
2018-08-17 13:44:01 +01:00
committed by GitHub
parent c0321fe449
commit 160226094d
14 changed files with 996 additions and 576 deletions
+7
View File
@@ -24,6 +24,13 @@
"unfavorite", "unfavorite",
"Snackbar", "Snackbar",
"devtools", "devtools",
"gitter",
"jira",
"markdownlint",
"uploader",
"nginx",
"docx",
"SOLR",
"unshare", "unshare",
"validators", "validators",
+5 -3
View File
@@ -1,5 +1,7 @@
# Alfresco Example Content Application # Alfresco Example Content Application
<!-- markdownlint-disable MD033 -->
## Introduction ## Introduction
The Alfresco Content Application is an example application built using The Alfresco Content Application is an example application built using
@@ -287,7 +289,7 @@ The Header & Toolbar section of the viewer contains a number of features that re
The File Viewer consists of four separate views that handle displaying the content based on four types of content, covering various [file/mime](https://alfresco.github.io/adf-component-catalog/components/ViewerComponent.html#supported-file-formats) types: The File Viewer consists of four separate views that handle displaying the content based on four types of content, covering various [file/mime](https://alfresco.github.io/adf-component-catalog/components/ViewerComponent.html#supported-file-formats) types:
- Document View: PDFs are displayed in the application File Viewer, for other document types (DOCX etc) then a PDF rendition is automatically retrieved. - Document View: PDF files are displayed in the application File Viewer, for other document types (DOCX etc) then a PDF rendition is automatically retrieved.
- Image View: JPEG, PNG, GIF, BMP and SVG images are natively displayed in the application File Viewer. - Image View: JPEG, PNG, GIF, BMP and SVG images are natively displayed in the application File Viewer.
- Media View: MP4, MP3, WAV, OGG and WEBM files are played natively application File Viewer. The File Viewer will download, by default, 50MB of the content at a time to ensure a smooth playback of the content. - Media View: MP4, MP3, WAV, OGG and WEBM files are played natively application File Viewer. The File Viewer will download, by default, 50MB of the content at a time to ensure a smooth playback of the content.
- Text View: TXT, XML, JS, HTML, JSON and TS files are natively displayed as text in the application File Viewer. - Text View: TXT, XML, JS, HTML, JSON and TS files are natively displayed as text in the application File Viewer.
@@ -313,7 +315,7 @@ At the bottom of the content the Viewer Controls allow users to interact with th
- Media View: - Media View:
- Play/pause - Play/pause
- Timeline position - Timeline position
- Audio mute/unmute - Toggle audio
- Audio volume - Audio volume
- Full screen - Full screen
@@ -329,7 +331,7 @@ The Properties tab displays the node's metadata info by using the [ContentMetada
![](images/content-metadata.png) ![](images/content-metadata.png)
For more information, please check also the ADF's [ContentMetadataComponent](https://alfresco.github.io/adf-component-catalog/components/ContentMetadataComponent.html). For more information, please check also the [ContentMetadataComponent](https://alfresco.github.io/adf-component-catalog/components/ContentMetadataComponent.html).
#### Versions tab #### Versions tab
+444 -13
View File
@@ -2,6 +2,8 @@
title: Extending title: Extending
--- ---
<!-- markdownlint-disable MD033 -->
<p class="danger"> <p class="danger">
Work is still in progress, the documentation and examples may change. Work is still in progress, the documentation and examples may change.
</p> </p>
@@ -18,6 +20,7 @@ You can create plugins that change, toggle or extend the following areas:
* Navigation sidebar links and groups * Navigation sidebar links and groups
* Context Menu * Context Menu
* Sidebar (aka Info Drawer)
* Toolbar entries * Toolbar entries
* buttons * buttons
* menu buttons * menu buttons
@@ -116,9 +119,9 @@ To create a new route, populate the `routes` section with the corresponding entr
| **id** | Unique identifier. | | **id** | Unique identifier. |
| **path** | Runtime path of the route. | | **path** | Runtime path of the route. |
| **component** | The main [component](#components) to use for the route. | | **component** | The main [component](#components) to use for the route. |
| *layout* | The layout [component](#components) to use for the route. | | layout | The layout [component](#components) to use for the route. |
| *auth* | List of [authentication guards](#authentication-guards). Defaults to `[ "app.auth" ]`. | | auth | List of [authentication guards](#authentication-guards). Defaults to `[ "app.auth" ]`. |
| *data* | Custom property bag to carry with the route. | | data | Custom property bag to carry with the route. |
<p class="tip"> <p class="tip">
Use the `app.layout.main` value for the `layout` property to get the default application layout, Use the `app.layout.main` value for the `layout` property to get the default application layout,
@@ -150,6 +153,11 @@ You can define the full route schema like in the next example:
} }
``` ```
<p class="warning">
All application routes require at least one authentication guard.
If you do not provide a guard the default `['app.auth`]` will be used at runtime.
</p>
### Authentication Guards ### Authentication Guards
Below is the list of the authentication guards main application registers on startup. Below is the list of the authentication guards main application registers on startup.
@@ -539,9 +547,9 @@ on how to register your own entries to be re-used at runtime.
The rule in the example below evaluates to `true` if all the conditions are met: The rule in the example below evaluates to `true` if all the conditions are met:
- user has selected node(s) * user has selected node(s)
- user is not using **Trashcan** page * user is not using **Trashcan** page
- user is not using **Libraries** page * user is not using **Libraries** page
```json ```json
{ {
@@ -565,19 +573,443 @@ The rule in the example below evaluates to `true` if all the conditions are met:
## Application Features ## Application Features
### Extending Create Menu This section contains application-specific features that may vary depending on the final implementation.
### Extending Navigation Sidebar The ACA supports the following set of extension points:
### Extending Toolbar * Create menu
* Navigation Bar
* Toolbar
* Context Menu
* Viewer
* Sidebar (aka Info Drawer)
### Extending Context Menu All the customisations are stored in the `features` section of the configuration file:
### Extending Viewer ```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"create": [],
"navbar": [],
"toolbar": [],
"contextMenu": [],
"viewer": {
"toolbar:": [],
"openWith": []
},
"sidebar": []
}
}
```
Other applications or external plugins can utilise different subsets of the configuration above.
Also, extra entries can be added to the configuration schema.
### Content Actions
Most of the UI elements that operate with content, like toolbar buttons or menus,
are based on `ContentActionRef` interface implementation:
```ts
interface ContentActionRef {
id: string;
type: ContentActionType;
title?: string;
description?: string;
order?: number;
icon?: string;
disabled?: boolean;
children?: Array<ContentActionRef>;
component?: string;
actions?: {
click?: string;
[key: string]: string;
};
rules?: {
enabled?: string;
visible?: string;
[key: string]: string;
};
}
```
You can define content actions in the `app.extensions.json` file using the structure above.
### Create Menu
Provides extension endpoint for the "NEW" menu options.
You can populate the menu with an extra entries like in the example below:
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"create": [
{
"id": "app.create.folder",
"icon": "create_new_folder",
"title": "Create Folder",
"actions": {
"click": "CREATE_FOLDER"
},
"rules": {
"enabled": "app.navigation.folder.canCreate"
}
},
{
"id": "app.create.uploadFile",
"icon": "file_upload",
"title": "Upload Files",
"actions": {
"click": "UPLOAD_FILES"
},
"rules": {
"enabled": "app.navigation.folder.canUpload"
}
}
]
}
}
```
Please refer to the [Content Actions](#content-actions) section for more details on supported properties.
<p class="tip">
It is also possible to update or disable existing entries from within the external extension files. You will need to know the `id` of the target element to customise.
</p>
### Navigation Bar
Navigation bar consists of Link elements (`NavBarLinkRef`) organized into Groups (`NavBarGroupRef`).
```ts
export interface NavBarGroupRef {
id: string;
items: Array<NavBarLinkRef>;
order?: number;
disabled?: boolean;
}
export interface NavBarLinkRef {
id: string;
icon: string;
title: string;
route: string;
url?: string; // evaluated at runtime based on route ref
description?: string;
order?: number;
disabled?: boolean;
}
```
You extensions can perform the following actions at runtime:
* Register new groups with links
* Insert new links into existing groups
* Update properties of the existing links
* Disable existing links or entire groups
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"navbar": [
{
"id": "app.navbar.primary",
"items": [
{
"id": "app.navbar.personalFiles",
"icon": "folder",
"title": "Personal Files",
"route": "personal-files"
},
{
"id": "app.navbar.libraries",
"icon": "group_work",
"title": "Libraries",
"route": "libraries"
}
]
},
{
"id": "app.navbar.secondary",
"items": [
{
"id": "app.navbar.shared",
"icon": "people",
"title": "Shared",
"route": "shared"
}
]
}
]
}
}
```
### Sidebar (Info Drawer)
You can provide the following customisations for the Sidebar (aka Info Drawer) component:
* Add extra tabs with custom components
* Disable tabs from the main application or extensions
* Replace content or properties of existing tabs
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"sidebar": {
{
"id": "app.sidebar.properties",
"order": 100,
"title": "Properties",
"component": "app.components.tabs.metadata"
},
{
"id": "app.sidebar.comments",
"order": 200,
"title": "Comments",
"component": "app.components.tabs.comments"
}
}
}
}
```
The example above renders two tabs:
* `Properties` tab that references `app.components.tabs.metadata` component
* `Comments` tab that references `app.components.tabs.comments` component
All corresponding components must be registered for runtime use.
<p class="tip">
See [Registration](#registration) section for more details
on how to register your own entries to be re-used at runtime.
</p>
#### Tab properties
| Name | Description |
| --- | --- |
| **id** | Unique identifier. |
| **component** | The main [component](#components) to use for the route. |
| **title** | Tab title or resource key. |
| icon | Tab icon |
| disabled | Toggles disabled state. Can be assigned from other plugins. |
| order | The order of the element. |
### Toolbar
The toolbar extension point is represented by an array of Content Action references.
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"toolbar": [
{
"id": "app.toolbar.preview",
"title": "View",
"icon": "open_in_browser",
"actions": {
"click": "VIEW_FILE"
},
"rules": {
"visible": "app.toolbar.canViewFile"
}
},
{
"id": "app.toolbar.download",
"title": "Download",
"icon": "get_app",
"actions": {
"click": "DOWNLOAD_NODES"
},
"rules": {
"visible": "app.toolbar.canDownload"
}
}
]
}
}
```
The content actions are applied to the toolbars for the following Views:
* Personal Files
* Libraries
* Shared
* Recent Files
* Favorites
* Trash
* Search Results
### Context Menu
Context Menu extensibility is similar to the one of the Toolbar.
You may want to define a list of content actions backed by Rules and wired with Application Actions.
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"contextMenu": [
{
"id": "app.context.menu.download",
"order": 100,
"title": "Download",
"icon": "get_app",
"actions": {
"click": "DOWNLOAD_NODES"
},
"rules": {
"visible": "app.toolbar.canDownload"
}
},
]
}
}
```
Note that you can re-use any rules and evaluators available.
In the example above, the context menu action `Download` utilizes the `app.toolbar.canDownload` rule,
declared in the `rules` section:
```json
{
"rules": [
{
"id": "app.toolbar.canDownload",
"type": "core.every",
"parameters": [
{ "type": "rule", "value": "app.selection.canDownload" },
{ "type": "rule", "value": "app.navigation.isNotTrashcan" }
]
}
]
}
```
### Viewer
Viewer component in ACA supports the following extension points:
* `More` toolbar actions
* `Open With` actions
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"viewer": {
"toolbar:": [],
"openWith": []
}
}
}
```
#### Toolbar actions
The ADF Viewer component allows providing custom entries for the `More` menu button on the toolbar.
The ACA provides an extension point for this menu that you can utilise to populate custom menu items:
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"viewer": {
"toolbar:": [
{
"id": "app.viewer.share",
"order": 300,
"title": "Share",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
}
]
}
}
}
```
#### Open With actions #### Open With actions
#### Toolbar actions You can provide a list of `Open With` actions to render with every instance of the Viewer.
In the following example, we create a simple `Snackbar` action reference,
and invoke it from the custom `Open With` menu entry called `Snackbar`.
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"actions": [
{
"id": "plugin1.actions.info",
"type": "SNACKBAR_INFO",
"payload": "I'm a nice little popup raised by extension."
},
],
"features": {
"viewer": {
"openWith": [
{
"id": "plugin1.viewer.openWith.action1",
"type": "button",
"icon": "build",
"title": "Snackbar",
"actions": {
"click": "plugin1.actions.info"
}
}
]
}
}
}
```
As with other content actions, custom plugins can disable, update or extend `Open With` actions.
## Registration ## Registration
@@ -699,7 +1131,6 @@ extensions.setEvaluators({
Now, the `plugin1.rules.hasSelection` evaluator can be used as an inline rule reference, Now, the `plugin1.rules.hasSelection` evaluator can be used as an inline rule reference,
or part of the composite rule like `core.every`. or part of the composite rule like `core.every`.
<p class="tip"> <p class="tip">
See [Registration](#registration) section for more details See [Registration](#registration) section for more details
on how to register your own entries to be re-used at runtime. on how to register your own entries to be re-used at runtime.
+1 -1
View File
@@ -482,7 +482,7 @@ In the `app.config.json` define a link entry which will point to the custom page
{ {
"icon": "work", "icon": "work",
"label": "Link", "label": "Link",
"title": "My custome link", "title": "My custom link",
"route": { "route": {
"url": "/custom-route" "url": "/custom-route"
} }
+6 -12
View File
@@ -332,8 +332,8 @@
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
}, },
"actions": { "toolbar": {
"description": "Content actions (toolbar, context menus, etc.)", "description": "Toolbar entries",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
@@ -352,18 +352,14 @@
"items": { "$ref": "#/definitions/sidebarTabRef" }, "items": { "$ref": "#/definitions/sidebarTabRef" },
"minItems": 1 "minItems": 1
}, },
"content": { "toolbar": {
"description": "Main application content extensions", "description": "Toolbar entries",
"type": "object",
"properties": {
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
}, },
"contextActions": { "contextMenu": {
"description": "Content actions (toolbar, context menus, etc.)", "description": "Context menu entries",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
@@ -372,5 +368,3 @@
} }
} }
} }
}
}
@@ -112,7 +112,7 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit {
.subscribe(selection => { .subscribe(selection => {
if (selection.count) { if (selection.count) {
this.selection = selection; this.selection = selection;
this.actions = this.extensions.getAllowedContentContextActions(); this.actions = this.extensions.getAllowedContextMenuActions();
} }
}); });
} }
+3 -3
View File
@@ -51,7 +51,7 @@ export abstract class PageComponent implements OnInit, OnDestroy {
documentDisplayMode$: Observable<string>; documentDisplayMode$: Observable<string>;
sharedPreviewUrl$: Observable<string>; sharedPreviewUrl$: Observable<string>;
actions: Array<ContentActionRef> = []; actions: Array<ContentActionRef> = [];
viewerActions: Array<ContentActionRef> = []; viewerToolbarActions: Array<ContentActionRef> = [];
canUpdateNode = false; canUpdateNode = false;
canUpload = false; canUpload = false;
@@ -76,8 +76,8 @@ export abstract class PageComponent implements OnInit, OnDestroy {
.pipe(takeUntil(this.onDestroy$)) .pipe(takeUntil(this.onDestroy$))
.subscribe(selection => { .subscribe(selection => {
this.selection = selection; this.selection = selection;
this.actions = this.extensions.getAllowedContentActions(); this.actions = this.extensions.getAllowedToolbarActions();
this.viewerActions = this.extensions.getViewerActions(); this.viewerToolbarActions = this.extensions.getViewerToolbarActions();
this.canUpdateNode = this.selection.count === 1 && this.content.canUpdateNode(selection.first); this.canUpdateNode = this.selection.count === 1 && this.content.canUpdateNode(selection.first);
}); });
@@ -24,7 +24,7 @@
</adf-viewer-open-with> </adf-viewer-open-with>
<adf-viewer-more-actions> <adf-viewer-more-actions>
<ng-container *ngFor="let action of viewerActions; trackBy: trackByActionId"> <ng-container *ngFor="let action of viewerToolbarActions; trackBy: trackByActionId">
<aca-toolbar-action type="menu-item" [entry]="action"></aca-toolbar-action> <aca-toolbar-action type="menu-item" [entry]="action"></aca-toolbar-action>
</ng-container> </ng-container>
</adf-viewer-more-actions> </adf-viewer-more-actions>
+3 -5
View File
@@ -42,13 +42,11 @@ export interface ExtensionConfig {
create?: Array<ContentActionRef>; create?: Array<ContentActionRef>;
viewer?: { viewer?: {
openWith?: Array<ContentActionRef>; openWith?: Array<ContentActionRef>;
actions?: Array<ContentActionRef>; toolbar?: Array<ContentActionRef>;
}; };
navbar?: Array<NavBarGroupRef>; navbar?: Array<NavBarGroupRef>;
sidebar?: Array<SidebarTabRef>; sidebar?: Array<SidebarTabRef>;
content?: { toolbar?: Array<ContentActionRef>;
actions?: Array<ContentActionRef>; contextMenu?: Array<ContentActionRef>;
contextActions?: Array<ContentActionRef>
};
}; };
} }
+6 -10
View File
@@ -290,8 +290,7 @@ describe('ExtensionService', () => {
$name: 'test', $name: 'test',
$version: '1.0.0', $version: '1.0.0',
features: { features: {
content: { toolbar: [
actions: [
{ {
id: 'aca:toolbar/separator-1', id: 'aca:toolbar/separator-1',
order: 1, order: 1,
@@ -306,10 +305,9 @@ describe('ExtensionService', () => {
} }
] ]
} }
}
}); });
expect(extensions.contentActions.length).toBe(2); expect(extensions.toolbarActions.length).toBe(2);
}); });
it('should sort content actions by order', () => { it('should sort content actions by order', () => {
@@ -317,8 +315,7 @@ describe('ExtensionService', () => {
$name: 'test', $name: 'test',
$version: '1.0.0', $version: '1.0.0',
features: { features: {
content: { toolbar: [
actions: [
{ {
id: 'aca:toolbar/separator-2', id: 'aca:toolbar/separator-2',
order: 2, order: 2,
@@ -333,14 +330,13 @@ describe('ExtensionService', () => {
} }
] ]
} }
}
}); });
expect(extensions.contentActions.length).toBe(2); expect(extensions.toolbarActions.length).toBe(2);
expect(extensions.contentActions[0].id).toBe( expect(extensions.toolbarActions[0].id).toBe(
'aca:toolbar/separator-1' 'aca:toolbar/separator-1'
); );
expect(extensions.contentActions[1].id).toBe( expect(extensions.toolbarActions[1].id).toBe(
'aca:toolbar/separator-2' 'aca:toolbar/separator-2'
); );
}); });
+22 -20
View File
@@ -38,6 +38,7 @@ import { ActionRef, ContentActionRef, ContentActionType } from './action.extensi
import * as core from './evaluators/core.evaluators'; import * as core from './evaluators/core.evaluators';
import { NodePermissionService } from '../services/node-permission.service'; import { NodePermissionService } from '../services/node-permission.service';
import { SidebarTabRef } from './sidebar.extensions'; import { SidebarTabRef } from './sidebar.extensions';
import { ProfileResolver } from '../services/profile.resolver';
@Injectable() @Injectable()
export class ExtensionService implements RuleContext { export class ExtensionService implements RuleContext {
@@ -53,9 +54,9 @@ export class ExtensionService implements RuleContext {
routes: Array<RouteRef> = []; routes: Array<RouteRef> = [];
actions: Array<ActionRef> = []; actions: Array<ActionRef> = [];
contentActions: Array<ContentActionRef> = []; toolbarActions: Array<ContentActionRef> = [];
viewerActions: Array<ContentActionRef> = []; viewerToolbarActions: Array<ContentActionRef> = [];
contentContextmenuActions: Array<ContentActionRef> = []; contextMenuActions: Array<ContentActionRef> = [];
openWithActions: Array<ContentActionRef> = []; openWithActions: Array<ContentActionRef> = [];
createActions: Array<ContentActionRef> = []; createActions: Array<ContentActionRef> = [];
navbar: Array<NavBarGroupRef> = []; navbar: Array<NavBarGroupRef> = [];
@@ -133,9 +134,9 @@ export class ExtensionService implements RuleContext {
this.rules = this.loadRules(config); this.rules = this.loadRules(config);
this.actions = this.loadActions(config); this.actions = this.loadActions(config);
this.routes = this.loadRoutes(config); this.routes = this.loadRoutes(config);
this.contentActions = this.loadContentActions(config); this.toolbarActions = this.loadToolbarActions(config);
this.viewerActions = this.loadViewerActions(config); this.viewerToolbarActions = this.loadViewerToolbarActions(config);
this.contentContextmenuActions = this.loadContentContextMenuActions(config); this.contextMenuActions = this.loadContextMenuActions(config);
this.openWithActions = this.loadViewerOpenWith(config); this.openWithActions = this.loadViewerOpenWith(config);
this.createActions = this.loadCreateActions(config); this.createActions = this.loadCreateActions(config);
this.navbar = this.loadNavBar(config); this.navbar = this.loadNavBar(config);
@@ -168,27 +169,27 @@ export class ExtensionService implements RuleContext {
return []; return [];
} }
protected loadContentActions(config: ExtensionConfig) { protected loadToolbarActions(config: ExtensionConfig) {
if (config && config.features && config.features.content) { if (config && config.features && config.features.toolbar) {
return (config.features.content.actions || []) return (config.features.toolbar || [])
.sort(this.sortByOrder) .sort(this.sortByOrder)
.map(this.setActionDefaults); .map(this.setActionDefaults);
} }
return []; return [];
} }
protected loadViewerActions(config: ExtensionConfig): Array<ContentActionRef> { protected loadViewerToolbarActions(config: ExtensionConfig): Array<ContentActionRef> {
if (config && config.features && config.features.viewer) { if (config && config.features && config.features.viewer) {
return (config.features.viewer.actions || []) return (config.features.viewer.toolbar || [])
.sort(this.sortByOrder) .sort(this.sortByOrder)
.map(this.setActionDefaults); .map(this.setActionDefaults);
} }
return []; return [];
} }
protected loadContentContextMenuActions(config: ExtensionConfig): Array<ContentActionRef> { protected loadContextMenuActions(config: ExtensionConfig): Array<ContentActionRef> {
if (config && config.features && config.features.content) { if (config && config.features && config.features.contextMenu) {
return (config.features.content.contextActions || []) return (config.features.contextMenu || [])
.sort(this.sortByOrder) .sort(this.sortByOrder)
.map(this.setActionDefaults); .map(this.setActionDefaults);
} }
@@ -312,6 +313,7 @@ export class ExtensionService implements RuleContext {
component: this.getComponentById(route.layout || this.defaults.layout), component: this.getComponentById(route.layout || this.defaults.layout),
canActivateChild: guards, canActivateChild: guards,
canActivate: guards, canActivate: guards,
resolve: { profile: ProfileResolver },
children: [ children: [
{ {
path: '', path: '',
@@ -342,8 +344,8 @@ export class ExtensionService implements RuleContext {
} }
// evaluates content actions for the selection and parent folder node // evaluates content actions for the selection and parent folder node
getAllowedContentActions(): Array<ContentActionRef> { getAllowedToolbarActions(): Array<ContentActionRef> {
return this.contentActions return this.toolbarActions
.filter(this.filterEnabled) .filter(this.filterEnabled)
.filter(action => this.filterByRules(action)) .filter(action => this.filterByRules(action))
.map(action => { .map(action => {
@@ -364,14 +366,14 @@ export class ExtensionService implements RuleContext {
.reduce(this.reduceSeparators, []); .reduce(this.reduceSeparators, []);
} }
getViewerActions(): Array<ContentActionRef> { getViewerToolbarActions(): Array<ContentActionRef> {
return this.viewerActions return this.viewerToolbarActions
.filter(this.filterEnabled) .filter(this.filterEnabled)
.filter(action => this.filterByRules(action)); .filter(action => this.filterByRules(action));
} }
getAllowedContentContextActions(): Array<ContentActionRef> { getAllowedContextMenuActions(): Array<ContentActionRef> {
return this.contentContextmenuActions return this.contextMenuActions
.filter(this.filterEnabled) .filter(this.filterEnabled)
.filter(action => this.filterByRules(action)); .filter(action => this.filterByRules(action));
} }
+18 -20
View File
@@ -237,8 +237,7 @@
] ]
} }
], ],
"content": { "toolbar": [
"actions": [
{ {
"id": "app.toolbar.preview", "id": "app.toolbar.preview",
"order": 100, "order": 100,
@@ -460,9 +459,9 @@
] ]
} }
], ],
"contextActions": [ "contextMenu": [
{ {
"id": "app.contextmenu.download", "id": "app.context.menu.download",
"order": 100, "order": 100,
"title": "APP.ACTIONS.DOWNLOAD", "title": "APP.ACTIONS.DOWNLOAD",
"icon": "get_app", "icon": "get_app",
@@ -474,7 +473,7 @@
} }
}, },
{ {
"id": "app.contextmenu.preview", "id": "app.context.menu.preview",
"order": 200, "order": 200,
"title": "APP.ACTIONS.VIEW", "title": "APP.ACTIONS.VIEW",
"icon": "open_in_browser", "icon": "open_in_browser",
@@ -486,7 +485,7 @@
} }
}, },
{ {
"id": "app.contextmenu.editFolder", "id": "app.context.menu.editFolder",
"order": 300, "order": 300,
"title": "APP.ACTIONS.EDIT", "title": "APP.ACTIONS.EDIT",
"icon": "create", "icon": "create",
@@ -498,7 +497,7 @@
} }
}, },
{ {
"id": "app.contextmenu.share", "id": "app.context.menu.share",
"title": "APP.ACTIONS.SHARE", "title": "APP.ACTIONS.SHARE",
"order": 400, "order": 400,
"icon": "share", "icon": "share",
@@ -510,7 +509,7 @@
} }
}, },
{ {
"id": "app.contextmenu.favorite.add", "id": "app.context.menu.favorite.add",
"title": "APP.ACTIONS.FAVORITE", "title": "APP.ACTIONS.FAVORITE",
"order": 500, "order": 500,
"icon": "star_border", "icon": "star_border",
@@ -522,7 +521,7 @@
} }
}, },
{ {
"id": "app.contextmenu.favorite.remove", "id": "app.context.menu.favorite.remove",
"title": "APP.ACTIONS.FAVORITE", "title": "APP.ACTIONS.FAVORITE",
"order": 600, "order": 600,
"icon": "star", "icon": "star",
@@ -534,7 +533,7 @@
} }
}, },
{ {
"id": "app.contextmenu.favorite", "id": "app.context.menu.favorite",
"comment": "workaround for Recent Files and Search API issue", "comment": "workaround for Recent Files and Search API issue",
"type": "custom", "type": "custom",
"order": 501, "order": 501,
@@ -544,7 +543,7 @@
} }
}, },
{ {
"id": "app.contextmenu.copy", "id": "app.context.menu.copy",
"title": "APP.ACTIONS.COPY", "title": "APP.ACTIONS.COPY",
"order": 700, "order": 700,
"icon": "content_copy", "icon": "content_copy",
@@ -556,7 +555,7 @@
} }
}, },
{ {
"id": "app.contextmenu.move", "id": "app.context.menu.move",
"title": "APP.ACTIONS.MOVE", "title": "APP.ACTIONS.MOVE",
"order": 800, "order": 800,
"icon": "library_books", "icon": "library_books",
@@ -568,7 +567,7 @@
} }
}, },
{ {
"id": "app.contextmenu.delete", "id": "app.context.menu.delete",
"title": "APP.ACTIONS.DELETE", "title": "APP.ACTIONS.DELETE",
"order": 900, "order": 900,
"icon": "delete", "icon": "delete",
@@ -580,7 +579,7 @@
} }
}, },
{ {
"id": "app.contextmenu.versions", "id": "app.context.menu.versions",
"title": "APP.ACTIONS.VERSIONS", "title": "APP.ACTIONS.VERSIONS",
"order": 1000, "order": 1000,
"icon": "history", "icon": "history",
@@ -592,7 +591,7 @@
} }
}, },
{ {
"id": "app.contextmenu.permissions", "id": "app.context.menu.permissions",
"title": "APP.ACTIONS.PERMISSIONS", "title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component", "icon": "settings_input_component",
"order": 1100, "order": 1100,
@@ -604,7 +603,7 @@
} }
}, },
{ {
"id": "app.contextmenu.purgeDeletedNodes", "id": "app.context.menu.purgeDeletedNodes",
"order": 1200, "order": 1200,
"title": "APP.ACTIONS.DELETE_PERMANENT", "title": "APP.ACTIONS.DELETE_PERMANENT",
"icon": "delete_forever", "icon": "delete_forever",
@@ -616,7 +615,7 @@
} }
}, },
{ {
"id": "app.contextmenu.restoreDeletedNodes", "id": "app.context.menu.restoreDeletedNodes",
"order": 1300, "order": 1300,
"title": "APP.ACTIONS.RESTORE", "title": "APP.ACTIONS.RESTORE",
"icon": "restore", "icon": "restore",
@@ -627,10 +626,9 @@
"visible": "app.trashcan.hasSelection" "visible": "app.trashcan.hasSelection"
} }
} }
] ],
},
"viewer": { "viewer": {
"actions": [ "toolbar": [
{ {
"id": "app.viewer.favorite.add", "id": "app.viewer.favorite.add",
"order": 100, "order": 100,
+6 -12
View File
@@ -332,8 +332,8 @@
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
}, },
"actions": { "toolbar": {
"description": "Content actions (toolbar, context menus, etc.)", "description": "Toolbar entries",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
@@ -352,18 +352,14 @@
"items": { "$ref": "#/definitions/sidebarTabRef" }, "items": { "$ref": "#/definitions/sidebarTabRef" },
"minItems": 1 "minItems": 1
}, },
"content": { "toolbar": {
"description": "Main application content extensions", "description": "Toolbar entries",
"type": "object",
"properties": {
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
}, },
"contextActions": { "contextMenu": {
"description": "Content actions (toolbar, context menus, etc.)", "description": "Context menu entries",
"type": "array", "type": "array",
"items": { "$ref": "#/definitions/contentActionRef" }, "items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1 "minItems": 1
@@ -372,5 +368,3 @@
} }
} }
} }
}
}
+1 -3
View File
@@ -50,8 +50,7 @@
] ]
} }
], ],
"content": { "toolbar": [
"actions": [
{ {
"disabled": true, "disabled": true,
"id": "app.toolbar.createFolder", "id": "app.toolbar.createFolder",
@@ -124,4 +123,3 @@
] ]
} }
} }
}