-
Notifications
You must be signed in to change notification settings - Fork 105
[7418] plugin - serializers/retrievers/validators #8882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,6 +126,7 @@ import SectionAccordion from './components/SectionAccordion'; | |
| import useSaveForm from './lib/useSaveForm'; | ||
| import { FormPrepError } from './components/FormPrepError'; | ||
| import { createParsedValuesObject } from './lib/valueRetrievers'; | ||
| import { preloadControlPluginsForFields } from './lib/controlPluginLoader'; | ||
| import { fromString } from '../../utils/xml'; | ||
| import { displayWithPendingChangesConfirm } from '../../utils/ui'; | ||
| import useActiveUser from '../../hooks/useActiveUser'; | ||
|
|
@@ -334,6 +335,7 @@ function FormBootstrap(props: FormsEngineProps) { | |
| useEffect(() => { | ||
| // Guard statement: If content types are not loaded, we can't proceed. | ||
| if (!contentTypesLoaded) return; | ||
| let disposed = false; | ||
| // TODO: If props are changed, things can be left off... previous item locked, edits get lost, etc. Not sure how much support for prop changes we should implement. | ||
| const isChildForm = stackIndex > 0; | ||
| // In the form stack, the present form being opened would be in the last position [length-1], the parent form state would be on [length-2] if it is nested (e.g. Root => Component(L1) => Repeat(L2)|Component(L2)). Otherwise,the parent should be the root. | ||
|
|
@@ -494,43 +496,54 @@ function FormBootstrap(props: FormsEngineProps) { | |
| fileName: atom('') | ||
| }); | ||
| const contentObject = createObjectWithSystemProps(contentType); | ||
| const values = createParsedValuesObject( | ||
| contentType.fields, | ||
| contentObject, | ||
| contentTypesById, | ||
| (fieldId, value, isAdditional) => { | ||
| setFieldAtoms( | ||
| stableFormContextRef, | ||
| contentType, | ||
| contentType.fields, | ||
| fieldId, | ||
| atoms, | ||
| value, | ||
| { siteId, contentTypesById }, | ||
| isAdditional | ||
| ); | ||
| }, | ||
| customControls | ||
| ); | ||
| const { [XmlKeys.fileName]: _, ...valuesWithoutFileName } = values; | ||
| const initCreateForm = () => { | ||
| if (disposed) return; | ||
| const values = createParsedValuesObject( | ||
| contentType.fields, | ||
| contentObject, | ||
| contentTypesById, | ||
| (fieldId, value, isAdditional) => { | ||
| setFieldAtoms( | ||
| stableFormContextRef, | ||
| contentType, | ||
| contentType.fields, | ||
| fieldId, | ||
| atoms, | ||
| value, | ||
| { siteId, contentTypesById }, | ||
| isAdditional | ||
| ); | ||
| }, | ||
| customControls | ||
| ); | ||
| const { [XmlKeys.fileName]: _, ...valuesWithoutFileName } = values; | ||
|
|
||
| const objectId = contentObject[XmlKeys.modelId] as string; | ||
| initializeState(atoms, values, { | ||
| id: objectId, | ||
| // TODO: Should/could we somehow deduce the target path? | ||
| path: null, | ||
| // TODO: Sourcemap? How can we determine what would be inherited by this content? New API? | ||
| sourceMap: null, | ||
| pathInSite: processPathMacros({ | ||
| path: create.path, | ||
| objectId, | ||
| fullParentPath: '', | ||
| useUUID: false | ||
| }), | ||
| contentType, | ||
| contentObject, | ||
| contentXml: buildContentXml(valuesWithoutFileName, contentTypesById) | ||
| }); | ||
| const objectId = contentObject[XmlKeys.modelId] as string; | ||
| initializeState(atoms, values, { | ||
| id: objectId, | ||
| // TODO: Should/could we somehow deduce the target path? | ||
| path: null, | ||
| // TODO: Sourcemap? How can we determine what would be inherited by this content? New API? | ||
| sourceMap: null, | ||
| pathInSite: processPathMacros({ | ||
| path: create.path, | ||
| objectId, | ||
| fullParentPath: '', | ||
| useUUID: false | ||
| }), | ||
| contentType, | ||
| contentObject, | ||
| contentXml: buildContentXml(valuesWithoutFileName, contentTypesById) | ||
| }); | ||
| }; | ||
| preloadControlPluginsForFields(siteId, contentType.fields) | ||
| .catch((error) => { | ||
| console.error('Failed to preload control plugins before create-form value parse.', error); | ||
| }) | ||
| .then(initCreateForm); | ||
|
Comment on lines
+539
to
+543
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Stop form initialization when control-plugin preload fails. Both paths catch the preload rejection and then parse values without plugin hooks. This can load or save plugin field data with incorrect conversions.
📍 Affects 1 file
🤖 Prompt for AI Agents |
||
| return () => { | ||
| disposed = true; | ||
| }; | ||
|
Comment on lines
+539
to
+546
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift Preload plugins for embedded child forms. The embedded-component branch at Lines 443-478 calls Preload the embedded content type fields before 🤖 Prompt for AI Agents |
||
| } /* if (isUpdateMode) */ else { | ||
| const subscription = fetchUpdateRequirements({ | ||
| siteId, | ||
|
|
@@ -570,37 +583,47 @@ function FormBootstrap(props: FormsEngineProps) { | |
| expandedStateBySectionId: buildSectionExpandedStateAtoms(requirements.contentType.sections), | ||
| fileName: createFileNameAtom(requirements.item.path) | ||
| }); | ||
| const values = createParsedValuesObject( | ||
| requirements.contentType.fields, | ||
| requirements.contentObject, | ||
| effectRefs.current.contentTypesById, | ||
| (fieldId, value, isAdditional) => { | ||
| setFieldAtoms( | ||
| stableFormContextRef, | ||
| requirements.contentType, | ||
| preloadControlPluginsForFields(siteId, requirements.contentType.fields) | ||
| .catch((error) => { | ||
| console.error('Failed to preload control plugins before edit-form value parse.', error); | ||
| }) | ||
| .then(() => { | ||
| if (disposed) return; | ||
| const values = createParsedValuesObject( | ||
| requirements.contentType.fields, | ||
| fieldId, | ||
| atoms, | ||
| value, | ||
| { siteId, contentTypesById }, | ||
| isAdditional | ||
| requirements.contentObject, | ||
| effectRefs.current.contentTypesById, | ||
| (fieldId, value, isAdditional) => { | ||
| setFieldAtoms( | ||
| stableFormContextRef, | ||
| requirements.contentType, | ||
| requirements.contentType.fields, | ||
| fieldId, | ||
| atoms, | ||
| value, | ||
| { siteId, contentTypesById: effectRefs.current.contentTypesById }, | ||
| isAdditional | ||
| ); | ||
| }, | ||
| customControls | ||
| ); | ||
| }, | ||
| customControls | ||
| ); | ||
|
|
||
| initializeState(atoms, values, { | ||
| id: values[XmlKeys.modelId] as string, | ||
| path: requirements.item.path, | ||
| // TODO: Sourcemap? How can we determine what would be inherited by this content? New API? | ||
| sourceMap: requirements.sourceMap, | ||
| pathInSite: requirements.pathInSite, | ||
| contentType: requirements.contentType, | ||
| contentXml: requirements.contentXml, | ||
| contentObject: requirements.contentObject | ||
| }); | ||
| initializeState(atoms, values, { | ||
| id: values[XmlKeys.modelId] as string, | ||
| path: requirements.item.path, | ||
| // TODO: Sourcemap? How can we determine what would be inherited by this content? New API? | ||
| sourceMap: requirements.sourceMap, | ||
| pathInSite: requirements.pathInSite, | ||
| contentType: requirements.contentType, | ||
| contentXml: requirements.contentXml, | ||
| contentObject: requirements.contentObject | ||
| }); | ||
| }); | ||
| }); | ||
| return () => subscription.unsubscribe(); | ||
| return () => { | ||
| disposed = true; | ||
| subscription.unsubscribe(); | ||
| }; | ||
| } | ||
| }, [ | ||
| contentTypesLoaded, | ||
|
|
@@ -1231,7 +1254,6 @@ export default FormGuard; | |
| // - Where do we put the "config" to determine whether to use new or old form engine? | ||
| // - Form controller loading and execution | ||
| // - FOR LATER... | ||
| // - Allow overriding/extending validators, retrievers, [and maybe] controlMap through plugins | ||
| // - Inherited non overridable if not in the model | ||
| // - AI | ||
| // - Edit template & controller | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Synchronize the retired control entries with Open decisions.
Line 670 says
link-input,link-textarea, andlinked-dropdownwere removed. It also says the former open item is closed. Line 654 still lists retired IDs and remapped aliases as unresolved. Update Line 654, or remove the entry if no null map slots remain, so the document has one completion status.Proposed documentation fix
As per path instructions, update the Progress and Open decisions sections in
studio-ui/docs/type-builder-forms-engine.mdin the same effort.🤖 Prompt for AI Agents
Source: Coding guidelines