turnstone/web/src/components/LogEntryRow.vue

63 lines
2.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div
class="border-b border-surface-border px-4 py-3 hover:bg-surface-raised transition-colors"
:class="{ 'border-l-2 border-l-sev-error': isHighSeverity }"
>
<div class="flex items-start gap-3">
<SeverityBadge :severity="entry.severity" class="mt-0.5 shrink-0 w-16 text-center" />
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2 mb-1 flex-wrap">
<span class="text-accent text-xs">{{ entry.source_id }}</span>
<span v-if="entry.timestamp_iso" class="text-text-dim text-xs">{{ formatTs(entry.timestamp_iso) }}</span>
<span
v-for="p in entry.matched_patterns"
:key="p"
class="px-1.5 py-0.5 rounded bg-accent-muted text-accent text-xs"
>{{ p }}</span>
<span v-if="entry.repeat_count > 1" class="text-text-dim text-xs">×{{ entry.repeat_count }}</span>
</div>
<p
:id="`entry-text-${entry.entry_id}`"
class="text-text-primary text-sm whitespace-pre-wrap break-words leading-relaxed"
:class="{ 'line-clamp-3': isLong && !expanded }"
>{{ entry.text }}</p>
<button
v-if="isLong"
@click="expanded = !expanded"
:aria-expanded="expanded"
:aria-controls="`entry-text-${entry.entry_id}`"
class="mt-1 text-text-dim hover:text-accent text-xs transition-colors"
>
<span aria-hidden="true">{{ expanded ? '▲' : '▼' }}</span>
{{ expanded ? 'Collapse entry' : 'Expand entry' }}
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { LogEntry } from '@/stores/search'
import SeverityBadge from './SeverityBadge.vue'
const props = defineProps<{ entry: LogEntry }>()
const expanded = ref(false)
const isHighSeverity = computed(() =>
['ERROR', 'CRITICAL'].includes((props.entry.severity ?? '').toUpperCase())
)
const isLong = computed(() => props.entry.text.length > 200 || props.entry.text.includes('\n'))
function formatTs(iso: string): string {
try {
return new Date(iso).toLocaleString(undefined, {
month: 'short', day: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit',
})
} catch {
return iso
}
}
</script>