From 2c4d930808930ab1511bf53cce936c34910c3bf8 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Mon, 15 Jul 2024 11:57:53 +0200 Subject: [PATCH 01/14] ACS-8036 create bulk-actions-dropdown --- extension.schema.json | 6 +++ .../aca-content/assets/app.extensions.json | 8 +++ projects/aca-content/assets/i18n/en.json | 1 + .../aca-content/src/lib/aca-content.module.ts | 2 + .../bulk-actions-dropdown.component.html | 17 +++++++ .../bulk-actions-dropdown.component.scss | 14 +++++ .../bulk-actions-dropdown.component.spec.ts | 49 ++++++++++++++++++ .../bulk-actions-dropdown.component.ts | 51 +++++++++++++++++++ .../search-results.component.html | 1 + .../search-results.component.ts | 6 ++- .../src/lib/store/reducers/app.reducer.ts | 7 +++ .../document-base-page.component.ts | 10 +++- .../src/lib/services/app.extension.service.ts | 24 +++++++++ .../store/src/actions/app-action-types.ts | 3 +- .../store/src/actions/app.actions.ts | 6 +++ .../store/src/selectors/app.selectors.ts | 1 + .../aca-shared/store/src/states/app.state.ts | 1 + 17 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html create mode 100644 projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss create mode 100644 projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts create mode 100644 projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts diff --git a/extension.schema.json b/extension.schema.json index d1fac19d27..bf4778aa81 100644 --- a/extension.schema.json +++ b/extension.schema.json @@ -837,6 +837,12 @@ "items": { "$ref": "#/definitions/contentActionRef" }, "minItems": 1 }, + "bulk-actions-dropdown": { + "description": "bulk actions dropdown entries", + "type": "array", + "items": { "$ref": "#/definitions/contentActionRef" }, + "minItems": 1 + }, "content-metadata-presets": { "description": "Configuration for the presets for content metadata component", "type": "array", diff --git a/projects/aca-content/assets/app.extensions.json b/projects/aca-content/assets/app.extensions.json index 06ae6f63c7..93de437628 100644 --- a/projects/aca-content/assets/app.extensions.json +++ b/projects/aca-content/assets/app.extensions.json @@ -688,6 +688,14 @@ ] } ], + "bulk-actions-dropdown": [ + { + "id": "app.bulk.actions.legalHold", + "component": "app.bulk-actions-dropdown", + "title": "GOVERNANCE.MANAGE_HOLDS.DIALOG_TITLE", + "type": "custom" + } + ], "contextMenu": [ { "id": "app.context.menu.share", diff --git a/projects/aca-content/assets/i18n/en.json b/projects/aca-content/assets/i18n/en.json index de1acbfe5c..fc8641aeab 100644 --- a/projects/aca-content/assets/i18n/en.json +++ b/projects/aca-content/assets/i18n/en.json @@ -500,6 +500,7 @@ } }, "SEARCH": { + "BULK_ACTIONS_DROPDOWN": "Bulk Actions ({{ count }} Items)", "INPUT": { "PLACEHOLDER": "Search", "FILES": "Files", diff --git a/projects/aca-content/src/lib/aca-content.module.ts b/projects/aca-content/src/lib/aca-content.module.ts index 033ba88806..643d084807 100644 --- a/projects/aca-content/src/lib/aca-content.module.ts +++ b/projects/aca-content/src/lib/aca-content.module.ts @@ -76,6 +76,7 @@ import { UserMenuComponent } from './components/sidenav/user-menu/user-menu.comp import { ContextMenuComponent } from './components/context-menu/context-menu.component'; import { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material/dialog'; import { SearchResultsRowComponent } from './components/search/search-results-row/search-results-row.component'; +import { BulkActionsDropdownComponent } from './components/bulk-actions-dropdown/bulk-actions-dropdown.component'; @NgModule({ imports: [ @@ -138,6 +139,7 @@ export class ContentServiceExtensionModule { 'app.toolbar.toggleFavoriteLibrary': ToggleFavoriteLibraryComponent, 'app.toolbar.toggleJoinLibrary': ToggleJoinLibraryButtonComponent, 'app.menu.toggleJoinLibrary': ToggleJoinLibraryMenuComponent, + 'app.bulk-actions-dropdown': BulkActionsDropdownComponent, 'app.shared-link.toggleSharedLink': ToggleSharedComponent, 'app.columns.name': CustomNameColumnComponent, 'app.columns.libraryName': LibraryNameColumnComponent, diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html new file mode 100644 index 0000000000..f05812d5c1 --- /dev/null +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -0,0 +1,17 @@ + + + + + {{ option.title | translate }} + + + + diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss new file mode 100644 index 0000000000..bb68d77868 --- /dev/null +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss @@ -0,0 +1,14 @@ +.aca-bulk-form-feild { + margin-left: 24px; + margin-top: 1.4375em; + width: 295px; +} + +.aca-bulk-select { + margin-top: 31px; +} + +// /* stylelint-disable-next-line selector-class-pattern */ +// .mat-form-field-wrapper { +// padding-bottom: 0; +// } diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts new file mode 100644 index 0000000000..2f2077acaa --- /dev/null +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -0,0 +1,49 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BulkActionsDropdownComponent } from './bulk-actions-dropdown.component'; + +describe('BulkActionsDropdownComponent', () => { + let component: BulkActionsDropdownComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BulkActionsDropdownComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BulkActionsDropdownComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts new file mode 100644 index 0000000000..8d9ec32367 --- /dev/null +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts @@ -0,0 +1,51 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { ContentActionRef } from '@alfresco/adf-extensions'; +import { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store'; +import { CommonModule } from '@angular/common'; +import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSelectModule } from '@angular/material/select'; +import { Store } from '@ngrx/store'; +import { TranslateModule } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; + +@Component({ + standalone: true, + selector: 'aca-bulk-actions-dropdown', + templateUrl: './bulk-actions-dropdown.component.html', + styleUrls: ['./bulk-actions-dropdown.component.scss'], + imports: [CommonModule, TranslateModule, MatSelectModule, MatFormFieldModule, MatInputModule, MatIconModule], + encapsulation: ViewEncapsulation.None +}) +export class BulkActionsDropdownComponent { + @Input() items: ContentActionRef[]; + + selection$: Observable = this.store.select(getSearchItemsTotalCount); + + constructor(private store: Store) {} +} diff --git a/projects/aca-content/src/lib/components/search/search-results/search-results.component.html b/projects/aca-content/src/lib/components/search/search-results/search-results.component.html index d642335ff1..79bf5805c5 100644 --- a/projects/aca-content/src/lib/components/search/search-results/search-results.component.html +++ b/projects/aca-content/src/lib/components/search/search-results/search-results.component.html @@ -1,6 +1,7 @@
+
diff --git a/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts b/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts index b5d6173077..2f17bbcdd5 100644 --- a/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts +++ b/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts @@ -31,6 +31,7 @@ import { NavigateToFolder, SetInfoDrawerPreviewStateAction, SetInfoDrawerStateAction, + SetSearchItemsTotalCountAction, ShowInfoDrawerPreviewAction, SnackbarErrorAction } from '@alfresco/aca-shared/store'; @@ -59,6 +60,7 @@ import { TagsColumnComponent } from '../../dl-custom-components/tags-column/tags import { MatIconModule } from '@angular/material/icon'; import { SearchResultsRowComponent } from '../search-results-row/search-results-row.component'; import { DocumentListPresetRef, DynamicColumnComponent } from '@alfresco/adf-extensions'; +import { BulkActionsDropdownComponent } from '../../bulk-actions-dropdown/bulk-actions-dropdown.component'; @Component({ standalone: true, @@ -86,7 +88,8 @@ import { DocumentListPresetRef, DynamicColumnComponent } from '@alfresco/adf-ext PageLayoutComponent, ToolbarComponent, AlfrescoViewerComponent, - DynamicColumnComponent + DynamicColumnComponent, + BulkActionsDropdownComponent ], selector: 'aca-search-results', templateUrl: './search-results.component.html', @@ -245,6 +248,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit { onSearchResultLoaded(nodePaging: ResultSetPaging) { this.data = nodePaging; this.totalResults = this.getNumberOfResults(); + this.store.dispatch(new SetSearchItemsTotalCountAction(this.totalResults)); } getNumberOfResults() { diff --git a/projects/aca-content/src/lib/store/reducers/app.reducer.ts b/projects/aca-content/src/lib/store/reducers/app.reducer.ts index 192d8398d4..d6d13eee4b 100644 --- a/projects/aca-content/src/lib/store/reducers/app.reducer.ts +++ b/projects/aca-content/src/lib/store/reducers/app.reducer.ts @@ -39,6 +39,7 @@ import { AppActionTypes, ShowLoaderAction, INITIAL_APP_STATE + SetSearchItemsTotalCountAction } from '@alfresco/aca-shared/store'; export function appReducer(state: AppState = INITIAL_APP_STATE, action: Action): AppState { @@ -84,6 +85,12 @@ export function appReducer(state: AppState = INITIAL_APP_STATE, action: Action): case AppActionTypes.ShowLoaderAction: newState = showLoader(state, action as ShowLoaderAction); break; + case AppActionTypes.SetSearchItemsTotalCount: + newState = { + ...state, + searchItemsTotalCount: (action as SetSearchItemsTotalCountAction).payload + }; + break; default: newState = { ...state }; } diff --git a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts index ed28b2950e..318d6e95cd 100644 --- a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts +++ b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts @@ -61,12 +61,13 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { selection: SelectionState; actions: Array = []; viewerToolbarActions: Array = []; + bulkActions: ContentActionRef[] = []; canUpdateNode = false; canUpload = false; nodeResult: NodePaging; showHeader = ShowHeaderMode.Data; filterSorting = 'name-asc'; - createActions: Array = []; + createActions: ContentActionRef[] = []; isSmallScreen = false; protected extensions = inject(AppExtensionService); @@ -104,6 +105,13 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { this.actions = actions; }); + this.extensions + .getBulkActions() + .pipe(takeUntil(this.onDestroy$)) + .subscribe((actions) => { + this.bulkActions = actions; + }); + this.extensions .getViewerToolbarActions() .pipe(takeUntil(this.onDestroy$)) diff --git a/projects/aca-shared/src/lib/services/app.extension.service.ts b/projects/aca-shared/src/lib/services/app.extension.service.ts index 24e2fcf8e5..0351d383a4 100644 --- a/projects/aca-shared/src/lib/services/app.extension.service.ts +++ b/projects/aca-shared/src/lib/services/app.extension.service.ts @@ -68,6 +68,7 @@ export class AppExtensionService implements RuleContext { sidebarTabs: Array = []; contentMetadata: any; search: any; + bulkActionsDropdown: any; viewerRules: ViewerRules = {}; private _headerActions = new BehaviorSubject>([]); @@ -81,6 +82,7 @@ export class AppExtensionService implements RuleContext { private _badges = new BehaviorSubject>([]); private _filesDocumentListPreset = new BehaviorSubject>([]); private _customMetadataPanels = new BehaviorSubject>([]); + private _bulkActionsDropdown = new BehaviorSubject>([]); documentListPresets: { libraries: Array; @@ -160,10 +162,12 @@ export class AppExtensionService implements RuleContext { this._badges.next(this.loader.getElements(config, 'features.badges')); this._filesDocumentListPreset.next(this.getDocumentListPreset(config, 'files')); this._customMetadataPanels.next(this.loader.getElements(config, 'features.customMetadataPanels')); + this._bulkActionsDropdown.next(this.loader.getElements(config, 'features.bulk-actions-dropdown')); this.navbar = this.loadNavBar(config); this.sidebarTabs = this.loader.getElements(config, 'features.sidebar.tabs'); this.contentMetadata = this.loadContentMetadata(config); + this.bulkActionsDropdown = this.loadBulkActionsDropdown(config); this.search = this.loadSearchForms(config); this.search?.forEach((searchSet) => { searchSet.categories = searchSet.categories?.filter((category) => this.filterVisible(category)); @@ -305,6 +309,22 @@ export class AppExtensionService implements RuleContext { return { presets }; } + loadBulkActionsDropdown(config: ExtensionConfig): any { + const elements = this.loader.getElements(config, 'features.bulk-actions-dropdown'); + if (!elements.length) { + return null; + } + + let presets = {}; + presets = this.filterDisabled(mergeObjects(presets, ...elements)); + + const metadata = this.appConfig.config['content-metadata'] || {}; + metadata.presets = presets; + + this.appConfig.config['content-metadata'] = metadata; + return { presets }; + } + loadSearchForms(config: ExtensionConfig): any { const elements = this.loader.getElements(config, 'features.search'); if (!elements.length) { @@ -424,6 +444,10 @@ export class AppExtensionService implements RuleContext { return this._viewerToolbarActions.pipe(map((viewerToolbarActions) => this.getAllowedActions(viewerToolbarActions))); } + getBulkActions(): Observable> { + return this._bulkActionsDropdown.pipe(map((bulkActions) => this.getAllowedActions(bulkActions))); + } + getOpenWithActions(): Observable> { return this._openWithActions.pipe(map((openWithActions) => this.getAllowedActions(openWithActions))); } diff --git a/projects/aca-shared/store/src/actions/app-action-types.ts b/projects/aca-shared/store/src/actions/app-action-types.ts index 6aef4a830b..804c23df92 100644 --- a/projects/aca-shared/store/src/actions/app-action-types.ts +++ b/projects/aca-shared/store/src/actions/app-action-types.ts @@ -38,5 +38,6 @@ export enum AppActionTypes { SetFileUploadingDialog = 'SET_FILE_UPLOADING_DIALOG', ShowInfoDrawerPreview = 'SHOW_INFO_DRAWER_PREVIEW', SetInfoDrawerPreviewState = 'SET_INFO_DRAWER_PREVIEW_STATE', - ShowLoaderAction = 'SHOW_LOADER' + ShowLoaderAction = 'SHOW_LOADER', + SetSearchItemsTotalCount = 'SET_SEARCH_ITEMS_TOTAL_COUNT' } diff --git a/projects/aca-shared/store/src/actions/app.actions.ts b/projects/aca-shared/store/src/actions/app.actions.ts index 22cc211a92..8de65737ec 100644 --- a/projects/aca-shared/store/src/actions/app.actions.ts +++ b/projects/aca-shared/store/src/actions/app.actions.ts @@ -108,3 +108,9 @@ export class ShowLoaderAction implements Action { constructor(public payload: boolean) {} } + +export class SetSearchItemsTotalCountAction implements Action { + readonly type = AppActionTypes.SetSearchItemsTotalCount; + + constructor(public payload: number) {} +} diff --git a/projects/aca-shared/store/src/selectors/app.selectors.ts b/projects/aca-shared/store/src/selectors/app.selectors.ts index 54639b422e..e7babba338 100644 --- a/projects/aca-shared/store/src/selectors/app.selectors.ts +++ b/projects/aca-shared/store/src/selectors/app.selectors.ts @@ -42,6 +42,7 @@ export const isHXIConnectorEnabled = createSelector(getRepositoryStatus, (info) export const isAdmin = createSelector(selectApp, (state) => state.user.isAdmin); export const getFileUploadingDialog = createSelector(selectApp, (state) => state.fileUploadingDialog); export const showLoaderSelector = createSelector(selectApp, (state) => state.showLoader); +export const getSearchItemsTotalCount = createSelector(selectApp, (state) => state.searchItemsTotalCount); export const getSideNavState = createSelector(getAppSelection, getNavigationState, (selection, navigation) => ({ selection, diff --git a/projects/aca-shared/store/src/states/app.state.ts b/projects/aca-shared/store/src/states/app.state.ts index e19ca048f0..318d21606f 100644 --- a/projects/aca-shared/store/src/states/app.state.ts +++ b/projects/aca-shared/store/src/states/app.state.ts @@ -74,6 +74,7 @@ export interface AppState { repository: RepositoryInfo; fileUploadingDialog: boolean; showLoader: boolean; + searchItemsTotalCount: number; } export interface AppStore { From fcf18354870ba3fdaa637a8e5bcadacfd6e48d2f Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Wed, 17 Jul 2024 13:33:40 +0200 Subject: [PATCH 02/14] ACS-8325 update names and add unit tests --- .../aca-content/assets/app.extensions.json | 8 -- .../bulk-actions-dropdown.component.html | 30 ++++-- .../bulk-actions-dropdown.component.scss | 35 +++++-- .../bulk-actions-dropdown.component.spec.ts | 99 ++++++++++++++++++- .../bulk-actions-dropdown.component.ts | 2 +- 5 files changed, 144 insertions(+), 30 deletions(-) diff --git a/projects/aca-content/assets/app.extensions.json b/projects/aca-content/assets/app.extensions.json index 93de437628..06ae6f63c7 100644 --- a/projects/aca-content/assets/app.extensions.json +++ b/projects/aca-content/assets/app.extensions.json @@ -688,14 +688,6 @@ ] } ], - "bulk-actions-dropdown": [ - { - "id": "app.bulk.actions.legalHold", - "component": "app.bulk-actions-dropdown", - "title": "GOVERNANCE.MANAGE_HOLDS.DIALOG_TITLE", - "type": "custom" - } - ], "contextMenu": [ { "id": "app.context.menu.share", diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index f05812d5c1..ac40dd454b 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -1,17 +1,33 @@ - - - {{ option.title | translate }} + + {{ option.title | translate }} - + + + + diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss index bb68d77868..8abcf537ef 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss @@ -1,14 +1,31 @@ -.aca-bulk-form-feild { +/* stylelint-disable selector-class-pattern */ +.aca-bulk-select { + margin-top: 31px; +} + +.aca-bulk-form-field { margin-left: 24px; margin-top: 1.4375em; width: 295px; -} -.aca-bulk-select { - margin-top: 31px; -} + .mat-form-field-flex, + .mat-form-field-infix { + height: 48px; + line-height: 48px; + display: flex; + align-items: center; + border: 0; + } + + .mat-form-field-appearance-outline .mat-form-field-outline { + top: 0; + } -// /* stylelint-disable-next-line selector-class-pattern */ -// .mat-form-field-wrapper { -// padding-bottom: 0; -// } + .mat-select-arrow-wrapper { + margin-top: 10px; + } + + .mat-select { + margin-top: 0.25rem; + } +} diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 2f2077acaa..5cb6b207bf 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -23,27 +23,116 @@ */ /* tslint:disable:no-unused-variable */ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BulkActionsDropdownComponent } from './bulk-actions-dropdown.component'; +import { Store } from '@ngrx/store'; +import { AppStore } from '../../../../../aca-shared/store/src/public-api'; +import { BehaviorSubject } from 'rxjs'; +import { By } from '@angular/platform-browser'; +import { ContentActionType } from '@alfresco/adf-extensions'; +import { AppTestingModule } from '../../testing/app-testing.module'; describe('BulkActionsDropdownComponent', () => { let component: BulkActionsDropdownComponent; let fixture: ComponentFixture; + let store: Store; - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [BulkActionsDropdownComponent] + const totalItemsMock$: BehaviorSubject = new BehaviorSubject(0); + + const getElement = (selector: string): HTMLInputElement | null => + fixture.debugElement.query(By.css(`[data-automation-id="${selector}"]`)).nativeElement; + + const getLabelText = (selector: string): string => getElement(selector).textContent.trim(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BulkActionsDropdownComponent, AppTestingModule] }).compileComponents(); - })); + + store = TestBed.inject(Store); + spyOn(store, 'select').and.returnValue(totalItemsMock$); + }); beforeEach(() => { fixture = TestBed.createComponent(BulkActionsDropdownComponent); component = fixture.componentInstance; + component.items = [ + { + id: 'app.bulk.actions.legalHold', + component: 'app.bulk-actions-dropdown', + title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + description: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + type: ContentActionType.custom, + rules: { + visible: 'app.manage.holds.isLegalHoldPluginEnabled' + } + } + ]; + fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('when there are no search items', () => { + let disabledDropdown; + + beforeEach(() => { + totalItemsMock$.next(0); + fixture.detectChanges(); + disabledDropdown = getElement('aca-bulk-dropdown-disabled'); + fixture.detectChanges(); + }); + + it('should disable dropdown', () => { + expect(disabledDropdown.getAttribute('aria-disabled')).toBe('true'); + }); + + it('should has correct tooltip', () => { + expect(disabledDropdown.getAttribute('title')).toBe('GOVERNANCE.MANAGE_HOLDS.BULK_NOT_AVAILABLE_TOOLTIP'); + }); + + it('should has correct placeholder', () => { + expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('BULK_NOT_AVAILABLE'); + }); + }); + + describe('when there are search elements', () => { + let dropdown; + + beforeEach(() => { + totalItemsMock$.next(10); + fixture.detectChanges(); + dropdown = getElement('aca-bulk-dropdown'); + dropdown.click(); + fixture.detectChanges(); + }); + + it('should enable dropdown', () => { + expect(dropdown.getAttribute('aria-disabled')).toBe('false'); + }); + + it('should has correct tooltip', () => { + expect(dropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN'); + }); + + it('should has correct placeholder', () => { + expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN'); + }); + + it('should have option with correct tooltip', () => { + const option = getElement('app.bulk.actions.legalHold'); + + expect(option.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + }); + + it('should have option with correct label', () => { + const optionLabel = getLabelText('app.bulk.actions.legalHold'); + + expect(optionLabel).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + }); + }); }); diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts index 8d9ec32367..98363922a6 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts @@ -45,7 +45,7 @@ import { Observable } from 'rxjs'; export class BulkActionsDropdownComponent { @Input() items: ContentActionRef[]; - selection$: Observable = this.store.select(getSearchItemsTotalCount); + totalItems$: Observable = this.store.select(getSearchItemsTotalCount); constructor(private store: Store) {} } From c39fef1cfdab831e9923ee00c866a13c84ac443d Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Wed, 17 Jul 2024 18:59:08 +0200 Subject: [PATCH 03/14] ACS-8325 added icon and unit tests --- .../bulk-actions-dropdown.component.html | 6 +++++ .../bulk-actions-dropdown.component.spec.ts | 23 +++++++++++-------- .../bulk-actions-dropdown.component.ts | 6 ++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index ac40dd454b..f39b4f76c9 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -18,6 +18,12 @@ [title]="option.description" [attr.data-automation-id]="option.id" > + {{ option.title | translate }} diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 5cb6b207bf..be24344c52 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -40,8 +40,7 @@ describe('BulkActionsDropdownComponent', () => { const totalItemsMock$: BehaviorSubject = new BehaviorSubject(0); - const getElement = (selector: string): HTMLInputElement | null => - fixture.debugElement.query(By.css(`[data-automation-id="${selector}"]`)).nativeElement; + const getElement = (selector: string): HTMLElement | null => fixture.debugElement.query(By.css(`[data-automation-id="${selector}"]`)).nativeElement; const getLabelText = (selector: string): string => getElement(selector).textContent.trim(); @@ -63,13 +62,13 @@ describe('BulkActionsDropdownComponent', () => { component: 'app.bulk-actions-dropdown', title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', description: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + icon: 'adf:manage_hold', type: ContentActionType.custom, rules: { visible: 'app.manage.holds.isLegalHoldPluginEnabled' } } ]; - fixture.detectChanges(); }); @@ -78,7 +77,7 @@ describe('BulkActionsDropdownComponent', () => { }); describe('when there are no search items', () => { - let disabledDropdown; + let disabledDropdown: HTMLElement; beforeEach(() => { totalItemsMock$.next(0); @@ -91,17 +90,17 @@ describe('BulkActionsDropdownComponent', () => { expect(disabledDropdown.getAttribute('aria-disabled')).toBe('true'); }); - it('should has correct tooltip', () => { + it('should have correct tooltip', () => { expect(disabledDropdown.getAttribute('title')).toBe('GOVERNANCE.MANAGE_HOLDS.BULK_NOT_AVAILABLE_TOOLTIP'); }); - it('should has correct placeholder', () => { + it('should have correct placeholder', () => { expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('BULK_NOT_AVAILABLE'); }); }); describe('when there are search elements', () => { - let dropdown; + let dropdown: HTMLElement; beforeEach(() => { totalItemsMock$.next(10); @@ -115,11 +114,11 @@ describe('BulkActionsDropdownComponent', () => { expect(dropdown.getAttribute('aria-disabled')).toBe('false'); }); - it('should has correct tooltip', () => { + it('should have correct tooltip', () => { expect(dropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN'); }); - it('should has correct placeholder', () => { + it('should have correct placeholder', () => { expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN'); }); @@ -134,5 +133,11 @@ describe('BulkActionsDropdownComponent', () => { expect(optionLabel).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); }); + + it('should have correct icon in an option', () => { + const icon = getElement('aca-option-icon-app.bulk.actions.legalHold'); + + expect(icon.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + }); }); }); diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts index 98363922a6..353a050760 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts @@ -26,20 +26,18 @@ import { ContentActionRef } from '@alfresco/adf-extensions'; import { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store'; import { CommonModule } from '@angular/common'; import { Component, Input, ViewEncapsulation } from '@angular/core'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { Observable } from 'rxjs'; +import { IconComponent } from '@alfresco/adf-core'; @Component({ standalone: true, selector: 'aca-bulk-actions-dropdown', templateUrl: './bulk-actions-dropdown.component.html', styleUrls: ['./bulk-actions-dropdown.component.scss'], - imports: [CommonModule, TranslateModule, MatSelectModule, MatFormFieldModule, MatInputModule, MatIconModule], + imports: [CommonModule, TranslateModule, MatSelectModule, IconComponent], encapsulation: ViewEncapsulation.None }) export class BulkActionsDropdownComponent { From 9887136e25861e60b5f70ced2aa100d0c944afd4 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Thu, 18 Jul 2024 14:04:00 +0200 Subject: [PATCH 04/14] ACS-8325 fix translation --- .../bulk-actions-dropdown.component.html | 4 ++-- .../bulk-actions-dropdown.component.spec.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index f39b4f76c9..b205ae10ac 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -15,7 +15,7 @@ { }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('BULK_NOT_AVAILABLE'); + expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('GOVERNANCE.MANAGE_HOLDS.BULK_NOT_AVAILABLE'); }); }); From 084db92c73a5bf7bd0114b873e1b8eaf4083c078 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Thu, 18 Jul 2024 14:47:02 +0200 Subject: [PATCH 05/14] ACS-8325 add and refactor tests in app extension service --- .../services/app.extension.service.spec.ts | 257 ++++-------------- 1 file changed, 59 insertions(+), 198 deletions(-) diff --git a/projects/aca-shared/src/lib/services/app.extension.service.spec.ts b/projects/aca-shared/src/lib/services/app.extension.service.spec.ts index 75ce669ed5..f28d2e915a 100644 --- a/projects/aca-shared/src/lib/services/app.extension.service.spec.ts +++ b/projects/aca-shared/src/lib/services/app.extension.service.spec.ts @@ -88,6 +88,16 @@ describe('AppExtensionService', () => { } }; + const defaultConfigMock = { + $id: 'test', + $name: 'test', + $version: '1.0.0', + $license: 'MIT', + $vendor: 'Good company', + $runtime: '1.5.0', + features: {} + } as ExtensionConfig; + describe('configs', () => { it('should log an error during setup', async () => { spyOn(extensions, 'load').and.returnValue(Promise.resolve(null)); @@ -100,12 +110,7 @@ describe('AppExtensionService', () => { it('should load content metadata presets', () => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { 'content-metadata-presets': [ { @@ -180,12 +185,7 @@ describe('AppExtensionService', () => { it('should support column orders', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { documentList: { files: [ @@ -250,12 +250,7 @@ describe('AppExtensionService', () => { it('should ignore column if visibility in rules is false', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { documentList: { files: [ @@ -301,12 +296,7 @@ describe('AppExtensionService', () => { describe('actions', () => { beforeEach(() => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, actions: [ { id: 'aca:actions/create-folder', @@ -415,12 +405,7 @@ describe('AppExtensionService', () => { describe('content actions', () => { it('should load content actions from the config', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { toolbar: [ { @@ -447,12 +432,7 @@ describe('AppExtensionService', () => { it('should sort content actions by order', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { toolbar: [ { @@ -483,12 +463,7 @@ describe('AppExtensionService', () => { describe('open with', () => { it('should load [open with] actions for the viewer', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { openWith: [ @@ -516,12 +491,7 @@ describe('AppExtensionService', () => { it('should load only enabled [open with] actions for the viewer', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { openWith: [ @@ -560,12 +530,7 @@ describe('AppExtensionService', () => { it('should sort [open with] actions by order', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { openWith: [ @@ -606,12 +571,7 @@ describe('AppExtensionService', () => { describe('create', () => { it('should load [create] actions from config', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { create: [ { @@ -633,12 +593,7 @@ describe('AppExtensionService', () => { it('should sort [create] actions by order', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { create: [ { @@ -876,12 +831,7 @@ describe('AppExtensionService', () => { applyConfig( { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { shared: { @@ -905,14 +855,7 @@ describe('AppExtensionService', () => { appConfigService.config = { auth: { withCredentials: true } }; - applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0' - }); + applyConfig(defaultConfigMock); expect(service.withCredentials).toBe(true); }); @@ -921,28 +864,14 @@ describe('AppExtensionService', () => { appConfigService.config = { auth: { withCredentials: false } }; - applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0' - }); + applyConfig(defaultConfigMock); expect(service.withCredentials).toBe(false); }); it('should set `withCredentials` to false as default value if no app configuration', () => { appConfigService.config = {}; - applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0' - }); + applyConfig(defaultConfigMock); expect(service.withCredentials).toBe(false); }); @@ -951,12 +880,7 @@ describe('AppExtensionService', () => { describe('getHeaderActions', () => { it('should load user actions from the config', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { header: [ { @@ -981,12 +905,7 @@ describe('AppExtensionService', () => { it('should sort header actions by order', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { header: [ { @@ -1013,12 +932,7 @@ describe('AppExtensionService', () => { it('should sort header menu children actions by order', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { header: [ { @@ -1060,12 +974,7 @@ describe('AppExtensionService', () => { notVisible: () => false }); config = { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { search: [ { @@ -1361,12 +1270,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for create actions', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { create: actions } @@ -1380,12 +1284,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for sidebar actions', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { sidebar: { toolbar: actions @@ -1401,12 +1300,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for toolbar actions', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { toolbar: actions } @@ -1420,12 +1314,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for viewer toolbar actions', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { toolbarActions: actions } } @@ -1440,12 +1329,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for shared link viewer toolbar actions', (done) => { applyConfig( { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { viewer: { shared: { @@ -1465,12 +1349,7 @@ describe('AppExtensionService', () => { it('should set the action disabled for header actions', (done) => { applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { header: actions } @@ -1482,15 +1361,27 @@ describe('AppExtensionService', () => { }); }); + it('should set the action disabled for bulk actions dropdown actions', (done) => { + applyConfig( + { + ...defaultConfigMock, + features: { + 'bulk-actions-dropdown': actions + } + }, + true + ); + + service.getBulkActions().subscribe((bulkActions) => { + expect(bulkActions).toEqual(expectedActionsWithoutChildren); + done(); + }); + }); + it('should set the action disabled for context menu actions', (done) => { applyConfig( { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { contextMenu: actions } @@ -1524,12 +1415,7 @@ describe('AppExtensionService', () => { ]; config = { - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { contextMenu: [...actions], toolbar: [...actions], @@ -1629,12 +1515,7 @@ describe('AppExtensionService', () => { const rawUrl = './assets/images/ft_ic_ms_excel.svg'; applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { icons: [ { @@ -1653,12 +1534,7 @@ describe('AppExtensionService', () => { const warn = spyOn(logService, 'warn').and.stub(); applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { icons: [ { @@ -1675,12 +1551,7 @@ describe('AppExtensionService', () => { const warn = spyOn(logService, 'warn').and.stub(); applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { icons: [ { @@ -1701,12 +1572,7 @@ describe('AppExtensionService', () => { }); applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { badges: [ { @@ -1759,12 +1625,7 @@ describe('AppExtensionService', () => { }); applyConfig({ - $id: 'test', - $name: 'test', - $version: '1.0.0', - $license: 'MIT', - $vendor: 'Good company', - $runtime: '1.5.0', + ...defaultConfigMock, features: { customMetadataPanels: [ { From 6fb603d987a4d972e47c5aed61f92e593d825d61 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Mon, 22 Jul 2024 11:25:47 +0200 Subject: [PATCH 06/14] ACS-8325 resolve conversations: remove loadBulkActions, rename bulk schema, add translations --- extension.schema.json | 4 ++-- projects/aca-content/assets/i18n/en.json | 6 ++++- .../bulk-actions-dropdown.component.html | 8 +++---- .../bulk-actions-dropdown.component.scss | 3 +++ .../bulk-actions-dropdown.component.spec.ts | 10 ++++---- .../src/lib/services/app.extension.service.ts | 24 +++---------------- 6 files changed, 21 insertions(+), 34 deletions(-) diff --git a/extension.schema.json b/extension.schema.json index bf4778aa81..40d5931d75 100644 --- a/extension.schema.json +++ b/extension.schema.json @@ -837,8 +837,8 @@ "items": { "$ref": "#/definitions/contentActionRef" }, "minItems": 1 }, - "bulk-actions-dropdown": { - "description": "bulk actions dropdown entries", + "bulk-actions": { + "description": "Bulk actions entries", "type": "array", "items": { "$ref": "#/definitions/contentActionRef" }, "minItems": 1 diff --git a/projects/aca-content/assets/i18n/en.json b/projects/aca-content/assets/i18n/en.json index fc8641aeab..a2b42bd0de 100644 --- a/projects/aca-content/assets/i18n/en.json +++ b/projects/aca-content/assets/i18n/en.json @@ -500,7 +500,11 @@ } }, "SEARCH": { - "BULK_ACTIONS_DROPDOWN": "Bulk Actions ({{ count }} Items)", + "BULK_ACTIONS_DROPDOWN": { + "TITLE": "Bulk Actions ({{ count }} Items)", + "BULK_NOT_AVAILABLE": "Bulk Actions (Not Available)", + "BULK_NOT_AVAILABLE_TOOLTIP": "Bulk Actions cannot be used without search results" + }, "INPUT": { "PLACEHOLDER": "Search", "FILES": "Files", diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index b205ae10ac..fb4cb7a74d 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -5,8 +5,8 @@ > diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss index 8abcf537ef..7fbd693a7f 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss @@ -1,4 +1,7 @@ /* stylelint-disable selector-class-pattern */ + +// TODO: ACS-8458 Review css selectors + .aca-bulk-select { margin-top: 31px; } diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 6aa5ce86b6..421ce93387 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -22,9 +22,7 @@ * from Hyland Software. If not, see . */ -/* tslint:disable:no-unused-variable */ import { ComponentFixture, TestBed } from '@angular/core/testing'; - import { BulkActionsDropdownComponent } from './bulk-actions-dropdown.component'; import { Store } from '@ngrx/store'; import { AppStore } from '../../../../../aca-shared/store/src/public-api'; @@ -91,11 +89,11 @@ describe('BulkActionsDropdownComponent', () => { }); it('should have correct tooltip', () => { - expect(disabledDropdown.getAttribute('title')).toBe('GOVERNANCE.MANAGE_HOLDS.BULK_NOT_AVAILABLE_TOOLTIP'); + expect(disabledDropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE_TOOLTIP'); }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('GOVERNANCE.MANAGE_HOLDS.BULK_NOT_AVAILABLE'); + expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); }); }); @@ -115,11 +113,11 @@ describe('BulkActionsDropdownComponent', () => { }); it('should have correct tooltip', () => { - expect(dropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN'); + expect(dropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN'); + expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); }); it('should have option with correct tooltip', () => { diff --git a/projects/aca-shared/src/lib/services/app.extension.service.ts b/projects/aca-shared/src/lib/services/app.extension.service.ts index 0351d383a4..ddfa6f8505 100644 --- a/projects/aca-shared/src/lib/services/app.extension.service.ts +++ b/projects/aca-shared/src/lib/services/app.extension.service.ts @@ -68,7 +68,6 @@ export class AppExtensionService implements RuleContext { sidebarTabs: Array = []; contentMetadata: any; search: any; - bulkActionsDropdown: any; viewerRules: ViewerRules = {}; private _headerActions = new BehaviorSubject>([]); @@ -82,7 +81,7 @@ export class AppExtensionService implements RuleContext { private _badges = new BehaviorSubject>([]); private _filesDocumentListPreset = new BehaviorSubject>([]); private _customMetadataPanels = new BehaviorSubject>([]); - private _bulkActionsDropdown = new BehaviorSubject>([]); + private _bulkActions = new BehaviorSubject>([]); documentListPresets: { libraries: Array; @@ -162,12 +161,11 @@ export class AppExtensionService implements RuleContext { this._badges.next(this.loader.getElements(config, 'features.badges')); this._filesDocumentListPreset.next(this.getDocumentListPreset(config, 'files')); this._customMetadataPanels.next(this.loader.getElements(config, 'features.customMetadataPanels')); - this._bulkActionsDropdown.next(this.loader.getElements(config, 'features.bulk-actions-dropdown')); + this._bulkActions.next(this.loader.getElements(config, 'features.bulk-actions')); this.navbar = this.loadNavBar(config); this.sidebarTabs = this.loader.getElements(config, 'features.sidebar.tabs'); this.contentMetadata = this.loadContentMetadata(config); - this.bulkActionsDropdown = this.loadBulkActionsDropdown(config); this.search = this.loadSearchForms(config); this.search?.forEach((searchSet) => { searchSet.categories = searchSet.categories?.filter((category) => this.filterVisible(category)); @@ -309,22 +307,6 @@ export class AppExtensionService implements RuleContext { return { presets }; } - loadBulkActionsDropdown(config: ExtensionConfig): any { - const elements = this.loader.getElements(config, 'features.bulk-actions-dropdown'); - if (!elements.length) { - return null; - } - - let presets = {}; - presets = this.filterDisabled(mergeObjects(presets, ...elements)); - - const metadata = this.appConfig.config['content-metadata'] || {}; - metadata.presets = presets; - - this.appConfig.config['content-metadata'] = metadata; - return { presets }; - } - loadSearchForms(config: ExtensionConfig): any { const elements = this.loader.getElements(config, 'features.search'); if (!elements.length) { @@ -445,7 +427,7 @@ export class AppExtensionService implements RuleContext { } getBulkActions(): Observable> { - return this._bulkActionsDropdown.pipe(map((bulkActions) => this.getAllowedActions(bulkActions))); + return this._bulkActions.pipe(map((bulkActions) => this.getAllowedActions(bulkActions))); } getOpenWithActions(): Observable> { From 359e04f75bfb661f9eface73556ecc3f34078164 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Mon, 22 Jul 2024 13:34:07 +0200 Subject: [PATCH 07/14] ACS-8325 update state --- projects/aca-content/src/lib/store/reducers/app.reducer.ts | 2 +- projects/aca-shared/store/src/states/app.state.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/aca-content/src/lib/store/reducers/app.reducer.ts b/projects/aca-content/src/lib/store/reducers/app.reducer.ts index d6d13eee4b..aa62580c86 100644 --- a/projects/aca-content/src/lib/store/reducers/app.reducer.ts +++ b/projects/aca-content/src/lib/store/reducers/app.reducer.ts @@ -38,7 +38,7 @@ import { SetInfoDrawerPreviewStateAction, AppActionTypes, ShowLoaderAction, - INITIAL_APP_STATE + INITIAL_APP_STATE, SetSearchItemsTotalCountAction } from '@alfresco/aca-shared/store'; diff --git a/projects/aca-shared/store/src/states/app.state.ts b/projects/aca-shared/store/src/states/app.state.ts index 318d21606f..af9f2ce308 100644 --- a/projects/aca-shared/store/src/states/app.state.ts +++ b/projects/aca-shared/store/src/states/app.state.ts @@ -55,7 +55,8 @@ export const INITIAL_APP_STATE: AppState = { status: { isQuickShareEnabled: true } - } as any + } as any, + searchItemsTotalCount: null }; /** @deprecated no longer used */ From 55d576e6d72f78b8fbb0e7609ff1e74f5e2cdd10 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Mon, 22 Jul 2024 13:44:56 +0200 Subject: [PATCH 08/14] ACS-8325 temporary remove disabled state as it doesn't work after Angular migration --- .../bulk-actions-dropdown/bulk-actions-dropdown.component.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index fb4cb7a74d..7af13219ff 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -7,7 +7,6 @@ *ngIf="(totalItems$ | async) as totalItems; else disabledMode" [placeholder]="'SEARCH.BULK_ACTIONS_DROPDOWN.TITLE' | translate: { count: totalItems }" [title]="'SEARCH.BULK_ACTIONS_DROPDOWN.TITLE' | translate: { count: totalItems }" - [disabled]="false" panelClass="aca-bulk-select" disableOptionCentering data-automation-id="aca-bulk-dropdown" @@ -32,7 +31,6 @@ From 33a63bd6bca8cb3e08e4c10bc40410030fe26de9 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Tue, 23 Jul 2024 14:17:21 +0200 Subject: [PATCH 09/14] ACS-8325 add formControl and tests --- .../bulk-actions-dropdown.component.html | 19 +++---- .../bulk-actions-dropdown.component.spec.ts | 32 +++++++++--- .../bulk-actions-dropdown.component.ts | 52 ++++++++++++++++--- 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index 7af13219ff..adb7919d17 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -1,37 +1,30 @@ {{ option.title | translate }} - - - - diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 421ce93387..92adfacc52 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -26,15 +26,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BulkActionsDropdownComponent } from './bulk-actions-dropdown.component'; import { Store } from '@ngrx/store'; import { AppStore } from '../../../../../aca-shared/store/src/public-api'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; import { By } from '@angular/platform-browser'; import { ContentActionType } from '@alfresco/adf-extensions'; import { AppTestingModule } from '../../testing/app-testing.module'; +import { TranslationService } from '@alfresco/adf-core'; describe('BulkActionsDropdownComponent', () => { let component: BulkActionsDropdownComponent; let fixture: ComponentFixture; let store: Store; + let translationService: TranslationService; + let bulkFormField: HTMLElement; const totalItemsMock$: BehaviorSubject = new BehaviorSubject(0); @@ -48,7 +51,9 @@ describe('BulkActionsDropdownComponent', () => { }).compileComponents(); store = TestBed.inject(Store); + translationService = TestBed.inject(TranslationService); spyOn(store, 'select').and.returnValue(totalItemsMock$); + spyOn(translationService, 'get').and.callFake((key) => of(key)); }); beforeEach(() => { @@ -75,35 +80,42 @@ describe('BulkActionsDropdownComponent', () => { }); describe('when there are no search items', () => { - let disabledDropdown: HTMLElement; + let dropdown: HTMLElement; beforeEach(() => { totalItemsMock$.next(0); fixture.detectChanges(); - disabledDropdown = getElement('aca-bulk-dropdown-disabled'); + dropdown = getElement('aca-bulk-dropdown'); + bulkFormField = getElement('aca-bulk-form-field'); fixture.detectChanges(); }); it('should disable dropdown', () => { - expect(disabledDropdown.getAttribute('aria-disabled')).toBe('true'); + expect(dropdown.getAttribute('aria-disabled')).toBe('true'); }); it('should have correct tooltip', () => { - expect(disabledDropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE_TOOLTIP'); + expect(bulkFormField.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE_TOOLTIP'); }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown-disabled')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); + expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); + }); + + it('should call translationService.get with correct arguments', () => { + expect(translationService.get).toHaveBeenCalledWith('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); + expect(translationService.get).toHaveBeenCalledWith('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE_TOOLTIP'); }); }); - describe('when there are search elements', () => { + describe('when there are search items', () => { let dropdown: HTMLElement; beforeEach(() => { totalItemsMock$.next(10); fixture.detectChanges(); dropdown = getElement('aca-bulk-dropdown'); + bulkFormField = getElement('aca-bulk-form-field'); dropdown.click(); fixture.detectChanges(); }); @@ -113,7 +125,7 @@ describe('BulkActionsDropdownComponent', () => { }); it('should have correct tooltip', () => { - expect(dropdown.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); + expect(bulkFormField.getAttribute('title')).toBe('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); }); it('should have correct placeholder', () => { @@ -137,5 +149,9 @@ describe('BulkActionsDropdownComponent', () => { expect(icon.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); }); + + it('should call translationService.get with correct arguments', () => { + expect(translationService.get).toHaveBeenCalledWith('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: 10 }); + }); }); }); diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts index 353a050760..c647149350 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts @@ -25,25 +25,65 @@ import { ContentActionRef } from '@alfresco/adf-extensions'; import { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store'; import { CommonModule } from '@angular/common'; -import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { MatSelectModule } from '@angular/material/select'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; -import { Observable } from 'rxjs'; -import { IconComponent } from '@alfresco/adf-core'; +import { combineLatest, Observable, Subject } from 'rxjs'; +import { IconComponent, TranslationService } from '@alfresco/adf-core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { switchMap, takeUntil } from 'rxjs/operators'; @Component({ standalone: true, selector: 'aca-bulk-actions-dropdown', templateUrl: './bulk-actions-dropdown.component.html', styleUrls: ['./bulk-actions-dropdown.component.scss'], - imports: [CommonModule, TranslateModule, MatSelectModule, IconComponent], + imports: [CommonModule, TranslateModule, MatSelectModule, IconComponent, ReactiveFormsModule], encapsulation: ViewEncapsulation.None }) -export class BulkActionsDropdownComponent { +export class BulkActionsDropdownComponent implements OnInit, OnDestroy { @Input() items: ContentActionRef[]; + placeholder: string; + tooltip: string; totalItems$: Observable = this.store.select(getSearchItemsTotalCount); + selectControl = new FormControl(); - constructor(private store: Store) {} + private onDestroy$ = new Subject(); + + constructor(private store: Store, private translationService: TranslationService) {} + + ngOnInit() { + this.totalItems$ + .pipe( + switchMap((totalItems) => { + if (totalItems > 0) { + this.selectControl.enable(); + + return combineLatest([ + this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: totalItems }), + this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: totalItems }) + ]); + } else { + this.selectControl.disable(); + + return combineLatest([ + this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'), + this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE_TOOLTIP') + ]); + } + }), + takeUntil(this.onDestroy$) + ) + .subscribe(([placeholder, title]) => { + this.tooltip = title; + this.placeholder = placeholder; + }); + } + + ngOnDestroy() { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } } From 3898c217d7eec860d5dcf090f52abc8a239d8a85 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Tue, 23 Jul 2024 22:34:50 +0200 Subject: [PATCH 10/14] ACS-8325 clean code --- .../bulk-actions-dropdown.component.html | 2 +- .../bulk-actions-dropdown.component.spec.ts | 2 +- .../bulk-actions-dropdown.component.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index adb7919d17..10ce0bf661 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -6,7 +6,7 @@ data-automation-id="aca-bulk-form-field" > = this.store.select(getSearchItemsTotalCount); - selectControl = new FormControl(); + disableControl = new FormControl(); private onDestroy$ = new Subject(); @@ -59,14 +59,14 @@ export class BulkActionsDropdownComponent implements OnInit, OnDestroy { .pipe( switchMap((totalItems) => { if (totalItems > 0) { - this.selectControl.enable(); + this.disableControl.enable(); return combineLatest([ this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: totalItems }), this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: totalItems }) ]); } else { - this.selectControl.disable(); + this.disableControl.disable(); return combineLatest([ this.translationService.get('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'), From 4e83271c9330b2706d7faf64dcf7c78ae4639f2d Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Wed, 24 Jul 2024 09:03:33 +0200 Subject: [PATCH 11/14] ACS-8325 place create component to one place --- .../bulk-actions-dropdown.component.spec.ts | 9 +++------ .../bulk-actions-dropdown.component.ts | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 8ef8066a39..7caa5bf32b 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -38,6 +38,7 @@ describe('BulkActionsDropdownComponent', () => { let store: Store; let translationService: TranslationService; let bulkFormField: HTMLElement; + let dropdown: HTMLElement; const totalItemsMock$: BehaviorSubject = new BehaviorSubject(0); @@ -52,13 +53,13 @@ describe('BulkActionsDropdownComponent', () => { store = TestBed.inject(Store); translationService = TestBed.inject(TranslationService); + spyOn(store, 'select').and.returnValue(totalItemsMock$); spyOn(translationService, 'get').and.callFake((key) => of(key)); - }); - beforeEach(() => { fixture = TestBed.createComponent(BulkActionsDropdownComponent); component = fixture.componentInstance; + component.items = [ { id: 'app.bulk.actions.legalHold', @@ -80,8 +81,6 @@ describe('BulkActionsDropdownComponent', () => { }); describe('when there are no search items', () => { - let dropdown: HTMLElement; - beforeEach(() => { totalItemsMock$.next(0); fixture.detectChanges(); @@ -109,8 +108,6 @@ describe('BulkActionsDropdownComponent', () => { }); describe('when there are search items', () => { - let dropdown: HTMLElement; - beforeEach(() => { totalItemsMock$.next(10); fixture.detectChanges(); diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts index e61ebeecd3..f1b751fab0 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.ts @@ -47,10 +47,10 @@ export class BulkActionsDropdownComponent implements OnInit, OnDestroy { placeholder: string; tooltip: string; - totalItems$: Observable = this.store.select(getSearchItemsTotalCount); disableControl = new FormControl(); - private onDestroy$ = new Subject(); + private readonly totalItems$: Observable = this.store.select(getSearchItemsTotalCount); + private readonly onDestroy$ = new Subject(); constructor(private store: Store, private translationService: TranslationService) {} From 25408cb2aada9e91cf5f356bb0c9b15484897529 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Wed, 24 Jul 2024 10:14:53 +0200 Subject: [PATCH 12/14] ACS-8325 add condition to use title if no description provided and cover with test --- .../bulk-actions-dropdown.component.html | 2 +- .../bulk-actions-dropdown.component.spec.ts | 44 +++++++++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index 10ce0bf661..ac0af25465 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -15,7 +15,7 @@ { let bulkFormField: HTMLElement; let dropdown: HTMLElement; + const mockItem: ContentActionRef = { + id: 'app.bulk.actions.legalHold', + component: 'app.bulk-actions-dropdown', + title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + description: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + icon: 'adf:manage_hold', + type: ContentActionType.custom, + rules: { + visible: 'app.manage.holds.isLegalHoldPluginEnabled' + } + }; + const totalItemsMock$: BehaviorSubject = new BehaviorSubject(0); const getElement = (selector: string): HTMLElement | null => fixture.debugElement.query(By.css(`[data-automation-id="${selector}"]`)).nativeElement; @@ -60,19 +72,7 @@ describe('BulkActionsDropdownComponent', () => { fixture = TestBed.createComponent(BulkActionsDropdownComponent); component = fixture.componentInstance; - component.items = [ - { - id: 'app.bulk.actions.legalHold', - component: 'app.bulk-actions-dropdown', - title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', - description: 'GOVERNANCE.MANAGE_HOLDS.TITLE', - icon: 'adf:manage_hold', - type: ContentActionType.custom, - rules: { - visible: 'app.manage.holds.isLegalHoldPluginEnabled' - } - } - ]; + component.items = [mockItem]; fixture.detectChanges(); }); @@ -151,4 +151,20 @@ describe('BulkActionsDropdownComponent', () => { expect(translationService.get).toHaveBeenCalledWith('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: 10 }); }); }); + + it('should use option title for tooltip if no description provided', () => { + component.items = [ + { + ...mockItem, + description: null + } + ]; + totalItemsMock$.next(1); + dropdown = getElement('aca-bulk-dropdown'); + dropdown.click(); + fixture.detectChanges(); + const option = getElement('app.bulk.actions.legalHold'); + + expect(option.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + }); }); From f9fa5c040b6ce0efaa0cfc32647082a8675c5632 Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Fri, 26 Jul 2024 11:27:51 +0200 Subject: [PATCH 13/14] ACS-8325 add tooltip and update Badge interface --- extension.schema.json | 4 ++++ .../bulk-actions-dropdown.component.html | 2 +- .../bulk-actions-dropdown.component.spec.ts | 18 +----------------- projects/aca-shared/src/lib/models/types.ts | 4 +++- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/extension.schema.json b/extension.schema.json index 40d5931d75..8664fe4d9a 100644 --- a/extension.schema.json +++ b/extension.schema.json @@ -115,6 +115,10 @@ "description": "Element title", "type": "string" }, + "tooltip": { + "description": "Element tooltip to display on hover", + "type": "string" + }, "description": { "description": "Element description, used for the tooltips.", "type": "string" diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index ac0af25465..62ddf5bea3 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -15,7 +15,7 @@ { id: 'app.bulk.actions.legalHold', component: 'app.bulk-actions-dropdown', title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', - description: 'GOVERNANCE.MANAGE_HOLDS.TITLE', + tooltip: 'GOVERNANCE.MANAGE_HOLDS.TITLE', icon: 'adf:manage_hold', type: ContentActionType.custom, rules: { @@ -151,20 +151,4 @@ describe('BulkActionsDropdownComponent', () => { expect(translationService.get).toHaveBeenCalledWith('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE', { count: 10 }); }); }); - - it('should use option title for tooltip if no description provided', () => { - component.items = [ - { - ...mockItem, - description: null - } - ]; - totalItemsMock$.next(1); - dropdown = getElement('aca-bulk-dropdown'); - dropdown.click(); - fixture.detectChanges(); - const option = getElement('app.bulk.actions.legalHold'); - - expect(option.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); - }); }); diff --git a/projects/aca-shared/src/lib/models/types.ts b/projects/aca-shared/src/lib/models/types.ts index 9ea7af3787..fe39c72237 100644 --- a/projects/aca-shared/src/lib/models/types.ts +++ b/projects/aca-shared/src/lib/models/types.ts @@ -29,6 +29,8 @@ export interface ExtensionRoute extends Route { parentRoute?: string; } -export interface Badge extends ContentActionRef { +export interface Badge extends Partial> { + id: string; + icon: string; tooltip: string; } From 67249e9c4e4609ccda162c3cd7dc2e14b565c83c Mon Sep 17 00:00:00 2001 From: Darya Balvanovich Date: Mon, 29 Jul 2024 21:46:06 +0200 Subject: [PATCH 14/14] ACS-8325 rename class names and mockItem object --- .../bulk-actions-dropdown.component.html | 10 +++--- .../bulk-actions-dropdown.component.scss | 4 +-- .../bulk-actions-dropdown.component.spec.ts | 35 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html index 62ddf5bea3..b755a954c0 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.html @@ -2,15 +2,15 @@ *ngIf="items?.length" [title]="tooltip" appearance="outline" - class="aca-bulk-form-field" - data-automation-id="aca-bulk-form-field" + class="aca-bulk-actions-form-field" + data-automation-id="aca-bulk-actions-form-field" > {{ option.title | translate }} diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss index 7fbd693a7f..ca462e74b9 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.scss @@ -2,11 +2,11 @@ // TODO: ACS-8458 Review css selectors -.aca-bulk-select { +.aca-bulk-actions-select { margin-top: 31px; } -.aca-bulk-form-field { +.aca-bulk-actions-form-field { margin-left: 24px; margin-top: 1.4375em; width: 295px; diff --git a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts index 3726bc9e43..43a0ac3f9a 100644 --- a/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts +++ b/projects/aca-content/src/lib/components/bulk-actions-dropdown/bulk-actions-dropdown.component.spec.ts @@ -41,14 +41,13 @@ describe('BulkActionsDropdownComponent', () => { let dropdown: HTMLElement; const mockItem: ContentActionRef = { - id: 'app.bulk.actions.legalHold', - component: 'app.bulk-actions-dropdown', - title: 'GOVERNANCE.MANAGE_HOLDS.TITLE', - tooltip: 'GOVERNANCE.MANAGE_HOLDS.TITLE', - icon: 'adf:manage_hold', + id: 'mockId', + title: 'some title', + tooltip: 'some tooltip', + icon: 'adf:mock-icon', type: ContentActionType.custom, rules: { - visible: 'app.manage.holds.isLegalHoldPluginEnabled' + visible: 'isItemVisible' } }; @@ -84,8 +83,8 @@ describe('BulkActionsDropdownComponent', () => { beforeEach(() => { totalItemsMock$.next(0); fixture.detectChanges(); - dropdown = getElement('aca-bulk-dropdown'); - bulkFormField = getElement('aca-bulk-form-field'); + dropdown = getElement('aca-bulk-actions-dropdown'); + bulkFormField = getElement('aca-bulk-actions-form-field'); fixture.detectChanges(); }); @@ -98,7 +97,7 @@ describe('BulkActionsDropdownComponent', () => { }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); + expect(getLabelText('aca-bulk-actions-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.BULK_NOT_AVAILABLE'); }); it('should call translationService.get with correct arguments', () => { @@ -111,8 +110,8 @@ describe('BulkActionsDropdownComponent', () => { beforeEach(() => { totalItemsMock$.next(10); fixture.detectChanges(); - dropdown = getElement('aca-bulk-dropdown'); - bulkFormField = getElement('aca-bulk-form-field'); + dropdown = getElement('aca-bulk-actions-dropdown'); + bulkFormField = getElement('aca-bulk-actions-form-field'); dropdown.click(); fixture.detectChanges(); }); @@ -126,25 +125,25 @@ describe('BulkActionsDropdownComponent', () => { }); it('should have correct placeholder', () => { - expect(getLabelText('aca-bulk-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); + expect(getLabelText('aca-bulk-actions-dropdown')).toEqual('SEARCH.BULK_ACTIONS_DROPDOWN.TITLE'); }); it('should have option with correct tooltip', () => { - const option = getElement('app.bulk.actions.legalHold'); + const option = getElement('mockId'); - expect(option.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + expect(option.getAttribute('title')).toEqual('some tooltip'); }); it('should have option with correct label', () => { - const optionLabel = getLabelText('app.bulk.actions.legalHold'); + const optionLabel = getLabelText('mockId'); - expect(optionLabel).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + expect(optionLabel).toEqual('some title'); }); it('should have correct icon in an option', () => { - const icon = getElement('aca-option-icon-app.bulk.actions.legalHold'); + const icon = getElement('aca-bulk-action-icon-mockId'); - expect(icon.getAttribute('title')).toEqual('GOVERNANCE.MANAGE_HOLDS.TITLE'); + expect(icon.getAttribute('title')).toEqual('some title'); }); it('should call translationService.get with correct arguments', () => {