fix console log time and server card layout
This commit is contained in:
@@ -6,6 +6,7 @@ import type { JobResponse, LogEntryBody, LogStreamResponse } from "../api/types"
|
||||
import { scumSourceRCONCommandRequest } from "../schemas/scumManagementRcon";
|
||||
import { cx } from "../utils/classes";
|
||||
import { mergeLogStreams, parseLogSessionEvent, parseLogStreamEvent, parseServerLogEvent, streamFromServerLogEvent } from "../utils/logEvents";
|
||||
import { formatTerminalLogTime } from "../utils/logTime";
|
||||
import { EmptyState, ResultBadge } from "./StateViews";
|
||||
|
||||
type LoadState<T> = { status: "loading" } | { status: "error"; reason: string } | { status: "ready"; data: T };
|
||||
@@ -410,7 +411,7 @@ function terminalLineFromLog(stream: LogStreamResponse, entry: LogEntryBody): Te
|
||||
id: `log-${stream.id}-${entry.seq}`,
|
||||
tone: terminalTone(entry),
|
||||
text: entry.line,
|
||||
at: new Date(entry.timestamp).toLocaleTimeString(),
|
||||
at: formatTerminalLogTime(entry.timestamp, entry.line),
|
||||
sortKey: Date.parse(entry.timestamp) || Date.now(),
|
||||
streamKey: stream.streamKey || stream.source,
|
||||
level: entry.level,
|
||||
|
||||
@@ -58,6 +58,14 @@ describe("platform web shared theme CSS", () => {
|
||||
expect(css).toContain(":root[data-custom-background=true].server-card-stat");
|
||||
});
|
||||
|
||||
it("gives server cards enough room for long status labels", () => {
|
||||
const css = compact(readThemeCss());
|
||||
|
||||
expect(css).toContain(".server-card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr))");
|
||||
expect(css).toContain(".server-card-head{display:grid;gap:8px;min-width:0}");
|
||||
expect(css).toContain(".server-card-head>span:last-child{justify-self:start;white-space:normal");
|
||||
});
|
||||
|
||||
it("keeps magical custom-background signal rows readable without the jelly wash", () => {
|
||||
const css = compact(readThemeCss());
|
||||
|
||||
|
||||
@@ -450,11 +450,13 @@ to{transform:translate(-50%,-50%) rotate(calc(var(--construct-drift) + 360deg))}
|
||||
.server-toolbar select{min-height:38px;border:1px solid var(--line-strong);border-radius:8px;padding:0 10px;background:var(--surface-solid);color:var(--ink);font:inherit;min-width:180px}
|
||||
.server-toolbar select:focus{border-color:var(--accent);outline:2px solid var(--accent-soft)}
|
||||
.server-toolbar input[type=search]:focus{border-color:var(--accent);outline:2px solid var(--accent-soft)}
|
||||
.server-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));gap:14px}
|
||||
.server-card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));gap:16px}
|
||||
.server-card{display:grid;gap:12px;padding:16px;border:1px solid var(--line);border-radius:8px;background:var(--frosted-surface),var(--glass-tint),var(--surface);backdrop-filter:blur(22px) saturate(1.28);text-align:left;transition:transform 120ms ease,border-color 120ms ease;box-shadow:var(--jelly-inset),inset 0 0 0 1px var(--diamond-line),0 18px 42px var(--glass-shadow),0 0 28px rgba(255,255,255,.2);position:relative;overflow:hidden;min-width:0}
|
||||
.server-card:focus-visible,.server-card:hover{border-color:var(--accent);outline:0;transform:translateY(-2px)}
|
||||
.server-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
|
||||
.server-card-head>span:first-child{min-width:0}
|
||||
.server-card-head{display:grid;gap:8px;min-width:0}
|
||||
.server-card-head>span:first-child,.server-card-head>span:last-child{min-width:0;max-width:100%}
|
||||
.server-card-head>span:last-child{justify-self:start;white-space:normal;line-height:1.3}
|
||||
.server-card>*{min-width:0}
|
||||
.server-card-head strong{display:block;font-size:16px;color:var(--ink);overflow-wrap:anywhere}
|
||||
.server-card-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
|
||||
.server-card-stat{display:grid;gap:2px;padding:8px;border:1px solid color-mix(in srgb,var(--line-strong) 56%,rgba(255,255,255,.16));border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--surface-solid) 88%,rgba(255,255,255,.06)),color-mix(in srgb,var(--surface-solid) 72%,var(--accent-soft))),var(--glass-wash);min-height:52px;align-content:center;box-shadow:inset 0 1px 0 color-mix(in srgb,var(--crystal-rim) 68%,transparent),0 8px 18px rgba(0,0,0,.18);min-width:0;backdrop-filter:blur(10px) saturate(0.92)}
|
||||
@@ -767,6 +769,8 @@ button.operations-inline-warning{cursor:pointer}
|
||||
.inline-link-command{border:0;padding:0;background:0 0;color:var(--accent-deep);text-decoration:underline;cursor:pointer}
|
||||
.inline-link-command:focus-visible,.inline-link-command:hover{color:var(--ink);outline:0}
|
||||
.server-card-warning{justify-self:start;color:var(--gold)}
|
||||
.server-card .action-strip{min-width:0}
|
||||
.server-card .action-strip button{min-width:0;white-space:nowrap}
|
||||
.resource-filter-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:12px 0}
|
||||
.resource-filter-bar input,.resource-filter-bar select{min-height:36px;min-width:150px;border:1px solid var(--line-strong);border-radius:6px;padding:0 10px;background:var(--surface-solid);color:var(--ink);font:inherit}
|
||||
.resource-filter-bar input{flex:1 1 240px}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { formatTerminalLogTime } from "./logTime";
|
||||
|
||||
describe("formatTerminalLogTime", () => {
|
||||
it("uses the SCUM log clock instead of the browser timezone", () => {
|
||||
expect(formatTerminalLogTime("2026-08-24T01:23:44Z", "[2026.08.23-17.23.44][418]LogSCUM: Global Stats"))
|
||||
.toBe("17:23:44");
|
||||
});
|
||||
|
||||
it("falls back to the event timestamp for generic logs", () => {
|
||||
expect(formatTerminalLogTime("not-a-timestamp")).toBe("时间未知");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
const scumLogTimestampPattern = /\[?(\d{4})\.(\d{2})\.(\d{2})-(\d{2})\.(\d{2})\.(\d{2})(?:[.:]\d{1,3})?\]?/;
|
||||
|
||||
export function formatTerminalLogTime(timestamp: string, line?: string): string {
|
||||
const embedded = line?.match(scumLogTimestampPattern);
|
||||
if (embedded) {
|
||||
return `${embedded[4]}:${embedded[5]}:${embedded[6]}`;
|
||||
}
|
||||
|
||||
const date = new Date(timestamp);
|
||||
return Number.isNaN(date.getTime()) ? "时间未知" : date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
||||
}
|
||||
Reference in New Issue
Block a user