mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
merge main
This commit is contained in:
@ -88,10 +88,10 @@ const HeaderOptions: FC<Props> = ({
|
||||
await clearAllAnnotations(appId)
|
||||
onAdded()
|
||||
}
|
||||
catch (_) {
|
||||
catch (_) {
|
||||
}
|
||||
finally {
|
||||
setShowClearConfirm(false)
|
||||
finally {
|
||||
setShowClearConfirm(false)
|
||||
}
|
||||
}
|
||||
const Operations = () => {
|
||||
@ -146,7 +146,7 @@ catch (_) {
|
||||
onClick={handleClearAll}
|
||||
className='mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 text-red-600 hover:bg-red-50 disabled:opacity-50'
|
||||
>
|
||||
<RiDeleteBinLine className='h-4 w-4'/>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
<span className='system-sm-regular grow text-left'>
|
||||
{t('appAnnotation.table.header.clearAll')}
|
||||
</span>
|
||||
@ -168,11 +168,9 @@ catch (_) {
|
||||
position="br"
|
||||
trigger="click"
|
||||
btnElement={
|
||||
<Button variant='secondary' className='w-8 p-0'>
|
||||
<RiMoreFill className='h-4 w-4' />
|
||||
</Button>
|
||||
<RiMoreFill className='h-4 w-4' />
|
||||
}
|
||||
btnClassName='p-0 border-0'
|
||||
btnClassName='btn btn-secondary btn-medium w-8 p-0'
|
||||
className={'!z-20 h-fit !w-[155px]'}
|
||||
popupClassName='!w-full !overflow-visible'
|
||||
manualClose
|
||||
@ -196,12 +194,12 @@ catch (_) {
|
||||
)
|
||||
}
|
||||
{
|
||||
showClearConfirm && (
|
||||
<ClearAllAnnotationsConfirmModal
|
||||
isShow={showClearConfirm}
|
||||
onHide={() => setShowClearConfirm(false)}
|
||||
onConfirm={handleConfirmed}
|
||||
/>
|
||||
showClearConfirm && (
|
||||
<ClearAllAnnotationsConfirmModal
|
||||
isShow={showClearConfirm}
|
||||
onHide={() => setShowClearConfirm(false)}
|
||||
onConfirm={handleConfirmed}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -22,14 +22,14 @@ const WarningMask: FC<IWarningMaskProps> = ({
|
||||
footer,
|
||||
}) => {
|
||||
return (
|
||||
<div className={`${s.mask} absolute inset-0 z-10 pt-16`}
|
||||
<div className={`${s.mask} absolute inset-0 z-10 bg-components-panel-bg-blur pt-16`}
|
||||
>
|
||||
<div className='mx-auto px-10'>
|
||||
<div className={`${s.icon} flex h-11 w-11 items-center justify-center rounded-xl bg-white`}>{warningIcon}</div>
|
||||
<div className='mt-4 text-[24px] font-semibold leading-normal text-gray-800'>
|
||||
<div className={`${s.icon} flex h-11 w-11 items-center justify-center rounded-xl bg-components-panel-bg`}>{warningIcon}</div>
|
||||
<div className='mt-4 text-[24px] font-semibold leading-normal text-text-primary'>
|
||||
{title}
|
||||
</div>
|
||||
<div className='mt-3 text-base text-gray-500'>
|
||||
<div className='mt-3 text-base text-text-secondary'>
|
||||
{description}
|
||||
</div>
|
||||
<div className='mt-6'>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
.mask {
|
||||
background-color: rgba(239, 244, 255, 0.9);
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
|
||||
@ -244,6 +244,7 @@ const ConfigModal: FC<IConfigModalProps> = ({
|
||||
<SimpleSelect
|
||||
key={`default-select-${options.join('-')}`}
|
||||
className="w-full"
|
||||
optionWrapClassName="max-h-[140px] overflow-y-auto"
|
||||
items={[
|
||||
{ value: '', name: t('appDebug.variableConfig.noDefaultValue') },
|
||||
...options.filter(opt => opt.trim() !== '').map(option => ({
|
||||
|
||||
@ -11,6 +11,7 @@ import PureSelect from '@/app/components/base/select/pure'
|
||||
import type { FormSchema } from '@/app/components/base/form/types'
|
||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
import RadioE from '@/app/components/base/radio/ui'
|
||||
|
||||
export type BaseFieldProps = {
|
||||
fieldClassName?: string
|
||||
@ -57,8 +58,27 @@ const BaseField = ({
|
||||
if (typeof placeholder === 'object' && placeholder !== null)
|
||||
return renderI18nObject(placeholder as Record<string, string>)
|
||||
}, [placeholder, renderI18nObject])
|
||||
const optionValues = useStore(field.form.store, (s) => {
|
||||
const result: Record<string, any> = {}
|
||||
options?.forEach((option) => {
|
||||
if (option.show_on?.length) {
|
||||
option.show_on.forEach((condition) => {
|
||||
result[condition.variable] = s.values[condition.variable]
|
||||
})
|
||||
}
|
||||
})
|
||||
return result
|
||||
})
|
||||
const memorizedOptions = useMemo(() => {
|
||||
return options?.map((option) => {
|
||||
return options?.filter((option) => {
|
||||
if (!option.show_on?.length)
|
||||
return true
|
||||
|
||||
return option.show_on.every((condition) => {
|
||||
const conditionValue = optionValues[condition.variable]
|
||||
return conditionValue === condition.value
|
||||
})
|
||||
}).map((option) => {
|
||||
return {
|
||||
label: typeof option.label === 'string' ? option.label : renderI18nObject(option.label),
|
||||
value: option.value,
|
||||
@ -151,17 +171,28 @@ const BaseField = ({
|
||||
}
|
||||
{
|
||||
formSchema.type === FormTypeEnum.radio && (
|
||||
<div className='flex items-center space-x-2'>
|
||||
<div className={cn(
|
||||
memorizedOptions.length < 3 ? 'flex items-center space-x-2' : 'space-y-2',
|
||||
)}>
|
||||
{
|
||||
memorizedOptions.map(option => (
|
||||
<div
|
||||
key={option.value}
|
||||
className={cn(
|
||||
'system-sm-regular hover:bg-components-option-card-option-hover-bg hover:border-components-option-card-option-hover-border flex h-8 grow cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg p-2 text-text-secondary',
|
||||
'system-sm-regular hover:bg-components-option-card-option-hover-bg hover:border-components-option-card-option-hover-border flex h-8 flex-[1] grow cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg p-2 text-text-secondary',
|
||||
value === option.value && 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary shadow-xs',
|
||||
inputClassName,
|
||||
)}
|
||||
onClick={() => field.handleChange(option.value)}
|
||||
>
|
||||
{
|
||||
formSchema.showRadioUI && (
|
||||
<RadioE
|
||||
className='mr-2'
|
||||
isChecked={value === option.value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{option.label}
|
||||
</div>
|
||||
))
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
memo,
|
||||
useCallback,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import type {
|
||||
AnyFieldApi,
|
||||
@ -45,8 +46,18 @@ const BaseForm = ({
|
||||
disabled,
|
||||
formFromProps,
|
||||
}: BaseFormProps) => {
|
||||
const initialDefaultValues = useMemo(() => {
|
||||
if (defaultValues)
|
||||
return defaultValues
|
||||
|
||||
return formSchemas.reduce((acc, schema) => {
|
||||
if (schema.default)
|
||||
acc[schema.name] = schema.default
|
||||
return acc
|
||||
}, {} as Record<string, any>)
|
||||
}, [defaultValues])
|
||||
const formFromHook = useForm({
|
||||
defaultValues,
|
||||
defaultValues: initialDefaultValues,
|
||||
})
|
||||
const form: any = formFromProps || formFromHook
|
||||
const { getFormValues } = useGetFormValues(form, formSchemas)
|
||||
|
||||
@ -7,6 +7,7 @@ const AuthForm = ({
|
||||
defaultValues,
|
||||
ref,
|
||||
formFromProps,
|
||||
...rest
|
||||
}: BaseFormProps) => {
|
||||
return (
|
||||
<BaseForm
|
||||
@ -16,6 +17,7 @@ const AuthForm = ({
|
||||
formClassName='space-y-4'
|
||||
labelClassName='h-6 flex items-center mb-1 system-sm-medium text-text-secondary'
|
||||
formFromProps={formFromProps}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ export type FormSchema = {
|
||||
options?: FormOption[]
|
||||
labelClassName?: string
|
||||
validators?: AnyValidators
|
||||
showRadioUI?: boolean
|
||||
}
|
||||
|
||||
export type FormValues = Record<string, any>
|
||||
|
||||
@ -77,7 +77,6 @@ const Select: FC<ISelectProps> = ({
|
||||
defaultSelect = existed
|
||||
|
||||
setSelectedItem(defaultSelect)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultValue])
|
||||
|
||||
const filteredItems: Item[]
|
||||
@ -201,7 +200,6 @@ const SimpleSelect: FC<ISelectProps> = ({
|
||||
defaultSelect = existed
|
||||
|
||||
setSelectedItem(defaultSelect)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [defaultValue])
|
||||
|
||||
const listboxRef = useRef<HTMLDivElement>(null)
|
||||
@ -344,7 +342,7 @@ const PortalSelect: FC<PortalSelectProps> = ({
|
||||
>
|
||||
<span
|
||||
className={`
|
||||
grow truncate
|
||||
grow truncate text-text-secondary
|
||||
${!selectedItem?.name && 'text-components-input-text-placeholder'}
|
||||
`}
|
||||
>
|
||||
|
||||
@ -39,7 +39,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
destructive && 'border-components-input-border-destructive bg-components-input-bg-destructive text-components-input-text-filled hover:border-components-input-border-destructive hover:bg-components-input-bg-destructive focus:border-components-input-border-destructive focus:bg-components-input-bg-destructive',
|
||||
className,
|
||||
)}
|
||||
value={value}
|
||||
value={value ?? ''}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
|
||||
@ -66,7 +66,9 @@ const RunOnce: FC<IRunOnceProps> = ({
|
||||
useEffect(() => {
|
||||
const newInputs: Record<string, any> = {}
|
||||
promptConfig.prompt_variables.forEach((item) => {
|
||||
if (item.type === 'string' || item.type === 'paragraph')
|
||||
if (item.type === 'select')
|
||||
newInputs[item.key] = item.default
|
||||
else if (item.type === 'string' || item.type === 'paragraph')
|
||||
newInputs[item.key] = ''
|
||||
else
|
||||
newInputs[item.key] = undefined
|
||||
|
||||
@ -179,8 +179,8 @@ const WorkflowToolConfigureButton = ({
|
||||
{(!published || !isLoading) && (
|
||||
<div className={cn(
|
||||
'group rounded-lg bg-background-section-burn transition-colors',
|
||||
disabled ? 'cursor-not-allowed opacity-30 shadow-xs' : 'cursor-pointer',
|
||||
!disabled && !published && 'hover:bg-state-accent-hover',
|
||||
disabled || !isCurrentWorkspaceManager ? 'cursor-not-allowed opacity-60 shadow-xs' : 'cursor-pointer',
|
||||
!disabled && !published && isCurrentWorkspaceManager && 'hover:bg-state-accent-hover',
|
||||
)}>
|
||||
{isCurrentWorkspaceManager
|
||||
? (
|
||||
|
||||
@ -198,7 +198,7 @@ const FormInputItem: FC<Props> = ({
|
||||
<Input
|
||||
className='h-8 grow'
|
||||
type='number'
|
||||
value={varInput?.value || ''}
|
||||
value={Number.isNaN(varInput?.value) ? '' : varInput?.value}
|
||||
onChange={e => handleValueChange(e.target.value)}
|
||||
placeholder={placeholder?.[language] || placeholder?.en_US}
|
||||
/>
|
||||
|
||||
@ -64,55 +64,56 @@ const ClassList: FC<Props> = ({
|
||||
const handleSideWidth = 3
|
||||
// Todo Remove; edit topic name
|
||||
return (
|
||||
<ReactSortable
|
||||
list={list.map(item => ({ ...item }))}
|
||||
setList={handleSortTopic}
|
||||
handle='.handle'
|
||||
ghostClass='bg-components-panel-bg'
|
||||
animation={150}
|
||||
disabled={readonly}
|
||||
className='space-y-2'
|
||||
>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
const canDrag = (() => {
|
||||
if (readonly)
|
||||
return false
|
||||
<>
|
||||
<ReactSortable
|
||||
list={list.map(item => ({ ...item }))}
|
||||
setList={handleSortTopic}
|
||||
handle='.handle'
|
||||
ghostClass='bg-components-panel-bg'
|
||||
animation={150}
|
||||
disabled={readonly}
|
||||
className='space-y-2'
|
||||
>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
const canDrag = (() => {
|
||||
if (readonly)
|
||||
return false
|
||||
|
||||
return topicCount >= 2
|
||||
})()
|
||||
return (
|
||||
<div key={item.id}
|
||||
className={cn(
|
||||
'group relative rounded-[10px] bg-components-panel-bg',
|
||||
`-ml-${handleSideWidth} min-h-[40px] px-0 py-0`,
|
||||
)}>
|
||||
<div >
|
||||
<Item
|
||||
className={cn(canDrag && 'handle')}
|
||||
headerClassName={cn(canDrag && 'cursor-grab')}
|
||||
nodeId={nodeId}
|
||||
key={list[index].id}
|
||||
payload={item}
|
||||
onChange={handleClassChange(index)}
|
||||
onRemove={handleRemoveClass(index)}
|
||||
index={index + 1}
|
||||
readonly={readonly}
|
||||
filterVar={filterVar}
|
||||
/>
|
||||
return topicCount >= 2
|
||||
})()
|
||||
return (
|
||||
<div key={item.id}
|
||||
className={cn(
|
||||
'group relative rounded-[10px] bg-components-panel-bg',
|
||||
`-ml-${handleSideWidth} min-h-[40px] px-0 py-0`,
|
||||
)}>
|
||||
<div >
|
||||
<Item
|
||||
className={cn(canDrag && 'handle')}
|
||||
headerClassName={cn(canDrag && 'cursor-grab')}
|
||||
nodeId={nodeId}
|
||||
key={list[index].id}
|
||||
payload={item}
|
||||
onChange={handleClassChange(index)}
|
||||
onRemove={handleRemoveClass(index)}
|
||||
index={index + 1}
|
||||
readonly={readonly}
|
||||
filterVar={filterVar}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
</ReactSortable>
|
||||
{!readonly && (
|
||||
<AddButton
|
||||
onClick={handleAddClass}
|
||||
text={t(`${i18nPrefix}.addClass`)}
|
||||
/>
|
||||
)}
|
||||
|
||||
</ReactSortable>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default React.memo(ClassList)
|
||||
|
||||
@ -22,13 +22,13 @@ const Node: FC<NodeProps<ToolNodeType>> = ({
|
||||
{key}
|
||||
</div>
|
||||
{typeof tool_configurations[key].value === 'string' && (
|
||||
<div title={tool_configurations[key]} className='w-0 shrink-0 grow truncate text-right text-xs font-normal text-text-secondary'>
|
||||
<div title={tool_configurations[key].value} className='w-0 shrink-0 grow truncate text-right text-xs font-normal text-text-secondary'>
|
||||
{paramSchemas?.find(i => i.name === key)?.type === FormTypeEnum.secretInput ? '********' : tool_configurations[key].value}
|
||||
</div>
|
||||
)}
|
||||
{typeof tool_configurations[key].value === 'number' && (
|
||||
<div title={tool_configurations[key].toString()} className='w-0 shrink-0 grow truncate text-right text-xs font-normal text-text-secondary'>
|
||||
{tool_configurations[key].value}
|
||||
<div title={Number.isNaN(tool_configurations[key].value) ? '' : tool_configurations[key].value} className='w-0 shrink-0 grow truncate text-right text-xs font-normal text-text-secondary'>
|
||||
{Number.isNaN(tool_configurations[key].value) ? '' : tool_configurations[key].value}
|
||||
</div>
|
||||
)}
|
||||
{typeof tool_configurations[key] !== 'string' && tool_configurations[key]?.type === FormTypeEnum.modelSelector && (
|
||||
|
||||
@ -14,6 +14,7 @@ const TipPopup = ({
|
||||
}: TipPopupProps) => {
|
||||
return (
|
||||
<Tooltip
|
||||
needsDelay={false}
|
||||
offset={4}
|
||||
popupClassName='p-0 bg-transparent'
|
||||
popupContent={
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -32,9 +33,12 @@ type Props = {
|
||||
const InputsPanel = ({ onRun }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { inputs, setInputs } = useStore(s => ({
|
||||
inputs: s.inputs,
|
||||
setInputs: s.setInputs,
|
||||
}))
|
||||
const fileSettings = useFeatures(s => s.features.file)
|
||||
const nodes = useNodes<StartNodeType>()
|
||||
const inputs = useStore(s => s.inputs)
|
||||
const files = useStore(s => s.files)
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const {
|
||||
@ -44,6 +48,24 @@ const InputsPanel = ({ onRun }: Props) => {
|
||||
const startVariables = startNode?.data.variables
|
||||
const { checkInputsForm } = useCheckInputsForms()
|
||||
|
||||
const initialInputs = useMemo(() => {
|
||||
const initInputs: Record<string, any> = {}
|
||||
if (startVariables) {
|
||||
startVariables.forEach((variable) => {
|
||||
if (variable.default)
|
||||
initInputs[variable.variable] = variable.default
|
||||
})
|
||||
}
|
||||
return initInputs
|
||||
}, [startVariables])
|
||||
|
||||
useEffect(() => {
|
||||
setInputs({
|
||||
...initialInputs,
|
||||
...inputs,
|
||||
})
|
||||
}, [initialInputs])
|
||||
|
||||
const variables = useMemo(() => {
|
||||
const data = startVariables || []
|
||||
if (fileSettings?.image?.enabled) {
|
||||
|
||||
Reference in New Issue
Block a user