mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-31 17:38:28 +00:00
[ACA-1508] extensions: wave 1 (#480)
* initial structure scaffold * core extensions module * simple navbar composition * allow using app routes instead of registered * migrate to new navbar setup * remove commented out tests * populate toolbar * evaluate expressions * redirect to url from toolbar * populate "open with" viewer menu * update test setup * experimental flag for extensions * test fixes * fix tests * code improvements, order support * improve routing management * populate "create" menu * extra dictionaries for spellcheck * allow disabling extension content * support file/folder targets for toolbar actions * add safety check * navigate directly * toolbar actions for all pages * support route data * "experimental" flag for "create" menu extensions * code fixes
This commit is contained in:
@@ -6,6 +6,14 @@
|
||||
<mat-icon [title]="'APP.NEW_MENU.TOOLTIP' | translate">queue</mat-icon>
|
||||
</div>
|
||||
<div sidebar-menu-options>
|
||||
<ng-container *ifExperimental="'extensions'">
|
||||
<button *ngFor="let entry of createActions"
|
||||
mat-menu-item
|
||||
(click)="runAction(entry.action)">
|
||||
<mat-icon>{{ entry.icon }}</mat-icon>
|
||||
<span>{{ entry.title | translate }}</span>
|
||||
</button>
|
||||
</ng-container>
|
||||
<button
|
||||
mat-menu-item
|
||||
[disabled]="!permission.check(node, ['create'])"
|
||||
@@ -48,16 +56,17 @@
|
||||
</adf-sidebar-action-menu>
|
||||
</div>
|
||||
|
||||
<div class="sidenav__section sidenav__section--menu" *ngFor="let list of navigation">
|
||||
<div class="sidenav__section sidenav__section--menu" *ngFor="let group of groups">
|
||||
<ul class="sidenav-menu">
|
||||
<li *ngFor="let item of list" class="sidenav-menu__item"
|
||||
<li *ngFor="let item of group" class="sidenav-menu__item"
|
||||
routerLinkActive
|
||||
#rla="routerLinkActive"
|
||||
title="{{ item.title || '' | translate }}">
|
||||
title="{{ item.description | translate }}">
|
||||
|
||||
<button [routerLink]="item.route.url"
|
||||
<button
|
||||
[routerLink]="item.route"
|
||||
[color]="rla.isActive ? 'accent': 'primary'"
|
||||
[attr.aria-label]="item.label | translate"
|
||||
[attr.aria-label]="item.title | translate"
|
||||
mat-icon-button
|
||||
mat-ripple
|
||||
matRippleColor="primary"
|
||||
@@ -68,13 +77,13 @@
|
||||
</button>
|
||||
|
||||
<span #rippleTrigger
|
||||
[routerLink]="item.route"
|
||||
class="menu__item--label"
|
||||
[routerLink]="item.route.url"
|
||||
[hidden]="!showLabel"
|
||||
[ngClass]="{
|
||||
'menu__item--active': rla.isActive,
|
||||
'menu__item--default': !rla.isActive
|
||||
}">{{ item.label | translate }}</span>
|
||||
}">{{ item.title | translate }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -25,26 +25,17 @@
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
import { BrowsingFilesService } from '../../common/services/browsing-files.service';
|
||||
import { SidenavComponent } from './sidenav.component';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { NodeEffects } from '../../store/effects/node.effects';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
|
||||
describe('SidenavComponent', () => {
|
||||
let fixture: ComponentFixture<SidenavComponent>;
|
||||
let component: SidenavComponent;
|
||||
let browsingService: BrowsingFilesService;
|
||||
let appConfig: AppConfigService;
|
||||
let appConfigSpy;
|
||||
|
||||
const navItem = {
|
||||
label: 'some-label',
|
||||
route: {
|
||||
url: '/some-url'
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@@ -53,19 +44,17 @@ describe('SidenavComponent', () => {
|
||||
EffectsModule.forRoot([NodeEffects])
|
||||
],
|
||||
declarations: [
|
||||
SidenavComponent
|
||||
SidenavComponent,
|
||||
ExperimentalDirective
|
||||
],
|
||||
schemas: [ NO_ERRORS_SCHEMA ]
|
||||
})
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
browsingService = TestBed.get(BrowsingFilesService);
|
||||
appConfig = TestBed.get(AppConfigService);
|
||||
|
||||
fixture = TestBed.createComponent(SidenavComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
appConfigSpy = spyOn(appConfig, 'get').and.returnValue([navItem]);
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -77,20 +66,4 @@ describe('SidenavComponent', () => {
|
||||
|
||||
expect(component.node).toBe(node);
|
||||
});
|
||||
|
||||
describe('menu', () => {
|
||||
it('should build menu from array', () => {
|
||||
appConfigSpy.and.returnValue([navItem, navItem]);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.navigation).toEqual([[navItem, navItem]]);
|
||||
});
|
||||
|
||||
it('should build menu from object', () => {
|
||||
appConfigSpy.and.returnValue({ a: [navItem, navItem], b: [navItem, navItem] });
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.navigation).toEqual([[navItem, navItem], [navItem, navItem]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -26,11 +26,11 @@
|
||||
import { Subscription } from 'rxjs/Rx';
|
||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
|
||||
|
||||
import { BrowsingFilesService } from '../../common/services/browsing-files.service';
|
||||
import { NodePermissionService } from '../../common/services/node-permission.service';
|
||||
import { ExtensionService } from '../../extensions/extension.service';
|
||||
import { NavigationExtension } from '../../extensions/navigation.extension';
|
||||
import { CreateExtension } from '../../extensions/create.extension';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sidenav',
|
||||
@@ -41,22 +41,25 @@ export class SidenavComponent implements OnInit, OnDestroy {
|
||||
@Input() showLabel: boolean;
|
||||
|
||||
node: MinimalNodeEntryEntity = null;
|
||||
navigation = [];
|
||||
groups: Array<NavigationExtension[]> = [];
|
||||
createActions: Array<CreateExtension> = [];
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
constructor(
|
||||
private browsingFilesService: BrowsingFilesService,
|
||||
private appConfig: AppConfigService,
|
||||
public permission: NodePermissionService
|
||||
public permission: NodePermissionService,
|
||||
private extensions: ExtensionService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.navigation = this.buildMenu();
|
||||
this.groups = this.extensions.getNavigationGroups();
|
||||
this.createActions = this.extensions.createActions;
|
||||
|
||||
this.subscriptions.concat([
|
||||
this.browsingFilesService.onChangeParent
|
||||
.subscribe((node: MinimalNodeEntryEntity) => this.node = node)
|
||||
this.browsingFilesService.onChangeParent.subscribe(
|
||||
(node: MinimalNodeEntryEntity) => (this.node = node)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -64,10 +67,9 @@ export class SidenavComponent implements OnInit, OnDestroy {
|
||||
this.subscriptions.forEach(s => s.unsubscribe());
|
||||
}
|
||||
|
||||
private buildMenu() {
|
||||
const schema = this.appConfig.get('navigation');
|
||||
const data = Array.isArray(schema) ? { main: schema } : schema;
|
||||
|
||||
return Object.keys(data).map((key) => data[key]);
|
||||
// this is where each application decides how to treat an action and what to do
|
||||
// the ACA maps actions to the NgRx actions as an example
|
||||
runAction(actionId: string) {
|
||||
this.extensions.runActionById(actionId);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user