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",
"Snackbar",
"devtools",
"gitter",
"jira",
"markdownlint",
"uploader",
"nginx",
"docx",
"SOLR",
"unshare",
"validators",
+5 -3
View File
@@ -1,5 +1,7 @@
# Alfresco Example Content Application
<!-- markdownlint-disable MD033 -->
## Introduction
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:
- 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.
- 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.
@@ -313,7 +315,7 @@ At the bottom of the content the Viewer Controls allow users to interact with th
- Media View:
- Play/pause
- Timeline position
- Audio mute/unmute
- Toggle audio
- Audio volume
- Full screen
@@ -329,7 +331,7 @@ The Properties tab displays the node's metadata info by using the [ContentMetada
![](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
+444 -13
View File
@@ -2,6 +2,8 @@
title: Extending
---
<!-- markdownlint-disable MD033 -->
<p class="danger">
Work is still in progress, the documentation and examples may change.
</p>
@@ -18,6 +20,7 @@ You can create plugins that change, toggle or extend the following areas:
* Navigation sidebar links and groups
* Context Menu
* Sidebar (aka Info Drawer)
* Toolbar entries
* buttons
* menu buttons
@@ -116,9 +119,9 @@ To create a new route, populate the `routes` section with the corresponding entr
| **id** | Unique identifier. |
| **path** | Runtime path of the route. |
| **component** | The main [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" ]`. |
| *data* | Custom property bag to carry with the route. |
| layout | The layout [component](#components) to use for the route. |
| auth | List of [authentication guards](#authentication-guards). Defaults to `[ "app.auth" ]`. |
| data | Custom property bag to carry with the route. |
<p class="tip">
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
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:
- user has selected node(s)
- user is not using **Trashcan** page
- user is not using **Libraries** page
* user has selected node(s)
* user is not using **Trashcan** page
* user is not using **Libraries** page
```json
{
@@ -565,19 +573,443 @@ The rule in the example below evaluates to `true` if all the conditions are met:
## 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
#### 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
@@ -699,7 +1131,6 @@ extensions.setEvaluators({
Now, the `plugin1.rules.hasSelection` evaluator can be used as an inline rule reference,
or part of the composite rule like `core.every`.
<p class="tip">
See [Registration](#registration) section for more details
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",
"label": "Link",
"title": "My custome link",
"title": "My custom link",
"route": {
"url": "/custom-route"
}
+6 -12
View File
@@ -332,8 +332,8 @@
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
},
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"toolbar": {
"description": "Toolbar entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
@@ -352,18 +352,14 @@
"items": { "$ref": "#/definitions/sidebarTabRef" },
"minItems": 1
},
"content": {
"description": "Main application content extensions",
"type": "object",
"properties": {
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"toolbar": {
"description": "Toolbar entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
},
"contextActions": {
"description": "Content actions (toolbar, context menus, etc.)",
"contextMenu": {
"description": "Context menu entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
@@ -372,5 +368,3 @@
}
}
}
}
}
@@ -112,7 +112,7 @@ export class ContextMenuComponent implements OnInit, OnDestroy, AfterViewInit {
.subscribe(selection => {
if (selection.count) {
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>;
sharedPreviewUrl$: Observable<string>;
actions: Array<ContentActionRef> = [];
viewerActions: Array<ContentActionRef> = [];
viewerToolbarActions: Array<ContentActionRef> = [];
canUpdateNode = false;
canUpload = false;
@@ -76,8 +76,8 @@ export abstract class PageComponent implements OnInit, OnDestroy {
.pipe(takeUntil(this.onDestroy$))
.subscribe(selection => {
this.selection = selection;
this.actions = this.extensions.getAllowedContentActions();
this.viewerActions = this.extensions.getViewerActions();
this.actions = this.extensions.getAllowedToolbarActions();
this.viewerToolbarActions = this.extensions.getViewerToolbarActions();
this.canUpdateNode = this.selection.count === 1 && this.content.canUpdateNode(selection.first);
});
@@ -24,7 +24,7 @@
</adf-viewer-open-with>
<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>
</ng-container>
</adf-viewer-more-actions>
+3 -5
View File
@@ -42,13 +42,11 @@ export interface ExtensionConfig {
create?: Array<ContentActionRef>;
viewer?: {
openWith?: Array<ContentActionRef>;
actions?: Array<ContentActionRef>;
toolbar?: Array<ContentActionRef>;
};
navbar?: Array<NavBarGroupRef>;
sidebar?: Array<SidebarTabRef>;
content?: {
actions?: Array<ContentActionRef>;
contextActions?: Array<ContentActionRef>
};
toolbar?: Array<ContentActionRef>;
contextMenu?: Array<ContentActionRef>;
};
}
+6 -10
View File
@@ -290,8 +290,7 @@ describe('ExtensionService', () => {
$name: 'test',
$version: '1.0.0',
features: {
content: {
actions: [
toolbar: [
{
id: 'aca:toolbar/separator-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', () => {
@@ -317,8 +315,7 @@ describe('ExtensionService', () => {
$name: 'test',
$version: '1.0.0',
features: {
content: {
actions: [
toolbar: [
{
id: 'aca:toolbar/separator-2',
order: 2,
@@ -333,14 +330,13 @@ describe('ExtensionService', () => {
}
]
}
}
});
expect(extensions.contentActions.length).toBe(2);
expect(extensions.contentActions[0].id).toBe(
expect(extensions.toolbarActions.length).toBe(2);
expect(extensions.toolbarActions[0].id).toBe(
'aca:toolbar/separator-1'
);
expect(extensions.contentActions[1].id).toBe(
expect(extensions.toolbarActions[1].id).toBe(
'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 { NodePermissionService } from '../services/node-permission.service';
import { SidebarTabRef } from './sidebar.extensions';
import { ProfileResolver } from '../services/profile.resolver';
@Injectable()
export class ExtensionService implements RuleContext {
@@ -53,9 +54,9 @@ export class ExtensionService implements RuleContext {
routes: Array<RouteRef> = [];
actions: Array<ActionRef> = [];
contentActions: Array<ContentActionRef> = [];
viewerActions: Array<ContentActionRef> = [];
contentContextmenuActions: Array<ContentActionRef> = [];
toolbarActions: Array<ContentActionRef> = [];
viewerToolbarActions: Array<ContentActionRef> = [];
contextMenuActions: Array<ContentActionRef> = [];
openWithActions: Array<ContentActionRef> = [];
createActions: Array<ContentActionRef> = [];
navbar: Array<NavBarGroupRef> = [];
@@ -133,9 +134,9 @@ export class ExtensionService implements RuleContext {
this.rules = this.loadRules(config);
this.actions = this.loadActions(config);
this.routes = this.loadRoutes(config);
this.contentActions = this.loadContentActions(config);
this.viewerActions = this.loadViewerActions(config);
this.contentContextmenuActions = this.loadContentContextMenuActions(config);
this.toolbarActions = this.loadToolbarActions(config);
this.viewerToolbarActions = this.loadViewerToolbarActions(config);
this.contextMenuActions = this.loadContextMenuActions(config);
this.openWithActions = this.loadViewerOpenWith(config);
this.createActions = this.loadCreateActions(config);
this.navbar = this.loadNavBar(config);
@@ -168,27 +169,27 @@ export class ExtensionService implements RuleContext {
return [];
}
protected loadContentActions(config: ExtensionConfig) {
if (config && config.features && config.features.content) {
return (config.features.content.actions || [])
protected loadToolbarActions(config: ExtensionConfig) {
if (config && config.features && config.features.toolbar) {
return (config.features.toolbar || [])
.sort(this.sortByOrder)
.map(this.setActionDefaults);
}
return [];
}
protected loadViewerActions(config: ExtensionConfig): Array<ContentActionRef> {
protected loadViewerToolbarActions(config: ExtensionConfig): Array<ContentActionRef> {
if (config && config.features && config.features.viewer) {
return (config.features.viewer.actions || [])
return (config.features.viewer.toolbar || [])
.sort(this.sortByOrder)
.map(this.setActionDefaults);
}
return [];
}
protected loadContentContextMenuActions(config: ExtensionConfig): Array<ContentActionRef> {
if (config && config.features && config.features.content) {
return (config.features.content.contextActions || [])
protected loadContextMenuActions(config: ExtensionConfig): Array<ContentActionRef> {
if (config && config.features && config.features.contextMenu) {
return (config.features.contextMenu || [])
.sort(this.sortByOrder)
.map(this.setActionDefaults);
}
@@ -312,6 +313,7 @@ export class ExtensionService implements RuleContext {
component: this.getComponentById(route.layout || this.defaults.layout),
canActivateChild: guards,
canActivate: guards,
resolve: { profile: ProfileResolver },
children: [
{
path: '',
@@ -342,8 +344,8 @@ export class ExtensionService implements RuleContext {
}
// evaluates content actions for the selection and parent folder node
getAllowedContentActions(): Array<ContentActionRef> {
return this.contentActions
getAllowedToolbarActions(): Array<ContentActionRef> {
return this.toolbarActions
.filter(this.filterEnabled)
.filter(action => this.filterByRules(action))
.map(action => {
@@ -364,14 +366,14 @@ export class ExtensionService implements RuleContext {
.reduce(this.reduceSeparators, []);
}
getViewerActions(): Array<ContentActionRef> {
return this.viewerActions
getViewerToolbarActions(): Array<ContentActionRef> {
return this.viewerToolbarActions
.filter(this.filterEnabled)
.filter(action => this.filterByRules(action));
}
getAllowedContentContextActions(): Array<ContentActionRef> {
return this.contentContextmenuActions
getAllowedContextMenuActions(): Array<ContentActionRef> {
return this.contextMenuActions
.filter(this.filterEnabled)
.filter(action => this.filterByRules(action));
}
+18 -20
View File
@@ -237,8 +237,7 @@
]
}
],
"content": {
"actions": [
"toolbar": [
{
"id": "app.toolbar.preview",
"order": 100,
@@ -460,9 +459,9 @@
]
}
],
"contextActions": [
"contextMenu": [
{
"id": "app.contextmenu.download",
"id": "app.context.menu.download",
"order": 100,
"title": "APP.ACTIONS.DOWNLOAD",
"icon": "get_app",
@@ -474,7 +473,7 @@
}
},
{
"id": "app.contextmenu.preview",
"id": "app.context.menu.preview",
"order": 200,
"title": "APP.ACTIONS.VIEW",
"icon": "open_in_browser",
@@ -486,7 +485,7 @@
}
},
{
"id": "app.contextmenu.editFolder",
"id": "app.context.menu.editFolder",
"order": 300,
"title": "APP.ACTIONS.EDIT",
"icon": "create",
@@ -498,7 +497,7 @@
}
},
{
"id": "app.contextmenu.share",
"id": "app.context.menu.share",
"title": "APP.ACTIONS.SHARE",
"order": 400,
"icon": "share",
@@ -510,7 +509,7 @@
}
},
{
"id": "app.contextmenu.favorite.add",
"id": "app.context.menu.favorite.add",
"title": "APP.ACTIONS.FAVORITE",
"order": 500,
"icon": "star_border",
@@ -522,7 +521,7 @@
}
},
{
"id": "app.contextmenu.favorite.remove",
"id": "app.context.menu.favorite.remove",
"title": "APP.ACTIONS.FAVORITE",
"order": 600,
"icon": "star",
@@ -534,7 +533,7 @@
}
},
{
"id": "app.contextmenu.favorite",
"id": "app.context.menu.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 501,
@@ -544,7 +543,7 @@
}
},
{
"id": "app.contextmenu.copy",
"id": "app.context.menu.copy",
"title": "APP.ACTIONS.COPY",
"order": 700,
"icon": "content_copy",
@@ -556,7 +555,7 @@
}
},
{
"id": "app.contextmenu.move",
"id": "app.context.menu.move",
"title": "APP.ACTIONS.MOVE",
"order": 800,
"icon": "library_books",
@@ -568,7 +567,7 @@
}
},
{
"id": "app.contextmenu.delete",
"id": "app.context.menu.delete",
"title": "APP.ACTIONS.DELETE",
"order": 900,
"icon": "delete",
@@ -580,7 +579,7 @@
}
},
{
"id": "app.contextmenu.versions",
"id": "app.context.menu.versions",
"title": "APP.ACTIONS.VERSIONS",
"order": 1000,
"icon": "history",
@@ -592,7 +591,7 @@
}
},
{
"id": "app.contextmenu.permissions",
"id": "app.context.menu.permissions",
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"order": 1100,
@@ -604,7 +603,7 @@
}
},
{
"id": "app.contextmenu.purgeDeletedNodes",
"id": "app.context.menu.purgeDeletedNodes",
"order": 1200,
"title": "APP.ACTIONS.DELETE_PERMANENT",
"icon": "delete_forever",
@@ -616,7 +615,7 @@
}
},
{
"id": "app.contextmenu.restoreDeletedNodes",
"id": "app.context.menu.restoreDeletedNodes",
"order": 1300,
"title": "APP.ACTIONS.RESTORE",
"icon": "restore",
@@ -627,10 +626,9 @@
"visible": "app.trashcan.hasSelection"
}
}
]
},
],
"viewer": {
"actions": [
"toolbar": [
{
"id": "app.viewer.favorite.add",
"order": 100,
+6 -12
View File
@@ -332,8 +332,8 @@
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
},
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"toolbar": {
"description": "Toolbar entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
@@ -352,18 +352,14 @@
"items": { "$ref": "#/definitions/sidebarTabRef" },
"minItems": 1
},
"content": {
"description": "Main application content extensions",
"type": "object",
"properties": {
"actions": {
"description": "Content actions (toolbar, context menus, etc.)",
"toolbar": {
"description": "Toolbar entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
},
"contextActions": {
"description": "Content actions (toolbar, context menus, etc.)",
"contextMenu": {
"description": "Context menu entries",
"type": "array",
"items": { "$ref": "#/definitions/contentActionRef" },
"minItems": 1
@@ -372,5 +368,3 @@
}
}
}
}
}
+1 -3
View File
@@ -50,8 +50,7 @@
]
}
],
"content": {
"actions": [
"toolbar": [
{
"disabled": true,
"id": "app.toolbar.createFolder",
@@ -124,4 +123,3 @@
]
}
}
}