mirror of
https://github.com/1f349/admin.1f349.com.git
synced 2025-02-22 13:34:57 +00:00
Rewrite domains page
This commit is contained in:
parent
e27386f4dd
commit
9909f06a40
@ -23,6 +23,7 @@
|
|||||||
"vite": "^4.4.5"
|
"vite": "^4.4.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^7.9.0"
|
"d3": "^7.9.0",
|
||||||
|
"ipaddr.js": "^2.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/components/CutOff.svelte
Normal file
25
src/components/CutOff.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<div class="cutoff-wrapper">
|
||||||
|
<span class="cutoff"><slot /></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.cutoff-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cutoff {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-wrap: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-inline: 15px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 1rem;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
</style>
|
13
src/components/CutOffTd.svelte
Normal file
13
src/components/CutOffTd.svelte
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script>
|
||||||
|
import CutOff from "./CutOff.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<td {...$$restProps}>
|
||||||
|
<CutOff><slot /></CutOff>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
td {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -22,7 +22,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
background-color: rgba(0,0,0,0.55);
|
background-color: rgba(0, 0, 0, 0.55);
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
&.show {
|
&.show {
|
||||||
@ -45,6 +45,7 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50vh;
|
top: 50vh;
|
||||||
left: 50vw;
|
left: 50vw;
|
||||||
|
max-width: calc(100vw - 72px);
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
background-color: $theme-header;
|
background-color: $theme-header;
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
|
40
src/components/create-domains/ACreate.svelte
Normal file
40
src/components/create-domains/ACreate.svelte
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {DnsTypeA, DnsTypeAAAA, type AaaaRecord, type ARecord} from "../../types/records";
|
||||||
|
import {IPv4, IPv6, parse as parseAddr} from "ipaddr.js";
|
||||||
|
|
||||||
|
export let editItem: ARecord | AaaaRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
|
||||||
|
let value: string = "";
|
||||||
|
|
||||||
|
function onChange() {
|
||||||
|
try {
|
||||||
|
let addr = parseAddr(value);
|
||||||
|
if (addr instanceof IPv4) {
|
||||||
|
(editItem as ARecord).A = addr.toString();
|
||||||
|
editItem.Hdr.Rrtype = DnsTypeA;
|
||||||
|
} else if (addr instanceof IPv6) {
|
||||||
|
(editItem as AaaaRecord).AAAA = addr.toString();
|
||||||
|
editItem.Hdr.Rrtype = DnsTypeAAAA;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
editItem.Hdr.Rrtype = 0;
|
||||||
|
console.error("Invalid IP address:", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div>IP Address</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value on:keyup={onChange} size={Math.max(20, value.length + 2)} /></div>
|
||||||
|
{#if editItem.Hdr.Rrtype === DnsTypeA}
|
||||||
|
<div>IP address is IPv4</div>
|
||||||
|
{:else if editItem.Hdr.Rrtype === DnsTypeAAAA}
|
||||||
|
<div>IP address is IPv6</div>
|
||||||
|
{/if}
|
17
src/components/create-domains/CaaCreate.svelte
Normal file
17
src/components/create-domains/CaaCreate.svelte
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {CaaRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: CaaRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Tag</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Tag} size={Math.max(20, editItem.Tag.length + 2)} /></div>
|
||||||
|
<div>Value</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Value} size={Math.max(20, editItem.Value.length + 2)} /></div>
|
15
src/components/create-domains/CnameCreate.svelte
Normal file
15
src/components/create-domains/CnameCreate.svelte
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {CnameRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: CnameRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Target</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Target} size={Math.max(20, editItem.Target.length + 2)} /></div>
|
17
src/components/create-domains/MxCreate.svelte
Normal file
17
src/components/create-domains/MxCreate.svelte
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {MxRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: MxRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Mail Server</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Mx} size={Math.max(20, editItem.Mx.length + 2)} /></div>
|
||||||
|
<div>Preference</div>
|
||||||
|
<div><input type="number" class="code-font" bind:value={editItem.Preference} /></div>
|
15
src/components/create-domains/NsCreate.svelte
Normal file
15
src/components/create-domains/NsCreate.svelte
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {NsRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: NsRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Nameserver</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Ns} size={Math.max(20, editItem.Ns.length + 2)} /></div>
|
21
src/components/create-domains/SrvCreate.svelte
Normal file
21
src/components/create-domains/SrvCreate.svelte
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {SrvRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: SrvRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Priority</div>
|
||||||
|
<div><input type="number" class="code-font" bind:value={editItem.Priority} /></div>
|
||||||
|
<div>Weight</div>
|
||||||
|
<div><input type="number" class="code-font" bind:value={editItem.Weight} /></div>
|
||||||
|
<div>Port</div>
|
||||||
|
<div><input type="number" class="code-font" bind:value={editItem.Port} /></div>
|
||||||
|
<div>Target</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Target} size={Math.max(20, editItem.Target.length + 2)} /></div>
|
19
src/components/create-domains/TxtCreate.svelte
Normal file
19
src/components/create-domains/TxtCreate.svelte
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type {TxtRecord} from "../../types/records";
|
||||||
|
|
||||||
|
export let editItem: TxtRecord;
|
||||||
|
export let editMode: boolean;
|
||||||
|
|
||||||
|
function constrain(min: number, max: number, value: number) {
|
||||||
|
return Math.min(max, Math.max(min, value));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>Name</div>
|
||||||
|
{#if editMode}
|
||||||
|
<div class="code-font">{editItem.Hdr.Name}</div>
|
||||||
|
{:else}
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Hdr.Name} size={Math.max(20, editItem.Hdr.Name.length + 2)} /></div>
|
||||||
|
{/if}
|
||||||
|
<div>Value</div>
|
||||||
|
<div><input type="text" class="code-font" bind:value={editItem.Txt[0]} size={constrain(20, 100, editItem.Txt[0].length + 2)} /></div>
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {isAaaaRecord, isARecord, type AaaaRecord, type ARecord} from "../../stores/records";
|
import {isAaaaRecord, isARecord, type AaaaRecord, type ARecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import ACreate from "../create-domains/ACreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<ARecord | AaaaRecord>;
|
export let value: RestItem<ARecord | AaaaRecord>;
|
||||||
let editItem: ARecord & AaaaRecord = {
|
let editItem: ARecord & AaaaRecord = {
|
||||||
@ -26,6 +27,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">{isARecord(value.data) ? value.data.A : isAaaaRecord(value.data) ? value.data.AAAA : ""}</td>
|
<td class="code-font">{isARecord(value.data) ? value.data.A : isAaaaRecord(value.data) ? value.data.AAAA : ""}</td>
|
||||||
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -37,17 +39,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit {isARecord(value.data) ? 'A' : 'AAAA'} Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit {isARecord(value.data) ? 'A' : 'AAAA'} Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<ACreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
{#if isARecord(value.data)}
|
|
||||||
<div>IPv4 Address</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.A} size={Math.max(20, editItem.A.length + 2)} /></div>
|
|
||||||
{:else if isAaaaRecord(value.data)}
|
|
||||||
<div>IPv6 Address</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.AAAA} size={Math.max(20, editItem.AAAA.length + 2)} /></div>
|
|
||||||
{:else}
|
|
||||||
<div>Pretty sure something is broken. WOMP WOMP!!</div>
|
|
||||||
{/if}
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {CaaRecord} from "../../stores/records";
|
import type {CaaRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import CaaCreate from "../create-domains/CaaCreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<CaaRecord>;
|
export let value: RestItem<CaaRecord>;
|
||||||
let editItem: CaaRecord = {
|
let editItem: CaaRecord = {
|
||||||
@ -28,6 +29,7 @@
|
|||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">{value.data.Tag}</td>
|
<td class="code-font">{value.data.Tag}</td>
|
||||||
<td class="code-font">{value.data.Value}</td>
|
<td class="code-font">{value.data.Value}</td>
|
||||||
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -39,12 +41,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit CAA Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit CAA Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<CaaCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Tag</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Tag} size={Math.max(20, editItem.Tag.length + 2)} /></div>
|
|
||||||
<div>Value</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Value} size={Math.max(20, editItem.Value.length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {CnameRecord} from "../../stores/records";
|
import type {CnameRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import CnameCreate from "../create-domains/CnameCreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<CnameRecord>;
|
export let value: RestItem<CnameRecord>;
|
||||||
let editItem: CnameRecord = {
|
let editItem: CnameRecord = {
|
||||||
@ -25,6 +26,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">{value.data.Target}</td>
|
<td class="code-font">{value.data.Target}</td>
|
||||||
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -36,10 +38,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit CNAME Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit CNAME Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<CnameCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Target</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Target} size={Math.max(20, editItem.Target.length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {MxRecord} from "../../stores/records";
|
import type {MxRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import MxCreate from "../create-domains/MxCreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<MxRecord>;
|
export let value: RestItem<MxRecord>;
|
||||||
let editItem: MxRecord = {
|
let editItem: MxRecord = {
|
||||||
@ -27,6 +28,7 @@
|
|||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">{value.data.Mx}</td>
|
<td class="code-font">{value.data.Mx}</td>
|
||||||
<td class="code-font">{value.data.Preference}</td>
|
<td class="code-font">{value.data.Preference}</td>
|
||||||
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -37,13 +39,8 @@
|
|||||||
remove={() => value.remove()}
|
remove={() => value.remove()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit SOA Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit MX Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<MxCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Mail Server</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Mx} size={Math.max(20, editItem.Mx.length + 2)} /></div>
|
|
||||||
<div>Preference</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Preference} size={Math.max(20, editItem.Preference.length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {NsRecord} from "../../stores/records";
|
import type {NsRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import NsCreate from "../create-domains/NsCreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<NsRecord>;
|
export let value: RestItem<NsRecord>;
|
||||||
let editItem: NsRecord = {
|
let editItem: NsRecord = {
|
||||||
@ -25,6 +26,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">{value.data.Ns}</td>
|
<td class="code-font">{value.data.Ns}</td>
|
||||||
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -36,10 +38,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit SOA Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit SOA Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<NsCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Nameserver</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Ns} size={Math.max(20, editItem.Ns.length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {SoaRecord} from "../../stores/records";
|
import type {SoaRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {CnameRecord, SrvRecord} from "../../stores/records";
|
import type {SrvRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import SrvCreate from "../create-domains/SrvCreate.svelte";
|
||||||
|
|
||||||
export let value: RestItem<SrvRecord>;
|
export let value: RestItem<SrvRecord>;
|
||||||
let editItem: SrvRecord = {
|
let editItem: SrvRecord = {
|
||||||
@ -43,10 +44,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit CNAME Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit CNAME Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<SrvCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Target</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Target} size={Math.max(20, editItem.Target.length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {TxtRecord} from "../../stores/records";
|
import type {TxtRecord} from "../../types/records";
|
||||||
import type {RestItem} from "../../utils/rest-table";
|
import type {RestItem} from "../../utils/rest-table";
|
||||||
import ActionMenu from "../ActionMenu.svelte";
|
import ActionMenu from "../ActionMenu.svelte";
|
||||||
import ActionPopup from "../ActionPopup.svelte";
|
import ActionPopup from "../ActionPopup.svelte";
|
||||||
|
import TxtCreate from "../create-domains/TxtCreate.svelte";
|
||||||
|
import TdCutOff from "../CutOffTd.svelte";
|
||||||
|
|
||||||
export let value: RestItem<TxtRecord>;
|
export let value: RestItem<TxtRecord>;
|
||||||
let editItem: TxtRecord = {
|
let editItem: TxtRecord = {
|
||||||
@ -24,9 +26,8 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="code-font">{value.data.Hdr.Name}</td>
|
<td class="code-font">{value.data.Hdr.Name}</td>
|
||||||
<td class="code-font">
|
<TdCutOff class="code-font">{value.data.Txt.join("\n")}</TdCutOff>
|
||||||
<span class="cutoff">{value.data.Txt.join("\n")}</span>
|
<td class="code-font">{value.data.Hdr.Ttl}</td>
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<ActionMenu
|
<ActionMenu
|
||||||
data={value}
|
data={value}
|
||||||
@ -38,10 +39,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ActionPopup name="Edit TXT Record" bind:show={editPopup} on:save={save}>
|
<ActionPopup name="Edit TXT Record" bind:show={editPopup} on:save={save}>
|
||||||
<div>Name</div>
|
<TxtCreate bind:editItem editMode={true} />
|
||||||
<div class="code-font">{editItem.Hdr.Name}</div>
|
|
||||||
<div>Value</div>
|
|
||||||
<div><input type="text" class="code-font" bind:value={editItem.Txt[0]} size={Math.max(20, editItem.Txt[0].length + 2)} /></div>
|
|
||||||
</ActionPopup>
|
</ActionPopup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -8,6 +8,8 @@ export const DnsTypeTXT = 16;
|
|||||||
export const DnsTypeSRV = 33;
|
export const DnsTypeSRV = 33;
|
||||||
export const DnsTypeCAA = 257;
|
export const DnsTypeCAA = 257;
|
||||||
|
|
||||||
|
export type AllRecords = SoaRecord | NsRecord | MxRecord | ARecord | AaaaRecord | CnameRecord | TxtRecord | SrvRecord | CaaRecord;
|
||||||
|
|
||||||
export interface RecordHeader {
|
export interface RecordHeader {
|
||||||
Name: string;
|
Name: string;
|
||||||
Rrtype: number;
|
Rrtype: number;
|
71
src/views/DomainTableView.svelte
Normal file
71
src/views/DomainTableView.svelte
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {domainOption} from "../stores/domain-option";
|
||||||
|
import type {RestItem, RestTable} from "../utils/rest-table";
|
||||||
|
import PromiseTable from "../components/PromiseTable.svelte";
|
||||||
|
import PromiseLike from "../components/PromiseLike.svelte";
|
||||||
|
import type {AllRecords, UnknownRecord} from "../types/records";
|
||||||
|
import ActionPopup from "../components/ActionPopup.svelte";
|
||||||
|
|
||||||
|
type T = $$Generic<UnknownRecord>;
|
||||||
|
|
||||||
|
export let recordName: string;
|
||||||
|
export let table: RestTable<AllRecords>;
|
||||||
|
export let emptyRecord: (() => any) | null;
|
||||||
|
export let rowOrdering: (rows: RestItem<AllRecords>[], domain: string, isTRecord: (t: UnknownRecord) => t is T) => RestItem<T>[];
|
||||||
|
export let isTRecord: (t: UnknownRecord) => t is T;
|
||||||
|
|
||||||
|
let createItem: T | null = emptyRecord == null ? null : emptyRecord();
|
||||||
|
let createPopup: boolean = false;
|
||||||
|
|
||||||
|
function createRecord() {
|
||||||
|
table.addItem(createItem as any);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h2>{recordName} Records</h2>
|
||||||
|
{#if emptyRecord != null && createItem != null}
|
||||||
|
<button class="create-button" on:click={() => (createPopup = true)}>Create {recordName} Record</button>
|
||||||
|
|
||||||
|
<ActionPopup name="Create {recordName} Record" bind:show={createPopup} on:save={createRecord}>
|
||||||
|
<slot name="create" editItem={createItem} editMode={false} />
|
||||||
|
</ActionPopup>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PromiseTable value={table}>
|
||||||
|
<slot name="headers" slot="headers" />
|
||||||
|
|
||||||
|
<svelte:fragment slot="rows" let:value>
|
||||||
|
{#each rowOrdering(value.rows, $domainOption, isTRecord) as item}
|
||||||
|
<PromiseLike value={item}>
|
||||||
|
<tr slot="loading" class="empty-row">
|
||||||
|
<td colspan="100">
|
||||||
|
<div>Loading...</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr slot="error" let:reason class="empty-row">
|
||||||
|
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<slot name="row" slot="ok" let:value {value} />
|
||||||
|
</PromiseLike>
|
||||||
|
{/each}
|
||||||
|
</svelte:fragment>
|
||||||
|
</PromiseTable>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../values.scss";
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-button {
|
||||||
|
@include button-green-box;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,8 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {LOGIN} from "../utils/login";
|
|
||||||
import {domainOption} from "../stores/domain-option";
|
import {domainOption} from "../stores/domain-option";
|
||||||
import {
|
import {
|
||||||
|
DnsTypeA,
|
||||||
|
DnsTypeCAA,
|
||||||
|
DnsTypeCNAME,
|
||||||
|
DnsTypeMX,
|
||||||
|
DnsTypeNS,
|
||||||
DnsTypeSOA,
|
DnsTypeSOA,
|
||||||
|
DnsTypeSRV,
|
||||||
|
DnsTypeTXT,
|
||||||
isARecord,
|
isARecord,
|
||||||
isAaaaRecord,
|
isAaaaRecord,
|
||||||
isCaaRecord,
|
isCaaRecord,
|
||||||
@ -14,6 +20,7 @@
|
|||||||
isTxtRecord,
|
isTxtRecord,
|
||||||
type ARecord,
|
type ARecord,
|
||||||
type AaaaRecord,
|
type AaaaRecord,
|
||||||
|
type AllRecords,
|
||||||
type CaaRecord,
|
type CaaRecord,
|
||||||
type CnameRecord,
|
type CnameRecord,
|
||||||
type MxRecord,
|
type MxRecord,
|
||||||
@ -22,9 +29,7 @@
|
|||||||
type SrvRecord,
|
type SrvRecord,
|
||||||
type TxtRecord,
|
type TxtRecord,
|
||||||
type UnknownRecord,
|
type UnknownRecord,
|
||||||
} from "../stores/records";
|
} from "../types/records";
|
||||||
import ActionMenu from "../components/ActionMenu.svelte";
|
|
||||||
import PromiseTable from "../components/PromiseTable.svelte";
|
|
||||||
import {RestItem, RestTable} from "../utils/rest-table";
|
import {RestItem, RestTable} from "../utils/rest-table";
|
||||||
import PromiseLike from "../components/PromiseLike.svelte";
|
import PromiseLike from "../components/PromiseLike.svelte";
|
||||||
import SoaRow from "../components/domains/SoaRow.svelte";
|
import SoaRow from "../components/domains/SoaRow.svelte";
|
||||||
@ -35,15 +40,21 @@
|
|||||||
import TxtRow from "../components/domains/TxtRow.svelte";
|
import TxtRow from "../components/domains/TxtRow.svelte";
|
||||||
import CaaRow from "../components/domains/CaaRow.svelte";
|
import CaaRow from "../components/domains/CaaRow.svelte";
|
||||||
import SrvRow from "../components/domains/SrvRow.svelte";
|
import SrvRow from "../components/domains/SrvRow.svelte";
|
||||||
|
import DomainTableView from "./DomainTableView.svelte";
|
||||||
|
import ActionPopup from "../components/ActionPopup.svelte";
|
||||||
|
import NsCreate from "../components/create-domains/NsCreate.svelte";
|
||||||
|
import MxCreate from "../components/create-domains/MxCreate.svelte";
|
||||||
|
import ACreate from "../components/create-domains/ACreate.svelte";
|
||||||
|
import CnameCreate from "../components/create-domains/CnameCreate.svelte";
|
||||||
|
import CaaCreate from "../components/create-domains/CaaCreate.svelte";
|
||||||
|
import TxtCreate from "../components/create-domains/TxtCreate.svelte";
|
||||||
|
|
||||||
const apiAzalea = import.meta.env.VITE_API_AZALEA;
|
const apiAzalea = import.meta.env.VITE_API_AZALEA;
|
||||||
|
|
||||||
type AllRecords = SoaRecord | NsRecord | MxRecord | ARecord | AaaaRecord | CnameRecord | TxtRecord | SrvRecord | CaaRecord;
|
|
||||||
|
|
||||||
const table = new RestTable<AllRecords>(apiAzalea + "/domains/" + $domainOption + "/records", (item: AllRecords) => item.Hdr.Name);
|
const table = new RestTable<AllRecords>(apiAzalea + "/domains/" + $domainOption + "/records", (item: AllRecords) => item.Hdr.Name);
|
||||||
|
|
||||||
function rowOrdering<T extends UnknownRecord>(
|
function rowOrdering<T extends UnknownRecord>(
|
||||||
rows: RestItem<UnknownRecord>[],
|
rows: RestItem<AllRecords>[],
|
||||||
domain: string,
|
domain: string,
|
||||||
isTRecord: (t: UnknownRecord) => t is T,
|
isTRecord: (t: UnknownRecord) => t is T,
|
||||||
): RestItem<T>[] {
|
): RestItem<T>[] {
|
||||||
@ -54,6 +65,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function domainFilter(src: string, domain: string) {
|
function domainFilter(src: string, domain: string) {
|
||||||
|
domain = fqdn(domain);
|
||||||
if (domain == "*") return true;
|
if (domain == "*") return true;
|
||||||
let n = src.indexOf("/");
|
let n = src.indexOf("/");
|
||||||
if (n == -1) n = src.length;
|
if (n == -1) n = src.length;
|
||||||
@ -71,6 +83,11 @@
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fqdn(domain: string): string {
|
||||||
|
if (domain.endsWith(".")) return domain;
|
||||||
|
return domain + ".";
|
||||||
|
}
|
||||||
|
|
||||||
let soaRecords: SoaRecord[] = [
|
let soaRecords: SoaRecord[] = [
|
||||||
{
|
{
|
||||||
Hdr: {
|
Hdr: {
|
||||||
@ -88,285 +105,174 @@
|
|||||||
Minttl: 0,
|
Minttl: 0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
let domainTitle: string = getTitleDomain(soaRecords[0].Hdr.Name);
|
||||||
|
let zoneFileUrl: string = `${import.meta.env.VITE_API_AZALEA}/domains/${domainTitle}/zone-file`;
|
||||||
|
|
||||||
|
let recordTypes = [
|
||||||
|
{
|
||||||
|
name: "SOA",
|
||||||
|
headers: ["Primary Domain", "Email", "Default TTL", "Refresh Rate", "Retry Rate", "Expire Time"],
|
||||||
|
filter: isSoaRecord,
|
||||||
|
render: SoaRow,
|
||||||
|
create: null,
|
||||||
|
save: null,
|
||||||
|
empty: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NS",
|
||||||
|
headers: ["Subdomain", "Name Server", "TTL"],
|
||||||
|
filter: isNsRecord,
|
||||||
|
render: NsRow,
|
||||||
|
create: NsCreate,
|
||||||
|
empty: (): NsRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeNS,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Ns: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MX",
|
||||||
|
headers: ["Mail Server", "Preference", "Subdomain", "TTL"],
|
||||||
|
filter: isMxRecord,
|
||||||
|
render: MxRow,
|
||||||
|
create: MxCreate,
|
||||||
|
empty: (): MxRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeMX,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Mx: "",
|
||||||
|
Preference: 0,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "A/AAAA",
|
||||||
|
headers: ["Hostname", "IP Address", "TTL"],
|
||||||
|
filter: (t: UnknownRecord) => isARecord(t) || isAaaaRecord(t),
|
||||||
|
render: ARow,
|
||||||
|
create: ACreate,
|
||||||
|
empty: (): ARecord | AaaaRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: 0, // this is on purpose
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
A: "",
|
||||||
|
AAAA: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CNAME",
|
||||||
|
headers: ["Hostname", "Aliases to", "TTL"],
|
||||||
|
filter: isCnameRecord,
|
||||||
|
render: CnameRow,
|
||||||
|
create: CnameCreate,
|
||||||
|
empty: (): CnameRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeCNAME,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Target: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TXT",
|
||||||
|
headers: ["Hostname", "Value", "TTL"],
|
||||||
|
filter: isTxtRecord,
|
||||||
|
render: TxtRow,
|
||||||
|
create: TxtCreate,
|
||||||
|
empty: (): TxtRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeTXT,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Txt: [""],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SRV",
|
||||||
|
headers: ["Name", "Priority", "Weight", "Port", "Target", "TTL"],
|
||||||
|
filter: isSrvRecord,
|
||||||
|
render: SrvRow,
|
||||||
|
create: null,
|
||||||
|
empty: (): SrvRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeSRV,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Priority: 0,
|
||||||
|
Weight: 0,
|
||||||
|
Port: 0,
|
||||||
|
Target: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CAA",
|
||||||
|
headers: ["Name", "Tag", "Value", "TTL"],
|
||||||
|
filter: isCaaRecord,
|
||||||
|
render: CaaRow,
|
||||||
|
create: CaaCreate,
|
||||||
|
empty: (): CaaRecord => ({
|
||||||
|
Hdr: {
|
||||||
|
Name: "",
|
||||||
|
Rrtype: DnsTypeCAA,
|
||||||
|
Class: 1,
|
||||||
|
Ttl: 0,
|
||||||
|
},
|
||||||
|
Flag: 0,
|
||||||
|
Tag: "",
|
||||||
|
Value: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function toAny(a: any) {
|
||||||
|
return a as any;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if soaRecords.length >= 1}
|
{#if soaRecords.length >= 1}
|
||||||
<div class="title-row">
|
<div class="title-row">
|
||||||
<h1>Domains / {getTitleDomain(soaRecords[0].Hdr.Name)}</h1>
|
<h1>Domains / {domainTitle}</h1>
|
||||||
<a
|
<a class="zone-download" href={zoneFileUrl} download="{domainTitle}.zone">Download DNS Zone File</a>
|
||||||
class="zone-download"
|
|
||||||
href="{import.meta.env.VITE_API_AZALEA}/domains/{getTitleDomain(soaRecords[0].Hdr.Name)}/zone-file"
|
|
||||||
download="{getTitleDomain(soaRecords[0].Hdr.Name)}.zone"
|
|
||||||
>
|
|
||||||
Download DNS Zone File
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<h2>SOA Record</h2>
|
{#each recordTypes as recordType}
|
||||||
<PromiseTable value={table}>
|
<DomainTableView recordName={recordType.name} {table} emptyRecord={recordType.empty} {rowOrdering} isTRecord={recordType.filter}>
|
||||||
<tr slot="headers">
|
<tr slot="headers">
|
||||||
<th>Primary Domain</th>
|
{#each recordType.headers as header}
|
||||||
<th>Email</th>
|
<th>{header}</th>
|
||||||
<th>Default TTL</th>
|
{/each}
|
||||||
<th>Refresh Rate</th>
|
<th></th>
|
||||||
<th>Retry Rate</th>
|
</tr>
|
||||||
<th>Expire Time</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
<svelte:fragment slot="create" let:editItem let:editMode>
|
||||||
{#each rowOrdering(value.rows, $domainOption, isSoaRecord) as item}
|
{#if recordType.create != null && recordType.empty != null}
|
||||||
<PromiseLike value={item}>
|
<svelte:component this={recordType.create} editItem={toAny(editItem)} {editMode} />
|
||||||
<tr slot="loading" class="empty-row">
|
{/if}
|
||||||
<td colspan="100">
|
</svelte:fragment>
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
<svelte:component this={recordType.render} slot="row" let:value {value} />
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
</DomainTableView>
|
||||||
</tr>
|
{/each}
|
||||||
|
|
||||||
<SoaRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>NS Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Name Server</th>
|
|
||||||
<th>Subdomain</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isNsRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<NsRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>MX Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Mail Server</th>
|
|
||||||
<th>Preference</th>
|
|
||||||
<th>Subdomain</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isMxRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<MxRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>A/AAAA Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Hostname</th>
|
|
||||||
<th>IP Address</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, t => isARecord(t) || isAaaaRecord(t)) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<ARow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>CNAME Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Hostname</th>
|
|
||||||
<th>Aliases to</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isCnameRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<CnameRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>TXT Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Hostname</th>
|
|
||||||
<th>Value</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isTxtRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<TxtRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>SRV Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Priority</th>
|
|
||||||
<th>Weight</th>
|
|
||||||
<th>Port</th>
|
|
||||||
<th>Target</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isSrvRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<SrvRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<h2>CAA Record</h2>
|
|
||||||
<PromiseTable value={table}>
|
|
||||||
<tr slot="headers">
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Tag</th>
|
|
||||||
<th>Value</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<svelte:fragment slot="rows" let:value>
|
|
||||||
{#each rowOrdering(value.rows, $domainOption, isCaaRecord) as item}
|
|
||||||
<PromiseLike value={item}>
|
|
||||||
<tr slot="loading" class="empty-row">
|
|
||||||
<td colspan="100">
|
|
||||||
<div>Loading...</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr slot="error" let:reason class="empty-row">
|
|
||||||
<td colspan="100">Error loading row for {item.data.Hdr.Name}: {reason}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<CaaRow slot="ok" let:value {value} />
|
|
||||||
</PromiseLike>
|
|
||||||
{/each}
|
|
||||||
</svelte:fragment>
|
|
||||||
</PromiseTable>
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "../values.scss";
|
@import "../values.scss";
|
||||||
|
|
||||||
button.action-menu {
|
|
||||||
@include button-green-highlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
table tbody tr {
|
|
||||||
td {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
span.cutoff {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
text-wrap: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
margin-inline: 15px;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1rem;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.empty-row td {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-row {
|
.title-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -731,6 +731,11 @@ inherits@2:
|
|||||||
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
|
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
|
||||||
integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
|
integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
|
||||||
|
|
||||||
|
ipaddr.js@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
|
||||||
|
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
|
||||||
|
|
||||||
is-binary-path@~2.1.0:
|
is-binary-path@~2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
|
resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user