feat(#153): feat(dashboard): status badge UI component for agents#200
feat(#153): feat(dashboard): status badge UI component for agents#200xsovad06 wants to merge 1 commit into
Conversation
WalkthroughReplaces hardcoded switch statements in Status badge component
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@sova/dashboard/static/app.js`:
- Around line 105-107: The stepIndex and totalSteps values in the label
concatenation within the currentStep && totalSteps condition are not escaped
before HTML interpolation, creating a DOM-XSS vulnerability. Additionally, the
expression (stepIndex || '?') incorrectly treats 0 as missing and replaces it
with '?'. Apply escapeHtml() to both stepIndex and totalSteps before inserting
them into the label string, and change the falsy check logic to explicitly test
for null/undefined instead of relying on truthiness so that 0 values are
preserved correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6a57916d-d23c-483e-a9b5-7afb66ec7fc6
📒 Files selected for processing (3)
sova/dashboard/static/app.jssova/dashboard/static/style.csssova/dashboard/templates/agents.html
| if (currentStep && totalSteps) { | ||
| label += ' (' + escapeHtml(currentStep) + ', ' + (stepIndex || '?') + '/' + totalSteps + ')'; | ||
| } else if (currentStep) { |
There was a problem hiding this comment.
Escape or coerce step counters before HTML interpolation.
Line 106 injects stepIndex/totalSteps into an innerHTML string without sanitization. If either arrives as non-numeric text, this is a DOM-XSS surface and can also misrender valid 0 values because (stepIndex || '?') treats 0 as missing.
Proposed fix
- if (currentStep && totalSteps) {
- label += ' (' + escapeHtml(currentStep) + ', ' + (stepIndex || '?') + '/' + totalSteps + ')';
+ if (currentStep && totalSteps != null) {
+ var safeStepIndex = (stepIndex == null) ? '?' : escapeHtml(String(stepIndex));
+ var safeTotalSteps = escapeHtml(String(totalSteps));
+ label += ' (' + escapeHtml(currentStep) + ', ' + safeStepIndex + '/' + safeTotalSteps + ')';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (currentStep && totalSteps) { | |
| label += ' (' + escapeHtml(currentStep) + ', ' + (stepIndex || '?') + '/' + totalSteps + ')'; | |
| } else if (currentStep) { | |
| if (currentStep && totalSteps != null) { | |
| var safeStepIndex = (stepIndex == null) ? '?' : escapeHtml(String(stepIndex)); | |
| var safeTotalSteps = escapeHtml(String(totalSteps)); | |
| label += ' (' + escapeHtml(currentStep) + ', ' + safeStepIndex + '/' + safeTotalSteps + ')'; | |
| } else if (currentStep) { |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@sova/dashboard/static/app.js` around lines 105 - 107, The stepIndex and
totalSteps values in the label concatenation within the currentStep &&
totalSteps condition are not escaped before HTML interpolation, creating a
DOM-XSS vulnerability. Additionally, the expression (stepIndex || '?')
incorrectly treats 0 as missing and replaces it with '?'. Apply escapeHtml() to
both stepIndex and totalSteps before inserting them into the label string, and
change the falsy check logic to explicitly test for null/undefined instead of
relying on truthiness so that 0 values are preserved correctly.



Summary
Changes
Dashboard Frontend (Status Badge)
app.js: Added comprehensiveSTATUS_COLORSmapping for all 17 statuses, implementedrenderStatusBadge()function with stuck detection (300s threshold) and elapsed time tracking, expandedstatusColor()andstatusDot()helpers for consistency across all pagesstyle.css: Added.sova-status-badgeinline-flex layout styles,.sova-status-stuckmodifier for long-running steps, and@keyframes sova-stuck-pulseanimation with red box-shadowagents.html: Integrated badge intorenderAgentCard()(replacing bare colored dot at line 704) andrenderCompletedCard()(replacing inline status text at lines 745/748), added sharedsetIntervalfor real-time elapsed time updates across all visible badgesIncidental Changes
.claude/agent-memory/cookbook.md(191 lines) - appears to be unrelated cleanupsova/commands/templates.pyandtests/test_commands.py- minor fixes/refactors.claude/rules/bash-patterns.mdReview guidance
Focus on the status badge implementation in
app.js,style.css, andagents.html. The badge component is designed for client-side rendering withininnerHTML-based card renderers, not as a Jinja macro. Key areas:STATUS_COLORSuses Catppuccin CSS variables consistently and covers all semantic groupings (pending, active work, CI/review, terminal states)sova-status-stuckclass correctly and animation is visually distinctcurrentStep,stepIndex,totalSteps, orelapsedSecondsare null/undefined (completed agents)setIntervalre-queries.sova-status-elapsedelements on each tick (polling re-renders destroy and recreate DOM nodes)The unrelated file changes (cookbook deletion, template/test modifications) appear to be incidental cleanup that should have been in separate commits but don't affect the badge feature.
Test plan
http://localhost:8111/agentswith multiple concurrent running agentspending,in_progress,developing,done,failed,interruptedmake check)make lint)Closes #153