mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
Merge branch 'main' into feat/grouping-branching
This commit is contained in:
@ -4,9 +4,8 @@ import type { Plugin } from '@/app/components/plugins/types.ts'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
|
||||
import I18n from '@/context/i18n'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { cn } from '@/utils/classnames'
|
||||
|
||||
import { formatNumber } from '@/utils/format'
|
||||
@ -27,7 +26,7 @@ const Item: FC<Props> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const { locale } = useContext(I18n)
|
||||
const locale = useLocale()
|
||||
const getLocalizedText = (obj: Record<string, string> | undefined) =>
|
||||
obj?.[locale] || obj?.['en-US'] || obj?.en_US || ''
|
||||
const [isShowInstallModal, {
|
||||
|
||||
@ -96,7 +96,8 @@ const RAGToolRecommendations = ({
|
||||
{!isFetchingRAGRecommendedPlugins && recommendedPlugins.length === 0 && unInstalledPlugins.length === 0 && (
|
||||
<p className="system-xs-regular px-3 py-1 text-text-tertiary">
|
||||
<Trans
|
||||
i18nKey="pipeline.ragToolSuggestions.noRecommendationPlugins"
|
||||
i18nKey="ragToolSuggestions.noRecommendationPlugins"
|
||||
ns="pipeline"
|
||||
components={{
|
||||
CustomLink: (
|
||||
<Link
|
||||
|
||||
@ -3,9 +3,8 @@ import type { Plugin } from '@/app/components/plugins/types'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
|
||||
import I18n from '@/context/i18n'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import BlockIcon from '../../block-icon'
|
||||
import { BlockEnum } from '../../types'
|
||||
|
||||
@ -17,7 +16,7 @@ const UninstalledItem = ({
|
||||
payload,
|
||||
}: UninstalledItemProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useContext(I18n)
|
||||
const locale = useLocale()
|
||||
|
||||
const getLocalizedText = (obj: Record<string, string> | undefined) =>
|
||||
obj?.[locale] || obj?.['en-US'] || obj?.en_US || ''
|
||||
|
||||
@ -3,10 +3,9 @@ import type { DocExtractorNodeType } from './types'
|
||||
import type { NodePanelProps } from '@/app/components/workflow/types'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import I18n from '@/context/i18n'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { LanguagesSupported } from '@/i18n-config/language'
|
||||
import { useFileSupportTypes } from '@/service/use-common'
|
||||
import OutputVars, { VarItem } from '../_base/components/output-vars'
|
||||
@ -22,7 +21,7 @@ const Panel: FC<NodePanelProps<DocExtractorNodeType>> = ({
|
||||
data,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useContext(I18n)
|
||||
const locale = useLocale()
|
||||
const link = useNodeHelpLink(BlockEnum.DocExtractor)
|
||||
const { data: supportFileTypesResponse } = useFileSupportTypes()
|
||||
const supportTypes = supportFileTypesResponse?.allowed_extensions || []
|
||||
|
||||
@ -0,0 +1,156 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { WorkflowVersion } from '../../types'
|
||||
|
||||
const mockHandleRestoreFromPublishedWorkflow = vi.fn()
|
||||
const mockHandleLoadBackupDraft = vi.fn()
|
||||
const mockSetCurrentVersion = vi.fn()
|
||||
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useSelector: () => ({ id: 'test-user-id' }),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-workflow', () => ({
|
||||
useDeleteWorkflow: () => ({ mutateAsync: vi.fn() }),
|
||||
useInvalidAllLastRun: () => vi.fn(),
|
||||
useResetWorkflowVersionHistory: () => vi.fn(),
|
||||
useUpdateWorkflow: () => ({ mutateAsync: vi.fn() }),
|
||||
useWorkflowVersionHistory: () => ({
|
||||
data: {
|
||||
pages: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
id: 'draft-version-id',
|
||||
version: WorkflowVersion.Draft,
|
||||
graph: { nodes: [], edges: [], viewport: null },
|
||||
features: {
|
||||
opening_statement: '',
|
||||
suggested_questions: [],
|
||||
suggested_questions_after_answer: { enabled: false },
|
||||
text_to_speech: { enabled: false },
|
||||
speech_to_text: { enabled: false },
|
||||
retriever_resource: { enabled: false },
|
||||
sensitive_word_avoidance: { enabled: false },
|
||||
file_upload: { image: { enabled: false } },
|
||||
},
|
||||
created_at: Date.now() / 1000,
|
||||
created_by: { id: 'user-1', name: 'User 1' },
|
||||
environment_variables: [],
|
||||
marked_name: '',
|
||||
marked_comment: '',
|
||||
},
|
||||
{
|
||||
id: 'published-version-id',
|
||||
version: '2024-01-01T00:00:00Z',
|
||||
graph: { nodes: [], edges: [], viewport: null },
|
||||
features: {
|
||||
opening_statement: '',
|
||||
suggested_questions: [],
|
||||
suggested_questions_after_answer: { enabled: false },
|
||||
text_to_speech: { enabled: false },
|
||||
speech_to_text: { enabled: false },
|
||||
retriever_resource: { enabled: false },
|
||||
sensitive_word_avoidance: { enabled: false },
|
||||
file_upload: { image: { enabled: false } },
|
||||
},
|
||||
created_at: Date.now() / 1000,
|
||||
created_by: { id: 'user-1', name: 'User 1' },
|
||||
environment_variables: [],
|
||||
marked_name: 'v1.0',
|
||||
marked_comment: 'First release',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
fetchNextPage: vi.fn(),
|
||||
hasNextPage: false,
|
||||
isFetching: false,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../../hooks', () => ({
|
||||
useDSL: () => ({ handleExportDSL: vi.fn() }),
|
||||
useNodesSyncDraft: () => ({ handleSyncWorkflowDraft: vi.fn() }),
|
||||
useWorkflowRun: () => ({
|
||||
handleRestoreFromPublishedWorkflow: mockHandleRestoreFromPublishedWorkflow,
|
||||
handleLoadBackupDraft: mockHandleLoadBackupDraft,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../../hooks-store', () => ({
|
||||
useHooksStore: () => ({
|
||||
flowId: 'test-flow-id',
|
||||
flowType: 'workflow',
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../../store', () => ({
|
||||
useStore: (selector: (state: any) => any) => {
|
||||
const state = {
|
||||
setShowWorkflowVersionHistoryPanel: vi.fn(),
|
||||
currentVersion: null,
|
||||
setCurrentVersion: mockSetCurrentVersion,
|
||||
}
|
||||
return selector(state)
|
||||
},
|
||||
useWorkflowStore: () => ({
|
||||
getState: () => ({
|
||||
deleteAllInspectVars: vi.fn(),
|
||||
}),
|
||||
setState: vi.fn(),
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('./delete-confirm-modal', () => ({
|
||||
default: () => null,
|
||||
}))
|
||||
|
||||
vi.mock('./restore-confirm-modal', () => ({
|
||||
default: () => null,
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/app/app-publisher/version-info-modal', () => ({
|
||||
default: () => null,
|
||||
}))
|
||||
|
||||
describe('VersionHistoryPanel', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('Version Click Behavior', () => {
|
||||
it('should call handleLoadBackupDraft when draft version is selected on mount', async () => {
|
||||
const { VersionHistoryPanel } = await import('./index')
|
||||
|
||||
render(
|
||||
<VersionHistoryPanel
|
||||
latestVersionId="published-version-id"
|
||||
/>,
|
||||
)
|
||||
|
||||
// Draft version auto-clicks on mount via useEffect in VersionHistoryItem
|
||||
expect(mockHandleLoadBackupDraft).toHaveBeenCalled()
|
||||
expect(mockHandleRestoreFromPublishedWorkflow).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should call handleRestoreFromPublishedWorkflow when clicking published version', async () => {
|
||||
const { VersionHistoryPanel } = await import('./index')
|
||||
|
||||
render(
|
||||
<VersionHistoryPanel
|
||||
latestVersionId="published-version-id"
|
||||
/>,
|
||||
)
|
||||
|
||||
// Clear mocks after initial render (draft version auto-clicks on mount)
|
||||
vi.clearAllMocks()
|
||||
|
||||
const publishedItem = screen.getByText('v1.0')
|
||||
fireEvent.click(publishedItem)
|
||||
|
||||
expect(mockHandleRestoreFromPublishedWorkflow).toHaveBeenCalled()
|
||||
expect(mockHandleLoadBackupDraft).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -13,7 +13,7 @@ import { useDeleteWorkflow, useInvalidAllLastRun, useResetWorkflowVersionHistory
|
||||
import { useDSL, useNodesSyncDraft, useWorkflowRun } from '../../hooks'
|
||||
import { useHooksStore } from '../../hooks-store'
|
||||
import { useStore, useWorkflowStore } from '../../store'
|
||||
import { VersionHistoryContextMenuOptions, WorkflowVersionFilterOptions } from '../../types'
|
||||
import { VersionHistoryContextMenuOptions, WorkflowVersion, WorkflowVersionFilterOptions } from '../../types'
|
||||
import DeleteConfirmModal from './delete-confirm-modal'
|
||||
import Empty from './empty'
|
||||
import Filter from './filter'
|
||||
@ -73,9 +73,12 @@ export const VersionHistoryPanel = ({
|
||||
const handleVersionClick = useCallback((item: VersionHistory) => {
|
||||
if (item.id !== currentVersion?.id) {
|
||||
setCurrentVersion(item)
|
||||
handleRestoreFromPublishedWorkflow(item)
|
||||
if (item.version === WorkflowVersion.Draft)
|
||||
handleLoadBackupDraft()
|
||||
else
|
||||
handleRestoreFromPublishedWorkflow(item)
|
||||
}
|
||||
}, [currentVersion?.id, setCurrentVersion, handleRestoreFromPublishedWorkflow])
|
||||
}, [currentVersion?.id, setCurrentVersion, handleLoadBackupDraft, handleRestoreFromPublishedWorkflow])
|
||||
|
||||
const handleNextPage = () => {
|
||||
if (hasNextPage)
|
||||
|
||||
Reference in New Issue
Block a user