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.

endpoint-modal.tsx 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import { RiArrowRightUpLine, RiCloseLine } from '@remixicon/react'
  6. import ActionButton from '@/app/components/base/action-button'
  7. import Button from '@/app/components/base/button'
  8. import Drawer from '@/app/components/base/drawer'
  9. import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
  10. import Toast from '@/app/components/base/toast'
  11. import { useRenderI18nObject } from '@/hooks/use-i18n'
  12. import cn from '@/utils/classnames'
  13. type Props = {
  14. formSchemas: any
  15. defaultValues?: any
  16. onCancel: () => void
  17. onSaved: (value: Record<string, any>) => void
  18. }
  19. const extractDefaultValues = (schemas: any[]) => {
  20. const result: Record<string, any> = {}
  21. for (const field of schemas) {
  22. if (field.default !== undefined)
  23. result[field.name] = field.default
  24. }
  25. return result
  26. }
  27. const EndpointModal: FC<Props> = ({
  28. formSchemas,
  29. defaultValues = {},
  30. onCancel,
  31. onSaved,
  32. }) => {
  33. const getValueFromI18nObject = useRenderI18nObject()
  34. const { t } = useTranslation()
  35. const initialValues = Object.keys(defaultValues).length > 0
  36. ? defaultValues
  37. : extractDefaultValues(formSchemas)
  38. const [tempCredential, setTempCredential] = React.useState<any>(initialValues)
  39. const handleSave = () => {
  40. for (const field of formSchemas) {
  41. if (field.required && !tempCredential[field.name]) {
  42. Toast.notify({ type: 'error', message: t('common.errorMsg.fieldRequired', { field: getValueFromI18nObject(field.label) }) })
  43. return
  44. }
  45. }
  46. // Fix: Process boolean fields to ensure they are sent as proper boolean values
  47. const processedCredential = { ...tempCredential }
  48. formSchemas.forEach((field) => {
  49. if (field.type === 'boolean' && processedCredential[field.name] !== undefined) {
  50. const value = processedCredential[field.name]
  51. if (typeof value === 'string')
  52. processedCredential[field.name] = value === 'true' || value === '1' || value === 'True'
  53. else if (typeof value === 'number')
  54. processedCredential[field.name] = value === 1
  55. else if (typeof value === 'boolean')
  56. processedCredential[field.name] = value
  57. }
  58. })
  59. onSaved(processedCredential)
  60. }
  61. return (
  62. <Drawer
  63. isOpen
  64. clickOutsideNotOpen={false}
  65. onClose={onCancel}
  66. footer={null}
  67. mask
  68. positionCenter={false}
  69. panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')}
  70. >
  71. <>
  72. <div className='p-4 pb-2'>
  73. <div className='flex items-center justify-between'>
  74. <div className='system-xl-semibold text-text-primary'>{t('plugin.detailPanel.endpointModalTitle')}</div>
  75. <ActionButton onClick={onCancel}>
  76. <RiCloseLine className='h-4 w-4' />
  77. </ActionButton>
  78. </div>
  79. <div className='system-xs-regular mt-0.5 text-text-tertiary'>{t('plugin.detailPanel.endpointModalDesc')}</div>
  80. </div>
  81. <div className='grow overflow-y-auto'>
  82. <div className='px-4 py-2'>
  83. <Form
  84. value={tempCredential}
  85. onChange={(v) => {
  86. setTempCredential(v)
  87. }}
  88. formSchemas={formSchemas}
  89. isEditMode={true}
  90. showOnVariableMap={{}}
  91. validating={false}
  92. inputClassName='bg-components-input-bg-normal hover:bg-components-input-bg-hover'
  93. fieldMoreInfo={item => item.url
  94. ? (<a
  95. href={item.url}
  96. target='_blank' rel='noopener noreferrer'
  97. className='body-xs-regular inline-flex items-center text-text-accent-secondary'
  98. >
  99. {t('tools.howToGet')}
  100. <RiArrowRightUpLine className='ml-1 h-3 w-3' />
  101. </a>)
  102. : null}
  103. />
  104. </div>
  105. <div className={cn('flex justify-end p-4 pt-0')} >
  106. <div className='flex gap-2'>
  107. <Button onClick={onCancel}>{t('common.operation.cancel')}</Button>
  108. <Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button>
  109. </div>
  110. </div>
  111. </div>
  112. </>
  113. </Drawer>
  114. )
  115. }
  116. export default React.memo(EndpointModal)