Files
pepperplus-ui/src/pages/MonitoringPage/MonitoringPageAPI.ts
Pim Hutting f73bbb9d02 chore: added tests and removed restart phase
this version also has recursive goals functional
2026-01-22 10:15:20 +01:00

121 lines
3.7 KiB
TypeScript

import React, { useEffect } from 'react';
const API_BASE = "http://localhost:8000";
const API_BASE_BP = API_BASE + "/button_pressed"; //UserInterruptAgent endpoint
/**
* HELPER: Unified sender function
*/
export const sendAPICall = async (type: string, context: string, endpoint?: string) => {
try {
const response = await fetch(`${API_BASE_BP}${endpoint ?? ""}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ type, context }),
});
if (!response.ok) throw new Error("Backend response error");
console.log(`API Call send - Type: ${type}, Context: ${context} ${endpoint ? `, Endpoint: ${endpoint}` : ""}`);
} catch (err) {
console.error(`Failed to send api call:`, err);
}
};
/**
* Sends an API call to the CB for going to the next phase.
* In case we can't go to the next phase, the function will throw an error.
*/
export async function nextPhase(): Promise<void> {
const type = "next_phase"
const context = ""
sendAPICall(type, context)
}
/**
* Sends an API call to the CB for going to pause experiment
*/
export async function pauseExperiment(): Promise<void> {
const type = "pause"
const context = "true"
sendAPICall(type, context)
}
/**
* Sends an API call to the CB for going to resume experiment
*/
export async function playExperiment(): Promise<void> {
const type = "pause"
const context = "false"
sendAPICall(type, context)
}
/**
* Types for the experiment stream messages
*/
export type PhaseUpdate = { type: 'phase_update'; id: string };
export type GoalUpdate = { type: 'goal_update'; id: string };
export type TriggerUpdate = { type: 'trigger_update'; id: string; achieved: boolean };
export type CondNormsStateUpdate = { type: 'cond_norms_state_update'; norms: { id: string; active: boolean }[] };
export type ExperimentStreamData = PhaseUpdate | GoalUpdate | TriggerUpdate | CondNormsStateUpdate | Record<string, unknown>;
/**
* A hook that listens to the experiment stream that updates current state of the program
* via updates sent from the backend
*/
export function useExperimentLogger(onUpdate?: (data: ExperimentStreamData) => void) {
const callbackRef = React.useRef(onUpdate);
// Ref is updated every time with on update
React.useEffect(() => {
callbackRef.current = onUpdate;
}, [onUpdate]);
useEffect(() => {
console.log("Connecting to Experiment Stream...");
const eventSource = new EventSource(`${API_BASE}/experiment_stream`);
eventSource.onmessage = (event) => {
try {
const parsedData = JSON.parse(event.data) as ExperimentStreamData;
//call function using the ref
callbackRef.current?.(parsedData);
} catch (err) {
console.warn("Stream parse error:", err);
}
};
eventSource.onerror = (err) => {
console.error("SSE Connection Error:", err);
eventSource.close();
};
return () => {
console.log("Closing Experiment Stream...");
eventSource.close();
};
}, []);
}
/**
* A hook that listens to the status stream that updates active conditional norms
* via updates sent from the backend
*/
export function useStatusLogger(onUpdate?: (data: ExperimentStreamData) => void) {
const callbackRef = React.useRef(onUpdate);
React.useEffect(() => {
callbackRef.current = onUpdate;
}, [onUpdate]);
useEffect(() => {
const eventSource = new EventSource(`${API_BASE}/status_stream`);
eventSource.onmessage = (event) => {
try {
const parsedData = JSON.parse(event.data);
callbackRef.current?.(parsedData);
} catch (err) { console.warn("Status stream error:", err); }
};
return () => eventSource.close();
}, []);
}