Compare commits
4 Commits
4dcbe78abf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b826b8ae47 | |||
| d8308b0d0b | |||
| af196529f8 | |||
| 901159ae2d |
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This script checks if the current branch name follows the specified format.
|
|
||||||
# It's designed to be used as a 'pre-commit' git hook.
|
|
||||||
|
|
||||||
# Format: <type>/<short-description>
|
|
||||||
# Example: feat/add-user-login
|
|
||||||
|
|
||||||
# --- Configuration ---
|
|
||||||
# An array of allowed commit types
|
|
||||||
ALLOWED_TYPES=(feat fix refactor perf style test docs build chore revert)
|
|
||||||
# An array of branches to ignore
|
|
||||||
IGNORED_BRANCHES=(main dev demo)
|
|
||||||
|
|
||||||
# --- Colors for Output ---
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# --- Helper Functions ---
|
|
||||||
error_exit() {
|
|
||||||
echo -e "${RED}ERROR: $1${NC}" >&2
|
|
||||||
echo -e "${YELLOW}Branch name format is incorrect. Aborting commit.${NC}" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Main Logic ---
|
|
||||||
|
|
||||||
# 1. Get the current branch name
|
|
||||||
BRANCH_NAME=$(git symbolic-ref --short HEAD)
|
|
||||||
|
|
||||||
# 2. Check if the current branch is in the ignored list
|
|
||||||
for ignored_branch in "${IGNORED_BRANCHES[@]}"; do
|
|
||||||
if [ "$BRANCH_NAME" == "$ignored_branch" ]; then
|
|
||||||
echo -e "${GREEN}Branch check skipped for default branch: $BRANCH_NAME${NC}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 3. Validate the overall structure: <type>/<description>
|
|
||||||
if ! [[ "$BRANCH_NAME" =~ ^[a-z]+/.+$ ]]; then
|
|
||||||
error_exit "Branch name must be in the format: <type>/<short-description>\nExample: feat/add-user-login"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4. Extract the type and description
|
|
||||||
TYPE=$(echo "$BRANCH_NAME" | cut -d'/' -f1)
|
|
||||||
DESCRIPTION=$(echo "$BRANCH_NAME" | cut -d'/' -f2-)
|
|
||||||
|
|
||||||
# 5. Validate the <type>
|
|
||||||
type_valid=false
|
|
||||||
for allowed_type in "${ALLOWED_TYPES[@]}"; do
|
|
||||||
if [ "$TYPE" == "$allowed_type" ]; then
|
|
||||||
type_valid=true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$type_valid" == false ]; then
|
|
||||||
error_exit "Invalid type '$TYPE'.\nAllowed types are: ${ALLOWED_TYPES[*]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 6. Validate the <short-description>
|
|
||||||
# Regex breakdown:
|
|
||||||
# ^[a-z0-9]+ - Starts with one or more lowercase letters/numbers (the first word).
|
|
||||||
# (-[a-z0-9]+){0,5} - Followed by a group of (dash + word) 0 to 5 times.
|
|
||||||
# $ - End of the string.
|
|
||||||
# This entire pattern enforces 1 to 6 words total, separated by dashes.
|
|
||||||
DESCRIPTION_REGEX="^[a-z0-9]+(-[a-z0-9]+){0,5}$"
|
|
||||||
|
|
||||||
if ! [[ "$DESCRIPTION" =~ $DESCRIPTION_REGEX ]]; then
|
|
||||||
error_exit "Invalid short description '$DESCRIPTION'.\nIt must be a maximum of 6 words, all lowercase, separated by dashes.\nExample: add-new-user-authentication-feature"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If all checks pass, exit successfully
|
|
||||||
echo -e "${GREEN}Branch name '$BRANCH_NAME' is valid.${NC}"
|
|
||||||
exit 0
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This script checks if a commit message follows the specified format.
|
|
||||||
# It's designed to be used as a 'commit-msg' git hook.
|
|
||||||
|
|
||||||
# Format:
|
|
||||||
# <type>: <short description>
|
|
||||||
#
|
|
||||||
# [optional]<body>
|
|
||||||
#
|
|
||||||
# [ref/close]: <issue identifier>
|
|
||||||
|
|
||||||
# --- Configuration ---
|
|
||||||
# An array of allowed commit types
|
|
||||||
ALLOWED_TYPES=(feat fix refactor perf style test docs build chore revert)
|
|
||||||
|
|
||||||
# --- Colors for Output ---
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# The first argument to the hook is the path to the file containing the commit message
|
|
||||||
COMMIT_MSG_FILE=$1
|
|
||||||
|
|
||||||
# --- Automated Commit Detection ---
|
|
||||||
|
|
||||||
# Read the first line (header) for initial checks
|
|
||||||
HEADER=$(head -n 1 "$COMMIT_MSG_FILE")
|
|
||||||
|
|
||||||
echo 'Given commit message:'
|
|
||||||
echo $HEADER
|
|
||||||
|
|
||||||
# Check for Merge commits (covers 'git merge' and PR merges from GitHub/GitLab)
|
|
||||||
# Examples: "Merge branch 'main' into ...", "Merge pull request #123 from ..."
|
|
||||||
MERGE_PATTERN="^Merge (remote-tracking )?(branch|pull request|tag) .*"
|
|
||||||
if [[ "$HEADER" =~ $MERGE_PATTERN ]]; then
|
|
||||||
echo -e "${GREEN}Merge commit detected by message content. Skipping validation.${NC}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for Revert commits
|
|
||||||
# Example: "Revert "feat: add new feature""
|
|
||||||
REVERT_PATTERN="^Revert \".*\""
|
|
||||||
if [[ "$HEADER" =~ $REVERT_PATTERN ]]; then
|
|
||||||
echo -e "${GREEN}Revert commit detected by message content. Skipping validation.${NC}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for Cherry-pick commits (this pattern appears at the end of the message)
|
|
||||||
# Example: "(cherry picked from commit deadbeef...)"
|
|
||||||
# We use grep -q to search the whole file quietly.
|
|
||||||
CHERRY_PICK_PATTERN="\(cherry picked from commit [a-f0-9]{7,40}\)"
|
|
||||||
if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then
|
|
||||||
echo -e "${GREEN}Cherry-pick detected by message content. Skipping validation.${NC}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for Squash
|
|
||||||
# Example: "Squash commits ..."
|
|
||||||
SQUASH_PATTERN="^Squash .+"
|
|
||||||
if [[ "$HEADER" =~ $SQUASH_PATTERN ]]; then
|
|
||||||
echo -e "${GREEN}Squash commit detected by message content. Skipping validation.${NC}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- Validation Functions ---
|
|
||||||
|
|
||||||
# Function to print an error message and exit
|
|
||||||
# Usage: error_exit "Your error message here"
|
|
||||||
error_exit() {
|
|
||||||
# >&2 redirects echo to stderr
|
|
||||||
echo -e "${RED}ERROR: $1${NC}" >&2
|
|
||||||
echo -e "${YELLOW}Commit message format is incorrect. Aborting commit.${NC}" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Main Logic ---
|
|
||||||
|
|
||||||
# 1. Read the header (first line) of the commit message
|
|
||||||
HEADER=$(head -n 1 "$COMMIT_MSG_FILE")
|
|
||||||
|
|
||||||
# 2. Validate the header format: <type>: <description>
|
|
||||||
# Regex breakdown:
|
|
||||||
# ^(type1|type2|...) - Starts with one of the allowed types
|
|
||||||
# : - Followed by a literal colon
|
|
||||||
# \s - Followed by a single space
|
|
||||||
# .+ - Followed by one or more characters for the description
|
|
||||||
# $ - End of the line
|
|
||||||
TYPES_REGEX=$(
|
|
||||||
IFS="|"
|
|
||||||
echo "${ALLOWED_TYPES[*]}"
|
|
||||||
)
|
|
||||||
HEADER_REGEX="^($TYPES_REGEX): .+$"
|
|
||||||
|
|
||||||
if ! [[ "$HEADER" =~ $HEADER_REGEX ]]; then
|
|
||||||
error_exit "Invalid header format.\n\nHeader must be in the format: <type>: <short description>\nAllowed types: ${ALLOWED_TYPES[*]}\nExample: feat: add new user authentication feature"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Only validate footer if commit type is not chore
|
|
||||||
TYPE=$(echo "$HEADER" | cut -d':' -f1)
|
|
||||||
if [ "$TYPE" != "chore" ]; then
|
|
||||||
# 3. Validate the footer (last line) of the commit message
|
|
||||||
FOOTER=$(tail -n 1 "$COMMIT_MSG_FILE")
|
|
||||||
|
|
||||||
# Regex breakdown:
|
|
||||||
# ^(ref|close) - Starts with 'ref' or 'close'
|
|
||||||
# : - Followed by a literal colon
|
|
||||||
# \s - Followed by a single space
|
|
||||||
# N25B- - Followed by the literal string 'N25B-'
|
|
||||||
# [0-9]+ - Followed by one or more digits
|
|
||||||
# $ - End of the line
|
|
||||||
FOOTER_REGEX="^(ref|close): N25B-[0-9]+$"
|
|
||||||
|
|
||||||
if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then
|
|
||||||
error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: <issue identifier>\nExample: ref: N25B-123"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4. If the message has more than 2 lines, validate the separator
|
|
||||||
# A blank line must exist between the header and the body.
|
|
||||||
LINE_COUNT=$(wc -l <"$COMMIT_MSG_FILE" | xargs) # xargs trims whitespace
|
|
||||||
|
|
||||||
# We only care if there is a body. Header + Footer = 2 lines.
|
|
||||||
# Header + Blank Line + Body... + Footer > 2 lines.
|
|
||||||
if [ "$LINE_COUNT" -gt 2 ]; then
|
|
||||||
# Get the second line
|
|
||||||
SECOND_LINE=$(sed -n '2p' "$COMMIT_MSG_FILE")
|
|
||||||
|
|
||||||
# Check if the second line is NOT empty. If it's not, it's an error.
|
|
||||||
if [ -n "$SECOND_LINE" ]; then
|
|
||||||
error_exit "Missing blank line between header and body.\n\nThe second line of your commit message must be empty if a body is present."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If all checks pass, exit with success
|
|
||||||
echo -e "${GREEN}Commit message is valid.${NC}"
|
|
||||||
exit 0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
sh .githooks/check-commit-msg.sh $1
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
sh .githooks/check-branch-name.sh
|
|
||||||
|
|
||||||
npm run lint
|
|
||||||
17
package-lock.json
generated
17
package-lock.json
generated
@@ -31,7 +31,6 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
"husky": "^9.1.7",
|
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
"jest-environment-jsdom": "^30.2.0",
|
"jest-environment-jsdom": "^30.2.0",
|
||||||
@@ -5544,22 +5543,6 @@
|
|||||||
"node": ">=10.17.0"
|
"node": ">=10.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/husky": {
|
|
||||||
"version": "9.1.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
|
||||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"husky": "bin.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/typicode"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint src test",
|
"lint": "eslint src test",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test": "jest",
|
"test": "jest"
|
||||||
"prepare": "husky"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@neodrag/react": "^2.3.1",
|
"@neodrag/react": "^2.3.1",
|
||||||
@@ -35,7 +34,6 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
"husky": "^9.1.7",
|
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
"jest-environment-jsdom": "^30.2.0",
|
"jest-environment-jsdom": "^30.2.0",
|
||||||
|
|||||||
@@ -98,6 +98,11 @@ University within the Software Project course.
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stop {
|
||||||
|
background-color: red;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.restartExperiment{
|
.restartExperiment{
|
||||||
background-color: red;
|
background-color: red;
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@@ -6,17 +6,18 @@ import styles from './MonitoringPage.module.css';
|
|||||||
|
|
||||||
// Store & API
|
// Store & API
|
||||||
import useProgramStore from "../../utils/programStore";
|
import useProgramStore from "../../utils/programStore";
|
||||||
import {
|
import {
|
||||||
nextPhase,
|
nextPhase,
|
||||||
useExperimentLogger,
|
stopExperiment,
|
||||||
useStatusLogger,
|
useExperimentLogger,
|
||||||
pauseExperiment,
|
useStatusLogger,
|
||||||
playExperiment,
|
pauseExperiment,
|
||||||
type ExperimentStreamData,
|
playExperiment,
|
||||||
type GoalUpdate,
|
type ExperimentStreamData,
|
||||||
type TriggerUpdate,
|
type GoalUpdate,
|
||||||
type CondNormsStateUpdate,
|
type TriggerUpdate,
|
||||||
type PhaseUpdate
|
type CondNormsStateUpdate,
|
||||||
|
type PhaseUpdate
|
||||||
} from "./MonitoringPageAPI";
|
} from "./MonitoringPageAPI";
|
||||||
import { graphReducer, runProgram } from '../VisProgPage/VisProgLogic.ts';
|
import { graphReducer, runProgram } from '../VisProgPage/VisProgLogic.ts';
|
||||||
|
|
||||||
@@ -26,12 +27,12 @@ import type { GoalNode } from '../VisProgPage/visualProgrammingUI/nodes/GoalNode
|
|||||||
import type { TriggerNode } from '../VisProgPage/visualProgrammingUI/nodes/TriggerNode';
|
import type { TriggerNode } from '../VisProgPage/visualProgrammingUI/nodes/TriggerNode';
|
||||||
|
|
||||||
// Sub-components
|
// Sub-components
|
||||||
import {
|
import {
|
||||||
GestureControls,
|
GestureControls,
|
||||||
SpeechPresets,
|
SpeechPresets,
|
||||||
DirectSpeechInput,
|
DirectSpeechInput,
|
||||||
StatusList,
|
StatusList,
|
||||||
RobotConnected
|
RobotConnected
|
||||||
} from './MonitoringPageComponents';
|
} from './MonitoringPageComponents';
|
||||||
import ExperimentLogs from "./components/ExperimentLogs.tsx";
|
import ExperimentLogs from "./components/ExperimentLogs.tsx";
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ function useExperimentLogic() {
|
|||||||
setGoalIndex(0);
|
setGoalIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (data.type === 'goal_update') {
|
else if (data.type === 'goal_update') {
|
||||||
const payload = data as GoalUpdate;
|
const payload = data as GoalUpdate;
|
||||||
const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]) as GoalNode[];
|
const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]) as GoalNode[];
|
||||||
@@ -97,7 +98,7 @@ function useExperimentLogic() {
|
|||||||
return nextState;
|
return nextState;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (data.type === 'trigger_update') {
|
else if (data.type === 'trigger_update') {
|
||||||
const payload = data as TriggerUpdate;
|
const payload = data as TriggerUpdate;
|
||||||
setActiveIds((prev) => ({ ...prev, [payload.id]: payload.achieved }));
|
setActiveIds((prev) => ({ ...prev, [payload.id]: payload.achieved }));
|
||||||
@@ -111,7 +112,7 @@ function useExperimentLogic() {
|
|||||||
setActiveIds((prev) => {
|
setActiveIds((prev) => {
|
||||||
const hasChanges = payload.norms.some((u) => prev[u.id] !== u.active);
|
const hasChanges = payload.norms.some((u) => prev[u.id] !== u.active);
|
||||||
if (!hasChanges) return prev;
|
if (!hasChanges) return prev;
|
||||||
|
|
||||||
const nextState = { ...prev };
|
const nextState = { ...prev };
|
||||||
payload.norms.forEach((u) => { nextState[u.id] = u.active; });
|
payload.norms.forEach((u) => { nextState[u.id] = u.active; });
|
||||||
return nextState;
|
return nextState;
|
||||||
@@ -144,7 +145,7 @@ function useExperimentLogic() {
|
|||||||
}
|
}
|
||||||
}, [setProgramState]);
|
}, [setProgramState]);
|
||||||
|
|
||||||
const handleControlAction = async (action: "pause" | "play" | "nextPhase") => {
|
const handleControlAction = async (action: "pause" | "play" | "nextPhase" | "stop") => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@@ -159,6 +160,9 @@ function useExperimentLogic() {
|
|||||||
case "nextPhase":
|
case "nextPhase":
|
||||||
await nextPhase();
|
await nextPhase();
|
||||||
break;
|
break;
|
||||||
|
case "stop":
|
||||||
|
await stopExperiment();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -189,14 +193,14 @@ function useExperimentLogic() {
|
|||||||
/**
|
/**
|
||||||
* Visual indicator of progress through experiment phases.
|
* Visual indicator of progress through experiment phases.
|
||||||
*/
|
*/
|
||||||
function PhaseProgressBar({
|
function PhaseProgressBar({
|
||||||
phaseIds,
|
phaseIds,
|
||||||
phaseIndex,
|
phaseIndex,
|
||||||
isFinished
|
isFinished
|
||||||
}: {
|
}: {
|
||||||
phaseIds: string[],
|
phaseIds: string[],
|
||||||
phaseIndex: number,
|
phaseIndex: number,
|
||||||
isFinished: boolean
|
isFinished: boolean
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.phaseProgress}>
|
<div className={styles.phaseProgress}>
|
||||||
@@ -218,16 +222,16 @@ function PhaseProgressBar({
|
|||||||
/**
|
/**
|
||||||
* Main control buttons (Play, Pause, Next, Reset).
|
* Main control buttons (Play, Pause, Next, Reset).
|
||||||
*/
|
*/
|
||||||
function ControlPanel({
|
function ControlPanel({
|
||||||
loading,
|
loading,
|
||||||
isPlaying,
|
isPlaying,
|
||||||
onAction,
|
onAction,
|
||||||
onReset
|
onReset
|
||||||
}: {
|
}: {
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
isPlaying: boolean,
|
isPlaying: boolean,
|
||||||
onAction: (a: "pause" | "play" | "nextPhase") => void,
|
onAction: (a: "pause" | "play" | "nextPhase" | "stop") => void,
|
||||||
onReset: () => void
|
onReset: () => void
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.experimentControls}>
|
<div className={styles.experimentControls}>
|
||||||
@@ -245,17 +249,23 @@ function ControlPanel({
|
|||||||
disabled={loading}
|
disabled={loading}
|
||||||
>▶</button>
|
>▶</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={styles.next}
|
className={styles.next}
|
||||||
onClick={() => onAction("nextPhase")}
|
onClick={() => onAction("nextPhase")}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>⏭</button>
|
>⏭</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={styles.restartExperiment}
|
className={styles.restartExperiment}
|
||||||
onClick={onReset}
|
onClick={onReset}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>⟲</button>
|
>⟲</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className={styles.stop}
|
||||||
|
onClick={() => onAction("stop")}
|
||||||
|
disabled={loading}
|
||||||
|
>⏹</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -353,11 +363,11 @@ const MonitoringPage: React.FC = () => {
|
|||||||
<PhaseProgressBar phaseIds={phaseIds} phaseIndex={phaseIndex} isFinished={isFinished} />
|
<PhaseProgressBar phaseIds={phaseIds} phaseIndex={phaseIndex} isFinished={isFinished} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ControlPanel
|
<ControlPanel
|
||||||
loading={loading}
|
loading={loading}
|
||||||
isPlaying={isPlaying}
|
isPlaying={isPlaying}
|
||||||
onAction={handleControlAction}
|
onAction={handleControlAction}
|
||||||
onReset={resetExperiment}
|
onReset={resetExperiment}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.connectionStatus}>
|
<div className={styles.connectionStatus}>
|
||||||
@@ -370,17 +380,17 @@ const MonitoringPage: React.FC = () => {
|
|||||||
<section className={styles.phaseOverviewText}>
|
<section className={styles.phaseOverviewText}>
|
||||||
<h3>Phase Overview</h3>
|
<h3>Phase Overview</h3>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{isFinished ? (
|
{isFinished ? (
|
||||||
<div className={styles.finishedMessage}>
|
<div className={styles.finishedMessage}>
|
||||||
<p>All phases have been successfully completed.</p>
|
<p>All phases have been successfully completed.</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<PhaseDashboard
|
<PhaseDashboard
|
||||||
phaseId={phaseIds[phaseIndex]}
|
phaseId={phaseIds[phaseIndex]}
|
||||||
activeIds={activeIds}
|
activeIds={activeIds}
|
||||||
setActiveIds={setActiveIds}
|
setActiveIds={setActiveIds}
|
||||||
goalIndex={goalIndex}
|
goalIndex={goalIndex}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
@@ -398,4 +408,4 @@ const MonitoringPage: React.FC = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MonitoringPage;
|
export default MonitoringPage;
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ export async function nextPhase(): Promise<void> {
|
|||||||
sendAPICall(type, context)
|
sendAPICall(type, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function stopExperiment(): Promise<void> {
|
||||||
|
const type = "stop"
|
||||||
|
const context = ""
|
||||||
|
sendAPICall(type, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an API call to the CB for going to pause experiment
|
* Sends an API call to the CB for going to pause experiment
|
||||||
@@ -95,14 +101,14 @@ export function useExperimentLogger(onUpdate?: (data: ExperimentStreamData) => v
|
|||||||
console.log("Closing Experiment Stream...");
|
console.log("Closing Experiment Stream...");
|
||||||
eventSource.close();
|
eventSource.close();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hook that listens to the status stream that updates active conditional norms
|
* A hook that listens to the status stream that updates active conditional norms
|
||||||
* via updates sent from the backend
|
* via updates sent from the backend
|
||||||
*/
|
*/
|
||||||
export function useStatusLogger(onUpdate?: (data: ExperimentStreamData) => void) {
|
export function useStatusLogger(onUpdate?: (data: ExperimentStreamData) => void) {
|
||||||
const callbackRef = React.useRef(onUpdate);
|
const callbackRef = React.useRef(onUpdate);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user