Skip to content

Commit

Permalink
feat: add custom error message for upload handler #144 (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
foyarash authored Mar 12, 2024
1 parent 104aaba commit e16aa42
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 253 deletions.
6 changes: 6 additions & 0 deletions .changeset/many-baboons-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@premieroctet/next-admin": minor
---

feat: add custom error message for upload handler ([#144](https://github.com/premieroctet/next-admin/issues/144))
feat: add custom error message for form submission
33 changes: 16 additions & 17 deletions apps/docs/pages/docs/api-docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -233,21 +233,19 @@ This property determines how your data is displayed in the [List View](/docs/glo

This property determines how your data is displayed in the [edit view](/docs/glossary#edit-view)

| Name | Description | Default value |
| --------- | ----------------------------------------------------------------------- | ------------------------------- |
| `display` | an array of fields that are displayed in the form | all scalar fields are displayed |
| `styles` | an object containing the styles of the form | undefined |
| `fields` | an object containing the model fields as keys, and customization values | undefined |
| Name | Description | Default value |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| `display` | an array of fields that are displayed in the form | all scalar fields are displayed |
| `styles` | an object containing the styles of the form | undefined |
| `fields` | an object containing the model fields as keys, and customization values | undefined |
| `submissionErrorMessage` | a message displayed if an error occurs during the form submission, after the form validation and before any call to prisma | Submission error |

##### `styles` property

The `styles` property is available in the `edit` property.

> ⚠️ If your options are defined in a separate file, make sure to add the path to the `content` property of the `tailwind.config.js` file

```ts

| Name | Description |
| ------- | ------------------------------------------------------------------------------ |
| `_form` | a string defining the classname of the form |
Expand All @@ -274,15 +272,16 @@ For the `list` property, it can take the following:

For the `edit` property, it can take the following:

| Name | Description |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `validate` | a function that takes the field value as a parameter, and that returns a boolean |
| `format` | a string defining an OpenAPI field format, overriding the one set in the generator. An extra `file` format can be used to be able to have a file input |
| `input` | a React Element that should receive [CustomInputProps](#custominputprops). For App Router, this element must be a client component. |
| `handler` | an object that can take the following properties |
| `handler.get` | a function that takes the field value as a parameter and returns a transformed value displayed in the form |
| `handler.upload` | an async function that is used only for formats `file` and `data-url`. It takes a buffer as parameter and must return a string. Useful to upload a file to a remote provider |
| `optionFormatter` | only for realtion fields, a function that takes the field values as a parameter and returns a string. Useful to display your record in related list |
| Name | Description |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `validate` | a function that takes the field value as a parameter, and that returns a boolean |
| `format` | a string defining an OpenAPI field format, overriding the one set in the generator. An extra `file` format can be used to be able to have a file input |
| `input` | a React Element that should receive [CustomInputProps](#custominputprops). For App Router, this element must be a client component. |
| `handler` | an object that can take the following properties |
| `handler.get` | a function that takes the field value as a parameter and returns a transformed value displayed in the form |
| `handler.upload` | an async function that is used only for formats `file` and `data-url`. It takes a buffer as parameter and must return a string. Useful to upload a file to a remote provider |
| `handler.uploadErrorMessage` | an optional string displayed in the input field as an error message in case of a failure during the upload handler |
| `optionFormatter` | only for realtion fields, a function that takes the field values as a parameter and returns a string. Useful to display your record in related list |

### `pages`

Expand Down
39 changes: 23 additions & 16 deletions packages/next-admin/src/actions/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,34 @@ export const submitForm = async (
// Validate
validate(parsedFormData, fields);

const { formattedData, errors } = await formattedFormData(
formValues,
dmmfSchema?.fields!,
schema,
resource,
resourceId === undefined,
fields
);

if (errors.length) {
return {
error:
options.model?.[resource]?.edit?.submissionErrorMessage ??
"Submission error",
validation: errors.map((error) => ({
property: error.field,
message: error.message,
})),
};
}

if (resourceId !== undefined) {
// @ts-expect-error
data = await prisma[resource].update({
where: {
[resourceIdField]: resourceId,
},
data: await formattedFormData(
formValues,
dmmfSchema?.fields!,
schema,
resource,
false,
fields
),
data: formattedData,
});

return { updated: true, redirect: redirect === "list" };
Expand All @@ -93,14 +107,7 @@ export const submitForm = async (
// Create
// @ts-expect-error
data = await prisma[resource].create({
data: await formattedFormData(
formValues,
dmmfSchema?.fields!,
schema,
resource,
true,
fields
),
data: formattedData,
});

return {
Expand Down
42 changes: 26 additions & 16 deletions packages/next-admin/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,37 @@ export const nextAdminRouter = async (
// Validate
validate(parsedFormData, fields);

const { formattedData, errors } = await formattedFormData(
formData,
dmmfSchema?.fields!,
schema,
resource,
resourceId === undefined,
fields
);

if (errors.length) {
return {
props: {
...(await getProps()),
error:
options.model?.[resource]?.edit?.submissionErrorMessage ??
"Submission error",
validation: errors.map((error) => ({
property: error.field,
message: error.message,
})),
},
};
}

if (resourceId !== undefined) {
// @ts-expect-error
await prisma[resource].update({
where: {
[modelIdProperty]: resourceId,
},
data: await formattedFormData(
formData,
dmmfSchema?.fields!,
schema,
resource,
false,
fields
),
data: formattedData,
});

const message = {
Expand Down Expand Up @@ -198,14 +215,7 @@ export const nextAdminRouter = async (
// Create
// @ts-expect-error
const createdData = await prisma[resource].create({
data: await formattedFormData(
formData,
dmmfSchema?.fields!,
schema,
resource,
true,
fields
),
data: formattedData,
});

const pathname = redirect
Expand Down
2 changes: 2 additions & 0 deletions packages/next-admin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type Handler<
> = {
get?: (input: T) => any;
upload?: (file: Buffer) => Promise<string>;
uploadErrorMessage?: string;
};

export type RichTextFormat = "html" | "json";
Expand Down Expand Up @@ -141,6 +142,7 @@ export type EditOptions<T extends ModelName> = {
_form?: string;
} & Partial<Record<Field<T>, string>>;
fields?: EditFieldsOptions<T>;
submissionErrorMessage?: string;
};

export type ActionStyle = "default" | "destructive";
Expand Down
Loading

0 comments on commit e16aa42

Please sign in to comment.