400 lines
13 KiB
TypeScript
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
|