mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 19:06:51 +08:00
feat: economy hover effect & upload page
This commit is contained in:
parent
f22c608c89
commit
3f6aee6c51
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import type { FC, PropsWithChildren } from 'react'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
@ -10,6 +10,7 @@ import {
|
||||
} from '@remixicon/react'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import { useHover } from 'ahooks'
|
||||
import SettingCog from '../assets/setting-gear-mod.svg'
|
||||
import OrangeEffect from '../assets/option-card-effect-orange.svg'
|
||||
import FamilyMod from '../assets/family-mod.svg'
|
||||
@ -59,6 +60,7 @@ 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 CustomDialog from '@/app/components/base/dialog'
|
||||
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
|
||||
|
||||
const TextLabel: FC<PropsWithChildren> = (props) => {
|
||||
return <label className='text-text-secondary text-xs font-semibold leading-none'>{props.children}</label>
|
||||
@ -559,6 +561,9 @@ const StepTwo = ({
|
||||
score_threshold: 0.5,
|
||||
} as RetrievalConfig)
|
||||
|
||||
const economyDomRef = useRef<HTMLDivElement>(null)
|
||||
const isHoveringEconomy = useHover(economyDomRef)
|
||||
|
||||
return (
|
||||
<div className='flex w-full max-h-full h-full overflow-y-auto'>
|
||||
<div className='relative h-full w-full overflow-y-scroll'>
|
||||
@ -566,7 +571,8 @@ const StepTwo = ({
|
||||
<div className={s.label}>{t('datasetCreation.stepTwo.segmentation')}</div>
|
||||
<div className='max-w-[640px]'>
|
||||
<div className='space-y-4'>
|
||||
<OptionCard
|
||||
{(!datasetId || [ChuckingMode.text, ChuckingMode.qa].includes(docForm))
|
||||
&& <OptionCard
|
||||
title={t('datasetCreation.stepTwo.general')}
|
||||
icon={<Image src={SettingCog} alt={t('datasetCreation.stepTwo.general')} />}
|
||||
activeHeaderClassName='bg-gradient-to-r from-[#EFF0F9] to-[#F9FAFB]'
|
||||
@ -588,6 +594,7 @@ const StepTwo = ({
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
noHighlight={Boolean(datasetId)}
|
||||
>
|
||||
<div className='space-y-4'>
|
||||
<div className='flex gap-3'>
|
||||
@ -663,8 +670,10 @@ const StepTwo = ({
|
||||
)}
|
||||
</>}
|
||||
</div>
|
||||
</OptionCard>
|
||||
<OptionCard
|
||||
</OptionCard>}
|
||||
{
|
||||
(!datasetId || docForm === ChuckingMode.parentChild)
|
||||
&& <OptionCard
|
||||
title={t('datasetCreation.stepTwo.parentChild')}
|
||||
icon={<Image src={FamilyMod} alt={t('datasetCreation.stepTwo.parentChild')} />}
|
||||
effectImg={OrangeEffect.src}
|
||||
@ -683,6 +692,7 @@ const StepTwo = ({
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
noHighlight={Boolean(datasetId)}
|
||||
>
|
||||
<div className='space-y-4'>
|
||||
<div className='space-y-2'>
|
||||
@ -785,7 +795,7 @@ const StepTwo = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</OptionCard>
|
||||
</OptionCard>}
|
||||
</div>
|
||||
</div>
|
||||
<Divider className='my-5' />
|
||||
@ -828,6 +838,13 @@ const StepTwo = ({
|
||||
)}
|
||||
|
||||
{(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.ECONOMICAL)) && (
|
||||
<PortalToFollowElem
|
||||
open={
|
||||
isHoveringEconomy && docForm !== ChuckingMode.text
|
||||
}
|
||||
placement={'top'}
|
||||
>
|
||||
<PortalToFollowElemTrigger>
|
||||
<div
|
||||
className={cn(
|
||||
s.radioItem,
|
||||
@ -838,6 +855,7 @@ const StepTwo = ({
|
||||
docForm !== ChuckingMode.text && s.disabled,
|
||||
)}
|
||||
onClick={changeToEconomicalType}
|
||||
ref={economyDomRef}
|
||||
>
|
||||
<CustomDialog show={isQAConfirmDialogOpen} onClose={() => setIsQAConfirmDialogOpen(false)} className='w-[432px]'>
|
||||
<header className='pt-6 mb-4'>
|
||||
@ -872,6 +890,17 @@ const StepTwo = ({
|
||||
<div className={s.tip}>{t('datasetCreation.stepTwo.economicalTip')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent>
|
||||
<div className='p-3 bg-white text-xs font-medium text-text-secondary rounded-lg shadow-lg'>
|
||||
{
|
||||
docForm === ChuckingMode.qa
|
||||
? t('datasetCreation.stepTwo.notAvailableForQA')
|
||||
: t('datasetCreation.stepTwo.notAvailableForParentChild')
|
||||
}
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
)}
|
||||
</div>
|
||||
{hasSetIndexType && indexType === IndexingType.ECONOMICAL && (
|
||||
|
||||
@ -51,14 +51,15 @@ type OptionCardProps = {
|
||||
actions?: ReactNode
|
||||
effectImg?: string
|
||||
onSwitched?: () => void
|
||||
noHighlight?: boolean
|
||||
} & Omit<ComponentProps<'div'>, 'title'>
|
||||
|
||||
export const OptionCard: FC<OptionCardProps> = (props) => {
|
||||
const { icon, className, title, description, isActive, children, actions, activeHeaderClassName, style, effectImg, onSwitched, onClick, ...rest } = props
|
||||
const { icon, className, title, description, isActive, children, actions, activeHeaderClassName, style, effectImg, onSwitched, onClick, noHighlight, ...rest } = props
|
||||
return <div
|
||||
className={classNames(
|
||||
'rounded-xl',
|
||||
isActive ? 'border-components-option-card-option-selected-border bg-components-panel-bg' : 'border-components-option-card-option-border bg-components-option-card-option-bg',
|
||||
(isActive && !noHighlight) ? 'border-components-option-card-option-selected-border bg-components-panel-bg' : 'border-components-option-card-option-border bg-components-option-card-option-bg',
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
@ -75,7 +76,7 @@ export const OptionCard: FC<OptionCardProps> = (props) => {
|
||||
icon={icon}
|
||||
title={title}
|
||||
description={description}
|
||||
isActive={isActive}
|
||||
isActive={isActive && !noHighlight}
|
||||
activeClassName={activeHeaderClassName}
|
||||
effectImg={effectImg}
|
||||
/>
|
||||
|
||||
@ -169,6 +169,8 @@ const translation = {
|
||||
switch: 'Switch',
|
||||
qaSwitchHighQualityTipTitle: 'Q&A Format Requires High-quality Indexing Method',
|
||||
qaSwitchHighQualityTipContent: 'Currently, only high-quality index method supports Q&A format chunking. Would you like to switch to high-quality mode?',
|
||||
notAvailableForParentChild: 'Not available for Parent-child Index',
|
||||
notAvailableForQA: 'Not available for Q&A Index',
|
||||
},
|
||||
stepThree: {
|
||||
creationTitle: '🎉 Knowledge created',
|
||||
|
||||
@ -169,6 +169,8 @@ const translation = {
|
||||
switch: '切换',
|
||||
qaSwitchHighQualityTipTitle: 'Q&A 格式需要高质量的索引方法',
|
||||
qaSwitchHighQualityTipContent: '目前,只有高质量的索引方法支持 Q&A 格式分块。您要切换到高质量模式吗?',
|
||||
notAvailableForParentChild: '不支持父子索引',
|
||||
notAvailableForQA: '不支持 Q&A 索引',
|
||||
},
|
||||
stepThree: {
|
||||
creationTitle: '🎉 知识库已创建',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user