chore: handles server errors
This commit is contained in:
@@ -47,6 +47,68 @@ export function fieldReducer(state: FormState, action: FieldAction): FormState {
|
|||||||
return newState
|
return newState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'ADD_SERVER_ERRORS': {
|
||||||
|
let newState = { ...state }
|
||||||
|
|
||||||
|
const errorPaths: { fieldErrorPath: string; parentPath: string }[] = []
|
||||||
|
|
||||||
|
action.errors.forEach(({ field, message }) => {
|
||||||
|
newState[field] = {
|
||||||
|
...(newState[field] || {
|
||||||
|
initialValue: null,
|
||||||
|
value: null,
|
||||||
|
}),
|
||||||
|
errorMessage: message,
|
||||||
|
valid: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments = field.split('.')
|
||||||
|
if (segments.length > 1) {
|
||||||
|
errorPaths.push({
|
||||||
|
fieldErrorPath: field,
|
||||||
|
parentPath: segments.slice(0, segments.length - 1).join('.'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
newState = Object.entries(newState).reduce((acc, [path, fieldState]) => {
|
||||||
|
const fieldErrorPaths = errorPaths.reduce((errorACC, { fieldErrorPath, parentPath }) => {
|
||||||
|
if (parentPath.startsWith(path)) {
|
||||||
|
errorACC.push(fieldErrorPath)
|
||||||
|
}
|
||||||
|
return errorACC
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
let changed = false
|
||||||
|
|
||||||
|
if (fieldErrorPaths.length > 0) {
|
||||||
|
const newErrorPaths = Array.isArray(fieldState.errorPaths) ? fieldState.errorPaths : []
|
||||||
|
|
||||||
|
fieldErrorPaths.forEach((fieldErrorPath) => {
|
||||||
|
if (!newErrorPaths.includes(fieldErrorPath)) {
|
||||||
|
newErrorPaths.push(fieldErrorPath)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
acc[path] = {
|
||||||
|
...fieldState,
|
||||||
|
errorPaths: newErrorPaths,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changed) {
|
||||||
|
acc[path] = fieldState
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
return newState
|
||||||
|
}
|
||||||
|
|
||||||
case 'UPDATE': {
|
case 'UPDATE': {
|
||||||
const newField = Object.entries(action).reduce(
|
const newField = Object.entries(action).reduce(
|
||||||
(field, [key, value]) => {
|
(field, [key, value]) => {
|
||||||
|
|||||||
@@ -317,14 +317,9 @@ export const Form: React.FC<FormProps> = (props) => {
|
|||||||
[[], []],
|
[[], []],
|
||||||
)
|
)
|
||||||
|
|
||||||
fieldErrors.forEach((err) => {
|
dispatchFields({
|
||||||
dispatchFields({
|
type: 'ADD_SERVER_ERRORS',
|
||||||
type: 'UPDATE',
|
errors: fieldErrors,
|
||||||
...(contextRef.current?.fields?.[err.field] || {}),
|
|
||||||
errorMessage: err.message,
|
|
||||||
path: err.field,
|
|
||||||
valid: false,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
nonFieldErrors.forEach((err) => {
|
nonFieldErrors.forEach((err) => {
|
||||||
|
|||||||
@@ -129,6 +129,14 @@ export type MOVE_ROW = {
|
|||||||
type: 'MOVE_ROW'
|
type: 'MOVE_ROW'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ADD_SERVER_ERRORS = {
|
||||||
|
errors: {
|
||||||
|
field: string
|
||||||
|
message: string
|
||||||
|
}[]
|
||||||
|
type: 'ADD_SERVER_ERRORS'
|
||||||
|
}
|
||||||
|
|
||||||
export type SET_ROW_COLLAPSED = {
|
export type SET_ROW_COLLAPSED = {
|
||||||
collapsed: boolean
|
collapsed: boolean
|
||||||
path: string
|
path: string
|
||||||
@@ -146,6 +154,7 @@ export type SET_ALL_ROWS_COLLAPSED = {
|
|||||||
|
|
||||||
export type FieldAction =
|
export type FieldAction =
|
||||||
| ADD_ROW
|
| ADD_ROW
|
||||||
|
| ADD_SERVER_ERRORS
|
||||||
| DUPLICATE_ROW
|
| DUPLICATE_ROW
|
||||||
| MODIFY_CONDITION
|
| MODIFY_CONDITION
|
||||||
| MOVE_ROW
|
| MOVE_ROW
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ describe('fields', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// TODO - This test is flaky. Rarely, but sometimes it randomly fails.
|
// TODO - This test is flaky. Rarely, but sometimes it randomly fails.
|
||||||
test.skip('should display unique constraint error in ui', async () => {
|
test('should display unique constraint error in ui', async () => {
|
||||||
const uniqueText = 'uniqueText'
|
const uniqueText = 'uniqueText'
|
||||||
await payload.create({
|
await payload.create({
|
||||||
collection: 'indexed-fields',
|
collection: 'indexed-fields',
|
||||||
|
|||||||
@@ -40,8 +40,12 @@
|
|||||||
"@payloadcms/ui/scss": ["../packages/ui/src/scss.scss"],
|
"@payloadcms/ui/scss": ["../packages/ui/src/scss.scss"],
|
||||||
"@payloadcms/ui/scss/app.scss": ["../packages/ui/src/scss/app.scss"],
|
"@payloadcms/ui/scss/app.scss": ["../packages/ui/src/scss/app.scss"],
|
||||||
"payload/types": ["../packages/payload/src/exports/types/index.ts"],
|
"payload/types": ["../packages/payload/src/exports/types/index.ts"],
|
||||||
"@payloadcms/next/*": ["../packages/next/src/*"],
|
"@payloadcms/next/*": [
|
||||||
"@payloadcms/next": ["../packages/next/src/exports/*"],
|
"./packages/next/src/exports/*"
|
||||||
|
],
|
||||||
|
"@payloadcms/next": [
|
||||||
|
"./packages/next/src/exports/*"
|
||||||
|
],
|
||||||
"@payload-config": ["./_community/config.ts"]
|
"@payload-config": ["./_community/config.ts"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user