Update to material-ui 1.0 beta
This commit is contained in:
parent
48a96b57fa
commit
bef07649d0
14 changed files with 1164 additions and 395 deletions
|
|
@ -1,5 +1,4 @@
|
|||
[ignore]
|
||||
.*node_modules/react-event-listener/.*
|
||||
|
||||
[include]
|
||||
src/
|
||||
|
|
|
|||
BIN
img/layers/rzl/details.png
Normal file
BIN
img/layers/rzl/details.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
img/layers/rzl/labels.png
Normal file
BIN
img/layers/rzl/labels.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
img/layers/rzl/rooms.png
Normal file
BIN
img/layers/rzl/rooms.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -57,11 +57,14 @@
|
|||
/* Support for IE. */
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
#drawer_uiComponents .material-icons {
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<script src="public/dist/main.js"></script>
|
||||
<script src="dist/main.js"></script>
|
||||
</body>
|
||||
|
|
|
|||
10
package.json
10
package.json
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "reacttest",
|
||||
"name": "spacemap",
|
||||
"version": "1.0.0",
|
||||
"author": "uwap <me@uwap.name>",
|
||||
"description": "react",
|
||||
"author": "uwap <me+spacemap.package.json@uwap.name>",
|
||||
"description": "control devices via mqtt on a beautiful map of your space",
|
||||
"scripts": {
|
||||
"build": "webpack --bail",
|
||||
"watch": "webpack --watch"
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
"dependencies": {
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"leaflet": "^1.2.0",
|
||||
"material-ui": "^0.18.7",
|
||||
"material-ui": "next",
|
||||
"material-ui-old": "npm:material-ui@latest",
|
||||
"mqtt": "^2.11.0",
|
||||
"ramda": "^0.24.1",
|
||||
"react": "^15.6.1",
|
||||
|
|
@ -26,6 +27,7 @@
|
|||
"babel-preset-react": "^6.24.1",
|
||||
"flow": "^0.2.3",
|
||||
"flow-bin": "^0.50.0",
|
||||
"flow-typed": "^2.2.1",
|
||||
"webpack": "^3.1.0",
|
||||
"webpack-shell-plugin": "^0.5.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,26 +1,38 @@
|
|||
// @flow
|
||||
import React from "react";
|
||||
import Toggle from "material-ui/Toggle";
|
||||
import SelectField from 'material-ui/SelectField';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import Slider from 'material-ui/Slider';
|
||||
import Switch from "material-ui/Switch";
|
||||
import Select from 'material-ui/Select';
|
||||
import { MenuItem } from 'material-ui/Menu';
|
||||
import Slider from 'material-ui-old/Slider';
|
||||
import MuiThemeProvider from 'material-ui-old/styles/MuiThemeProvider';
|
||||
import Icon from 'material-ui/Icon';
|
||||
import Config from "./config";
|
||||
import { keyOf } from "./util";
|
||||
import Input, { InputLabel } from 'material-ui/Input';
|
||||
import { FormControl } from 'material-ui/Form';
|
||||
import R from "ramda";
|
||||
import List, {
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemSecondaryAction,
|
||||
ListItemText,
|
||||
ListSubheader,
|
||||
} from 'material-ui/List';
|
||||
|
||||
const enabled = (props: ControlUI, state: State) => {
|
||||
if (props.enableCondition == null) return true;
|
||||
else {
|
||||
const val = state.values[props.topic];
|
||||
return props.enableCondition(
|
||||
val.internal == null ? val.actual : val.internal, val.actual);
|
||||
val.internal == null ? val.actual : val.internal, val.actual, R.map(x => x.internal == null ?
|
||||
x.actual : x.internal, state.values == null ? {} : state.values));
|
||||
}
|
||||
};
|
||||
|
||||
const getValue = (topic: string, val: string) =>
|
||||
Config.topics[topic].values[val];
|
||||
|
||||
const onToggle = (topic: string, props: ControlUI, state: State) =>
|
||||
const onSwitch = (topic: string, props: ControlUI, state: State) =>
|
||||
(x, toggled: boolean) => {
|
||||
if (state.mqtt != null) {
|
||||
state.mqtt.publish(Config.topics[topic].command,
|
||||
|
|
@ -39,31 +51,49 @@ export const toggle = (state: State, props: ControlUI) => {
|
|||
return val.internal === R.propOr("on", "on", props);
|
||||
}
|
||||
})();
|
||||
return (<Toggle label={props.text}
|
||||
toggled={toggled}
|
||||
onToggle={onToggle(props.topic, props, state)}
|
||||
return (
|
||||
<ListItem>
|
||||
{props.icon && <ListItemIcon><Icon>{props.icon}</Icon></ListItemIcon>}
|
||||
<ListItemText primary={props.text} />
|
||||
<ListItemSecondaryAction>
|
||||
<Switch label={props.text}
|
||||
checked={toggled}
|
||||
onChange={onSwitch(props.topic, props, state)}
|
||||
disabled={!(enabled(props, state))} />
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
|
||||
const onDropDownChange = (topic: string, props: ControlUI, state: State) =>
|
||||
(event, index, value) => {
|
||||
(event) => {
|
||||
if (state.mqtt != null) {
|
||||
state.mqtt.publish(Config.topics[topic].command, value);
|
||||
state.mqtt.publish(Config.topics[topic].command, event.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const dropDownItem = (topic: string) => (text: string, key: string) => (
|
||||
<MenuItem value={Config.topics[topic].values[key]} primaryText={text} />
|
||||
<MenuItem value={Config.topics[topic].values[key]} key={key}>{text}</MenuItem>
|
||||
);
|
||||
|
||||
export const dropDown = (state: State, props: ControlUI) => (
|
||||
<SelectField value={state.values[props.topic].actual}
|
||||
onChange={onDropDownChange(props.topic, props, state)}
|
||||
disabled={!(enabled(props, state))}>
|
||||
{R.values(R.mapObjIndexed(dropDownItem(props.topic), props.options))}
|
||||
</SelectField>
|
||||
);
|
||||
export const dropDown = (state: State, props: ControlUI) => {
|
||||
const id = `${props.topic}.${Object.keys(props.options).reduce((v,r) => v + "." + r)}`;
|
||||
return (
|
||||
<ListItem>
|
||||
{props.icon && <ListItemIcon><Icon>{props.icon}</Icon></ListItemIcon>}
|
||||
<FormControl>
|
||||
<InputLabel htmlFor={id}>{props.text}</InputLabel>
|
||||
<Select value={state.values[props.topic].actual}
|
||||
onChange={onDropDownChange(props.topic, props, state)}
|
||||
disabled={!(enabled(props, state))}
|
||||
input={<Input id={id} />}
|
||||
>
|
||||
{R.values(R.mapObjIndexed(dropDownItem(props.topic), props.options))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
const onSliderChange = (state: State, props: ControlUI) =>
|
||||
(event, value) => {
|
||||
|
|
@ -73,13 +103,22 @@ const onSliderChange = (state: State, props: ControlUI) =>
|
|||
};
|
||||
|
||||
export const slider = (state: State, props: ControlUI) => (
|
||||
<div>
|
||||
<span>{props.text}</span>
|
||||
<Slider value={state.values[props.topic].actual}
|
||||
min={props.min == null ? 0 : props.min}
|
||||
max={props.max == null ? 1 : props.max}
|
||||
step={props.step == null ? 1 : props.step}
|
||||
onChange={onSliderChange(state, props)}
|
||||
/>
|
||||
</div>
|
||||
<ListItem>
|
||||
{props.icon && <ListItemIcon><Icon>{props.icon}</Icon></ListItemIcon>}
|
||||
<ListItemText primary={props.text} />
|
||||
<ListItemSecondaryAction>
|
||||
<MuiThemeProvider>
|
||||
<Slider value={state.values[props.topic].actual}
|
||||
min={props.min == null ? 0 : props.min}
|
||||
max={props.max == null ? 1 : props.max}
|
||||
step={props.step == null ? 1 : props.step}
|
||||
onChange={onSliderChange(state, props)}
|
||||
style={{width: 100}}
|
||||
/></MuiThemeProvider>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
|
||||
export const section = (state: State, props: ControlUI) => (
|
||||
<ListSubheader>{props.text}</ListSubheader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,57 +1,44 @@
|
|||
// @flow
|
||||
import React from "react";
|
||||
import AppBar from "material-ui/AppBar";
|
||||
import CircularProgress from "material-ui/CircularProgress";
|
||||
import MapIcon from "material-ui/svg-icons/maps/map";
|
||||
import PhonelinkOffIcon from "material-ui/svg-icons/hardware/phonelink-off";
|
||||
import LayersIcon from "material-ui/svg-icons/maps/layers";
|
||||
import IconMenu from "material-ui/IconMenu";
|
||||
import Toolbar from 'material-ui/Toolbar';
|
||||
import { CircularProgress } from "material-ui/Progress";
|
||||
import Icon from 'material-ui/Icon';
|
||||
import IconButton from "material-ui/IconButton";
|
||||
import MenuItem from "material-ui/MenuItem";
|
||||
import { orange400, grey50 } from "material-ui/styles/colors";
|
||||
import Menu, { MenuItem } from "material-ui/Menu";
|
||||
import Typography from 'material-ui/Typography';
|
||||
|
||||
const TopBarLayerSelector = (props: Object) => (
|
||||
<IconMenu
|
||||
iconButtonElement={
|
||||
<IconButton style={{width: 48, height: 48, padding: 0}}
|
||||
iconStyle={{width: 48, height: 48}}>
|
||||
<LayersIcon color={grey50} />
|
||||
</IconButton>}
|
||||
style={{width:48, height:48}}>
|
||||
<MenuItem primaryText="Layer1" />
|
||||
</IconMenu>
|
||||
<IconButton>
|
||||
<Icon>layers</Icon>
|
||||
</IconButton>
|
||||
)
|
||||
|
||||
const TopBarIndicatorMenu = (props: Object) => (
|
||||
<IconMenu
|
||||
iconButtonElement={
|
||||
<IconButton style={{width:48, height:48, padding: 0}}
|
||||
iconStyle={{width:48, height: 48}}
|
||||
tooltip={props.mqtt.connected ? "Connected!" : "Disconnected!"}>
|
||||
<IconButton>
|
||||
{props.mqtt.connected ?
|
||||
(<MapIcon color={grey50} />) :
|
||||
(<PhonelinkOffIcon color={grey50} />)}
|
||||
</IconButton>}
|
||||
style={{width:48, height:48}}>
|
||||
<MenuItem primaryText="Reconnect (Not yet implemented)" />
|
||||
</IconMenu>
|
||||
(<Icon style={{fontSize: 48}}>map</Icon>) :
|
||||
(<Icon style={{fontSize: 48}}>phonelink_off</Icon>)}
|
||||
</IconButton>
|
||||
);
|
||||
|
||||
|
||||
const TopBarIndicator = (props: Object) => {
|
||||
if (props.mqtt == null || props.mqtt.reconnecting) {
|
||||
return (<CircularProgress size={48} color={grey50} />);
|
||||
return (<CircularProgress size={48} style={{color: "rgba(0, 0, 0, 0.54)"}} />);
|
||||
} else {
|
||||
return (<TopBarIndicatorMenu {...props} />);
|
||||
}
|
||||
};
|
||||
|
||||
const TopBar = (props: Object) => (
|
||||
<AppBar title={props.title}
|
||||
style={{background:orange400}}
|
||||
iconElementLeft={<TopBarIndicator {...props} />}
|
||||
iconElementRight={<TopBarLayerSelector {...props} />}
|
||||
className="nav"
|
||||
/>);
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<TopBarIndicator {...props} />
|
||||
<Typography type="title">{props.title}</Typography>
|
||||
{false && <TopBarLayerSelector {...props} />}
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
|
||||
export default TopBar;
|
||||
|
|
|
|||
130
src/config.js
130
src/config.js
|
|
@ -51,6 +51,20 @@ const config : Config = {
|
|||
blue: "blue", green: "green", red: "red", random: "random",
|
||||
cycle: "cycle-random" }
|
||||
},
|
||||
onkyo_power: {
|
||||
state: "/service/onkyo/status/system-power",
|
||||
command: "/service/onkyo/command",
|
||||
defaultValue: "PWR00",
|
||||
values: { off: "PWR00", on: "PWR01" },
|
||||
parseState: msg => JSON.parse(msg.toString()).onkyo_raw
|
||||
},
|
||||
onkyo_mute: {
|
||||
state: "/service/onkyo/status/audio-muting",
|
||||
command: "/service/onkyo/command",
|
||||
defaultValue: "AMT00",
|
||||
values: { off: "AMT00", on: "AMT01" },
|
||||
parseState: msg => JSON.parse(msg.toString()).onkyo_raw
|
||||
},
|
||||
onkyo_volume: {
|
||||
state: "/service/onkyo/status/volume",
|
||||
command: "/service/onkyo/set/volume",
|
||||
|
|
@ -62,9 +76,16 @@ const config : Config = {
|
|||
state: "/service/onkyo/status/input-selector",
|
||||
command: "/service/onkyo/command",
|
||||
defaultValue: "SLI00",
|
||||
values: { tisch: "SLI11", chromecast: "SLI01", pult: "SLI10" },
|
||||
values: { tisch: "SLI11", chromecast: "SLI01", pult: "SLI10", netzwerk: "SLI2B" },
|
||||
parseState: msg => JSON.parse(msg.toString()).onkyo_raw
|
||||
},
|
||||
onkyo_radios: {
|
||||
state: "/service/onkyo/status/latest-NPR",
|
||||
command: "/service/onkyo/command",
|
||||
defaultValue: "",
|
||||
values: { mpd: "NPR01", kohina: "NPR02", somafm_dronezone: "NPR03", somafm_thetrip: "NPR04",
|
||||
querfunk: "NPR05", somafm_defconradio: "NPR06", somafm_secretagent: "NPR07", somafm_lush: "NPR08"}
|
||||
},
|
||||
rundumleuchte: {
|
||||
state: "/service/openhab/out/pca301_rundumleuchte/state",
|
||||
command: "/service/openhab/in/pca301_rundumleuchte/command",
|
||||
|
|
@ -87,98 +108,105 @@ const config : Config = {
|
|||
controls: {
|
||||
led_stahltrager: {
|
||||
name: "LED Stahlträger",
|
||||
position: [390, 100],
|
||||
position: [380, 300],
|
||||
icon: "wb_incandescent",
|
||||
iconColor: state => state.led_stahltraeger == "on" ? "#CCCC00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Stahlträger LED",
|
||||
topic: "led_stahltraeger"
|
||||
topic: "led_stahltraeger",
|
||||
icon: "power_settings_new"
|
||||
},
|
||||
]
|
||||
},
|
||||
snackbar: {
|
||||
name: "Snackbar",
|
||||
position: [560, 465],
|
||||
position: [510, 500],
|
||||
icon: "kitchen",
|
||||
iconColor: state => state.snackbar == "on" ? "#E20074" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Snackbar",
|
||||
topic: "snackbar"
|
||||
topic: "snackbar",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
twinkle: {
|
||||
name: "Twinkle",
|
||||
position: [500, 540],
|
||||
position: [530, 560],
|
||||
icon: "wb_incandescent",
|
||||
iconColor: state => state.twinkle == "on" ? "#CCCC00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Twinkle",
|
||||
topic: "twinkle"
|
||||
topic: "twinkle",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
fan: {
|
||||
name: "Ventilator",
|
||||
position: [530, 450],
|
||||
position: [510, 460],
|
||||
icon: "toys",
|
||||
iconColor: state => state.fan == "on" ? "#00FF00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Ventilator",
|
||||
topic: "fan"
|
||||
topic: "fan",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
videogames: {
|
||||
name: "Videospiele",
|
||||
position: [79, 50],
|
||||
position: [100, 100],
|
||||
icon: "videogame_asset",
|
||||
iconColor: state => state.videogames == "on" ? "#00FF00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Videospiele",
|
||||
topic: "videogames"
|
||||
topic: "videogames",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
olymp_pc: {
|
||||
name: "Rechner und Drucker",
|
||||
position: [298, 20],
|
||||
position: [297, 90],
|
||||
icon: "desktop_windows",
|
||||
iconColor: state => state.olymp_pc == "on" ? "#00FF00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Rechner und Drucker",
|
||||
topic: "olymp_pc"
|
||||
topic: "olymp_pc",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
flyfry: {
|
||||
name: "Fliegenbratgerät",
|
||||
position: [450, 560],
|
||||
position: [450, 590],
|
||||
icon: "whatshot",
|
||||
iconColor: state => state.flyfry == "on" ? "#6666FF" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Fliegenbratgerät",
|
||||
topic: "flyfry"
|
||||
topic: "flyfry",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
artnet: {
|
||||
name: "Artnet",
|
||||
position: [560,430],
|
||||
position: [535,475],
|
||||
icon: "wb_incandescent",
|
||||
iconColor: state =>
|
||||
({
|
||||
|
|
@ -195,77 +223,121 @@ const config : Config = {
|
|||
text: "An/Aus",
|
||||
topic: "artnet",
|
||||
on: "cycle",
|
||||
toggled: val => val != "off"
|
||||
toggled: val => val != "off",
|
||||
icon: "power_settings_new"
|
||||
},
|
||||
{
|
||||
type: "dropDown",
|
||||
text: "Artnet",
|
||||
text: "Farbe",
|
||||
topic: "artnet",
|
||||
options: {
|
||||
yellow: "Gelb",
|
||||
red: "Rot",
|
||||
purple: "Pink",
|
||||
green: "Grün",
|
||||
cycle: "Cycle Random"
|
||||
cycle: "Farbwechsel"
|
||||
},
|
||||
enableCondition: val => val != "off"
|
||||
enableCondition: val => val != "off",
|
||||
icon: "color_lens"
|
||||
}
|
||||
]
|
||||
},
|
||||
onkyo: {
|
||||
name: "Onkyo",
|
||||
position: [350, 620],
|
||||
position: [350, 650],
|
||||
icon: "volume_up",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Power",
|
||||
icon: "power_settings_new",
|
||||
topic: "onkyo_power"
|
||||
},
|
||||
{
|
||||
type: "section",
|
||||
text: "Lautstärkeregelung"
|
||||
},
|
||||
{
|
||||
type: "slider",
|
||||
text: "Volume",
|
||||
topic: "onkyo_volume",
|
||||
min: 0,
|
||||
max: 100
|
||||
max: 100,
|
||||
icon: "volume_up"
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Mute",
|
||||
topic: "onkyo_mute",
|
||||
icon: "volume_off"
|
||||
},
|
||||
{
|
||||
type: "section",
|
||||
text: "Eingänge"
|
||||
},
|
||||
{
|
||||
type: "dropDown",
|
||||
text: "Inputs",
|
||||
text: "Eingang",
|
||||
topic: "onkyo_inputs",
|
||||
options: {
|
||||
netzwerk: "Netzwerk",
|
||||
tisch: "Tisch",
|
||||
chromecast: "Chromecast",
|
||||
pult: "Pult"
|
||||
}
|
||||
},
|
||||
icon: "settings_input_component"
|
||||
},
|
||||
{
|
||||
type: "dropDown",
|
||||
text: "Netzwerksender",
|
||||
topic: "onkyo_radios",
|
||||
options: {
|
||||
mpd: "MPD",
|
||||
kohina: "Kohina",
|
||||
somafm_dronezone: "Drone Zone (SomaFM)",
|
||||
somafm_thetrip: "The Trip (SomaFM)",
|
||||
querfunk: "Querfunk",
|
||||
somafm_defconradio: "Defcon Radio (SomaFM)",
|
||||
somafm_secretagent: "Secret Agent (SomaFM)",
|
||||
somafm_lush: "Lush (SomaFM)"
|
||||
},
|
||||
icon: "radio",
|
||||
enableCondition: (a, b, state) => state.onkyo_inputs == "netzwerk"
|
||||
}
|
||||
]
|
||||
},
|
||||
rundumleuchte: {
|
||||
name: "Rundumleuchte",
|
||||
position: [310,220],
|
||||
position: [310,275],
|
||||
icon: "wb_sunny",
|
||||
iconColor: state => state.rundumleuchte == "on" ? "#CCCC00" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Rundumleuchte",
|
||||
topic: "rundumleuchte"
|
||||
topic: "rundumleuchte",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
},
|
||||
door: {
|
||||
name: "Tür",
|
||||
position: [480,300],
|
||||
position: [455,350],
|
||||
icon: "swap_vert",
|
||||
iconColor: state => state.door_status == "on" ? "#00FF00" : "#FF0000",
|
||||
ui: []
|
||||
},
|
||||
infoscreen: {
|
||||
name: "Infoscreen",
|
||||
position: [255, 455],
|
||||
position: [255, 495],
|
||||
icon: "developer_board",
|
||||
iconColor: state => state.infoscreen == "on" ? "#4444FF" : "#000000",
|
||||
ui: [
|
||||
{
|
||||
type: "toggle",
|
||||
text: "Infoscreen",
|
||||
topic: "infoscreen"
|
||||
topic: "infoscreen",
|
||||
icon: "power_settings_new"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,17 +2,25 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
|
||||
import createMuiTheme from 'material-ui/styles/createMuiTheme';
|
||||
import withStyles from 'material-ui/styles/withStyles';
|
||||
import Drawer from 'material-ui/Drawer';
|
||||
import injectTapEventPlugin from 'react-tap-event-plugin';
|
||||
import { store } from "./state";
|
||||
import { store, Actions } from "./state";
|
||||
import connectMqtt from "./mqtt";
|
||||
import AppBar from "./appbar";
|
||||
import Toggle from "material-ui/Toggle";
|
||||
import SpaceMapBar from "./appbar";
|
||||
import Switch from "material-ui/Switch";
|
||||
import * as UiItems from "./UiItems.js";
|
||||
import SpaceMap from "./map.js";
|
||||
import R from "ramda";
|
||||
import Config from "./config";
|
||||
import { Toolbar, ToolbarGroup, ToolbarTitle } from "material-ui/Toolbar";
|
||||
import Toolbar from "material-ui/Toolbar";
|
||||
import orange from 'material-ui/colors/orange';
|
||||
import Typography from 'material-ui/Typography';
|
||||
import List, { ListSubheader } from 'material-ui/List';
|
||||
import IconButton from 'material-ui/IconButton';
|
||||
import Icon from 'material-ui/Icon';
|
||||
import AppBar from 'material-ui/AppBar';
|
||||
|
||||
injectTapEventPlugin();
|
||||
|
||||
|
|
@ -23,36 +31,60 @@ const renderUi = (state: State, key: ?string) =>
|
|||
key != null && Config.controls[key] != null ?
|
||||
R.map(UiItem(state), Config.controls[key].ui) : null;
|
||||
|
||||
const App = (state: State) => {
|
||||
if (state == null) return (<div></div>);
|
||||
return (
|
||||
<div>
|
||||
<MuiThemeProvider>
|
||||
const theme = createMuiTheme({
|
||||
palette: {
|
||||
primary: orange
|
||||
}
|
||||
});
|
||||
|
||||
const appStyles = withStyles((theme) => ({
|
||||
drawerPaper: {
|
||||
width: 320
|
||||
}
|
||||
}));
|
||||
|
||||
class app extends React.Component<{state: State, classes: Object}> {
|
||||
render() {
|
||||
const state = this.props.state;
|
||||
const classes = this.props.classes;
|
||||
if (state == null) return (<div></div>);
|
||||
return (
|
||||
<div>
|
||||
<AppBar title="RZL Map" {...state} />
|
||||
<Drawer open={state.uiOpened != null}
|
||||
openSecondary={true} disableSwipeToOpen={true}>
|
||||
<Toolbar>
|
||||
<ToolbarGroup firstChild={true}>
|
||||
<ToolbarTitle text={
|
||||
state.uiOpened == null ? "" : Config.controls[state.uiOpened].name}
|
||||
style={{"marginLeft": 10}} />
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
<div id="drawer_uiComponents">
|
||||
{renderUi(state, state.uiOpened)}
|
||||
<MuiThemeProvider theme={theme}>
|
||||
<div>
|
||||
<SpaceMapBar title="RZL Map" {...state} />
|
||||
<Drawer open={state.uiOpened != null}
|
||||
anchor="right"
|
||||
onRequestClose={() => store.dispatch({type: Actions.CHANGE_UI})}
|
||||
classes={{paper: classes.drawerPaper}}
|
||||
type="persistent"
|
||||
>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<IconButton onClick={() => store.dispatch({type: Actions.CHANGE_UI})}>
|
||||
<Icon>keyboard_tab</Icon>
|
||||
</IconButton>
|
||||
<Typography type="title">
|
||||
{state.uiOpened == null ? "" : Config.controls[state.uiOpened].name}
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<List id="drawer_uiComponents">
|
||||
{renderUi(state, state.uiOpened)}
|
||||
</List>
|
||||
</Drawer>
|
||||
</div>
|
||||
</Drawer>
|
||||
</MuiThemeProvider>
|
||||
<SpaceMap width={1000} height={700} image="rzl.png" zoom={0.1} state={state} />
|
||||
</div>
|
||||
</MuiThemeProvider>
|
||||
<SpaceMap width={950} height={640} image="rzl.png" zoom={0.1} state={state} />
|
||||
</div>
|
||||
);}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const App = appStyles(app);
|
||||
|
||||
store.subscribe(() => ReactDOM.render(<App {...store.getState()} />, document.getElementById("content")));
|
||||
store.subscribe(() => ReactDOM.render(<App state={store.getState()} />, document.getElementById("content")));
|
||||
|
||||
store.dispatch({type:null});
|
||||
|
||||
// 192.168.178.6
|
||||
connectMqtt("ws://172.22.36.207:1884", store); // wss://mqtt.starletp9.de/mqtt", store);
|
||||
connectMqtt("ws://172.22.36.207:1884", store);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { Actions } from "./state";
|
|||
import { keyOf } from "./util";
|
||||
import { store } from "./state";
|
||||
|
||||
import ActionInfo from 'material-ui/svg-icons/action/info';
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
// convert width/height coordinates to -height/width coordinates
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ const handleEvent = (state: State = initState, action: StateAction) => {
|
|||
return match(action.type, {
|
||||
[Actions.MQTT_CONNECT ]: R.merge(state, { mqtt: action.payload }),
|
||||
[Actions.MQTT_MESSAGE ]: onMessage(state, action),
|
||||
[Actions.CHANGE_UI ]: R.merge(state, { uiOpened: action.payload })
|
||||
[Actions.CHANGE_UI ]: R.merge(state, { uiOpened: action.payload }),
|
||||
[null]: state
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ declare type Topic = {
|
|||
declare type Topics = Map<string,Topic>;
|
||||
|
||||
declare type ControlUI = {
|
||||
type: "toggle" | "dropDown" | "slider",
|
||||
type: "toggle" | "dropDown" | "slider" | "section",
|
||||
text: string,
|
||||
topic: string,
|
||||
topic?: string,
|
||||
icon?: string,
|
||||
|
||||
enableCondition?: (internal: string, actual: any) => boolean,
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ declare type ControlUI = {
|
|||
|
||||
// DROPDOWN optional properties
|
||||
options?: Map<string,any>, //options for dropDown
|
||||
renderValue?: (value: string) => string
|
||||
|
||||
// SLIDER optional properties
|
||||
min?: number,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue