mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-09-17 14:21:14 +00:00
[ACA-2064] support custom icons for extensions (#864)
* icon component, custom svg * split components, fix modules * simplify code * universal icon component * support custom icon registration * update docs * test fixes
This commit is contained in:
@@ -24,6 +24,7 @@ You can create plugins that change, toggle, or extend the following areas:
|
|||||||
- buttons
|
- buttons
|
||||||
- "More actions" buttons
|
- "More actions" buttons
|
||||||
- Content metadata presets (used on `Properties` tab)
|
- Content metadata presets (used on `Properties` tab)
|
||||||
|
- Custom icons
|
||||||
|
|
||||||
Extensions can also:
|
Extensions can also:
|
||||||
|
|
||||||
|
42
docs/extending/icons.md
Normal file
42
docs/extending/icons.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Custom Icons
|
||||||
|
|
||||||
|
You can register and use custom `.svg` icons with toolbars, context menus, etc.
|
||||||
|
|
||||||
|
The icons are declared in the `features.icons` section, for example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"id": "adf:join_library",
|
||||||
|
"value": "./assets/images/join-library.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "adf:move_file",
|
||||||
|
"value": "./assets/images/adf-move-file-24px.svg"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `id` value must conform to the format `[namespace]:[name]`,
|
||||||
|
similar to that of the [Material Icon](https://material.angular.io/components/icon/api) component.
|
||||||
|
The icon file path should be relative to the deployed application root (or `index.html` file);
|
||||||
|
|
||||||
|
After that, you can use the icon id with other elements, for example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "app.toolbar.move",
|
||||||
|
"order": 500,
|
||||||
|
"title": "APP.ACTIONS.MOVE",
|
||||||
|
"icon": "adf:move_file",
|
||||||
|
"actions": {
|
||||||
|
"click": "MOVE_NODES"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It is also possible to override the icon value or disable the entry from within external extensions.
|
65
docs/toc.md
65
docs/toc.md
@@ -1,38 +1,39 @@
|
|||||||
- [Home](/)
|
- [Home](/)
|
||||||
- [Documentation](/#documentation)
|
- [Documentation](/#documentation)
|
||||||
- [How to contribute](/#how-to-contribute)
|
- [How to contribute](/#how-to-contribute)
|
||||||
- [App features](/features/)
|
- [App features](/features/)
|
||||||
- [User interface layout](/features/user-interface-layout)
|
- [User interface layout](/features/user-interface-layout)
|
||||||
- [Header](/features/header)
|
- [Header](/features/header)
|
||||||
- [Side navigation](/features/side-navigation)
|
- [Side navigation](/features/side-navigation)
|
||||||
- [Document List Layout](/features/document-list-layout)
|
- [Document List Layout](/features/document-list-layout)
|
||||||
- [File Viewer](/features/file-viewer)
|
- [File Viewer](/features/file-viewer)
|
||||||
- [Info Drawer](/features/info-drawer)
|
- [Info Drawer](/features/info-drawer)
|
||||||
- [Version Manager](/features/version-manager)
|
- [Version Manager](/features/version-manager)
|
||||||
- [Search results](/features/search-results)
|
- [Search results](/features/search-results)
|
||||||
- [Getting started](/getting-started/)
|
- [Getting started](/getting-started/)
|
||||||
- [Prerequisites](/getting-started/prerequisites)
|
- [Prerequisites](/getting-started/prerequisites)
|
||||||
- [Building from source](/getting-started/building-from-source)
|
- [Building from source](/getting-started/building-from-source)
|
||||||
- [Internationalization (i18n)](/getting-started/internationalization)
|
- [Internationalization (i18n)](/getting-started/internationalization)
|
||||||
- [CORS](/getting-started/cors)
|
- [CORS](/getting-started/cors)
|
||||||
- [Configuration](/getting-started/configuration)
|
- [Configuration](/getting-started/configuration)
|
||||||
- [Navigation](/getting-started/navigation)
|
- [Navigation](/getting-started/navigation)
|
||||||
- [Docker](/getting-started/docker)
|
- [Docker](/getting-started/docker)
|
||||||
- [Extending](/extending/)
|
- [Extending](/extending/)
|
||||||
- [Extensibility features](/extending/extensibility-features)
|
- [Extensibility features](/extending/extensibility-features)
|
||||||
- [Extension format](/extending/extension-format)
|
- [Extension format](/extending/extension-format)
|
||||||
- [Routes](/extending/routes)
|
- [Routes](/extending/routes)
|
||||||
- [Components](/extending/components)
|
- [Components](/extending/components)
|
||||||
- [Actions](/extending/actions)
|
- [Actions](/extending/actions)
|
||||||
- [Application actions](/extending/application-actions)
|
- [Application actions](/extending/application-actions)
|
||||||
- [Rules](/extending/rules)
|
- [Rules](/extending/rules)
|
||||||
- [Application features](/extending/application-features)
|
- [Application features](/extending/application-features)
|
||||||
- [Registration](/extending/registration)
|
- [Custom icons](/extending/icons)
|
||||||
- [Creating custom evaluators](/extending/creating-custom-evaluators)
|
- [Registration](/extending/registration)
|
||||||
- [Tutorials](/extending/tutorials)
|
- [Creating custom evaluators](/extending/creating-custom-evaluators)
|
||||||
- [Redistributable libraries](/extending/redistributable-libraries)
|
- [Tutorials](/extending/tutorials)
|
||||||
|
- [Redistributable libraries](/extending/redistributable-libraries)
|
||||||
- [Tutorials](/tutorials/)
|
- [Tutorials](/tutorials/)
|
||||||
- [Introduction to extending ACA](/tutorials/introduction-to-extending)
|
- [Introduction to extending ACA](/tutorials/introduction-to-extending)
|
||||||
- [Custom route with parameters](/tutorials/custom-route-with-parameters)
|
- [Custom route with parameters](/tutorials/custom-route-with-parameters)
|
||||||
- [Dialog actions](/tutorials/dialog-actions)
|
- [Dialog actions](/tutorials/dialog-actions)
|
||||||
- [Get help](/help)
|
- [Get help](/help)
|
||||||
|
@@ -563,6 +563,24 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"iconRef": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "value"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Unique identifier. Must be in the format '[namespace]:[name]'.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"description": "Icon path relative to the application root.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"description": "Toggles the disabled state",
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -628,6 +646,12 @@
|
|||||||
"description": "Application-specific features and extensions",
|
"description": "Application-specific features and extensions",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"icons": {
|
||||||
|
"description": "Custom icons",
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/iconRef" },
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"description": "Application header extensions",
|
"description": "Application header extensions",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@@ -73,10 +73,6 @@ import { AppSearchResultsModule } from './components/search/search-results.modul
|
|||||||
import { AppLoginModule } from './components/login/login.module';
|
import { AppLoginModule } from './components/login/login.module';
|
||||||
import { AppHeaderModule } from './components/header/header.module';
|
import { AppHeaderModule } from './components/header/header.module';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { LibraryMembershipDirective } from './directives/library-membership.directive';
|
|
||||||
import { ToggleJoinLibraryComponent } from './components/toolbar/toggle-join-library/toggle-join-library.component';
|
|
||||||
import { LibraryFavoriteDirective } from './directives/library-favorite.directive';
|
|
||||||
import { ToggleFavoriteLibraryComponent } from './components/toolbar/toggle-favorite-library/toggle-favorite-library.component';
|
|
||||||
import { AppDataService } from './services/data.service';
|
import { AppDataService } from './services/data.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -118,11 +114,7 @@ import { AppDataService } from './services/data.service';
|
|||||||
LibrariesComponent,
|
LibrariesComponent,
|
||||||
FavoriteLibrariesComponent,
|
FavoriteLibrariesComponent,
|
||||||
NodeVersionsDialogComponent,
|
NodeVersionsDialogComponent,
|
||||||
LibraryDialogComponent,
|
LibraryDialogComponent
|
||||||
LibraryMembershipDirective,
|
|
||||||
ToggleJoinLibraryComponent,
|
|
||||||
LibraryFavoriteDirective,
|
|
||||||
ToggleFavoriteLibraryComponent
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: RouteReuseStrategy, useClass: AppRouteReuseStrategy },
|
{ provide: RouteReuseStrategy, useClass: AppRouteReuseStrategy },
|
||||||
@@ -137,12 +129,7 @@ import { AppDataService } from './services/data.service';
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [LibraryDialogComponent, NodeVersionsDialogComponent],
|
||||||
LibraryDialogComponent,
|
|
||||||
NodeVersionsDialogComponent,
|
|
||||||
ToggleJoinLibraryComponent,
|
|
||||||
ToggleFavoriteLibraryComponent
|
|
||||||
],
|
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@@ -34,9 +34,11 @@ import { LibraryStatusColumnComponent } from './library-status-column/library-st
|
|||||||
import { LibraryRoleColumnComponent } from './library-role-column/library-role-column.component';
|
import { LibraryRoleColumnComponent } from './library-role-column/library-role-column.component';
|
||||||
import { TrashcanNameColumnComponent } from './trashcan-name-column/trashcan-name-column.component';
|
import { TrashcanNameColumnComponent } from './trashcan-name-column/trashcan-name-column.component';
|
||||||
import { DynamicColumnComponent } from './dynamic-column/dynamic-column.component';
|
import { DynamicColumnComponent } from './dynamic-column/dynamic-column.component';
|
||||||
|
import { IconComponent } from './icon/icon.component';
|
||||||
|
import { MatIconModule } from '@angular/material';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, CoreModule.forChild()],
|
imports: [CommonModule, CoreModule.forChild(), MatIconModule],
|
||||||
declarations: [
|
declarations: [
|
||||||
GenericErrorComponent,
|
GenericErrorComponent,
|
||||||
LocationLinkComponent,
|
LocationLinkComponent,
|
||||||
@@ -45,7 +47,8 @@ import { DynamicColumnComponent } from './dynamic-column/dynamic-column.componen
|
|||||||
LibraryStatusColumnComponent,
|
LibraryStatusColumnComponent,
|
||||||
LibraryRoleColumnComponent,
|
LibraryRoleColumnComponent,
|
||||||
TrashcanNameColumnComponent,
|
TrashcanNameColumnComponent,
|
||||||
DynamicColumnComponent
|
DynamicColumnComponent,
|
||||||
|
IconComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
GenericErrorComponent,
|
GenericErrorComponent,
|
||||||
@@ -55,7 +58,8 @@ import { DynamicColumnComponent } from './dynamic-column/dynamic-column.componen
|
|||||||
LibraryStatusColumnComponent,
|
LibraryStatusColumnComponent,
|
||||||
LibraryRoleColumnComponent,
|
LibraryRoleColumnComponent,
|
||||||
TrashcanNameColumnComponent,
|
TrashcanNameColumnComponent,
|
||||||
DynamicColumnComponent
|
DynamicColumnComponent,
|
||||||
|
IconComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
LocationLinkComponent,
|
LocationLinkComponent,
|
||||||
|
7
src/app/components/common/icon/icon.component.html
Normal file
7
src/app/components/common/icon/icon.component.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<ng-container *ngIf="isCustom; else: default">
|
||||||
|
<mat-icon [svgIcon]="value"></mat-icon>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-template #default>
|
||||||
|
<mat-icon>{{ value }}</mat-icon>
|
||||||
|
</ng-template>
|
4
src/app/components/common/icon/icon.component.scss
Normal file
4
src/app/components/common/icon/icon.component.scss
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.adf-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
58
src/app/components/common/icon/icon.component.ts
Normal file
58
src/app/components/common/icon/icon.component.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Alfresco Example Content Application
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||||
|
*
|
||||||
|
* This file is part of the Alfresco Example Content Application.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 {
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
ViewEncapsulation,
|
||||||
|
ChangeDetectionStrategy
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-icon',
|
||||||
|
templateUrl: './icon.component.html',
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
host: { class: 'adf-icon' },
|
||||||
|
styleUrls: ['./icon.component.scss']
|
||||||
|
})
|
||||||
|
export class IconComponent {
|
||||||
|
private _value = '';
|
||||||
|
private _isCustom = false;
|
||||||
|
|
||||||
|
get value(): string {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set value(value: string) {
|
||||||
|
this._value = value || 'settings';
|
||||||
|
this._isCustom = this._value.includes(':');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isCustom(): boolean {
|
||||||
|
return this._isCustom;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,39 +1,38 @@
|
|||||||
<div class="aca-context-menu">
|
<div class="aca-context-menu">
|
||||||
<ng-container [ngSwitch]="actionRef.type">
|
<ng-container [ngSwitch]="actionRef.type">
|
||||||
|
<ng-container *ngSwitchCase="'menu'">
|
||||||
|
<button mat-menu-item [id]="actionRef.id" [matMenuTriggerFor]="childMenu">
|
||||||
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
|
<span>{{ actionRef.title | translate }}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'menu'">
|
<mat-menu #childMenu="matMenu">
|
||||||
<button
|
<ng-container
|
||||||
mat-menu-item
|
*ngFor="let child of actionRef.children; trackBy: trackById"
|
||||||
[id]="actionRef.id"
|
>
|
||||||
[matMenuTriggerFor]="childMenu">
|
<app-context-menu-item [actionRef]="child"></app-context-menu-item>
|
||||||
<mat-icon color="primary">{{ actionRef.icon }}</mat-icon>
|
|
||||||
<span>{{ actionRef.title | translate }}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<mat-menu #childMenu="matMenu">
|
|
||||||
<ng-container *ngFor="let child of actionRef.children; trackBy: trackById">
|
|
||||||
<app-context-menu-item [actionRef]="child"></app-context-menu-item>
|
|
||||||
</ng-container>
|
|
||||||
</mat-menu>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'separator'">
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'custom'">
|
|
||||||
<adf-dynamic-component [id]="actionRef.component"></adf-dynamic-component>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
|
|
||||||
<ng-container *ngSwitchDefault>
|
|
||||||
<button mat-menu-item
|
|
||||||
color="primary"
|
|
||||||
[id]="actionRef.id"
|
|
||||||
(click)="runAction()">
|
|
||||||
<mat-icon color="primary">{{ actionRef.icon }}</mat-icon>
|
|
||||||
<span>{{ actionRef.title | translate }}</span>
|
|
||||||
</button>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</mat-menu>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'separator'">
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'custom'">
|
||||||
|
<adf-dynamic-component [id]="actionRef.component"></adf-dynamic-component>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchDefault>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
color="primary"
|
||||||
|
[id]="actionRef.id"
|
||||||
|
(click)="runAction()"
|
||||||
|
>
|
||||||
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
|
<span>{{ actionRef.title | translate }}</span>
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
@@ -75,7 +75,9 @@ describe('ContextMenuComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const buttonElement = fixture.nativeElement.querySelector('button');
|
const buttonElement = fixture.nativeElement.querySelector('button');
|
||||||
expect(buttonElement.innerText.trim()).toBe(contextItem.title);
|
expect(buttonElement.querySelector('span').innerText.trim()).toBe(
|
||||||
|
contextItem.title
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not run action when entry has no click attribute defined', () => {
|
it('should not run action when entry has no click attribute defined', () => {
|
||||||
|
@@ -1,41 +1,50 @@
|
|||||||
<button style="visibility: hidden" [matMenuTriggerFor]="rootMenu" #rootTriggerEl></button>
|
<button
|
||||||
|
style="visibility: hidden"
|
||||||
|
[matMenuTriggerFor]="rootMenu"
|
||||||
|
#rootTriggerEl
|
||||||
|
></button>
|
||||||
|
|
||||||
<mat-menu #rootMenu="matMenu"
|
<mat-menu
|
||||||
class="aca-context-menu"
|
#rootMenu="matMenu"
|
||||||
hasBackdrop="false"
|
class="aca-context-menu"
|
||||||
acaContextMenuOutsideEvent
|
hasBackdrop="false"
|
||||||
(clickOutside)="onClickOutsideEvent()">
|
acaContextMenuOutsideEvent
|
||||||
<ng-container *ngFor="let entry of actions; trackBy: trackById" [ngSwitch]="entry.type">
|
(clickOutside)="onClickOutsideEvent()"
|
||||||
<ng-container *ngSwitchDefault>
|
>
|
||||||
<button mat-menu-item
|
<ng-container
|
||||||
[id]="entry.id"
|
*ngFor="let entry of actions; trackBy: trackById"
|
||||||
(click)="runAction(entry.actions.click)">
|
[ngSwitch]="entry.type"
|
||||||
<mat-icon color="primary">{{ entry.icon }}</mat-icon>
|
>
|
||||||
<span>{{ entry.title | translate }}</span>
|
<ng-container *ngSwitchDefault>
|
||||||
</button>
|
<button
|
||||||
</ng-container>
|
mat-menu-item
|
||||||
|
[id]="entry.id"
|
||||||
<ng-container *ngSwitchCase="'separator'">
|
(click)="runAction(entry.actions.click)"
|
||||||
<mat-divider></mat-divider>
|
>
|
||||||
</ng-container>
|
<adf-icon [value]="entry.icon"></adf-icon>
|
||||||
|
<span>{{ entry.title | translate }}</span>
|
||||||
<ng-container *ngSwitchCase="'menu'">
|
</button>
|
||||||
<button mat-menu-item
|
|
||||||
[id]="entry.id"
|
|
||||||
[matMenuTriggerFor]="childMenu">
|
|
||||||
<mat-icon color="primary">{{ entry.icon }}</mat-icon>
|
|
||||||
<span>{{ entry.title | translate }}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<mat-menu #childMenu="matMenu">
|
|
||||||
<ng-container *ngFor="let child of entry.children; trackBy: trackById">
|
|
||||||
<app-context-menu-item [actionRef]="child"></app-context-menu-item>
|
|
||||||
</ng-container>
|
|
||||||
</mat-menu>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'custom'">
|
|
||||||
<adf-dynamic-component [id]="entry.component"></adf-dynamic-component>
|
|
||||||
</ng-container>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'separator'">
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'menu'">
|
||||||
|
<button mat-menu-item [id]="entry.id" [matMenuTriggerFor]="childMenu">
|
||||||
|
<adf-icon [value]="entry.icon"></adf-icon>
|
||||||
|
<span>{{ entry.title | translate }}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<mat-menu #childMenu="matMenu">
|
||||||
|
<ng-container *ngFor="let child of entry.children; trackBy: trackById">
|
||||||
|
<app-context-menu-item [actionRef]="child"></app-context-menu-item>
|
||||||
|
</ng-container>
|
||||||
|
</mat-menu>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'custom'">
|
||||||
|
<adf-dynamic-component [id]="entry.component"></adf-dynamic-component>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
@@ -111,7 +111,9 @@ describe('ContextMenuComponent', () => {
|
|||||||
.querySelectorAll('button');
|
.querySelectorAll('button');
|
||||||
|
|
||||||
expect(contextMenuElements.length).toBe(1);
|
expect(contextMenuElements.length).toBe(1);
|
||||||
expect(contextMenuElements[0].innerText).toBe(contextItem.title);
|
expect(contextMenuElements[0].querySelector('span').innerText).toBe(
|
||||||
|
contextItem.title
|
||||||
|
);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should run action with provided action id', fakeAsync(() => {
|
it('should run action with provided action id', fakeAsync(() => {
|
||||||
|
@@ -38,6 +38,7 @@ import { ContextMenuComponent } from './context-menu.component';
|
|||||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
import { OutsideEventDirective } from './context-menu-outside-event.directive';
|
import { OutsideEventDirective } from './context-menu-outside-event.directive';
|
||||||
import { ContextMenuItemComponent } from './context-menu-item.component';
|
import { ContextMenuItemComponent } from './context-menu-item.component';
|
||||||
|
import { AppCommonModule } from '../common/common.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -47,6 +48,7 @@ import { ContextMenuItemComponent } from './context-menu-item.component';
|
|||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
CoreExtensionsModule.forChild(),
|
CoreExtensionsModule.forChild(),
|
||||||
CoreModule.forChild(),
|
CoreModule.forChild(),
|
||||||
|
AppCommonModule,
|
||||||
ExtensionsModule
|
ExtensionsModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@@ -44,8 +44,6 @@ import { currentFolder } from '../../../store/selectors/app.selectors';
|
|||||||
import { AppStore } from '../../../store/states';
|
import { AppStore } from '../../../store/states';
|
||||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||||
import { SetSelectedNodesAction } from '../../../store/actions';
|
import { SetSelectedNodesAction } from '../../../store/actions';
|
||||||
import { MatIconRegistry } from '@angular/material';
|
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layout',
|
selector: 'app-layout',
|
||||||
@@ -70,25 +68,14 @@ export class AppLayoutComponent implements OnInit, OnDestroy {
|
|||||||
private minimizeConditions: string[] = ['search'];
|
private minimizeConditions: string[] = ['search'];
|
||||||
private hideConditions: string[] = ['preview'];
|
private hideConditions: string[] = ['preview'];
|
||||||
|
|
||||||
customIcon: any = {
|
|
||||||
join_library: './assets/images/join-library.svg'
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected store: Store<AppStore>,
|
protected store: Store<AppStore>,
|
||||||
private permission: NodePermissionService,
|
private permission: NodePermissionService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private userPreferenceService: UserPreferencesService,
|
private userPreferenceService: UserPreferencesService,
|
||||||
private appConfigService: AppConfigService,
|
private appConfigService: AppConfigService,
|
||||||
private breakpointObserver: BreakpointObserver,
|
private breakpointObserver: BreakpointObserver
|
||||||
matIconRegistry: MatIconRegistry,
|
) {}
|
||||||
sanitizer: DomSanitizer
|
|
||||||
) {
|
|
||||||
matIconRegistry.addSvgIcon(
|
|
||||||
'join_library',
|
|
||||||
sanitizer.bypassSecurityTrustResourceUrl(this.customIcon['join_library'])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.isSmallScreen$ = this.breakpointObserver
|
this.isSmallScreen$ = this.breakpointObserver
|
||||||
|
@@ -37,10 +37,11 @@ import {
|
|||||||
import { SetSelectedNodesAction } from '../../../store/actions/node.actions';
|
import { SetSelectedNodesAction } from '../../../store/actions/node.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-toggle-join-library',
|
selector: 'app-toggle-join-library-button',
|
||||||
template: `
|
template: `
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-icon-button
|
||||||
|
color="primary"
|
||||||
#membership="libraryMembership"
|
#membership="libraryMembership"
|
||||||
(toggle)="onToggleEvent($event)"
|
(toggle)="onToggleEvent($event)"
|
||||||
(error)="onErrorEvent($event)"
|
(error)="onErrorEvent($event)"
|
||||||
@@ -54,36 +55,14 @@ import { SetSelectedNodesAction } from '../../../store/actions/node.actions';
|
|||||||
<mat-icon *ngIf="(membership.isJoinRequested | async)">cancel</mat-icon>
|
<mat-icon *ngIf="(membership.isJoinRequested | async)">cancel</mat-icon>
|
||||||
<mat-icon
|
<mat-icon
|
||||||
*ngIf="!(membership.isJoinRequested | async)"
|
*ngIf="!(membership.isJoinRequested | async)"
|
||||||
svgIcon="join_library"
|
svgIcon="adf:join_library"
|
||||||
style="pointer-events: none;"
|
|
||||||
></mat-icon>
|
></mat-icon>
|
||||||
<span class="sideLabel">{{
|
|
||||||
(membership.isJoinRequested | async)
|
|
||||||
? ('APP.ACTIONS.CANCEL_JOIN' | translate)
|
|
||||||
: ('APP.ACTIONS.JOIN' | translate)
|
|
||||||
}}</span>
|
|
||||||
</button>
|
</button>
|
||||||
`,
|
`,
|
||||||
styles: [
|
|
||||||
`
|
|
||||||
aca-toolbar-action .app-toggle-join-library .sideLabel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
aca-toolbar-action .app-toggle-join-library .mat-menu-item mat-icon {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-toolbar .app-toggle-join-library .mat-menu-item:hover {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
],
|
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'app-toggle-join-library' }
|
host: { class: 'app-toggle-join-library' }
|
||||||
})
|
})
|
||||||
export class ToggleJoinLibraryComponent {
|
export class ToggleJoinLibraryButtonComponent {
|
||||||
selection$: Observable<SelectionState>;
|
selection$: Observable<SelectionState>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
@@ -0,0 +1,66 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Alfresco Example Content Application
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||||
|
*
|
||||||
|
* This file is part of the Alfresco Example Content Application.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 { Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppStore } from '../../../store/states';
|
||||||
|
import { ContentManagementService } from '../../../services/content-management.service';
|
||||||
|
import { ToggleJoinLibraryButtonComponent } from './toggle-join-library-button.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-toggle-join-library-menu',
|
||||||
|
template: `
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
#membership="libraryMembership"
|
||||||
|
(toggle)="onToggleEvent($event)"
|
||||||
|
(error)="onErrorEvent($event)"
|
||||||
|
[acaLibraryMembership]="(selection$ | async).library"
|
||||||
|
[attr.title]="
|
||||||
|
(membership.isJoinRequested | async)
|
||||||
|
? ('APP.ACTIONS.CANCEL_JOIN' | translate)
|
||||||
|
: ('APP.ACTIONS.JOIN' | translate)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<mat-icon *ngIf="(membership.isJoinRequested | async)">cancel</mat-icon>
|
||||||
|
<mat-icon
|
||||||
|
*ngIf="!(membership.isJoinRequested | async)"
|
||||||
|
svgIcon="adf:join_library"
|
||||||
|
></mat-icon>
|
||||||
|
<span>{{
|
||||||
|
(membership.isJoinRequested | async)
|
||||||
|
? ('APP.ACTIONS.CANCEL_JOIN' | translate)
|
||||||
|
: ('APP.ACTIONS.JOIN' | translate)
|
||||||
|
}}</span>
|
||||||
|
</button>
|
||||||
|
`,
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
host: { class: 'app-toggle-join-library' }
|
||||||
|
})
|
||||||
|
export class ToggleJoinLibraryMenuComponent extends ToggleJoinLibraryButtonComponent {
|
||||||
|
constructor(store: Store<AppStore>, content: ContentManagementService) {
|
||||||
|
super(store, content);
|
||||||
|
}
|
||||||
|
}
|
@@ -23,7 +23,6 @@
|
|||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ToggleJoinLibraryComponent } from './toggle-join-library.component';
|
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core';
|
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core';
|
||||||
@@ -36,10 +35,11 @@ import {
|
|||||||
} from '../../../store/actions/snackbar.actions';
|
} from '../../../store/actions/snackbar.actions';
|
||||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||||
import { ContentManagementService } from '../../../services/content-management.service';
|
import { ContentManagementService } from '../../../services/content-management.service';
|
||||||
|
import { ToggleJoinLibraryButtonComponent } from './toggle-join-library-button.component';
|
||||||
|
|
||||||
describe('ToggleJoinLibraryComponent', () => {
|
describe('ToggleJoinLibraryComponent', () => {
|
||||||
let component: ToggleJoinLibraryComponent;
|
let component: ToggleJoinLibraryButtonComponent;
|
||||||
let fixture: ComponentFixture<ToggleJoinLibraryComponent>;
|
let fixture: ComponentFixture<ToggleJoinLibraryButtonComponent>;
|
||||||
let alfrescoApi: AlfrescoApiService;
|
let alfrescoApi: AlfrescoApiService;
|
||||||
let contentManagementService: ContentManagementService;
|
let contentManagementService: ContentManagementService;
|
||||||
let entry;
|
let entry;
|
||||||
@@ -59,7 +59,10 @@ describe('ToggleJoinLibraryComponent', () => {
|
|||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [AppTestingModule],
|
imports: [AppTestingModule],
|
||||||
declarations: [ToggleJoinLibraryComponent, LibraryMembershipDirective],
|
declarations: [
|
||||||
|
ToggleJoinLibraryButtonComponent,
|
||||||
|
LibraryMembershipDirective
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: Store, useValue: storeMock },
|
{ provide: Store, useValue: storeMock },
|
||||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }
|
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }
|
||||||
@@ -67,7 +70,7 @@ describe('ToggleJoinLibraryComponent', () => {
|
|||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture = TestBed.createComponent(ToggleJoinLibraryComponent);
|
fixture = TestBed.createComponent(ToggleJoinLibraryButtonComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
alfrescoApi = TestBed.get(AlfrescoApiService);
|
alfrescoApi = TestBed.get(AlfrescoApiService);
|
||||||
contentManagementService = TestBed.get(ContentManagementService);
|
contentManagementService = TestBed.get(ContentManagementService);
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
<ng-container [ngSwitch]="type">
|
<ng-container [ngSwitch]="type">
|
||||||
<ng-container *ngSwitchCase="'icon-button'">
|
<ng-container *ngSwitchCase="'icon-button'">
|
||||||
<button
|
<button
|
||||||
[id]="actionRef.id"
|
[id]="actionRef.id"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
[color]="color"
|
[color]="color"
|
||||||
[attr.title]="(actionRef.description || actionRef.title) | translate"
|
[attr.title]="actionRef.description || actionRef.title | translate"
|
||||||
(click)="runAction()">
|
(click)="runAction()"
|
||||||
<mat-icon>{{ actionRef.icon }}</mat-icon>
|
>
|
||||||
</button>
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
</ng-container>
|
</button>
|
||||||
<ng-container *ngSwitchCase="'menu-item'">
|
</ng-container>
|
||||||
<app-toolbar-menu-item [actionRef]="actionRef"></app-toolbar-menu-item>
|
<ng-container *ngSwitchCase="'menu-item'">
|
||||||
</ng-container>
|
<app-toolbar-menu-item [actionRef]="actionRef"></app-toolbar-menu-item>
|
||||||
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@@ -1,19 +1,21 @@
|
|||||||
<ng-container [ngSwitch]="actionRef.type">
|
<ng-container [ngSwitch]="actionRef.type">
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'menu'">
|
<ng-container *ngSwitchCase="'menu'">
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
[disabled]="actionRef.disabled"
|
[disabled]="actionRef.disabled"
|
||||||
[matMenuTriggerFor]="childMenu">
|
[matMenuTriggerFor]="childMenu"
|
||||||
<mat-icon>{{ actionRef.icon }}</mat-icon>
|
>
|
||||||
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
<span>{{ actionRef.title | translate }}</span>
|
<span>{{ actionRef.title | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<mat-menu #childMenu="matMenu" class="app-create-menu__sub-menu">
|
<mat-menu #childMenu="matMenu" class="app-create-menu__sub-menu">
|
||||||
<ng-container *ngFor="let child of actionRef.children; trackBy: trackById">
|
<ng-container
|
||||||
|
*ngFor="let child of actionRef.children; trackBy: trackById"
|
||||||
|
>
|
||||||
<app-toolbar-menu-item [actionRef]="child"></app-toolbar-menu-item>
|
<app-toolbar-menu-item [actionRef]="child"></app-toolbar-menu-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'separator'">
|
<ng-container *ngSwitchCase="'separator'">
|
||||||
@@ -30,17 +32,15 @@
|
|||||||
mat-menu-item
|
mat-menu-item
|
||||||
color="primary"
|
color="primary"
|
||||||
[disabled]="actionRef.disabled"
|
[disabled]="actionRef.disabled"
|
||||||
[attr.title]="(
|
[attr.title]="
|
||||||
actionRef.disabled
|
(actionRef.disabled
|
||||||
? actionRef['description-disabled']
|
? actionRef['description-disabled']
|
||||||
: actionRef.description || actionRef.title
|
: actionRef.description || actionRef.title) | translate
|
||||||
) | translate"
|
"
|
||||||
(click)="runAction()">
|
(click)="runAction()"
|
||||||
<mat-icon>{{ actionRef.icon }}</mat-icon>
|
>
|
||||||
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
<span>{{ actionRef.title | translate }}</span>
|
<span>{{ actionRef.title | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
[id]="actionRef.id"
|
[id]="actionRef.id"
|
||||||
[color]="color"
|
[color]="color"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
[attr.title]="(actionRef.description || actionRef.title) | translate"
|
[attr.title]="actionRef.description || actionRef.title | translate"
|
||||||
[matMenuTriggerFor]="menu">
|
[matMenuTriggerFor]="menu"
|
||||||
<mat-icon>{{ actionRef.icon }}</mat-icon>
|
>
|
||||||
|
<adf-icon [value]="actionRef.icon"></adf-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<mat-menu #menu="matMenu" [overlapTrigger]="false">
|
<mat-menu #menu="matMenu" [overlapTrigger]="false">
|
||||||
|
@@ -34,6 +34,11 @@ import { ToolbarActionComponent } from './toolbar-action/toolbar-action.componen
|
|||||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
import { ToolbarMenuItemComponent } from './toolbar-menu-item/toolbar-menu-item.component';
|
import { ToolbarMenuItemComponent } from './toolbar-menu-item/toolbar-menu-item.component';
|
||||||
import { ToolbarMenuComponent } from './toolbar-menu/toolbar-menu.component';
|
import { ToolbarMenuComponent } from './toolbar-menu/toolbar-menu.component';
|
||||||
|
import { ToggleJoinLibraryButtonComponent } from './toggle-join-library/toggle-join-library-button.component';
|
||||||
|
import { ToggleJoinLibraryMenuComponent } from './toggle-join-library/toggle-join-library-menu.component';
|
||||||
|
import { DirectivesModule } from '../../directives/directives.module';
|
||||||
|
import { ToggleFavoriteLibraryComponent } from './toggle-favorite-library/toggle-favorite-library.component';
|
||||||
|
import { AppCommonModule } from '../common/common.module';
|
||||||
|
|
||||||
export function components() {
|
export function components() {
|
||||||
return [
|
return [
|
||||||
@@ -43,12 +48,21 @@ export function components() {
|
|||||||
ToolbarButtonComponent,
|
ToolbarButtonComponent,
|
||||||
ToolbarActionComponent,
|
ToolbarActionComponent,
|
||||||
ToolbarMenuItemComponent,
|
ToolbarMenuItemComponent,
|
||||||
ToolbarMenuComponent
|
ToolbarMenuComponent,
|
||||||
|
ToggleJoinLibraryButtonComponent,
|
||||||
|
ToggleJoinLibraryMenuComponent,
|
||||||
|
ToggleFavoriteLibraryComponent
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, CoreModule.forChild(), ExtensionsModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
CoreModule.forChild(),
|
||||||
|
AppCommonModule,
|
||||||
|
ExtensionsModule,
|
||||||
|
DirectivesModule
|
||||||
|
],
|
||||||
declarations: components(),
|
declarations: components(),
|
||||||
exports: components(),
|
exports: components(),
|
||||||
entryComponents: components()
|
entryComponents: components()
|
||||||
|
@@ -27,13 +27,21 @@ import { NgModule } from '@angular/core';
|
|||||||
import { ExperimentalDirective } from './experimental.directive';
|
import { ExperimentalDirective } from './experimental.directive';
|
||||||
import { DocumentListDirective } from './document-list.directive';
|
import { DocumentListDirective } from './document-list.directive';
|
||||||
import { PaginationDirective } from './pagination.directive';
|
import { PaginationDirective } from './pagination.directive';
|
||||||
|
import { LibraryMembershipDirective } from './library-membership.directive';
|
||||||
|
import { LibraryFavoriteDirective } from './library-favorite.directive';
|
||||||
|
|
||||||
@NgModule({
|
export function directives() {
|
||||||
declarations: [
|
return [
|
||||||
ExperimentalDirective,
|
ExperimentalDirective,
|
||||||
DocumentListDirective,
|
DocumentListDirective,
|
||||||
PaginationDirective
|
PaginationDirective,
|
||||||
],
|
LibraryMembershipDirective,
|
||||||
exports: [ExperimentalDirective, DocumentListDirective, PaginationDirective]
|
LibraryFavoriteDirective
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: directives(),
|
||||||
|
exports: directives()
|
||||||
})
|
})
|
||||||
export class DirectivesModule {}
|
export class DirectivesModule {}
|
||||||
|
@@ -48,7 +48,8 @@ import { LibraryStatusColumnComponent } from '../components/common/library-statu
|
|||||||
import { TrashcanNameColumnComponent } from '../components/common/trashcan-name-column/trashcan-name-column.component';
|
import { TrashcanNameColumnComponent } from '../components/common/trashcan-name-column/trashcan-name-column.component';
|
||||||
import { LocationLinkComponent } from '../components/common/location-link/location-link.component';
|
import { LocationLinkComponent } from '../components/common/location-link/location-link.component';
|
||||||
import { DocumentDisplayModeComponent } from '../components/toolbar/document-display-mode/document-display-mode.component';
|
import { DocumentDisplayModeComponent } from '../components/toolbar/document-display-mode/document-display-mode.component';
|
||||||
import { ToggleJoinLibraryComponent } from '../components/toolbar/toggle-join-library/toggle-join-library.component';
|
import { ToggleJoinLibraryButtonComponent } from '../components/toolbar/toggle-join-library/toggle-join-library-button.component';
|
||||||
|
import { ToggleJoinLibraryMenuComponent } from '../components/toolbar/toggle-join-library/toggle-join-library-menu.component';
|
||||||
|
|
||||||
export function setupExtensions(service: AppExtensionService): Function {
|
export function setupExtensions(service: AppExtensionService): Function {
|
||||||
return () => service.load();
|
return () => service.load();
|
||||||
@@ -88,8 +89,9 @@ export class CoreExtensionsModule {
|
|||||||
'app.toolbar.toggleInfoDrawer': ToggleInfoDrawerComponent,
|
'app.toolbar.toggleInfoDrawer': ToggleInfoDrawerComponent,
|
||||||
'app.toolbar.toggleFavorite': ToggleFavoriteComponent,
|
'app.toolbar.toggleFavorite': ToggleFavoriteComponent,
|
||||||
'app.toolbar.toggleFavoriteLibrary': ToggleFavoriteLibraryComponent,
|
'app.toolbar.toggleFavoriteLibrary': ToggleFavoriteLibraryComponent,
|
||||||
'app.toolbar.toggleJoinLibrary': ToggleJoinLibraryComponent,
|
'app.toolbar.toggleJoinLibrary': ToggleJoinLibraryButtonComponent,
|
||||||
'app.toolbar.cardView': DocumentDisplayModeComponent,
|
'app.toolbar.cardView': DocumentDisplayModeComponent,
|
||||||
|
'app.menu.toggleJoinLibrary': ToggleJoinLibraryMenuComponent,
|
||||||
'app.shared-link.toggleSharedLink': ToggleSharedComponent,
|
'app.shared-link.toggleSharedLink': ToggleSharedComponent,
|
||||||
'app.columns.name': NameColumnComponent,
|
'app.columns.name': NameColumnComponent,
|
||||||
'app.columns.libraryName': LibraryNameColumnComponent,
|
'app.columns.libraryName': LibraryNameColumnComponent,
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { Route } from '@angular/router';
|
import { Route } from '@angular/router';
|
||||||
|
import { MatIconRegistry } from '@angular/material';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { AppStore } from '../store/states';
|
import { AppStore } from '../store/states';
|
||||||
import { ruleContext } from '../store/selectors/app.selectors';
|
import { ruleContext } from '../store/selectors/app.selectors';
|
||||||
import { NodePermissionService } from '../services/node-permission.service';
|
import { NodePermissionService } from '../services/node-permission.service';
|
||||||
@@ -53,6 +55,7 @@ import {
|
|||||||
import { AppConfigService } from '@alfresco/adf-core';
|
import { AppConfigService } from '@alfresco/adf-core';
|
||||||
import { DocumentListPresetRef } from './document-list.extensions';
|
import { DocumentListPresetRef } from './document-list.extensions';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { IconRef } from './icon.extensions';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -105,11 +108,13 @@ export class AppExtensionService implements RuleContext {
|
|||||||
references$: Observable<ExtensionRef[]>;
|
references$: Observable<ExtensionRef[]>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<AppStore>,
|
protected store: Store<AppStore>,
|
||||||
private loader: ExtensionLoaderService,
|
protected loader: ExtensionLoaderService,
|
||||||
private extensions: ExtensionService,
|
protected extensions: ExtensionService,
|
||||||
public permissions: NodePermissionService,
|
public permissions: NodePermissionService,
|
||||||
private appConfig: AppConfigService
|
protected appConfig: AppConfigService,
|
||||||
|
protected matIconRegistry: MatIconRegistry,
|
||||||
|
protected sanitizer: DomSanitizer
|
||||||
) {
|
) {
|
||||||
this.references$ = this._references.asObservable();
|
this.references$ = this._references.asObservable();
|
||||||
|
|
||||||
@@ -184,12 +189,37 @@ export class AppExtensionService implements RuleContext {
|
|||||||
searchLibraries: this.getDocumentListPreset(config, 'search-libraries')
|
searchLibraries: this.getDocumentListPreset(config, 'search-libraries')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.registerIcons(config);
|
||||||
|
|
||||||
const references = (config.$references || [])
|
const references = (config.$references || [])
|
||||||
.filter(entry => typeof entry === 'object')
|
.filter(entry => typeof entry === 'object')
|
||||||
.map(entry => <ExtensionRef>entry);
|
.map(entry => <ExtensionRef>entry);
|
||||||
this._references.next(references);
|
this._references.next(references);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected registerIcons(config: ExtensionConfig) {
|
||||||
|
const icons: Array<IconRef> = this.loader
|
||||||
|
.getElements<IconRef>(config, 'features.icons')
|
||||||
|
.filter(entry => !entry.disabled);
|
||||||
|
|
||||||
|
for (const icon of icons) {
|
||||||
|
const [ns, id] = icon.id.split(':');
|
||||||
|
const value = icon.value;
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
console.warn(`Missing icon value for "${icon.id}".`);
|
||||||
|
} else if (!ns || !id) {
|
||||||
|
console.warn(`Incorrect icon id format: "${icon.id}".`);
|
||||||
|
} else {
|
||||||
|
this.matIconRegistry.addSvgIconInNamespace(
|
||||||
|
ns,
|
||||||
|
id,
|
||||||
|
this.sanitizer.bypassSecurityTrustResourceUrl(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected loadNavBar(config: ExtensionConfig): Array<NavBarGroupRef> {
|
protected loadNavBar(config: ExtensionConfig): Array<NavBarGroupRef> {
|
||||||
return this.loader.getElements<NavBarGroupRef>(config, 'features.navbar');
|
return this.loader.getElements<NavBarGroupRef>(config, 'features.navbar');
|
||||||
}
|
}
|
||||||
|
30
src/app/extensions/icon.extensions.ts
Normal file
30
src/app/extensions/icon.extensions.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Alfresco Example Content Application
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||||
|
*
|
||||||
|
* This file is part of the Alfresco Example Content Application.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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 { ExtensionElement } from '@alfresco/adf-extensions';
|
||||||
|
|
||||||
|
export interface IconRef extends ExtensionElement {
|
||||||
|
value: string;
|
||||||
|
}
|
@@ -220,6 +220,16 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
"features": {
|
"features": {
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"id": "adf:join_library",
|
||||||
|
"value": "./assets/images/join-library.svg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "adf:move_file",
|
||||||
|
"value": "./assets/images/adf-move-file-24px.svg"
|
||||||
|
}
|
||||||
|
],
|
||||||
"create": [
|
"create": [
|
||||||
{
|
{
|
||||||
"id": "app.create.uploadFile",
|
"id": "app.create.uploadFile",
|
||||||
@@ -362,7 +372,7 @@
|
|||||||
"id": "app.toolbar.share",
|
"id": "app.toolbar.share",
|
||||||
"order": 100,
|
"order": 100,
|
||||||
"title": "APP.ACTIONS.SHARE",
|
"title": "APP.ACTIONS.SHARE",
|
||||||
"icon": "share",
|
"icon": "link",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "SHARE_NODE"
|
"click": "SHARE_NODE"
|
||||||
},
|
},
|
||||||
@@ -374,7 +384,7 @@
|
|||||||
"id": "app.toolbar.share.edit",
|
"id": "app.toolbar.share.edit",
|
||||||
"order": 101,
|
"order": 101,
|
||||||
"title": "APP.ACTIONS.SHARE_EDIT",
|
"title": "APP.ACTIONS.SHARE_EDIT",
|
||||||
"icon": "share",
|
"icon": "link",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "SHARE_NODE"
|
"click": "SHARE_NODE"
|
||||||
},
|
},
|
||||||
@@ -386,7 +396,7 @@
|
|||||||
"id": "app.toolbar.preview",
|
"id": "app.toolbar.preview",
|
||||||
"order": 300,
|
"order": 300,
|
||||||
"title": "APP.ACTIONS.VIEW",
|
"title": "APP.ACTIONS.VIEW",
|
||||||
"icon": "open_in_browser",
|
"icon": "visibility",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "VIEW_FILE"
|
"click": "VIEW_FILE"
|
||||||
},
|
},
|
||||||
@@ -557,7 +567,7 @@
|
|||||||
"id": "app.toolbar.move",
|
"id": "app.toolbar.move",
|
||||||
"order": 500,
|
"order": 500,
|
||||||
"title": "APP.ACTIONS.MOVE",
|
"title": "APP.ACTIONS.MOVE",
|
||||||
"icon": "library_books",
|
"icon": "adf:move_file",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "MOVE_NODES"
|
"click": "MOVE_NODES"
|
||||||
},
|
},
|
||||||
@@ -647,7 +657,7 @@
|
|||||||
"id": "app.context.menu.preview",
|
"id": "app.context.menu.preview",
|
||||||
"order": 300,
|
"order": 300,
|
||||||
"title": "APP.ACTIONS.VIEW",
|
"title": "APP.ACTIONS.VIEW",
|
||||||
"icon": "open_in_browser",
|
"icon": "visibility",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "VIEW_FILE"
|
"click": "VIEW_FILE"
|
||||||
},
|
},
|
||||||
@@ -714,7 +724,7 @@
|
|||||||
"id": "app.context.menu.joinLibrary",
|
"id": "app.context.menu.joinLibrary",
|
||||||
"type": "custom",
|
"type": "custom",
|
||||||
"order": 603,
|
"order": 603,
|
||||||
"component": "app.toolbar.toggleJoinLibrary",
|
"component": "app.menu.toggleJoinLibrary",
|
||||||
"rules": {
|
"rules": {
|
||||||
"visible": "app.libraries.toolbar.canToggleJoin"
|
"visible": "app.libraries.toolbar.canToggleJoin"
|
||||||
}
|
}
|
||||||
@@ -752,7 +762,7 @@
|
|||||||
"id": "app.context.menu.move",
|
"id": "app.context.menu.move",
|
||||||
"title": "APP.ACTIONS.MOVE",
|
"title": "APP.ACTIONS.MOVE",
|
||||||
"order": 800,
|
"order": 800,
|
||||||
"icon": "library_books",
|
"icon": "adf:move_file",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "MOVE_NODES"
|
"click": "MOVE_NODES"
|
||||||
},
|
},
|
||||||
@@ -868,7 +878,7 @@
|
|||||||
"id": "app.viewer.share",
|
"id": "app.viewer.share",
|
||||||
"order": 200,
|
"order": 200,
|
||||||
"title": "APP.ACTIONS.SHARE",
|
"title": "APP.ACTIONS.SHARE",
|
||||||
"icon": "share",
|
"icon": "link",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "SHARE_NODE"
|
"click": "SHARE_NODE"
|
||||||
},
|
},
|
||||||
@@ -880,7 +890,7 @@
|
|||||||
"id": "app.viewer.share.edit",
|
"id": "app.viewer.share.edit",
|
||||||
"order": 201,
|
"order": 201,
|
||||||
"title": "APP.ACTIONS.SHARE_EDIT",
|
"title": "APP.ACTIONS.SHARE_EDIT",
|
||||||
"icon": "share",
|
"icon": "link",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "SHARE_NODE"
|
"click": "SHARE_NODE"
|
||||||
},
|
},
|
||||||
@@ -962,7 +972,7 @@
|
|||||||
"id": "app.viewer.move",
|
"id": "app.viewer.move",
|
||||||
"order": 500,
|
"order": 500,
|
||||||
"title": "APP.ACTIONS.MOVE",
|
"title": "APP.ACTIONS.MOVE",
|
||||||
"icon": "library_books",
|
"icon": "adf:move_file",
|
||||||
"actions": {
|
"actions": {
|
||||||
"click": "MOVE_NODES"
|
"click": "MOVE_NODES"
|
||||||
},
|
},
|
||||||
|
1
src/assets/images/adf-move-file-24px.svg
Normal file
1
src/assets/images/adf-move-file-24px.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><g id="Artboard_1"><g id="Page_1"><rect id="Fill_1" x="0" y="0" width="24" height="24" style="fill:none;"/><path id="Fill_2" d="M20,20l-16,0c-1.097,0 -2,-0.903 -2,-2l0.01,-12c0,-1.093 0.897,-1.995 1.99,-2l6,0l2,2l8,0c1.097,0 2,0.903 2,2l0,10c0,1.097 -0.903,2 -2,2Zm-9,-9l0,4l4,0l0,2l4,-4l-4,-4l0,2l-4,0Z" style="fill-rule:nonzero;"/></g></g></svg>
|
After Width: | Height: | Size: 794 B |
@@ -1,8 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>join-library</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs>
|
<defs>
|
||||||
<polygon id="path-1" points="0.0003 0 16 0 16 16 0.0003 16"></polygon>
|
<polygon id="path-1" points="0.0003 0 16 0 16 16 0.0003 16"></polygon>
|
||||||
<polygon id="path-3" points="0 0 15.9998 0 15.9998 16 0 16"></polygon>
|
<polygon id="path-3" points="0 0 15.9998 0 15.9998 16 0 16"></polygon>
|
||||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -55,7 +55,12 @@
|
|||||||
"check-type"
|
"check-type"
|
||||||
],
|
],
|
||||||
"directive-selector": [true, "attribute", "aca", "camelCase"],
|
"directive-selector": [true, "attribute", "aca", "camelCase"],
|
||||||
"component-selector": [true, "element", ["app", "aca"], "kebab-case"],
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
["app", "aca", "adf"],
|
||||||
|
"kebab-case"
|
||||||
|
],
|
||||||
"use-input-property-decorator": true,
|
"use-input-property-decorator": true,
|
||||||
"use-output-property-decorator": true,
|
"use-output-property-decorator": true,
|
||||||
"use-host-property-decorator": false,
|
"use-host-property-decorator": false,
|
||||||
|
Reference in New Issue
Block a user