This commit is contained in:
Mateusz Gruszczyński committed 2026-10-21 09:38:21 +02:00
1 parent 3776edf4fc
commit 7cfc3a6da1
35 files changed
+1377 -875

No files matched your search

+32 -15
View File
@@ -61,25 +61,42 @@
if (backendList?.children.length >= 32) { toast(t("streamBackendLimit"), true); return; }
const row = el("fieldset", undefined, "stream-backend-row vh-wide"); row.append(el("legend", backend.id || t("streamBackend")));
const controls = el("div", undefined, "vh-grid"); row.append(controls);
field(controls, "backend-id", "streamBackendId", backend.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" });
field(controls, "backend-name", "streamBackendName", backend.name || "", "text", { maxLength: 96 });
field(controls, "backend-address", "streamBackendAddress", backend.address, "text", { required: true, maxLength: 128 });
field(controls, "backend-weight", "streamBackendWeight", backend.weight ?? 1, "number", { min: 1, max: 16, required: true });
field(controls, "backend-max", "streamBackendMaxSessions", backend.max_sessions ?? "", "number", { min: 1, max: 65535 });
field(controls, "backend-enabled", "vhEnabled", backend.enabled !== false, "checkbox");
field(controls, "backend-drain", "streamBackendDrain", backend.drain === true, "checkbox");
const backendSection = key => {
const section = el("section", undefined, "vh-wide vh-setting-section stream-backend-section");
section.append(text("h3", key));
const grid = el("div", undefined, "vh-grid"); section.append(grid); controls.append(section);
return grid;
};
const connectionFields = backendSection("streamBackendConnectionSection");
field(connectionFields, "backend-id", "streamBackendId", backend.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" });
field(connectionFields, "backend-name", "streamBackendName", backend.name || "", "text", { maxLength: 96 });
field(connectionFields, "backend-address", "streamBackendAddress", backend.address, "text", { required: true, maxLength: 128 });
field(connectionFields, "backend-weight", "streamBackendWeight", backend.weight ?? 1, "number", { min: 1, max: 16, required: true });
field(connectionFields, "backend-max", "streamBackendMaxSessions", backend.max_sessions ?? "", "number", { min: 1, max: 65535 });
field(connectionFields, "backend-enabled", "vhEnabled", backend.enabled !== false, "checkbox");
field(connectionFields, "backend-drain", "streamBackendDrain", backend.drain === true, "checkbox");
const detail = backend.metrics_enabled == null ? "inherit" : String(backend.metrics_enabled);
field(controls, "backend-metrics", "streamBackendDetailMetrics", detail, "select", { values: [["inherit", "streamMetricsFromStream"], ["true", "streamMetricsOn"], ["false", "streamMetricsOff"]] });
field(connectionFields, "backend-metrics", "streamBackendDetailMetrics", detail, "select", { values: [["inherit", "streamMetricsFromStream"], ["true", "streamMetricsOn"], ["false", "streamMetricsOff"]] });
const hc = backend.health || backendDefaults().health;
field(controls, "backend-health-mode", "streamHealthMode", hc.mode || "off", "select", { values: [["off", "streamHealthOff"], [protocol === "tcp" ? "tcp_connect" : "udp_probe", protocol === "tcp" ? "streamHealthTcp" : "streamHealthUdp"]] });
field(controls, "backend-health-interval", "streamHealthInterval", hc.interval_seconds ?? 10, "number", { min: 1, max: 3600, required: true });
field(controls, "backend-health-timeout", "streamHealthTimeout", hc.timeout_ms ?? 1000, "number", { min: 50, max: 30000, required: true });
field(controls, "backend-health-rise", "streamHealthRise", hc.rise ?? 2, "number", { min: 1, max: 10, required: true });
field(controls, "backend-health-fall", "streamHealthFall", hc.fall ?? 2, "number", { min: 1, max: 10, required: true });
const healthFields = backendSection("streamBackendHealthSection");
const healthMode = field(healthFields, "backend-health-mode", "streamHealthMode", hc.mode || "off", "select", { values: [["off", "streamHealthOff"], [protocol === "tcp" ? "tcp_connect" : "udp_probe", protocol === "tcp" ? "streamHealthTcp" : "streamHealthUdp"]] });
const probeFields = el("div", undefined, "vh-wide vh-grid stream-health-probe-fields");
healthFields.append(probeFields);
const syncProbeFields = () => {
const inactive = healthMode.value === "off";
probeFields.hidden = inactive;
probeFields.querySelectorAll("input, select, textarea").forEach(input => { input.disabled = inactive; });
};
healthMode.addEventListener("change", syncProbeFields);
field(probeFields, "backend-health-interval", "streamHealthInterval", hc.interval_seconds ?? 10, "number", { min: 1, max: 3600, required: true });
field(probeFields, "backend-health-timeout", "streamHealthTimeout", hc.timeout_ms ?? 1000, "number", { min: 50, max: 30000, required: true });
field(probeFields, "backend-health-rise", "streamHealthRise", hc.rise ?? 2, "number", { min: 1, max: 10, required: true });
field(probeFields, "backend-health-fall", "streamHealthFall", hc.fall ?? 2, "number", { min: 1, max: 10, required: true });
if (protocol === "udp") {
field(controls, "backend-health-payload", "streamHealthPayload", hc.payload_hex || "", "text", { maxLength: 256 });
field(controls, "backend-health-expected", "streamHealthExpected", hc.expect_hex || "", "text", { maxLength: 256 });
field(probeFields, "backend-health-payload", "streamHealthPayload", hc.payload_hex || "", "text", { maxLength: 256 });
field(probeFields, "backend-health-expected", "streamHealthExpected", hc.expect_hex || "", "text", { maxLength: 256 });
}
syncProbeFields();
const remove = button("remove", () => { if (backendList.children.length > 1) { row.remove(); changed(); } });
row.append(remove); backendList.append(row);
}