feat(KB-013): complete Step 1 — add step progress component to TaskDetailModal
This commit is contained in:
@@ -9,6 +9,20 @@ import { useAgentLogs } from "../hooks/useAgentLogs";
|
||||
import { AgentLogViewer } from "./AgentLogViewer";
|
||||
import { SteeringTab } from "./SteeringTab";
|
||||
|
||||
function getStepStatusColor(status: string): string {
|
||||
switch (status) {
|
||||
case "done":
|
||||
return "var(--color-success, #3fb950)";
|
||||
case "in-progress":
|
||||
return "var(--todo, #58a6ff)";
|
||||
case "skipped":
|
||||
return "var(--text-dim, #484f58)";
|
||||
case "pending":
|
||||
default:
|
||||
return "var(--border, #30363d)";
|
||||
}
|
||||
}
|
||||
|
||||
function formatTimestamp(iso: string): string {
|
||||
const date = new Date(iso);
|
||||
const now = new Date();
|
||||
@@ -459,6 +473,28 @@ export function TaskDetailModal({
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="detail-section detail-step-progress">
|
||||
<h4>Progress</h4>
|
||||
{task.steps && task.steps.length > 0 ? (
|
||||
<div className="step-progress-wrapper">
|
||||
<div className="step-progress-bar">
|
||||
{task.steps.map((step, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`step-progress-segment step-progress-segment--${step.status}`}
|
||||
data-tooltip={`${step.name} (${step.status})`}
|
||||
style={{ backgroundColor: getStepStatusColor(step.status) }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<span className="step-progress-label">
|
||||
{task.steps.filter(s => s.status === "done").length}/{task.steps.length} steps
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="step-progress-empty">(no steps defined)</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="detail-section detail-activity">
|
||||
<h4>Activity</h4>
|
||||
{task.log && task.log.length > 0 ? (
|
||||
|
||||
@@ -1117,6 +1117,79 @@ body {
|
||||
font-family: "SF Mono", Monaco, Consolas, monospace;
|
||||
}
|
||||
|
||||
/* === Step Progress === */
|
||||
.detail-step-progress {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.detail-step-progress h4 {
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.step-progress-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.step-progress-bar {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.step-progress-segment {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border-radius: 2px;
|
||||
transition: filter 0.15s ease, transform 0.15s ease;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-progress-segment:hover {
|
||||
filter: brightness(1.2);
|
||||
transform: scaleY(1.1);
|
||||
}
|
||||
|
||||
.step-progress-segment[data-tooltip]:hover::after {
|
||||
content: attr(data-tooltip);
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 4px 8px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
margin-bottom: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.step-progress-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
font-family: "SF Mono", Monaco, Consolas, monospace;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-progress-empty {
|
||||
font-size: 13px;
|
||||
color: var(--text-dim);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* === Activity Timeline === */
|
||||
.detail-activity {
|
||||
margin-top: 20px;
|
||||
|
||||
Reference in New Issue
Block a user