From d1793941b99469015f91b93f1c3b8737e35751d8 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 7 Oct 2020 17:21:48 -0400 Subject: [PATCH 1/1] LP1846042 Angular grid filter dropdown improvements Add an explicit Close button to filter dropdowns to cover cases where the user wishes to close the dropdown without making any changes and clicking-away is not supported. Othor minor repairs. Signed-off-by: Bill Erickson Signed-off-by: Michele Morgan --- .../date-select/date-select.component.ts | 1 + .../grid/grid-filter-control.component.html | 118 +++++++++--------- .../grid/grid-filter-control.component.ts | 74 ++++++++--- .../share/admin-page/admin-page.component.ts | 5 +- 4 files changed, 123 insertions(+), 75 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts index 66d363af15..d855f6d4ea 100644 --- a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts +++ b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts @@ -84,6 +84,7 @@ export class DateSelectComponent implements OnInit, ControlValueAccessor { } isValidDate(dt: NgbDateStruct): dt is NgbDateStruct { + if (!dt) { return false; } return (dt).year !== undefined; } diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.html b/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.html index 4e85407666..112ee99031 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.html +++ b/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.html @@ -1,6 +1,6 @@ - + Filter filter_list @@ -11,18 +11,18 @@ - +
- + - + + +
- + +
+
- + @@ -87,11 +89,11 @@
- +
@@ -126,20 +128,20 @@
- +
@@ -150,20 +152,20 @@
- +
@@ -174,20 +176,20 @@
- +
@@ -198,20 +200,20 @@
- +
@@ -225,11 +227,11 @@
- +
@@ -264,16 +266,17 @@
-
- +
diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.ts b/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.ts index da23710484..36fcfae73f 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid-filter-control.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit, QueryList, ViewChildren} from '@angular/core'; +import {Component, Input, OnInit, QueryList, ViewChild, ViewChildren} from '@angular/core'; import {GridContext, GridColumn} from './grid'; import {IdlObject} from '@eg/core/idl.service'; import {ComboboxComponent} from '@eg/share/combobox/combobox.component'; @@ -6,6 +6,7 @@ import {DateSelectComponent} from '@eg/share/date-select/date-select.component'; import {OrgSelectComponent} from '@eg/share/org-select/org-select.component'; import {OrgService} from '@eg/core/org.service'; import {NgbDropdown} from '@ng-bootstrap/ng-bootstrap'; +import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; @Component({ selector: 'eg-grid-filter-control', @@ -19,10 +20,15 @@ export class GridFilterControlComponent implements OnInit { @ViewChildren(ComboboxComponent) filterComboboxes: QueryList; - @ViewChildren(DateSelectComponent) dateSelects: QueryList; @ViewChildren(OrgSelectComponent) orgSelects: QueryList; @ViewChildren(NgbDropdown) dropdowns: QueryList; + @ViewChild('dateSelectOne') dateSelectOne: DateSelectComponent; + @ViewChild('dateSelectTwo') dateSelectTwo: DateSelectComponent; + + // So we can use (ngModelChange) on the link combobox + linkFilterEntry: ComboboxEntry = null; + constructor( private org: OrgService ) {} @@ -38,7 +44,9 @@ export class GridFilterControlComponent implements OnInit { } } - applyOrgFilter(org: IdlObject, col: GridColumn) { + applyOrgFilter(col: GridColumn) { + const org: IdlObject = (col.filterValue as unknown) as IdlObject; + if (org == null) { this.clearFilter(col); return; @@ -61,11 +69,12 @@ export class GridFilterControlComponent implements OnInit { this.context.dataSource.filters[col.name] = [ filt ]; col.isFiltered = true; this.context.reload(); + + this.closeDropdown(); } - applyLinkFilter($event, col: GridColumn) { - if ($event) { - col.filterValue = $event.id; + applyLinkFilter(col: GridColumn) { + if (col.filterValue) { this.applyFilter(col); } else { @@ -81,7 +90,20 @@ export class GridFilterControlComponent implements OnInit { return new Date( Number(parts[0]), Number(parts[1]) - 1, Number(parts[2])); } - applyDateFilter(dateStr: string, col: GridColumn, endDateStr: string) { + + applyDateFilter(col: GridColumn) { + const dateStr = this.dateSelectOne.currentAsYmd(); + const endDateStr = + this.dateSelectTwo ? this.dateSelectTwo.currentAsYmd() : null; + + if (endDateStr && !dateStr) { + // User has applied a second date (e.g. between) but cleared + // the first date. Avoid applying the filter until + // dateStr gets a value or endDateStr is cleared or the + // operator changes. + return; + } + if (col.filterOperator === 'null' || col.filterOperator === 'not null') { this.applyFilter(col); } else { @@ -199,17 +221,15 @@ export class GridFilterControlComponent implements OnInit { this.context.dataSource.filters[col.name] = filters; col.isFiltered = true; this.context.reload(); + this.closeDropdown(); } - - // The date filter has autoClose=false so that interacting with - // date selectors won't result in closing the dropdown. Once - // we've successfully applied a filter, force it closed. - this.closeDropdown(); } + clearDateFilter(col: GridColumn) { delete this.context.dataSource.filters[col.name]; col.isFiltered = false; this.context.reload(); + this.closeDropdown(); } applyBooleanFilter(col: GridColumn) { if (!col.filterValue || col.filterValue === '') { @@ -227,7 +247,28 @@ export class GridFilterControlComponent implements OnInit { col.isFiltered = true; this.context.reload(); } + + this.closeDropdown(); } + + applyFilterCommon(col: GridColumn) { + + switch (col.datatype) { + case 'link': + col.filterValue = + this.linkFilterEntry ? this.linkFilterEntry.id : null; + return this.applyLinkFilter(col); + case 'bool': + return this.applyBooleanFilter(col); + case 'timestamp': + return this.applyDateFilter(col); + case 'org_unit': + return this.applyOrgFilter(col); + default: + return this.applyFilter(col); + } + } + applyFilter(col: GridColumn) { // fallback if the operator somehow was not set yet if (col.filterOperator === undefined) { col.filterOperator = '='; } @@ -272,6 +313,7 @@ export class GridFilterControlComponent implements OnInit { } } this.context.reload(); + this.closeDropdown(); } clearFilter(col: GridColumn) { // clear filter values... @@ -281,16 +323,20 @@ export class GridFilterControlComponent implements OnInit { col.isFiltered = false; this.reset(); this.context.reload(); + this.closeDropdown(); } closeDropdown() { - this.dropdowns.forEach(drp => { drp.close(); }); + // Timeout allows actions to occur before closing (some) dropdows + // clears the values (e.g. link selector) + setTimeout(() => this.dropdowns.forEach(drp => { drp.close(); })); } reset() { this.filterComboboxes.forEach(ctl => { ctl.applyEntryId(null); }); - this.dateSelects.forEach(ctl => { ctl.reset(); }); this.orgSelects.forEach(ctl => { ctl.reset(); }); + if (this.dateSelectOne) { this.dateSelectOne.reset(); } + if (this.dateSelectTwo) { this.dateSelectTwo.reset(); } } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts index 2f85522a09..dfcd549036 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.ts @@ -265,8 +265,6 @@ export class AdminPageComponent implements OnInit { order_by: orderBy }; - console.debug(this.dataSource); - console.debug(this.dataSource.filters); if (!this.contextOrg && !this.gridFilters && !Object.keys(this.dataSource.filters).length) { // No org filter -- fetch all rows return this.pcrud.retrieveAll( @@ -279,7 +277,7 @@ export class AdminPageComponent implements OnInit { if (this.orgField && (this.searchOrgs || this.contextOrg)) { orgFilter[this.orgField] = this.searchOrgs.orgIds || [this.contextOrg.id()]; - search.push(orgFilter) + search.push(orgFilter); } Object.keys(this.dataSource.filters).forEach(key => { @@ -340,7 +338,6 @@ export class AdminPageComponent implements OnInit { idlThings.forEach(idlThing => idlThing.isdeleted(true)); this.pcrud.autoApply(idlThings).subscribe( val => { - console.debug('deleted: ' + val); this.deleteSuccessString.current() .then(str => this.toast.success(str)); }, -- 2.43.2