mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 08:15:17 +00:00
fix(ui): guard invalid log detail timestamps
This commit is contained in:
1 parent
c21f589247
commit
4ce6669e26
3 files changed
+42
-1
No files matched your search
@@ -9,6 +9,7 @@ import { LogLevelBadge } from './log-level-badge';
|
|||||||
import { LogsEmpty } from './logs-empty';
|
import { LogsEmpty } from './logs-empty';
|
||||||
import {
|
import {
|
||||||
formatJson,
|
formatJson,
|
||||||
|
formatLogTimestampIso,
|
||||||
getDisplayLatency,
|
getDisplayLatency,
|
||||||
getDisplayModule,
|
getDisplayModule,
|
||||||
getDisplayRequestId,
|
getDisplayRequestId,
|
||||||
@@ -34,7 +35,7 @@ interface OverviewRow {
|
|||||||
function buildOverviewRows(entry: LogsEntry, sourceLabel?: string): OverviewRow[] {
|
function buildOverviewRows(entry: LogsEntry, sourceLabel?: string): OverviewRow[] {
|
||||||
// Use shared accessors so this panel and the list row never diverge.
|
// Use shared accessors so this panel and the list row never diverge.
|
||||||
return [
|
return [
|
||||||
{ label: 'Time', value: new Date(entry.timestamp).toISOString(), mono: true },
|
{ label: 'Time', value: formatLogTimestampIso(entry.timestamp), mono: true },
|
||||||
{ label: 'Level', value: entry.level },
|
{ label: 'Level', value: entry.level },
|
||||||
{ label: 'Module', value: getDisplayModule(entry, sourceLabel) },
|
{ label: 'Module', value: getDisplayModule(entry, sourceLabel) },
|
||||||
{ label: 'Stage', value: getDisplayStage(entry) },
|
{ label: 'Stage', value: getDisplayStage(entry) },
|
||||||
|
|||||||
@@ -21,6 +21,19 @@ export function formatLogTimestamp(timestamp: string | null | undefined) {
|
|||||||
}).format(date);
|
}).format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatLogTimestampIso(timestamp: string | null | undefined) {
|
||||||
|
if (!timestamp) {
|
||||||
|
return 'No activity yet';
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(timestamp);
|
||||||
|
if (Number.isNaN(date.getTime())) {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
export function formatRelativeLogTime(timestamp: string | null | undefined) {
|
export function formatRelativeLogTime(timestamp: string | null | undefined) {
|
||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
return 'No activity yet';
|
return 'No activity yet';
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { render, screen } from '@tests/setup/test-utils';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { LogsDetailPanel } from '@/components/logs/logs-detail-panel';
|
||||||
|
import type { LogsEntry } from '@/lib/api-client';
|
||||||
|
|
||||||
|
function buildEntry(overrides: Partial<LogsEntry> = {}): LogsEntry {
|
||||||
|
return {
|
||||||
|
id: 'entry-1',
|
||||||
|
timestamp: '2026-04-07T11:00:00.000Z',
|
||||||
|
level: 'info',
|
||||||
|
source: 'dashboard',
|
||||||
|
event: 'logs.bootstrap',
|
||||||
|
message: 'Dashboard log entry',
|
||||||
|
processId: 25582,
|
||||||
|
runId: 'run-1',
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('LogsDetailPanel', () => {
|
||||||
|
it('falls back to the raw timestamp when the selected log entry has an invalid timestamp', () => {
|
||||||
|
render(<LogsDetailPanel entry={buildEntry({ timestamp: 'not-a-date' })} />);
|
||||||
|
|
||||||
|
expect(screen.getByText('not-a-date')).toBeInTheDocument();
|
||||||
|
expect(screen.getByTitle('not-a-date')).toHaveTextContent('not-a-date');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user