@strapi/content-type-builder 5.55.1 → 5.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js +117 -13
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js.map +1 -1
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs +118 -13
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.js +31 -19
- package/dist/admin/components/AIChat/providers/SchemaProvider.js.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs +31 -19
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs.map +1 -1
- package/dist/admin/components/DataManager/DataManagerContext.js.map +1 -1
- package/dist/admin/components/DataManager/DataManagerContext.mjs.map +1 -1
- package/dist/admin/components/DataManager/DataManagerProvider.js +166 -6
- package/dist/admin/components/DataManager/DataManagerProvider.js.map +1 -1
- package/dist/admin/components/DataManager/DataManagerProvider.mjs +165 -7
- package/dist/admin/components/DataManager/DataManagerProvider.mjs.map +1 -1
- package/dist/admin/components/DataManager/RenameMigrationModal.js +285 -0
- package/dist/admin/components/DataManager/RenameMigrationModal.js.map +1 -0
- package/dist/admin/components/DataManager/RenameMigrationModal.mjs +257 -0
- package/dist/admin/components/DataManager/RenameMigrationModal.mjs.map +1 -0
- package/dist/admin/components/DataManager/reducer.js +107 -2
- package/dist/admin/components/DataManager/reducer.js.map +1 -1
- package/dist/admin/components/DataManager/reducer.mjs +106 -2
- package/dist/admin/components/DataManager/reducer.mjs.map +1 -1
- package/dist/admin/components/DataManager/utils/cleanData.js +8 -1
- package/dist/admin/components/DataManager/utils/cleanData.js.map +1 -1
- package/dist/admin/components/DataManager/utils/cleanData.mjs +8 -1
- package/dist/admin/components/DataManager/utils/cleanData.mjs.map +1 -1
- package/dist/admin/components/DataManager/utils/groupRenameChains.js +86 -0
- package/dist/admin/components/DataManager/utils/groupRenameChains.js.map +1 -0
- package/dist/admin/components/DataManager/utils/groupRenameChains.mjs +84 -0
- package/dist/admin/components/DataManager/utils/groupRenameChains.mjs.map +1 -0
- package/dist/admin/components/DataManager/utils/isStorageCompatibleRename.js +29 -0
- package/dist/admin/components/DataManager/utils/isStorageCompatibleRename.js.map +1 -0
- package/dist/admin/components/DataManager/utils/isStorageCompatibleRename.mjs +27 -0
- package/dist/admin/components/DataManager/utils/isStorageCompatibleRename.mjs.map +1 -0
- package/dist/admin/components/DataManager/utils/resolveAfterEditRenameConsent.js +35 -0
- package/dist/admin/components/DataManager/utils/resolveAfterEditRenameConsent.js.map +1 -0
- package/dist/admin/components/DataManager/utils/resolveAfterEditRenameConsent.mjs +33 -0
- package/dist/admin/components/DataManager/utils/resolveAfterEditRenameConsent.mjs.map +1 -0
- package/dist/admin/components/DataManager/utils/splitChainsByInheritedConsent.js +48 -0
- package/dist/admin/components/DataManager/utils/splitChainsByInheritedConsent.js.map +1 -0
- package/dist/admin/components/DataManager/utils/splitChainsByInheritedConsent.mjs +45 -0
- package/dist/admin/components/DataManager/utils/splitChainsByInheritedConsent.mjs.map +1 -0
- package/dist/admin/components/FormModal/FormModal.js +143 -9
- package/dist/admin/components/FormModal/FormModal.js.map +1 -1
- package/dist/admin/components/FormModal/FormModal.mjs +144 -10
- package/dist/admin/components/FormModal/FormModal.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/validation/common.js +6 -5
- package/dist/admin/components/FormModal/attributes/validation/common.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/validation/common.mjs +1 -1
- package/dist/admin/components/FormModal/attributes/validation/common.mjs.map +1 -1
- package/dist/admin/components/FormModal/component/createComponentSchema.js +10 -7
- package/dist/admin/components/FormModal/component/createComponentSchema.js.map +1 -1
- package/dist/admin/components/FormModal/component/createComponentSchema.mjs +1 -1
- package/dist/admin/components/FormModal/component/createComponentSchema.mjs.map +1 -1
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.js +24 -21
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.js.map +1 -1
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.mjs +1 -1
- package/dist/admin/components/FormModal/contentType/createContentTypeSchema.mjs.map +1 -1
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.js +3 -2
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.js.map +1 -1
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.mjs +1 -1
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.mjs.map +1 -1
- package/dist/admin/components/FormModal/utils/getRenameStorageChange.js +73 -0
- package/dist/admin/components/FormModal/utils/getRenameStorageChange.js.map +1 -0
- package/dist/admin/components/FormModal/utils/getRenameStorageChange.mjs +70 -0
- package/dist/admin/components/FormModal/utils/getRenameStorageChange.mjs.map +1 -0
- package/dist/admin/src/components/AIChat/components/AnimatedBox.d.ts +2 -2
- package/dist/admin/src/components/AIChat/components/Input.d.ts +2 -2
- package/dist/admin/src/components/AIChat/lib/transforms/schemas/toCTB.d.ts +4 -3
- package/dist/admin/src/components/AIChat/lib/types/schema.d.ts +6 -1
- package/dist/admin/src/components/AttributeOptions/OptionBoxWrapper.d.ts +2 -2
- package/dist/admin/src/components/ComponentRow.d.ts +2 -2
- package/dist/admin/src/components/DataManager/DataManagerContext.d.ts +28 -2
- package/dist/admin/src/components/DataManager/RenameMigrationModal.d.ts +73 -0
- package/dist/admin/src/components/DataManager/reducer.d.ts +17 -2
- package/dist/admin/src/components/DataManager/utils/cleanData.d.ts +16 -0
- package/dist/admin/src/components/DataManager/utils/groupRenameChains.d.ts +31 -0
- package/dist/admin/src/components/DataManager/utils/isStorageCompatibleRename.d.ts +10 -0
- package/dist/admin/src/components/DataManager/utils/resolveAfterEditRenameConsent.d.ts +24 -0
- package/dist/admin/src/components/DataManager/utils/splitChainsByInheritedConsent.d.ts +26 -0
- package/dist/admin/src/components/FormModal/utils/getRenameStorageChange.d.ts +40 -0
- package/dist/admin/src/components/List.d.ts +2 -2
- package/dist/admin/src/components/Relation/RelationNaturePicker/Components.d.ts +4 -4
- package/dist/admin/src/types.d.ts +23 -0
- package/dist/admin/translations/en.json.js +12 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +12 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/config.js +24 -3
- package/dist/server/config.js.map +1 -1
- package/dist/server/config.mjs +21 -3
- package/dist/server/config.mjs.map +1 -1
- package/dist/server/controllers/schema.js +2 -2
- package/dist/server/controllers/schema.js.map +1 -1
- package/dist/server/controllers/schema.mjs +1 -1
- package/dist/server/controllers/schema.mjs.map +1 -1
- package/dist/server/controllers/validation/content-type.js +9 -11
- package/dist/server/controllers/validation/content-type.js.map +1 -1
- package/dist/server/controllers/validation/content-type.mjs +7 -9
- package/dist/server/controllers/validation/content-type.mjs.map +1 -1
- package/dist/server/controllers/validation/model-schema.js +2 -3
- package/dist/server/controllers/validation/model-schema.js.map +1 -1
- package/dist/server/controllers/validation/model-schema.mjs +1 -2
- package/dist/server/controllers/validation/model-schema.mjs.map +1 -1
- package/dist/server/controllers/validation/relations.js +1 -2
- package/dist/server/controllers/validation/relations.js.map +1 -1
- package/dist/server/controllers/validation/relations.mjs +1 -2
- package/dist/server/controllers/validation/relations.mjs.map +1 -1
- package/dist/server/controllers/validation/schema.js +42 -23
- package/dist/server/controllers/validation/schema.js.map +1 -1
- package/dist/server/controllers/validation/schema.mjs +43 -24
- package/dist/server/controllers/validation/schema.mjs.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/services/content-types.js +1 -2
- package/dist/server/services/content-types.js.map +1 -1
- package/dist/server/services/content-types.mjs +2 -3
- package/dist/server/services/content-types.mjs.map +1 -1
- package/dist/server/services/migration-builder/index.js +580 -0
- package/dist/server/services/migration-builder/index.js.map +1 -0
- package/dist/server/services/migration-builder/index.mjs +573 -0
- package/dist/server/services/migration-builder/index.mjs.map +1 -0
- package/dist/server/services/schema-builder/content-type-builder.js +31 -1
- package/dist/server/services/schema-builder/content-type-builder.js.map +1 -1
- package/dist/server/services/schema-builder/content-type-builder.mjs +31 -1
- package/dist/server/services/schema-builder/content-type-builder.mjs.map +1 -1
- package/dist/server/services/schema-mutation.js +30 -2
- package/dist/server/services/schema-mutation.js.map +1 -1
- package/dist/server/services/schema-mutation.mjs +10 -2
- package/dist/server/services/schema-mutation.mjs.map +1 -1
- package/dist/server/services/schema.js +259 -15
- package/dist/server/services/schema.js.map +1 -1
- package/dist/server/services/schema.mjs +252 -9
- package/dist/server/services/schema.mjs.map +1 -1
- package/dist/server/src/config.d.ts +23 -2
- package/dist/server/src/config.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/content-type.d.ts +0 -1
- package/dist/server/src/controllers/validation/content-type.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/schema.d.ts +28 -0
- package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +10 -2
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/content-types.d.ts.map +1 -1
- package/dist/server/src/services/migration-builder/index.d.ts +83 -0
- package/dist/server/src/services/migration-builder/index.d.ts.map +1 -0
- package/dist/server/src/services/schema-builder/content-type-builder.d.ts.map +1 -1
- package/dist/server/src/services/schema-mutation.d.ts +4 -2
- package/dist/server/src/services/schema-mutation.d.ts.map +1 -1
- package/dist/server/src/services/schema.d.ts +19 -0
- package/dist/server/src/services/schema.d.ts.map +1 -1
- package/package.json +11 -10
|
@@ -52,27 +52,39 @@ const SchemaChatProvider = ({ children })=>{
|
|
|
52
52
|
const schemaChanges = extractSchemaChangesFromMessage(latestMessage);
|
|
53
53
|
// Check if addField action is already completed
|
|
54
54
|
const isAddFieldCompleted = state.completedActions.includes(strapiAdmin.GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
// Changes are applied one at a time: a change that renames existing fields
|
|
56
|
+
// may prompt the user for consent, and prompts must not overlap.
|
|
57
|
+
const applyChanges = async ()=>{
|
|
58
|
+
for (const change of schemaChanges){
|
|
59
|
+
const oldSchema = change.schema.modelType === 'contentType' ? contentTypes[change.schema.uid] : components[change.schema.uid];
|
|
60
|
+
const newSchema = toCTB.transformChatToCTB(change.schema, oldSchema);
|
|
61
|
+
// Check if any attributes/fields are being added to any schema (existing or new)
|
|
62
|
+
if (!isAddFieldCompleted && change.schema.attributes) {
|
|
63
|
+
// If a field is being added or updated, dispatch guided tour action to show Save tooltip
|
|
64
|
+
if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {
|
|
65
|
+
dispatch({
|
|
66
|
+
type: 'set_completed_actions',
|
|
67
|
+
payload: [
|
|
68
|
+
strapiAdmin.GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// eslint-disable-next-line no-await-in-loop
|
|
74
|
+
const applied = await applyChange({
|
|
75
|
+
action: TYPE_TO_ACTION[change.type],
|
|
76
|
+
schema: newSchema
|
|
77
|
+
});
|
|
78
|
+
// The user cancelled a rename prompt: stop here. Earlier changes in this
|
|
79
|
+
// batch stay applied (they are in the undo history); the message is not
|
|
80
|
+
// marked as revised.
|
|
81
|
+
if (!applied) {
|
|
82
|
+
return;
|
|
68
83
|
}
|
|
69
84
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
setLastRevisedId(latestMessage.id);
|
|
85
|
+
setLastRevisedId(latestMessage.id);
|
|
86
|
+
};
|
|
87
|
+
applyChanges();
|
|
76
88
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
77
89
|
}, [
|
|
78
90
|
messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaProvider.js","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\nimport type { Schema } from '../lib/types/schema';\nimport type { Internal } from '@strapi/types';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\ntype SchemaGenerationOutput = {\n schemas?: Schema[];\n error?: unknown;\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as SchemaGenerationOutput | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n
|
|
1
|
+
{"version":3,"file":"SchemaProvider.js","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\nimport type { Schema } from '../lib/types/schema';\nimport type { Internal } from '@strapi/types';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\ntype SchemaGenerationOutput = {\n schemas?: Schema[];\n error?: unknown;\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as SchemaGenerationOutput | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n // Changes are applied one at a time: a change that renames existing fields\n // may prompt the user for consent, and prompts must not overlap.\n const applyChanges = async () => {\n for (const change of schemaChanges) {\n const oldSchema =\n change.schema.modelType === 'contentType'\n ? contentTypes[change.schema.uid as Internal.UID.ContentType]\n : components[change.schema.uid as Internal.UID.Component];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n // eslint-disable-next-line no-await-in-loop\n const applied = await applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n\n // The user cancelled a rename prompt: stop here. Earlier changes in this\n // batch stay applied (they are in the undo history); the message is not\n // marked as revised.\n if (!applied) {\n return;\n }\n }\n\n setLastRevisedId(latestMessage.id);\n };\n\n applyChanges();\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","applyChanges","change","oldSchema","modelType","newSchema","transformChatToCTB","attributes","Object","keys","payload","applied","_jsx","Provider","value"],"mappings":"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"}
|
|
@@ -50,27 +50,39 @@ const SchemaChatProvider = ({ children })=>{
|
|
|
50
50
|
const schemaChanges = extractSchemaChangesFromMessage(latestMessage);
|
|
51
51
|
// Check if addField action is already completed
|
|
52
52
|
const isAddFieldCompleted = state.completedActions.includes(GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
// Changes are applied one at a time: a change that renames existing fields
|
|
54
|
+
// may prompt the user for consent, and prompts must not overlap.
|
|
55
|
+
const applyChanges = async ()=>{
|
|
56
|
+
for (const change of schemaChanges){
|
|
57
|
+
const oldSchema = change.schema.modelType === 'contentType' ? contentTypes[change.schema.uid] : components[change.schema.uid];
|
|
58
|
+
const newSchema = transformChatToCTB(change.schema, oldSchema);
|
|
59
|
+
// Check if any attributes/fields are being added to any schema (existing or new)
|
|
60
|
+
if (!isAddFieldCompleted && change.schema.attributes) {
|
|
61
|
+
// If a field is being added or updated, dispatch guided tour action to show Save tooltip
|
|
62
|
+
if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {
|
|
63
|
+
dispatch({
|
|
64
|
+
type: 'set_completed_actions',
|
|
65
|
+
payload: [
|
|
66
|
+
GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// eslint-disable-next-line no-await-in-loop
|
|
72
|
+
const applied = await applyChange({
|
|
73
|
+
action: TYPE_TO_ACTION[change.type],
|
|
74
|
+
schema: newSchema
|
|
75
|
+
});
|
|
76
|
+
// The user cancelled a rename prompt: stop here. Earlier changes in this
|
|
77
|
+
// batch stay applied (they are in the undo history); the message is not
|
|
78
|
+
// marked as revised.
|
|
79
|
+
if (!applied) {
|
|
80
|
+
return;
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
setLastRevisedId(latestMessage.id);
|
|
83
|
+
setLastRevisedId(latestMessage.id);
|
|
84
|
+
};
|
|
85
|
+
applyChanges();
|
|
74
86
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
87
|
}, [
|
|
76
88
|
messages
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaProvider.mjs","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\nimport type { Schema } from '../lib/types/schema';\nimport type { Internal } from '@strapi/types';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\ntype SchemaGenerationOutput = {\n schemas?: Schema[];\n error?: unknown;\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as SchemaGenerationOutput | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n
|
|
1
|
+
{"version":3,"file":"SchemaProvider.mjs","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\nimport type { Schema } from '../lib/types/schema';\nimport type { Internal } from '@strapi/types';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\ntype SchemaGenerationOutput = {\n schemas?: Schema[];\n error?: unknown;\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as SchemaGenerationOutput | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n // Changes are applied one at a time: a change that renames existing fields\n // may prompt the user for consent, and prompts must not overlap.\n const applyChanges = async () => {\n for (const change of schemaChanges) {\n const oldSchema =\n change.schema.modelType === 'contentType'\n ? contentTypes[change.schema.uid as Internal.UID.ContentType]\n : components[change.schema.uid as Internal.UID.Component];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n // eslint-disable-next-line no-await-in-loop\n const applied = await applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n\n // The user cancelled a rename prompt: stop here. Earlier changes in this\n // batch stay applied (they are in the undo history); the message is not\n // marked as revised.\n if (!applied) {\n return;\n }\n }\n\n setLastRevisedId(latestMessage.id);\n };\n\n applyChanges();\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","applyChanges","change","oldSchema","modelType","newSchema","transformChatToCTB","attributes","Object","keys","payload","applied","_jsx","Provider","value"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataManagerContext.js","sources":["../../../../admin/src/components/DataManager/DataManagerContext.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { createContext } from 'react';\n\nimport type { ContentStructure, FolderSelection, SectionKey } from './utils/contentStructure';\nimport type { Component, ContentType } from '../../types';\nimport type { ComponentWithChildren } from './utils/retrieveComponentsThatHaveComponents';\nimport type { NestedComponent } from './utils/retrieveNestedComponents';\nimport type { Internal, Struct } from '@strapi/types';\n\nexport interface DataManagerContextValue {\n isLoading: boolean;\n addAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n }) => void;\n moveAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n from: number;\n to: number;\n }) => void;\n addCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n }) => void;\n addCreatedComponentToDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n componentsToAdd: Internal.UID.Component[];\n }) => void;\n createComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentCategory: string;\n uid: Internal.UID.Component;\n }) => void;\n createSchema: (opts: {\n data: {\n displayName: string;\n singularName: string;\n pluralName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.Schema;\n folder?: FolderSelection;\n }) => void;\n changeDynamicZoneComponents: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n newComponents: Internal.UID.Component[];\n }) => void;\n removeAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n attributeToRemoveName: string;\n }) => void;\n deleteComponent(uid: Internal.UID.Component): void;\n deleteContentType(uid: Internal.UID.ContentType): void;\n contentStructure: ContentStructure;\n createFolder: (opts: { section: SectionKey; name: string; parentId: string | null }) => void;\n renameFolder: (opts: { section: SectionKey; id: string; name: string }) => void;\n moveFolder: (opts: {\n section: SectionKey;\n id: string;\n newParentId: string | null;\n index?: number;\n }) => void;\n deleteFolderOnly: (opts: { section: SectionKey; id: string }) => void;\n deleteFolderAndContent: (opts: {\n section: SectionKey;\n id: string;\n contentTypeUids: Internal.UID.ContentType[];\n }) => void;\n assignContentTypeToFolder: (opts: {\n section: SectionKey;\n uid: Internal.UID.ContentType;\n targetGroupId: string | null;\n index?: number;\n }) => void;\n reorderFolderChildren: (opts: {\n section: SectionKey;\n groupId: string;\n from: number;\n to: number;\n }) => void;\n removeComponentFromDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dzName: string;\n componentToRemoveIndex: number;\n }) => void;\n sortedContentTypesList: {\n visible: ContentType['visible'];\n name: ContentType['uid'];\n title: ContentType['info']['displayName'];\n plugin: ContentType['plugin'];\n uid: ContentType['uid'];\n to: string;\n kind: ContentType['kind'];\n restrictRelationsTo: ContentType['restrictRelationsTo'];\n status: ContentType['status'];\n }[];\n updateComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentUID: Internal.UID.Component;\n }) => void;\n updateComponentUid: (opts: {\n newComponentUID: Internal.UID.Component;\n componentUID: Internal.UID.Component;\n }) => void;\n updateSchema: (opts: {\n data: {\n displayName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.ContentType;\n folder?: FolderSelection;\n }) => void;\n initialComponents: Record<Internal.UID.Component, Component>;\n components: Record<Internal.UID.Component, Component>;\n componentsGroupedByCategory: Record<string, Component[]>;\n componentsThatHaveOtherComponentInTheirAttributes: ComponentWithChildren[];\n initialContentTypes: Record<Internal.UID.ContentType, ContentType>;\n contentTypes: Record<Internal.UID.ContentType, ContentType>;\n isInDevelopmentMode?: boolean;\n nestedComponents: NestedComponent[];\n reservedNames: {\n models: string[];\n attributes: string[];\n };\n allComponentsCategories: string[];\n saveSchema(): Promise<void>;\n isModified: boolean;\n isSaving: boolean;\n applyChange: (opts: {\n action: 'add' | 'update' | 'delete';\n schema: ContentType | Component;\n }) =>
|
|
1
|
+
{"version":3,"file":"DataManagerContext.js","sources":["../../../../admin/src/components/DataManager/DataManagerContext.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { createContext } from 'react';\n\nimport type { AttributeRenameMigrationMode } from './RenameMigrationModal';\nimport type { ContentStructure, FolderSelection, SectionKey } from './utils/contentStructure';\nimport type { Component, ContentType } from '../../types';\nimport type { ComponentWithChildren } from './utils/retrieveComponentsThatHaveComponents';\nimport type { NestedComponent } from './utils/retrieveNestedComponents';\nimport type { Internal, Struct } from '@strapi/types';\n\nexport interface DataManagerContextValue {\n isLoading: boolean;\n addAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n recordRename?: boolean;\n declineRename?: boolean;\n recordTargetRename?: boolean;\n declineTargetRename?: boolean;\n }) => void;\n moveAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n from: number;\n to: number;\n }) => void;\n addCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n recordRename?: boolean;\n declineRename?: boolean;\n }) => void;\n /**\n * Resolves the user's consent to preserve data for one rename hop performed\n * in the attribute form: `true` records the hop, `false` declines it (and the\n * rest of its chain), `null` means the user cancelled the edit.\n */\n confirmAttributeRenameMigration: (rename: {\n forTarget: Struct.ModelType;\n uid: Internal.UID.Schema;\n oldName: string;\n newName: string;\n }) => Promise<boolean | null>;\n /** Effective `renameMigrations.attributes` plugin setting. */\n attributeRenameMigrationMode: AttributeRenameMigrationMode;\n addCreatedComponentToDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n componentsToAdd: Internal.UID.Component[];\n }) => void;\n createComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentCategory: string;\n uid: Internal.UID.Component;\n }) => void;\n createSchema: (opts: {\n data: {\n displayName: string;\n singularName: string;\n pluralName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.Schema;\n folder?: FolderSelection;\n }) => void;\n changeDynamicZoneComponents: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n newComponents: Internal.UID.Component[];\n }) => void;\n removeAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n attributeToRemoveName: string;\n }) => void;\n deleteComponent(uid: Internal.UID.Component): void;\n deleteContentType(uid: Internal.UID.ContentType): void;\n contentStructure: ContentStructure;\n createFolder: (opts: { section: SectionKey; name: string; parentId: string | null }) => void;\n renameFolder: (opts: { section: SectionKey; id: string; name: string }) => void;\n moveFolder: (opts: {\n section: SectionKey;\n id: string;\n newParentId: string | null;\n index?: number;\n }) => void;\n deleteFolderOnly: (opts: { section: SectionKey; id: string }) => void;\n deleteFolderAndContent: (opts: {\n section: SectionKey;\n id: string;\n contentTypeUids: Internal.UID.ContentType[];\n }) => void;\n assignContentTypeToFolder: (opts: {\n section: SectionKey;\n uid: Internal.UID.ContentType;\n targetGroupId: string | null;\n index?: number;\n }) => void;\n reorderFolderChildren: (opts: {\n section: SectionKey;\n groupId: string;\n from: number;\n to: number;\n }) => void;\n removeComponentFromDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dzName: string;\n componentToRemoveIndex: number;\n }) => void;\n sortedContentTypesList: {\n visible: ContentType['visible'];\n name: ContentType['uid'];\n title: ContentType['info']['displayName'];\n plugin: ContentType['plugin'];\n uid: ContentType['uid'];\n to: string;\n kind: ContentType['kind'];\n restrictRelationsTo: ContentType['restrictRelationsTo'];\n status: ContentType['status'];\n }[];\n updateComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentUID: Internal.UID.Component;\n }) => void;\n updateComponentUid: (opts: {\n newComponentUID: Internal.UID.Component;\n componentUID: Internal.UID.Component;\n }) => void;\n updateSchema: (opts: {\n data: {\n displayName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.ContentType;\n folder?: FolderSelection;\n }) => void;\n initialComponents: Record<Internal.UID.Component, Component>;\n components: Record<Internal.UID.Component, Component>;\n componentsGroupedByCategory: Record<string, Component[]>;\n componentsThatHaveOtherComponentInTheirAttributes: ComponentWithChildren[];\n initialContentTypes: Record<Internal.UID.ContentType, ContentType>;\n contentTypes: Record<Internal.UID.ContentType, ContentType>;\n isInDevelopmentMode?: boolean;\n nestedComponents: NestedComponent[];\n reservedNames: {\n models: string[];\n attributes: string[];\n };\n allComponentsCategories: string[];\n saveSchema(): Promise<void>;\n isModified: boolean;\n isSaving: boolean;\n /**\n * Applies a whole-type change (AI chat). Rename hops declared by the change\n * go through the same preservation consent as manual renames, so this may\n * prompt the user. Resolves `false` when the user cancelled and nothing was\n * applied.\n */\n applyChange: (opts: {\n action: 'add' | 'update' | 'delete';\n schema: ContentType | Component;\n }) => Promise<boolean>;\n history: {\n undo(): void;\n redo(): void;\n discardAllChanges(): void;\n canUndo: boolean;\n canRedo: boolean;\n canDiscardAll: boolean;\n };\n}\n\n// @ts-expect-error need to pass initial value to params\nexport const DataManagerContext = createContext<DataManagerContextValue>();\n"],"names":["DataManagerContext","createContext"],"mappings":";;;;AAuMA;AACO,MAAMA,qBAAqBC,mBAAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataManagerContext.mjs","sources":["../../../../admin/src/components/DataManager/DataManagerContext.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { createContext } from 'react';\n\nimport type { ContentStructure, FolderSelection, SectionKey } from './utils/contentStructure';\nimport type { Component, ContentType } from '../../types';\nimport type { ComponentWithChildren } from './utils/retrieveComponentsThatHaveComponents';\nimport type { NestedComponent } from './utils/retrieveNestedComponents';\nimport type { Internal, Struct } from '@strapi/types';\n\nexport interface DataManagerContextValue {\n isLoading: boolean;\n addAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n }) => void;\n moveAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n from: number;\n to: number;\n }) => void;\n addCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n }) => void;\n addCreatedComponentToDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n componentsToAdd: Internal.UID.Component[];\n }) => void;\n createComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentCategory: string;\n uid: Internal.UID.Component;\n }) => void;\n createSchema: (opts: {\n data: {\n displayName: string;\n singularName: string;\n pluralName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.Schema;\n folder?: FolderSelection;\n }) => void;\n changeDynamicZoneComponents: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n newComponents: Internal.UID.Component[];\n }) => void;\n removeAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n attributeToRemoveName: string;\n }) => void;\n deleteComponent(uid: Internal.UID.Component): void;\n deleteContentType(uid: Internal.UID.ContentType): void;\n contentStructure: ContentStructure;\n createFolder: (opts: { section: SectionKey; name: string; parentId: string | null }) => void;\n renameFolder: (opts: { section: SectionKey; id: string; name: string }) => void;\n moveFolder: (opts: {\n section: SectionKey;\n id: string;\n newParentId: string | null;\n index?: number;\n }) => void;\n deleteFolderOnly: (opts: { section: SectionKey; id: string }) => void;\n deleteFolderAndContent: (opts: {\n section: SectionKey;\n id: string;\n contentTypeUids: Internal.UID.ContentType[];\n }) => void;\n assignContentTypeToFolder: (opts: {\n section: SectionKey;\n uid: Internal.UID.ContentType;\n targetGroupId: string | null;\n index?: number;\n }) => void;\n reorderFolderChildren: (opts: {\n section: SectionKey;\n groupId: string;\n from: number;\n to: number;\n }) => void;\n removeComponentFromDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dzName: string;\n componentToRemoveIndex: number;\n }) => void;\n sortedContentTypesList: {\n visible: ContentType['visible'];\n name: ContentType['uid'];\n title: ContentType['info']['displayName'];\n plugin: ContentType['plugin'];\n uid: ContentType['uid'];\n to: string;\n kind: ContentType['kind'];\n restrictRelationsTo: ContentType['restrictRelationsTo'];\n status: ContentType['status'];\n }[];\n updateComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentUID: Internal.UID.Component;\n }) => void;\n updateComponentUid: (opts: {\n newComponentUID: Internal.UID.Component;\n componentUID: Internal.UID.Component;\n }) => void;\n updateSchema: (opts: {\n data: {\n displayName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.ContentType;\n folder?: FolderSelection;\n }) => void;\n initialComponents: Record<Internal.UID.Component, Component>;\n components: Record<Internal.UID.Component, Component>;\n componentsGroupedByCategory: Record<string, Component[]>;\n componentsThatHaveOtherComponentInTheirAttributes: ComponentWithChildren[];\n initialContentTypes: Record<Internal.UID.ContentType, ContentType>;\n contentTypes: Record<Internal.UID.ContentType, ContentType>;\n isInDevelopmentMode?: boolean;\n nestedComponents: NestedComponent[];\n reservedNames: {\n models: string[];\n attributes: string[];\n };\n allComponentsCategories: string[];\n saveSchema(): Promise<void>;\n isModified: boolean;\n isSaving: boolean;\n applyChange: (opts: {\n action: 'add' | 'update' | 'delete';\n schema: ContentType | Component;\n }) =>
|
|
1
|
+
{"version":3,"file":"DataManagerContext.mjs","sources":["../../../../admin/src/components/DataManager/DataManagerContext.ts"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { createContext } from 'react';\n\nimport type { AttributeRenameMigrationMode } from './RenameMigrationModal';\nimport type { ContentStructure, FolderSelection, SectionKey } from './utils/contentStructure';\nimport type { Component, ContentType } from '../../types';\nimport type { ComponentWithChildren } from './utils/retrieveComponentsThatHaveComponents';\nimport type { NestedComponent } from './utils/retrieveNestedComponents';\nimport type { Internal, Struct } from '@strapi/types';\n\nexport interface DataManagerContextValue {\n isLoading: boolean;\n addAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editAttribute: (opts: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n recordRename?: boolean;\n declineRename?: boolean;\n recordTargetRename?: boolean;\n declineTargetRename?: boolean;\n }) => void;\n moveAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n from: number;\n to: number;\n }) => void;\n addCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n }) => void;\n editCustomFieldAttribute: (params: {\n attributeToSet: Record<string, unknown>;\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n name: string;\n recordRename?: boolean;\n declineRename?: boolean;\n }) => void;\n /**\n * Resolves the user's consent to preserve data for one rename hop performed\n * in the attribute form: `true` records the hop, `false` declines it (and the\n * rest of its chain), `null` means the user cancelled the edit.\n */\n confirmAttributeRenameMigration: (rename: {\n forTarget: Struct.ModelType;\n uid: Internal.UID.Schema;\n oldName: string;\n newName: string;\n }) => Promise<boolean | null>;\n /** Effective `renameMigrations.attributes` plugin setting. */\n attributeRenameMigrationMode: AttributeRenameMigrationMode;\n addCreatedComponentToDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n componentsToAdd: Internal.UID.Component[];\n }) => void;\n createComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentCategory: string;\n uid: Internal.UID.Component;\n }) => void;\n createSchema: (opts: {\n data: {\n displayName: string;\n singularName: string;\n pluralName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.Schema;\n folder?: FolderSelection;\n }) => void;\n changeDynamicZoneComponents: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dynamicZoneTarget: string;\n newComponents: Internal.UID.Component[];\n }) => void;\n removeAttribute: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n attributeToRemoveName: string;\n }) => void;\n deleteComponent(uid: Internal.UID.Component): void;\n deleteContentType(uid: Internal.UID.ContentType): void;\n contentStructure: ContentStructure;\n createFolder: (opts: { section: SectionKey; name: string; parentId: string | null }) => void;\n renameFolder: (opts: { section: SectionKey; id: string; name: string }) => void;\n moveFolder: (opts: {\n section: SectionKey;\n id: string;\n newParentId: string | null;\n index?: number;\n }) => void;\n deleteFolderOnly: (opts: { section: SectionKey; id: string }) => void;\n deleteFolderAndContent: (opts: {\n section: SectionKey;\n id: string;\n contentTypeUids: Internal.UID.ContentType[];\n }) => void;\n assignContentTypeToFolder: (opts: {\n section: SectionKey;\n uid: Internal.UID.ContentType;\n targetGroupId: string | null;\n index?: number;\n }) => void;\n reorderFolderChildren: (opts: {\n section: SectionKey;\n groupId: string;\n from: number;\n to: number;\n }) => void;\n removeComponentFromDynamicZone: (opts: {\n forTarget: Struct.ModelType;\n targetUid: Internal.UID.Schema;\n dzName: string;\n componentToRemoveIndex: number;\n }) => void;\n sortedContentTypesList: {\n visible: ContentType['visible'];\n name: ContentType['uid'];\n title: ContentType['info']['displayName'];\n plugin: ContentType['plugin'];\n uid: ContentType['uid'];\n to: string;\n kind: ContentType['kind'];\n restrictRelationsTo: ContentType['restrictRelationsTo'];\n status: ContentType['status'];\n }[];\n updateComponentSchema: (opts: {\n data: {\n icon?: string;\n displayName: string;\n };\n componentUID: Internal.UID.Component;\n }) => void;\n updateComponentUid: (opts: {\n newComponentUID: Internal.UID.Component;\n componentUID: Internal.UID.Component;\n }) => void;\n updateSchema: (opts: {\n data: {\n displayName: string;\n kind: Struct.ContentTypeKind;\n draftAndPublish: boolean;\n pluginOptions: Record<string, unknown>;\n };\n uid: Internal.UID.ContentType;\n folder?: FolderSelection;\n }) => void;\n initialComponents: Record<Internal.UID.Component, Component>;\n components: Record<Internal.UID.Component, Component>;\n componentsGroupedByCategory: Record<string, Component[]>;\n componentsThatHaveOtherComponentInTheirAttributes: ComponentWithChildren[];\n initialContentTypes: Record<Internal.UID.ContentType, ContentType>;\n contentTypes: Record<Internal.UID.ContentType, ContentType>;\n isInDevelopmentMode?: boolean;\n nestedComponents: NestedComponent[];\n reservedNames: {\n models: string[];\n attributes: string[];\n };\n allComponentsCategories: string[];\n saveSchema(): Promise<void>;\n isModified: boolean;\n isSaving: boolean;\n /**\n * Applies a whole-type change (AI chat). Rename hops declared by the change\n * go through the same preservation consent as manual renames, so this may\n * prompt the user. Resolves `false` when the user cancelled and nothing was\n * applied.\n */\n applyChange: (opts: {\n action: 'add' | 'update' | 'delete';\n schema: ContentType | Component;\n }) => Promise<boolean>;\n history: {\n undo(): void;\n redo(): void;\n discardAllChanges(): void;\n canUndo: boolean;\n canRedo: boolean;\n canDiscardAll: boolean;\n };\n}\n\n// @ts-expect-error need to pass initial value to params\nexport const DataManagerContext = createContext<DataManagerContextValue>();\n"],"names":["DataManagerContext","createContext"],"mappings":";;AAuMA;AACO,MAAMA,qBAAqBC,aAAAA;;;;"}
|
|
@@ -6,6 +6,8 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
|
6
6
|
var groupBy = require('lodash/groupBy');
|
|
7
7
|
var isEqual = require('lodash/isEqual');
|
|
8
8
|
var mapValues = require('lodash/mapValues');
|
|
9
|
+
var omit = require('lodash/omit');
|
|
10
|
+
var uniq = require('lodash/uniq');
|
|
9
11
|
var reactIntl = require('react-intl');
|
|
10
12
|
var reactRedux = require('react-redux');
|
|
11
13
|
var reactRouterDom = require('react-router-dom');
|
|
@@ -17,12 +19,16 @@ var useCTBTracking = require('../CTBSession/useCTBTracking.js');
|
|
|
17
19
|
var useFormModalNavigation = require('../FormModalNavigation/useFormModalNavigation.js');
|
|
18
20
|
var DataManagerContext = require('./DataManagerContext.js');
|
|
19
21
|
var reducer = require('./reducer.js');
|
|
22
|
+
var RenameMigrationModal = require('./RenameMigrationModal.js');
|
|
20
23
|
var useServerRestartWatcher = require('./useServerRestartWatcher.js');
|
|
21
24
|
var cleanData = require('./utils/cleanData.js');
|
|
22
25
|
var contentStructure = require('./utils/contentStructure.js');
|
|
26
|
+
var groupRenameChains = require('./utils/groupRenameChains.js');
|
|
27
|
+
var resolveAfterEditRenameConsent = require('./utils/resolveAfterEditRenameConsent.js');
|
|
23
28
|
var retrieveComponentsThatHaveComponents = require('./utils/retrieveComponentsThatHaveComponents.js');
|
|
24
29
|
var retrieveNestedComponents = require('./utils/retrieveNestedComponents.js');
|
|
25
30
|
var retrieveSpecificInfoFromComponents = require('./utils/retrieveSpecificInfoFromComponents.js');
|
|
31
|
+
var splitChainsByInheritedConsent = require('./utils/splitChainsByInheritedConsent.js');
|
|
26
32
|
|
|
27
33
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
28
34
|
|
|
@@ -48,6 +54,8 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
48
54
|
var groupBy__default = /*#__PURE__*/_interopDefault(groupBy);
|
|
49
55
|
var isEqual__default = /*#__PURE__*/_interopDefault(isEqual);
|
|
50
56
|
var mapValues__default = /*#__PURE__*/_interopDefault(mapValues);
|
|
57
|
+
var omit__default = /*#__PURE__*/_interopDefault(omit);
|
|
58
|
+
var uniq__default = /*#__PURE__*/_interopDefault(uniq);
|
|
51
59
|
|
|
52
60
|
/**
|
|
53
61
|
* Including the new folder state in the same payload as create/edit transactions ensures the
|
|
@@ -78,7 +86,9 @@ const selectState = (state)=>state['content-type-builder_dataManagerProvider'] |
|
|
|
78
86
|
'InitialData',
|
|
79
87
|
'ContentTypesConfiguration',
|
|
80
88
|
'ContentTypeSettings',
|
|
81
|
-
'ComponentConfiguration'
|
|
89
|
+
'ComponentConfiguration',
|
|
90
|
+
// Existing cached documents still use the pre-change field names.
|
|
91
|
+
'Document'
|
|
82
92
|
];
|
|
83
93
|
const invalidateContentManagerSchemaCaches = ()=>strapiAdmin.adminApi.util.invalidateTags(CONTENT_MANAGER_SCHEMA_CACHE_TAGS);
|
|
84
94
|
const DataManagerProvider = ({ children })=>{
|
|
@@ -100,6 +110,10 @@ const DataManagerProvider = ({ children })=>{
|
|
|
100
110
|
const { onCloseModal } = useFormModalNavigation.useFormModalNavigation();
|
|
101
111
|
const [isSaving, setIsSaving] = React__namespace.useState(false);
|
|
102
112
|
const previousLocationRef = React__namespace.useRef(null);
|
|
113
|
+
const renameMigrationModeRef = React__namespace.useRef('prompt-before-save');
|
|
114
|
+
// When `modal` mode prompts the user, we hold the pending renames plus the
|
|
115
|
+
// promise resolver here so `saveSchema` can await the decision.
|
|
116
|
+
const [renameModal, setRenameModal] = React__namespace.useState(null);
|
|
103
117
|
const isModified = React__namespace.useMemo(()=>{
|
|
104
118
|
return !(isEqual__default.default(components, initialComponents) && isEqual__default.default(contentTypes, initialContentTypes) && isEqual__default.default(contentStructure$1, initialContentStructure));
|
|
105
119
|
}, [
|
|
@@ -119,7 +133,10 @@ const DataManagerProvider = ({ children })=>{
|
|
|
119
133
|
fetchClient.get(`/content-type-builder/schema`),
|
|
120
134
|
fetchClient.get(`/content-type-builder/reserved-names`)
|
|
121
135
|
]);
|
|
122
|
-
const { components, contentTypes, contentStructure: contentStructure$1 } = schemaResponse.data.data;
|
|
136
|
+
const { components, contentTypes, contentStructure: contentStructure$1, settings } = schemaResponse.data.data;
|
|
137
|
+
if (settings?.renameMigrations?.attributes) {
|
|
138
|
+
renameMigrationModeRef.current = settings.renameMigrations.attributes;
|
|
139
|
+
}
|
|
123
140
|
dispatch(reducer.actions.init({
|
|
124
141
|
components: mapValues__default.default(components, (component)=>({
|
|
125
142
|
...component,
|
|
@@ -198,6 +215,16 @@ const DataManagerProvider = ({ children })=>{
|
|
|
198
215
|
const updatePermissions = async ()=>{
|
|
199
216
|
await refetchPermissions();
|
|
200
217
|
};
|
|
218
|
+
const requestRenameDecision = async (renames)=>{
|
|
219
|
+
const acceptedKeys = await new Promise((resolve)=>{
|
|
220
|
+
setRenameModal({
|
|
221
|
+
renames,
|
|
222
|
+
resolve
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
setRenameModal(null);
|
|
226
|
+
return acceptedKeys;
|
|
227
|
+
};
|
|
201
228
|
const saveSchema = async ()=>{
|
|
202
229
|
setIsSaving(true);
|
|
203
230
|
const PluginForms = plugin?.apis?.forms;
|
|
@@ -211,6 +238,18 @@ const DataManagerProvider = ({ children })=>{
|
|
|
211
238
|
contentStructure: state.current.contentStructure,
|
|
212
239
|
initialContentStructure: state.current.initialContentStructure
|
|
213
240
|
});
|
|
241
|
+
if (RenameMigrationModal.shouldPromptForRenamesBeforeSave(renameMigrationModeRef.current)) {
|
|
242
|
+
const pendingRenames = RenameMigrationModal.collectPendingRenames(requestData);
|
|
243
|
+
if (pendingRenames.length > 0) {
|
|
244
|
+
const acceptedKeys = await requestRenameDecision(pendingRenames);
|
|
245
|
+
// The user cancelled the whole save — return to editing untouched.
|
|
246
|
+
if (acceptedKeys === null) {
|
|
247
|
+
setIsSaving(false);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
RenameMigrationModal.applyRenameDecisions(requestData, acceptedKeys);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
214
253
|
// Track that the save button was clicked (includes session ID via useCTBTracking)
|
|
215
254
|
trackUsage('willUpdateCTBSchema', {
|
|
216
255
|
...trackingEventProperties,
|
|
@@ -316,6 +355,7 @@ const DataManagerProvider = ({ children })=>{
|
|
|
316
355
|
componentsGroupedByCategory,
|
|
317
356
|
sortedContentTypesList,
|
|
318
357
|
isLoading,
|
|
358
|
+
attributeRenameMigrationMode: renameMigrationModeRef.current,
|
|
319
359
|
addAttribute (payload) {
|
|
320
360
|
dispatch(reducer.actions.addAttribute({
|
|
321
361
|
...payload,
|
|
@@ -340,6 +380,49 @@ const DataManagerProvider = ({ children })=>{
|
|
|
340
380
|
attributeToSet: payload.attributeToSet
|
|
341
381
|
}));
|
|
342
382
|
},
|
|
383
|
+
async confirmAttributeRenameMigration ({ forTarget, uid, oldName, newName }) {
|
|
384
|
+
if (oldName === newName) {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
const schema = forTarget === 'contentType' ? contentTypes[uid] : components[uid];
|
|
388
|
+
// A field that was never saved has no data to preserve: accept without
|
|
389
|
+
// prompting so neither name ends up in `declinedRenameNames`.
|
|
390
|
+
const initialAttribute = schema?.attributes.find((attribute)=>attribute.name === oldName);
|
|
391
|
+
if (initialAttribute?.status === 'NEW') {
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
// Consent inherits along a chain: a hop joining an accepted chain is
|
|
395
|
+
// accepted, one touching a declined name is declined, neither prompts.
|
|
396
|
+
const consent = resolveAfterEditRenameConsent.resolveAfterEditRenameConsent({
|
|
397
|
+
renames: schema?.renames ?? [],
|
|
398
|
+
declinedRenameNames: schema?.declinedRenameNames ?? [],
|
|
399
|
+
oldName,
|
|
400
|
+
newName,
|
|
401
|
+
mode: renameMigrationModeRef.current
|
|
402
|
+
});
|
|
403
|
+
if (consent !== 'prompt') {
|
|
404
|
+
return consent === 'accept';
|
|
405
|
+
}
|
|
406
|
+
const key = `${uid}:edit`;
|
|
407
|
+
const acceptedKeys = await requestRenameDecision([
|
|
408
|
+
{
|
|
409
|
+
key,
|
|
410
|
+
uid,
|
|
411
|
+
typeName: schema?.info.displayName ?? uid,
|
|
412
|
+
pairs: [
|
|
413
|
+
{
|
|
414
|
+
oldName,
|
|
415
|
+
newName
|
|
416
|
+
}
|
|
417
|
+
],
|
|
418
|
+
via: []
|
|
419
|
+
}
|
|
420
|
+
]);
|
|
421
|
+
if (acceptedKeys === null) {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
return acceptedKeys.has(key);
|
|
425
|
+
},
|
|
343
426
|
addCreatedComponentToDynamicZone (payload) {
|
|
344
427
|
dispatch(reducer.actions.addCreatedComponentToDynamicZone(payload));
|
|
345
428
|
},
|
|
@@ -445,8 +528,78 @@ const DataManagerProvider = ({ children })=>{
|
|
|
445
528
|
moveAttribute (args) {
|
|
446
529
|
dispatch(reducer.actions.moveAttribute(args));
|
|
447
530
|
},
|
|
448
|
-
applyChange (
|
|
449
|
-
|
|
531
|
+
async applyChange ({ action, schema }) {
|
|
532
|
+
const renames = schema.renames ?? [];
|
|
533
|
+
if (action !== 'update' || renames.length === 0) {
|
|
534
|
+
dispatch(reducer.actions.applyChange({
|
|
535
|
+
action,
|
|
536
|
+
schema
|
|
537
|
+
}));
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
const mode = renameMigrationModeRef.current;
|
|
541
|
+
if (mode === 'never') {
|
|
542
|
+
dispatch(reducer.actions.applyChange({
|
|
543
|
+
action,
|
|
544
|
+
schema: omit__default.default(schema, [
|
|
545
|
+
'renames'
|
|
546
|
+
])
|
|
547
|
+
}));
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
// 'always' | 'prompt-before-save': the before-save modal decides per chain.
|
|
551
|
+
if (mode !== 'prompt-after-edit') {
|
|
552
|
+
dispatch(reducer.actions.applyChange({
|
|
553
|
+
action,
|
|
554
|
+
schema
|
|
555
|
+
}));
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
// 'prompt-after-edit': decide per chain now, inheriting consent already
|
|
559
|
+
// given (or refused) for the hops recorded on the type.
|
|
560
|
+
const existing = schema.modelType === 'contentType' ? contentTypes[schema.uid] : components[schema.uid];
|
|
561
|
+
const chains = groupRenameChains.groupRenameChains(schema.uid, renames);
|
|
562
|
+
const { keep, prompt } = splitChainsByInheritedConsent.splitChainsByInheritedConsent({
|
|
563
|
+
recorded: existing?.renames ?? [],
|
|
564
|
+
declinedRenameNames: existing?.declinedRenameNames ?? [],
|
|
565
|
+
chains,
|
|
566
|
+
renames
|
|
567
|
+
});
|
|
568
|
+
const accepted = new Set(keep.map((chain)=>chain.id));
|
|
569
|
+
if (prompt.length > 0) {
|
|
570
|
+
const typeName = schema.info?.displayName ?? schema.uid;
|
|
571
|
+
const decision = await requestRenameDecision(prompt.map((chain)=>RenameMigrationModal.toPendingRename(chain, renames, {
|
|
572
|
+
uid: schema.uid,
|
|
573
|
+
typeName
|
|
574
|
+
})));
|
|
575
|
+
// The user cancelled: apply nothing.
|
|
576
|
+
if (decision === null) {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
decision.forEach((id)=>accepted.add(id));
|
|
580
|
+
}
|
|
581
|
+
const declinedChains = chains.filter((chain)=>!accepted.has(chain.id));
|
|
582
|
+
const keptRenames = RenameMigrationModal.filterRenamesByAcceptedChains(schema.uid, renames, accepted);
|
|
583
|
+
const declinedRenameNames = uniq__default.default([
|
|
584
|
+
...schema.declinedRenameNames ?? [],
|
|
585
|
+
...splitChainsByInheritedConsent.namesOfChains(declinedChains, renames)
|
|
586
|
+
]);
|
|
587
|
+
dispatch(reducer.actions.applyChange({
|
|
588
|
+
action,
|
|
589
|
+
schema: {
|
|
590
|
+
...omit__default.default(schema, [
|
|
591
|
+
'renames',
|
|
592
|
+
'declinedRenameNames'
|
|
593
|
+
]),
|
|
594
|
+
...keptRenames.length > 0 ? {
|
|
595
|
+
renames: keptRenames
|
|
596
|
+
} : {},
|
|
597
|
+
...declinedRenameNames.length > 0 ? {
|
|
598
|
+
declinedRenameNames
|
|
599
|
+
} : {}
|
|
600
|
+
}
|
|
601
|
+
}));
|
|
602
|
+
return true;
|
|
450
603
|
},
|
|
451
604
|
history: {
|
|
452
605
|
undo () {
|
|
@@ -463,9 +616,16 @@ const DataManagerProvider = ({ children })=>{
|
|
|
463
616
|
canDiscardAll: isModified
|
|
464
617
|
}
|
|
465
618
|
};
|
|
466
|
-
return /*#__PURE__*/ jsxRuntime.
|
|
619
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(DataManagerContext.DataManagerContext.Provider, {
|
|
467
620
|
value: context,
|
|
468
|
-
children:
|
|
621
|
+
children: [
|
|
622
|
+
children,
|
|
623
|
+
renameModal && /*#__PURE__*/ jsxRuntime.jsx(RenameMigrationModal.RenameMigrationModal, {
|
|
624
|
+
renames: renameModal.renames,
|
|
625
|
+
onConfirm: (acceptedKeys)=>renameModal.resolve(acceptedKeys),
|
|
626
|
+
onCancel: ()=>renameModal.resolve(null)
|
|
627
|
+
})
|
|
628
|
+
]
|
|
469
629
|
});
|
|
470
630
|
};
|
|
471
631
|
|