sorting+modal fix
Deploy / deploy (push) Successful in 8s

This commit is contained in:
2026-08-31 23:09:35 +05:00
parent 28702bd029
commit b714c00b27
2 changed files with 30 additions and 6 deletions
+15 -1
View File
@@ -30,7 +30,21 @@ func (s *server) services(ctx context.Context) []*homelabv1.Service {
if s.mockSvcs != nil {
return s.mockSvcs
}
return append(s.systemdServices(ctx), s.dockerServices(ctx)...)
svcs := append(s.systemdServices(ctx), s.dockerServices(ctx)...)
// живые (active/partial) наверх, остальное (inactive, not-found, failed, error) вниз; внутри групп — по имени
rank := func(svc *homelabv1.Service) int {
if svc.Error == "" && (svc.State == "active" || svc.State == "partial") {
return 0
}
return 1
}
sort.SliceStable(svcs, func(i, j int) bool {
if ri, rj := rank(svcs[i]), rank(svcs[j]); ri != rj {
return ri < rj
}
return svcs[i].Name < svcs[j].Name
})
return svcs
}
// logProbeChange logs poll-path probe failures once per change: the poll repeats every 3s per client,
+15 -5
View File
@@ -1,4 +1,4 @@
import { useState } from "preact/hooks";
import { useState, useRef } from "preact/hooks";
import { createClient } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-web";
import { Container, Server, X } from "lucide-preact";
@@ -63,7 +63,10 @@ function Controls({
class="btn btn-xs btn-outline"
disabled={busy || disabled}
title={title}
onClick={() => onAct(op)}
onClick={(e) => {
e.stopPropagation(); // кнопка не должна открывать info-модалку карточки
onAct(op);
}}
>
{label}
</button>
@@ -94,13 +97,19 @@ export function ServiceCard({
const [info, setInfo] = useState<string | null>(null);
const [infoBusy, setInfoBusy] = useState(false);
const infoOpen = useRef(false);
const closeInfo = () => {
infoOpen.current = false;
setInfo(null);
};
const act = async (op: ServiceOp) => {
setBusy(true);
setError("");
try {
await client.serviceAction({ name: s.name, kind: s.kind, op });
refresh(); // не ждём 3s поллинга
if (info !== null) {
if (infoOpen.current) {
const r = await client.serviceInfo({ name: s.name, kind: s.kind });
setInfo(r.output);
}
@@ -114,6 +123,7 @@ export function ServiceCard({
const openInfo = async () => {
setInfoBusy(true);
setError("");
infoOpen.current = true;
try {
setInfo(
(await client.serviceInfo({ name: s.name, kind: s.kind })).output,
@@ -160,7 +170,7 @@ export function ServiceCard({
<div class="modal-box max-w-2xl">
<button
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
onClick={() => setInfo(null)}
onClick={closeInfo}
>
<X size={16} />
</button>
@@ -174,7 +184,7 @@ export function ServiceCard({
{infoBusy ? "…" : info}
</pre>
</div>
<div class="modal-backdrop" onClick={() => setInfo(null)} />
<div class="modal-backdrop" onClick={closeInfo} />
</div>
)}
</div>