fix: upload zip not show confirm

This commit is contained in:
Joel
2026-03-02 18:47:36 +08:00
parent a0d1816a6e
commit 4f1e12ea04
3 changed files with 62 additions and 39 deletions

View File

@ -47,10 +47,18 @@ vi.mock('../hooks/use-apps-query-state', () => ({
}))
let mockOnDSLFileDropped: ((file: File) => void) | null = null
let mockOnBundleFileDropped: ((file: File) => void) | null = null
let mockDragging = false
vi.mock('../hooks/use-dsl-drag-drop', () => ({
useDSLDragDrop: ({ onDSLFileDropped }: { onDSLFileDropped: (file: File) => void }) => {
useDSLDragDrop: ({
onDSLFileDropped,
onBundleFileDropped,
}: {
onDSLFileDropped: (file: File) => void
onBundleFileDropped?: (file: File) => void
}) => {
mockOnDSLFileDropped = onDSLFileDropped
mockOnBundleFileDropped = onBundleFileDropped ?? null
return { dragging: mockDragging }
},
}))
@ -223,6 +231,7 @@ describe('List', () => {
mockIsCurrentWorkspaceDatasetOperator.mockReturnValue(false)
mockDragging = false
mockOnDSLFileDropped = null
mockOnBundleFileDropped = null
mockServiceState.error = null
mockServiceState.hasNextPage = false
mockServiceState.isLoading = false
@ -510,6 +519,18 @@ describe('List', () => {
expect(screen.getByTestId('create-dsl-modal')).toBeInTheDocument()
})
it('should handle zip file drop and show modal', () => {
renderList()
const mockFile = new File(['zip content'], 'bundle.zip', { type: 'application/zip' })
act(() => {
if (mockOnBundleFileDropped)
mockOnBundleFileDropped(mockFile)
})
expect(screen.getByTestId('create-dsl-modal')).toBeInTheDocument()
})
it('should close DSL modal when onClose is called', () => {
renderList()

View File

@ -5,12 +5,14 @@ import { useDSLDragDrop } from '../use-dsl-drag-drop'
describe('useDSLDragDrop', () => {
let container: HTMLDivElement
let mockOnDSLFileDropped: Mock
let mockOnBundleFileDropped: Mock
beforeEach(() => {
vi.clearAllMocks()
container = document.createElement('div')
document.body.appendChild(container)
mockOnDSLFileDropped = vi.fn()
mockOnBundleFileDropped = vi.fn()
})
afterEach(() => {
@ -195,6 +197,7 @@ describe('useDSLDragDrop', () => {
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -214,6 +217,7 @@ describe('useDSLDragDrop', () => {
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -233,6 +237,7 @@ describe('useDSLDragDrop', () => {
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -247,11 +252,33 @@ describe('useDSLDragDrop', () => {
expect(mockOnDSLFileDropped).toHaveBeenCalledWith(file)
})
it('should call onBundleFileDropped for .zip file', () => {
const containerRef = { current: container }
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
const file = createMockFile('test.zip')
const dropEvent = createDragEvent('drop', [file])
act(() => {
container.dispatchEvent(dropEvent)
})
expect(mockOnBundleFileDropped).toHaveBeenCalledWith(file)
expect(mockOnDSLFileDropped).not.toHaveBeenCalled()
})
it('should not call onDSLFileDropped for non-yaml file', () => {
const containerRef = { current: container }
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -264,6 +291,7 @@ describe('useDSLDragDrop', () => {
})
expect(mockOnDSLFileDropped).not.toHaveBeenCalled()
expect(mockOnBundleFileDropped).not.toHaveBeenCalled()
})
it('should set dragging to false on drop', () => {
@ -271,6 +299,7 @@ describe('useDSLDragDrop', () => {
const { result } = renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -294,6 +323,7 @@ describe('useDSLDragDrop', () => {
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -324,6 +354,7 @@ describe('useDSLDragDrop', () => {
renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -386,6 +417,7 @@ describe('useDSLDragDrop', () => {
({ enabled }) =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
enabled,
}),
@ -407,6 +439,7 @@ describe('useDSLDragDrop', () => {
const { result } = renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -429,6 +462,7 @@ describe('useDSLDragDrop', () => {
const { unmount } = renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)
@ -450,6 +484,7 @@ describe('useDSLDragDrop', () => {
const { result } = renderHook(() =>
useDSLDragDrop({
onDSLFileDropped: mockOnDSLFileDropped,
onBundleFileDropped: mockOnBundleFileDropped,
containerRef,
}),
)

View File

@ -18,22 +18,18 @@ import {
import { parseAsString, useQueryState } from 'nuqs'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import Input from '@/app/components/base/input'
import TabSliderNew from '@/app/components/base/tab-slider-new'
import TagFilter from '@/app/components/base/tag-management/filter'
import { useStore as useTagStore } from '@/app/components/base/tag-management/store'
import { ToastContext } from '@/app/components/base/toast'
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { useAppContext } from '@/context/app-context'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { CheckModal } from '@/hooks/use-pay'
import { DSLImportStatus } from '@/models/app'
import { fetchWorkflowOnlineUsers, importAppBundle } from '@/service/apps'
import { fetchWorkflowOnlineUsers } from '@/service/apps'
import { useInfiniteAppList } from '@/service/use-apps'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
import AppCard from './app-card'
import { AppCardSkeleton } from './app-card-skeleton'
@ -67,10 +63,8 @@ const List: FC<Props> = ({
controlRefreshList = 0,
}) => {
const { t } = useTranslation()
const { notify } = useContext(ToastContext)
const { systemFeatures } = useGlobalPublicStore()
const router = useRouter()
const { push } = useRouter()
const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator, isLoadingCurrentWorkspace } = useAppContext()
const showTagManagementModal = useTagStore(s => s.showTagManagementModal)
const [activeTab, setActiveTab] = useQueryState(
@ -98,37 +92,10 @@ const List: FC<Props> = ({
setShowCreateFromDSLModal(true)
}, [])
const [importingBundle, setImportingBundle] = useState(false)
const handleBundleFileDropped = useCallback(async (file: File) => {
if (importingBundle)
return
setImportingBundle(true)
try {
const response = await importAppBundle({ file })
const { status, app_id, app_mode } = response
if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
notify({
type: status === DSLImportStatus.COMPLETED ? 'success' : 'warning',
message: t(status === DSLImportStatus.COMPLETED ? 'newApp.appCreated' : 'newApp.caution', { ns: 'app' }),
})
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
if (app_id)
getRedirection(isCurrentWorkspaceEditor, { id: app_id, mode: app_mode }, push)
}
else {
notify({ type: 'error', message: t('importBundleFailed', { ns: 'app' }) })
}
}
catch (e) {
const error = e as Error
notify({ type: 'error', message: error.message || t('importBundleFailed', { ns: 'app' }) })
}
finally {
setImportingBundle(false)
}
}, [importingBundle, isCurrentWorkspaceEditor, notify, push, t])
const handleBundleFileDropped = useCallback((file: File) => {
setDroppedDSLFile(file)
setShowCreateFromDSLModal(true)
}, [])
const { dragging } = useDSLDragDrop({
onDSLFileDropped: handleDSLFileDropped,