From 60887682a57ce0d35138a025091488f86bee8e64 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Mon, 23 Feb 2026 22:09:33 +0100 Subject: [PATCH] phase 2 codeeditor --- src/pages/FeatureView.tsx | 4 +- .../views/codeeditor/CodeEditor.module.css | 121 ++++++++++++++++++ src/pages/views/codeeditor/CodeEditorPage.tsx | 48 ++++++- .../codeeditor/CodeEditorWorkflowsPage.tsx | 83 ++++++++++++ src/pages/views/codeeditor/index.ts | 1 + src/pages/views/codeeditor/useCodeEditor.ts | 37 +++++- 6 files changed, 281 insertions(+), 13 deletions(-) create mode 100644 src/pages/views/codeeditor/CodeEditorWorkflowsPage.tsx diff --git a/src/pages/FeatureView.tsx b/src/pages/FeatureView.tsx index 9f960ac..4bc0dd8 100644 --- a/src/pages/FeatureView.tsx +++ b/src/pages/FeatureView.tsx @@ -33,7 +33,7 @@ import { PlaygroundPage, WorkflowsPage } from './workflows'; import { AutomationsPage, AutomationTemplatesPage } from './workflows'; // CodeEditor Views -import { CodeEditorPage } from './views/codeeditor'; +import { CodeEditorPage, CodeEditorWorkflowsPage } from './views/codeeditor'; // Teamsbot Views import { TeamsbotDashboardView } from './views/teamsbot/TeamsbotDashboardView'; @@ -128,7 +128,7 @@ const VIEW_COMPONENTS: Record> = { }, codeeditor: { editor: CodeEditorPage, - workflows: WorkflowsPage, + workflows: CodeEditorWorkflowsPage, }, teamsbot: { dashboard: TeamsbotDashboardView, diff --git a/src/pages/views/codeeditor/CodeEditor.module.css b/src/pages/views/codeeditor/CodeEditor.module.css index 95dcd68..96ce517 100644 --- a/src/pages/views/codeeditor/CodeEditor.module.css +++ b/src/pages/views/codeeditor/CodeEditor.module.css @@ -161,6 +161,65 @@ background: var(--disabled-bg, #f5f5f5); } +/* Mode Toggle */ +.modeToggle { + display: flex; + gap: 4px; + margin-bottom: 8px; +} + +.modeButton { + display: flex; + align-items: center; + gap: 4px; + padding: 4px 12px; + border: 1px solid var(--border-color, #e0e0e0); + border-radius: 4px; + background: transparent; + font-size: 12px; + cursor: pointer; + transition: all 0.15s; + color: var(--text-secondary, #666); +} + +.modeButton:hover { + background: var(--hover-bg, #f5f5f5); +} + +.modeActive { + background: var(--primary-color, #4a90d9); + color: white; + border-color: var(--primary-color, #4a90d9); +} + +.modeActive:hover { + background: var(--primary-dark, #3a7bc8); +} + +.modeButton:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +/* Agent Progress */ +.agentProgress { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + margin: 8px 0; + background: var(--info-light, #e8f4fd); + border-radius: 6px; + font-size: 12px; + color: var(--info-dark, #0c5460); + animation: pulse 2s ease-in-out infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.7; } +} + .inputActions { display: flex; justify-content: space-between; @@ -342,3 +401,65 @@ background: var(--danger-color, #dc3545); color: white; } + +/* Workflows Page */ +.workflowsPage { + padding: 16px 24px; +} + +.workflowsHeader { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} + +.workflowsHeader h3 { + margin: 0; +} + +.refreshButton { + padding: 6px 14px; + border: 1px solid var(--border-color, #e0e0e0); + border-radius: 4px; + background: transparent; + cursor: pointer; + font-size: 13px; +} + +.refreshButton:hover { + background: var(--hover-bg, #f5f5f5); +} + +.workflowTable { + width: 100%; + border-collapse: collapse; + font-size: 13px; +} + +.workflowTable th, +.workflowTable td { + padding: 8px 12px; + text-align: left; + border-bottom: 1px solid var(--border-color, #e0e0e0); +} + +.workflowTable th { + font-weight: 600; + color: var(--text-secondary, #666); + font-size: 12px; + text-transform: uppercase; +} + +.statusBadge { + padding: 2px 8px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; +} + +.status_running { background: var(--info-light, #e8f4fd); color: var(--info-dark, #0c5460); } +.status_completed { background: var(--success-light, #d4edda); color: var(--success-dark, #155724); } +.status_stopped { background: var(--warning-light, #fff3cd); color: var(--warning-dark, #856404); } +.status_error { background: var(--danger-light, #f8d7da); color: var(--danger-dark, #721c24); } +.status_unknown { background: #f0f0f0; color: #666; } diff --git a/src/pages/views/codeeditor/CodeEditorPage.tsx b/src/pages/views/codeeditor/CodeEditorPage.tsx index b548b0a..fc8d1f0 100644 --- a/src/pages/views/codeeditor/CodeEditorPage.tsx +++ b/src/pages/views/codeeditor/CodeEditorPage.tsx @@ -3,6 +3,7 @@ * * Main page for the CodeEditor feature. * Three-panel layout: FileList (left) | Chat (center) | DiffPreview (right) + * Supports simple mode (Phase 1) and agent mode (Phase 2). */ import React, { useState, useRef, useCallback } from 'react'; @@ -12,7 +13,7 @@ import { FileListPanel } from './FileListPanel'; import { DiffPreviewPanel } from './DiffPreviewPanel'; import { useResizablePanels } from '../../../hooks/useResizablePanels'; import { Messages } from '../../../components/UiComponents'; -import { FaPaperPlane, FaStop } from 'react-icons/fa'; +import { FaPaperPlane, FaStop, FaRobot, FaEdit } from 'react-icons/fa'; import styles from './CodeEditor.module.css'; export const CodeEditorPage: React.FC = () => { @@ -20,6 +21,7 @@ export const CodeEditorPage: React.FC = () => { const instanceId = instance?.id || ''; const inputRef = useRef(null); const [inputValue, setInputValue] = useState(''); + const [mode, setMode] = useState<'simple' | 'agent'>('simple'); const { messages, @@ -32,6 +34,7 @@ export const CodeEditorPage: React.FC = () => { sendMessage, stopProcessing, files, + agentProgress, } = useCodeEditor(instanceId); const { @@ -61,9 +64,9 @@ export const CodeEditorPage: React.FC = () => { const handleSubmit = useCallback(() => { const trimmed = inputValue.trim(); if (!trimmed || isProcessing) return; - sendMessage(trimmed, selectedFileIds); + sendMessage(trimmed, selectedFileIds, mode); setInputValue(''); - }, [inputValue, isProcessing, sendMessage, selectedFileIds]); + }, [inputValue, isProcessing, sendMessage, selectedFileIds, mode]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { @@ -95,22 +98,57 @@ export const CodeEditorPage: React.FC = () => {
+ + {agentProgress && isProcessing && ( +
+ + + Round {agentProgress.round} | {agentProgress.totalToolCalls} tools |{' '} + {agentProgress.costCHF.toFixed(4)} CHF + +
+ )}
+
+ + +
+