fix(ui): full-row host click, agent version label on host card
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+14
-17
@@ -17,29 +17,26 @@ a {
|
|||||||
color: #7eb8ff;
|
color: #7eb8ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Клик по хосту в таблице — как пункты левого меню (полоска слева, без подчёркивания). */
|
/* Клик по строке хоста — как пункты левого меню (полоска слева на всю строку). */
|
||||||
.sac-host-nav-link {
|
.sac-host-row {
|
||||||
display: inline-block;
|
|
||||||
padding: 0.2rem 0.45rem 0.2rem 0.3rem;
|
|
||||||
margin: -0.2rem -0.35rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border-left: 3px solid transparent;
|
|
||||||
color: #c5d0dc;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
|
transition: background 0.12s ease, box-shadow 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sac-host-nav-link:hover {
|
.sac-host-row:hover,
|
||||||
|
.sac-host-row:focus-visible {
|
||||||
background: #1e2d3d;
|
background: #1e2d3d;
|
||||||
color: #fff;
|
box-shadow: inset 3px 0 0 #3db8ff;
|
||||||
border-left-color: #3db8ff;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sac-host-nav-link.router-link-active {
|
.sac-host-row td.actions {
|
||||||
background: #1a3a52;
|
cursor: default;
|
||||||
color: #fff;
|
}
|
||||||
border-left-color: #3db8ff;
|
|
||||||
|
.sac-host-row:hover td.actions,
|
||||||
|
.sac-host-row:focus-visible td.actions {
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
|
|||||||
@@ -8,11 +8,10 @@
|
|||||||
<p>
|
<p>
|
||||||
<strong>Hostname:</strong> {{ host.hostname }}
|
<strong>Hostname:</strong> {{ host.hostname }}
|
||||||
· <strong>ID:</strong> {{ host.id }}
|
· <strong>ID:</strong> {{ host.id }}
|
||||||
· <strong>Агент:</strong>
|
· <strong>Агент:</strong> <span :class="'agent-' + host.agent_status">{{ agentLabel(host.agent_status) }}</span>
|
||||||
<span :class="'agent-' + host.agent_status">{{ agentLabel(host.agent_status) }}</span>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Product:</strong> {{ host.product }} {{ host.product_version || "" }}
|
<strong>Версия агента:</strong> {{ host.product_version || "—" }}
|
||||||
· <strong>OS:</strong> {{ host.os_family }} {{ host.os_version || "" }}
|
· <strong>OS:</strong> {{ host.os_family }} {{ host.os_version || "" }}
|
||||||
· <strong>IPv4:</strong> {{ host.ipv4 || "—" }}
|
· <strong>IPv4:</strong> {{ host.ipv4 || "—" }}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<p v-else-if="loading">Загрузка…</p>
|
<p v-else-if="loading">Загрузка…</p>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p>Всего: {{ data?.total ?? 0 }}</p>
|
<p>Всего: {{ data?.total ?? 0 }}</p>
|
||||||
<table>
|
<table class="hosts-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><button type="button" class="th-sort" @click="setSort('id')">ID {{ sortMark('id') }}</button></th>
|
<th><button type="button" class="th-sort" @click="setSort('id')">ID {{ sortMark('id') }}</button></th>
|
||||||
@@ -29,24 +29,24 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="h in sortedItems" :key="h.id">
|
<tr
|
||||||
|
v-for="h in sortedItems"
|
||||||
|
:key="h.id"
|
||||||
|
class="sac-host-row"
|
||||||
|
tabindex="0"
|
||||||
|
:title="`Карточка хоста ${h.hostname}`"
|
||||||
|
@click="openHost(h.id)"
|
||||||
|
@keydown.enter="openHost(h.id)"
|
||||||
|
>
|
||||||
<td>{{ h.id }}</td>
|
<td>{{ h.id }}</td>
|
||||||
<td>
|
<td>{{ h.display_name || h.hostname }}</td>
|
||||||
<RouterLink
|
|
||||||
:to="`/hosts/${h.id}`"
|
|
||||||
class="sac-host-nav-link"
|
|
||||||
:title="`Карточка хоста ${h.hostname}`"
|
|
||||||
>
|
|
||||||
{{ h.display_name || h.hostname }}
|
|
||||||
</RouterLink>
|
|
||||||
</td>
|
|
||||||
<td>{{ h.hostname }}</td>
|
<td>{{ h.hostname }}</td>
|
||||||
<td>{{ h.product_version || "—" }}</td>
|
<td>{{ h.product_version || "—" }}</td>
|
||||||
<td>{{ h.os_family }}</td>
|
<td>{{ h.os_family }}</td>
|
||||||
<td>{{ h.ipv4 || "—" }}</td>
|
<td>{{ h.ipv4 || "—" }}</td>
|
||||||
<td :class="'agent-' + h.agent_status">{{ agentLabel(h.agent_status) }}</td>
|
<td :class="'agent-' + h.agent_status">{{ agentLabel(h.agent_status) }}</td>
|
||||||
<td>{{ h.last_heartbeat_at ? formatDt(h.last_heartbeat_at) : "—" }}</td>
|
<td>{{ h.last_heartbeat_at ? formatDt(h.last_heartbeat_at) : "—" }}</td>
|
||||||
<td>
|
<td @click.stop>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
v-if="h.last_daily_report_at"
|
v-if="h.last_daily_report_at"
|
||||||
:to="{ path: '/reports', query: { hostname: h.hostname } }"
|
:to="{ path: '/reports', query: { hostname: h.hostname } }"
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>{{ formatDt(h.last_seen_at) }}</td>
|
<td>{{ formatDt(h.last_seen_at) }}</td>
|
||||||
<td>{{ h.event_count ?? 0 }}</td>
|
<td>{{ h.event_count ?? 0 }}</td>
|
||||||
<td class="actions">
|
<td class="actions" @click.stop>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="danger"
|
class="danger"
|
||||||
@@ -76,8 +76,11 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
import { apiFetch, type HostListResponse, type HostSummary } from "../api";
|
import { apiFetch, type HostListResponse, type HostSummary } from "../api";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const data = ref<HostListResponse | null>(null);
|
const data = ref<HostListResponse | null>(null);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const error = ref("");
|
const error = ref("");
|
||||||
@@ -147,6 +150,10 @@ function agentLabel(status: string) {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openHost(id: number) {
|
||||||
|
router.push(`/hosts/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
function agentStatusOrder(status: string) {
|
function agentStatusOrder(status: string) {
|
||||||
if (status === "online") return 0;
|
if (status === "online") return 0;
|
||||||
if (status === "stale") return 1;
|
if (status === "stale") return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user