added front end basics

This commit is contained in:
Max 2020-07-05 14:10:26 +02:00
parent 49a0cb1366
commit 7bddf1f8de
14 changed files with 847 additions and 59 deletions

View File

@ -1,4 +0,0 @@
body {
padding: 10px;
font-family: sans-serif;
}

View File

@ -1,7 +1,11 @@
<head>
<title>smart_garden_server</title>
</head>
<!--
<script
src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
crossorigin>
</script>
-->
<body>
<div id="react-target"></div>
</body>
<div id="root"></div>
</body>

View File

@ -1,8 +1,9 @@
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import { App } from '/imports/ui/App';
import ReactDOM from 'react-dom';
import App from '../imports/ui/App';
import 'bootstrap/dist/css/bootstrap.min.css';
Meteor.startup(() => {
render(<App/>, document.getElementById('react-target'));
ReactDOM.render(<App />, document.getElementById('root'));
});

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

9
imports/ui/About.jsx Normal file
View File

@ -0,0 +1,9 @@
import React from 'react'
export default function About() {
return (
<div>
About
</div>
)
}

View File

@ -1,11 +1,36 @@
import React from 'react';
import { Hello } from './Hello.jsx';
import { Info } from './Info.jsx';
import React, { Suspense } from 'react'
import NavBar from './NavigationBar'
import Home from './Home'
import About from './About'
import Settings from './Settings'
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom'
export const App = () => (
<div>
<h1>Welcome to Meteor!</h1>
<Hello/>
<Info/>
</div>
);
function App() {
const exampleData = [
{ name: 'Timestamp A', temperature: 38, humidity: 66, light: 75, moisture: 21 },
{ name: 'Timestamp B', temperature: 37, humidity: 65, light: 65, moisture: 22 },
{ name: 'Timestamp C', temperature: 39, humidity: 62, light: 55, moisture: 22 },
{ name: 'Timestamp D', temperature: 40, humidity: 61, light: 85, moisture: 21 },
{ name: 'Timestamp E', temperature: 40, humidity: 60, light: 80, moisture: 21 }
];
return (
<>
<NavBar/>
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route path="/" exact>
<Home dummyData={exampleData}></Home>
</Route>
<Route path="/settings" component={Settings}></Route>
<Route path="/about" component={About}></Route>
</Switch>
</Suspense>
</Router>
</>
)
}
export default App;

View File

@ -1,16 +0,0 @@
import React, { useState } from 'react';
export const Hello = () => {
const [counter, setCounter] = useState(0);
const increment = () => {
setCounter(counter + 1);
};
return (
<div>
<button onClick={increment}>Click Me</button>
<p>You've pressed the button {counter} times.</p>
</div>
);
};

51
imports/ui/Home.jsx Normal file
View File

@ -0,0 +1,51 @@
import React, {useEffect, useState} from 'react' // useState to rerender the view each time something changed
import { LineChart, Line, CartesianGrid, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import SensorCardDeck from './SensorCardDeck'
export default function Home(props) {
var updateCardValues = () => {
var updatedValues = [
props.dummyData[props.dummyData.length - 1].temperature,
props.dummyData[props.dummyData.length - 1].humidity,
props.dummyData[props.dummyData.length - 1].light,
props.dummyData[props.dummyData.length - 1].moisture
];
return updatedValues;
}
// this data represents the sensor values, they should be initialized empty.. this is just for the simulation when it first renders
const [sensorCardValues, setSensorCardValues] = useState(updateCardValues);
const [dataHistory, setDataHistory] = useState(props.dummyData); // for init data
// runs when the app mounts
// if you give a prop to useEffect, it also runs each time this prop changes..
useEffect(() => {
console.log("data is changing, start rerender..")
setDataHistory(props.dummyData);
setSensorCardValues(updateCardValues);
}, [props.dummyData])
// render the data
// make sensorCarddeck responsive
return (
<>
<SensorCardDeck sensorCardValues={sensorCardValues}/>
<ResponsiveContainer width='100%' height={400}>
<LineChart data={dataHistory} margin={{ top: 60, right: 60, bottom: 30, left: 5 }}>
<Line type="monotone" dataKey="temperature" stroke="#10b5de" />
<Line type="monotone" dataKey="humidity" stroke="#ff6f00" />
<Line type="monotone" dataKey="light" stroke="#ffd500" />
<Line type="monotone" dataKey="moisture" stroke="#1c4399" />
<CartesianGrid stroke="#ccc" strokeDasharray="5 5"/>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
</LineChart>
</ResponsiveContainer>
</>
)
}

View File

@ -1,20 +0,0 @@
import React from 'react';
import { useTracker } from 'meteor/react-meteor-data';
import { LinksCollection } from '../api/links';
export const Info = () => {
const links = useTracker(() => {
return LinksCollection.find().fetch();
});
return (
<div>
<h2>Learn Meteor!</h2>
<ul>{links.map(
link => <li key={link._id}>
<a href={link.url} target="_blank">{link.title}</a>
</li>
)}</ul>
</div>
);
};

View File

@ -0,0 +1,34 @@
import React from 'react'
import { Navbar, Nav, NavDropdown } from 'react-bootstrap';
export default function NavigationBar() {
return (
<Navbar collapseOnSelect expand="lg" bg="light" variant="light">
<Navbar.Brand href="/">
<img
src="SmartGarden.svg"
width="30"
height="30"
className="d-inline-block align-top"
rounded="true"
alt="SmartGarden"
/>{' '}
SmartGarden
</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="/settings">Settings</Nav.Link>
<Nav.Link href="/about">About</Nav.Link>
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Navbar>
)
}

View File

@ -0,0 +1,33 @@
import React from 'react'
import { Card, CardDeck } from 'react-bootstrap';
export default function SensorCardDeck( {sensorCardValues} ) {
return (
<CardDeck>
<Card>
<Card.Body>
<Card.Title>Temperature</Card.Title>
<Card.Text>{sensorCardValues[0]} °C</Card.Text>
</Card.Body>
</Card>
<Card>
<Card.Body>
<Card.Title>Humidity</Card.Title>
<Card.Text>{sensorCardValues[1]} %</Card.Text>
</Card.Body>
</Card>
<Card>
<Card.Body>
<Card.Title>Light</Card.Title>
<Card.Text>{sensorCardValues[2]} H</Card.Text>
</Card.Body>
</Card>
<Card>
<Card.Body>
<Card.Title>Moisture</Card.Title>
<Card.Text>{sensorCardValues[3]} %</Card.Text>
</Card.Body>
</Card>
</CardDeck>
)
}

181
imports/ui/Settings.jsx Normal file
View File

@ -0,0 +1,181 @@
import React from 'react'
import { Button, Form, Container, Row, Col, Table } from 'react-bootstrap';
class Settings extends React.Component{
constructor(props){
super(props);
this.state = {
name: '',
type: '',
dirt: '',
plants: [],
types: ['Chile', 'Mint'], // hardcoded for now
dirts: ['Vegetable Soil', 'Potting Soil'], // hardcoded for now
updateId: -1,
btnName: 'submit'
}
}
componentDidMount(){
// fetch data from db here
}
render(){
return (
<>
<Container>
<Row className="justify-content-md-center">
<Col md="auto">
<h1>Settings</h1>
</Col>
</Row>
<Row className="justify-content-md-center">
<a>Configurate your plant here. Based on your settings the smart garden will automate your plant environment.</a>
</Row>
<br></br>
{
this.state.updateId >= 0 | this.state.plants.length === 0? // show the form only if we edit the plant or there is no plant set yet
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="exampleForm.ControlInput1">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
value={this.state.name}
autoFocus ref={(input) => {this.nameInput=(input)}}
placeholder="plant"
onChange={(e)=>this.setState({name:e.target.value})} />
</Form.Group>
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Label>Type</Form.Label>
<Form.Control
as="select"
type="text"
value={this.state.type}
onChange={(e)=>this.setState({type:e.target.value})}
>
<option></option>
{this.state.types.map((type, index) => {
return <option key={index} value={type}>{type}</option>
})}
</Form.Control>
</Form.Group>
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Label>Dirt</Form.Label>
<Form.Control
as="select"
type="text"
value={this.state.dirt}
onChange={(e)=>this.setState({dirt:e.target.value})}
>
<option></option>
{this.state.dirts.map((dirt, index) => {
return <option key={index}>{dirt}</option>
})}
</Form.Control>
</Form.Group>
<Button type={"submit"}>{this.state.btnName}</Button>
</Form>
:null
}
<Row className="justify-content-md-center">
<Col md={{ span: 4, offset: 4 }}></Col>
</Row>
<br></br>
{
this.state.plants.length !== 0?
<Table striped bordered hover>
<thead>
<tr>
<th>Plant name</th>
<th>Plant type</th>
<th>Dirt type</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{
this.state.plants.map((plant, index) => {
return <tr key={index}>
<td>{plant[0]}</td>
<td>{plant[1]}</td>
<td>{plant[2]}</td>
<td><Button type={"button"} onClick={() => this.editItem(plant[0], plant[1], plant[2], index)}>Edit</Button></td>
<td><Button type={"button"} onClick={() => this.removeItem(plant)}>Delete</Button></td>
</tr>
})
}
</tbody>
</Table>
: null
}
</Container>
</>
);
}
// search for arrow function for further syntax knowledge
handleSubmit = (e) => {
e.preventDefault();
if (this.state.updateId >= 0) { // check if it is in edit mode
this.state.plants[this.state.updateId][0] = this.state.name;
this.state.plants[this.state.updateId][1] = this.state.type;
this.state.plants[this.state.updateId][2] = this.state.dirt; // updates the name of the plant
this.setState({
updateId:-1, // Todo check docu
name:'', // reset inputtext again
btnName:'submit' // reset button to submit again
})
} else {
let newDataElement = [
this.state.name,
this.state.type,
this.state.dirt
]
console.log("name " + newDataElement[0])
console.log("type " + newDataElement[1])
console.log("dirt " + newDataElement[2])
this.setState(prevState =>({
plants:[...prevState.plants, newDataElement], // adds a new plant array
name:'' //to reset the inputfield
}))
return this.state.plants;
}
}
removeItem = (value) => {
this.setState({
plants:this.state.plants.filter((plant) => { // filter function add docu
return plant !== value;
}),
name:''
})
}
editItem = (editedName, editedType, editedDirt, index) => {
this.setState({
name:editedName,
type:editedType,
dirt:editedDirt,
btnName:'update',
updateId:index // should be edited to a boolean
})
}
}
export default Settings;

473
package-lock.json generated
View File

@ -11,11 +11,208 @@
"regenerator-runtime": "^0.13.4"
}
},
"@popperjs/core": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.4.4.tgz",
"integrity": "sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg=="
},
"@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
"integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
},
"@restart/hooks": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.25.tgz",
"integrity": "sha512-m2v3N5pxTsIiSH74/sb1yW8D9RxkJidGW+5Mfwn/lHb2QzhZNlaU1su7abSyT9EGf0xS/0waLjrf7/XxQHUk7w==",
"requires": {
"lodash": "^4.17.15",
"lodash-es": "^4.17.15"
}
},
"@types/prop-types": {
"version": "15.7.3",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
},
"@types/react": {
"version": "16.9.41",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.41.tgz",
"integrity": "sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug==",
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"
}
},
"@types/warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
"integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI="
},
"balanced-match": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
},
"bootstrap": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz",
"integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA=="
},
"classnames": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"core-js": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
},
"csstype": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.11.tgz",
"integrity": "sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw=="
},
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
"d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
"integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
},
"d3-color": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
},
"d3-format": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.4.tgz",
"integrity": "sha512-TWks25e7t8/cqctxCmxpUuzZN11QxIA7YrMbram94zMQ0PXjE4LVIMe/f6a4+xxL8HQ3OsAFULOINQi1pE62Aw=="
},
"d3-interpolate": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
"requires": {
"d3-color": "1"
}
},
"d3-path": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
"d3-scale": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
"requires": {
"d3-array": "^1.2.0",
"d3-collection": "1",
"d3-format": "1",
"d3-interpolate": "1",
"d3-time": "1",
"d3-time-format": "2"
}
},
"d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
"requires": {
"d3-path": "1"
}
},
"d3-time": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
},
"d3-time-format": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz",
"integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==",
"requires": {
"d3-time": "1"
}
},
"decimal.js-light": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.0.tgz",
"integrity": "sha512-b3VJCbd2hwUpeRGG3Toob+CRo8W22xplipNhP3tN7TSVB/cyMX71P1vM2Xjc9H74uV6dS2hDDmo/rHq8L87Upg=="
},
"dom-helpers": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
"requires": {
"@babel/runtime": "^7.1.2"
}
},
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"requires": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
}
},
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"lodash-es": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
"integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -24,6 +221,11 @@
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
"math-expression-evaluator": {
"version": "1.2.22",
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz",
"integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ=="
},
"meteor-node-stubs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-1.0.0.tgz",
@ -585,11 +787,33 @@
}
}
},
"mini-create-react-context": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
"integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
"requires": {
"@babel/runtime": "^7.5.5",
"tiny-warning": "^1.0.3"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
@ -600,6 +824,23 @@
"react-is": "^16.8.1"
}
},
"prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"requires": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
}
},
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
},
"react": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
@ -610,6 +851,48 @@
"prop-types": "^15.6.2"
}
},
"react-bootstrap": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.0.1.tgz",
"integrity": "sha512-xMHwsvDN7sIv26P9wWiosWjITZije2dRCjEJHVfV2KFoSJY+8uv2zttEw0XMB7xviQcW3zuIGLJXuj8vf6lYEg==",
"requires": {
"@babel/runtime": "^7.4.2",
"@restart/context": "^2.1.4",
"@restart/hooks": "^0.3.21",
"@types/react": "^16.9.23",
"classnames": "^2.2.6",
"dom-helpers": "^5.1.2",
"invariant": "^2.2.4",
"prop-types": "^15.7.2",
"prop-types-extra": "^1.1.0",
"react-overlays": "^3.1.2",
"react-transition-group": "^4.0.0",
"uncontrollable": "^7.0.0",
"warning": "^4.0.3"
},
"dependencies": {
"dom-helpers": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz",
"integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^2.6.7"
}
},
"react-transition-group": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
"integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
}
}
},
"react-dom": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
@ -626,11 +909,167 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-overlays": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-3.2.0.tgz",
"integrity": "sha512-YTgCmw6l4uBOYylSnc3V8WLX+A0EoGnzDrqkYz0K7MUKbMBZFpaxLXH4EF9eZbspd+syZHQ5XAABI7n/zak1EA==",
"requires": {
"@babel/runtime": "^7.4.5",
"@popperjs/core": "^2.0.0",
"@restart/hooks": "^0.3.12",
"@types/warning": "^3.0.0",
"dom-helpers": "^5.1.0",
"prop-types": "^15.7.2",
"uncontrollable": "^7.0.0",
"warning": "^4.0.3"
},
"dependencies": {
"dom-helpers": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz",
"integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^2.6.7"
}
}
}
},
"react-resize-detector": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-2.3.0.tgz",
"integrity": "sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ==",
"requires": {
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1",
"prop-types": "^15.6.0",
"resize-observer-polyfill": "^1.5.0"
}
},
"react-router": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
"integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
"mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
}
},
"react-router-dom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz",
"integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
"react-router": "5.2.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
}
},
"react-smooth": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz",
"integrity": "sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==",
"requires": {
"lodash": "~4.17.4",
"prop-types": "^15.6.0",
"raf": "^3.4.0",
"react-transition-group": "^2.5.0"
}
},
"react-transition-group": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
"integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
"requires": {
"dom-helpers": "^3.4.0",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2",
"react-lifecycles-compat": "^3.0.4"
}
},
"recharts": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/recharts/-/recharts-1.8.5.tgz",
"integrity": "sha512-tM9mprJbXVEBxjM7zHsIy6Cc41oO/pVYqyAsOHLxlJrbNBuLs0PHB3iys2M+RqCF0//k8nJtZF6X6swSkWY3tg==",
"requires": {
"classnames": "^2.2.5",
"core-js": "^2.6.10",
"d3-interpolate": "^1.3.0",
"d3-scale": "^2.1.0",
"d3-shape": "^1.2.0",
"lodash": "^4.17.5",
"prop-types": "^15.6.0",
"react-resize-detector": "^2.3.0",
"react-smooth": "^1.0.5",
"recharts-scale": "^0.4.2",
"reduce-css-calc": "^1.3.0"
}
},
"recharts-scale": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz",
"integrity": "sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==",
"requires": {
"decimal.js-light": "^2.4.1"
}
},
"reduce-css-calc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
"integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
"requires": {
"balanced-match": "^0.4.2",
"math-expression-evaluator": "^1.2.14",
"reduce-function-call": "^1.0.1"
}
},
"reduce-function-call": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz",
"integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==",
"requires": {
"balanced-match": "^1.0.0"
},
"dependencies": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}
}
},
"regenerator-runtime": {
"version": "0.13.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
},
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
"scheduler": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
@ -639,6 +1078,40 @@
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
},
"tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
"integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw=="
},
"tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"uncontrollable": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.1.1.tgz",
"integrity": "sha512-EcPYhot3uWTS3w00R32R2+vS8Vr53tttrvMj/yA1uYRhf8hbTG2GyugGqWDY0qIskxn0uTTojVd6wPYW9ZEf8Q==",
"requires": {
"@babel/runtime": "^7.6.3",
"@types/react": "^16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
}
},
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw=="
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
}
}
}

View File

@ -9,9 +9,13 @@
},
"dependencies": {
"@babel/runtime": "^7.8.4",
"bootstrap": "^4.5.0",
"meteor-node-stubs": "^1.0.0",
"react": "^16.13.0",
"react-dom": "^16.13.0"
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.0",
"react-router-dom": "^5.2.0",
"recharts": "^1.8.5"
},
"meteor": {
"mainModule": {