reCoreD-UI/web/src/components/domains/DomainEditModal.tsx
2024-04-11 22:05:58 +08:00

219 lines
7.1 KiB
TypeScript

import {
NModal,
NCard,
NForm,
NFormItem,
NFlex,
NIcon,
NButton,
NInput,
NInputNumber,
type FormRules,
type FormItemRule,
createDiscreteApi
} from 'naive-ui'
import { getErrorInfo } from '@/apis/api';
import { useDomainStore, type Domain } from '@/stores/domains';
import { Check, Times } from '@vicons/fa';
import i18n from '@/locale/i18n'
import { ref, type SetupContext } from 'vue';
const { t } = i18n.global
const domainStore = useDomainStore()
const { notification } = createDiscreteApi(['notification'])
const enum validFlags {
domainNameValid = 1,
mainNsValid = domainNameValid << 1,
adminEmailValid = mainNsValid << 1
}
const allFlags = validFlags.adminEmailValid | validFlags.mainNsValid | validFlags.domainNameValid
const rules = {
domain_name: [{
required: true,
trigger: 'blur',
validator: (_rule: FormItemRule, value: string) => {
return validate(
value,
/^([\w-]+\.)+[\w-]+$/,
'domains.errors.domainName',
validFlags.domainNameValid
)
}
}],
main_dns: [{
required: true,
trigger: 'blur',
validator: (_rule: FormItemRule, value: string) => {
return validate(
value,
/^([\w-]+\.)+[\w-]+$/,
'domains.errors.domainName',
validFlags.mainNsValid,
)
}
}],
admin_email: [{
required: true,
trigger: 'blur',
validator: (_rule: FormItemRule, value: string) => {
return validate(
value,
/^[\w-.]+@([\w-]+\.)+[\w-]+$/,
'domains.errors.mail',
validFlags.adminEmailValid
)
}
}],
refresh_interval: [{
required: true,
trigger: 'blur',
type: 'number',
}],
retry_interval: [{
required: true,
trigger: 'blur',
type: 'number',
}],
expiry_period: [{
required: true,
trigger: 'blur',
type: 'number',
}],
negative_ttl: [{
required: true,
trigger: 'blur',
type: 'number'
}]
} as FormRules
type Props = {
domain: Domain
show: boolean
}
type Events = {
'update:show': (v: boolean) => void
'update:value': (v: string | number | null) => void
}
const loading = ref(false)
const invalidData = ref(0)
function validate(value: string, reg: RegExp, msg: string, flag: validFlags): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (!value) {
invalidData.value &= ~flag
reject(Error(t('common.mandatory')))
} else if (!reg.test(value)) {
invalidData.value &= ~flag
reject(Error(t(msg)))
} else {
invalidData.value |= flag
resolve()
}
})
}
async function confirm(domain: Domain) {
loading.value = true;
try {
if (!domain.id || domain.id < 1) {
await domainStore.addDomain(domain)
} else {
await domainStore.updateDomain(domain)
}
} catch (e) {
const msg = getErrorInfo(e)
notification.error(msg)
console.error(e)
} finally {
loading.value = false
}
}
function easyInput(domain_name: string, domain: Domain) {
domain.admin_email = `admin@${domain_name}`
domain.main_dns = `ns1.${domain_name}`
}
function modalHeader({ domain }: Props) {
return (
<>
{(!domain || !domain.id || domain.id < 1) ? <span>{t('common.new')}</span> : <span>{t('common.edit')}</span>}
<span>{t('domains._')}</span>
</>
)
}
function modalInputNumbers({ value, label, path }: { value: number, label: string, path: string }, { emit }: SetupContext<Events>) {
return (
<NFormItem label={t(label)} path={path}>
<NInputNumber value={value} onUpdate:value={v => emit('update:value', v)} showButton={false}>
{{
suffix: () => t('common.unitForSecond')
}}
</NInputNumber>
</NFormItem>
)
}
function modalBody({ domain }: Props) {
return (
<>
<NForm model={domain} rules={rules}>
<NFormItem label={t('domains._')} path='domain_name'>
<NInput placeholder='example.com' value={domain.domain_name} onUpdate:value={v => domain.domain_name = v} onInput={v => easyInput(v, domain)} />
</NFormItem>
<NFormItem label={t('domains.form.mainDNS')} path='main_dns'>
<NInput placeholder="ns1.example.com" value={domain.main_dns} onUpdate:value={v => domain.main_dns = v} />
</NFormItem>
<NFormItem label={t('domains.form.adminMail')} path='admin_email'>
<NInput placeholder="admin@example.com" value={domain.admin_email} onUpdate:value={v => domain.admin_email = v} inputProps={{ type: 'email' }} />
</NFormItem>
</NForm>
<NForm model={domain} rules={rules} inline>
<modalInputNumbers value={domain.refresh_interval} onUpdate:value={(v: number) => domain.refresh_interval = v} path='refresh_interval' label='records.refresh' />
<modalInputNumbers value={domain.retry_interval} onUpdate:value={(v: number) => domain.retry_interval = v} path='retry_interval' label='records.retry' />
<modalInputNumbers value={domain.expiry_period} onUpdate:value={(v: number) => domain.expiry_period = v} path='expiry_period' label='records.expire' />
<modalInputNumbers value={domain.negative_ttl} onUpdate:value={(v: number) => domain.negative_ttl = v} path='negative_ttl' label='records.ttl' />
</NForm>
</>
)
}
function modalActions({ domain }: Props, { emit }: SetupContext<Events>) {
return (
<NFlex justify='end'>
<NButton size='small' onClick={() => emit("update:show", false)} >
{{
default: () => t('common.cancel'),
icon: () => <NIcon><Times /></NIcon>
}}
</NButton>
<NButton size='small' type='primary' disabled={invalidData.value !== allFlags} loading={loading.value} onClick={() => confirm(domain).then(() => emit('update:show', false))} attrType='submit'>
{{
default: () => t('common.confirm'),
icon: () => <NIcon><Check /></NIcon>
}}
</NButton>
</NFlex>
)
}
function DomainEditModal({ domain, show }: Props, { emit }: SetupContext<Events>) {
return (
<NModal maskClosable={false} show={show}>
<NCard style={{ width: '640px' }} role='dialog'>
{{
headler: () => <modalHeader domain={domain} />,
default: () => <modalBody domain={domain} />,
action: () => <modalActions domain={domain} onUpdate:show={(v: boolean) => { emit("update:show", v) }} />
}}
</NCard>
</NModal>
)
}
export default DomainEditModal