Skip to content

Commit 1733767

Browse files
committed
0.1.10
Modified config 'formatOp' - added param 'valueSrc' For all widgets added 'type' Added config 'canCompareFieldWithField'
1 parent 0aadf63 commit 1733767

File tree

6 files changed

+87
-34
lines changed

6 files changed

+87
-34
lines changed

examples/demo/config.js

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ export default {
286286
],
287287
widgetProps: {
288288
},
289-
}
289+
},
290290
},
291291
},
292292
multiselect: {
@@ -306,6 +306,7 @@ export default {
306306
"equal",
307307
],
308308
widgetProps: {
309+
//you can enable this if you don't use fields as value sources
309310
//hideOperator: true,
310311
//operatorInlineLabel: "is",
311312
}
@@ -355,7 +356,7 @@ export default {
355356
label: 'Between',
356357
labelForFormat: 'BETWEEN',
357358
cardinality: 2,
358-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
359+
formatOp: (field, op, values, valueSrcs, opDef, operatorOptions, isForDisplay) => {
359360
let valFrom = values.first();
360361
let valTo = values.get(1);
361362
if (isForDisplay)
@@ -395,7 +396,7 @@ export default {
395396
labelForFormat: 'IS EMPTY',
396397
cardinality: 0,
397398
reversedOp: 'is_not_empty',
398-
formatOp: (field, op, value, opDef, operatorOptions, isForDisplay) => {
399+
formatOp: (field, op, value, valueSrc, opDef, operatorOptions, isForDisplay,) => {
399400
return isForDisplay ? `${field} IS EMPTY` : `!${field}`;
400401
},
401402
},
@@ -405,55 +406,67 @@ export default {
405406
labelForFormat: 'IS NOT EMPTY',
406407
cardinality: 0,
407408
reversedOp: 'is_empty',
408-
formatOp: (field, op, value, opDef, operatorOptions, isForDisplay) => {
409+
formatOp: (field, op, value, valueSrc, opDef, operatorOptions, isForDisplay) => {
409410
return isForDisplay ? `${field} IS NOT EMPTY` : `!!${field}`;
410411
},
411412
},
412413
select_equals: {
413414
label: '==',
414415
labelForFormat: '==',
415-
formatOp: (field, op, value, opDef, operatorOptions, isForDisplay) => {
416+
formatOp: (field, op, value, valueSrc, opDef, operatorOptions, isForDisplay) => {
416417
return `${field} == ${value}`;
417418
},
418419
reversedOp: 'select_not_equals',
419420
},
420421
select_not_equals: {
421422
label: '!=',
422423
labelForFormat: '!=',
423-
formatOp: (field, op, value, opDef, operatorOptions, isForDisplay) => {
424+
formatOp: (field, op, value, valueSrc, opDef, operatorOptions, isForDisplay) => {
424425
return `${field} != ${value}`;
425426
},
426427
reversedOp: 'select_equals',
427428
},
428429
select_any_in: {
429430
label: 'Any in',
430431
labelForFormat: 'IN',
431-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
432-
return `${field} IN (${values.join(', ')})`;
432+
formatOp: (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
433+
if (valueSrc == 'value')
434+
return `${field} IN (${values.join(', ')})`;
435+
else
436+
return `${field} IN (${values})`;
433437
},
434438
reversedOp: 'select_not_any_in',
435439
},
436440
select_not_any_in: {
437441
label: 'Not in',
438442
labelForFormat: 'NOT IN',
439-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
440-
return `${field} NOT IN (${values.join(', ')})`;
443+
formatOp: (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
444+
if (valueSrc == 'value')
445+
return `${field} NOT IN (${values.join(', ')})`;
446+
else
447+
return `${field} NOT IN (${values})`;
441448
},
442449
reversedOp: 'select_any_in',
443450
},
444451
multiselect_equals: {
445452
label: 'Equals',
446453
labelForFormat: '==',
447-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
448-
return `${field} == (${values.join(', ')})`;
454+
formatOp: (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
455+
if (valueSrc == 'value')
456+
return `${field} == [${values.join(', ')}]`;
457+
else
458+
return `${field} == ${values}`;
449459
},
450460
reversedOp: 'multiselect_not_equals',
451461
},
452462
multiselect_not_equals: {
453463
label: 'Not equals',
454464
labelForFormat: '!=',
455-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
456-
return `${field} != (${values.join(', ')})`;
465+
formatOp: (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
466+
if (valueSrc == 'value')
467+
return `${field} != [${values.join(', ')}]`;
468+
else
469+
return `${field} != ${values}`;
457470
},
458471
reversedOp: 'multiselect_equals',
459472
},
@@ -465,7 +478,7 @@ export default {
465478
{label: 'Word 1', placeholder: 'Enter first word'},
466479
'Word 2'
467480
],
468-
formatOp: (field, op, values, opDef, operatorOptions, isForDisplay) => {
481+
formatOp: (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
469482
let val1 = values.first();
470483
let val2 = values.get(1);
471484
return `${field} ${val1} NEAR/${operatorOptions.get('proximity')} ${val2}`;
@@ -482,13 +495,15 @@ export default {
482495
},
483496
widgets: {
484497
text: {
498+
type: "text",
485499
valueSrc: 'value',
486500
factory: (props) => <TextWidget {...props} />,
487501
formatValue: (val, fieldDef, wgtDef, isForDisplay) => {
488502
return isForDisplay ? '"'+val+'"' : JSON.stringify(val);
489503
},
490504
},
491505
number: {
506+
type: "number",
492507
valueSrc: 'value',
493508
factory: (props) => <NumberWidget {...props} />,
494509
valueLabel: "Number",
@@ -498,6 +513,7 @@ export default {
498513
},
499514
},
500515
select: {
516+
type: "select",
501517
valueSrc: 'value',
502518
factory: (props) => <SelectWidget {...props} />,
503519
formatValue: (val, fieldDef, wgtDef, isForDisplay) => {
@@ -506,6 +522,7 @@ export default {
506522
},
507523
},
508524
multiselect: {
525+
type: "multiselect",
509526
valueSrc: 'value',
510527
factory: (props) => <MultiSelectWidget {...props} />,
511528
formatValue: (vals, fieldDef, wgtDef, isForDisplay) => {
@@ -514,6 +531,7 @@ export default {
514531
},
515532
},
516533
date: {
534+
type: "date",
517535
valueSrc: 'value',
518536
factory: (props) => <DateWidget {...props} />,
519537
dateFormat: 'DD.MM.YYYY',
@@ -524,6 +542,7 @@ export default {
524542
},
525543
},
526544
time: {
545+
type: "time",
527546
valueSrc: 'value',
528547
factory: (props) => <TimeWidget {...props} />,
529548
timeFormat: 'HH:mm',
@@ -534,6 +553,7 @@ export default {
534553
},
535554
},
536555
datetime: {
556+
type: "datetime",
537557
valueSrc: 'value',
538558
factory: (props) => <DateTimeWidget {...props} />,
539559
timeFormat: 'HH:mm',
@@ -545,6 +565,7 @@ export default {
545565
},
546566
},
547567
boolean: {
568+
type: "boolean",
548569
valueSrc: 'value',
549570
factory: (props) => <BooleanWidget {...props} />,
550571
labelYes: "Yes",
@@ -615,5 +636,9 @@ export default {
615636
},
616637
valueSourcesPopupTitle: "Select value source",
617638
canReorder: false,
639+
canCompareFieldWithField: (leftField, leftFieldConfig, rightField, rightFieldConfig) => {
640+
//for type == 'select'/'multiselect' you can check listValues
641+
return true;
642+
},
618643
}
619644
};

modules/components/containers/SortableContainer.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {getFieldConfig} from "../../utils/index";
55
import getFlatTree from "../../utils/getFlatTree";
66
import * as constants from '../../constants';
77

8-
//todo: add to readme about .query-builder-container
98

109
export default (Builder, CanMoveFn = null) => {
1110
return class SortableContainer extends Component {

modules/components/widgets/ValueField.js

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { Component, PropTypes } from 'react';
22
import shallowCompare from 'react-addons-shallow-compare';
3-
import {getFieldConfig, getFieldPath, getFieldPathLabels, calcTextWidth} from "../../utils/index";
3+
import {
4+
getFieldConfig, getFieldPath, getFieldPathLabels, calcTextWidth, getValueSourcesForFieldOp, getWidgetForFieldOp
5+
} from "../../utils/index";
46
import { Menu, Dropdown, Icon, Tooltip, Button, Select } from 'antd';
57
const { Option, OptGroup } = Select;
68
const SubMenu = Menu.SubMenu;
@@ -34,24 +36,40 @@ export default class ValueField extends Component {
3436
this.props.setValue(key);
3537
}
3638

37-
//tip: empty groups is ok for antd
38-
filterFieldsByLeftField(fields, leftFieldKey) {
39-
const leftFieldConfig = getFieldConfig(leftFieldKey, this.props.config);
39+
//tip: empty groups are ok for antd
40+
filterFields(config, fields, leftFieldFullkey, operator) {
41+
fields = clone(fields);
42+
const valueSources = getValueSourcesForFieldOp(config, leftFieldFullkey, operator);
43+
const leftFieldConfig = getFieldConfig(leftFieldFullkey, config);
44+
let valueSrc = valueSources.find(vs => vs == 'value');
45+
if (!valueSrc)
46+
return [];
47+
let widget = getWidgetForFieldOp(config, leftFieldFullkey, operator, valueSrc);
48+
let widgetConfig = config.widgets[widget];
49+
let widgetType = widgetConfig.type;
50+
//let expectedType = leftFieldConfig.type;
51+
let expectedType = widgetType;
52+
const fieldSeparator = config.settings.fieldSeparator;
53+
4054
function _filter(list, path) {
41-
for (let fieldKey in list) {
42-
let field = list[fieldKey];
43-
if (field.type == "!struct") {
44-
let subpath = (path ? path : []).concat(fieldKey);
45-
_filter(field.subfields, subpath);
55+
for (let rightFieldKey in list) {
56+
let subfields = list[rightFieldKey].subfields;
57+
let subpath = (path ? path : []).concat(rightFieldKey);
58+
let rightFieldFullkey = subpath.join(fieldSeparator);
59+
let rightFieldConfig = getFieldConfig(rightFieldFullkey, config);
60+
if (rightFieldConfig.type == "!struct") {
61+
_filter(subfields, subpath);
4662
} else {
47-
if (field.type != leftFieldConfig.type || fieldKey == leftFieldKey) {
48-
delete list[fieldKey];
49-
}
63+
let canUse = rightFieldConfig.type == expectedType && rightFieldFullkey != leftFieldFullkey;
64+
let fn = config.settings.canCompareFieldWithField;
65+
if (fn)
66+
canUse = canUse && fn(leftFieldFullkey, leftFieldConfig, rightFieldFullkey, rightFieldConfig);
67+
if (!canUse)
68+
delete list[rightFieldKey];
5069
}
5170
}
5271
}
5372

54-
fields = clone(fields);
5573
_filter(fields, []);
5674

5775
return fields;
@@ -134,7 +152,7 @@ export default class ValueField extends Component {
134152
}
135153

136154
renderAsSelect() {
137-
let fieldOptions = this.filterFieldsByLeftField(this.props.config.fields, this.props.field);
155+
let fieldOptions = this.filterFields(this.props.config, this.props.config.fields, this.props.field, this.props.operator);
138156
let placeholder = this.curFieldOpts().label || this.props.config.settings.fieldPlaceholder;
139157
let placeholderWidth = calcTextWidth(placeholder, '12px');
140158
let fieldSelectItems = this.buildSelectItems(fieldOptions);
@@ -154,7 +172,7 @@ export default class ValueField extends Component {
154172
}
155173

156174
renderAsDropdown() {
157-
let fieldOptions = this.filterFieldsByLeftField(this.props.config.fields, this.props.field);
175+
let fieldOptions = this.filterFields(this.props.config, this.props.config.fields, this.props.field, this.props.operator);
158176
let selectedFieldKeys = getFieldPath(this.props.value, this.props.config);
159177
let selectedFieldPartsLabels = getFieldPathLabels(this.props.value, this.props.config);
160178
let selectedFieldFullLabel = selectedFieldPartsLabels ? selectedFieldPartsLabels.join(this.props.config.settings.fieldSeparatorDisplay) : null;

modules/utils/configUtils.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const extendConfig = (config) => {
8484
}
8585
}
8686
_extendFieldsConfig(config.fields);
87-
//console.log(config);
87+
console.log(config);
8888
return config;
8989
};
9090

@@ -256,6 +256,14 @@ function _getWidgetsAndSrcsForFieldOp (config, field, operator, valueSrc = null)
256256
}
257257
}
258258
}
259+
widgets.sort((w1, w2) => {
260+
let w1Main = w1 == fieldConfig.mainWidget;
261+
let w2Main = w2 == fieldConfig.mainWidget;
262+
if (w1 != w2) {
263+
return w1 ? -1 : +1;
264+
}
265+
return 0;
266+
});
259267
return {widgets, valueSrcs};
260268
};
261269

modules/utils/queryString.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const queryString = (item, config, isForDisplay = false) => {
3636
const fieldSeparator = config.settings.fieldSeparator;
3737

3838
//format value
39+
let valueSrcs = [];
3940
let value = properties.get('value').map((currentValue, ind) => {
4041
const valueSrc = properties.get('valueSrc') ? properties.get('valueSrc').get(ind) : null;
4142
const widget = getWidgetForFieldOp(config, field, operator, valueSrc);
@@ -68,6 +69,7 @@ export const queryString = (item, config, isForDisplay = false) => {
6869
}
6970
return currentValue;
7071
}
72+
valueSrcs.push(valueSrc);
7173
});
7274
if (value.size < cardinality)
7375
return undefined;
@@ -84,7 +86,7 @@ export const queryString = (item, config, isForDisplay = false) => {
8486
}
8587
if (!fn && cardinality == 1) {
8688
let _operator = operatorDefinition.labelForFormat || operator;
87-
fn = (field, operator, value, fieldDef, isForDisplay) => {
89+
fn = (field, op, values, valueSrc, opDef, operatorOptions, isForDisplay) => {
8890
return `${field} ${_operator} ${value}`;
8991
};
9092
}
@@ -104,6 +106,7 @@ export const queryString = (item, config, isForDisplay = false) => {
104106
formattedField,
105107
operator,
106108
formattedValue,
109+
(valueSrcs.length > 1 ? valueSrcs : valueSrcs[0]),
107110
omit(operatorDefinition, ['formatOp']),
108111
operatorOptions,
109112
isForDisplay

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-awesome-query-builder",
3-
"version": "0.1.9",
3+
"version": "0.1.10",
44
"main1": "modules",
55
"main": "build/npm/lib",
66
"main2": "build/global/ReactQueryBuilder.js",

0 commit comments

Comments
 (0)