UNPKG

@premieroctet/next-admin

Version:

Next-Admin provides a customizable and turnkey admin dashboard for applications built with Next.js and powered by the Prisma ORM. It aims to simplify the development process by providing a turnkey admin system that can be easily integrated into your proje

554 lines (553 loc) 31.5 kB
"use client"; "use strict"; var __webpack_modules__ = { "./inputs/RichText/RichTextField": function(module) { module.exports = import("./inputs/RichText/RichTextField.js").then(function(module) { return module; }); } }; var __webpack_module_cache__ = {}; function __webpack_require__(moduleId) { var cachedModule = __webpack_module_cache__[moduleId]; if (void 0 !== cachedModule) return cachedModule.exports; var module = __webpack_module_cache__[moduleId] = { exports: {} }; __webpack_modules__[moduleId](module, module.exports, __webpack_require__); return module.exports; } (()=>{ __webpack_require__.n = (module)=>{ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module; __webpack_require__.d(getter, { a: getter }); return getter; }; })(); (()=>{ __webpack_require__.d = (exports1, definition)=>{ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, { enumerable: true, get: definition[key] }); }; })(); (()=>{ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); })(); (()=>{ __webpack_require__.r = (exports1)=>{ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, { value: 'Module' }); Object.defineProperty(exports1, '__esModule', { value: true }); }; })(); var __webpack_exports__ = {}; (()=>{ __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { default: ()=>components_Form }); const jsx_runtime_namespaceObject = require("react/jsx-runtime"); const outline_namespaceObject = require("@heroicons/react/24/outline"); const core_namespaceObject = require("@rjsf/core"); var core_default = /*#__PURE__*/ __webpack_require__.n(core_namespaceObject); const validator_ajv8_namespaceObject = require("@rjsf/validator-ajv8"); var validator_ajv8_default = /*#__PURE__*/ __webpack_require__.n(validator_ajv8_namespaceObject); const external_clsx_namespaceObject = require("clsx"); var external_clsx_default = /*#__PURE__*/ __webpack_require__.n(external_clsx_namespaceObject); const external_react_namespaceObject = require("react"); var external_react_default = /*#__PURE__*/ __webpack_require__.n(external_react_namespaceObject); const external_tailwind_merge_namespaceObject = require("tailwind-merge"); const ClientActionDialogContext_js_namespaceObject = require("../context/ClientActionDialogContext.js"); var ClientActionDialogContext_js_default = /*#__PURE__*/ __webpack_require__.n(ClientActionDialogContext_js_namespaceObject); const ConfigContext_js_namespaceObject = require("../context/ConfigContext.js"); const FormDataContext_js_namespaceObject = require("../context/FormDataContext.js"); var FormDataContext_js_default = /*#__PURE__*/ __webpack_require__.n(FormDataContext_js_namespaceObject); const FormStateContext_js_namespaceObject = require("../context/FormStateContext.js"); var FormStateContext_js_default = /*#__PURE__*/ __webpack_require__.n(FormStateContext_js_namespaceObject); const I18nContext_js_namespaceObject = require("../context/I18nContext.js"); const MessageContext_js_namespaceObject = require("../context/MessageContext.js"); const useDeleteAction_js_namespaceObject = require("../hooks/useDeleteAction.js"); const useRouterInternal_js_namespaceObject = require("../hooks/useRouterInternal.js"); const external_types_js_namespaceObject = require("../types.js"); const jsonSchema_js_namespaceObject = require("../utils/jsonSchema.js"); const tools_js_namespaceObject = require("../utils/tools.js"); const external_FormHeader_js_namespaceObject = require("./FormHeader.js"); var external_FormHeader_js_default = /*#__PURE__*/ __webpack_require__.n(external_FormHeader_js_namespaceObject); const ArrayField_js_namespaceObject = require("./inputs/ArrayField.js"); var ArrayField_js_default = /*#__PURE__*/ __webpack_require__.n(ArrayField_js_namespaceObject); const BaseInput_js_namespaceObject = require("./inputs/BaseInput.js"); var BaseInput_js_default = /*#__PURE__*/ __webpack_require__.n(BaseInput_js_namespaceObject); const CheckboxWidget_js_namespaceObject = require("./inputs/CheckboxWidget.js"); var CheckboxWidget_js_default = /*#__PURE__*/ __webpack_require__.n(CheckboxWidget_js_namespaceObject); const DateTimeWidget_js_namespaceObject = require("./inputs/DateTimeWidget.js"); var DateTimeWidget_js_default = /*#__PURE__*/ __webpack_require__.n(DateTimeWidget_js_namespaceObject); const DateWidget_js_namespaceObject = require("./inputs/DateWidget.js"); var DateWidget_js_default = /*#__PURE__*/ __webpack_require__.n(DateWidget_js_namespaceObject); const FileWidget_js_namespaceObject = require("./inputs/FileWidget/FileWidget.js"); var FileWidget_js_default = /*#__PURE__*/ __webpack_require__.n(FileWidget_js_namespaceObject); const JsonField_js_namespaceObject = require("./inputs/JsonField.js"); var JsonField_js_default = /*#__PURE__*/ __webpack_require__.n(JsonField_js_namespaceObject); const NullField_js_namespaceObject = require("./inputs/NullField.js"); var NullField_js_default = /*#__PURE__*/ __webpack_require__.n(NullField_js_namespaceObject); const SelectWidget_js_namespaceObject = require("./inputs/SelectWidget.js"); var SelectWidget_js_default = /*#__PURE__*/ __webpack_require__.n(SelectWidget_js_namespaceObject); const TextareaWidget_js_namespaceObject = require("./inputs/TextareaWidget.js"); var TextareaWidget_js_default = /*#__PURE__*/ __webpack_require__.n(TextareaWidget_js_namespaceObject); const external_Message_js_namespaceObject = require("./Message.js"); const Button_js_namespaceObject = require("./radix/Button.js"); var Button_js_default = /*#__PURE__*/ __webpack_require__.n(Button_js_namespaceObject); const Tooltip_js_namespaceObject = require("./radix/Tooltip.js"); const rjsf_js_namespaceObject = require("../utils/rjsf.js"); const RichTextField = /*#__PURE__*/ (0, external_react_namespaceObject.lazy)(()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./inputs/RichText/RichTextField"))); const widgets = { DateWidget: DateWidget_js_default(), DateTimeWidget: DateTimeWidget_js_default(), SelectWidget: SelectWidget_js_default(), CheckboxWidget: CheckboxWidget_js_default(), FileWidget: FileWidget_js_default(), TextareaWidget: TextareaWidget_js_default() }; const Form = ({ data, schema, resource, validation: validationProp, customInputs })=>{ const [validation, setValidation] = (0, external_react_namespaceObject.useState)(validationProp); const { basePath, options, apiBasePath } = (0, ConfigContext_js_namespaceObject.useConfig)(); const modelOptions = options?.model?.[resource]; const canDelete = !modelOptions?.permissions || modelOptions?.permissions?.includes(external_types_js_namespaceObject.Permission.DELETE); const canEdit = !modelOptions?.permissions || modelOptions?.permissions?.includes(external_types_js_namespaceObject.Permission.EDIT); const canCreate = !modelOptions?.permissions || modelOptions?.permissions?.includes(external_types_js_namespaceObject.Permission.CREATE); const { edit, id, ...schemas } = (0, jsonSchema_js_namespaceObject.getSchemas)(data, schema, modelOptions?.edit?.fields); const { router } = (0, useRouterInternal_js_namespaceObject.useRouterInternal)(); const { t } = (0, I18nContext_js_namespaceObject.useI18n)(); const formRef = (0, external_react_namespaceObject.useRef)(null); const [isPending, setIsPending] = (0, external_react_namespaceObject.useState)(false); const allDisabled = edit && !canEdit; const { runSingleDeletion } = (0, useDeleteAction_js_namespaceObject.useDeleteAction)(resource); const { showMessage } = (0, MessageContext_js_namespaceObject.useMessage)(); const { cleanAll } = (0, FormStateContext_js_namespaceObject.useFormState)(); const { setFormData } = (0, FormDataContext_js_namespaceObject.useFormData)(); (0, external_react_namespaceObject.useEffect)(()=>{ if (!edit && !canCreate) router.replace({ pathname: "/" }); }, [ canCreate, edit, router ]); const submitButton = (0, external_react_namespaceObject.useMemo)(()=>(props)=>{ const { uiSchema } = props; const { norender, props: buttonProps } = (0, rjsf_js_namespaceObject.getSubmitButtonOptions)(uiSchema); if (norender) return null; return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", { className: "align-center mt-4 flex flex-wrap justify-between gap-2", children: [ (edit && canEdit || !edit && canCreate) && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", { className: "order-2 flex gap-2", children: [ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(Button_js_default(), { ...buttonProps, className: "order-2 flex gap-2", type: "submit", name: "__admin_redirect", value: "list", loading: isPending, children: [ !isPending && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(outline_namespaceObject.CheckCircleIcon, { className: "h-6 w-6" }), t("form.button.save.label") ] }), /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Button_js_default(), { ...buttonProps, variant: "ghost", className: "order-1 hidden sm:block", tabIndex: -1, type: "submit", loading: isPending, name: "save_edit", children: t("form.button.save_edit.label") }) ] }), /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: "order-1", children: edit && canDelete && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(Button_js_default(), { variant: "destructiveOutline", className: "flex gap-2", formNoValidate: true, tabIndex: -1, onClick: async (e)=>{ if (confirm(t("form.delete.alert"))) try { setIsPending(true); await runSingleDeletion(id); router.replace({ pathname: `${basePath}/${(0, tools_js_namespaceObject.slugify)(resource)}`, query: { message: JSON.stringify({ type: "success", message: t("form.delete.succeed") }) } }); } catch (e) { showMessage({ type: "error", message: t(e.message) }); } finally{ setIsPending(false); } else e.preventDefault(); }, loading: isPending, children: [ !isPending && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(outline_namespaceObject.TrashIcon, { className: "h-4 w-4" }), t("form.button.delete.label") ] }) }) ] }); }, [ isPending, id ]); const extraErrors = validation?.reduce((acc, curr)=>{ acc[curr.property] = { __errors: [ curr.message ] }; return acc; }, {}); const onSubmit = (0, external_react_namespaceObject.useCallback)(async (formData)=>{ try { setIsPending(true); const response = await fetch(`${apiBasePath}/${(0, tools_js_namespaceObject.slugify)(resource)}${id ? `/${id}` : ""}`, { method: "POST", body: formData }); const result = await response.json(); result?.validation ? setValidation(result.validation) : setValidation(void 0); if (result?.data) { setFormData(result.data); cleanAll(); } if (result?.deleted) return router.replace({ pathname: `${basePath}/${(0, tools_js_namespaceObject.slugify)(resource)}`, query: { message: JSON.stringify({ type: "success", message: t("form.delete.succeed") }) } }); if (result?.created) { const pathname = result?.redirect ? `${basePath}/${(0, tools_js_namespaceObject.slugify)(resource)}` : `${basePath}/${(0, tools_js_namespaceObject.slugify)(resource)}/${result.createdId}`; return router.push({ pathname, query: { message: JSON.stringify({ type: "success", message: t("form.create.succeed") }) } }); } if (result?.updated) { const pathname = result?.redirect ? `${basePath}/${(0, tools_js_namespaceObject.slugify)(resource)}` : location.pathname; if (pathname === location.pathname) { router.refresh(); showMessage({ type: "success", message: t("form.update.succeed") }); } else router.push({ pathname, query: { message: JSON.stringify({ type: "success", message: t("form.update.succeed") }) } }); } if (result?.error) showMessage({ type: "error", message: t(result.error) }); } finally{ setIsPending(false); } }, [ apiBasePath, id ]); const fields = (0, external_react_namespaceObject.useMemo)(()=>({ ArrayField: (props)=>{ const customInput = customInputs?.[props.name]; const improvedCustomInput = customInput ? /*#__PURE__*/ (0, external_react_namespaceObject.cloneElement)(customInput, { ...customInput.props, mode: edit ? "edit" : "create" }) : void 0; return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(ArrayField_js_default(), { ...props, customInput: improvedCustomInput }); }, NullField: NullField_js_default() }), [ customInputs, edit ]); const templates = { FieldTemplate: (props)=>{ const { id, classNames, style, label, help, required, description, errors, children, schema } = props; const labelAlias = modelOptions?.aliases?.[id] || (0, tools_js_namespaceObject.formatLabel)(label); const labelName = t(`model.${resource}.fields.${id}`, {}, labelAlias); let styleField = modelOptions?.edit?.styles?.[id]; const tooltip = modelOptions?.edit?.fields?.[id]?.tooltip || modelOptions?.edit?.customFields?.[id]?.tooltip; const sanitizedClassNames = classNames?.split(",").filter((className)=>"null" !== className).join(" "); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", { style: style, className: external_clsx_default()(sanitizedClassNames, styleField), children: [ "null" !== schema.type && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("label", { className: external_clsx_default()("text-nextadmin-content-inverted dark:text-dark-nextadmin-content-inverted mb-2 flex items-center gap-2 text-sm font-medium leading-6"), htmlFor: id, children: [ labelName, required ? "*" : null, !!tooltip && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Tooltip_js_namespaceObject.TooltipProvider, { children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(Tooltip_js_namespaceObject.TooltipRoot, { children: [ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Tooltip_js_namespaceObject.TooltipTrigger, { asChild: true, children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(outline_namespaceObject.InformationCircleIcon, { className: "text-nextadmin-content-default dark:text-dark-nextadmin-content-default h-4 w-4" }) }), /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Tooltip_js_namespaceObject.TooltipPortal, { children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Tooltip_js_namespaceObject.TooltipContent, { side: "right", className: "px-2 py-1", sideOffset: 4, children: tooltip }) }) ] }) }) ] }), children, description, errors, help ] }); }, ObjectFieldTemplate: (props)=>{ const styleForm = modelOptions?.edit?.styles?._form; return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: (0, external_tailwind_merge_namespaceObject.twMerge)("grid gap-4", styleForm), children: props.properties.map((element)=>element.content) }); }, BaseInputTemplate: ({ onChange, options, onChangeOverride, uiSchema, readonly, formContext, autofocus, rawErrors, schema, registry, hideError, hideLabel, ...props })=>{ const { setFieldDirty } = (0, FormStateContext_js_namespaceObject.useFormState)(); const onTextChange = ({ target: { value: val } })=>{ setFieldDirty(props.name); onChange("" === val ? options.emptyValue || "" : val); }; const customInput = customInputs?.[props.name]; if (customInput) return /*#__PURE__*/ (0, external_react_namespaceObject.cloneElement)(customInput, { value: props.value, onChange: onChangeOverride || onTextChange, readonly, rawErrors, name: props.name, required: props.required, disabled: props.disabled, mode: edit ? "edit" : "create", item: data }); if (schema?.format === "json") return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(JsonField_js_default(), { onChange: onChangeOverride || onTextChange, readonly: readonly, rawErrors: rawErrors, ...props }); if (schema?.format?.startsWith("richtext-")) return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_namespaceObject.Suspense, { fallback: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: "h-48 animate-pulse rounded bg-gray-500" }), children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(RichTextField, { onChange: onChangeOverride || onTextChange, readonly: readonly, rawErrors: rawErrors, name: props.name, value: props.value, schema: schema, disabled: props.disabled, required: props.required }) }); if ([ "time", "time-second" ].includes(schema?.format)) return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(BaseInput_js_default(), { type: "time", onChange: onChangeOverride || onTextChange, ...props, value: props.value.split(":").slice(0, schema?.format === "time-second" ? 3 : 2).join(":") ?? "", className: external_clsx_default()({ "ring-red-600 dark:ring-red-400": rawErrors }), step: schema?.format === "time-second" ? 1 : void 0 }); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(BaseInput_js_default(), { onChange: onChangeOverride || onTextChange, ...props, value: props.value ?? "", className: external_clsx_default()({ "ring-red-600 dark:ring-red-400": rawErrors }) }); }, ErrorListTemplate: ()=>null, FieldErrorTemplate: ({ errors })=>errors ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: errors.map((error, idx)=>{ if ("string" == typeof error) return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_default().Fragment, { children: t(error) }, idx); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_react_default().Fragment, { children: error }, idx); }) }) : null, DescriptionFieldTemplate: ({ description, schema })=>description && "null" !== schema.type ? /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", { className: "text-nextadmin-content-emphasis dark:text-dark-nextadmin-content-emphasis text-sm", children: description }) : null, ButtonTemplates: { SubmitButton: submitButton } }; const CustomForm = (0, external_react_namespaceObject.useMemo)(()=>/*#__PURE__*/ (0, external_react_namespaceObject.forwardRef)((props, ref)=>{ const { dirtyFields } = (0, FormStateContext_js_namespaceObject.useFormState)(); const { formData } = (0, FormDataContext_js_namespaceObject.useFormData)(); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("form", { ...props, ref: ref, onSubmit: (e)=>{ e.preventDefault(); const formValues = new FormData(e.target); const data = new FormData(); dirtyFields.forEach((field)=>{ const schemaProperties = schema.properties[field]; const isFieldArrayOfFiles = schemaProperties?.type === "array" && (0, tools_js_namespaceObject.isFileUploadFormat)(schemaProperties.format ?? ""); if (isFieldArrayOfFiles) { const files = formValues.getAll(field).filter((file)=>"string" == typeof file || file instanceof File && !!file.name); const values = formData[field]; values.forEach((val)=>{ data.append(field, val); }); if (files.length > 0) files.forEach((file)=>{ data.append(field, file); }); else data.append(field, new File([], "")); return; } data.append(field, formValues.get(field)); }); const submitter = e.nativeEvent.submitter; data.append(submitter.name, submitter.value); onSubmit(data); } }); }), [ onSubmit, schema ]); const RjsfFormComponent = (0, external_react_namespaceObject.useMemo)(()=>/*#__PURE__*/ (0, external_react_namespaceObject.forwardRef)((_props, ref)=>{ const { formData } = (0, FormDataContext_js_namespaceObject.useFormData)(); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(core_default(), { tagName: CustomForm, idPrefix: "", idSeparator: "", ...schemas, onChange: (e)=>{ setFormData(e.formData); }, formData: formData, validator: validator_ajv8_default(), extraErrors: extraErrors, fields: fields, disabled: allDisabled, formContext: { isPending, schema }, templates: templates, widgets: widgets, ref: ref, className: "relative" }); }), [ submitButton ]); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: "relative h-full", children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", { className: "bg-nextadmin-background-default dark:bg-dark-nextadmin-background-default max-w-full p-4 align-middle sm:p-8", children: [ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Message_js_namespaceObject.Message, { className: "-mt-2 mb-2 sm:-mt-4 sm:mb-4" }), /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { className: "bg-nextadmin-background-default dark:bg-dark-nextadmin-background-emphasis border-nextadmin-border-default dark:border-dark-nextadmin-border-default max-w-screen-md rounded-lg border p-4 sm:p-8", children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(RjsfFormComponent, { ref: formRef }) }) ] }) }); }; const FormWrapper = ({ clientActionsComponents, relationshipsRawData, ...props })=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(ClientActionDialogContext_js_default(), { componentsMap: clientActionsComponents, children: [ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_FormHeader_js_default(), { ...props }), /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(FormDataContext_js_default(), { data: props.data, relationshipsRawData: relationshipsRawData, children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(FormStateContext_js_default(), { children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(Form, { ...props }) }) }) ] }); const components_Form = FormWrapper; })(); exports["default"] = __webpack_exports__["default"]; for(var __webpack_i__ in __webpack_exports__)if (-1 === [ "default" ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__]; Object.defineProperty(exports, '__esModule', { value: true });