@tomino/dynamic-form-semantic-ui
Version:
Semantic UI form renderer based on dynamic form generation
196 lines • 9.38 kB
JavaScript
import * as React from 'react';
import { observer } from 'mobx-react';
import { Button, Table } from 'semantic-ui-react';
import { buildDataSet } from '@tomino/dynamic-form';
import { ErrorView } from './error_view';
import { css, toJS, prop } from '../common';
import { getValue, getPropValue, simpleHandle, valueSource } from '../helpers';
import { Context } from '../context';
import { DynamicComponent } from '../wrapper';
export function createDataset(items, parent) {
let schema = {
type: 'object',
properties: {}
};
for (let column of items) {
schema.properties[column.source] = {
type: column.type || 'string'
};
}
return buildDataSet(schema, toJS(parent));
}
export const tableAddButton = css `
margin-top: 12px !important;
`;
function hasControl(template, i) {
return template && template.elements && template.elements.length > i && template.elements[i];
}
const tableProps = [
'attached',
'basic',
'inverted',
'celled',
'collapsing',
'compact',
'padded',
'fixed',
'selectable',
'singleLine',
'sortable',
'stackable',
'striped',
'structured',
'textAlign',
'verticalAlign'
];
const TableComponent = props => {
const [editingRow, editRow] = React.useState(-1);
const context = React.useContext(Context);
const controlProps = props.formElement.props || {};
const { formElement, owner } = controlProps.onCreate
? simpleHandle(props, controlProps.onCreate, context)
: { formElement: props.formElement, owner: props.owner };
const readOnly = props.readOnly;
const list = controlProps.propSource
? props.dataProps[controlProps.propSource]
: getValue(props, context) || [];
const { items, allowAdd, allowDelete, allowEdit, customView } = formElement.props || {};
const edit = React.useCallback((e) => {
editRow(parseInt(e.currentTarget.getAttribute('data-index')));
}, []);
const source = prop(props.formElement);
const viewTemplate = formElement.elements && formElement.elements.length > 0 && formElement.elements[0];
const editTemplate = formElement.elements && formElement.elements.length > 1 && formElement.elements[1];
const addTemplate = formElement.elements && formElement.elements.length > 2 && formElement.elements[2];
let filteredItems = (items || []).filter(i => i && i.title && i.type && i.source);
const addDataset = React.useMemo(() => {
return createDataset(filteredItems, owner);
}, [items]);
const addRow = React.useCallback(() => {
const data = toJS(addDataset);
if (formElement.props.onAdd) {
simpleHandle(props, formElement.props.onAdd, context, { data });
}
else if (data.__item) {
owner.addRow(source, data.__item);
}
else {
owner.addRow(source, data);
}
}, [addDataset, context, formElement.props.onAdd, owner, props, source]);
let rowDataset = editingRow >= 0 ? createDataset(items, list[editingRow]) : null;
const cancelEdit = React.useCallback(() => {
editRow(-1);
}, []);
const editRowHandler = React.useCallback(() => {
const data = toJS(rowDataset);
if (formElement.props.onSave) {
simpleHandle(props, formElement.props.onSave, context, { data });
}
else if (owner && owner.replaceRow) {
const source = valueSource(props.formElement);
owner.replaceRow(source, editingRow, data);
}
else {
alert('You need to define an on save handler');
}
editRow(-1);
}, [context, editingRow, formElement.props.onSave, owner, props, rowDataset]);
const deleteRow = React.useCallback((e) => {
if (formElement.props.onDelete) {
simpleHandle(props, formElement.props.onDelete, context, {
index: parseInt(e.currentTarget.getAttribute('data-index')),
data: list
});
}
else {
owner.removeRowIndex(source, parseInt(e.currentTarget.getAttribute('data-index')));
}
}, [context, formElement.props.onDelete, list, owner, props, source]);
if (!filteredItems || !filteredItems.length) {
return React.createElement("div", null, "You need to define table columns");
}
let simpleArray = filteredItems.length === 1 && filteredItems[0].source === '__item';
if (!list) {
return React.createElement("div", null, "Collection contains no items ...");
}
return (React.createElement(DynamicComponent, Object.assign({ control: Table, controlProps: tableProps }, props),
React.createElement(Table.Header, null,
React.createElement(Table.Row, null,
filteredItems.map((m, i) => (React.createElement(Table.HeaderCell, { key: m.title + i }, m.title))),
!readOnly && (allowEdit || allowDelete || allowAdd) ? React.createElement(Table.HeaderCell, null) : null)),
React.createElement(Table.Body, null,
list.map((row, i) => (React.createElement(Table.Row, { key: i },
editingRow === i
? filteredItems.map((e, i) => {
if (simpleArray) {
const r = row;
row = {
setValue(_s, value) {
owner.replaceRow(source, i, value);
},
getValue() {
return r;
},
getSchema() {
return owner.getSchema().items;
},
isRequired() {
return false;
}
};
}
else {
row = rowDataset;
}
return (React.createElement(Table.Cell, { key: i }, props.catalogue.createComponent({ ...props, owner: row, dataProps: owner }, hasControl(editTemplate, i)
? editTemplate.elements[i]
: {
control: 'Input',
props: { value: { source: e.source } }
}, context)));
})
: filteredItems.map((m, j) => {
const value = m.source === '__item' ? row : row[m.source];
return (React.createElement(Table.Cell, { key: m.title + j }, customView && hasControl(viewTemplate, j)
? props.catalogue.createComponent({
...props,
owner: row,
dataProps: owner
}, viewTemplate.elements[j], context)
: value && typeof value == 'object'
? '[object]'
: value));
}),
!readOnly && (allowEdit || allowDelete || allowAdd) ? (React.createElement(Table.Cell, { collapsing: true },
allowEdit && editingRow === i && (React.createElement(React.Fragment, null,
React.createElement(Button, { icon: "close", color: "orange", "data-index": i, onClick: cancelEdit }),
React.createElement(Button, { icon: "check", color: "green", "data-index": i, onClick: editRowHandler }))),
allowEdit && editingRow !== i && (React.createElement(Button, { icon: "edit", color: "blue", "data-index": i, onClick: edit })),
allowDelete && editingRow !== i && (React.createElement(Button, { icon: "trash", color: "red", "data-index": i, onClick: deleteRow })))) : null))),
!readOnly && allowAdd ? (React.createElement(Table.Row, null,
filteredItems.map((m, i) => (React.createElement(Table.Cell, { key: m.title + i }, props.catalogue.createComponent({ ...props, owner: addDataset, dataProps: owner }, hasControl(addTemplate, i)
? addTemplate.elements[i]
: {
control: 'Input',
props: {
value: { source: m.source },
placeholder: m.title
}
}, context)))),
React.createElement(Table.Cell, null,
React.createElement(Button, { icon: "plus", color: "blue", onClick: addRow })))) : null),
React.createElement(ErrorView, { owner: props.owner, source: prop(formElement), pointing: "left" })));
};
export const TableView = {
Component: observer(TableComponent),
toString: (_owner, props, context) => {
const tableList = getValue(props, context);
return tableList
.map((_, i) => `[${i + 1}] ${props.formElement.elements
.map(e => `${getPropValue(props, e, context, 'label')}: ${getPropValue(props, e, context)}`)
.join('\n ')}`)
.join('\n\n');
}
};
//# sourceMappingURL=table_view.js.map