summaryrefslogtreecommitdiff
path: root/web/app.js
diff options
context:
space:
mode:
authorClaudomator Agent <agent@claudomator>2026-03-16 20:01:59 +0000
committerClaudomator Agent <agent@claudomator>2026-03-16 20:01:59 +0000
commit1b2deb13daa788dc43d98caeaa9507254b1ca283 (patch)
treeb78fdeb30d0e96b4141ec9e66937b40018e4f99f /web/app.js
parent054ec8b653b175917ef8bea45d55025e6775f187 (diff)
feat: display deployment status badge on READY task cards
Add deployment_status field to task list/get API responses for READY tasks. The field includes deployed_commit, fix_commits, and includes_fix so the UI can show whether the deployed server includes each fix. - internal/api/task_view.go: taskView struct + enrichTask() helper - handleListTasks/handleGetTask: return enriched taskView responses - web/app.js: export renderDeploymentBadge(); add badge to READY cards - web/test/deployment-badge.test.mjs: 8 tests for renderDeploymentBadge - web/style.css: .deployment-badge--deployed / --pending styles - server_test.go: 3 new tests (red→green) for enriched task responses Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'web/app.js')
-rw-r--r--web/app.js26
1 files changed, 26 insertions, 0 deletions
diff --git a/web/app.js b/web/app.js
index e1782dd..9708727 100644
--- a/web/app.js
+++ b/web/app.js
@@ -96,6 +96,26 @@ export function renderChangestatsBadge(stats, doc = (typeof document !== 'undefi
return span;
}
+// Returns a <span class="deployment-badge"> element indicating whether the
+// currently-deployed server includes the task's fix commits.
+// Returns null if status is null/undefined or doc is null.
+// Accepts an optional doc parameter for testability (defaults to document).
+export function renderDeploymentBadge(status, doc = (typeof document !== 'undefined' ? document : null)) {
+ if (status == null || doc == null) return null;
+ const span = doc.createElement('span');
+ if (status.includes_fix) {
+ span.className = 'deployment-badge deployment-badge--deployed';
+ span.textContent = '✓ Deployed';
+ } else {
+ span.className = 'deployment-badge deployment-badge--pending';
+ span.textContent = '⚠ Not deployed';
+ }
+ if (status.deployed_commit) {
+ span.title = `Deployed commit: ${status.deployed_commit.slice(0, 8)}`;
+ }
+ return span;
+}
+
function truncateToWordBoundary(text, maxLen = 120) {
if (!text || text.length <= maxLen) return text;
const cut = text.lastIndexOf(' ', maxLen);
@@ -153,6 +173,12 @@ function createTaskCard(task) {
if (csBadge) card.appendChild(csBadge);
}
+ // Deployment status badge for READY tasks
+ if (task.state === 'READY' && task.deployment_status != null) {
+ const depBadge = renderDeploymentBadge(task.deployment_status);
+ if (depBadge) card.appendChild(depBadge);
+ }
+
// Footer: action buttons based on state
// Interrupted states (CANCELLED, FAILED, BUDGET_EXCEEDED) show both Resume and Restart.
// TIMED_OUT shows Resume only. Others show a single action.