mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-10 03:16:51 +08:00
feat: fe mobile responsive next (#1609)
This commit is contained in:
@@ -15,10 +15,10 @@
|
||||
color: #667085;
|
||||
}
|
||||
.uploader {
|
||||
@apply relative box-border flex justify-center items-center mb-2;
|
||||
@apply relative box-border flex justify-center items-center mb-2 p-3;
|
||||
flex-direction: column;
|
||||
max-width: 640px;
|
||||
height: 80px;
|
||||
min-height: 80px;
|
||||
background: #F9FAFB;
|
||||
border: 1px dashed #EAECF0;
|
||||
border-radius: 12px;
|
||||
|
||||
@@ -234,10 +234,12 @@ const FileUploader = ({
|
||||
/>
|
||||
<div className={cn(s.title, titleClassName)}>{t('datasetCreation.stepOne.uploader.title')}</div>
|
||||
<div ref={dropRef} className={cn(s.uploader, dragging && s.dragging)}>
|
||||
<div className='flex justify-center items-center h-6 mb-2'>
|
||||
<div className='flex justify-center items-center min-h-6 mb-2'>
|
||||
<span className={s.uploadIcon}/>
|
||||
<span>{t('datasetCreation.stepOne.uploader.button')}</span>
|
||||
<label className={s.browse} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
|
||||
<span>
|
||||
{t('datasetCreation.stepOne.uploader.button')}
|
||||
<label className={s.browse} onClick={selectHandle}>{t('datasetCreation.stepOne.uploader.browse')}</label>
|
||||
</span>
|
||||
</div>
|
||||
<div className={s.tip}>{t('datasetCreation.stepOne.uploader.tip', { size: fileUploadConfig.file_size_limit })}</div>
|
||||
{dragging && <div ref={dragRef} className={s.draggingCover}/>}
|
||||
|
||||
@@ -103,7 +103,7 @@ const DatasetUpdateForm = ({ datasetId }: DatasetUpdateFormProps) => {
|
||||
|
||||
return (
|
||||
<div className='flex' style={{ height: 'calc(100vh - 56px)' }}>
|
||||
<div className="flex flex-col w-56 overflow-y-auto bg-white border-r border-gray-200 shrink-0">
|
||||
<div className="flex flex-col w-11 sm:w-56 overflow-y-auto bg-white border-r border-gray-200 shrink-0">
|
||||
<StepsNavBar step={step} datasetId={datasetId} />
|
||||
</div>
|
||||
<div className="grow bg-white">
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.dataSourceTypeList {
|
||||
@apply flex items-center mb-8;
|
||||
}
|
||||
.dataSourceItem {
|
||||
@apply box-border relative shrink-0 flex items-center mr-3 p-3 h-14 bg-white rounded-xl cursor-pointer;
|
||||
border: 0.5px solid #EAECF0;
|
||||
|
||||
@@ -106,7 +106,7 @@ const StepOne = ({
|
||||
<div className={s.form}>
|
||||
{
|
||||
shouldShowDataSourceTypeList && (
|
||||
<div className={s.dataSourceTypeList}>
|
||||
<div className='flex items-center mb-8 flex-wrap gap-y-4'>
|
||||
<div
|
||||
className={cn(
|
||||
s.dataSourceItem,
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn from 'classnames'
|
||||
import EmbeddingProcess from '../embedding-process'
|
||||
|
||||
import s from './index.module.css'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import type { FullDocumentDetail, createDocumentResponse } from '@/models/datasets'
|
||||
|
||||
type StepThreeProps = {
|
||||
@@ -17,9 +18,12 @@ type StepThreeProps = {
|
||||
const StepThree = ({ datasetId, datasetName, indexingType, creationCache }: StepThreeProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
return (
|
||||
<div className='flex w-full h-full'>
|
||||
<div className={'h-full w-full overflow-y-scroll px-16'}>
|
||||
<div className={'h-full w-full overflow-y-scroll px-6 sm:px-16'}>
|
||||
<div className='max-w-[636px]'>
|
||||
{!datasetId && (
|
||||
<>
|
||||
@@ -46,13 +50,13 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache }: Step
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={cn(s.sideTip)}>
|
||||
{!isMobile && <div className={cn(s.sideTip)}>
|
||||
<div className={s.tipCard}>
|
||||
<span className={s.icon}/>
|
||||
<div className={s.title}>{t('datasetCreation.stepThree.sideTipTitle')}</div>
|
||||
<div className={s.content}>{t('datasetCreation.stepThree.sideTipContent')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.pageHeader {
|
||||
@apply px-16;
|
||||
@apply px-16 flex justify-between items-center;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -251,7 +251,7 @@
|
||||
}
|
||||
|
||||
.ruleItem {
|
||||
@apply flex items-center h-7;
|
||||
@apply flex items-center;
|
||||
}
|
||||
|
||||
.formFooter {
|
||||
@@ -382,7 +382,7 @@
|
||||
|
||||
.previewWrap {
|
||||
flex-shrink: 0;
|
||||
width: 524px;
|
||||
max-width: 524px;
|
||||
}
|
||||
|
||||
.previewHeader {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import { RocketLaunchIcon } from '@heroicons/react/24/outline'
|
||||
import cn from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import { groupBy } from 'lodash-es'
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
} from '@/service/datasets'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
|
||||
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
|
||||
import { type RetrievalConfig } from '@/types/app'
|
||||
@@ -37,6 +39,8 @@ import I18n from '@/context/i18n'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { RETRIEVE_METHOD } from '@/types/app'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type ValueOf<T> = T[keyof T]
|
||||
type StepTwoProps = {
|
||||
@@ -84,6 +88,9 @@ const StepTwo = ({
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useContext(I18n)
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const { dataset: currentDataset, mutateDatasetRes } = useDatasetDetailContext()
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
const [scrolled, setScrolled] = useState(false)
|
||||
@@ -467,7 +474,7 @@ const StepTwo = ({
|
||||
useEffect(() => {
|
||||
if (segmentationType === SegmentType.AUTO) {
|
||||
setAutomaticFileIndexingEstimate(null)
|
||||
setShowPreview()
|
||||
!isMobile && setShowPreview()
|
||||
fetchFileIndexingEstimate()
|
||||
setPreviewSwitched(false)
|
||||
}
|
||||
@@ -493,8 +500,23 @@ const StepTwo = ({
|
||||
return (
|
||||
<div className='flex w-full h-full'>
|
||||
<div ref={scrollRef} className='relative h-full w-full overflow-y-scroll'>
|
||||
<div className={cn(s.pageHeader, scrolled && s.fixed)}>{t('datasetCreation.steps.two')}</div>
|
||||
<div className={cn(s.form)}>
|
||||
<div className={cn(s.pageHeader, scrolled && s.fixed, isMobile && '!px-6')}>
|
||||
<span>{t('datasetCreation.steps.two')}</span>
|
||||
{isMobile && (
|
||||
<Button
|
||||
className='border-[0.5px] !h-8 hover:outline hover:outline-[0.5px] hover:outline-gray-300 text-gray-700 font-medium bg-white shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]'
|
||||
onClick={setShowPreview}
|
||||
>
|
||||
<Tooltip selector='data-preview-toggle'>
|
||||
<div className="flex flex-row items-center">
|
||||
<RocketLaunchIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" />
|
||||
<span className="text-[13px]">{t('datasetCreation.stepTwo.previewTitleButton')}</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className={cn(s.form, isMobile && '!px-4')}>
|
||||
<div className={s.label}>{t('datasetCreation.stepTwo.segmentation')}</div>
|
||||
<div className='max-w-[640px]'>
|
||||
<div
|
||||
@@ -554,7 +576,7 @@ const StepTwo = ({
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.formRow}>
|
||||
<div className='w-full'>
|
||||
<div className='w-full flex flex-col gap-1'>
|
||||
<div className={s.label}>{t('datasetCreation.stepTwo.rules')}</div>
|
||||
{rules.map(rule => (
|
||||
<div key={rule.id} className={s.ruleItem}>
|
||||
@@ -574,7 +596,7 @@ const StepTwo = ({
|
||||
</div>
|
||||
<div className={s.label}>{t('datasetCreation.stepTwo.indexMode')}</div>
|
||||
<div className='max-w-[640px]'>
|
||||
<div className='flex items-center gap-3'>
|
||||
<div className='flex items-center gap-3 flex-wrap sm:flex-nowrap'>
|
||||
{(!hasSetIndexType || (hasSetIndexType && indexingType === IndexingType.QUALIFIED)) && (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -797,68 +819,69 @@ const StepTwo = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{(showPreview)
|
||||
? (
|
||||
<div ref={previewScrollRef} className={cn(s.previewWrap, 'relativeh-full overflow-y-scroll border-l border-[#F2F4F7]')}>
|
||||
<div className={cn(s.previewHeader, previewScrolled && `${s.fixed} pb-3`)}>
|
||||
<div className='flex items-center justify-between px-8'>
|
||||
<div className='grow flex items-center'>
|
||||
<div>{t('datasetCreation.stepTwo.previewTitle')}</div>
|
||||
{docForm === DocForm.QA && !previewSwitched && (
|
||||
<Button className='ml-2 !h-[26px] !py-[3px] !px-2 !text-xs !font-medium !text-primary-600' onClick={previewSwitch}>{t('datasetCreation.stepTwo.previewButton')}</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
|
||||
<XMarkIcon className='h-4 w-4'></XMarkIcon>
|
||||
</div>
|
||||
<FloatRightContainer isMobile={isMobile} isOpen={showPreview} onClose={hidePreview} footer={null}>
|
||||
{showPreview && <div ref={previewScrollRef} className={cn(s.previewWrap, 'relative h-full overflow-y-scroll border-l border-[#F2F4F7]')}>
|
||||
<div className={cn(s.previewHeader, previewScrolled && `${s.fixed} pb-3`)}>
|
||||
<div className='flex items-center justify-between px-8'>
|
||||
<div className='grow flex items-center'>
|
||||
<div>{t('datasetCreation.stepTwo.previewTitle')}</div>
|
||||
{docForm === DocForm.QA && !previewSwitched && (
|
||||
<Button className='ml-2 !h-[26px] !py-[3px] !px-2 !text-xs !font-medium !text-primary-600' onClick={previewSwitch}>{t('datasetCreation.stepTwo.previewButton')}</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex items-center justify-center w-6 h-6 cursor-pointer' onClick={hidePreview}>
|
||||
<XMarkIcon className='h-4 w-4'></XMarkIcon>
|
||||
</div>
|
||||
{docForm === DocForm.QA && !previewSwitched && (
|
||||
<div className='px-8 pr-12 text-xs text-gray-500'>
|
||||
<span>{t('datasetCreation.stepTwo.previewSwitchTipStart')}</span>
|
||||
<span className='text-amber-600'>{t('datasetCreation.stepTwo.previewSwitchTipEnd')}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='my-4 px-8 space-y-4'>
|
||||
{previewSwitched && docForm === DocForm.QA && fileIndexingEstimate?.qa_preview && (
|
||||
<>
|
||||
{fileIndexingEstimate?.qa_preview.map((item, index) => (
|
||||
<PreviewItem type={PreviewType.QA} key={item.question} qa={item} index={index + 1} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{(docForm === DocForm.TEXT || !previewSwitched) && fileIndexingEstimate?.preview && (
|
||||
<>
|
||||
{fileIndexingEstimate?.preview.map((item, index) => (
|
||||
<PreviewItem type={PreviewType.TEXT} key={item} content={item} index={index + 1} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{previewSwitched && docForm === DocForm.QA && !fileIndexingEstimate?.qa_preview && (
|
||||
<div className='flex items-center justify-center h-[200px]'>
|
||||
<Loading type='area' />
|
||||
</div>
|
||||
)}
|
||||
{!previewSwitched && !fileIndexingEstimate?.preview && (
|
||||
<div className='flex items-center justify-center h-[200px]'>
|
||||
<Loading type='area' />
|
||||
</div>
|
||||
)}
|
||||
{docForm === DocForm.QA && !previewSwitched && (
|
||||
<div className='px-8 pr-12 text-xs text-gray-500'>
|
||||
<span>{t('datasetCreation.stepTwo.previewSwitchTipStart')}</span>
|
||||
<span className='text-amber-600'>{t('datasetCreation.stepTwo.previewSwitchTipEnd')}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className='my-4 px-8 space-y-4'>
|
||||
{previewSwitched && docForm === DocForm.QA && fileIndexingEstimate?.qa_preview && (
|
||||
<>
|
||||
{fileIndexingEstimate?.qa_preview.map((item, index) => (
|
||||
<PreviewItem type={PreviewType.QA} key={item.question} qa={item} index={index + 1} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{(docForm === DocForm.TEXT || !previewSwitched) && fileIndexingEstimate?.preview && (
|
||||
<>
|
||||
{fileIndexingEstimate?.preview.map((item, index) => (
|
||||
<PreviewItem type={PreviewType.TEXT} key={item} content={item} index={index + 1} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{previewSwitched && docForm === DocForm.QA && !fileIndexingEstimate?.qa_preview && (
|
||||
<div className='flex items-center justify-center h-[200px]'>
|
||||
<Loading type='area' />
|
||||
</div>
|
||||
)}
|
||||
{!previewSwitched && !fileIndexingEstimate?.preview && (
|
||||
<div className='flex items-center justify-center h-[200px]'>
|
||||
<Loading type='area' />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>}
|
||||
{!showPreview && (
|
||||
<div className={cn(s.sideTip)}>
|
||||
<div className={s.tipCard}>
|
||||
<span className={s.icon} />
|
||||
<div className={s.title}>{t('datasetCreation.stepTwo.sideTipTitle')}</div>
|
||||
<div className={s.content}>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP1')}</p>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP2')}</p>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP3')}</p>
|
||||
<p>{t('datasetCreation.stepTwo.sideTipP4')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
: (<div className={cn(s.sideTip)}>
|
||||
<div className={s.tipCard}>
|
||||
<span className={s.icon} />
|
||||
<div className={s.title}>{t('datasetCreation.stepTwo.sideTipTitle')}</div>
|
||||
<div className={s.content}>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP1')}</p>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP2')}</p>
|
||||
<p className='mb-3'>{t('datasetCreation.stepTwo.sideTipP3')}</p>
|
||||
<p>{t('datasetCreation.stepTwo.sideTipP4')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>)}
|
||||
)}
|
||||
</FloatRightContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
background-size: 16px;
|
||||
}
|
||||
.stepList {
|
||||
@apply p-4;
|
||||
@apply p-4 relative;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.stepItem {
|
||||
@apply relative flex justify-items-start pt-3 pr-0 pb-3;
|
||||
@apply relative flex justify-items-start pt-3 pr-0 pb-3 box-content;
|
||||
padding-left: 52px;
|
||||
font-size: 13px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.stepItem.step1::before {
|
||||
|
||||
@@ -3,46 +3,56 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useRouter } from 'next/navigation'
|
||||
|
||||
import cn from 'classnames'
|
||||
import { useCallback } from 'react'
|
||||
import s from './index.module.css'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
|
||||
type IStepsNavBarProps = {
|
||||
step: number,
|
||||
datasetId?: string,
|
||||
step: number
|
||||
datasetId?: string
|
||||
}
|
||||
|
||||
const STEP_T_MAP: Record<number, string> = {
|
||||
1: 'datasetCreation.steps.one',
|
||||
2: 'datasetCreation.steps.two',
|
||||
3: 'datasetCreation.steps.three',
|
||||
}
|
||||
|
||||
const STEP_LIST = [1, 2, 3]
|
||||
|
||||
const StepsNavBar = ({
|
||||
step,
|
||||
datasetId,
|
||||
}: IStepsNavBarProps) => {
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const navBackHandle = () => {
|
||||
if (!datasetId) {
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const navBackHandle = useCallback(() => {
|
||||
if (!datasetId)
|
||||
router.replace('/datasets')
|
||||
} else {
|
||||
else
|
||||
router.replace(`/datasets/${datasetId}/documents`)
|
||||
}
|
||||
}
|
||||
}, [router, datasetId])
|
||||
|
||||
return (
|
||||
<div className='w-full pt-4'>
|
||||
<div className={s.stepsHeader}>
|
||||
<div onClick={navBackHandle} className={s.navBack} />
|
||||
{!datasetId ? t('datasetCreation.steps.header.creation') : t('datasetCreation.steps.header.update')}
|
||||
<div className={cn(s.stepsHeader, isMobile && '!px-0 justify-center')}>
|
||||
<div onClick={navBackHandle} className={cn(s.navBack, isMobile && '!mr-0')} />
|
||||
{!isMobile && (!datasetId ? t('datasetCreation.steps.header.creation') : t('datasetCreation.steps.header.update'))}
|
||||
</div>
|
||||
<div className={cn(s.stepList)}>
|
||||
<div className={cn(s.stepItem, s.step1, step === 1 && s.active, step !== 1 && s.done)}>
|
||||
<div className={cn(s.stepNum)}>{step === 1 ? 1 : ''}</div>
|
||||
<div className={cn(s.stepName)}>{t('datasetCreation.steps.one')}</div>
|
||||
</div>
|
||||
<div className={cn(s.stepItem, s.step2, step === 2 && s.active, step === 3 && s.done)}>
|
||||
<div className={cn(s.stepNum)}>{step !== 3 ? 2 : ''}</div>
|
||||
<div className={cn(s.stepName)}>{t('datasetCreation.steps.two')}</div>
|
||||
</div>
|
||||
<div className={cn(s.stepItem, s.step3, step === 3 && s.active)}>
|
||||
<div className={cn(s.stepNum)}>3</div>
|
||||
<div className={cn(s.stepName)}>{t('datasetCreation.steps.three')}</div>
|
||||
</div>
|
||||
<div className={cn(s.stepList, isMobile && '!p-0')}>
|
||||
{STEP_LIST.map(item => (
|
||||
<div
|
||||
key={item}
|
||||
className={cn(s.stepItem, s[`step${item}`], step === item && s.active, step > item && s.done, isMobile && 'px-0')}
|
||||
>
|
||||
<div className={cn(s.stepNum)}>{item}</div>
|
||||
<div className={cn(s.stepName)}>{isMobile ? '' : t(STEP_T_MAP[item])}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -178,7 +178,7 @@ const SegmentDetailComponent: FC<ISegmentDetailProps> = ({
|
||||
}
|
||||
</div>
|
||||
<div className={cn(s.footer, s.numberInfo)}>
|
||||
<div className='flex items-center'>
|
||||
<div className='flex items-center flex-wrap gap-y-2'>
|
||||
<div className={cn(s.commonIcon, s.typeSquareIcon)} /><span className='mr-8'>{formatNumber(segInfo?.word_count as number)} {t('datasetDocuments.segment.characters')}</span>
|
||||
<div className={cn(s.commonIcon, s.targetIcon)} /><span className='mr-8'>{formatNumber(segInfo?.hit_count as number)} {t('datasetDocuments.segment.hitCount')}</span>
|
||||
<div className={cn(s.commonIcon, s.bezierCurveIcon)} /><span className={s.hashText}>{t('datasetDocuments.segment.vectorHash')}{segInfo?.index_node_hash}</span>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@apply text-gray-900 font-medium text-base flex-1;
|
||||
}
|
||||
.docSearchWrapper {
|
||||
@apply sticky w-full h-10 -top-3 bg-white flex items-center mb-3 justify-between z-10;
|
||||
@apply sticky w-full py-1 -top-3 bg-white flex items-center mb-3 justify-between z-10 flex-wrap gap-y-1;
|
||||
}
|
||||
.listContainer {
|
||||
height: calc(100% - 3.25rem);
|
||||
@@ -18,7 +18,7 @@
|
||||
@apply grid gap-4 grid-cols-3 min-w-[902px] last:mb-[30px];
|
||||
}
|
||||
.segWrapper {
|
||||
@apply box-border h-[180px] min-w-[290px] bg-gray-50 px-4 pt-4 flex flex-col text-opacity-50 rounded-xl border border-transparent hover:border-gray-200 hover:shadow-lg hover:cursor-pointer hover:bg-white;
|
||||
@apply box-border h-[180px] w-full xl:min-w-[290px] bg-gray-50 px-4 pt-4 flex flex-col text-opacity-50 rounded-xl border border-transparent hover:border-gray-200 hover:shadow-lg hover:cursor-pointer hover:bg-white;
|
||||
}
|
||||
.segTitleWrapper {
|
||||
@apply flex items-center justify-between;
|
||||
@@ -48,7 +48,7 @@
|
||||
white-space: pre-line;
|
||||
}
|
||||
.footer {
|
||||
@apply flex items-center justify-between box-border border-t-gray-200 border-t-[0.5px] pt-3 mt-4;
|
||||
@apply flex items-center justify-between box-border border-t-gray-200 border-t-[0.5px] pt-3 mt-4 flex-wrap gap-y-2;
|
||||
}
|
||||
.numberInfo {
|
||||
@apply text-gray-500 text-xs font-medium;
|
||||
|
||||
@@ -23,6 +23,8 @@ import { checkSegmentBatchImportProgress, fetchDocumentDetail, segmentBatchImpor
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
import type { DocForm } from '@/models/datasets'
|
||||
import { useDatasetDetailContext } from '@/context/dataset-detail'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
|
||||
export const DocumentContext = createContext<{ datasetId?: string; documentId?: string; docForm: string }>({ docForm: '' })
|
||||
|
||||
@@ -50,10 +52,14 @@ type Props = {
|
||||
const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
|
||||
const router = useRouter()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const { notify } = useContext(ToastContext)
|
||||
const { dataset } = useDatasetDetailContext()
|
||||
const embeddingAvailable = !!dataset?.embedding_available
|
||||
const [showMetadata, setShowMetadata] = useState(true)
|
||||
const [showMetadata, setShowMetadata] = useState(!isMobile)
|
||||
const [newSegmentModalVisible, setNewSegmentModalVisible] = useState(false)
|
||||
const [batchModalVisible, setBatchModalVisible] = useState(false)
|
||||
const [importStatus, setImportStatus] = useState<ProcessStatus | string>()
|
||||
@@ -124,44 +130,46 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
|
||||
return (
|
||||
<DocumentContext.Provider value={{ datasetId, documentId, docForm: documentDetail?.doc_form || '' }}>
|
||||
<div className='flex flex-col h-full'>
|
||||
<div className='flex h-16 border-b-gray-100 border-b items-center p-4'>
|
||||
<div onClick={backToPrev} className={'rounded-full w-8 h-8 flex justify-center items-center border-gray-100 cursor-pointer border hover:border-gray-300 shadow-[0px_12px_16px_-4px_rgba(16,24,40,0.08),0px_4px_6px_-2px_rgba(16,24,40,0.03)]'}>
|
||||
<div className='flex min-h-16 border-b-gray-100 border-b items-center p-4 justify-between flex-wrap gap-y-2'>
|
||||
<div onClick={backToPrev} className={'shrink-0 rounded-full w-8 h-8 flex justify-center items-center border-gray-100 cursor-pointer border hover:border-gray-300 shadow-[0px_12px_16px_-4px_rgba(16,24,40,0.08),0px_4px_6px_-2px_rgba(16,24,40,0.03)]'}>
|
||||
<ArrowLeftIcon className='text-primary-600 fill-current stroke-current h-4 w-4' />
|
||||
</div>
|
||||
<Divider className='!h-4' type='vertical' />
|
||||
<DocumentTitle extension={documentDetail?.data_source_info?.upload_file?.extension} name={documentDetail?.name} />
|
||||
<StatusItem status={documentDetail?.display_status || 'available'} scene='detail' errorMessage={documentDetail?.error || ''} />
|
||||
{embeddingAvailable && documentDetail && !documentDetail.archived && (
|
||||
<SegmentAdd
|
||||
importStatus={importStatus}
|
||||
clearProcessStatus={resetProcessStatus}
|
||||
showNewSegmentModal={showNewSegmentModal}
|
||||
showBatchModal={showBatchModal}
|
||||
<div className='flex items-center flex-wrap gap-y-2'>
|
||||
<StatusItem status={documentDetail?.display_status || 'available'} scene='detail' errorMessage={documentDetail?.error || ''} />
|
||||
{embeddingAvailable && documentDetail && !documentDetail.archived && (
|
||||
<SegmentAdd
|
||||
importStatus={importStatus}
|
||||
clearProcessStatus={resetProcessStatus}
|
||||
showNewSegmentModal={showNewSegmentModal}
|
||||
showBatchModal={showBatchModal}
|
||||
/>
|
||||
)}
|
||||
<OperationAction
|
||||
scene='detail'
|
||||
embeddingAvailable={embeddingAvailable}
|
||||
detail={{
|
||||
enabled: documentDetail?.enabled || false,
|
||||
archived: documentDetail?.archived || false,
|
||||
id: documentId,
|
||||
data_source_type: documentDetail?.data_source_type || '',
|
||||
doc_form: documentDetail?.doc_form || '',
|
||||
}}
|
||||
datasetId={datasetId}
|
||||
onUpdate={handleOperate}
|
||||
className='!w-[216px]'
|
||||
/>
|
||||
)}
|
||||
<OperationAction
|
||||
scene='detail'
|
||||
embeddingAvailable={embeddingAvailable}
|
||||
detail={{
|
||||
enabled: documentDetail?.enabled || false,
|
||||
archived: documentDetail?.archived || false,
|
||||
id: documentId,
|
||||
data_source_type: documentDetail?.data_source_type || '',
|
||||
doc_form: documentDetail?.doc_form || '',
|
||||
}}
|
||||
datasetId={datasetId}
|
||||
onUpdate={handleOperate}
|
||||
className='!w-[216px]'
|
||||
/>
|
||||
<button
|
||||
className={cn(style.layoutRightIcon, showMetadata ? style.iconShow : style.iconClose)}
|
||||
onClick={() => setShowMetadata(!showMetadata)}
|
||||
/>
|
||||
<button
|
||||
className={cn(style.layoutRightIcon, showMetadata ? style.iconShow : style.iconClose)}
|
||||
onClick={() => setShowMetadata(!showMetadata)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-row flex-1' style={{ height: 'calc(100% - 4rem)' }}>
|
||||
{isDetailLoading
|
||||
? <Loading type='app' />
|
||||
: <div className={`box-border h-full w-full overflow-y-scroll ${embedding ? 'py-12 px-16' : 'pb-[30px] pt-3 px-6'}`}>
|
||||
: <div className={`h-full w-full flex flex-col ${embedding ? 'px-6 py-3 sm:py-12 sm:px-16' : 'pb-[30px] pt-3 px-6'}`}>
|
||||
{embedding
|
||||
? <Embedding detail={documentDetail} detailUpdate={detailMutate} />
|
||||
: <Completed
|
||||
@@ -174,11 +182,13 @@ const DocumentDetail: FC<Props> = ({ datasetId, documentId }) => {
|
||||
}
|
||||
</div>
|
||||
}
|
||||
{showMetadata && <Metadata
|
||||
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as any}
|
||||
loading={isMetadataLoading}
|
||||
onUpdate={metadataMutate}
|
||||
/>}
|
||||
<FloatRightContainer showClose isOpen={showMetadata} onClose={() => setShowMetadata(false)} isMobile={isMobile} panelClassname='!justify-start' footer={null}>
|
||||
<Metadata
|
||||
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as any}
|
||||
loading={isMetadataLoading}
|
||||
onUpdate={metadataMutate}
|
||||
/>
|
||||
</FloatRightContainer>
|
||||
</div>
|
||||
<BatchModal
|
||||
isShow={batchModalVisible}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.main {
|
||||
@apply w-96 xl:w-[360px] flex-shrink-0 px-6 py-5 overflow-y-auto border-l-gray-100 border-l;
|
||||
@apply w-full sm:w-96 xl:w-[360px] flex-shrink-0 p-0 sm:px-6 sm:py-5 overflow-y-auto border-none sm:border-l-gray-100 sm:border-l;
|
||||
}
|
||||
.operationWrapper {
|
||||
@apply flex flex-col items-center gap-4 mt-7 mb-8;
|
||||
|
||||
@@ -198,7 +198,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
<p className={s.desc}>{t('datasetDocuments.list.desc')}</p>
|
||||
</div>
|
||||
<div className='flex flex-col px-6 py-4 flex-1'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center justify-between flex-wrap gap-y-2 '>
|
||||
<Input
|
||||
showPrefix
|
||||
wrapperClassName='!w-[200px]'
|
||||
@@ -207,7 +207,7 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
value={searchValue}
|
||||
/>
|
||||
{embeddingAvailable && (
|
||||
<Button type='primary' onClick={routeToDocCreate} className='!h-8 !text-[13px]'>
|
||||
<Button type='primary' onClick={routeToDocCreate} className='!h-8 !text-[13px] !shrink-0'>
|
||||
<PlusIcon className='h-4 w-4 mr-2 stroke-current' />
|
||||
{isDataSourceNotion && t('datasetDocuments.list.addPages')}
|
||||
{!isDataSourceNotion && t('datasetDocuments.list.addFile')}
|
||||
|
||||
@@ -316,8 +316,8 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<table className={`w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}>
|
||||
<div className='w-full h-full overflow-x-auto'>
|
||||
<table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}>
|
||||
<thead className="h-8 leading-8 border-b border-gray-200 text-gray-500 font-medium text-xs uppercase">
|
||||
<tr>
|
||||
<td className='w-12'>#</td>
|
||||
@@ -380,7 +380,7 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ const HitDetail: FC<IHitDetailProps> = ({ segInfo, vectorInfo }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={'flex flex-row'}>
|
||||
<div className="flex-1 bg-gray-25 p-6">
|
||||
<div className='flex flex-row overflow-x-auto'>
|
||||
<div className="flex-1 bg-gray-25 p-6 min-w-[300px]">
|
||||
<div className="flex items-center">
|
||||
<SegmentIndexTag
|
||||
positionId={segInfo?.position || ''}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useSWR from 'swr'
|
||||
import { omit } from 'lodash-es'
|
||||
import cn from 'classnames'
|
||||
import dayjs from 'dayjs'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import SegmentCard from '../documents/detail/completed/SegmentCard'
|
||||
import docStyle from '../documents/detail/completed/style.module.css'
|
||||
@@ -17,9 +18,11 @@ import type { HitTestingResponse, HitTesting as HitTestingType } from '@/models/
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
import { fetchTestingRecords } from '@/service/datasets'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import type { RetrievalConfig } from '@/types/app'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
|
||||
const limit = 10
|
||||
|
||||
@@ -39,6 +42,10 @@ const RecordsEmpty: FC = () => {
|
||||
|
||||
const HitTesting: FC<Props> = ({ datasetId }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
||||
const [hitResult, setHitResult] = useState<HitTestingResponse | undefined>() // 初始化记录为空数组
|
||||
const [submitLoading, setSubmitLoading] = useState(false)
|
||||
const [currParagraph, setCurrParagraph] = useState<{ paraInfo?: HitTestingType; showModal: boolean }>({ showModal: false })
|
||||
@@ -63,6 +70,11 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
|
||||
|
||||
const [retrievalConfig, setRetrievalConfig] = useState(currentDataset?.retrieval_model_dict as RetrievalConfig)
|
||||
const [isShowModifyRetrievalModal, setIsShowModifyRetrievalModal] = useState(false)
|
||||
const [isShowRightPanel, { setTrue: showRightPanel, setFalse: hideRightPanel, set: setShowRightPanel }] = useBoolean(!isMobile)
|
||||
|
||||
useEffect(() => {
|
||||
setShowRightPanel(!isMobile)
|
||||
}, [isMobile, setShowRightPanel])
|
||||
|
||||
return (
|
||||
<div className={s.container}>
|
||||
@@ -74,6 +86,7 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
|
||||
<Textarea
|
||||
datasetId={datasetId}
|
||||
setHitResult={setHitResult}
|
||||
onSubmit={showRightPanel}
|
||||
onUpdateList={recordsMutate}
|
||||
loading={submitLoading}
|
||||
setLoading={setSubmitLoading}
|
||||
@@ -131,53 +144,56 @@ const HitTesting: FC<Props> = ({ datasetId }: Props) => {
|
||||
<RecordsEmpty />
|
||||
)}
|
||||
</div>
|
||||
<div className={s.rightDiv}>
|
||||
{submitLoading
|
||||
? <div className={s.cardWrapper}>
|
||||
<SegmentCard
|
||||
loading={true}
|
||||
scene='hitTesting'
|
||||
className='h-[216px]'
|
||||
/>
|
||||
<SegmentCard
|
||||
loading={true}
|
||||
scene='hitTesting'
|
||||
className='h-[216px]'
|
||||
/>
|
||||
</div>
|
||||
: !hitResult?.records.length
|
||||
? (
|
||||
<div className='h-full flex flex-col justify-center items-center'>
|
||||
<div className={cn(docStyle.commonIcon, docStyle.targetIcon, '!bg-gray-200 !h-14 !w-14')} />
|
||||
<div className='text-gray-300 text-[13px] mt-3'>
|
||||
{t('datasetHitTesting.hit.emptyTip')}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<div className='text-gray-600 font-semibold mb-4'>{t('datasetHitTesting.hit.title')}</div>
|
||||
<div className='overflow-auto flex-1'>
|
||||
<div className={s.cardWrapper}>
|
||||
{hitResult?.records.map((record, idx) => {
|
||||
return <SegmentCard
|
||||
key={idx}
|
||||
loading={false}
|
||||
detail={record.segment as any}
|
||||
score={record.score}
|
||||
scene='hitTesting'
|
||||
className='h-[216px] mb-4'
|
||||
onClick={() => onClickCard(record as any)}
|
||||
/>
|
||||
})}
|
||||
<FloatRightContainer panelClassname='!justify-start !overflow-y-auto' showClose isMobile={isMobile} isOpen={isShowRightPanel} onClose={hideRightPanel} footer={null}>
|
||||
<div className={cn(s.rightDiv, 'p-0 sm:px-8 sm:pt-[42px] sm:pb-[26px]')}>
|
||||
{submitLoading
|
||||
? <div className={s.cardWrapper}>
|
||||
<SegmentCard
|
||||
loading={true}
|
||||
scene='hitTesting'
|
||||
className='h-[216px]'
|
||||
/>
|
||||
<SegmentCard
|
||||
loading={true}
|
||||
scene='hitTesting'
|
||||
className='h-[216px]'
|
||||
/>
|
||||
</div>
|
||||
: !hitResult?.records.length
|
||||
? (
|
||||
<div className='h-full flex flex-col justify-center items-center'>
|
||||
<div className={cn(docStyle.commonIcon, docStyle.targetIcon, '!bg-gray-200 !h-14 !w-14')} />
|
||||
<div className='text-gray-300 text-[13px] mt-3'>
|
||||
{t('datasetHitTesting.hit.emptyTip')}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<div className='text-gray-600 font-semibold mb-4'>{t('datasetHitTesting.hit.title')}</div>
|
||||
<div className='overflow-auto flex-1'>
|
||||
<div className={s.cardWrapper}>
|
||||
{hitResult?.records.map((record, idx) => {
|
||||
return <SegmentCard
|
||||
key={idx}
|
||||
loading={false}
|
||||
detail={record.segment as any}
|
||||
score={record.score}
|
||||
scene='hitTesting'
|
||||
className='h-[216px] mb-4'
|
||||
onClick={() => onClickCard(record as any)}
|
||||
/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</FloatRightContainer>
|
||||
<Modal
|
||||
className='!max-w-[960px] !p-0'
|
||||
wrapperClassName='!z-40'
|
||||
closable
|
||||
onClose={() => setCurrParagraph({ showModal: false })}
|
||||
isShow={currParagraph.showModal}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.container {
|
||||
@apply flex h-full w-full relative;
|
||||
@apply flex h-full w-full relative overflow-y-auto;
|
||||
}
|
||||
.container > div {
|
||||
@apply flex-1 h-full;
|
||||
@@ -8,7 +8,7 @@
|
||||
@apply border-r border-gray-100 px-6 py-3 flex flex-col;
|
||||
}
|
||||
.rightDiv {
|
||||
@apply px-8 pt-[42px] pb-[26px] flex flex-col;
|
||||
@apply flex flex-col;
|
||||
}
|
||||
.titleWrapper {
|
||||
@apply flex flex-col justify-center gap-1 mb-5;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { FC } from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import cn from 'classnames'
|
||||
@@ -13,7 +12,7 @@ import { hitTesting } from '@/service/datasets'
|
||||
import { asyncRunSafe } from '@/utils'
|
||||
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
|
||||
|
||||
type Props = {
|
||||
type TextAreaWithButtonIProps = {
|
||||
datasetId: string
|
||||
onUpdateList: () => void
|
||||
setHitResult: (res: HitTestingResponse) => void
|
||||
@@ -24,9 +23,10 @@ type Props = {
|
||||
onClickRetrievalMethod: () => void
|
||||
retrievalConfig: RetrievalConfig
|
||||
isEconomy: boolean
|
||||
onSubmit?: () => void
|
||||
}
|
||||
|
||||
const TextAreaWithButton: FC<Props> = ({
|
||||
const TextAreaWithButton = ({
|
||||
datasetId,
|
||||
onUpdateList,
|
||||
setHitResult,
|
||||
@@ -37,7 +37,8 @@ const TextAreaWithButton: FC<Props> = ({
|
||||
onClickRetrievalMethod,
|
||||
retrievalConfig,
|
||||
isEconomy,
|
||||
}) => {
|
||||
onSubmit: _onSubmit,
|
||||
}: TextAreaWithButtonIProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { indexingTechnique } = useContext(DatasetDetailContext)
|
||||
|
||||
@@ -55,6 +56,7 @@ const TextAreaWithButton: FC<Props> = ({
|
||||
onUpdateList?.()
|
||||
}
|
||||
setLoading(false)
|
||||
_onSubmit && _onSubmit()
|
||||
}
|
||||
|
||||
const retrievalMethod = isEconomy ? RETRIEVE_METHOD.invertedIndex : retrievalConfig.search_method
|
||||
|
||||
@@ -24,13 +24,13 @@ import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { ensureRerankModelSelected, isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
|
||||
const rowClass = `
|
||||
flex justify-between py-4
|
||||
flex justify-between py-4 flex-wrap gap-y-2
|
||||
`
|
||||
const labelClass = `
|
||||
flex items-center w-[168px] h-9
|
||||
`
|
||||
const inputClass = `
|
||||
w-[480px] px-3 bg-gray-100 text-sm text-gray-800 rounded-lg outline-none appearance-none
|
||||
w-full max-w-[480px] px-3 bg-gray-100 text-sm text-gray-800 rounded-lg outline-none appearance-none
|
||||
`
|
||||
const useInitialValue: <T>(depend: T, dispatch: Dispatch<T>) => void = (depend, dispatch) => {
|
||||
useEffect(() => {
|
||||
@@ -118,14 +118,14 @@ const Form = () => {
|
||||
useInitialValue<DataSet['indexing_technique'] | undefined>(currentDataset?.indexing_technique, setIndexMethod)
|
||||
|
||||
return (
|
||||
<div className='w-[800px] px-16 py-6'>
|
||||
<div className='w-full sm:w-[800px] p-4 sm:px-16 sm:py-6'>
|
||||
<div className={rowClass}>
|
||||
<div className={labelClass}>
|
||||
<div>{t('datasetSettings.form.name')}</div>
|
||||
</div>
|
||||
<input
|
||||
disabled={!currentDataset?.embedding_available}
|
||||
className={cn(inputClass, !currentDataset?.embedding_available && 'opacity-60')}
|
||||
className={cn(inputClass, !currentDataset?.embedding_available && 'opacity-60', 'h-9')}
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
/>
|
||||
@@ -134,7 +134,7 @@ const Form = () => {
|
||||
<div className={labelClass}>
|
||||
<div>{t('datasetSettings.form.desc')}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className='w-full max-w-[480px]'>
|
||||
<textarea
|
||||
disabled={!currentDataset?.embedding_available}
|
||||
className={cn(`${inputClass} block mb-2 h-[120px] py-2 resize-none`, !currentDataset?.embedding_available && 'opacity-60')}
|
||||
@@ -152,7 +152,7 @@ const Form = () => {
|
||||
<div className={labelClass}>
|
||||
<div>{t('datasetSettings.form.permissions')}</div>
|
||||
</div>
|
||||
<div className='w-[480px]'>
|
||||
<div className='w-full sm:w-[480px]'>
|
||||
<PermissionsRadio
|
||||
disable={!currentDataset?.embedding_available}
|
||||
value={permission}
|
||||
@@ -167,7 +167,7 @@ const Form = () => {
|
||||
<div className={labelClass}>
|
||||
<div>{t('datasetSettings.form.indexMethod')}</div>
|
||||
</div>
|
||||
<div className='w-[480px]'>
|
||||
<div className='w-full sm:w-[480px]'>
|
||||
<IndexMethodRadio
|
||||
disable={!currentDataset?.embedding_available}
|
||||
value={indexMethod}
|
||||
|
||||
@@ -5,7 +5,7 @@ import s from './index.module.css'
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
|
||||
const itemClass = `
|
||||
w-[234px] p-3 rounded-xl bg-gray-25 border border-gray-100 cursor-pointer
|
||||
w-full sm:w-[234px] p-3 rounded-xl bg-gray-25 border border-gray-100 cursor-pointer
|
||||
`
|
||||
const radioClass = `
|
||||
w-4 h-4 border-[2px] border-gray-200 rounded-full
|
||||
@@ -40,7 +40,7 @@ const IndexMethodRadio = ({
|
||||
]
|
||||
|
||||
return (
|
||||
<div className={classNames(s.wrapper, 'flex justify-between w-full')}>
|
||||
<div className={classNames(s.wrapper, 'flex justify-between w-full flex-wrap gap-y-2')}>
|
||||
{
|
||||
options.map(option => (
|
||||
<div
|
||||
|
||||
@@ -5,7 +5,7 @@ import s from './index.module.css'
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
|
||||
const itemClass = `
|
||||
flex items-center w-[234px] h-12 px-3 rounded-xl bg-gray-25 border border-gray-100 cursor-pointer
|
||||
flex items-center w-full sm:w-[234px] h-12 px-3 rounded-xl bg-gray-25 border border-gray-100 cursor-pointer
|
||||
`
|
||||
const radioClass = `
|
||||
w-4 h-4 border-[2px] border-gray-200 rounded-full
|
||||
@@ -36,7 +36,7 @@ const PermissionsRadio = ({
|
||||
]
|
||||
|
||||
return (
|
||||
<div className={classNames(s.wrapper, 'flex justify-between w-full')}>
|
||||
<div className={classNames(s.wrapper, 'flex justify-between w-full flex-wrap gap-y-2')}>
|
||||
{
|
||||
options.map(option => (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user