UNPKG

@vs-form/vs-form

Version:

A schema-based form generator component for React using material-ui

341 lines (337 loc) 16.1 kB
import { Component, createElement, Fragment } from 'react'; import 'lodash/capitalize'; import cloneDeep from 'lodash/cloneDeep'; import get from 'lodash/get'; import 'lodash/has'; import 'lodash/isArray'; import 'lodash/isDate'; import 'lodash/isBoolean'; import 'lodash/isEmpty'; import 'lodash/isFunction'; import 'lodash/isInteger'; import 'lodash/isNull'; import 'lodash/isNumber'; import 'lodash/isObject'; import 'lodash/isPlainObject'; import 'lodash/isRegExp'; import 'lodash/isString'; import 'lodash/isUndefined'; import 'lodash/merge'; import 'lodash/set'; import 'lodash/toInteger'; import 'lodash/toNumber'; import 'lodash/trimEnd'; import 'lodash/uniq'; import 'lodash/debounce'; import 'lodash/throttle'; import './chunk-6c10537c.js'; import '@material-ui/core/FormControl'; import '@material-ui/core/FormHelperText'; import '@material-ui/core/FormLabel'; import '@material-ui/core/TextField'; import '@material-ui/core/InputAdornment'; import { a as DataType } from './chunk-68362596.js'; import '@material-ui/core/Tooltip'; import { c as checkIsDataComponent, d as IconButton, e as SchemaManager, b as Item } from './chunk-cbe9c61d.js'; import '@material-ui/core/styles'; import 'classnames'; import '@material-ui/core/Icon'; import '@material-ui/core/SvgIcon'; import './chunk-9f5de191.js'; import './chunk-3774fd4c.js'; import 'date-fns'; import 'events'; import '@material-ui/core/Typography'; import { a as Text } from './chunk-4358fb9c.js'; import '@material-ui/core/Grid'; import '@material-ui/core/IconButton'; import { d as check, e as close, f as plus, g as pencil, h as del } from './chunk-dab541a3.js'; import VsPanelWithLabel from './chunk-5fd404e9.js'; import Paper from '@material-ui/core/Paper'; import Checkbox from '@material-ui/core/Checkbox'; import Divider from '@material-ui/core/Divider'; import Table from '@material-ui/core/Table'; import TableBody from '@material-ui/core/TableBody'; import TableCell from '@material-ui/core/TableCell'; import TableHead from '@material-ui/core/TableHead'; import TablePagination from '@material-ui/core/TablePagination'; import TableRow from '@material-ui/core/TableRow'; import TableSortLabel from '@material-ui/core/TableSortLabel'; import Toolbar from '@material-ui/core/Toolbar'; import { a as form } from './chunk-7293e165.js'; var SortDirection; (function (SortDirection) { SortDirection["asc"] = "asc"; SortDirection["desc"] = "desc"; })(SortDirection || (SortDirection = {})); class SubSchemaArray extends Component { constructor(props) { super(props); this.insertMode = false; this.oldData = {}; this.dataComponents = []; this.Body = () => { const sortedData = this.sortedData(); return (sortedData.slice(this.state.page * this.state.rowsPerPage, this.state.page * this.state.rowsPerPage + this.state.rowsPerPage).map((rec) => { const id = rec[this.props.schemaManager.getSubschemaKeyField(this.props.comp, true)]; return (createElement(Fragment, { key: id }, createElement(TableRow, { hover: true, onClick: this.handleSelectClick(id), onDoubleClick: this.handleSelectDoubleClick(id), selected: this.isSelected(id) }, createElement(TableCell, { style: this.applyCellStyle(true) }, createElement(Checkbox, { checked: this.isSelected(id) })), this.state.columnSettings.map(c => { const cd = checkIsDataComponent(this.props.schema.components[c.compId]); if (cd) { let val; try { val = rec[cd.data.field].toString(); } catch (error) { val = ''; } return (createElement(TableCell, { key: c.compId, component: "th", align: get(cd, 'data.dataType') === DataType.number ? 'right' : 'left', style: this.applyCellStyle(false, c) }, val)); } })), this.ErrorRow(id))); })); }; this.getDefaultColumnSettings = () => { let columnSettings = this.props.comp.columnSettings; if (!columnSettings || columnSettings.length === 0) { columnSettings = this.dataComponents.map(c => ({ compId: c.node, alignRight: c.data.dataType === DataType.number, autowidth: true, sortable: true, widthUnit: 'px' })); } return columnSettings; }; this.addRecord = () => { const data = this.props.schemaManager.insertSubschemaArrayRecord(this.props.comp, this.dataComponents); this.setData(data); if (data.length > 0) { this.setState({ selected: [data[data.length - 1][this.props.schemaManager.getSubschemaKeyField(this.props.comp, true)]] }); this.insertMode = true; this.setState({ showForm: true }); } }; this.editRecord = () => { this.insertMode = false; this.oldData = cloneDeep(this.state.data); this.setState({ showForm: true }); }; this.deleteRecords = () => { if (this.state.selected.length > 0) { const data = this.state.data.filter((r) => this.state.selected.indexOf(r[this.props.schemaManager.getSubschemaKeyField(this.props.comp, true)]) === -1); this.setData(data); this.setState({ selected: [] }); } }; this.cancelEditing = () => { if (this.insertMode) { this.deleteRecords(); } else { this.setData(this.oldData); } this.setState({ showForm: false }); }; this.setData = (data) => { this.props.schemaManager.updateSchemaValue(this.props.comp, data); this.setState({ data }); }; this.updateValue = () => { this.props.schemaManager.updateSchemaValue(this.props.comp, this.state.data); const errors = this.props.schemaManager.getValueErrorsComp(this.props.comp, this.props.arrayId); this.setState({ errors }); return errors.length === 0; }; this.showTable = () => { this.updateValue(); this.setState({ showForm: false }); }; this.isSelected = (id) => this.state.selected.indexOf(id) !== -1; this.handleSelectClick = (id) => () => { const { selected } = this.state; const selectedIndex = selected.indexOf(id); let newSelected = []; if (selectedIndex === -1) { newSelected = newSelected.concat(selected, id); } else { newSelected = selected.filter(i => i !== id); } this.setState({ selected: newSelected }); }; this.handleSelectDoubleClick = (index) => () => { this.setState({ selected: [index] }, () => this.editRecord()); }; this.handleSelectAllClick = (_event, checked) => { if (checked) { this.setState({ selected: this.state.data.map((r) => r[this.props.schemaManager.getSubschemaKeyField(this.props.comp, true)]) }); } else { this.setState({ selected: [] }); } }; this.handleChangePage = (_event, page) => { this.setState({ page }); }; this.handleChangeRowsPerPage = (event) => { this.setState({ rowsPerPage: event.target.value }); }; this.updateSort = (comp) => () => { let orderBy = comp; let order = SortDirection.asc; if (this.state.orderBy === comp) { if (this.state.order === SortDirection.asc) { order = SortDirection.desc; } else { order = SortDirection.asc; orderBy = null; } } this.setState({ order, orderBy }); }; this.sortedData = () => { if (this.state.orderBy) { const comp = this.state.orderBy; let dataType = DataType.string; const cd = checkIsDataComponent(comp); if (cd) { dataType = get(cd, 'data.dataType'); const field = cd.data.field; const sortFn = this.state.order === SortDirection.desc ? dataType === DataType.number ? (a, b) => (b[field] - a[field]) : (a, b) => (a[field] > b[field] ? -1 : a[field] < b[field] ? 1 : 0) : dataType === DataType.number ? (a, b) => (a[field] - b[field]) : (a, b) => (a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0); return this.state.data.map(r => r).sort(sortFn); } else { return []; } } else { return this.state.data; } }; this.applyCellStyle = (selectionCell, setting) => { if (selectionCell) { return { width: '30px' }; } else { if (setting) { if (!setting.autowidth && setting.width && setting.widthUnit) { return { width: setting.width.toString() + setting.widthUnit }; } } } return {}; }; this.Toolbar = () => (createElement(Toolbar, null, this.props.comp.label && createElement(Text, { variant: "h6", text: this.props.comp.label }), this.state.showForm ? this.ToolbarForm() : this.ToolbarTable())); this.ToolbarForm = () => (createElement(Fragment, null, createElement(Divider, { variant: "inset" }), createElement(IconButton, { svg: check, onClick: this.showTable }), createElement(IconButton, { svg: close, onClick: this.cancelEditing }))); this.ToolbarTable = () => (createElement(Fragment, null, !this.props.designMode && createElement(IconButton, { svg: plus, onClick: this.addRecord }), !this.props.designMode && this.numSelected === 1 && createElement(IconButton, { svg: pencil, onClick: this.editRecord }), !this.props.designMode && this.numSelected > 0 && createElement(IconButton, { svg: del, style: { color: 'red' }, onClick: this.deleteRecords }), !this.props.designMode && this.numSelected > 0 && createElement(Text, { variant: "caption", text: this.numSelected === 1 ? this.numSelected.toString() + form.recordSelected : this.numSelected.toString() + form.recordsSelected }))); this.Head = () => (createElement(TableHead, null, createElement(TableRow, null, createElement(TableCell, { style: this.applyCellStyle(true) }, this.state.data.length > 0 ? createElement(Checkbox, { indeterminate: this.numSelected > 0 && this.numSelected < this.state.data.length, checked: this.numSelected > 0 && this.numSelected === this.state.data.length, onChange: this.handleSelectAllClick }) : null), this.state.columnSettings.map(c => { const comp = this.props.schema.components[c.compId]; if (comp) { return (createElement(TableCell, { key: c.compId, align: c.alignRight ? 'right' : 'left', style: this.applyCellStyle(false, c) }, c.sortable ? createElement(TableSortLabel, { active: comp === this.state.orderBy, direction: this.state.order, onClick: this.updateSort(comp) }, createElement(Text, { text: comp.label })) : createElement(Text, { text: comp.label }))); } })))); this.Pagination = () => { const comp = this.props.comp; if (comp.hidePagination) { return null; } return (createElement(TablePagination, { component: "div", count: this.state.data.length, rowsPerPage: this.state.rowsPerPage, page: this.state.page, onChangePage: this.handleChangePage, onChangeRowsPerPage: this.handleChangeRowsPerPage })); }; this.EmptyRows = () => { const emptyRows = this.state.rowsPerPage - Math.min(this.state.rowsPerPage, this.state.data.length - this.state.page * this.state.rowsPerPage); if (emptyRows) { return (createElement(TableRow, { style: { height: 49 * emptyRows } }, createElement(TableCell, { colSpan: this.state.columnSettings.length + 1 }))); } else { return null; } }; this.ErrorRow = (arrayId) => { let length = 1; const cs = this.props.comp.columnSettings; if (cs) { length = cs.length + 1; } const errs = this.state.errors.filter(e => e.arrayId === arrayId); if (errs.length > 0) { return (createElement(TableRow, null, createElement(TableCell, { colSpan: length }, createElement(Text, { text: errs.map(e => e.error).join('\n'), color: "error", variant: "caption" })))); } else { return null; } }; this.dataComponents = SchemaManager.getDataComponents(this.props.schema); const comp = this.props.comp; const data = this.props.schemaManager.initSubschemaArrayRecords(this.props.comp); this.state = { columnSettings: this.getDefaultColumnSettings(), showForm: false, order: SortDirection.asc, orderBy: null, selected: [], data, page: 0, rowsPerPage: comp.rowsPerPage || 5, errors: this.props.schemaManager.validateValueComp(this.props.comp, data), }; } render() { const { classes, ...other } = this.props; return (createElement(Paper, { style: { width: '100%', overflowX: 'auto' } }, this.Toolbar(), this.state.showForm ? createElement(Item, Object.assign({}, other, { schema: this.props.schema, node: "root", comp: this.props.schema.components.root, arrayId: this.state.selected[0] })) : createElement(Fragment, null, createElement(Table, null, this.Head(), createElement(TableBody, null, this.Body(), this.EmptyRows())), this.Pagination()))); } get numSelected() { return this.state.selected.length; } } const getComponent = (props) => { const comp = props.comp; const { classes, ...other } = props; if (comp.data.dataType === DataType.object) { return (createElement(VsPanelWithLabel, Object.assign({}, other), createElement(Item, Object.assign({}, other, { schema: comp.schema, node: "root", comp: comp.schema.components.root })))); } else { return (createElement(SubSchemaArray, Object.assign({}, other, { schema: comp.schema }))); } }; const SubSchema = props => { return getComponent(props); }; export default SubSchema;