[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:
swapnil-verma-gl
2023-06-06 14:02:19 +05:30
committed by GitHub
parent e9dce5f65a
commit d125fe5ff9
52 changed files with 314 additions and 297 deletions

View File

@@ -1,8 +1,8 @@
<ng-container *ngIf="selection$ | async as selection">
<ng-container *ngIf="selectionState">
<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>
<ng-container *ngIf="isShared(selection); else not_shared">
<ng-container *ngIf="isShared; else not_shared">
<span>{{ 'APP.ACTIONS.SHARE_EDIT' | translate }}</span>
</ng-container>
</button>
@@ -12,9 +12,9 @@
<button
mat-icon-button
data-automation-id="share-action-button"
(click)="editSharedNode(selection, '#share-action-button')"
[attr.aria-label]="getLabel(selection) | translate"
[attr.title]="getLabel(selection) | translate"
(click)="editSharedNode(selectionState, '#share-action-button')"
[attr.aria-label]="selectionLabel | translate"
[attr.title]="selectionLabel | translate"
id="share-action-button"
>
<mat-icon>link</mat-icon>

View File

@@ -56,14 +56,14 @@ describe('ToggleSharedComponent', () => {
it('should return false when entry is not shared', () => {
component.ngOnInit();
expect(component.isShared({ first: { entry } })).toBe(false);
expect(component.isShared).toBe(false);
});
it('should return true when entry is shared', () => {
entry.properties['qshare:sharedId'] = 'some-id';
component.ngOnInit();
expect(component.isShared({ first: { entry } })).toBe(true);
expect(component.isShared).toBe(true);
});
it('should dispatch `SHARE_NODE` action on share', () => {
@@ -74,7 +74,7 @@ describe('ToggleSharedComponent', () => {
it('should get action label for unshared file', () => {
component.ngOnInit();
const label = component.getLabel({ first: { entry } });
const label = component.selectionLabel;
expect(label).toBe('APP.ACTIONS.SHARE');
});
@@ -82,7 +82,7 @@ describe('ToggleSharedComponent', () => {
it('should get action label for shared file', () => {
entry.properties['qshare:sharedId'] = 'some-id';
component.ngOnInit();
const label = component.getLabel({ first: { entry } });
const label = component.selectionLabel;
expect(label).toBe('APP.ACTIONS.SHARE_EDIT');
});

View File

@@ -22,8 +22,8 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, OnInit, Input } from '@angular/core';
import { Observable } from 'rxjs';
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Store } from '@ngrx/store';
import { SelectionState } from '@alfresco/adf-extensions';
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 { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { takeUntil } from 'rxjs/operators';
@Component({
standalone: true,
@@ -39,29 +40,38 @@ import { MatButtonModule } from '@angular/material/button';
selector: 'app-toggle-shared',
templateUrl: './toggle-shared.component.html'
})
export class ToggleSharedComponent implements OnInit {
export class ToggleSharedComponent implements OnInit, OnDestroy {
@Input()
data: {
iconButton?: string;
};
selection$: Observable<SelectionState>;
selectionState: SelectionState;
selectionLabel = '';
isShared = false;
onDestroy$ = new Subject<void>();
constructor(private store: Store<AppStore>) {}
ngOnInit() {
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) {
// workaround for shared files
if (selection.first && selection.first.entry && (selection.first.entry as any).sharedByUser) {
return true;
}
return selection.first && selection.first.entry && selection.first.entry.properties && !!selection.first.entry.properties['qshare:sharedId'];
ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete();
}
editSharedNode(selection: SelectionState, focusedElementOnCloseSelector: string) {
this.store.dispatch(
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';
}
}

View File

@@ -46,12 +46,17 @@ import { TranslateModule } from '@ngx-translate/core';
export class CustomNameColumnComponent extends NameColumnComponent implements OnInit, OnDestroy {
private onDestroy$$ = new Subject<boolean>();
isFile: boolean;
isFileWriteLocked: boolean;
constructor(element: ElementRef, private cd: ChangeDetectorRef, private actions$: Actions, private nodesService: NodesApiService) {
super(element, nodesService);
}
ngOnInit() {
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) => {
const row = this.context.row;
@@ -65,6 +70,9 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
row.node = { entry };
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$$)
)
.subscribe(() => {
this.isFileWriteLocked = isLocked(this.node);
this.cd.detectChanges();
});
}
@@ -90,12 +99,4 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
this.onDestroy$$.next(true);
this.onDestroy$$.complete();
}
get isFile(): boolean {
return this.node && this.node.entry && !this.node.entry.isFolder;
}
get isFileWriteLocked(): boolean {
return isLocked(this.node);
}
}

View File

@@ -22,16 +22,15 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { ShareDataRow, TagModule } from '@alfresco/adf-content-services';
import { ChangeDetectorRef, Component, Input, ViewEncapsulation } from '@angular/core';
import { TagModule } from '@alfresco/adf-content-services';
import { ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
@Component({
standalone: true,
imports: [TagModule],
selector: 'aca-tags-column',
template: `
<adf-tag-node-list [showDelete]="false" [limitTagsDisplayed]="true" [nodeId]="getNodeId(context.row)" (results)="onTagsLoaded()">
</adf-tag-node-list>
<adf-tag-node-list [showDelete]="false" [limitTagsDisplayed]="true" [nodeId]="nodeId" (results)="onTagsLoaded()"> </adf-tag-node-list>
`,
styleUrls: ['./tags-column.component.scss'],
encapsulation: ViewEncapsulation.None,
@@ -39,14 +38,16 @@ import { ChangeDetectorRef, Component, Input, ViewEncapsulation } from '@angular
class: 'adf-datatable-content-cell aca-tags-name-column'
}
})
export class TagsColumnComponent {
export class TagsColumnComponent implements OnInit {
@Input()
context: any;
nodeId: string;
constructor(private cd: ChangeDetectorRef) {}
getNodeId(row: ShareDataRow): string {
return row.id;
ngOnInit(): void {
this.nodeId = this.context?.row?.id;
}
onTagsLoaded(): void {

View File

@@ -72,7 +72,7 @@
</ng-container>
</data-columns>
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive()">
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive">
<ng-container>
<div class="empty-search__block" aria-live="polite">
<p class="empty-search__text">

View File

@@ -46,6 +46,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
private nodePath: PathElement[];
columns: DocumentListPresetRef[] = [];
isFilterHeaderActive = false;
constructor(private route: ActivatedRoute, private contentApi: ContentApiService, private nodeActionsService: NodeActionsService) {
super();
@@ -306,9 +307,11 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
onFilterSelected(activeFilters: FilterSearch[]) {
if (activeFilters.length) {
this.showHeader = ShowHeaderMode.Always;
this.isFilterHeaderActive = true;
this.navigateToFilter(activeFilters);
} else {
this.router.navigate(['.'], { relativeTo: this.route });
this.isFilterHeaderActive = false;
this.showHeader = ShowHeaderMode.Data;
this.onAllFilterCleared();
}
@@ -329,10 +332,6 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
this.router.navigate([], { relativeTo: this.route, queryParams: objectFromMap });
}
isFilterHeaderActive(): boolean {
return this.showHeader === ShowHeaderMode.Always;
}
onError() {
this.isValidPath = false;
}

View File

@@ -83,22 +83,26 @@ describe('CommentsTabComponent', () => {
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 = {
id: 'test-node-id',
isFile: true,
isFolder: false
} as Node;
fixture.detectChanges();
await fixture.whenStable();
expect(component.canUpdateNode).toBe(true);
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 = {
id: 'test-node-id',
isFile: false,
isFolder: true
} as Node;
fixture.detectChanges();
await fixture.whenStable();
expect(component.canUpdateNode).toBe(true);
expect(checked).toContain('update');
});

View File

@@ -22,7 +22,7 @@
* 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 { NodePermissionService, isLocked } from '@alfresco/aca-shared';
import { MatCardModule } from '@angular/material/card';
@@ -34,20 +34,20 @@ import { NodeCommentsModule } from '@alfresco/adf-content-services';
selector: 'app-comments-tab',
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()
node: MinimalNodeEntryEntity;
canUpdateNode = false;
constructor(private permission: NodePermissionService) {}
get canUpdateNode(): boolean {
ngOnInit(): void {
if (!this.node) {
return false;
this.canUpdateNode = false;
}
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;
}
}

View File

@@ -47,7 +47,7 @@
</span>
<span class="mat-input-element">
{{ getVisibilityLabel(form.controls.visibility.value) | translate }}
{{ visibilityLabel | translate }}
</span>
</div>
</div>

View File

@@ -92,15 +92,12 @@ export class LibraryMetadataFormComponent implements OnInit, OnChanges, OnDestro
});
matcher = new InstantErrorStateMatcher();
canUpdateLibrary = false;
visibilityLabel = '';
onDestroy$: Subject<boolean> = new Subject<boolean>();
constructor(private alfrescoApiService: AlfrescoApiService, protected store: Store<AppStore>) {}
get canUpdateLibrary() {
return this.node && this.node.entry && this.node.entry.role === 'SiteManager';
}
getVisibilityLabel(value: string) {
return this.libraryType.find((type) => type.value === value).label;
}
@@ -136,6 +133,8 @@ export class LibraryMetadataFormComponent implements OnInit, OnChanges, OnDestro
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() {

View File

@@ -23,14 +23,14 @@
*/
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 { AppTestingModule } from '../../../testing/app-testing.module';
import { AppConfigService, CoreModule } from '@alfresco/adf-core';
import { Store } from '@ngrx/store';
import { AppState, SetInfoDrawerMetadataAspectAction } from '@alfresco/aca-shared/store';
import { By } from '@angular/platform-browser';
import { AppExtensionService } from '@alfresco/aca-shared';
import { AppExtensionService, NodePermissionService } from '@alfresco/aca-shared';
describe('MetadataTabComponent', () => {
let fixture: ComponentFixture<MetadataTabComponent>;
@@ -38,17 +38,22 @@ describe('MetadataTabComponent', () => {
let store: Store<AppState>;
let appConfig: AppConfigService;
let extensions: AppExtensionService;
let nodePermissionService: NodePermissionService;
const presets = {
default: {
includeAll: true
},
custom: []
};
beforeEach(() => {
TestBed.configureTestingModule({
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(() => {
@@ -86,11 +91,12 @@ describe('MetadataTabComponent', () => {
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 = {
isLocked: false,
allowableOperations: ['update']
} as Node;
component.ngOnInit();
expect(component.canUpdateNode).toBe(true);
});
@@ -99,6 +105,7 @@ describe('MetadataTabComponent', () => {
isLocked: true,
allowableOperations: ['update']
} as Node;
component.ngOnInit();
expect(component.canUpdateNode).toBe(false);
});
@@ -107,6 +114,7 @@ describe('MetadataTabComponent', () => {
isLocked: false,
allowableOperations: ['other']
} as Node;
component.ngOnInit();
expect(component.canUpdateNode).toBe(false);
});
@@ -118,6 +126,7 @@ describe('MetadataTabComponent', () => {
'cm:lockType': 'WRITE_LOCK'
}
} as Node;
component.ngOnInit();
expect(component.canUpdateNode).toBe(false);
});
});

View File

@@ -52,6 +52,8 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
displayAspect$: Observable<string>;
canUpdateNode = false;
constructor(
private permission: NodePermissionService,
protected extensions: AppExtensionService,
@@ -66,18 +68,13 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
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() {
this.contentMetadataService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
this.notificationService.showError(err.message);
});
if (this.node && !isLocked({ entry: this.node })) {
this.canUpdateNode = this.permission.check(this.node, ['update']);
}
}
ngOnDestroy() {

View File

@@ -37,7 +37,7 @@
(searchChange)="onSearchChange($event)"
>
</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">
<mat-checkbox

View File

@@ -91,7 +91,7 @@ describe('SearchInputComponent', () => {
});
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 () => {
@@ -103,7 +103,7 @@ describe('SearchInputComponent', () => {
appHookService.library400Error.next();
expect(component.hasLibraryConstraint()).toBe(true);
expect(component.evaluateLibrariesConstraint()).toBe(true);
});
describe('onSearchSubmit()', () => {

View File

@@ -49,6 +49,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
hasNewChange = false;
navigationTimer: any;
has400LibraryError = false;
hasLibrariesConstraint = false;
searchOnChange: boolean;
searchedWord: string = null;
@@ -106,6 +107,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
this.appHookService.library400Error.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
this.has400LibraryError = true;
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
});
}
@@ -116,6 +118,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
showInputValue() {
this.appService.appNavNarMode$.next('collapsed');
this.has400LibraryError = false;
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
this.searchedWord = this.getUrlSearchTerm();
if (this.searchInputControl) {
@@ -162,6 +165,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
}
this.has400LibraryError = false;
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
this.searchedWord = searchTerm;
if (this.hasOneChange) {
@@ -187,6 +191,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
this.syncInputValues();
this.has400LibraryError = false;
if (this.isLibrariesChecked()) {
this.hasLibrariesConstraint = this.evaluateLibrariesConstraint();
if (this.onLibrariesSearchResults && this.isSameSearchTerm()) {
this.queryLibrariesBuilder.update();
} else if (this.searchedWord) {
@@ -238,7 +243,7 @@ export class SearchInputComponent implements OnInit, OnDestroy {
return this.isFilesChecked() || this.isFoldersChecked();
}
hasLibraryConstraint(): boolean {
evaluateLibrariesConstraint(): boolean {
if (this.isLibrariesChecked()) {
return this.has400LibraryError || this.searchInputControl.isTermTooShort();
}

View File

@@ -79,7 +79,7 @@
</adf-custom-empty-content-template>
</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>
</div>
</div>

View File

@@ -50,6 +50,8 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
name$ = new BehaviorSubject<string>('');
title$ = new BehaviorSubject<string>('');
isFile = false;
constructor(
private store: Store<any>,
private nodesApiService: NodesApiService,
@@ -77,6 +79,7 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
private updateValues() {
this.node = this.context.row.node;
this.isFile = this.node.entry.isFile;
const { name, properties } = this.node.entry;
const title = properties ? properties['cm:title'] : '';
@@ -93,10 +96,6 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
this.onDestroy$.complete();
}
get isFile(): boolean {
return this.node.entry.isFile;
}
showPreview(event: Event) {
event.stopPropagation();
if (this.fileAutoDownloadService.shouldFileAutoDownload(this.node.entry.content.sizeInBytes)) {

View File

@@ -95,7 +95,7 @@
</adf-custom-empty-content-template>
</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>
</div>
</div>

View File

@@ -56,6 +56,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
data: ResultSetPaging;
sorting = ['name', 'asc'];
isLoading = false;
totalResults: number;
constructor(private queryBuilder: SearchQueryBuilderService, private route: ActivatedRoute, private translationService: TranslationService) {
super();
@@ -191,6 +192,14 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
onSearchResultLoaded(nodePaging: ResultSetPaging) {
this.data = nodePaging;
this.totalResults = this.getNumberOfResults();
}
getNumberOfResults() {
if (this.data?.list?.pagination) {
return this.data.list.pagination.totalItems;
}
return 0;
}
onPaginationChanged(pagination: Pagination) {

View File

@@ -25,7 +25,7 @@
[attr.aria-label]="item.title | translate"
class="action-button"
[ngClass]="{
'action-button--active': acaMenuPanel.hasActiveLinks()
'action-button--active': acaMenuPanel.hasActiveChildren
}"
>
<adf-icon [value]="item.icon"></adf-icon>

View File

@@ -27,22 +27,25 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreModule } from '@alfresco/adf-core';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { of } from 'rxjs';
import { provideMockStore } from '@ngrx/store/testing';
import { Store } from '@ngrx/store';
describe('DocumentDisplayModeComponent', () => {
let component: DocumentDisplayModeComponent;
let fixture: ComponentFixture<DocumentDisplayModeComponent>;
let store: Store;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreModule, AppTestingModule]
imports: [CoreModule, AppTestingModule],
providers: [provideMockStore()]
});
fixture = TestBed.createComponent(DocumentDisplayModeComponent);
component = fixture.componentInstance;
store = TestBed.inject(Store);
});
it('should show the list button when list', async () => {
component.displayMode$ = of('list');
spyOn(store, 'select').and.returnValue(of('list'));
fixture.detectChanges();
await fixture.whenStable();
@@ -50,11 +53,10 @@ describe('DocumentDisplayModeComponent', () => {
expect(displayButton.title).toBe('APP.ACTIONS.LIST_MODE');
});
it('should show the gallery button when list', async () => {
component.displayMode$ = of('gallery');
it('should show the gallery button when gallery', async () => {
spyOn(store, 'select').and.returnValue(of('gallery'));
fixture.detectChanges();
await fixture.whenStable();
const displayButton: HTMLButtonElement = fixture.nativeElement.querySelector('#app-document-display-mode-button');
expect(displayButton.title).toBe('APP.ACTIONS.GALLERY_MODE');
});

View File

@@ -22,10 +22,11 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ViewEncapsulation } from '@angular/core';
import { Observable } from 'rxjs';
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Store } from '@ngrx/store';
import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@alfresco/aca-shared/store';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-document-display-mode',
@@ -33,8 +34,8 @@ import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@al
<ng-container *ngIf="displayMode$ | async as displayMode">
<button
id="app-document-display-mode-button"
[attr.title]="getTitle(displayMode) | translate"
[attr.aria-label]="getTitle(displayMode) | translate"
[attr.title]="displayModeTitle | translate"
[attr.aria-label]="displayModeTitle | translate"
mat-icon-button
color="primary"
(click)="onClick()"
@@ -47,15 +48,24 @@ import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@al
encapsulation: ViewEncapsulation.None,
host: { class: 'app-document-display-mode' }
})
export class DocumentDisplayModeComponent {
export class DocumentDisplayModeComponent implements OnInit, OnDestroy {
displayMode$: Observable<string>;
displayModeTitle: string;
constructor(private store: Store<AppStore>) {
this.displayMode$ = store.select(getDocumentDisplayMode);
onDestroy$ = new Subject<void>();
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 {
return displayMode === 'list' ? 'APP.ACTIONS.LIST_MODE' : 'APP.ACTIONS.GALLERY_MODE';
ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete();
}
onClick() {

View File

@@ -32,11 +32,7 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
@Component({
selector: 'app-toggle-edit-offline',
template: `
<button
mat-menu-item
[attr.title]="(isNodeLocked ? 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' : 'APP.ACTIONS.EDIT_OFFLINE') | translate"
(click)="onClick()"
>
<button mat-menu-item [attr.title]="nodeTitle | translate" (click)="onClick()">
<ng-container *ngIf="isNodeLocked">
<mat-icon>cancel</mat-icon>
<span>{{ 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' | translate }}</span>
@@ -54,6 +50,8 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
export class ToggleEditOfflineComponent implements OnInit {
private nodesApi: NodesApi;
selection: MinimalNodeEntity;
nodeTitle = '';
isNodeLocked = false;
constructor(private store: Store<AppStore>, private alfrescoApiService: AlfrescoApiService) {
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
@@ -62,13 +60,11 @@ export class ToggleEditOfflineComponent implements OnInit {
ngOnInit() {
this.store.select(getAppSelection).subscribe(({ 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() {
await this.toggleLock(this.selection);
}

View File

@@ -23,7 +23,7 @@
<div class="app-general-edit-btn" *ngIf="!generalSectionButtonsToggle">
<button mat-raised-button class="app-general-cancel-btn" id="general-cancel-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>
</div>
</div>
@@ -92,7 +92,7 @@
<div class="app-general-edit-btn" *ngIf="!contactSectionButtonsToggle">
<button mat-raised-button class="app-general-cancel-btn" id="contact-cancel-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>
</div>
</div>
@@ -142,4 +142,4 @@
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
<h2 mat-dialog-title [innerHTML]="title()"></h2>
<h2 mat-dialog-title [innerHTML]="title"></h2>
<div mat-dialog-content>
<form [formGroup]="form" novalidate>
<mat-form-field class="adf-full-width">

View File

@@ -45,6 +45,8 @@ import { MatButtonModule } from '@angular/material/button';
export class CreateFromTemplateDialogComponent implements OnInit {
public form: UntypedFormGroup;
title = '';
constructor(
private translationService: TranslationService,
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)],
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() {
@@ -73,14 +80,6 @@ export class CreateFromTemplateDialogComponent implements OnInit {
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() {
this.dialogRef.close();
}