mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-10-29 00:01:24 +00:00
feat: external importers + uptime monitors (merge plan M1)
Two tracks from the Beszel/Domain-Locker merge plan in ROADMAP.md: - Importers: POST /api/import/external sniffs Homepage services.yml, Homarr JSON, and Dashy conf.yml into sections/items; SettingsDialog import now accepts all four formats. - Monitors (M1): monitors + heartbeats schema, pure checkers for http/tcp/ping/dns/keyword/json-query/push, scheduler on app ctx, CRUD + check-now + push ingest API, /monitors + /monitors/:id pages (wouter), monitor board widget, ServiceDialog monitor opt-in. Authored By: TDvorak <[email protected]> Generated with Devin (https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
f428e721fe
commit
1ff1b29ae7
29 files changed
+3050
-98
No files matched your search
@@ -31,6 +31,7 @@ export function WidgetDialog({
|
||||
const [name, setName] = useState("");
|
||||
const [sectionId, setSectionId] = useState("");
|
||||
const [values, setValues] = useState<Record<string, string>>({});
|
||||
const [monitors, setMonitors] = useState<{ id?: string; name?: string }[]>([]);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [err, setErr] = useState("");
|
||||
|
||||
@@ -42,6 +43,10 @@ export function WidgetDialog({
|
||||
.then((r) => r.json() as Promise<WidgetType[]>)
|
||||
.then(setTypes)
|
||||
.catch(() => setTypes([]));
|
||||
fetch("/api/monitors")
|
||||
.then((r) => r.json() as Promise<{ id?: string; name?: string }[]>)
|
||||
.then(setMonitors)
|
||||
.catch(() => setMonitors([]));
|
||||
|
||||
const cfg = item?.config ?? null;
|
||||
setType(cfg && typeof cfg.type === "string" ? cfg.type : "");
|
||||
@@ -141,14 +146,28 @@ export function WidgetDialog({
|
||||
<Label htmlFor={`wdg-${f.key}`}>
|
||||
{f.label}{f.required ? "" : " (optional)"}
|
||||
</Label>
|
||||
<Input
|
||||
id={`wdg-${f.key}`}
|
||||
type={f.secret ? "password" : "text"}
|
||||
value={values[f.key] ?? ""}
|
||||
placeholder={f.placeholder}
|
||||
onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}
|
||||
className="font-mono text-[12px]"
|
||||
/>
|
||||
{f.key === "monitorId" ? (
|
||||
<Select
|
||||
value={values[f.key] ?? ""}
|
||||
onValueChange={(v) => setValues((s) => ({ ...s, [f.key]: v }))}
|
||||
>
|
||||
<SelectTrigger><SelectValue placeholder="Pick a monitor…" /></SelectTrigger>
|
||||
<SelectContent>
|
||||
{monitors.map((m) => (
|
||||
<SelectItem key={m.id} value={m.id ?? ""}>{m.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
) : (
|
||||
<Input
|
||||
id={`wdg-${f.key}`}
|
||||
type={f.secret ? "password" : "text"}
|
||||
value={values[f.key] ?? ""}
|
||||
placeholder={f.placeholder}
|
||||
onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}
|
||||
className="font-mono text-[12px]"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
||||
Reference in new issue
Block a user