Compare commits
	
		
			2 Commits
		
	
	
		
			master
			...
			dev/add-mo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8c4dbadf16 | ||
|  | 53ee280acc | 
							
								
								
									
										150
									
								
								src/actions/arduinoActions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/actions/arduinoActions.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | |||||||
|  | import { GET_ARDUINO_EXAMPLES } from './types'; | ||||||
|  | 
 | ||||||
|  | import axios from 'axios'; | ||||||
|  | import { returnErrors, returnSuccess } from './messageActions'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | export const getArduinoExamples = () => (dispatch) => { | ||||||
|  |   const config = { | ||||||
|  |     success: res => { | ||||||
|  |       var examples = res.data.arduinoExamples; | ||||||
|  |       console.log(examples); | ||||||
|  |       dispatch({ | ||||||
|  |         type: GET_ARDUINO_EXAMPLES, | ||||||
|  |         payload: examples | ||||||
|  |       }); | ||||||
|  |       dispatch(returnSuccess(res.data.message, res.status)); | ||||||
|  |     }, | ||||||
|  |     error: err => { | ||||||
|  |       if (err.response) { | ||||||
|  |         dispatch(returnErrors(err.response.data.message, err.response.status, 'GET_PROJECTS_FAIL')); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   axios.get(`${process.env.REACT_APP_BLOCKLY_API}/arduino`, config) | ||||||
|  |     .then(res => { | ||||||
|  |       res.config.success(res); | ||||||
|  |     }) | ||||||
|  |     .catch(err => { | ||||||
|  |       err.config.error(err); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // export const updateProject = (type, id) => (dispatch, getState) => {
 | ||||||
|  | //   var workspace = getState().workspace;
 | ||||||
|  | //   var body = {
 | ||||||
|  | //     xml: workspace.code.xml,
 | ||||||
|  | //     title: workspace.name,
 | ||||||
|  | //     board: getState().board.board,
 | ||||||
|  | //   };
 | ||||||
|  | //   var project = getState().project;
 | ||||||
|  | //   if (type === 'gallery') {
 | ||||||
|  | //     body.description = project.description;
 | ||||||
|  | //   }
 | ||||||
|  | //   const config = {
 | ||||||
|  | //     success: res => {
 | ||||||
|  | //       var project = res.data[type];
 | ||||||
|  | //       var projects = getState().project.projects;
 | ||||||
|  | //       var index = projects.findIndex(res => res._id === project._id);
 | ||||||
|  | //       projects[index] = project;
 | ||||||
|  | //       dispatch({
 | ||||||
|  | //         type: GET_PROJECTS,
 | ||||||
|  | //         payload: projects
 | ||||||
|  | //       });
 | ||||||
|  | //       if (type === 'project') {
 | ||||||
|  | //         dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_UPDATE_SUCCESS'));
 | ||||||
|  | //       } else {
 | ||||||
|  | //         dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_UPDATE_SUCCESS'));
 | ||||||
|  | //       }
 | ||||||
|  | //     },
 | ||||||
|  | //     error: err => {
 | ||||||
|  | //       if (err.response) {
 | ||||||
|  | //         if (type === 'project') {
 | ||||||
|  | //           dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_UPDATE_FAIL'));
 | ||||||
|  | //         } else {
 | ||||||
|  | //           dispatch(returnErrors(err.response.data.message, err.response.status, 'GALLERY_UPDATE_FAIL'));
 | ||||||
|  | //         }
 | ||||||
|  | //       }
 | ||||||
|  | //     }
 | ||||||
|  | //   };
 | ||||||
|  | //   axios.put(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, body, config)
 | ||||||
|  | //     .then(res => {
 | ||||||
|  | //       res.config.success(res);
 | ||||||
|  | //     })
 | ||||||
|  | //     .catch(err => {
 | ||||||
|  | //       err.config.error(err);
 | ||||||
|  | //     });
 | ||||||
|  | // };
 | ||||||
|  | 
 | ||||||
|  | // export const deleteProject = (type, id) => (dispatch, getState) => {
 | ||||||
|  | //   const config = {
 | ||||||
|  | //     success: res => {
 | ||||||
|  | //       var projects = getState().project.projects;
 | ||||||
|  | //       var index = projects.findIndex(res => res._id === id);
 | ||||||
|  | //       projects.splice(index, 1)
 | ||||||
|  | //       dispatch({
 | ||||||
|  | //         type: GET_PROJECTS,
 | ||||||
|  | //         payload: projects
 | ||||||
|  | //       });
 | ||||||
|  | //       if (type === 'project') {
 | ||||||
|  | //         dispatch(returnSuccess(res.data.message, res.status, 'PROJECT_DELETE_SUCCESS'));
 | ||||||
|  | //       } else {
 | ||||||
|  | //         dispatch(returnSuccess(res.data.message, res.status, 'GALLERY_DELETE_SUCCESS'));
 | ||||||
|  | //       }
 | ||||||
|  | //     },
 | ||||||
|  | //     error: err => {
 | ||||||
|  | //       dispatch(returnErrors(err.response.data.message, err.response.status, 'PROJECT_DELETE_FAIL'));
 | ||||||
|  | //     }
 | ||||||
|  | //   };
 | ||||||
|  | //   axios.delete(`${process.env.REACT_APP_BLOCKLY_API}/${type}/${id}`, config)
 | ||||||
|  | //     .then(res => {
 | ||||||
|  | //       res.config.success(res);
 | ||||||
|  | //     })
 | ||||||
|  | //     .catch(err => {
 | ||||||
|  | //       if (err.response && err.response.status !== 401) {
 | ||||||
|  | //         err.config.error(err);
 | ||||||
|  | //       }
 | ||||||
|  | //     });
 | ||||||
|  | // };
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // export const shareProject = (title, type, id) => (dispatch, getState) => {
 | ||||||
|  | //   var body = {
 | ||||||
|  | //     title: title,
 | ||||||
|  | //     board: getState().board.board
 | ||||||
|  | //   };
 | ||||||
|  | //   if (type === 'project') {
 | ||||||
|  | //     body.projectId = id;
 | ||||||
|  | //   } else {
 | ||||||
|  | //     body.xml = getState().workspace.code.xml;
 | ||||||
|  | //   }
 | ||||||
|  | //   axios.post(`${process.env.REACT_APP_BLOCKLY_API}/share`, body)
 | ||||||
|  | //     .then(res => {
 | ||||||
|  | //       var shareContent = res.data.content;
 | ||||||
|  | //       if (body.projectId) {
 | ||||||
|  | //         var projects = getState().project.projects;
 | ||||||
|  | //         var index = projects.findIndex(res => res._id === id);
 | ||||||
|  | //         projects[index].shared = shareContent.expiresAt;
 | ||||||
|  | //         dispatch({
 | ||||||
|  | //           type: GET_PROJECTS,
 | ||||||
|  | //           payload: projects
 | ||||||
|  | //         });
 | ||||||
|  | //       }
 | ||||||
|  | //       dispatch(returnSuccess(res.data.message, shareContent._id, 'SHARE_SUCCESS'));
 | ||||||
|  | //     })
 | ||||||
|  | //     .catch(err => {
 | ||||||
|  | //       if (err.response) {
 | ||||||
|  | //         dispatch(returnErrors(err.response.data.message, err.response.status, 'SHARE_FAIL'));
 | ||||||
|  | //       }
 | ||||||
|  | //     });
 | ||||||
|  | // };
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // export const resetProject = () => (dispatch) => {
 | ||||||
|  | //   dispatch({
 | ||||||
|  | //     type: GET_PROJECTS,
 | ||||||
|  | //     payload: []
 | ||||||
|  | //   });
 | ||||||
|  | //   dispatch(setType(''));
 | ||||||
|  | //   dispatch(setDescription(''));
 | ||||||
|  | // };
 | ||||||
| @ -90,7 +90,8 @@ export const updateProject = (type, id) => (dispatch, getState) => { | |||||||
|   var workspace = getState().workspace; |   var workspace = getState().workspace; | ||||||
|   var body = { |   var body = { | ||||||
|     xml: workspace.code.xml, |     xml: workspace.code.xml, | ||||||
|     title: workspace.name |     title: workspace.name, | ||||||
|  |     board: getState().board.board, | ||||||
|   }; |   }; | ||||||
|   var project = getState().project; |   var project = getState().project; | ||||||
|   if (type === 'gallery') { |   if (type === 'gallery') { | ||||||
| @ -165,7 +166,8 @@ export const deleteProject = (type, id) => (dispatch, getState) => { | |||||||
| 
 | 
 | ||||||
| export const shareProject = (title, type, id) => (dispatch, getState) => { | export const shareProject = (title, type, id) => (dispatch, getState) => { | ||||||
|   var body = { |   var body = { | ||||||
|     title: title |     title: title, | ||||||
|  |     board: getState().board.board | ||||||
|   }; |   }; | ||||||
|   if (type === 'project') { |   if (type === 'project') { | ||||||
|     body.projectId = id; |     body.projectId = id; | ||||||
|  | |||||||
| @ -64,5 +64,7 @@ export const GET_PROJECTS = "GET_PROJECTS"; | |||||||
| export const PROJECT_TYPE = "PROJECT_TYPE"; | export const PROJECT_TYPE = "PROJECT_TYPE"; | ||||||
| export const PROJECT_DESCRIPTION = "PROJECT_DESCRIPTION"; | export const PROJECT_DESCRIPTION = "PROJECT_DESCRIPTION"; | ||||||
| 
 | 
 | ||||||
|  | export const GET_ARDUINO_EXAMPLES = "GET_ARDUINO_EXAMPLES"; | ||||||
|  | 
 | ||||||
| //board
 | //board
 | ||||||
| export const BOARD = "BOARD"; | export const BOARD = "BOARD"; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import React from "react"; | import React, { useEffect } from "react"; | ||||||
| import Blockly from "blockly"; | import Blockly from "blockly"; | ||||||
| import { useSelector } from "react-redux"; | import { useSelector } from "react-redux"; | ||||||
| import Accordion from "@mui/material/Accordion"; | import Accordion from "@mui/material/Accordion"; | ||||||
| @ -10,17 +10,20 @@ import { useMonaco } from "@monaco-editor/react"; | |||||||
| import { Button } from "@mui/material"; | import { Button } from "@mui/material"; | ||||||
| import SerialMonitor from "./SerialMonitor.js"; | import SerialMonitor from "./SerialMonitor.js"; | ||||||
| import axios from "axios"; | import axios from "axios"; | ||||||
|  | import { useDispatch } from "react-redux"; | ||||||
|  | import { getArduinoExamples } from "../../actions/arduinoActions"; | ||||||
|  | //import getArduinoExamples from "../../reducers/arduinoReducer"
 | ||||||
| 
 | 
 | ||||||
| const Sidebar = () => { | const Sidebar = () => { | ||||||
|   //const [examples, setExamples] = React.useState([]);
 | 
 | ||||||
|  | 
 | ||||||
|  |   const examples = useSelector((state) => state.arduino.examples); | ||||||
|   const user = useSelector((state) => state.auth.user); |   const user = useSelector((state) => state.auth.user); | ||||||
|   // useEffect(() => {
 |   const dispatch = useDispatch() | ||||||
|   //   axios
 | 
 | ||||||
|   //     .get("https://coelho.opensensemap.org/items/blocklysamples")
 |     useEffect(() => { | ||||||
|   //     .then((res) => {
 |       dispatch(getArduinoExamples()); | ||||||
|   //       setExamples(res.data.data);
 |     }, [dispatch]); | ||||||
|   //     });
 |  | ||||||
|   // }, []);
 |  | ||||||
|   const monaco = useMonaco(); |   const monaco = useMonaco(); | ||||||
|   const loadCode = (code) => { |   const loadCode = (code) => { | ||||||
|     monaco.editor.getModels()[0].setValue(code); |     monaco.editor.getModels()[0].setValue(code); | ||||||
| @ -52,7 +55,7 @@ const Sidebar = () => { | |||||||
|           </AccordionDetails> |           </AccordionDetails> | ||||||
|         </Accordion> |         </Accordion> | ||||||
|       ) : null} |       ) : null} | ||||||
|       {/* <Accordion> |      <Accordion> | ||||||
|         <AccordionSummary |         <AccordionSummary | ||||||
|           expandIcon={""} |           expandIcon={""} | ||||||
|           aria-controls="panel1a-content" |           aria-controls="panel1a-content" | ||||||
| @ -71,13 +74,13 @@ const Sidebar = () => { | |||||||
|                   key={i} |                   key={i} | ||||||
|                   onClick={() => loadCode(object.code)} |                   onClick={() => loadCode(object.code)} | ||||||
|                 > |                 > | ||||||
|                   {object.name} |                   {object.title} | ||||||
|                 </Button> |                 </Button> | ||||||
|               ); |               ); | ||||||
|             })} |             })} | ||||||
|           </Typography> |           </Typography> | ||||||
|         </AccordionDetails> |         </AccordionDetails> | ||||||
|       </Accordion> */} |       </Accordion>  | ||||||
|       {user ? ( |       {user ? ( | ||||||
|         <Accordion> |         <Accordion> | ||||||
|           <AccordionSummary |           <AccordionSummary | ||||||
|  | |||||||
| @ -15,15 +15,22 @@ import { setBoard } from './Blockly/helpers/board'; | |||||||
| class Content extends Component { | class Content extends Component { | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|  |     console.log(this.props.board); | ||||||
|  |     setBoard(this.props.board) | ||||||
|     if (this.props.language === 'de_DE') { |     if (this.props.language === 'de_DE') { | ||||||
|       Blockly.setLocale(De); |       Blockly.setLocale(De); | ||||||
|     } else if (this.props.language === 'en_US') { |     } else if (this.props.language === 'en_US') { | ||||||
|       Blockly.setLocale(En); |       Blockly.setLocale(En); | ||||||
|     } |     } | ||||||
|     setBoard(this.props.board) |      | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   componentDidUpdate(props) { |   componentDidUpdate(props) { | ||||||
|  |     console.log(props.board); | ||||||
|  |     console.log(this.props.board); | ||||||
|  |    // if (props.board !== this.props.board) {
 | ||||||
|  |       setBoard(this.props.board); | ||||||
|  |        | ||||||
|     if (props.language !== this.props.language) { |     if (props.language !== this.props.language) { | ||||||
|       if (this.props.language === 'de_DE') { |       if (this.props.language === 'de_DE') { | ||||||
|         Blockly.setLocale(De); |         Blockly.setLocale(De); | ||||||
| @ -31,7 +38,7 @@ class Content extends Component { | |||||||
|         Blockly.setLocale(En); |         Blockly.setLocale(En); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     setBoard(this.props.board) |     | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ import Dialog from "./Dialog"; | |||||||
| 
 | 
 | ||||||
| import withStyles from '@mui/styles/withStyles'; | import withStyles from '@mui/styles/withStyles'; | ||||||
| import * as Blockly from "blockly"; | import * as Blockly from "blockly"; | ||||||
|  | import { setBoard } from "../actions/boardActions"; | ||||||
| import { IconButton, Grid, Avatar, Typography } from "@mui/material"; | import { IconButton, Grid, Avatar, Typography } from "@mui/material"; | ||||||
| import { setBoard } from "../actions/boardAction"; |  | ||||||
| 
 | 
 | ||||||
| const styles = (theme) => ({ | const styles = (theme) => ({ | ||||||
|   link: { |   link: { | ||||||
|  | |||||||
| @ -2,10 +2,10 @@ import React, { Component } from "react"; | |||||||
| import PropTypes from "prop-types"; | import PropTypes from "prop-types"; | ||||||
| import { connect } from "react-redux"; | import { connect } from "react-redux"; | ||||||
| import { clearStats, workspaceName } from "../actions/workspaceActions"; | import { clearStats, workspaceName } from "../actions/workspaceActions"; | ||||||
| 
 | import { setBoard } from "../actions/boardActions"; | ||||||
| import * as Blockly from "blockly/core"; | import * as Blockly from "blockly/core"; | ||||||
| import { createNameId } from "mnemonic-id"; | import { createNameId } from "mnemonic-id"; | ||||||
| 
 | import * as BoardHelper from "./Blockly/helpers/board"; | ||||||
| import WorkspaceStats from "./Workspace/WorkspaceStats"; | import WorkspaceStats from "./Workspace/WorkspaceStats"; | ||||||
| import WorkspaceFunc from "./Workspace/WorkspaceFunc"; | import WorkspaceFunc from "./Workspace/WorkspaceFunc"; | ||||||
| import BlocklyWindow from "./Blockly/BlocklyWindow"; | import BlocklyWindow from "./Blockly/BlocklyWindow"; | ||||||
| @ -66,6 +66,10 @@ class Home extends Component { | |||||||
|     this.setState({ stats: window.localStorage.getItem("stats") }); |     this.setState({ stats: window.localStorage.getItem("stats") }); | ||||||
|     if (!this.props.project) { |     if (!this.props.project) { | ||||||
|       this.props.workspaceName(createNameId()); |       this.props.workspaceName(createNameId()); | ||||||
|  |     } else { | ||||||
|  |       console.log(this.props.project); | ||||||
|  |       this.props.setBoard(this.props.project.board); | ||||||
|  |       BoardHelper.setBoard(this.props.project.board); | ||||||
|     } |     } | ||||||
|     if (this.props.message && this.props.message.id === "GET_SHARE_FAIL") { |     if (this.props.message && this.props.message.id === "GET_SHARE_FAIL") { | ||||||
|       this.setState({ |       this.setState({ | ||||||
| @ -187,7 +191,8 @@ class Home extends Component { | |||||||
|             </Grid> |             </Grid> | ||||||
|           ) : null} |           ) : null} | ||||||
|         </Grid> |         </Grid> | ||||||
|         <DeviceSelection /> |         {!this.props.board ? <DeviceSelection /> : null} | ||||||
|  |         {/* <DeviceSelection /> */} | ||||||
|         {/* <HintTutorialExists /> */} |         {/* <HintTutorialExists /> */} | ||||||
|         {this.props.platform ? ( |         {this.props.platform ? ( | ||||||
|           <Dialog |           <Dialog | ||||||
| @ -220,6 +225,7 @@ class Home extends Component { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Home.propTypes = { | Home.propTypes = { | ||||||
|  |   setBoard: PropTypes.func.isRequired, | ||||||
|   clearStats: PropTypes.func.isRequired, |   clearStats: PropTypes.func.isRequired, | ||||||
|   workspaceName: PropTypes.func.isRequired, |   workspaceName: PropTypes.func.isRequired, | ||||||
|   message: PropTypes.object.isRequired, |   message: PropTypes.object.isRequired, | ||||||
| @ -231,8 +237,9 @@ const mapStateToProps = (state) => ({ | |||||||
|   message: state.message, |   message: state.message, | ||||||
|   statistics: state.general.statistics, |   statistics: state.general.statistics, | ||||||
|   platform: state.general.platform, |   platform: state.general.platform, | ||||||
|  |   board: state.board.board | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export default connect(mapStateToProps, { clearStats, workspaceName })( | export default connect(mapStateToProps, { clearStats, workspaceName, setBoard })( | ||||||
|   withStyles(styles, { withTheme: true })(Home) |   withStyles(styles, { withTheme: true })(Home) | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import React, { Component } from 'react'; | import React, { Component } from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { setBoard } from '../../actions/boardAction'; | import { setBoard } from '../../actions/boardActions'; | ||||||
| 
 | 
 | ||||||
| import * as Blockly from 'blockly/core'; | import * as Blockly from 'blockly/core'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -91,8 +91,11 @@ class SaveProject extends Component { | |||||||
|   saveProject = () => { |   saveProject = () => { | ||||||
|     var body = { |     var body = { | ||||||
|       xml: this.props.xml, |       xml: this.props.xml, | ||||||
|       title: this.props.name |       title: this.props.name, | ||||||
|  |       board: this.props.board, | ||||||
|  |       type: "blockly" | ||||||
|     }; |     }; | ||||||
|  |     console.log(body); | ||||||
|     if (this.state.projectType === 'gallery') { |     if (this.state.projectType === 'gallery') { | ||||||
|       body.description = this.state.description; |       body.description = this.state.description; | ||||||
|     } |     } | ||||||
| @ -210,7 +213,8 @@ const mapStateToProps = state => ({ | |||||||
|   description: state.project.description, |   description: state.project.description, | ||||||
|   xml: state.workspace.code.xml, |   xml: state.workspace.code.xml, | ||||||
|   message: state.message, |   message: state.message, | ||||||
|   user: state.auth.user |   user: state.auth.user, | ||||||
|  |   board: state.board.board, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| export default connect(mapStateToProps, { updateProject, setDescription })(withStyles(styles, { withTheme: true })(withRouter(SaveProject))); | export default connect(mapStateToProps, { updateProject, setDescription })(withStyles(styles, { withTheme: true })(withRouter(SaveProject))); | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								src/reducers/arduinoReducer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/reducers/arduinoReducer.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | import { GET_ARDUINO_EXAMPLES } from '../actions/types'; | ||||||
|  | 
 | ||||||
|  | const initialState = { | ||||||
|  |   examples: [], | ||||||
|  |   type: '', | ||||||
|  |   description: '', | ||||||
|  |   progress: false | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default function foo(state = initialState, action) { | ||||||
|  |   switch (action.type) { | ||||||
|  |     case GET_ARDUINO_EXAMPLES: | ||||||
|  |       return { | ||||||
|  |         ...state, | ||||||
|  |         examples: action.payload | ||||||
|  |       }; | ||||||
|  |     default: | ||||||
|  |       return state; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -8,6 +8,7 @@ import messageReducer from './messageReducer'; | |||||||
| import authReducer from './authReducer'; | import authReducer from './authReducer'; | ||||||
| import boardReducer from './boardReducer'; | import boardReducer from './boardReducer'; | ||||||
| import sensorwikiReducer from './sensorwikiReducer'; | import sensorwikiReducer from './sensorwikiReducer'; | ||||||
|  | import arduinoReducer from './arduinoReducer'; | ||||||
| 
 | 
 | ||||||
| export default combineReducers({ | export default combineReducers({ | ||||||
|   auth: authReducer, |   auth: authReducer, | ||||||
| @ -18,5 +19,6 @@ export default combineReducers({ | |||||||
|   project: projectReducer, |   project: projectReducer, | ||||||
|   general: generalReducer, |   general: generalReducer, | ||||||
|   message: messageReducer, |   message: messageReducer, | ||||||
|   sensorwiki: sensorwikiReducer |   sensorwiki: sensorwikiReducer, | ||||||
|  |   arduino: arduinoReducer | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user