Skip to content

Commit

Permalink
[AAE-7817] Add columns selector for processes and tasks tasks (#7612)
Browse files Browse the repository at this point in the history
* [AAE-7817] Add columns selector for processes and tasks tasks

* cr

* Update

* fix unit tests

* preserve order while sorting

* add input toggle to show main actions

* fix test
  • Loading branch information
BSekula committed May 17, 2022
1 parent 1e3099b commit 95fc295
Show file tree
Hide file tree
Showing 16 changed files with 271 additions and 33 deletions.
Expand Up @@ -20,6 +20,7 @@
[actions]="true"
[resolverFn]="resolver"
rowStyleClass="custom-row-style"
[showMainDatatableActions]="true"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)">
<!-- HTML column definition demo -->
Expand Down
Expand Up @@ -114,11 +114,15 @@ describe('ColumnsSelectorComponent', () => {

const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness);

expect(checkboxes.length).toBe(4);
expect(await checkboxes[0].getLabelText()).toBe(inputColumns[0].title);
expect(await checkboxes[1].getLabelText()).toBe(inputColumns[1].title);
expect(await checkboxes[2].getLabelText()).toBe(inputColumns[2].title);
expect(await checkboxes[3].getLabelText()).toBe(inputColumns[4].title);
const inputColumnsWithTitle = inputColumns.filter(column => !!column.title);
expect(checkboxes.length).toBe(inputColumnsWithTitle.length);

for await (const checkbox of checkboxes) {
const checkboxLabel = await checkbox.getLabelText();

const inputColumn = inputColumnsWithTitle.find(inputColumnWithTitle => inputColumnWithTitle.title === checkboxLabel);
expect(inputColumn).toBeTruthy('Should have all columns with title');
}
});

it('should filter columns by search text', fakeAsync(async () => {
Expand All @@ -143,9 +147,13 @@ describe('ColumnsSelectorComponent', () => {
fixture.detectChanges();

const firstColumnCheckbox = await loader.getHarness(MatCheckboxHarness);
await firstColumnCheckbox.toggle();
const checkBoxName = await firstColumnCheckbox.getLabelText();

expect(component.columnItems[0].isHidden).toBe(true);
let toggledColumnItem = component.columnItems.find(item => item.title === checkBoxName);
expect(toggledColumnItem.isHidden).toBeFalsy();

await firstColumnCheckbox.toggle();
expect(toggledColumnItem.isHidden).toBe(true);
});

it('should set proper default state for checkboxes', async () => {
Expand All @@ -159,4 +167,30 @@ describe('ColumnsSelectorComponent', () => {
expect(await checkboxes[2].isChecked()).toBe(true);
expect(await checkboxes[3].isChecked()).toBe(false);
});

it('should show hidden columns at the end of the list', async () => {
const hiddenDataColumn: DataColumn = {
id: 'hiddenDataColumn',
title: 'hiddenDataColumn',
key: 'hiddenDataColumn',
type: 'text',
isHidden: true
};

const shownDataColumn: DataColumn = {
id: 'shownDataColumn',
title: 'shownDataColumn',
key: 'shownDataColumn',
type: 'text'
};

component.columns = [hiddenDataColumn, shownDataColumn];
menuOpenedTrigger.next();
fixture.detectChanges();

const checkboxes = await loader.getAllHarnesses(MatCheckboxHarness);

expect(await checkboxes[0].getLabelText()).toBe(shownDataColumn.title);
expect(await checkboxes[1].getLabelText()).toBe(hiddenDataColumn.title);
});
});
Expand Up @@ -46,7 +46,8 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
this.mainMenuTrigger.menuOpened.pipe(
takeUntil(this.onDestroy$)
).subscribe(() => {
this.columnItems = this.columns.map(column => ({...column}));
const columns = this.columns.map(column => ({...column}));
this.columnItems = this.sortColumns(columns);
});

this.mainMenuTrigger.menuClosed.pipe(
Expand Down Expand Up @@ -80,4 +81,11 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
this.submitColumnsVisibility.emit(this.columnItems);
this.closeMenu();
}

private sortColumns(columns: DataColumn[]): DataColumn[] {
const shownColumns = columns.filter(column => !column.isHidden);
const hiddenColumns = columns.filter(column => column.isHidden);

return [...shownColumns, ...hiddenColumns];
}
}
Expand Up @@ -97,11 +97,13 @@

<!-- Header actions (right) -->
<div
*ngIf="actions && actionsPosition === 'right' || mainActionTemplate"
*ngIf="(actions && actionsPosition === 'right') ||
(mainActionTemplate && showMainDatatableActions)"
class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell"
>
<ng-container *ngIf="mainActionTemplate">
<button
data-automation-id="adf-datatable-main-menu-button"
mat-icon-button
#mainMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="mainMenu">
Expand Down Expand Up @@ -286,7 +288,9 @@
</div>

<!-- Row actions (right) -->
<div *ngIf="(actions && actionsPosition === 'right') || mainActionTemplate"
<div *ngIf="
(actions && actionsPosition === 'right') ||
(mainActionTemplate && showMainDatatableActions)"
role="gridcell"
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie">

Expand Down
Expand Up @@ -112,6 +112,10 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
@Input()
actions: boolean = false;

/** Toggles the main datatable action. */
@Input()
showMainDatatableActions: boolean = false;

/** Position of the actions dropdown menu. Can be "left" or "right". */
@Input()
actionsPosition: string = 'right'; // left|right
Expand Down
14 changes: 6 additions & 8 deletions lib/core/datatable/data/data-table.schema.ts
Expand Up @@ -38,8 +38,7 @@ export abstract class DataTableSchema {
protected columnsOrder: string[] | undefined;
protected columnsOrderedByKey: string = 'id';

protected hiddenColumns: string[] | undefined;
protected hiddenColumnsKey: string = 'id';
protected columnsVisibility: { [columnId: string]: boolean } | undefined;

private layoutPresets = {};

Expand Down Expand Up @@ -133,14 +132,13 @@ export abstract class DataTableSchema {
}

private setHiddenColumns(columns: DataColumn[]): DataColumn[] {
if (this.hiddenColumns) {
if (this.columnsVisibility) {
return columns.map(column => {
const columnShouldBeHidden = this.hiddenColumns.includes(column[this.hiddenColumnsKey]);
const isColumnVisible = this.columnsVisibility[column.id];

return {
...column,
isHidden: columnShouldBeHidden
};
return isColumnVisible === undefined ?
column :
{ ...column, isHidden: !isColumnVisible };
});
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
[actions]="showActions"
[actionsPosition]="actionsPosition"
[contextMenu]="showContextMenu"
[showMainDatatableActions]="showMainDatatableActions"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(showRowContextMenu)="onShowRowContextMenu($event)"
(executeRowAction)="onExecuteRowAction($event)"
Expand Down Expand Up @@ -39,4 +40,14 @@
<ng-content select="adf-custom-empty-content-template"></ng-content>
</ng-template>
</adf-no-content-template>

<adf-main-menu-datatable-template>
<ng-template let-mainMenuTrigger>
<adf-datatable-column-selector
[columns]="columns"
[mainMenuTrigger]="mainMenuTrigger"
(submitColumnsVisibility)="onColumnsVisibilityChange($event)">
</adf-datatable-column-selector>
</ng-template>
</adf-main-menu-datatable-template>
</adf-datatable>
Expand Up @@ -19,6 +19,8 @@ import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
AppConfigService,
ColumnsSelectorComponent,
DataColumn,
DataRowEvent,
ObjectDataRow,
setupTestBed
Expand Down Expand Up @@ -225,6 +227,64 @@ describe('ProcessListCloudComponent', () => {
fixture.detectChanges();
});

it('should not shown columns selector by default', () => {
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));

const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });

fixture.detectChanges();

const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
expect(mainMenuButton).toBeFalsy();
});

it('should shown columns selector', () => {
component.showMainDatatableActions = true;
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));

const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });

fixture.detectChanges();

const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
expect(mainMenuButton).toBeTruthy();
});

it('should hide columns on applying new columns visibility through columns selector', () => {
component.showMainDatatableActions = true;
fixture.detectChanges();

spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));

const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });

fixture.detectChanges();

const mainMenuButton = fixture.debugElement.query(By.css('[data-automation-id="adf-datatable-main-menu-button"]'));
mainMenuButton.triggerEventHandler('click', {});
fixture.detectChanges();

const columnSelectorMenu = fixture.debugElement.query(By.css('adf-datatable-column-selector'));
expect(columnSelectorMenu).toBeTruthy();

const newColumns = (component.columns as DataColumn[]).map((column, index) => ({
...column,
isHidden: index !== 0 // only first one is shown
}));

const columnsSelectorInstance = columnSelectorMenu.componentInstance as ColumnsSelectorComponent;
expect(columnsSelectorInstance.columns).toBe(component.columns, 'should use columns as input');

columnSelectorMenu.triggerEventHandler('submitColumnsVisibility', newColumns);
fixture.detectChanges();

const displayedColumns = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-header'));
expect(displayedColumns.length).toBe(2, 'only column with isHidden set to false and action column should be shown');
});

it('should reload tasks when reload() is called', (done) => {
component.appName = 'fake';
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
Expand Down
Expand Up @@ -159,6 +159,10 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
@Input()
showContextMenu: boolean = false;

/** Toggle main datatable actions. */
@Input()
showMainDatatableActions: boolean = false;

/** Emitted when a row in the process list is clicked. */
@Output()
rowClick: EventEmitter<string> = new EventEmitter<string>();
Expand Down Expand Up @@ -223,14 +227,22 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
map((preferences => {
const preferencesList = preferences?.list?.entries ?? [];
const columnsOrder = preferencesList.find(preference => preference.entry.key === ProcessListCloudPreferences.columnOrder);
const columnsVisibility = preferencesList.find(preference => preference.entry.key === ProcessListCloudPreferences.columnsVisibility);

return {
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined
columnsOrder: columnsOrder ? JSON.parse(columnsOrder.entry.value) : undefined,
columnsVisibility: columnsVisibility ? JSON.parse(columnsVisibility.entry.value) : undefined
};
}))
)
.subscribe(({ columnsOrder }) => {
this.columnsOrder = columnsOrder;
.subscribe(({ columnsOrder, columnsVisibility }) => {
if (columnsVisibility) {
this.columnsVisibility = columnsVisibility;
}

if (columnsOrder) {
this.columnsOrder = columnsOrder;
}

this.createDatatableSchema();
});
Expand Down Expand Up @@ -326,12 +338,33 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan
}

onColumnOrderChanged(columnsWithNewOrder: DataColumn[]): void {
this.columnsOrder = columnsWithNewOrder.map(column => column.id);

if (this.appName) {
const newColumnsOrder = columnsWithNewOrder.map(column => column.id);
this.cloudPreferenceService.updatePreference(
this.appName,
ProcessListCloudPreferences.columnOrder,
newColumnsOrder
this.columnsOrder
);
}
}

onColumnsVisibilityChange(columns: DataColumn[]): void {
this.columnsVisibility = columns.reduce((visibleColumnsMap, column) => {
if (column.isHidden !== undefined) {
visibleColumnsMap[column.id] = !column.isHidden;
}

return visibleColumnsMap;
}, {});

this.createColumns();

if (this.appName) {
this.cloudPreferenceService.updatePreference(
this.appName,
ProcessListCloudPreferences.columnsVisibility,
this.columnsVisibility
);
}
}
Expand Down
@@ -1,4 +1,5 @@
// eslint-disable-next-line no-shadow
export enum ProcessListCloudPreferences {
columnOrder = 'processes-cloud-list-columns-order'
columnOrder = 'processes-cloud-list-columns-order',
columnsVisibility = 'processes-cloud-columns-visibility'
}
Expand Up @@ -18,12 +18,14 @@
export const processCloudPresetsDefaultModel = {
default: [
{
id: 'id',
key: 'name',
type: 'text',
title: 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME',
sortable: true
},
{
id: 'startDate',
key: 'startDate',
type: 'date',
title: 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.START_DATE',
Expand Down
Expand Up @@ -12,6 +12,7 @@
[actionsPosition]="actionsPosition"
[contextMenu]="showContextMenu"
[resolverFn]="boundReplacePriorityValues"
[showMainDatatableActions]="showMainDatatableActions"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(showRowContextMenu)="onShowRowContextMenu($event)"
(executeRowAction)="onExecuteRowAction($event)"
Expand Down Expand Up @@ -40,5 +41,15 @@
<ng-content select="adf-custom-empty-content-template"></ng-content>
</ng-template>
</adf-no-content-template>

<adf-main-menu-datatable-template>
<ng-template let-mainMenuTrigger>
<adf-datatable-column-selector
[columns]="columns"
[mainMenuTrigger]="mainMenuTrigger"
(submitColumnsVisibility)="onColumnsVisibilityChange($event)">
</adf-datatable-column-selector>
</ng-template>
</adf-main-menu-datatable-template>
</adf-datatable>
</ng-container>

0 comments on commit 95fc295

Please sign in to comment.