diff --git a/src/pages/MonitoringPage/Components.tsx b/src/pages/MonitoringPage/Components.tsx index c60a702..f1adffa 100644 --- a/src/pages/MonitoringPage/Components.tsx +++ b/src/pages/MonitoringPage/Components.tsx @@ -106,24 +106,34 @@ interface StatusListProps { title: string; items: any[]; type: 'goal' | 'trigger' | 'norm'| 'cond_norm'; + activeIds: Record; + currentGoalIndex?: number; } // --- STATUS LIST COMPONENT --- -export const StatusList: React.FC = ({ title, items, type }) => { - +export const StatusList: React.FC = ({ + title, + items, + type, + activeIds, + currentGoalIndex // Destructure this prop +}) => { return (

{title}

    {items.map((item, idx) => { - let isAchieved = item.achieved; + const isActive = !!activeIds[item.id]; const showIndicator = type !== 'norm'; - const canOverride = showIndicator && !isAchieved; - const isCurrentGoal = type === 'goal' && item.isCurrent; + const canOverride = showIndicator && !isActive; + + // HIGHLIGHT LOGIC: + // If this is the "Goals" list, check if the current index matches + const isCurrentGoal = type === 'goal' && idx === currentGoalIndex; + const handleOverrideClick = () => { if (!canOverride) return; - let contextValue = String(item.id); - sendUserInterrupt("override", contextValue); + sendUserInterrupt("override", String(item.id)); }; return ( @@ -133,18 +143,23 @@ export const StatusList: React.FC = ({ title, items, type }) => className={`${styles.statusIndicator} ${canOverride ? styles.clickable : ''}`} onClick={handleOverrideClick} > - {isAchieved ? "✔️" : "❌"} + {isActive ? "✔️" : "❌"} )} - {item.description || item.label || item.norm} + {isCurrentGoal && " (Current)"} ); diff --git a/src/pages/MonitoringPage/MonitoringPage.tsx b/src/pages/MonitoringPage/MonitoringPage.tsx index e63eaee..47b3570 100644 --- a/src/pages/MonitoringPage/MonitoringPage.tsx +++ b/src/pages/MonitoringPage/MonitoringPage.tsx @@ -22,6 +22,7 @@ const MonitoringPage: React.FC = () => { const phaseIds = getPhaseIds(); const [phaseIndex, setPhaseIndex] = React.useState(0); + const isFinished = phaseIndex >= phaseIds.length; //determines if experiment is over const handleStreamUpdate = React.useCallback((data: any) => { // Check for phase updates @@ -34,19 +35,29 @@ const MonitoringPage: React.FC = () => { } } else if (data.type === 'goal_update') { - // We find which goal in the current phase matches this ID - const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]); + const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]) as any[]; const gIndex = currentPhaseGoals.findIndex((g: any) => g.id === data.id); - if (gIndex !== -1) { - setGoalIndex(gIndex); - console.log(`Goal index updated to ${gIndex} for goal ID ${data.id}`); - } - setActiveIds((prev) => ({ - ...prev, - [data.id]: true - })); + if (gIndex !== -1) { + //set current goal to the goal that is just started + setGoalIndex(gIndex); + + // All previous goals are set to "active" which means they are achieved + setActiveIds((prev) => { + const nextState = { ...prev }; + + // We loop until i is LESS than gIndex. + // This leaves currentPhaseGoals[gIndex] as isActive: false. + for (let i = 0; i < gIndex; i++) { + nextState[currentPhaseGoals[i].id ] = true; + } + + return nextState; + }); + + console.log(`Now pursuing goal: ${data.id}. Previous goals marked achieved.`); } + } else if (data.type === 'trigger_update') { setActiveIds((prev) => ({ @@ -54,7 +65,19 @@ const MonitoringPage: React.FC = () => { [data.id]: data.achieved // data.id is de key, achieved is true/false })); } - }, [getPhaseIds]); + else if (data.type === 'cond_norms_state_update') { + setActiveIds((prev) => { + const nextState = { ...prev }; + + data.norms.forEach((normUpdate: { id: string; active: boolean }) => { + nextState[normUpdate.id] = normUpdate.active; + }); + + return nextState; + }); + console.log("Updated conditional norms state:", data.norms); + } +}, [getPhaseIds]); useExperimentLogger(handleStreamUpdate); @@ -74,30 +97,39 @@ const MonitoringPage: React.FC = () => { const triggers = (getTriggersInPhase(phaseId) as any[]).map(t => ({ ...t, label: (() => { - // Determine the Condition Prefix - let prefix = t.label; // Default fallback + + let prefix = ""; if (t.condition?.keyword) { prefix = `if keywords said: "${t.condition.keyword}"`; } else if (t.condition?.name) { prefix = `if LLM belief: ${t.condition.name}`; + } else { //fallback + prefix = t.label || "Trigger"; } - // Format the Plan Steps - // We check if plan exists and has steps + const stepLabels = t.plan?.steps?.map((step: any) => { - - return step.label || step.name || "Action"; + if (step.text) { + return `say: "${step.text}"`; + } + if (step.gesture) { + return `perform gesture: ${step.gesture.name || step.gesture.type}`; + } + if (step.goal) { + return `perform LLM: ${step.goal}`; + } + return "Action"; // Fallback }) || []; const planText = stepLabels.length > 0 ? `➔ Do: ${stepLabels.join(", ")}` : "➔ (No actions set)"; - // "If [Condition] ➔ Do: [Steps]" return `${prefix} ${planText}`; })(), - achieved: activeIds[t.id] ?? false + isActive: activeIds[t.id] ?? false })); + const norms = (getNormsInPhase(phaseId) as NormNodeData[]) .filter(n => !n.condition) .map(n => ({ @@ -186,11 +218,18 @@ const MonitoringPage: React.FC = () => {

    Phase Overview

    - - - - - + {isFinished ? ( +
    +

    All phases have been successfully completed.

    +
    + ) : ( + <> + + + + + + )} {/* LOGS */}