@talend/react-forms
Version:
React forms library based on json schema form.
295 lines (282 loc) • 9.57 kB
JavaScript
"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