Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# v13.5.0 (2022-07-21)
* **deps** add dom iterable in tsconfig
* **grid** add tests for custom filter
* **playground** add custom filter input
* **grid** add input for custom filter value
* **playground** convert filter value to string

# v13.4.1 (2022-06-22)
* **suggest** hide no results when header items are available

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-components",
"version": "13.4.1",
"version": "13.5.0",
"author": {
"name": "UiPath Inc",
"url": "https://uipath.com"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import { IFilterModel } from '../models';
* @internal
*/
export class FilterManager<T> {
hasCustomFilter$ = new BehaviorSubject(false);
customFilters?: IFilterModel<T>[];

filter$ = new BehaviorSubject<IFilterModel<T>[]>([]);

dirty$ = this.filter$.pipe(
Expand Down Expand Up @@ -105,6 +108,17 @@ export class FilterManager<T> {
}
}

updateCustomFilters(customValue: IFilterModel<T>[]) {
this.customFilters = customValue;
this.hasCustomFilter$.next(true);
this.filter$.next(customValue);
}

clearCustomFilters() {
this.hasCustomFilter$.next(false);
this._emitFilterOptions();
}

private _updateFilterValue = (
column: UiGridColumnDirective<T> | undefined,
value: ISuggestValue | IDropdownOption | undefined,
Expand Down Expand Up @@ -142,7 +156,11 @@ export class FilterManager<T> {
: [];
if (isEqual(this.filter$.getValue(), updatedFilters)) { return; }

this.filter$.next(updatedFilters);
this.filter$.next(
this.hasCustomFilter$.value
? this.customFilters!
: updatedFilters,
);
};

private _hasFilterValue = (dropdown?: UiGridSearchFilterDirective<T> | UiGridDropdownFilterDirective<T>) =>
Expand Down
86 changes: 49 additions & 37 deletions projects/angular/components/ui-grid/src/ui-grid.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,64 @@
class="ui-grid-filter-container">
<div class="ui-grid-filter-container-lhs-group">
<div class="ui-grid-filter-container-lhs-group-actions">
<ng-container *ngIf="useLegacyDesign">
<ng-container *ngIf="filterManager.hasCustomFilter$ | async; else noCustomFilter">
<ng-container *ngTemplateOutlet="toggleColumnsTmpl"></ng-container>
<button (click)="clearCustomFilter()"
mat-flat-button type="button"
data-cy="clear-custom-filter">
{{ intl.clearCustomFilter }}
</button>
</ng-container>
<ng-template #noCustomFilter>
<ng-container>
<ng-container *ngIf="useLegacyDesign">
<ng-container *ngTemplateOutlet="toggleColumnsTmpl"></ng-container>
</ng-container>

<ng-container *ngIf="!(hasSelection$ | async) ||
!header?.actionButtons?.length">
<ui-grid-search *ngIf="header?.search"
[debounce]="header!.searchDebounce"
[maxLength]="header!.searchMaxLength"
[placeholder]="intl.searchPlaceholder"
[searchTooltip]="intl.searchTooltip"
[clearTooltip]="intl.clearTooltip"
[tooltipDisabled]="resizeManager.isResizing"
[value]="header!.searchValue!"
(searchChange)="filterManager.searchChange($event, header!, footer)"
class="ui-grid-search ui-grid-filter-option">
</ui-grid-search>

<ng-container *ngIf="!useLegacyDesign">
<ng-container *ngTemplateOutlet="toggleColumnsTmpl"></ng-container>
</ng-container>

<ng-container *ngTemplateOutlet="filtersTmpl">
</ng-container>
</ng-container>
<ng-container *ngIf="!(hasSelection$ | async) ||
!header?.actionButtons?.length">
<ui-grid-search *ngIf="header?.search"
[debounce]="header!.searchDebounce"
[maxLength]="header!.searchMaxLength"
[placeholder]="intl.searchPlaceholder"
[searchTooltip]="intl.searchTooltip"
[clearTooltip]="intl.clearTooltip"
[tooltipDisabled]="resizeManager.isResizing"
[value]="header!.searchValue!"
(searchChange)="filterManager.searchChange($event, header!, footer)"
class="ui-grid-search ui-grid-filter-option">
</ui-grid-search>

<ng-container *ngIf="!useLegacyDesign">
<ng-container *ngTemplateOutlet="toggleColumnsTmpl"></ng-container>
</ng-container>

<div *ngIf="!(hasSelection$ | async)"
class="ui-grid-action-buttons ui-grid-action-buttons-inline">
<ng-container *ngFor="let button of header?.inlineButtons">
<ng-container *ngIf="button.visible">
<ng-container *ngTemplateOutlet="button.html ?? null">
<ng-container *ngTemplateOutlet="filtersTmpl">
</ng-container>
</ng-container>
</ng-container>
</div>

<div #gridActionButtons
*ngIf="hasSelection$ | async"
class="ui-grid-action-buttons ui-grid-action-buttons-selection">
<ng-container *ngFor="let button of header?.actionButtons">
<ng-container *ngIf="button.visible">
<ng-container *ngTemplateOutlet="button.html?? null">
<div *ngIf="!(hasSelection$ | async)"
class="ui-grid-action-buttons ui-grid-action-buttons-inline">
<ng-container *ngFor="let button of header?.inlineButtons">
<ng-container *ngIf="button.visible">
<ng-container *ngTemplateOutlet="button.html ?? null">
</ng-container>
</ng-container>
</ng-container>
</ng-container>
</div>

<div #gridActionButtons
*ngIf="hasSelection$ | async"
class="ui-grid-action-buttons ui-grid-action-buttons-selection">
<ng-container *ngFor="let button of header?.actionButtons">
<ng-container *ngIf="button.visible">
<ng-container *ngTemplateOutlet="button.html?? null">
</ng-container>
</ng-container>
</ng-container>
</div>
</ng-container>
</div>
</ng-template>
</div>
<div *ngIf="showFilters && (hasAnyFiltersVisible$ | async)"
[@filters-container]
Expand Down
109 changes: 108 additions & 1 deletion projects/angular/components/ui-grid/src/ui-grid.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ import { MatMenuItem } from '@angular/material/menu';
import { PageEvent } from '@angular/material/paginator';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ResizeStrategy } from '@uipath/angular/components/ui-grid';
import {
IFilterModel,
ResizeStrategy,
} from '@uipath/angular/components/ui-grid';
import {
ISuggestValues,
UiSuggestComponent,
Expand Down Expand Up @@ -3630,4 +3633,108 @@ describe('Component: UiGrid', () => {
expect(buttons.length).toEqual(2);
});
});

describe('Behaviour: Clear custom filter', () => {
@Component({
template: `
<ui-grid [data]="data"
[customFilterValue]="customFilter">
<ui-grid-header [search]="search">
</ui-grid-header>
<ui-grid-column [property]="'myNumber'"
[searchable]="true"
[sortable]="true"
title="Number Header"
width="50%">
<ui-grid-dropdown-filter
[value]="filterValue"
[items]="filterItems">
</ui-grid-dropdown-filter>
</ui-grid-column>
</ui-grid>
`,
})
class TestFixtureCustomFilterGridComponent {
@ViewChild(UiGridComponent, {
static: true,
})
grid!: UiGridComponent<ITestEntity>;

get filterItems(): IDropdownOption[] {
return [1, 2, 3].map(count => ({
value: count,
label: count.toString(),
}));
}
customFilter: IFilterModel<any>[] = [];
filterValue = {
value: '777',
label: 'the label',
};
data: ITestEntity[] = [];
}

let fixture: ComponentFixture<TestFixtureCustomFilterGridComponent>;

beforeEach(async () => {
TestBed.configureTestingModule({
imports: [
UiGridModule,
UiGridCustomPaginatorModule,
NoopAnimationsModule,
],
providers: [
UiMatPaginatorIntl,
{
provide: UI_GRID_OPTIONS,
useValue: {
useLegacyDesign: false,
},
},
],
declarations: [
TestFixtureCustomFilterGridComponent,
],
});

fixture = TestBed.createComponent(TestFixtureCustomFilterGridComponent);

fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
});

afterEach(() => {
fixture.destroy();
});

it('should show custom filter after setting the grid\'s custom filter input', () => {
expect(document.querySelector('.ui-grid-dropdown-filter-button')).toBeTruthy();
fixture.componentInstance.customFilter = [{ property: 'myNumber1',
method: 'eq',
value: '2' }];
fixture.detectChanges();
expect(document.querySelector('.ui-grid-dropdown-filter-button')).toBeFalsy();
expect(document.querySelector('[data-cy="clear-custom-filter"]')).toBeTruthy();
});

it('should revert to old filter value after clearing the custom filter', fakeAsync(() => {
fixture.componentInstance.customFilter = [{ property: 'myNumber2',
method: 'eq',
value: '2' }];
fixture.detectChanges();
expect(JSON.stringify(fixture.componentInstance.grid.filterManager.filter$.value))
.toEqual(JSON.stringify(fixture.componentInstance.customFilter));
expect(fixture.componentInstance.grid.filterManager.hasCustomFilter$.value).toBeTrue();

const clearCustomFilterButton = fixture.debugElement.query(By.css('[data-cy="clear-custom-filter"]'));
clearCustomFilterButton.nativeElement.dispatchEvent(EventGenerator.click);
fixture.detectChanges();

expect(document.querySelector('.ui-grid-dropdown-filter-button')).toBeTruthy();
expect(fixture.componentInstance.grid.filterManager.hasCustomFilter$.value).toBeFalse();
expect(fixture.componentInstance.grid.filterManager.filter$.value[0].value)
.toEqual(fixture.componentInstance.filterValue.value);
}));
});
});
15 changes: 15 additions & 0 deletions projects/angular/components/ui-grid/src/ui-grid.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import {
import { ResizableGrid } from './managers/resize/types';
import {
GridOptions,
IFilterModel,
ISortModel,
} from './models';
import { UiGridIntl } from './ui-grid.intl';
Expand Down Expand Up @@ -340,6 +341,12 @@ export class UiGridComponent<T extends { id: number | string }> extends Resizabl
@Input()
disableSelectionByEntry: (entry: T) => null | string;

@Input()
set customFilterValue(customValue: IFilterModel<T>[]) {
if (!Array.isArray(customValue) || !customValue.length) { return; }
this.filterManager.updateCustomFilters(customValue);
}

/**
* Emits an event with the sort model when a column sort changes.
*
Expand Down Expand Up @@ -368,6 +375,9 @@ export class UiGridComponent<T extends { id: number | string }> extends Resizabl
@Output()
resizeEnd = new EventEmitter<void>();

@Output()
removeCustomFilter = new EventEmitter<void>();

/**
* Emits the column definitions when their definition changes.
*
Expand Down Expand Up @@ -893,6 +903,11 @@ export class UiGridComponent<T extends { id: number | string }> extends Resizabl
this.gridActionButtons?.nativeElement.querySelector(FOCUSABLE_ELEMENTS_QUERY)?.focus();
}

clearCustomFilter() {
this.removeCustomFilter.emit();
this.filterManager.clearCustomFilters();
}

private _announceGridHeaderActions() {
this._queuedAnnouncer.enqueue(this.intl.gridHeaderActionsNotice);
}
Expand Down
5 changes: 5 additions & 0 deletions projects/angular/components/ui-grid/src/ui-grid.intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ export class UiGridIntl implements OnDestroy {
*
*/
gridHeaderActionsNotice = 'Grid header actions updated. Press Shift + Alt + Arrow Up to move there.';
/**
* Message for the button that clears the applied custom filter.
*
*/
clearCustomFilter = 'Clear custom filter';
/**
* No data row message alternative function.
*
Expand Down
2 changes: 1 addition & 1 deletion projects/angular/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@uipath/angular",
"version": "13.4.1",
"version": "13.5.0",
"license": "MIT",
"author": {
"name": "UiPath Inc",
Expand Down
4 changes: 4 additions & 0 deletions projects/angular/testing/src/utilities/fake-file-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export class FakeFileList implements FileList {
});
}

[Symbol.iterator](): IterableIterator<File> {
return this.files[Symbol.iterator]();
}

/**
* Retrieve an item at the specified index.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
[showPaintTime]="inputs.showPaintTime"
[showHeaderRow]="inputs.showHeaderRow"
[expandedEntry]="editedEntity"
[expandMode]="'preserve'">
[expandMode]="'preserve'"
[customFilterValue]="inputs.customFilter ? [{property: 'parity', method: 'eq', value: 'odd'}] : []">

<ui-grid-header [search]="header.searchable">
<ui-header-button *ngFor="let button of generateButtons(header.main)"
Expand Down
Loading