UNPKG

@talend/react-forms

Version:

React forms library based on json schema form.

295 lines (282 loc) 9.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.NestedListViewWidget = void 0; var _react = require("react"); var _reactI18next = require("react-i18next"); var _propTypes = _interopRequireDefault(require("prop-types")); var _constants = require("../../../constants"); var _translate = _interopRequireDefault(require("../../../translate")); var _generateId = require("../../Message/generateId"); var _FieldTemplate = _interopRequireDefault(require("../FieldTemplate")); var _NestedListView = require("./NestedListView.utils"); var _NestedListViewModule = _interopRequireDefault(require("./NestedListView.module.scss")); var _reactComponents = require("@talend/react-components"); var _lodash = require("lodash"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const DISPLAY_MODE_DEFAULT = 'DISPLAY_MODE_DEFAULT'; const DISPLAY_MODE_SEARCH = 'DISPLAY_MODE_SEARCH'; const DEFAULT_ITEM_HEIGHT = 33; const getItemHeight = () => DEFAULT_ITEM_HEIGHT; class NestedListViewWidget extends _react.Component { constructor(props) { super(props); const { t, value, schema, id } = props; this.defaultHeaderActions = [{ id: `${id}-search`, icon: 'talend-search', label: t('LISTVIEW_WIDGET_SEARCH', { defaultValue: 'Search for specific values' }), onClick: this.switchToSearchMode.bind(this) }]; this.defaultSearchHeaderActions = [{ id: 'abort', icon: 'talend-cross', label: t('LISTVIEW_WIDGET_REMOVE', { defaultValue: 'Remove filter' }), onClick: this.switchToDefaultMode.bind(this) }]; this.onInputKeyDown = this.onInputKeyDown.bind(this); this.onInputChange = this.onInputChange.bind(this); const callbacks = { onExpandToggle: this.onExpandToggle.bind(this), onParentChange: this.onParentChange.bind(this), onCheck: this.onCheck.bind(this) }; this.items = (0, _NestedListView.prepareItemsFromSchema)(schema, callbacks, value); this.value = value; this.state = { searchCriteria: null, displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value) }; } /** * Detect changes of props * @param { Object } prevProps The new props */ componentDidUpdate(prevProps) { // If props.value if different from previous prop and this.value, refresh the displayed items if (!(0, _lodash.isEqual)(prevProps.value, this.props.value) && !(0, _lodash.isEqual)(this.value, this.props.value)) { var _this$props$schema$op; if ((_this$props$schema$op = this.props.schema.options) !== null && _this$props$schema$op !== void 0 && _this$props$schema$op.expandChecked) { this.items = this.items.map(item => { const values = this.props.value[item.key] || []; return { ...item, expanded: values.length > 0 && values.length !== item.children.length }; }); } this.value = this.props.value; // eslint-disable-next-line react/no-did-update-set-state this.setState({ displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, this.state.searchCriteria) }); } } /** * Click callback to toggle the expanded status of children elements * @param {Object} event * @param {Object} item */ onExpandToggle(event, item) { this.items = this.items.map(fieldItem => { if (fieldItem.key === item.key) { return { ...fieldItem, expanded: !fieldItem.expanded }; } return fieldItem; }); this.setState(({ searchCriteria }) => ({ displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, searchCriteria) })); } /** * Handle checked item (parent) in the ListView change * @param { Object } event The event that triggered the change * @param { Object } item */ onParentChange(event, item) { const { enum: availableOptions } = this.props.schema.schema.properties[item.key].items; // Toggle all values this.value = { ...this.value, [item.key]: (this.value[item.key] || []).length === 0 ? availableOptions : [] }; this.setState(({ searchCriteria }) => ({ displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, searchCriteria) }), () => this.onChange(event)); } /** * Handle checked item (child) in the ListView change * @param { Object } event * @param { Object } item * @param { Object } parent */ onCheck(event, item, parent) { const { key } = parent; if (!(key in this.value)) { this.value[key] = []; } this.value[key] = this.value[key].includes(item.value) ? this.value[key].filter(storedValue => storedValue !== item.value) // Unselect : this.value[key].concat(item.value); // Select this.setState(({ searchCriteria }) => ({ displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, searchCriteria) }), () => this.onChange(event)); } /** * Propagate a ListView value change * @param { Object } event The event that triggered the change * @param { Object } newValue The new Value */ onChange(event) { const payload = { schema: this.props.schema, value: this.value }; this.props.onChange(event, payload); this.props.onFinish(event, payload); } /** * Search input change * @param { Object } event * @param { Object } item */ onInputChange(event, item) { clearTimeout(this.timerSearch); this.timerSearch = setTimeout(() => { const { value: searchCriteria } = item; this.setState({ searchCriteria, displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, searchCriteria) }); }, 400); } /** * Search input ENTER/ESC management * @param { Object } event The keydown event */ onInputKeyDown(event) { if (event.key === 'Enter') { event.preventDefault(); } else if (event.key === 'Esc' || event.key === 'Escape') { clearTimeout(this.timerSearch); event.preventDefault(); this.switchToDefaultMode(); } } /** * Switch header to search mode */ switchToSearchMode() { this.setState({ headerInput: this.defaultSearchHeaderActions, displayMode: DISPLAY_MODE_SEARCH }); } /** * Switch header to default mode. * Reset display to no filter */ switchToDefaultMode() { const searchCriteria = null; this.setState({ displayedItems: (0, _NestedListView.getDisplayedItems)(this.items, this.value, searchCriteria), searchCriteria, headerInput: this.defaultHeaderActions, displayMode: DISPLAY_MODE_DEFAULT }); } render() { const { id, schema } = this.props; return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: _NestedListViewModule.default['nested-list-view'], children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FieldTemplate.default, { description: schema.description, descriptionId: (0, _generateId.generateDescriptionId)(id), errorId: (0, _generateId.generateErrorId)(id), errorMessage: this.props.errorMessage, id: id, isValid: this.props.isValid, required: schema.required, valueIsUpdating: this.props.valueIsUpdating, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactComponents.ListView, { ...this.state, getItemHeight: schema.autosize ? null : getItemHeight, id: this.props.id, items: this.state.displayedItems, headerDefault: this.defaultHeaderActions, onAddKeyDown: this.onInputKeyDown, onInputChange: this.onInputChange, headerLabel: schema.title, labelProps: schema.labelProps, required: schema.required, searchPlaceholder: schema.placeholder, dataTest: schema.dataTest, showToggleAll: false }) }) }); } } exports.NestedListViewWidget = NestedListViewWidget; NestedListViewWidget.defaultProps = { value: {}, t: (0, _translate.default)() }; // eslint-disable-next-line no-undef if (process.env.NODE_ENV !== 'production') { NestedListViewWidget.propTypes = { id: _propTypes.default.string, isValid: _propTypes.default.bool, errorMessage: _propTypes.default.string, onChange: _propTypes.default.func.isRequired, onFinish: _propTypes.default.func.isRequired, schema: _propTypes.default.shape({ schema: _propTypes.default.object, description: _propTypes.default.string, disabled: _propTypes.default.bool, placeholder: _propTypes.default.string, required: _propTypes.default.bool, title: _propTypes.default.string, labelProps: _propTypes.default.object, dataTest: _propTypes.default.string, autosize: _propTypes.default.bool, items: _propTypes.default.array, options: _propTypes.default.shape({ expandChecked: _propTypes.default.bool }) }), value: _propTypes.default.object, valueIsUpdating: _propTypes.default.bool, t: _propTypes.default.func }; } var _default = exports.default = (0, _reactI18next.withTranslation)(_constants.I18N_DOMAIN_FORMS)(NestedListViewWidget); //# sourceMappingURL=NestedListView.component.js.map