chore(web): new lint setup (#30020)

Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
Stephen Zhou
2025-12-23 16:58:55 +08:00
committed by GitHub
parent 9701a2994b
commit f2842da397
3356 changed files with 85046 additions and 81278 deletions

View File

@ -1,18 +1,19 @@
import type { Option } from './types'
import { useTranslation } from 'react-i18next'
import {
GeneralChunk,
ParentChildChunk,
QuestionAndAnswer,
} from '@/app/components/base/icons/src/vender/knowledge'
import { EffectColor, type Option } from './types'
import { ChunkingMode } from '@/models/datasets'
import { useTranslation } from 'react-i18next'
import { EffectColor } from './types'
export const useChunkStructure = () => {
const { t } = useTranslation()
const GeneralOption: Option = {
id: ChunkingMode.text,
icon: <GeneralChunk className='size-[18px]' />,
icon: <GeneralChunk className="size-[18px]" />,
iconActiveColor: 'text-util-colors-indigo-indigo-600',
title: 'General',
description: t('datasetCreation.stepTwo.generalTip'),
@ -21,7 +22,7 @@ export const useChunkStructure = () => {
}
const ParentChildOption: Option = {
id: ChunkingMode.parentChild,
icon: <ParentChildChunk className='size-[18px]' />,
icon: <ParentChildChunk className="size-[18px]" />,
iconActiveColor: 'text-util-colors-blue-light-blue-light-500',
title: 'Parent-Child',
description: t('datasetCreation.stepTwo.parentChildTip'),
@ -30,7 +31,7 @@ export const useChunkStructure = () => {
}
const QuestionAnswerOption: Option = {
id: ChunkingMode.qa,
icon: <QuestionAndAnswer className='size-[18px]' />,
icon: <QuestionAndAnswer className="size-[18px]" />,
title: 'Q&A',
description: t('datasetCreation.stepTwo.qaTip'),
}

View File

@ -1,7 +1,7 @@
import type { ChunkingMode } from '@/models/datasets'
import React from 'react'
import { useChunkStructure } from './hooks'
import OptionCard from '../option-card'
import { useChunkStructure } from './hooks'
type ChunkStructureProps = {
chunkStructure: ChunkingMode
@ -15,7 +15,7 @@ const ChunkStructure = ({
} = useChunkStructure()
return (
<div className='flex flex-col gap-y-1'>
<div className="flex flex-col gap-y-1">
{
options.map(option => (
<OptionCard
@ -28,7 +28,7 @@ const ChunkStructure = ({
isActive={chunkStructure === option.id}
effectColor={option.effectColor}
showEffectColor
className='gap-x-1.5 p-3 pr-4'
className="gap-x-1.5 p-3 pr-4"
disabled
/>
))

View File

@ -1,38 +1,38 @@
'use client'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Member } from '@/models/common'
import type { IconInfo } from '@/models/datasets'
import type { AppIconType, RetrievalConfig } from '@/types/app'
import { RiAlertFill } from '@remixicon/react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import PermissionSelector from '../permission-selector'
import IndexMethod from '../index-method'
import RetrievalSettings from '../../external-knowledge-base/create/RetrievalSettings'
import { IndexingType } from '../../create/step-two'
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
import AppIcon from '@/app/components/base/app-icon'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
import Input from '@/app/components/base/input'
import Textarea from '@/app/components/base/textarea'
import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
import { updateDatasetSetting } from '@/service/datasets'
import type { IconInfo } from '@/models/datasets'
import { ChunkingMode, DatasetPermission } from '@/models/datasets'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import type { AppIconType, RetrievalConfig } from '@/types/app'
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Member } from '@/models/common'
import AppIcon from '@/app/components/base/app-icon'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import Divider from '@/app/components/base/divider'
import ChunkStructure from '../chunk-structure'
import Toast from '@/app/components/base/toast'
import { RiAlertFill } from '@remixicon/react'
import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { useDocLink } from '@/context/i18n'
import { ChunkingMode, DatasetPermission } from '@/models/datasets'
import { updateDatasetSetting } from '@/service/datasets'
import { useInvalidDatasetList } from '@/service/knowledge/use-dataset'
import { useMembers } from '@/service/use-common'
import { IndexingType } from '../../create/step-two'
import RetrievalSettings from '../../external-knowledge-base/create/RetrievalSettings'
import ChunkStructure from '../chunk-structure'
import IndexMethod from '../index-method'
import PermissionSelector from '../permission-selector'
import { checkShowMultiModalTip } from '../utils'
const rowClass = 'flex gap-x-1'
@ -68,13 +68,13 @@ const Form = () => {
const [embeddingModel, setEmbeddingModel] = useState<DefaultModel>(
currentDataset?.embedding_model
? {
provider: currentDataset.embedding_model_provider,
model: currentDataset.embedding_model,
}
provider: currentDataset.embedding_model_provider,
model: currentDataset.embedding_model,
}
: {
provider: '',
model: '',
},
provider: '',
model: '',
},
)
const { data: rerankModelList } = useModelList(ModelTypeEnum.rerank)
const { data: embeddingModelList } = useModelList(ModelTypeEnum.textEmbedding)
@ -102,7 +102,7 @@ const Form = () => {
setShowAppIconPicker(false)
}, [])
const handleSettingsChange = useCallback((data: { top_k?: number; score_threshold?: number; score_threshold_enabled?: boolean }) => {
const handleSettingsChange = useCallback((data: { top_k?: number, score_threshold?: number, score_threshold_enabled?: boolean }) => {
if (data.top_k !== undefined)
setTopK(data.top_k)
if (data.score_threshold !== undefined)
@ -209,17 +209,17 @@ const Form = () => {
}, [embeddingModel, rerankModelList, retrievalConfig.reranking_enable, retrievalConfig.reranking_model, embeddingModelList, indexMethod])
return (
<div className='flex w-full flex-col gap-y-4 px-20 py-8 sm:w-[960px]'>
<div className="flex w-full flex-col gap-y-4 px-20 py-8 sm:w-[960px]">
{/* Dataset name and icon */}
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.nameAndIcon')}</div>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.nameAndIcon')}</div>
</div>
<div className='flex grow items-center gap-x-2'>
<div className="flex grow items-center gap-x-2">
<AppIcon
size='small'
size="small"
onClick={handleOpenAppIconPicker}
className='cursor-pointer'
className="cursor-pointer"
iconType={iconInfo.icon_type as AppIconType}
icon={iconInfo.icon}
background={iconInfo.icon_background}
@ -236,12 +236,12 @@ const Form = () => {
{/* Dataset description */}
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.desc')}</div>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.desc')}</div>
</div>
<div className='grow'>
<div className="grow">
<Textarea
disabled={!currentDataset?.embedding_available}
className='resize-none'
className="resize-none"
placeholder={t('datasetSettings.form.descPlaceholder') || ''}
value={description}
onChange={e => setDescription(e.target.value)}
@ -251,9 +251,9 @@ const Form = () => {
{/* Permissions */}
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.permissions')}</div>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.permissions')}</div>
</div>
<div className='grow'>
<div className="grow">
<PermissionSelector
disabled={!currentDataset?.embedding_available || isCurrentWorkspaceDatasetOperator}
permission={permission}
@ -268,28 +268,28 @@ const Form = () => {
currentDataset?.doc_form && (
<>
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
{/* Chunk Structure */}
<div className={rowClass}>
<div className='flex w-[180px] shrink-0 flex-col'>
<div className='system-sm-semibold flex h-8 items-center text-text-secondary'>
<div className="flex w-[180px] shrink-0 flex-col">
<div className="system-sm-semibold flex h-8 items-center text-text-secondary">
{t('datasetSettings.form.chunkStructure.title')}
</div>
<div className='body-xs-regular text-text-tertiary'>
<div className="body-xs-regular text-text-tertiary">
<a
target='_blank'
rel='noopener noreferrer'
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/chunking-and-cleaning-text')}
className='text-text-accent'
className="text-text-accent"
>
{t('datasetSettings.form.chunkStructure.learnMore')}
</a>
{t('datasetSettings.form.chunkStructure.description')}
</div>
</div>
<div className='grow'>
<div className="grow">
<ChunkStructure
chunkStructure={currentDataset?.doc_form}
/>
@ -300,16 +300,16 @@ const Form = () => {
}
{(isShowIndexMethod || indexMethod === 'high_quality') && (
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
)}
{isShowIndexMethod && (
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.indexMethod')}</div>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.indexMethod')}</div>
</div>
<div className='grow'>
<div className="grow">
<IndexMethod
value={indexMethod}
disabled={!currentDataset?.embedding_available}
@ -319,12 +319,12 @@ const Form = () => {
onKeywordNumberChange={setKeywordNumber}
/>
{currentDataset.indexing_technique === IndexingType.ECONOMICAL && indexMethod === IndexingType.QUALIFIED && (
<div className='relative mt-2 flex h-10 items-center gap-x-0.5 overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur px-2 shadow-xs shadow-shadow-shadow-3'>
<div className='absolute left-0 top-0 flex h-full w-full items-center bg-toast-warning-bg opacity-40' />
<div className='p-1'>
<RiAlertFill className='size-4 text-text-warning-secondary' />
<div className="relative mt-2 flex h-10 items-center gap-x-0.5 overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur px-2 shadow-xs shadow-shadow-shadow-3">
<div className="absolute left-0 top-0 flex h-full w-full items-center bg-toast-warning-bg opacity-40" />
<div className="p-1">
<RiAlertFill className="size-4 text-text-warning-secondary" />
</div>
<span className='system-xs-medium text-text-primary'>
<span className="system-xs-medium text-text-primary">
{t('datasetSettings.form.upgradeHighQualityTip')}
</span>
</div>
@ -335,11 +335,11 @@ const Form = () => {
{indexMethod === IndexingType.QUALIFIED && (
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>
<div className="system-sm-semibold text-text-secondary">
{t('datasetSettings.form.embeddingModel')}
</div>
</div>
<div className='grow'>
<div className="grow">
<ModelSelector
defaultModel={embeddingModel}
modelList={embeddingModelList}
@ -351,119 +351,118 @@ const Form = () => {
{/* Retrieval Method Config */}
{currentDataset?.provider === 'external'
? (
<>
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
/>
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.retrievalSetting.title')}</div>
</div>
<RetrievalSettings
topK={topK}
scoreThreshold={scoreThreshold}
scoreThresholdEnabled={scoreThresholdEnabled}
onChange={handleSettingsChange}
isInRetrievalSetting={true}
/>
</div>
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
/>
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.externalKnowledgeAPI')}</div>
</div>
<div className='w-full'>
<div className='flex h-full items-center gap-1 rounded-lg bg-components-input-bg-normal px-3 py-2'>
<ApiConnectionMod className='h-4 w-4 text-text-secondary' />
<div className='system-sm-medium overflow-hidden text-ellipsis text-text-secondary'>
{currentDataset?.external_knowledge_info.external_knowledge_api_name}
</div>
<div className='system-xs-regular text-text-tertiary'>·</div>
<div className='system-xs-regular text-text-tertiary'>
{currentDataset?.external_knowledge_info.external_knowledge_api_endpoint}
</div>
</div>
</div>
</div>
<div className={rowClass}>
<div className={labelClass}>
<div className='system-sm-semibold text-text-secondary'>{t('datasetSettings.form.externalKnowledgeID')}</div>
</div>
<div className='w-full'>
<div className='flex h-full items-center gap-1 rounded-lg bg-components-input-bg-normal px-3 py-2'>
<div className='system-xs-regular text-text-tertiary'>
{currentDataset?.external_knowledge_info.external_knowledge_id}
</div>
</div>
</div>
</div>
</>
)
// eslint-disable-next-line sonarjs/no-nested-conditional
: indexMethod
? (
<>
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
<div className={rowClass}>
<div className={labelClass}>
<div className='flex w-[180px] shrink-0 flex-col'>
<div className='system-sm-semibold flex h-7 items-center pt-1 text-text-secondary'>
{t('datasetSettings.form.retrievalSetting.title')}
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.retrievalSetting.title')}</div>
</div>
<RetrievalSettings
topK={topK}
scoreThreshold={scoreThreshold}
scoreThresholdEnabled={scoreThresholdEnabled}
onChange={handleSettingsChange}
isInRetrievalSetting={true}
/>
</div>
<Divider
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
<div className={rowClass}>
<div className={labelClass}>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.externalKnowledgeAPI')}</div>
</div>
<div className="w-full">
<div className="flex h-full items-center gap-1 rounded-lg bg-components-input-bg-normal px-3 py-2">
<ApiConnectionMod className="h-4 w-4 text-text-secondary" />
<div className="system-sm-medium overflow-hidden text-ellipsis text-text-secondary">
{currentDataset?.external_knowledge_info.external_knowledge_api_name}
</div>
<div className='body-xs-regular text-text-tertiary'>
<a
target='_blank'
rel='noopener noreferrer'
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#setting-the-retrieval-setting', {
'zh-Hans': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#指定检索方式',
'ja-JP': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#検索方法の指定',
})}
className='text-text-accent'
>
{t('datasetSettings.form.retrievalSetting.learnMore')}
</a>
{t('datasetSettings.form.retrievalSetting.description')}
<div className="system-xs-regular text-text-tertiary">·</div>
<div className="system-xs-regular text-text-tertiary">
{currentDataset?.external_knowledge_info.external_knowledge_api_endpoint}
</div>
</div>
</div>
<div className='grow'>
{indexMethod === IndexingType.QUALIFIED
? (
<RetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
showMultiModalTip={showMultiModalTip}
/>
)
: (
<EconomicalRetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)}
</div>
<div className={rowClass}>
<div className={labelClass}>
<div className="system-sm-semibold text-text-secondary">{t('datasetSettings.form.externalKnowledgeID')}</div>
</div>
<div className="w-full">
<div className="flex h-full items-center gap-1 rounded-lg bg-components-input-bg-normal px-3 py-2">
<div className="system-xs-regular text-text-tertiary">
{currentDataset?.external_knowledge_info.external_knowledge_id}
</div>
</div>
</div>
</div>
</>
)
: null
}
// eslint-disable-next-line sonarjs/no-nested-conditional
: indexMethod
? (
<>
<Divider
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
<div className={rowClass}>
<div className={labelClass}>
<div className="flex w-[180px] shrink-0 flex-col">
<div className="system-sm-semibold flex h-7 items-center pt-1 text-text-secondary">
{t('datasetSettings.form.retrievalSetting.title')}
</div>
<div className="body-xs-regular text-text-tertiary">
<a
target="_blank"
rel="noopener noreferrer"
href={docLink('/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#setting-the-retrieval-setting', {
'zh-Hans': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#指定检索方式',
'ja-JP': '/guides/knowledge-base/create-knowledge-and-upload-documents/setting-indexing-methods#検索方法の指定',
})}
className="text-text-accent"
>
{t('datasetSettings.form.retrievalSetting.learnMore')}
</a>
{t('datasetSettings.form.retrievalSetting.description')}
</div>
</div>
</div>
<div className="grow">
{indexMethod === IndexingType.QUALIFIED
? (
<RetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
showMultiModalTip={showMultiModalTip}
/>
)
: (
<EconomicalRetrievalMethodConfig
value={retrievalConfig}
onChange={setRetrievalConfig}
/>
)}
</div>
</div>
</>
)
: null}
<Divider
type='horizontal'
className='my-1 h-px bg-divider-subtle'
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
<div className={rowClass}>
<div className={labelClass} />
<div className='grow'>
<div className="grow">
<Button
className='min-w-24'
variant='primary'
className="min-w-24"
variant="primary"
loading={loading}
disabled={loading}
onClick={handleSave}

View File

@ -1,15 +1,15 @@
'use client'
import { useTranslation } from 'react-i18next'
import { useRef } from 'react'
import { useHover } from 'ahooks'
import { IndexingType } from '../../create/step-two'
import { cn } from '@/utils/classnames'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Economic, HighQuality } from '@/app/components/base/icons/src/vender/knowledge'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { Economic, HighQuality } from '@/app/components/base/icons/src/vender/knowledge'
import { cn } from '@/utils/classnames'
import { IndexingType } from '../../create/step-two'
import { EffectColor } from '../chunk-structure/types'
import OptionCard from '../option-card'
import KeywordNumber from './keyword-number'
@ -43,21 +43,21 @@ const IndexMethod = ({
id={IndexingType.QUALIFIED}
isActive={value === IndexingType.QUALIFIED}
onClick={onChange}
icon={<HighQuality className='size-[18px]' />}
iconActiveColor='text-util-colors-orange-orange-500'
icon={<HighQuality className="size-[18px]" />}
iconActiveColor="text-util-colors-orange-orange-500"
title={t('datasetCreation.stepTwo.qualified')}
description={t('datasetSettings.form.indexMethodHighQualityTip')}
disabled={disabled}
isRecommended
effectColor={EffectColor.orange}
showEffectColor
className='gap-x-2'
className="gap-x-2"
/>
{/* Economy */}
<PortalToFollowElem
open={isHoveringEconomy}
offset={4}
placement={'right'}
placement="right"
>
<PortalToFollowElemTrigger>
<OptionCard
@ -65,15 +65,15 @@ const IndexMethod = ({
id={IndexingType.ECONOMICAL}
isActive={value === IndexingType.ECONOMICAL}
onClick={onChange}
icon={<Economic className='size-[18px]' />}
iconActiveColor='text-util-colors-indigo-indigo-600'
icon={<Economic className="size-[18px]" />}
iconActiveColor="text-util-colors-indigo-indigo-600"
title={t('datasetSettings.form.indexMethodEconomy')}
description={t('datasetSettings.form.indexMethodEconomyTip', { count: keywordNumber })}
disabled={disabled || isEconomyDisabled}
effectColor={EffectColor.indigo}
showEffectColor
showChildren
className='gap-x-2'
className="gap-x-2"
>
<KeywordNumber
keywordNumber={keywordNumber}
@ -82,7 +82,7 @@ const IndexMethod = ({
</OptionCard>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent style={{ zIndex: 60 }}>
<div className='rounded-lg border-components-panel-border bg-components-tooltip-bg p-3 text-xs font-medium text-text-secondary shadow-lg'>
<div className="rounded-lg border-components-panel-border bg-components-tooltip-bg p-3 text-xs font-medium text-text-secondary shadow-lg">
{t('datasetSettings.form.indexMethodChangeToEconomyDisabledTip')}
</div>
</PortalToFollowElemContent>

View File

@ -1,9 +1,9 @@
import { InputNumber } from '@/app/components/base/input-number'
import Slider from '@/app/components/base/slider'
import Tooltip from '@/app/components/base/tooltip'
import { RiQuestionLine } from '@remixicon/react'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { InputNumber } from '@/app/components/base/input-number'
import Slider from '@/app/components/base/slider'
import Tooltip from '@/app/components/base/tooltip'
type KeyWordNumberProps = {
keywordNumber: number
@ -22,26 +22,26 @@ const KeyWordNumber = ({
}, [onKeywordNumberChange])
return (
<div className='flex items-center gap-x-1'>
<div className='flex grow items-center gap-x-0.5'>
<div className='system-xs-medium truncate text-text-secondary'>
<div className="flex items-center gap-x-1">
<div className="flex grow items-center gap-x-0.5">
<div className="system-xs-medium truncate text-text-secondary">
{t('datasetSettings.form.numberOfKeywords')}
</div>
<Tooltip
popupContent='number of keywords'
popupContent="number of keywords"
>
<RiQuestionLine className='h-3.5 w-3.5 text-text-quaternary' />
<RiQuestionLine className="h-3.5 w-3.5 text-text-quaternary" />
</Tooltip>
</div>
<Slider
className='mr-3 w-[206px] shrink-0'
className="mr-3 w-[206px] shrink-0"
value={keywordNumber}
max={50}
onChange={onKeywordNumberChange}
/>
<InputNumber
wrapperClassName='shrink-0 w-12'
type='number'
wrapperClassName="shrink-0 w-12"
type="number"
value={keywordNumber}
onChange={handleInputChange}
/>

View File

@ -1,10 +1,10 @@
import type { ReactNode } from 'react'
import React from 'react'
import { cn } from '@/utils/classnames'
import Badge from '@/app/components/base/badge'
import { useTranslation } from 'react-i18next'
import { EffectColor } from './chunk-structure/types'
import Badge from '@/app/components/base/badge'
import { cn } from '@/utils/classnames'
import { ArrowShape } from '../../base/icons/src/vender/knowledge'
import { EffectColor } from './chunk-structure/types'
const HEADER_EFFECT_MAP: Record<EffectColor, string> = {
[EffectColor.indigo]: 'bg-util-colors-indigo-indigo-600 opacity-50',
@ -57,20 +57,23 @@ const OptionCard = <T,>({
disabled && 'cursor-not-allowed opacity-50',
)}
onClick={() => {
if (isActive || disabled) return
if (isActive || disabled)
return
onClick?.(id)
}}
>
<div className={cn(
'relative flex rounded-t-xl p-2',
className,
)}>
)}
>
{
effectColor && showEffectColor && (
<div className={cn(
'absolute left-[-2px] top-[-2px] h-14 w-14 rounded-full blur-[80px]',
`${HEADER_EFFECT_MAP[effectColor]}`,
)} />
)}
/>
)
}
{
@ -78,19 +81,20 @@ const OptionCard = <T,>({
<div className={cn(
'flex size-6 shrink-0 items-center justify-center text-text-tertiary',
isActive && iconActiveColor,
)}>
)}
>
{icon}
</div>
)
}
<div className='flex grow flex-col gap-y-0.5 py-px'>
<div className='flex items-center gap-x-1'>
<span className='system-sm-medium text-text-secondary'>
<div className="flex grow flex-col gap-y-0.5 py-px">
<div className="flex items-center gap-x-1">
<span className="system-sm-medium text-text-secondary">
{title}
</span>
{
isRecommended && (
<Badge className='h-[18px] border-text-accent-secondary text-text-accent-secondary'>
<Badge className="h-[18px] border-text-accent-secondary text-text-accent-secondary">
{t('datasetCreation.stepTwo.recommend')}
</Badge>
)
@ -98,7 +102,7 @@ const OptionCard = <T,>({
</div>
{
description && (
<div className='system-xs-regular text-text-tertiary'>
<div className="system-xs-regular text-text-tertiary">
{description}
</div>
)
@ -107,8 +111,8 @@ const OptionCard = <T,>({
</div>
{
children && showChildren && (
<div className='relative rounded-b-xl bg-components-panel-bg p-4'>
<ArrowShape className='absolute left-[14px] top-[-11px] size-4 text-components-panel-bg' />
<div className="relative rounded-b-xl bg-components-panel-bg p-4">
<ArrowShape className="absolute left-[14px] top-[-11px] size-4 text-components-panel-bg" />
{children}
</div>
)

View File

@ -1,20 +1,20 @@
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
import React, { useCallback, useMemo, useState } from 'react'
import { useDebounceFn } from 'ahooks'
import type { Member } from '@/models/common'
import { RiArrowDownSLine, RiGroup2Line, RiLock2Line } from '@remixicon/react'
import { useDebounceFn } from 'ahooks'
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Avatar from '@/app/components/base/avatar'
import Input from '@/app/components/base/input'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import Avatar from '@/app/components/base/avatar'
import Input from '@/app/components/base/input'
import { DatasetPermission } from '@/models/datasets'
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
import type { Member } from '@/models/common'
import Item from './permission-item'
import { DatasetPermission } from '@/models/datasets'
import { cn } from '@/utils/classnames'
import MemberItem from './member-item'
import Item from './permission-item'
export type RoleSelectorProps = {
disabled?: boolean
@ -92,25 +92,22 @@ const PermissionSelector = ({
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='bottom-start'
placement="bottom-start"
offset={4}
>
<div className='relative'>
<div className="relative">
<PortalToFollowElemTrigger
onClick={() => !disabled && setOpen(v => !v)}
className='block'
className="block"
>
<div className={cn('flex cursor-pointer items-center gap-x-0.5 rounded-lg bg-components-input-bg-normal px-2 py-1 hover:bg-state-base-hover-alt',
open && 'bg-state-base-hover-alt',
disabled && '!cursor-not-allowed !bg-components-input-bg-disabled hover:!bg-components-input-bg-disabled',
)}>
<div className={cn('flex cursor-pointer items-center gap-x-0.5 rounded-lg bg-components-input-bg-normal px-2 py-1 hover:bg-state-base-hover-alt', open && 'bg-state-base-hover-alt', disabled && '!cursor-not-allowed !bg-components-input-bg-disabled hover:!bg-components-input-bg-disabled')}>
{
isOnlyMe && (
<>
<div className='flex size-6 shrink-0 items-center justify-center'>
<div className="flex size-6 shrink-0 items-center justify-center">
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} size={20} />
</div>
<div className='system-sm-regular grow p-1 text-components-input-text-filled'>
<div className="system-sm-regular grow p-1 text-components-input-text-filled">
{t('datasetSettings.form.permissionsOnlyMe')}
</div>
</>
@ -119,10 +116,10 @@ const PermissionSelector = ({
{
isAllTeamMembers && (
<>
<div className='flex size-6 shrink-0 items-center justify-center'>
<RiGroup2Line className='size-4 text-text-secondary' />
<div className="flex size-6 shrink-0 items-center justify-center">
<RiGroup2Line className="size-4 text-text-secondary" />
</div>
<div className='system-sm-regular grow p-1 text-components-input-text-filled'>
<div className="system-sm-regular grow p-1 text-components-input-text-filled">
{t('datasetSettings.form.permissionsAllMember')}
</div>
</>
@ -131,7 +128,7 @@ const PermissionSelector = ({
{
isPartialMembers && (
<>
<div className='relative flex size-6 shrink-0 items-center justify-center'>
<div className="relative flex size-6 shrink-0 items-center justify-center">
{
selectedMembers.length === 1 && (
<Avatar
@ -147,13 +144,13 @@ const PermissionSelector = ({
<Avatar
avatar={selectedMembers[0].avatar_url}
name={selectedMembers[0].name}
className='absolute left-0 top-0 z-0'
className="absolute left-0 top-0 z-0"
size={16}
/>
<Avatar
avatar={selectedMembers[1].avatar_url}
name={selectedMembers[1].name}
className='absolute bottom-0 right-0 z-10'
className="absolute bottom-0 right-0 z-10"
size={16}
/>
</>
@ -162,7 +159,7 @@ const PermissionSelector = ({
</div>
<div
title={selectedMemberNames}
className='system-sm-regular grow truncate p-1 text-components-input-text-filled'
className="system-sm-regular grow truncate p-1 text-components-input-text-filled"
>
{selectedMemberNames}
</div>
@ -178,13 +175,13 @@ const PermissionSelector = ({
/>
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[1002]'>
<div className='relative w-[480px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg shadow-shadow-shadow-5'>
<div className='p-1'>
<PortalToFollowElemContent className="z-[1002]">
<div className="relative w-[480px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg shadow-shadow-shadow-5">
<div className="p-1">
{/* Only me */}
<Item
leftIcon={
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0' size={24} />
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className="shrink-0" size={24} />
}
text={t('datasetSettings.form.permissionsOnlyMe')}
onClick={onSelectOnlyMe}
@ -192,30 +189,30 @@ const PermissionSelector = ({
/>
{/* All team members */}
<Item
leftIcon={
<div className='flex size-6 shrink-0 items-center justify-center'>
<RiGroup2Line className='size-4 text-text-secondary' />
leftIcon={(
<div className="flex size-6 shrink-0 items-center justify-center">
<RiGroup2Line className="size-4 text-text-secondary" />
</div>
}
)}
text={t('datasetSettings.form.permissionsAllMember')}
onClick={onSelectAllMembers}
isSelected={isAllTeamMembers}
/>
{/* Partial members */}
<Item
leftIcon={
<div className='flex size-6 shrink-0 items-center justify-center'>
<RiLock2Line className='size-4 text-text-secondary' />
leftIcon={(
<div className="flex size-6 shrink-0 items-center justify-center">
<RiLock2Line className="size-4 text-text-secondary" />
</div>
}
)}
text={t('datasetSettings.form.permissionsInvitedMembers')}
onClick={onSelectPartialMembers}
isSelected={isPartialMembers}
/>
</div>
{isPartialMembers && (
<div className='max-h-[360px] overflow-y-auto border-t-[1px] border-divider-regular pb-1 pl-1 pr-1'>
<div className='sticky left-0 top-0 z-10 bg-components-panel-on-panel-item-bg p-2 pb-1'>
<div className="max-h-[360px] overflow-y-auto border-t-[1px] border-divider-regular pb-1 pl-1 pr-1">
<div className="sticky left-0 top-0 z-10 bg-components-panel-on-panel-item-bg p-2 pb-1">
<Input
showLeftIcon
showClearIcon
@ -224,11 +221,11 @@ const PermissionSelector = ({
onClear={() => handleKeywordsChange('')}
/>
</div>
<div className='flex flex-col p-1'>
<div className="flex flex-col p-1">
{showMe && (
<MemberItem
leftIcon={
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0' size={24} />
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className="shrink-0" size={24} />
}
name={userProfile.name}
email={userProfile.email}
@ -239,7 +236,7 @@ const PermissionSelector = ({
{filteredMemberList.map(member => (
<MemberItem
leftIcon={
<Avatar avatar={member.avatar_url} name={member.name} className='shrink-0' size={24} />
<Avatar avatar={member.avatar_url} name={member.name} className="shrink-0" size={24} />
}
name={member.name}
email={member.email}
@ -249,7 +246,7 @@ const PermissionSelector = ({
))}
{
!showMe && filteredMemberList.length === 0 && (
<div className='system-xs-regular flex items-center justify-center whitespace-pre-wrap px-1 py-6 text-center text-text-tertiary'>
<div className="system-xs-regular flex items-center justify-center whitespace-pre-wrap px-1 py-6 text-center text-text-tertiary">
{t('datasetSettings.form.onSearchResults')}
</div>
)

View File

@ -1,7 +1,7 @@
import { cn } from '@/utils/classnames'
import { RiCheckLine } from '@remixicon/react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
type MemberItemProps = {
leftIcon: React.ReactNode
@ -24,18 +24,20 @@ const MemberItem = ({
return (
<div
className='flex cursor-pointer items-center gap-2 rounded-lg py-1 pl-2 pr-[10px] hover:bg-state-base-hover'
className="flex cursor-pointer items-center gap-2 rounded-lg py-1 pl-2 pr-[10px] hover:bg-state-base-hover"
onClick={onClick}
>
{leftIcon}
<div className='grow'>
<div className='system-sm-medium truncate text-text-secondary'>
<div className="grow">
<div className="system-sm-medium truncate text-text-secondary">
{name}
{isMe && <span className='system-xs-regular text-text-tertiary'>
{t('datasetSettings.form.me')}
</span>}
{isMe && (
<span className="system-xs-regular text-text-tertiary">
{t('datasetSettings.form.me')}
</span>
)}
</div>
<div className='system-xs-regular truncate text-text-tertiary'>{email}</div>
<div className="system-xs-regular truncate text-text-tertiary">{email}</div>
</div>
{isSelected && <RiCheckLine className={cn('size-4 shrink-0 text-text-accent', isMe && 'opacity-30')} />}
</div>

View File

@ -1,5 +1,5 @@
import React from 'react'
import { RiCheckLine } from '@remixicon/react'
import React from 'react'
type PermissionItemProps = {
leftIcon: React.ReactNode
@ -16,14 +16,14 @@ const PermissionItem = ({
}: PermissionItemProps) => {
return (
<div
className='flex cursor-pointer items-center gap-x-1 rounded-lg px-2 py-1 hover:bg-state-base-hover'
className="flex cursor-pointer items-center gap-x-1 rounded-lg px-2 py-1 hover:bg-state-base-hover"
onClick={onClick}
>
{leftIcon}
<div className='system-md-regular grow px-1 text-text-secondary'>
<div className="system-md-regular grow px-1 text-text-secondary">
{text}
</div>
{isSelected && <RiCheckLine className='size-4 text-text-accent' />}
{isSelected && <RiCheckLine className="size-4 text-text-accent" />}
</div>
)
}

View File

@ -1,4 +1,5 @@
import { type DefaultModel, type Model, ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { DefaultModel, Model } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { IndexingType } from '../../create/step-two'
type ShowMultiModalTipProps = {