| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 | 
							- import type { FC } from 'react'
 
- import {
 
-   memo,
 
-   useCallback,
 
-   useEffect,
 
-   useMemo,
 
-   useState,
 
- } from 'react'
 
- import { useTranslation } from 'react-i18next'
 
- import {
 
-   RiErrorWarningFill,
 
- } from '@remixicon/react'
 
- import type {
 
-   CredentialFormSchema,
 
-   CredentialFormSchemaRadio,
 
-   CredentialFormSchemaSelect,
 
-   CredentialFormSchemaTextInput,
 
-   CustomConfigurationModelFixedFields,
 
-   FormValue,
 
-   ModelLoadBalancingConfigEntry,
 
-   ModelProvider,
 
- } from '../declarations'
 
- import {
 
-   ConfigurationMethodEnum,
 
-   FormTypeEnum,
 
- } from '../declarations'
 
- import {
 
-   useLanguage,
 
- } from '../hooks'
 
- import { useValidate } from '../../key-validator/hooks'
 
- import { ValidatedStatus } from '../../key-validator/declarations'
 
- import { validateLoadBalancingCredentials } from '../utils'
 
- import Form from './Form'
 
- import Button from '@/app/components/base/button'
 
- import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
 
- import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
 
- import {
 
-   PortalToFollowElem,
 
-   PortalToFollowElemContent,
 
- } from '@/app/components/base/portal-to-follow-elem'
 
- import { useToastContext } from '@/app/components/base/toast'
 
- import Confirm from '@/app/components/base/confirm'
 
- type ModelModalProps = {
 
-   provider: ModelProvider
 
-   configurationMethod: ConfigurationMethodEnum
 
-   currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
 
-   entry?: ModelLoadBalancingConfigEntry
 
-   onCancel: () => void
 
-   onSave: (entry: ModelLoadBalancingConfigEntry) => void
 
-   onRemove: () => void
 
- }
 
- const ModelLoadBalancingEntryModal: FC<ModelModalProps> = ({
 
-   provider,
 
-   configurationMethod,
 
-   currentCustomConfigurationModelFixedFields,
 
-   entry,
 
-   onCancel,
 
-   onSave,
 
-   onRemove,
 
- }) => {
 
-   const providerFormSchemaPredefined = configurationMethod === ConfigurationMethodEnum.predefinedModel
 
-   // const { credentials: formSchemasValue } = useProviderCredentialsAndLoadBalancing(
 
-   //   provider.provider,
 
-   //   configurationMethod,
 
-   //   providerFormSchemaPredefined && provider.custom_configuration.status === CustomConfigurationStatusEnum.active,
 
-   //   currentCustomConfigurationModelFixedFields,
 
-   // )
 
-   const isEditMode = !!entry
 
-   const { t } = useTranslation()
 
-   const { notify } = useToastContext()
 
-   const language = useLanguage()
 
-   const [loading, setLoading] = useState(false)
 
-   const [showConfirm, setShowConfirm] = useState(false)
 
-   const formSchemas = useMemo(() => {
 
-     return [
 
-       {
 
-         type: FormTypeEnum.textInput,
 
-         label: {
 
-           en_US: 'Config Name',
 
-           zh_Hans: '配置名称',
 
-         },
 
-         variable: 'name',
 
-         required: true,
 
-         show_on: [],
 
-         placeholder: {
 
-           en_US: 'Enter your Config Name here',
 
-           zh_Hans: '输入配置名称',
 
-         },
 
-       } as CredentialFormSchemaTextInput,
 
-       ...(
 
-         providerFormSchemaPredefined
 
-           ? provider.provider_credential_schema.credential_form_schemas
 
-           : provider.model_credential_schema.credential_form_schemas
 
-       ),
 
-     ]
 
-   }, [
 
-     providerFormSchemaPredefined,
 
-     provider.provider_credential_schema?.credential_form_schemas,
 
-     provider.model_credential_schema?.credential_form_schemas,
 
-   ])
 
-   const [
 
-     requiredFormSchemas,
 
-     secretFormSchemas,
 
-     defaultFormSchemaValue,
 
-     showOnVariableMap,
 
-   ] = useMemo(() => {
 
-     const requiredFormSchemas: CredentialFormSchema[] = []
 
-     const secretFormSchemas: CredentialFormSchema[] = []
 
-     const defaultFormSchemaValue: Record<string, string | number> = {}
 
-     const showOnVariableMap: Record<string, string[]> = {}
 
-     formSchemas.forEach((formSchema) => {
 
-       if (formSchema.required)
 
-         requiredFormSchemas.push(formSchema)
 
-       if (formSchema.type === FormTypeEnum.secretInput)
 
-         secretFormSchemas.push(formSchema)
 
-       if (formSchema.default)
 
-         defaultFormSchemaValue[formSchema.variable] = formSchema.default
 
-       if (formSchema.show_on.length) {
 
-         formSchema.show_on.forEach((showOnItem) => {
 
-           if (!showOnVariableMap[showOnItem.variable])
 
-             showOnVariableMap[showOnItem.variable] = []
 
-           if (!showOnVariableMap[showOnItem.variable].includes(formSchema.variable))
 
-             showOnVariableMap[showOnItem.variable].push(formSchema.variable)
 
-         })
 
-       }
 
-       if (formSchema.type === FormTypeEnum.select || formSchema.type === FormTypeEnum.radio) {
 
-         (formSchema as (CredentialFormSchemaRadio | CredentialFormSchemaSelect)).options.forEach((option) => {
 
-           if (option.show_on.length) {
 
-             option.show_on.forEach((showOnItem) => {
 
-               if (!showOnVariableMap[showOnItem.variable])
 
-                 showOnVariableMap[showOnItem.variable] = []
 
-               if (!showOnVariableMap[showOnItem.variable].includes(formSchema.variable))
 
-                 showOnVariableMap[showOnItem.variable].push(formSchema.variable)
 
-             })
 
-           }
 
-         })
 
-       }
 
-     })
 
-     return [
 
-       requiredFormSchemas,
 
-       secretFormSchemas,
 
-       defaultFormSchemaValue,
 
-       showOnVariableMap,
 
-     ]
 
-   }, [formSchemas])
 
-   const [initialValue, setInitialValue] = useState<ModelLoadBalancingConfigEntry['credentials']>()
 
-   useEffect(() => {
 
-     if (entry && !initialValue) {
 
-       setInitialValue({
 
-         ...defaultFormSchemaValue,
 
-         ...entry.credentials,
 
-         id: entry.id,
 
-         name: entry.name,
 
-       } as Record<string, string | undefined | boolean>)
 
-     }
 
-   }, [entry, defaultFormSchemaValue, initialValue])
 
-   const formSchemasValue = useMemo(() => ({
 
-     ...currentCustomConfigurationModelFixedFields,
 
-     ...initialValue,
 
-   }), [currentCustomConfigurationModelFixedFields, initialValue])
 
-   const initialFormSchemasValue: Record<string, string | number> = useMemo(() => {
 
-     return {
 
-       ...defaultFormSchemaValue,
 
-       ...formSchemasValue,
 
-     } as Record<string, string | number>
 
-   }, [formSchemasValue, defaultFormSchemaValue])
 
-   const [value, setValue] = useState(initialFormSchemasValue)
 
-   useEffect(() => {
 
-     setValue(initialFormSchemasValue)
 
-   }, [initialFormSchemasValue])
 
-   const [_, validating, validatedStatusState] = useValidate(value)
 
-   const filteredRequiredFormSchemas = requiredFormSchemas.filter((requiredFormSchema) => {
 
-     if (requiredFormSchema.show_on.length && requiredFormSchema.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
 
-       return true
 
-     if (!requiredFormSchema.show_on.length)
 
-       return true
 
-     return false
 
-   })
 
-   const getSecretValues = useCallback((v: FormValue) => {
 
-     return secretFormSchemas.reduce((prev, next) => {
 
-       if (isEditMode && v[next.variable] && v[next.variable] === initialFormSchemasValue[next.variable])
 
-         prev[next.variable] = '[__HIDDEN__]'
 
-       return prev
 
-     }, {} as Record<string, string>)
 
-   }, [initialFormSchemasValue, isEditMode, secretFormSchemas])
 
-   // const handleValueChange = ({ __model_type, __model_name, ...v }: FormValue) => {
 
-   const handleValueChange = (v: FormValue) => {
 
-     setValue(v)
 
-   }
 
-   const handleSave = async () => {
 
-     try {
 
-       setLoading(true)
 
-       const res = await validateLoadBalancingCredentials(
 
-         providerFormSchemaPredefined,
 
-         provider.provider,
 
-         {
 
-           ...value,
 
-           ...getSecretValues(value),
 
-         },
 
-         entry?.id,
 
-       )
 
-       if (res.status === ValidatedStatus.Success) {
 
-         // notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
 
-         const { __model_type, __model_name, name, ...credentials } = value
 
-         onSave({
 
-           ...(entry || {}),
 
-           name: name as string,
 
-           credentials: credentials as Record<string, string | boolean | undefined>,
 
-         })
 
-         //   onCancel()
 
-       }
 
-       else {
 
-         notify({ type: 'error', message: res.message || '' })
 
-       }
 
-     }
 
-     finally {
 
-       setLoading(false)
 
-     }
 
-   }
 
-   const handleRemove = () => {
 
-     onRemove?.()
 
-   }
 
-   return (
 
-     <PortalToFollowElem open>
 
-       <PortalToFollowElemContent className='z-[60] h-full w-full'>
 
-         <div className='fixed inset-0 flex items-center justify-center bg-black/[.25]'>
 
-           <div className='mx-2 max-h-[calc(100vh-120px)] w-[640px] overflow-y-auto rounded-2xl bg-white shadow-xl'>
 
-             <div className='px-8 pt-8'>
 
-               <div className='mb-2 flex items-center justify-between'>
 
-                 <div className='text-xl font-semibold text-gray-900'>{t(isEditMode ? 'common.modelProvider.editConfig' : 'common.modelProvider.addConfig')}</div>
 
-               </div>
 
-               <Form
 
-                 value={value}
 
-                 onChange={handleValueChange}
 
-                 formSchemas={formSchemas}
 
-                 validating={validating}
 
-                 validatedSuccess={validatedStatusState.status === ValidatedStatus.Success}
 
-                 showOnVariableMap={showOnVariableMap}
 
-                 isEditMode={isEditMode}
 
-               />
 
-               <div className='sticky bottom-0 flex flex-wrap items-center justify-between gap-y-2 bg-white py-6'>
 
-                 {
 
-                   (provider.help && (provider.help.title || provider.help.url))
 
-                     ? (
 
-                       <a
 
-                         href={provider.help?.url[language] || provider.help?.url.en_US}
 
-                         target='_blank' rel='noopener noreferrer'
 
-                         className='inline-flex items-center text-xs text-primary-600'
 
-                         onClick={e => !provider.help.url && e.preventDefault()}
 
-                       >
 
-                         {provider.help.title?.[language] || provider.help.url[language] || provider.help.title?.en_US || provider.help.url.en_US}
 
-                         <LinkExternal02 className='ml-1 h-3 w-3' />
 
-                       </a>
 
-                     )
 
-                     : <div />
 
-                 }
 
-                 <div>
 
-                   {
 
-                     isEditMode && (
 
-                       <Button
 
-                         size='large'
 
-                         className='mr-2 text-[#D92D20]'
 
-                         onClick={() => setShowConfirm(true)}
 
-                       >
 
-                         {t('common.operation.remove')}
 
-                       </Button>
 
-                     )
 
-                   }
 
-                   <Button
 
-                     size='large'
 
-                     className='mr-2'
 
-                     onClick={onCancel}
 
-                   >
 
-                     {t('common.operation.cancel')}
 
-                   </Button>
 
-                   <Button
 
-                     size='large'
 
-                     variant='primary'
 
-                     onClick={handleSave}
 
-                     disabled={loading || filteredRequiredFormSchemas.some(item => value[item.variable] === undefined)}
 
-                   >
 
-                     {t('common.operation.save')}
 
-                   </Button>
 
-                 </div>
 
-               </div>
 
-             </div>
 
-             <div className='border-t-[0.5px] border-t-black/5'>
 
-               {
 
-                 (validatedStatusState.status === ValidatedStatus.Error && validatedStatusState.message)
 
-                   ? (
 
-                     <div className='flex bg-[#FEF3F2] px-[10px] py-3 text-xs text-[#D92D20]'>
 
-                       <RiErrorWarningFill className='mr-2 mt-[1px] h-[14px] w-[14px]' />
 
-                       {validatedStatusState.message}
 
-                     </div>
 
-                   )
 
-                   : (
 
-                     <div className='flex items-center justify-center bg-gray-50 py-3 text-xs text-gray-500'>
 
-                       <Lock01 className='mr-1 h-3 w-3 text-gray-500' />
 
-                       {t('common.modelProvider.encrypted.front')}
 
-                       <a
 
-                         className='mx-1 text-primary-600'
 
-                         target='_blank' rel='noopener noreferrer'
 
-                         href='https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html'
 
-                       >
 
-                         PKCS1_OAEP
 
-                       </a>
 
-                       {t('common.modelProvider.encrypted.back')}
 
-                     </div>
 
-                   )
 
-               }
 
-             </div>
 
-           </div>
 
-           {
 
-             showConfirm && (
 
-               <Confirm
 
-                 title={t('common.modelProvider.confirmDelete')}
 
-                 isShow={showConfirm}
 
-                 onCancel={() => setShowConfirm(false)}
 
-                 onConfirm={handleRemove}
 
-               />
 
-             )
 
-           }
 
-         </div>
 
-       </PortalToFollowElemContent>
 
-     </PortalToFollowElem>
 
-   )
 
- }
 
- export default memo(ModelLoadBalancingEntryModal)
 
 
  |