From d96c546c6afadb572c462406668f8f89729fe247 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sat, 27 Dec 2025 23:33:18 -0300 Subject: [PATCH] feat(tasks): Add quick intent input with Create & Run at top - Add prominent input box at top of tasks page - Gradient header with clean design - HTMX integration for /api/autotask/create - Show progress indicator during processing - Display result with app link when done - Enter key triggers submit - Auto-refresh task list after creation --- ui/suite/tasks/tasks.css | 167 ++++++++++++++++++++++++++++++++++++++ ui/suite/tasks/tasks.html | 30 ++++++- ui/suite/tasks/tasks.js | 73 +++++++++++++++-- 3 files changed, 260 insertions(+), 10 deletions(-) diff --git a/ui/suite/tasks/tasks.css b/ui/suite/tasks/tasks.css index 7ade6e9..9778c38 100644 --- a/ui/suite/tasks/tasks.css +++ b/ui/suite/tasks/tasks.css @@ -3,6 +3,173 @@ Automated Intelligent Task Management Interface ============================================================================= */ +/* ============================================================================= + INTENT INPUT SECTION + ============================================================================= */ + +.intent-input-section { + padding: 24px; + background: linear-gradient(135deg, var(--primary) 0%, #764ba2 100%); + border-bottom: 1px solid var(--border); +} + +.intent-input-container { + max-width: 900px; + margin: 0 auto; +} + +.intent-input-wrapper { + display: flex; + gap: 12px; + align-items: stretch; +} + +.quick-intent-input { + flex: 1; + padding: 16px 20px; + font-size: 16px; + border: none; + border-radius: 12px; + background: rgba(255, 255, 255, 0.95); + color: #333; + outline: none; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + transition: box-shadow 0.2s ease; +} + +.quick-intent-input::placeholder { + color: #888; +} + +.quick-intent-input:focus { + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.25); +} + +.btn-create-run { + display: flex; + align-items: center; + gap: 8px; + padding: 16px 28px; + background: #fff; + color: var(--primary); + border: none; + border-radius: 12px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + white-space: nowrap; +} + +.btn-create-run:hover { + transform: translateY(-2px); + box-shadow: 0 6px 30px rgba(0, 0, 0, 0.2); +} + +.btn-create-run:active { + transform: translateY(0); +} + +.btn-create-run .spinner { + display: none; + width: 18px; + height: 18px; + border: 2px solid var(--primary); + border-top-color: transparent; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +.btn-create-run.htmx-request .btn-text { + opacity: 0.5; +} + +.btn-create-run.htmx-request .spinner { + display: block; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +.intent-result { + margin-top: 16px; + padding: 0; + border-radius: 12px; + overflow: hidden; +} + +.intent-result:empty { + display: none; +} + +.intent-result .result-card { + background: rgba(255, 255, 255, 0.95); + padding: 20px; + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); +} + +.intent-result .result-success { + color: #059669; +} + +.intent-result .result-error { + color: #dc2626; +} + +.intent-result .result-message { + font-size: 15px; + margin-bottom: 12px; + color: #333; +} + +.intent-result .result-link { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 10px 20px; + background: var(--primary); + color: #fff; + text-decoration: none; + border-radius: 8px; + font-weight: 500; + transition: background 0.2s; +} + +.intent-result .result-link:hover { + background: #5b21b6; +} + +.intent-result .result-progress { + margin-top: 12px; + height: 6px; + background: #e5e7eb; + border-radius: 3px; + overflow: hidden; +} + +.intent-result .result-progress-bar { + height: 100%; + background: var(--primary); + border-radius: 3px; + transition: width 0.3s ease; + animation: progress-pulse 1.5s ease-in-out infinite; +} + +@keyframes progress-pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.7; + } +} + /* ============================================================================= LAYOUT STRUCTURE ============================================================================= */ diff --git a/ui/suite/tasks/tasks.html b/ui/suite/tasks/tasks.html index 4849c47..ab49def 100644 --- a/ui/suite/tasks/tasks.html +++ b/ui/suite/tasks/tasks.html @@ -4,9 +4,35 @@ ============================================================================= -->
- +
+
+
+ + +
+
+
+
+
-
diff --git a/ui/suite/tasks/tasks.js b/ui/suite/tasks/tasks.js index 25de2e5..13fd105 100644 --- a/ui/suite/tasks/tasks.js +++ b/ui/suite/tasks/tasks.js @@ -28,21 +28,78 @@ document.addEventListener("DOMContentLoaded", function () { }); function initTasksApp() { - // Initialize WebSocket for real-time updates initWebSocket(); - - // Setup event listeners setupEventListeners(); - - // Setup keyboard shortcuts setupKeyboardShortcuts(); - - // Auto-scroll agent log to bottom + setupIntentInputHandlers(); scrollAgentLogToBottom(); - console.log("[Tasks] Initialized"); } +function setupIntentInputHandlers() { + const input = document.getElementById("quick-intent-input"); + const btn = document.getElementById("quick-intent-btn"); + + if (input) { + input.addEventListener("keypress", function (e) { + if (e.key === "Enter" && input.value.trim()) { + btn.click(); + } + }); + } + + document.body.addEventListener("htmx:beforeRequest", function (e) { + if (e.detail.elt.id === "quick-intent-btn") { + const resultDiv = document.getElementById("intent-result"); + resultDiv.innerHTML = ` +
+
Processing your request...
+
+
+
+
+ `; + } + }); + + document.body.addEventListener("htmx:afterRequest", function (e) { + if (e.detail.elt.id === "quick-intent-btn") { + const resultDiv = document.getElementById("intent-result"); + try { + const response = JSON.parse(e.detail.xhr.responseText); + if (response.success) { + let html = `
+
✓ ${response.message || "Done!"}
`; + + if (response.app_url) { + html += ` + Open App → + `; + } + + if (response.task_id) { + html += `
Task ID: ${response.task_id}
`; + } + + html += `
`; + resultDiv.innerHTML = html; + + document.getElementById("quick-intent-input").value = ""; + htmx.trigger(document.body, "taskCreated"); + } else { + resultDiv.innerHTML = `
+
✗ ${response.error || response.message || "Something went wrong"}
+
`; + } + } catch (err) { + resultDiv.innerHTML = `
+
✗ Failed to process response
+
`; + } + } + }); +} + // ============================================================================= // WEBSOCKET CONNECTION // =============================================================================