diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx index f880984c65..183a268f53 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx @@ -58,8 +58,8 @@ const AppDetailLayout: FC = (props) => { }>>([]) const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures) - const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => { - const navs = [ + const getNavigationConfig = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => { + const navConfig = [ ...(isCurrentWorkspaceEditor ? [{ name: t('common.appMenus.promptEng'), @@ -93,8 +93,8 @@ const AppDetailLayout: FC = (props) => { selectedIcon: RiDashboard2Fill, }, ] - return navs - }, []) + return navConfig + }, [t]) useEffect(() => { if (appDetail) { @@ -141,7 +141,7 @@ const AppDetailLayout: FC = (props) => { } else { setAppDetail({ ...res, enable_sso: false }) - setNavigation(getNavigations(appId, isCurrentWorkspaceEditor, res.mode)) + setNavigation(getNavigationConfig(appId, isCurrentWorkspaceEditor, res.mode)) if (systemFeatures.enable_web_sso_switch_component && canIEditApp) { fetchAppSSO({ appId }).then((ssoRes) => { setAppDetail({ ...res, enable_sso: ssoRes.enabled }) diff --git a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx index 351d3696ce..a88afc3adc 100644 --- a/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx +++ b/web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout-main.tsx @@ -4,9 +4,10 @@ import React, { useEffect, useMemo } from 'react' import { usePathname } from 'next/navigation' import useSWR from 'swr' import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' import type { RemixiconComponentType } from '@remixicon/react' import { + RiApps2AddLine, + RiBookOpenLine, RiEqualizer2Fill, RiEqualizer2Line, RiFileTextFill, @@ -17,7 +18,7 @@ import { import { PaperClipIcon, } from '@heroicons/react/24/outline' -import { RiApps2AddLine, RiBookOpenLine, RiInformation2Line } from '@remixicon/react' +import { RiInformation2Line } from '@remixicon/react' import classNames from '@/utils/classnames' import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets' import type { RelatedAppResponse } from '@/models/datasets' @@ -26,13 +27,14 @@ import Loading from '@/app/components/base/loading' import DatasetDetailContext from '@/context/dataset-detail' import { DataSourceType } from '@/models/datasets' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' -import { LanguagesSupported } from '@/i18n/language' import { useStore } from '@/app/components/app/store' import { getLocaleOnClient } from '@/i18n' import { useAppContext } from '@/context/app-context' 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/public/pipeline' +import { Divider } from '@/app/components/base/icons/src/public/knowledge' +import { LanguagesSupported } from '@/i18n/language' export type IAppDetailLayoutProps = { children: React.ReactNode @@ -42,83 +44,106 @@ export type IAppDetailLayoutProps = { type IExtraInfoProps = { isMobile: boolean relatedApps?: RelatedAppResponse + documentCount?: number expand: boolean } -const ExtraInfo = ({ isMobile, relatedApps, expand }: IExtraInfoProps) => { +const ExtraInfo = React.memo(({ + isMobile, + relatedApps, + documentCount, + expand, +}: IExtraInfoProps) => { const locale = getLocaleOnClient() - const [isShowTips, { toggle: toggleTips, set: setShowTips }] = useBoolean(!isMobile) const { t } = useTranslation() const hasRelatedApps = relatedApps?.data && relatedApps?.data?.length > 0 const relatedAppsTotal = relatedApps?.data?.length || 0 - useEffect(() => { - setShowTips(!isMobile) - }, [isMobile, setShowTips]) - - return
- {hasRelatedApps && ( - <> - {!isMobile && ( - - } - > -
- {relatedAppsTotal || '--'} {t('common.datasetMenus.relatedApp')} - + return ( +
+ {hasRelatedApps && ( + <> + {!isMobile && ( +
+
+
+ {documentCount || '--'} +
+
+ {t('common.datasetMenus.documents')} +
+
+
+ +
+
+
+ {relatedAppsTotal || '--'} +
+ + } + > +
+ {t('common.datasetMenus.relatedApp')} + +
+
+
- - )} + )} - {isMobile &&
- {relatedAppsTotal || '--'} - -
} - - )} - {!hasRelatedApps && !expand && ( - -
- + {isMobile && ( +
+ {relatedAppsTotal || '--'} +
-
{t('common.datasetMenus.emptyTip')}
- - - {t('common.datasetMenus.viewDoc')} - + )} + + )} + {!hasRelatedApps && !expand && ( + +
+ +
+
{t('common.datasetMenus.emptyTip')}
+ + + {t('common.datasetMenus.viewDoc')} + +
+ } + > +
+ {t('common.datasetMenus.noRelatedApp')} +
- } - > -
- {t('common.datasetMenus.noRelatedApp')} - -
-
- )} -
-} + + )} +
+ ) +}) const DatasetDetailLayout: FC = (props) => { const { @@ -185,12 +210,16 @@ const DatasetDetailLayout: FC = (props) => {
{!hideSideBar && : undefined} + extraInfo={ + !isCurrentWorkspaceDatasetOperator + ? mode => + : undefined + } iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'} />} React.ReactNode } -const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigation, extraInfo, iconType = 'app' }: IAppDetailNavProps) => { +const AppDetailNav = ({ + title, + desc, + isExternal, + icon, + icon_background, + navigation, + extraInfo, + iconType = 'app', +}: IAppDetailNavProps) => { const { appSidebarExpand, setAppSidebarExpand } = useAppStore(useShallow(state => ({ appSidebarExpand: state.appSidebarExpand, setAppSidebarExpand: state.setAppSidebarExpand, diff --git a/web/app/components/base/icons/assets/public/knowledge/divider.svg b/web/app/components/base/icons/assets/public/knowledge/divider.svg new file mode 100644 index 0000000000..5bf3dbead9 --- /dev/null +++ b/web/app/components/base/icons/assets/public/knowledge/divider.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/app/components/base/icons/src/public/knowledge/Divider.json b/web/app/components/base/icons/src/public/knowledge/Divider.json new file mode 100644 index 0000000000..7d0b412f4a --- /dev/null +++ b/web/app/components/base/icons/src/public/knowledge/Divider.json @@ -0,0 +1,29 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "6", + "height": "30", + "viewBox": "0 0 6 30", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Line 3", + "d": "M1.44595 28.7455L5.49125 1.00004", + "stroke": "currentColor", + "stroke-opacity": "0.08", + "stroke-linecap": "round" + }, + "children": [] + } + ] + }, + "name": "Divider" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/public/knowledge/Divider.tsx b/web/app/components/base/icons/src/public/knowledge/Divider.tsx new file mode 100644 index 0000000000..56606448be --- /dev/null +++ b/web/app/components/base/icons/src/public/knowledge/Divider.tsx @@ -0,0 +1,20 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Divider.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconData } from '@/app/components/base/icons/IconBase' + +const Icon = ( + { + ref, + ...props + }: React.SVGProps & { + ref?: React.RefObject>; + }, +) => + +Icon.displayName = 'Divider' + +export default Icon diff --git a/web/app/components/base/icons/src/public/knowledge/index.ts b/web/app/components/base/icons/src/public/knowledge/index.ts index cfe9c6a996..d01055078b 100644 --- a/web/app/components/base/icons/src/public/knowledge/index.ts +++ b/web/app/components/base/icons/src/public/knowledge/index.ts @@ -1,5 +1,6 @@ export { default as Chunk } from './Chunk' export { default as Collapse } from './Collapse' +export { default as Divider } from './Divider' export { default as ExternalKnowledgeBase } from './ExternalKnowledgeBase' export { default as File } from './File' export { default as GeneralType } from './GeneralType' diff --git a/web/app/components/base/linked-apps-panel/index.tsx b/web/app/components/base/linked-apps-panel/index.tsx index 4ee67c5243..0655c0a5fd 100644 --- a/web/app/components/base/linked-apps-panel/index.tsx +++ b/web/app/components/base/linked-apps-panel/index.tsx @@ -2,7 +2,6 @@ import type { FC } from 'react' import React from 'react' import Link from 'next/link' -import { useTranslation } from 'react-i18next' import { RiArrowRightUpLine } from '@remixicon/react' import cn from '@/utils/classnames' import AppIcon from '@/app/components/base/app-icon' @@ -49,10 +48,8 @@ const LinkedAppsPanel: FC = ({ relatedApps, isMobile, }) => { - const { t } = useTranslation() return (
-
{relatedApps.length || '--'} {t('common.datasetMenus.relatedApp')}
{relatedApps.map((item, index) => ( ))} diff --git a/web/models/datasets.ts b/web/models/datasets.ts index 56476f069a..f6a5d8aab8 100644 --- a/web/models/datasets.ts +++ b/web/models/datasets.ts @@ -34,8 +34,13 @@ export type MetadataInDoc = { export type DataSet = { id: string name: string - icon: string - icon_background: string + indexing_status: DocumentIndexingStatus + icon_info: { + icon: string + icon_background: string + icon_type: AppIconType + icon_url: string + } description: string permission: DatasetPermission data_source_type: DataSourceType @@ -46,6 +51,7 @@ export type DataSet = { app_count: number doc_form: ChunkingMode document_count: number + total_document_count: number available_document_count?: number word_count: number provider: string