Commit 37ea862d authored by Joel's avatar Joel

feat: support select dataset

parent 58d06ba0
'use client' 'use client'
import React, { FC, ReactNode } from 'react' import type { FC, ReactNode } from 'react'
import React from 'react'
import cn from 'classnames' import cn from 'classnames'
export interface IFeaturePanelProps { export type IFeaturePanelProps = {
className?: string className?: string
headerIcon: ReactNode headerIcon?: ReactNode
title: ReactNode title: ReactNode
headerRight: ReactNode headerRight: ReactNode
hasHeaderBottomBorder?: boolean hasHeaderBottomBorder?: boolean
...@@ -26,15 +27,17 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({ ...@@ -26,15 +27,17 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({
return ( return (
<div <div
className={cn(className, isFocus && 'border border-[#2D0DEE]', 'rounded-xl bg-gray-50 pt-2 pb-3', noBodySpacing && '!pb-0')} className={cn(className, isFocus && 'border border-[#2D0DEE]', 'rounded-xl bg-gray-50 pt-2 pb-3', noBodySpacing && '!pb-0')}
style={isFocus ? { style={isFocus
boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)', ? {
} : {}} boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)',
}
: {}}
> >
{/* Header */} {/* Header */}
<div className={cn('pb-2 px-3', hasHeaderBottomBorder && 'border-b border-gray-100')}> <div className={cn('pb-2 px-3', hasHeaderBottomBorder && 'border-b border-gray-100')}>
<div className='flex justify-between items-center h-8'> <div className='flex justify-between items-center h-8'>
<div className='flex items-center space-x-1 shrink-0'> <div className='flex items-center space-x-1 shrink-0'>
<div className='flex items-center justify-center w-4 h-4'>{headerIcon}</div> {headerIcon && <div className='flex items-center justify-center w-4 h-4'>{headerIcon}</div>}
<div className='text-sm font-semibold text-gray-800'>{title}</div> <div className='text-sm font-semibold text-gray-800'>{title}</div>
</div> </div>
<div> <div>
......
'use client'
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
import { isEqual } from 'lodash-es'
import produce from 'immer'
import FeaturePanel from '@/app/components/app/configuration/base/feature-panel'
import OperationBtn from '@/app/components/app/configuration/base/operation-btn'
import CardItem from '@/app/components/app/configuration/dataset-config/card-item'
import SelectDataSet from '@/app/components/app/configuration/dataset-config/select-dataset'
import type { DataSet } from '@/models/datasets'
type Props = {
dataSets: DataSet[]
onChange: (data: DataSet[]) => void
}
const DatasetConfig: FC<Props> = ({
dataSets,
onChange,
}) => {
const { t } = useTranslation()
const selectedIds = dataSets.map(item => item.id)
const hasData = dataSets.length > 0
const [isShowSelectDataSet, { setTrue: showSelectDataSet, setFalse: hideSelectDataSet }] = useBoolean(false)
const handleSelect = (data: DataSet[]) => {
if (isEqual(data.map(item => item.id), dataSets.map(item => item.id))) {
hideSelectDataSet()
return
}
if (data.find(item => !item.name)) { // has not loaded selected dataset
const newSelected = produce(data, (draft) => {
data.forEach((item, index) => {
if (!item.name) { // not fetched database
const newItem = dataSets.find(i => i.id === item.id)
if (newItem)
draft[index] = newItem
}
})
})
onChange(newSelected)
}
else {
onChange(data)
}
hideSelectDataSet()
}
const onRemove = (id: string) => {
onChange(dataSets.filter(item => item.id !== id))
}
return (
<FeaturePanel
className='mt-3'
title={t('appDebug.feature.dataSet.title')}
headerRight={<OperationBtn type="add" onClick={showSelectDataSet} />}
hasHeaderBottomBorder={!hasData}
>
{hasData
? (
<div className='max-h-[220px] overflow-y-auto'>
{dataSets.map(item => (
<CardItem
className="mb-2 !w-full"
key={item.id}
config={item}
onRemove={onRemove}
/>
))}
</div>
)
: (
<div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.feature.dataSet.noData')}</div>
)}
{isShowSelectDataSet && (
<SelectDataSet
isShow={isShowSelectDataSet}
onClose={hideSelectDataSet}
selectedIds={selectedIds}
onSelect={handleSelect}
/>
)}
</FeaturePanel>
)
}
export default React.memo(DatasetConfig)
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import DataConfig from './data-config'
export type IConfigProps = { export type IConfigProps = {
className?: string className?: string
plugins: Record<string, boolean> plugins: Record<string, boolean>
onPluginChange: (key: string, value: boolean) => void onPluginChange: (key: string, value: boolean) => void
contexts: any[] dataSets: any[]
onContextChange: (contexts: any[]) => void onDataSetsChange: (contexts: any[]) => void
} }
const Config: FC<IConfigProps> = ({ const Config: FC<IConfigProps> = ({
className, className,
plugins, plugins,
onPluginChange, onPluginChange,
contexts, dataSets,
onContextChange, onDataSetsChange,
}) => { }) => {
return ( return (
<div className={className}> <div className={className}>
Config content <div >
</div>
<DataConfig
dataSets={dataSets}
onChange={onDataSetsChange}
/>
</div> </div>
) )
} }
......
...@@ -34,6 +34,8 @@ import Loading from '@/app/components/base/loading' ...@@ -34,6 +34,8 @@ import Loading from '@/app/components/base/loading'
import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel' import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
import { userInputsFormToPromptVariables } from '@/utils/model-config' import { userInputsFormToPromptVariables } from '@/utils/model-config'
import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import type { DataSet } from '@/models/datasets'
const APP_ID = 'universal-chat' const APP_ID = 'universal-chat'
const isUniversalChat = true const isUniversalChat = true
...@@ -518,7 +520,7 @@ const Main: FC<IMainProps> = () => { ...@@ -518,7 +520,7 @@ const Main: FC<IMainProps> = () => {
[key]: value, [key]: value,
}) })
} }
const [contexts, setContexts] = useState<any[]>([]) const [dataSets, setDateSets] = useState<DataSet[]>([])
if (appUnavailable) if (appUnavailable)
return <AppUnavailable isUnknwonReason={isUnknwonReason} /> return <AppUnavailable isUnknwonReason={isUnknwonReason} />
...@@ -560,8 +562,8 @@ const Main: FC<IMainProps> = () => { ...@@ -560,8 +562,8 @@ const Main: FC<IMainProps> = () => {
configElem={<Init configElem={<Init
plugins={plugins} plugins={plugins}
onPluginChange={handlePluginsChange} onPluginChange={handlePluginsChange}
contexts={contexts} dataSets={dataSets}
onContextChange={setContexts} onDataSetsChange={setDateSets}
/>} />}
chatList={chatList} chatList={chatList}
onSend={handleSend} onSend={handleSend}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment