pull/22493/head
zxhlyh 7 months ago
parent 964e29b27f
commit 3f273cae73

@ -87,7 +87,7 @@ const BaseField = ({
<div className={cn(labelClassName, formLabelClassName)}> <div className={cn(labelClassName, formLabelClassName)}>
{memorizedLabel} {memorizedLabel}
{ {
required && ( required && !isValidElement(label) && (
<span className='ml-1 text-text-destructive-secondary'>*</span> <span className='ml-1 text-text-destructive-secondary'>*</span>
) )
} }

@ -5,6 +5,7 @@ import {
} from 'react' } from 'react'
import type { import type {
AnyFieldApi, AnyFieldApi,
AnyFormApi,
} from '@tanstack/react-form' } from '@tanstack/react-form'
import { useForm } from '@tanstack/react-form' import { useForm } from '@tanstack/react-form'
import type { import type {
@ -29,6 +30,7 @@ export type BaseFormProps = {
formClassName?: string formClassName?: string
ref?: FormRef ref?: FormRef
disabled?: boolean disabled?: boolean
formFromProps?: AnyFormApi
} & Pick<BaseFieldProps, 'fieldClassName' | 'labelClassName' | 'inputContainerClassName' | 'inputClassName'> } & Pick<BaseFieldProps, 'fieldClassName' | 'labelClassName' | 'inputContainerClassName' | 'inputClassName'>
const BaseForm = ({ const BaseForm = ({
@ -41,10 +43,12 @@ const BaseForm = ({
inputClassName, inputClassName,
ref, ref,
disabled, disabled,
formFromProps,
}: BaseFormProps) => { }: BaseFormProps) => {
const form = useForm({ const formFromHook = useForm({
defaultValues, defaultValues,
}) })
const form: any = formFromProps || formFromHook
const { getFormValues } = useGetFormValues(form) const { getFormValues } = useGetFormValues(form)
const { getValidators } = useGetValidators() const { getValidators } = useGetValidators()
@ -102,10 +106,6 @@ const BaseForm = ({
return ( return (
<form <form
className={cn(formClassName)} className={cn(formClassName)}
onSubmit={(e) => {
e.preventDefault()
form?.handleSubmit()
}}
> >
{formSchemas.map(renderFieldWrapper)} {formSchemas.map(renderFieldWrapper)}
</form> </form>

@ -6,6 +6,7 @@ const AuthForm = ({
formSchemas = [], formSchemas = [],
defaultValues, defaultValues,
ref, ref,
formFromProps,
}: BaseFormProps) => { }: BaseFormProps) => {
return ( return (
<BaseForm <BaseForm
@ -14,6 +15,7 @@ const AuthForm = ({
defaultValues={defaultValues} defaultValues={defaultValues}
formClassName='space-y-4' formClassName='space-y-4'
labelClassName='h-6 flex items-center mb-1 system-sm-medium text-text-secondary' labelClassName='h-6 flex items-center mb-1 system-sm-medium text-text-secondary'
formFromProps={formFromProps}
/> />
) )
} }

@ -24,7 +24,7 @@ const AddApiKeyButton = ({
return ( return (
<> <>
<Button <Button
className='grow' className='w-0 grow'
variant={buttonVariant} variant={buttonVariant}
onClick={() => setIsApiKeyModalOpen(true)} onClick={() => setIsApiKeyModalOpen(true)}
disabled={disabled} disabled={disabled}

@ -103,6 +103,11 @@ const AddOAuthButton = ({
</div> </div>
<div className='system-sm-medium flex h-6 items-center text-text-secondary'> <div className='system-sm-medium flex h-6 items-center text-text-secondary'>
{renderI18nObject(item.label as Record<string, string>)} {renderI18nObject(item.label as Record<string, string>)}
{
item.required && (
<span className='ml-1 text-text-destructive-secondary'>*</span>
)
}
</div> </div>
</div> </div>
) )
@ -157,7 +162,7 @@ const AddOAuthButton = ({
<Button <Button
variant={buttonVariant} variant={buttonVariant}
className={cn( className={cn(
'grow px-0 py-0 hover:bg-components-button-primary-bg', 'w-0 grow px-0 py-0 hover:bg-components-button-primary-bg',
className, className,
)} )}
disabled={disabled} disabled={disabled}
@ -171,7 +176,10 @@ const AddOAuthButton = ({
{ {
is_oauth_custom_client_enabled && ( is_oauth_custom_client_enabled && (
<Badge <Badge
className='ml-1 border-text-primary-on-surface bg-components-badge-bg-dimm text-text-primary-on-surface' className={cn(
'ml-1',
buttonVariant === 'primary' && 'border-text-primary-on-surface bg-components-badge-bg-dimm text-text-primary-on-surface',
)}
> >
{t('plugin.auth.custom')} {t('plugin.auth.custom')}
</Badge> </Badge>
@ -203,6 +211,7 @@ const AddOAuthButton = ({
variant={buttonVariant} variant={buttonVariant}
onClick={() => setIsOAuthSettingsOpen(true)} onClick={() => setIsOAuthSettingsOpen(true)}
disabled={disabled} disabled={disabled}
className='w-0 grow'
> >
<RiEqualizer2Line className='mr-0.5 h-4 w-4' /> <RiEqualizer2Line className='mr-0.5 h-4 w-4' />
{t('plugin.auth.setupOAuth')} {t('plugin.auth.setupOAuth')}
@ -217,7 +226,11 @@ const AddOAuthButton = ({
disabled={disabled || isLoading} disabled={disabled || isLoading}
schemas={memorizedSchemas} schemas={memorizedSchemas}
onAuth={handleOAuth} onAuth={handleOAuth}
editValues={client_params} editValues={{
...client_params,
__oauth_client__: is_oauth_custom_client_enabled ? 'custom' : 'default',
}}
hasOriginalClientParams={Object.keys(client_params || {}).length > 0}
/> />
) )
} }

@ -4,10 +4,16 @@ import {
useRef, useRef,
useState, useState,
} from 'react' } from 'react'
import {
useForm,
useStore,
} from '@tanstack/react-form'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Modal from '@/app/components/base/modal/modal' import Modal from '@/app/components/base/modal/modal'
import { import {
useDeletePluginOAuthCustomClientHook,
useInvalidPluginCredentialInfoHook, useInvalidPluginCredentialInfoHook,
useInvalidPluginOAuthClientSchemaHook,
useSetPluginOAuthCustomClientHook, useSetPluginOAuthCustomClientHook,
} from '../hooks/use-credential' } from '../hooks/use-credential'
import type { PluginPayload } from '../types' import type { PluginPayload } from '../types'
@ -17,6 +23,7 @@ import type {
FormSchema, FormSchema,
} from '@/app/components/base/form/types' } from '@/app/components/base/form/types'
import { useToastContext } from '@/app/components/base/toast' import { useToastContext } from '@/app/components/base/toast'
import Button from '@/app/components/base/button'
type OAuthClientSettingsProps = { type OAuthClientSettingsProps = {
pluginPayload: PluginPayload pluginPayload: PluginPayload
@ -25,6 +32,7 @@ type OAuthClientSettingsProps = {
disabled?: boolean disabled?: boolean
schemas: FormSchema[] schemas: FormSchema[]
onAuth?: () => Promise<void> onAuth?: () => Promise<void>
hasOriginalClientParams?: boolean
} }
const OAuthClientSettings = ({ const OAuthClientSettings = ({
pluginPayload, pluginPayload,
@ -33,6 +41,7 @@ const OAuthClientSettings = ({
disabled, disabled,
schemas, schemas,
onAuth, onAuth,
hasOriginalClientParams,
}: OAuthClientSettingsProps) => { }: OAuthClientSettingsProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const { notify } = useToastContext() const { notify } = useToastContext()
@ -48,7 +57,8 @@ const OAuthClientSettings = ({
return acc return acc
}, {} as Record<string, any>) }, {} as Record<string, any>)
const { mutateAsync: setPluginOAuthCustomClient } = useSetPluginOAuthCustomClientHook(pluginPayload) const { mutateAsync: setPluginOAuthCustomClient } = useSetPluginOAuthCustomClientHook(pluginPayload)
const invalidatePluginCredentialInfo = useInvalidPluginCredentialInfoHook(pluginPayload) const invalidPluginCredentialInfo = useInvalidPluginCredentialInfoHook(pluginPayload)
const invalidPluginOAuthClientSchema = useInvalidPluginOAuthClientSchemaHook(pluginPayload)
const formRef = useRef<FormRefObject>(null) const formRef = useRef<FormRefObject>(null)
const handleConfirm = useCallback(async () => { const handleConfirm = useCallback(async () => {
if (doingActionRef.current) if (doingActionRef.current)
@ -80,18 +90,42 @@ const OAuthClientSettings = ({
}) })
onClose?.() onClose?.()
invalidatePluginCredentialInfo() invalidPluginCredentialInfo()
invalidPluginOAuthClientSchema()
} }
finally { finally {
handleSetDoingAction(false) handleSetDoingAction(false)
} }
}, [onClose, invalidatePluginCredentialInfo, setPluginOAuthCustomClient, notify, t, handleSetDoingAction]) }, [onClose, invalidPluginCredentialInfo, invalidPluginOAuthClientSchema, setPluginOAuthCustomClient, notify, t, handleSetDoingAction])
const handleConfirmAndAuthorize = useCallback(async () => { const handleConfirmAndAuthorize = useCallback(async () => {
await handleConfirm() await handleConfirm()
if (onAuth) if (onAuth)
await onAuth() await onAuth()
}, [handleConfirm, onAuth]) }, [handleConfirm, onAuth])
const { mutateAsync: deletePluginOAuthCustomClient } = useDeletePluginOAuthCustomClientHook(pluginPayload)
const handleRemove = useCallback(async () => {
if (doingActionRef.current)
return
try {
handleSetDoingAction(true)
await deletePluginOAuthCustomClient()
notify({
type: 'success',
message: t('common.api.actionSuccess'),
})
invalidPluginCredentialInfo()
invalidPluginOAuthClientSchema()
}
finally {
handleSetDoingAction(false)
}
}, [invalidPluginCredentialInfo, invalidPluginOAuthClientSchema, deletePluginOAuthCustomClient, notify, t, handleSetDoingAction])
const form = useForm({
defaultValues: editValues || defaultValues,
})
const __oauth_client__ = useStore(form.store, s => s.values.__oauth_client__)
return ( return (
<Modal <Modal
title={t('plugin.auth.oauthClientSettings')} title={t('plugin.auth.oauthClientSettings')}
@ -105,8 +139,23 @@ const OAuthClientSettings = ({
onCancel={handleConfirm} onCancel={handleConfirm}
onConfirm={handleConfirmAndAuthorize} onConfirm={handleConfirmAndAuthorize}
disabled={disabled || doingAction} disabled={disabled || doingAction}
footerSlot={
__oauth_client__ === 'custom' && hasOriginalClientParams && (
<div className='grow'>
<Button
variant='secondary'
className='text-components-button-destructive-secondary-text'
disabled={disabled || doingAction || !editValues}
onClick={handleRemove}
>
{t('common.operation.remove')}
</Button>
</div>
)
}
> >
<AuthForm <AuthForm
formFromProps={form}
ref={formRef} ref={formRef}
formSchemas={schemas} formSchemas={schemas}
defaultValues={editValues || defaultValues} defaultValues={editValues || defaultValues}

@ -1,11 +1,13 @@
import { import {
useAddPluginCredential, useAddPluginCredential,
useDeletePluginCredential, useDeletePluginCredential,
useDeletePluginOAuthCustomClient,
useGetPluginCredentialInfo, useGetPluginCredentialInfo,
useGetPluginCredentialSchema, useGetPluginCredentialSchema,
useGetPluginOAuthClientSchema, useGetPluginOAuthClientSchema,
useGetPluginOAuthUrl, useGetPluginOAuthUrl,
useInvalidPluginCredentialInfo, useInvalidPluginCredentialInfo,
useInvalidPluginOAuthClientSchema,
useSetPluginDefaultCredential, useSetPluginDefaultCredential,
useSetPluginOAuthCustomClient, useSetPluginOAuthCustomClient,
useUpdatePluginCredential, useUpdatePluginCredential,
@ -67,8 +69,20 @@ export const useGetPluginOAuthClientSchemaHook = (pluginPayload: PluginPayload)
return useGetPluginOAuthClientSchema(apiMap.getOauthClientSchema) return useGetPluginOAuthClientSchema(apiMap.getOauthClientSchema)
} }
export const useInvalidPluginOAuthClientSchemaHook = (pluginPayload: PluginPayload) => {
const apiMap = useGetApi(pluginPayload)
return useInvalidPluginOAuthClientSchema(apiMap.getOauthClientSchema)
}
export const useSetPluginOAuthCustomClientHook = (pluginPayload: PluginPayload) => { export const useSetPluginOAuthCustomClientHook = (pluginPayload: PluginPayload) => {
const apiMap = useGetApi(pluginPayload) const apiMap = useGetApi(pluginPayload)
return useSetPluginOAuthCustomClient(apiMap.setCustomOauthClient) return useSetPluginOAuthCustomClient(apiMap.setCustomOauthClient)
} }
export const useDeletePluginOAuthCustomClientHook = (pluginPayload: PluginPayload) => {
const apiMap = useGetApi(pluginPayload)
return useDeletePluginOAuthCustomClient(apiMap.deleteCustomOAuthClient)
}

@ -20,6 +20,7 @@ export const useGetApi = ({ category = AuthCategory.tool, provider }: PluginPayl
getOauthClientSchema: `/workspaces/current/tool-provider/builtin/${provider}/oauth/client-schema`, getOauthClientSchema: `/workspaces/current/tool-provider/builtin/${provider}/oauth/client-schema`,
setCustomOauthClient: `/workspaces/current/tool-provider/builtin/${provider}/oauth/custom-client`, setCustomOauthClient: `/workspaces/current/tool-provider/builtin/${provider}/oauth/custom-client`,
getCustomOAuthClientValues: `/workspaces/current/tool-provider/builtin/${provider}/oauth/custom-client`, getCustomOAuthClientValues: `/workspaces/current/tool-provider/builtin/${provider}/oauth/custom-client`,
deleteCustomOAuthClient: `/workspaces/current/tool-provider/builtin/${provider}/oauth/custom-client`,
} }
} }
@ -35,5 +36,6 @@ export const useGetApi = ({ category = AuthCategory.tool, provider }: PluginPayl
getOauthClientSchema: '', getOauthClientSchema: '',
setCustomOauthClient: '', setCustomOauthClient: '',
getCustomOAuthClientValues: '', getCustomOAuthClientValues: '',
deleteCustomOAuthClient: '',
} }
} }

@ -2,7 +2,7 @@ import {
useMutation, useMutation,
useQuery, useQuery,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import { get, post } from './base' import { del, get, post } from './base'
import { useInvalid } from './use-base' import { useInvalid } from './use-base'
import type { import type {
Credential, Credential,
@ -131,6 +131,12 @@ export const useGetPluginOAuthClientSchema = (
}) })
} }
export const useInvalidPluginOAuthClientSchema = (
url: string,
) => {
return useInvalid([NAME_SPACE, 'oauth-client-schema', url])
}
export const useSetPluginOAuthCustomClient = ( export const useSetPluginOAuthCustomClient = (
url: string, url: string,
) => { ) => {
@ -143,3 +149,13 @@ export const useSetPluginOAuthCustomClient = (
}, },
}) })
} }
export const useDeletePluginOAuthCustomClient = (
url: string,
) => {
return useMutation({
mutationFn: () => {
return del<{ result: string }>(url)
},
})
}

Loading…
Cancel
Save