UNPKG

react-editable-json-tree

Version:
565 lines (497 loc) 21.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _getOwnPropertyNames = require('babel-runtime/core-js/object/get-own-property-names'); var _getOwnPropertyNames2 = _interopRequireDefault(_getOwnPropertyNames); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _JsonNode = require('./JsonNode'); var _JsonNode2 = _interopRequireDefault(_JsonNode); var _JsonAddValue = require('./JsonAddValue'); var _JsonAddValue2 = _interopRequireDefault(_JsonAddValue); var _objectTypes = require('../utils/objectTypes'); var _deltaTypes = require('../types/deltaTypes'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ // Prop types /* * Author: Alexandre Havrileck (Oxyno-zeta) * Date: 18/10/16 * Licence: See Readme */ /* ************************************* */ /* ******** IMPORTS ******** */ /* ************************************* */ var propTypes = { data: _propTypes2.default.object.isRequired, name: _propTypes2.default.string.isRequired, isCollapsed: _propTypes2.default.func.isRequired, keyPath: _propTypes2.default.array, deep: _propTypes2.default.number, handleRemove: _propTypes2.default.func, onUpdate: _propTypes2.default.func.isRequired, onDeltaUpdate: _propTypes2.default.func.isRequired, readOnly: _propTypes2.default.func.isRequired, dataType: _propTypes2.default.string, getStyle: _propTypes2.default.func.isRequired, addButtonElement: _propTypes2.default.element, cancelButtonElement: _propTypes2.default.element, editButtonElement: _propTypes2.default.element, inputElementGenerator: _propTypes2.default.func.isRequired, textareaElementGenerator: _propTypes2.default.func.isRequired, minusMenuElement: _propTypes2.default.element, plusMenuElement: _propTypes2.default.element, beforeRemoveAction: _propTypes2.default.func, beforeAddAction: _propTypes2.default.func, beforeUpdateAction: _propTypes2.default.func, logger: _propTypes2.default.object.isRequired, onSubmitValueParser: _propTypes2.default.func.isRequired }; // Default props var defaultProps = { keyPath: [], deep: 0, minusMenuElement: _react2.default.createElement( 'span', null, ' - ' ), plusMenuElement: _react2.default.createElement( 'span', null, ' + ' ) }; /* ************************************* */ /* ******** COMPONENT ******** */ /* ************************************* */ var JsonObject = function (_Component) { (0, _inherits3.default)(JsonObject, _Component); function JsonObject(props) { (0, _classCallCheck3.default)(this, JsonObject); var _this = (0, _possibleConstructorReturn3.default)(this, (JsonObject.__proto__ || (0, _getPrototypeOf2.default)(JsonObject)).call(this, props)); var keyPath = props.deep === -1 ? [] : [].concat((0, _toConsumableArray3.default)(props.keyPath), [props.name]); _this.state = { name: props.name, data: props.data, keyPath: keyPath, deep: props.deep, nextDeep: props.deep + 1, collapsed: props.isCollapsed(keyPath, props.deep, props.data), addFormVisible: false }; // Bind _this.handleCollapseMode = _this.handleCollapseMode.bind(_this); _this.handleRemoveValue = _this.handleRemoveValue.bind(_this); _this.handleAddMode = _this.handleAddMode.bind(_this); _this.handleAddValueAdd = _this.handleAddValueAdd.bind(_this); _this.handleAddValueCancel = _this.handleAddValueCancel.bind(_this); _this.handleEditValue = _this.handleEditValue.bind(_this); _this.onChildUpdate = _this.onChildUpdate.bind(_this); _this.renderCollapsed = _this.renderCollapsed.bind(_this); _this.renderNotCollapsed = _this.renderNotCollapsed.bind(_this); return _this; } (0, _createClass3.default)(JsonObject, [{ key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { this.setState({ data: nextProps.data }); } }, { key: 'onChildUpdate', value: function onChildUpdate(childKey, childData) { var _state = this.state, data = _state.data, keyPath = _state.keyPath; // Update data data[childKey] = childData; // Put new data this.setState({ data: data }); // Spread var onUpdate = this.props.onUpdate; var size = keyPath.length; onUpdate(keyPath[size - 1], data); } }, { key: 'handleAddMode', value: function handleAddMode() { this.setState({ addFormVisible: true }); } }, { key: 'handleAddValueCancel', value: function handleAddValueCancel() { this.setState({ addFormVisible: false }); } }, { key: 'handleAddValueAdd', value: function handleAddValueAdd(_ref) { var _this2 = this; var key = _ref.key, newValue = _ref.newValue; var _state2 = this.state, data = _state2.data, keyPath = _state2.keyPath, deep = _state2.nextDeep; var _props = this.props, beforeAddAction = _props.beforeAddAction, logger = _props.logger; beforeAddAction(key, keyPath, deep, newValue).then(function () { // Update data data[key] = newValue; _this2.setState({ data: data }); // Cancel add to close _this2.handleAddValueCancel(); // Spread new update var _props2 = _this2.props, onUpdate = _props2.onUpdate, onDeltaUpdate = _props2.onDeltaUpdate; onUpdate(keyPath[keyPath.length - 1], data); // Spread delta update onDeltaUpdate({ type: _deltaTypes.ADD_DELTA_TYPE, keyPath: keyPath, deep: deep, key: key, newValue: newValue }); }).catch(logger.error); } }, { key: 'handleRemoveValue', value: function handleRemoveValue(key) { var _this3 = this; return function () { var _props3 = _this3.props, beforeRemoveAction = _props3.beforeRemoveAction, logger = _props3.logger; var _state3 = _this3.state, data = _state3.data, keyPath = _state3.keyPath, deep = _state3.nextDeep; var oldValue = data[key]; // Before Remove Action beforeRemoveAction(key, keyPath, deep, oldValue).then(function () { var objType = (0, _objectTypes.getObjectType)(oldValue); var deltaUpdateResult = { keyPath: keyPath, deep: deep, key: key, oldValue: oldValue }; if (objType === 'Object' || objType === 'Array') { deltaUpdateResult.type = _deltaTypes.UPDATE_DELTA_TYPE; deltaUpdateResult.newValue = null; data[key] = null; } else { deltaUpdateResult.type = _deltaTypes.REMOVE_DELTA_TYPE; delete data[key]; } _this3.setState({ data: data }); // Spread new update var _props4 = _this3.props, onUpdate = _props4.onUpdate, onDeltaUpdate = _props4.onDeltaUpdate; onUpdate(keyPath[keyPath.length - 1], data); // Spread delta update onDeltaUpdate(deltaUpdateResult); }).catch(logger.error); }; } }, { key: 'handleCollapseMode', value: function handleCollapseMode() { this.setState({ collapsed: !this.state.collapsed }); } }, { key: 'handleEditValue', value: function handleEditValue(_ref2) { var _this4 = this; var key = _ref2.key, value = _ref2.value; return new _promise2.default(function (resolve, reject) { var beforeUpdateAction = _this4.props.beforeUpdateAction; var _state4 = _this4.state, data = _state4.data, keyPath = _state4.keyPath, deep = _state4.nextDeep; // Old value var oldValue = data[key]; // Before update action beforeUpdateAction(key, keyPath, deep, oldValue, value).then(function () { // Update value data[key] = value; // Set state _this4.setState({ data: data }); // Spread new update var _props5 = _this4.props, onUpdate = _props5.onUpdate, onDeltaUpdate = _props5.onDeltaUpdate; onUpdate(keyPath[keyPath.length - 1], data); // Spread delta update onDeltaUpdate({ type: _deltaTypes.UPDATE_DELTA_TYPE, keyPath: keyPath, deep: deep, key: key, newValue: value, oldValue: oldValue }); // Resolve resolve(); }).catch(reject); }); } }, { key: 'renderCollapsed', value: function renderCollapsed() { var _state5 = this.state, name = _state5.name, keyPath = _state5.keyPath, deep = _state5.deep, data = _state5.data; var _props6 = this.props, handleRemove = _props6.handleRemove, readOnly = _props6.readOnly, dataType = _props6.dataType, getStyle = _props6.getStyle, minusMenuElement = _props6.minusMenuElement; var _getStyle = getStyle(name, data, keyPath, deep, dataType), minus = _getStyle.minus, collapsed = _getStyle.collapsed; var keyList = (0, _getOwnPropertyNames2.default)(data); var collapseValue = ' {...}'; var numberOfItems = keyList.length; var itemName = numberOfItems > 1 ? 'keys' : 'key'; var minusElement = null; // Check if readOnly is activated if (!readOnly(name, data, keyPath, deep, dataType)) { var minusMenuLayout = _react2.default.cloneElement(minusMenuElement, { onClick: handleRemove, className: 'rejt-minus-menu', style: minus }); minusElement = deep !== -1 ? minusMenuLayout : null; } /* eslint-disable jsx-a11y/no-static-element-interactions */ return _react2.default.createElement( 'span', { className: 'rejt-collapsed' }, _react2.default.createElement( 'span', { className: 'rejt-collapsed-text', style: collapsed, onClick: this.handleCollapseMode }, collapseValue, ' ', numberOfItems, ' ', itemName ), minusElement ); /* eslint-enable */ } }, { key: 'renderNotCollapsed', value: function renderNotCollapsed() { var _this5 = this; var _state6 = this.state, name = _state6.name, data = _state6.data, keyPath = _state6.keyPath, deep = _state6.deep, nextDeep = _state6.nextDeep, addFormVisible = _state6.addFormVisible; var _props7 = this.props, isCollapsed = _props7.isCollapsed, handleRemove = _props7.handleRemove, onDeltaUpdate = _props7.onDeltaUpdate, readOnly = _props7.readOnly, getStyle = _props7.getStyle, dataType = _props7.dataType, addButtonElement = _props7.addButtonElement, cancelButtonElement = _props7.cancelButtonElement, editButtonElement = _props7.editButtonElement, inputElementGenerator = _props7.inputElementGenerator, textareaElementGenerator = _props7.textareaElementGenerator, minusMenuElement = _props7.minusMenuElement, plusMenuElement = _props7.plusMenuElement, beforeRemoveAction = _props7.beforeRemoveAction, beforeAddAction = _props7.beforeAddAction, beforeUpdateAction = _props7.beforeUpdateAction, logger = _props7.logger, onSubmitValueParser = _props7.onSubmitValueParser; var _getStyle2 = getStyle(name, data, keyPath, deep, dataType), minus = _getStyle2.minus, plus = _getStyle2.plus, addForm = _getStyle2.addForm, ul = _getStyle2.ul, delimiter = _getStyle2.delimiter; var keyList = (0, _getOwnPropertyNames2.default)(data); var minusElement = null; var readOnlyResult = readOnly(name, data, keyPath, deep, dataType); // Check if readOnly is activated if (!readOnlyResult) { var minusMenuLayout = _react2.default.cloneElement(minusMenuElement, { onClick: handleRemove, className: 'rejt-minus-menu', style: minus }); minusElement = deep !== -1 ? minusMenuLayout : null; } var list = keyList.map(function (key) { return _react2.default.createElement(_JsonNode2.default, { key: key, name: key, data: data[key], keyPath: keyPath, deep: nextDeep, isCollapsed: isCollapsed, handleRemove: _this5.handleRemoveValue(key), handleUpdateValue: _this5.handleEditValue, onUpdate: _this5.onChildUpdate, onDeltaUpdate: onDeltaUpdate, readOnly: readOnly, getStyle: getStyle, addButtonElement: addButtonElement, cancelButtonElement: cancelButtonElement, editButtonElement: editButtonElement, inputElementGenerator: inputElementGenerator, textareaElementGenerator: textareaElementGenerator, minusMenuElement: minusMenuElement, plusMenuElement: plusMenuElement, beforeRemoveAction: beforeRemoveAction, beforeAddAction: beforeAddAction, beforeUpdateAction: beforeUpdateAction, logger: logger, onSubmitValueParser: onSubmitValueParser }); }); var startObject = '{'; var endObject = '}'; var menu = null; // Check if readOnly is activated if (!readOnlyResult) { var plusMenuLayout = _react2.default.cloneElement(plusMenuElement, { onClick: this.handleAddMode, className: 'rejt-plus-menu', style: plus }); menu = addFormVisible ? _react2.default.createElement( 'span', { className: 'rejt-add-form', style: addForm }, _react2.default.createElement(_JsonAddValue2.default, { handleAdd: this.handleAddValueAdd, handleCancel: this.handleAddValueCancel, addButtonElement: addButtonElement, cancelButtonElement: cancelButtonElement, inputElementGenerator: inputElementGenerator, keyPath: keyPath, deep: deep, onSubmitValueParser: onSubmitValueParser }) ) : _react2.default.createElement( 'span', null, plusMenuLayout, ' ', minusElement ); } return _react2.default.createElement( 'span', { className: 'rejt-not-collapsed' }, _react2.default.createElement( 'span', { className: 'rejt-not-collapsed-delimiter', style: delimiter }, startObject ), _react2.default.createElement( 'ul', { className: 'rejt-not-collapsed-list', style: ul }, list ), _react2.default.createElement( 'span', { className: 'rejt-not-collapsed-delimiter', style: delimiter }, endObject ), menu ); } }, { key: 'render', value: function render() { var _state7 = this.state, name = _state7.name, collapsed = _state7.collapsed, data = _state7.data, keyPath = _state7.keyPath, deep = _state7.deep; var _props8 = this.props, getStyle = _props8.getStyle, dataType = _props8.dataType; var value = collapsed ? this.renderCollapsed() : this.renderNotCollapsed(); var style = getStyle(name, data, keyPath, deep, dataType); /* eslint-disable jsx-a11y/no-static-element-interactions */ return _react2.default.createElement( 'div', { className: 'rejt-object-node' }, _react2.default.createElement( 'span', { onClick: this.handleCollapseMode }, _react2.default.createElement( 'span', { className: 'rejt-name', style: style.name }, name, ' : ' ) ), value ); /* eslint-enable */ } }]); return JsonObject; }(_react.Component); // Add prop types JsonObject.propTypes = propTypes; // Add default props JsonObject.defaultProps = defaultProps; /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ exports.default = JsonObject;