feat: SSH card UX, agent version sync, persistent ssh_admin_ok (0.11.5)

Silent SSH probe on host card open; manual test feedback auto-hides. Persist ssh_admin_ok in DB (migration 019). After agent update read version from host and refresh UI.
This commit is contained in:
PTah
2026-06-20 01:01:56 +10:00
parent 6fea8262fb
commit 2eb06acb5b
17 changed files with 423 additions and 70 deletions
+20 -2
View File
@@ -96,17 +96,19 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useSacLiveEventStream } from "../composables/useSacLiveEventStream";
import {
apiFetch,
fetchHost,
fetchRecentEvents,
type HostDetail,
type HostListResponse,
type HostSummary,
} from "../api";
import { patchHostSummaryFromDetail } from "../utils/hostsLiveUpdate";
import { bumpLatestAgentVersion, patchHostSummaryFromDetail } from "../utils/hostsLiveUpdate";
import { subscribeHostPatch } from "../utils/hostPatchBus";
import { isAgentVersionOutdated } from "../utils/agentVersion";
const router = useRouter();
@@ -172,6 +174,16 @@ const sortBy = ref<SortKey>(initialSort.sortBy);
const sortDir = ref<"asc" | "desc">(initialSort.sortDir);
const deletingId = ref<number | null>(null);
let patchingHostRow = false;
let unsubscribeHostPatch: (() => void) | null = null;
function applyHostPatchFromDetail(detail: HostDetail) {
if (!data.value) return;
const row = data.value.items.find((h) => h.id === detail.id);
if (row) {
patchHostSummaryFromDetail(row, detail);
bumpLatestAgentVersion(data.value.latest_agent_versions, row.product, detail.product_version);
}
}
const { live } = useSacLiveEventStream(() => {
void patchHostRowFromLatestEvent();
@@ -369,6 +381,12 @@ async function confirmDelete(h: HostSummary) {
onMounted(() => {
syncFromRoute();
loadHosts();
unsubscribeHostPatch = subscribeHostPatch(applyHostPatchFromDetail);
});
onUnmounted(() => {
unsubscribeHostPatch?.();
unsubscribeHostPatch = null;
});
watch(