@vs-form/vs-form
Version:
A schema-based form generator component for React using material-ui
341 lines (337 loc) • 16.1 kB
JavaScript
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;