Improve DNS editor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Page>
|
||||
<TopBar :breadcrumbs="breadcrumbs"/>
|
||||
<TopBar :breadcrumbs="breadcrumbs" />
|
||||
|
||||
<Content>
|
||||
<Container>
|
||||
@@ -13,7 +13,7 @@
|
||||
<PageBody>
|
||||
<SettingsLayout>
|
||||
<template #nav>
|
||||
<Tabs :site="site"/>
|
||||
<Tabs :site="site" />
|
||||
</template>
|
||||
<template #segments>
|
||||
<SettingsSegment>
|
||||
@@ -23,8 +23,31 @@
|
||||
</template>
|
||||
<template #form>
|
||||
<form class="space-y-4" @submit.prevent="submit">
|
||||
<FormInput :disabled="sending" :label="__('Name')" :errors="$page.props.errors.name" v-model="form.name"/>
|
||||
<FormInput :disabled="sending" :label="__('IPv4 address')" :errors="$page.props.errors.content" v-model="form.content"/>
|
||||
<FormInput :disabled="sending" :label="__('Name')" :errors="action === 'create' ? $page.props.errors.name : []" v-model="form.name" />
|
||||
<FormInput :disabled="sending" :label="__('IPv4 address')" :errors="action === 'create' ? $page.props.errors.content : []" v-model="form.content" />
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-4">
|
||||
<FormSelect class="col-span-1" :disabled="sending" :label="__('Type')" :errors="action === 'create' ? $page.props.errors.type : []" v-model="form.type">
|
||||
<option value="A">{{ __('A') }}</option>
|
||||
<option value="AAAA">{{ __('AAAA') }}</option>
|
||||
<option value="CNAME">{{ __('CNAME') }}</option>
|
||||
<option value="HTTPS">{{ __('HTTPS') }}</option>
|
||||
<option value="TXT">{{ __('TXT') }}</option>
|
||||
<option value="SRV">{{ __('SRV') }}</option>
|
||||
<option value="LOC">{{ __('LOC') }}</option>
|
||||
<option value="MX">{{ __('MX') }}</option>
|
||||
<option value="NS">{{ __('NS') }}</option>
|
||||
<option value="CERT">{{ __('CERT') }}</option>
|
||||
<option value="DNSKEY">{{ __('DNSKEY') }}</option>
|
||||
<option value="DS">{{ __('DS') }}</option>
|
||||
<option value="NAPTR">{{ __('NAPTR') }}</option>
|
||||
<option value="SMIMEA">{{ __('SMIMEA') }}</option>
|
||||
<option value="SSHFP">{{ __('SSHFP') }}</option>
|
||||
<option value="SVCB">{{ __('SVCB') }}</option>
|
||||
<option value="TLSA">{{ __('TLSA') }}</option>
|
||||
</FormSelect>
|
||||
<FormInput type="number" :disabled="sending" :label="__('TTL')" :errors="action === 'create' ? $page.props.errors.ttl : []" v-model="form.ttl" />
|
||||
</div>
|
||||
|
||||
<FormActions>
|
||||
<Button>{{ __('Save') }}</Button>
|
||||
@@ -33,7 +56,7 @@
|
||||
</template>
|
||||
</SettingsSegment>
|
||||
|
||||
<EmptyImage v-if="!records.length && !loading" />
|
||||
<EmptyImage v-if="records === null && !loading" />
|
||||
|
||||
<div v-if="loading" class="inline-flex px-4">
|
||||
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
@@ -50,23 +73,50 @@
|
||||
<Table caption="DNS records list overview">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeader>{{ __('Type') }}</TableHeader>
|
||||
<TableHeader>{{ __('Name') }}</TableHeader>
|
||||
<TableHeader>{{ __('Content') }}</TableHeader>
|
||||
<TableHeader>{{ __('TTL') }}</TableHeader>
|
||||
<TableHeader></TableHeader>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow v-for="(record, index) in records" :key="record.id" class="px-2">
|
||||
<TableData>
|
||||
<Input :value="record.name" type="text" :id="index + 'x'" onkeyup="window.Vue.set(this.records, index, this.value)" />
|
||||
<p v-text="records[index].name" />
|
||||
<TableData class="pr-4">
|
||||
<FormSelect :value="record.type" :disabled="sending" :id="record.id + '-type'" :errors="(action === 'update' && recordIdBeingUpdated === record.id) ? $page.props.errors.type : []">
|
||||
<option value="A">{{ __('A') }}</option>
|
||||
<option value="AAAA">{{ __('AAAA') }}</option>
|
||||
<option value="CNAME">{{ __('CNAME') }}</option>
|
||||
<option value="HTTPS">{{ __('HTTPS') }}</option>
|
||||
<option value="TXT">{{ __('TXT') }}</option>
|
||||
<option value="SRV">{{ __('SRV') }}</option>
|
||||
<option value="LOC">{{ __('LOC') }}</option>
|
||||
<option value="MX">{{ __('MX') }}</option>
|
||||
<option value="NS">{{ __('NS') }}</option>
|
||||
<option value="CERT">{{ __('CERT') }}</option>
|
||||
<option value="DNSKEY">{{ __('DNSKEY') }}</option>
|
||||
<option value="DS">{{ __('DS') }}</option>
|
||||
<option value="NAPTR">{{ __('NAPTR') }}</option>
|
||||
<option value="SMIMEA">{{ __('SMIMEA') }}</option>
|
||||
<option value="SSHFP">{{ __('SSHFP') }}</option>
|
||||
<option value="SVCB">{{ __('SVCB') }}</option>
|
||||
<option value="TLSA">{{ __('TLSA') }}</option>
|
||||
</FormSelect>
|
||||
</TableData>
|
||||
<TableData class="pr-4">
|
||||
<FormInput class="col-span-2" :value="record.name" type="text" :id="record.id + '-name'" :errors="(action === 'update' && recordIdBeingUpdated === record.id) ? $page.props.errors.name : []" />
|
||||
</TableData>
|
||||
<TableData class="pr-4">
|
||||
<FormInput class="col-span-2" :value="record.content" type="text" :id="record.id + '-content'" :errors="(action === 'update' && recordIdBeingUpdated === record.id) ? $page.props.errors.content : []" />
|
||||
</TableData>
|
||||
<TableData class="pr-4">
|
||||
<FormInput class="!w-16" :value="record.ttl" type="number" :id="record.id + '-ttl'" :disabled="sending" :errors="(action === 'update' && recordIdBeingUpdated === record.id) ? $page.props.errors.ttl : []" />
|
||||
</TableData>
|
||||
<TableData>
|
||||
<Input v-model="records[index].content" type="text" id="TODO" />
|
||||
</TableData>
|
||||
<TableData>
|
||||
<Button @click="save(record, index)" variant="primary" size="sm">Save</Button>
|
||||
<Button @click="confirmDelete(record)" variant="danger" size="sm">Delete</Button>
|
||||
<div class="col-span-1 flex flex-col gap-y-2">
|
||||
<Button @click="save(record, index)" variant="primary" size="sm">Save</Button>
|
||||
<Button @click="confirmDelete(record)" variant="danger" size="sm">Delete</Button>
|
||||
</div>
|
||||
</TableData>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
@@ -114,155 +164,184 @@ import TableBody from '@/components/TableBody'
|
||||
import TableData from '@/components/TableData'
|
||||
import EmptyImage from '@/components/EmptyImage'
|
||||
import Input from "../../components/Input";
|
||||
import FormSelect from "../../components/forms/FormSelect";
|
||||
|
||||
export default {
|
||||
metaInfo() {
|
||||
return {
|
||||
title: `${this.__('DNS')} - ${this.site.domain}`,
|
||||
}
|
||||
},
|
||||
metaInfo() {
|
||||
return {
|
||||
title: `${this.__('DNS')} - ${this.site.domain}`,
|
||||
}
|
||||
},
|
||||
|
||||
layout: MainLayout,
|
||||
layout: MainLayout,
|
||||
|
||||
components: {
|
||||
Input,
|
||||
TopBar,
|
||||
Container,
|
||||
Content,
|
||||
Page,
|
||||
PageHeader,
|
||||
PageHeaderTitle,
|
||||
PageBody,
|
||||
Button,
|
||||
List,
|
||||
ListItem,
|
||||
StatusBubble,
|
||||
NotificationBadge,
|
||||
FormInput,
|
||||
SettingsLayout,
|
||||
SettingsSegment,
|
||||
Form,
|
||||
FormActions,
|
||||
Pagination,
|
||||
Tabs,
|
||||
Table,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableBody,
|
||||
TableData,
|
||||
EmptyImage,
|
||||
},
|
||||
components: {
|
||||
FormSelect,
|
||||
Input,
|
||||
TopBar,
|
||||
Container,
|
||||
Content,
|
||||
Page,
|
||||
PageHeader,
|
||||
PageHeaderTitle,
|
||||
PageBody,
|
||||
Button,
|
||||
List,
|
||||
ListItem,
|
||||
StatusBubble,
|
||||
NotificationBadge,
|
||||
FormInput,
|
||||
SettingsLayout,
|
||||
SettingsSegment,
|
||||
Form,
|
||||
FormActions,
|
||||
Pagination,
|
||||
Tabs,
|
||||
Table,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableBody,
|
||||
TableData,
|
||||
EmptyImage,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
loading: true,
|
||||
data() {
|
||||
return {
|
||||
sending: false,
|
||||
loading: true,
|
||||
action: 'create',
|
||||
recordIdBeingUpdated: null,
|
||||
|
||||
records: [],
|
||||
records: {},
|
||||
|
||||
recordUpdateValidationMessages: {},
|
||||
form: {
|
||||
name: null,
|
||||
content: null,
|
||||
type: null,
|
||||
ttl: null,
|
||||
},
|
||||
|
||||
form: {
|
||||
name: null,
|
||||
content: null,
|
||||
breadcrumbs: [
|
||||
{
|
||||
title: this.$page.props.settings.name,
|
||||
to: '/',
|
||||
},
|
||||
{
|
||||
title: this.__('Sites'),
|
||||
to: this.route('sites.index'),
|
||||
},
|
||||
{
|
||||
title: this.site.domain,
|
||||
to: this.route('sites.show', this.site.id),
|
||||
},
|
||||
{
|
||||
title: this.__('DNS'),
|
||||
to: this.route('sites.dns.index', this.site.id),
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
site: Object,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getRecords();
|
||||
},
|
||||
|
||||
methods: {
|
||||
useNotification,
|
||||
|
||||
submit() {
|
||||
this.$inertia.post(this.route('sites.dns.store', this.site.id), this.form, {
|
||||
onStart: () => {
|
||||
this.action = 'create';
|
||||
this.recordIdBeingUpdated = null;
|
||||
this.sending = true;
|
||||
this.records = [];
|
||||
},
|
||||
onFinish: () => {
|
||||
this.sending = false;
|
||||
this.records = [];
|
||||
this.getRecords();
|
||||
|
||||
this.form = {
|
||||
name: null,
|
||||
content: null,
|
||||
type: null,
|
||||
ttl: null,
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
breadcrumbs: [
|
||||
{
|
||||
title: this.$page.props.settings.name,
|
||||
to: '/',
|
||||
},
|
||||
{
|
||||
title: this.__('Sites'),
|
||||
to: this.route('sites.index'),
|
||||
},
|
||||
{
|
||||
title: this.site.domain,
|
||||
to: this.route('sites.show', this.site.id),
|
||||
},
|
||||
{
|
||||
title: this.__('DNS'),
|
||||
to: this.route('sites.dns.index', this.site.id),
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
site: Object,
|
||||
},
|
||||
getRecords() {
|
||||
this.loading = true;
|
||||
|
||||
mounted () {
|
||||
this.getRecords();
|
||||
},
|
||||
|
||||
methods: {
|
||||
useNotification,
|
||||
|
||||
submit() {
|
||||
this.$inertia.post(this.route('sites.dns.store', this.site.id), this.form, {
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => {
|
||||
this.sending = false;
|
||||
this.records = [];
|
||||
this.getRecords();
|
||||
|
||||
this.form = {
|
||||
name: null,
|
||||
content: null,
|
||||
};
|
||||
}
|
||||
window.axios.get(this.route('sites.dns.records', this.site.id))
|
||||
.then(response => {
|
||||
this.loading = false;
|
||||
this.records = response.data;
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
updateRecordName(event, index) {
|
||||
alert(event.target.value, index);
|
||||
},
|
||||
|
||||
getRecords() {
|
||||
this.loading = true;
|
||||
|
||||
window.axios.get(this.route('sites.dns.records', this.site.id))
|
||||
.then(response => {
|
||||
this.loading = false;
|
||||
this.records = response.data
|
||||
g})
|
||||
.catch(error => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
|
||||
save(record) {
|
||||
this.$inertia.put(this.route('sites.dns.update', [this.site.id, record.id]), {
|
||||
name: record.name,
|
||||
content: record.content,
|
||||
}, {
|
||||
preserveScroll: true,
|
||||
onStart: () => this.sending = true,
|
||||
});
|
||||
},
|
||||
|
||||
confirmDelete(record) {
|
||||
useConfirm({
|
||||
title: this.__('Are you sure?'),
|
||||
message: this.__('Your DNS will be completely removed.'),
|
||||
onConfirm: () => this.delete(record),
|
||||
.catch(error => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
|
||||
delete(record) {
|
||||
this.$inertia.delete(this.route('sites.dns.delete', [this.site.id, record.id]), {
|
||||
preserveScroll: true,
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => {
|
||||
this.sending = false;
|
||||
this.records = [];
|
||||
this.getRecords();
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
save(record, index) {
|
||||
// Vue is not reactive on nested arrays. That's why we cannot use the v-model directive on the input fields,
|
||||
// because the input fields are part of a v-for.
|
||||
let type = document.getElementById(record.id + '-type').value;
|
||||
let name = document.getElementById(record.id + '-name').value;
|
||||
let content = document.getElementById(record.id + '-content').value;
|
||||
let ttl = document.getElementById(record.id + '-ttl').value;
|
||||
|
||||
this.records[index].type = type;
|
||||
this.records[index].name = name;
|
||||
this.records[index].content = content;
|
||||
this.records[index].ttl = ttl;
|
||||
|
||||
this.$inertia.put(this.route('sites.dns.update', [this.site.id, record.id]), {
|
||||
type: type,
|
||||
name: name,
|
||||
content: content,
|
||||
ttl: ttl,
|
||||
}, {
|
||||
preserveScroll: true,
|
||||
onStart: () => {
|
||||
this.sending = true;
|
||||
this.action = 'update';
|
||||
this.recordIdBeingUpdated = record.id;
|
||||
},
|
||||
onFinish: () => {
|
||||
this.sending = false;
|
||||
this.getRecords();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
confirmDelete(record) {
|
||||
useConfirm({
|
||||
title: this.__('Are you sure?'),
|
||||
message: this.__('Your DNS will be completely removed.'),
|
||||
onConfirm: () => this.delete(record),
|
||||
})
|
||||
},
|
||||
|
||||
delete(record) {
|
||||
this.$inertia.delete(this.route('sites.dns.delete', [this.site.id, record.id]), {
|
||||
preserveScroll: true,
|
||||
onStart: () => this.sending = true,
|
||||
onFinish: () => {
|
||||
this.sending = false;
|
||||
this.records = [];
|
||||
this.getRecords();
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<FormGroup class="relative">
|
||||
<Label :errors="errors" :forId="id">{{ label }}</Label>
|
||||
<Label :errors="errors" :forId="id" v-if="label">{{ label }}</Label>
|
||||
|
||||
<button type="button" @click="copy" v-if="allowCopy" class="flex items-center right-0 absolute text-xs text-medium-emphasis">
|
||||
<IconClipboard class="mr-2" />
|
||||
@@ -50,7 +50,7 @@ export default {
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<FormGroup>
|
||||
<Label :errors="errors" :forId="id">{{ label }}</Label>
|
||||
<Label :errors="errors" :forId="id" v-if="label">{{ label }}</Label>
|
||||
<select :disabled="loading || disabled" :class="[
|
||||
defaultClasses,
|
||||
disabled || loading ? 'opacity-50' : '',
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
|
||||
Reference in New Issue
Block a user