erp-platform/ui/src/views/admin/tenant-management/TenantsConnectionString.tsx
2025-11-06 21:13:35 +03:00

400 lines
13 KiB
TypeScript

import {
Button,
Dialog,
FormContainer,
FormItem,
Input,
Notification,
Select,
Tabs,
toast,
} from '@/components/ui'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import { SeedTenantDataInput } from '@/proxy/admin/tenant/models'
import {
deleteTenantDefaultConnectionString,
getTenantDefaultConnectionString,
postSeedTenantData,
putTenantDefaultConnectionString,
} from '@/services/tenant.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { Suspense, useEffect, useRef, useState } from 'react'
import * as Yup from 'yup'
import { dataSourceTypeOptions } from '../listForm/edit/options'
import { DataSourceTypeEnum } from '@/proxy/form/models'
export interface ConnectionStringDto {
id: string
name: string
value: string
isNew?: boolean
dataSourceType?: number
}
const schemaCs = Yup.object().shape({
id: Yup.string().required(),
name: Yup.string().required(),
dataSourceType: Yup.number().required(),
value: Yup.string().required(),
})
const schemaSeed = Yup.object().shape({
id: Yup.string().required(),
adminEmail: Yup.string().required(),
adminPassword: Yup.string().required(),
})
function TenantConnectionString({
open,
onDialogClose,
name,
id,
}: {
open: boolean
onDialogClose: () => void
name: string
id: string
}) {
const { translate } = useLocalization()
const [currentTab, setCurrentTab] = useState('cs')
const [loading, setLoading] = useState(true)
const [connectionString, setConnectionString] = useState<ConnectionStringDto>()
const fetchDataTenants = async () => {
if (!id) {
return
}
setLoading(true)
const response = await getTenantDefaultConnectionString(id)
let value = ''
let isNew = false
if (response.data.length == 0) {
isNew = true
value = ''
} else {
isNew = false
value = response.data
}
setConnectionString({
id,
name: 'Default',
value,
isNew,
...(value && { dataSourceType: value.startsWith('Server') ? 1 : 2 }),
})
setLoading(false)
}
useEffect(() => {
fetchDataTenants()
}, [id])
const deleteConnectionString = async () => {
if (!id) {
return
}
setLoading(true)
try {
await deleteTenantDefaultConnectionString(id)
toast.push(
<Notification type="success" duration={2000}>
{translate('::AbpTenantManagement.Tenants.ConnectionStringDeleted')}
</Notification>,
{
placement: 'top-end',
},
)
onDialogClose()
} catch (error) {
toast.push(
<Notification type="danger" duration={2000}>
{'Hata'}
</Notification>,
{
placement: 'top-end',
},
)
} finally {
setLoading(false)
}
}
const handleSubmit = async (
values: ConnectionStringDto,
{ setSubmitting }: FormikHelpers<ConnectionStringDto>,
) => {
if (!id) {
return
}
setLoading(true)
setSubmitting(true)
try {
await putTenantDefaultConnectionString(id, values.value)
toast.push(
<Notification type="success" duration={2000}>
{translate('::AbpTenantManagement.Tenants.ConnectionStringSaved')}
</Notification>,
{
placement: 'top-end',
},
)
await fetchDataTenants()
//onDialogClose()
} catch (error) {
toast.push(
<Notification type="danger" duration={2000}>
{'Hata'}
</Notification>,
{
placement: 'top-end',
},
)
} finally {
setLoading(false)
setSubmitting(false)
}
}
const handleSubmitSeed = async (
values: SeedTenantDataInput,
{ setSubmitting }: FormikHelpers<SeedTenantDataInput>,
) => {
if (!id) {
return
}
setLoading(true)
setSubmitting(true)
try {
await postSeedTenantData(values)
toast.push(
<Notification type="success" duration={2000}>
{translate('::AbpTenantManagement.Tenants.DatabaseSeeded')}
</Notification>,
{
placement: 'top-end',
},
)
} catch (error) {
toast.push(
<Notification type="danger" duration={2000}>
{'Hata'}
</Notification>,
{
placement: 'top-end',
},
)
} finally {
setLoading(false)
setSubmitting(false)
}
}
if (!connectionString) {
return <></>
}
return (
<Dialog isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
<h5 className="mb-4">{name}</h5>
<hr className="my-2"></hr>
<Tabs value={currentTab} onChange={setCurrentTab}>
<TabList>
<TabNav key="cs" value="cs">
Connection String
</TabNav>
<TabNav key="seed" value="seed">
{connectionString.isNew
? translate('::Abp.Account.SignUp')
: translate('::AbpTenantManagement.Tenants.DatabaseSeed')}
</TabNav>
</TabList>
</Tabs>
<div className="px-4 py-6">
<Suspense fallback={<></>}>
{currentTab === 'cs' && (
<Formik
initialValues={connectionString}
validationSchema={schemaCs}
onSubmit={handleSubmit}
>
{({ touched, errors, values, isSubmitting }) => {
return (
<Form>
<FormContainer size="sm">
<FormItem
label={translate('AbpAccount::DisplayName:Name')}
invalid={errors.name && touched.name}
errorMessage={errors.name}
>
<Field
type="text"
autoComplete="off"
name="name"
placeholder="Name"
disabled
component={Input}
/>
</FormItem>
<FormItem
label={translate('::ListForms.ListFormFieldEdit.LookupDataSourceType')}
invalid={errors.dataSourceType && touched.dataSourceType}
errorMessage={errors.dataSourceType}
>
<Field
type="text"
autoComplete="off"
name="dataSourceType"
placeholder={translate(
'::ListForms.ListFormFieldEdit.LookupDataSourceType',
)}
>
{({ field, form }: FieldProps<DataSourceTypeEnum>) => (
<Select
field={field}
form={form}
autoFocus
isClearable={true}
options={dataSourceTypeOptions}
value={dataSourceTypeOptions?.filter(
(option: any) => option.value === values.dataSourceType,
)}
onChange={(option) => {
form.setFieldValue(field.name, option?.value)
if (option?.value == 1)
//PostgreSQL
form.setFieldValue(
'value',
'Server=sql;Database=' +
name +
';User Id=sa;password=@Password;Trusted_Connection=False;TrustServerCertificate=True;Connection Timeout=60;MultipleActiveResultSets=true;',
)
else if (option?.value == 2)
//MsSql
form.setFieldValue(
'value',
'User ID=sa;Password=@Password;Host=postgres;Port=5432;Database=' +
name +
';',
)
}}
/>
)}
</Field>
</FormItem>
<FormItem
label="Connection String"
invalid={errors.value && touched.value}
errorMessage={errors.value}
>
<Field
textArea="true"
type="text"
autoComplete="off"
name="value"
placeholder="Value"
component={Input}
/>
</FormItem>
<div className="mt-6 flex flex-row justify-end gap-3">
<Button
disabled={connectionString.isNew}
className="mr-auto"
type="button"
color="red-500"
variant="twoTone"
onClick={deleteConnectionString}
>
{translate('::Delete')}
</Button>
<Button variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
<Button type="button" variant="plain" onClick={onDialogClose}>
{translate('::Cancel')}
</Button>
</div>
</FormContainer>
</Form>
)
}}
</Formik>
)}
{currentTab === 'seed' && (
<Formik
initialValues={{ id, adminEmail: '', adminPassword: '' } as SeedTenantDataInput}
validationSchema={schemaSeed}
onSubmit={handleSubmitSeed}
>
{({ touched, errors, values, isSubmitting }) => {
return (
<Form>
<FormContainer size="sm">
<FormItem
label={translate('::Abp.Account.EmailAddress')}
invalid={errors.adminEmail && touched.adminEmail}
errorMessage={errors.adminEmail}
>
<Field
type="text"
autoFocus
autoComplete="off"
name="adminEmail"
component={Input}
/>
</FormItem>
<FormItem
label={translate('::Abp.Account.Password')}
invalid={errors.adminPassword && touched.adminPassword}
errorMessage={errors.adminPassword}
>
<Field
type="text"
autoComplete="off"
name="adminPassword"
component={Input}
/>
</FormItem>
<div className="mt-6 flex flex-row justify-end gap-3">
<Button variant="solid" loading={isSubmitting} type="submit">
{isSubmitting
? connectionString.isNew
? translate('::Abp.Identity.UserCreating')
: translate('::AbpTenantManagement.Tenants.DatabaseSeeding')
: connectionString.isNew
? translate('::Abp.Identity.CreateUser')
: translate('::AbpTenantManagement.Tenants.DatabaseSeed')}
</Button>
<Button type="button" variant="plain" onClick={onDialogClose}>
{translate('::Cancel')}
</Button>
</div>
</FormContainer>
</Form>
)
}}
</Formik>
)}
</Suspense>
</div>
</Dialog>
)
}
export default TenantConnectionString