@arudovwen/react-form-builder
Version:
A complete form builder for react.
367 lines (362 loc) • 11.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _immutabilityHelper = _interopRequireDefault(require("immutability-helper"));
var _store = _interopRequireDefault(require("./stores/store"));
var _formDynamicEdit = _interopRequireDefault(require("./form-dynamic-edit"));
var _sortableFormElements = _interopRequireDefault(require("./sortable-form-elements"));
var _componentDragLayer = _interopRequireDefault(require("./form-elements/component-drag-layer"));
/**
* <Preview />
*/
const {
PlaceHolder
} = _sortableFormElements.default;
class Preview extends _react.default.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "state", {
data: [],
answer_data: {}
});
(0, _defineProperty2.default)(this, "editModeOff", e => {
if (this.editForm.current && !this.editForm.current.contains(e.target)) {
this.manualEditModeOff();
}
});
(0, _defineProperty2.default)(this, "manualEditModeOff", () => {
const {
editElement
} = this.props;
if (editElement && editElement.dirty) {
editElement.dirty = false;
this.updateElement(editElement);
}
this.props.manualEditModeOff();
});
(0, _defineProperty2.default)(this, "duplicateElement", elementData => {
const elementId = elementData?.id;
const {
data
} = this.state;
const element = this.getDataById(elementId);
if (!element) return;
// Deep clone the element and assign a new id
const newElement = {
...JSON.parse(JSON.stringify(element)),
id: Date.now() + Math.random()
};
// Optionally, update other fields if needed (e.g., field_name)
newElement.field_name = `${element.field_name}_copy`;
// Insert the duplicated element after the original
const index = data.findIndex(x => x.id === elementId);
const newData = [...data];
newData.splice(index + 1, 0, newElement);
this.setState({
data: newData
});
_store.default.dispatch('updateOrder', newData);
});
const {
onLoad,
onPost
} = props;
_store.default.setExternalHandler(onLoad, onPost);
this.editForm = /*#__PURE__*/_react.default.createRef();
this.state = {
data: props.data || [],
answer_data: {}
};
this.seq = 0;
this._onUpdate = this._onChange.bind(this);
this.getDataById = this.getDataById.bind(this);
this.moveCard = this.moveCard.bind(this);
this.insertCard = this.insertCard.bind(this);
this.setAsChild = this.setAsChild.bind(this);
this.removeChild = this.removeChild.bind(this);
this._onDestroy = this._onDestroy.bind(this);
this.duplicateElement = this.duplicateElement?.bind(this);
}
componentDidMount() {
const {
data,
url,
saveUrl,
saveAlways
} = this.props;
_store.default.subscribe(state => this._onUpdate(state.data));
_store.default.dispatch('load', {
loadUrl: url,
saveUrl,
data: data || [],
saveAlways
});
document.addEventListener('mousedown', this.editModeOff);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.editModeOff);
}
_setValue(text) {
return text.replace(/[^A-Z0-9]+/ig, '_').toLowerCase();
}
updateElement(element) {
const {
data
} = this.state;
let found = false;
for (let i = 0, len = data.length; i < len; i++) {
if (element.id === data[i].id) {
data[i] = element;
found = true;
break;
}
}
if (found) {
this.seq = this.seq > 100000 ? 0 : this.seq + 1;
_store.default.dispatch('updateOrder', data);
}
}
_onChange(data) {
const answer_data = {};
data.forEach(item => {
if (item && item.readOnly && this.props.variables[item.variableKey]) {
answer_data[item.field_name] = this.props.variables[item.variableKey];
}
});
this.setState({
data,
answer_data
});
}
_onDestroy(item) {
if (item.childItems) {
item.childItems.forEach(x => {
const child = this.getDataById(x);
if (child) {
_store.default.dispatch('delete', child);
}
});
}
_store.default.dispatch('delete', item);
}
getDataById(id) {
const {
data
} = this.state;
return data.find(x => x && x.id === id);
}
swapChildren(data, item, child, col) {
if (child.col !== undefined && item.id !== child.parentId) {
return false;
}
if (!(child.col !== undefined && child.col !== col && item.childItems[col])) {
// No child was assigned yet in both source and target.
return false;
}
const oldId = item.childItems[col];
const oldItem = this.getDataById(oldId);
const oldCol = child.col;
// eslint-disable-next-line no-param-reassign
item.childItems[oldCol] = oldId;
oldItem.col = oldCol;
// eslint-disable-next-line no-param-reassign
item.childItems[col] = child.id;
child.col = col;
_store.default.dispatch('updateOrder', data);
return true;
}
setAsChild(item, child, col, isBusy) {
const {
data
} = this.state;
if (this.swapChildren(data, item, child, col)) {
return;
}
if (isBusy) {
return;
}
const oldParent = this.getDataById(child.parentId);
const oldCol = child.col;
// eslint-disable-next-line no-param-reassign
item.childItems[col] = child.id;
child.col = col;
// eslint-disable-next-line no-param-reassign
child.parentId = item.id;
// eslint-disable-next-line no-param-reassign
child.parentIndex = data.indexOf(item);
if (oldParent) {
oldParent.childItems[oldCol] = null;
}
const list = data.filter(x => x && x.parentId === item.id);
const toRemove = list.filter(x => item.childItems.indexOf(x.id) === -1);
let newData = data;
if (toRemove.length) {
// console.log('toRemove', toRemove);
newData = data.filter(x => toRemove.indexOf(x) === -1);
}
if (!this.getDataById(child.id)) {
newData.push(child);
}
_store.default.dispatch('updateOrder', newData);
}
removeChild(item, col) {
const {
data
} = this.state;
const oldId = item.childItems[col];
const oldItem = this.getDataById(oldId);
if (oldItem) {
const newData = data.filter(x => x !== oldItem);
// eslint-disable-next-line no-param-reassign
item.childItems[col] = null;
// delete oldItem.parentId;
this.seq = this.seq > 100000 ? 0 : this.seq + 1;
_store.default.dispatch('updateOrder', newData);
this.setState({
data: newData
});
}
}
restoreCard(item, id) {
const {
data
} = this.state;
const parent = this.getDataById(item.data.parentId);
const oldItem = this.getDataById(id);
if (parent && oldItem) {
const newIndex = data.indexOf(oldItem);
const newData = [...data]; // data.filter(x => x !== oldItem);
// eslint-disable-next-line no-param-reassign
parent.childItems[oldItem.col] = null;
delete oldItem.parentId;
// eslint-disable-next-line no-param-reassign
delete item.setAsChild;
// eslint-disable-next-line no-param-reassign
delete item.parentIndex;
// eslint-disable-next-line no-param-reassign
item.index = newIndex;
this.seq = this.seq > 100000 ? 0 : this.seq + 1;
_store.default.dispatch('updateOrder', newData);
this.setState({
data: newData
});
}
}
insertCard(item, hoverIndex, id) {
const {
data
} = this.state;
if (id) {
this.restoreCard(item, id);
} else {
data.splice(hoverIndex, 0, item);
this.saveData(item, hoverIndex, hoverIndex);
_store.default.dispatch('insertItem', item);
}
}
moveCard(dragIndex, hoverIndex) {
const {
data
} = this.state;
const dragCard = data[dragIndex];
// happens sometimes when you click to insert a new item from the toolbox
if (dragCard !== undefined) {
this.saveData(dragCard, dragIndex, hoverIndex);
}
}
// eslint-disable-next-line no-unused-vars
cardPlaceHolder(dragIndex, hoverIndex) {
// Dummy
}
saveData(dragCard, dragIndex, hoverIndex) {
const newData = (0, _immutabilityHelper.default)(this.state, {
data: {
$splice: [[dragIndex, 1], [hoverIndex, 0, dragCard]]
}
});
this.setState(newData);
_store.default.dispatch('updateOrder', newData.data);
}
getElement(item, index) {
if (item.custom) {
if (!item.component || typeof item.component !== 'function') {
// eslint-disable-next-line no-param-reassign
item.component = this.props.registry.get(item.key);
}
}
const SortableFormElement = _sortableFormElements.default[item.element];
if (SortableFormElement === null) {
return null;
}
return /*#__PURE__*/_react.default.createElement(SortableFormElement, {
id: item.id,
seq: this.seq,
index: index,
moveCard: this.moveCard,
insertCard: this.insertCard,
mutable: false,
parent: this.props.parent,
editModeOn: this.props.editModeOn,
isDraggable: true,
key: item.id,
sortData: item.id,
data: item,
getDataById: this.getDataById,
setAsChild: this.setAsChild,
removeChild: this.removeChild,
_onDestroy: this._onDestroy,
duplicateElement: this.duplicateElement
});
}
showEditForm() {
const handleUpdateElement = element => this.updateElement(element);
handleUpdateElement.bind(this);
const formElementEditProps = {
showCorrectColumn: this.props.showCorrectColumn,
files: this.props.files,
manualEditModeOff: this.manualEditModeOff,
preview: this,
element: this.props.editElement,
updateElement: handleUpdateElement,
formData: this.state.data,
apiBaseUrl: this.props.apiBaseUrl || 'https://api.dev.gateway.kusala.com.ng'
};
return this.props.renderEditForm(formElementEditProps);
}
render() {
let classes = this.props.className;
if (this.props.editMode) {
classes += ' is-editing';
}
const data = this.state.data.filter(x => !!x && !x.parentId);
const items = data.map((item, index) => this.getElement(item, index));
return /*#__PURE__*/_react.default.createElement("div", {
className: classes
}, /*#__PURE__*/_react.default.createElement("div", {
className: "edit-form",
ref: this.editForm
}, this.props.editElement !== null && this.showEditForm()), /*#__PURE__*/_react.default.createElement("div", {
className: "Sortable"
}, items), /*#__PURE__*/_react.default.createElement(PlaceHolder, {
id: "form-place-holder",
show: items.length === 0,
index: items.length,
moveCard: this.cardPlaceHolder,
insertCard: this.insertCard
}), /*#__PURE__*/_react.default.createElement(_componentDragLayer.default, null));
}
}
exports.default = Preview;
Preview.defaultProps = {
showCorrectColumn: false,
files: [],
editMode: false,
editElement: null,
className: 'react-form-builder-preview flex-1',
renderEditForm: props => /*#__PURE__*/_react.default.createElement(_formDynamicEdit.default, props)
};