From b19b14da17578cc51860ebc39883ef4a452efd88 Mon Sep 17 00:00:00 2001 From: rdunk Date: Mon, 15 Jul 2024 19:57:02 +0100 Subject: [PATCH] fix(sanity): open correct groups and fieldsets on `setOpenPath` --- dev/test-studio/preview/FieldGroups.tsx | 62 +++++++++++++ dev/test-studio/preview/main.tsx | 41 ++++++++- .../debug/fieldGroupsWithFieldsetsHidden.js | 86 +++++++++++++++++++ dev/test-studio/schema/index.ts | 2 + dev/test-studio/structure/constants.ts | 1 + .../__tests__/immutableReconcile.test.ts | 13 +++ .../form/store/utils/getExpandOperations.ts | 10 ++- .../form/store/utils/immutableReconcile.ts | 8 +- 8 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 dev/test-studio/preview/FieldGroups.tsx create mode 100644 dev/test-studio/schema/debug/fieldGroupsWithFieldsetsHidden.js diff --git a/dev/test-studio/preview/FieldGroups.tsx b/dev/test-studio/preview/FieldGroups.tsx new file mode 100644 index 00000000000..bca2af357cb --- /dev/null +++ b/dev/test-studio/preview/FieldGroups.tsx @@ -0,0 +1,62 @@ +import {Box, Card, Stack, Text} from '@sanity/ui' + +import {useQuery} from './loader' + +export function FieldGroups(): JSX.Element { + const {data, loading, error} = useQuery< + { + _id: string + field1: string | null + field2: string | null + nested: { + field3: string | null + field4: string | null + field5: string | null + nested: { + field6: string | null + field7: string | null + field8: string | null + } | null + } | null + }[] + >( + /* groq */ `*[_type == "fieldGroupsWithFieldsetsHidden"]{_id,field1,field2,nested{field3,field4,field5,nested{field6,field7,field8}}}`, + ) + + if (error) { + throw error + } + + if (loading) { + return

Loading...

+ } + + return ( + + {data?.map((item) => { + return ( + + + {item.field1 || 'N/A'} + {item.field2 || 'N/A'} + {item.nested && ( + + {item.nested.field3 || 'N/A'} + {item.nested.field4 || 'N/A'} + {item.nested.field5 || 'N/A'} + {item.nested.nested && ( + + {item.nested.nested.field6 || 'N/A'} + {item.nested.nested.field7 || 'N/A'} + {item.nested.nested.field8 || 'N/A'} + + )} + + )} + + + ) + })} + + ) +} diff --git a/dev/test-studio/preview/main.tsx b/dev/test-studio/preview/main.tsx index 2d8b6eac32e..7fb32fa58a7 100644 --- a/dev/test-studio/preview/main.tsx +++ b/dev/test-studio/preview/main.tsx @@ -1,14 +1,51 @@ +import {Box, Flex, studioTheme, Tab, TabList, TabPanel, ThemeProvider} from '@sanity/ui' import {enableVisualEditing} from '@sanity/visual-editing' -import {Suspense, useEffect} from 'react' +import {Suspense, useEffect, useState} from 'react' import {createRoot} from 'react-dom/client' +import {FieldGroups} from './FieldGroups' import {useLiveMode} from './loader' import {SimpleBlockPortableText} from './SimpleBlockPortableText' function Main() { + const [id, setId] = useState('simple') return ( <> - + + + + + setId('simple')} + selected={id === 'simple'} + /> + setId('nested')} + selected={id === 'nested'} + /> + + + + {id === 'simple' && ( + + + + )} + + {id === 'nested' && ( + + + + )} + + + diff --git a/dev/test-studio/schema/debug/fieldGroupsWithFieldsetsHidden.js b/dev/test-studio/schema/debug/fieldGroupsWithFieldsetsHidden.js new file mode 100644 index 00000000000..66008cb0dac --- /dev/null +++ b/dev/test-studio/schema/debug/fieldGroupsWithFieldsetsHidden.js @@ -0,0 +1,86 @@ +const group = { + name: 'group', + title: 'Group', + default: true, +} +const group2 = { + name: 'group2', + title: 'Group 2', +} +const fieldset = { + name: 'fieldset', + title: 'Fieldset', + options: {collapsed: true}, +} + +export default { + name: 'fieldGroupsWithFieldsetsHidden', + title: 'With default groups and collapsed fieldsets', + type: 'document', + groups: [group, group2], + fieldsets: [fieldset], + fields: [ + { + name: 'field1', + type: 'string', + }, + { + name: 'field2', + type: 'string', + group: group.name, + fieldset: fieldset.name, + }, + { + name: 'nested', + type: 'object', + group: group.name, + fieldset: fieldset.name, + groups: [group, group2], + fieldsets: [fieldset], + fields: [ + { + name: 'field3', + type: 'string', + fieldset: fieldset.name, + }, + { + name: 'field4', + type: 'string', + group: group.name, + fieldset: fieldset.name, + }, + { + name: 'field5', + type: 'string', + group: group2.name, + }, + { + name: 'nested', + type: 'object', + group: group.name, + fieldset: fieldset.name, + groups: [group, group2], + fieldsets: [fieldset], + fields: [ + { + name: 'field6', + type: 'string', + fieldset: fieldset.name, + }, + { + name: 'field7', + type: 'string', + group: group.name, + fieldset: fieldset.name, + }, + { + name: 'field8', + type: 'string', + group: group2.name, + }, + ], + }, + ], + }, + ], +} diff --git a/dev/test-studio/schema/index.ts b/dev/test-studio/schema/index.ts index 51b229532b6..b579539513f 100644 --- a/dev/test-studio/schema/index.ts +++ b/dev/test-studio/schema/index.ts @@ -32,6 +32,7 @@ import fieldGroupsDefault from './debug/fieldGroupsDefault' import fieldGroupsMany from './debug/fieldGroupsMany' import fieldGroupsWithFieldsets from './debug/fieldGroupsWithFieldsets' import fieldGroupsWithFieldsetsAndValidation from './debug/fieldGroupsWithFieldsetsAndValidation' +import fieldGroupsWithFieldsetsHidden from './debug/fieldGroupsWithFieldsetsHidden' import fieldGroupsWithI18n from './debug/fieldGroupsWithI18n' import fieldGroupsWithValidation from './debug/fieldGroupsWithValidation' import fieldsets from './debug/fieldsets' @@ -252,6 +253,7 @@ export const schemaTypes = [ fieldGroupsWithI18n, fieldGroupsWithValidation, fieldGroupsWithFieldsetsAndValidation, + fieldGroupsWithFieldsetsHidden, virtualizationInObject, virtualizationDebug, diff --git a/dev/test-studio/structure/constants.ts b/dev/test-studio/structure/constants.ts index fbbc480ed0d..ffcdea6447a 100644 --- a/dev/test-studio/structure/constants.ts +++ b/dev/test-studio/structure/constants.ts @@ -98,6 +98,7 @@ export const DEBUG_FIELD_GROUP_TYPES = [ 'fieldGroupsWithValidation', 'fieldGroupsWithFieldsets', 'fieldGroupsWithFieldsetsAndValidation', + 'fieldGroupsWithFieldsetsHidden', ] export const EXTERNAL_PLUGIN_INPUT_TYPES = ['markdownTest', 'muxVideoPost'] diff --git a/packages/sanity/src/core/form/store/utils/__tests__/immutableReconcile.test.ts b/packages/sanity/src/core/form/store/utils/__tests__/immutableReconcile.test.ts index 041280744ab..90796f09109 100644 --- a/packages/sanity/src/core/form/store/utils/__tests__/immutableReconcile.test.ts +++ b/packages/sanity/src/core/form/store/utils/__tests__/immutableReconcile.test.ts @@ -171,3 +171,16 @@ test('returns new array when previous and next has different length', () => { expect(immutableReconcile(lessItems, moreItems)).not.toBe(lessItems) }) + +test('returns latest non-enumerable value', () => { + const prev = {enumerable: true} + const next = {enumerable: true} + Object.defineProperty(next, 'nonEnumerable', { + value: {foo: 'bar'}, + enumerable: false, + }) + // @ts-expect-error Object.defineProperty + expect(immutableReconcile(next, prev).nonEnumerable).toBeUndefined() + // @ts-expect-error Object.defineProperty + expect(immutableReconcile(prev, next).nonEnumerable).toBe(next.nonEnumerable) +}) diff --git a/packages/sanity/src/core/form/store/utils/getExpandOperations.ts b/packages/sanity/src/core/form/store/utils/getExpandOperations.ts index be285de9c1c..79acae7bc30 100644 --- a/packages/sanity/src/core/form/store/utils/getExpandOperations.ts +++ b/packages/sanity/src/core/form/store/utils/getExpandOperations.ts @@ -107,19 +107,21 @@ function getObjectFieldsetAndFieldGroupOperations( // Group handling const schemaField = node.schemaType.fields.find((field) => field.name === fieldName) const selectedGroupName = node.groups.find((group) => group.selected)?.name - const defaultGroupName = (node.schemaType.groups || []).find((group) => group.default)?.name + const schemaFieldGroup = (schemaField && castArray(schemaField.group)) || [] const inSelectedGroup = selectedGroupName && - (selectedGroupName === ALL_FIELDS_GROUP.name || - (schemaField && castArray(schemaField.group).includes(selectedGroupName))) + (selectedGroupName === ALL_FIELDS_GROUP.name || schemaFieldGroup.includes(selectedGroupName)) const ops: (ExpandFieldSetOperation | SetActiveGroupOperation)[] = [] if (!inSelectedGroup) { + const groupName = + node.groups.find((group) => schemaFieldGroup.includes(group.name))?.name || + ALL_FIELDS_GROUP.name ops.push({ type: 'setSelectedGroup', path: node.path, - groupName: defaultGroupName || ALL_FIELDS_GROUP.name, + groupName, }) } diff --git a/packages/sanity/src/core/form/store/utils/immutableReconcile.ts b/packages/sanity/src/core/form/store/utils/immutableReconcile.ts index 095c1a84dbc..8e8da4d12f1 100644 --- a/packages/sanity/src/core/form/store/utils/immutableReconcile.ts +++ b/packages/sanity/src/core/form/store/utils/immutableReconcile.ts @@ -54,12 +54,14 @@ function _immutableReconcile( assertType>(previous) assertType>(next) - const nextKeys = Object.keys(next) - let allEqual = Object.keys(previous).length === nextKeys.length + const nextKeys = Object.getOwnPropertyNames(next) + let allEqual = Object.getOwnPropertyNames(previous).length === nextKeys.length const result: Record = {} parents.set(next, result) for (const key of nextKeys) { - const nextValue = _immutableReconcile(previous[key], next[key]!, parents) + const nextValue = next.propertyIsEnumerable(key) + ? _immutableReconcile(previous[key], next[key]!, parents) + : next[key] if (nextValue !== previous[key]) { allEqual = false }