UNPKG

@croz/nrich-registry-mui

Version:

Contains the UI implementation of registry for the MUI component library

511 lines (505 loc) 18.4 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/component/RegistryEntity.tsx import React4 from "react"; import { Backdrop, Box as Box2, Button as Button2, CircularProgress, Modal, Paper as Paper3 } from "@mui/material"; import { RegistryEntityContextProvider, useRegistryEntityAdministration } from "@croz/nrich-registry-core"; // src/component/RegistryFilter.tsx import React from "react"; import SearchIcon from "@mui/icons-material/Search"; import { FormControl, InputAdornment, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material"; import { useDebouncedUpdateEffect, useRegistryFilter } from "@croz/nrich-registry-core"; var RegistryFilter = ({ onFilterUpdate }) => { const { availableFields, searchParameter, handleFieldsChange, handleQueryChange } = useRegistryFilter(); useDebouncedUpdateEffect(() => { onFilterUpdate(searchParameter); }, 300, [searchParameter]); return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(FormControl, { sx: { m: 1, width: 300 }, size: "small" }, /* @__PURE__ */ React.createElement(InputLabel, { htmlFor: "search-query" }, "Search..."), /* @__PURE__ */ React.createElement(OutlinedInput, { id: "search-query", value: searchParameter.query, onChange: handleQueryChange, label: "Search...", startAdornment: /* @__PURE__ */ React.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React.createElement(SearchIcon, null)) })), /* @__PURE__ */ React.createElement(FormControl, { sx: { m: 1, width: 300 }, size: "small" }, /* @__PURE__ */ React.createElement(InputLabel, { id: "demo-multiple-name-label" }, "Properties"), /* @__PURE__ */ React.createElement(Select, { labelId: "demo-multiple-name-label", id: "demo-multiple-name", multiple: true, label: "Properties", value: searchParameter.propertyNameList, onChange: (event) => handleFieldsChange(event), input: /* @__PURE__ */ React.createElement(OutlinedInput, null) }, availableFields.map((field) => /* @__PURE__ */ React.createElement(MenuItem, { key: field.value, value: field.value }, field.label))))); }; // src/component/RegistryForm.tsx import React2 from "react"; import { Box, Button, FormControl as FormControl2, FormHelperText, InputLabel as InputLabel2, MenuItem as MenuItem2, OutlinedInput as OutlinedInput2, Paper, Select as Select2, TextField, Typography } from "@mui/material"; import { findIdField, formatIdName, useRegistryEntity, useRegistryForm } from "@croz/nrich-registry-core"; var SubEntityField = ({ configuration, value, onChange, error }) => { var _a; const { entityConfiguration, data } = useRegistryEntity(configuration.singularAssociationReferencedClass, { pageNumber: 0, pageSize: 1e3 }); const idField = findIdField(entityConfiguration); return /* @__PURE__ */ React2.createElement(FormControl2, { size: "small" }, /* @__PURE__ */ React2.createElement(InputLabel2, { id: `${configuration.name}-picker-label` }, configuration.formLabel), /* @__PURE__ */ React2.createElement(Select2, { labelId: `${configuration.name}-picker-label`, id: `${configuration.name}-picker`, label: configuration.formLabel, value: (_a = value == null ? void 0 : value[idField.name]) != null ? _a : "", onChange: (event) => onChange({ [idField.name]: event.target.value }), error: !!error, input: /* @__PURE__ */ React2.createElement(OutlinedInput2, null) }, ((data == null ? void 0 : data.content) || []).map((option) => /* @__PURE__ */ React2.createElement(MenuItem2, { key: option[idField.name], value: option[idField.name] }, formatIdName(entityConfiguration.classFullName, idField.name, option[idField.name])))), !!error && /* @__PURE__ */ React2.createElement(FormHelperText, null, error)); }; var Field = ({ configuration, value, onChange, error }) => { var _a; switch (configuration.javascriptType) { case "string": return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: value != null ? value : "", size: "small", onChange: (event) => onChange(event.target.value), disabled: !configuration.editable }); case "number": if (configuration.decimal) { return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: value != null ? value : "", size: "small", inputProps: { inputMode: "numeric", pattern: "[0-9.,]*" }, disabled: !configuration.editable, onChange: (event) => onChange(+event.target.value) }); } return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: value != null ? value : "", size: "small", inputProps: { inputMode: "numeric", pattern: "[0-9]*" }, disabled: !configuration.editable, onChange: (event) => onChange(+event.target.value) }); case "boolean": return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: value != null ? value : "", size: "small", onChange: (event) => onChange(event.target.value), disabled: !configuration.editable }); case "object": return /* @__PURE__ */ React2.createElement(SubEntityField, { configuration, value, onChange, error }); case "date": return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: (_a = value == null ? void 0 : value.split("T")[0]) != null ? _a : "", type: "date", size: "small", onChange: (event) => onChange(event.target.value), disabled: !configuration.editable, InputLabelProps: { shrink: true } }); default: return /* @__PURE__ */ React2.createElement(TextField, { error: !!error, helperText: error, label: configuration.formLabel, value: value != null ? value : null, size: "small", onChange: (event) => onChange(event.target.value), disabled: !configuration.editable }); } }; var paperStyle = { display: "flex", flexDirection: "column", p: 4, gap: 2 }; var RegistryForm = ({ initialValues, type, onSubmit, onClose }) => { const { entityConfiguration, yupSchema, finalInitialValues, properties } = useRegistryForm(initialValues, type); const [value, setValue] = React2.useState(finalInitialValues); const [errors, setErrors] = React2.useState({}); const clearError = (fieldName) => { setErrors((oldErrors) => __spreadProps(__spreadValues({}, oldErrors), { [fieldName]: void 0 })); }; const updateField = (fieldName, newValue) => { setValue((oldValue) => __spreadProps(__spreadValues({}, oldValue), { [fieldName]: newValue })); clearError(fieldName); }; const handleSubmit = () => __async(void 0, null, function* () { try { yield yupSchema.validate(value, { abortEarly: false }); onSubmit(value); } catch (e) { setErrors(e.inner.reduce((all, error) => __spreadProps(__spreadValues({}, all), { [error.path]: error.message }), {})); } }); return /* @__PURE__ */ React2.createElement(Paper, { sx: paperStyle }, /* @__PURE__ */ React2.createElement(Typography, { variant: "h5" }, type === "update" ? `Update ${entityConfiguration.name}` : `Create ${entityConfiguration.name}`), properties.map((field) => /* @__PURE__ */ React2.createElement(Field, { key: field.name, configuration: field, value: value[field.name], onChange: (newValue) => updateField(field.name, newValue), error: errors[field.name] })), /* @__PURE__ */ React2.createElement(Box, { sx: { alignSelf: "end" } }, /* @__PURE__ */ React2.createElement(Button, { variant: "outlined", onClick: onClose, sx: { mr: 2 } }, "Cancel"), /* @__PURE__ */ React2.createElement(Button, { variant: "contained", onClick: handleSubmit }, type === "update" ? "Update" : "Create"))); }; // src/component/RegistryTable.tsx import React3 from "react"; import DeleteIcon from "@mui/icons-material/Delete"; import EditIcon from "@mui/icons-material/Edit"; import { IconButton, Paper as Paper2, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow } from "@mui/material"; import TableSortLabel from "@mui/material/TableSortLabel"; import { findIdField as findIdField2, formatIdName as formatIdName2, resolveId, resolveValue, useRegistryEntityContext, useRegistrySort } from "@croz/nrich-registry-core"; var RegistryTableHeadCell = ({ property, sortPropertyList, onSortChange }) => { const { sortDirection, sortChangeHandler } = useRegistrySort(property, sortPropertyList, onSortChange); const muiSortDirection = sortDirection === void 0 ? false : sortDirection.toLowerCase(); return /* @__PURE__ */ React3.createElement(TableCell, { key: property.name, sortDirection: muiSortDirection }, /* @__PURE__ */ React3.createElement(TableSortLabel, { active: muiSortDirection !== false, direction: muiSortDirection !== false ? muiSortDirection : void 0, onClick: property.sortable ? () => sortChangeHandler() : () => { } }, property.columnHeader)); }; var PropertyCell = ({ propertyConfiguration, value, subEntityMap }) => { let stringValue = value; if (value === void 0 || value === null) { stringValue = "-"; } else if (propertyConfiguration.javascriptType === "object") { const configuration = subEntityMap[propertyConfiguration.singularAssociationReferencedClass]; const idField = findIdField2(configuration); stringValue = formatIdName2(configuration.classFullName, idField.name, value[idField.name]); } else if (propertyConfiguration.javascriptType === "date") { stringValue = new Date(value).toLocaleDateString(); } else if (propertyConfiguration.javascriptType === "number") { if (propertyConfiguration.decimal) { stringValue = Number(value).toFixed(2); } else { stringValue = value; } } else if (propertyConfiguration.javascriptType === "boolean") { stringValue = value ? "Yes" : "No"; } return /* @__PURE__ */ React3.createElement(TableCell, null, stringValue); }; var RegistryTableRow = ({ row, onEdit, onRemove }) => { const { entityConfiguration, singularAssociationsMap, finalProperties } = useRegistryEntityContext(); return /* @__PURE__ */ React3.createElement(TableRow, { sx: { "&:last-child td, &:last-child th": { border: 0 } } }, finalProperties.map((property) => /* @__PURE__ */ React3.createElement(PropertyCell, { key: property.name, propertyConfiguration: property, value: resolveValue(property, row), subEntityMap: singularAssociationsMap })), (entityConfiguration.updateable || entityConfiguration.deletable) && /* @__PURE__ */ React3.createElement(TableCell, null, entityConfiguration.updateable && /* @__PURE__ */ React3.createElement(IconButton, { onClick: () => onEdit(resolveId(entityConfiguration, row), row) }, /* @__PURE__ */ React3.createElement(EditIcon, null)), entityConfiguration.deletable && /* @__PURE__ */ React3.createElement(IconButton, { onClick: () => onRemove(resolveId(entityConfiguration, row)) }, /* @__PURE__ */ React3.createElement(DeleteIcon, null)))); }; var RegistryTable = ({ data, request, onRequestChange, onEdit, onRemove }) => { var _a; const { entityConfiguration, finalProperties } = useRegistryEntityContext(); const onPageChange = (event, newPage) => { onRequestChange(__spreadProps(__spreadValues({}, request), { pageNumber: newPage })); }; const onPageSizeChange = (event) => { onRequestChange(__spreadProps(__spreadValues({}, request), { pageSize: +event.target.value, pageNumber: 0 })); }; const onSortChange = (sortPropertyList) => { onRequestChange(__spreadProps(__spreadValues({}, request), { sortPropertyList })); }; return /* @__PURE__ */ React3.createElement(Paper2, null, /* @__PURE__ */ React3.createElement(TableContainer, null, /* @__PURE__ */ React3.createElement(Table, { sx: { minWidth: 650 }, size: "small" }, /* @__PURE__ */ React3.createElement(TableHead, null, /* @__PURE__ */ React3.createElement(TableRow, null, finalProperties.map((property) => { var _a2; return /* @__PURE__ */ React3.createElement(RegistryTableHeadCell, { key: property.name, property, sortPropertyList: (_a2 = request.sortPropertyList) != null ? _a2 : [], onSortChange }); }), (entityConfiguration.updateable || entityConfiguration.deletable) && /* @__PURE__ */ React3.createElement(TableCell, null))), /* @__PURE__ */ React3.createElement(TableBody, null, ((_a = data.content) != null ? _a : []).map((row, index) => /* @__PURE__ */ React3.createElement(RegistryTableRow, { key: index, row, onEdit, onRemove }))))), /* @__PURE__ */ React3.createElement(TablePagination, { rowsPerPageOptions: [5, 10, 25], component: "div", count: data.totalElements, rowsPerPage: request.pageSize, page: request.pageNumber, onPageChange, onRowsPerPageChange: onPageSizeChange })); }; // src/component/RegistryEntity.tsx var modalStyle = { position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: 600, bgcolor: "background.paper", boxShadow: 12 }; var RegistryEntity = ({ entityName }) => { const { entityConfiguration, data, request, handlePagingUpdate, handleFilterUpdate, handleAddClick, handleEditClick, handleSubmitClick, formType, formData, formModalOpen, closeFormModal, loading, remove } = useRegistryEntityAdministration(entityName); return /* @__PURE__ */ React4.createElement(RegistryEntityContextProvider, { entityConfiguration }, /* @__PURE__ */ React4.createElement(Paper3, { sx: { display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center" } }, /* @__PURE__ */ React4.createElement(RegistryFilter, { onFilterUpdate: handleFilterUpdate }), /* @__PURE__ */ React4.createElement("div", null, entityConfiguration.creatable && /* @__PURE__ */ React4.createElement(Button2, { variant: "contained", onClick: handleAddClick }, "Add"))), /* @__PURE__ */ React4.createElement(RegistryTable, { data, request, onRequestChange: handlePagingUpdate, onEdit: handleEditClick, onRemove: remove }), formModalOpen && /* @__PURE__ */ React4.createElement(Modal, { open: formModalOpen, onClose: (_, reason) => reason !== "backdropClick" && closeFormModal() }, /* @__PURE__ */ React4.createElement(Box2, { sx: modalStyle }, /* @__PURE__ */ React4.createElement(RegistryForm, { type: formType, initialValues: formData, onClose: closeFormModal, onSubmit: handleSubmitClick }))), loading && /* @__PURE__ */ React4.createElement(Backdrop, { sx: { color: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }, open: true }, /* @__PURE__ */ React4.createElement(CircularProgress, { color: "inherit" }))); }; // src/component/RegistryEntityPicker.tsx import React5 from "react"; import { FormControl as FormControl3, InputLabel as InputLabel3, MenuItem as MenuItem3, OutlinedInput as OutlinedInput3, Select as Select3 } from "@mui/material"; import { useRegistryConfigurationStore } from "@croz/nrich-registry-core"; var RegistryEntityPicker = ({ value, setValue }) => { const entityConfigurations = useRegistryConfigurationStore((state) => state.groupConfigurations.flatMap((groupConfiguration) => groupConfiguration.entityConfigurationList)); return /* @__PURE__ */ React5.createElement(FormControl3, { sx: { m: 1, width: 300 }, size: "small" }, /* @__PURE__ */ React5.createElement(InputLabel3, { id: "registry-entity-picker-label" }, "Entity"), /* @__PURE__ */ React5.createElement(Select3, { labelId: "registry-entity-picker-label", id: "registry-entity-picker", label: "Entity", value, onChange: (event) => setValue(event.target.value), input: /* @__PURE__ */ React5.createElement(OutlinedInput3, null) }, entityConfigurations.map((entity) => /* @__PURE__ */ React5.createElement(MenuItem3, { key: entity.name, value: entity.name }, entity.name)))); }; export { RegistryEntity, RegistryEntityPicker, RegistryFilter, RegistryForm, RegistryTable }; //# sourceMappingURL=index.mjs.map