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:
@@ -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>
|
||||
|
@@ -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');
|
||||
});
|
||||
|
@@ -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';
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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">
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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');
|
||||
});
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@
|
||||
</span>
|
||||
|
||||
<span class="mat-input-element">
|
||||
{{ getVisibilityLabel(form.controls.visibility.value) | translate }}
|
||||
{{ visibilityLabel | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -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() {
|
||||
|
@@ -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);
|
||||
});
|
||||
});
|
||||
|
@@ -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() {
|
||||
|
@@ -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
|
||||
|
@@ -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()', () => {
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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)) {
|
||||
|
@@ -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>
|
||||
|
@@ -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) {
|
||||
|
@@ -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>
|
||||
|
@@ -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');
|
||||
});
|
||||
|
@@ -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() {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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">
|
||||
|
@@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user