diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index f87ce7557b..bec60902ca 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -2211,7 +2211,7 @@ "name": "sentry-triage", "source": "plugins/sentry-triage", "description": "Scan live Sentry issues in a Copilot canvas, group them by urgency, and hand issues off for tracking or a fix PR.", - "version": "1.2.0" + "version": "1.3.0" }, { "name": "signals-dashboard", diff --git a/extensions/sentry-triage/components/card.mjs b/extensions/sentry-triage/components/card.mjs index b8c9259fc2..67873bc27d 100644 --- a/extensions/sentry-triage/components/card.mjs +++ b/extensions/sentry-triage/components/card.mjs @@ -1,21 +1,30 @@ import { escapeHtml, safeHref } from '../escape.mjs' +// KEEP IN SYNC with compactNumber in page.mjs's client script. +function compactNumber(value) { + const n = Number(value) || 0 + if (n >= 1e6) return (n / 1e6).toFixed(n >= 1e7 ? 0 : 1) + 'M' + if (n >= 1e4) return Math.round(n / 1e3) + 'k' + if (n >= 1e3) return (n / 1e3).toFixed(1) + 'k' + return String(n) +} + function statusLabel(workStatus) { if (!workStatus || typeof workStatus !== 'object') return '' if (workStatus.phase === 'working' || workStatus.phase === 'queued') { - return workStatus.copilotFix ? '⏳ starting Copilot fix session…' : '⏳ filing tracking issue…' + return workStatus.copilotFix ? 'Starting Copilot fix…' : 'Filing tracking issue…' } if (workStatus.phase === 'done') { // Numbers move into clickable links (statusLinks); keep the label a plain badge. - return 'created ✓' + return 'Created' } if (workStatus.phase === 'handed-off') { - const sessionPart = workStatus.sessionName ? `🧵 ${workStatus.sessionName}` : '🧵 session started' + const sessionPart = workStatus.sessionName ? workStatus.sessionName : 'Session started' return `${sessionPart} ↗` } - if (workStatus.phase === 'skipped') return '🔒 already being worked on' - if (workStatus.phase === 'tracked') return '👀 Tracked' - if (workStatus.phase === 'error') return `⚠️ ${workStatus.error || 'work failed'}` + if (workStatus.phase === 'skipped') return 'Already in progress' + if (workStatus.phase === 'tracked') return 'Tracked' + if (workStatus.phase === 'error') return workStatus.error || 'Work failed' return '' } @@ -60,7 +69,21 @@ function statusLinks(workStatus) { return links.join(' · ') } -export function Card({ key, summary, plainEnglish, reason, events, users, url, workStatus, plainEnglishView, availableModels = [] }) { +// KEEP IN SYNC with sparklineSvg in page.mjs's client script. +function sparklineSvg(trend) { + const values = (Array.isArray(trend) ? trend : []).map((v) => Number(v) || 0) + if (values.length < 2) return '' + const w = 72, h = 24, max = Math.max(1, ...values) + const pts = values.map((v, i) => `${((i / (values.length - 1)) * w).toFixed(1)},${(h - 2 - (v / max) * (h - 4)).toFixed(1)}`) + return `` +} + +function trendAttrs(trend, trendStart, trendStep) { + const values = (Array.isArray(trend) ? trend : []).map((v) => Number(v) || 0) + return values.length ? ` data-trend="${values.join(',')}" data-trend-start="${Number(trendStart) || 0}" data-trend-step="${Number(trendStep) || 0}"` : '' +} + +export function Card({ key, category, categoryLabel, summary, plainEnglish, reason, events, users, url, workStatus, plainEnglishView, availableModels = [], trend, trendStart, trendStep }) { const href = safeHref(url) const safeKey = escapeHtml(key) const title = plainEnglishView ? (plainEnglish || summary) : summary @@ -80,9 +103,10 @@ export function Card({ key, summary, plainEnglish, reason, events, users, url, w ? 'working' : 'idle' const meta = [ - events != null ? `${Number(events).toLocaleString()} events` : null, - users != null ? `${Number(users).toLocaleString()} users` : null - ].filter(Boolean).join(' · ') + sparklineSvg(trend) || null, + events != null ? `${compactNumber(events)}events` : null, + users != null ? `${compactNumber(users)}users` : null + ].filter(Boolean).join('') // Per-card model override. Empty value means "use the toolbar/batch default". const cardModelOptions = [''] @@ -93,22 +117,19 @@ export function Card({ key, summary, plainEnglish, reason, events, users, url, w ) .join('') - return `