Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

modal-context.tsx 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. 'use client'
  2. import type { Dispatch, SetStateAction } from 'react'
  3. import { useCallback, useState } from 'react'
  4. import { createContext, useContext, useContextSelector } from 'use-context-selector'
  5. import { useRouter, useSearchParams } from 'next/navigation'
  6. import AccountSetting from '@/app/components/header/account-setting'
  7. import ApiBasedExtensionModal from '@/app/components/header/account-setting/api-based-extension-page/modal'
  8. import ModerationSettingModal from '@/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal'
  9. import ExternalDataToolModal from '@/app/components/app/configuration/tools/external-data-tool-modal'
  10. import AnnotationFullModal from '@/app/components/billing/annotation-full/modal'
  11. import ModelModal from '@/app/components/header/account-setting/model-provider-page/model-modal'
  12. import ExternalAPIModal from '@/app/components/datasets/external-api/external-api-modal'
  13. import type {
  14. ConfigurationMethodEnum,
  15. CustomConfigurationModelFixedFields,
  16. ModelLoadBalancingConfigEntry,
  17. ModelProvider,
  18. } from '@/app/components/header/account-setting/model-provider-page/declarations'
  19. import Pricing from '@/app/components/billing/pricing'
  20. import type { ModerationConfig, PromptVariable } from '@/models/debug'
  21. import type {
  22. ApiBasedExtension,
  23. ExternalDataTool,
  24. } from '@/models/common'
  25. import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
  26. import ModelLoadBalancingEntryModal from '@/app/components/header/account-setting/model-provider-page/model-modal/model-load-balancing-entry-modal'
  27. import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
  28. import ModelLoadBalancingModal from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
  29. import OpeningSettingModal from '@/app/components/base/features/new-feature-panel/conversation-opener/modal'
  30. import type { OpeningStatement } from '@/app/components/base/features/types'
  31. export type ModalState<T> = {
  32. payload: T
  33. onCancelCallback?: () => void
  34. onSaveCallback?: (newPayload: T) => void
  35. onRemoveCallback?: (newPayload: T) => void
  36. onEditCallback?: (newPayload: T) => void
  37. onValidateBeforeSaveCallback?: (newPayload: T) => boolean
  38. isEditMode?: boolean
  39. datasetBindings?: { id: string; name: string }[]
  40. }
  41. export type ModelModalType = {
  42. currentProvider: ModelProvider
  43. currentConfigurationMethod: ConfigurationMethodEnum
  44. currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
  45. }
  46. export type LoadBalancingEntryModalType = ModelModalType & {
  47. entry?: ModelLoadBalancingConfigEntry
  48. index?: number
  49. }
  50. export type ModalContextState = {
  51. setShowAccountSettingModal: Dispatch<SetStateAction<ModalState<string> | null>>
  52. setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>>
  53. setShowModerationSettingModal: Dispatch<SetStateAction<ModalState<ModerationConfig> | null>>
  54. setShowExternalDataToolModal: Dispatch<SetStateAction<ModalState<ExternalDataTool> | null>>
  55. setShowPricingModal: () => void
  56. setShowAnnotationFullModal: () => void
  57. setShowModelModal: Dispatch<SetStateAction<ModalState<ModelModalType> | null>>
  58. setShowExternalKnowledgeAPIModal: Dispatch<SetStateAction<ModalState<CreateExternalAPIReq> | null>>
  59. setShowModelLoadBalancingModal: Dispatch<SetStateAction<ModelLoadBalancingModalProps | null>>
  60. setShowModelLoadBalancingEntryModal: Dispatch<SetStateAction<ModalState<LoadBalancingEntryModalType> | null>>
  61. setShowOpeningModal: Dispatch<SetStateAction<ModalState<OpeningStatement & {
  62. promptVariables?: PromptVariable[]
  63. onAutoAddPromptVariable?: (variable: PromptVariable[]) => void
  64. }> | null>>
  65. }
  66. const ModalContext = createContext<ModalContextState>({
  67. setShowAccountSettingModal: () => { },
  68. setShowApiBasedExtensionModal: () => { },
  69. setShowModerationSettingModal: () => { },
  70. setShowExternalDataToolModal: () => { },
  71. setShowPricingModal: () => { },
  72. setShowAnnotationFullModal: () => { },
  73. setShowModelModal: () => { },
  74. setShowExternalKnowledgeAPIModal: () => { },
  75. setShowModelLoadBalancingModal: () => { },
  76. setShowModelLoadBalancingEntryModal: () => { },
  77. setShowOpeningModal: () => { },
  78. })
  79. export const useModalContext = () => useContext(ModalContext)
  80. // Adding a dangling comma to avoid the generic parsing issue in tsx, see:
  81. // https://github.com/microsoft/TypeScript/issues/15713
  82. // eslint-disable-next-line @typescript-eslint/comma-dangle
  83. export const useModalContextSelector = <T,>(selector: (state: ModalContextState) => T): T =>
  84. useContextSelector(ModalContext, selector)
  85. type ModalContextProviderProps = {
  86. children: React.ReactNode
  87. }
  88. export const ModalContextProvider = ({
  89. children,
  90. }: ModalContextProviderProps) => {
  91. const [showAccountSettingModal, setShowAccountSettingModal] = useState<ModalState<string> | null>(null)
  92. const [showApiBasedExtensionModal, setShowApiBasedExtensionModal] = useState<ModalState<ApiBasedExtension> | null>(null)
  93. const [showModerationSettingModal, setShowModerationSettingModal] = useState<ModalState<ModerationConfig> | null>(null)
  94. const [showExternalDataToolModal, setShowExternalDataToolModal] = useState<ModalState<ExternalDataTool> | null>(null)
  95. const [showModelModal, setShowModelModal] = useState<ModalState<ModelModalType> | null>(null)
  96. const [showExternalKnowledgeAPIModal, setShowExternalKnowledgeAPIModal] = useState<ModalState<CreateExternalAPIReq> | null>(null)
  97. const [showModelLoadBalancingModal, setShowModelLoadBalancingModal] = useState<ModelLoadBalancingModalProps | null>(null)
  98. const [showModelLoadBalancingEntryModal, setShowModelLoadBalancingEntryModal] = useState<ModalState<LoadBalancingEntryModalType> | null>(null)
  99. const [showOpeningModal, setShowOpeningModal] = useState<ModalState<OpeningStatement & {
  100. promptVariables?: PromptVariable[]
  101. onAutoAddPromptVariable?: (variable: PromptVariable[]) => void
  102. }> | null>(null)
  103. const searchParams = useSearchParams()
  104. const router = useRouter()
  105. const [showPricingModal, setShowPricingModal] = useState(searchParams.get('show-pricing') === '1')
  106. const [showAnnotationFullModal, setShowAnnotationFullModal] = useState(false)
  107. const handleCancelAccountSettingModal = () => {
  108. setShowAccountSettingModal(null)
  109. if (showAccountSettingModal?.onCancelCallback)
  110. showAccountSettingModal?.onCancelCallback()
  111. }
  112. const handleCancelModerationSettingModal = () => {
  113. setShowModerationSettingModal(null)
  114. if (showModerationSettingModal?.onCancelCallback)
  115. showModerationSettingModal.onCancelCallback()
  116. }
  117. const handleCancelExternalDataToolModal = () => {
  118. setShowExternalDataToolModal(null)
  119. if (showExternalDataToolModal?.onCancelCallback)
  120. showExternalDataToolModal.onCancelCallback()
  121. }
  122. const handleCancelModelModal = useCallback(() => {
  123. setShowModelModal(null)
  124. if (showModelModal?.onCancelCallback)
  125. showModelModal.onCancelCallback()
  126. }, [showModelModal])
  127. const handleSaveModelModal = useCallback(() => {
  128. if (showModelModal?.onSaveCallback)
  129. showModelModal.onSaveCallback(showModelModal.payload)
  130. setShowModelModal(null)
  131. }, [showModelModal])
  132. const handleCancelExternalApiModal = useCallback(() => {
  133. setShowExternalKnowledgeAPIModal(null)
  134. if (showExternalKnowledgeAPIModal?.onCancelCallback)
  135. showExternalKnowledgeAPIModal.onCancelCallback()
  136. }, [showExternalKnowledgeAPIModal])
  137. const handleSaveExternalApiModal = useCallback(async (updatedFormValue: CreateExternalAPIReq) => {
  138. if (showExternalKnowledgeAPIModal?.onSaveCallback)
  139. showExternalKnowledgeAPIModal.onSaveCallback(updatedFormValue)
  140. setShowExternalKnowledgeAPIModal(null)
  141. }, [showExternalKnowledgeAPIModal])
  142. const handleEditExternalApiModal = useCallback(async (updatedFormValue: CreateExternalAPIReq) => {
  143. if (showExternalKnowledgeAPIModal?.onEditCallback)
  144. showExternalKnowledgeAPIModal.onEditCallback(updatedFormValue)
  145. setShowExternalKnowledgeAPIModal(null)
  146. }, [showExternalKnowledgeAPIModal])
  147. const handleCancelModelLoadBalancingEntryModal = useCallback(() => {
  148. showModelLoadBalancingEntryModal?.onCancelCallback?.()
  149. setShowModelLoadBalancingEntryModal(null)
  150. }, [showModelLoadBalancingEntryModal])
  151. const handleCancelOpeningModal = useCallback(() => {
  152. setShowOpeningModal(null)
  153. if (showOpeningModal?.onCancelCallback)
  154. showOpeningModal.onCancelCallback()
  155. }, [showOpeningModal])
  156. const handleSaveModelLoadBalancingEntryModal = useCallback((entry: ModelLoadBalancingConfigEntry) => {
  157. showModelLoadBalancingEntryModal?.onSaveCallback?.({
  158. ...showModelLoadBalancingEntryModal.payload,
  159. entry,
  160. })
  161. setShowModelLoadBalancingEntryModal(null)
  162. }, [showModelLoadBalancingEntryModal])
  163. const handleRemoveModelLoadBalancingEntry = useCallback(() => {
  164. showModelLoadBalancingEntryModal?.onRemoveCallback?.(showModelLoadBalancingEntryModal.payload)
  165. setShowModelLoadBalancingEntryModal(null)
  166. }, [showModelLoadBalancingEntryModal])
  167. const handleSaveApiBasedExtension = (newApiBasedExtension: ApiBasedExtension) => {
  168. if (showApiBasedExtensionModal?.onSaveCallback)
  169. showApiBasedExtensionModal.onSaveCallback(newApiBasedExtension)
  170. setShowApiBasedExtensionModal(null)
  171. }
  172. const handleSaveModeration = (newModerationConfig: ModerationConfig) => {
  173. if (showModerationSettingModal?.onSaveCallback)
  174. showModerationSettingModal.onSaveCallback(newModerationConfig)
  175. setShowModerationSettingModal(null)
  176. }
  177. const handleSaveExternalDataTool = (newExternalDataTool: ExternalDataTool) => {
  178. if (showExternalDataToolModal?.onSaveCallback)
  179. showExternalDataToolModal.onSaveCallback(newExternalDataTool)
  180. setShowExternalDataToolModal(null)
  181. }
  182. const handleValidateBeforeSaveExternalDataTool = (newExternalDataTool: ExternalDataTool) => {
  183. if (showExternalDataToolModal?.onValidateBeforeSaveCallback)
  184. return showExternalDataToolModal?.onValidateBeforeSaveCallback(newExternalDataTool)
  185. return true
  186. }
  187. const handleSaveOpeningModal = (newOpening: OpeningStatement) => {
  188. if (showOpeningModal?.onSaveCallback)
  189. showOpeningModal.onSaveCallback(newOpening)
  190. setShowOpeningModal(null)
  191. }
  192. return (
  193. <ModalContext.Provider value={{
  194. setShowAccountSettingModal,
  195. setShowApiBasedExtensionModal,
  196. setShowModerationSettingModal,
  197. setShowExternalDataToolModal,
  198. setShowPricingModal: () => setShowPricingModal(true),
  199. setShowAnnotationFullModal: () => setShowAnnotationFullModal(true),
  200. setShowModelModal,
  201. setShowExternalKnowledgeAPIModal,
  202. setShowModelLoadBalancingModal,
  203. setShowModelLoadBalancingEntryModal,
  204. setShowOpeningModal,
  205. }}>
  206. <>
  207. {children}
  208. {
  209. !!showAccountSettingModal && (
  210. <AccountSetting
  211. activeTab={showAccountSettingModal.payload}
  212. onCancel={handleCancelAccountSettingModal}
  213. />
  214. )
  215. }
  216. {
  217. !!showApiBasedExtensionModal && (
  218. <ApiBasedExtensionModal
  219. data={showApiBasedExtensionModal.payload}
  220. onCancel={() => setShowApiBasedExtensionModal(null)}
  221. onSave={handleSaveApiBasedExtension}
  222. />
  223. )
  224. }
  225. {
  226. !!showModerationSettingModal && (
  227. <ModerationSettingModal
  228. data={showModerationSettingModal.payload}
  229. onCancel={handleCancelModerationSettingModal}
  230. onSave={handleSaveModeration}
  231. />
  232. )
  233. }
  234. {
  235. !!showExternalDataToolModal && (
  236. <ExternalDataToolModal
  237. data={showExternalDataToolModal.payload}
  238. onCancel={handleCancelExternalDataToolModal}
  239. onSave={handleSaveExternalDataTool}
  240. onValidateBeforeSave={handleValidateBeforeSaveExternalDataTool}
  241. />
  242. )
  243. }
  244. {
  245. !!showPricingModal && (
  246. <Pricing onCancel={() => {
  247. if (searchParams.get('show-pricing') === '1')
  248. router.push(location.pathname, { forceOptimisticNavigation: true } as any)
  249. setShowPricingModal(false)
  250. }} />
  251. )
  252. }
  253. {
  254. showAnnotationFullModal && (
  255. <AnnotationFullModal
  256. show={showAnnotationFullModal}
  257. onHide={() => setShowAnnotationFullModal(false)} />
  258. )
  259. }
  260. {
  261. !!showModelModal && (
  262. <ModelModal
  263. provider={showModelModal.payload.currentProvider}
  264. configurateMethod={showModelModal.payload.currentConfigurationMethod}
  265. currentCustomConfigurationModelFixedFields={showModelModal.payload.currentCustomConfigurationModelFixedFields}
  266. onCancel={handleCancelModelModal}
  267. onSave={handleSaveModelModal}
  268. />
  269. )
  270. }
  271. {
  272. !!showExternalKnowledgeAPIModal && (
  273. <ExternalAPIModal
  274. data={showExternalKnowledgeAPIModal.payload}
  275. datasetBindings={showExternalKnowledgeAPIModal.datasetBindings ?? []}
  276. onSave={handleSaveExternalApiModal}
  277. onCancel={handleCancelExternalApiModal}
  278. onEdit={handleEditExternalApiModal}
  279. isEditMode={showExternalKnowledgeAPIModal.isEditMode ?? false}
  280. />
  281. )
  282. }
  283. {
  284. Boolean(showModelLoadBalancingModal) && (
  285. <ModelLoadBalancingModal {...showModelLoadBalancingModal!} />
  286. )
  287. }
  288. {
  289. !!showModelLoadBalancingEntryModal && (
  290. <ModelLoadBalancingEntryModal
  291. provider={showModelLoadBalancingEntryModal.payload.currentProvider}
  292. configurationMethod={showModelLoadBalancingEntryModal.payload.currentConfigurationMethod}
  293. currentCustomConfigurationModelFixedFields={showModelLoadBalancingEntryModal.payload.currentCustomConfigurationModelFixedFields}
  294. entry={showModelLoadBalancingEntryModal.payload.entry}
  295. onCancel={handleCancelModelLoadBalancingEntryModal}
  296. onSave={handleSaveModelLoadBalancingEntryModal}
  297. onRemove={handleRemoveModelLoadBalancingEntry}
  298. />
  299. )
  300. }
  301. {showOpeningModal && (
  302. <OpeningSettingModal
  303. data={showOpeningModal.payload}
  304. onSave={handleSaveOpeningModal}
  305. onCancel={handleCancelOpeningModal}
  306. promptVariables={showOpeningModal.payload.promptVariables}
  307. onAutoAddPromptVariable={showOpeningModal.payload.onAutoAddPromptVariable}
  308. />
  309. )}
  310. </>
  311. </ModalContext.Provider>
  312. )
  313. }
  314. export default ModalContext