219 lines
7.1 KiB
TypeScript
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 |