mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACA-3257] Add actions extension capability to info drawer (#1471)
* info drawer action added * actions added * * improved docs * * added unit test * fixed e2e * * rename actions to toolbar * * minor changes * Update application-features.md Co-authored-by: Eugenio Romano <eromano@users.noreply.github.com>
This commit is contained in:
parent
234b41b917
commit
3b4579c19c
@ -200,6 +200,7 @@ You can provide the following customizations for the Sidebar (aka Info Drawer) c
|
||||
- Add extra tabs with custom components
|
||||
- Disable tabs from the main application or extensions
|
||||
- Replace content or properties of existing tabs
|
||||
- Add toolbar buttons
|
||||
|
||||
```json
|
||||
{
|
||||
@ -208,7 +209,16 @@ You can provide the following customizations for the Sidebar (aka Info Drawer) c
|
||||
"$name": "plugin1",
|
||||
|
||||
"features": {
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"toolbar": [
|
||||
{
|
||||
"id": "app.sidebar.close",
|
||||
"order": 100,
|
||||
"title": "close",
|
||||
"icon": "highlight_off"
|
||||
}
|
||||
],
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -224,9 +234,10 @@ You can provide the following customizations for the Sidebar (aka Info Drawer) c
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The example above renders two tabs:
|
||||
The example above renders two tabs with `close` icon:
|
||||
|
||||
- `Properties` tab that references the `app.components.tabs.metadata` component
|
||||
- `Comments` tab that references the `app.components.tabs.comments` component
|
||||
|
@ -209,7 +209,8 @@ export interface NavBarLinkRef {
|
||||
"$name": "plugin1",
|
||||
|
||||
"features": {
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -225,6 +226,7 @@ export interface NavBarLinkRef {
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上記の例は2つのタブをレンダリングします:
|
||||
|
@ -903,7 +903,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -923,7 +924,8 @@
|
||||
"title": "APP.INFO_DRAWER.TABS.VERSIONS",
|
||||
"component": "app.components.tabs.versions"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -821,7 +821,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -841,7 +842,8 @@
|
||||
"title": "APP.INFO_DRAWER.TABS.VERSIONS",
|
||||
"component": "app.components.tabs.versions"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -806,7 +806,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -829,3 +830,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +842,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -862,7 +863,8 @@
|
||||
"title": "APP.INFO_DRAWER.TABS.VERSIONS",
|
||||
"component": "app.components.tabs.versions"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -1220,7 +1220,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 1,
|
||||
@ -1247,7 +1248,8 @@
|
||||
"title": "APP.INFO_DRAWER.TABS.COMMENTS",
|
||||
"component": "app.components.tabs.comments"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -841,7 +841,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -861,7 +862,8 @@
|
||||
"title": "APP.INFO_DRAWER.TABS.VERSIONS",
|
||||
"component": "app.components.tabs.versions"
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -1244,7 +1244,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -1282,7 +1283,8 @@
|
||||
"visible": "app.libraries.toolbar"
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
@ -803,9 +803,20 @@
|
||||
},
|
||||
"sidebar": {
|
||||
"description": "Sidebar extensions",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"toolbar": {
|
||||
"description": "Toolbar entries",
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/contentActionRef" }
|
||||
},
|
||||
"tabs": {
|
||||
"description": "Tabs entries",
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/sidebarTabRef" },
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"description": "Toolbar entries",
|
||||
|
@ -7,6 +7,12 @@
|
||||
cdkTrapFocus
|
||||
cdkTrapFocusAutoCapture
|
||||
>
|
||||
<adf-toolbar class="adf-toolbar--inline" info-drawer-buttons>
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
</ng-container>
|
||||
</adf-toolbar>
|
||||
|
||||
<adf-info-drawer-tab
|
||||
*ngFor="let tab of tabs"
|
||||
[icon]="tab.icon"
|
||||
|
@ -22,18 +22,20 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { InfoDrawerComponent } from './info-drawer.component';
|
||||
import { TestBed, ComponentFixture, async } from '@angular/core/testing';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
SetInfoDrawerStateAction,
|
||||
ToggleInfoDrawerAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { of, Subject } from 'rxjs';
|
||||
import { InfoDrawerComponent } from './info-drawer.component';
|
||||
import { LibTestingModule } from '../../testing/lib-testing-module';
|
||||
import { AppExtensionService } from '../../services/app.extension.service';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { of } from 'rxjs';
|
||||
import { SharedToolbarModule } from '../tool-bar/shared-toolbar.module';
|
||||
|
||||
describe('InfoDrawerComponent', () => {
|
||||
let fixture: ComponentFixture<InfoDrawerComponent>;
|
||||
@ -41,16 +43,26 @@ describe('InfoDrawerComponent', () => {
|
||||
let contentApiService: ContentApiService;
|
||||
let tab;
|
||||
let appExtensionService: AppExtensionService;
|
||||
const mockStream = new Subject();
|
||||
const storeMock = {
|
||||
dispatch: jasmine.createSpy('dispatch')
|
||||
dispatch: jasmine.createSpy('dispatch'),
|
||||
select: () => mockStream
|
||||
};
|
||||
const extensionServiceMock = {
|
||||
getSidebarTabs: () => {}
|
||||
getSidebarTabs: () => {},
|
||||
getAllowedSidebarActions: () => [
|
||||
{
|
||||
id: 'app.sidebar.close',
|
||||
order: 100,
|
||||
title: 'close',
|
||||
icon: 'highlight_off'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [LibTestingModule],
|
||||
imports: [LibTestingModule, SharedToolbarModule],
|
||||
declarations: [InfoDrawerComponent],
|
||||
providers: [
|
||||
ContentApiService,
|
||||
@ -166,4 +178,17 @@ describe('InfoDrawerComponent', () => {
|
||||
new ToggleInfoDrawerAction()
|
||||
);
|
||||
});
|
||||
|
||||
it('should show the icons from extension', () => {
|
||||
fixture.detectChanges();
|
||||
mockStream.next();
|
||||
expect(component.actions).toEqual([
|
||||
{
|
||||
id: 'app.sidebar.close',
|
||||
order: 100,
|
||||
title: 'close',
|
||||
icon: 'highlight_off'
|
||||
} as ContentActionRef
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -36,14 +36,17 @@ import {
|
||||
MinimalNodeEntryEntity,
|
||||
SiteEntry
|
||||
} from '@alfresco/js-api';
|
||||
import { SidebarTabRef } from '@alfresco/adf-extensions';
|
||||
import { ContentActionRef, SidebarTabRef } from '@alfresco/adf-extensions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
getAppSelection,
|
||||
SetInfoDrawerStateAction,
|
||||
ToggleInfoDrawerAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { AppExtensionService } from '../../services/app.extension.service';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-info-drawer',
|
||||
@ -58,6 +61,8 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
isLoading = false;
|
||||
displayNode: MinimalNodeEntryEntity | SiteEntry;
|
||||
tabs: Array<SidebarTabRef> = [];
|
||||
actions: Array<ContentActionRef> = [];
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@HostListener('keydown.escape')
|
||||
onEscapeKeyboardEvent(): void {
|
||||
@ -72,9 +77,17 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.tabs = this.extensions.getSidebarTabs();
|
||||
this.store
|
||||
.select(getAppSelection)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.actions = this.extensions.getAllowedSidebarActions();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
this.store.dispatch(new SetInfoDrawerStateAction(false));
|
||||
}
|
||||
|
||||
@ -91,6 +104,10 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
trackByActionId(_: number, action: ContentActionRef) {
|
||||
return action.id;
|
||||
}
|
||||
|
||||
private close() {
|
||||
this.store.dispatch(new ToggleInfoDrawerAction());
|
||||
}
|
||||
|
@ -26,16 +26,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { InfoDrawerComponent } from './info-drawer.component';
|
||||
import { InfoDrawerModule } from '@alfresco/adf-core';
|
||||
import { InfoDrawerModule, ToolbarModule } from '@alfresco/adf-core';
|
||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||
import { MatProgressBarModule } from '@angular/material';
|
||||
import { SharedToolbarModule } from '../tool-bar/shared-toolbar.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
InfoDrawerModule,
|
||||
MatProgressBarModule,
|
||||
ExtensionsModule
|
||||
ExtensionsModule,
|
||||
ToolbarModule,
|
||||
SharedToolbarModule
|
||||
],
|
||||
declarations: [InfoDrawerComponent],
|
||||
exports: [InfoDrawerComponent]
|
||||
|
@ -83,7 +83,8 @@ export class AppExtensionService implements RuleContext {
|
||||
openWithActions: Array<ContentActionRef> = [];
|
||||
createActions: Array<ContentActionRef> = [];
|
||||
navbar: Array<NavBarGroupRef> = [];
|
||||
sidebar: Array<SidebarTabRef> = [];
|
||||
sidebarTabs: Array<SidebarTabRef> = [];
|
||||
sidebarActions: Array<ContentActionRef> = [];
|
||||
contentMetadata: any;
|
||||
viewerRules: ViewerRules = {};
|
||||
userActions: Array<ContentActionRef> = [];
|
||||
@ -163,6 +164,10 @@ export class AppExtensionService implements RuleContext {
|
||||
config,
|
||||
'features.header'
|
||||
);
|
||||
this.sidebarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.sidebar.toolbar'
|
||||
);
|
||||
this.toolbarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.toolbar'
|
||||
@ -189,9 +194,9 @@ export class AppExtensionService implements RuleContext {
|
||||
'features.create'
|
||||
);
|
||||
this.navbar = this.loadNavBar(config);
|
||||
this.sidebar = this.loader.getElements<SidebarTabRef>(
|
||||
this.sidebarTabs = this.loader.getElements<SidebarTabRef>(
|
||||
config,
|
||||
'features.sidebar'
|
||||
'features.sidebar.tabs'
|
||||
);
|
||||
this.userActions = this.loader.getContentActions(
|
||||
config,
|
||||
@ -382,7 +387,7 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
getSidebarTabs(): Array<SidebarTabRef> {
|
||||
return this.sidebar.filter(action => this.filterVisible(action));
|
||||
return this.sidebarTabs.filter(action => this.filterVisible(action));
|
||||
}
|
||||
|
||||
getComponentById(id: string): Type<{}> {
|
||||
@ -486,6 +491,10 @@ export class AppExtensionService implements RuleContext {
|
||||
.reduce(reduceSeparators, []);
|
||||
}
|
||||
|
||||
getAllowedSidebarActions(): Array<ContentActionRef> {
|
||||
return this.getAllowedActions(this.sidebarActions);
|
||||
}
|
||||
|
||||
getAllowedToolbarActions(): Array<ContentActionRef> {
|
||||
return this.getAllowedActions(this.toolbarActions);
|
||||
}
|
||||
|
@ -1007,7 +1007,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"sidebar": [
|
||||
"sidebar": {
|
||||
"tabs": [
|
||||
{
|
||||
"id": "app.sidebar.properties",
|
||||
"order": 100,
|
||||
@ -1045,7 +1046,8 @@
|
||||
"visible": "app.selection.library"
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
"content-metadata-presets": [
|
||||
{
|
||||
"id": "app.content.metadata.custom",
|
||||
|
Loading…
x
Reference in New Issue
Block a user