fix: object validation collapsed (#416)
This commit is contained in:
parent
dad93b42fc
commit
d17378d557
@ -606,6 +606,27 @@ collections:
|
|||||||
name: thumb
|
name: thumb
|
||||||
widget: image
|
widget: image
|
||||||
required: false
|
required: false
|
||||||
|
- label: Collapsed, optional with required children
|
||||||
|
name: collapsed_optional_with_required_children
|
||||||
|
widget: object
|
||||||
|
required: false
|
||||||
|
collapsed: true
|
||||||
|
fields:
|
||||||
|
- name: layout
|
||||||
|
widget: hidden
|
||||||
|
default: post
|
||||||
|
- label: Number of posts on frontpage
|
||||||
|
name: front_limit
|
||||||
|
widget: number
|
||||||
|
required: true
|
||||||
|
- label: Author
|
||||||
|
name: author
|
||||||
|
widget: string
|
||||||
|
required: true
|
||||||
|
- label: Thumbnail
|
||||||
|
name: thumb
|
||||||
|
widget: image
|
||||||
|
required: true
|
||||||
- name: relation
|
- name: relation
|
||||||
label: Relation
|
label: Relation
|
||||||
file: _widgets/relation.json
|
file: _widgets/relation.json
|
||||||
|
@ -3,9 +3,13 @@ import { getDataPath } from '@staticcms/core/lib/i18n';
|
|||||||
import type { I18nSettings } from '@staticcms/core/interface';
|
import type { I18nSettings } from '@staticcms/core/interface';
|
||||||
import type { RootState } from '@staticcms/core/store';
|
import type { RootState } from '@staticcms/core/store';
|
||||||
|
|
||||||
|
export const getEntryDataPath = (i18n: I18nSettings | undefined) => {
|
||||||
|
return (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
|
||||||
|
};
|
||||||
|
|
||||||
export const selectFieldErrors =
|
export const selectFieldErrors =
|
||||||
(path: string, i18n: I18nSettings | undefined) => (state: RootState) => {
|
(path: string, i18n: I18nSettings | undefined) => (state: RootState) => {
|
||||||
const dataPath = (i18n && getDataPath(i18n.currentLocale, i18n.defaultLocale)) || ['data'];
|
const dataPath = getEntryDataPath(i18n);
|
||||||
const fullPath = `${dataPath.join('.')}.${path}`;
|
const fullPath = `${dataPath.join('.')}.${path}`;
|
||||||
return state.entryDraft.fieldsErrors[fullPath] ?? [];
|
return state.entryDraft.fieldsErrors[fullPath] ?? [];
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@ import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar
|
|||||||
import Outline from '@staticcms/core/components/UI/Outline';
|
import Outline from '@staticcms/core/components/UI/Outline';
|
||||||
import { transientOptions } from '@staticcms/core/lib';
|
import { transientOptions } from '@staticcms/core/lib';
|
||||||
import { compileStringTemplate } from '@staticcms/core/lib/widgets/stringTemplate';
|
import { compileStringTemplate } from '@staticcms/core/lib/widgets/stringTemplate';
|
||||||
|
import { getEntryDataPath } from '@staticcms/core/reducers/selectors/entryDraft';
|
||||||
|
|
||||||
import type { ObjectField, ObjectValue, WidgetControlProps } from '@staticcms/core/interface';
|
import type { ObjectField, ObjectValue, WidgetControlProps } from '@staticcms/core/interface';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@ -61,7 +62,7 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
|||||||
hasErrors,
|
hasErrors,
|
||||||
value = {},
|
value = {},
|
||||||
}) => {
|
}) => {
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(field.collapsed ?? false);
|
||||||
|
|
||||||
const handleCollapseToggle = useCallback(() => {
|
const handleCollapseToggle = useCallback(() => {
|
||||||
setCollapsed(!collapsed);
|
setCollapsed(!collapsed);
|
||||||
@ -75,6 +76,13 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
|||||||
|
|
||||||
const multiFields = useMemo(() => field.fields, [field.fields]);
|
const multiFields = useMemo(() => field.fields, [field.fields]);
|
||||||
|
|
||||||
|
const childHasError = useMemo(() => {
|
||||||
|
const dataPath = getEntryDataPath(i18n);
|
||||||
|
const fullPath = `${dataPath}.${path}`;
|
||||||
|
|
||||||
|
return Boolean(Object.keys(fieldsErrors).find(key => key.startsWith(fullPath)));
|
||||||
|
}, [fieldsErrors, i18n, path]);
|
||||||
|
|
||||||
const renderedField = useMemo(() => {
|
const renderedField = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
multiFields?.map((field, index) => {
|
multiFields?.map((field, index) => {
|
||||||
@ -132,7 +140,7 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
|||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
onCollapseToggle={handleCollapseToggle}
|
onCollapseToggle={handleCollapseToggle}
|
||||||
heading={objectLabel}
|
heading={objectLabel}
|
||||||
hasError={hasErrors}
|
hasError={hasErrors || childHasError}
|
||||||
t={t}
|
t={t}
|
||||||
testId="object-title"
|
testId="object-title"
|
||||||
/>
|
/>
|
||||||
@ -140,7 +148,9 @@ const ObjectControl: FC<WidgetControlProps<ObjectValue, ObjectField>> = ({
|
|||||||
<StyledFieldsBox $collapsed={collapsed} key="object-control-fields">
|
<StyledFieldsBox $collapsed={collapsed} key="object-control-fields">
|
||||||
{renderedField}
|
{renderedField}
|
||||||
</StyledFieldsBox>
|
</StyledFieldsBox>
|
||||||
{forList ? null : <Outline key="object-control-outline" hasError={hasErrors} />}
|
{forList ? null : (
|
||||||
|
<Outline key="object-control-outline" hasError={hasErrors || childHasError} />
|
||||||
|
)}
|
||||||
</StyledObjectControlWrapper>
|
</StyledObjectControlWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user