mirror of
https://github.com/langgenius/dify.git
synced 2026-08-31 01:36:38 +08:00
refactor(web): migrate empty dataset input (#41030)
This commit is contained in:
+36
-7
@@ -1,5 +1,6 @@
|
||||
import type { MockedFunction } from 'vite-plus/test'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { createEmptyDataset } from '@/service/datasets'
|
||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||
import EmptyDatasetCreationModal from '../index'
|
||||
@@ -73,9 +74,8 @@ describe('EmptyDatasetCreationModal', () => {
|
||||
|
||||
expect(screen.getByText('datasetCreation.stepOne.modal.title')).toBeInTheDocument()
|
||||
expect(screen.getByText('datasetCreation.stepOne.modal.tip')).toBeInTheDocument()
|
||||
expect(screen.getByText('datasetCreation.stepOne.modal.input')).toBeInTheDocument()
|
||||
expect(
|
||||
screen.getByPlaceholderText('datasetCreation.stepOne.modal.placeholder'),
|
||||
screen.getByRole('textbox', { name: 'datasetCreation.stepOne.modal.input' }),
|
||||
).toBeInTheDocument()
|
||||
expect(screen.getByText('datasetCreation.stepOne.modal.confirmButton')).toBeInTheDocument()
|
||||
expect(screen.getByText('datasetCreation.stepOne.modal.cancelButton')).toBeInTheDocument()
|
||||
@@ -289,20 +289,49 @@ describe('EmptyDatasetCreationModal', () => {
|
||||
|
||||
// API Calls - Test API interactions
|
||||
describe('API Calls', () => {
|
||||
it('should call createEmptyDataset with correct parameters', async () => {
|
||||
it('should submit from the dataset name input with Enter', async () => {
|
||||
const mockOnHide = vi.fn()
|
||||
render(<EmptyDatasetCreationModal show={true} onHide={mockOnHide} />)
|
||||
const input = screen.getByPlaceholderText('datasetCreation.stepOne.modal.placeholder')
|
||||
const confirmButton = screen.getByText('datasetCreation.stepOne.modal.confirmButton')
|
||||
const user = userEvent.setup()
|
||||
const input = screen.getByRole('textbox', { name: 'datasetCreation.stepOne.modal.input' })
|
||||
|
||||
fireEvent.change(input, { target: { value: 'New Dataset' } })
|
||||
fireEvent.click(confirmButton)
|
||||
await user.type(input, 'New Dataset{Enter}')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockCreateEmptyDataset).toHaveBeenCalledWith({ name: 'New Dataset' })
|
||||
})
|
||||
})
|
||||
|
||||
it('should not submit again while dataset creation is pending', async () => {
|
||||
let resolveRequest:
|
||||
| ((value: Awaited<ReturnType<typeof createEmptyDataset>>) => void)
|
||||
| undefined
|
||||
mockCreateEmptyDataset.mockReturnValueOnce(
|
||||
new Promise((resolve) => {
|
||||
resolveRequest = resolve
|
||||
}),
|
||||
)
|
||||
const onHide = vi.fn()
|
||||
render(<EmptyDatasetCreationModal show={true} onHide={onHide} />)
|
||||
const user = userEvent.setup()
|
||||
const input = screen.getByRole('textbox', { name: 'datasetCreation.stepOne.modal.input' })
|
||||
|
||||
await user.type(input, 'New Dataset{Enter}')
|
||||
await waitFor(() => {
|
||||
expect(mockCreateEmptyDataset).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
await user.keyboard('{Enter}')
|
||||
expect(mockCreateEmptyDataset).toHaveBeenCalledTimes(1)
|
||||
|
||||
resolveRequest?.({
|
||||
id: 'dataset-123',
|
||||
name: 'New Dataset',
|
||||
} as Awaited<ReturnType<typeof createEmptyDataset>>)
|
||||
await waitFor(() => {
|
||||
expect(onHide).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
it('should call invalidDatasetList after successful creation', async () => {
|
||||
const mockOnHide = vi.fn()
|
||||
render(<EmptyDatasetCreationModal show={true} onHide={mockOnHide} />)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
@apply mb-8;
|
||||
}
|
||||
.form .label {
|
||||
@apply mb-2 text-text-primary;
|
||||
@apply py-0 text-text-primary;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
'use client'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
|
||||
import { Dialog, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
|
||||
import { Field, FieldLabel } from '@langgenius/dify-ui/field'
|
||||
import { Form } from '@langgenius/dify-ui/form'
|
||||
import { Input } from '@langgenius/dify-ui/input'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import * as React from 'react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { createEmptyDataset } from '@/service/datasets'
|
||||
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
|
||||
@@ -19,10 +21,13 @@ type IProps = {
|
||||
}
|
||||
const EmptyDatasetCreationModal = ({ show = false, onHide }: IProps) => {
|
||||
const [inputValue, setInputValue] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const invalidDatasetList = useInvalidDatasetList()
|
||||
const submit = async () => {
|
||||
if (isSubmitting) return
|
||||
|
||||
if (!inputValue) {
|
||||
toast.error(t(($) => $['stepOne.modal.nameNotEmpty'], { ns: 'datasetCreation' }))
|
||||
return
|
||||
@@ -31,6 +36,7 @@ const EmptyDatasetCreationModal = ({ show = false, onHide }: IProps) => {
|
||||
toast.error(t(($) => $['stepOne.modal.nameLengthInvalid'], { ns: 'datasetCreation' }))
|
||||
return
|
||||
}
|
||||
setIsSubmitting(true)
|
||||
try {
|
||||
const dataset = await createEmptyDataset({ name: inputValue })
|
||||
invalidDatasetList()
|
||||
@@ -42,6 +48,8 @@ const EmptyDatasetCreationModal = ({ show = false, onHide }: IProps) => {
|
||||
router.push(`/datasets/${dataset.id}/documents`)
|
||||
} catch {
|
||||
toast.error(t(($) => $['stepOne.modal.failed'], { ns: 'datasetCreation' }))
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
return (
|
||||
@@ -53,9 +61,9 @@ const EmptyDatasetCreationModal = ({ show = false, onHide }: IProps) => {
|
||||
>
|
||||
<DialogContent className="w-full max-w-130! overflow-hidden! border-none px-8 text-left align-middle">
|
||||
<div className={s.modalHeader}>
|
||||
<div className={s.title}>
|
||||
<DialogTitle className={s.title}>
|
||||
{t(($) => $['stepOne.modal.title'], { ns: 'datasetCreation' })}
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
@@ -67,24 +75,28 @@ const EmptyDatasetCreationModal = ({ show = false, onHide }: IProps) => {
|
||||
/>
|
||||
</div>
|
||||
<div className={s.tip}>{t(($) => $['stepOne.modal.tip'], { ns: 'datasetCreation' })}</div>
|
||||
<div className={s.form}>
|
||||
<div className={s.label}>
|
||||
{t(($) => $['stepOne.modal.input'], { ns: 'datasetCreation' })}
|
||||
<Form onFormSubmit={() => void submit()}>
|
||||
<Field name="datasetName" className={cn(s.form, 'gap-2')}>
|
||||
<FieldLabel className={s.label}>
|
||||
{t(($) => $['stepOne.modal.input'], { ns: 'datasetCreation' })}
|
||||
</FieldLabel>
|
||||
<Input
|
||||
value={inputValue}
|
||||
placeholder={
|
||||
t(($) => $['stepOne.modal.placeholder'], { ns: 'datasetCreation' }) || ''
|
||||
}
|
||||
onValueChange={setInputValue}
|
||||
/>
|
||||
</Field>
|
||||
<div className="flex flex-row-reverse">
|
||||
<Button type="submit" className="ml-2 w-24" variant="primary" loading={isSubmitting}>
|
||||
{t(($) => $['stepOne.modal.confirmButton'], { ns: 'datasetCreation' })}
|
||||
</Button>
|
||||
<Button type="button" className="w-24" onClick={onHide}>
|
||||
{t(($) => $['stepOne.modal.cancelButton'], { ns: 'datasetCreation' })}
|
||||
</Button>
|
||||
</div>
|
||||
<Input
|
||||
value={inputValue}
|
||||
placeholder={t(($) => $['stepOne.modal.placeholder'], { ns: 'datasetCreation' }) || ''}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row-reverse">
|
||||
<Button className="ml-2 w-24" variant="primary" onClick={submit}>
|
||||
{t(($) => $['stepOne.modal.confirmButton'], { ns: 'datasetCreation' })}
|
||||
</Button>
|
||||
<Button className="w-24" onClick={onHide}>
|
||||
{t(($) => $['stepOne.modal.cancelButton'], { ns: 'datasetCreation' })}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user