@coocoon/react-awesome-query-builder
Version:
User-friendly query builder for React. Demo: https://ukrbublik.github.io/react-awesome-query-builder
114 lines (101 loc) • 3.87 kB
JSX
import React, { PureComponent } from "react";
import { Tooltip, Select } from "antd";
import {BUILT_IN_PLACEMENTS, SELECT_WIDTH_OFFSET_RIGHT, calcTextWidth} from "../../../../utils/domUtils";
import PropTypes from "prop-types";
const { Option, OptGroup } = Select;
export default class FieldSelect extends PureComponent {
static propTypes = {
config: PropTypes.object.isRequired,
customProps: PropTypes.object,
items: PropTypes.array.isRequired,
placeholder: PropTypes.string,
selectedKey: PropTypes.string,
selectedKeys: PropTypes.array,
selectedPath: PropTypes.array,
selectedLabel: PropTypes.string,
selectedAltLabel: PropTypes.string,
selectedFullLabel: PropTypes.string,
selectedOpts: PropTypes.object,
readonly: PropTypes.bool,
//actions
setField: PropTypes.func.isRequired,
};
onChange = (key) => {
this.props.setField(key);
};
filterOption = (input, option) => {
const dataForFilter = option;
const keysForFilter = ["title", "value", "grouplabel", "label"];
const valueForFilter = keysForFilter
.map(k => (typeof dataForFilter[k] == "string" ? dataForFilter[k] : ""))
.join("\0");
return valueForFilter.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
render() {
const {
config, customProps, items, placeholder,
selectedKey, selectedLabel, selectedOpts, selectedAltLabel, selectedFullLabel, readonly,
} = this.props;
const {showSearch} = customProps || {};
const selectText = selectedLabel || placeholder;
const selectWidth = calcTextWidth(selectText);
const isFieldSelected = !!selectedKey;
const dropdownPlacement = config.settings.dropdownPlacement;
const dropdownAlign = dropdownPlacement ? BUILT_IN_PLACEMENTS[dropdownPlacement] : undefined;
const width = isFieldSelected && !showSearch ? null : selectWidth + SELECT_WIDTH_OFFSET_RIGHT;
let tooltipText = selectedAltLabel || selectedFullLabel;
if (tooltipText == selectedLabel)
tooltipText = null;
const fieldSelectItems = this.renderSelectItems(items);
let res = (
<Select
dropdownAlign={dropdownAlign}
dropdownMatchSelectWidth={false}
style={{ width }}
placeholder={placeholder}
size={config.settings.renderSize}
onChange={this.onChange}
value={selectedKey || undefined}
filterOption={this.filterOption}
disabled={readonly}
{...customProps}
>{fieldSelectItems}</Select>
);
if (tooltipText && !selectedOpts.tooltip) {
res = <Tooltip title={tooltipText}>{res}</Tooltip>;
}
return res;
}
renderSelectItems(fields, level = 0) {
return fields.map(field => {
const {items, key, path, label, fullLabel, altLabel, tooltip, grouplabel, disabled} = field;
const groupPrefix = level > 0 ? "\u00A0\u00A0".repeat(level) : "";
const prefix = level > 1 ? "\u00A0\u00A0".repeat(level-1) : "";
const pathKey = path || key;
if (items) {
const simpleItems = items.filter(it => !it.items);
const complexItems = items.filter(it => !!it.items);
const gr = simpleItems.length
? [<OptGroup
key={pathKey}
label={groupPrefix+label}
>{this.renderSelectItems(simpleItems, level+1)}</OptGroup>]
: [];
const list = complexItems.length ? this.renderSelectItems(complexItems, level+1) : [];
return [...gr, ...list];
} else {
const option = tooltip ? <Tooltip title={tooltip}>{prefix+label}</Tooltip> : prefix+label;
return <Option
key={pathKey}
value={pathKey}
title={altLabel}
grouplabel={grouplabel}
label={label}
disabled={disabled}
>
{option}
</Option>;
}
}).flat(Infinity);
}
}