[ACS-8036] [Bulk update] [Many files to 1 Hold flow] "Manage Holds" dialog with Manage Existing Holds/Apply New Hold tabs (#4019)

* [ACS-8325] [Bulk Legal Hold] Create Bulk Actions Dropdown (#3956)

* ACS-8036 create bulk-actions-dropdown

* ACS-8325 update names and add unit tests

* ACS-8325 added icon and unit tests

* ACS-8325 fix translation

* ACS-8325 add and refactor tests in app extension service

* ACS-8325 resolve conversations: remove loadBulkActions, rename bulk schema, add translations

* ACS-8325 update state

* ACS-8325 temporary remove disabled state as it doesn't work after Angular migration

* ACS-8325 add formControl and tests

* ACS-8325 clean code

* ACS-8325 place create component to one place

* ACS-8325 add condition to use title if no description provided and cover with test

* ACS-8325 add tooltip and update Badge interface

* ACS-8325 rename class names and mockItem object

* [ACS-8326] enable running actions from bulk dropdown and resetting selection (#3971)

* ACS-8036 create bulk-actions-dropdown

* ACS-8325 update names and add unit tests

* ACS-8325 fix translation

* ACS-8325 resolve conversations: remove loadBulkActions, rename bulk schema, add translations

* ACS-8325 temporary remove disabled state as it doesn't work after Angular migration

* ACS-8325 add formControl and tests

* ACS-8325 add condition to use title if no description provided and cover with test

* ACS-8325 add tooltip and update Badge interface

* ACS-8326 enable running actions from bulk dropdown and resetting dropdown selection

* ACS-8326 review remarks - use select control, fix naming

* ACS-8326 fix unit test selectors

* ACS-8326 review remarks - change property name to more universal, adjust unit tests

---------

Co-authored-by: Darya Balvanovich <darya.balvanovich@hyland.com>

* [ACS-8424][Bulk Legal Hold] Add Badge for items (#3985)

* [ACS-8424] display badges in search result

* [ACS-8424] display badges in search result

* ACS-8424 create separate badge component, add/move unit tests, undo highlight change failing tests

* ACS-8424 template cleanup

* ACS-8424 template cleanup cleanup

* ACS-8424 revert single deletion in template

* ACS-8424 rename new component, change property order

---------

Co-authored-by: g-jaskowski <grzegorz.jaskowski@hyland.com>

* ACS-8458 refactor styles (#4018)

* [ACS-8489] Legal Holds keyboard accessibility (#4009)

* ACS-8489 handle keyboard accessibility

* ACS-8489 wording fix

* ACS-8489 change function name

* ACS-8489 fix typo

* ACS-8489 review remarks - simplify keyboard event handling, improve unit tests

* ACS-8489 move duplicated code to method

* ACS-8489 change type name to more precise

* [ACS-8036] fix icon visibility in mat-select

* ACS-8036 fix styles and import

* ACS-8036 remove async from test

* ACS-8036 handle event when dropdown closed

* ACS-8036 fix rebase issues

* ACS-8036 fix rebase issues

* ACS-8036 fix rebase

---------

Co-authored-by: Grzegorz Jaśkowski <138671284+g-jaskowski@users.noreply.github.com>
Co-authored-by: tamaragruszka <156320606+tamaragruszka@users.noreply.github.com>
Co-authored-by: g-jaskowski <grzegorz.jaskowski@hyland.com>
Co-authored-by: tamaragruszka <tamara.gruszka@hyland.com>
This commit is contained in:
Darya Blavanovich
2024-08-14 20:15:19 +02:00
committed by GitHub
parent 068f6bb8e9
commit 53e90312b0
30 changed files with 856 additions and 340 deletions

View File

@@ -61,12 +61,13 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges {
selection: SelectionState;
actions: Array<ContentActionRef> = [];
viewerToolbarActions: Array<ContentActionRef> = [];
bulkActions: ContentActionRef[] = [];
canUpdateNode = false;
canUpload = false;
nodeResult: NodePaging;
showHeader = ShowHeaderMode.Data;
filterSorting = 'name-asc';
createActions: Array<ContentActionRef> = [];
createActions: ContentActionRef[] = [];
isSmallScreen = false;
selectedRowItemsCount = 0;
@@ -107,6 +108,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$))

View File

@@ -29,6 +29,8 @@ export interface ExtensionRoute extends Route {
parentRoute?: string;
}
export interface Badge extends ContentActionRef {
export interface Badge extends Partial<Pick<ContentActionRef, 'component' | 'actions' | 'rules'>> {
id: string;
icon: string;
tooltip: string;
}

View File

@@ -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': 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: [
{
@@ -1814,4 +1675,14 @@ describe('AppExtensionService', () => {
service.updateSidebarActions();
expect(loader.getContentActions).toHaveBeenCalledWith(service.config, 'features.sidebar.toolbar');
});
it('should emit bulkActionExecuted', (done) => {
spyOn(service, 'bulkActionExecuted').and.callThrough();
service.bulkActionExecuted$.subscribe(() => {
expect(service.bulkActionExecuted).toHaveBeenCalled();
done();
});
service.bulkActionExecuted();
});
});

View File

@@ -50,7 +50,7 @@ import {
sortByOrder
} from '@alfresco/adf-extensions';
import { AppConfigService, AuthenticationService, LogService } from '@alfresco/adf-core';
import { BehaviorSubject, Observable } from 'rxjs';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { NodeEntry, RepositoryInfo } from '@alfresco/js-api';
import { ViewerRules } from '../models/viewer.rules';
import { Badge } from '../models/types';
@@ -63,6 +63,7 @@ import { SearchCategory } from '@alfresco/adf-content-services';
})
export class AppExtensionService implements RuleContext {
private _references = new BehaviorSubject<ExtensionRef[]>([]);
bulkActionExecuted$ = new Subject<void>();
navbar: Array<NavBarGroupRef> = [];
sidebarTabs: Array<SidebarTabRef> = [];
@@ -81,6 +82,7 @@ export class AppExtensionService implements RuleContext {
private _badges = new BehaviorSubject<Array<Badge>>([]);
private _filesDocumentListPreset = new BehaviorSubject<Array<DocumentListPresetRef>>([]);
private _customMetadataPanels = new BehaviorSubject<Array<ContentActionRef>>([]);
private _bulkActions = new BehaviorSubject<Array<ContentActionRef>>([]);
documentListPresets: {
libraries: Array<DocumentListPresetRef>;
@@ -160,6 +162,7 @@ export class AppExtensionService implements RuleContext {
this._badges.next(this.loader.getElements<Badge>(config, 'features.badges'));
this._filesDocumentListPreset.next(this.getDocumentListPreset(config, 'files'));
this._customMetadataPanels.next(this.loader.getElements<ContentActionRef>(config, 'features.customMetadataPanels'));
this._bulkActions.next(this.loader.getElements<ContentActionRef>(config, 'features.bulk-actions'));
this.navbar = this.loadNavBar(config);
this.sidebarTabs = this.loader.getElements<SidebarTabRef>(config, 'features.sidebar.tabs');
@@ -424,6 +427,10 @@ export class AppExtensionService implements RuleContext {
return this._viewerToolbarActions.pipe(map((viewerToolbarActions) => this.getAllowedActions(viewerToolbarActions)));
}
getBulkActions(): Observable<Array<ContentActionRef>> {
return this._bulkActions.pipe(map((bulkActions) => this.getAllowedActions(bulkActions)));
}
getOpenWithActions(): Observable<Array<ContentActionRef>> {
return this._openWithActions.pipe(map((openWithActions) => this.getAllowedActions(openWithActions)));
}
@@ -565,4 +572,8 @@ export class AppExtensionService implements RuleContext {
return true;
}
bulkActionExecuted(): void {
this.bulkActionExecuted$.next();
}
}