+
{children}
)}
@@ -183,3 +166,5 @@ Toast.notify = ({
}
export default Toast
+
+export type { IToastProps } from './context'
diff --git a/web/app/components/custom/custom-web-app-brand/__tests__/index.spec.tsx b/web/app/components/custom/custom-web-app-brand/__tests__/index.spec.tsx
index 2ceb45235c..1d17a2ae0f 100644
--- a/web/app/components/custom/custom-web-app-brand/__tests__/index.spec.tsx
+++ b/web/app/components/custom/custom-web-app-brand/__tests__/index.spec.tsx
@@ -1,7 +1,7 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { getImageUploadErrorMessage, imageUpload } from '@/app/components/base/image-uploader/utils'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { Plan } from '@/app/components/billing/type'
import { useAppContext } from '@/context/app-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
@@ -9,7 +9,7 @@ import { useProviderContext } from '@/context/provider-context'
import { updateCurrentWorkspace } from '@/service/common'
import CustomWebAppBrand from '../index'
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: vi.fn(),
}))
vi.mock('@/service/common', () => ({
diff --git a/web/app/components/custom/custom-web-app-brand/index.tsx b/web/app/components/custom/custom-web-app-brand/index.tsx
index 438e69894d..e6f9a3837b 100644
--- a/web/app/components/custom/custom-web-app-brand/index.tsx
+++ b/web/app/components/custom/custom-web-app-brand/index.tsx
@@ -16,7 +16,7 @@ import { BubbleTextMod } from '@/app/components/base/icons/src/vender/solid/comm
import { getImageUploadErrorMessage, imageUpload } from '@/app/components/base/image-uploader/utils'
import DifyLogo from '@/app/components/base/logo/dify-logo'
import Switch from '@/app/components/base/switch'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { Plan } from '@/app/components/billing/type'
import { useAppContext } from '@/context/app-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
diff --git a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/__tests__/uploader.spec.tsx b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/__tests__/uploader.spec.tsx
index db67c91bc0..e47a876fe8 100644
--- a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/__tests__/uploader.spec.tsx
+++ b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/__tests__/uploader.spec.tsx
@@ -4,7 +4,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import Uploader from '../uploader'
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {
Provider: ({ children }: { children: React.ReactNode }) => children,
Consumer: ({ children }: { children: (value: { notify: typeof mockNotify }) => React.ReactNode }) => children({ notify: mockNotify }),
diff --git a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/hooks/use-dsl-import.ts b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/hooks/use-dsl-import.ts
index 87e55ea740..c839fad3a2 100644
--- a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/hooks/use-dsl-import.ts
+++ b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/hooks/use-dsl-import.ts
@@ -4,7 +4,7 @@ import { useRouter } from 'next/navigation'
import { useCallback, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import {
DSLImportMode,
diff --git a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
index 3fa940c60d..faf168c73a 100644
--- a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
+++ b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/uploader.tsx
@@ -10,7 +10,7 @@ import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import ActionButton from '@/app/components/base/action-button'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { cn } from '@/utils/classnames'
import { formatFileSize } from '@/utils/format'
diff --git a/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx b/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx
index a9f55c8b84..0a4064de2a 100644
--- a/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx
+++ b/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx
@@ -8,7 +8,7 @@ import { trackEvent } from '@/app/components/base/amplitude'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { createEmptyDataset } from '@/service/datasets'
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
diff --git a/web/app/components/datasets/create/file-uploader/hooks/__tests__/use-file-upload.spec.tsx b/web/app/components/datasets/create/file-uploader/hooks/__tests__/use-file-upload.spec.tsx
index b5d1a96554..80331afe2a 100644
--- a/web/app/components/datasets/create/file-uploader/hooks/__tests__/use-file-upload.spec.tsx
+++ b/web/app/components/datasets/create/file-uploader/hooks/__tests__/use-file-upload.spec.tsx
@@ -2,7 +2,7 @@ import type { ReactNode } from 'react'
import type { CustomFile, FileItem } from '@/models/datasets'
import { act, render, renderHook, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { PROGRESS_COMPLETE, PROGRESS_ERROR, PROGRESS_NOT_STARTED } from '../../constants'
// Import after mocks
diff --git a/web/app/components/datasets/create/file-uploader/hooks/use-file-upload.ts b/web/app/components/datasets/create/file-uploader/hooks/use-file-upload.ts
index e097bab755..ada60fac1a 100644
--- a/web/app/components/datasets/create/file-uploader/hooks/use-file-upload.ts
+++ b/web/app/components/datasets/create/file-uploader/hooks/use-file-upload.ts
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { getFileUploadErrorMessage } from '@/app/components/base/file-uploader/utils'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { IS_CE_EDITION } from '@/config'
import { useLocale } from '@/context/i18n'
import { LanguagesSupported } from '@/i18n-config/language'
diff --git a/web/app/components/datasets/documents/components/__tests__/operations.spec.tsx b/web/app/components/datasets/documents/components/__tests__/operations.spec.tsx
index 5aae8dda73..b988b1aeab 100644
--- a/web/app/components/datasets/documents/components/__tests__/operations.spec.tsx
+++ b/web/app/components/datasets/documents/components/__tests__/operations.spec.tsx
@@ -10,7 +10,7 @@ vi.mock('next/navigation', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {
Provider: ({ children }: { children: React.ReactNode }) => children,
},
diff --git a/web/app/components/datasets/documents/components/operations.tsx b/web/app/components/datasets/documents/components/operations.tsx
index 15c89a9b26..84e16c7c48 100644
--- a/web/app/components/datasets/documents/components/operations.tsx
+++ b/web/app/components/datasets/documents/components/operations.tsx
@@ -24,7 +24,7 @@ import Divider from '@/app/components/base/divider'
import { SearchLinesSparkle } from '@/app/components/base/icons/src/vender/knowledge'
import CustomPopover from '@/app/components/base/popover'
import Switch from '@/app/components/base/switch'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { IS_CE_EDITION } from '@/config'
import { DataSourceType, DocumentActionType } from '@/models/datasets'
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx
index bc9ce04beb..efd1f2a483 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx
@@ -9,7 +9,7 @@ const mockNotify = vi.fn()
const mockClose = vi.fn()
// Mock ToastContext with factory function
-vi.mock('@/app/components/base/toast', async () => {
+vi.mock('@/app/components/base/toast/context', async () => {
const { createContext, useContext } = await import('use-context-selector')
const context = createContext({ notify: mockNotify, close: mockClose })
return {
@@ -87,7 +87,7 @@ vi.mock('@/service/base', () => ({
// Import after all mocks are set up
const { useLocalFileUpload } = await import('../use-local-file-upload')
-const { ToastContext } = await import('@/app/components/base/toast')
+const { ToastContext } = await import('@/app/components/base/toast/context')
const createWrapper = () => {
return ({ children }: { children: ReactNode }) => (
diff --git a/web/app/components/datasets/documents/detail/batch-modal/__tests__/csv-uploader.spec.tsx b/web/app/components/datasets/documents/detail/batch-modal/__tests__/csv-uploader.spec.tsx
index 7fb1de7cf9..6876753714 100644
--- a/web/app/components/datasets/documents/detail/batch-modal/__tests__/csv-uploader.spec.tsx
+++ b/web/app/components/datasets/documents/detail/batch-modal/__tests__/csv-uploader.spec.tsx
@@ -25,7 +25,7 @@ vi.mock('@/hooks/use-theme', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {
Provider: ({ children }: { children: ReactNode }) => children,
Consumer: ({ children }: { children: (ctx: { notify: typeof mockNotify }) => ReactNode }) => children({ notify: mockNotify }),
diff --git a/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx b/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
index f3a86e910d..63efc766b7 100644
--- a/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
+++ b/web/app/components/datasets/documents/detail/batch-modal/csv-uploader.tsx
@@ -12,7 +12,7 @@ import Button from '@/app/components/base/button'
import { getFileUploadErrorMessage } from '@/app/components/base/file-uploader/utils'
import { Csv as CSVIcon } from '@/app/components/base/icons/src/public/files'
import SimplePieChart from '@/app/components/base/simple-pie-chart'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import useTheme from '@/hooks/use-theme'
import { upload } from '@/service/base'
import { useFileUploadConfig } from '@/service/use-common'
diff --git a/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx b/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx
index 5802fb8b82..59ecbf5f25 100644
--- a/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx
@@ -65,7 +65,7 @@ vi.mock('../../context', () => ({
},
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: { Provider: ({ children }: { children: React.ReactNode }) => children, Consumer: () => null },
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/datasets/documents/detail/completed/common/__tests__/regeneration-modal.spec.tsx b/web/app/components/datasets/documents/detail/completed/common/__tests__/regeneration-modal.spec.tsx
index 719e2867b7..cc7f1aafa4 100644
--- a/web/app/components/datasets/documents/detail/completed/common/__tests__/regeneration-modal.spec.tsx
+++ b/web/app/components/datasets/documents/detail/completed/common/__tests__/regeneration-modal.spec.tsx
@@ -1,7 +1,8 @@
import type { ReactNode } from 'react'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { EventEmitterContextProvider, useEventEmitterContextContext } from '@/context/event-emitter'
+import { useEventEmitterContextContext } from '@/context/event-emitter'
+import { EventEmitterContextProvider } from '@/context/event-emitter-provider'
import RegenerationModal from '../regeneration-modal'
// Store emit function for triggering events in tests
diff --git a/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-child-segment-data.spec.ts b/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-child-segment-data.spec.ts
index 83918a3f30..4cfb4d5927 100644
--- a/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-child-segment-data.spec.ts
+++ b/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-child-segment-data.spec.ts
@@ -59,7 +59,7 @@ vi.mock('../../../context', () => ({
},
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-segment-list-data.spec.ts b/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-segment-list-data.spec.ts
index aef2053298..f54c00e3e7 100644
--- a/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-segment-list-data.spec.ts
+++ b/web/app/components/datasets/documents/detail/completed/hooks/__tests__/use-segment-list-data.spec.ts
@@ -92,7 +92,7 @@ vi.mock('../../../context', () => ({
},
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/datasets/documents/detail/completed/hooks/use-child-segment-data.ts b/web/app/components/datasets/documents/detail/completed/hooks/use-child-segment-data.ts
index 4f4c6a532d..cdc8a0b22d 100644
--- a/web/app/components/datasets/documents/detail/completed/hooks/use-child-segment-data.ts
+++ b/web/app/components/datasets/documents/detail/completed/hooks/use-child-segment-data.ts
@@ -2,7 +2,7 @@ import type { ChildChunkDetail, ChildSegmentsResponse, SegmentDetailModel, Segme
import { useQueryClient } from '@tanstack/react-query'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import {
useChildSegmentList,
diff --git a/web/app/components/datasets/documents/detail/completed/hooks/use-segment-list-data.ts b/web/app/components/datasets/documents/detail/completed/hooks/use-segment-list-data.ts
index fd391d2864..aa91e9f464 100644
--- a/web/app/components/datasets/documents/detail/completed/hooks/use-segment-list-data.ts
+++ b/web/app/components/datasets/documents/detail/completed/hooks/use-segment-list-data.ts
@@ -4,7 +4,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { usePathname } from 'next/navigation'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { ChunkingMode } from '@/models/datasets'
import {
diff --git a/web/app/components/datasets/documents/detail/completed/new-child-segment.tsx b/web/app/components/datasets/documents/detail/completed/new-child-segment.tsx
index 89143662c6..7a6ae4b306 100644
--- a/web/app/components/datasets/documents/detail/completed/new-child-segment.tsx
+++ b/web/app/components/datasets/documents/detail/completed/new-child-segment.tsx
@@ -8,7 +8,7 @@ import { useContext } from 'use-context-selector'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
import Divider from '@/app/components/base/divider'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { ChunkingMode } from '@/models/datasets'
import { useAddChildSegment } from '@/service/knowledge/use-segment'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/datasets/documents/detail/embedding/index.tsx b/web/app/components/datasets/documents/detail/embedding/index.tsx
index e89a85c6de..bd344800db 100644
--- a/web/app/components/datasets/documents/detail/embedding/index.tsx
+++ b/web/app/components/datasets/documents/detail/embedding/index.tsx
@@ -5,7 +5,7 @@ import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useProcessRule } from '@/service/knowledge/use-dataset'
import { useDocumentContext } from '../context'
import { ProgressBar, RuleDetail, SegmentProgress, StatusHeader } from './components'
diff --git a/web/app/components/datasets/documents/detail/metadata/hooks/__tests__/use-metadata-state.spec.ts b/web/app/components/datasets/documents/detail/metadata/hooks/__tests__/use-metadata-state.spec.ts
index ab1d45338f..3d7b28c78c 100644
--- a/web/app/components/datasets/documents/detail/metadata/hooks/__tests__/use-metadata-state.spec.ts
+++ b/web/app/components/datasets/documents/detail/metadata/hooks/__tests__/use-metadata-state.spec.ts
@@ -3,7 +3,7 @@ import type { FullDocumentDetail } from '@/models/datasets'
import { act, renderHook } from '@testing-library/react'
import * as React from 'react'
import { describe, expect, it, vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useMetadataState } from '../use-metadata-state'
diff --git a/web/app/components/datasets/documents/detail/metadata/hooks/use-metadata-state.ts b/web/app/components/datasets/documents/detail/metadata/hooks/use-metadata-state.ts
index 08651b699e..f786609981 100644
--- a/web/app/components/datasets/documents/detail/metadata/hooks/use-metadata-state.ts
+++ b/web/app/components/datasets/documents/detail/metadata/hooks/use-metadata-state.ts
@@ -4,7 +4,7 @@ import type { DocType, FullDocumentDetail } from '@/models/datasets'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { modifyDocMetadata } from '@/service/datasets'
import { asyncRunSafe } from '@/utils'
import { useDocumentContext } from '../../context'
diff --git a/web/app/components/datasets/documents/detail/new-segment.tsx b/web/app/components/datasets/documents/detail/new-segment.tsx
index 3a58d6ac06..f32c94bf70 100644
--- a/web/app/components/datasets/documents/detail/new-segment.tsx
+++ b/web/app/components/datasets/documents/detail/new-segment.tsx
@@ -9,7 +9,7 @@ import { useContext } from 'use-context-selector'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useAppStore } from '@/app/components/app/store'
import Divider from '@/app/components/base/divider'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import ImageUploaderInChunk from '@/app/components/datasets/common/image-uploader/image-uploader-in-chunk'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { ChunkingMode } from '@/models/datasets'
diff --git a/web/app/components/datasets/documents/status-item/index.tsx b/web/app/components/datasets/documents/status-item/index.tsx
index 60d837fd81..8d3abed7cf 100644
--- a/web/app/components/datasets/documents/status-item/index.tsx
+++ b/web/app/components/datasets/documents/status-item/index.tsx
@@ -8,7 +8,7 @@ import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import Switch from '@/app/components/base/switch'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import Indicator from '@/app/components/header/indicator'
import { useDocumentDelete, useDocumentDisable, useDocumentEnable } from '@/service/knowledge/use-document'
diff --git a/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx
index a631de3ea0..66d9a163be 100644
--- a/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx
@@ -12,7 +12,7 @@ vi.mock('@/service/datasets', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/datasets/external-api/external-api-modal/index.tsx b/web/app/components/datasets/external-api/external-api-modal/index.tsx
index a9a87d11bd..b6e870cdc1 100644
--- a/web/app/components/datasets/external-api/external-api-modal/index.tsx
+++ b/web/app/components/datasets/external-api/external-api-modal/index.tsx
@@ -19,7 +19,7 @@ import {
PortalToFollowElem,
PortalToFollowElemContent,
} from '@/app/components/base/portal-to-follow-elem'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { createExternalAPI } from '@/service/datasets'
import Form from './Form'
diff --git a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
index ccd637887b..a6a60aa856 100644
--- a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
@@ -22,7 +22,7 @@ vi.mock('@/context/i18n', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/datasets/external-knowledge-base/connector/index.tsx b/web/app/components/datasets/external-knowledge-base/connector/index.tsx
index 1545c0d232..cf36eed382 100644
--- a/web/app/components/datasets/external-knowledge-base/connector/index.tsx
+++ b/web/app/components/datasets/external-knowledge-base/connector/index.tsx
@@ -5,7 +5,7 @@ import { useRouter } from 'next/navigation'
import * as React from 'react'
import { useState } from 'react'
import { trackEvent } from '@/app/components/base/amplitude'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import ExternalKnowledgeBaseCreate from '@/app/components/datasets/external-knowledge-base/create'
import { createExternalKnowledgeBase } from '@/service/datasets'
diff --git a/web/app/components/header/account-dropdown/workplace-selector/index.spec.tsx b/web/app/components/header/account-dropdown/workplace-selector/index.spec.tsx
index fc32b5f8df..20104b572c 100644
--- a/web/app/components/header/account-dropdown/workplace-selector/index.spec.tsx
+++ b/web/app/components/header/account-dropdown/workplace-selector/index.spec.tsx
@@ -1,7 +1,7 @@
import type { ProviderContextState } from '@/context/provider-context'
import type { IWorkspace } from '@/models/common'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { baseProviderContextValue, useProviderContext } from '@/context/provider-context'
import { useWorkspacesContext } from '@/context/workspace-context'
import { switchWorkspace } from '@/service/common'
diff --git a/web/app/components/header/account-dropdown/workplace-selector/index.tsx b/web/app/components/header/account-dropdown/workplace-selector/index.tsx
index 058935aa27..528686a26a 100644
--- a/web/app/components/header/account-dropdown/workplace-selector/index.tsx
+++ b/web/app/components/header/account-dropdown/workplace-selector/index.tsx
@@ -4,7 +4,7 @@ import { RiArrowDownSLine } from '@remixicon/react'
import { Fragment } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import PlanBadge from '@/app/components/header/plan-badge'
import { useWorkspacesContext } from '@/context/workspace-context'
import { switchWorkspace } from '@/service/common'
diff --git a/web/app/components/header/account-setting/api-based-extension-page/modal.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/modal.spec.tsx
index 3903fbfcf3..884ee8df33 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/modal.spec.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/modal.spec.tsx
@@ -1,8 +1,8 @@
import type { TFunction } from 'i18next'
-import type { IToastProps } from '@/app/components/base/toast'
+import type { IToastProps } from '@/app/components/base/toast/context'
import { fireEvent, render as RTLRender, screen, waitFor } from '@testing-library/react'
import * as reactI18next from 'react-i18next'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useDocLink } from '@/context/i18n'
import { addApiBasedExtension, updateApiBasedExtension } from '@/service/common'
import ApiBasedExtensionModal from './modal'
diff --git a/web/app/components/header/account-setting/api-based-extension-page/modal.tsx b/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
index b04981bf3c..efe6c46dcc 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education'
import Modal from '@/app/components/base/modal'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useDocLink } from '@/context/i18n'
import {
addApiBasedExtension,
diff --git a/web/app/components/header/account-setting/language-page/index.tsx b/web/app/components/header/account-setting/language-page/index.tsx
index 2a0604421f..5751e88285 100644
--- a/web/app/components/header/account-setting/language-page/index.tsx
+++ b/web/app/components/header/account-setting/language-page/index.tsx
@@ -7,7 +7,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { SimpleSelect } from '@/app/components/base/select'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import { useLocale } from '@/context/i18n'
import { setLocaleOnClient } from '@/i18n-config'
diff --git a/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.spec.tsx b/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.spec.tsx
index 46ce3f1992..ae0dd8cd4d 100644
--- a/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.spec.tsx
+++ b/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.spec.tsx
@@ -3,7 +3,7 @@ import type { ICurrentWorkspace } from '@/models/common'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import { updateWorkspaceInfo } from '@/service/common'
import EditWorkspaceModal from './index'
diff --git a/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.tsx b/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.tsx
index a702a83da9..1c3984b0b5 100644
--- a/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.tsx
+++ b/web/app/components/header/account-setting/members-page/edit-workspace-modal/index.tsx
@@ -6,7 +6,7 @@ import { useContext } from 'use-context-selector'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import { updateWorkspaceInfo } from '@/service/common'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/header/account-setting/members-page/invite-modal/index.spec.tsx b/web/app/components/header/account-setting/members-page/invite-modal/index.spec.tsx
index ef55425ee0..82882c8be5 100644
--- a/web/app/components/header/account-setting/members-page/invite-modal/index.spec.tsx
+++ b/web/app/components/header/account-setting/members-page/invite-modal/index.spec.tsx
@@ -2,7 +2,7 @@ import type { InvitationResponse } from '@/models/common'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useProviderContextSelector } from '@/context/provider-context'
import { inviteMember } from '@/service/common'
import InviteModal from './index'
diff --git a/web/app/components/header/account-setting/members-page/invite-modal/index.tsx b/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
index a8c0da40bf..8e4e47e0b8 100644
--- a/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
+++ b/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
@@ -9,7 +9,7 @@ import { ReactMultiEmail } from 'react-multi-email'
import { useContext } from 'use-context-selector'
import Button from '@/app/components/base/button'
import Modal from '@/app/components/base/modal'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { emailRegex } from '@/config'
import { useLocale } from '@/context/i18n'
import { useProviderContextSelector } from '@/context/provider-context'
diff --git a/web/app/components/header/account-setting/members-page/operation/index.spec.tsx b/web/app/components/header/account-setting/members-page/operation/index.spec.tsx
index 661b2fbc83..e5e7fac10f 100644
--- a/web/app/components/header/account-setting/members-page/operation/index.spec.tsx
+++ b/web/app/components/header/account-setting/members-page/operation/index.spec.tsx
@@ -2,7 +2,7 @@ import type { Member } from '@/models/common'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import Operation from './index'
const mockUpdateMemberRole = vi.fn()
diff --git a/web/app/components/header/account-setting/members-page/operation/index.tsx b/web/app/components/header/account-setting/members-page/operation/index.tsx
index 88c8e250ea..306a67a093 100644
--- a/web/app/components/header/account-setting/members-page/operation/index.tsx
+++ b/web/app/components/header/account-setting/members-page/operation/index.tsx
@@ -9,7 +9,7 @@ import {
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useProviderContext } from '@/context/provider-context'
import { deleteMemberOrCancelInvitation, updateMemberRole } from '@/service/common'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.spec.tsx b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.spec.tsx
index 11a0a2db4a..4baa90a7fa 100644
--- a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.spec.tsx
+++ b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.spec.tsx
@@ -3,7 +3,7 @@ import type { ICurrentWorkspace } from '@/models/common'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import { ownershipTransfer, sendOwnerEmail, verifyOwnerEmail } from '@/service/common'
import { useMembers } from '@/service/use-common'
diff --git a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx
index 21ea8aa1e9..c4f614737a 100644
--- a/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx
+++ b/web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx
@@ -6,7 +6,7 @@ import { useContext } from 'use-context-selector'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import {
ownershipTransfer,
diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.spec.tsx
index c2259f543c..b637fed894 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.spec.tsx
@@ -20,7 +20,7 @@ const mockAddModelCredential = vi.fn()
const mockEditProviderCredential = vi.fn()
const mockEditModelCredential = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.ts b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.ts
index 3576c749b2..4e01677b29 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.ts
+++ b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/use-auth.ts
@@ -12,7 +12,7 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
useModelModalHandler,
useRefreshModel,
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.spec.tsx
index 554efc93d2..9f493d25e5 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.spec.tsx
@@ -24,7 +24,7 @@ vi.mock('@/config', async (importOriginal) => {
}
})
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx
index c46f9d56bd..efa768e7f5 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx
@@ -3,7 +3,7 @@ import type {
} from '../declarations'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { ConfigProvider } from '@/app/components/header/account-setting/model-provider-page/model-auth'
import { useCredentialStatus } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
import Indicator from '@/app/components/header/indicator'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.spec.tsx
index ea78234612..b945b50e9b 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.spec.tsx
@@ -43,7 +43,7 @@ let mockCredentialData: CredentialData | undefined = {
current_credential_name: 'Default',
}
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx
index 93229f1257..0009237edc 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx
@@ -12,7 +12,7 @@ import Button from '@/app/components/base/button'
import Confirm from '@/app/components/base/confirm'
import Loading from '@/app/components/base/loading'
import Modal from '@/app/components/base/modal'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { SwitchCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
import {
useGetModelCredential,
diff --git a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.spec.tsx
index 819bb71164..22186b34e1 100644
--- a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.spec.tsx
@@ -42,7 +42,7 @@ vi.mock('@/context/provider-context', () => ({
}),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
index 29c71e04fc..5df062789b 100644
--- a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
@@ -12,7 +12,7 @@ import {
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
diff --git a/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.spec.tsx b/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.spec.tsx
index de480d47a1..97a79815ff 100644
--- a/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.spec.tsx
+++ b/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.spec.tsx
@@ -1,6 +1,6 @@
import type { PluginProvider } from '@/models/common'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import SerpapiPlugin from './SerpapiPlugin'
import { updatePluginKey, validatePluginKey } from './utils'
@@ -20,7 +20,7 @@ const mockEventEmitter = vi.hoisted(() => {
}
})
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: vi.fn(),
}))
diff --git a/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.tsx b/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.tsx
index f6909fad28..fe8832e84b 100644
--- a/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.tsx
+++ b/web/app/components/header/account-setting/plugin-page/SerpapiPlugin.tsx
@@ -2,7 +2,7 @@ import type { Form, ValidateValue } from '../key-validator/declarations'
import type { PluginProvider } from '@/models/common'
import Image from 'next/image'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useAppContext } from '@/context/app-context'
import SerpapiLogo from '../../assets/serpapi.png'
import KeyValidator from '../key-validator'
diff --git a/web/app/components/header/account-setting/plugin-page/index.spec.tsx b/web/app/components/header/account-setting/plugin-page/index.spec.tsx
index 654292443f..0654bb68aa 100644
--- a/web/app/components/header/account-setting/plugin-page/index.spec.tsx
+++ b/web/app/components/header/account-setting/plugin-page/index.spec.tsx
@@ -14,7 +14,7 @@ vi.mock('@/context/app-context', () => ({
useAppContext: vi.fn(),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: vi.fn(),
}),
diff --git a/web/app/components/header/index.spec.tsx b/web/app/components/header/index.spec.tsx
index 2d5ce50fb8..36c85e6f08 100644
--- a/web/app/components/header/index.spec.tsx
+++ b/web/app/components/header/index.spec.tsx
@@ -52,7 +52,7 @@ vi.mock('@/app/components/header/plan-badge', () => ({
),
}))
-vi.mock('@/context/workspace-context', () => ({
+vi.mock('@/context/workspace-context-provider', () => ({
WorkspaceProvider: ({ children }: { children?: React.ReactNode }) => children,
}))
diff --git a/web/app/components/header/index.tsx b/web/app/components/header/index.tsx
index 210c62b660..64498a82f8 100644
--- a/web/app/components/header/index.tsx
+++ b/web/app/components/header/index.tsx
@@ -8,7 +8,7 @@ import { useAppContext } from '@/context/app-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
-import { WorkspaceProvider } from '@/context/workspace-context'
+import { WorkspaceProvider } from '@/context/workspace-context-provider'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { Plan } from '../billing/type'
import AccountDropdown from './account-dropdown'
diff --git a/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx b/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx
index 7e8208b995..91ffbaa24a 100644
--- a/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx
@@ -42,7 +42,7 @@ vi.mock('@/context/app-context', () => ({
}),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: vi.fn() }),
}))
diff --git a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
index 6b66aca9dd..901c3ab49a 100644
--- a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
@@ -42,7 +42,7 @@ vi.mock('@/context/app-context', () => ({
}),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: vi.fn() }),
}))
diff --git a/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx b/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
index a99b3363d6..430149e50b 100644
--- a/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
@@ -9,7 +9,7 @@ const mockAddPluginCredential = vi.fn().mockResolvedValue({})
const mockUpdatePluginCredential = vi.fn().mockResolvedValue({})
const mockFormValues = { isCheckValidated: true, values: { __name__: 'My Key', api_key: 'sk-123' } }
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx b/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
index 51aa287fea..d120902e6d 100644
--- a/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
@@ -95,7 +95,7 @@ vi.mock('@/app/components/base/form/form-scenarios/auth', () => ({
// Mock useToastContext
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/plugins/plugin-auth/authorize/__tests__/oauth-client-settings.spec.tsx b/web/app/components/plugins/plugin-auth/authorize/__tests__/oauth-client-settings.spec.tsx
index 61920e2869..f1b86f80ea 100644
--- a/web/app/components/plugins/plugin-auth/authorize/__tests__/oauth-client-settings.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/__tests__/oauth-client-settings.spec.tsx
@@ -9,7 +9,7 @@ const mockDeletePluginOAuthCustomClient = vi.fn().mockResolvedValue({})
const mockInvalidPluginOAuthClientSchema = vi.fn()
const mockFormValues = { isCheckValidated: true, values: { __oauth_client__: 'custom', client_id: 'test-id' } }
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/plugins/plugin-auth/authorize/api-key-modal.tsx b/web/app/components/plugins/plugin-auth/authorize/api-key-modal.tsx
index cc98ca3731..d8ab1cafdd 100644
--- a/web/app/components/plugins/plugin-auth/authorize/api-key-modal.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/api-key-modal.tsx
@@ -16,7 +16,7 @@ import AuthForm from '@/app/components/base/form/form-scenarios/auth'
import { FormTypeEnum } from '@/app/components/base/form/types'
import Loading from '@/app/components/base/loading'
import Modal from '@/app/components/base/modal/modal'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { ReadmeEntrance } from '../../readme-panel/entrance'
import { ReadmeShowType } from '../../readme-panel/store'
import {
diff --git a/web/app/components/plugins/plugin-auth/authorize/oauth-client-settings.tsx b/web/app/components/plugins/plugin-auth/authorize/oauth-client-settings.tsx
index 7eb22ee4ac..28989da77c 100644
--- a/web/app/components/plugins/plugin-auth/authorize/oauth-client-settings.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/oauth-client-settings.tsx
@@ -17,7 +17,7 @@ import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import AuthForm from '@/app/components/base/form/form-scenarios/auth'
import Modal from '@/app/components/base/modal/modal'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { ReadmeEntrance } from '../../readme-panel/entrance'
import { ReadmeShowType } from '../../readme-panel/store'
import {
diff --git a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
index f56c814222..a617c2543e 100644
--- a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
@@ -52,7 +52,7 @@ vi.mock('../../hooks/use-credential', () => ({
// Mock toast context
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/plugins/plugin-auth/authorized/index.tsx b/web/app/components/plugins/plugin-auth/authorized/index.tsx
index ea58cd16c9..daee3131ad 100644
--- a/web/app/components/plugins/plugin-auth/authorized/index.tsx
+++ b/web/app/components/plugins/plugin-auth/authorized/index.tsx
@@ -19,7 +19,7 @@ import {
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import Indicator from '@/app/components/header/indicator'
import { cn } from '@/utils/classnames'
import Authorize from '../authorize'
diff --git a/web/app/components/plugins/plugin-auth/hooks/__tests__/use-plugin-auth-action.spec.ts b/web/app/components/plugins/plugin-auth/hooks/__tests__/use-plugin-auth-action.spec.ts
index d31b29ab85..f779623697 100644
--- a/web/app/components/plugins/plugin-auth/hooks/__tests__/use-plugin-auth-action.spec.ts
+++ b/web/app/components/plugins/plugin-auth/hooks/__tests__/use-plugin-auth-action.spec.ts
@@ -11,7 +11,7 @@ const mockSetPluginDefaultCredential = vi.fn().mockResolvedValue({})
const mockUpdatePluginCredential = vi.fn().mockResolvedValue({})
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/plugins/plugin-auth/hooks/use-plugin-auth-action.ts b/web/app/components/plugins/plugin-auth/hooks/use-plugin-auth-action.ts
index e9218e2d3d..5628c76cc3 100644
--- a/web/app/components/plugins/plugin-auth/hooks/use-plugin-auth-action.ts
+++ b/web/app/components/plugins/plugin-auth/hooks/use-plugin-auth-action.ts
@@ -5,7 +5,7 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
useDeletePluginCredentialHook,
useSetPluginDefaultCredentialHook,
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/apikey-edit-modal.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/apikey-edit-modal.spec.tsx
index af145df2da..e0fb7455ce 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/apikey-edit-modal.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/apikey-edit-modal.spec.tsx
@@ -54,13 +54,16 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
default: {
notify: (args: { type: string, message: string }) => mockToast(args),
},
- useToastContext: () => ({
- notify: (args: { type: string, message: string }) => mockToast(args),
- close: vi.fn(),
- }),
}
})
+vi.mock('@/app/components/base/toast/context', () => ({
+ useToastContext: () => ({
+ notify: (args: { type: string, message: string }) => mockToast(args),
+ close: vi.fn(),
+ }),
+}))
+
const createSubscription = (overrides: Partial
= {}): TriggerSubscription => ({
id: 'sub-1',
name: 'Subscription One',
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/manual-edit-modal.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/manual-edit-modal.spec.tsx
index c6144542ab..60a8428287 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/manual-edit-modal.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/manual-edit-modal.spec.tsx
@@ -37,13 +37,16 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
default: {
notify: (args: { type: string, message: string }) => mockToast(args),
},
- useToastContext: () => ({
- notify: (args: { type: string, message: string }) => mockToast(args),
- close: vi.fn(),
- }),
}
})
+vi.mock('@/app/components/base/toast/context', () => ({
+ useToastContext: () => ({
+ notify: (args: { type: string, message: string }) => mockToast(args),
+ close: vi.fn(),
+ }),
+}))
+
const createSubscription = (overrides: Partial = {}): TriggerSubscription => ({
id: 'sub-1',
name: 'Subscription One',
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/oauth-edit-modal.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/oauth-edit-modal.spec.tsx
index 7bdcdbc936..8835b46695 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/oauth-edit-modal.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/edit/__tests__/oauth-edit-modal.spec.tsx
@@ -37,13 +37,16 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
default: {
notify: (args: { type: string, message: string }) => mockToast(args),
},
- useToastContext: () => ({
- notify: (args: { type: string, message: string }) => mockToast(args),
- close: vi.fn(),
- }),
}
})
+vi.mock('@/app/components/base/toast/context', () => ({
+ useToastContext: () => ({
+ notify: (args: { type: string, message: string }) => mockToast(args),
+ close: vi.fn(),
+ }),
+}))
+
const createSubscription = (overrides: Partial = {}): TriggerSubscription => ({
id: 'sub-1',
name: 'Subscription One',
diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/__tests__/tool-credentials-form.spec.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/__tests__/tool-credentials-form.spec.tsx
index 20655d0139..cb5b929d29 100644
--- a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/__tests__/tool-credentials-form.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/__tests__/tool-credentials-form.spec.tsx
@@ -12,6 +12,9 @@ vi.mock('@/utils/classnames', () => ({
vi.mock('@/app/components/base/toast', () => ({
default: { notify: vi.fn() },
+}))
+
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: vi.fn() }),
}))
diff --git a/web/app/components/plugins/plugin-page/__tests__/context.spec.tsx b/web/app/components/plugins/plugin-page/__tests__/context.spec.tsx
index ab0e35e042..389c161e8a 100644
--- a/web/app/components/plugins/plugin-page/__tests__/context.spec.tsx
+++ b/web/app/components/plugins/plugin-page/__tests__/context.spec.tsx
@@ -3,7 +3,8 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
// Import mocks
import { useGlobalPublicStore } from '@/context/global-public-context'
-import { PluginPageContext, PluginPageContextProvider, usePluginPageContext } from '../context'
+import { PluginPageContext, usePluginPageContext } from '../context'
+import { PluginPageContextProvider } from '../context-provider'
// Mock dependencies
vi.mock('nuqs', () => ({
diff --git a/web/app/components/plugins/plugin-page/context.tsx b/web/app/components/plugins/plugin-page/context-provider.tsx
similarity index 58%
rename from web/app/components/plugins/plugin-page/context.tsx
rename to web/app/components/plugins/plugin-page/context-provider.tsx
index 01ec518347..83776b48f9 100644
--- a/web/app/components/plugins/plugin-page/context.tsx
+++ b/web/app/components/plugins/plugin-page/context-provider.tsx
@@ -1,24 +1,20 @@
'use client'
-import type { ReactNode, RefObject } from 'react'
+import type { ReactNode } from 'react'
+import type { PluginPageTab } from './context'
import type { FilterState } from './filter-management'
-import { noop } from 'es-toolkit/function'
import { parseAsStringEnum, useQueryState } from 'nuqs'
import {
useMemo,
useRef,
useState,
} from 'react'
-import {
- createContext,
- useContextSelector,
-} from 'use-context-selector'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { PLUGIN_PAGE_TABS_MAP, usePluginPageTabs } from '../hooks'
import { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/constants'
-
-export type PluginPageTab = typeof PLUGIN_PAGE_TABS_MAP[keyof typeof PLUGIN_PAGE_TABS_MAP]
- | (typeof PLUGIN_TYPE_SEARCH_MAP)[keyof typeof PLUGIN_TYPE_SEARCH_MAP]
+import {
+ PluginPageContext,
+} from './context'
const PLUGIN_PAGE_TAB_VALUES: PluginPageTab[] = [
PLUGIN_PAGE_TABS_MAP.plugins,
@@ -29,42 +25,10 @@ const PLUGIN_PAGE_TAB_VALUES: PluginPageTab[] = [
const parseAsPluginPageTab = parseAsStringEnum(PLUGIN_PAGE_TAB_VALUES)
.withDefault(PLUGIN_PAGE_TABS_MAP.plugins)
-export type PluginPageContextValue = {
- containerRef: RefObject
- currentPluginID: string | undefined
- setCurrentPluginID: (pluginID?: string) => void
- filters: FilterState
- setFilters: (filter: FilterState) => void
- activeTab: PluginPageTab
- setActiveTab: (tab: PluginPageTab) => void
- options: Array<{ value: string, text: string }>
-}
-
-const emptyContainerRef: RefObject = { current: null }
-
-export const PluginPageContext = createContext({
- containerRef: emptyContainerRef,
- currentPluginID: undefined,
- setCurrentPluginID: noop,
- filters: {
- categories: [],
- tags: [],
- searchQuery: '',
- },
- setFilters: noop,
- activeTab: PLUGIN_PAGE_TABS_MAP.plugins,
- setActiveTab: noop,
- options: [],
-})
-
type PluginPageContextProviderProps = {
children: ReactNode
}
-export function usePluginPageContext(selector: (value: PluginPageContextValue) => any) {
- return useContextSelector(PluginPageContext, selector)
-}
-
export const PluginPageContextProvider = ({
children,
}: PluginPageContextProviderProps) => {
diff --git a/web/app/components/plugins/plugin-page/context.ts b/web/app/components/plugins/plugin-page/context.ts
new file mode 100644
index 0000000000..04ab1eef19
--- /dev/null
+++ b/web/app/components/plugins/plugin-page/context.ts
@@ -0,0 +1,46 @@
+'use client'
+
+import type { RefObject } from 'react'
+import type { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/constants'
+import type { FilterState } from './filter-management'
+import { noop } from 'es-toolkit/function'
+import {
+ createContext,
+ useContextSelector,
+} from 'use-context-selector'
+import { PLUGIN_PAGE_TABS_MAP } from '../hooks'
+
+export type PluginPageTab = typeof PLUGIN_PAGE_TABS_MAP[keyof typeof PLUGIN_PAGE_TABS_MAP]
+ | (typeof PLUGIN_TYPE_SEARCH_MAP)[keyof typeof PLUGIN_TYPE_SEARCH_MAP]
+
+export type PluginPageContextValue = {
+ containerRef: RefObject
+ currentPluginID: string | undefined
+ setCurrentPluginID: (pluginID?: string) => void
+ filters: FilterState
+ setFilters: (filter: FilterState) => void
+ activeTab: PluginPageTab
+ setActiveTab: (tab: PluginPageTab) => void
+ options: Array<{ value: string, text: string }>
+}
+
+const emptyContainerRef: RefObject = { current: null }
+
+export const PluginPageContext = createContext({
+ containerRef: emptyContainerRef,
+ currentPluginID: undefined,
+ setCurrentPluginID: noop,
+ filters: {
+ categories: [],
+ tags: [],
+ searchQuery: '',
+ },
+ setFilters: noop,
+ activeTab: PLUGIN_PAGE_TABS_MAP.plugins,
+ setActiveTab: noop,
+ options: [],
+})
+
+export function usePluginPageContext(selector: (value: PluginPageContextValue) => any) {
+ return useContextSelector(PluginPageContext, selector)
+}
diff --git a/web/app/components/plugins/plugin-page/index.tsx b/web/app/components/plugins/plugin-page/index.tsx
index bec1eb60ab..6768361acf 100644
--- a/web/app/components/plugins/plugin-page/index.tsx
+++ b/web/app/components/plugins/plugin-page/index.tsx
@@ -28,10 +28,8 @@ import { PLUGIN_PAGE_TABS_MAP } from '../hooks'
import InstallFromLocalPackage from '../install-plugin/install-from-local-package'
import InstallFromMarketplace from '../install-plugin/install-from-marketplace'
import { PLUGIN_TYPE_SEARCH_MAP } from '../marketplace/constants'
-import {
- PluginPageContextProvider,
- usePluginPageContext,
-} from './context'
+import { usePluginPageContext } from './context'
+import { PluginPageContextProvider } from './context-provider'
import DebugInfo from './debug-info'
import InstallPluginDropdown from './install-plugin-dropdown'
import PluginTasks from './plugin-tasks'
diff --git a/web/app/components/rag-pipeline/components/__tests__/update-dsl-modal.spec.tsx b/web/app/components/rag-pipeline/components/__tests__/update-dsl-modal.spec.tsx
index 2f9b2172bd..98ad5f78f4 100644
--- a/web/app/components/rag-pipeline/components/__tests__/update-dsl-modal.spec.tsx
+++ b/web/app/components/rag-pipeline/components/__tests__/update-dsl-modal.spec.tsx
@@ -20,7 +20,7 @@ vi.mock('use-context-selector', () => ({
useContext: () => ({ notify: mockNotify }),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: { Provider: ({ children }: PropsWithChildren) => children },
}))
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/__tests__/index.spec.tsx
index 0b858eaaa7..00c989acb0 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/__tests__/index.spec.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/__tests__/index.spec.tsx
@@ -155,7 +155,7 @@ vi.mock('@/app/components/base/amplitude', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx
index 6129d3fe73..9cd1af2736 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx
@@ -3,7 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import Publisher from '../index'
import Popup from '../popup'
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx
index 71707721a4..48282820d8 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/popup.spec.tsx
@@ -57,7 +57,7 @@ vi.mock('@/app/components/workflow/store', () => ({
}),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
index 2dd56b4277..371e4fd721 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
@@ -24,7 +24,7 @@ import Confirm from '@/app/components/base/confirm'
import Divider from '@/app/components/base/divider'
import { SparklesSoft } from '@/app/components/base/icons/src/public/common'
import PremiumBadge from '@/app/components/base/premium-badge'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
useChecklistBeforePublish,
} from '@/app/components/workflow/hooks'
diff --git a/web/app/components/rag-pipeline/hooks/__tests__/index.spec.ts b/web/app/components/rag-pipeline/hooks/__tests__/index.spec.ts
index 4c60e5133c..95fe763d61 100644
--- a/web/app/components/rag-pipeline/hooks/__tests__/index.spec.ts
+++ b/web/app/components/rag-pipeline/hooks/__tests__/index.spec.ts
@@ -31,7 +31,7 @@ vi.mock('@/app/components/workflow/store', () => ({
}))
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({
notify: mockNotify,
}),
diff --git a/web/app/components/rag-pipeline/hooks/__tests__/use-DSL.spec.ts b/web/app/components/rag-pipeline/hooks/__tests__/use-DSL.spec.ts
index c0b983052d..c5603f2fc7 100644
--- a/web/app/components/rag-pipeline/hooks/__tests__/use-DSL.spec.ts
+++ b/web/app/components/rag-pipeline/hooks/__tests__/use-DSL.spec.ts
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useDSL } from '../use-DSL'
const mockNotify = vi.fn()
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: mockNotify }),
}))
diff --git a/web/app/components/rag-pipeline/hooks/__tests__/use-update-dsl-modal.spec.ts b/web/app/components/rag-pipeline/hooks/__tests__/use-update-dsl-modal.spec.ts
index 942e337ad8..a50965fb3b 100644
--- a/web/app/components/rag-pipeline/hooks/__tests__/use-update-dsl-modal.spec.ts
+++ b/web/app/components/rag-pipeline/hooks/__tests__/use-update-dsl-modal.spec.ts
@@ -23,7 +23,7 @@ vi.mock('use-context-selector', () => ({
useContext: () => ({ notify: mockNotify }),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
ToastContext: {},
}))
diff --git a/web/app/components/rag-pipeline/hooks/use-DSL.ts b/web/app/components/rag-pipeline/hooks/use-DSL.ts
index 5c0f9def1c..f45cf35bdf 100644
--- a/web/app/components/rag-pipeline/hooks/use-DSL.ts
+++ b/web/app/components/rag-pipeline/hooks/use-DSL.ts
@@ -3,7 +3,7 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
DSL_EXPORT_CHECK,
} from '@/app/components/workflow/constants'
diff --git a/web/app/components/rag-pipeline/hooks/use-update-dsl-modal.ts b/web/app/components/rag-pipeline/hooks/use-update-dsl-modal.ts
index 3b86937417..48d2bc78b4 100644
--- a/web/app/components/rag-pipeline/hooks/use-update-dsl-modal.ts
+++ b/web/app/components/rag-pipeline/hooks/use-update-dsl-modal.ts
@@ -6,7 +6,7 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { WORKFLOW_DATA_UPDATE } from '@/app/components/workflow/constants'
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import { useWorkflowStore } from '@/app/components/workflow/store'
diff --git a/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx b/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
index 4a7fd1275f..2318a1c7bc 100644
--- a/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
+++ b/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
@@ -4,7 +4,7 @@ import type { App } from '@/types/app'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useStore as useAppStore } from '@/app/components/app/store'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { Plan } from '@/app/components/billing/type'
import { BlockEnum, InputVarType } from '@/app/components/workflow/types'
import FeaturesTrigger from '../features-trigger'
diff --git a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
index d58eb6c669..84603e9a13 100644
--- a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
+++ b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
@@ -17,7 +17,7 @@ import AppPublisher from '@/app/components/app/app-publisher'
import { useStore as useAppStore } from '@/app/components/app/store'
import Button from '@/app/components/base/button'
import { useFeatures } from '@/app/components/base/features/hooks'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { Plan } from '@/app/components/billing/type'
import {
useChecklist,
diff --git a/web/app/components/workflow-app/hooks/use-DSL.ts b/web/app/components/workflow-app/hooks/use-DSL.ts
index 939e43b554..918a60f185 100644
--- a/web/app/components/workflow-app/hooks/use-DSL.ts
+++ b/web/app/components/workflow-app/hooks/use-DSL.ts
@@ -4,7 +4,7 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
DSL_EXPORT_CHECK,
} from '@/app/components/workflow/constants'
diff --git a/web/app/components/workflow/header/run-mode.tsx b/web/app/components/workflow/header/run-mode.tsx
index 63c48ff0dc..943af13a92 100644
--- a/web/app/components/workflow/header/run-mode.tsx
+++ b/web/app/components/workflow/header/run-mode.tsx
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { trackEvent } from '@/app/components/base/amplitude'
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useWorkflowRun, useWorkflowRunValidation, useWorkflowStartRun } from '@/app/components/workflow/hooks'
import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import { useStore } from '@/app/components/workflow/store'
diff --git a/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts b/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
index d72d001e0b..1b37055134 100644
--- a/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
+++ b/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
@@ -82,7 +82,7 @@ vi.mock('../index', () => ({
useNodesMetaData: () => ({ nodes: [], nodesMap: mockNodesMap }),
}))
-vi.mock('@/app/components/base/toast', () => ({
+vi.mock('@/app/components/base/toast/context', () => ({
useToastContext: () => ({ notify: vi.fn() }),
}))
diff --git a/web/app/components/workflow/hooks/use-checklist.ts b/web/app/components/workflow/hooks/use-checklist.ts
index 642179aed7..dd1d012aed 100644
--- a/web/app/components/workflow/hooks/use-checklist.ts
+++ b/web/app/components/workflow/hooks/use-checklist.ts
@@ -22,7 +22,7 @@ import {
import { useTranslation } from 'react-i18next'
import { useEdges, useStoreApi } from 'reactflow'
import { useStore as useAppStore } from '@/app/components/app/store'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
import useNodes from '@/app/components/workflow/store/workflow/use-nodes'
diff --git a/web/app/components/workflow/note-node/note-editor/plugins/link-editor-plugin/hooks.ts b/web/app/components/workflow/note-node/note-editor/plugins/link-editor-plugin/hooks.ts
index 3a084ef0af..511940d142 100644
--- a/web/app/components/workflow/note-node/note-editor/plugins/link-editor-plugin/hooks.ts
+++ b/web/app/components/workflow/note-node/note-editor/plugins/link-editor-plugin/hooks.ts
@@ -15,7 +15,7 @@ import {
useEffect,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { useNoteEditorStore } from '../../store'
import { urlRegExp } from '../../utils'
diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/object-value-item.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/object-value-item.tsx
index ef4b4d71a9..74765c2b9e 100644
--- a/web/app/components/workflow/panel/chat-variable-panel/components/object-value-item.tsx
+++ b/web/app/components/workflow/panel/chat-variable-panel/components/object-value-item.tsx
@@ -5,7 +5,7 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import RemoveButton from '@/app/components/workflow/nodes/_base/components/remove-button'
import VariableTypeSelector from '@/app/components/workflow/panel/chat-variable-panel/components/variable-type-select'
import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel/type'
diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx
index 5c07cca3df..dd14bcf75a 100644
--- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx
+++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx
@@ -7,7 +7,7 @@ import { useContext } from 'use-context-selector'
import { v4 as uuid4 } from 'uuid'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import ArrayValueList from '@/app/components/workflow/panel/chat-variable-panel/components/array-value-list'
diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts
index b31673ee26..3481733cd2 100644
--- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts
+++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts
@@ -26,7 +26,7 @@ import {
getProcessedFiles,
getProcessedFilesFromResponse,
} from '@/app/components/base/file-uploader/utils'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import {
CUSTOM_NODE,
} from '@/app/components/workflow/constants'
diff --git a/web/app/components/workflow/panel/env-panel/variable-modal.tsx b/web/app/components/workflow/panel/env-panel/variable-modal.tsx
index 0e120ac77c..493a73405a 100644
--- a/web/app/components/workflow/panel/env-panel/variable-modal.tsx
+++ b/web/app/components/workflow/panel/env-panel/variable-modal.tsx
@@ -7,7 +7,7 @@ import { useContext } from 'use-context-selector'
import { v4 as uuid4 } from 'uuid'
import Button from '@/app/components/base/button'
import Input from '@/app/components/base/input'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx
index 441002c86c..96acb1a026 100644
--- a/web/app/components/workflow/run/index.tsx
+++ b/web/app/components/workflow/run/index.tsx
@@ -6,7 +6,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import Loading from '@/app/components/base/loading'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
import { fetchRunDetail, fetchTracingList } from '@/service/log'
import { cn } from '@/utils/classnames'
diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx
index d33679ff1b..08107a0c24 100644
--- a/web/app/components/workflow/update-dsl-modal.tsx
+++ b/web/app/components/workflow/update-dsl-modal.tsx
@@ -24,7 +24,7 @@ import { useStore as useAppStore } from '@/app/components/app/store'
import Button from '@/app/components/base/button'
import Modal from '@/app/components/base/modal'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
-import { ToastContext } from '@/app/components/base/toast'
+import { ToastContext } from '@/app/components/base/toast/context'
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import {
diff --git a/web/app/education-apply/education-apply-page.tsx b/web/app/education-apply/education-apply-page.tsx
index 3f8d80a67e..636a471d3d 100644
--- a/web/app/education-apply/education-apply-page.tsx
+++ b/web/app/education-apply/education-apply-page.tsx
@@ -12,7 +12,7 @@ import {
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Checkbox from '@/app/components/base/checkbox'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { EDUCATION_VERIFYING_LOCALSTORAGE_ITEM } from '@/app/education-apply/constants'
import { useDocLink } from '@/context/i18n'
import { useProviderContext } from '@/context/provider-context'
diff --git a/web/context/datasets-context.tsx b/web/context/datasets-context.ts
similarity index 100%
rename from web/context/datasets-context.tsx
rename to web/context/datasets-context.ts
diff --git a/web/context/event-emitter-provider.tsx b/web/context/event-emitter-provider.tsx
new file mode 100644
index 0000000000..da8d2d78c2
--- /dev/null
+++ b/web/context/event-emitter-provider.tsx
@@ -0,0 +1,22 @@
+'use client'
+
+import type { ReactNode } from 'react'
+import type { EventEmitterValue } from './event-emitter'
+import { useEventEmitter } from 'ahooks'
+import { EventEmitterContext } from './event-emitter'
+
+type EventEmitterContextProviderProps = {
+ children: ReactNode
+}
+
+export const EventEmitterContextProvider = ({
+ children,
+}: EventEmitterContextProviderProps) => {
+ const eventEmitter = useEventEmitter()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/web/context/event-emitter.tsx b/web/context/event-emitter.ts
similarity index 53%
rename from web/context/event-emitter.tsx
rename to web/context/event-emitter.ts
index 14b81eacb6..eb7794dfe1 100644
--- a/web/context/event-emitter.tsx
+++ b/web/context/event-emitter.ts
@@ -1,7 +1,6 @@
'use client'
import type { EventEmitter } from 'ahooks/lib/useEventEmitter'
-import { useEventEmitter } from 'ahooks'
import { createContext, useContext } from 'use-context-selector'
/**
@@ -16,25 +15,10 @@ export type EventEmitterMessage = {
export type EventEmitterValue = string | EventEmitterMessage
-const EventEmitterContext = createContext<{ eventEmitter: EventEmitter | null }>({
+export const EventEmitterContext = createContext<{ eventEmitter: EventEmitter | null }>({
eventEmitter: null,
})
export const useEventEmitterContextContext = () => useContext(EventEmitterContext)
-type EventEmitterContextProviderProps = {
- children: React.ReactNode
-}
-export const EventEmitterContextProvider = ({
- children,
-}: EventEmitterContextProviderProps) => {
- const eventEmitter = useEventEmitter()
-
- return (
-
- {children}
-
- )
-}
-
export default EventEmitterContext
diff --git a/web/context/mitt-context-provider.tsx b/web/context/mitt-context-provider.tsx
new file mode 100644
index 0000000000..b177694d8d
--- /dev/null
+++ b/web/context/mitt-context-provider.tsx
@@ -0,0 +1,19 @@
+'use client'
+
+import type { ReactNode } from 'react'
+import { useMitt } from '@/hooks/use-mitt'
+import { MittContext } from './mitt-context'
+
+type MittProviderProps = {
+ children: ReactNode
+}
+
+export const MittProvider = ({ children }: MittProviderProps) => {
+ const mitt = useMitt()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/web/context/mitt-context.tsx b/web/context/mitt-context.ts
similarity index 66%
rename from web/context/mitt-context.tsx
rename to web/context/mitt-context.ts
index 4317fc5660..5c4a0771c5 100644
--- a/web/context/mitt-context.tsx
+++ b/web/context/mitt-context.ts
@@ -1,6 +1,8 @@
+'use client'
+
+import type { useMitt } from '@/hooks/use-mitt'
import { noop } from 'es-toolkit/function'
import { createContext, useContext, useContextSelector } from 'use-context-selector'
-import { useMitt } from '@/hooks/use-mitt'
type ContextValueType = ReturnType
export const MittContext = createContext({
@@ -8,16 +10,6 @@ export const MittContext = createContext({
useSubscribe: noop,
})
-export const MittProvider = ({ children }: { children: React.ReactNode }) => {
- const mitt = useMitt()
-
- return (
-
- {children}
-
- )
-}
-
export const useMittContext = () => {
return useContext(MittContext)
}
diff --git a/web/context/modal-context.tsx b/web/context/modal-context-provider.tsx
similarity index 81%
rename from web/context/modal-context.tsx
rename to web/context/modal-context-provider.tsx
index ae1184e5bf..8c64642f43 100644
--- a/web/context/modal-context.tsx
+++ b/web/context/modal-context-provider.tsx
@@ -1,32 +1,20 @@
'use client'
-import type { Dispatch, SetStateAction } from 'react'
-import type { TriggerEventsLimitModalPayload } from './hooks/use-trigger-events-limit-modal'
+import type { ReactNode, SetStateAction } from 'react'
+import type { ModalState, ModelModalType } from './modal-context'
import type { OpeningStatement } from '@/app/components/base/features/types'
import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
import type { AccountSettingTab } from '@/app/components/header/account-setting/constants'
-import type {
- ConfigurationMethodEnum,
- Credential,
- CustomConfigurationModelFixedFields,
- CustomModel,
- ModelModalModeEnum,
- ModelProvider,
-} from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
import type { UpdatePluginPayload } from '@/app/components/plugins/types'
import type { InputVar } from '@/app/components/workflow/types'
import type { ExpireNoticeModalPayloadProps } from '@/app/education-apply/expire-notice-modal'
-import type {
- ApiBasedExtension,
- ExternalDataTool,
-} from '@/models/common'
+import type { ApiBasedExtension, ExternalDataTool } from '@/models/common'
import type { ModerationConfig, PromptVariable } from '@/models/debug'
-import { noop } from 'es-toolkit/function'
import dynamic from 'next/dynamic'
import { useCallback, useEffect, useRef, useState } from 'react'
-import { createContext, useContext, useContextSelector } from 'use-context-selector'
import {
+
DEFAULT_ACCOUNT_SETTING_TAB,
isValidAccountSettingTab,
} from '@/app/components/header/account-setting/constants'
@@ -39,11 +27,10 @@ import {
useAccountSettingModal,
usePricingModal,
} from '@/hooks/use-query-params'
-
+import { useTriggerEventsLimitModal } from './hooks/use-trigger-events-limit-modal'
import {
-
- useTriggerEventsLimitModal,
-} from './hooks/use-trigger-events-limit-modal'
+ ModalContext,
+} from './modal-context'
const AccountSetting = dynamic(() => import('@/app/components/header/account-setting'), {
ssr: false,
@@ -86,72 +73,8 @@ const TriggerEventsLimitModal = dynamic(() => import('@/app/components/billing/t
ssr: false,
})
-export type ModalState = {
- payload: T
- onCancelCallback?: () => void
- onSaveCallback?: (newPayload?: T, formValues?: Record) => void
- onRemoveCallback?: (newPayload?: T, formValues?: Record) => void
- onEditCallback?: (newPayload: T) => void
- onValidateBeforeSaveCallback?: (newPayload: T) => boolean
- isEditMode?: boolean
- datasetBindings?: { id: string, name: string }[]
-}
-
-export type ModelModalType = {
- currentProvider: ModelProvider
- currentConfigurationMethod: ConfigurationMethodEnum
- currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
- isModelCredential?: boolean
- credential?: Credential
- model?: CustomModel
- mode?: ModelModalModeEnum
-}
-
-export type ModalContextState = {
- setShowAccountSettingModal: Dispatch | null>>
- setShowApiBasedExtensionModal: Dispatch | null>>
- setShowModerationSettingModal: Dispatch | null>>
- setShowExternalDataToolModal: Dispatch | null>>
- setShowPricingModal: () => void
- setShowAnnotationFullModal: () => void
- setShowModelModal: Dispatch | null>>
- setShowExternalKnowledgeAPIModal: Dispatch | null>>
- setShowModelLoadBalancingModal: Dispatch>
- setShowOpeningModal: Dispatch void
- }> | null>>
- setShowUpdatePluginModal: Dispatch | null>>
- setShowEducationExpireNoticeModal: Dispatch | null>>
- setShowTriggerEventsLimitModal: Dispatch | null>>
-}
-
-const ModalContext = createContext({
- setShowAccountSettingModal: noop,
- setShowApiBasedExtensionModal: noop,
- setShowModerationSettingModal: noop,
- setShowExternalDataToolModal: noop,
- setShowPricingModal: noop,
- setShowAnnotationFullModal: noop,
- setShowModelModal: noop,
- setShowExternalKnowledgeAPIModal: noop,
- setShowModelLoadBalancingModal: noop,
- setShowOpeningModal: noop,
- setShowUpdatePluginModal: noop,
- setShowEducationExpireNoticeModal: noop,
- setShowTriggerEventsLimitModal: noop,
-})
-
-export const useModalContext = () => useContext(ModalContext)
-
-// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
-// https://github.com/microsoft/TypeScript/issues/15713
-export const useModalContextSelector = (selector: (state: ModalContextState) => T): T =>
- useContextSelector(ModalContext, selector)
-
type ModalContextProviderProps = {
- children: React.ReactNode
+ children: ReactNode
}
export const ModalContextProvider = ({
children,
diff --git a/web/context/modal-context.test.tsx b/web/context/modal-context.test.tsx
index a0f6ff35ec..98f67a5473 100644
--- a/web/context/modal-context.test.tsx
+++ b/web/context/modal-context.test.tsx
@@ -2,7 +2,7 @@ import { act, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { defaultPlan } from '@/app/components/billing/config'
import { Plan } from '@/app/components/billing/type'
-import { ModalContextProvider } from '@/context/modal-context'
+import { ModalContextProvider } from '@/context/modal-context-provider'
import { renderWithNuqs } from '@/test/nuqs-testing'
vi.mock('@/config', async (importOriginal) => {
diff --git a/web/context/modal-context.ts b/web/context/modal-context.ts
new file mode 100644
index 0000000000..cc0ca28a42
--- /dev/null
+++ b/web/context/modal-context.ts
@@ -0,0 +1,92 @@
+'use client'
+
+import type { Dispatch, SetStateAction } from 'react'
+import type { TriggerEventsLimitModalPayload } from './hooks/use-trigger-events-limit-modal'
+import type { OpeningStatement } from '@/app/components/base/features/types'
+import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
+import type { AccountSettingTab } from '@/app/components/header/account-setting/constants'
+import type {
+ ConfigurationMethodEnum,
+ Credential,
+ CustomConfigurationModelFixedFields,
+ CustomModel,
+ ModelModalModeEnum,
+ ModelProvider,
+} from '@/app/components/header/account-setting/model-provider-page/declarations'
+import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
+import type { UpdatePluginPayload } from '@/app/components/plugins/types'
+import type { InputVar } from '@/app/components/workflow/types'
+import type { ExpireNoticeModalPayloadProps } from '@/app/education-apply/expire-notice-modal'
+import type {
+ ApiBasedExtension,
+ ExternalDataTool,
+} from '@/models/common'
+import type { ModerationConfig, PromptVariable } from '@/models/debug'
+import { noop } from 'es-toolkit/function'
+import { createContext, useContext, useContextSelector } from 'use-context-selector'
+
+export type ModalState = {
+ payload: T
+ onCancelCallback?: () => void
+ onSaveCallback?: (newPayload?: T, formValues?: Record) => void
+ onRemoveCallback?: (newPayload?: T, formValues?: Record) => void
+ onEditCallback?: (newPayload: T) => void
+ onValidateBeforeSaveCallback?: (newPayload: T) => boolean
+ isEditMode?: boolean
+ datasetBindings?: { id: string, name: string }[]
+}
+
+export type ModelModalType = {
+ currentProvider: ModelProvider
+ currentConfigurationMethod: ConfigurationMethodEnum
+ currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
+ isModelCredential?: boolean
+ credential?: Credential
+ model?: CustomModel
+ mode?: ModelModalModeEnum
+}
+
+export type ModalContextState = {
+ setShowAccountSettingModal: Dispatch | null>>
+ setShowApiBasedExtensionModal: Dispatch | null>>
+ setShowModerationSettingModal: Dispatch | null>>
+ setShowExternalDataToolModal: Dispatch | null>>
+ setShowPricingModal: () => void
+ setShowAnnotationFullModal: () => void
+ setShowModelModal: Dispatch | null>>
+ setShowExternalKnowledgeAPIModal: Dispatch | null>>
+ setShowModelLoadBalancingModal: Dispatch>
+ setShowOpeningModal: Dispatch void
+ }> | null>>
+ setShowUpdatePluginModal: Dispatch | null>>
+ setShowEducationExpireNoticeModal: Dispatch | null>>
+ setShowTriggerEventsLimitModal: Dispatch | null>>
+}
+
+export const ModalContext = createContext({
+ setShowAccountSettingModal: noop,
+ setShowApiBasedExtensionModal: noop,
+ setShowModerationSettingModal: noop,
+ setShowExternalDataToolModal: noop,
+ setShowPricingModal: noop,
+ setShowAnnotationFullModal: noop,
+ setShowModelModal: noop,
+ setShowExternalKnowledgeAPIModal: noop,
+ setShowModelLoadBalancingModal: noop,
+ setShowOpeningModal: noop,
+ setShowUpdatePluginModal: noop,
+ setShowEducationExpireNoticeModal: noop,
+ setShowTriggerEventsLimitModal: noop,
+})
+
+export const useModalContext = () => useContext(ModalContext)
+
+// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
+// https://github.com/microsoft/TypeScript/issues/15713
+export const useModalContextSelector = (selector: (state: ModalContextState) => T): T =>
+ useContextSelector(ModalContext, selector)
+
+export default ModalContext
diff --git a/web/context/provider-context.tsx b/web/context/provider-context-provider.tsx
similarity index 70%
rename from web/context/provider-context.tsx
rename to web/context/provider-context-provider.tsx
index 2a71d9cf93..ce7f2ba40c 100644
--- a/web/context/provider-context.tsx
+++ b/web/context/provider-context-provider.tsx
@@ -1,14 +1,10 @@
'use client'
-import type { Plan, UsagePlanInfo, UsageResetInfo } from '@/app/components/billing/type'
-import type { Model, ModelProvider } from '@/app/components/header/account-setting/model-provider-page/declarations'
-import type { RETRIEVE_METHOD } from '@/types/app'
+import type { ReactNode } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import dayjs from 'dayjs'
-import { noop } from 'es-toolkit/function'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { createContext, useContext, useContextSelector } from 'use-context-selector'
import Toast from '@/app/components/base/toast'
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
import { defaultPlan } from '@/app/components/billing/config'
@@ -25,93 +21,13 @@ import {
useModelProviders,
useSupportRetrievalMethods,
} from '@/service/use-common'
-import {
- useEducationStatus,
-} from '@/service/use-education'
-
-export type ProviderContextState = {
- modelProviders: ModelProvider[]
- refreshModelProviders: () => void
- textGenerationModelList: Model[]
- supportRetrievalMethods: RETRIEVE_METHOD[]
- isAPIKeySet: boolean
- plan: {
- type: Plan
- usage: UsagePlanInfo
- total: UsagePlanInfo
- reset: UsageResetInfo
- }
- isFetchedPlan: boolean
- enableBilling: boolean
- onPlanInfoChanged: () => void
- enableReplaceWebAppLogo: boolean
- modelLoadBalancingEnabled: boolean
- datasetOperatorEnabled: boolean
- enableEducationPlan: boolean
- isEducationWorkspace: boolean
- isEducationAccount: boolean
- allowRefreshEducationVerify: boolean
- educationAccountExpireAt: number | null
- isLoadingEducationAccountInfo: boolean
- isFetchingEducationAccountInfo: boolean
- webappCopyrightEnabled: boolean
- licenseLimit: {
- workspace_members: {
- size: number
- limit: number
- }
- }
- refreshLicenseLimit: () => void
- isAllowTransferWorkspace: boolean
- isAllowPublishAsCustomKnowledgePipelineTemplate: boolean
- humanInputEmailDeliveryEnabled: boolean
-}
-
-export const baseProviderContextValue: ProviderContextState = {
- modelProviders: [],
- refreshModelProviders: noop,
- textGenerationModelList: [],
- supportRetrievalMethods: [],
- isAPIKeySet: true,
- plan: defaultPlan,
- isFetchedPlan: false,
- enableBilling: false,
- onPlanInfoChanged: noop,
- enableReplaceWebAppLogo: false,
- modelLoadBalancingEnabled: false,
- datasetOperatorEnabled: false,
- enableEducationPlan: false,
- isEducationWorkspace: false,
- isEducationAccount: false,
- allowRefreshEducationVerify: false,
- educationAccountExpireAt: null,
- isLoadingEducationAccountInfo: false,
- isFetchingEducationAccountInfo: false,
- webappCopyrightEnabled: false,
- licenseLimit: {
- workspace_members: {
- size: 0,
- limit: 0,
- },
- },
- refreshLicenseLimit: noop,
- isAllowTransferWorkspace: false,
- isAllowPublishAsCustomKnowledgePipelineTemplate: false,
- humanInputEmailDeliveryEnabled: false,
-}
-
-const ProviderContext = createContext(baseProviderContextValue)
-
-export const useProviderContext = () => useContext(ProviderContext)
-
-// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
-// https://github.com/microsoft/TypeScript/issues/15713
-export const useProviderContextSelector = (selector: (state: ProviderContextState) => T): T =>
- useContextSelector(ProviderContext, selector)
+import { useEducationStatus } from '@/service/use-education'
+import { ProviderContext } from './provider-context'
type ProviderContextProviderProps = {
- children: React.ReactNode
+ children: ReactNode
}
+
export const ProviderContextProvider = ({
children,
}: ProviderContextProviderProps) => {
@@ -262,5 +178,3 @@ export const ProviderContextProvider = ({
)
}
-
-export default ProviderContext
diff --git a/web/context/provider-context.ts b/web/context/provider-context.ts
new file mode 100644
index 0000000000..27c43e7c91
--- /dev/null
+++ b/web/context/provider-context.ts
@@ -0,0 +1,90 @@
+'use client'
+
+import type { Plan, UsagePlanInfo, UsageResetInfo } from '@/app/components/billing/type'
+import type { Model, ModelProvider } from '@/app/components/header/account-setting/model-provider-page/declarations'
+import type { RETRIEVE_METHOD } from '@/types/app'
+import { noop } from 'es-toolkit/function'
+import { createContext, useContext, useContextSelector } from 'use-context-selector'
+import { defaultPlan } from '@/app/components/billing/config'
+
+export type ProviderContextState = {
+ modelProviders: ModelProvider[]
+ refreshModelProviders: () => void
+ textGenerationModelList: Model[]
+ supportRetrievalMethods: RETRIEVE_METHOD[]
+ isAPIKeySet: boolean
+ plan: {
+ type: Plan
+ usage: UsagePlanInfo
+ total: UsagePlanInfo
+ reset: UsageResetInfo
+ }
+ isFetchedPlan: boolean
+ enableBilling: boolean
+ onPlanInfoChanged: () => void
+ enableReplaceWebAppLogo: boolean
+ modelLoadBalancingEnabled: boolean
+ datasetOperatorEnabled: boolean
+ enableEducationPlan: boolean
+ isEducationWorkspace: boolean
+ isEducationAccount: boolean
+ allowRefreshEducationVerify: boolean
+ educationAccountExpireAt: number | null
+ isLoadingEducationAccountInfo: boolean
+ isFetchingEducationAccountInfo: boolean
+ webappCopyrightEnabled: boolean
+ licenseLimit: {
+ workspace_members: {
+ size: number
+ limit: number
+ }
+ }
+ refreshLicenseLimit: () => void
+ isAllowTransferWorkspace: boolean
+ isAllowPublishAsCustomKnowledgePipelineTemplate: boolean
+ humanInputEmailDeliveryEnabled: boolean
+}
+
+export const baseProviderContextValue: ProviderContextState = {
+ modelProviders: [],
+ refreshModelProviders: noop,
+ textGenerationModelList: [],
+ supportRetrievalMethods: [],
+ isAPIKeySet: true,
+ plan: defaultPlan,
+ isFetchedPlan: false,
+ enableBilling: false,
+ onPlanInfoChanged: noop,
+ enableReplaceWebAppLogo: false,
+ modelLoadBalancingEnabled: false,
+ datasetOperatorEnabled: false,
+ enableEducationPlan: false,
+ isEducationWorkspace: false,
+ isEducationAccount: false,
+ allowRefreshEducationVerify: false,
+ educationAccountExpireAt: null,
+ isLoadingEducationAccountInfo: false,
+ isFetchingEducationAccountInfo: false,
+ webappCopyrightEnabled: false,
+ licenseLimit: {
+ workspace_members: {
+ size: 0,
+ limit: 0,
+ },
+ },
+ refreshLicenseLimit: noop,
+ isAllowTransferWorkspace: false,
+ isAllowPublishAsCustomKnowledgePipelineTemplate: false,
+ humanInputEmailDeliveryEnabled: false,
+}
+
+export const ProviderContext = createContext(baseProviderContextValue)
+
+export const useProviderContext = () => useContext(ProviderContext)
+
+// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
+// https://github.com/microsoft/TypeScript/issues/15713
+export const useProviderContextSelector = (selector: (state: ProviderContextState) => T): T =>
+ useContextSelector(ProviderContext, selector)
+
+export default ProviderContext
diff --git a/web/context/workspace-context-provider.tsx b/web/context/workspace-context-provider.tsx
new file mode 100644
index 0000000000..afec62f710
--- /dev/null
+++ b/web/context/workspace-context-provider.tsx
@@ -0,0 +1,24 @@
+'use client'
+
+import type { ReactNode } from 'react'
+import { useWorkspaces } from '@/service/use-common'
+import { WorkspacesContext } from './workspace-context'
+
+type WorkspaceProviderProps = {
+ children: ReactNode
+}
+
+export const WorkspaceProvider = ({
+ children,
+}: WorkspaceProviderProps) => {
+ const { data } = useWorkspaces()
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/web/context/workspace-context.ts b/web/context/workspace-context.ts
new file mode 100644
index 0000000000..e088d12f4e
--- /dev/null
+++ b/web/context/workspace-context.ts
@@ -0,0 +1,16 @@
+'use client'
+
+import type { IWorkspace } from '@/models/common'
+import { createContext, useContext } from 'use-context-selector'
+
+export type WorkspacesContextValue = {
+ workspaces: IWorkspace[]
+}
+
+export const WorkspacesContext = createContext({
+ workspaces: [],
+})
+
+export const useWorkspacesContext = () => useContext(WorkspacesContext)
+
+export default WorkspacesContext
diff --git a/web/context/workspace-context.tsx b/web/context/workspace-context.tsx
deleted file mode 100644
index 3834641bc1..0000000000
--- a/web/context/workspace-context.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-'use client'
-
-import type { IWorkspace } from '@/models/common'
-import { createContext, useContext } from 'use-context-selector'
-import { useWorkspaces } from '@/service/use-common'
-
-export type WorkspacesContextValue = {
- workspaces: IWorkspace[]
-}
-
-const WorkspacesContext = createContext({
- workspaces: [],
-})
-
-type IWorkspaceProviderProps = {
- children: React.ReactNode
-}
-
-export const WorkspaceProvider = ({
- children,
-}: IWorkspaceProviderProps) => {
- const { data } = useWorkspaces()
-
- return (
-
- {children}
-
- )
-}
-
-export const useWorkspacesContext = () => useContext(WorkspacesContext)
-
-export default WorkspacesContext
diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json
index 0880084320..22f225d1d0 100644
--- a/web/eslint-suppressions.json
+++ b/web/eslint-suppressions.json
@@ -968,11 +968,6 @@
"count": 6
}
},
- "app/components/app/configuration/debug/debug-with-multiple-model/context.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
"app/components/app/configuration/debug/debug-with-multiple-model/debug-item.tsx": {
"no-restricted-imports": {
"count": 2
@@ -1561,7 +1556,7 @@
"count": 7
}
},
- "app/components/base/chat/chat-with-history/context.tsx": {
+ "app/components/base/chat/chat-with-history/context.ts": {
"ts/no-explicit-any": {
"count": 7
}
@@ -1715,11 +1710,6 @@
"count": 1
}
},
- "app/components/base/chat/chat/context.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
"app/components/base/chat/chat/hooks.ts": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 2
@@ -1759,7 +1749,7 @@
"count": 7
}
},
- "app/components/base/chat/embedded-chatbot/context.tsx": {
+ "app/components/base/chat/embedded-chatbot/context.ts": {
"ts/no-explicit-any": {
"count": 7
}
@@ -2763,7 +2753,7 @@
"count": 2
}
},
- "app/components/base/radio/context/index.tsx": {
+ "app/components/base/radio/context/index.ts": {
"ts/no-explicit-any": {
"count": 1
}
@@ -2915,14 +2905,6 @@
"count": 1
}
},
- "app/components/base/toast/index.tsx": {
- "react-refresh/only-export-components": {
- "count": 2
- },
- "tailwindcss/enforce-consistent-class-order": {
- "count": 2
- }
- },
"app/components/base/video-gallery/VideoPlayer.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1
@@ -5683,10 +5665,7 @@
"count": 1
}
},
- "app/components/plugins/plugin-page/context.tsx": {
- "react-refresh/only-export-components": {
- "count": 2
- },
+ "app/components/plugins/plugin-page/context.ts": {
"ts/no-explicit-any": {
"count": 1
}
@@ -9571,16 +9550,6 @@
"count": 5
}
},
- "context/datasets-context.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
- "context/event-emitter.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
"context/external-api-panel-context.tsx": {
"react-refresh/only-export-components": {
"count": 1
@@ -9601,8 +9570,8 @@
"count": 3
}
},
- "context/mitt-context.tsx": {
- "react-refresh/only-export-components": {
+ "context/modal-context-provider.tsx": {
+ "ts/no-explicit-any": {
"count": 3
}
},
@@ -9611,18 +9580,12 @@
"count": 3
}
},
- "context/modal-context.tsx": {
- "react-refresh/only-export-components": {
- "count": 2
- },
+ "context/modal-context.ts": {
"ts/no-explicit-any": {
- "count": 5
+ "count": 2
}
},
- "context/provider-context.tsx": {
- "react-refresh/only-export-components": {
- "count": 3
- },
+ "context/provider-context-provider.tsx": {
"ts/no-explicit-any": {
"count": 1
}
@@ -9632,11 +9595,6 @@
"count": 1
}
},
- "context/workspace-context.tsx": {
- "react-refresh/only-export-components": {
- "count": 1
- }
- },
"hooks/use-async-window-open.spec.ts": {
"ts/no-explicit-any": {
"count": 6
diff --git a/web/hooks/use-import-dsl.ts b/web/hooks/use-import-dsl.ts
index ba33db1e84..454f580b42 100644
--- a/web/hooks/use-import-dsl.ts
+++ b/web/hooks/use-import-dsl.ts
@@ -10,7 +10,7 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useToastContext } from '@/app/components/base/toast'
+import { useToastContext } from '@/app/components/base/toast/context'
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { useSelector } from '@/context/app-context'