mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-09 02:24:11 +08:00
feat: Loop Monitor UI optimization - Phases 1-6 complete
Complete comprehensive optimization of Loop Monitor interface with 6 phases: Phase 1: Internationalization (i18n) - Added 28 new translation keys (English + Chinese) - Complete dual-language support for all new features - Coverage: kanban board, task status, navigation, priority Phase 2: CSS Styling Optimization - 688 lines of kanban board styling system - Task cards, status badges, priority badges - Drag-and-drop visual feedback - Base responsive design Phase 3: UI Layout Design - Left navigation panel optimization - Kanban board layout (4 columns: Pending, In Progress, Blocked, Done) - Task card information architecture - Status update flow design Phase 4: Backend API Extensions - New PATCH /api/loops/v2/:loopId/status endpoint for quick status updates - Extended PUT /api/loops/v2/:loopId with metadata support (tags, priority, notes) - Enhanced V2LoopStorage interface - Improved validation and error handling - WebSocket broadcasting for real-time updates Phase 5: Frontend JavaScript Implementation - 967 lines of interactive functionality - View switching system (Loops ↔ Kanban) - Kanban board rendering with 4-column layout - Drag-and-drop functionality (HTML5 API) - Status update functions (updateLoopStatus, updateTaskStatus, updateLoopMetadata) - Task context menu (right-click) - Navigation grouping by status Phase 6: Final Optimization - Smooth animations (@keyframes slideInUp, fadeIn, modalFadeIn, pulse) - Enhanced responsive design (desktop, tablet, mobile) - Full ARIA accessibility support - Complete keyboard navigation (arrow keys, Enter/Space, Ctrl+K, ?) - Performance optimizations (debounce, throttle, will-change) - Screen reader support Key Features: ✅ Kanban board with drag-and-drop task management ✅ Task status management (pending, in_progress, blocked, done) ✅ Loop status quick update via PATCH API ✅ Navigation grouping with status-based filtering ✅ Full keyboard navigation support ✅ ARIA accessibility attributes ✅ Responsive design (mobile, tablet, desktop) ✅ Smooth animations and transitions ✅ Internationalization (English & Chinese) ✅ Performance optimizations Code Statistics: - Total: ~1798 lines - loop-monitor.js: +967 lines (frontend logic) - 36-loop-monitor.css: +688 lines (styling) - loop-v2-routes.ts: +86/-3 lines (API backend) - i18n.js: +60 lines (translations) Technical Stack: - JavaScript ES6+ (frontend) - CSS3 with animations - TypeScript (backend) - HTML5 Drag & Drop API - ARIA accessibility - Responsive design Browser Compatibility: - Chrome/Edge 90+ - Firefox 88+ - Safari 14+ All TypeScript compilation tests pass. Ready for production deployment.
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
* - GET /api/loops/v2 - List all loops with pagination
|
||||
* - POST /api/loops/v2 - Create loop with {title, description, max_iterations}
|
||||
* - GET /api/loops/v2/:loopId - Get loop details
|
||||
* - PUT /api/loops/v2/:loopId - Update loop metadata
|
||||
* - PUT /api/loops/v2/:loopId - Update loop metadata (title, description, max_iterations, tags, priority, notes)
|
||||
* - PATCH /api/loops/v2/:loopId/status - Quick status update with {status}
|
||||
* - DELETE /api/loops/v2/:loopId - Delete loop
|
||||
* - POST /api/loops/v2/:loopId/start - Start loop execution
|
||||
* - POST /api/loops/v2/:loopId/pause - Pause loop
|
||||
@@ -44,12 +45,18 @@ interface V2LoopCreateRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* V2 Loop Update Request
|
||||
* V2 Loop Update Request (extended)
|
||||
*/
|
||||
interface V2LoopUpdateRequest {
|
||||
// Basic fields
|
||||
title?: string;
|
||||
description?: string;
|
||||
max_iterations?: number;
|
||||
|
||||
// Extended metadata fields
|
||||
tags?: string[];
|
||||
priority?: 'low' | 'medium' | 'high';
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +73,12 @@ interface V2LoopStorage {
|
||||
updated_at: string;
|
||||
completed_at?: string;
|
||||
failure_reason?: string;
|
||||
|
||||
// Extended metadata fields
|
||||
tags?: string[];
|
||||
priority?: 'low' | 'medium' | 'high';
|
||||
notes?: string;
|
||||
|
||||
// Tasks stored in separate tasks.jsonl file
|
||||
}
|
||||
|
||||
@@ -505,7 +518,7 @@ export async function handleLoopV2Routes(ctx: RouteContext): Promise<boolean> {
|
||||
}
|
||||
|
||||
handlePostRequest(req, res, async (body) => {
|
||||
const { title, description, max_iterations } = body as V2LoopUpdateRequest;
|
||||
const { title, description, max_iterations, tags, priority, notes } = body as V2LoopUpdateRequest;
|
||||
|
||||
try {
|
||||
const loop = await readLoopStorage(loopId);
|
||||
@@ -540,6 +553,28 @@ export async function handleLoopV2Routes(ctx: RouteContext): Promise<boolean> {
|
||||
loop.max_iterations = max_iterations;
|
||||
}
|
||||
|
||||
// Extended metadata fields
|
||||
if (tags !== undefined) {
|
||||
if (!Array.isArray(tags) || !tags.every(t => typeof t === 'string')) {
|
||||
return { success: false, error: 'tags must be an array of strings', status: 400 };
|
||||
}
|
||||
loop.tags = tags;
|
||||
}
|
||||
|
||||
if (priority !== undefined) {
|
||||
if (!['low', 'medium', 'high'].includes(priority)) {
|
||||
return { success: false, error: 'priority must be one of: low, medium, high', status: 400 };
|
||||
}
|
||||
loop.priority = priority;
|
||||
}
|
||||
|
||||
if (notes !== undefined) {
|
||||
if (typeof notes !== 'string') {
|
||||
return { success: false, error: 'notes must be a string', status: 400 };
|
||||
}
|
||||
loop.notes = notes.trim();
|
||||
}
|
||||
|
||||
loop.updated_at = new Date().toISOString();
|
||||
await writeLoopStorage(loop);
|
||||
|
||||
@@ -553,6 +588,51 @@ export async function handleLoopV2Routes(ctx: RouteContext): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
// PATCH /api/loops/v2/:loopId/status - Quick status update
|
||||
if (pathname.match(/\/api\/loops\/v2\/[^/]+\/status$/) && req.method === 'PATCH') {
|
||||
const loopId = pathname.split('/').slice(-2)[0];
|
||||
if (!loopId || !isValidId(loopId)) {
|
||||
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ success: false, error: 'Invalid loop ID format' }));
|
||||
return true;
|
||||
}
|
||||
|
||||
handlePostRequest(req, res, async (body) => {
|
||||
const { status } = body as { status?: string };
|
||||
|
||||
if (!status || typeof status !== 'string') {
|
||||
return { success: false, error: 'status is required', status: 400 };
|
||||
}
|
||||
|
||||
if (!Object.values(LoopStatus).includes(status as LoopStatus)) {
|
||||
return { success: false, error: `Invalid status: ${status}`, status: 400 };
|
||||
}
|
||||
|
||||
try {
|
||||
const loop = await readLoopStorage(loopId);
|
||||
if (!loop) {
|
||||
return { success: false, error: 'Loop not found', status: 404 };
|
||||
}
|
||||
|
||||
loop.status = status as LoopStatus;
|
||||
loop.updated_at = new Date().toISOString();
|
||||
|
||||
if (status === LoopStatus.COMPLETED && !loop.completed_at) {
|
||||
loop.completed_at = new Date().toISOString();
|
||||
}
|
||||
|
||||
await writeLoopStorage(loop);
|
||||
|
||||
broadcastStateUpdate(loopId, loop.status);
|
||||
|
||||
return { success: true, data: loop };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message, status: 500 };
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// DELETE /api/loops/v2/:loopId - Delete loop
|
||||
if (pathname.match(/^\/api\/loops\/v2\/[^/]+$/) && req.method === 'DELETE') {
|
||||
const loopId = pathname.split('/').pop();
|
||||
|
||||
Reference in New Issue
Block a user