@ai-stack/payloadcms 3.68.0-beta.2 → 3.68.0-beta.4
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/ai/core/media/image/generateImage.js +2 -6
- package/dist/ai/core/media/image/generateImage.js.map +1 -1
- package/dist/ai/prompts.d.ts +1 -2
- package/dist/ai/prompts.js +0 -110
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
- package/dist/ai/providers/blocks/google.js +9 -5
- package/dist/ai/providers/blocks/google.js.map +1 -1
- package/dist/ai/providers/blocks/openai.js +1 -1
- package/dist/ai/providers/blocks/openai.js.map +1 -1
- package/dist/ai/providers/registry.js +0 -1
- package/dist/ai/providers/registry.js.map +1 -1
- package/dist/ai/utils/filterEditorSchemaByNodes.d.ts +9 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.js +30 -3
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +1 -1
- package/dist/ai/utils/nodeToSchemaMap.d.ts +22 -0
- package/dist/ai/utils/nodeToSchemaMap.js +72 -0
- package/dist/ai/utils/nodeToSchemaMap.js.map +1 -0
- package/dist/collections/AISettings.js +44 -17
- package/dist/collections/AISettings.js.map +1 -1
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +8 -0
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/fetchFields.js +10 -0
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/endpoints/index.js +12 -0
- package/dist/endpoints/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +16 -32
- package/dist/plugin.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +44 -15
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +36 -16
- package/dist/providers/InstructionsProvider/context.d.ts +3 -0
- package/dist/providers/InstructionsProvider/context.js +2 -0
- package/dist/providers/InstructionsProvider/context.js.map +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.js +3 -1
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/types.d.ts +1 -5
- package/dist/types.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.js +198 -22
- package/dist/ui/AIConfigDashboard/index.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.jsx +159 -13
- package/dist/ui/Compose/Compose.js +21 -2
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +21 -2
- package/dist/ui/Compose/hooks/useGenerate.js +26 -174
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerateUpload.d.ts +11 -0
- package/dist/ui/Compose/hooks/useGenerateUpload.js +150 -0
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.d.ts +8 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.js +48 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -0
- package/dist/ui/EncryptedTextField/index.js +4 -4
- package/dist/ui/EncryptedTextField/index.js.map +1 -1
- package/dist/ui/EncryptedTextField/index.jsx +4 -4
- package/dist/utilities/buildSmartPrompt.js +4 -6
- package/dist/utilities/buildSmartPrompt.js.map +1 -1
- package/dist/utilities/encryption.js +2 -1
- package/dist/utilities/encryption.js.map +1 -1
- package/dist/utilities/seedProperties.d.ts +7 -0
- package/dist/utilities/seedProperties.js +100 -0
- package/dist/utilities/seedProperties.js.map +1 -0
- package/dist/utilities/setSafeLexicalState.js +79 -6
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/dist/utilities/updateFieldsConfig.d.ts +1 -1
- package/dist/utilities/updateFieldsConfig.js +1 -0
- package/dist/utilities/updateFieldsConfig.js.map +1 -1
- package/package.json +2 -1
- package/dist/init.d.ts +0 -7
- package/dist/init.js +0 -152
- package/dist/init.js.map +0 -1
|
@@ -13,6 +13,7 @@ export const InstructionsProvider = ({ children })=>{
|
|
|
13
13
|
const [activeCollection, setActiveCollection] = useState('');
|
|
14
14
|
const [isConfigAllowed, setIsConfigAllowed] = useState(false);
|
|
15
15
|
const [enabledLanguages, setEnabledLanguages] = useState();
|
|
16
|
+
const [enabledCollections, setEnabledCollections] = useState();
|
|
16
17
|
const [debugging, setDebugging] = useState(false);
|
|
17
18
|
const { user } = useAuth();
|
|
18
19
|
const { config } = useConfig();
|
|
@@ -37,44 +38,72 @@ export const InstructionsProvider = ({ children })=>{
|
|
|
37
38
|
drawerOpenCount,
|
|
38
39
|
openPayloadDrawer
|
|
39
40
|
]);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const handleSave = useCallback(({ doc })=>{
|
|
42
|
+
setInstructionsState((prev)=>{
|
|
43
|
+
return {
|
|
44
|
+
...prev,
|
|
45
|
+
[doc['schema-path']]: {
|
|
46
|
+
id: doc.id,
|
|
47
|
+
disabled: !!doc.disabled,
|
|
48
|
+
fieldType: doc['field-type']
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}, [
|
|
53
|
+
setInstructionsState
|
|
54
|
+
]);
|
|
55
|
+
const fetchFieldsData = useCallback(async ()=>{
|
|
43
56
|
// Only fetch if we have a user ID - prevents fetching on every user object reference change
|
|
44
57
|
if (!user?.id) {
|
|
45
58
|
return;
|
|
46
59
|
}
|
|
47
|
-
|
|
48
|
-
await
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
try {
|
|
61
|
+
const res = await fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`);
|
|
62
|
+
const data = await res.json();
|
|
63
|
+
setIsConfigAllowed(data?.isConfigAllowed || false);
|
|
64
|
+
setEnabledLanguages(data?.enabledLanguages || []);
|
|
65
|
+
setEnabledCollections(data?.enabledCollections || []);
|
|
66
|
+
setInstructionsState(data?.fields || {});
|
|
67
|
+
setPromptFields(data?.promptFields || []);
|
|
68
|
+
setDebugging(data?.debugging || false);
|
|
69
|
+
} catch (err) {
|
|
56
70
|
console.error('InstructionsProvider:', err);
|
|
57
|
-
}
|
|
71
|
+
}
|
|
58
72
|
}, [
|
|
59
73
|
api,
|
|
60
74
|
serverURL,
|
|
61
75
|
user?.id
|
|
62
76
|
]);
|
|
77
|
+
useEffect(()=>{
|
|
78
|
+
void fetchFieldsData();
|
|
79
|
+
}, [
|
|
80
|
+
fetchFieldsData
|
|
81
|
+
]);
|
|
82
|
+
const refresh = useCallback(async ()=>{
|
|
83
|
+
await fetchFieldsData();
|
|
84
|
+
}, [
|
|
85
|
+
fetchFieldsData
|
|
86
|
+
]);
|
|
63
87
|
return /*#__PURE__*/ _jsxs(InstructionsContext.Provider, {
|
|
64
88
|
value: {
|
|
65
89
|
activeCollection,
|
|
66
90
|
debugging,
|
|
91
|
+
enabledCollections,
|
|
67
92
|
enabledLanguages,
|
|
68
93
|
hasInstructions: instructions && Object.keys(instructions).length > 0,
|
|
69
94
|
instructions,
|
|
70
95
|
isConfigAllowed,
|
|
71
96
|
openDrawer,
|
|
72
97
|
promptFields,
|
|
73
|
-
|
|
98
|
+
refresh,
|
|
99
|
+
setActiveCollection,
|
|
100
|
+
setEnabledCollections
|
|
74
101
|
},
|
|
75
102
|
children: [
|
|
76
103
|
children,
|
|
77
|
-
/*#__PURE__*/ _jsx(DocumentDrawer, {
|
|
104
|
+
/*#__PURE__*/ _jsx(DocumentDrawer, {
|
|
105
|
+
onSave: handleSave
|
|
106
|
+
})
|
|
78
107
|
]
|
|
79
108
|
});
|
|
80
109
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport { useAuth, useConfig, useDocumentDrawer } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { useActiveFieldTracking } from '../../ui/Compose/hooks/useActiveFieldTracking.js'\nimport { InstructionsContext } from './context.js'\n\nexport const InstructionsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n // Initialize field tracking globally so ai-plugin-active class is added on field focus\n useActiveFieldTracking()\n
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport { useAuth, useConfig, useDocumentDrawer } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { useActiveFieldTracking } from '../../ui/Compose/hooks/useActiveFieldTracking.js'\nimport { InstructionsContext } from './context.js'\n\nexport const InstructionsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n // Initialize field tracking globally so ai-plugin-active class is added on field focus\n useActiveFieldTracking()\n\n const [instructions, setInstructionsState] = useState({})\n const [promptFields, setPromptFields] = useState<SerializedPromptField[]>([])\n const [activeCollection, setActiveCollection] = useState('')\n const [isConfigAllowed, setIsConfigAllowed] = useState(false)\n const [enabledLanguages, setEnabledLanguages] = useState<string[]>()\n const [enabledCollections, setEnabledCollections] = useState<string[]>()\n const [debugging, setDebugging] = useState(false)\n const { user } = useAuth()\n\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n\n // Global Document Drawer state\n const [drawerInstructionId, setDrawerInstructionId] = useState<string>('')\n const [drawerOpenCount, setDrawerOpenCount] = useState(0)\n\n const [DocumentDrawer, _, { openDrawer: openPayloadDrawer }] = useDocumentDrawer({\n id: drawerInstructionId,\n collectionSlug: PLUGIN_INSTRUCTIONS_TABLE,\n })\n\n const openDrawer = useCallback((id: string) => {\n setDrawerInstructionId(id)\n setDrawerOpenCount((prev) => prev + 1)\n }, [])\n\n // Open drawer when count changes\n useEffect(() => {\n if (drawerOpenCount > 0) {\n openPayloadDrawer()\n }\n }, [drawerOpenCount, openPayloadDrawer])\n\n const handleSave = useCallback(\n ({ doc }: { doc: any }) => {\n setInstructionsState((prev) => {\n return {\n ...prev,\n [doc['schema-path']]: {\n id: doc.id,\n disabled: !!doc.disabled,\n fieldType: doc['field-type'],\n },\n }\n })\n },\n [setInstructionsState],\n )\n\n const fetchFieldsData = useCallback(async () => {\n // Only fetch if we have a user ID - prevents fetching on every user object reference change\n if (!user?.id) {\n return\n }\n\n try {\n const res = await fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`)\n const data = await res.json()\n setIsConfigAllowed(data?.isConfigAllowed || false)\n setEnabledLanguages(data?.enabledLanguages || [])\n setEnabledCollections(data?.enabledCollections || [])\n setInstructionsState(data?.fields || {})\n setPromptFields(data?.promptFields || [])\n setDebugging(data?.debugging || false)\n } catch (err) {\n console.error('InstructionsProvider:', err)\n }\n }, [api, serverURL, user?.id])\n\n useEffect(() => {\n void fetchFieldsData()\n }, [fetchFieldsData])\n\n const refresh = useCallback(async () => {\n await fetchFieldsData()\n }, [fetchFieldsData])\n\n return (\n <InstructionsContext.Provider\n value={{\n activeCollection,\n debugging,\n enabledCollections,\n enabledLanguages,\n hasInstructions: instructions && Object.keys(instructions).length > 0,\n instructions,\n isConfigAllowed,\n openDrawer,\n promptFields,\n refresh,\n setActiveCollection,\n setEnabledCollections,\n }}\n >\n {children}\n <DocumentDrawer onSave={handleSave} />\n </InstructionsContext.Provider>\n )\n}\n"],"names":["useAuth","useConfig","useDocumentDrawer","React","useCallback","useEffect","useState","PLUGIN_FETCH_FIELDS_ENDPOINT","PLUGIN_INSTRUCTIONS_TABLE","useActiveFieldTracking","InstructionsContext","InstructionsProvider","children","instructions","setInstructionsState","promptFields","setPromptFields","activeCollection","setActiveCollection","isConfigAllowed","setIsConfigAllowed","enabledLanguages","setEnabledLanguages","enabledCollections","setEnabledCollections","debugging","setDebugging","user","config","routes","api","serverURL","drawerInstructionId","setDrawerInstructionId","drawerOpenCount","setDrawerOpenCount","DocumentDrawer","_","openDrawer","openPayloadDrawer","id","collectionSlug","prev","handleSave","doc","disabled","fieldType","fetchFieldsData","res","fetch","data","json","fields","err","console","error","refresh","Provider","value","hasInstructions","Object","keys","length","onSave"],"mappings":"AAAA;;AAEA,SAASA,OAAO,EAAEC,SAAS,EAAEC,iBAAiB,QAAQ,iBAAgB;AACtE,OAAOC,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAI/D,SAASC,4BAA4B,EAAEC,yBAAyB,QAAQ,oBAAmB;AAC3F,SAASC,sBAAsB,QAAQ,mDAAkD;AACzF,SAASC,mBAAmB,QAAQ,eAAc;AAElD,OAAO,MAAMC,uBAAgE,CAAC,EAAEC,QAAQ,EAAE;IACxF,uFAAuF;IACvFH;IAEA,MAAM,CAACI,cAAcC,qBAAqB,GAAGR,SAAS,CAAC;IACvD,MAAM,CAACS,cAAcC,gBAAgB,GAAGV,SAAkC,EAAE;IAC5E,MAAM,CAACW,kBAAkBC,oBAAoB,GAAGZ,SAAS;IACzD,MAAM,CAACa,iBAAiBC,mBAAmB,GAAGd,SAAS;IACvD,MAAM,CAACe,kBAAkBC,oBAAoB,GAAGhB;IAChD,MAAM,CAACiB,oBAAoBC,sBAAsB,GAAGlB;IACpD,MAAM,CAACmB,WAAWC,aAAa,GAAGpB,SAAS;IAC3C,MAAM,EAAEqB,IAAI,EAAE,GAAG3B;IAEjB,MAAM,EAAE4B,MAAM,EAAE,GAAG3B;IACnB,MAAM,EACJ4B,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,GAAGH;IAEJ,+BAA+B;IAC/B,MAAM,CAACI,qBAAqBC,uBAAuB,GAAG3B,SAAiB;IACvE,MAAM,CAAC4B,iBAAiBC,mBAAmB,GAAG7B,SAAS;IAEvD,MAAM,CAAC8B,gBAAgBC,GAAG,EAAEC,YAAYC,iBAAiB,EAAE,CAAC,GAAGrC,kBAAkB;QAC/EsC,IAAIR;QACJS,gBAAgBjC;IAClB;IAEA,MAAM8B,aAAalC,YAAY,CAACoC;QAC9BP,uBAAuBO;QACvBL,mBAAmB,CAACO,OAASA,OAAO;IACtC,GAAG,EAAE;IAEL,iCAAiC;IACjCrC,UAAU;QACR,IAAI6B,kBAAkB,GAAG;YACvBK;QACF;IACF,GAAG;QAACL;QAAiBK;KAAkB;IAEvC,MAAMI,aAAavC,YACjB,CAAC,EAAEwC,GAAG,EAAgB;QACpB9B,qBAAqB,CAAC4B;YACpB,OAAO;gBACL,GAAGA,IAAI;gBACP,CAACE,GAAG,CAAC,cAAc,CAAC,EAAE;oBACpBJ,IAAII,IAAIJ,EAAE;oBACVK,UAAU,CAAC,CAACD,IAAIC,QAAQ;oBACxBC,WAAWF,GAAG,CAAC,aAAa;gBAC9B;YACF;QACF;IACF,GACA;QAAC9B;KAAqB;IAGxB,MAAMiC,kBAAkB3C,YAAY;QAClC,4FAA4F;QAC5F,IAAI,CAACuB,MAAMa,IAAI;YACb;QACF;QAEA,IAAI;YACF,MAAMQ,MAAM,MAAMC,MAAM,CAAC,EAAElB,UAAU,EAAED,IAAI,EAAEvB,6BAA6B,CAAC;YAC3E,MAAM2C,OAAO,MAAMF,IAAIG,IAAI;YAC3B/B,mBAAmB8B,MAAM/B,mBAAmB;YAC5CG,oBAAoB4B,MAAM7B,oBAAoB,EAAE;YAChDG,sBAAsB0B,MAAM3B,sBAAsB,EAAE;YACpDT,qBAAqBoC,MAAME,UAAU,CAAC;YACtCpC,gBAAgBkC,MAAMnC,gBAAgB,EAAE;YACxCW,aAAawB,MAAMzB,aAAa;QAClC,EAAE,OAAO4B,KAAK;YACZC,QAAQC,KAAK,CAAC,yBAAyBF;QACzC;IACF,GAAG;QAACvB;QAAKC;QAAWJ,MAAMa;KAAG;IAE7BnC,UAAU;QACR,KAAK0C;IACP,GAAG;QAACA;KAAgB;IAEpB,MAAMS,UAAUpD,YAAY;QAC1B,MAAM2C;IACR,GAAG;QAACA;KAAgB;IAEpB,qBACE,MAACrC,oBAAoB+C,QAAQ;QAC3BC,OAAO;YACLzC;YACAQ;YACAF;YACAF;YACAsC,iBAAiB9C,gBAAgB+C,OAAOC,IAAI,CAAChD,cAAciD,MAAM,GAAG;YACpEjD;YACAM;YACAmB;YACAvB;YACAyC;YACAtC;YACAM;QACF;;YAECZ;0BACD,KAACwB;gBAAe2B,QAAQpB;;;;AAG9B,EAAC"}
|
|
@@ -12,6 +12,7 @@ export const InstructionsProvider = ({ children }) => {
|
|
|
12
12
|
const [activeCollection, setActiveCollection] = useState('');
|
|
13
13
|
const [isConfigAllowed, setIsConfigAllowed] = useState(false);
|
|
14
14
|
const [enabledLanguages, setEnabledLanguages] = useState();
|
|
15
|
+
const [enabledCollections, setEnabledCollections] = useState();
|
|
15
16
|
const [debugging, setDebugging] = useState(false);
|
|
16
17
|
const { user } = useAuth();
|
|
17
18
|
const { config } = useConfig();
|
|
@@ -33,39 +34,58 @@ export const InstructionsProvider = ({ children }) => {
|
|
|
33
34
|
openPayloadDrawer();
|
|
34
35
|
}
|
|
35
36
|
}, [drawerOpenCount, openPayloadDrawer]);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const handleSave = useCallback(({ doc }) => {
|
|
38
|
+
setInstructionsState((prev) => {
|
|
39
|
+
return {
|
|
40
|
+
...prev,
|
|
41
|
+
[doc['schema-path']]: {
|
|
42
|
+
id: doc.id,
|
|
43
|
+
disabled: !!doc.disabled,
|
|
44
|
+
fieldType: doc['field-type'],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}, [setInstructionsState]);
|
|
49
|
+
const fetchFieldsData = useCallback(async () => {
|
|
39
50
|
// Only fetch if we have a user ID - prevents fetching on every user object reference change
|
|
40
51
|
if (!user?.id) {
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
await res.json()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`);
|
|
56
|
+
const data = await res.json();
|
|
57
|
+
setIsConfigAllowed(data?.isConfigAllowed || false);
|
|
58
|
+
setEnabledLanguages(data?.enabledLanguages || []);
|
|
59
|
+
setEnabledCollections(data?.enabledCollections || []);
|
|
60
|
+
setInstructionsState(data?.fields || {});
|
|
61
|
+
setPromptFields(data?.promptFields || []);
|
|
62
|
+
setDebugging(data?.debugging || false);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
54
65
|
console.error('InstructionsProvider:', err);
|
|
55
|
-
}
|
|
66
|
+
}
|
|
56
67
|
}, [api, serverURL, user?.id]);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
void fetchFieldsData();
|
|
70
|
+
}, [fetchFieldsData]);
|
|
71
|
+
const refresh = useCallback(async () => {
|
|
72
|
+
await fetchFieldsData();
|
|
73
|
+
}, [fetchFieldsData]);
|
|
57
74
|
return (<InstructionsContext.Provider value={{
|
|
58
75
|
activeCollection,
|
|
59
76
|
debugging,
|
|
77
|
+
enabledCollections,
|
|
60
78
|
enabledLanguages,
|
|
61
79
|
hasInstructions: instructions && Object.keys(instructions).length > 0,
|
|
62
80
|
instructions,
|
|
63
81
|
isConfigAllowed,
|
|
64
82
|
openDrawer,
|
|
65
83
|
promptFields,
|
|
84
|
+
refresh,
|
|
66
85
|
setActiveCollection,
|
|
86
|
+
setEnabledCollections,
|
|
67
87
|
}}>
|
|
68
88
|
{children}
|
|
69
|
-
<DocumentDrawer />
|
|
89
|
+
<DocumentDrawer onSave={handleSave}/>
|
|
70
90
|
</InstructionsContext.Provider>);
|
|
71
91
|
};
|
|
@@ -4,6 +4,7 @@ import type { SerializedPromptField } from '../../types.js';
|
|
|
4
4
|
export type InstructionsContextValue = {
|
|
5
5
|
activeCollection?: string;
|
|
6
6
|
debugging?: boolean;
|
|
7
|
+
enabledCollections?: string[];
|
|
7
8
|
enabledLanguages?: string[];
|
|
8
9
|
field?: Field;
|
|
9
10
|
hasInstructions: boolean;
|
|
@@ -12,8 +13,10 @@ export type InstructionsContextValue = {
|
|
|
12
13
|
openDrawer: (instructionId: string) => void;
|
|
13
14
|
path?: string;
|
|
14
15
|
promptFields: SerializedPromptField[];
|
|
16
|
+
refresh: () => Promise<void>;
|
|
15
17
|
schemaPath?: unknown;
|
|
16
18
|
setActiveCollection?: React.Dispatch<React.SetStateAction<string>>;
|
|
19
|
+
setEnabledCollections?: React.Dispatch<React.SetStateAction<string[] | undefined>>;
|
|
17
20
|
};
|
|
18
21
|
export declare const initialContext: InstructionsContextValue;
|
|
19
22
|
export declare const InstructionsContext: React.Context<InstructionsContextValue>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createContext } from 'react';
|
|
3
3
|
export const initialContext = {
|
|
4
4
|
debugging: false,
|
|
5
|
+
enabledCollections: [],
|
|
5
6
|
field: undefined,
|
|
6
7
|
hasInstructions: false,
|
|
7
8
|
instructions: {},
|
|
@@ -9,6 +10,7 @@ export const initialContext = {
|
|
|
9
10
|
openDrawer: ()=>null,
|
|
10
11
|
path: '',
|
|
11
12
|
promptFields: [],
|
|
13
|
+
refresh: ()=>Promise.resolve(),
|
|
12
14
|
schemaPath: ''
|
|
13
15
|
};
|
|
14
16
|
export const InstructionsContext = createContext(initialContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/context.ts"],"sourcesContent":["'use client'\n\nimport type { Field } from 'payload'\nimport type React from 'react';\n\nimport { createContext } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nexport type InstructionsContextValue = {\n activeCollection?: string\n debugging?: boolean\n enabledLanguages?: string[]\n field?: Field\n hasInstructions: boolean\n instructions: Record<string, any>\n isConfigAllowed: boolean\n openDrawer: (instructionId: string) => void\n path?: string\n promptFields: SerializedPromptField[]\n schemaPath?: unknown\n setActiveCollection?: React.Dispatch<React.SetStateAction<string>>\n}\n\nexport const initialContext: InstructionsContextValue = {\n debugging: false,\n field: undefined,\n hasInstructions: false,\n instructions: {},\n isConfigAllowed: true,\n openDrawer: () => null,\n path: '',\n promptFields: [],\n schemaPath: '',\n}\n\nexport const InstructionsContext = createContext<InstructionsContextValue>(initialContext)\n"],"names":["createContext","initialContext","debugging","field","undefined","hasInstructions","instructions","isConfigAllowed","openDrawer","path","promptFields","schemaPath","InstructionsContext"],"mappings":"AAAA;AAKA,SAASA,aAAa,QAAQ,QAAO;
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/context.ts"],"sourcesContent":["'use client'\n\nimport type { Field } from 'payload'\nimport type React from 'react';\n\nimport { createContext } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nexport type InstructionsContextValue = {\n activeCollection?: string\n debugging?: boolean\n enabledCollections?: string[]\n enabledLanguages?: string[]\n field?: Field\n hasInstructions: boolean\n instructions: Record<string, any>\n isConfigAllowed: boolean\n openDrawer: (instructionId: string) => void\n path?: string\n promptFields: SerializedPromptField[]\n refresh: () => Promise<void>\n schemaPath?: unknown\n setActiveCollection?: React.Dispatch<React.SetStateAction<string>>\n setEnabledCollections?: React.Dispatch<React.SetStateAction<string[] | undefined>>\n}\n\nexport const initialContext: InstructionsContextValue = {\n debugging: false,\n enabledCollections: [],\n field: undefined,\n hasInstructions: false,\n instructions: {},\n isConfigAllowed: true,\n openDrawer: () => null,\n path: '',\n promptFields: [],\n refresh: () => Promise.resolve(),\n schemaPath: '',\n}\n\nexport const InstructionsContext = createContext<InstructionsContextValue>(initialContext)\n"],"names":["createContext","initialContext","debugging","enabledCollections","field","undefined","hasInstructions","instructions","isConfigAllowed","openDrawer","path","promptFields","refresh","Promise","resolve","schemaPath","InstructionsContext"],"mappings":"AAAA;AAKA,SAASA,aAAa,QAAQ,QAAO;AAsBrC,OAAO,MAAMC,iBAA2C;IACtDC,WAAW;IACXC,oBAAoB,EAAE;IACtBC,OAAOC;IACPC,iBAAiB;IACjBC,cAAc,CAAC;IACfC,iBAAiB;IACjBC,YAAY,IAAM;IAClBC,MAAM;IACNC,cAAc,EAAE;IAChBC,SAAS,IAAMC,QAAQC,OAAO;IAC9BC,YAAY;AACd,EAAC;AAED,OAAO,MAAMC,sBAAsBhB,cAAwCC,gBAAe"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { InstructionsContext } from '@ai-stack/payloadcms/client';
|
|
2
1
|
import { useDocumentInfo } from '@payloadcms/ui';
|
|
3
2
|
import { useContext, useEffect, useMemo, useState } from 'react';
|
|
4
3
|
import { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js';
|
|
5
4
|
import { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js';
|
|
5
|
+
import { InstructionsContext } from './context.js';
|
|
6
6
|
/**
|
|
7
7
|
* Normalize a schema path by removing array indices.
|
|
8
8
|
* This allows fields inside arrays to match their instruction records.
|
|
@@ -112,9 +112,11 @@ export const useInstructions = (update = {})=>{
|
|
|
112
112
|
if (debugging && !pathInstructions && schemaPath && hasInstructions) {
|
|
113
113
|
warnOnceOnMissingInstructions(schemaPath);
|
|
114
114
|
}
|
|
115
|
+
const isCollectionEnabled = context.enabledCollections?.includes(collectionSlug || activeCollection || '') ?? false;
|
|
115
116
|
return {
|
|
116
117
|
...context,
|
|
117
118
|
...pathInstructions || {},
|
|
119
|
+
disabled: !isCollectionEnabled || (pathInstructions?.disabled ?? false),
|
|
118
120
|
promptEditorSuggestions
|
|
119
121
|
};
|
|
120
122
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { useDocumentInfo } from '@payloadcms/ui'\nimport { useContext, useEffect, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js'\nimport { InstructionsContext } from './context.js'\n\n/**\n * Normalize a schema path by removing array indices.\n * This allows fields inside arrays to match their instruction records.\n * \n * Example:\n * 'array-test-cases.keywords.0.keyword' -> 'array-test-cases.keywords.keyword'\n * 'characters.views.2.description' -> 'characters.views.description'\n * 'posts.title' -> 'posts.title' (no change)\n */\nconst normalizeSchemaPath = (path: string): string => {\n if (!path) {\n return path\n }\n // Remove numeric path segments (array indices)\n return path.split('.').filter(segment => !/^\\d+$/.test(segment)).join('.')\n}\n\nconst warnedOnceOnNoInstructionId = new Set<string>()\nconst warnOnceOnMissingInstructions = (path: string) => {\n if (!warnedOnceOnNoInstructionId.has(path)) {\n warnedOnceOnNoInstructionId.add(path)\n // eslint-disable-next-line no-console\n console.info(`[AI Plugin] There are no AI instructions for this field: ${path}. Enable \"generatePromptOnInit\" option to enable them.`)\n }\n}\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n const { collectionSlug } = useDocumentInfo()\n const { activeCollection, debugging, hasInstructions, instructions, promptFields, setActiveCollection } = context\n\n const [schemaPath, setSchemaPath] = useState(update.schemaPath as string)\n\n useEffect(() => {\n if (update.schemaPath !== schemaPath) {\n setSchemaPath((update.schemaPath as string) ?? '')\n }\n }, [update.schemaPath, schemaPath])\n\n useEffect(() => {\n if (\n activeCollection !== collectionSlug &&\n collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE &&\n typeof setActiveCollection === 'function'\n ) {\n setActiveCollection(collectionSlug ?? '')\n }\n }, [activeCollection, collectionSlug, setActiveCollection])\n\n const groupedFields = useMemo(() => {\n const result: Record<string, string[]> = {}\n\n for (const fullKey of Object.keys(instructions || {})) {\n const [collection, ...pathParts] = fullKey.split('.')\n const path = pathParts.join('.')\n if (!result[collection]) {\n result[collection] = []\n }\n result[collection].push(path)\n }\n\n return result\n }, [instructions])\n\n // Suggestions for prompt editor\n const promptEditorSuggestions = useMemo(() => {\n const activeFields = groupedFields[activeCollection as string] || []\n const suggestions: string[] = []\n\n // Build instruction lookup map once for O(1) access instead of O(n) search per field\n const instructionLookup = new Map(\n Object.entries(instructions).map(([key, value]) => {\n const path = key.split('.').slice(1).join('.')\n return [path, value]\n })\n )\n\n activeFields.forEach((f) => {\n const fieldInfo = instructionLookup.get(f)\n\n if (!fieldInfo) {return}\n\n if (fieldInfo.fieldType === 'upload') {\n return\n }\n\n const helpers = handlebarsHelpers.filter(\n (h) => (handlebarsHelpersMap as Record<string, { field?: string }>)[h]?.field === fieldInfo.fieldType,\n )\n\n if (helpers.length) {\n for (const helper of helpers) {\n suggestions.push(`${helper} ${f}`)\n }\n } else {\n suggestions.push(f)\n }\n })\n\n promptFields.forEach(({ name, collections }) => {\n if (!activeCollection) {return}\n\n if (!collections || collections.includes(activeCollection)) {\n suggestions.push(name)\n }\n })\n\n return suggestions\n }, [groupedFields, activeCollection, instructions, promptFields])\n\n // Normalize the schema path to handle array indices\n const normalizedSchemaPath = normalizeSchemaPath(schemaPath)\n const pathInstructions = instructions[normalizedSchemaPath]\n\n if (debugging && !pathInstructions && schemaPath && hasInstructions) {\n warnOnceOnMissingInstructions(schemaPath)\n }\n\n const isCollectionEnabled = context.enabledCollections?.includes(collectionSlug || activeCollection || '') ?? false\n\n return {\n ...context,\n ...(pathInstructions || {}),\n disabled: !isCollectionEnabled || (pathInstructions?.disabled ?? false),\n promptEditorSuggestions,\n }\n}\n\n"],"names":["useDocumentInfo","useContext","useEffect","useMemo","useState","PLUGIN_INSTRUCTIONS_TABLE","handlebarsHelpers","handlebarsHelpersMap","InstructionsContext","normalizeSchemaPath","path","split","filter","segment","test","join","warnedOnceOnNoInstructionId","Set","warnOnceOnMissingInstructions","has","add","console","info","useInstructions","update","context","collectionSlug","activeCollection","debugging","hasInstructions","instructions","promptFields","setActiveCollection","schemaPath","setSchemaPath","groupedFields","result","fullKey","Object","keys","collection","pathParts","push","promptEditorSuggestions","activeFields","suggestions","instructionLookup","Map","entries","map","key","value","slice","forEach","f","fieldInfo","get","fieldType","helpers","h","field","length","helper","name","collections","includes","normalizedSchemaPath","pathInstructions","isCollectionEnabled","enabledCollections","disabled"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -39,9 +39,6 @@ export interface PluginConfig {
|
|
|
39
39
|
* By default, all AI features require authentication
|
|
40
40
|
*/
|
|
41
41
|
access?: PluginConfigAccess;
|
|
42
|
-
collections: {
|
|
43
|
-
[key: CollectionSlug]: boolean;
|
|
44
|
-
};
|
|
45
42
|
debugging?: boolean;
|
|
46
43
|
disableSponsorMessage?: boolean;
|
|
47
44
|
editorConfig?: {
|
|
@@ -66,8 +63,7 @@ export interface PluginConfig {
|
|
|
66
63
|
prompts?: ActionPrompt[];
|
|
67
64
|
/**
|
|
68
65
|
* Custom seed prompt function for generating field-specific prompts
|
|
69
|
-
* If not provided,
|
|
70
|
-
* You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'
|
|
66
|
+
* If not provided, fields will have empty prompts by default
|
|
71
67
|
*/
|
|
72
68
|
seedPrompts?: SeedPromptFunction;
|
|
73
69
|
uploadCollectionSlug?: CollectionSlug;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { MediaResult } from './ai/core/index.js'\nimport type {PLUGIN_INSTRUCTIONS_TABLE} from \"./defaults.js\";\n\nexport interface PluginConfigAccess {\n /**\n * Control access to AI generation features (generate text, images, audio)\n * @default () => !!req.user (requires authentication)\n */\n generate?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n /**\n * Control access to AI settings/configuration\n * @default () => !!req.user (requires authentication)\n */\n settings?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n}\n\nexport interface PluginOptions {\n /**\n * Provide local tags to filter language options from the Translate Menu\n * Check for the available local tags,\n * visit: https://www.npmjs.com/package/locale-codes\n * Example: [\"en-US\", \"zh-SG\", \"zh-CN\", \"en\"]\n */\n enabledLanguages?: string[]\n}\n\nexport type PluginConfigMediaUploadFunction = (\n result: MediaResult,\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { MediaResult } from './ai/core/index.js'\nimport type {PLUGIN_INSTRUCTIONS_TABLE} from \"./defaults.js\";\n\nexport interface PluginConfigAccess {\n /**\n * Control access to AI generation features (generate text, images, audio)\n * @default () => !!req.user (requires authentication)\n */\n generate?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n /**\n * Control access to AI settings/configuration\n * @default () => !!req.user (requires authentication)\n */\n settings?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n}\n\nexport interface PluginOptions {\n /**\n * Provide local tags to filter language options from the Translate Menu\n * Check for the available local tags,\n * visit: https://www.npmjs.com/package/locale-codes\n * Example: [\"en-US\", \"zh-SG\", \"zh-CN\", \"en\"]\n */\n enabledLanguages?: string[]\n}\n\nexport type PluginConfigMediaUploadFunction = (\n result: MediaResult,\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n debugging?: boolean\n disableSponsorMessage?: boolean\n editorConfig?: { nodes: JSONSchema[] }\n fields?: Field[]\n generatePromptOnInit?: boolean\n generationModels?: ((defaultModels: GenerationModel[]) => GenerationModel[]) | GenerationModel[]\n globals?: {\n [key: GlobalConfig['slug']]: boolean\n }\n interfaceName?: string\n mediaUpload?: PluginConfigMediaUploadFunction\n options?: PluginOptions\n // Override the instructions collection config\n overrideInstructions?: Partial<CollectionConfig>\n promptFields?: PromptField[]\n /**\n * Custom action prompts for AI text generation\n * If not provided, uses default prompts\n * You can access default prompts by importing { defaultPrompts } from '@ai-stack/payloadcms'\n */\n prompts?: ActionPrompt[]\n /**\n * Custom seed prompt function for generating field-specific prompts\n * If not provided, fields will have empty prompts by default\n */\n seedPrompts?: SeedPromptFunction\n uploadCollectionSlug?: CollectionSlug\n}\n\nexport interface GenerationModel {\n fields: string[]\n generateText?: (prompt: string, system: string) => Promise<string>\n handler?: (prompt: string, options: any) => File | Promise<any> | Response\n id: string\n name: string\n output: 'audio' | 'file' | 'image' | 'json' | 'text' | 'video'\n settings?: GroupField\n supportsPromptOptimization?: boolean\n}\n\nexport interface GenerationConfig {\n models: GenerationModel[]\n provider: string\n}\n\nexport type GenerateTextarea<T = any> = (args: {\n collectionSlug: CollectionSlug\n doc: T\n documentId?: number | string\n locale?: string\n options?: any\n}) => Promise<string> | string\n\nexport interface Endpoints {\n fetchVoices?: Omit<Endpoint, 'root'>\n textarea: Omit<Endpoint, 'root'>\n upload: Omit<Endpoint, 'root'>\n videogenWebhook?: Omit<Endpoint, 'root'>\n}\n\nexport type ActionMenuItems =\n | 'Compose'\n | 'Expand'\n | 'Proofread'\n | 'Rephrase'\n | 'Settings'\n | 'Simplify'\n | 'Summarize'\n | 'Tone'\n | 'Translate'\n\nexport type ActionPromptOptions = {\n layout?: string\n locale?: string\n prompt?: string\n systemPrompt?: string\n}\n\nexport type ActionPrompt = {\n layout?: (options?: ActionPromptOptions) => string\n name: ActionMenuItems\n system: (options: ActionPromptOptions) => string\n}\n\nexport type SeedPromptOptions = {\n fieldLabel: string\n fieldSchemaPaths: Record<string, any>\n fieldType: string\n path: string\n}\n\nexport type SeedPromptData = Omit<\n TypedCollection[typeof PLUGIN_INSTRUCTIONS_TABLE],\n 'createdAt' | 'id' | 'updatedAt'\n>\n\nexport type SeedPromptResult =\n | {\n data?: SeedPromptData\n }\n | {\n data?: SeedPromptData\n prompt: string\n system: string\n }\n | false\n | undefined\n | void\n\nexport type SeedPromptFunction = (\n options: SeedPromptOptions,\n) => Promise<SeedPromptResult> | SeedPromptResult\n\nexport type ActionMenuEvents =\n | 'onCompose'\n | 'onExpand'\n | 'onProofread'\n | 'onRephrase'\n | 'onSettings'\n | 'onSimplify'\n | 'onSummarize'\n | 'onTone'\n | 'onTranslate'\n\nexport type UseMenuEvents = {\n [key in ActionMenuEvents]?: (data?: unknown) => void\n}\n\nexport type UseMenuOptions = {\n isConfigAllowed: boolean\n}\n\nexport type BaseItemProps<T = any> = {\n children?: React.ReactNode\n disabled?: boolean\n hideIcon?: boolean\n isActive?: boolean\n isMenu?: boolean\n onClick: (data?: unknown) => void\n onMouseEnter?: MouseEventHandler<T> | undefined\n onMouseLeave?: MouseEventHandler<T> | undefined\n style?: CSSProperties | undefined\n title?: string\n}\n\nexport type ImageReference = {\n data: Blob\n name: string\n size: number\n type: string\n url: string\n}\n\nexport type GenerateImageParams = {\n images?: ImageReference[]\n size?: ImageGenerateParams['size']\n style?: ImageGenerateParams['style']\n version?: ImageGenerateParams['model']\n}\n\nexport type SerializedPromptField = {\n collections?: CollectionSlug[]\n name: string\n}\n\nexport type PromptFieldGetterContext = {\n collection: CollectionSlug\n type: string\n}\n\nexport type PromptField = {\n // If not provided, the value will be returned from the data object as-is\n getter?: (data: object, ctx: PromptFieldGetterContext) => Promise<string> | string\n} & SerializedPromptField\n"],"names":[],"mappings":"AAqOA,WAGyB"}
|
|
@@ -1,43 +1,219 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
3
|
+
import { Button, toast, useConfig } from '@payloadcms/ui';
|
|
4
|
+
// @ts-expect-error - Next.js types are not resolving correctly with nodenext but runtime is fine
|
|
5
|
+
import { useRouter } from 'next/navigation';
|
|
6
|
+
import React, { useContext, useEffect, useState } from 'react';
|
|
7
|
+
import { excludeCollections } from '../../defaults.js';
|
|
8
|
+
import { InstructionsContext } from '../../providers/InstructionsProvider/context.js';
|
|
4
9
|
export const AIConfigDashboard = ()=>{
|
|
10
|
+
const { config: { collections, routes: { admin: adminRoute, api: apiRoute } } } = useConfig();
|
|
11
|
+
const router = useRouter();
|
|
12
|
+
const { refresh, setEnabledCollections: setEnabledCollectionsInContext } = useContext(InstructionsContext);
|
|
13
|
+
const [enabledCollections, setEnabledCollections] = useState([]);
|
|
14
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
15
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
16
|
+
const availableCollections = collections.filter((c)=>!excludeCollections.includes(c.slug) && !c.admin?.hidden);
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
const fetchSettings = async ()=>{
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(`${apiRoute}/globals/ai-settings`);
|
|
21
|
+
if (response.ok) {
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
// Handle both simple array and object wrapper if Payload wraps it
|
|
24
|
+
const storedEnabled = data.enabledCollections || [];
|
|
25
|
+
setEnabledCollections(Array.isArray(storedEnabled) ? storedEnabled : []);
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('Failed to fetch AI settings:', error);
|
|
29
|
+
} finally{
|
|
30
|
+
setIsLoading(false);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
fetchSettings().catch((e)=>{
|
|
34
|
+
console.log(e);
|
|
35
|
+
});
|
|
36
|
+
}, [
|
|
37
|
+
apiRoute
|
|
38
|
+
]);
|
|
39
|
+
const handleToggle = (slug)=>{
|
|
40
|
+
setEnabledCollections((prev)=>{
|
|
41
|
+
if (prev.includes(slug)) {
|
|
42
|
+
return prev.filter((s)=>s !== slug);
|
|
43
|
+
}
|
|
44
|
+
return [
|
|
45
|
+
...prev,
|
|
46
|
+
slug
|
|
47
|
+
];
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const handleSave = async ()=>{
|
|
51
|
+
setIsSaving(true);
|
|
52
|
+
try {
|
|
53
|
+
// First fetch current settings to get ID or just rely on global update behavior
|
|
54
|
+
// We need to adhere to Payload's global update API
|
|
55
|
+
const response = await fetch(`${apiRoute}/globals/ai-settings`, {
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
enabledCollections
|
|
58
|
+
}),
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json'
|
|
61
|
+
},
|
|
62
|
+
method: 'POST'
|
|
63
|
+
});
|
|
64
|
+
if (response.ok) {
|
|
65
|
+
toast.success('Settings saved successfully');
|
|
66
|
+
if (setEnabledCollectionsInContext) {
|
|
67
|
+
setEnabledCollectionsInContext(enabledCollections);
|
|
68
|
+
}
|
|
69
|
+
if (refresh) {
|
|
70
|
+
await refresh();
|
|
71
|
+
}
|
|
72
|
+
router.refresh();
|
|
73
|
+
} else {
|
|
74
|
+
toast.error('Failed to save settings');
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error('Error saving settings:', error);
|
|
78
|
+
toast.error('Error saving settings');
|
|
79
|
+
} finally{
|
|
80
|
+
setIsSaving(false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
if (isLoading) {
|
|
84
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
85
|
+
style: {
|
|
86
|
+
padding: '20px',
|
|
87
|
+
textAlign: 'center'
|
|
88
|
+
},
|
|
89
|
+
children: "Loading AI configuration..."
|
|
90
|
+
});
|
|
91
|
+
}
|
|
5
92
|
return /*#__PURE__*/ _jsxs("div", {
|
|
6
93
|
style: {
|
|
7
|
-
alignItems: 'center',
|
|
8
94
|
background: 'var(--theme-elevation-50)',
|
|
9
|
-
border: '1px solid var(--theme-elevation-150)',
|
|
10
|
-
borderRadius: '8px',
|
|
11
|
-
display: 'flex',
|
|
12
|
-
justifyContent: 'space-between',
|
|
95
|
+
// border: '1px solid var(--theme-elevation-150)',
|
|
96
|
+
// borderRadius: '8px',
|
|
13
97
|
marginBottom: '20px',
|
|
14
|
-
|
|
98
|
+
overflow: 'hidden'
|
|
15
99
|
},
|
|
16
100
|
children: [
|
|
17
101
|
/*#__PURE__*/ _jsxs("div", {
|
|
102
|
+
style: {
|
|
103
|
+
alignItems: 'center',
|
|
104
|
+
borderBottom: '1px solid var(--theme-elevation-150)',
|
|
105
|
+
display: 'flex',
|
|
106
|
+
justifyContent: 'space-between',
|
|
107
|
+
padding: '20px'
|
|
108
|
+
},
|
|
18
109
|
children: [
|
|
19
|
-
/*#__PURE__*/
|
|
110
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
111
|
+
children: [
|
|
112
|
+
/*#__PURE__*/ _jsx("h4", {
|
|
113
|
+
style: {
|
|
114
|
+
margin: '0 0 5px 0'
|
|
115
|
+
},
|
|
116
|
+
children: "AI Configuration"
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsx("p", {
|
|
119
|
+
style: {
|
|
120
|
+
color: 'var(--theme-elevation-500)',
|
|
121
|
+
fontSize: '14px',
|
|
122
|
+
margin: '0'
|
|
123
|
+
},
|
|
124
|
+
children: "Manage your AI providers, API keys, and enable AI for specific collections."
|
|
125
|
+
})
|
|
126
|
+
]
|
|
127
|
+
}),
|
|
128
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
20
129
|
style: {
|
|
21
|
-
|
|
130
|
+
display: 'flex',
|
|
131
|
+
gap: '10px'
|
|
22
132
|
},
|
|
23
|
-
children:
|
|
133
|
+
children: [
|
|
134
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
135
|
+
buttonStyle: "secondary",
|
|
136
|
+
el: "link",
|
|
137
|
+
to: `${adminRoute}/globals/ai-settings`,
|
|
138
|
+
children: "Settings"
|
|
139
|
+
}),
|
|
140
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
141
|
+
disabled: isSaving,
|
|
142
|
+
onClick: handleSave,
|
|
143
|
+
children: isSaving ? 'Saving...' : 'Save Changes'
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
}),
|
|
149
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
150
|
+
style: {
|
|
151
|
+
padding: '20px'
|
|
152
|
+
},
|
|
153
|
+
children: [
|
|
154
|
+
/*#__PURE__*/ _jsx("h5", {
|
|
155
|
+
style: {
|
|
156
|
+
marginBottom: '15px'
|
|
157
|
+
},
|
|
158
|
+
children: "Enabled Collections"
|
|
24
159
|
}),
|
|
25
|
-
/*#__PURE__*/ _jsx("
|
|
160
|
+
/*#__PURE__*/ _jsx("div", {
|
|
26
161
|
style: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
162
|
+
display: 'grid',
|
|
163
|
+
gap: '15px',
|
|
164
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))'
|
|
30
165
|
},
|
|
31
|
-
children:
|
|
166
|
+
children: availableCollections.map((collection)=>{
|
|
167
|
+
const isEnabled = enabledCollections.includes(collection.slug);
|
|
168
|
+
return /*#__PURE__*/ _jsxs("button", {
|
|
169
|
+
onClick: ()=>handleToggle(collection.slug),
|
|
170
|
+
style: {
|
|
171
|
+
alignItems: 'center',
|
|
172
|
+
background: isEnabled ? 'var(--theme-elevation-100)' : 'var(--theme-elevation-50)',
|
|
173
|
+
border: `1px solid ${isEnabled ? 'var(--theme-text-success)' : 'var(--theme-elevation-200)'}`,
|
|
174
|
+
borderRadius: '6px',
|
|
175
|
+
cursor: 'pointer',
|
|
176
|
+
display: 'flex',
|
|
177
|
+
gap: '10px',
|
|
178
|
+
padding: '10px 15px',
|
|
179
|
+
textAlign: 'left',
|
|
180
|
+
transition: 'all 0.2s ease',
|
|
181
|
+
width: '100%'
|
|
182
|
+
},
|
|
183
|
+
type: "button",
|
|
184
|
+
children: [
|
|
185
|
+
/*#__PURE__*/ _jsx("div", {
|
|
186
|
+
style: {
|
|
187
|
+
alignItems: 'center',
|
|
188
|
+
background: isEnabled ? 'var(--theme-text-success)' : 'var(--theme-elevation-200)',
|
|
189
|
+
borderRadius: '12px',
|
|
190
|
+
display: 'flex',
|
|
191
|
+
height: '24px',
|
|
192
|
+
justifyContent: isEnabled ? 'flex-end' : 'flex-start',
|
|
193
|
+
padding: '2px',
|
|
194
|
+
transition: 'all 0.2s ease',
|
|
195
|
+
width: '44px'
|
|
196
|
+
},
|
|
197
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
198
|
+
style: {
|
|
199
|
+
background: 'white',
|
|
200
|
+
borderRadius: '50%',
|
|
201
|
+
height: '20px',
|
|
202
|
+
width: '20px'
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
}),
|
|
206
|
+
/*#__PURE__*/ _jsx("span", {
|
|
207
|
+
style: {
|
|
208
|
+
fontWeight: 500
|
|
209
|
+
},
|
|
210
|
+
children: typeof collection.labels?.singular === 'string' ? collection.labels.singular : collection.labels?.singular?.en || collection.slug
|
|
211
|
+
})
|
|
212
|
+
]
|
|
213
|
+
}, collection.slug);
|
|
214
|
+
})
|
|
32
215
|
})
|
|
33
216
|
]
|
|
34
|
-
}),
|
|
35
|
-
/*#__PURE__*/ _jsx("a", {
|
|
36
|
-
href: "/admin/globals/ai-settings",
|
|
37
|
-
children: /*#__PURE__*/ _jsx("button", {
|
|
38
|
-
className: "btn btn--style-primary btn--size-small",
|
|
39
|
-
children: "Manage AI Settings"
|
|
40
|
-
})
|
|
41
217
|
})
|
|
42
218
|
]
|
|
43
219
|
});
|