Skip to content

Commit

Permalink
Feature/add support for an in filter operator to grid helper (#115)
Browse files Browse the repository at this point in the history
* Add support for an in filter operator

* Added js overrides for in filter and compatability with id property.

* Allow for filtering of floating numbers using in filter

* Sanitize number filter values better when usin IN filter

* Remove unnecessary comment
  • Loading branch information
mfedak-notebooksbillger committed Sep 19, 2023
1 parent c4b0b48 commit 82aa7a8
Show file tree
Hide file tree
Showing 2 changed files with 317 additions and 1 deletion.
298 changes: 298 additions & 0 deletions public/js/pimcore/overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -1066,3 +1066,301 @@ Ext.define('Ext.overrides.grid.RowEditor', {
return scrollDelta;
},
});

Ext.define('Ext.local.grid.filters.filter.TriFilter', {
extend: 'Ext.grid.filters.filter.TriFilter',
menuItems: [
'lt',
'gt',
'-',
'eq',
'in'
],
constructor: function(config) {
var me = this,
stateful = false,
filter = {},
filterGt, filterLt, filterEq, filterIn, value, operator;
me.callParent([
config
]);
value = me.value;
filterLt = me.getStoreFilter('lt');
filterGt = me.getStoreFilter('gt');
filterEq = me.getStoreFilter('eq');
filterIn = me.getStoreFilter('in');

if (filterLt || filterGt || filterEq || filterIn) {
stateful = me.active = true;
if (filterLt) {
me.onStateRestore(filterLt);
}
if (filterGt) {
me.onStateRestore(filterGt);
}
if (filterEq) {
me.onStateRestore(filterEq);
}
if (filterIn) {
me.onStateRestore(filterIn);
}
} else {
if (me.grid.stateful && me.getGridStore().saveStatefulFilters) {
value = undefined;
}
me.active = me.getActiveState(config, value);
}
filter.lt = filterLt || me.createFilter({
operator: 'lt',
value: (!stateful && value && value.lt) || null
}, 'lt');
filter.gt = filterGt || me.createFilter({
operator: 'gt',
value: (!stateful && value && value.gt) || null
}, 'gt');
filter.eq = filterEq || me.createFilter({
operator: 'eq',
value: (!stateful && value && value.eq) || null
}, 'eq');
filter.in = filterIn || me.createFilter({
operator: 'in',
type: 'numeric',
value: (!stateful && value && value.in) || null
}, 'in');
me.filter = filter;
if (me.active) {
me.setColumnActive(true);
if (!stateful) {
for (operator in value) {
me.addStoreFilter(me.filter[operator]);
}
}
}
},
setValue: function(value) {
var me = this,
filters = me.filter,
add = [],
remove = [],
active = false,
filterCollection = me.getGridStore().getFilters(),
field, filter, v, i, len, rLen, aLen;
if (me.preventFilterRemoval) {
return;
}
me.preventFilterRemoval = true;
if ('eq' in value) {
v = filters.lt.getValue();
if (v || v === 0) {
remove.push(filters.lt);
}
v = filters.gt.getValue();
if (v || v === 0) {
remove.push(filters.gt);
}
v = filters.in.getValue();
if (v || v === 0) {
remove.push(filters.in);
}
v = value.eq;
if (v || v === 0) {
add.push(filters.eq);
filters.eq.setValue(v);
} else {
remove.push(filters.eq);
}
} else {
v = filters.eq.getValue();
if (v || v === 0) {
remove.push(filters.eq);
}
if ('lt' in value) {
v = value.lt;
if (v || v === 0) {
add.push(filters.lt);
filters.lt.setValue(v);
} else {
remove.push(filters.lt);
}
}
if ('gt' in value) {
v = value.gt;
if (v || v === 0) {
add.push(filters.gt);
filters.gt.setValue(v);
} else {
remove.push(filters.gt);
}
}
if ('in' in value) {
v = value.in;
if (typeof v === "object" && v[0][0] == '') {
remove.push(filters.in);
} else if (v || v === 0) {
add.push(filters.in);
filters.in.setValue(v);
} else {
remove.push(filters.in);
}
}
}
rLen = remove.length;
aLen = add.length;
active = !!(me.countActiveFilters() + aLen - rLen);
if (rLen || aLen || active !== me.active) {
filterCollection.beginUpdate();
if (rLen) {
for (i = 0; i < rLen; i++) {
filter = remove[i];
me.fields[filter.getOperator()].setValue(null);
filter.setValue(null);
me.removeStoreFilter(filter);
}
}
if (aLen) {
for (i = 0; i < aLen; i++) {
me.addStoreFilter(add[i]);
}
}
me.setActive(active);
filterCollection.endUpdate();
}
me.preventFilterRemoval = false;
}
});

Ext.define('Ext.grid.filters.filter.Number', {
extend: 'Ext.local.grid.filters.filter.TriFilter',
alias: ['grid.filter.number', 'grid.filter.numeric'],

uses: ['Ext.form.field.Number'],

type: 'number',

config: {
fields: {
gt: {
iconCls: Ext.baseCSSPrefix + 'grid-filters-gt',
margin: '0 0 3px 0'
},
lt: {
iconCls: Ext.baseCSSPrefix + 'grid-filters-lt',
margin: '0 0 3px 0'
},
eq: {
iconCls: Ext.baseCSSPrefix + 'grid-filters-eq',
margin: '0 0 3px 0'
},
in: {
iconCls: Ext.baseCSSPrefix + 'grid-filters-find',
margin: 0
}
}
},

itemDefaults: {
enableKeyEvents: true,
hideEmptyLabel: false,
labelSeparator: '',
labelWidth: 29,
selectOnFocus: false
},

menuDefaults: {
bodyPadding: 3,
showSeparator: false
},

createMenu: function() {
var me = this,
listeners = {
scope: me,
keyup: me.onValueChange,
spin: {
fn: me.onInputSpin,
buffer: 200
},
el: {
click: me.stopFn
}
},
itemDefaults = me.getItemDefaults(),
menuItems = me.menuItems,
fields = me.getFields(),
field, i, len, key, item, cfg;

me.callParent();

me.fields = {};

for (i = 0, len = menuItems.length; i < len; i++) {
key = menuItems[i];

if (key !== '-' && key !== 'in') {
itemDefaults.xtype = 'numberfield';
field = fields[key];

cfg = {
labelClsExtra: Ext.baseCSSPrefix + 'grid-filters-icon ' + field.iconCls,
emptyText: 'Enter Number...'
};

if (itemDefaults) {
Ext.merge(cfg, itemDefaults);
}

Ext.merge(cfg, field);
cfg.emptyText = cfg.emptyText || me.emptyText;
delete cfg.iconCls;

me.fields[key] = item = me.menu.add(cfg);

item.filter = me.filter[key];
item.filterKey = key;
item.on(listeners);
} else if (key === 'in') {
itemDefaults.xtype = 'textfield';
field = fields.in;

cfg = {
labelClsExtra: Ext.baseCSSPrefix + 'grid-filters-icon ' + field.iconCls,
emptyText: 'Enter Numbers...'
};

if (itemDefaults) {
Ext.merge(cfg, itemDefaults);
}

Ext.merge(cfg, field);
cfg.emptyText = cfg.emptyText || me.emptyText;
delete cfg.iconCls;

me.fields[key] = item = me.menu.add(cfg);

item.filter = me.filter[key];
item.filterKey = key;
item.on(listeners);
}
else {
me.menu.add(key);
}
}
},
getValue: function(field) {
var value = {};

value[field.filterKey] = field.getValue();

return value;
},
onInputSpin: function(field, direction) {
var value = {};

value[field.filterKey] = field.getValue();

this.setValue(value);
},
stopFn: function(e) {
e.stopPropagation();
}
});
20 changes: 19 additions & 1 deletion src/Helper/GridHelperService.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,22 @@ public function getFilterCondition(string $filterJson, ClassDefinition $class, ?
} elseif ($filter['type'] == 'boolean') {
$operator = '=';
$filter['value'] = (int)$filter['value'];
} elseif ($filterOperator == 'in' && is_array($filter['value'])) {
$operator = 'in';
$matches = preg_split('/[^0-9\.]+/', $filter['value'][0][0] ?? [], -1, PREG_SPLIT_NO_EMPTY);
if (is_array($matches) && count($matches) > 0) {
$filter['value'][0][0] = implode(',', array_unique(array_map(floatval(...), $matches)));
} else {
continue;
}
} elseif ($filterOperator == 'in' && !is_array($filter['value'])) {
$operator = 'in';
$matches = preg_split('/[^0-9\.]+/', $filter['value'], -1, PREG_SPLIT_NO_EMPTY);
if (is_array($matches) && count($matches) > 0) {
$filter['value'] = implode(',', array_unique(array_map(floatval(...), $matches)));
} else {
continue;
}
} else {
if ($filterOperator == 'lt') {
$operator = '<';
Expand Down Expand Up @@ -323,8 +339,10 @@ public function getFilterCondition(string $filterJson, ClassDefinition $class, ?
$conditionPartsFilters[] = 'concat(`path`, `key`) ' . $operator . ' ' . $db->quote('%' . $filter['value'] . '%');
} elseif ($filterField == 'key') {
$conditionPartsFilters[] = '`key` ' . $operator . ' ' . $db->quote('%' . $filter['value'] . '%');
} elseif ($filterField == 'id') {
} elseif ($filterField == 'id' && $operator !== 'in') {
$conditionPartsFilters[] = 'oo_id ' . $operator . ' ' . $db->quote($filter['value']);
} elseif ($filterField == 'id' && $operator === 'in') {
$conditionPartsFilters[] = 'oo_id ' . $operator . ' (' . $filter['value'] . ')';
} else {
$filterField = $db->quoteIdentifier($filterField);
if ($filter['type'] == 'date' && $operator == '=') {
Expand Down

0 comments on commit 82aa7a8

Please sign in to comment.