Skip to content

Commit

Permalink
move SystemStatus to Redux store
Browse files Browse the repository at this point in the history
  • Loading branch information
GreenWizard2015 committed Jan 3, 2024
1 parent 835ffd4 commit 2b66c7b
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 22 deletions.
91 changes: 91 additions & 0 deletions ui/package-lock.json

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

2 changes: 2 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^2.0.1",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand All @@ -11,6 +12,7 @@
"react": "^18.2.0",
"react-bootstrap": "^2.9.2",
"react-dom": "^18.2.0",
"react-redux": "^9.0.4",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
Expand Down
19 changes: 4 additions & 15 deletions ui/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,15 @@ import PourTimeField from './components/PourTimeField';
import SystemControls from './components/SystemControls';
import SystemStatusArea from './components/SystemStatusArea';

// TODO: Replace this with a real system status
// replace "water threshold" with "waterThreshold"
// replace "time left" with "timeLeft"
// add field "updated"
const systemStatus = {
waterThreshold: 1234,
pump: {
running: false,
timeLeft: 0,
},
updated: new Date(),
};

function App() {
// TODO: Move this to a redux store
const [pourTime, setPourTime] = useState(1000);
// TODO: Add a fake countdown timer of timeLeft
const systemStatus = null; // TODO: Remove usage of this variable and use redux store instead
return (
<Container className="App">
<h1>Tea System UI</h1>
<SystemStatusArea status={systemStatus} />
<SystemStatusArea />

<Form>
<APIAddressField />
Expand All @@ -45,4 +34,4 @@ function App() {
);
}

export default App;
export default App;
9 changes: 7 additions & 2 deletions ui/src/components/SystemStatusArea.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Card } from 'react-bootstrap';
import { connect } from 'react-redux';

// TODO: Update time since last update every second,
// currently it only updates when the status changes
Expand All @@ -22,7 +23,7 @@ function _systemStatus(status) {
);
}

function SystemStatusArea({ status }) {
export function SystemStatusAreaComponent({ status }) {
return (
<Card>
<Card.Body>
Expand All @@ -35,4 +36,8 @@ function SystemStatusArea({ status }) {
);
}

export default SystemStatusArea;
export default connect(
state => ({
status: state.systemStatus
}), []
)(SystemStatusAreaComponent);
14 changes: 9 additions & 5 deletions ui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import 'bootstrap/dist/css/bootstrap.min.css'; // Importing Bootstrap CSS

import { NotificationsProvider } from './contexts/NotificationsContext.js';
import { WaterPumpAPIProvider } from './contexts/WaterPumpAPIContext.js';
// Redux store
import { AppStore } from './store';

import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<NotificationsProvider>
<WaterPumpAPIProvider>
<App />
</WaterPumpAPIProvider>
</NotificationsProvider>
<AppStore>
<NotificationsProvider>
<WaterPumpAPIProvider>
<App />
</WaterPumpAPIProvider>
</NotificationsProvider>
</AppStore>
</React.StrictMode>
);
52 changes: 52 additions & 0 deletions ui/src/store/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { configureStore } from "@reduxjs/toolkit";
import { Provider } from "react-redux";

// slices
import { ALL_APP_SLICES } from "./slices";

// listeners
// import { eventsListener } from "./listeners";

function buildAppStore(preloadedState) {
const slices = ALL_APP_SLICES;
const reducers = {};
const state = {};
Object.keys(slices).forEach(key => {
reducers[key] = slices[key].reducer;
const defaultState = slices[key].getInitialState();
state[key] = defaultState;

if (key in preloadedState) {
// if default state is an object, merge it with the preloaded state
if (typeof defaultState === 'object') {
const preloadedStateForKey = preloadedState[key] || {};
state[key] = { ...defaultState, ...preloadedStateForKey };
} else { // otherwise, just use the preloaded state
state[key] = preloadedState[key];
}
}
});

return { reducers, state };
}

// AppStore is a wrapper component that provides the Redux store to the rest of the application.
// preloadedState is an optional parameter that allows you to pass in an initial state for the store.
const AppStore = ({ children, preloadedState = {}, returnStore = false }) => {
const { reducers, state } = buildAppStore(preloadedState);
const store = configureStore({
reducer: reducers,
preloadedState: state,
// middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(eventsListener.middleware),
});
const provider = (
<Provider store={store}>
{children}
</Provider>
);

if (returnStore) return { store, provider };
return provider;
};

export { AppStore };
28 changes: 28 additions & 0 deletions ui/src/store/slices/SystemStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { createSlice } from '@reduxjs/toolkit';

// TODO: Replace this with a real system status
// replace "water threshold" with "waterThreshold"
// replace "time left" with "timeLeft"
// add field "updated"
const systemStatus = {
waterThreshold: 1234,
pump: {
running: false,
timeLeft: 0,
},
updated: new Date(),
};

// slice for system status
export const SystemStatusSlice = createSlice({
name: 'systemStatus',
initialState: systemStatus,
reducers: {
updateSystemStatus(state, action) {
return action.payload;
},
},
});

export const actions = SystemStatusSlice.actions;
export const { updateSystemStatus } = actions;
8 changes: 8 additions & 0 deletions ui/src/store/slices/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SystemStatusSlice } from "./SystemStatus";

const slices = [ SystemStatusSlice ];
// export all slices as an object { [sliceName]: slice }
export const ALL_APP_SLICES = slices.reduce((acc, slice) => {
acc[slice.name] = slice;
return acc;
}, {});

0 comments on commit 2b66c7b

Please sign in to comment.