mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[ACS-5088] Replaced function calls in templates with variable references (#3227)
* [ACS-5088] Replaced method calls in templates with variables * [ACS-5088] Replaced method calls in templates with variables * [ACS-5088] Replaced method calls for *ngIf and *ngFor with variables - Batch 1 (WIP) * [ACS-5088] Replaced method calls for *ngIf and *ngFor with variables - Batch 2 (WIP) * [ACS-5088] Replaced instances of $any with cast pipe. Replaced other instances of method calls in templates with variables * [ACS-5088] Resolved test cases * [ACS-5088] Resolved test cases in aca-content library * [ACS-5088] Resolved test cases in aca-shared library * [ACS-5088] Resolved test cases in aca-folder-rules library * [ACS-5088] Reverted usage of cast pipe to $any() * [ACS-5088] Fixed incorrect revert * [ACS-5088] Resolved code review findings - shortened expressions and made onDestroy subjects use void instead of boolean * [ACS-5088] Resolved code review findings - changed parameter name in sort function * [ACS-5088] Resolved code review findings - added 'void' type to onDestroy subjects * [ACS-5088] Upgraded eslint version to 8.41.0. Added "@angular-eslint/template/no-call-expression" rule to prevent function calls in templates unless needed (reports warnings) * [ACS-5088] Resolved typo in ToggleFavoriteComponent
This commit is contained in:
@@ -315,10 +315,12 @@
|
|||||||
"*.html"
|
"*.html"
|
||||||
],
|
],
|
||||||
"extends": ["plugin:@nrwl/nx/angular-template", "plugin:@angular-eslint/template/accessibility"],
|
"extends": ["plugin:@nrwl/nx/angular-template", "plugin:@angular-eslint/template/accessibility"],
|
||||||
|
"parser": "@angular-eslint/template-parser",
|
||||||
"rules": {
|
"rules": {
|
||||||
"@angular-eslint/template/no-negated-async": "off",
|
"@angular-eslint/template/no-negated-async": "off",
|
||||||
"@angular-eslint/template/no-positive-tabindex": "error",
|
"@angular-eslint/template/no-positive-tabindex": "error",
|
||||||
"@angular-eslint/template/eqeqeq": "error"
|
"@angular-eslint/template/eqeqeq": "error",
|
||||||
|
"@angular-eslint/template/no-call-expression": "warn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
<ng-container *ngIf="selection$ | async as selection">
|
<ng-container *ngIf="selectionState">
|
||||||
<ng-container *ngIf="!data.iconButton">
|
<ng-container *ngIf="!data.iconButton">
|
||||||
<button mat-menu-item data-automation-id="share-action-button" (click)="editSharedNode(selection, '.adf-context-menu-source')">
|
<button mat-menu-item data-automation-id="share-action-button" (click)="editSharedNode(selectionState, '.adf-context-menu-source')">
|
||||||
<mat-icon>link</mat-icon>
|
<mat-icon>link</mat-icon>
|
||||||
<ng-container *ngIf="isShared(selection); else not_shared">
|
<ng-container *ngIf="isShared; else not_shared">
|
||||||
<span>{{ 'APP.ACTIONS.SHARE_EDIT' | translate }}</span>
|
<span>{{ 'APP.ACTIONS.SHARE_EDIT' | translate }}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</button>
|
</button>
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
data-automation-id="share-action-button"
|
data-automation-id="share-action-button"
|
||||||
(click)="editSharedNode(selection, '#share-action-button')"
|
(click)="editSharedNode(selectionState, '#share-action-button')"
|
||||||
[attr.aria-label]="getLabel(selection) | translate"
|
[attr.aria-label]="selectionLabel | translate"
|
||||||
[attr.title]="getLabel(selection) | translate"
|
[attr.title]="selectionLabel | translate"
|
||||||
id="share-action-button"
|
id="share-action-button"
|
||||||
>
|
>
|
||||||
<mat-icon>link</mat-icon>
|
<mat-icon>link</mat-icon>
|
||||||
|
@@ -56,14 +56,14 @@ describe('ToggleSharedComponent', () => {
|
|||||||
it('should return false when entry is not shared', () => {
|
it('should return false when entry is not shared', () => {
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
|
|
||||||
expect(component.isShared({ first: { entry } })).toBe(false);
|
expect(component.isShared).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true when entry is shared', () => {
|
it('should return true when entry is shared', () => {
|
||||||
entry.properties['qshare:sharedId'] = 'some-id';
|
entry.properties['qshare:sharedId'] = 'some-id';
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
|
|
||||||
expect(component.isShared({ first: { entry } })).toBe(true);
|
expect(component.isShared).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should dispatch `SHARE_NODE` action on share', () => {
|
it('should dispatch `SHARE_NODE` action on share', () => {
|
||||||
@@ -74,7 +74,7 @@ describe('ToggleSharedComponent', () => {
|
|||||||
|
|
||||||
it('should get action label for unshared file', () => {
|
it('should get action label for unshared file', () => {
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
const label = component.getLabel({ first: { entry } });
|
const label = component.selectionLabel;
|
||||||
|
|
||||||
expect(label).toBe('APP.ACTIONS.SHARE');
|
expect(label).toBe('APP.ACTIONS.SHARE');
|
||||||
});
|
});
|
||||||
@@ -82,7 +82,7 @@ describe('ToggleSharedComponent', () => {
|
|||||||
it('should get action label for shared file', () => {
|
it('should get action label for shared file', () => {
|
||||||
entry.properties['qshare:sharedId'] = 'some-id';
|
entry.properties['qshare:sharedId'] = 'some-id';
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
const label = component.getLabel({ first: { entry } });
|
const label = component.selectionLabel;
|
||||||
|
|
||||||
expect(label).toBe('APP.ACTIONS.SHARE_EDIT');
|
expect(label).toBe('APP.ACTIONS.SHARE_EDIT');
|
||||||
});
|
});
|
||||||
|
@@ -22,8 +22,8 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { SelectionState } from '@alfresco/adf-extensions';
|
import { SelectionState } from '@alfresco/adf-extensions';
|
||||||
import { AppStore, ShareNodeAction, getAppSelection } from '@alfresco/aca-shared/store';
|
import { AppStore, ShareNodeAction, getAppSelection } from '@alfresco/aca-shared/store';
|
||||||
@@ -32,6 +32,7 @@ import { MatMenuModule } from '@angular/material/menu';
|
|||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
@@ -39,29 +40,38 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
selector: 'app-toggle-shared',
|
selector: 'app-toggle-shared',
|
||||||
templateUrl: './toggle-shared.component.html'
|
templateUrl: './toggle-shared.component.html'
|
||||||
})
|
})
|
||||||
export class ToggleSharedComponent implements OnInit {
|
export class ToggleSharedComponent implements OnInit, OnDestroy {
|
||||||
@Input()
|
@Input()
|
||||||
data: {
|
data: {
|
||||||
iconButton?: string;
|
iconButton?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
selection$: Observable<SelectionState>;
|
selection$: Observable<SelectionState>;
|
||||||
|
selectionState: SelectionState;
|
||||||
|
selectionLabel = '';
|
||||||
|
isShared = false;
|
||||||
|
|
||||||
|
onDestroy$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(private store: Store<AppStore>) {}
|
constructor(private store: Store<AppStore>) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.selection$ = this.store.select(getAppSelection);
|
this.selection$ = this.store.select(getAppSelection);
|
||||||
|
this.selection$.pipe(takeUntil(this.onDestroy$)).subscribe((selectionState) => {
|
||||||
|
this.selectionState = selectionState;
|
||||||
|
|
||||||
|
this.isShared =
|
||||||
|
(this.selectionState.first && this.selectionState.first.entry && (this.selectionState.first.entry as any).sharedByUser) ||
|
||||||
|
!!this.selectionState?.first?.entry?.properties?.['qshare:sharedId'];
|
||||||
|
|
||||||
|
this.selectionLabel = this.isShared ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isShared(selection: SelectionState) {
|
ngOnDestroy(): void {
|
||||||
// workaround for shared files
|
this.onDestroy$.next();
|
||||||
if (selection.first && selection.first.entry && (selection.first.entry as any).sharedByUser) {
|
this.onDestroy$.complete();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return selection.first && selection.first.entry && selection.first.entry.properties && !!selection.first.entry.properties['qshare:sharedId'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editSharedNode(selection: SelectionState, focusedElementOnCloseSelector: string) {
|
editSharedNode(selection: SelectionState, focusedElementOnCloseSelector: string) {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
new ShareNodeAction(selection.first, {
|
new ShareNodeAction(selection.first, {
|
||||||
@@ -69,8 +79,4 @@ export class ToggleSharedComponent implements OnInit {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLabel(selection: SelectionState): string {
|
|
||||||
return this.isShared(selection) ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -46,12 +46,17 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
export class CustomNameColumnComponent extends NameColumnComponent implements OnInit, OnDestroy {
|
export class CustomNameColumnComponent extends NameColumnComponent implements OnInit, OnDestroy {
|
||||||
private onDestroy$$ = new Subject<boolean>();
|
private onDestroy$$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
isFile: boolean;
|
||||||
|
isFileWriteLocked: boolean;
|
||||||
|
|
||||||
constructor(element: ElementRef, private cd: ChangeDetectorRef, private actions$: Actions, private nodesService: NodesApiService) {
|
constructor(element: ElementRef, private cd: ChangeDetectorRef, private actions$: Actions, private nodesService: NodesApiService) {
|
||||||
super(element, nodesService);
|
super(element, nodesService);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.updateValue();
|
this.updateValue();
|
||||||
|
this.isFile = this.node?.entry && !this.node.entry.isFolder;
|
||||||
|
this.isFileWriteLocked = isLocked(this.node);
|
||||||
|
|
||||||
this.nodesService.nodeUpdated.pipe(takeUntil(this.onDestroy$$)).subscribe((node: any) => {
|
this.nodesService.nodeUpdated.pipe(takeUntil(this.onDestroy$$)).subscribe((node: any) => {
|
||||||
const row = this.context.row;
|
const row = this.context.row;
|
||||||
@@ -65,6 +70,9 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
row.node = { entry };
|
row.node = { entry };
|
||||||
this.updateValue();
|
this.updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isFile = this.node?.entry && !this.node.entry.isFolder;
|
||||||
|
this.isFileWriteLocked = isLocked(this.node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,6 +83,7 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
takeUntil(this.onDestroy$$)
|
takeUntil(this.onDestroy$$)
|
||||||
)
|
)
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
|
this.isFileWriteLocked = isLocked(this.node);
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -90,12 +99,4 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
this.onDestroy$$.next(true);
|
this.onDestroy$$.next(true);
|
||||||
this.onDestroy$$.complete();
|
this.onDestroy$$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isFile(): boolean {
|
|
||||||
return this.node && this.node.entry && !this.node.entry.isFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isFileWriteLocked(): boolean {
|
|
||||||
return isLocked(this.node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -22,16 +22,15 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ShareDataRow, TagModule } from '@alfresco/adf-content-services';
|
import { TagModule } from '@alfresco/adf-content-services';
|
||||||
import { ChangeDetectorRef, Component, Input, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TagModule],
|
imports: [TagModule],
|
||||||
selector: 'aca-tags-column',
|
selector: 'aca-tags-column',
|
||||||
template: `
|
template: `
|
||||||
<adf-tag-node-list [showDelete]="false" [limitTagsDisplayed]="true" [nodeId]="getNodeId(context.row)" (results)="onTagsLoaded()">
|
<adf-tag-node-list [showDelete]="false" [limitTagsDisplayed]="true" [nodeId]="nodeId" (results)="onTagsLoaded()"> </adf-tag-node-list>
|
||||||
</adf-tag-node-list>
|
|
||||||
`,
|
`,
|
||||||
styleUrls: ['./tags-column.component.scss'],
|
styleUrls: ['./tags-column.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
@@ -39,14 +38,16 @@ import { ChangeDetectorRef, Component, Input, ViewEncapsulation } from '@angular
|
|||||||
class: 'adf-datatable-content-cell aca-tags-name-column'
|
class: 'adf-datatable-content-cell aca-tags-name-column'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class TagsColumnComponent {
|
export class TagsColumnComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
context: any;
|
context: any;
|
||||||
|
|
||||||
|
nodeId: string;
|
||||||
|
|
||||||
constructor(private cd: ChangeDetectorRef) {}
|
constructor(private cd: ChangeDetectorRef) {}
|
||||||
|
|
||||||
getNodeId(row: ShareDataRow): string {
|
ngOnInit(): void {
|
||||||
return row.id;
|
this.nodeId = this.context?.row?.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
onTagsLoaded(): void {
|
onTagsLoaded(): void {
|
||||||
|
@@ -72,7 +72,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</data-columns>
|
</data-columns>
|
||||||
|
|
||||||
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive()">
|
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive">
|
||||||
<ng-container>
|
<ng-container>
|
||||||
<div class="empty-search__block" aria-live="polite">
|
<div class="empty-search__block" aria-live="polite">
|
||||||
<p class="empty-search__text">
|
<p class="empty-search__text">
|
||||||
|
@@ -46,6 +46,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
|||||||
private nodePath: PathElement[];
|
private nodePath: PathElement[];
|
||||||
|
|
||||||
columns: DocumentListPresetRef[] = [];
|
columns: DocumentListPresetRef[] = [];
|
||||||
|
isFilterHeaderActive = false;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private contentApi: ContentApiService, private nodeActionsService: NodeActionsService) {
|
constructor(private route: ActivatedRoute, private contentApi: ContentApiService, private nodeActionsService: NodeActionsService) {
|
||||||
super();
|
super();
|
||||||
@@ -306,9 +307,11 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
|||||||
onFilterSelected(activeFilters: FilterSearch[]) {
|
onFilterSelected(activeFilters: FilterSearch[]) {
|
||||||
if (activeFilters.length) {
|
if (activeFilters.length) {
|
||||||
this.showHeader = ShowHeaderMode.Always;
|
this.showHeader = ShowHeaderMode.Always;
|
||||||
|
this.isFilterHeaderActive = true;
|
||||||
this.navigateToFilter(activeFilters);
|
this.navigateToFilter(activeFilters);
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate(['.'], { relativeTo: this.route });
|
this.router.navigate(['.'], { relativeTo: this.route });
|
||||||
|
this.isFilterHeaderActive = false;
|
||||||
this.showHeader = ShowHeaderMode.Data;
|
this.showHeader = ShowHeaderMode.Data;
|
||||||
this.onAllFilterCleared();
|
this.onAllFilterCleared();
|
||||||
}
|
}
|
||||||
@@ -329,10 +332,6 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
|||||||
this.router.navigate([], { relativeTo: this.route, queryParams: objectFromMap });
|
this.router.navigate([], { relativeTo: this.route, queryParams: objectFromMap });
|
||||||
}
|
}
|
||||||
|
|
||||||
isFilterHeaderActive(): boolean {
|
|
||||||
return this.showHeader === ShowHeaderMode.Always;
|
|
||||||
}
|
|
||||||
|
|
||||||
onError() {
|
onError() {
|
||||||
this.isValidPath = false;
|
this.isValidPath = false;
|
||||||
}
|
}
|
||||||
|
@@ -83,22 +83,26 @@ describe('CommentsTabComponent', () => {
|
|||||||
expect(component.canUpdateNode).toBe(false);
|
expect(component.canUpdateNode).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check [update] permission if node selected is a not locked file', () => {
|
it('should check [update] permission if node selected is a not locked file', async () => {
|
||||||
component.node = {
|
component.node = {
|
||||||
id: 'test-node-id',
|
id: 'test-node-id',
|
||||||
isFile: true,
|
isFile: true,
|
||||||
isFolder: false
|
isFolder: false
|
||||||
} as Node;
|
} as Node;
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
expect(component.canUpdateNode).toBe(true);
|
expect(component.canUpdateNode).toBe(true);
|
||||||
expect(checked).toContain('update');
|
expect(checked).toContain('update');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check [update] permission if node selected is a folder', () => {
|
it('should check [update] permission if node selected is a folder', async () => {
|
||||||
component.node = {
|
component.node = {
|
||||||
id: 'test-node-id',
|
id: 'test-node-id',
|
||||||
isFile: false,
|
isFile: false,
|
||||||
isFolder: true
|
isFolder: true
|
||||||
} as Node;
|
} as Node;
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
expect(component.canUpdateNode).toBe(true);
|
expect(component.canUpdateNode).toBe(true);
|
||||||
expect(checked).toContain('update');
|
expect(checked).toContain('update');
|
||||||
});
|
});
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||||
import { NodePermissionService, isLocked } from '@alfresco/aca-shared';
|
import { NodePermissionService, isLocked } from '@alfresco/aca-shared';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
@@ -34,20 +34,20 @@ import { NodeCommentsModule } from '@alfresco/adf-content-services';
|
|||||||
selector: 'app-comments-tab',
|
selector: 'app-comments-tab',
|
||||||
template: `<mat-card><adf-node-comments [readOnly]="!canUpdateNode" [nodeId]="node?.id"></adf-node-comments></mat-card>`
|
template: `<mat-card><adf-node-comments [readOnly]="!canUpdateNode" [nodeId]="node?.id"></adf-node-comments></mat-card>`
|
||||||
})
|
})
|
||||||
export class CommentsTabComponent {
|
export class CommentsTabComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
node: MinimalNodeEntryEntity;
|
node: MinimalNodeEntryEntity;
|
||||||
|
|
||||||
|
canUpdateNode = false;
|
||||||
|
|
||||||
constructor(private permission: NodePermissionService) {}
|
constructor(private permission: NodePermissionService) {}
|
||||||
|
|
||||||
get canUpdateNode(): boolean {
|
ngOnInit(): void {
|
||||||
if (!this.node) {
|
if (!this.node) {
|
||||||
return false;
|
this.canUpdateNode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.node.isFolder || (this.node.isFile && !isLocked({ entry: this.node }))) {
|
if (this.node.isFolder || (this.node.isFile && !isLocked({ entry: this.node }))) {
|
||||||
return this.permission.check(this.node, ['update']);
|
this.canUpdateNode = this.permission.check(this.node, ['update']);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="mat-input-element">
|
<span class="mat-input-element">
|
||||||
{{ getVisibilityLabel(form.controls.visibility.value) | translate }}
|
{{ visibilityLabel | translate }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -92,15 +92,12 @@ export class LibraryMetadataFormComponent implements OnInit, OnChanges, OnDestro
|
|||||||
});
|
});
|
||||||
|
|
||||||
matcher = new InstantErrorStateMatcher();
|
matcher = new InstantErrorStateMatcher();
|
||||||
|
canUpdateLibrary = false;
|
||||||
|
visibilityLabel = '';
|
||||||
|
|
||||||
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||||
|
|
||||||
constructor(private alfrescoApiService: AlfrescoApiService, protected store: Store<AppStore>) {}
|
constructor(private alfrescoApiService: AlfrescoApiService, protected store: Store<AppStore>) {}
|
||||||
|
|
||||||
get canUpdateLibrary() {
|
|
||||||
return this.node && this.node.entry && this.node.entry.role === 'SiteManager';
|
|
||||||
}
|
|
||||||
|
|
||||||
getVisibilityLabel(value: string) {
|
getVisibilityLabel(value: string) {
|
||||||
return this.libraryType.find((type) => type.value === value).label;
|
return this.libraryType.find((type) => type.value === value).label;
|
||||||
}
|
}
|
||||||
@@ -136,6 +133,8 @@ export class LibraryMetadataFormComponent implements OnInit, OnChanges, OnDestro
|
|||||||
this.libraryTitleExists = false;
|
this.libraryTitleExists = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.canUpdateLibrary = this.node?.entry?.role === 'SiteManager';
|
||||||
|
this.visibilityLabel = this.libraryType.find((type) => type.value === this.form.controls['visibility'].value).label;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@@ -23,14 +23,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { MetadataTabComponent } from './metadata-tab.component';
|
import { MetadataTabComponent } from './metadata-tab.component';
|
||||||
import { Node } from '@alfresco/js-api';
|
import { MinimalNodeEntryEntity, Node } from '@alfresco/js-api';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||||
import { AppConfigService, CoreModule } from '@alfresco/adf-core';
|
import { AppConfigService, CoreModule } from '@alfresco/adf-core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppState, SetInfoDrawerMetadataAspectAction } from '@alfresco/aca-shared/store';
|
import { AppState, SetInfoDrawerMetadataAspectAction } from '@alfresco/aca-shared/store';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { AppExtensionService } from '@alfresco/aca-shared';
|
import { AppExtensionService, NodePermissionService } from '@alfresco/aca-shared';
|
||||||
|
|
||||||
describe('MetadataTabComponent', () => {
|
describe('MetadataTabComponent', () => {
|
||||||
let fixture: ComponentFixture<MetadataTabComponent>;
|
let fixture: ComponentFixture<MetadataTabComponent>;
|
||||||
@@ -38,17 +38,22 @@ describe('MetadataTabComponent', () => {
|
|||||||
let store: Store<AppState>;
|
let store: Store<AppState>;
|
||||||
let appConfig: AppConfigService;
|
let appConfig: AppConfigService;
|
||||||
let extensions: AppExtensionService;
|
let extensions: AppExtensionService;
|
||||||
|
let nodePermissionService: NodePermissionService;
|
||||||
|
|
||||||
const presets = {
|
const presets = {
|
||||||
default: {
|
default: {
|
||||||
includeAll: true
|
includeAll: true
|
||||||
},
|
},
|
||||||
custom: []
|
custom: []
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule, AppTestingModule, MetadataTabComponent]
|
imports: [CoreModule, AppTestingModule, MetadataTabComponent]
|
||||||
});
|
});
|
||||||
|
nodePermissionService = TestBed.inject(NodePermissionService);
|
||||||
|
spyOn(nodePermissionService, 'check').and.callFake((source: MinimalNodeEntryEntity, permissions: string[]) => {
|
||||||
|
return permissions.some((permission) => source.allowableOperations.includes(permission));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -86,11 +91,12 @@ describe('MetadataTabComponent', () => {
|
|||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if node is not locked and has update permission', () => {
|
it('should return true if node is not locked and has update permission', async () => {
|
||||||
component.node = {
|
component.node = {
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
allowableOperations: ['update']
|
allowableOperations: ['update']
|
||||||
} as Node;
|
} as Node;
|
||||||
|
component.ngOnInit();
|
||||||
expect(component.canUpdateNode).toBe(true);
|
expect(component.canUpdateNode).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -99,6 +105,7 @@ describe('MetadataTabComponent', () => {
|
|||||||
isLocked: true,
|
isLocked: true,
|
||||||
allowableOperations: ['update']
|
allowableOperations: ['update']
|
||||||
} as Node;
|
} as Node;
|
||||||
|
component.ngOnInit();
|
||||||
expect(component.canUpdateNode).toBe(false);
|
expect(component.canUpdateNode).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -107,6 +114,7 @@ describe('MetadataTabComponent', () => {
|
|||||||
isLocked: false,
|
isLocked: false,
|
||||||
allowableOperations: ['other']
|
allowableOperations: ['other']
|
||||||
} as Node;
|
} as Node;
|
||||||
|
component.ngOnInit();
|
||||||
expect(component.canUpdateNode).toBe(false);
|
expect(component.canUpdateNode).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -118,6 +126,7 @@ describe('MetadataTabComponent', () => {
|
|||||||
'cm:lockType': 'WRITE_LOCK'
|
'cm:lockType': 'WRITE_LOCK'
|
||||||
}
|
}
|
||||||
} as Node;
|
} as Node;
|
||||||
|
component.ngOnInit();
|
||||||
expect(component.canUpdateNode).toBe(false);
|
expect(component.canUpdateNode).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -52,6 +52,8 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
displayAspect$: Observable<string>;
|
displayAspect$: Observable<string>;
|
||||||
|
|
||||||
|
canUpdateNode = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private permission: NodePermissionService,
|
private permission: NodePermissionService,
|
||||||
protected extensions: AppExtensionService,
|
protected extensions: AppExtensionService,
|
||||||
@@ -66,18 +68,13 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
|
|||||||
this.displayAspect$ = this.store.select(infoDrawerMetadataAspect);
|
this.displayAspect$ = this.store.select(infoDrawerMetadataAspect);
|
||||||
}
|
}
|
||||||
|
|
||||||
get canUpdateNode(): boolean {
|
|
||||||
if (this.node && !isLocked({ entry: this.node })) {
|
|
||||||
return this.permission.check(this.node, ['update']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.contentMetadataService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
|
this.contentMetadataService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
|
||||||
this.notificationService.showError(err.message);
|
this.notificationService.showError(err.message);
|
||||||
});
|
});
|
||||||
|
if (this.node && !isLocked({ entry: this.node })) {
|
||||||
|
this.canUpdateNode = this.permission.check(this.node, ['update']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
(searchChange)="onSearchChange($event)"
|
(searchChange)="onSearchChange($event)"
|
||||||
>
|
>
|
||||||
</app-search-input-control>
|
</app-search-input-control>
|
||||||
<mat-hint *ngIf="hasLibraryConstraint()" class="app-search-hint">{{ 'SEARCH.INPUT.HINT' | translate }}</mat-hint>
|
<mat-hint *ngIf="hasLibrariesConstraint" class="app-search-hint">{{ 'SEARCH.INPUT.HINT' | translate }}</mat-hint>
|
||||||
|
|
||||||
<div id="search-options">
|
<div id="search-options">
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
|
@@ -91,7 +91,7 @@ describe('SearchInputComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have no library constraint by default', () => {
|
it('should have no library constraint by default', () => {
|
||||||
expect(component.hasLibraryConstraint()).toBe(false);
|
expect(component.evaluateLibrariesConstraint()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have library constraint on 400 error received', async () => {
|
it('should have library constraint on 400 error received', async () => {
|
||||||
@@ -103,7 +103,7 @@ describe('SearchInputComponent', () => {
|
|||||||
|
|
||||||
appHookService.library400Error.next();
|
appHookService.library400Error.next();
|
||||||
|
|
||||||
expect(component.hasLibraryConstraint()).toBe(true);
|
expect(component.evaluateLibrariesConstraint()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onSearchSubmit()', () => {
|
describe('onSearchSubmit()', () => {
|
||||||
|
@@ -49,6 +49,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
hasNewChange = false;
|
hasNewChange = false;
|
||||||
navigationTimer: any;
|
navigationTimer: any;
|
||||||
has400LibraryError = false;
|
has400LibraryError = false;
|
||||||
|
hasLibrariesConstraint = false;
|
||||||
searchOnChange: boolean;
|
searchOnChange: boolean;
|
||||||
|
|
||||||
searchedWord: string = null;
|
searchedWord: string = null;
|
||||||
@@ -106,6 +107,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.appHookService.library400Error.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
this.appHookService.library400Error.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||||
this.has400LibraryError = true;
|
this.has400LibraryError = true;
|
||||||
|
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +118,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
showInputValue() {
|
showInputValue() {
|
||||||
this.appService.appNavNarMode$.next('collapsed');
|
this.appService.appNavNarMode$.next('collapsed');
|
||||||
this.has400LibraryError = false;
|
this.has400LibraryError = false;
|
||||||
|
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
|
||||||
this.searchedWord = this.getUrlSearchTerm();
|
this.searchedWord = this.getUrlSearchTerm();
|
||||||
|
|
||||||
if (this.searchInputControl) {
|
if (this.searchInputControl) {
|
||||||
@@ -162,6 +165,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.has400LibraryError = false;
|
this.has400LibraryError = false;
|
||||||
|
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
|
||||||
this.searchedWord = searchTerm;
|
this.searchedWord = searchTerm;
|
||||||
|
|
||||||
if (this.hasOneChange) {
|
if (this.hasOneChange) {
|
||||||
@@ -187,6 +191,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
this.syncInputValues();
|
this.syncInputValues();
|
||||||
this.has400LibraryError = false;
|
this.has400LibraryError = false;
|
||||||
if (this.isLibrariesChecked()) {
|
if (this.isLibrariesChecked()) {
|
||||||
|
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
|
||||||
if (this.onLibrariesSearchResults && this.isSameSearchTerm()) {
|
if (this.onLibrariesSearchResults && this.isSameSearchTerm()) {
|
||||||
this.queryLibrariesBuilder.update();
|
this.queryLibrariesBuilder.update();
|
||||||
} else if (this.searchedWord) {
|
} else if (this.searchedWord) {
|
||||||
@@ -238,7 +243,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
|
|||||||
return this.isFilesChecked() || this.isFoldersChecked();
|
return this.isFilesChecked() || this.isFoldersChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
hasLibraryConstraint(): boolean {
|
evaluateLibrariesConstraint(): boolean {
|
||||||
if (this.isLibrariesChecked()) {
|
if (this.isLibrariesChecked()) {
|
||||||
return this.has400LibraryError || this.searchInputControl.isTermTooShort();
|
return this.has400LibraryError || this.searchInputControl.isTermTooShort();
|
||||||
}
|
}
|
||||||
|
@@ -79,7 +79,7 @@
|
|||||||
</adf-custom-empty-content-template>
|
</adf-custom-empty-content-template>
|
||||||
</adf-document-list>
|
</adf-document-list>
|
||||||
|
|
||||||
<adf-pagination *ngIf="!documentList.isEmpty()" acaPagination [target]="documentList" (change)="onPaginationChanged($event)">
|
<adf-pagination *ngIf="totalResults > 0" acaPagination [target]="documentList" (change)="onPaginationChanged($event)">
|
||||||
</adf-pagination>
|
</adf-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -50,6 +50,8 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
|
|||||||
name$ = new BehaviorSubject<string>('');
|
name$ = new BehaviorSubject<string>('');
|
||||||
title$ = new BehaviorSubject<string>('');
|
title$ = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
|
isFile = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private nodesApiService: NodesApiService,
|
private nodesApiService: NodesApiService,
|
||||||
@@ -77,6 +79,7 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private updateValues() {
|
private updateValues() {
|
||||||
this.node = this.context.row.node;
|
this.node = this.context.row.node;
|
||||||
|
this.isFile = this.node.entry.isFile;
|
||||||
|
|
||||||
const { name, properties } = this.node.entry;
|
const { name, properties } = this.node.entry;
|
||||||
const title = properties ? properties['cm:title'] : '';
|
const title = properties ? properties['cm:title'] : '';
|
||||||
@@ -93,10 +96,6 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
|
|||||||
this.onDestroy$.complete();
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isFile(): boolean {
|
|
||||||
return this.node.entry.isFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
showPreview(event: Event) {
|
showPreview(event: Event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (this.fileAutoDownloadService.shouldFileAutoDownload(this.node.entry.content.sizeInBytes)) {
|
if (this.fileAutoDownloadService.shouldFileAutoDownload(this.node.entry.content.sizeInBytes)) {
|
||||||
|
@@ -95,7 +95,7 @@
|
|||||||
</adf-custom-empty-content-template>
|
</adf-custom-empty-content-template>
|
||||||
</adf-document-list>
|
</adf-document-list>
|
||||||
|
|
||||||
<adf-pagination *ngIf="!documentList.isEmpty()" acaPagination [target]="documentList" (change)="onPaginationChanged($event)">
|
<adf-pagination *ngIf="totalResults > 0" acaPagination [target]="documentList" (change)="onPaginationChanged($event)">
|
||||||
</adf-pagination>
|
</adf-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -56,6 +56,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
|||||||
data: ResultSetPaging;
|
data: ResultSetPaging;
|
||||||
sorting = ['name', 'asc'];
|
sorting = ['name', 'asc'];
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
totalResults: number;
|
||||||
|
|
||||||
constructor(private queryBuilder: SearchQueryBuilderService, private route: ActivatedRoute, private translationService: TranslationService) {
|
constructor(private queryBuilder: SearchQueryBuilderService, private route: ActivatedRoute, private translationService: TranslationService) {
|
||||||
super();
|
super();
|
||||||
@@ -191,6 +192,14 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
|||||||
|
|
||||||
onSearchResultLoaded(nodePaging: ResultSetPaging) {
|
onSearchResultLoaded(nodePaging: ResultSetPaging) {
|
||||||
this.data = nodePaging;
|
this.data = nodePaging;
|
||||||
|
this.totalResults = this.getNumberOfResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
getNumberOfResults() {
|
||||||
|
if (this.data?.list?.pagination) {
|
||||||
|
return this.data.list.pagination.totalItems;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
onPaginationChanged(pagination: Pagination) {
|
onPaginationChanged(pagination: Pagination) {
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
[attr.aria-label]="item.title | translate"
|
[attr.aria-label]="item.title | translate"
|
||||||
class="action-button"
|
class="action-button"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'action-button--active': acaMenuPanel.hasActiveLinks()
|
'action-button--active': acaMenuPanel.hasActiveChildren
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<adf-icon [value]="item.icon"></adf-icon>
|
<adf-icon [value]="item.icon"></adf-icon>
|
||||||
|
@@ -27,22 +27,25 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
describe('DocumentDisplayModeComponent', () => {
|
describe('DocumentDisplayModeComponent', () => {
|
||||||
let component: DocumentDisplayModeComponent;
|
|
||||||
let fixture: ComponentFixture<DocumentDisplayModeComponent>;
|
let fixture: ComponentFixture<DocumentDisplayModeComponent>;
|
||||||
|
let store: Store;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CoreModule, AppTestingModule]
|
imports: [CoreModule, AppTestingModule],
|
||||||
|
providers: [provideMockStore()]
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture = TestBed.createComponent(DocumentDisplayModeComponent);
|
fixture = TestBed.createComponent(DocumentDisplayModeComponent);
|
||||||
component = fixture.componentInstance;
|
store = TestBed.inject(Store);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the list button when list', async () => {
|
it('should show the list button when list', async () => {
|
||||||
component.displayMode$ = of('list');
|
spyOn(store, 'select').and.returnValue(of('list'));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
@@ -50,11 +53,10 @@ describe('DocumentDisplayModeComponent', () => {
|
|||||||
expect(displayButton.title).toBe('APP.ACTIONS.LIST_MODE');
|
expect(displayButton.title).toBe('APP.ACTIONS.LIST_MODE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the gallery button when list', async () => {
|
it('should show the gallery button when gallery', async () => {
|
||||||
component.displayMode$ = of('gallery');
|
spyOn(store, 'select').and.returnValue(of('gallery'));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
|
|
||||||
const displayButton: HTMLButtonElement = fixture.nativeElement.querySelector('#app-document-display-mode-button');
|
const displayButton: HTMLButtonElement = fixture.nativeElement.querySelector('#app-document-display-mode-button');
|
||||||
expect(displayButton.title).toBe('APP.ACTIONS.GALLERY_MODE');
|
expect(displayButton.title).toBe('APP.ACTIONS.GALLERY_MODE');
|
||||||
});
|
});
|
||||||
|
@@ -22,10 +22,11 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation } from '@angular/core';
|
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@alfresco/aca-shared/store';
|
import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@alfresco/aca-shared/store';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-document-display-mode',
|
selector: 'app-document-display-mode',
|
||||||
@@ -33,8 +34,8 @@ import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@al
|
|||||||
<ng-container *ngIf="displayMode$ | async as displayMode">
|
<ng-container *ngIf="displayMode$ | async as displayMode">
|
||||||
<button
|
<button
|
||||||
id="app-document-display-mode-button"
|
id="app-document-display-mode-button"
|
||||||
[attr.title]="getTitle(displayMode) | translate"
|
[attr.title]="displayModeTitle | translate"
|
||||||
[attr.aria-label]="getTitle(displayMode) | translate"
|
[attr.aria-label]="displayModeTitle | translate"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
color="primary"
|
color="primary"
|
||||||
(click)="onClick()"
|
(click)="onClick()"
|
||||||
@@ -47,15 +48,24 @@ import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@al
|
|||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'app-document-display-mode' }
|
host: { class: 'app-document-display-mode' }
|
||||||
})
|
})
|
||||||
export class DocumentDisplayModeComponent {
|
export class DocumentDisplayModeComponent implements OnInit, OnDestroy {
|
||||||
displayMode$: Observable<string>;
|
displayMode$: Observable<string>;
|
||||||
|
displayModeTitle: string;
|
||||||
|
|
||||||
constructor(private store: Store<AppStore>) {
|
onDestroy$ = new Subject<void>();
|
||||||
this.displayMode$ = store.select(getDocumentDisplayMode);
|
|
||||||
|
constructor(private store: Store<AppStore>) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.displayMode$ = this.store.select(getDocumentDisplayMode);
|
||||||
|
this.displayMode$.pipe(takeUntil(this.onDestroy$)).subscribe((displayMode) => {
|
||||||
|
this.displayModeTitle = displayMode === 'list' ? 'APP.ACTIONS.LIST_MODE' : 'APP.ACTIONS.GALLERY_MODE';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getTitle(displayMode: string): string {
|
ngOnDestroy(): void {
|
||||||
return displayMode === 'list' ? 'APP.ACTIONS.LIST_MODE' : 'APP.ACTIONS.GALLERY_MODE';
|
this.onDestroy$.next();
|
||||||
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick() {
|
onClick() {
|
||||||
|
@@ -32,11 +32,7 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-toggle-edit-offline',
|
selector: 'app-toggle-edit-offline',
|
||||||
template: `
|
template: `
|
||||||
<button
|
<button mat-menu-item [attr.title]="nodeTitle | translate" (click)="onClick()">
|
||||||
mat-menu-item
|
|
||||||
[attr.title]="(isNodeLocked ? 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' : 'APP.ACTIONS.EDIT_OFFLINE') | translate"
|
|
||||||
(click)="onClick()"
|
|
||||||
>
|
|
||||||
<ng-container *ngIf="isNodeLocked">
|
<ng-container *ngIf="isNodeLocked">
|
||||||
<mat-icon>cancel</mat-icon>
|
<mat-icon>cancel</mat-icon>
|
||||||
<span>{{ 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' | translate }}</span>
|
<span>{{ 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' | translate }}</span>
|
||||||
@@ -54,6 +50,8 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
|
|||||||
export class ToggleEditOfflineComponent implements OnInit {
|
export class ToggleEditOfflineComponent implements OnInit {
|
||||||
private nodesApi: NodesApi;
|
private nodesApi: NodesApi;
|
||||||
selection: MinimalNodeEntity;
|
selection: MinimalNodeEntity;
|
||||||
|
nodeTitle = '';
|
||||||
|
isNodeLocked = false;
|
||||||
|
|
||||||
constructor(private store: Store<AppStore>, private alfrescoApiService: AlfrescoApiService) {
|
constructor(private store: Store<AppStore>, private alfrescoApiService: AlfrescoApiService) {
|
||||||
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
|
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
|
||||||
@@ -62,13 +60,11 @@ export class ToggleEditOfflineComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.store.select(getAppSelection).subscribe(({ file }) => {
|
this.store.select(getAppSelection).subscribe(({ file }) => {
|
||||||
this.selection = file;
|
this.selection = file;
|
||||||
|
this.isNodeLocked = this.selection && isLocked(this.selection);
|
||||||
|
this.nodeTitle = this.isNodeLocked ? 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' : 'APP.ACTIONS.EDIT_OFFLINE';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get isNodeLocked(): boolean {
|
|
||||||
return !!(this.selection && isLocked(this.selection));
|
|
||||||
}
|
|
||||||
|
|
||||||
async onClick() {
|
async onClick() {
|
||||||
await this.toggleLock(this.selection);
|
await this.toggleLock(this.selection);
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
<div class="app-general-edit-btn" *ngIf="!generalSectionButtonsToggle">
|
<div class="app-general-edit-btn" *ngIf="!generalSectionButtonsToggle">
|
||||||
<button mat-raised-button class="app-general-cancel-btn" id="general-cancel-button"
|
<button mat-raised-button class="app-general-cancel-btn" id="general-cancel-button"
|
||||||
(click)="toggleGeneralButtons()">{{'APP.EDIT_PROFILE.CANCEL' | translate}}</button>
|
(click)="toggleGeneralButtons()">{{'APP.EDIT_PROFILE.CANCEL' | translate}}</button>
|
||||||
<button mat-raised-button class="app-general-save-btn" id="general-save-button" [disabled]="isSaveButtonDisabled()"
|
<button mat-raised-button class="app-general-save-btn" id="general-save-button" [disabled]="profileForm.invalid"
|
||||||
(click)="onSaveGeneralData(profileForm)">{{'APP.EDIT_PROFILE.SAVE' | translate}}</button>
|
(click)="onSaveGeneralData(profileForm)">{{'APP.EDIT_PROFILE.SAVE' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<div class="app-general-edit-btn" *ngIf="!contactSectionButtonsToggle">
|
<div class="app-general-edit-btn" *ngIf="!contactSectionButtonsToggle">
|
||||||
<button mat-raised-button class="app-general-cancel-btn" id="contact-cancel-button"
|
<button mat-raised-button class="app-general-cancel-btn" id="contact-cancel-button"
|
||||||
(click)="toggleContactButtons()">{{'APP.EDIT_PROFILE.CANCEL' | translate}}</button>
|
(click)="toggleContactButtons()">{{'APP.EDIT_PROFILE.CANCEL' | translate}}</button>
|
||||||
<button mat-raised-button class="app-general-save-btn" id="contact-save-button" [disabled]="isSaveButtonDisabled()"
|
<button mat-raised-button class="app-general-save-btn" id="contact-save-button" [disabled]="profileForm.invalid"
|
||||||
(click)="onSaveCompanyData(profileForm)">{{'APP.EDIT_PROFILE.SAVE' | translate}}</button>
|
(click)="onSaveCompanyData(profileForm)">{{'APP.EDIT_PROFILE.SAVE' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,4 +142,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<h2 mat-dialog-title [innerHTML]="title()"></h2>
|
<h2 mat-dialog-title [innerHTML]="title"></h2>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<form [formGroup]="form" novalidate>
|
<form [formGroup]="form" novalidate>
|
||||||
<mat-form-field class="adf-full-width">
|
<mat-form-field class="adf-full-width">
|
||||||
|
@@ -45,6 +45,8 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
export class CreateFromTemplateDialogComponent implements OnInit {
|
export class CreateFromTemplateDialogComponent implements OnInit {
|
||||||
public form: UntypedFormGroup;
|
public form: UntypedFormGroup;
|
||||||
|
|
||||||
|
title = '';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private translationService: TranslationService,
|
private translationService: TranslationService,
|
||||||
private store: Store<AppStore>,
|
private store: Store<AppStore>,
|
||||||
@@ -59,6 +61,11 @@ export class CreateFromTemplateDialogComponent implements OnInit {
|
|||||||
title: [this.data.properties ? this.data.properties['cm:title'] : '', Validators.maxLength(256)],
|
title: [this.data.properties ? this.data.properties['cm:title'] : '', Validators.maxLength(256)],
|
||||||
description: [this.data.properties ? this.data.properties['cm:description'] : '', Validators.maxLength(512)]
|
description: [this.data.properties ? this.data.properties['cm:description'] : '', Validators.maxLength(512)]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.title = this.translationService.instant(
|
||||||
|
this.data.isFolder ? 'NODE_FROM_TEMPLATE.FOLDER_DIALOG_TITLE' : 'NODE_FROM_TEMPLATE.FILE_DIALOG_TITLE',
|
||||||
|
{ template: this.data.name }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
@@ -73,14 +80,6 @@ export class CreateFromTemplateDialogComponent implements OnInit {
|
|||||||
this.store.dispatch(new CreateFromTemplate(data));
|
this.store.dispatch(new CreateFromTemplate(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
title(): string {
|
|
||||||
if (this.data.isFolder) {
|
|
||||||
return this.translationService.instant('NODE_FROM_TEMPLATE.FOLDER_DIALOG_TITLE', { template: this.data.name });
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.translationService.instant('NODE_FROM_TEMPLATE.FILE_DIALOG_TITLE', { template: this.data.name });
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
}
|
}
|
||||||
|
@@ -47,7 +47,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
*ngIf="canEditRule(mainRuleSet$ | async)"
|
*ngIf="canEditMainRule"
|
||||||
data-automation-id="manage-rules-create-button"
|
data-automation-id="manage-rules-create-button"
|
||||||
mat-flat-button color="primary"
|
mat-flat-button color="primary"
|
||||||
(click)="openCreateUpdateRuleDialog()">
|
(click)="openCreateUpdateRuleDialog()">
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
</adf-toolbar>
|
</adf-toolbar>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<div class="aca-manage-rules__container" *ngIf="isMainRuleSetNotEmpty(mainRuleSet$ | async) || isInheritedRuleSetsNotEmpty(inheritedRuleSets$ | async); else emptyContent">
|
<div class="aca-manage-rules__container" *ngIf="isMainRuleSetNotEmpty || isInheritedRuleSetsNotEmpty; else emptyContent">
|
||||||
<aca-rule-list
|
<aca-rule-list
|
||||||
[mainRuleSet]="mainRuleSet$ | async"
|
[mainRuleSet]="mainRuleSet$ | async"
|
||||||
[folderId]="nodeId"
|
[folderId]="nodeId"
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="aca-manage-rules__container__rule-details__header__buttons">
|
<div class="aca-manage-rules__container__rule-details__header__buttons">
|
||||||
<ng-container *ngIf="canEditRule(selectedRuleSet$ | async); else goToFolderButton">
|
<ng-container *ngIf="canEditSelectedRule; else goToFolderButton">
|
||||||
<button mat-stroked-button (click)="onRuleDeleteButtonClicked(selectedRule)" id="delete-rule-btn">
|
<button mat-stroked-button (click)="onRuleDeleteButtonClicked(selectedRule)" id="delete-rule-btn">
|
||||||
<mat-icon>delete_outline</mat-icon>
|
<mat-icon>delete_outline</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { FolderRulesService } from '../services/folder-rules.service';
|
import { FolderRulesService } from '../services/folder-rules.service';
|
||||||
import { Observable, Subject, Subscription } from 'rxjs';
|
import { Observable, Subject, Subscription } from 'rxjs';
|
||||||
@@ -47,6 +47,7 @@ import { ActionParameterConstraint } from '../model/action-parameter-constraint.
|
|||||||
templateUrl: 'manage-rules.smart-component.html',
|
templateUrl: 'manage-rules.smart-component.html',
|
||||||
styleUrls: ['manage-rules.smart-component.scss'],
|
styleUrls: ['manage-rules.smart-component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.Default,
|
||||||
host: { class: 'aca-manage-rules' }
|
host: { class: 'aca-manage-rules' }
|
||||||
})
|
})
|
||||||
export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
||||||
@@ -65,6 +66,10 @@ export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
|||||||
actionsLoading$: Observable<boolean>;
|
actionsLoading$: Observable<boolean>;
|
||||||
actionDefinitions$: Observable<ActionDefinitionTransformed[]>;
|
actionDefinitions$: Observable<ActionDefinitionTransformed[]>;
|
||||||
parameterConstraints$: Observable<ActionParameterConstraint[]>;
|
parameterConstraints$: Observable<ActionParameterConstraint[]>;
|
||||||
|
canEditMainRule = false;
|
||||||
|
canEditSelectedRule = false;
|
||||||
|
isMainRuleSetNotEmpty = false;
|
||||||
|
isInheritedRuleSetsNotEmpty = false;
|
||||||
|
|
||||||
private destroyed$ = new Subject<void>();
|
private destroyed$ = new Subject<void>();
|
||||||
private _actionDefinitionsSub: Subscription;
|
private _actionDefinitionsSub: Subscription;
|
||||||
@@ -110,6 +115,19 @@ export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
|||||||
this._actionDefinitionsSub = this.actionDefinitions$.subscribe((actionDefinitions: ActionDefinitionTransformed[]) =>
|
this._actionDefinitionsSub = this.actionDefinitions$.subscribe((actionDefinitions: ActionDefinitionTransformed[]) =>
|
||||||
this.actionsService.loadActionParameterConstraints(actionDefinitions)
|
this.actionsService.loadActionParameterConstraints(actionDefinitions)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.mainRuleSet$.pipe(takeUntil(this.destroyed$)).subscribe((ruleSet) => {
|
||||||
|
this.canEditMainRule = this.canEditRule(ruleSet);
|
||||||
|
this.isMainRuleSetNotEmpty = !!ruleSet;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.inheritedRuleSets$.pipe(takeUntil(this.destroyed$)).subscribe((inheritedRuleSet) => {
|
||||||
|
this.isInheritedRuleSetsNotEmpty = inheritedRuleSet.some((ruleSet) => ruleSet.rules.some((rule: Rule) => rule.isEnabled));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.selectedRuleSet$.pipe(takeUntil(this.destroyed$)).subscribe((ruleSet) => {
|
||||||
|
this.canEditSelectedRule = this.canEditRule(ruleSet);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@@ -251,12 +269,4 @@ export class ManageRulesSmartComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isMainRuleSetNotEmpty(mainRuleSet: RuleSet): boolean {
|
|
||||||
return !!mainRuleSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
isInheritedRuleSetsNotEmpty(inheritedRuleSets: RuleSet[]): boolean {
|
|
||||||
return inheritedRuleSets.some((ruleSet) => ruleSet.rules.some((rule: Rule) => rule.isEnabled));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
mat-menu-item
|
mat-menu-item
|
||||||
data-automation-id="rule-action-list-remove-action-button"
|
data-automation-id="rule-action-list-remove-action-button"
|
||||||
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate"
|
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate"
|
||||||
[disabled]="formArray.controls.length <= 1"
|
[disabled]="formControls.length <= 1"
|
||||||
(click)="removeAction(control)">
|
(click)="removeAction(control)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate }}</span>
|
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate }}</span>
|
||||||
|
@@ -56,9 +56,7 @@ export class RuleActionListUiComponent implements ControlValueAccessor, OnDestro
|
|||||||
formArray = new FormArray([]);
|
formArray = new FormArray([]);
|
||||||
private formArraySubscription: Subscription;
|
private formArraySubscription: Subscription;
|
||||||
|
|
||||||
get formControls(): FormControl[] {
|
formControls: FormControl[] = [];
|
||||||
return this.formArray.controls as FormControl[];
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange: (actions: RuleAction[]) => void = () => undefined;
|
onChange: (actions: RuleAction[]) => void = () => undefined;
|
||||||
onTouch: () => void = () => undefined;
|
onTouch: () => void = () => undefined;
|
||||||
@@ -73,6 +71,7 @@ export class RuleActionListUiComponent implements ControlValueAccessor, OnDestro
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
this.formArray = new FormArray(actions.map((action: RuleAction) => new FormControl(action)));
|
this.formArray = new FormArray(actions.map((action: RuleAction) => new FormControl(action)));
|
||||||
|
this.formControls = this.formArray.controls as FormControl[];
|
||||||
this.formArraySubscription?.unsubscribe();
|
this.formArraySubscription?.unsubscribe();
|
||||||
this.formArraySubscription = this.formArray.valueChanges.subscribe((value: any) => {
|
this.formArraySubscription = this.formArray.valueChanges.subscribe((value: any) => {
|
||||||
this.onChange(value);
|
this.onChange(value);
|
||||||
@@ -94,6 +93,7 @@ export class RuleActionListUiComponent implements ControlValueAccessor, OnDestro
|
|||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
this.formArray.push(new FormControl(newAction, [Validators.required, ruleActionValidator(this.actionDefinitions)]));
|
this.formArray.push(new FormControl(newAction, [Validators.required, ruleActionValidator(this.actionDefinitions)]));
|
||||||
|
this.formControls = this.formArray.controls as FormControl[];
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@@ -103,5 +103,6 @@ export class RuleActionListUiComponent implements ControlValueAccessor, OnDestro
|
|||||||
removeAction(control: FormControl) {
|
removeAction(control: FormControl) {
|
||||||
const index = this.formArray.value.indexOf(control.value);
|
const index = this.formArray.value.indexOf(control.value);
|
||||||
this.formArray.removeAt(index);
|
this.formArray.removeAt(index);
|
||||||
|
this.formControls = this.formArray.controls as FormControl[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
<adf-card-view
|
<adf-card-view
|
||||||
data-automation-id="rule-action-card-view"
|
data-automation-id="rule-action-card-view"
|
||||||
[properties]="cardViewItems"
|
[properties]="cardViewItems"
|
||||||
[ngStyle]="cardViewStyle"
|
[ngClass]="{ 'aca-rule-action-full-width': isFullWidth }"
|
||||||
[editable]="!readOnly">
|
[editable]="!readOnly">
|
||||||
</adf-card-view>
|
</adf-card-view>
|
||||||
|
|
||||||
|
@@ -8,4 +8,8 @@
|
|||||||
width: 280px;
|
width: 280px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, forwardRef, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, forwardRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||||
import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||||
import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model';
|
import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model';
|
||||||
import { CardViewItem } from '@alfresco/adf-core/lib/card-view/interfaces/card-view-item.interface';
|
import { CardViewItem } from '@alfresco/adf-core/lib/card-view/interfaces/card-view-item.interface';
|
||||||
@@ -57,27 +57,15 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
CardViewUpdateService
|
CardViewUpdateService
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDestroy {
|
export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnChanges, OnDestroy {
|
||||||
@Input()
|
@Input()
|
||||||
nodeId = '';
|
nodeId = '';
|
||||||
|
|
||||||
private _actionDefinitions: ActionDefinitionTransformed[];
|
|
||||||
@Input()
|
@Input()
|
||||||
get actionDefinitions(): ActionDefinitionTransformed[] {
|
actionDefinitions: ActionDefinitionTransformed[];
|
||||||
return this._actionDefinitions;
|
|
||||||
}
|
|
||||||
set actionDefinitions(value: ActionDefinitionTransformed[]) {
|
|
||||||
this._actionDefinitions = value.sort((a, b) => a.title.localeCompare(b.title));
|
|
||||||
}
|
|
||||||
|
|
||||||
private _readOnly = false;
|
|
||||||
@Input()
|
@Input()
|
||||||
get readOnly(): boolean {
|
readOnly = false;
|
||||||
return this._readOnly;
|
|
||||||
}
|
|
||||||
set readOnly(isReadOnly: boolean) {
|
|
||||||
this.setDisabledState(isReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _parameterConstraints = [];
|
private _parameterConstraints = [];
|
||||||
@Input()
|
@Input()
|
||||||
@@ -135,6 +123,10 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.actionDefinitions = this.actionDefinitions.sort((firstActionDefinition, secondActionDefinition) =>
|
||||||
|
firstActionDefinition.title.localeCompare(secondActionDefinition.title)
|
||||||
|
);
|
||||||
|
|
||||||
this.form.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
this.form.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||||
this.setDefaultParameters();
|
this.setDefaultParameters();
|
||||||
this.setCardViewProperties();
|
this.setCardViewProperties();
|
||||||
@@ -158,6 +150,14 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
const readOnly = changes['readOnly']?.currentValue;
|
||||||
|
if (readOnly !== undefined && readOnly !== null) {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
this.setDisabledState(readOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.onDestroy$.next();
|
this.onDestroy$.next();
|
||||||
this.onDestroy$.complete();
|
this.onDestroy$.complete();
|
||||||
@@ -272,10 +272,10 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
|
|||||||
|
|
||||||
setDisabledState(isDisabled: boolean) {
|
setDisabledState(isDisabled: boolean) {
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
this._readOnly = true;
|
this.readOnly = true;
|
||||||
this.form.disable();
|
this.form.disable();
|
||||||
} else {
|
} else {
|
||||||
this._readOnly = false;
|
this.readOnly = false;
|
||||||
this.form.enable();
|
this.form.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,9 +9,8 @@
|
|||||||
|
|
||||||
<mat-form-field *ngIf="i === 0">
|
<mat-form-field *ngIf="i === 0">
|
||||||
<mat-select
|
<mat-select
|
||||||
[value]="invertedControl.value"
|
[formControl]="invertedControl"
|
||||||
[disabled]="readOnly"
|
[disabled]="readOnly">
|
||||||
(selectionChange)="setInverted($event.value)">
|
|
||||||
<mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option>
|
<mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option>
|
||||||
<mat-option [value]="true">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.NOT_IF' | translate }}</mat-option>
|
<mat-option [value]="true">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.NOT_IF' | translate }}</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
@@ -19,9 +18,8 @@
|
|||||||
|
|
||||||
<mat-form-field *ngIf="i > 0">
|
<mat-form-field *ngIf="i > 0">
|
||||||
<mat-select
|
<mat-select
|
||||||
[value]="booleanModeControl.value"
|
|
||||||
[disabled]="!isOrImplemented || i > 1 || readOnly"
|
[disabled]="!isOrImplemented || i > 1 || readOnly"
|
||||||
(selectionChange)="setBooleanMode($event.value)">
|
[formControl]="booleanModeControl">
|
||||||
<mat-option value="and">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.AND' | translate }}</mat-option>
|
<mat-option value="and">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.AND' | translate }}</mat-option>
|
||||||
<mat-option value="or">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.OR' | translate }}</mat-option>
|
<mat-option value="or">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.OR' | translate }}</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, forwardRef, HostBinding, Input, OnDestroy, ViewEncapsulation } from '@angular/core';
|
import { Component, forwardRef, HostBinding, Input, OnChanges, OnDestroy, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||||
import { RuleCompositeCondition } from '../../model/rule-composite-condition.model';
|
import { RuleCompositeCondition } from '../../model/rule-composite-condition.model';
|
||||||
import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
|
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
|
||||||
@@ -41,7 +41,7 @@ import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class RuleCompositeConditionUiComponent implements ControlValueAccessor, OnDestroy {
|
export class RuleCompositeConditionUiComponent implements ControlValueAccessor, OnDestroy, OnChanges {
|
||||||
@HostBinding('class.secondaryBackground')
|
@HostBinding('class.secondaryBackground')
|
||||||
@Input()
|
@Input()
|
||||||
secondaryBackground = false;
|
secondaryBackground = false;
|
||||||
@@ -58,26 +58,17 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
|||||||
|
|
||||||
readonly isOrImplemented = false;
|
readonly isOrImplemented = false;
|
||||||
|
|
||||||
private _readOnly = false;
|
|
||||||
@Input()
|
@Input()
|
||||||
get readOnly(): boolean {
|
public readOnly = false;
|
||||||
return this._readOnly;
|
|
||||||
}
|
|
||||||
set readOnly(isReadOnly: boolean) {
|
|
||||||
this.setDisabledState(isReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
private formSubscription = this.form.valueChanges.subscribe((value: any) => {
|
private formSubscription = this.form.valueChanges.subscribe((value: any) => {
|
||||||
this.onChange(value);
|
this.onChange(value);
|
||||||
this.onTouch();
|
this.onTouch();
|
||||||
});
|
});
|
||||||
|
|
||||||
get invertedControl(): FormControl {
|
public invertedControl = this.form.get('inverted') as FormControl;
|
||||||
return this.form.get('inverted') as FormControl;
|
public booleanModeControl = this.form.get('booleanMode') as FormControl;
|
||||||
}
|
|
||||||
get booleanModeControl(): FormControl {
|
|
||||||
return this.form.get('booleanMode') as FormControl;
|
|
||||||
}
|
|
||||||
get compositeConditionsFormArray(): FormArray {
|
get compositeConditionsFormArray(): FormArray {
|
||||||
return this.form.get('compositeConditions') as FormArray;
|
return this.form.get('compositeConditions') as FormArray;
|
||||||
}
|
}
|
||||||
@@ -111,22 +102,14 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
|||||||
|
|
||||||
setDisabledState(isDisabled: boolean) {
|
setDisabledState(isDisabled: boolean) {
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
this._readOnly = true;
|
this.readOnly = true;
|
||||||
this.form.disable();
|
this.form.disable();
|
||||||
} else {
|
} else {
|
||||||
this._readOnly = false;
|
this.readOnly = false;
|
||||||
this.form.enable();
|
this.form.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInverted(value: boolean) {
|
|
||||||
this.invertedControl.setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
setBooleanMode(value: 'and' | 'or') {
|
|
||||||
this.booleanModeControl.setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
isFormControlSimpleCondition(control: FormControl): boolean {
|
isFormControlSimpleCondition(control: FormControl): boolean {
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
// eslint-disable-next-line no-prototype-builtins
|
||||||
return control.value.hasOwnProperty('field');
|
return control.value.hasOwnProperty('field');
|
||||||
@@ -160,4 +143,12 @@ export class RuleCompositeConditionUiComponent implements ControlValueAccessor,
|
|||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.formSubscription.unsubscribe();
|
this.formSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
const readOnly = changes['readOnly'].currentValue;
|
||||||
|
if (readOnly !== undefined && readOnly !== null) {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
this.setDisabledState(readOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -52,6 +52,9 @@ export class EditRuleDialogUiComponent {
|
|||||||
formValue: Partial<Rule>;
|
formValue: Partial<Rule>;
|
||||||
@Output() submitted = new EventEmitter<Partial<Rule>>();
|
@Output() submitted = new EventEmitter<Partial<Rule>>();
|
||||||
|
|
||||||
|
title = 'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.' + (this.isUpdateMode ? 'UPDATE_TITLE' : 'CREATE_TITLE');
|
||||||
|
submitLabel = 'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.' + (this.isUpdateMode ? 'UPDATE' : 'CREATE');
|
||||||
|
|
||||||
constructor(@Inject(MAT_DIALOG_DATA) public data: EditRuleDialogOptions) {
|
constructor(@Inject(MAT_DIALOG_DATA) public data: EditRuleDialogOptions) {
|
||||||
this.model = this.data?.model || {};
|
this.model = this.data?.model || {};
|
||||||
this.nodeId = this.data?.nodeId;
|
this.nodeId = this.data?.nodeId;
|
||||||
@@ -62,15 +65,6 @@ export class EditRuleDialogUiComponent {
|
|||||||
get isUpdateMode(): boolean {
|
get isUpdateMode(): boolean {
|
||||||
return !!this.data?.model?.id;
|
return !!this.data?.model?.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get title(): string {
|
|
||||||
return 'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.' + (this.isUpdateMode ? 'UPDATE_TITLE' : 'CREATE_TITLE');
|
|
||||||
}
|
|
||||||
|
|
||||||
get submitLabel(): string {
|
|
||||||
return 'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.' + (this.isUpdateMode ? 'UPDATE' : 'CREATE');
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.submitted.emit(this.formValue);
|
this.submitted.emit(this.formValue);
|
||||||
}
|
}
|
||||||
|
@@ -18,14 +18,10 @@
|
|||||||
data-automation-id="rule-option-select-errorScript">
|
data-automation-id="rule-option-select-errorScript">
|
||||||
|
|
||||||
<mat-option value="">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT' | translate }}</mat-option>
|
<mat-option value="">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT' | translate }}</mat-option>
|
||||||
|
<mat-option *ngFor="let option of errorScriptOptions"
|
||||||
<ng-template ngFor [ngForOf]="errorScriptOptions" let-option>
|
|
||||||
<mat-option
|
|
||||||
[value]="option.value">
|
[value]="option.value">
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</ng-template>
|
|
||||||
|
|
||||||
</mat-select>
|
</mat-select>
|
||||||
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, forwardRef, HostBinding, Input, OnDestroy, ViewEncapsulation } from '@angular/core';
|
import { Component, forwardRef, HostBinding, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { AbstractControl, ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { AbstractControl, ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||||
import { RuleOptions } from '../../model/rule.model';
|
import { RuleOptions } from '../../model/rule.model';
|
||||||
@@ -42,7 +42,7 @@ import { ActionParameterConstraint, ConstraintValue } from '../../model/action-p
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class RuleOptionsUiComponent implements ControlValueAccessor, OnDestroy {
|
export class RuleOptionsUiComponent implements ControlValueAccessor, OnInit, OnDestroy {
|
||||||
form = new FormGroup({
|
form = new FormGroup({
|
||||||
isDisabled: new FormControl(),
|
isDisabled: new FormControl(),
|
||||||
isInheritable: new FormControl(),
|
isInheritable: new FormControl(),
|
||||||
@@ -51,6 +51,8 @@ export class RuleOptionsUiComponent implements ControlValueAccessor, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
formSubscription = this.form.valueChanges.subscribe((value: any) => {
|
formSubscription = this.form.valueChanges.subscribe((value: any) => {
|
||||||
|
this.isAsynchronousChecked = value.isAsynchronous;
|
||||||
|
this.isInheritableChecked = value.isInheritable;
|
||||||
this.onChange({
|
this.onChange({
|
||||||
isEnabled: !value.isDisabled,
|
isEnabled: !value.isDisabled,
|
||||||
isInheritable: value.isInheritable,
|
isInheritable: value.isInheritable,
|
||||||
@@ -71,16 +73,10 @@ export class RuleOptionsUiComponent implements ControlValueAccessor, OnDestroy {
|
|||||||
onChange: (options: RuleOptions) => void = () => undefined;
|
onChange: (options: RuleOptions) => void = () => undefined;
|
||||||
onTouch: () => void = () => undefined;
|
onTouch: () => void = () => undefined;
|
||||||
|
|
||||||
get isAsynchronousChecked(): boolean {
|
isAsynchronousChecked = false;
|
||||||
return this.form.get('isAsynchronous').value;
|
isInheritableChecked = false;
|
||||||
}
|
|
||||||
get isInheritableChecked(): boolean {
|
|
||||||
return this.form.get('isInheritable').value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get errorScriptOptions(): ConstraintValue[] {
|
errorScriptOptions: ConstraintValue[] = [];
|
||||||
return this.errorScriptConstraint?.constraints ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(options: RuleOptions) {
|
writeValue(options: RuleOptions) {
|
||||||
const isAsynchronousFormControl = this.form.get('isAsynchronous');
|
const isAsynchronousFormControl = this.form.get('isAsynchronous');
|
||||||
@@ -116,6 +112,10 @@ export class RuleOptionsUiComponent implements ControlValueAccessor, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.errorScriptOptions = this.errorScriptConstraint?.constraints ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.formSubscription.unsubscribe();
|
this.formSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@@ -8,8 +8,8 @@
|
|||||||
<input
|
<input
|
||||||
id="rule-details-name-input"
|
id="rule-details-name-input"
|
||||||
matInput type="text" formControlName="name" data-automation-id="rule-details-name-input"
|
matInput type="text" formControlName="name" data-automation-id="rule-details-name-input"
|
||||||
[placeholder]="getPlaceholder('name') | translate">
|
[placeholder]="'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.NAME' | translate">
|
||||||
<mat-error>{{ getErrorMessage(name) | translate }}</mat-error>
|
<mat-error>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.REQUIRED' | translate }}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<textarea
|
<textarea
|
||||||
id="rule-details-description-textarea"
|
id="rule-details-description-textarea"
|
||||||
matInput formControlName="description" data-automation-id="rule-details-description-textarea"
|
matInput formControlName="description" data-automation-id="rule-details-description-textarea"
|
||||||
[placeholder]="getPlaceholder('description') | translate">
|
[placeholder]="descriptionPlaceHolder | translate">
|
||||||
</textarea>
|
</textarea>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,13 +32,13 @@
|
|||||||
<div class="label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.WHEN' | translate }}</div>
|
<div class="label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.WHEN' | translate }}</div>
|
||||||
<div>
|
<div>
|
||||||
<aca-rule-triggers formControlName="triggers" data-automation-id="rule-details-triggers-component"></aca-rule-triggers>
|
<aca-rule-triggers formControlName="triggers" data-automation-id="rule-details-triggers-component"></aca-rule-triggers>
|
||||||
<mat-error class="rule-details-error">{{ getErrorMessage(triggers) | translate }}</mat-error>
|
<mat-error class="rule-details-error" *ngIf="triggers.hasError('required')">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.INSUFFICIENT_TRIGGERS_SELECTED' | translate }}</mat-error>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="aca-rule-details__form__conditions">
|
<div class="aca-rule-details__form__conditions">
|
||||||
<aca-rule-composite-condition formControlName="conditions"></aca-rule-composite-condition>
|
<aca-rule-composite-condition formControlName="conditions"></aca-rule-composite-condition>
|
||||||
<mat-error class="rule-details-error">{{ getErrorMessage(conditions) | translate }}</mat-error>
|
<mat-error class="rule-details-error" *ngIf="conditions.hasError('ruleCompositeConditionInvalid')">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.RULE_COMPOSITE_CONDITION_INVALID' | translate }}</mat-error>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="aca-rule-details__form__row aca-rule-details__form__actions">
|
<div class="aca-rule-details__form__row aca-rule-details__form__actions">
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
|
||||||
import { Rule, RuleForForm } from '../model/rule.model';
|
import { Rule, RuleForForm } from '../model/rule.model';
|
||||||
@@ -41,21 +41,11 @@ import { ActionParameterConstraint } from '../model/action-parameter-constraint.
|
|||||||
host: { class: 'aca-rule-details' }
|
host: { class: 'aca-rule-details' }
|
||||||
})
|
})
|
||||||
export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
||||||
private _readOnly = false;
|
|
||||||
@Input()
|
@Input()
|
||||||
get readOnly(): boolean {
|
readOnly: boolean;
|
||||||
return this._readOnly;
|
|
||||||
}
|
descriptionPlaceHolder: string;
|
||||||
set readOnly(value: boolean) {
|
|
||||||
this._readOnly = value;
|
|
||||||
if (this.form?.disable) {
|
|
||||||
if (value) {
|
|
||||||
this.form.disable();
|
|
||||||
} else {
|
|
||||||
this.form.enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private _initialValue: RuleForForm = FolderRulesService.emptyRuleForForm;
|
private _initialValue: RuleForForm = FolderRulesService.emptyRuleForForm;
|
||||||
@Input()
|
@Input()
|
||||||
get value(): Partial<Rule> {
|
get value(): Partial<Rule> {
|
||||||
@@ -107,6 +97,7 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
|||||||
private onDestroy$ = new Subject();
|
private onDestroy$ = new Subject();
|
||||||
form: UntypedFormGroup;
|
form: UntypedFormGroup;
|
||||||
|
|
||||||
|
errorScriptConstraint: ActionParameterConstraint;
|
||||||
get name(): UntypedFormControl {
|
get name(): UntypedFormControl {
|
||||||
return this.form.get('name') as UntypedFormControl;
|
return this.form.get('name') as UntypedFormControl;
|
||||||
}
|
}
|
||||||
@@ -116,6 +107,7 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
|||||||
get triggers(): UntypedFormControl {
|
get triggers(): UntypedFormControl {
|
||||||
return this.form.get('triggers') as UntypedFormControl;
|
return this.form.get('triggers') as UntypedFormControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
get conditions(): UntypedFormControl {
|
get conditions(): UntypedFormControl {
|
||||||
return this.form.get('conditions') as UntypedFormControl;
|
return this.form.get('conditions') as UntypedFormControl;
|
||||||
}
|
}
|
||||||
@@ -124,10 +116,6 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
|||||||
return !this.readOnly || this.value.isAsynchronous || this.value.isInheritable;
|
return !this.readOnly || this.value.isAsynchronous || this.value.isInheritable;
|
||||||
}
|
}
|
||||||
|
|
||||||
get errorScriptConstraint(): ActionParameterConstraint {
|
|
||||||
return this.parameterConstraints.find((parameterConstraint: ActionParameterConstraint) => parameterConstraint.name === 'script-ref');
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.form = new UntypedFormGroup({
|
this.form = new UntypedFormGroup({
|
||||||
id: new UntypedFormControl(this.value.id),
|
id: new UntypedFormControl(this.value.id),
|
||||||
@@ -151,7 +139,6 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
|||||||
errorScript: this.value.errorScript
|
errorScript: this.value.errorScript
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
this.readOnly = this._readOnly;
|
|
||||||
|
|
||||||
this.form.statusChanges
|
this.form.statusChanges
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -167,39 +154,24 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
|
|||||||
this.form.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
this.form.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||||
this.formValueChanged.emit(this.value);
|
this.formValueChanged.emit(this.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.readOnly) {
|
||||||
|
this.form.disable();
|
||||||
|
} else {
|
||||||
|
this.form.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.descriptionPlaceHolder = this.readOnly
|
||||||
|
? 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.NO_DESCRIPTION'
|
||||||
|
: 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.DESCRIPTION';
|
||||||
|
|
||||||
|
this.errorScriptConstraint = this.parameterConstraints.find(
|
||||||
|
(parameterConstraint: ActionParameterConstraint) => parameterConstraint.name === 'script-ref'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.onDestroy$.next();
|
this.onDestroy$.next();
|
||||||
this.onDestroy$.complete();
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
getErrorMessage(control: AbstractControl): string {
|
|
||||||
if (this.readOnly) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
if (control.hasError('required')) {
|
|
||||||
return control === this.triggers
|
|
||||||
? 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.INSUFFICIENT_TRIGGERS_SELECTED'
|
|
||||||
: 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.REQUIRED';
|
|
||||||
} else if (control.hasError('ruleCompositeConditionInvalid')) {
|
|
||||||
return 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.RULE_COMPOSITE_CONDITION_INVALID';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
getPlaceholder(fieldName: string): string {
|
|
||||||
let str = 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.';
|
|
||||||
switch (fieldName) {
|
|
||||||
case 'name':
|
|
||||||
str += 'NAME';
|
|
||||||
break;
|
|
||||||
case 'description':
|
|
||||||
str += this.readOnly ? 'NO_DESCRIPTION' : 'DESCRIPTION';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div *ngFor="let trigger of triggerOptions">
|
<div *ngFor="let trigger of triggerOptions">
|
||||||
<ng-container *ngIf="readOnly; else checkbox">
|
<ng-container *ngIf="readOnly; else checkbox">
|
||||||
<div
|
<div
|
||||||
*ngIf="isTriggerSelected(trigger)"
|
*ngIf="selectedTriggers[trigger]"
|
||||||
[attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase">
|
[attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase">
|
||||||
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
|
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
|
||||||
</div>
|
</div>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<ng-template #checkbox>
|
<ng-template #checkbox>
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
[attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase"
|
[attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase"
|
||||||
[checked]="isTriggerChecked(trigger)"
|
[checked]="selectedTriggers[trigger]"
|
||||||
(change)="onTriggerChange(trigger, $event.checked)">
|
(change)="onTriggerChange(trigger, $event.checked)">
|
||||||
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
|
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
|
@@ -42,6 +42,10 @@ import { RuleTrigger } from '../../model/rule.model';
|
|||||||
export class RuleTriggersUiComponent implements ControlValueAccessor {
|
export class RuleTriggersUiComponent implements ControlValueAccessor {
|
||||||
readonly triggerOptions: RuleTrigger[] = ['inbound', 'update', 'outbound'];
|
readonly triggerOptions: RuleTrigger[] = ['inbound', 'update', 'outbound'];
|
||||||
|
|
||||||
|
public selectedTriggers: { [key: string]: boolean } = {
|
||||||
|
inbound: true
|
||||||
|
};
|
||||||
|
|
||||||
value: RuleTrigger[] = ['inbound'];
|
value: RuleTrigger[] = ['inbound'];
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
|
|
||||||
@@ -50,6 +54,8 @@ export class RuleTriggersUiComponent implements ControlValueAccessor {
|
|||||||
|
|
||||||
writeValue(triggers: RuleTrigger[]) {
|
writeValue(triggers: RuleTrigger[]) {
|
||||||
this.value = triggers;
|
this.value = triggers;
|
||||||
|
this.selectedTriggers = {};
|
||||||
|
this.value.forEach((trigger) => (this.selectedTriggers[trigger] = true));
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOnChange(fn: () => void) {
|
registerOnChange(fn: () => void) {
|
||||||
@@ -64,10 +70,6 @@ export class RuleTriggersUiComponent implements ControlValueAccessor {
|
|||||||
this.readOnly = isDisabled;
|
this.readOnly = isDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
isTriggerChecked(trigger: RuleTrigger): boolean {
|
|
||||||
return this.value.includes(trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
onTriggerChange(trigger: RuleTrigger, checked: boolean) {
|
onTriggerChange(trigger: RuleTrigger, checked: boolean) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.value.push(trigger);
|
this.value.push(trigger);
|
||||||
@@ -77,11 +79,8 @@ export class RuleTriggersUiComponent implements ControlValueAccessor {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.selectedTriggers[trigger] = checked;
|
||||||
this.onTouch();
|
this.onTouch();
|
||||||
this.onChange([...this.value]);
|
this.onChange([...this.value]);
|
||||||
}
|
}
|
||||||
|
|
||||||
isTriggerSelected(trigger: RuleTrigger): boolean {
|
|
||||||
return this.value.includes(trigger);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
matRipple matRippleColor="hsla(0,0%,0%,0.05)"
|
matRipple matRippleColor="hsla(0,0%,0%,0.05)"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
[rule]="item.rule"
|
[rule]="item.rule"
|
||||||
[isSelected]="isSelected(item.rule)"
|
[isSelected]="item.rule.id === this.selectedRule?.id"
|
||||||
[showEnabledToggle]="showEnabledToggles"
|
[showEnabledToggle]="showEnabledToggles"
|
||||||
(click)="onRuleClicked(item.rule)"
|
(click)="onRuleClicked(item.rule)"
|
||||||
(enabledChanged)="onEnabledChanged(item.rule, $event)">
|
(enabledChanged)="onEnabledChanged(item.rule, $event)">
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #rulesLoaded>
|
<ng-template #rulesLoaded>
|
||||||
<ng-container *ngIf="hasOwnedRules(mainRuleSet$ | async); else noOwnedRules">
|
<ng-container *ngIf="hasOwnedRules; else noOwnedRules">
|
||||||
<div class="aca-rule-set-picker__content__rule-list__header">
|
<div class="aca-rule-set-picker__content__rule-list__header">
|
||||||
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.LIST_OF_RULES_TO_LINK' | translate }}
|
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.LIST_OF_RULES_TO_LINK' | translate }}
|
||||||
</div>
|
</div>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
mat-flat-button color="primary"
|
mat-flat-button color="primary"
|
||||||
[disabled]="!hasOwnedRules(mainRuleSet$ | async) || isBusy"
|
[disabled]="!hasOwnedRules || isBusy"
|
||||||
(click)="onSubmit()">
|
(click)="onSubmit()">
|
||||||
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.SUBMIT' | translate }}
|
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.SUBMIT' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
@@ -22,13 +22,13 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Inject, ViewEncapsulation } from '@angular/core';
|
import { Component, Inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
|
||||||
import { Node } from '@alfresco/js-api';
|
import { Node } from '@alfresco/js-api';
|
||||||
import { RuleSet } from '../model/rule-set.model';
|
import { RuleSet } from '../model/rule-set.model';
|
||||||
import { BehaviorSubject, combineLatest, from, of } from 'rxjs';
|
import { BehaviorSubject, combineLatest, from, of, Subject } from 'rxjs';
|
||||||
import { finalize, map, switchMap } from 'rxjs/operators';
|
import { finalize, map, switchMap, takeUntil } from 'rxjs/operators';
|
||||||
import { NotificationService } from '@alfresco/adf-core';
|
import { NotificationService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
export interface RuleSetPickerOptions {
|
export interface RuleSetPickerOptions {
|
||||||
@@ -45,11 +45,12 @@ export interface RuleSetPickerOptions {
|
|||||||
host: { class: 'aca-rule-set-picker' },
|
host: { class: 'aca-rule-set-picker' },
|
||||||
providers: [FolderRuleSetsService]
|
providers: [FolderRuleSetsService]
|
||||||
})
|
})
|
||||||
export class RuleSetPickerSmartComponent {
|
export class RuleSetPickerSmartComponent implements OnInit, OnDestroy {
|
||||||
nodeId = '-root-';
|
nodeId = '-root-';
|
||||||
defaultNodeId = '-root-';
|
defaultNodeId = '-root-';
|
||||||
isBusy = false;
|
isBusy = false;
|
||||||
existingRuleSet: RuleSet = null;
|
existingRuleSet: RuleSet = null;
|
||||||
|
hasOwnedRules = false;
|
||||||
|
|
||||||
private selectedNodeId = '';
|
private selectedNodeId = '';
|
||||||
private folderLoading$ = new BehaviorSubject<boolean>(true);
|
private folderLoading$ = new BehaviorSubject<boolean>(true);
|
||||||
@@ -59,6 +60,8 @@ export class RuleSetPickerSmartComponent {
|
|||||||
map(([rulesLoading, folderLoading]) => rulesLoading || folderLoading)
|
map(([rulesLoading, folderLoading]) => rulesLoading || folderLoading)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onDestroy$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(MAT_DIALOG_DATA) public data: RuleSetPickerOptions,
|
@Inject(MAT_DIALOG_DATA) public data: RuleSetPickerOptions,
|
||||||
private folderRuleSetsService: FolderRuleSetsService,
|
private folderRuleSetsService: FolderRuleSetsService,
|
||||||
@@ -70,8 +73,15 @@ export class RuleSetPickerSmartComponent {
|
|||||||
this.existingRuleSet = this.data?.existingRuleSet ?? null;
|
this.existingRuleSet = this.data?.existingRuleSet ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasOwnedRules(ruleSet: RuleSet): boolean {
|
ngOnInit(): void {
|
||||||
return ruleSet?.rules.length > 0 && FolderRuleSetsService.isOwnedRuleSet(ruleSet, this.selectedNodeId);
|
this.mainRuleSet$.pipe(takeUntil(this.onDestroy$)).subscribe((mainRuleSet) => {
|
||||||
|
this.hasOwnedRules = mainRuleSet?.rules.length > 0 && FolderRuleSetsService.isOwnedRuleSet(mainRuleSet, this.selectedNodeId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.onDestroy$.next();
|
||||||
|
this.onDestroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
onNodeSelect(nodes: Node[]) {
|
onNodeSelect(nodes: Node[]) {
|
||||||
|
@@ -233,8 +233,8 @@ export class FolderRuleSetsService {
|
|||||||
|
|
||||||
refreshMainRuleSet(ruleToSelect: Rule = null) {
|
refreshMainRuleSet(ruleToSelect: Rule = null) {
|
||||||
this.getMainRuleSet(this.currentFolder.id).subscribe((mainRuleSet: RuleSet) => {
|
this.getMainRuleSet(this.currentFolder.id).subscribe((mainRuleSet: RuleSet) => {
|
||||||
this.mainRuleSet = mainRuleSet;
|
this.mainRuleSet = { ...mainRuleSet };
|
||||||
this.mainRuleSetSource.next(mainRuleSet);
|
this.mainRuleSetSource.next(this.mainRuleSet);
|
||||||
if (mainRuleSet) {
|
if (mainRuleSet) {
|
||||||
const ruleToSelectInRuleSet = ruleToSelect ? mainRuleSet.rules.find((rule: Rule) => rule.id === ruleToSelect.id) : mainRuleSet.rules[0];
|
const ruleToSelectInRuleSet = ruleToSelect ? mainRuleSet.rules.find((rule: Rule) => rule.id === ruleToSelect.id) : mainRuleSet.rules[0];
|
||||||
this.folderRulesService.selectRule(ruleToSelectInRuleSet);
|
this.folderRulesService.selectRule(ruleToSelectInRuleSet);
|
||||||
|
@@ -162,7 +162,7 @@ export class FolderRulesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private formatRules(res): Rule[] {
|
private formatRules(res): Rule[] {
|
||||||
return res.list.entries.map((entry) => this.formatRule(entry.entry));
|
return [...res.list.entries.map((entry) => this.formatRule(entry.entry))];
|
||||||
}
|
}
|
||||||
|
|
||||||
private formatRule(obj): Rule {
|
private formatRule(obj): Rule {
|
||||||
|
@@ -36,7 +36,7 @@ describe('LockedByComponent', () => {
|
|||||||
}
|
}
|
||||||
} as any
|
} as any
|
||||||
};
|
};
|
||||||
|
component.ngOnInit();
|
||||||
expect(component.text).toBe('owner-name');
|
expect(component.text).toBe('owner-name');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
|
import { Component, Input, ChangeDetectionStrategy, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
import { NodeEntry } from '@alfresco/js-api';
|
import { NodeEntry } from '@alfresco/js-api';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
@@ -43,11 +43,13 @@ import { MatIconModule } from '@angular/material/icon';
|
|||||||
class: 'aca-locked-by'
|
class: 'aca-locked-by'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class LockedByComponent {
|
export class LockedByComponent implements OnInit {
|
||||||
@Input()
|
@Input()
|
||||||
node: NodeEntry;
|
node: NodeEntry;
|
||||||
|
|
||||||
get text(): string {
|
public text: string;
|
||||||
return this.node?.entry?.properties?.['cm:lockOwner']?.displayName;
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.text = this.node?.entry?.properties?.['cm:lockOwner']?.displayName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, ViewEncapsulation, HostListener, ViewChild, ViewChildren, QueryList, AfterViewInit } from '@angular/core';
|
import { Component, Input, ViewEncapsulation, HostListener, ViewChild, ViewChildren, QueryList, AfterViewInit, OnInit } from '@angular/core';
|
||||||
import { ContentActionRef } from '@alfresco/adf-extensions';
|
import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||||
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
|
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
|
||||||
import { ThemePalette } from '@angular/material/core';
|
import { ThemePalette } from '@angular/material/core';
|
||||||
@@ -34,7 +34,7 @@ import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item
|
|||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
host: { class: 'app-toolbar-menu' }
|
host: { class: 'app-toolbar-menu' }
|
||||||
})
|
})
|
||||||
export class ToolbarMenuComponent implements AfterViewInit {
|
export class ToolbarMenuComponent implements OnInit, AfterViewInit {
|
||||||
@Input()
|
@Input()
|
||||||
actionRef: ContentActionRef;
|
actionRef: ContentActionRef;
|
||||||
|
|
||||||
@@ -56,15 +56,17 @@ export class ToolbarMenuComponent implements AfterViewInit {
|
|||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
get type(): string {
|
type = 'default';
|
||||||
return this.data?.menuType || 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('document:keydown.Escape')
|
@HostListener('document:keydown.Escape')
|
||||||
handleKeydownEscape() {
|
handleKeydownEscape() {
|
||||||
this.matTrigger.closeMenu();
|
this.matTrigger.closeMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.type = this.data?.menuType || 'default';
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
const menuItems: MatMenuItem[] = [];
|
const menuItems: MatMenuItem[] = [];
|
||||||
this.toolbarMenuItems.forEach((toolbarMenuItem: ToolbarMenuItemComponent) => {
|
this.toolbarMenuItems.forEach((toolbarMenuItem: ToolbarMenuItemComponent) => {
|
||||||
|
Reference in New Issue
Block a user