fix: list widget validation when removing invalid item
This commit is contained in:
parent
fb72cec318
commit
3d02a6b180
@ -4,8 +4,8 @@ import { currentBackend } from '../backend';
|
|||||||
import {
|
import {
|
||||||
ADD_DRAFT_ENTRY_MEDIA_FILE,
|
ADD_DRAFT_ENTRY_MEDIA_FILE,
|
||||||
CHANGE_VIEW_STYLE,
|
CHANGE_VIEW_STYLE,
|
||||||
DRAFT_UPDATE,
|
|
||||||
DRAFT_CHANGE_FIELD,
|
DRAFT_CHANGE_FIELD,
|
||||||
|
DRAFT_CLEAR_CHILD_VALIDATION,
|
||||||
DRAFT_CREATE_DUPLICATE_FROM_ENTRY,
|
DRAFT_CREATE_DUPLICATE_FROM_ENTRY,
|
||||||
DRAFT_CREATE_EMPTY,
|
DRAFT_CREATE_EMPTY,
|
||||||
DRAFT_CREATE_FROM_ENTRY,
|
DRAFT_CREATE_FROM_ENTRY,
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
DRAFT_DISCARD,
|
DRAFT_DISCARD,
|
||||||
DRAFT_LOCAL_BACKUP_DELETE,
|
DRAFT_LOCAL_BACKUP_DELETE,
|
||||||
DRAFT_LOCAL_BACKUP_RETRIEVED,
|
DRAFT_LOCAL_BACKUP_RETRIEVED,
|
||||||
|
DRAFT_UPDATE,
|
||||||
DRAFT_VALIDATION_ERRORS,
|
DRAFT_VALIDATION_ERRORS,
|
||||||
ENTRIES_FAILURE,
|
ENTRIES_FAILURE,
|
||||||
ENTRIES_REQUEST,
|
ENTRIES_REQUEST,
|
||||||
@ -485,6 +486,17 @@ export function changeDraftField({
|
|||||||
} as const;
|
} as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearDraftFieldChildValidation(
|
||||||
|
path: string,
|
||||||
|
i18n?: I18nSettings,
|
||||||
|
isMeta?: boolean,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: DRAFT_CLEAR_CHILD_VALIDATION,
|
||||||
|
payload: { path, i18n, isMeta },
|
||||||
|
} as const;
|
||||||
|
}
|
||||||
|
|
||||||
export function changeDraftFieldValidation(
|
export function changeDraftFieldValidation(
|
||||||
path: string,
|
path: string,
|
||||||
errors: FieldError[],
|
errors: FieldError[],
|
||||||
@ -1135,6 +1147,7 @@ export type EntriesAction = ReturnType<
|
|||||||
| typeof discardDraft
|
| typeof discardDraft
|
||||||
| typeof updateDraft
|
| typeof updateDraft
|
||||||
| typeof changeDraftField
|
| typeof changeDraftField
|
||||||
|
| typeof clearDraftFieldChildValidation
|
||||||
| typeof changeDraftFieldValidation
|
| typeof changeDraftFieldValidation
|
||||||
| typeof localBackupRetrieved
|
| typeof localBackupRetrieved
|
||||||
| typeof loadLocalBackup
|
| typeof loadLocalBackup
|
||||||
|
@ -7,6 +7,7 @@ import { connect } from 'react-redux';
|
|||||||
import {
|
import {
|
||||||
changeDraftField as changeDraftFieldAction,
|
changeDraftField as changeDraftFieldAction,
|
||||||
changeDraftFieldValidation,
|
changeDraftFieldValidation,
|
||||||
|
clearDraftFieldChildValidation,
|
||||||
} from '@staticcms/core/actions/entries';
|
} from '@staticcms/core/actions/entries';
|
||||||
import { query as queryAction } from '@staticcms/core/actions/search';
|
import { query as queryAction } from '@staticcms/core/actions/search';
|
||||||
import useDebouncedCallback from '@staticcms/core/lib/hooks/useDebouncedCallback';
|
import useDebouncedCallback from '@staticcms/core/lib/hooks/useDebouncedCallback';
|
||||||
@ -127,6 +128,10 @@ const EditorControl = ({
|
|||||||
i18nDisabled,
|
i18nDisabled,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const clearChildValidation = useCallback(() => {
|
||||||
|
dispatch(clearDraftFieldChildValidation(path, i18n, isMeta));
|
||||||
|
}, [dispatch, i18n, isMeta, path]);
|
||||||
|
|
||||||
const handleChangeDraftField = useCallback(
|
const handleChangeDraftField = useCallback(
|
||||||
async (value: ValueOrNestedValue) => {
|
async (value: ValueOrNestedValue) => {
|
||||||
setDirty(
|
setDirty(
|
||||||
@ -191,6 +196,7 @@ const EditorControl = ({
|
|||||||
label: getFieldLabel(field, t),
|
label: getFieldLabel(field, t),
|
||||||
locale,
|
locale,
|
||||||
onChange: handleDebouncedChangeDraftField,
|
onChange: handleDebouncedChangeDraftField,
|
||||||
|
clearChildValidation,
|
||||||
path,
|
path,
|
||||||
query,
|
query,
|
||||||
t,
|
t,
|
||||||
|
@ -49,6 +49,7 @@ export const DRAFT_CREATE_EMPTY = 'DRAFT_CREATE_EMPTY';
|
|||||||
export const DRAFT_DISCARD = 'DRAFT_DISCARD';
|
export const DRAFT_DISCARD = 'DRAFT_DISCARD';
|
||||||
export const DRAFT_UPDATE = 'DRAFT_UPDATE';
|
export const DRAFT_UPDATE = 'DRAFT_UPDATE';
|
||||||
export const DRAFT_CHANGE_FIELD = 'DRAFT_CHANGE_FIELD';
|
export const DRAFT_CHANGE_FIELD = 'DRAFT_CHANGE_FIELD';
|
||||||
|
export const DRAFT_CLEAR_CHILD_VALIDATION = 'DRAFT_CLEAR_CHILD_VALIDATION';
|
||||||
export const DRAFT_VALIDATION_ERRORS = 'DRAFT_VALIDATION_ERRORS';
|
export const DRAFT_VALIDATION_ERRORS = 'DRAFT_VALIDATION_ERRORS';
|
||||||
export const DRAFT_LOCAL_BACKUP_RETRIEVED = 'DRAFT_LOCAL_BACKUP_RETRIEVED';
|
export const DRAFT_LOCAL_BACKUP_RETRIEVED = 'DRAFT_LOCAL_BACKUP_RETRIEVED';
|
||||||
export const DRAFT_LOCAL_BACKUP_DELETE = 'DRAFT_LOCAL_BACKUP_DELETE';
|
export const DRAFT_LOCAL_BACKUP_DELETE = 'DRAFT_LOCAL_BACKUP_DELETE';
|
||||||
|
@ -317,6 +317,7 @@ export interface WidgetControlProps<T, F extends BaseField = UnknownField, EV =
|
|||||||
label: string;
|
label: string;
|
||||||
locale: string | undefined;
|
locale: string | undefined;
|
||||||
onChange: (value: T | null | undefined) => void;
|
onChange: (value: T | null | undefined) => void;
|
||||||
|
clearChildValidation: () => void;
|
||||||
i18n: I18nSettings | undefined;
|
i18n: I18nSettings | undefined;
|
||||||
hasErrors: boolean;
|
hasErrors: boolean;
|
||||||
errors: FieldError[];
|
errors: FieldError[];
|
||||||
|
@ -4,6 +4,7 @@ import { v4 as uuid } from 'uuid';
|
|||||||
import {
|
import {
|
||||||
ADD_DRAFT_ENTRY_MEDIA_FILE,
|
ADD_DRAFT_ENTRY_MEDIA_FILE,
|
||||||
DRAFT_CHANGE_FIELD,
|
DRAFT_CHANGE_FIELD,
|
||||||
|
DRAFT_CLEAR_CHILD_VALIDATION,
|
||||||
DRAFT_CREATE_DUPLICATE_FROM_ENTRY,
|
DRAFT_CREATE_DUPLICATE_FROM_ENTRY,
|
||||||
DRAFT_CREATE_EMPTY,
|
DRAFT_CREATE_EMPTY,
|
||||||
DRAFT_CREATE_FROM_ENTRY,
|
DRAFT_CREATE_FROM_ENTRY,
|
||||||
@ -218,6 +219,33 @@ function entryDraftReducer(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DRAFT_CLEAR_CHILD_VALIDATION: {
|
||||||
|
const { path, i18n, isMeta } = action.payload;
|
||||||
|
const fieldsErrors = { ...state.fieldsErrors };
|
||||||
|
|
||||||
|
const dataPath = isMeta
|
||||||
|
? ['meta']
|
||||||
|
: (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
|
||||||
|
const fullPath = `${dataPath.join('.')}.${path}`;
|
||||||
|
|
||||||
|
const pathsToDelete: string[] = [];
|
||||||
|
|
||||||
|
Object.keys(fieldsErrors).forEach(p => {
|
||||||
|
if (p === fullPath || p.startsWith(fullPath)) {
|
||||||
|
pathsToDelete.push(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pathsToDelete.forEach(p => {
|
||||||
|
delete fieldsErrors[p];
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fieldsErrors,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case DRAFT_VALIDATION_ERRORS: {
|
case DRAFT_VALIDATION_ERRORS: {
|
||||||
const { path, errors, i18n, isMeta } = action.payload;
|
const { path, errors, i18n, isMeta } = action.payload;
|
||||||
const fieldsErrors = { ...state.fieldsErrors };
|
const fieldsErrors = { ...state.fieldsErrors };
|
||||||
|
@ -189,6 +189,7 @@ const ListControl: FC<WidgetControlProps<ValueOrNestedValue[], ListField>> = pro
|
|||||||
errors,
|
errors,
|
||||||
forSingleList,
|
forSingleList,
|
||||||
onChange,
|
onChange,
|
||||||
|
clearChildValidation,
|
||||||
t,
|
t,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@ -267,10 +268,12 @@ const ListControl: FC<WidgetControlProps<ValueOrNestedValue[], ListField>> = pro
|
|||||||
newKeys.splice(index, 1);
|
newKeys.splice(index, 1);
|
||||||
newValue.splice(index, 1);
|
newValue.splice(index, 1);
|
||||||
|
|
||||||
|
clearChildValidation();
|
||||||
|
|
||||||
setKeys(newKeys);
|
setKeys(newKeys);
|
||||||
onChange(newValue as string[] | ObjectValue[]);
|
onChange(newValue as string[] | ObjectValue[]);
|
||||||
},
|
},
|
||||||
[onChange, internalValue, keys],
|
[keys, internalValue, clearChildValidation, onChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user