Skip to content

Commit

Permalink
feat: base for interactive activity
Browse files Browse the repository at this point in the history
  • Loading branch information
alberto-abarzua committed Nov 20, 2023
1 parent 64e7a33 commit 0e8afb0
Show file tree
Hide file tree
Showing 17 changed files with 743 additions and 84 deletions.
75 changes: 75 additions & 0 deletions ;
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { createSlice } from '@reduxjs/toolkit';
import { loadState } from '@/utils/state';

const Steps = {
HOME_ARM: 'HOME_ARM',
MOVE_JOINT_3: 'MOVE_JOINT_3',
ADD_MOVE_TO_ACTION_LIST: 'ADD_MOVE_TO_ACTION_LIST',
};

const evaluateStepMap = {
[Steps.HOME_ARM]: state => {
// The state passed holds all the store state
const armpose = state.armPose;
if (armpose === null) {
return false;
}
return armpose.isHomed;
},
[Steps.MOVE_JOINT_3]: state => {
const armPose = state.armPose;
},
[Steps.ADD_MOVE_TO_ACTION_LIST]: state => {
// The state passed holds all the store state
return true;
},
};

const initialState = {
steps: [
{
name: 'Home the arm',
id: 0,
description: 'Home the arm',
completion: {
done: false,
timestamp: null,
},
},
{
name: 'Move joint 3',
id: 1,
description: 'Go to the control panel and move joint 3',
completion: {
done: false,
timestamp: null,
},
},
{
name: 'Add Move to action list',
id: 2,
description: 'Add the move to the action list',
completion: {
done: false,
timestamp: null,
},
},
],
};

const loadedState = loadState()?.activity;

if (loadedState && loadedState.steps) {
initialState.steps = loadedState.steps;
}
const ActivitySlice = createSlice({
name: 'activity',
initialState,
reducers: {},
});

export const currentStepSelector = state =>
state.activity.steps?.find(step => !step.completion.done);

export const activityActions = ActivitySlice.actions;
export default ActivitySlice.reducer;
25 changes: 25 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-progress": "^1.0.3",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
Expand Down
9 changes: 0 additions & 9 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,35 @@ function App() {
const [denied, setDenied] = useState(true);

useEffect(() => {
console.log('useEffect triggered');
if (isMobileDevice()) {
setDenied(true);
setLoading(false);
return;
}

const getBackendInfo = async () => {
console.log('getBackendInfo function called');
let envBackendUrl = import.meta.env.VITE_BACKEND_URL;
console.log('VITE_BACKEND_URL:', envBackendUrl);
window.localStorage.removeItem('backendUrl');

if (envBackendUrl === undefined || envBackendUrl === 'no_backend') {
console.log('Fetching backend URL from API');
const access_token = searchParams.get('access_token');
try {
const response = await instanciatorApi.get('/backend_url/', {
params: { token: access_token },
});
console.log('Response from API:', response);
const { backend_port } = response.data;

const backend_url = `${import.meta.env.VITE_INSTANCIATOR_URL}/s${backend_port}`;
window.localStorage.setItem('backendUrl', backend_url);
console.log('Backend URL saved to local storage from API:', backend_url);
if (backend_port === undefined) {
console.log('Backend port is undefined');
setDenied(true);
}
setDenied(false);
} catch (error) {
console.log('Error fetching backend URL from API');
setDenied(true);
console.log(error);
}
} else {
console.log('Saving env variable to local storage:', envBackendUrl);
window.localStorage.setItem('backendUrl', envBackendUrl);
setDenied(false);
}
Expand Down
3 changes: 0 additions & 3 deletions frontend/src/components/actions/ActionsPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const ActionPanel = () => {

const [running, setRunning] = useState(false);
const runningRef = useRef(false);
console.log(loop);

useEffect(() => {
runningRef.current = running;
Expand All @@ -60,7 +59,6 @@ const ActionPanel = () => {
}

if (loop) {
console.log('looping');
await runActions();
}
setRunning(false);
Expand All @@ -75,7 +73,6 @@ const ActionPanel = () => {
};

const playSelectValueChange = value => {
console.log(value);
if (value === 'loop') {
setLoop(true);
}
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/components/armsimulation/ArmSimulation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ const ArmSimulation = () => {
}, [websocketPort, websocketHost, simulationUrl, websocketProtocol]);

const srcUrl = `${simulationUrl}/game.html?ip=${websocketHost}&port=${websocketPort}&protocol=${websocketProtocol}`;
console.log(srcUrl);

return (
<div className="relative h-full w-full">
{valid ? (
Expand Down
69 changes: 69 additions & 0 deletions frontend/src/components/general/tutorial/ActivityBox.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Button } from '@/components/ui/button';
import { Progress } from '@/components/ui/progress';
import { currentStepSelector } from '@/redux/ActivitySlice';
import { activityActions } from '@/redux/ActivitySlice';
import QuizIcon from '@mui/icons-material/Quiz';
import { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

const ActivityBox = () => {
const [isVisible, setIsVisible] = useState(false);
const dispatch = useDispatch();
const steps = useSelector(state => state.activity.steps);
const currentStep = useSelector(currentStepSelector);

const numSteps = steps.length;
let num_done = 0;
for (let step of steps) {
if (step.completion.done) {
num_done++;
} else {
break;
}
}
const completion = Math.round((num_done / numSteps) * 100);
console.log(steps);

useEffect(() => {
const timer = setTimeout(() => {
setIsVisible(true);
}, 4000);

return () => clearTimeout(timer);
}, []);

const clearActivity = () => {
dispatch(activityActions.clearActivity());
};

return (
<div
className={`absolute left-1/2 top-2 z-20 flex w-1/4 transform flex-col justify-center rounded-md border border-gray-700 bg-purple-700 bg-opacity-90 p-4 text-white transition-all duration-500 ${
isVisible ? 'translate-y-0 opacity-100' : '-translate-y-full opacity-0'
}`}
>
<div className="mb-2 flex items-center gap-x-2">
<QuizIcon className="animate-bounce" />
<p className="whitespace-nowrap text-lg">Arm Activity!</p>
<Progress value={completion} />
<div role="button" onClick={clearActivity}>
&#10005;
</div>
</div>
{currentStep ? (
<div className="flex flex-col gap-x-2">
<p className="text-lg">Your current step is:</p>

<div className="rounded bg-slate-50 px-3 py-1 text-gray-800 shadow-sm shadow-white">
<p className="text-xl">{currentStep.name}</p>
<p className="text-sm text-gray-600">{currentStep.description}</p>
</div>
</div>
) : (
<div>Activity Completed!</div>
)}
</div>
);
};

export default ActivityBox;
18 changes: 18 additions & 0 deletions frontend/src/components/ui/progress.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"

import { cn } from "@/lib/utils"

const Progress = React.forwardRef(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn("relative h-4 w-full overflow-hidden rounded-full bg-secondary", className)}
{...props}>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }} />
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName

export { Progress }
25 changes: 15 additions & 10 deletions frontend/src/redux/ActionListSlice.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { ActionTypes } from '@/utils/actions';
import { loadState } from '@/utils/state';
import { createSlice } from '@reduxjs/toolkit';

const initialState = {
actions: [], // array actions
byId: {}, // hash table with all actions by id
};

// Action
// {
// id,
// value,
// type,
// parentId,
// valid,
// running,
// name,
// }
const loadedState = loadState()?.actionList;

if (loadedState) {
console.log('loadedState', loadedState);
if (loadedState.actions) {
initialState.actions = loadedState.actions;
}
if (loadedState.byId) {
initialState.byId = loadedState.byId;
}
}

const getParentList = (state, action) => {
const { parentId } = action;
Expand Down Expand Up @@ -157,6 +159,9 @@ const actionListSlice = createSlice({
setRunningStatus: (state, action) => {
const { actionId, running } = action.payload;
state.byId[actionId].running = running;
if (running) {
state.byId[actionId].lastRun = Date.now();
}
},

setActionValue: (state, action) => {
Expand Down
Loading

0 comments on commit 0e8afb0

Please sign in to comment.