mirror of https://github.com/langgenius/dify.git
Merge branch 'feat/parent-child-retrieval' of https://github.com/langgenius/dify into feat/parent-child-retrieval
This commit is contained in:
commit
8baaf7c84e
|
|
@ -7,85 +7,36 @@ import { useTranslation } from 'react-i18next'
|
|||
import { useBoolean } from 'ahooks'
|
||||
import {
|
||||
Cog8ToothIcon,
|
||||
// CommandLineIcon,
|
||||
Squares2X2Icon,
|
||||
// eslint-disable-next-line sort-imports
|
||||
PuzzlePieceIcon,
|
||||
DocumentTextIcon,
|
||||
PaperClipIcon,
|
||||
QuestionMarkCircleIcon,
|
||||
} from '@heroicons/react/24/outline'
|
||||
import {
|
||||
Cog8ToothIcon as Cog8ToothSolidIcon,
|
||||
// CommandLineIcon as CommandLineSolidIcon,
|
||||
DocumentTextIcon as DocumentTextSolidIcon,
|
||||
} from '@heroicons/react/24/solid'
|
||||
import Link from 'next/link'
|
||||
import { RiApps2AddLine, RiInformation2Line } from '@remixicon/react'
|
||||
import s from './style.module.css'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { fetchDatasetDetail, fetchDatasetRelatedApps } from '@/service/datasets'
|
||||
import type { RelatedApp, RelatedAppResponse } from '@/models/datasets'
|
||||
import type { RelatedAppResponse } from '@/models/datasets'
|
||||
import AppSideBar from '@/app/components/app-sidebar'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import FloatPopoverContainer from '@/app/components/base/float-popover-container'
|
||||
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 { AiText, ChatBot, CuteRobot } from '@/app/components/base/icons/src/vender/solid/communication'
|
||||
import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel'
|
||||
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'
|
||||
|
||||
export type IAppDetailLayoutProps = {
|
||||
children: React.ReactNode
|
||||
params: { datasetId: string }
|
||||
}
|
||||
|
||||
type ILikedItemProps = {
|
||||
type?: 'plugin' | 'app'
|
||||
appStatus?: boolean
|
||||
detail: RelatedApp
|
||||
isMobile: boolean
|
||||
}
|
||||
|
||||
const LikedItem = ({
|
||||
type = 'app',
|
||||
detail,
|
||||
isMobile,
|
||||
}: ILikedItemProps) => {
|
||||
return (
|
||||
<Link className={classNames(s.itemWrapper, 'px-2', isMobile && 'justify-center')} href={`/app/${detail?.id}/overview`}>
|
||||
<div className={classNames(s.iconWrapper, 'mr-0')}>
|
||||
<AppIcon size='tiny' iconType={detail.icon_type} icon={detail.icon} background={detail.icon_background} imageUrl={detail.icon_url} />
|
||||
{type === 'app' && (
|
||||
<span className='absolute bottom-[-2px] right-[-2px] w-3.5 h-3.5 p-0.5 bg-white rounded border-[0.5px] border-[rgba(0,0,0,0.02)] shadow-sm'>
|
||||
{detail.mode === 'advanced-chat' && (
|
||||
<ChatBot className='w-2.5 h-2.5 text-[#1570EF]' />
|
||||
)}
|
||||
{detail.mode === 'agent-chat' && (
|
||||
<CuteRobot className='w-2.5 h-2.5 text-indigo-600' />
|
||||
)}
|
||||
{detail.mode === 'chat' && (
|
||||
<ChatBot className='w-2.5 h-2.5 text-[#1570EF]' />
|
||||
)}
|
||||
{detail.mode === 'completion' && (
|
||||
<AiText className='w-2.5 h-2.5 text-[#0E9384]' />
|
||||
)}
|
||||
{detail.mode === 'workflow' && (
|
||||
<Route className='w-2.5 h-2.5 text-[#f79009]' />
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{!isMobile && <div className={classNames(s.appInfo, 'ml-2')}>{detail?.name || '--'}</div>}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
const TargetIcon = ({ className }: SVGProps<SVGElement>) => {
|
||||
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
|
||||
<g clipPath="url(#clip0_4610_6951)">
|
||||
|
|
@ -117,65 +68,80 @@ const BookOpenIcon = ({ className }: SVGProps<SVGElement>) => {
|
|||
type IExtraInfoProps = {
|
||||
isMobile: boolean
|
||||
relatedApps?: RelatedAppResponse
|
||||
expand: boolean
|
||||
}
|
||||
|
||||
const ExtraInfo = ({ isMobile, relatedApps }: IExtraInfoProps) => {
|
||||
const ExtraInfo = ({ isMobile, relatedApps, 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 <div className='w-full flex flex-col items-center'>
|
||||
<Divider className='mt-5' />
|
||||
{(relatedApps?.data && relatedApps?.data?.length > 0) && (
|
||||
return <div>
|
||||
{hasRelatedApps && (
|
||||
<>
|
||||
{!isMobile && <div className='w-full px-2 pb-1 pt-4 uppercase text-xs text-gray-500 font-medium'>{relatedApps?.total || '--'} {t('common.datasetMenus.relatedApp')}</div>}
|
||||
{!isMobile && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<LinkedAppsPanel
|
||||
relatedApps={relatedApps.data}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
|
||||
<span>{relatedAppsTotal || '--'} {t('common.datasetMenus.relatedApp')}</span>
|
||||
<RiInformation2Line className='w-4 h-4' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{isMobile && <div className={classNames(s.subTitle, 'flex items-center justify-center !px-0 gap-1')}>
|
||||
{relatedApps?.total || '--'}
|
||||
{relatedAppsTotal || '--'}
|
||||
<PaperClipIcon className='h-4 w-4 text-gray-700' />
|
||||
</div>}
|
||||
{relatedApps?.data?.map((item, index) => (<LikedItem key={index} isMobile={isMobile} detail={item} />))}
|
||||
</>
|
||||
)}
|
||||
{!relatedApps?.data?.length && (
|
||||
<FloatPopoverContainer
|
||||
placement='bottom-start'
|
||||
open={isShowTips}
|
||||
toggle={toggleTips}
|
||||
isMobile={isMobile}
|
||||
triggerElement={
|
||||
<div className={classNames('h-7 w-7 inline-flex justify-center items-center rounded-lg bg-transparent', isShowTips && '!bg-gray-50')}>
|
||||
<QuestionMarkCircleIcon className='h-4 w-4 flex-shrink-0 text-gray-500' />
|
||||
{!hasRelatedApps && !expand && (
|
||||
<Tooltip
|
||||
position='right'
|
||||
noDecoration
|
||||
needsDelay
|
||||
popupContent={
|
||||
<div className='p-4 w-[240px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl'>
|
||||
<div className='inline-flex p-2 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle'>
|
||||
<RiApps2AddLine className='h-4 w-4 text-text-tertiary' />
|
||||
</div>
|
||||
<div className='text-xs text-text-tertiary my-2'>{t('common.datasetMenus.emptyTip')}</div>
|
||||
<a
|
||||
className='inline-flex items-center text-xs text-text-accent mt-2 cursor-pointer'
|
||||
href={
|
||||
locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
: 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
>
|
||||
<BookOpenIcon className='mr-1' />
|
||||
{t('common.datasetMenus.viewDoc')}
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={classNames('mt-5 p-3', isMobile && 'border-[0.5px] border-gray-200 shadow-lg rounded-lg bg-white w-[160px]')}>
|
||||
<div className='flex items-center justify-start gap-2'>
|
||||
<div className={s.emptyIconDiv}>
|
||||
<Squares2X2Icon className='w-3 h-3 text-gray-500' />
|
||||
</div>
|
||||
<div className={s.emptyIconDiv}>
|
||||
<PuzzlePieceIcon className='w-3 h-3 text-gray-500' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='text-xs text-gray-500 mt-2'>{t('common.datasetMenus.emptyTip')}</div>
|
||||
<a
|
||||
className='inline-flex items-center text-xs text-primary-600 mt-2 cursor-pointer'
|
||||
href={
|
||||
locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate_knowledge_within_application'
|
||||
: 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
|
||||
}
|
||||
target='_blank' rel='noopener noreferrer'
|
||||
>
|
||||
<BookOpenIcon className='mr-1' />
|
||||
{t('common.datasetMenus.viewDoc')}
|
||||
</a>
|
||||
<div className='inline-flex items-center system-xs-medium-uppercase text-text-secondary space-x-1 cursor-pointer'>
|
||||
<span>{t('common.datasetMenus.noRelatedApp')}</span>
|
||||
<RiInformation2Line className='w-4 h-4' />
|
||||
</div>
|
||||
</FloatPopoverContainer>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
|
|
@ -246,7 +212,7 @@ const DatasetDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
|||
desc={datasetRes?.description || '--'}
|
||||
isExternal={datasetRes?.provider === 'external'}
|
||||
navigation={navigation}
|
||||
extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} /> : undefined}
|
||||
extraInfo={!isCurrentWorkspaceDatasetOperator ? mode => <ExtraInfo isMobile={mode === 'collapse'} relatedApps={relatedApps} expand={mode === 'collapse'} /> : undefined}
|
||||
iconType={datasetRes?.data_source_type === DataSourceType.NOTION ? 'notion' : 'dataset'}
|
||||
/>}
|
||||
<DatasetDetailContext.Provider value={{
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
.itemWrapper {
|
||||
@apply flex items-center w-full h-10 rounded-lg hover:bg-gray-50 cursor-pointer;
|
||||
}
|
||||
.appInfo {
|
||||
@apply truncate text-gray-700 text-sm font-normal;
|
||||
}
|
||||
.iconWrapper {
|
||||
@apply relative w-6 h-6 rounded-lg;
|
||||
}
|
||||
.statusPoint {
|
||||
@apply flex justify-center items-center absolute -right-0.5 -bottom-0.5 w-2.5 h-2.5 bg-white rounded;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AppIcon from '../base/app-icon'
|
||||
|
||||
const DatasetSvg = <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M0.833497 5.13481C0.833483 4.69553 0.83347 4.31654 0.858973 4.0044C0.88589 3.67495 0.94532 3.34727 1.10598 3.03195C1.34567 2.56155 1.72812 2.17909 2.19852 1.93941C2.51384 1.77875 2.84152 1.71932 3.17097 1.6924C3.48312 1.6669 3.86209 1.66691 4.30137 1.66693L7.62238 1.66684C8.11701 1.66618 8.55199 1.66561 8.95195 1.80356C9.30227 1.92439 9.62134 2.12159 9.88607 2.38088C10.1883 2.67692 10.3823 3.06624 10.603 3.50894L11.3484 5.00008H14.3679C15.0387 5.00007 15.5924 5.00006 16.0434 5.03691C16.5118 5.07518 16.9424 5.15732 17.3468 5.36339C17.974 5.68297 18.4839 6.19291 18.8035 6.82011C19.0096 7.22456 19.0917 7.65515 19.13 8.12356C19.1668 8.57455 19.1668 9.12818 19.1668 9.79898V13.5345C19.1668 14.2053 19.1668 14.7589 19.13 15.2099C19.0917 15.6784 19.0096 16.1089 18.8035 16.5134C18.4839 17.1406 17.974 17.6505 17.3468 17.9701C16.9424 18.1762 16.5118 18.2583 16.0434 18.2966C15.5924 18.3334 15.0387 18.3334 14.3679 18.3334H5.63243C4.96163 18.3334 4.40797 18.3334 3.95698 18.2966C3.48856 18.2583 3.05798 18.1762 2.65353 17.9701C2.02632 17.6505 1.51639 17.1406 1.19681 16.5134C0.990734 16.1089 0.908597 15.6784 0.870326 15.2099C0.833478 14.7589 0.833487 14.2053 0.833497 13.5345V5.13481ZM7.51874 3.33359C8.17742 3.33359 8.30798 3.34447 8.4085 3.37914C8.52527 3.41942 8.63163 3.48515 8.71987 3.57158C8.79584 3.64598 8.86396 3.7579 9.15852 4.34704L9.48505 5.00008L2.50023 5.00008C2.50059 4.61259 2.50314 4.34771 2.5201 4.14012C2.5386 3.91374 2.57 3.82981 2.59099 3.7886C2.67089 3.6318 2.79837 3.50432 2.95517 3.42442C2.99638 3.40343 3.08031 3.37203 3.30669 3.35353C3.54281 3.33424 3.85304 3.33359 4.3335 3.33359H7.51874Z" fill="#444CE7" />
|
||||
</svg>
|
||||
|
||||
type Props = {
|
||||
isExternal?: boolean
|
||||
name: string
|
||||
description: string
|
||||
expand: boolean
|
||||
extraInfo?: React.ReactNode
|
||||
}
|
||||
|
||||
const DatasetInfo: FC<Props> = ({
|
||||
name,
|
||||
description,
|
||||
isExternal,
|
||||
expand,
|
||||
extraInfo,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='pl-1 pt-1'>
|
||||
<div className='flex-shrink-0 mr-3'>
|
||||
<AppIcon innerIcon={DatasetSvg} className='!border-[0.5px] !border-indigo-100 !bg-indigo-25' />
|
||||
</div>
|
||||
{expand && (
|
||||
<div className='mt-2'>
|
||||
<div className='system-md-semibold text-text-secondary'>
|
||||
{name}
|
||||
</div>
|
||||
<div className='mt-1 text-text-tertiary system-2xs-medium-uppercase'>{isExternal ? t('dataset.externalTag') : t('dataset.localDocs')}</div>
|
||||
<div className='my-3 system-xs-regular text-text-tertiary'>{description}</div>
|
||||
</div>
|
||||
)}
|
||||
{extraInfo}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(DatasetInfo)
|
||||
|
|
@ -4,12 +4,14 @@ import NavLink from './navLink'
|
|||
import type { NavIcon } from './navLink'
|
||||
import AppBasic from './basic'
|
||||
import AppInfo from './app-info'
|
||||
import DatasetInfo from './dataset-info'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import {
|
||||
AlignLeft01,
|
||||
AlignRight01,
|
||||
} from '@/app/components/base/icons/src/vender/line/layout'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type IAppDetailNavProps = {
|
||||
iconType?: 'app' | 'dataset' | 'notion'
|
||||
|
|
@ -63,7 +65,16 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
|||
{iconType === 'app' && (
|
||||
<AppInfo expand={expand} />
|
||||
)}
|
||||
{iconType !== 'app' && (
|
||||
{iconType === 'dataset' && (
|
||||
<DatasetInfo
|
||||
name={title}
|
||||
description={desc}
|
||||
isExternal={isExternal}
|
||||
expand={expand}
|
||||
extraInfo={extraInfo && extraInfo(appSidebarExpand)}
|
||||
/>
|
||||
)}
|
||||
{!['app', 'dataset'].includes(iconType) && (
|
||||
<AppBasic
|
||||
mode={appSidebarExpand}
|
||||
iconType={iconType}
|
||||
|
|
@ -75,9 +86,9 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
{!expand && (
|
||||
<div className='mt-1 mx-auto w-6 h-[1px] bg-divider-subtle' />
|
||||
)}
|
||||
<div className='px-4'>
|
||||
<div className={cn('mt-1 mx-auto h-[1px] bg-divider-subtle', !expand && 'w-6')} />
|
||||
</div>
|
||||
<nav
|
||||
className={`
|
||||
grow space-y-1
|
||||
|
|
@ -89,7 +100,6 @@ const AppDetailNav = ({ title, desc, isExternal, icon, icon_background, navigati
|
|||
<NavLink key={index} mode={appSidebarExpand} iconMap={{ selected: item.selectedIcon, normal: item.icon }} name={item.name} href={item.href} />
|
||||
)
|
||||
})}
|
||||
{extraInfo && extraInfo(appSidebarExpand)}
|
||||
</nav>
|
||||
{
|
||||
!isMobile && (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
'use client'
|
||||
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'
|
||||
import type { RelatedApp } from '@/models/datasets'
|
||||
|
||||
type ILikedItemProps = {
|
||||
appStatus?: boolean
|
||||
detail: RelatedApp
|
||||
isMobile: boolean
|
||||
}
|
||||
|
||||
const appTypeMap = {
|
||||
'chat': 'Chatbot',
|
||||
'completion': 'Completion',
|
||||
'agent-chat': 'Agent',
|
||||
'advanced-chat': 'Chatflow',
|
||||
'workflow': 'Workflow',
|
||||
}
|
||||
|
||||
const LikedItem = ({
|
||||
detail,
|
||||
isMobile,
|
||||
}: ILikedItemProps) => {
|
||||
return (
|
||||
<Link className={cn('group/link-item flex items-center justify-between w-full h-8 rounded-lg hover:bg-state-base-hover cursor-pointer px-2', isMobile && 'justify-center')} href={`/app/${detail?.id}/overview`}>
|
||||
<div className='flex items-center'>
|
||||
<div className={cn('relative w-6 h-6 rounded-md')}>
|
||||
<AppIcon size='tiny' iconType={detail.icon_type} icon={detail.icon} background={detail.icon_background} imageUrl={detail.icon_url} />
|
||||
</div>
|
||||
{!isMobile && <div className={cn(' ml-2 truncate system-sm-medium text-text-primary')}>{detail?.name || '--'}</div>}
|
||||
</div>
|
||||
<div className='group-hover/link-item:hidden shrink-0 system-2xs-medium-uppercase text-text-tertiary'>{appTypeMap[detail.mode]}</div>
|
||||
<RiArrowRightUpLine className='hidden group-hover/link-item:block w-4 h-4 text-text-tertiary' />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
type Props = {
|
||||
relatedApps: RelatedApp[]
|
||||
isMobile: boolean
|
||||
}
|
||||
|
||||
const LinkedAppsPanel: FC<Props> = ({
|
||||
relatedApps,
|
||||
isMobile,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className='p-1 w-[320px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg rounded-xl backdrop-blur-[5px]'>
|
||||
<div className='mt-1 mb-0.5 pl-2 system-xs-medium-uppercase text-text-tertiary'>{relatedApps.length || '--'} {t('common.datasetMenus.relatedApp')}</div>
|
||||
{relatedApps.map((item, index) => (
|
||||
<LikedItem key={index} detail={item} isMobile={isMobile} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(LinkedAppsPanel)
|
||||
|
|
@ -14,6 +14,7 @@ export type TooltipProps = {
|
|||
popupContent?: React.ReactNode
|
||||
children?: React.ReactNode
|
||||
popupClassName?: string
|
||||
noDecoration?: boolean
|
||||
offset?: OffsetOptions
|
||||
needsDelay?: boolean
|
||||
asChild?: boolean
|
||||
|
|
@ -27,6 +28,7 @@ const Tooltip: FC<TooltipProps> = ({
|
|||
popupContent,
|
||||
children,
|
||||
popupClassName,
|
||||
noDecoration,
|
||||
offset,
|
||||
asChild = true,
|
||||
needsDelay = false,
|
||||
|
|
@ -96,7 +98,7 @@ const Tooltip: FC<TooltipProps> = ({
|
|||
>
|
||||
{popupContent && (<div
|
||||
className={cn(
|
||||
'relative px-3 py-2 text-xs font-normal text-text-secondary bg-components-tooltip-bg rounded-md shadow-lg break-words',
|
||||
!noDecoration && 'relative px-3 py-2 text-xs font-normal text-text-secondary bg-components-tooltip-bg rounded-md shadow-lg break-words',
|
||||
popupClassName,
|
||||
)}
|
||||
onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ const RetrievalMethodConfig: FC<Props> = ({
|
|||
isActive={
|
||||
value.search_method === RETRIEVE_METHOD.semantic
|
||||
}
|
||||
onClick={() => onChange({
|
||||
onSwitched={() => onChange({
|
||||
...value,
|
||||
search_method: RETRIEVE_METHOD.semantic,
|
||||
})}
|
||||
|
|
@ -85,7 +85,7 @@ const RetrievalMethodConfig: FC<Props> = ({
|
|||
isActive={
|
||||
value.search_method === RETRIEVE_METHOD.fullText
|
||||
}
|
||||
onClick={() => onChange({
|
||||
onSwitched={() => onChange({
|
||||
...value,
|
||||
search_method: RETRIEVE_METHOD.fullText,
|
||||
})}
|
||||
|
|
@ -104,7 +104,7 @@ const RetrievalMethodConfig: FC<Props> = ({
|
|||
title={
|
||||
<div className='flex items-center space-x-1'>
|
||||
<div>{t('dataset.retrieval.hybrid_search.title')}</div>
|
||||
<Badge text={t('dataset.retrieval.hybrid_search.recommend')} className='border-text-accent-secondary text-text-accent-secondary ml-2' uppercase />
|
||||
<Badge text={t('dataset.retrieval.hybrid_search.recommend')!} className='border-text-accent-secondary text-text-accent-secondary ml-2' uppercase />
|
||||
</div>
|
||||
}
|
||||
description={t('dataset.retrieval.hybrid_search.description')} isActive={
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import Textarea from '@/app/components/base/textarea'
|
|||
import Divider from '@/app/components/base/divider'
|
||||
import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
|
||||
import { updateDatasetSetting } from '@/service/datasets'
|
||||
import type { DataSetListResponse } from '@/models/datasets'
|
||||
import { type DataSetListResponse } from '@/models/datasets'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import { type RetrievalConfig } from '@/types/app'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
|
@ -234,6 +234,7 @@ const Form = () => {
|
|||
disable={!currentDataset?.embedding_available}
|
||||
value={indexMethod}
|
||||
onChange={v => setIndexMethod(v)}
|
||||
docForm={currentDataset.doc_form}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { IndexingType } from '../../create/step-two'
|
||||
import s from './index.module.css'
|
||||
import classNames from '@/utils/classnames'
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
import { ChuckingMode } from '@/models/datasets'
|
||||
|
||||
const itemClass = `
|
||||
w-full sm:w-[234px] p-3 rounded-xl bg-gray-25 border border-gray-100 cursor-pointer
|
||||
|
|
@ -15,6 +17,7 @@ type IIndexMethodRadioProps = {
|
|||
onChange: (v?: DataSet['indexing_technique']) => void
|
||||
disable?: boolean
|
||||
itemClassName?: string
|
||||
docForm?: ChuckingMode
|
||||
}
|
||||
|
||||
const IndexMethodRadio = ({
|
||||
|
|
@ -22,6 +25,7 @@ const IndexMethodRadio = ({
|
|||
onChange,
|
||||
disable,
|
||||
itemClassName,
|
||||
docForm,
|
||||
}: IIndexMethodRadioProps) => {
|
||||
const { t } = useTranslation()
|
||||
const options = [
|
||||
|
|
@ -42,29 +46,35 @@ const IndexMethodRadio = ({
|
|||
return (
|
||||
<div className={classNames(s.wrapper, 'flex justify-between w-full flex-wrap gap-y-2')}>
|
||||
{
|
||||
options.map(option => (
|
||||
<div
|
||||
key={option.key}
|
||||
className={classNames(
|
||||
itemClass,
|
||||
itemClassName,
|
||||
s.item,
|
||||
option.key === value && s['item-active'],
|
||||
disable && s.disable,
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!disable)
|
||||
onChange(option.key as DataSet['indexing_technique'])
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center mb-1'>
|
||||
<div className={classNames(s.icon, s[`${option.icon}-icon`])} />
|
||||
<div className='grow text-sm text-gray-900'>{option.text}</div>
|
||||
<div className={classNames(radioClass, s.radio)} />
|
||||
options.map((option) => {
|
||||
const isParentChild = docForm === ChuckingMode.parentChild
|
||||
return (
|
||||
<div
|
||||
key={option.key}
|
||||
className={classNames(
|
||||
itemClass,
|
||||
itemClassName,
|
||||
s.item,
|
||||
option.key === value && s['item-active'],
|
||||
disable && s.disable,
|
||||
isParentChild && option.key === IndexingType.ECONOMICAL && s.disable,
|
||||
)}
|
||||
onClick={() => {
|
||||
if (isParentChild && option.key === IndexingType.ECONOMICAL)
|
||||
return
|
||||
if (!disable)
|
||||
onChange(option.key as DataSet['indexing_technique'])
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center mb-1'>
|
||||
<div className={classNames(s.icon, s[`${option.icon}-icon`])} />
|
||||
<div className='grow text-sm text-gray-900'>{option.text}</div>
|
||||
<div className={classNames(radioClass, s.radio)} />
|
||||
</div>
|
||||
<div className='pl-9 text-xs text-gray-500 leading-[18px]'>{option.desc}</div>
|
||||
</div>
|
||||
<div className='pl-9 text-xs text-gray-500 leading-[18px]'>{option.desc}</div>
|
||||
</div>
|
||||
))
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -474,9 +474,10 @@ const translation = {
|
|||
documents: 'Documents',
|
||||
hitTesting: 'Retrieval Testing',
|
||||
settings: 'Settings',
|
||||
emptyTip: 'The Knowledge has not been associated, please go to the application or plug-in to complete the association.',
|
||||
emptyTip: 'This Knowledge has not been integrated within any application. Please refer to the document for guidance.',
|
||||
viewDoc: 'View documentation',
|
||||
relatedApp: 'linked apps',
|
||||
noRelatedApp: 'No linked apps',
|
||||
},
|
||||
voiceInput: {
|
||||
speaking: 'Speak now...',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const translation = {
|
|||
learnHowToWriteGoodKnowledgeDescription: 'Learn how to write a good knowledge description',
|
||||
externalAPIPanelDescription: 'The external knowledge API is used to connect to a knowledge base outside of Dify and retrieve knowledge from that knowledge base.',
|
||||
externalAPIPanelDocumentation: 'Learn how to create an External Knowledge API',
|
||||
localDocs: 'Local Docs',
|
||||
documentCount: ' docs',
|
||||
wordCount: ' k words',
|
||||
appCount: ' linked apps',
|
||||
|
|
|
|||
|
|
@ -474,9 +474,10 @@ const translation = {
|
|||
documents: '文档',
|
||||
hitTesting: '召回测试',
|
||||
settings: '设置',
|
||||
emptyTip: ' 知识库尚未关联,请前往应用程序或插件完成关联。',
|
||||
emptyTip: '此知识尚未集成到任何应用程序中。请参阅文档以获取指导。',
|
||||
viewDoc: '查看文档',
|
||||
relatedApp: '个关联应用',
|
||||
noRelatedApp: '无关联应用',
|
||||
},
|
||||
voiceInput: {
|
||||
speaking: '现在讲...',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const translation = {
|
|||
learnHowToWriteGoodKnowledgeDescription: '了解如何编写良好的知识库描述',
|
||||
externalAPIPanelDescription: '外部知识库 API 用于连接到 Dify 之外的知识库并从中检索知识。',
|
||||
externalAPIPanelDocumentation: '了解如何创建外部知识库 API',
|
||||
localDocs: '本地文档',
|
||||
documentCount: ' 文档',
|
||||
wordCount: ' 千字符',
|
||||
appCount: ' 关联应用',
|
||||
|
|
@ -119,8 +120,10 @@ const translation = {
|
|||
change: '更改',
|
||||
changeRetrievalMethod: '更改检索方法',
|
||||
},
|
||||
docsFailedNotice: '文档无法被索引',
|
||||
docsFailedNotice: '文档索引失败',
|
||||
retry: '重试',
|
||||
documentsDisabled: '{{num}} 个文档已禁用 - 未活动超过 30 天',
|
||||
enable: '启用',
|
||||
indexingTechnique: {
|
||||
high_quality: '高质量',
|
||||
economy: '经济',
|
||||
|
|
|
|||
Loading…
Reference in New Issue