You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

oauth-client-settings.tsx 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import {
  2. memo,
  3. useCallback,
  4. useRef,
  5. useState,
  6. } from 'react'
  7. import {
  8. useForm,
  9. useStore,
  10. } from '@tanstack/react-form'
  11. import { useTranslation } from 'react-i18next'
  12. import Modal from '@/app/components/base/modal/modal'
  13. import {
  14. useDeletePluginOAuthCustomClientHook,
  15. useInvalidPluginOAuthClientSchemaHook,
  16. useSetPluginOAuthCustomClientHook,
  17. } from '../hooks/use-credential'
  18. import type { PluginPayload } from '../types'
  19. import AuthForm from '@/app/components/base/form/form-scenarios/auth'
  20. import type {
  21. FormRefObject,
  22. FormSchema,
  23. } from '@/app/components/base/form/types'
  24. import { useToastContext } from '@/app/components/base/toast'
  25. import Button from '@/app/components/base/button'
  26. type OAuthClientSettingsProps = {
  27. pluginPayload: PluginPayload
  28. onClose?: () => void
  29. editValues?: Record<string, any>
  30. disabled?: boolean
  31. schemas: FormSchema[]
  32. onAuth?: () => Promise<void>
  33. hasOriginalClientParams?: boolean
  34. onUpdate?: () => void
  35. }
  36. const OAuthClientSettings = ({
  37. pluginPayload,
  38. onClose,
  39. editValues,
  40. disabled,
  41. schemas,
  42. onAuth,
  43. hasOriginalClientParams,
  44. onUpdate,
  45. }: OAuthClientSettingsProps) => {
  46. const { t } = useTranslation()
  47. const { notify } = useToastContext()
  48. const [doingAction, setDoingAction] = useState(false)
  49. const doingActionRef = useRef(doingAction)
  50. const handleSetDoingAction = useCallback((value: boolean) => {
  51. doingActionRef.current = value
  52. setDoingAction(value)
  53. }, [])
  54. const defaultValues = schemas.reduce((acc, schema) => {
  55. if (schema.default)
  56. acc[schema.name] = schema.default
  57. return acc
  58. }, {} as Record<string, any>)
  59. const { mutateAsync: setPluginOAuthCustomClient } = useSetPluginOAuthCustomClientHook(pluginPayload)
  60. const invalidPluginOAuthClientSchema = useInvalidPluginOAuthClientSchemaHook(pluginPayload)
  61. const formRef = useRef<FormRefObject>(null)
  62. const handleConfirm = useCallback(async () => {
  63. if (doingActionRef.current)
  64. return
  65. try {
  66. const {
  67. isCheckValidated,
  68. values,
  69. } = formRef.current?.getFormValues({
  70. needCheckValidatedValues: true,
  71. needTransformWhenSecretFieldIsPristine: true,
  72. }) || { isCheckValidated: false, values: {} }
  73. if (!isCheckValidated)
  74. throw new Error('error')
  75. const {
  76. __oauth_client__,
  77. ...restValues
  78. } = values
  79. handleSetDoingAction(true)
  80. await setPluginOAuthCustomClient({
  81. client_params: restValues,
  82. enable_oauth_custom_client: __oauth_client__ === 'custom',
  83. })
  84. notify({
  85. type: 'success',
  86. message: t('common.api.actionSuccess'),
  87. })
  88. onClose?.()
  89. onUpdate?.()
  90. invalidPluginOAuthClientSchema()
  91. }
  92. finally {
  93. handleSetDoingAction(false)
  94. }
  95. }, [onClose, onUpdate, invalidPluginOAuthClientSchema, setPluginOAuthCustomClient, notify, t, handleSetDoingAction])
  96. const handleConfirmAndAuthorize = useCallback(async () => {
  97. await handleConfirm()
  98. if (onAuth)
  99. await onAuth()
  100. }, [handleConfirm, onAuth])
  101. const { mutateAsync: deletePluginOAuthCustomClient } = useDeletePluginOAuthCustomClientHook(pluginPayload)
  102. const handleRemove = useCallback(async () => {
  103. if (doingActionRef.current)
  104. return
  105. try {
  106. handleSetDoingAction(true)
  107. await deletePluginOAuthCustomClient()
  108. notify({
  109. type: 'success',
  110. message: t('common.api.actionSuccess'),
  111. })
  112. onClose?.()
  113. onUpdate?.()
  114. invalidPluginOAuthClientSchema()
  115. }
  116. finally {
  117. handleSetDoingAction(false)
  118. }
  119. }, [onUpdate, invalidPluginOAuthClientSchema, deletePluginOAuthCustomClient, notify, t, handleSetDoingAction, onClose])
  120. const form = useForm({
  121. defaultValues: editValues || defaultValues,
  122. })
  123. const __oauth_client__ = useStore(form.store, s => s.values.__oauth_client__)
  124. return (
  125. <Modal
  126. title={t('plugin.auth.oauthClientSettings')}
  127. confirmButtonText={t('plugin.auth.saveAndAuth')}
  128. cancelButtonText={t('plugin.auth.saveOnly')}
  129. extraButtonText={t('common.operation.cancel')}
  130. showExtraButton
  131. extraButtonVariant='secondary'
  132. onExtraButtonClick={onClose}
  133. onClose={onClose}
  134. onCancel={handleConfirm}
  135. onConfirm={handleConfirmAndAuthorize}
  136. disabled={disabled || doingAction}
  137. footerSlot={
  138. __oauth_client__ === 'custom' && hasOriginalClientParams && (
  139. <div className='grow'>
  140. <Button
  141. variant='secondary'
  142. className='text-components-button-destructive-secondary-text'
  143. disabled={disabled || doingAction || !editValues}
  144. onClick={handleRemove}
  145. >
  146. {t('common.operation.remove')}
  147. </Button>
  148. </div>
  149. )
  150. }
  151. >
  152. <>
  153. <AuthForm
  154. formFromProps={form}
  155. ref={formRef}
  156. formSchemas={schemas}
  157. defaultValues={editValues || defaultValues}
  158. disabled={disabled}
  159. />
  160. </>
  161. </Modal>
  162. )
  163. }
  164. export default memo(OAuthClientSettings)