merge feat/tool-oauth
commit
b0f81b5c4e
@ -0,0 +1,78 @@
|
|||||||
|
'use client'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React, { useCallback } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import produce from 'immer'
|
||||||
|
import { useContext } from 'use-context-selector'
|
||||||
|
|
||||||
|
import { Microphone01 } from '@/app/components/base/icons/src/vender/features'
|
||||||
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
|
import ConfigContext from '@/context/debug-configuration'
|
||||||
|
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||||
|
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||||
|
import Switch from '@/app/components/base/switch'
|
||||||
|
|
||||||
|
const ConfigAudio: FC = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const file = useFeatures(s => s.features.file)
|
||||||
|
const featuresStore = useFeaturesStore()
|
||||||
|
const { isShowAudioConfig } = useContext(ConfigContext)
|
||||||
|
|
||||||
|
const isAudioEnabled = file?.allowed_file_types?.includes(SupportUploadFileTypes.audio) ?? false
|
||||||
|
|
||||||
|
const handleChange = useCallback((value: boolean) => {
|
||||||
|
const {
|
||||||
|
features,
|
||||||
|
setFeatures,
|
||||||
|
} = featuresStore!.getState()
|
||||||
|
|
||||||
|
const newFeatures = produce(features, (draft) => {
|
||||||
|
if (value) {
|
||||||
|
draft.file!.allowed_file_types = Array.from(new Set([
|
||||||
|
...(draft.file?.allowed_file_types || []),
|
||||||
|
SupportUploadFileTypes.audio,
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
draft.file!.allowed_file_types = draft.file!.allowed_file_types?.filter(
|
||||||
|
type => type !== SupportUploadFileTypes.audio,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (draft.file)
|
||||||
|
draft.file.enabled = (draft.file.allowed_file_types?.length ?? 0) > 0
|
||||||
|
})
|
||||||
|
setFeatures(newFeatures)
|
||||||
|
}, [featuresStore])
|
||||||
|
|
||||||
|
if (!isShowAudioConfig)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-2 flex items-center gap-2 rounded-xl border-l-[0.5px] border-t-[0.5px] bg-background-section-burn p-2'>
|
||||||
|
<div className='shrink-0 p-1'>
|
||||||
|
<div className='rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-violet-violet-600 p-1 shadow-xs'>
|
||||||
|
<Microphone01 className='h-4 w-4 text-text-primary-on-surface' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex grow items-center'>
|
||||||
|
<div className='system-sm-semibold mr-1 text-text-secondary'>{t('appDebug.feature.audioUpload.title')}</div>
|
||||||
|
<Tooltip
|
||||||
|
popupContent={
|
||||||
|
<div className='w-[180px]' >
|
||||||
|
{t('appDebug.feature.audioUpload.description')}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='flex shrink-0 items-center'>
|
||||||
|
<div className='ml-1 mr-3 h-3.5 w-[1px] bg-divider-subtle'></div>
|
||||||
|
<Switch
|
||||||
|
defaultValue={isAudioEnabled}
|
||||||
|
onChange={handleChange}
|
||||||
|
size='md'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default React.memo(ConfigAudio)
|
||||||
@ -1,5 +1,6 @@
|
|||||||
export { default as PluginAuth } from './plugin-auth'
|
export { default as PluginAuth } from './plugin-auth'
|
||||||
export { default as Authorized } from './authorized'
|
export { default as Authorized } from './authorized'
|
||||||
export { default as AuthorizedInNode } from './authorized-in-node'
|
export { default as AuthorizedInNode } from './authorized-in-node'
|
||||||
|
export { default as PluginAuthInAgent } from './plugin-auth-in-agent'
|
||||||
export { usePluginAuth } from './hooks/use-plugin-auth'
|
export { usePluginAuth } from './hooks/use-plugin-auth'
|
||||||
export * from './types'
|
export * from './types'
|
||||||
|
|||||||
@ -0,0 +1,120 @@
|
|||||||
|
import {
|
||||||
|
memo,
|
||||||
|
useCallback,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
|
import { RiArrowDownSLine } from '@remixicon/react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Authorize from './authorize'
|
||||||
|
import Authorized from './authorized'
|
||||||
|
import type {
|
||||||
|
Credential,
|
||||||
|
PluginPayload,
|
||||||
|
} from './types'
|
||||||
|
import { usePluginAuth } from './hooks/use-plugin-auth'
|
||||||
|
import Button from '@/app/components/base/button'
|
||||||
|
import Indicator from '@/app/components/header/indicator'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
|
type PluginAuthInAgentProps = {
|
||||||
|
pluginPayload: PluginPayload
|
||||||
|
credentialId?: string
|
||||||
|
onAuthorizationItemClick?: (id: string) => void
|
||||||
|
}
|
||||||
|
const PluginAuthInAgent = ({
|
||||||
|
pluginPayload,
|
||||||
|
credentialId,
|
||||||
|
onAuthorizationItemClick,
|
||||||
|
}: PluginAuthInAgentProps) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
const {
|
||||||
|
isAuthorized,
|
||||||
|
canOAuth,
|
||||||
|
canApiKey,
|
||||||
|
credentials,
|
||||||
|
disabled,
|
||||||
|
} = usePluginAuth(pluginPayload, true)
|
||||||
|
|
||||||
|
const extraAuthorizationItems: Credential[] = [
|
||||||
|
{
|
||||||
|
id: '__workspace_default__',
|
||||||
|
name: t('plugin.auth.workspaceDefault'),
|
||||||
|
provider: '',
|
||||||
|
is_default: !credentialId,
|
||||||
|
isWorkspaceDefault: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const handleAuthorizationItemClick = useCallback((id: string) => {
|
||||||
|
onAuthorizationItemClick?.(id)
|
||||||
|
setIsOpen(false)
|
||||||
|
}, [
|
||||||
|
onAuthorizationItemClick,
|
||||||
|
setIsOpen,
|
||||||
|
])
|
||||||
|
|
||||||
|
const renderTrigger = useCallback((isOpen?: boolean) => {
|
||||||
|
let label = ''
|
||||||
|
let removed = false
|
||||||
|
if (!credentialId) {
|
||||||
|
label = t('plugin.auth.workspaceDefault')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const credential = credentials.find(c => c.id === credentialId)
|
||||||
|
label = credential ? credential.name : t('plugin.auth.authRemoved')
|
||||||
|
removed = !credential
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
className={cn(
|
||||||
|
'w-full',
|
||||||
|
isOpen && 'bg-components-button-secondary-bg-hover',
|
||||||
|
removed && 'text-text-destructive',
|
||||||
|
)}>
|
||||||
|
<Indicator
|
||||||
|
className='mr-2'
|
||||||
|
color={removed ? 'red' : 'green'}
|
||||||
|
/>
|
||||||
|
{label}
|
||||||
|
<RiArrowDownSLine className='ml-0.5 h-4 w-4' />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}, [credentialId, credentials, t])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
!isAuthorized && (
|
||||||
|
<Authorize
|
||||||
|
pluginPayload={pluginPayload}
|
||||||
|
canOAuth={canOAuth}
|
||||||
|
canApiKey={canApiKey}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
isAuthorized && (
|
||||||
|
<Authorized
|
||||||
|
pluginPayload={pluginPayload}
|
||||||
|
credentials={credentials}
|
||||||
|
canOAuth={canOAuth}
|
||||||
|
canApiKey={canApiKey}
|
||||||
|
disabled={disabled}
|
||||||
|
disableSetDefault
|
||||||
|
onItemClick={handleAuthorizationItemClick}
|
||||||
|
extraAuthorizationItems={extraAuthorizationItems}
|
||||||
|
showItemSelectedIcon
|
||||||
|
renderTrigger={renderTrigger}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onOpenChange={setIsOpen}
|
||||||
|
selectedCredentialId={credentialId || '__workspace_default__'}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(PluginAuthInAgent)
|
||||||
Loading…
Reference in New Issue