Skip to content

Commit 0c4c5d9

Browse files
committed
feat(frontend): custom dns
1 parent 63f056f commit 0c4c5d9

File tree

1 file changed

+121
-2
lines changed
  • apps/frontend/src/pages/servers/manage/[id]/options

1 file changed

+121
-2
lines changed

apps/frontend/src/pages/servers/manage/[id]/options/network.vue

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<!-- Subdomain section -->
4242
<div class="card flex flex-col gap-4">
4343
<label for="username-field" class="flex flex-col gap-2">
44-
<span class="text-lg font-bold text-contrast">Custom URL</span>
44+
<span class="text-lg font-bold text-contrast">Custom Subdomain</span>
4545
<span> Your friends can connect to your server using this URL. </span>
4646
</label>
4747
<div class="flex w-full items-center gap-2 md:w-[60%]">
@@ -59,6 +59,73 @@
5959
</span>
6060
</div>
6161

62+
<div class="card flex flex-col gap-4">
63+
<div class="flex w-full flex-row items-center justify-between">
64+
<label for="username-field" class="flex flex-col gap-2">
65+
<span class="text-lg font-bold text-contrast">DNS records</span>
66+
<span> Use your personal domain to connect to your server. </span>
67+
</label>
68+
69+
<Button @click="exportDnsRecords"> Export DNS records </Button>
70+
</div>
71+
72+
<input
73+
v-model="userDomain"
74+
class="w-full md:w-[50%]"
75+
maxlength="64"
76+
minlength="1"
77+
type="text"
78+
placeholder="domain.com"
79+
/>
80+
81+
<div class="rounded-xl bg-table-alternateRow p-4">
82+
<table
83+
class="min-w-full border-collapse overflow-hidden rounded-lg border-2 border-gray-300"
84+
>
85+
<tbody>
86+
<tr v-for="record in dnsRecords" :key="record.content">
87+
<td class="py-3">
88+
<div class="ml-2 flex flex-col gap-1" @click="copyText(record.type)">
89+
<span
90+
class="text-md font-bold tracking-wide text-contrast hover:cursor-pointer"
91+
>
92+
{{ record.type }}
93+
</span>
94+
<span class="text-xs uppercase text-secondary">type</span>
95+
</div>
96+
</td>
97+
<td class="py-3">
98+
<div class="flex flex-col gap-1" @click="copyText(record.name)">
99+
<span
100+
class="text-md font-bold tracking-wide text-contrast hover:cursor-pointer"
101+
>
102+
{{ record.name }}
103+
</span>
104+
<span class="text-xs uppercase text-secondary">name</span>
105+
</div>
106+
</td>
107+
<td class="px-4">
108+
<div class="flex flex-col gap-1" @click="copyText(record.content)">
109+
<span
110+
class="text-md w-fit font-bold tracking-wide text-contrast hover:cursor-pointer"
111+
>
112+
{{ record.content }}
113+
</span>
114+
<span class="text-xs uppercase text-secondary">content</span>
115+
</div>
116+
</td>
117+
</tr>
118+
</tbody>
119+
</table>
120+
</div>
121+
<div class="flex items-center gap-2">
122+
<InfoIcon />
123+
<span class="text-sm text-secondary">
124+
You must own your own domain to use this feature.
125+
</span>
126+
</div>
127+
</div>
128+
62129
<!-- Allocations section -->
63130
<div class="card flex flex-col gap-4">
64131
<div class="flex w-full flex-row items-center justify-between">
@@ -143,7 +210,7 @@
143210
</template>
144211

145212
<script setup lang="ts">
146-
import { PlusIcon, TrashIcon, EditIcon, VersionIcon, SaveIcon } from "@modrinth/assets";
213+
import { PlusIcon, TrashIcon, EditIcon, VersionIcon, SaveIcon, InfoIcon } from "@modrinth/assets";
147214
import { ButtonStyled, Modal, Button } from "@modrinth/ui";
148215
import type { Server } from "~/composables/pyroServers";
149216
@@ -157,6 +224,7 @@ const data = computed(() => props.server.general);
157224
const serverIP = ref(data?.value?.net?.ip ?? "");
158225
const serverSubdomain = ref(data?.value?.net?.domain ?? "");
159226
const serverPrimaryPort = ref(data?.value?.net?.port ?? 0);
227+
const userDomain = ref("play.yourdomain.com");
160228
161229
const network = computed(() => props.server.network);
162230
const allocations = computed(() => network.value?.allocations);
@@ -279,4 +347,55 @@ const saveNetwork = async () => {
279347
const resetNetwork = () => {
280348
serverSubdomain.value = data?.value?.net?.domain ?? "";
281349
};
350+
351+
const dnsRecords = computed(() => {
352+
return [
353+
{
354+
type: "A",
355+
name: `${userDomain.value}`,
356+
content: data.value?.net?.ip ?? "",
357+
},
358+
{
359+
type: "SRV",
360+
name: `_minecraft._tcp.${userDomain.value}`,
361+
content: `0 0 ${data.value?.net?.port} ${userDomain.value}`,
362+
},
363+
];
364+
});
365+
366+
const exportDnsRecords = () => {
367+
const records = dnsRecords.value.reduce(
368+
(acc, record) => {
369+
const type = record.type;
370+
if (!acc[type]) {
371+
acc[type] = [];
372+
}
373+
acc[type].push(record);
374+
return acc;
375+
},
376+
{} as Record<string, any[]>,
377+
);
378+
379+
const text = Object.entries(records)
380+
.map(([type, records]) => {
381+
return `; ${type} Record\n${records.map((record) => `${record.name}. 1 IN ${record.type} ${record.content}`).join("\n")}\n`;
382+
})
383+
.join("\n");
384+
const blob = new Blob([text], { type: "text/plain" });
385+
const a = document.createElement("a");
386+
a.href = window.URL.createObjectURL(blob);
387+
a.download = `${userDomain.value}.txt`;
388+
a.click();
389+
a.remove();
390+
};
391+
392+
const copyText = (text: string) => {
393+
navigator.clipboard.writeText(text);
394+
addNotification({
395+
group: "serverOptions",
396+
type: "success",
397+
title: "Text copied",
398+
text: `${text} has been copied to your clipboard`,
399+
});
400+
};
282401
</script>

0 commit comments

Comments
 (0)