Skip to content

Commit e9996ed

Browse files
authored
SpEL support (#613)
* . * . * . * spelFormatValue * mongo: fix for empty aggregation * fix T() * string: fix empty aggr * sql: add asyncListValues * aggr * # * func * ? escape * fixed escape * float, array, .?[true] * #this not needed? * formatSpelField, isSpel* * spel2js init * import1 * typo width * fix revop * fix omitBrackets * use my fork * . * fix valueType and unary minus * group basic * inline list * date, datetime * time * lint fix * test fix * added simple tests * group fix * some/all/none * between * valueType from field config * !func * excludeOperators for type * fix $contains * chlog * Like -> Contains Moved is_empty, is_null to end of operators list * fix test * chlog . . * readme * add "sh " for win * ternary1 * ternary 2 . * . * . * parentReordableNodesCnt * export ?: * import ternary * ternary import complete with react-select * . * . * fix * add case * ! * lint fix * tsc fix * fix add first case * unsafe warning fix * demo /switch * fix * fix validation * fix * . * logger * . * fix import * add/del default * getSwitchValues * lint fix * . * . * lint fix * fix for npm 7+ * . * lint fix . * Added `Utils._loadFromJsonLogic()` that returns `[tree, errors]` (issue #621) * return Errors * useCallback * . * fix tests * . * fix
1 parent b6be2d7 commit e9996ed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+3421
-405
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# Changelog
22
- 5.0.0
3+
- Support of SpEL for import and export. See `loadFromSpel` and `spelFormat` in `Utils` (PR #613)
4+
- Added `excludeOperators` for type config (PR #613)
5+
See `excludeOperators: ["proximity"]` in demo
6+
- Changed export of `not_between` op for text format (`!(num >= 3 && num <= 4)` -> `(num < 3 || num > 4)`) (PR #613)
7+
- Rename `Like` -> `Contains`. Moved `is_empty`, `is_null` to end of operators list (PR #613)
38
- Support MUI v5 (PR #628)
49
- Upgraded to React 17. Moved from RHL to react-refresh. Converted demo app to FC. (PR #628)
10+
- Added `Utils._loadFromJsonLogic()` that returns `[tree, errors]` (issue #621)
511
- 4.10.0
612
- Support Bootstrap (via `reactstrap`) (PR #604)
713
- 4.9.0

CONFIG.adoc

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ Optionally you can override some options in basic config or add your own types/w
2828

2929
There are functions for building query string: `formatConj`, `formatValue`, `formatOp`, `formatField`, `formatFunc` which are used for `QbUtils.queryString()`. +
3030
They have common param `isForDisplay` - false by default, true will be used for (https://github.com/ukrbublik/react-awesome-query-builder/#querystring-immutablevalue-config-isfordisplay---string)[`QbUtils.queryString(immutableTree, config, true)`] (see 3rd param true). +
31-
Also there are similar `mongoConj`, `mongoFormatOp`, `mongoFormatValue`, `mongoFunc` for building MongoDb query with `QbUtils.mongodbFormat()`. +
32-
And `sqlFormatConj`, `sqlFormatOp`, `sqlFormatValue`, `sqlFormatReverse`, `sqlFunc` for building SQL where query with `QbUtils.sqlFormat()`. +
31+
Also there are similar `mongoConj`, `mongoFormatOp`, `mongoFormatValue`, `mongoFunc`, `mongoFormatFunc`, `mongoArgsAsObject` for building MongoDb query with `QbUtils.mongodbFormat()`. +
32+
And `sqlFormatConj`, `sqlOp`, `sqlFormatOp`, `sqlFormatValue`, `sqlFormatReverse`, `formatSpelField`, `sqlFunc`, `sqlFormatFunc` for building SQL where query with `QbUtils.sqlFormat()`. +
33+
And `spelFormatConj`, `spelOp`, `spelFormatOp`, `spelFormatValue`, `spelFormatReverse`, `spelFunc`, `spelFormatFunc` for building query in (https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html)[Spring Expression Language (SpEL)] with `QbUtils.spelFormat()`. +
3334
And `jsonLogic` for building http://jsonlogic.com[JsonLogic] with `QbUtils.jsonLogicFormat()`. +
3435

3536
TIP: Example: https://github.com/ukrbublik/react-awesome-query-builder/tree/master/examples/demo/config.tsx[`demo config`]
@@ -447,6 +448,7 @@ where `AND` and `OR` - available conjuctions (logical operators). You can add `N
447448
`children` - list of already formatted queries (strings) to be joined with conjuction
448449
|mongoConj |+ for MongoDB format |https://docs.mongodb.com/manual/reference/operator/query-logical/[Name] of logical operator for MongoDb
449450
|sqlFormatConj |+ for SQL format |See `formatConj`
451+
|spelFormatConj |+ for SpEL format |See `formatConj`
450452
|reversedConj | |Opposite logical operator. +
451453
Can be used to optimize `!(A OR B)` to `!A && !B` (done for MongoDB format)
452454
|===
@@ -485,15 +487,19 @@ where `AND` and `OR` - available conjuctions (logical operators). You can add `N
485487
`value` - string (already formatted value) for `cardinality==1` -or- `Immutable.List` of strings for `cardinality>1`
486488
|labelForFormat | | |If `formatOp` is missing, `labelForFormat` will be used to join operands when building query string
487489
|mongoFormatOp |+ for MongoDB format | |Function for formatting MongoDb expression, used to join operands into rule. +
488-
`(string field, string op, mixed value, bool useExpr, string valueSrc, string valueType, Object opDef, Object operatorOptions) => object` +
490+
`(string field, string op, mixed value, bool useExpr, string valueSrc, string valueType, Object opDef, Object operatorOptions, Object fieldDef) => object` +
489491
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2` +
490492
`useExpr` - true if resulted expression will be wrapped in https://docs.mongodb.com/manual/reference/operator/query/expr/index.html[`{'$expr': {...}}`] (used only if you compare field with another field or function) (you need to use aggregation operators in this case, like https://docs.mongodb.com/manual/reference/operator/aggregation/eq/[$eq (aggregation)] instead of https://docs.mongodb.com/manual/reference/operator/query/eq/[$eq])
491493
|sqlOp |+ for SQL format | |Operator name in SQL
492-
|sqlFormatOp |- for SQL format | |Function for advanced formatting SQL WHERE query if just `sqlOp` is not enough. +
493-
`(string field, string op, mixed value, string valueSrc, string valueType, Object opDef, Object operatorOptions) => object` +
494+
|sqlFormatOp |- for SQL format | |Function for advanced formatting SQL WHERE query when just `sqlOp` is not enough. +
495+
`(string field, string op, mixed value, string valueSrc, string valueType, Object opDef, Object operatorOptions, Object fieldDef) => string` +
496+
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2`
497+
|spelOp |+ for SpEL format | |Operator name in SpEL
498+
|spelFormatOp |- for SpEL format | |Function for advanced formatting query in SpEL when just `spelOp` is not enough. +
499+
`(string field, string op, mixed value, string valueSrc, string valueType, Object opDef, Object operatorOptions, Object fieldDef) => string` +
494500
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2`
495501
|jsonLogic |+ for http://jsonlogic.com[JsonLogic] | |String (eg. `'<'`) -or- function for advanced formatting +
496-
`(object field, string op, mixed value, Object opDef, Object operatorOptions) => object` +
502+
`(object field, string op, mixed value, Object opDef, Object operatorOptions, Object fieldDef) => object` +
497503
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2` +
498504
`field` - already formatted `{"var": <some field>}`
499505
|elasticSearchQueryType |+ for ElasticSearch format | |String (eg. `term`) -or- function `(string valueType) => string` +
@@ -584,6 +590,8 @@ const {
584590
`(mixed val, Object fieldDef, Object wgtDef, string op, Object opDef) => any`
585591
|sqlFormatValue |- for SQL format |`v => SqlString.escape(v)` |Function for formatting widget's value in SQL WHERE query. +
586592
`(mixed val, Object fieldDef, Object wgtDef, string op, Object opDef) => string`
593+
|spelFormatValue |- for SpEL format | |Function for formatting widget's value in SpEL query. +
594+
`(mixed val, Object fieldDef, Object wgtDef, string op, Object opDef) => string`
587595
|jsonLogic |- for http://jsonlogic.com[JsonLogic] |v => v |Function for formatting widget's value for JsonLogic. +
588596
`(mixed val, Object fieldDef, Object wgtDef, string op, Object opDef) => any`
589597
|elasticSearchFormatValue |- for ElasticSearch format |`v => v` |Function for formatting widget's value for ES query. +
@@ -694,6 +702,9 @@ To enable this feature set `valueSources` of type to `['value', 'func']` (see be
694702
|sqlFunc |- for SQL format |same as func key |Func name in SQL
695703
|sqlFormatFunc |- for SQL format | |Can be used instead of `sqlFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression string. +
696704
Example: SUM function can be formatted with `({a, b}) => a + " + " + b`
705+
|spelFunc |- for SpEL format |same as func key |Func name in SpEL
706+
|spelFormatFunc |- for SpEL format | |Can be used instead of `spelFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression string. +
707+
Example: SUM function can be formatted with `({a, b}) => a + " + " + b`
697708
|mongoFunc |- for MongoDB format |same as func key |Func name in Mongo
698709
|mongoArgsAsObject | |false |Some functions like https://docs.mongodb.com/manual/reference/operator/aggregation/rtrim/[$rtrim] supports named args, other ones like https://docs.mongodb.com/manual/reference/operator/aggregation/slice/[$slice] takes args as array
699710
|mongoFormatFunc |- for MongoDB format | |Can be used instead of `mongoFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression object.

README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ See [live demo](https://ukrbublik.github.io/react-awesome-query-builder)
6868
- [Bootstrap](https://reactstrap.github.io/)
6969
- vanilla
7070
(Using another UI framework and custom widgets is possible, see below)
71-
- Export to MongoDb, SQL, [JsonLogic](http://jsonlogic.com), ElasticSearch or your custom format
72-
- Import from [JsonLogic](http://jsonlogic.com)
71+
- Export to MongoDb, SQL, [JsonLogic](http://jsonlogic.com), [SpEL](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html), ElasticSearch or your custom format
72+
- Import from [JsonLogic](http://jsonlogic.com), [SpEL](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html)
7373
- TypeScript support (see [types](/modules/index.d.ts) and [demo in TS](/examples))
7474

7575

@@ -81,7 +81,7 @@ npm i react-awesome-query-builder --save
8181

8282
For AntDesign widgets only:
8383
```
84-
npm i antd --save
84+
npm i antd @ant-design/icons --save
8585
```
8686

8787
For Material-UI 4 widgets only:
@@ -229,7 +229,7 @@ class DemoQueryBuilder extends Component {
229229
#### Minimal TypeScript example with function component
230230
([Codesandbox](https://codesandbox.io/s/relaxed-sun-erhnu?file=/src/demo/demo.tsx))
231231
```typescript
232-
import React, { useState } from "react";
232+
import React, { useState, useCallback } from "react";
233233
import { Query, Builder, Utils as QbUtils } from "react-awesome-query-builder";
234234
// types
235235
import {
@@ -307,22 +307,22 @@ export const Demo: React.FC = () => {
307307
config: config
308308
});
309309

310-
const onChange = (immutableTree: ImmutableTree, config: Config) => {
310+
const onChange = useCallback((immutableTree: ImmutableTree, config: Config) => {
311311
// Tip: for better performance you can apply `throttle` - see `examples/demo`
312-
setState({ tree: immutableTree, config: config });
312+
setState(prevState => { ...prevState, tree: immutableTree, config: config });
313313

314314
const jsonTree = QbUtils.getTree(immutableTree);
315315
console.log(jsonTree);
316316
// `jsonTree` can be saved to backend, and later loaded to `queryValue`
317-
};
317+
}, []);
318318

319-
const renderBuilder = (props: BuilderProps) => (
319+
const renderBuilder = useCallback((props: BuilderProps) => (
320320
<div className="query-builder-container" style={{ padding: "10px" }}>
321321
<div className="query-builder qb-lite">
322322
<Builder {...props} />
323323
</div>
324324
</div>
325-
);
325+
), []);
326326

327327
return (
328328
<div>
@@ -375,6 +375,7 @@ Props:
375375
- `renderBuilder` - function to render query builder itself. Takes 1 param `props` you need to pass into `<Builder {...props} />`.
376376

377377
*Notes*:
378+
- Please apply `useCallback` for `onChange` and `renderBuilder` for performance reason
378379
- If you put query builder component inside [Material-UI](https://github.com/mui-org/material-ui)'s `<Dialog />` or `<Popover />`, please:
379380
- use prop `disableEnforceFocus={true}` for dialog or popver
380381
- set css `.MuiPopover-root, .MuiDialog-root { z-index: 900 !important; }` (or 1000 for AntDesign v3)
@@ -419,6 +420,8 @@ Wrapping in `div.query-builder-container` is necessary if you put query builder
419420
Convert query value to MongoDb query object.
420421
#### sqlFormat (immutableValue, config) -> String
421422
Convert query value to SQL where string.
423+
#### spelFormat (immutableValue, config) -> String
424+
Convert query value to [Spring Expression Language (SpEL)](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html).
422425
#### elasticSearchFormat (immutableValue, config) -> Object
423426
Convert query value to ElasticSearch query object.
424427
#### jsonLogicFormat (immutableValue, config) -> {logic, data, errors}
@@ -427,6 +430,10 @@ Wrapping in `div.query-builder-container` is necessary if you put query builder
427430
- Import:
428431
#### loadFromJsonLogic (jsonLogicObject, config) -> Immutable
429432
Convert query value from [JsonLogic](http://jsonlogic.com) format to internal Immutable format.
433+
#### _loadFromJsonLogic (jsonLogicObject, config) -> [Immutable, errors]
434+
#### loadFromSpel (string, config) -> [Immutable, errors]
435+
Convert query value from [Spring Expression Language (SpEL)](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html) format to internal Immutable format.
436+
430437

431438

432439
### Config format

css/styles.scss

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,42 @@ ul.ant-select-selection__rendered {
284284
}
285285
}
286286

287+
/******************************************************************************/
288+
/** CASE_GROUP *********************************************************************/
289+
/******************************************************************************/
290+
291+
.case_group {
292+
border-width: 2px;
293+
}
294+
295+
.switch_group {
296+
& > .group--children {
297+
& > .group-or-rule-container > .group-or-rule {
298+
&::before, &::after {
299+
height: calc(50% + 12px); // for `border-width: 2px`
300+
}
301+
}
302+
}
303+
}
304+
305+
.case_group--body {
306+
display: flex;
307+
flex-direction: row;
308+
margin-top: 10px;
309+
margin-bottom: 10px;
310+
311+
.case_group--children {
312+
flex: auto;
313+
margin-top: 0 !important;
314+
margin-bottom: 0 !important;
315+
}
316+
317+
.case_group--value {
318+
margin-top: 0;
319+
margin-bottom: 0;
320+
margin-right: 10px;
321+
}
322+
}
287323

288324
/******************************************************************************/
289325
/** RULE_GROUP *********************************************************************/

examples/demo/config.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ export default (skin: string) => {
161161
const types: Types = {
162162
...InitialConfig.types,
163163
// examples of overriding
164+
text: {
165+
...InitialConfig.types.text,
166+
excludeOperators: ["proximity"],
167+
},
164168
boolean: merge(InitialConfig.types.boolean, {
165169
widgets: {
166170
boolean: {
@@ -271,7 +275,6 @@ export default (skin: string) => {
271275
firstName: {
272276
label2: "Username", //only for menu's toggler
273277
type: "text",
274-
excludeOperators: ["proximity"],
275278
fieldSettings: {
276279
validateValue: (val: string, fieldSettings) => {
277280
return (val.length < 10);
@@ -285,7 +288,6 @@ export default (skin: string) => {
285288
login: {
286289
type: "text",
287290
tableName: "t1", // legacy: PR #18, PR #20
288-
excludeOperators: ["proximity"],
289291
fieldSettings: {
290292
validateValue: (val: string, fieldSettings) => {
291293
return (val.length < 10 && (val === "" || val.match(/^[A-Za-z0-9_-]+$/) !== null));

0 commit comments

Comments
 (0)