Feat: dark mode of app configure (#13010)
This commit is contained in:
parent
899df30bf6
commit
c966bf1474
@ -143,22 +143,19 @@ const AppPublisher = ({
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[11]'>
|
||||
<div className='w-[336px] bg-white rounded-2xl border-[0.5px] border-gray-200 shadow-xl'>
|
||||
<div className='w-[336px] bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl'>
|
||||
<div className='p-4 pt-3'>
|
||||
<div className='flex items-center h-6 text-xs font-medium text-gray-500 uppercase'>
|
||||
<div className='flex items-center h-6 system-xs-medium-uppercase text-text-tertiary'>
|
||||
{publishedAt ? t('workflow.common.latestPublished') : t('workflow.common.currentDraftUnpublished')}
|
||||
</div>
|
||||
{publishedAt
|
||||
? (
|
||||
<div className='flex justify-between items-center h-[18px]'>
|
||||
<div className='flex items-center mt-[3px] mb-[3px] leading-[18px] text-[13px] font-medium text-gray-700'>
|
||||
<div className='flex items-center mt-[3px] mb-[3px] leading-[18px] text-[13px] font-medium text-text-secondary'>
|
||||
{t('workflow.common.publishedAt')} {formatTimeFromNow(publishedAt)}
|
||||
</div>
|
||||
<Button
|
||||
className={`
|
||||
ml-2 px-2 text-primary-600
|
||||
${published && 'text-primary-300 border-gray-100'}
|
||||
`}
|
||||
variant='secondary-accent'
|
||||
size='small'
|
||||
onClick={handleRestore}
|
||||
disabled={published}
|
||||
@ -168,7 +165,7 @@ const AppPublisher = ({
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className='flex items-center h-[18px] leading-[18px] text-[13px] font-medium text-gray-700'>
|
||||
<div className='flex items-center h-[18px] leading-[18px] text-[13px] font-medium text-text-secondary'>
|
||||
{t('workflow.common.autoSaved')} · {Boolean(draftUpdatedAt) && formatTimeFromNow(draftUpdatedAt!)}
|
||||
</div>
|
||||
)}
|
||||
@ -196,7 +193,7 @@ const AppPublisher = ({
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className='p-4 pt-3 border-t-[0.5px] border-t-black/5'>
|
||||
<div className='p-4 pt-3 border-t-[0.5px] border-divider-regular'>
|
||||
<SuggestedAction disabled={!publishedAt} link={appURL} icon={<PlayCircle />}>{t('workflow.common.runApp')}</SuggestedAction>
|
||||
{appDetail?.mode === 'workflow'
|
||||
? (
|
||||
|
@ -77,21 +77,21 @@ const PublishWithMultipleModel: FC<PublishWithMultipleModelProps> = ({
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='mt-1 w-[288px] z-50'>
|
||||
<div className='p-1 rounded-lg border-[0.5px] border-gray-200 shadow-lg bg-white'>
|
||||
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>
|
||||
<div className='p-1 rounded-lg border-[0.5px] border-components-panel-border shadow-lg bg-components-panel-bg'>
|
||||
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>
|
||||
{t('appDebug.publishAs')}
|
||||
</div>
|
||||
{
|
||||
validModelConfigs.map((item, index) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className='flex items-center h-8 px-3 text-sm text-gray-500 rounded-lg cursor-pointer hover:bg-gray-100'
|
||||
className='flex items-center h-8 px-3 text-sm text-text-tertiary rounded-lg cursor-pointer hover:bg-state-base-hover'
|
||||
onClick={() => handleSelect(item)}
|
||||
>
|
||||
<span className='italic min-w-[18px]'>#{index + 1}</span>
|
||||
<ModelIcon modelName={item.model} provider={item.providerItem} className='ml-2' />
|
||||
<div
|
||||
className='ml-1 text-gray-700 truncate'
|
||||
className='ml-1 text-text-secondary truncate'
|
||||
title={item.modelItem.label[language]}
|
||||
>
|
||||
{item.modelItem.label[language]}
|
||||
|
@ -14,8 +14,8 @@ const SuggestedAction = ({ icon, link, disabled, children, className, ...props }
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
className={classNames(
|
||||
'flex justify-start items-center gap-2 h-[34px] px-2.5 bg-gray-100 rounded-lg transition-colors [&:not(:first-child)]:mt-1',
|
||||
disabled ? 'shadow-xs opacity-30 cursor-not-allowed' : 'hover:bg-primary-50 hover:text-primary-600 cursor-pointer',
|
||||
'flex justify-start items-center gap-2 h-[34px] px-2.5 bg-background-section-burn rounded-lg transition-colors text-text-secondary [&:not(:first-child)]:mt-1',
|
||||
disabled ? 'shadow-xs opacity-30 cursor-not-allowed' : 'hover:bg-state-accent-hover hover:text-text-accent cursor-pointer',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
@ -23,7 +23,7 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}>
|
||||
<div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] border-effects-highlight bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}>
|
||||
{/* Header */}
|
||||
<div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-b border-divider-subtle')}>
|
||||
<div className='flex justify-between items-center h-8'>
|
||||
|
@ -2,7 +2,10 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PlusIcon } from '@heroicons/react/20/solid'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiEditLine,
|
||||
} from '@remixicon/react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type IOperationBtnProps = {
|
||||
@ -13,11 +16,8 @@ export type IOperationBtnProps = {
|
||||
}
|
||||
|
||||
const iconMap = {
|
||||
add: <PlusIcon className='w-3.5 h-3.5' />,
|
||||
edit: (<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.99998 11.6666H12.25M1.75 11.6666H2.72682C3.01217 11.6666 3.15485 11.6666 3.28912 11.6344C3.40816 11.6058 3.52196 11.5587 3.62635 11.4947C3.74408 11.4226 3.84497 11.3217 4.04675 11.1199L11.375 3.79164C11.8583 3.30839 11.8583 2.52488 11.375 2.04164C10.8918 1.55839 10.1083 1.55839 9.62501 2.04164L2.29674 9.3699C2.09496 9.57168 1.99407 9.67257 1.92192 9.7903C1.85795 9.89469 1.81081 10.0085 1.78224 10.1275C1.75 10.2618 1.75 10.4045 1.75 10.6898V11.6666Z" stroke="#344054" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
add: <RiAddLine className='w-3.5 h-3.5' />,
|
||||
edit: <RiEditLine className='w-3.5 h-3.5' />,
|
||||
}
|
||||
|
||||
const OperationBtn: FC<IOperationBtnProps> = ({
|
||||
@ -29,7 +29,7 @@ const OperationBtn: FC<IOperationBtnProps> = ({
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div
|
||||
className={cn(className, 'flex items-center rounded-md h-7 px-3 space-x-1 text-gray-700 cursor-pointer hover:bg-gray-200 select-none')}
|
||||
className={cn('flex items-center rounded-md h-7 px-3 space-x-1 text-text-secondary cursor-pointer hover:bg-state-base-hover select-none', className)}
|
||||
onClick={onClick}>
|
||||
<div>
|
||||
{iconMap[type]}
|
||||
|
@ -28,8 +28,8 @@ const EditModal: FC<Props> = ({
|
||||
isShow={isShow}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-gray-900'}>{t('appDebug.feature.conversationHistory.editModal.userPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-gray-100'}
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-text-primary'}>{t('appDebug.feature.conversationHistory.editModal.userPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-components-input-bg-normal'}
|
||||
value={tempData.user_prefix}
|
||||
onChange={e => setTempData({
|
||||
...tempData,
|
||||
@ -37,8 +37,8 @@ const EditModal: FC<Props> = ({
|
||||
})}
|
||||
/>
|
||||
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-gray-900'}>{t('appDebug.feature.conversationHistory.editModal.assistantPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-gray-100'}
|
||||
<div className={'mt-6 font-medium text-sm leading-[21px] text-text-primary'}>{t('appDebug.feature.conversationHistory.editModal.assistantPrefix')}</div>
|
||||
<input className={'mt-2 w-full rounded-lg h-10 box-border px-3 text-sm leading-10 bg-components-input-bg-normal'}
|
||||
value={tempData.assistant_prefix}
|
||||
onChange={e => setTempData({
|
||||
...tempData,
|
||||
@ -48,8 +48,8 @@ const EditModal: FC<Props> = ({
|
||||
/>
|
||||
|
||||
<div className='mt-10 flex justify-end'>
|
||||
<Button className='mr-2 flex-shrink-0' onClick={onClose}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant='primary' className='flex-shrink-0' onClick={() => onSave(tempData)} loading={saveLoading}>{t('common.operation.save')}</Button>
|
||||
<Button className='mr-2 shrink-0' onClick={onClose}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant='primary' className='shrink-0' onClick={() => onSave(tempData)} loading={saveLoading}>{t('common.operation.save')}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid
|
||||
import I18n from '@/context/i18n'
|
||||
import { LanguagesSupported } from '@/i18n/language'
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
showWarning: boolean
|
||||
onShowEditModal: () => void
|
||||
}
|
||||
@ -30,20 +30,20 @@ const HistoryPanel: FC<Props> = ({
|
||||
</div>
|
||||
}
|
||||
headerIcon={
|
||||
<div className='p-1 rounded-md bg-white shadow-xs'>
|
||||
<div className='p-1 rounded-md shadow-xs'>
|
||||
<MessageClockCircle className='w-4 h-4 text-[#DD2590]' />
|
||||
</div>}
|
||||
headerRight={
|
||||
<div className='flex items-center'>
|
||||
<div className='text-xs text-gray-500'>{t('appDebug.feature.conversationHistory.description')}</div>
|
||||
<div className='ml-3 w-[1px] h-[14px] bg-gray-200'></div>
|
||||
<div className='text-xs text-text-tertiary'>{t('appDebug.feature.conversationHistory.description')}</div>
|
||||
<div className='ml-3 w-[1px] h-[14px] bg-divider-regular'></div>
|
||||
<OperationBtn type="edit" onClick={onShowEditModal} />
|
||||
</div>
|
||||
}
|
||||
noBodySpacing
|
||||
>
|
||||
{showWarning && (
|
||||
<div className='flex justify-between py-2 px-3 rounded-b-xl bg-[#FFFAEB] text-xs text-gray-700'>
|
||||
<div className='flex justify-between py-2 px-3 rounded-b-xl bg-background-section-burn text-xs text-text-secondary'>
|
||||
<div>{t('appDebug.feature.conversationHistory.tip')}
|
||||
<a href={`${locale === LanguagesSupported[1]
|
||||
? 'https://docs.dify.ai/v/zh-hans/guides/application-design/prompt-engineering'
|
||||
|
@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||
|
||||
const TEXT_MAX_LENGTH = 256
|
||||
|
||||
export interface IConfigModalProps {
|
||||
export type IConfigModalProps = {
|
||||
isCreate?: boolean
|
||||
payload?: InputVar
|
||||
isShow: boolean
|
||||
|
@ -5,23 +5,15 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import produce from 'immer'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
} from '@remixicon/react'
|
||||
import Panel from '../base/feature-panel'
|
||||
import EditModal from './config-modal'
|
||||
import IconTypeIcon from './input-type-icon'
|
||||
import type { IInputTypeIconProps } from './input-type-icon'
|
||||
import s from './style.module.css'
|
||||
import VarItem from './var-item'
|
||||
import SelectVarType from './select-var-type'
|
||||
import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import type { PromptVariable } from '@/models/debug'
|
||||
import { DEFAULT_VALUE_MAX_LEN, getMaxVarNameLength } from '@/config'
|
||||
import { checkKeys, getNewVar } from '@/utils/var'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||
import { getNewVar } from '@/utils/var'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
import { AppType } from '@/types/app'
|
||||
@ -33,7 +25,7 @@ import { InputVarType } from '@/app/components/workflow/types'
|
||||
|
||||
export const ADD_EXTERNAL_DATA_TOOL = 'ADD_EXTERNAL_DATA_TOOL'
|
||||
|
||||
interface ExternalDataToolParams {
|
||||
type ExternalDataToolParams = {
|
||||
key: string
|
||||
type: string
|
||||
index: number
|
||||
@ -43,14 +35,12 @@ interface ExternalDataToolParams {
|
||||
icon_background?: string
|
||||
}
|
||||
|
||||
export interface IConfigVarProps {
|
||||
export type IConfigVarProps = {
|
||||
promptVariables: PromptVariable[]
|
||||
readonly?: boolean
|
||||
onPromptVariablesChange?: (promptVariables: PromptVariable[]) => void
|
||||
}
|
||||
|
||||
let conflictTimer: number
|
||||
|
||||
const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVariablesChange }) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
@ -60,19 +50,6 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
|
||||
const hasVar = promptVariables.length > 0
|
||||
const updatePromptVariable = (key: string, updateKey: string, newValue: string | boolean) => {
|
||||
const newPromptVariables = promptVariables.map((item) => {
|
||||
if (item.key === key) {
|
||||
return {
|
||||
...item,
|
||||
[updateKey]: newValue,
|
||||
}
|
||||
}
|
||||
|
||||
return item
|
||||
})
|
||||
onPromptVariablesChange?.(newPromptVariables)
|
||||
}
|
||||
const [currIndex, setCurrIndex] = useState<number>(-1)
|
||||
const currItem = currIndex !== -1 ? promptVariables[currIndex] : null
|
||||
const currItemToEdit: InputVar | null = (() => {
|
||||
@ -105,55 +82,6 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
|
||||
onPromptVariablesChange?.(newPromptVariables)
|
||||
}
|
||||
const updatePromptKey = (index: number, newKey: string) => {
|
||||
window.clearTimeout(conflictTimer)
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const newPromptVariables = promptVariables.map((item, i) => {
|
||||
if (i === index) {
|
||||
return {
|
||||
...item,
|
||||
key: newKey,
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
conflictTimer = window.setTimeout(() => {
|
||||
const isKeyExists = promptVariables.some(item => item.key?.trim() === newKey.trim())
|
||||
if (isKeyExists) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('appDebug.varKeyError.keyAlreadyExists', { key: newKey }),
|
||||
})
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
onPromptVariablesChange?.(newPromptVariables)
|
||||
}
|
||||
|
||||
const updatePromptNameIfNameEmpty = (index: number, newKey: string) => {
|
||||
if (!newKey)
|
||||
return
|
||||
const newPromptVariables = promptVariables.map((item, i) => {
|
||||
if (i === index && !item.name) {
|
||||
return {
|
||||
...item,
|
||||
name: newKey,
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
onPromptVariablesChange?.(newPromptVariables)
|
||||
}
|
||||
|
||||
const { setShowExternalDataToolModal } = useModalContext()
|
||||
|
||||
@ -272,9 +200,6 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
return (
|
||||
<Panel
|
||||
className="mt-2"
|
||||
headerIcon={
|
||||
<VarIcon className='w-4 h-4 text-primary-500' />
|
||||
}
|
||||
title={
|
||||
<div className='flex items-center'>
|
||||
<div className='mr-1'>{t('appDebug.variableTitle')}</div>
|
||||
@ -290,87 +215,27 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
</div>
|
||||
}
|
||||
headerRight={!readonly ? <SelectVarType onChange={handleAddVar} /> : null}
|
||||
noBodySpacing
|
||||
>
|
||||
{!hasVar && (
|
||||
<div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.notSetVar')}</div>
|
||||
<div className='mt-1 px-3 pb-3'>
|
||||
<div className='pt-2 pb-1 text-xs text-text-tertiary'>{t('appDebug.notSetVar')}</div>
|
||||
</div>
|
||||
)}
|
||||
{hasVar && (
|
||||
<div className='rounded-lg border border-gray-200 bg-white overflow-x-auto'>
|
||||
<table className={`${s.table} min-w-[440px] w-full max-w-full border-collapse border-0 rounded-lg text-sm`}>
|
||||
<thead className="border-b border-gray-200 text-gray-500 text-xs font-medium">
|
||||
<tr className='uppercase'>
|
||||
<td>{t('appDebug.variableTable.key')}</td>
|
||||
<td>{t('appDebug.variableTable.name')}</td>
|
||||
{!readonly && (
|
||||
<>
|
||||
<td>{t('appDebug.variableTable.optional')}</td>
|
||||
<td>{t('appDebug.variableTable.action')}</td>
|
||||
</>
|
||||
)}
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-gray-700">
|
||||
{promptVariables.map(({ key, name, type, required, config, icon, icon_background }, index) => (
|
||||
<tr key={index} className="h-9 leading-9">
|
||||
<td className="w-[160px] border-b border-gray-100 pl-3">
|
||||
<div className='flex items-center space-x-1'>
|
||||
<IconTypeIcon type={type as IInputTypeIconProps['type']} className='text-gray-400' />
|
||||
{!readonly
|
||||
? (
|
||||
<input
|
||||
type="text"
|
||||
placeholder="key"
|
||||
value={key}
|
||||
onChange={e => updatePromptKey(index, e.target.value)}
|
||||
onBlur={e => updatePromptNameIfNameEmpty(index, e.target.value)}
|
||||
maxLength={getMaxVarNameLength(name)}
|
||||
className="h-6 leading-6 block w-full rounded-md border-0 py-1.5 text-gray-900 placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200"
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<div className='h-6 leading-6 text-[13px] text-gray-700'>{key}</div>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="py-1 border-b border-gray-100">
|
||||
{!readonly
|
||||
? (
|
||||
<input
|
||||
type="text"
|
||||
placeholder={key}
|
||||
value={name}
|
||||
onChange={e => updatePromptVariable(key, 'name', e.target.value)}
|
||||
maxLength={getMaxVarNameLength(name)}
|
||||
className="h-6 leading-6 block w-full rounded-md border-0 py-1.5 text-gray-900 placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200"
|
||||
/>)
|
||||
: (
|
||||
<div className='h-6 leading-6 text-[13px] text-gray-700'>{name}</div>
|
||||
)}
|
||||
</td>
|
||||
{!readonly && (
|
||||
<>
|
||||
<td className='w-[84px] border-b border-gray-100'>
|
||||
<div className='flex items-center h-full'>
|
||||
<Switch defaultValue={!required} size='md' onChange={value => updatePromptVariable(key, 'required', !value)} />
|
||||
</div>
|
||||
</td>
|
||||
<td className='w-20 border-b border-gray-100'>
|
||||
<div className='flex h-full items-center space-x-1'>
|
||||
<div className=' p-1 rounded-md hover:bg-black/5 w-6 h-6 cursor-pointer' onClick={() => handleConfig({ type, key, index, name, config, icon, icon_background })}>
|
||||
<Settings01 className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
<div className=' p-1 rounded-md hover:bg-black/5 w-6 h-6 cursor-pointer' onClick={() => handleRemoveVar(index)} >
|
||||
<RiDeleteBinLine className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className='flex flex-wrap mt-1 px-3 pb-3 justify-between'>
|
||||
{promptVariables.map(({ key, name, type, required, config, icon, icon_background }, index) => (
|
||||
<VarItem
|
||||
key={index}
|
||||
readonly={readonly}
|
||||
name={key}
|
||||
label={name}
|
||||
required={!!required}
|
||||
type={type}
|
||||
onEdit={() => handleConfig({ type, key, index, name, config, icon, icon_background })}
|
||||
onRemove={() => handleRemoveVar(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
import type { InputVarType } from '@/app/components/workflow/types'
|
||||
import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon'
|
||||
export interface ISelectTypeItemProps {
|
||||
export type ISelectTypeItemProps = {
|
||||
type: InputVarType
|
||||
selected: boolean
|
||||
onClick: () => void
|
||||
@ -27,7 +27,7 @@ const SelectTypeItem: FC<ISelectTypeItemProps> = ({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-col justify-center items-center h-[58px] rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg space-y-1',
|
||||
'flex flex-col justify-center items-center h-[58px] rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg space-y-1 text-text-secondary',
|
||||
selected ? 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg shadow-xs system-xs-medium' : ' hover:border-components-option-card-option-border-hover hover:bg-components-option-card-option-bg-hover hover:shadow-xs cursor-pointer system-xs-regular')}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
@ -1,12 +0,0 @@
|
||||
.table td {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.table thead td {
|
||||
height: 33px;
|
||||
line-height: 33px;
|
||||
}
|
||||
|
||||
.table tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
74
web/app/components/app/configuration/config-var/var-item.tsx
Normal file
74
web/app/components/app/configuration/config-var/var-item.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
RiEditLine,
|
||||
} from '@remixicon/react'
|
||||
import type { IInputTypeIconProps } from './input-type-icon'
|
||||
import IconTypeIcon from './input-type-icon'
|
||||
import { BracketsX as VarIcon } from '@/app/components/base/icons/src/vender/line/development'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type ItemProps = {
|
||||
readonly?: boolean
|
||||
name: string
|
||||
label: string
|
||||
required: boolean
|
||||
type: string
|
||||
onEdit: () => void
|
||||
onRemove: () => void
|
||||
}
|
||||
|
||||
const VarItem: FC<ItemProps> = ({
|
||||
readonly,
|
||||
name,
|
||||
label,
|
||||
required,
|
||||
type,
|
||||
onEdit,
|
||||
onRemove,
|
||||
}) => {
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
|
||||
return (
|
||||
<div className={cn('group relative flex items-center mb-1 last-of-type:mb-0 pl-2.5 py-2 pr-3 w-full rounded-lg bg-components-panel-on-panel-item-bg border-components-panel-border-subtle border-[0.5px] shadow-xs hover:shadow-sm hover:bg-components-panel-on-panel-item-bg-hover', isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border', readonly && 'cursor-not-allowed opacity-30')}>
|
||||
<VarIcon className='shrink-0 mr-1 w-4 h-4 text-text-accent' />
|
||||
<div className='grow'>
|
||||
<div className='flex items-center h-[18px]'>
|
||||
<div className='grow truncate' title={name}>
|
||||
<span className='system-sm-medium text-text-secondary'>{name}</span>
|
||||
<span className='px-1 system-xs-regular text-text-quaternary'>·</span>
|
||||
<span className='system-xs-medium text-text-tertiary'>{label}</span>
|
||||
</div>
|
||||
<div className='group-hover:hidden flex items-center'>
|
||||
{required && <Badge text='required' />}
|
||||
<span className='pl-2 pr-1 system-xs-regular text-text-tertiary'>{type}</span>
|
||||
<IconTypeIcon type={type as IInputTypeIconProps['type']} className='text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!readonly && (
|
||||
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px]'>
|
||||
<div
|
||||
className='flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'
|
||||
onClick={onEdit}
|
||||
>
|
||||
<RiEditLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
<div
|
||||
className='flex items-center justify-center w-6 h-6 text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
onClick={onRemove}
|
||||
onMouseOver={() => setIsDeleting(true)}
|
||||
onMouseLeave={() => setIsDeleting(false)}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default VarItem
|
@ -57,7 +57,7 @@ const ConfigVision: FC = () => {
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className='mt-2 flex items-center gap-2 p-2 rounded-xl border-t-[0.5px] border-l-[0.5px] bg-background-section-burn'>
|
||||
<div className='mt-2 flex items-center gap-2 p-2 rounded-xl border-effects-highlight border-t-[0.5px] border-l-[0.5px] bg-background-section-burn'>
|
||||
<div className='shrink-0 p-1'>
|
||||
<div className='p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-indigo-indigo-600'>
|
||||
<Vision className='w-4 h-4 text-text-primary-on-surface' />
|
||||
@ -99,7 +99,7 @@ const ConfigVision: FC = () => {
|
||||
/>
|
||||
</div> */}
|
||||
<ParamConfig />
|
||||
<div className='ml-1 mr-3 w-[1px] h-3.5 bg-divider-subtle'></div>
|
||||
<div className='ml-1 mr-3 w-[1px] h-3.5 bg-divider-regular'></div>
|
||||
<Switch
|
||||
defaultValue={isImageEnabled}
|
||||
onChange={handleChange}
|
||||
|
@ -41,11 +41,11 @@ const ParamConfigContent: FC = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='leading-6 text-base font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.title')}</div>
|
||||
<div className='leading-6 text-base font-semibold text-text-primary'>{t('appDebug.vision.visionSettings.title')}</div>
|
||||
<div className='pt-3 space-y-6'>
|
||||
<div>
|
||||
<div className='mb-2 flex items-center space-x-1'>
|
||||
<div className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.resolution')}</div>
|
||||
<div className='leading-[18px] text-[13px] font-semibold text-text-secondary'>{t('appDebug.vision.visionSettings.resolution')}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]' >
|
||||
@ -78,7 +78,7 @@ const ParamConfigContent: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className='mb-2 leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.uploadMethod')}</div>
|
||||
<div className='mb-2 leading-[18px] text-[13px] font-semibold text-text-secondary'>{t('appDebug.vision.visionSettings.uploadMethod')}</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<OptionCard
|
||||
className='grow'
|
||||
|
@ -2,14 +2,15 @@
|
||||
import type { FC } from 'react'
|
||||
import { memo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiSettings2Line } from '@remixicon/react'
|
||||
import ParamConfigContent from './param-config-content'
|
||||
import cn from '@/utils/classnames'
|
||||
import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import Button from '@/app/components/base/button'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
const ParamsConfig: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -25,13 +26,13 @@ const ParamsConfig: FC = () => {
|
||||
}}
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
||||
<div className={cn('flex items-center rounded-md h-7 px-3 space-x-1 text-text-tertiary cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}>
|
||||
<Settings01 className='w-3.5 h-3.5 ' />
|
||||
<div className='ml-1 leading-[18px] text-xs font-medium '>{t('appDebug.voice.settings')}</div>
|
||||
</div>
|
||||
<Button variant='ghost' size='small' className={cn('')}>
|
||||
<RiSettings2Line className='w-3.5 h-3.5' />
|
||||
<div className='ml-1'>{t('appDebug.voice.settings')}</div>
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent style={{ zIndex: 50 }}>
|
||||
<div className='w-80 sm:w-[412px] p-4 bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg space-y-3'>
|
||||
<div className='w-80 sm:w-[412px] p-4 bg-components-panel-bg rounded-lg border-[0.5px] border-components-panel-border shadow-lg space-y-3'>
|
||||
<ParamConfigContent />
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
|
@ -2,9 +2,9 @@
|
||||
import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiSettings2Line } from '@remixicon/react'
|
||||
import AgentSetting from './agent/agent-setting'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import type { AgentConfig } from '@/models/debug'
|
||||
|
||||
type Props = {
|
||||
@ -26,7 +26,7 @@ const AgentSettingButton: FC<Props> = ({
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => setIsShowAgentSetting(true)} className='shrink-0 mr-2'>
|
||||
<Settings01 className='mr-1 w-4 h-4 text-gray-500' />
|
||||
<RiSettings2Line className='mr-1 w-4 h-4 text-text-tertiary' />
|
||||
{t('appDebug.agent.setting.name')}
|
||||
</Button>
|
||||
{isShowAgentSetting && (
|
||||
|
@ -42,10 +42,10 @@ const AgentSetting: FC<Props> = ({
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className='w-[640px] flex flex-col h-full overflow-hidden bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl'
|
||||
className='w-[640px] flex flex-col h-full overflow-hidden bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-xl shadow-xl'
|
||||
>
|
||||
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'>
|
||||
<div className='flex flex-col text-base font-semibold text-gray-900'>
|
||||
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-divider-regular'>
|
||||
<div className='flex flex-col text-base font-semibold text-text-primary'>
|
||||
<div className='leading-6'>{t('appDebug.agent.setting.name')}</div>
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
@ -53,7 +53,7 @@ const AgentSetting: FC<Props> = ({
|
||||
onClick={onCancel}
|
||||
className='flex justify-center items-center w-6 h-6 cursor-pointer'
|
||||
>
|
||||
<RiCloseLine className='w-4 h-4 text-gray-500' />
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -70,7 +70,7 @@ const AgentSetting: FC<Props> = ({
|
||||
name={t('appDebug.agent.agentMode')}
|
||||
description={t('appDebug.agent.agentModeDes')}
|
||||
>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-gray-900'>{isFunctionCall ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</div>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-text-primary'>{isFunctionCall ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}</div>
|
||||
</ItemPanel>
|
||||
|
||||
<ItemPanel
|
||||
@ -99,10 +99,10 @@ const AgentSetting: FC<Props> = ({
|
||||
type="number"
|
||||
min={maxIterationsMin}
|
||||
max={maxIterationsMax} step={1}
|
||||
className="block w-11 h-7 leading-7 rounded-lg border-0 pl-1 px-1.5 bg-gray-100 text-gray-900 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-primary-600"
|
||||
className="block w-11 h-7 leading-7 rounded-lg border-0 pl-1 px-1.5 bg-components-input-bg-normal text-text-primary placeholder:text-text-tertiary focus:ring-1 focus:ring-inset focus:ring-primary-600"
|
||||
value={tempPayload.max_iteration}
|
||||
onChange={(e) => {
|
||||
let value = parseInt(e.target.value, 10)
|
||||
let value = Number.parseInt(e.target.value, 10)
|
||||
if (value < maxIterationsMin)
|
||||
value = maxIterationsMin
|
||||
|
||||
@ -117,23 +117,20 @@ const AgentSetting: FC<Props> = ({
|
||||
</ItemPanel>
|
||||
|
||||
{!isFunctionCall && (
|
||||
<div className='py-2 bg-gray-50 rounded-xl shadow-xs'>
|
||||
<div className='flex items-center h-8 px-4 leading-6 text-sm font-semibold text-gray-700'>{t('tools.builtInPromptTitle')}</div>
|
||||
<div className='h-[396px] px-4 overflow-y-auto leading-5 text-sm font-normal text-gray-700 whitespace-pre-line'>
|
||||
<div className='py-2 bg-background-section-burn rounded-xl shadow-xs'>
|
||||
<div className='flex items-center h-8 px-4 leading-6 text-sm font-semibold text-text-secondary'>{t('tools.builtInPromptTitle')}</div>
|
||||
<div className='h-[396px] px-4 overflow-y-auto leading-5 text-sm font-normal text-text-secondary whitespace-pre-line'>
|
||||
{isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion}
|
||||
</div>
|
||||
<div className='px-4'>
|
||||
<div className='inline-flex items-center h-5 px-1 rounded-md bg-gray-100 leading-[18px] text-xs font-medium text-gray-500'>{(isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion).length}</div>
|
||||
<div className='inline-flex items-center h-5 px-1 bg-components-input-bg-normal rounded-md leading-[18px] text-xs font-medium text-text-tertiary'>{(isChatModel ? DEFAULT_AGENT_PROMPT.chat : DEFAULT_AGENT_PROMPT.completion).length}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
<div
|
||||
className='sticky z-[5] bottom-0 w-full flex justify-end py-4 px-6 border-t bg-white '
|
||||
style={{
|
||||
borderColor: 'rgba(0, 0, 0, 0.05)',
|
||||
}}
|
||||
className='sticky z-[5] bottom-0 w-full flex justify-end py-4 px-6 border-t bg-background-section-burn border-divider-regular'
|
||||
>
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
|
@ -19,10 +19,10 @@ const ItemPanel: FC<Props> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className={cn(className, 'flex justify-between items-center h-12 px-3 rounded-lg bg-gray-50')}>
|
||||
<div className={cn(className, 'flex justify-between items-center h-12 px-3 rounded-lg bg-background-section-burn')}>
|
||||
<div className='flex items-center'>
|
||||
{icon}
|
||||
<div className='ml-3 mr-1 leading-6 text-sm font-semibold text-gray-800'>{name}</div>
|
||||
<div className='ml-3 mr-1 leading-6 text-sm font-semibold text-text-secondary'>{name}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]'>
|
||||
|
@ -8,7 +8,6 @@ import produce from 'immer'
|
||||
import {
|
||||
RiDeleteBinLine,
|
||||
RiEqualizer2Line,
|
||||
RiHammerFill,
|
||||
RiInformation2Line,
|
||||
} from '@remixicon/react'
|
||||
import { useFormattingChangedDispatcher } from '../../../debug/hooks'
|
||||
@ -108,9 +107,6 @@ const AgentTools: FC = () => {
|
||||
<Panel
|
||||
className={cn('mt-2', tools.length === 0 && 'pb-2')}
|
||||
noBodySpacing={tools.length === 0}
|
||||
headerIcon={
|
||||
<RiHammerFill className='w-4 h-4 text-primary-500' />
|
||||
}
|
||||
title={
|
||||
<div className='flex items-center'>
|
||||
<div className='mr-1'>{t('appDebug.agent.tools.name')}</div>
|
||||
@ -125,10 +121,10 @@ const AgentTools: FC = () => {
|
||||
}
|
||||
headerRight={
|
||||
<div className='flex items-center'>
|
||||
<div className='leading-[18px] text-xs font-normal text-gray-500'>{tools.filter((item: any) => !!item.enabled).length}/{tools.length} {t('appDebug.agent.tools.enabled')}</div>
|
||||
<div className='leading-[18px] text-xs font-normal text-text-tertiary'>{tools.filter((item: any) => !!item.enabled).length}/{tools.length} {t('appDebug.agent.tools.enabled')}</div>
|
||||
{tools.length < MAX_TOOLS_NUM && (
|
||||
<>
|
||||
<div className='ml-3 mr-1 h-3.5 w-px bg-gray-200'></div>
|
||||
<div className='ml-3 mr-1 h-3.5 w-px bg-divider-regular'></div>
|
||||
<ToolPicker
|
||||
trigger={<OperationBtn type="add" />}
|
||||
isShow={isShowChooseTool}
|
||||
|
@ -16,6 +16,7 @@ import Drawer from '@/app/components/base/drawer'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { useKnowledge } from '@/hooks/use-knowledge'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type ItemProps = {
|
||||
className?: string
|
||||
@ -41,8 +42,10 @@ const Item: FC<ItemProps> = ({
|
||||
setShowSettingsModal(false)
|
||||
}
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
|
||||
return (
|
||||
<div className='group relative flex items-center mb-1 last-of-type:mb-0 pl-2.5 py-2 pr-3 w-full bg-white rounded-lg border-[0.5px] border-gray-200 shadow-xs'>
|
||||
<div className={cn('group relative flex items-center mb-1 last-of-type:mb-0 pl-2.5 py-2 pr-3 w-full rounded-lg bg-components-panel-on-panel-item-bg border-components-panel-border-subtle border-[0.5px] shadow-xs hover:shadow-sm hover:bg-components-panel-on-panel-item-bg-hover', isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border')}>
|
||||
{
|
||||
config.data_source_type === DataSourceType.FILE && (
|
||||
<div className='shrink-0 flex items-center justify-center mr-2 w-6 h-6 bg-[#F5F8FF] rounded-md border-[0.5px] border-[#E0EAFF]'>
|
||||
@ -66,26 +69,30 @@ const Item: FC<ItemProps> = ({
|
||||
}
|
||||
<div className='grow'>
|
||||
<div className='flex items-center h-[18px]'>
|
||||
<div className='grow text-[13px] font-medium text-gray-800 truncate' title={config.name}>{config.name}</div>
|
||||
{config.provider === 'external'
|
||||
? <Badge text={t('dataset.externalTag')}></Badge>
|
||||
: <Badge
|
||||
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}
|
||||
/>}
|
||||
<div className='grow text-[13px] font-medium text-text-secondary truncate' title={config.name}>{config.name}</div>
|
||||
<div className='group-hover:hidden flex items-center'>
|
||||
{config.provider === 'external'
|
||||
? <Badge text={t('dataset.externalTag')}></Badge>
|
||||
: <Badge
|
||||
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}
|
||||
/>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px] bg-gradient-to-r from-white/50 to-white to-50%'>
|
||||
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px]'>
|
||||
<div
|
||||
className='flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'
|
||||
onClick={() => setShowSettingsModal(true)}
|
||||
>
|
||||
<RiEditLine className='w-4 h-4 text-gray-500' />
|
||||
<RiEditLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
<div
|
||||
className='group/action flex items-center justify-center w-6 h-6 hover:bg-[#FEE4E2] rounded-md cursor-pointer'
|
||||
className='flex items-center justify-center w-6 h-6 text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
onClick={() => onRemove(config.id)}
|
||||
onMouseOver={() => setIsDeleting(true)}
|
||||
onMouseLeave={() => setIsDeleting(false)}
|
||||
>
|
||||
<RiDeleteBinLine className='w-4 h-4 text-gray-500 group-hover/action:text-[#D92D20]' />
|
||||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
</div>
|
||||
</div>
|
||||
<Drawer isOpen={showSettingsModal} onClose={() => setShowSettingsModal(false)} footer={null} mask={isMobile} panelClassname='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'>
|
||||
|
@ -14,12 +14,12 @@ const ContextVar: FC<Props> = (props) => {
|
||||
const currItem = options.find(item => item.value === value)
|
||||
const notSetVar = !currItem
|
||||
return (
|
||||
<div className={cn(notSetVar ? 'rounded-bl-xl rounded-br-xl bg-[#FEF0C7] border-[#FEF0C7]' : 'border-gray-200', 'flex justify-between items-center h-12 px-3 border-t ')}>
|
||||
<div className={cn(notSetVar ? 'rounded-bl-xl rounded-br-xl bg-[#FEF0C7] border-[#FEF0C7]' : 'border-components-panel-border-subtle', 'flex justify-between items-center h-12 px-3 border-t ')}>
|
||||
<div className='flex items-center space-x-1 shrink-0'>
|
||||
<div className='p-1'>
|
||||
<BracketsX className='w-4 h-4 text-primary-500' />
|
||||
<BracketsX className='w-4 h-4 text-text-accent' />
|
||||
</div>
|
||||
<div className='mr-1 text-sm font-medium text-gray-800'>{t('appDebug.feature.dataSet.queryVariable.title')}</div>
|
||||
<div className='mr-1 text-sm font-medium text-text-secondary'>{t('appDebug.feature.dataSet.queryVariable.title')}</div>
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div className='w-[180px]'>
|
||||
|
@ -1,3 +0,0 @@
|
||||
.trigger:hover .dropdownIcon {
|
||||
color: #98A2B3;
|
||||
}
|
@ -3,7 +3,6 @@ import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ChevronDownIcon } from '@heroicons/react/24/outline'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
@ -56,10 +55,9 @@ const VarPicker: FC<Props> = ({
|
||||
>
|
||||
<PortalToFollowElemTrigger className={cn(triggerClassName)} onClick={() => setOpen(v => !v)}>
|
||||
<div className={cn(
|
||||
s.trigger,
|
||||
className,
|
||||
notSetVar ? 'bg-[#FFFCF5] border-[#FEDF89] text-[#DC6803]' : ' hover:bg-gray-50 border-gray-200 text-primary-600',
|
||||
open ? 'bg-gray-50' : 'bg-white',
|
||||
notSetVar ? 'bg-[#FFFCF5] border-[#FEDF89] text-[#DC6803]' : ' hover:bg-components-button-secondary-bg border-components-button-secondary-border text-text-accent',
|
||||
open ? 'bg-components-button-secondary-bg' : 'bg-transparent',
|
||||
`
|
||||
flex items-center h-8 justify-center px-2 space-x-1 rounded-lg border shadow-xs cursor-pointer
|
||||
text-[13px] font-medium
|
||||
@ -73,16 +71,16 @@ const VarPicker: FC<Props> = ({
|
||||
{notSelectedVarTip || t('appDebug.feature.dataSet.queryVariable.choosePlaceholder')}
|
||||
</div>)}
|
||||
</div>
|
||||
<ChevronDownIcon className={cn(s.dropdownIcon, open && 'rotate-180 text-[#98A2B3]', 'w-3.5 h-3.5')} />
|
||||
<ChevronDownIcon className={cn(open && 'rotate-180 text-text-tertiary', 'w-3.5 h-3.5')} />
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent style={{ zIndex: 1000 }}>
|
||||
{options.length > 0
|
||||
? (<div className='w-[240px] max-h-[50vh] overflow-y-auto p-1 border bg-white border-gray-200 rounded-lg shadow-lg'>
|
||||
? (<div className='w-[240px] max-h-[50vh] overflow-y-auto p-1 border bg-components-panel-bg border-components-panel-border rounded-lg shadow-lg'>
|
||||
{options.map(({ name, value, type }, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className='px-3 py-1 flex rounded-lg hover:bg-gray-50 cursor-pointer'
|
||||
className='px-3 py-1 flex rounded-lg hover:bg-state-base-hover cursor-pointer'
|
||||
onClick={() => {
|
||||
onChange(value)
|
||||
setOpen(false)
|
||||
@ -93,9 +91,9 @@ const VarPicker: FC<Props> = ({
|
||||
))}
|
||||
</div>)
|
||||
: (
|
||||
<div className='w-[240px] p-6 bg-white border border-gray-200 rounded-lg shadow-lg'>
|
||||
<div className='mb-1 text-sm font-medium text-gray-700'>{t('appDebug.feature.dataSet.queryVariable.noVar')}</div>
|
||||
<div className='text-xs leading-normal text-gray-500'>{t('appDebug.feature.dataSet.queryVariable.noVarTip')}</div>
|
||||
<div className='w-[240px] p-6 bg-components-panel-bg border border-components-panel-border rounded-lg shadow-lg'>
|
||||
<div className='mb-1 text-sm font-medium text-text-secondary'>{t('appDebug.feature.dataSet.queryVariable.noVar')}</div>
|
||||
<div className='text-xs leading-normal text-text-tertiary'>{t('appDebug.feature.dataSet.queryVariable.noVarTip')}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -20,13 +20,6 @@ import {
|
||||
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
||||
const Icon = (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12.6667 5.34368C12.6667 5.32614 12.6667 5.31738 12.6659 5.30147C12.6502 4.97229 12.3607 4.68295 12.0315 4.66737C12.0156 4.66662 12.0104 4.66662 12 4.66663H9.8391C9.30248 4.66662 8.85957 4.66661 8.49878 4.69609C8.12405 4.72671 7.77958 4.79242 7.45603 4.95728C6.95426 5.21294 6.54631 5.62089 6.29065 6.12265C6.12579 6.44621 6.06008 6.79068 6.02946 7.16541C5.99999 7.5262 5.99999 7.96911 6 8.50574V15.4942C5.99999 16.0308 5.99999 16.4737 6.02946 16.8345C6.06008 17.2092 6.12579 17.5537 6.29065 17.8773C6.54631 18.379 6.95426 18.787 7.45603 19.0426C7.77958 19.2075 8.12405 19.2732 8.49878 19.3038C8.85958 19.3333 9.30248 19.3333 9.83912 19.3333H14.1609C14.6975 19.3333 15.1404 19.3333 15.5012 19.3038C15.8759 19.2732 16.2204 19.2075 16.544 19.0426C17.0457 18.787 17.4537 18.379 17.7093 17.8773C17.8742 17.5537 17.9399 17.2092 17.9705 16.8345C18 16.4737 18 16.0308 18 15.4942V10.6666C18 10.6562 18 10.6511 17.9993 10.6352C17.9837 10.306 17.6943 10.0164 17.3651 10.0007C17.3492 9.99997 17.3405 9.99997 17.323 9.99997L14.3787 9.99997C14.2105 9.99999 14.0466 10 13.9078 9.98867C13.7555 9.97622 13.5756 9.94684 13.3947 9.85464C13.1438 9.72681 12.9398 9.52284 12.812 9.27195C12.7198 9.09101 12.6904 8.91118 12.678 8.75879C12.6666 8.62001 12.6666 8.45615 12.6667 8.2879L12.6667 5.34368ZM9.33333 12.6666C8.96514 12.6666 8.66667 12.9651 8.66667 13.3333C8.66667 13.7015 8.96514 14 9.33333 14H14.6667C15.0349 14 15.3333 13.7015 15.3333 13.3333C15.3333 12.9651 15.0349 12.6666 14.6667 12.6666H9.33333ZM9.33333 15.3333C8.96514 15.3333 8.66667 15.6318 8.66667 16C8.66667 16.3681 8.96514 16.6666 9.33333 16.6666H13.3333C13.7015 16.6666 14 16.3681 14 16C14 15.6318 13.7015 15.3333 13.3333 15.3333H9.33333Z" fill="#6938EF" />
|
||||
<path d="M16.6053 8.66662C16.8011 8.66662 16.8989 8.66663 16.9791 8.61747C17.0923 8.54806 17.16 8.38452 17.129 8.25538C17.107 8.16394 17.0432 8.10018 16.9155 7.97265L14.694 5.75111C14.5664 5.62345 14.5027 5.55962 14.4112 5.53764C14.2821 5.5066 14.1186 5.57429 14.0492 5.68752C14 5.7677 14 5.86557 14 6.06132L14 8.13327C14 8.31994 14 8.41328 14.0363 8.48459C14.0683 8.54731 14.1193 8.5983 14.182 8.63026C14.2533 8.66659 14.3466 8.66659 14.5333 8.66659L16.6053 8.66662Z" fill="#6938EF" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const DatasetConfig: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
@ -108,7 +101,6 @@ const DatasetConfig: FC = () => {
|
||||
return (
|
||||
<FeaturePanel
|
||||
className='mt-2'
|
||||
headerIcon={Icon}
|
||||
title={t('appDebug.feature.dataSet.title')}
|
||||
headerRight={
|
||||
<div className='flex items-center gap-1'>
|
||||
@ -134,7 +126,7 @@ const DatasetConfig: FC = () => {
|
||||
)
|
||||
: (
|
||||
<div className='mt-1 px-3 pb-3'>
|
||||
<div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.feature.dataSet.noData')}</div>
|
||||
<div className='pt-2 pb-1 text-xs text-text-tertiary'>{t('appDebug.feature.dataSet.noData')}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import cn from '@/utils/classnames'
|
||||
import { useSelectedDatasetsMode } from '@/app/components/workflow/nodes/knowledge-retrieval/hooks'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
|
||||
type Props = {
|
||||
datasetConfigs: DatasetConfigs
|
||||
@ -188,7 +189,7 @@ const ConfigContent: FC<Props> = ({
|
||||
<div className='shrink-0 mr-2 system-xs-semibold-uppercase text-text-secondary'>
|
||||
{t('dataset.rerankSettings')}
|
||||
</div>
|
||||
<div className='grow h-[1px] bg-gradient-to-l from-white to-[rgba(16,24,40,0.08)]'></div>
|
||||
<Divider bgStyle='gradient' className='!h-px mx-0' />
|
||||
</div>
|
||||
{
|
||||
selectedDatasetsMode.inconsistentEmbeddingModel
|
||||
@ -352,7 +353,7 @@ const ConfigContent: FC<Props> = ({
|
||||
{isInWorkflow && type === RETRIEVE_TYPE.oneWay && (
|
||||
<div className='mt-4'>
|
||||
<div className='flex items-center space-x-0.5'>
|
||||
<div className='leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.systemReasoningModel.key')}</div>
|
||||
<div className='leading-[32px] text-[13px] font-medium text-text-primary'>{t('common.modelProvider.systemReasoningModel.key')}</div>
|
||||
<Tooltip
|
||||
popupContent={t('common.modelProvider.systemReasoningModel.tip')}
|
||||
/>
|
||||
|
@ -6,8 +6,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import Link from 'next/link'
|
||||
import produce from 'immer'
|
||||
import TypeIcon from '../type-icon'
|
||||
import s from './style.module.css'
|
||||
import cn from '@/utils/classnames'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
import Button from '@/app/components/base/button'
|
||||
@ -15,6 +13,7 @@ import { fetchDatasets } from '@/service/datasets'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import { useKnowledge } from '@/hooks/use-knowledge'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type ISelectDataSetProps = {
|
||||
isShow: boolean
|
||||
@ -111,8 +110,8 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
|
||||
borderColor: 'rgba(0, 0, 0, 0.02',
|
||||
}}
|
||||
>
|
||||
<span className='text-gray-500'>{t('appDebug.feature.dataSet.noDataSet')}</span>
|
||||
<Link href="/datasets/create" className='font-normal text-[#155EEF]'>{t('appDebug.feature.dataSet.toCreate')}</Link>
|
||||
<span className='text-text-tertiary'>{t('appDebug.feature.dataSet.noDataSet')}</span>
|
||||
<Link href="/datasets/create" className='font-normal text-text-accent'>{t('appDebug.feature.dataSet.toCreate')}</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -122,7 +121,11 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
|
||||
{datasets.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={cn(s.item, selected.some(i => i.id === item.id) && s.selected, 'flex justify-between items-center h-10 px-2 rounded-lg bg-white border border-gray-200 cursor-pointer', !item.embedding_available && s.disabled)}
|
||||
className={cn(
|
||||
'flex justify-between items-center h-10 px-2 rounded-lg bg-components-panel-on-panel-item-bg border-components-panel-border-subtle border-[0.5px] shadow-xs cursor-pointer hover:border-components-panel-border hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm',
|
||||
selected.some(i => i.id === item.id) && 'border-[1.5px] border-components-option-card-option-selected-border bg-state-accent-hover shadow-xs hover:shadow-xs hover:border-components-option-card-option-selected-border hover:bg-state-accent-hover',
|
||||
!item.embedding_available && 'hover:border-components-panel-border-subtle hover:bg-components-panel-on-panel-item-bg hover:shadow-xs',
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!item.embedding_available)
|
||||
return
|
||||
@ -130,12 +133,12 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
|
||||
}}
|
||||
>
|
||||
<div className='mr-1 flex items-center'>
|
||||
<div className={cn('mr-2', !item.embedding_available && 'opacity-50')}>
|
||||
<div className={cn('mr-2', !item.embedding_available && 'opacity-30')}>
|
||||
<TypeIcon type="upload_file" size='md' />
|
||||
</div>
|
||||
<div className={cn('max-w-[200px] text-[13px] font-medium text-gray-800 overflow-hidden text-ellipsis whitespace-nowrap', !item.embedding_available && 'opacity-50 !max-w-[120px]')}>{item.name}</div>
|
||||
<div className={cn('max-w-[200px] text-[13px] font-medium text-text-secondary overflow-hidden text-ellipsis whitespace-nowrap', !item.embedding_available && 'opacity-30 !max-w-[120px]')}>{item.name}</div>
|
||||
{!item.embedding_available && (
|
||||
<span className='ml-1 shrink-0 px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
|
||||
<span className='ml-1 shrink-0 px-1 border border-divider-deep rounded-md text-text-tertiary text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
|
||||
)}
|
||||
</div>
|
||||
{
|
||||
@ -157,7 +160,7 @@ const SelectDataSet: FC<ISelectDataSetProps> = ({
|
||||
)}
|
||||
{loaded && (
|
||||
<div className='flex justify-between items-center mt-8'>
|
||||
<div className='text-sm font-medium text-gray-700'>
|
||||
<div className='text-sm font-medium text-text-secondary'>
|
||||
{selected.length > 0 && `${selected.length} ${t('appDebug.feature.dataSet.selected')}`}
|
||||
</div>
|
||||
<div className='flex space-x-2'>
|
||||
|
@ -1,13 +0,0 @@
|
||||
.item {
|
||||
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
|
||||
}
|
||||
|
||||
.item:hover,
|
||||
.item.selected {
|
||||
background: #F5F8FF;
|
||||
border-color: #528BFF;
|
||||
}
|
||||
|
||||
.item.disabled {
|
||||
@apply bg-white border-gray-200 cursor-default;
|
||||
}
|
@ -172,14 +172,14 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className='overflow-hidden w-full flex flex-col bg-white border-[0.5px] border-gray-200 rounded-xl shadow-xl'
|
||||
className='overflow-hidden w-full flex flex-col bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-xl shadow-xl'
|
||||
style={{
|
||||
height: 'calc(100vh - 72px)',
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-b-gray-100'>
|
||||
<div className='flex flex-col text-base font-semibold text-gray-900'>
|
||||
<div className='shrink-0 flex justify-between items-center pl-6 pr-5 h-14 border-b border-divider-regular'>
|
||||
<div className='flex flex-col text-base font-semibold text-text-primary'>
|
||||
<div className='leading-6'>{t('datasetSettings.title')}</div>
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
@ -187,14 +187,12 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
onClick={onCancel}
|
||||
className='flex justify-center items-center w-6 h-6 cursor-pointer'
|
||||
>
|
||||
<RiCloseLine className='w-4 h-4 text-gray-500' />
|
||||
<RiCloseLine className='w-4 h-4 text-text-tertiary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<div className='p-6 pt-5 border-b overflow-y-auto pb-[68px]' style={{
|
||||
borderBottom: 'rgba(0, 0, 0, 0.05)',
|
||||
}}>
|
||||
<div className='p-6 pt-5 border-b border-divider-regular overflow-y-auto pb-[68px]'>
|
||||
<div className={cn(rowClass, 'items-center')}>
|
||||
<div className={labelClass}>
|
||||
<div className='text-text-secondary system-sm-semibold'>{t('datasetSettings.form.name')}</div>
|
||||
@ -217,7 +215,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
className='resize-none'
|
||||
placeholder={t('datasetSettings.form.descPlaceholder') || ''}
|
||||
/>
|
||||
<a className='mt-2 flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank' rel='noopener noreferrer'>
|
||||
<a className='mt-2 flex items-center h-[18px] px-3 text-xs text-text-tertiary' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank' rel='noopener noreferrer'>
|
||||
<BookOpenIcon className='w-3 h-[18px] mr-1' />
|
||||
{t('datasetSettings.form.descWrite')}
|
||||
</a>
|
||||
@ -260,7 +258,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
<div className='text-text-secondary system-sm-semibold'>{t('datasetSettings.form.embeddingModel')}</div>
|
||||
</div>
|
||||
<div className='w-full'>
|
||||
<div className='w-full h-9 rounded-lg bg-gray-100 opacity-60'>
|
||||
<div className='w-full h-8 rounded-lg bg-components-input-bg-normal opacity-60'>
|
||||
<ModelSelector
|
||||
readonly
|
||||
defaultModel={{
|
||||
@ -270,9 +268,9 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
modelList={embeddingsModelList}
|
||||
/>
|
||||
</div>
|
||||
<div className='mt-2 w-full text-xs leading-6 text-gray-500'>
|
||||
<div className='mt-2 w-full text-xs leading-6 text-text-tertiary'>
|
||||
{t('datasetSettings.form.embeddingModelTip')}
|
||||
<span className='text-[#155eef] cursor-pointer' onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('datasetSettings.form.embeddingModelTipLink')}</span>
|
||||
<span className='text-text-accent cursor-pointer' onClick={() => setShowAccountSettingModal({ payload: 'provider' })}>{t('datasetSettings.form.embeddingModelTipLink')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -326,8 +324,8 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
<div className={cn(labelClass, 'w-auto min-w-[168px]')}>
|
||||
<div>
|
||||
<div className='text-text-secondary system-sm-semibold'>{t('datasetSettings.form.retrievalSetting.title')}</div>
|
||||
<div className='leading-[18px] text-xs font-normal text-gray-500'>
|
||||
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
|
||||
<div className='leading-[18px] text-xs font-normal text-text-tertiary'>
|
||||
<a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/guides/knowledge-base/create-knowledge-and-upload-documents#id-4-retrieval-settings' className='text-text-accent'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
|
||||
{t('datasetSettings.form.retrievalSetting.description')}
|
||||
</div>
|
||||
</div>
|
||||
@ -360,16 +358,13 @@ const SettingsModal: FC<SettingsModalProps> = ({
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
}}>
|
||||
<RiCloseLine className='w-4 h-4 text-gray-500 ' />
|
||||
<RiCloseLine className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className='sticky z-[5] bottom-0 w-full flex justify-end py-4 px-6 border-t bg-white '
|
||||
style={{
|
||||
borderColor: 'rgba(0, 0, 0, 0.05)',
|
||||
}}
|
||||
className='sticky z-[5] bottom-0 w-full flex justify-end py-4 px-6 border-t border-divider-regular bg-background-section'
|
||||
>
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
|
@ -84,7 +84,6 @@ const ChatUserInput = ({
|
||||
onSelect={(i) => { handleInputValueChange(key, i.value as string) }}
|
||||
items={(options || []).map(i => ({ name: i, value: i }))}
|
||||
allowSearch={false}
|
||||
bgClassName='bg-gray-50'
|
||||
/>
|
||||
)}
|
||||
{type === 'number' && (
|
||||
|
@ -31,7 +31,7 @@ import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
import type { InputForm } from '@/app/components/base/chat/chat/type'
|
||||
import { getLastAnswer } from '@/app/components/base/chat/utils'
|
||||
|
||||
interface ChatItemProps {
|
||||
type ChatItemProps = {
|
||||
modelAndParameter: ModelAndParameter
|
||||
}
|
||||
const ChatItem: FC<ChatItemProps> = ({
|
||||
|
@ -64,11 +64,11 @@ const DebugItem: FC<DebugItemProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col min-w-[320px] rounded-xl bg-white border-[0.5px] border-black/5 ${className}`}
|
||||
className={`flex flex-col min-w-[320px] rounded-xl bg-background-section-burn ${className}`}
|
||||
style={style}
|
||||
>
|
||||
<div className='shrink-0 flex items-center justify-between h-10 px-3 border-b-[0.5px] border-b-black/5'>
|
||||
<div className='flex items-center justify-center w-6 h-5 font-medium italic text-gray-500'>
|
||||
<div className='shrink-0 flex items-center justify-between h-10 px-3 border-b-[0.5px] border-divider-regular'>
|
||||
<div className='flex items-center justify-center w-6 h-5 font-medium italic text-text-tertiary'>
|
||||
#{index + 1}
|
||||
</div>
|
||||
<ModelParameterTrigger
|
||||
|
@ -73,7 +73,7 @@ const ModelParameterTrigger: FC<ModelParameterTriggerProps> = ({
|
||||
<div
|
||||
className={`
|
||||
flex items-center max-w-[200px] h-8 px-2 rounded-lg cursor-pointer
|
||||
${open && 'bg-gray-100'}
|
||||
${open && 'bg-state-base-hover'}
|
||||
${currentModel && currentModel.status !== ModelStatusEnum.active && '!bg-[#FFFAEB]'}
|
||||
`}
|
||||
>
|
||||
@ -88,27 +88,27 @@ const ModelParameterTrigger: FC<ModelParameterTriggerProps> = ({
|
||||
}
|
||||
{
|
||||
!currentProvider && (
|
||||
<div className='flex items-center justify-center mr-1 w-4 h-4 rounded border border-dashed border-primary-100'>
|
||||
<CubeOutline className='w-[11px] h-[11px] text-primary-600' />
|
||||
<div className='flex items-center justify-center mr-1 w-4 h-4 rounded'>
|
||||
<CubeOutline className='w-4 h-4 text-text-accent' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
currentModel && (
|
||||
<ModelName
|
||||
className='mr-0.5 text-gray-800'
|
||||
className='mr-0.5 text-text-secondary'
|
||||
modelItem={currentModel}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
!currentModel && (
|
||||
<div className='mr-0.5 text-[13px] font-medium text-primary-600 truncate'>
|
||||
<div className='mr-0.5 text-[13px] font-medium text-text-accent truncate'>
|
||||
{t('common.modelProvider.selectModel')}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<RiArrowDownSLine className={`w-3 h-3 ${(currentModel && currentProvider) ? 'text-gray-800' : 'text-primary-600'}`} />
|
||||
<RiArrowDownSLine className={`w-3 h-3 ${(currentModel && currentProvider) ? 'text-text-tertiary' : 'text-text-accent'}`} />
|
||||
{
|
||||
currentModel && currentModel.status !== ModelStatusEnum.active && (
|
||||
<Tooltip popupContent={MODEL_STATUS_TEXT[currentModel.status][language]}>
|
||||
|
@ -15,7 +15,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
|
||||
interface TextGenerationItemProps {
|
||||
type TextGenerationItemProps = {
|
||||
modelAndParameter: ModelAndParameter
|
||||
}
|
||||
const TextGenerationItem: FC<TextGenerationItemProps> = ({
|
||||
|
@ -1,299 +0,0 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
RiAddLine,
|
||||
RiDeleteBinLine,
|
||||
} from '@remixicon/react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import produce from 'immer'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { ReactSortable } from 'react-sortablejs'
|
||||
import cn from '@/utils/classnames'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
import Panel from '@/app/components/app/configuration/base/feature-panel'
|
||||
import Button from '@/app/components/base/button'
|
||||
import OperationBtn from '@/app/components/app/configuration/base/operation-btn'
|
||||
import { getInputKeys } from '@/app/components/base/block-input'
|
||||
import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var'
|
||||
import { getNewVar } from '@/utils/var'
|
||||
import { varHighlightHTML } from '@/app/components/app/configuration/base/var-highlight'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
|
||||
const MAX_QUESTION_NUM = 10
|
||||
|
||||
export type IOpeningStatementProps = {
|
||||
value: string
|
||||
readonly?: boolean
|
||||
onChange?: (value: string) => void
|
||||
suggestedQuestions?: string[]
|
||||
onSuggestedQuestionsChange?: (value: string[]) => void
|
||||
}
|
||||
|
||||
// regex to match the {{}} and replace it with a span
|
||||
const regex = /\{\{([^}]+)\}\}/g
|
||||
|
||||
const OpeningStatement: FC<IOpeningStatementProps> = ({
|
||||
value = '',
|
||||
readonly,
|
||||
onChange,
|
||||
suggestedQuestions = [],
|
||||
onSuggestedQuestionsChange = () => { },
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
modelConfig,
|
||||
setModelConfig,
|
||||
} = useContext(ConfigContext)
|
||||
const promptVariables = modelConfig.configs.prompt_variables
|
||||
const [notIncludeKeys, setNotIncludeKeys] = useState<string[]>([])
|
||||
|
||||
const hasValue = !!(value || '').trim()
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null)
|
||||
|
||||
const [isFocus, { setTrue: didSetFocus, setFalse: setBlur }] = useBoolean(false)
|
||||
|
||||
const setFocus = () => {
|
||||
didSetFocus()
|
||||
setTimeout(() => {
|
||||
const input = inputRef.current
|
||||
if (input) {
|
||||
input.focus()
|
||||
input.setSelectionRange(input.value.length, input.value.length)
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const [tempValue, setTempValue] = useState(value)
|
||||
useEffect(() => {
|
||||
setTempValue(value || '')
|
||||
}, [value])
|
||||
|
||||
const [tempSuggestedQuestions, setTempSuggestedQuestions] = useState(suggestedQuestions || [])
|
||||
const notEmptyQuestions = tempSuggestedQuestions.filter(question => !!question && question.trim())
|
||||
const coloredContent = (tempValue || '')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(regex, varHighlightHTML({ name: '$1' })) // `<span class="${highLightClassName}">{{$1}}</span>`
|
||||
.replace(/\n/g, '<br />')
|
||||
|
||||
const handleEdit = () => {
|
||||
if (readonly)
|
||||
return
|
||||
setFocus()
|
||||
}
|
||||
|
||||
const [isShowConfirmAddVar, { setTrue: showConfirmAddVar, setFalse: hideConfirmAddVar }] = useBoolean(false)
|
||||
|
||||
const handleCancel = () => {
|
||||
setBlur()
|
||||
setTempValue(value)
|
||||
setTempSuggestedQuestions(suggestedQuestions)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (!(tempValue || '').trim()) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('common.errorMsg.fieldRequired', {
|
||||
field: t('appDebug.openingStatement.title'),
|
||||
}),
|
||||
})
|
||||
return
|
||||
}
|
||||
const keys = getInputKeys(tempValue)
|
||||
const promptKeys = promptVariables.map(item => item.key)
|
||||
let notIncludeKeys: string[] = []
|
||||
|
||||
if (promptKeys.length === 0) {
|
||||
if (keys.length > 0)
|
||||
notIncludeKeys = keys
|
||||
}
|
||||
else {
|
||||
notIncludeKeys = keys.filter(key => !promptKeys.includes(key))
|
||||
}
|
||||
|
||||
if (notIncludeKeys.length > 0) {
|
||||
setNotIncludeKeys(notIncludeKeys)
|
||||
showConfirmAddVar()
|
||||
return
|
||||
}
|
||||
setBlur()
|
||||
onChange?.(tempValue)
|
||||
onSuggestedQuestionsChange(tempSuggestedQuestions)
|
||||
}
|
||||
|
||||
const cancelAutoAddVar = () => {
|
||||
onChange?.(tempValue)
|
||||
hideConfirmAddVar()
|
||||
setBlur()
|
||||
}
|
||||
|
||||
const autoAddVar = () => {
|
||||
const newModelConfig = produce(modelConfig, (draft) => {
|
||||
draft.configs.prompt_variables = [...draft.configs.prompt_variables, ...notIncludeKeys.map(key => getNewVar(key, 'string'))]
|
||||
})
|
||||
onChange?.(tempValue)
|
||||
setModelConfig(newModelConfig)
|
||||
hideConfirmAddVar()
|
||||
setBlur()
|
||||
}
|
||||
|
||||
const headerRight = !readonly ? (
|
||||
isFocus ? (
|
||||
<div className='flex items-center space-x-1'>
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='small'
|
||||
onClick={handleCancel}
|
||||
>
|
||||
{t('common.operation.cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleConfirm}
|
||||
variant="primary"
|
||||
size='small'
|
||||
>
|
||||
{t('common.operation.save')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<OperationBtn type='edit' actionName={hasValue ? '' : t('appDebug.openingStatement.writeOpener') as string} onClick={handleEdit} />
|
||||
)
|
||||
) : null
|
||||
|
||||
const renderQuestions = () => {
|
||||
return isFocus ? (
|
||||
<div>
|
||||
<div className='flex items-center py-2'>
|
||||
<div className='shrink-0 flex space-x-0.5 leading-[18px] text-xs font-medium text-gray-500'>
|
||||
<div className='uppercase'>{t('appDebug.openingStatement.openingQuestion')}</div>
|
||||
<div>·</div>
|
||||
<div>{tempSuggestedQuestions.length}/{MAX_QUESTION_NUM}</div>
|
||||
</div>
|
||||
<div className='ml-3 grow w-0 h-px bg-[#243, 244, 246]'></div>
|
||||
</div>
|
||||
<ReactSortable
|
||||
className="space-y-1"
|
||||
list={tempSuggestedQuestions.map((name, index) => {
|
||||
return {
|
||||
id: index,
|
||||
name,
|
||||
}
|
||||
})}
|
||||
setList={list => setTempSuggestedQuestions(list.map(item => item.name))}
|
||||
handle='.handle'
|
||||
ghostClass="opacity-50"
|
||||
animation={150}
|
||||
>
|
||||
{tempSuggestedQuestions.map((question, index) => {
|
||||
return (
|
||||
<div className='group relative rounded-lg border border-gray-200 flex items-center pl-2.5 hover:border-gray-300 hover:bg-white' key={index}>
|
||||
<div className='handle flex items-center justify-center w-4 h-4 cursor-grab'>
|
||||
<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M1 2C1.55228 2 2 1.55228 2 1C2 0.447715 1.55228 0 1 0C0.447715 0 0 0.447715 0 1C0 1.55228 0.447715 2 1 2ZM1 6C1.55228 6 2 5.55228 2 5C2 4.44772 1.55228 4 1 4C0.447715 4 0 4.44772 0 5C0 5.55228 0.447715 6 1 6ZM6 1C6 1.55228 5.55228 2 5 2C4.44772 2 4 1.55228 4 1C4 0.447715 4.44772 0 5 0C5.55228 0 6 0.447715 6 1ZM5 6C5.55228 6 6 5.55228 6 5C6 4.44772 5.55228 4 5 4C4.44772 4 4 4.44772 4 5C4 5.55228 4.44772 6 5 6ZM2 9C2 9.55229 1.55228 10 1 10C0.447715 10 0 9.55229 0 9C0 8.44771 0.447715 8 1 8C1.55228 8 2 8.44771 2 9ZM5 10C5.55228 10 6 9.55229 6 9C6 8.44771 5.55228 8 5 8C4.44772 8 4 8.44771 4 9C4 9.55229 4.44772 10 5 10Z" fill="#98A2B3" />
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="input"
|
||||
value={question || ''}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
setTempSuggestedQuestions(tempSuggestedQuestions.map((item, i) => {
|
||||
if (index === i)
|
||||
return value
|
||||
|
||||
return item
|
||||
}))
|
||||
}}
|
||||
className={'w-full overflow-x-auto pl-1.5 pr-8 text-sm leading-9 text-gray-900 border-0 grow h-9 bg-transparent focus:outline-none cursor-pointer rounded-lg'}
|
||||
/>
|
||||
|
||||
<div
|
||||
className='block absolute top-1/2 translate-y-[-50%] right-1.5 p-1 rounded-md cursor-pointer hover:bg-[#FEE4E2] hover:text-[#D92D20]'
|
||||
onClick={() => {
|
||||
setTempSuggestedQuestions(tempSuggestedQuestions.filter((_, i) => index !== i))
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='w-3.5 h-3.5' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}</ReactSortable>
|
||||
{tempSuggestedQuestions.length < MAX_QUESTION_NUM && (
|
||||
<div
|
||||
onClick={() => { setTempSuggestedQuestions([...tempSuggestedQuestions, '']) }}
|
||||
className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-gray-400 bg-gray-100 hover:bg-gray-200'>
|
||||
<RiAddLine className='w-4 h-4' />
|
||||
<div className='text-gray-500 text-[13px]'>{t('appDebug.variableConfig.addOption')}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className='mt-1.5 flex flex-wrap'>
|
||||
{notEmptyQuestions.map((question, index) => {
|
||||
return (
|
||||
<div key={index} className='mt-1 mr-1 max-w-full truncate last:mr-0 shrink-0 leading-8 items-center px-2.5 rounded-lg border border-gray-200 shadow-xs bg-white text-[13px] font-normal text-gray-900 cursor-pointer'>
|
||||
{question}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Panel
|
||||
className={cn(isShowConfirmAddVar && 'h-[220px]', 'relative mt-4 !bg-gray-25')}
|
||||
title={t('appDebug.openingStatement.title')}
|
||||
headerIcon={
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M8.33353 1.33301C4.83572 1.33301 2.00019 4.16854 2.00019 7.66634C2.00019 8.37301 2.11619 9.05395 2.3307 9.69036C2.36843 9.80229 2.39063 9.86853 2.40507 9.91738L2.40979 9.93383L2.40729 9.93903C2.39015 9.97437 2.36469 10.0218 2.31705 10.11L1.2158 12.1484C1.14755 12.2746 1.07633 12.4064 1.02735 12.5209C0.978668 12.6348 0.899813 12.8437 0.938613 13.0914C0.984094 13.3817 1.15495 13.6373 1.40581 13.7903C1.61981 13.9208 1.843 13.9279 1.96683 13.9264C2.09141 13.925 2.24036 13.9095 2.38314 13.8947L5.81978 13.5395C5.87482 13.5338 5.9036 13.5309 5.92468 13.5292L5.92739 13.529L5.93564 13.532C5.96154 13.5413 5.99666 13.5548 6.0573 13.5781C6.76459 13.8506 7.53244 13.9997 8.33353 13.9997C11.8313 13.9997 14.6669 11.1641 14.6669 7.66634C14.6669 4.16854 11.8313 1.33301 8.33353 1.33301ZM5.9799 5.72116C6.73142 5.08698 7.73164 5.27327 8.33144 5.96584C8.93125 5.27327 9.91854 5.09365 10.683 5.72116C11.4474 6.34867 11.5403 7.41567 10.9501 8.16572C10.5845 8.6304 9.6668 9.47911 9.02142 10.0576C8.78435 10.2702 8.66582 10.3764 8.52357 10.4192C8.40154 10.456 8.26134 10.456 8.13931 10.4192C7.99706 10.3764 7.87853 10.2702 7.64147 10.0576C6.99609 9.47911 6.07839 8.6304 5.71276 8.16572C5.12259 7.41567 5.22839 6.35534 5.9799 5.72116Z" fill="#E74694" />
|
||||
</svg>
|
||||
}
|
||||
headerRight={headerRight}
|
||||
hasHeaderBottomBorder={!hasValue}
|
||||
isFocus={isFocus}
|
||||
>
|
||||
<div className='text-gray-700 text-sm'>
|
||||
{(hasValue || (!hasValue && isFocus)) ? (
|
||||
<>
|
||||
{isFocus
|
||||
? (
|
||||
<div>
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
value={tempValue}
|
||||
rows={3}
|
||||
onChange={e => setTempValue(e.target.value)}
|
||||
className="w-full px-0 text-sm border-0 bg-transparent focus:outline-none "
|
||||
placeholder={t('appDebug.openingStatement.placeholder') as string}
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div dangerouslySetInnerHTML={{
|
||||
__html: coloredContent,
|
||||
}}></div>
|
||||
)}
|
||||
{renderQuestions()}
|
||||
</>) : (
|
||||
<div className='pt-2 pb-1 text-xs text-gray-500'>{t('appDebug.openingStatement.noDataPlaceHolder')}</div>
|
||||
)}
|
||||
|
||||
{isShowConfirmAddVar && (
|
||||
<ConfirmAddVar
|
||||
varNameArr={notIncludeKeys}
|
||||
onConfirm={autoAddVar}
|
||||
onCancel={cancelAutoAddVar}
|
||||
onHide={hideConfirmAddVar}
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</Panel>
|
||||
)
|
||||
}
|
||||
export default React.memo(OpeningStatement)
|
@ -19,6 +19,7 @@ import {
|
||||
} from '@/app/components/app/configuration/debug/hooks'
|
||||
import type { ModelAndParameter } from '@/app/components/app/configuration/debug/types'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import AppPublisher from '@/app/components/app/app-publisher/features-wrapper'
|
||||
import type {
|
||||
@ -895,13 +896,13 @@ const Configuration: FC = () => {
|
||||
<div className="flex flex-col h-full">
|
||||
<div className='relative flex grow h-[200px] pt-14'>
|
||||
{/* Header */}
|
||||
<div className='absolute top-0 left-0 w-full bg-white h-14'>
|
||||
<div className='absolute top-0 left-0 w-full bg-default-subtle h-14'>
|
||||
<div className='flex items-center justify-between px-6 h-14'>
|
||||
<div className='flex items-center'>
|
||||
<div className='text-base font-semibold leading-6 text-gray-900'>{t('appDebug.orchestrate')}</div>
|
||||
<div className='system-xl-semibold text-text-primary'>{t('appDebug.orchestrate')}</div>
|
||||
<div className='flex items-center h-[14px] space-x-1 text-xs'>
|
||||
{isAdvancedMode && (
|
||||
<div className='ml-1 flex items-center h-5 px-1.5 border border-gray-100 rounded-md text-[11px] font-medium text-gray-500 uppercase'>{t('appDebug.promptMode.advanced')}</div>
|
||||
<div className='ml-1 flex items-center h-5 px-1.5 border border-components-button-secondary-border rounded-md system-xs-medium-uppercase text-text-tertiary uppercase'>{t('appDebug.promptMode.advanced')}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@ -937,13 +938,13 @@ const Configuration: FC = () => {
|
||||
debugWithMultipleModel={debugWithMultipleModel}
|
||||
onDebugWithMultipleModelChange={handleDebugWithMultipleModelChange}
|
||||
/>
|
||||
<div className='mx-2 w-[1px] h-[14px] bg-gray-200'></div>
|
||||
<Divider type='vertical' className='mx-2 h-[14px]' />
|
||||
</>
|
||||
)}
|
||||
{isMobile && (
|
||||
<Button className='!h-8 !text-[13px] font-medium' onClick={showDebugPanel}>
|
||||
<Button className='mr-2 !h-8 !text-[13px] font-medium' onClick={showDebugPanel}>
|
||||
<span className='mr-1'>{t('appDebug.operation.debugConfig')}</span>
|
||||
<CodeBracketIcon className="w-4 h-4 text-gray-500" />
|
||||
<CodeBracketIcon className="w-4 h-4 text-text-tertiary" />
|
||||
</Button>
|
||||
)}
|
||||
<AppPublisher {...{
|
||||
@ -1014,7 +1015,7 @@ const Configuration: FC = () => {
|
||||
/>
|
||||
)}
|
||||
{isMobile && (
|
||||
<Drawer showClose isOpen={isShowDebugPanel} onClose={hideDebugPanel} mask footer={null} panelClassname='!bg-gray-50'>
|
||||
<Drawer showClose isOpen={isShowDebugPanel} onClose={hideDebugPanel} mask footer={null}>
|
||||
<Debug
|
||||
isAPIKeySet={isAPIKeySet}
|
||||
onSetting={() => setShowAccountSettingModal({ payload: 'provider' })}
|
||||
|
@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export interface IPromptValuePanelProps {
|
||||
export type IPromptValuePanelProps = {
|
||||
appType: AppType
|
||||
onSend?: () => void
|
||||
inputs: Inputs
|
||||
@ -157,7 +157,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
|
||||
))}
|
||||
{visionConfig?.enabled && (
|
||||
<div className="mt-3 xl:flex justify-between">
|
||||
<div className="mr-1 py-2 shrink-0 w-[120px] text-sm text-gray-900">{t('common.imageUploader.imageUpload')}</div>
|
||||
<div className="mr-1 py-2 shrink-0 w-[120px] text-sm text-text-primary">{t('common.imageUploader.imageUpload')}</div>
|
||||
<div className='grow'>
|
||||
<TextGenerationImageUploader
|
||||
settings={visionConfig}
|
||||
|
@ -173,7 +173,7 @@ const ChatInputArea = ({
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
className={cn(
|
||||
'p-1 w-full leading-6 body-lg-regular text-text-tertiary outline-none',
|
||||
'p-1 w-full leading-6 body-lg-regular text-text-tertiary bg-transparent outline-none',
|
||||
)}
|
||||
placeholder={t('common.chat.inputPlaceholder') || ''}
|
||||
autoFocus
|
||||
|
@ -35,7 +35,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import type { AppData } from '@/models/share'
|
||||
|
||||
export interface ChatProps {
|
||||
export type ChatProps = {
|
||||
appData?: AppData
|
||||
chatList: ChatItem[]
|
||||
config?: ChatConfig
|
||||
@ -251,11 +251,8 @@ const Chat: FC<ChatProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`absolute bottom-0 ${(hasTryToAsk || !noChatInput || !noStopResponding) && chatFooterClassName}`}
|
||||
className={`absolute bottom-0 bg-chat-input-mask ${(hasTryToAsk || !noChatInput || !noStopResponding) && chatFooterClassName}`}
|
||||
ref={chatFooterRef}
|
||||
style={{
|
||||
background: 'linear-gradient(0deg, #F9FAFB 40%, rgba(255, 255, 255, 0.00) 100%)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={chatFooterInnerRef}
|
||||
|
@ -33,10 +33,10 @@ const ImageLinkInput: FC<ImageLinkInputProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex items-center pl-1.5 pr-1 h-8 border border-gray-200 bg-white shadow-xs rounded-lg'>
|
||||
<div className='flex items-center pl-1.5 pr-1 h-8 border border-components-panel-border bg-components-panel-bg shadow-xs rounded-lg'>
|
||||
<input
|
||||
type="text"
|
||||
className='grow mr-0.5 px-1 h-[18px] text-[13px] outline-none appearance-none'
|
||||
className='grow mr-0.5 px-1 h-[18px] text-[13px] text-text-primary bg-transparent outline-none appearance-none'
|
||||
value={imageLink}
|
||||
onChange={e => setImageLink(e.target.value)}
|
||||
placeholder={t('common.imageUploader.pasteImageLinkInputPlaceholder') || ''}
|
||||
|
@ -119,12 +119,12 @@ const ImageList: FC<ImageListProps> = ({
|
||||
type="button"
|
||||
className={cn(
|
||||
'absolute z-10 -top-[9px] -right-[9px] items-center justify-center w-[18px] h-[18px]',
|
||||
'bg-white hover:bg-gray-50 border-[0.5px] border-black/2 rounded-2xl shadow-lg',
|
||||
'hover:bg-state-base-hover rounded-2xl shadow-lg',
|
||||
item.progress === -1 ? 'flex' : 'hidden group-hover:flex',
|
||||
)}
|
||||
onClick={() => onRemove && onRemove(item._id)}
|
||||
>
|
||||
<RiCloseLine className="w-3 h-3 text-gray-500" />
|
||||
<RiCloseLine className="w-3 h-3 text-text-tertiary" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
@ -50,7 +50,7 @@ const PasteImageLinkButton: FC<PasteImageLinkButtonProps> = ({
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={handleToggle}>
|
||||
<div className={`
|
||||
relative flex items-center justify-center px-3 h-8 bg-gray-100 hover:bg-gray-200 text-xs text-gray-500 rounded-lg
|
||||
relative flex items-center justify-center px-3 h-8 bg-components-option-card-option-bg hover:bg-components-option-card-option-bg-hover text-xs text-text-tertiary rounded-lg
|
||||
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
||||
`}>
|
||||
<Link03 className='mr-2 w-4 h-4' />
|
||||
@ -58,7 +58,7 @@ const PasteImageLinkButton: FC<PasteImageLinkButtonProps> = ({
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-10'>
|
||||
<div className='p-2 w-[320px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg'>
|
||||
<div className='p-2 w-[320px] bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-lg shadow-lg'>
|
||||
<ImageLinkInput onUpload={handleUpload} />
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
@ -98,9 +98,9 @@ const TextGenerationImageUploader: FC<TextGenerationImageUploaderProps> = ({
|
||||
{
|
||||
hovering => (
|
||||
<div className={`
|
||||
flex items-center justify-center px-3 h-8 bg-gray-100
|
||||
text-xs text-gray-500 rounded-lg cursor-pointer
|
||||
${hovering && 'bg-gray-200'}
|
||||
flex items-center justify-center px-3 h-8 bg-components-option-card-option-bg
|
||||
text-xs text-text-tertiary rounded-lg cursor-pointer
|
||||
${hovering && 'bg-components-option-card-option-bg-hover'}
|
||||
`}>
|
||||
<ImagePlus className='mr-2 w-4 h-4' />
|
||||
{t('common.imageUploader.uploadFromComputer')}
|
||||
|
@ -59,7 +59,7 @@ const Select: FC<ISelectProps> = ({
|
||||
disabled = false,
|
||||
onSelect,
|
||||
allowSearch = true,
|
||||
bgClassName = 'bg-gray-100',
|
||||
bgClassName = 'bg-components-input-bg-normal',
|
||||
overlayClassName,
|
||||
optionClassName,
|
||||
renderOption,
|
||||
@ -99,10 +99,10 @@ const Select: FC<ISelectProps> = ({
|
||||
}
|
||||
}}>
|
||||
<div className={classNames('relative')}>
|
||||
<div className='group text-gray-800'>
|
||||
<div className='group text-text-secondary'>
|
||||
{allowSearch
|
||||
? <Combobox.Input
|
||||
className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
|
||||
className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
|
||||
onChange={(event) => {
|
||||
if (!disabled)
|
||||
setQuery(event.target.value)
|
||||
@ -114,10 +114,10 @@ const Select: FC<ISelectProps> = ({
|
||||
if (!disabled)
|
||||
setOpen(!open)
|
||||
}
|
||||
} className={classNames(`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200`, optionClassName)}>
|
||||
} className={classNames(`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover`, optionClassName)}>
|
||||
<div className='w-0 grow text-left truncate' title={selectedItem?.name}>{selectedItem?.name}</div>
|
||||
</Combobox.Button>}
|
||||
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none group-hover:bg-gray-200" onClick={
|
||||
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none" onClick={
|
||||
() => {
|
||||
if (!disabled)
|
||||
setOpen(!open)
|
||||
@ -128,15 +128,15 @@ const Select: FC<ISelectProps> = ({
|
||||
</div>
|
||||
|
||||
{(filteredItems.length > 0 && open) && (
|
||||
<Combobox.Options className={`absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm ${overlayClassName}`}>
|
||||
<Combobox.Options className={`absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm ${overlayClassName}`}>
|
||||
{filteredItems.map((item: Item) => (
|
||||
<Combobox.Option
|
||||
key={item.value}
|
||||
value={item}
|
||||
className={({ active }: { active: boolean }) =>
|
||||
classNames(
|
||||
'relative cursor-default select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700',
|
||||
active ? 'bg-gray-100' : '',
|
||||
'relative cursor-default select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary',
|
||||
active ? 'bg-state-base-hover' : '',
|
||||
optionClassName,
|
||||
)
|
||||
}
|
||||
@ -151,7 +151,7 @@ const Select: FC<ISelectProps> = ({
|
||||
{selected && (
|
||||
<span
|
||||
className={classNames(
|
||||
'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700',
|
||||
'absolute inset-y-0 right-0 flex items-center pr-4 text-text-secondary',
|
||||
)}
|
||||
>
|
||||
<RiCheckLine className="h-4 w-4" aria-hidden="true" />
|
||||
|
@ -15,7 +15,7 @@ import { Users01, UsersPlus } from '@/app/components/base/icons/src/vender/solid
|
||||
import type { DatasetPermission } from '@/models/datasets'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import type { Member } from '@/models/common'
|
||||
export interface RoleSelectorProps {
|
||||
export type RoleSelectorProps = {
|
||||
disabled?: boolean
|
||||
permission?: DatasetPermission
|
||||
value: string[]
|
||||
@ -73,45 +73,45 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
|
||||
className='block'
|
||||
>
|
||||
{permission === 'only_me' && (
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200', disabled && 'hover:!bg-gray-100 !cursor-default')}>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-components-input-bg-normal cursor-pointer hover:bg-state-base-hover-alt', open && 'hover:bg-state-base-hover-alt', disabled && 'bg-components-input-bg-disabled hover:bg-components-input-bg-disabled !cursor-default')}>
|
||||
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0 mr-2' size={24} />
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-gray-700' />}
|
||||
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />}
|
||||
</div>
|
||||
)}
|
||||
{permission === 'all_team_members' && (
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-components-input-bg-normal cursor-pointer hover:bg-state-base-hover-alt', open && 'hover:bg-state-base-hover-alt')}>
|
||||
<div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'>
|
||||
<Users01 className='w-3.5 h-3.5 text-[#444CE7]' />
|
||||
</div>
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-gray-700' />}
|
||||
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />}
|
||||
</div>
|
||||
)}
|
||||
{permission === 'partial_members' && (
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-gray-100 cursor-pointer hover:bg-gray-200', open && 'bg-gray-200')}>
|
||||
<div className={cn('flex items-center px-3 py-[6px] rounded-lg bg-components-input-bg-normal cursor-pointer hover:bg-state-base-hover-alt', open && 'hover:bg-state-base-hover-alt')}>
|
||||
<div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'>
|
||||
<Users01 className='w-3.5 h-3.5 text-[#444CE7]' />
|
||||
</div>
|
||||
<div title={selectedMembers} className='grow mr-2 text-gray-900 text-sm leading-5 truncate'>{selectedMembers}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-gray-700' />}
|
||||
<div title={selectedMembers} className='grow mr-2 text-text-primary text-sm leading-5 truncate'>{selectedMembers}</div>
|
||||
{!disabled && <RiArrowDownSLine className='shrink-0 w-4 h-4 text-text-secondary' />}
|
||||
</div>
|
||||
)}
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[1002]'>
|
||||
<div className='relative w-[480px] rounded-lg border-[0.5px] bg-white shadow-lg'>
|
||||
<div className='relative w-[480px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur backdrop-blur-sm shadow-lg'>
|
||||
<div className='p-1'>
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-state-base-hover cursor-pointer' onClick={() => {
|
||||
onChange('only_me')
|
||||
setOpen(false)
|
||||
}}>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0 mr-2' size={24} />
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
|
||||
{permission === 'only_me' && <Check className='w-4 h-4 text-primary-600' />}
|
||||
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsOnlyMe')}</div>
|
||||
{permission === 'only_me' && <Check className='w-4 h-4 text-text-accent' />}
|
||||
</div>
|
||||
</div>
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-state-base-hover cursor-pointer' onClick={() => {
|
||||
onChange('all_team_members')
|
||||
setOpen(false)
|
||||
}}>
|
||||
@ -119,11 +119,11 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
|
||||
<div className='mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#EEF4FF]'>
|
||||
<Users01 className='w-3.5 h-3.5 text-[#444CE7]' />
|
||||
</div>
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
|
||||
{permission === 'all_team_members' && <Check className='w-4 h-4 text-primary-600' />}
|
||||
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsAllMember')}</div>
|
||||
{permission === 'all_team_members' && <Check className='w-4 h-4 text-text-accent' />}
|
||||
</div>
|
||||
</div>
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => {
|
||||
<div className='pl-3 pr-2 py-1 rounded-lg hover:bg-state-base-hover cursor-pointer' onClick={() => {
|
||||
onChange('partial_members')
|
||||
onMemberSelect([userProfile.id])
|
||||
}}>
|
||||
@ -131,14 +131,14 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
|
||||
<div className={cn('mr-2 flex items-center justify-center w-6 h-6 rounded-lg bg-[#FFF6ED]', permission === 'partial_members' && '!bg-[#EEF4FF]')}>
|
||||
<UsersPlus className={cn('w-3.5 h-3.5 text-[#FB6514]', permission === 'partial_members' && '!text-[#444CE7]')} />
|
||||
</div>
|
||||
<div className='grow mr-2 text-gray-900 text-sm leading-5'>{t('datasetSettings.form.permissionsInvitedMembers')}</div>
|
||||
{permission === 'partial_members' && <Check className='w-4 h-4 text-primary-600' />}
|
||||
<div className='grow mr-2 text-text-primary text-sm leading-5'>{t('datasetSettings.form.permissionsInvitedMembers')}</div>
|
||||
{permission === 'partial_members' && <Check className='w-4 h-4 text-text-accent' />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{permission === 'partial_members' && (
|
||||
<div className='max-h-[360px] border-t-[1px] border-gray-100 p-1 overflow-y-auto'>
|
||||
<div className='sticky left-0 top-0 p-2 pb-1 bg-white'>
|
||||
<div className='max-h-[360px] border-t-[1px] border-divider-regular p-1 overflow-y-auto'>
|
||||
<div className='sticky left-0 top-0 p-2 pb-1 bg-components-panel-bg-blur'>
|
||||
<Input
|
||||
showLeftIcon
|
||||
showClearIcon
|
||||
@ -151,23 +151,23 @@ const PermissionSelector = ({ disabled, permission, value, memberList, onChange,
|
||||
<div className='pl-3 pr-[10px] py-1 flex gap-2 items-center rounded-lg'>
|
||||
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} className='shrink-0' size={24} />
|
||||
<div className='grow'>
|
||||
<div className='text-[13px] text-gray-700 font-medium leading-[18px] truncate'>
|
||||
<div className='text-[13px] text-text-secondary font-medium leading-[18px] truncate'>
|
||||
{userProfile.name}
|
||||
<span className='text-xs text-gray-500 font-normal'>{t('datasetSettings.form.me')}</span>
|
||||
<span className='text-xs text-text-tertiary font-normal'>{t('datasetSettings.form.me')}</span>
|
||||
</div>
|
||||
<div className='text-xs text-gray-500 leading-[18px] truncate'>{userProfile.email}</div>
|
||||
<div className='text-xs text-text-tertiary leading-[18px] truncate'>{userProfile.email}</div>
|
||||
</div>
|
||||
<Check className='shrink-0 w-4 h-4 text-primary-600 opacity-30' />
|
||||
<Check className='shrink-0 w-4 h-4 text-text-accent opacity-30' />
|
||||
</div>
|
||||
)}
|
||||
{filteredMemberList.map(member => (
|
||||
<div key={member.id} className='pl-3 pr-[10px] py-1 flex gap-2 items-center rounded-lg hover:bg-gray-100 cursor-pointer' onClick={() => selectMember(member)}>
|
||||
<div key={member.id} className='pl-3 pr-[10px] py-1 flex gap-2 items-center rounded-lg hover:bg-state-base-hover cursor-pointer' onClick={() => selectMember(member)}>
|
||||
<Avatar avatar={userProfile.avatar_url} name={member.name} className='shrink-0' size={24} />
|
||||
<div className='grow'>
|
||||
<div className='text-[13px] text-gray-700 font-medium leading-[18px] truncate'>{member.name}</div>
|
||||
<div className='text-xs text-gray-500 leading-[18px] truncate'>{member.email}</div>
|
||||
<div className='text-[13px] text-text-secondary font-medium leading-[18px] truncate'>{member.name}</div>
|
||||
<div className='text-xs text-text-tertiary leading-[18px] truncate'>{member.email}</div>
|
||||
</div>
|
||||
{value.includes(member.id) && <Check className='shrink-0 w-4 h-4 text-primary-600' />}
|
||||
{value.includes(member.id) && <Check className='shrink-0 w-4 h-4 text-text-accent' />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
@ -174,35 +174,35 @@ const WorkflowToolConfigureButton = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='mt-2 pt-2 border-t-[0.5px] border-t-black/5'>
|
||||
<div className='mt-2 pt-2 border-t-[0.5px] border-divider-regular'>
|
||||
{(!published || !isLoading) && (
|
||||
<div className={cn(
|
||||
'group bg-gray-100 rounded-lg transition-colors',
|
||||
'group bg-background-section-burn rounded-lg transition-colors',
|
||||
disabled ? 'shadow-xs opacity-30 cursor-not-allowed' : 'cursor-pointer',
|
||||
!published && 'hover:bg-primary-50',
|
||||
)}>
|
||||
{isCurrentWorkspaceManager
|
||||
? (
|
||||
<div
|
||||
className='flex justify-start items-center gap-2 px-2.5 py-2'
|
||||
className='flex justify-start items-center text-text-primary gap-2 px-2.5 py-2'
|
||||
onClick={() => !published && setShowModal(true)}
|
||||
>
|
||||
<Tools className={cn('relative w-4 h-4', !published && 'group-hover:text-primary-600')} />
|
||||
<div title={t('workflow.common.workflowAsTool') || ''} className={cn('grow shrink basis-0 text-[13px] font-medium leading-[18px] truncate', !published && 'group-hover:text-primary-600')}>{t('workflow.common.workflowAsTool')}</div>
|
||||
{!published && (
|
||||
<span className='shrink-0 px-1 border border-black/8 rounded-[5px] bg-white text-[10px] font-medium leading-[18px] text-gray-500'>{t('workflow.common.configureRequired').toLocaleUpperCase()}</span>
|
||||
<span className='shrink-0 px-1 border border-divider-regular rounded-[5px] bg-background-default-subtle text-[10px] font-medium leading-[18px] text-text-tertiary'>{t('workflow.common.configureRequired').toLocaleUpperCase()}</span>
|
||||
)}
|
||||
</div>)
|
||||
: (
|
||||
<div
|
||||
className='flex justify-start items-center gap-2 px-2.5 py-2'
|
||||
>
|
||||
<Tools className='w-4 h-4 text-gray-500' />
|
||||
<div title={t('workflow.common.workflowAsTool') || ''} className='grow shrink basis-0 text-[13px] font-medium leading-[18px] truncate text-gray-500'>{t('workflow.common.workflowAsTool')}</div>
|
||||
<Tools className='w-4 h-4 text-text-tertiary' />
|
||||
<div title={t('workflow.common.workflowAsTool') || ''} className='grow shrink basis-0 text-[13px] font-medium leading-[18px] truncate text-text-tertiary'>{t('workflow.common.workflowAsTool')}</div>
|
||||
</div>
|
||||
)}
|
||||
{published && (
|
||||
<div className='px-2.5 py-2 border-t-[0.5px] border-black/5'>
|
||||
<div className='px-2.5 py-2 border-t-[0.5px] border-divider-regular'>
|
||||
<div className='flex justify-between'>
|
||||
<Button
|
||||
size='small'
|
||||
|
@ -95,15 +95,15 @@ const AllTools = ({
|
||||
|
||||
return (
|
||||
<div className={cn(className)}>
|
||||
<div className='flex items-center justify-between px-3 bg-background-default-hover border-b-[0.5px] border-black/[0.08] shadow-xs'>
|
||||
<div className='flex items-center justify-between px-3 bg-background-default-hover border-b-[0.5px] border-divider-subtle shadow-xs'>
|
||||
<div className='flex items-center h-8 space-x-1'>
|
||||
{
|
||||
tabs.map(tab => (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center px-2 h-6 rounded-md hover:bg-gray-100 cursor-pointer',
|
||||
'text-xs font-medium text-gray-700',
|
||||
activeTab === tab.key && 'bg-gray-200',
|
||||
'flex items-center px-2 h-6 rounded-md hover:bg-state-base-hover cursor-pointer',
|
||||
'text-xs font-medium text-text-secondary',
|
||||
activeTab === tab.key && 'bg-state-base-hover-alt',
|
||||
)}
|
||||
key={tab.key}
|
||||
onClick={() => setActiveTab(tab.key)}
|
||||
|
@ -137,7 +137,7 @@ const ToolPicker: FC<Props> = ({
|
||||
</PortalToFollowElemTrigger>
|
||||
|
||||
<PortalToFollowElemContent className='z-[1000]'>
|
||||
<div className="relative w-[356px] min-h-20 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg">
|
||||
<div className="relative w-[356px] min-h-20 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg">
|
||||
<div className='p-2 pb-1'>
|
||||
<SearchBox
|
||||
search={searchText}
|
||||
|
@ -35,8 +35,8 @@ const ToolItem: FC<Props> = ({
|
||||
type={BlockEnum.Tool}
|
||||
toolIcon={provider.icon}
|
||||
/>
|
||||
<div className='mb-1 text-sm leading-5 text-gray-900'>{payload.label[language]}</div>
|
||||
<div className='text-xs text-gray-700 leading-[18px]'>{payload.description[language]}</div>
|
||||
<div className='mb-1 text-sm leading-5 text-text-primary'>{payload.label[language]}</div>
|
||||
<div className='text-xs text-text-secondary leading-[18px]'>{payload.description[language]}</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
|
@ -22,7 +22,7 @@ const Item: FC<Props> = ({
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>
|
||||
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>
|
||||
{groupName}
|
||||
</div>
|
||||
<div>
|
||||
|
@ -68,7 +68,7 @@ const Tool: FC<Props> = ({
|
||||
>
|
||||
<div className={cn(className)}>
|
||||
<div
|
||||
className='flex items-center justify-between pl-3 pr-1 w-full rounded-lg hover:bg-gray-50 cursor-pointer select-none'
|
||||
className='flex items-center justify-between pl-3 pr-1 w-full rounded-lg hover:bg-state-base-hover cursor-pointer select-none'
|
||||
onClick={() => {
|
||||
if (hasAction)
|
||||
setFold(!isFold)
|
||||
@ -96,7 +96,7 @@ const Tool: FC<Props> = ({
|
||||
type={BlockEnum.Tool}
|
||||
toolIcon={payload.icon}
|
||||
/>
|
||||
<div className='ml-2 text-sm text-gray-900 flex-1 w-0 grow truncate'>{payload.label[language]}</div>
|
||||
<div className='ml-2 text-sm text-text-primary flex-1 w-0 grow truncate'>{payload.label[language]}</div>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center'>
|
||||
|
@ -4,7 +4,7 @@ import React from 'react'
|
||||
import { RiAlignLeft, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react'
|
||||
import { InputVarType } from '../../../types'
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
className?: string
|
||||
type: InputVarType
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ const translation = {
|
||||
edit: 'Edit annotation',
|
||||
},
|
||||
dataSet: {
|
||||
title: 'Context',
|
||||
title: 'Knowledge',
|
||||
noData: 'You can import Knowledge as context',
|
||||
words: 'Words',
|
||||
textBlocks: 'Text Blocks',
|
||||
|
@ -103,7 +103,7 @@ const translation = {
|
||||
edit: '编辑标注',
|
||||
},
|
||||
dataSet: {
|
||||
title: '上下文',
|
||||
title: '知识库',
|
||||
noData: '您可以导入知识库作为上下文',
|
||||
words: '词',
|
||||
textBlocks: '文本块',
|
||||
|
@ -60,11 +60,11 @@ const config = {
|
||||
...tailwindThemeVarDefine,
|
||||
},
|
||||
screens: {
|
||||
mobile: '100px',
|
||||
'mobile': '100px',
|
||||
// => @media (min-width: 100px) { ... }
|
||||
tablet: '640px', // 391
|
||||
'tablet': '640px', // 391
|
||||
// => @media (min-width: 600px) { ... }
|
||||
pc: '769px',
|
||||
'pc': '769px',
|
||||
// => @media (min-width: 769px) { ... }
|
||||
'2k': '2560px',
|
||||
},
|
||||
@ -87,6 +87,7 @@ const config = {
|
||||
backgroundImage: {
|
||||
'chatbot-bg': 'var(--color-chatbot-bg)',
|
||||
'chat-bubble-bg': 'var(--color-chat-bubble-bg)',
|
||||
'chat-input-mask': 'var(--color-chat-input-mask)',
|
||||
'workflow-process-bg': 'var(--color-workflow-process-bg)',
|
||||
'mask-top2bottom-gray-50-to-transparent': 'var(--mask-top2bottom-gray-50-to-transparent)',
|
||||
'marketplace-divider-bg': 'var(--color-marketplace-divider-bg)',
|
||||
|
@ -5,6 +5,9 @@ html[data-theme="dark"] {
|
||||
--color-chat-bubble-bg: linear-gradient(180deg,
|
||||
rgba(200, 206, 218, 0.08) 0%,
|
||||
rgba(200, 206, 218, 0.02) 100%);
|
||||
--color-chat-input-mask: linear-gradient(180deg,
|
||||
rgba(24, 24, 27, 0.04) 0%,
|
||||
rgba(24, 24, 27, 0.60) 100%);
|
||||
--color-workflow-process-bg: linear-gradient(90deg,
|
||||
rgba(24, 24, 27, 0.25) 0%,
|
||||
rgba(24, 24, 27, 0.04) 100%);
|
||||
|
@ -3,8 +3,11 @@ html[data-theme="light"] {
|
||||
rgba(249, 250, 251, 0.9) 0%,
|
||||
rgba(242, 244, 247, 0.9) 90.48%);
|
||||
--color-chat-bubble-bg: linear-gradient(180deg,
|
||||
#fff 0%,
|
||||
rgba(255, 255, 255, 0.6) 100%);
|
||||
#fff 0%,
|
||||
rgba(255, 255, 255, 0.6) 100%);
|
||||
--color-chat-input-mask: linear-gradient(180deg,
|
||||
rgba(255, 255, 255, 0.01) 0%,
|
||||
#F2F4F7 100%);
|
||||
--color-workflow-process-bg: linear-gradient(90deg,
|
||||
rgba(200, 206, 218, 0.2) 0%,
|
||||
rgba(200, 206, 218, 0.04) 100%);
|
||||
|
Loading…
Reference in New Issue
Block a user