Update to material-ui 1.0 beta

This commit is contained in:
uwap 2017-10-31 17:01:12 +01:00
parent 48a96b57fa
commit bef07649d0
14 changed files with 1164 additions and 395 deletions

View file

@ -1,5 +1,4 @@
[ignore] [ignore]
.*node_modules/react-event-listener/.*
[include] [include]
src/ src/

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
img/layers/rzl/rooms.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -57,11 +57,14 @@
/* Support for IE. */ /* Support for IE. */
font-feature-settings: 'liga'; font-feature-settings: 'liga';
} }
#drawer_uiComponents .material-icons {
font-size: 24px;
}
</style> </style>
</head> </head>
<body> <body>
<div id="content"> <div id="content">
</div> </div>
<script src="public/dist/main.js"></script> <script src="dist/main.js"></script>
</body> </body>

View file

@ -1,8 +1,8 @@
{ {
"name": "reacttest", "name": "spacemap",
"version": "1.0.0", "version": "1.0.0",
"author": "uwap <me@uwap.name>", "author": "uwap <me+spacemap.package.json@uwap.name>",
"description": "react", "description": "control devices via mqtt on a beautiful map of your space",
"scripts": { "scripts": {
"build": "webpack --bail", "build": "webpack --bail",
"watch": "webpack --watch" "watch": "webpack --watch"
@ -10,7 +10,8 @@
"dependencies": { "dependencies": {
"babel-preset-env": "^1.6.0", "babel-preset-env": "^1.6.0",
"leaflet": "^1.2.0", "leaflet": "^1.2.0",
"material-ui": "^0.18.7", "material-ui": "next",
"material-ui-old": "npm:material-ui@latest",
"mqtt": "^2.11.0", "mqtt": "^2.11.0",
"ramda": "^0.24.1", "ramda": "^0.24.1",
"react": "^15.6.1", "react": "^15.6.1",
@ -26,6 +27,7 @@
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"flow": "^0.2.3", "flow": "^0.2.3",
"flow-bin": "^0.50.0", "flow-bin": "^0.50.0",
"flow-typed": "^2.2.1",
"webpack": "^3.1.0", "webpack": "^3.1.0",
"webpack-shell-plugin": "^0.5.0" "webpack-shell-plugin": "^0.5.0"
}, },

View file

@ -1,26 +1,38 @@
// @flow // @flow
import React from "react"; import React from "react";
import Toggle from "material-ui/Toggle"; import Switch from "material-ui/Switch";
import SelectField from 'material-ui/SelectField'; import Select from 'material-ui/Select';
import MenuItem from 'material-ui/MenuItem'; import { MenuItem } from 'material-ui/Menu';
import Slider from 'material-ui/Slider'; 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 Config from "./config";
import { keyOf } from "./util"; import { keyOf } from "./util";
import Input, { InputLabel } from 'material-ui/Input';
import { FormControl } from 'material-ui/Form';
import R from "ramda"; import R from "ramda";
import List, {
ListItem,
ListItemIcon,
ListItemSecondaryAction,
ListItemText,
ListSubheader,
} from 'material-ui/List';
const enabled = (props: ControlUI, state: State) => { const enabled = (props: ControlUI, state: State) => {
if (props.enableCondition == null) return true; if (props.enableCondition == null) return true;
else { else {
const val = state.values[props.topic]; const val = state.values[props.topic];
return props.enableCondition( 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) => const getValue = (topic: string, val: string) =>
Config.topics[topic].values[val]; Config.topics[topic].values[val];
const onToggle = (topic: string, props: ControlUI, state: State) => const onSwitch = (topic: string, props: ControlUI, state: State) =>
(x, toggled: boolean) => { (x, toggled: boolean) => {
if (state.mqtt != null) { if (state.mqtt != null) {
state.mqtt.publish(Config.topics[topic].command, 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 val.internal === R.propOr("on", "on", props);
} }
})(); })();
return (<Toggle label={props.text} return (
toggled={toggled} <ListItem>
onToggle={onToggle(props.topic, props, state)} {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))} /> disabled={!(enabled(props, state))} />
</ListItemSecondaryAction>
</ListItem>
); );
} }
const onDropDownChange = (topic: string, props: ControlUI, state: State) => const onDropDownChange = (topic: string, props: ControlUI, state: State) =>
(event, index, value) => { (event) => {
if (state.mqtt != null) { 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) => ( 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) => ( export const dropDown = (state: State, props: ControlUI) => {
<SelectField value={state.values[props.topic].actual} 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)} onChange={onDropDownChange(props.topic, props, state)}
disabled={!(enabled(props, state))}> disabled={!(enabled(props, state))}
input={<Input id={id} />}
>
{R.values(R.mapObjIndexed(dropDownItem(props.topic), props.options))} {R.values(R.mapObjIndexed(dropDownItem(props.topic), props.options))}
</SelectField> </Select>
</FormControl>
</ListItem>
); );
};
const onSliderChange = (state: State, props: ControlUI) => const onSliderChange = (state: State, props: ControlUI) =>
(event, value) => { (event, value) => {
@ -73,13 +103,22 @@ const onSliderChange = (state: State, props: ControlUI) =>
}; };
export const slider = (state: State, props: ControlUI) => ( export const slider = (state: State, props: ControlUI) => (
<div> <ListItem>
<span>{props.text}</span> {props.icon && <ListItemIcon><Icon>{props.icon}</Icon></ListItemIcon>}
<ListItemText primary={props.text} />
<ListItemSecondaryAction>
<MuiThemeProvider>
<Slider value={state.values[props.topic].actual} <Slider value={state.values[props.topic].actual}
min={props.min == null ? 0 : props.min} min={props.min == null ? 0 : props.min}
max={props.max == null ? 1 : props.max} max={props.max == null ? 1 : props.max}
step={props.step == null ? 1 : props.step} step={props.step == null ? 1 : props.step}
onChange={onSliderChange(state, props)} onChange={onSliderChange(state, props)}
/> style={{width: 100}}
</div> /></MuiThemeProvider>
</ListItemSecondaryAction>
</ListItem>
);
export const section = (state: State, props: ControlUI) => (
<ListSubheader>{props.text}</ListSubheader>
); );

View file

@ -1,57 +1,44 @@
// @flow // @flow
import React from "react"; import React from "react";
import AppBar from "material-ui/AppBar"; import AppBar from "material-ui/AppBar";
import CircularProgress from "material-ui/CircularProgress"; import Toolbar from 'material-ui/Toolbar';
import MapIcon from "material-ui/svg-icons/maps/map"; import { CircularProgress } from "material-ui/Progress";
import PhonelinkOffIcon from "material-ui/svg-icons/hardware/phonelink-off"; import Icon from 'material-ui/Icon';
import LayersIcon from "material-ui/svg-icons/maps/layers";
import IconMenu from "material-ui/IconMenu";
import IconButton from "material-ui/IconButton"; import IconButton from "material-ui/IconButton";
import MenuItem from "material-ui/MenuItem"; import Menu, { MenuItem } from "material-ui/Menu";
import { orange400, grey50 } from "material-ui/styles/colors"; import Typography from 'material-ui/Typography';
const TopBarLayerSelector = (props: Object) => ( const TopBarLayerSelector = (props: Object) => (
<IconMenu <IconButton>
iconButtonElement={ <Icon>layers</Icon>
<IconButton style={{width: 48, height: 48, padding: 0}} </IconButton>
iconStyle={{width: 48, height: 48}}>
<LayersIcon color={grey50} />
</IconButton>}
style={{width:48, height:48}}>
<MenuItem primaryText="Layer1" />
</IconMenu>
) )
const TopBarIndicatorMenu = (props: Object) => ( const TopBarIndicatorMenu = (props: Object) => (
<IconMenu <IconButton>
iconButtonElement={
<IconButton style={{width:48, height:48, padding: 0}}
iconStyle={{width:48, height: 48}}
tooltip={props.mqtt.connected ? "Connected!" : "Disconnected!"}>
{props.mqtt.connected ? {props.mqtt.connected ?
(<MapIcon color={grey50} />) : (<Icon style={{fontSize: 48}}>map</Icon>) :
(<PhonelinkOffIcon color={grey50} />)} (<Icon style={{fontSize: 48}}>phonelink_off</Icon>)}
</IconButton>} </IconButton>
style={{width:48, height:48}}>
<MenuItem primaryText="Reconnect (Not yet implemented)" />
</IconMenu>
); );
const TopBarIndicator = (props: Object) => { const TopBarIndicator = (props: Object) => {
if (props.mqtt == null || props.mqtt.reconnecting) { 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 { } else {
return (<TopBarIndicatorMenu {...props} />); return (<TopBarIndicatorMenu {...props} />);
} }
}; };
const TopBar = (props: Object) => ( const TopBar = (props: Object) => (
<AppBar title={props.title} <AppBar position="static">
style={{background:orange400}} <Toolbar>
iconElementLeft={<TopBarIndicator {...props} />} <TopBarIndicator {...props} />
iconElementRight={<TopBarLayerSelector {...props} />} <Typography type="title">{props.title}</Typography>
className="nav" {false && <TopBarLayerSelector {...props} />}
/>); </Toolbar>
</AppBar>
);
export default TopBar; export default TopBar;

View file

@ -51,6 +51,20 @@ const config : Config = {
blue: "blue", green: "green", red: "red", random: "random", blue: "blue", green: "green", red: "red", random: "random",
cycle: "cycle-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: { onkyo_volume: {
state: "/service/onkyo/status/volume", state: "/service/onkyo/status/volume",
command: "/service/onkyo/set/volume", command: "/service/onkyo/set/volume",
@ -62,9 +76,16 @@ const config : Config = {
state: "/service/onkyo/status/input-selector", state: "/service/onkyo/status/input-selector",
command: "/service/onkyo/command", command: "/service/onkyo/command",
defaultValue: "SLI00", 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 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: { rundumleuchte: {
state: "/service/openhab/out/pca301_rundumleuchte/state", state: "/service/openhab/out/pca301_rundumleuchte/state",
command: "/service/openhab/in/pca301_rundumleuchte/command", command: "/service/openhab/in/pca301_rundumleuchte/command",
@ -87,98 +108,105 @@ const config : Config = {
controls: { controls: {
led_stahltrager: { led_stahltrager: {
name: "LED Stahlträger", name: "LED Stahlträger",
position: [390, 100], position: [380, 300],
icon: "wb_incandescent", icon: "wb_incandescent",
iconColor: state => state.led_stahltraeger == "on" ? "#CCCC00" : "#000000", iconColor: state => state.led_stahltraeger == "on" ? "#CCCC00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Stahlträger LED", text: "Stahlträger LED",
topic: "led_stahltraeger" topic: "led_stahltraeger",
icon: "power_settings_new"
}, },
] ]
}, },
snackbar: { snackbar: {
name: "Snackbar", name: "Snackbar",
position: [560, 465], position: [510, 500],
icon: "kitchen", icon: "kitchen",
iconColor: state => state.snackbar == "on" ? "#E20074" : "#000000", iconColor: state => state.snackbar == "on" ? "#E20074" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Snackbar", text: "Snackbar",
topic: "snackbar" topic: "snackbar",
icon: "power_settings_new"
} }
] ]
}, },
twinkle: { twinkle: {
name: "Twinkle", name: "Twinkle",
position: [500, 540], position: [530, 560],
icon: "wb_incandescent", icon: "wb_incandescent",
iconColor: state => state.twinkle == "on" ? "#CCCC00" : "#000000", iconColor: state => state.twinkle == "on" ? "#CCCC00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Twinkle", text: "Twinkle",
topic: "twinkle" topic: "twinkle",
icon: "power_settings_new"
} }
] ]
}, },
fan: { fan: {
name: "Ventilator", name: "Ventilator",
position: [530, 450], position: [510, 460],
icon: "toys", icon: "toys",
iconColor: state => state.fan == "on" ? "#00FF00" : "#000000", iconColor: state => state.fan == "on" ? "#00FF00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Ventilator", text: "Ventilator",
topic: "fan" topic: "fan",
icon: "power_settings_new"
} }
] ]
}, },
videogames: { videogames: {
name: "Videospiele", name: "Videospiele",
position: [79, 50], position: [100, 100],
icon: "videogame_asset", icon: "videogame_asset",
iconColor: state => state.videogames == "on" ? "#00FF00" : "#000000", iconColor: state => state.videogames == "on" ? "#00FF00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Videospiele", text: "Videospiele",
topic: "videogames" topic: "videogames",
icon: "power_settings_new"
} }
] ]
}, },
olymp_pc: { olymp_pc: {
name: "Rechner und Drucker", name: "Rechner und Drucker",
position: [298, 20], position: [297, 90],
icon: "desktop_windows", icon: "desktop_windows",
iconColor: state => state.olymp_pc == "on" ? "#00FF00" : "#000000", iconColor: state => state.olymp_pc == "on" ? "#00FF00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Rechner und Drucker", text: "Rechner und Drucker",
topic: "olymp_pc" topic: "olymp_pc",
icon: "power_settings_new"
} }
] ]
}, },
flyfry: { flyfry: {
name: "Fliegenbratgerät", name: "Fliegenbratgerät",
position: [450, 560], position: [450, 590],
icon: "whatshot", icon: "whatshot",
iconColor: state => state.flyfry == "on" ? "#6666FF" : "#000000", iconColor: state => state.flyfry == "on" ? "#6666FF" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Fliegenbratgerät", text: "Fliegenbratgerät",
topic: "flyfry" topic: "flyfry",
icon: "power_settings_new"
} }
] ]
}, },
artnet: { artnet: {
name: "Artnet", name: "Artnet",
position: [560,430], position: [535,475],
icon: "wb_incandescent", icon: "wb_incandescent",
iconColor: state => iconColor: state =>
({ ({
@ -195,77 +223,121 @@ const config : Config = {
text: "An/Aus", text: "An/Aus",
topic: "artnet", topic: "artnet",
on: "cycle", on: "cycle",
toggled: val => val != "off" toggled: val => val != "off",
icon: "power_settings_new"
}, },
{ {
type: "dropDown", type: "dropDown",
text: "Artnet", text: "Farbe",
topic: "artnet", topic: "artnet",
options: { options: {
yellow: "Gelb", yellow: "Gelb",
red: "Rot", red: "Rot",
purple: "Pink", purple: "Pink",
green: "Grün", green: "Grün",
cycle: "Cycle Random" cycle: "Farbwechsel"
}, },
enableCondition: val => val != "off" enableCondition: val => val != "off",
icon: "color_lens"
} }
] ]
}, },
onkyo: { onkyo: {
name: "Onkyo", name: "Onkyo",
position: [350, 620], position: [350, 650],
icon: "volume_up", icon: "volume_up",
ui: [ ui: [
{
type: "toggle",
text: "Power",
icon: "power_settings_new",
topic: "onkyo_power"
},
{
type: "section",
text: "Lautstärkeregelung"
},
{ {
type: "slider", type: "slider",
text: "Volume", text: "Volume",
topic: "onkyo_volume", topic: "onkyo_volume",
min: 0, 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", type: "dropDown",
text: "Inputs", text: "Eingang",
topic: "onkyo_inputs", topic: "onkyo_inputs",
options: { options: {
netzwerk: "Netzwerk",
tisch: "Tisch", tisch: "Tisch",
chromecast: "Chromecast", chromecast: "Chromecast",
pult: "Pult" 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: { rundumleuchte: {
name: "Rundumleuchte", name: "Rundumleuchte",
position: [310,220], position: [310,275],
icon: "wb_sunny", icon: "wb_sunny",
iconColor: state => state.rundumleuchte == "on" ? "#CCCC00" : "#000000", iconColor: state => state.rundumleuchte == "on" ? "#CCCC00" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Rundumleuchte", text: "Rundumleuchte",
topic: "rundumleuchte" topic: "rundumleuchte",
icon: "power_settings_new"
} }
] ]
}, },
door: { door: {
name: "Tür", name: "Tür",
position: [480,300], position: [455,350],
icon: "swap_vert", icon: "swap_vert",
iconColor: state => state.door_status == "on" ? "#00FF00" : "#FF0000", iconColor: state => state.door_status == "on" ? "#00FF00" : "#FF0000",
ui: [] ui: []
}, },
infoscreen: { infoscreen: {
name: "Infoscreen", name: "Infoscreen",
position: [255, 455], position: [255, 495],
icon: "developer_board", icon: "developer_board",
iconColor: state => state.infoscreen == "on" ? "#4444FF" : "#000000", iconColor: state => state.infoscreen == "on" ? "#4444FF" : "#000000",
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Infoscreen", text: "Infoscreen",
topic: "infoscreen" topic: "infoscreen",
icon: "power_settings_new"
} }
] ]
} }

View file

@ -2,17 +2,25 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; 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 Drawer from 'material-ui/Drawer';
import injectTapEventPlugin from 'react-tap-event-plugin'; import injectTapEventPlugin from 'react-tap-event-plugin';
import { store } from "./state"; import { store, Actions } from "./state";
import connectMqtt from "./mqtt"; import connectMqtt from "./mqtt";
import AppBar from "./appbar"; import SpaceMapBar from "./appbar";
import Toggle from "material-ui/Toggle"; import Switch from "material-ui/Switch";
import * as UiItems from "./UiItems.js"; import * as UiItems from "./UiItems.js";
import SpaceMap from "./map.js"; import SpaceMap from "./map.js";
import R from "ramda"; import R from "ramda";
import Config from "./config"; 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(); injectTapEventPlugin();
@ -23,36 +31,60 @@ const renderUi = (state: State, key: ?string) =>
key != null && Config.controls[key] != null ? key != null && Config.controls[key] != null ?
R.map(UiItem(state), Config.controls[key].ui) : null; R.map(UiItem(state), Config.controls[key].ui) : null;
const App = (state: State) => { 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>); if (state == null) return (<div></div>);
return ( return (
<div> <div>
<MuiThemeProvider> <MuiThemeProvider theme={theme}>
<div> <div>
<AppBar title="RZL Map" {...state} /> <SpaceMapBar title="RZL Map" {...state} />
<Drawer open={state.uiOpened != null} <Drawer open={state.uiOpened != null}
openSecondary={true} disableSwipeToOpen={true}> anchor="right"
onRequestClose={() => store.dispatch({type: Actions.CHANGE_UI})}
classes={{paper: classes.drawerPaper}}
type="persistent"
>
<AppBar position="static">
<Toolbar> <Toolbar>
<ToolbarGroup firstChild={true}> <IconButton onClick={() => store.dispatch({type: Actions.CHANGE_UI})}>
<ToolbarTitle text={ <Icon>keyboard_tab</Icon>
state.uiOpened == null ? "" : Config.controls[state.uiOpened].name} </IconButton>
style={{"marginLeft": 10}} /> <Typography type="title">
</ToolbarGroup> {state.uiOpened == null ? "" : Config.controls[state.uiOpened].name}
</Typography>
</Toolbar> </Toolbar>
<div id="drawer_uiComponents"> </AppBar>
<List id="drawer_uiComponents">
{renderUi(state, state.uiOpened)} {renderUi(state, state.uiOpened)}
</div> </List>
</Drawer> </Drawer>
</div> </div>
</MuiThemeProvider> </MuiThemeProvider>
<SpaceMap width={950} height={640} image="rzl.png" zoom={0.1} state={state} /> <SpaceMap width={1000} height={700} image="rzl.png" zoom={0.1} state={state} />
</div> </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}); store.dispatch({type:null});
// 192.168.178.6 connectMqtt("ws://172.22.36.207:1884", store);
connectMqtt("ws://172.22.36.207:1884", store); // wss://mqtt.starletp9.de/mqtt", store);

View file

@ -8,7 +8,6 @@ import { Actions } from "./state";
import { keyOf } from "./util"; import { keyOf } from "./util";
import { store } from "./state"; import { store } from "./state";
import ActionInfo from 'material-ui/svg-icons/action/info';
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
// convert width/height coordinates to -height/width coordinates // convert width/height coordinates to -height/width coordinates

View file

@ -55,7 +55,8 @@ const handleEvent = (state: State = initState, action: StateAction) => {
return match(action.type, { return match(action.type, {
[Actions.MQTT_CONNECT ]: R.merge(state, { mqtt: action.payload }), [Actions.MQTT_CONNECT ]: R.merge(state, { mqtt: action.payload }),
[Actions.MQTT_MESSAGE ]: onMessage(state, action), [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
}); });
} }

View file

@ -10,9 +10,10 @@ declare type Topic = {
declare type Topics = Map<string,Topic>; declare type Topics = Map<string,Topic>;
declare type ControlUI = { declare type ControlUI = {
type: "toggle" | "dropDown" | "slider", type: "toggle" | "dropDown" | "slider" | "section",
text: string, text: string,
topic: string, topic?: string,
icon?: string,
enableCondition?: (internal: string, actual: any) => boolean, enableCondition?: (internal: string, actual: any) => boolean,
@ -23,6 +24,7 @@ declare type ControlUI = {
// DROPDOWN optional properties // DROPDOWN optional properties
options?: Map<string,any>, //options for dropDown options?: Map<string,any>, //options for dropDown
renderValue?: (value: string) => string
// SLIDER optional properties // SLIDER optional properties
min?: number, min?: number,

1163
yarn.lock

File diff suppressed because it is too large Load diff