diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx index 183a268f53..fbd332c69d 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx @@ -166,7 +166,13 @@ const AppDetailLayout: FC = (props) => { return (
{appDetail && ( - + )}
{children} diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx index b3d816e280..2f69fb48a5 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx @@ -6,8 +6,7 @@ import useSWR from 'swr' import { useTranslation } from 'react-i18next' import type { RemixiconComponentType } from '@remixicon/react' import { - RiApps2AddLine, - RiBookOpenLine, + RiAttachmentLine, RiEqualizer2Fill, RiEqualizer2Line, RiFileTextFill, @@ -15,9 +14,6 @@ import { RiFocus2Fill, RiFocus2Line, } from '@remixicon/react' -import { - PaperClipIcon, -} from '@heroicons/react/24/outline' import { RiInformation2Line } from '@remixicon/react' import classNames from '@/utils/classnames' import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets' @@ -33,7 +29,7 @@ import Tooltip from '@/app/components/base/tooltip' import LinkedAppsPanel from '@/app/components/base/linked-apps-panel' import { PipelineFill, PipelineLine } from '@/app/components/base/icons/src/vender/pipeline' import { Divider } from '@/app/components/base/icons/src/vender/knowledge' -import { useGetDocLanguage } from '@/context/i18n' +import NoLinkedAppsPanel from '@/app/components/datasets/no-linked-apps-panel' export type IAppDetailLayoutProps = { children: React.ReactNode @@ -41,102 +37,69 @@ export type IAppDetailLayoutProps = { } type IExtraInfoProps = { - isMobile: boolean relatedApps?: RelatedAppResponse documentCount?: number expand: boolean } const ExtraInfo = React.memo(({ - isMobile, relatedApps, documentCount, expand, }: IExtraInfoProps) => { const { t } = useTranslation() - const docLanguage = useGetDocLanguage() const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0 const relatedAppsTotal = relatedApps?.data?.length || 0 return ( -
- {hasRelatedApps && ( - <> - {!isMobile && ( -
-
-
- {documentCount || '--'} -
-
- {t('common.datasetMenus.documents')} -
-
-
- -
-
-
- {relatedAppsTotal || '--'} -
- - } - > -
- {t('common.datasetMenus.relatedApp')} - -
-
-
+ <> + {!expand && ( +
+
+
+ {documentCount ?? '--'}
- )} - - {isMobile && ( -
- {relatedAppsTotal || '--'} - +
+ {t('common.datasetMenus.documents')}
- )} - - )} - {!hasRelatedApps && !expand && ( - -
- -
-
{t('common.datasetMenus.emptyTip')}
- - - {t('common.datasetMenus.viewDoc')} - -
- } - > -
- {t('common.datasetMenus.noRelatedApp')} -
- +
+ +
+
+
+ {relatedAppsTotal ?? '--'} +
+ + ) : + } + > +
+ {t('common.datasetMenus.relatedApp')} + +
+
+
+
)} -
+ + {expand && ( +
+ {relatedAppsTotal ?? '--'} + +
+ )} + ) }) @@ -203,25 +166,27 @@ const DatasetDetailLayout: FC = (props) => { return (
- {!hideSideBar && - : undefined - } - iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'} - />} mutateDatasetRes(), }}> + {!hideSideBar && ( + + : undefined + } + iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'} + /> + )}
{children}
diff --git a/web/app/components/app-sidebar/dataset-info.tsx b/web/app/components/app-sidebar/dataset-info.tsx index 73740133ce..6c94650213 100644 --- a/web/app/components/app-sidebar/dataset-info.tsx +++ b/web/app/components/app-sidebar/dataset-info.tsx @@ -3,41 +3,74 @@ import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' import AppIcon from '../base/app-icon' - -const DatasetSvg = - - +import Effect from '../base/effect' +import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' +import { DOC_FORM_ICON_WITH_BG, DOC_FORM_TEXT } from '@/models/datasets' +import { useKnowledge } from '@/hooks/use-knowledge' +import Badge from '../base/badge' type Props = { - isExternal?: boolean - name: string - description: string expand: boolean extraInfo?: React.ReactNode } const DatasetInfo: FC = ({ - name, - description, - isExternal, expand, extraInfo, }) => { const { t } = useTranslation() + const dataset = useDatasetDetailContextWithSelector(state => state.dataset) + const iconInfo = dataset!.icon_info || { + icon: '📙', + icon_type: 'emoji', + icon_background: '#FFF4ED', + icon_url: '', + } + const isExternal = dataset!.provider === 'external' + const { formatIndexingTechniqueAndMethod } = useKnowledge() + const Icon = isExternal ? DOC_FORM_ICON_WITH_BG.external : DOC_FORM_ICON_WITH_BG[dataset!.doc_form] + return ( -
-
- -
- {expand && ( -
-
- {name} +
+ +
+
+ +
+
-
{isExternal ? t('dataset.externalTag') : t('dataset.localDocs')}
-
{description}
- )} + {expand && dataset && ( + <> +
+
+ {dataset.name} +
+
+ {isExternal && t('dataset.externalTag')} + {!isExternal && ( +
+ {t(`dataset.chunkingMode.${DOC_FORM_TEXT[dataset.doc_form]}`)} + {formatIndexingTechniqueAndMethod(dataset.indexing_technique, dataset.retrieval_model_dict?.search_method)} +
+ )} +
+
+

+ {dataset.description} +

+ + )} +
{extraInfo}
) diff --git a/web/app/components/app-sidebar/index.tsx b/web/app/components/app-sidebar/index.tsx index f03aa7018a..ab4ba32d93 100644 --- a/web/app/components/app-sidebar/index.tsx +++ b/web/app/components/app-sidebar/index.tsx @@ -73,9 +73,6 @@ const AppDetailNav = ({ )} {iconType === 'dataset' && ( diff --git a/web/app/components/base/effect/index.tsx b/web/app/components/base/effect/index.tsx new file mode 100644 index 0000000000..666674dd08 --- /dev/null +++ b/web/app/components/base/effect/index.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import cn from '@/utils/classnames' + +type EffectProps = { + className?: string +} + +const Effect = ({ + className, +}: EffectProps) => { + return ( +
+ ) +} + +export default React.memo(Effect) diff --git a/web/app/components/datasets/create-from-pipeline/header-effect.tsx b/web/app/components/datasets/create-from-pipeline/header-effect.tsx deleted file mode 100644 index 2462d28b96..0000000000 --- a/web/app/components/datasets/create-from-pipeline/header-effect.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' - -const HeaderEffect = () => { - return ( -
- ) -} - -export default React.memo(HeaderEffect) diff --git a/web/app/components/datasets/create-from-pipeline/index.tsx b/web/app/components/datasets/create-from-pipeline/index.tsx index b0f5fdf345..194d5a5204 100644 --- a/web/app/components/datasets/create-from-pipeline/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/index.tsx @@ -1,8 +1,8 @@ 'use client' -import HeaderEffect from './header-effect' import Header from './header' import CreateOptions from './create-options' import List from './list' +import Effect from '../../base/effect' const CreateFromPipeline = () => { return ( @@ -10,7 +10,7 @@ const CreateFromPipeline = () => { className='relative flex flex-col rounded-t-2xl border-t border-effects-highlight bg-background-default-subtle' style={{ height: 'calc(100vh - 56px)' }} > - +
diff --git a/web/app/components/datasets/create-from-pipeline/list/template-card/index.tsx b/web/app/components/datasets/create-from-pipeline/list/template-card/index.tsx index 4e346b8daa..eb6089c3c8 100644 --- a/web/app/components/datasets/create-from-pipeline/list/template-card/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/list/template-card/index.tsx @@ -9,7 +9,7 @@ import Operations from './operations' import Modal from '@/app/components/base/modal' import EditPipelineInfo from './edit-pipeline-info' import type { PipelineTemple } from '@/models/pipeline' -import { DOC_FORM_ICON, DOC_FORM_TEXT } from '@/models/datasets' +import { DOC_FORM_ICON_WITH_BG, DOC_FORM_TEXT } from '@/models/datasets' import Confirm from '@/app/components/base/confirm' import { useDeletePipeline, useExportPipelineDSL, useImportPipelineDSL, usePipelineTemplateById } from '@/service/use-pipeline' import { downloadFile } from '@/utils/format' @@ -131,7 +131,7 @@ const TemplateCard = ({ }) }, [pipeline.id, deletePipeline]) - const Icon = DOC_FORM_ICON[pipeline.doc_form] || General + const Icon = DOC_FORM_ICON_WITH_BG[pipeline.doc_form] || General const iconInfo = pipeline.icon_info return ( diff --git a/web/app/components/datasets/list/dataset-card/index.tsx b/web/app/components/datasets/list/dataset-card/index.tsx index f613b9a391..15190df4a3 100644 --- a/web/app/components/datasets/list/dataset-card/index.tsx +++ b/web/app/components/datasets/list/dataset-card/index.tsx @@ -3,7 +3,6 @@ import { useRouter } from 'next/navigation' import { useTranslation } from 'react-i18next' import type { DataSet } from '@/models/datasets' import { useSelector as useAppContextWithSelector } from '@/context/app-context' -import { General } from '@/app/components/base/icons/src/public/knowledge/dataset-card' import { useKnowledge } from '@/hooks/use-knowledge' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import type { Tag } from '@/app/components/base/tag-management/constant' @@ -22,7 +21,7 @@ import CustomPopover from '@/app/components/base/popover' import Operations from './operations' import AppIcon from '@/app/components/base/app-icon' import CornerLabel from '@/app/components/base/corner-label' -import { DOC_FORM_ICON, DOC_FORM_TEXT } from '@/models/datasets' +import { DOC_FORM_ICON_WITH_BG, DOC_FORM_TEXT } from '@/models/datasets' const EXTERNAL_PROVIDER = 'external' @@ -50,7 +49,7 @@ const DatasetCard = ({ const isExternalProvider = useMemo(() => { return dataset.provider === EXTERNAL_PROVIDER }, [dataset.provider]) - const Icon = isExternalProvider ? DOC_FORM_ICON.external : (DOC_FORM_ICON[dataset.doc_form] || General) + const Icon = isExternalProvider ? DOC_FORM_ICON_WITH_BG.external : DOC_FORM_ICON_WITH_BG[dataset.doc_form] const iconInfo = dataset.icon_info || { icon: '📙', icon_type: 'emoji', diff --git a/web/app/components/datasets/no-linked-apps-panel.tsx b/web/app/components/datasets/no-linked-apps-panel.tsx new file mode 100644 index 0000000000..b6e2e4addf --- /dev/null +++ b/web/app/components/datasets/no-linked-apps-panel.tsx @@ -0,0 +1,28 @@ +import { useGetDocLanguage } from '@/context/i18n' +import { RiApps2AddLine, RiBookOpenLine } from '@remixicon/react' +import React from 'react' +import { useTranslation } from 'react-i18next' + +const NoLinkedAppsPanel = () => { + const { t } = useTranslation() + const docLanguage = useGetDocLanguage() + + return ( +
+
+ +
+
{t('common.datasetMenus.emptyTip')}
+ + + {t('common.datasetMenus.viewDoc')} + +
+ ) +} + +export default React.memo(NoLinkedAppsPanel) diff --git a/web/context/dataset-detail.ts b/web/context/dataset-detail.ts index 198de381a8..d453f3f01f 100644 --- a/web/context/dataset-detail.ts +++ b/web/context/dataset-detail.ts @@ -11,7 +11,7 @@ const DatasetDetailContext = createContext({}) export const useDatasetDetailContext = () => useContext(DatasetDetailContext) -export const useDatasetDetailContextWithSelector = (selector: (value: DatasetDetailContextValue) => any) => { +export const useDatasetDetailContextWithSelector = (selector: (value: DatasetDetailContextValue) => T): T => { return useContextSelector(DatasetDetailContext, selector) } export default DatasetDetailContext diff --git a/web/models/datasets.ts b/web/models/datasets.ts index fa42f80dd5..52a16b2396 100644 --- a/web/models/datasets.ts +++ b/web/models/datasets.ts @@ -5,6 +5,7 @@ import type { IndexingType } from '@/app/components/datasets/create/step-two' import type { MetadataFilteringVariableType } from '@/app/components/workflow/nodes/knowledge-retrieval/types' import type { MetadataItemWithValue } from '@/app/components/datasets/metadata/types' import { ExternalKnowledgeBase, General, Graph, ParentChild, Qa } from '@/app/components/base/icons/src/public/knowledge/dataset-card' +import { GeneralChunk, ParentChildChunk, QuestionAndAnswer } from '@/app/components/base/icons/src/vender/knowledge' export enum DataSourceType { FILE = 'upload_file', @@ -704,7 +705,7 @@ export type BatchImportResponse = { job_status: string } -export const DOC_FORM_ICON: Record> = { +export const DOC_FORM_ICON_WITH_BG: Record> = { [ChunkingMode.text]: General, [ChunkingMode.qa]: Qa, [ChunkingMode.parentChild]: ParentChild, @@ -712,6 +713,12 @@ export const DOC_FORM_ICON: Record> = { + [ChunkingMode.text]: GeneralChunk, + [ChunkingMode.qa]: QuestionAndAnswer, + [ChunkingMode.parentChild]: ParentChildChunk, +} + export const DOC_FORM_TEXT: Record = { [ChunkingMode.text]: 'general', [ChunkingMode.qa]: 'qa',