diff --git a/web/app/components/base/retry-button/index.tsx b/web/app/components/base/retry-button/index.tsx
deleted file mode 100644
index 689827af7b..0000000000
--- a/web/app/components/base/retry-button/index.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useEffect, useReducer } from 'react'
-import { useTranslation } from 'react-i18next'
-import useSWR from 'swr'
-import s from './style.module.css'
-import classNames from '@/utils/classnames'
-import Divider from '@/app/components/base/divider'
-import { getErrorDocs, retryErrorDocs } from '@/service/datasets'
-import type { IndexingStatusResponse } from '@/models/datasets'
-
-const WarningIcon = () =>
-
-
-type Props = {
- datasetId: string
-}
-type IIndexState = {
- value: string
-}
-type ActionType = 'retry' | 'success' | 'error'
-
-type IAction = {
- type: ActionType
-}
-const indexStateReducer = (state: IIndexState, action: IAction) => {
- const actionMap = {
- retry: 'retry',
- success: 'success',
- error: 'error',
- }
-
- return {
- ...state,
- value: actionMap[action.type] || state.value,
- }
-}
-
-const RetryButton: FC = ({ datasetId }) => {
- const { t } = useTranslation()
- const [indexState, dispatch] = useReducer(indexStateReducer, { value: 'success' })
- const { data: errorDocs } = useSWR({ datasetId }, getErrorDocs)
-
- const onRetryErrorDocs = async () => {
- dispatch({ type: 'retry' })
- const document_ids = errorDocs?.data.map((doc: IndexingStatusResponse) => doc.id) || []
- const res = await retryErrorDocs({ datasetId, document_ids })
- if (res.result === 'success')
- dispatch({ type: 'success' })
- else
- dispatch({ type: 'error' })
- }
-
- useEffect(() => {
- if (errorDocs?.total === 0)
- dispatch({ type: 'success' })
- else
- dispatch({ type: 'error' })
- }, [errorDocs?.total])
-
- if (indexState.value === 'success')
- return null
-
- return (
-
-
-
- {errorDocs?.total} {t('dataset.docsFailedNotice')}
-
-
-
- {t('dataset.retry')}
-
-
- )
-}
-export default RetryButton
diff --git a/web/app/components/base/retry-button/style.module.css b/web/app/components/base/retry-button/style.module.css
deleted file mode 100644
index 99a0947576..0000000000
--- a/web/app/components/base/retry-button/style.module.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.retryBtn {
- @apply inline-flex justify-center items-center content-center h-9 leading-5 rounded-lg px-4 py-2 text-base;
- @apply border-solid border border-gray-200 text-gray-500 hover:bg-white hover:shadow-sm hover:border-gray-300;
-}
diff --git a/web/app/components/datasets/common/document-status-with-action/index-failed.tsx b/web/app/components/datasets/common/document-status-with-action/index-failed.tsx
new file mode 100644
index 0000000000..05ed9cd4b6
--- /dev/null
+++ b/web/app/components/datasets/common/document-status-with-action/index-failed.tsx
@@ -0,0 +1,69 @@
+'use client'
+import type { FC } from 'react'
+import React, { useEffect, useReducer } from 'react'
+import { useTranslation } from 'react-i18next'
+import useSWR from 'swr'
+import StatusWithAction from './status-with-action'
+import { getErrorDocs, retryErrorDocs } from '@/service/datasets'
+import type { IndexingStatusResponse } from '@/models/datasets'
+
+type Props = {
+ datasetId: string
+}
+type IIndexState = {
+ value: string
+}
+type ActionType = 'retry' | 'success' | 'error'
+
+type IAction = {
+ type: ActionType
+}
+const indexStateReducer = (state: IIndexState, action: IAction) => {
+ const actionMap = {
+ retry: 'retry',
+ success: 'success',
+ error: 'error',
+ }
+
+ return {
+ ...state,
+ value: actionMap[action.type] || state.value,
+ }
+}
+
+const RetryButton: FC = ({ datasetId }) => {
+ const { t } = useTranslation()
+ const [indexState, dispatch] = useReducer(indexStateReducer, { value: 'success' })
+ const { data: errorDocs } = useSWR({ datasetId }, getErrorDocs)
+
+ const onRetryErrorDocs = async () => {
+ dispatch({ type: 'retry' })
+ const document_ids = errorDocs?.data.map((doc: IndexingStatusResponse) => doc.id) || []
+ const res = await retryErrorDocs({ datasetId, document_ids })
+ if (res.result === 'success')
+ dispatch({ type: 'success' })
+ else
+ dispatch({ type: 'error' })
+ }
+
+ useEffect(() => {
+ if (errorDocs?.total === 0)
+ dispatch({ type: 'success' })
+ else
+ dispatch({ type: 'error' })
+ }, [errorDocs?.total])
+
+ if (indexState.value === 'success')
+ return null
+
+ return (
+ { }}
+ />
+ )
+}
+export default RetryButton
diff --git a/web/app/components/datasets/common/document-status-with-action/status-with-action.tsx b/web/app/components/datasets/common/document-status-with-action/status-with-action.tsx
new file mode 100644
index 0000000000..7127e12a89
--- /dev/null
+++ b/web/app/components/datasets/common/document-status-with-action/status-with-action.tsx
@@ -0,0 +1,63 @@
+'use client'
+import { RiAlertFill, RiCheckboxCircleFill, RiErrorWarningFill, RiInformation2Fill } from '@remixicon/react'
+import type { FC } from 'react'
+import React from 'react'
+import cn from '@/utils/classnames'
+import Divider from '@/app/components/base/divider'
+
+type Status = 'success' | 'error' | 'warning' | 'info'
+type Props = {
+ type?: Status
+ description: string
+ actionText: string
+ onAction: () => void
+ disabled?: boolean
+}
+
+const IconMap = {
+ success: {
+ Icon: RiCheckboxCircleFill,
+ color: 'text-text-success',
+ },
+ error: {
+ Icon: RiErrorWarningFill,
+ color: 'text-text-destructive',
+ },
+ warning: {
+ Icon: RiAlertFill,
+ color: 'text-text-warning-secondary',
+ },
+ info: {
+ Icon: RiInformation2Fill,
+ color: 'text-text-accent',
+ },
+}
+
+const getIcon = (type: Status) => {
+ return IconMap[type]
+}
+
+const StatusAction: FC = ({
+ type = 'info',
+ description,
+ actionText,
+ onAction,
+ disabled,
+}) => {
+ const { Icon, color } = getIcon(type)
+ return (
+
+
+
+
{description}
+
+
{actionText}
+
+ )
+}
+export default React.memo(StatusAction)
diff --git a/web/app/components/datasets/create/step-two/index.tsx b/web/app/components/datasets/create/step-two/index.tsx
index 8cba952ef6..8a5389a341 100644
--- a/web/app/components/datasets/create/step-two/index.tsx
+++ b/web/app/components/datasets/create/step-two/index.tsx
@@ -21,6 +21,7 @@ import { ChunkContainer, QAPreview } from '../../chunk'
import { PreviewHeader } from '../../preview/header'
import { FormattedText } from '../../formatted-text/formatted'
import { PreviewSlice } from '../../formatted-text/flavours/preview-slice'
+import PreviewDocumentPicker from '../../common/document-picker/preview-document-picker'
import s from './index.module.css'
import unescape from './unescape'
import escape from './escape'
@@ -28,7 +29,7 @@ import { OptionCard } from './option-card'
import LanguageSelect from './language-select'
import { DelimiterInput, MaxLengthInput, OverlapInput } from './inputs'
import cn from '@/utils/classnames'
-import type { CrawlOptions, CrawlResultItem, CreateDocumentReq, CustomFile, FullDocumentDetail, ParentMode, PreProcessingRule, ProcessRule, Rules, createDocumentResponse } from '@/models/datasets'
+import type { CrawlOptions, CrawlResultItem, CreateDocumentReq, CustomFile, DocumentItem, FullDocumentDetail, ParentMode, PreProcessingRule, ProcessRule, Rules, createDocumentResponse } from '@/models/datasets'
import Button from '@/app/components/base/button'
import FloatRightContainer from '@/app/components/base/float-right-container'
@@ -57,7 +58,6 @@ import { getNotionInfo, getWebsiteInfo, useCreateDocument, useCreateFirstDocumen
import Badge from '@/app/components/base/badge'
import { SkeletonContanier, SkeletonPoint, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
import Tooltip from '@/app/components/base/tooltip'
-import Select from '@/app/components/base/select'
const TextLabel: FC = (props) => {
return
@@ -168,7 +168,9 @@ const StepTwo = ({
: IndexingType.ECONOMICAL,
)
- const [previewFileName, setPreviewFileName] = useState()
+ const [previewFile, setPreviewFile] = useState(
+ (datasetId && documentDetail) ? documentDetail.file : files[0],
+ )
// QA Related
const [isLanguageSelectDisabled, setIsLanguageSelectDisabled] = useState(false)
@@ -229,8 +231,8 @@ const StepTwo = ({
docForm,
docLanguage,
dataSourceType: DataSourceType.FILE,
- files: previewFileName
- ? [files.find(file => file.name === previewFileName)!]
+ files: previewFile
+ ? [files.find(file => file.name === previewFile.name)!]
: files,
indexingTechnique: getIndexing_technique() as any,
processRule: getProcessRule(),
@@ -932,18 +934,14 @@ const StepTwo = ({
title='Preview'
>
-