@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
142 lines (141 loc) • 7.41 kB
JavaScript
import * as React from 'react';
import { Box, Flex } from 'rebass';
import FormLayout, { FormRow } from '../FormLayout';
import Input from '../Input';
import SimpleButton from '../SimpleButton';
import AdaptableInput from '../../View/Components/AdaptableInput';
import { useMemo } from 'react';
import { useAdaptable } from '../../View/AdaptableContext';
import { Select } from '../Select';
export function AdaptableFormComponentButtons({ formDef, onClick, defaultTone, disabledButtons, api, context, focusFirstButton = true, }) {
return (React.createElement(React.Fragment, null, formDef.buttons.map((button, index) => {
const buttonIcon = api.internalApi.getIconForButton(button, context, {
height: 15,
width: 15,
});
let buttonStyle = api.internalApi.getStyleForButton(button, context
? context
: {
...api.internalApi.buildBaseContext(),
});
let buttonLabel = api.internalApi.getLabelForButton(button, context
? context
: {
...api.internalApi.buildBaseContext(),
});
let buttonTooltip = api.internalApi.getTooltipForButton(button, context
? context
: {
...api.internalApi.buildBaseContext(),
});
return (React.createElement(SimpleButton, { autoFocus: focusFirstButton && index === 0, disabled: disabledButtons[index], key: index, tooltip: buttonTooltip, icon: buttonIcon, tone: buttonStyle?.tone ?? defaultTone, variant: buttonStyle?.variant, "data-text": buttonLabel, className: buttonStyle?.className, marginLeft: index ? 2 : 0, onClick: () => {
onClick(button);
} }, buttonLabel));
})));
}
export function AdaptableFormComponent({ formDef, data, onChange, onButtonClick, displayTitle, api, context, focusFirstButton, }) {
const getFieldValue = (key) => data[key];
const setFieldValue = (key, value) => {
const newData = { ...data, [key]: value };
onChange(newData);
};
const adaptable = useAdaptable();
const disabledButtons = useMemo(() => formDef.buttons?.map((button) => {
// defensive programming: conventionally context should ALWAYS be present for validating buttons
const isValid = !!button.disabled && !!context ? !button.disabled(button, context) : true;
return !isValid;
}) ?? [], [data]);
const renderLabel = (field) => {
return (React.createElement(Box, { className: 'ab-FormLayout_column--label', style: { textAlign: 'end' } }, field.label));
};
const renderField = (field) => {
const value = getFieldValue(field.name) ?? '';
const onChange = (event) => {
if (field.fieldType === 'number') {
const numberValue = Number(event.target.value);
if (isNaN(numberValue)) {
setFieldValue(field.name, null);
}
else {
setFieldValue(field.name, numberValue);
}
}
else {
setFieldValue(field.name, event.target.value);
}
};
switch (field.fieldType) {
case 'text':
case 'number':
case 'date':
return (React.createElement(AdaptableInput, { type: field.fieldType, style: { width: '100%' }, name: field.name, value: value, onChange: onChange }));
case 'select':
let items = field.options.map((item) => ({
value: item.value,
label: item.label,
onClick: () => setFieldValue(field.name, item.value),
}));
return (React.createElement(Select, { style: { width: '100%' }, className: `ab-options__select`, options: items, onChange: (newValue) => setFieldValue(field.name, newValue), value: value }));
case 'checkbox':
return (React.createElement(Input, { type: "checkbox", name: field.name, checked: value, onChange: (event) => {
setFieldValue(field.name, event.target.checked);
} }));
case 'textOutput':
return (React.createElement(Box, { paddingLeft: 2, style: { textAlign: 'left' } }, value));
default:
return React.createElement("div", null,
"Unknown field type: ",
field.fieldType);
}
};
// by default we have 2 columns: label & input
const columns = formDef.config?.columns ?? [1, 2];
return (React.createElement(React.Fragment, null,
displayTitle && formDef.title && (React.createElement(Box, { "data-name": "form-title", fontSize: 5, mb: 2, style: { fontWeight: 'bold' } }, formDef.title)),
formDef.description && (React.createElement(Box, { "data-name": "form-description", mb: 3 }, formDef.description)),
React.createElement(FormLayout, { onKeyDown: (event) => {
const target = event.target;
const targetName = target.name;
const field = formDef.fields
.map((field) => {
if (Array.isArray(field)) {
return field.filter((f) => f.name === targetName)[0];
}
else {
return field.name === targetName ? field : null;
}
})
.filter(Boolean)[0];
if (field && field.fieldType === 'number') {
// for number fields
// hook them up to the CellEditorKeyDown event
// so Shortcuts work as expected
const value = event.target.value;
adaptable._emit('CellEditorKeyDown', {
keyDownEvent: event,
cellValue: value,
columnId: field.name,
updateValueCallback: (updatedValue) => {
setFieldValue(field.name, updatedValue);
},
});
}
}, "data-name": "form-content", columns: columns, style: { overflow: 'auto' }, paddingRight: 1 }, formDef.fields?.map((field, index) => {
if (Array.isArray(field)) {
const rowFields = {};
field.map((fieldItem, index) => {
const rowFieldIndex = 2 * index + 1;
rowFields[rowFieldIndex] = renderLabel(fieldItem);
rowFields[rowFieldIndex + 1] = renderField(fieldItem);
});
return React.createElement(FormRow, { key: index, ...rowFields });
}
else {
return (React.createElement(FormRow, { key: field.name },
renderLabel(field),
renderField(field)));
}
})),
formDef.buttons ? (React.createElement(Flex, { "data-name": "form-buttons", marginTop: 3, flexDirection: "row", alignItems: "center", justifyContent: "center" },
React.createElement(AdaptableFormComponentButtons, { focusFirstButton: focusFirstButton, onClick: onButtonClick, disabledButtons: disabledButtons, defaultTone: "success", formDef: formDef, api: api, context: context }))) : null));
}