drop/server/components/ServerForm.vue
wdunn001 0348d10602 community: M4 -- game-server registry and issue reports
GameServer/GameServerStatusHistory/Issue/IssueComment models, a
strategy-per-probe_type ServerProbe (tcp_connect/http_get/presence_inferred,
mirroring script-library's game-server-registry-probe.py including the
integer ConnectTimeout fix), the bundled verified registry seed (WoW, EQEmu,
the Goldberg relay, Impostor, OpenDAoC), and full player+admin UI at
/community/servers and /community/issues. Featured flag pins the
persistent-world servers (WoW/EQEmu/OpenDAoC) to a compact status panel
surfaced on the community landing page. Scheduled sweep respects a
circuit-breaker backoff and never probes on page load; the relay is never
network-probed, only liveness-checked over ssh.
2026-08-03 03:19:54 -04:00

230 lines
7.4 KiB
Vue

<template>
<div class="flex flex-col gap-y-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{ $t("common.name") }}</span>
<input
v-model="model.name"
type="text"
required
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
<label class="flex items-center gap-x-2">
<input
v-model="model.featured"
type="checkbox"
class="rounded bg-zinc-800"
/>
<span class="text-sm text-zinc-300">{{
$t("community.servers.featured")
}}</span>
</label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.kindLabel")
}}</span>
<select
v-model="model.kind"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option v-for="k in kinds" :key="k" :value="k">{{ k }}</option>
</select>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.protocolLabel")
}}</span>
<select
v-model="model.protocol"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option value="tcp">tcp</option>
<option value="udp">udp</option>
<option value="http">http</option>
</select>
</label>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.hostLabel")
}}</span>
<input
v-model="model.host"
type="text"
required
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.portLabel")
}}</span>
<input
v-model.number="model.port"
type="number"
min="1"
max="65535"
required
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.probeTypeLabel")
}}</span>
<select
v-model="model.probeType"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option value="none">none</option>
<option value="tcp_connect">tcp_connect</option>
<option value="http_get">http_get</option>
<option value="presence_inferred">presence_inferred</option>
<option value="spire_api">spire_api</option>
<option value="source_query">source_query</option>
</select>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.probeIntervalLabel")
}}</span>
<input
v-model.number="model.probeIntervalSec"
type="number"
min="10"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
</div>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.probeConfigLabel")
}}</span>
<textarea
v-model="model.probeConfigJson"
rows="4"
placeholder="{}"
class="font-mono text-xs rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2"
/>
<span class="text-xs text-zinc-500">{{
$t("community.servers.probeConfigHint")
}}</span>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.joinInstructionsLabel")
}}</span>
<textarea
v-model="model.joinInstructions"
rows="3"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.deepLinkLabel")
}}</span>
<input
v-model="model.deepLink"
type="text"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
/>
</label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.titlePlatformLabel")
}}</span>
<select
v-model="model.titlePlatform"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option value="none">none</option>
<option value="drop">drop</option>
<option value="romm">romm</option>
</select>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.titleIdLabel")
}}</span>
<input
v-model="model.titleId"
type="text"
:disabled="model.titlePlatform === 'none'"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm disabled:opacity-50"
/>
</label>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.registrationLabel")
}}</span>
<select
v-model="model.registration"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option value="manual">manual</option>
<option value="auto">auto</option>
</select>
</label>
<label class="flex flex-col gap-y-1">
<span class="text-sm text-zinc-400">{{
$t("community.servers.visibilityLabel")
}}</span>
<select
v-model="model.visibility"
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
>
<option value="public">public</option>
<option value="private">private</option>
</select>
</label>
</div>
</div>
</template>
<script setup lang="ts">
export interface ServerFormModel {
name: string;
featured: boolean;
kind: string;
host: string;
port: number;
protocol: string;
probeType: string;
probeIntervalSec: number;
probeConfigJson: string;
joinInstructions: string;
deepLink: string;
registration: string;
visibility: string;
titlePlatform: string;
titleId: string;
}
const model = defineModel<ServerFormModel>({ required: true });
const kinds = [
"eqemu",
"wow",
"goldberg_relay",
"minecraft",
"source",
"generic",
];
</script>