Stian Aune
5 years ago
8 changed files with 357 additions and 0 deletions
-
3webui/src/App.js
-
53webui/src/Components/Bridge.jsx
-
23webui/src/Components/BridgeLight.jsx
-
25webui/src/Components/Bridges.jsx
-
94webui/src/Components/Modals/BridgeModal.jsx
-
18webui/src/Components/Pages/AdminPage.jsx
-
99webui/src/Hooks/bridge.js
-
42webui/src/Hooks/lights.js
@ -0,0 +1,53 @@ |
|||
import React, {useState} from "react"; |
|||
import {Button, Card, CardBody, CardFooter, CardHeader} from "reactstrap"; |
|||
import useBridges from "../Hooks/bridge"; |
|||
import BridgeModal from "./Modals/BridgeModal"; |
|||
import useLights from "../Hooks/lights"; |
|||
import Loading from "./Loading"; |
|||
import BridgeLight from "./BridgeLight"; |
|||
|
|||
function Bridge({addr, driver, id, name}) { |
|||
const {forgetBridge, discoverLights} = useBridges(); |
|||
const {lightsByBridge} = useLights(); |
|||
const [modal, setModal] = useState(false); |
|||
|
|||
function edit() { |
|||
setModal(true); |
|||
} |
|||
|
|||
function unEdit() { |
|||
setModal(false); |
|||
} |
|||
|
|||
function forget() { |
|||
if (window.confirm(`Vil du virkelig glemme bruen "${name}"?`)) { |
|||
forgetBridge(id); |
|||
} |
|||
} |
|||
|
|||
function discover() { |
|||
discoverLights(id); |
|||
} |
|||
|
|||
const lights = lightsByBridge(id); |
|||
const hasLights = lights !== null; |
|||
|
|||
return ( |
|||
<Card className="mt-3"> |
|||
<CardHeader>{name} ({driver}, {addr})</CardHeader> |
|||
<CardBody> |
|||
{hasLights ? lights.map(l => <BridgeLight key={l.id} {...l} />) : <Loading/>} |
|||
</CardBody> |
|||
<CardFooter> |
|||
<Button color="info" onClick={discover}>Oppdag lys</Button> |
|||
{" "} |
|||
<Button color="secondary" onClick={edit}>Endre</Button> |
|||
{" "} |
|||
<Button color="danger" onClick={forget}>Glem</Button> |
|||
</CardFooter> |
|||
{modal && <BridgeModal bridge={{addr, driver, id, name}} onCancel={unEdit} />} |
|||
</Card> |
|||
); |
|||
} |
|||
|
|||
export default Bridge; |
@ -0,0 +1,23 @@ |
|||
import React, {useState} from "react"; |
|||
import {Button, FormGroup} from "reactstrap"; |
|||
import useBridges from "../Hooks/bridge"; |
|||
|
|||
function BridgeLight({ id, bridgeId, name }) { |
|||
const [waiting, setWaiting] = useState(false); |
|||
const {forgetLight} = useBridges(); |
|||
|
|||
function forget() { |
|||
setWaiting(true); |
|||
forgetLight(bridgeId, id); |
|||
} |
|||
|
|||
return ( |
|||
<FormGroup> |
|||
<Button color="danger" size="sm" disabled={waiting} onClick={forget}>Glem</Button> |
|||
{" "} |
|||
{name} |
|||
</FormGroup> |
|||
); |
|||
} |
|||
|
|||
export default BridgeLight; |
@ -0,0 +1,25 @@ |
|||
import React, {useState} from "react"; |
|||
import useBridges from "../Hooks/bridge"; |
|||
import Bridge from "./Bridge"; |
|||
import {Button, FormGroup} from "reactstrap"; |
|||
import BridgeModal from "./Modals/BridgeModal"; |
|||
|
|||
function Bridges() { |
|||
const [modal, setModal] = useState(false); |
|||
const {bridges} = useBridges(); |
|||
if (bridges === null) { |
|||
return <></>; |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
{bridges.map(bridge => <Bridge key={bridge.id} {...bridge} />)} |
|||
<FormGroup className="free-buttons"> |
|||
<Button color="success" onClick={() => setModal(true)} >Søk etter bru</Button> |
|||
</FormGroup> |
|||
{modal && <BridgeModal onCancel={() => setModal(false)}/> } |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default Bridges; |
@ -0,0 +1,94 @@ |
|||
import React, {useState} from "react"; |
|||
import {Button, Col, Form, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap"; |
|||
import useBridges from "../../Hooks/bridge"; |
|||
import Loading from "../Loading"; |
|||
|
|||
function BridgeModal({onCancel, bridge = null}) { |
|||
const {addBridge, editBridge} = useBridges(); |
|||
|
|||
const edit = bridge !== null; |
|||
|
|||
const [name, setName] = useState(edit ? bridge.name : ""); |
|||
const [driver, setDriver] = useState(edit ? bridge.driver : ""); |
|||
const [addr, setAddr] = useState(edit ? bridge.addr : ""); |
|||
|
|||
const [waiting, setWaiting] = useState(false); |
|||
|
|||
function onConfirm() { |
|||
if (edit) { |
|||
editBridge(bridge.id, name); |
|||
} else { |
|||
setWaiting(true); |
|||
addBridge(name, driver, addr, (result) => { |
|||
if (!result) { |
|||
alert("Noe gikk galt"); |
|||
} |
|||
|
|||
setWaiting(false); |
|||
onCancel(); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<Modal isOpen={true}> |
|||
<ModalHeader>{edit ? "Bruegenskaper" : "Ny bru"}</ModalHeader> |
|||
<ModalBody> |
|||
{waiting ? ( |
|||
<Loading/> |
|||
) : ( |
|||
<Form> |
|||
<FormGroup row> |
|||
<Label sm={3} for="text-name"> |
|||
Navn: |
|||
</Label> |
|||
<Col sm={9}> |
|||
<Input type="text" |
|||
id="text-name" |
|||
name="name" |
|||
value={name} |
|||
onChange={e => setName(e.target.value)} |
|||
/> |
|||
</Col> |
|||
</FormGroup> |
|||
<FormGroup row> |
|||
<Label sm={3} for="text-driver"> |
|||
Driver: |
|||
</Label> |
|||
<Col sm={9}> |
|||
<Input type="text" |
|||
id="text-driver" |
|||
name="driver" |
|||
value={driver} |
|||
onChange={e => setDriver(e.target.value)} |
|||
disabled={edit} |
|||
/> |
|||
</Col> |
|||
</FormGroup> |
|||
<FormGroup row> |
|||
<Label sm={3} for="text-name"> |
|||
Adresse: |
|||
</Label> |
|||
<Col sm={9}> |
|||
<Input type="text" |
|||
id="text-addr" |
|||
name="addr" |
|||
value={addr} |
|||
onChange={e => setAddr(e.target.value)} |
|||
disabled={edit} |
|||
/> |
|||
</Col> |
|||
</FormGroup> |
|||
</Form> |
|||
)} |
|||
</ModalBody> |
|||
<ModalFooter> |
|||
<Button color="primary" disabled={waiting} onClick={onConfirm}>Bekreft</Button> |
|||
{" "} |
|||
<Button color="secondary" disabled={waiting} onClick={onCancel}>Avbryt</Button> |
|||
</ModalFooter> |
|||
</Modal> |
|||
); |
|||
} |
|||
|
|||
export default BridgeModal; |
@ -0,0 +1,18 @@ |
|||
import React from "react"; |
|||
import Bridges from "../Bridges"; |
|||
import useAuth from "../../Hooks/auth"; |
|||
|
|||
function AdminPage() { |
|||
const {user} = useAuth(); |
|||
if (user.name === "Admin") { |
|||
return <></>; |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<Bridges/> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default AdminPage; |
@ -0,0 +1,99 @@ |
|||
import {setGlobal, useGlobal} from "reactn"; |
|||
import {useEffect} from "react"; |
|||
import {fetchDelete, fetchGet, fetchPatch, fetchPost} from "../Helpers/fetcher"; |
|||
import useLights from "./lights"; |
|||
|
|||
setGlobal({ |
|||
bridges: null, |
|||
}); |
|||
|
|||
function useBridges() { |
|||
const [bridges, setBridges] = useGlobal("bridges"); |
|||
const {reloadLights} = useLights(); |
|||
|
|||
function reloadBridges() { |
|||
setBridges(null); |
|||
|
|||
fetchGet("/bridge/").then(({error, data}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
return; |
|||
} |
|||
|
|||
setBridges(data); |
|||
}); |
|||
} |
|||
|
|||
useEffect(() => { |
|||
if (bridges === null) { |
|||
reloadBridges(); |
|||
} |
|||
}, []); |
|||
|
|||
function bridge(id) { |
|||
if (bridges === null) { |
|||
return null; |
|||
} |
|||
|
|||
return bridges.find(b => b.id === id); |
|||
} |
|||
|
|||
function forgetBridge(id) { |
|||
fetchDelete(`/bridge/${id}`).then(({data, error}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
} |
|||
|
|||
reloadBridges(); |
|||
}); |
|||
} |
|||
|
|||
function forgetLight(bridgeId, lightId) { |
|||
fetchDelete(`/bridge/${bridgeId}/light/${lightId}`).then(({data, error}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
} |
|||
|
|||
reloadBridges(); |
|||
}); |
|||
} |
|||
|
|||
function addBridge(name, driver, addr, callback = null) { |
|||
fetchPost("/bridge/", {name, driver, addr}).then(({error}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
} |
|||
|
|||
if (callback !== null) { |
|||
callback(error === null); |
|||
} |
|||
|
|||
reloadBridges(); |
|||
}); |
|||
} |
|||
|
|||
function editBridge(id, name) { |
|||
fetchPatch(`/bridge/${id}`, {name}).then(({error}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
} |
|||
|
|||
reloadBridges(); |
|||
}); |
|||
} |
|||
|
|||
function discoverLights(id) { |
|||
fetchPost(`/bridge/${id}/discover`).then(({error}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
} |
|||
|
|||
reloadLights(); |
|||
reloadBridges(); |
|||
}); |
|||
} |
|||
|
|||
return {bridges, bridge, forgetBridge, addBridge, editBridge, forgetLight, discoverLights}; |
|||
} |
|||
|
|||
export default useBridges; |
@ -0,0 +1,42 @@ |
|||
import {setGlobal, useGlobal} from "reactn"; |
|||
import {fetchGet} from "../Helpers/fetcher"; |
|||
import {useEffect} from "react"; |
|||
|
|||
setGlobal({ |
|||
lights: null, |
|||
}); |
|||
|
|||
function useLights() { |
|||
const [lights, setLights] = useGlobal("lights"); |
|||
|
|||
function reloadLights() { |
|||
setLights(null); |
|||
|
|||
fetchGet("/light/").then(({error, data}) => { |
|||
if (error !== null) { |
|||
console.error(error); |
|||
return; |
|||
} |
|||
|
|||
setLights(data); |
|||
}); |
|||
} |
|||
|
|||
useEffect(() => { |
|||
if (lights === null) { |
|||
reloadLights(); |
|||
} |
|||
}, []); |
|||
|
|||
function lightsByBridge(bridgeId) { |
|||
if (lights === null) { |
|||
return null; |
|||
} |
|||
|
|||
return lights.filter(light => light.bridgeId === bridgeId); |
|||
} |
|||
|
|||
return {lights, lightsByBridge, reloadLights}; |
|||
} |
|||
|
|||
export default useLights; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue