diff --git a/config/rzl.js b/config/rzl.js index 6342361..840a383 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -122,7 +122,7 @@ const config : Config = { led_stahltrager: { name: "LED Stahlträger", position: [380, 300], - icon: "white-balance-iridescent mdi-rotate-90", + icon: "white-balance-iridescent rotate-90", iconColor: state => state.led_stahltraeger == "on" ? utils.rainbow : "#000000", ui: [ { @@ -150,7 +150,7 @@ const config : Config = { twinkle: { name: "Twinkle", position: [530, 560], - icon: "led-off mdi-flip-v", + icon: "led-off flip-v", iconColor: state => state.twinkle == "on" ? utils.rainbow : "#000000", ui: [ { @@ -399,18 +399,30 @@ const config : Config = { baseLayer: true, name: "RaumZeitLabor", defaultVisibility: "visible", - opacity: 0.7 + opacity: 0.7, + bounds: { + topLeft: [0, 0], + bottomRight: [1000, 700] + } }, { image: require("../img/layers/rzl/details.svg"), name: "Details", defaultVisibility: "visible", - opacity: 0.4 + opacity: 0.4, + bounds: { + topLeft: [0, 0], + bottomRight: [1000, 700] + } }, { image: require("../img/layers/rzl/labels.svg"), name: "Labels", - defaultVisibility: "visible" + defaultVisibility: "visible", + bounds: { + topLeft: [0, 0], + bottomRight: [1000, 700] + } } ] }; diff --git a/src/components/App.js b/src/components/App.js new file mode 100644 index 0000000..528aa6a --- /dev/null +++ b/src/components/App.js @@ -0,0 +1,63 @@ +// @flow +import React from "react"; + +import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"; +import createMuiTheme from "material-ui/styles/createMuiTheme"; +import withStyles from "material-ui/styles/withStyles"; +import * as Colors from "material-ui/colors"; + +import SideBar from "components/SideBar"; +import ControlMap from "components/ControlMap"; + +export type AppProps = { + config: Config +}; + +export type AppState = { + selectedControl: string +}; + +class App extends React.Component { + constructor(props: AppProps & Classes) { + super(props); + } + + static styles(_theme: Object) { + return { + drawerPaper: { + width: 320 + } + }; + } + + get theme() { + return createMuiTheme({ + palette: { + primary: Colors[this.props.config.space.color] + } + }); + } + + get selectedControl(): Control { + return this.props.config.controls[this.state.selectedControl]; + } + + // + render() { + return ( +
+ +
+ {false && } +
+
+ +
+ ); + } +} + +export default withStyles(App.styles)(App); diff --git a/src/components/ControlMap.js b/src/components/ControlMap.js new file mode 100644 index 0000000..26b9dc5 --- /dev/null +++ b/src/components/ControlMap.js @@ -0,0 +1,86 @@ +// @flow +import React from "react"; +import { Map, ImageOverlay, Marker, LayersControl } from "react-leaflet"; +import Leaflet from "leaflet"; + +export type Point = [number, number]; + +const convertPoint = (p: Point) => [-p[1], p[0]]; + +export type ControlMapProps = { + width: number, + height: number, + zoom: number, + layers: Array, + controls: Controls +}; + +export default class ControlMap extends React.Component { + constructor(props: SpaceMapProps) { + super(props); + } + + get center(): Point { + return convertPoint([ + this.props.width / 2, + this.props.height / 2 + ]); + } + + render() { + return ( + + {this.renderMarkers()} + {this.renderLayers()} + + ); + } + + renderMarkers() { + return Object.values(this.props.controls).map(this.renderMarker.bind(this)); + } + + createLeafletIcon(iconRaw: string) { + const icon = iconRaw.split(" ").map(name => "mdi-".concat(name)).join(" "); + return Leaflet.divIcon({ + className: `mdi mdi-36px ${icon}`, + iconSize: Leaflet.point(36, 36), + iconAnchor: Leaflet.point(18, 18) + }); + } + + renderMarker(control: Control) { + return ( + + + ); + } + + renderLayers() { + return ( + + {this.props.layers.map(this.renderLayer)} + + ); + } + + renderLayer(layer: Layer) { + const LayersControlType = + layer.baseLayer ? LayersControl.BaseLayer : LayersControl.Overlay; + return ( + + + + ); + } +} diff --git a/src/components/SideBar.js b/src/components/SideBar.js new file mode 100644 index 0000000..421025b --- /dev/null +++ b/src/components/SideBar.js @@ -0,0 +1,62 @@ +// @flow +import React from "react"; + +import withStyles from "material-ui/styles/withStyles"; +import Drawer from "material-ui/Drawer"; +import Typography from "material-ui/Typography"; +import IconButton from "material-ui/IconButton"; +import AppBar from "material-ui/AppBar"; +import Toolbar from "material-ui/Toolbar"; +import List from "material-ui/List"; + +export type SideBarProps = { + control: Control, + onCloseRequest: () => void +}; + +export type SideBarState = { +}; + +class SideBar extends React.Component { + constructor(props: SideBarProps & Classes) { + super(props); + } + + static styles(_theme: Object): Object { + return { + drawerPaper: { + width: 320 + } + }; + } + + close() { + this.props.onCloseRequest(); + } + + render() { + return ( + + + + + + + + {this.props.control.name} + + + + + + + ); + } +} + +export default withStyles(SideBar.styles)(SideBar); diff --git a/src/index.jsx b/src/index.jsx index 3c098e6..3e9376d 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,24 +1,11 @@ // @flow 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, Actions } from "./state"; -import connectMqtt from "./mqtt"; -import SpaceMapBar from "./appbar"; -import * as UiItems from "./UiItems.js"; -import SpaceMap from "./map.js"; -import R from "ramda"; + +import App from "components/App"; + import Config from "./config"; -import Toolbar from "material-ui/Toolbar"; -import * as colors from "material-ui/colors"; -import Typography from "material-ui/Typography"; -import List from "material-ui/List"; -import IconButton from "material-ui/IconButton"; -import AppBar from "material-ui/AppBar"; import "../node_modules/mdi/css/materialdesignicons.min.css"; import "../css/styles.css"; @@ -27,67 +14,4 @@ injectTapEventPlugin(); document.title = `${Config.space.name} Map`; -const UiItem = (state) => (props : ControlUI) => - UiItems[props.type](state, props); - -const renderUi = (state: State, key: ?string) => - key != null && Config.controls[key] != null ? - R.map(UiItem(state), Config.controls[key].ui) : null; - -const theme = createMuiTheme({ - palette: { - primary: colors[Config.space.color] - } -}); - -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 (
); - return ( -
- -
- - store.dispatch({type: Actions.CHANGE_UI})} - classes={{paper: classes.drawerPaper}} - type="persistent" - > - - - store.dispatch({type: Actions.CHANGE_UI})}> - - - - {state.uiOpened == null ? "" : Config.controls[state.uiOpened].name} - - - - - {renderUi(state, state.uiOpened)} - - -
-
- -
- ); - } -} - -const App = appStyles(app); - -store.subscribe(() => ReactDOM.render(, document.getElementById("content"))); - -store.dispatch({type:null}); - -connectMqtt(Config.space.mqtt, store); +ReactDOM.render(, document.getElementById("content")); diff --git a/types/types.js b/types/types.js index a65abad..4bb1414 100644 --- a/types/types.js +++ b/types/types.js @@ -1,5 +1,9 @@ declare type Map = { [K]: V }; +declare type Classes = { + classes: Map +}; + declare type Topic = { state: string, command: string, @@ -23,7 +27,7 @@ declare type ControlUI = { // TOGGLE optional properties on?: string, // on override for toggle off?: string, // off override for toggle - toggled?: (internal: string, actual: any) => boolean, + toggled?: (internal: string, actual: any, state: Map) => boolean, // DROPDOWN optional properties options?: Map, //options for dropDown @@ -70,12 +74,18 @@ declare type State = { visibleLayers: Array }; +declare type Point = [number, number]; + declare type Layer = { image: string, name: string, baseLayer: boolean, defaultVisibility: "visible" | "hidden", - opacity: number + opacity: number, + bounds: { + topLeft: Point, + bottomRight: Point + } }; declare type StateAction = { diff --git a/webpack.common.js b/webpack.common.js index 0ca1564..31d08f1 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -11,6 +11,7 @@ const preBuildScripts = process.env.NO_FLOW == undefined ? module.exports = { resolve: { + modules: [path.resolve(__dirname, "src"), "node_modules"], extensions: ['.js', '.jsx'] }, output: {