Skip to content

Commit 5b46699

Browse files
extract API address
1 parent c5a2c45 commit 5b46699

File tree

4 files changed

+90
-38
lines changed

4 files changed

+90
-38
lines changed

ui/src/App.js

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import React, { useState, useEffect } from 'react';
2+
import './App.css';
23
import { Container, Row, Col, Form, Button } from 'react-bootstrap';
3-
import { CWaterPumpAPI } from './api/CWaterPumpAPI.js';
4+
5+
import { useWaterPumpAPI } from './contexts/WaterPumpAPIContext';
46
import { useNotificationsSystem } from './contexts/NotificationsContext.js';
5-
import './App.css';
67
import NotificationsArea from './components/NotificationsArea.js';
8+
import APIAddressField from './components/APIAddressField';
79

8-
const STORE_API = 'apiAddress';
910
const STORE_RUNTIME = 'runTime';
1011

1112
function App() {
12-
const [apiAddress, setApiAddress] = useState('');
13+
const waterPumpCtx = useWaterPumpAPI();
1314
const [runTime, setRunTime] = useState(1000);
1415
const NotificationsSystem = useNotificationsSystem();
1516

1617
useEffect(() => {
17-
const storedApiAddress = localStorage.getItem(STORE_API);
18-
if (storedApiAddress) setApiAddress(storedApiAddress);
19-
2018
let storedRunTime = localStorage.getItem(STORE_RUNTIME);
2119
if (storedRunTime) {
2220
if (typeof storedRunTime === 'string') {
@@ -25,18 +23,16 @@ function App() {
2523
setRunTime(storedRunTime);
2624
}
2725
}, []);
28-
29-
const waterPumpAPI = React.useMemo(() => {
30-
let url = apiAddress;
31-
if (!url.startsWith('http://') && !url.startsWith('https://')) {
32-
url = 'http://' + url;
33-
}
34-
return new CWaterPumpAPI({ URL: url });
35-
}, [apiAddress]);
26+
27+
const handleRunTimeChange = (event) => {
28+
const runTime = parseInt(event.target.value, 10);
29+
setRunTime(runTime);
30+
localStorage.setItem(STORE_RUNTIME, runTime);
31+
};
3632

3733
const handleStart = async () => {
3834
try {
39-
await waterPumpAPI.start(runTime);
35+
await waterPumpCtx.API.start(runTime);
4036
NotificationsSystem.alert('Water pump started successfully!');
4137
} catch (error) {
4238
NotificationsSystem.alert('Error starting water pump: ' + error.message);
@@ -45,38 +41,19 @@ function App() {
4541

4642
const handleStop = async () => {
4743
try {
48-
await waterPumpAPI.stop();
44+
await waterPumpCtx.API.stop();
4945
NotificationsSystem.alert('Water pump stopped successfully!');
5046
} catch (error) {
5147
NotificationsSystem.alert('Error stopping water pump: ' + error.message);
5248
}
5349
};
5450

55-
const handleRunTimeChange = (event) => {
56-
const runTime = parseInt(event.target.value, 10);
57-
setRunTime(runTime);
58-
localStorage.setItem(STORE_RUNTIME, runTime);
59-
};
60-
61-
const handleApiAddressChange = (event) => {
62-
const apiAddress = event.target.value;
63-
setApiAddress(apiAddress);
64-
localStorage.setItem(STORE_API, apiAddress);
65-
};
66-
6751
return (
6852
<Container className="App">
6953
<h1>Tea System UI</h1>
7054
<NotificationsArea />
7155
<Form>
72-
<Form.Group as={Row} className="mb-3">
73-
<Form.Label column sm="2">
74-
API Address:
75-
</Form.Label>
76-
<Col sm="10">
77-
<Form.Control type="text" value={apiAddress} onChange={handleApiAddressChange} />
78-
</Col>
79-
</Form.Group>
56+
<APIAddressField />
8057
<Form.Group as={Row} className="mb-3">
8158
<Form.Label column sm="2">
8259
Run Time (ms):

ui/src/components/APIAddressField.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
import { Row, Col, Form } from 'react-bootstrap';
3+
import { useWaterPumpAPI } from '../contexts/WaterPumpAPIContext';
4+
5+
function APIAddressField() {
6+
const waterPumpCtx = useWaterPumpAPI();
7+
8+
const handleApiAddressChange = (event) => {
9+
const apiAddress = event.target.value;
10+
waterPumpCtx.bindApiHost(apiAddress);
11+
};
12+
13+
return (
14+
<Form.Group as={Row} className="mb-3">
15+
<Form.Label column sm="2">
16+
API Address:
17+
</Form.Label>
18+
<Col sm="10">
19+
<Form.Control type="text" value={waterPumpCtx.apiHost} onChange={handleApiAddressChange} />
20+
</Col>
21+
</Form.Group>
22+
);
23+
}
24+
25+
export default APIAddressField;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import { CWaterPumpAPI } from '../api/CWaterPumpAPI.js';
3+
4+
const STORE_API = 'apiAddress';
5+
const WaterPumpAPIContext = React.createContext();
6+
7+
export function useWaterPumpAPI() {
8+
return React.useContext(WaterPumpAPIContext);
9+
}
10+
11+
function preprocessApiHost(apiHost) {
12+
let url = apiHost;
13+
if (!url.startsWith('http://') && !url.startsWith('https://')) {
14+
url = 'http://' + url;
15+
}
16+
if (!url.endsWith('/')) url += '/';
17+
return url;
18+
}
19+
20+
export function WaterPumpAPIProvider({ children }) {
21+
const [apiHost, setApiHost] = React.useState('');
22+
React.useEffect(() => {
23+
const storedApiHost = localStorage.getItem(STORE_API);
24+
if (storedApiHost) setApiHost(storedApiHost);
25+
}, []); // on mount only
26+
27+
const apiObject = React.useMemo(() => {
28+
if (!apiHost) return null; // not ready yet
29+
30+
const url = preprocessApiHost(apiHost);
31+
localStorage.setItem(STORE_API, url);
32+
return new CWaterPumpAPI({ URL: url });
33+
}, [apiHost]
34+
);
35+
36+
const value = {
37+
API: apiObject,
38+
apiHost: apiHost,
39+
bindApiHost: setApiHost,
40+
};
41+
42+
return (
43+
<WaterPumpAPIContext.Provider value={value}>
44+
{children}
45+
</WaterPumpAPIContext.Provider>
46+
);
47+
}

ui/src/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import App from './App.js';
44
import 'bootstrap/dist/css/bootstrap.min.css'; // Importing Bootstrap CSS
55

66
import { NotificationsProvider } from './contexts/NotificationsContext.js';
7+
import { WaterPumpAPIProvider } from './contexts/WaterPumpAPIContext.js';
78

89
ReactDOM.render(
910
<React.StrictMode>
1011
<NotificationsProvider>
11-
<App />
12+
<WaterPumpAPIProvider>
13+
<App />
14+
</WaterPumpAPIProvider>
1215
</NotificationsProvider>
1316
</React.StrictMode>,
1417
document.getElementById('root')

0 commit comments

Comments
 (0)