cspace-ui
Version:
CollectionSpace user interface for browsers
309 lines (301 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactIntl = require("react-intl");
var _immutable = _interopRequireDefault(require("immutable"));
var _get = _interopRequireDefault(require("lodash/get"));
var _FieldInput = _interopRequireDefault(require("./FieldInput"));
var _OperatorInput = _interopRequireDefault(require("./OperatorInput"));
var _RangeSearchField = _interopRequireDefault(require("../RangeSearchField"));
var _SearchField = _interopRequireDefault(require("../SearchField"));
var _RemoveConditionButton = _interopRequireDefault(require("../RemoveConditionButton"));
var _searchOperators = require("../../../constants/searchOperators");
var _configHelpers = require("../../../helpers/configHelpers");
var _configContextInputs = require("../../../helpers/configContextInputs");
var _searchHelpers = require("../../../helpers/searchHelpers");
var _FieldConditionInput = _interopRequireDefault(require("../../../../styles/cspace-ui/FieldConditionInput.css"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const propTypes = {
condition: _propTypes.default.instanceOf(_immutable.default.Map),
config: _propTypes.default.shape({
recordTypes: _propTypes.default.object
}),
inline: _propTypes.default.bool,
name: _propTypes.default.string,
readOnly: _propTypes.default.bool,
recordType: _propTypes.default.string,
isNewSearchForm: _propTypes.default.bool,
rootPath: _propTypes.default.string,
onCommit: _propTypes.default.func,
onRemove: _propTypes.default.func
};
const messages = (0, _reactIntl.defineMessages)({
notFound: {
"id": "fieldConditionInput.notFound",
"defaultMessage": "field not found"
}
});
const isFieldControlled = fieldDescriptor => {
const viewType = (0, _get.default)(fieldDescriptor, [_configHelpers.configKey, 'view', 'type']);
return (viewType === null || viewType === void 0 ? void 0 : viewType.toJSON()) === _configContextInputs.AutocompleteInput.toJSON() || (viewType === null || viewType === void 0 ? void 0 : viewType.toJSON()) === _configContextInputs.OptionPickerInput.toJSON() || (viewType === null || viewType === void 0 ? void 0 : viewType.toJSON()) === _configContextInputs.TermPickerInput.toJSON();
};
const isOperatorMatchOrContain = operator => [_searchOperators.OP_MATCH, _searchOperators.OP_NOT_MATCH, _searchOperators.OP_CONTAIN, _searchOperators.OP_NOT_CONTAIN].includes(operator);
class FieldConditionInput extends _react.Component {
constructor() {
super();
this.handleFieldCommit = this.handleFieldCommit.bind(this);
this.handleOperatorCommit = this.handleOperatorCommit.bind(this);
this.handleRef = this.handleRef.bind(this);
this.handleRemoveButtonClick = this.handleRemoveButtonClick.bind(this);
this.handleValueCommit = this.handleValueCommit.bind(this);
}
componentDidMount() {
const {
condition
} = this.props;
const path = condition.get('path');
if (path === null) {
// The condition was just added, and the field needs to be selected. Focus it.
if (this.domNode) {
const input = this.domNode.querySelector('input[data-name="field"]');
if (input) {
input.focus();
}
}
}
}
componentDidUpdate(prevProps) {
const {
condition
} = this.props;
const {
condition: prevCondition
} = prevProps;
if (condition !== prevCondition) {
const path = condition.get('path');
if (path) {
const ops = this.getOperators(path);
if (!ops.includes(condition.get('op'))) {
// The new field's operators don't include the current operator. Set the operator to the
// first of the new field's supported operators.
// FIXME: This doesn't work if componentDidUpdate in AdvancedSearchBuilder executes
// normalizeCondition, and the condition is normalized. In that case, it will restore the
// previous operator. This all needs to be reworked.
this.setOperator(ops[0]);
}
}
if (path !== null && prevCondition.get('path') === null) {
// The field was just selected. Focus the operator.
if (this.domNode) {
const input = this.domNode.querySelector('input[data-name="searchOp"]');
if (input) {
input.focus();
}
}
}
}
}
handleFieldCommit(path, fieldPath) {
const {
condition,
name,
onCommit
} = this.props;
if (onCommit) {
// Delete the current value, since it may not be valid for the new field.
onCommit(name, condition.set('path', fieldPath).delete('value'));
}
}
handleOperatorCommit(path, operator) {
this.setOperator(operator);
}
handleRef(ref) {
this.domNode = ref;
}
handleRemoveButtonClick() {
const {
name,
onRemove
} = this.props;
if (onRemove) {
onRemove(name);
}
}
handleValueCommit(path, value) {
const {
condition,
name,
onCommit
} = this.props;
if (onCommit) {
onCommit(name, condition.set('value', value));
}
}
getOperators(path) {
const {
config,
recordType,
isNewSearchForm
} = this.props;
const fieldDescriptor = (0, _get.default)(config, ['recordTypes', recordType, 'fields', 'document', ...path.split('/')]);
const dataType = (0, _configHelpers.getFieldDataType)(fieldDescriptor);
const isControlled = isFieldControlled(fieldDescriptor);
const isAutocomplete = (0, _searchHelpers.isFieldAutocomplete)(fieldDescriptor);
return (0, _searchHelpers.getOperatorsForDataType)(dataType, isControlled, isNewSearchForm, isAutocomplete);
}
setOperator(operator) {
const {
condition,
name,
onCommit
} = this.props;
if (onCommit) {
let nextCondition = condition.set('op', operator);
if (!(0, _searchHelpers.operatorExpectsValue)(operator)) {
// If the new operator doesn't expect a value, remove any values that exist.
nextCondition = nextCondition.delete('value');
} else if (!(0, _searchHelpers.operatorSupportsMultipleValues)(operator)) {
// If the new operator doesn't support multiple values, prune all values except the first.
const value = condition.get('value');
if (_immutable.default.List.isList(value)) {
nextCondition = nextCondition.set('value', value.first());
}
}
onCommit(name, nextCondition);
}
}
renderFieldInput() {
const {
condition,
config,
inline,
recordType,
rootPath
} = this.props;
const pathSpec = condition.get('path');
if (!pathSpec) {
if (inline) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_FieldInput.default, {
config: config,
inline: inline,
name: "field",
placeholder: "Field",
recordType: recordType,
rootPath: rootPath,
onCommit: this.handleFieldCommit
});
}
const path = ['document', ...pathSpec.split('/')];
const fieldDescriptor = (0, _get.default)(config, ['recordTypes', recordType, 'fields', ...path]);
return /*#__PURE__*/_react.default.createElement(_FieldInput.default, {
config: config,
inline: inline,
readOnly: true,
recordType: recordType,
rootPath: rootPath,
value: pathSpec,
valueDescriptor: fieldDescriptor,
onCommit: this.handleFieldCommit
});
}
renderOperatorInput() {
const {
condition,
config,
inline,
readOnly,
recordType,
isNewSearchForm
} = this.props;
const pathSpec = condition.get('path');
if (!pathSpec) {
return inline ? null : /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("span", null, "..."));
}
const operator = condition.get('op');
const path = ['document', ...pathSpec.split('/')];
const fieldDescriptor = (0, _get.default)(config, ['recordTypes', recordType, 'fields', ...path]);
if (!fieldDescriptor) {
return inline ? null : /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, messages.notFound));
}
const dataType = (0, _configHelpers.getFieldDataType)(fieldDescriptor);
const isControlled = isFieldControlled(fieldDescriptor);
const isAutocomplete = (0, _searchHelpers.isFieldAutocomplete)(fieldDescriptor);
const operators = (0, _searchHelpers.getOperatorsForDataType)(dataType, isControlled, isNewSearchForm, isAutocomplete);
return /*#__PURE__*/_react.default.createElement(_OperatorInput.default, {
compact: inline,
inline: inline,
name: "searchOp",
operators: operators,
readOnly: readOnly,
value: operator,
onCommit: this.handleOperatorCommit
});
}
renderValueInput() {
const {
condition,
config,
inline,
readOnly,
recordType
} = this.props;
const pathSpec = condition.get('path');
let valueSearchField = null;
if (pathSpec) {
const operator = condition.get('op');
const value = condition.get('value');
const path = ['document', ...pathSpec.split('/')];
const name = path[path.length - 1];
const parentPath = path.slice(0, path.length - 1);
const fieldDescriptor = (0, _get.default)(config, ['recordTypes', recordType, 'fields', ...path]);
if (!fieldDescriptor) {
return /*#__PURE__*/_react.default.createElement("div", null);
}
const dataType = (0, _configHelpers.getFieldDataType)(fieldDescriptor);
if ((0, _searchHelpers.operatorExpectsValue)(operator)) {
const ValueSearchFieldComponent = operator === _searchOperators.OP_RANGE || operator === _searchOperators.OP_NOT_RANGE ? _RangeSearchField.default : _SearchField.default;
valueSearchField = /*#__PURE__*/_react.default.createElement(ValueSearchFieldComponent, {
inline: inline,
parentPath: parentPath,
name: name,
readOnly: readOnly,
repeating: (0, _searchHelpers.operatorSupportsMultipleValues)(operator) && (0, _searchHelpers.dataTypeSupportsMultipleValues)(dataType),
value: value,
onCommit: this.handleValueCommit,
forceTextInput: isOperatorMatchOrContain(operator)
});
}
}
return /*#__PURE__*/_react.default.createElement("div", null, valueSearchField);
}
renderRemoveButton() {
const {
readOnly
} = this.props;
if (readOnly) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_RemoveConditionButton.default, {
onClick: this.handleRemoveButtonClick
});
}
render() {
const {
inline
} = this.props;
const className = inline ? _FieldConditionInput.default.inline : _FieldConditionInput.default.normal;
return /*#__PURE__*/_react.default.createElement("div", {
className: className,
ref: this.handleRef
}, this.renderFieldInput(), inline ? ' ' : null, this.renderOperatorInput(), inline ? ' ' : null, this.renderValueInput(), this.renderRemoveButton());
}
}
exports.default = FieldConditionInput;
FieldConditionInput.propTypes = propTypes;