reCoreD-UI/web/src/views/RecordsView.vue
2024-04-10 16:53:03 +08:00

231 lines
7.4 KiB
Vue

<script setup lang="tsx">
import {
NSpin, NPageHeader, useNotification,
NFlex, NButton, NIcon, NGrid, NGi,
NStatistic, NDataTable, NInput,
NModalProvider
} from 'naive-ui'
import type { DataTableColumns } from 'naive-ui'
import { onMounted, ref } from 'vue'
import { useRecordStore, type Record, type SOARecord, RecordTypes } from '@/stores/records'
import { getErrorInfo } from '@/apis/api'
import { PlusSquare, RedoAlt, CheckCircle, Clock, Cogs, Search } from '@vicons/fa'
import router from '@/router';
import RecordOps from '@/components/records/RecordOps.vue'
import RecordEditModal from '@/components/records/RecordEditModal.vue'
import { useI18n } from 'vue-i18n';
const { t } = useI18n()
const props = defineProps<{
domain: string
}>()
const columns = [
{
key: 'no',
title: '#',
render(_, index) {
return index + 1
}
},
{
key: 'name',
title: t("records.name"),
},
{
key: 'record_type',
title: t('records.recordType')
},
{
key: 'content',
title: t('records.content'),
render(row: Record) {
return Object.entries(row.content).map(i => i[1]).join(" ")
}
},
{
key: 'ttl',
title: 'TTL (s)'
},
{
key: '',
render(row: Record) {
return <RecordOps record={row} domain={props.domain} onRecord-delete={deleteRecord} onEdit-record={showEditing} />
}
}
] as DataTableColumns<Record>
const recordStore = useRecordStore()
const notification = useNotification()
const records = ref<Record[] | undefined>([]as Record[]);
const soa = ref<SOARecord>({} as SOARecord)
const editModalShow = ref(false)
const editingRecord = ref<Record>({} as Record)
const loading = ref(true);
onMounted(() => {
try {
refreshRecords()
} catch (err) {
const msg = getErrorInfo(err)
notification.error(msg)
console.error(err)
}
})
const reloadRecords = () => records.value = recordStore.records?.filter(e => e.record_type !== RecordTypes.RecordTypeSOA)
async function refreshRecords() {
try {
await recordStore.loadRecords(props.domain)
reloadRecords()
soa.value = recordStore.records?.find(e => e.record_type === RecordTypes.RecordTypeSOA)?.content as SOARecord
} catch (err) {
const msg = getErrorInfo(err)
notification.error(msg)
console.error(err)
} finally {
loading.value = false;
}
}
function goBack() {
router.push('/domains')
}
function searchRecord(value: string) {
if (value.length > 0) {
records.value = recordStore.records?.
filter(e => e.record_type !== RecordTypes.RecordTypeSOA).
filter(e => !!~e.name.indexOf(value))
} else {
records.value = recordStore.records?.
filter(e => e.record_type !== RecordTypes.RecordTypeSOA)
}
}
async function deleteRecord(domain: string, record: Record) {
try {
await recordStore.removeRecord(domain, record)
reloadRecords()
} catch (err) {
const msg = getErrorInfo(err)
notification.error(msg)
console.error(err)
}
}
function showEditing(domain: string, record: Record) {
editModalShow.value = true
editingRecord.value = record
}
function newRecord() {
showEditing(props.domain, {
zone: `${props.domain}.`,
ttl: 500
} as Record)
}
</script>
<template>
<div id="records">
<RecordEditModal v-model:show="editModalShow" :domain="domain" :record="editingRecord" @reload-records="reloadRecords"/>
<NSpin size="large" v-if="loading" />
<div v-else class="content">
<NModalProvider>
<NPageHeader :title="t('domains.dnsRecord')" :subtitle="domain" @back="goBack">
<template #extra>
<NFlex :wrap="false" justify="end" inline>
<NButton type="primary" @click="newRecord">
<template #icon>
<NIcon>
<PlusSquare />
</NIcon>
</template>
{{ t('common.add') }}
</NButton>
<NInput :placeholder="t('records.search')" @update:value="searchRecord" clearable>
<template #prefix>
<NIcon :component="Search" />
</template>
</NInput>
</NFlex>
</template>
<NGrid :cols="4">
<NGi>
<NStatistic :value="soa?.refresh">
<template #suffix>
s
</template>
<template #label>
<NIcon class="icon">
<RedoAlt />
</NIcon>
{{ t('records.refresh') }}
</template>
</NStatistic>
</NGi>
<NGi>
<NStatistic :value="soa?.retry">
<template #suffix>
s
</template>
<template #label>
<NIcon class="icon">
<CheckCircle />
</NIcon>
{{ t('records.retry') }}
</template>
</NStatistic>
</NGi>
<NGi>
<NStatistic :value="soa?.expire">
<template #suffix>
s
</template>
<template #label>
<NIcon class="icon">
<Clock />
</NIcon>
{{ t('records.expire') }}
</template>
</NStatistic>
</NGi>
<NGi>
<NStatistic :value="soa?.minttl">
<template #suffix>
s
</template>
<template #label>
<NIcon class="icon">
<Cogs />
</NIcon>
{{ t('records.ttl') }}
</template>
</NStatistic>
</NGi>
</NGrid>
</NPageHeader>
<br />
<NDataTable :data="records" :columns="columns" :pagination="{ pageSize: 20 }" />
</NModalProvider>
</div>
</div>
</template>
<style scoped>
.icon {
transform: translateY(2px);
}
div#records {
position: absolute;
top: 0;
left: 0;
width: 100vw;
padding: 1.5rem;
}
</style>