mirror of
https://github.com/langgenius/dify.git
synced 2026-05-28 04:43:33 +08:00
fix: new components
This commit is contained in:
@ -3079,20 +3079,12 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/tools/edit-custom-collection-modal/get-schema.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/tools/edit-custom-collection-modal/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"react/set-state-in-effect": {
|
||||
"count": 4
|
||||
},
|
||||
|
||||
@ -141,18 +141,6 @@ describe('DuplicateAppModal', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
await user.click(screen.getByText('open-icon-picker'))
|
||||
await waitFor(() => {
|
||||
expect(screen.getByPlaceholderText('Search emojis...')).toBeInTheDocument()
|
||||
})
|
||||
const emojiButton = document.querySelector('em-emoji')?.closest('button')
|
||||
expect(emojiButton).toBeTruthy()
|
||||
await user.click(emojiButton!)
|
||||
await user.click(screen.getByRole('button', { name: '#E4FBCC' }))
|
||||
await user.click(screen.getByRole('button', { name: /iconPicker\.ok/ }))
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByPlaceholderText('Search emojis...')).not.toBeInTheDocument()
|
||||
})
|
||||
await user.click(screen.getByText('open-icon-picker'))
|
||||
await waitFor(() => {
|
||||
expect(screen.getByPlaceholderText('Search emojis...')).toBeInTheDocument()
|
||||
@ -165,9 +153,9 @@ describe('DuplicateAppModal', () => {
|
||||
|
||||
expect(onConfirm).toHaveBeenCalledWith(expect.objectContaining({
|
||||
name: 'Image App',
|
||||
icon_type: 'emoji',
|
||||
icon: expect.any(String),
|
||||
icon_background: '#E4FBCC',
|
||||
icon_type: 'image',
|
||||
icon: 'original-file',
|
||||
icon_background: undefined,
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
@ -14,12 +14,13 @@ import {
|
||||
} from '@langgenius/dify-ui/drawer'
|
||||
import { FieldItem, FieldLabel, FieldRoot } from '@langgenius/dify-ui/field'
|
||||
import { FieldsetLegend, FieldsetRoot } from '@langgenius/dify-ui/fieldset'
|
||||
import { Input } from '@langgenius/dify-ui/input'
|
||||
import { Radio } from '@langgenius/dify-ui/radio'
|
||||
import { RadioGroup } from '@langgenius/dify-ui/radio-group'
|
||||
import { ScrollArea } from '@langgenius/dify-ui/scroll-area'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Infotip } from '@/app/components/base/infotip'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { AuthHeaderPrefix, AuthType } from '@/app/components/tools/types'
|
||||
|
||||
type Props = {
|
||||
@ -41,11 +42,11 @@ function SelectItem({ text, value, isChecked }: ItemProps) {
|
||||
<FieldLabel
|
||||
className={cn(
|
||||
isChecked ? 'border-2 border-util-colors-indigo-indigo-600 bg-components-panel-on-panel-item-bg shadow-sm' : 'border border-components-card-border',
|
||||
'mb-2 flex h-9 w-37.5 cursor-pointer items-center space-x-2 rounded-xl bg-components-panel-on-panel-item-bg pl-3 text-left outline-hidden hover:bg-components-panel-on-panel-item-bg-hover focus-visible:ring-1 focus-visible:ring-components-input-border-hover',
|
||||
'flex h-9 w-full min-w-0 cursor-pointer items-center gap-2 rounded-xl bg-components-panel-on-panel-item-bg px-3 text-left outline-hidden hover:bg-components-panel-on-panel-item-bg-hover focus-visible:ring-1 focus-visible:ring-components-input-border-hover',
|
||||
)}
|
||||
>
|
||||
<Radio value={value} />
|
||||
<div className="system-sm-regular text-text-primary">{text}</div>
|
||||
<div className="min-w-0 truncate system-sm-regular text-text-primary">{text}</div>
|
||||
</FieldLabel>
|
||||
</FieldItem>
|
||||
)
|
||||
@ -104,7 +105,7 @@ export default function ConfigCredential({
|
||||
: 'data-[swipe-direction=right]:right-2',
|
||||
)}
|
||||
>
|
||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
||||
<DrawerContent className="flex min-h-0 flex-1 flex-col overflow-hidden p-0 pb-0">
|
||||
<div className="shrink-0 border-b border-divider-regular py-4">
|
||||
<div className="flex h-6 items-center justify-between pr-5 pl-6">
|
||||
<DrawerTitle className="min-w-0 truncate system-xl-semibold text-text-primary">
|
||||
@ -116,128 +117,132 @@ export default function ConfigCredential({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-6 pt-2">
|
||||
<div className="space-y-4">
|
||||
<FieldRoot name="auth_type" className="contents">
|
||||
<FieldsetRoot
|
||||
render={(
|
||||
<RadioGroup<AuthType>
|
||||
className="space-x-3"
|
||||
value={tempCredential.auth_type}
|
||||
onValueChange={handleAuthTypeChange}
|
||||
<ScrollArea
|
||||
className="min-h-0 flex-1 overflow-hidden"
|
||||
slotClassNames={{
|
||||
viewport: 'overscroll-contain',
|
||||
content: 'space-y-4 pt-2 pr-8 pl-6',
|
||||
}}
|
||||
>
|
||||
<FieldRoot name="auth_type" className="contents">
|
||||
<FieldsetRoot
|
||||
render={(
|
||||
<RadioGroup<AuthType>
|
||||
className="grid grid-cols-[repeat(auto-fit,minmax(8.5rem,1fr))] gap-2"
|
||||
value={tempCredential.auth_type}
|
||||
onValueChange={handleAuthTypeChange}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<FieldsetLegend className="col-span-full py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.type', { ns: 'tools' })}
|
||||
</FieldsetLegend>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.none', { ns: 'tools' })}
|
||||
value={AuthType.none}
|
||||
isChecked={tempCredential.auth_type === AuthType.none}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.api_key_header', { ns: 'tools' })}
|
||||
value={AuthType.apiKeyHeader}
|
||||
isChecked={tempCredential.auth_type === AuthType.apiKeyHeader}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.api_key_query', { ns: 'tools' })}
|
||||
value={AuthType.apiKeyQuery}
|
||||
isChecked={tempCredential.auth_type === AuthType.apiKeyQuery}
|
||||
/>
|
||||
</FieldsetRoot>
|
||||
</FieldRoot>
|
||||
{tempCredential.auth_type === AuthType.apiKeyHeader && (
|
||||
<>
|
||||
<FieldRoot name="api_key_header_prefix" className="contents">
|
||||
<FieldsetRoot
|
||||
render={(
|
||||
<RadioGroup<AuthHeaderPrefix>
|
||||
className="grid grid-cols-[repeat(auto-fit,minmax(8.5rem,1fr))] gap-2"
|
||||
value={tempCredential.api_key_header_prefix}
|
||||
onValueChange={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value })}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<FieldsetLegend className="col-span-full py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authHeaderPrefix.title', { ns: 'tools' })}
|
||||
</FieldsetLegend>
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.basic', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.basic}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.basic}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<FieldsetLegend className="py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.type', { ns: 'tools' })}
|
||||
</FieldsetLegend>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.none', { ns: 'tools' })}
|
||||
value={AuthType.none}
|
||||
isChecked={tempCredential.auth_type === AuthType.none}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.api_key_header', { ns: 'tools' })}
|
||||
value={AuthType.apiKeyHeader}
|
||||
isChecked={tempCredential.auth_type === AuthType.apiKeyHeader}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authMethod.types.api_key_query', { ns: 'tools' })}
|
||||
value={AuthType.apiKeyQuery}
|
||||
isChecked={tempCredential.auth_type === AuthType.apiKeyQuery}
|
||||
/>
|
||||
</FieldsetRoot>
|
||||
</FieldRoot>
|
||||
{tempCredential.auth_type === AuthType.apiKeyHeader && (
|
||||
<>
|
||||
<FieldRoot name="api_key_header_prefix" className="contents">
|
||||
<FieldsetRoot
|
||||
render={(
|
||||
<RadioGroup<AuthHeaderPrefix>
|
||||
className="space-x-3"
|
||||
value={tempCredential.api_key_header_prefix}
|
||||
onValueChange={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value })}
|
||||
/>
|
||||
)}
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.bearer', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.bearer}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.bearer}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.custom', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.custom}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.custom}
|
||||
/>
|
||||
</FieldsetRoot>
|
||||
</FieldRoot>
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.key', { ns: 'tools' })}
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 size-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
<FieldsetLegend className="py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authHeaderPrefix.title', { ns: 'tools' })}
|
||||
</FieldsetLegend>
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.basic', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.basic}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.basic}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.bearer', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.bearer}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.bearer}
|
||||
/>
|
||||
<SelectItem
|
||||
text={t('createTool.authHeaderPrefix.types.custom', { ns: 'tools' })}
|
||||
value={AuthHeaderPrefix.custom}
|
||||
isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.custom}
|
||||
/>
|
||||
</FieldsetRoot>
|
||||
</FieldRoot>
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.key', { ns: 'tools' })}
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 size-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
{t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_header}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_header: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiKeyPlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
{t('createTool.authMethod.keyTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<div>
|
||||
<div className="py-2 system-sm-medium text-text-primary">{t('createTool.authMethod.value', { ns: 'tools' })}</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_value}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiValuePlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
<Input
|
||||
value={tempCredential.api_key_header}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_header: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiKeyPlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="py-2 system-sm-medium text-text-primary">{t('createTool.authMethod.value', { ns: 'tools' })}</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_value}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiValuePlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{tempCredential.auth_type === AuthType.apiKeyQuery && (
|
||||
<>
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.queryParam', { ns: 'tools' })}
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 size-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
{t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{tempCredential.auth_type === AuthType.apiKeyQuery && (
|
||||
<>
|
||||
<div>
|
||||
<div className="flex items-center py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.authMethod.queryParam', { ns: 'tools' })}
|
||||
<Infotip
|
||||
aria-label={t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
className="ml-0.5 size-4"
|
||||
popupClassName="w-[261px] text-text-tertiary"
|
||||
>
|
||||
{t('createTool.authMethod.queryParamTooltip', { ns: 'tools' })}
|
||||
</Infotip>
|
||||
</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_query_param}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_query_param: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.queryParamPlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="py-2 system-sm-medium text-text-primary">{t('createTool.authMethod.value', { ns: 'tools' })}</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_value}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiValuePlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_query_param}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_query_param: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.queryParamPlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="py-2 system-sm-medium text-text-primary">{t('createTool.authMethod.value', { ns: 'tools' })}</div>
|
||||
<Input
|
||||
value={tempCredential.api_key_value}
|
||||
onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })}
|
||||
placeholder={t('createTool.authMethod.types.apiValuePlaceholder', { ns: 'tools' })!}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</ScrollArea>
|
||||
<div className="mt-4 flex shrink-0 justify-end space-x-2 px-6 py-4">
|
||||
<Button onClick={onHide}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
<Button
|
||||
|
||||
@ -13,6 +13,8 @@ import {
|
||||
DrawerTitle,
|
||||
DrawerViewport,
|
||||
} from '@langgenius/dify-ui/drawer'
|
||||
import { Input } from '@langgenius/dify-ui/input'
|
||||
import { ScrollArea } from '@langgenius/dify-ui/scroll-area'
|
||||
import { Textarea } from '@langgenius/dify-ui/textarea'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { RiSettings2Line } from '@remixicon/react'
|
||||
@ -23,7 +25,6 @@ import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import EmojiPicker from '@/app/components/base/emoji-picker'
|
||||
import Input from '@/app/components/base/input'
|
||||
import LabelSelector from '@/app/components/tools/labels/selector'
|
||||
import { parseParamsSchema } from '@/service/tools'
|
||||
import { LinkExternal02 } from '../../base/icons/src/vender/line/general'
|
||||
@ -220,7 +221,7 @@ const EditCustomCollectionModal: FC<Props> = ({
|
||||
: 'data-[swipe-direction=right]:right-2',
|
||||
)}
|
||||
>
|
||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
||||
<DrawerContent className="flex min-h-0 flex-1 flex-col overflow-hidden p-0 pb-0">
|
||||
<div className="shrink-0 border-b border-divider-regular py-4">
|
||||
<div className="flex h-6 items-center justify-between pr-5 pl-6">
|
||||
<DrawerTitle className="min-w-0 truncate system-xl-semibold text-text-primary">
|
||||
@ -233,8 +234,14 @@ const EditCustomCollectionModal: FC<Props> = ({
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-0 flex-1">
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="h-0 grow space-y-4 overflow-y-auto px-6 py-3">
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<ScrollArea
|
||||
className="min-h-0 flex-1 overflow-hidden"
|
||||
slotClassNames={{
|
||||
viewport: 'overscroll-contain',
|
||||
content: 'space-y-4 py-3 pr-8 pl-6',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div className="py-2 system-sm-medium text-text-primary">
|
||||
{t('createTool.name', { ns: 'tools' })}
|
||||
@ -373,7 +380,7 @@ const EditCustomCollectionModal: FC<Props> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ScrollArea>
|
||||
<div className={cn(isEdit ? 'justify-between' : 'justify-end', 'mt-2 flex shrink-0 rounded-b-[10px] border-t border-divider-regular bg-background-section-burn px-6 py-4')}>
|
||||
{
|
||||
isEdit && (
|
||||
|
||||
Reference in New Issue
Block a user