-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed the "Is blank"/"Is not blank" filters for the tags field type #3637
base: develop
Are you sure you want to change the base?
Changes from 7 commits
32446cd
fbc5741
3e48929
e384044
19c4196
abfa491
faf2ca7
c233c4c
a5631a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ import { | |
BaseFilterFieldSpec, | ||
BaseFilterFieldSpecConfig | ||
} from '@xh/hoist/data/filter/BaseFilterFieldSpec'; | ||
import {castArray, compact, flatten, isDate, isEmpty, uniqBy} from 'lodash'; | ||
import {castArray, compact, flatten, isDate, isEmpty, isEqual, uniqBy} from 'lodash'; | ||
import {GridFilterModel} from './GridFilterModel'; | ||
|
||
export interface GridFilterFieldSpecConfig extends BaseFilterFieldSpecConfig { | ||
|
@@ -82,10 +82,17 @@ export class GridFilterFieldSpec extends BaseFilterFieldSpec { | |
// Get values from current column filter | ||
const filterValues = []; | ||
columnFilters.forEach(filter => { | ||
const newValues = castArray(filter.value).map(value => { | ||
value = sourceField.parseVal(value); | ||
return filterModel.toDisplayValue(value); | ||
}); | ||
// The parseVal of tag will castArray the value a second time, so make sure to flatten at the end. | ||
const newValues = flatten( | ||
castArray(filter.value) | ||
.map(value => { | ||
value = sourceField.parseVal(value); | ||
return filterModel.toDisplayValue(value); | ||
}) | ||
// Filter out the null tag value as it isn't a valid value to display in value lists. | ||
// It is set by 'is blank'/'is not blank' filters. | ||
.filter(it => isEqual(it, [null])) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems safe enough, independent of whether we continue to put |
||
); | ||
filterValues.push(...newValues); | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import { | |
escapeRegExp, | ||
first, | ||
isArray, | ||
isEmpty, | ||
isEqual, | ||
isNil, | ||
isString, | ||
|
@@ -114,10 +115,11 @@ export class FieldFilter extends Filter { | |
const storeField = store.getField(field); | ||
if (!storeField) return () => true; // Ignore (do not filter out) if field not in store | ||
|
||
const fieldType = storeField.type === 'tags' ? 'string' : storeField.type; | ||
value = isArray(value) | ||
? value.map(v => parseFieldValue(v, fieldType)) | ||
: parseFieldValue(value, fieldType); | ||
const fieldType = storeField.type; | ||
value = | ||
isArray(value) && storeField.type !== 'tags' | ||
? value.map(v => parseFieldValue(v, fieldType)) | ||
: parseFieldValue(value, fieldType); | ||
} | ||
|
||
if (FieldFilter.ARRAY_OPERATORS.includes(op)) { | ||
|
@@ -128,14 +130,14 @@ export class FieldFilter extends Filter { | |
switch (op) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great suggestion! Might I suggest we are even more explicit and call them |
||
case '=': | ||
opFn = v => { | ||
if (isNil(v) || v === '') v = null; | ||
return value.some(it => isEqual(v, it)); | ||
if (isNil(v) || v === '' || (isArray(v) && isEmpty(v))) v = null; | ||
return (v == null && isEmpty(value)) || value.some(it => isEqual(v, it)); | ||
}; | ||
break; | ||
case '!=': | ||
opFn = v => { | ||
if (isNil(v) || v === '') v = null; | ||
return !value.some(it => isEqual(v, it)); | ||
if (isNil(v) || v === '' || (isArray(v) && isEmpty(v))) v = null; | ||
return (v != null || !isEmpty(value)) && !value.some(it => isEqual(v, it)); | ||
}; | ||
break; | ||
case '>': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,6 +119,6 @@ const switcherButton = hoistCmp.factory<ColumnHeaderFilterModel>(({model, id, ti | |
text: title, | ||
active: activeTabId === id, | ||
outlined: true, | ||
onClick: () => tabContainerModel.activateTab(id) | ||
onClick: () => model.activateTab(id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tabContainerModel reference no longer needed on line 114 |
||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,10 +67,15 @@ export class ColumnHeaderFilterModel extends HoistModel { | |
|
||
@computed | ||
get isCustomFilter() { | ||
const {columnCompoundFilter, columnFilters} = this; | ||
const {columnCompoundFilter, columnFilters, fieldType} = this; | ||
if (columnCompoundFilter) return true; | ||
if (isEmpty(columnFilters)) return false; | ||
return columnFilters.some(it => !['=', '!=', 'includes'].includes(it.op)); | ||
return columnFilters.some( | ||
it => | ||
!['=', '!=', 'includes'].includes(it.op) || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this code (line 75 and 77) would be easier to grok if we expanded out to equals checks, and did not try to use the javascript 'includes' function . We are already dealing with an 'includes' filter and it is confusing! |
||
// The is blank / is not blank filter on tags is only supported by custom filter. | ||
(fieldType === 'tags' && ['=', '!='].includes(it.op) && it.value == null) | ||
); | ||
} | ||
|
||
get commitOnChange() { | ||
|
@@ -158,6 +163,12 @@ export class ColumnHeaderFilterModel extends HoistModel { | |
this.isOpen = false; | ||
} | ||
|
||
activateTab(tabId) { | ||
const tabModel = tabId === 'valuesFilter' ? this.valuesTabModel : this.customTabModel; | ||
tabModel.syncWithFilter(); | ||
this.tabContainerModel.activateTab(tabId); | ||
} | ||
|
||
//------------------- | ||
// Implementation | ||
//------------------- | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ import {HoistModel} from '@xh/hoist/core'; | |
import {FieldFilterOperator, FieldFilterSpec} from '@xh/hoist/data'; | ||
import {ColumnHeaderFilterModel} from '@xh/hoist/desktop/cmp/grid/impl/filter/ColumnHeaderFilterModel'; | ||
import {bindable, computed, makeObservable} from '@xh/hoist/mobx'; | ||
import {isArray, isNil} from 'lodash'; | ||
import {isArray, isEmpty, isNil} from 'lodash'; | ||
import {CustomTabModel} from './CustomTabModel'; | ||
|
||
type OperatorOptionValue = 'blank' | 'not blank' | FieldFilterOperator; | ||
|
@@ -82,7 +82,7 @@ export class CustomRowModel extends HoistModel { | |
makeObservable(this); | ||
|
||
let newOp = op as OperatorOptionValue; | ||
if (isNil(value)) { | ||
if (isNil(value) || (isArray(value) && isEmpty(value))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might add a util |
||
if (op === '=') newOp = 'blank'; | ||
if (op === '!=') newOp = 'not blank'; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor thing, but I think this would be more readable if we flatten() on line 96 as we push to
filterValues