Merge branch 'master' into patch-10

This commit is contained in:
uwap 2018-06-24 16:39:47 +02:00 committed by GitHub
commit 4388de10c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 288 additions and 261 deletions

View file

@ -8,9 +8,9 @@
1. run `yarn` to install all dependencies. 1. run `yarn` to install all dependencies.
2. run `yarn watch CONFIG` to run a local build server that automatically builds 2. run `yarn watch CONFIG` to run a local build server that automatically builds
your the mqtt control map for the given CONFIG everytime something changes. your the mqtt control map for the given CONFIG everytime something changes.
3. run `yarn build CONFIG` to create just a single build of the mqtt control map 3. run `yarn dev CONFIG` to create just a single build of the mqtt control map
for the given config. for the given config.
4. run `yarn production-build CONFIG` to generate all files for production use. 4. run `yarn build CONFIG` to generate all files for production use.
## Config ## Config

View file

@ -1,6 +1,7 @@
// @flow // @flow
import type { Config } from "config/flowtypes"; import type { Config } from "config/flowtypes";
import { hex, rgb, rgba, rainbow } from "config/colors"; import { hex, rgb, rgba, rainbow } from "config/colors";
import { mdi } from "config/icon";
import { esper_topics, esper_statistics } from "./utils"; import { esper_topics, esper_statistics } from "./utils";
const config : Config = { const config : Config = {
@ -29,20 +30,20 @@ const config : Config = {
hauptraum_table_light: { hauptraum_table_light: {
name: "Hauptraum Tisch", name: "Hauptraum Tisch",
position: [450, 450], position: [450, 450],
icon: "white-balance-iridescent", icon: mdi("white-balance-iridescent"),
iconColor: () => hex("#000000"), iconColor: () => hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Licht", text: "Licht",
topic: "hauptraum_table_light", topic: "hauptraum_table_light",
icon: "power" icon: mdi("power")
}, },
{ {
type: "toggle", type: "toggle",
text: "Licht", text: "Licht",
topic: "hauptraum_table_light_on_hack", topic: "hauptraum_table_light_on_hack",
icon: "power" icon: mdi("power")
} }
] ]
} }

View file

@ -2,6 +2,7 @@
import type { Config } from "config/flowtypes"; import type { Config } from "config/flowtypes";
import * as types from "config/types"; import * as types from "config/types";
import { hex, rgb, rgba, rainbow } from "config/colors"; import { hex, rgb, rgba, rainbow } from "config/colors";
import { mdi, raw_mdi } from "config/icon";
import { esper_topics, esper_statistics, floalt, tradfri_remote } from "./utils"; import { esper_topics, esper_statistics, floalt, tradfri_remote } from "./utils";
const config : Config = { const config : Config = {
@ -48,6 +49,12 @@ const config : Config = {
defaultValue: "OFF", defaultValue: "OFF",
values: { on: "ON", off: "OFF" } values: { on: "ON", off: "OFF" }
}, },
olymp_printer: {
state: "stat/sonoff2/POWER",
command: "cmnd/sonoff2/power",
defaultValue: "OFF",
values: { on: "ON", off: "OFF" }
},
flyfry: { flyfry: {
state: "/service/openhab/out/wifi_flyfry/state", state: "/service/openhab/out/wifi_flyfry/state",
command: "/service/openhab/in/wifi_flyfry/command", command: "/service/openhab/in/wifi_flyfry/command",
@ -204,63 +211,64 @@ const config : Config = {
led_stahltrager: { led_stahltrager: {
name: "LED Stahlträger", name: "LED Stahlträger",
position: [380, 590], position: [380, 590],
icon: "white-balance-iridescent", icon: mdi("white-balance-iridescent"),
iconColor: ({led_stahltraeger}) => led_stahltraeger == "on" ? rainbow : hex("#000000"), iconColor: ({led_stahltraeger}) => led_stahltraeger == "on" ? rainbow : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Stahlträger LED", text: "Stahlträger LED",
topic: "led_stahltraeger", topic: "led_stahltraeger",
icon: "power" icon: mdi("power")
}, },
] ]
}, },
snackbar: { snackbar: {
name: "Snackbar", name: "Snackbar",
position: [510, 500], position: [510, 500],
icon: "fridge", icon: mdi("fridge"),
iconColor: ({snackbar}) => snackbar == "on" ? hex("#E20074") : hex("#000000"), iconColor: ({snackbar}) => snackbar == "on" ? hex("#E20074") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Snackbar", text: "Snackbar",
topic: "snackbar", topic: "snackbar",
icon: "power" icon: mdi("power")
} }
] ]
}, },
twinkle: { twinkle: {
name: "Twinkle", name: "Twinkle",
position: [530, 560], position: [530, 560],
icon: ({twinkle}) => twinkle == "on" ? "led-on flip-v" : "led-off flip-v", icon: ({twinkle}) =>
twinkle == "on" ? raw_mdi("led-on flip-v") : raw_mdi("led-off flip-v"),
iconColor: ({twinkle}) => twinkle == "on" ? rainbow : hex("#000000"), iconColor: ({twinkle}) => twinkle == "on" ? rainbow : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Twinkle", text: "Twinkle",
topic: "twinkle", topic: "twinkle",
icon: "power" icon: mdi("power")
} }
] ]
}, },
fan: { fan: {
name: "Ventilator", name: "Ventilator",
position: [520, 450], position: [520, 450],
icon: "fan", icon: mdi("fan"),
iconColor: ({fan}) => fan == "on" ? hex("#00FF00") : hex("#000000"), iconColor: ({fan}) => fan == "on" ? hex("#00FF00") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Ventilator", text: "Ventilator",
topic: "fan", topic: "fan",
icon: "power" icon: mdi("power")
} }
] ]
}, },
cashdesk: { cashdesk: {
name: "Cashdesk", name: "Cashdesk",
position: [500, 470], position: [500, 470],
icon: "coin", icon: mdi("coin"),
ui: [ ui: [
{ {
type: "link", type: "link",
@ -272,49 +280,68 @@ const config : Config = {
videogames: { videogames: {
name: "Videospiele", name: "Videospiele",
position: [100, 100], position: [100, 100],
icon: "gamepad-variant", icon: mdi("gamepad-variant"),
iconColor: ({videogames}) => videogames == "on" ? hex("#00FF00") : hex("#000000"), iconColor: ({videogames}) => videogames == "on" ? hex("#00FF00") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Videospiele", text: "Videospiele",
topic: "videogames", topic: "videogames",
icon: "power" icon: mdi("power")
} }
] ]
}, },
olymp_pc: { olymp_pc: {
name: "Rechner und Drucker", name: "Rechner",
position: [297, 90], position: [297, 90],
icon: "desktop-classic", icon: mdi("desktop-classic"),
iconColor: ({olymp_pc}) => olymp_pc == "on" ? hex("#00FF00") : hex("#000000"), iconColor: ({olymp_pc}) => olymp_pc == "on" ? hex("#00FF00") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Rechner und Drucker", text: "Rechner",
topic: "olymp_pc", topic: "olymp_pc",
icon: mdi("power")
}
]
},
olymp_printer: {
name: "Drucker",
position: [335, 90],
icon: "printer",
iconColor: ({olymp_printer}) => olymp_printer == "on" ? hex("#00FF00") : hex("#000000"),
ui: [
{
type: "toggle",
text: "Drucker",
topic: "olymp_printer",
icon: "power" icon: "power"
},
{
type: "link",
link: "http://annette.rzl/",
text: "Open Annette"
} }
] ]
}, },
flyfry: { flyfry: {
name: "Fliegenbratgerät", name: "Fliegenbratgerät",
position: [450, 590], position: [450, 590],
icon: "fire", icon: mdi("fire"),
iconColor: ({flyfry}) => flyfry == "on" ? hex("#6666FF") : hex("#000000"), iconColor: ({flyfry}) => flyfry == "on" ? hex("#6666FF") : hex("#000000"),
ui: esper_statistics("flyfry", [ ui: esper_statistics("flyfry", [
{ {
type: "toggle", type: "toggle",
text: "Fliegenbratgerät", text: "Fliegenbratgerät",
topic: "flyfry", topic: "flyfry",
icon: "power" icon: mdi("power")
} }
]) ])
}, },
artnet: { artnet: {
name: "Artnet", name: "Artnet",
position: [535,480], position: [535,480],
icon: "spotlight", icon: mdi("spotlight"),
iconColor: ({artnet}) => iconColor: ({artnet}) =>
({ ({
off: hex("#000000"), off: hex("#000000"),
@ -331,7 +358,7 @@ const config : Config = {
topic: "artnet", topic: "artnet",
on: "cycle", on: "cycle",
toggled: val => val != "off", toggled: val => val != "off",
icon: "power" icon: mdi("power")
}, },
{ {
type: "dropDown", type: "dropDown",
@ -345,7 +372,7 @@ const config : Config = {
cycle: "Farbwechsel" cycle: "Farbwechsel"
}, },
enableCondition: val => val != "off", enableCondition: val => val != "off",
icon: "palette" icon: mdi("palette")
} }
] ]
}, },
@ -354,12 +381,12 @@ const config : Config = {
position: [350, 650], position: [350, 650],
iconColor: ({onkyo_connection, onkyo_power}) => iconColor: ({onkyo_connection, onkyo_power}) =>
onkyo_connection != "connected" ? hex("#888888") : (onkyo_power == "on" ? hex("#00FF00") : hex("#000000")), onkyo_connection != "connected" ? hex("#888888") : (onkyo_power == "on" ? hex("#00FF00") : hex("#000000")),
icon: "volume-high", icon: mdi("audio-video"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Power", text: "Power",
icon: "power", icon: mdi("power"),
topic: "onkyo_power", topic: "onkyo_power",
enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected"
}, },
@ -373,14 +400,14 @@ const config : Config = {
topic: "onkyo_volume", topic: "onkyo_volume",
min: 0, min: 0,
max: 50, max: 50,
icon: "volume-high", icon: mdi("volume-high"),
enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected"
}, },
{ {
type: "toggle", type: "toggle",
text: "Mute", text: "Mute",
topic: "onkyo_mute", topic: "onkyo_mute",
icon: "volume-off", icon: mdi("volume-off"),
enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected"
}, },
{ {
@ -398,7 +425,7 @@ const config : Config = {
pult: "Pult", pult: "Pult",
front: "Front HDMI" front: "Front HDMI"
}, },
icon: "usb", icon: mdi("usb"),
enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected"
}, },
{ {
@ -417,7 +444,7 @@ const config : Config = {
somafm_beatblender: "Beat Blender (Soma FM)", somafm_beatblender: "Beat Blender (Soma FM)",
ponyville: "Ponyville FM" ponyville: "Ponyville FM"
}, },
icon: "radio", icon: mdi("radio"),
enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" && state.onkyo_inputs.internal == "netzwerk" enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" && state.onkyo_inputs.internal == "netzwerk"
}, },
{ {
@ -434,28 +461,28 @@ const config : Config = {
rundumleuchte: { rundumleuchte: {
name: "Rundumleuchte", name: "Rundumleuchte",
position: [310,275], position: [310,275],
icon: "alarm-light", icon: mdi("alarm-light"),
iconColor: ({rundumleuchte}) => rundumleuchte == "on" ? hex("#F0DF10") : hex("#000000"), iconColor: ({rundumleuchte}) => rundumleuchte == "on" ? hex("#F0DF10") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Rundumleuchte", text: "Rundumleuchte",
topic: "rundumleuchte", topic: "rundumleuchte",
icon: "power" icon: mdi("power")
} }
] ]
}, },
alarm: { alarm: {
name: "Alarm", name: "Alarm",
position: [340, 250], position: [340, 250],
icon: "alarm-bell", icon: mdi("alarm-bell"),
iconColor: () => hex("#000000"), iconColor: () => hex("#000000"),
ui: esper_statistics("alarm") ui: esper_statistics("alarm")
}, },
door: { door: {
name: "Tür", name: "Tür",
position: [455,350], position: [455,350],
icon: "swap-vertical", icon: mdi("swap-vertical"),
iconColor: ({door_status}) => door_status == "on" ? hex("#00FF00") : hex("#FF0000"), iconColor: ({door_status}) => door_status == "on" ? hex("#00FF00") : hex("#FF0000"),
ui: [ ui: [
{ {
@ -467,21 +494,21 @@ const config : Config = {
type: "text", type: "text",
text: "Anwesend", text: "Anwesend",
topic: "presence_status", topic: "presence_status",
icon: "account" icon: mdi("account")
} }
] ]
}, },
infoscreen: { infoscreen: {
name: "Infoscreen", name: "Infoscreen",
position: [255, 495], position: [255, 495],
icon: "television-guide flip-v", icon: mdi("television-guide flip-v"),
iconColor: ({infoscreen}) => infoscreen == "on" ? hex("#4444FF") : hex("#000000"), iconColor: ({infoscreen}) => infoscreen == "on" ? hex("#4444FF") : hex("#000000"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
text: "Infoscreen", text: "Infoscreen",
topic: "infoscreen", topic: "infoscreen",
icon: "power" icon: mdi("power")
}, },
{ {
type: "link", type: "link",
@ -493,7 +520,7 @@ const config : Config = {
printer_3d: { printer_3d: {
name: "Ultimaker 3", name: "Ultimaker 3",
position: [754, 560], position: [754, 560],
icon: "printer-3d", icon: mdi("printer-3d"),
iconColor: ({printer_3d_status}) => iconColor: ({printer_3d_status}) =>
({ ({
awaiting_interaction: hex("#b3b300"), awaiting_interaction: hex("#b3b300"),
@ -514,7 +541,7 @@ const config : Config = {
}, },
{ {
type: "progress", type: "progress",
icon: "rotate-right", icon: mdi("rotate-right"),
min: 0, min: 0,
max: 1, max: 1,
text: "Printing Progress", text: "Printing Progress",
@ -525,7 +552,7 @@ const config : Config = {
partkeepr: { partkeepr: {
name: "Partkeepr", name: "Partkeepr",
position: [48, 450], position: [48, 450],
icon: "chip", icon: mdi("chip"),
ui: [ ui: [
{ {
type: "link", type: "link",
@ -537,7 +564,7 @@ const config : Config = {
kitchen_light: { kitchen_light: {
name: "Deckenlicht Küche", name: "Deckenlicht Küche",
position: [325, 407], position: [325, 407],
icon: "ceiling-light", icon: mdi("ceiling-light"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
@ -546,14 +573,14 @@ const config : Config = {
toggled: n => parseInt(n) > 0, toggled: n => parseInt(n) > 0,
topic: "kitchen_light_brightness", topic: "kitchen_light_brightness",
text: "Ein/Ausschalten", text: "Ein/Ausschalten",
icon: "power" icon: mdi("power")
}, },
{ {
type: "slider", type: "slider",
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: "kitchen_light_brightness", topic: "kitchen_light_brightness",
delayedApply: true delayedApply: true
}, },
@ -562,7 +589,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Farbtemperatur", text: "Farbtemperatur",
icon: "weather-sunset-down", icon: mdi("weather-sunset-down"),
topic: "kitchen_light_color", topic: "kitchen_light_color",
delayedApply: true delayedApply: true
}, },
@ -575,7 +602,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: floalt.brightness("65537"), topic: floalt.brightness("65537"),
delayedApply: true delayedApply: true
}, },
@ -584,7 +611,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Farbtemperatur", text: "Farbtemperatur",
icon: "weather-sunset-down", icon: mdi("weather-sunset-down"),
topic: floalt.color("65537"), topic: floalt.color("65537"),
delayedApply: true delayedApply: true
}, },
@ -597,7 +624,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: floalt.brightness("65538"), topic: floalt.brightness("65538"),
delayedApply: true delayedApply: true
}, },
@ -606,7 +633,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Farbtemperatur", text: "Farbtemperatur",
icon: "weather-sunset-down", icon: mdi("weather-sunset-down"),
topic: floalt.color("65538"), topic: floalt.color("65538"),
delayedApply: true delayedApply: true
}, },
@ -619,7 +646,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: floalt.brightness("65539"), topic: floalt.brightness("65539"),
delayedApply: true delayedApply: true
}, },
@ -628,7 +655,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Farbtemperatur", text: "Farbtemperatur",
icon: "weather-sunset-down", icon: mdi("weather-sunset-down"),
topic: floalt.color("65539"), topic: floalt.color("65539"),
delayedApply: true delayedApply: true
}, },
@ -641,7 +668,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: floalt.brightness("65540"), topic: floalt.brightness("65540"),
delayedApply: true delayedApply: true
}, },
@ -650,7 +677,7 @@ const config : Config = {
min: 0, min: 0,
max: 100, max: 100,
text: "Farbtemperatur", text: "Farbtemperatur",
icon: "weather-sunset-down", icon: mdi("weather-sunset-down"),
topic: floalt.color("65540"), topic: floalt.color("65540"),
delayedApply: true delayedApply: true
} }
@ -658,8 +685,8 @@ const config : Config = {
}, },
kitchen_sink_light: { kitchen_sink_light: {
name: "Licht Spüle", name: "Licht Spüle",
position: [300, 348], position: [300, 345],
icon: "ceiling-light", icon: mdi("wall-sconce-flat"),
ui: [ ui: [
{ {
type: "toggle", type: "toggle",
@ -668,14 +695,14 @@ const config : Config = {
toggled: n => parseInt(n) > 0, toggled: n => parseInt(n) > 0,
topic: "kitchen_sink_light_brightness", topic: "kitchen_sink_light_brightness",
text: "Ein/Ausschalten", text: "Ein/Ausschalten",
icon: "power" icon: mdi("power")
}, },
{ {
type: "slider", type: "slider",
min: 0, min: 0,
max: 100, max: 100,
text: "Helligkeit", text: "Helligkeit",
icon: "brightness-7", icon: mdi("brightness-7"),
topic: "kitchen_sink_light_brightness", topic: "kitchen_sink_light_brightness",
delayedApply: true delayedApply: true
} }
@ -800,7 +827,8 @@ const config : Config = {
{ {
image: require("../img/layers/rzl/labels.svg"), image: require("../img/layers/rzl/labels.svg"),
name: "Labels", name: "Labels",
defaultVisibility: "visible", defaultVisibility: "hidden",
opacity: 0.8,
bounds: { bounds: {
topLeft: [0, 0], topLeft: [0, 0],
bottomRight: [1000, 700] bottomRight: [1000, 700]

View file

@ -1,5 +1,6 @@
// @flow // @flow
import type { ControlUI } from "config/flowtypes"; import type { ControlUI } from "config/flowtypes";
import { mdi } from "config/icon";
export const esper_topics = (chip_id: string, name: string) => ({ export const esper_topics = (chip_id: string, name: string) => ({
[ `esper_${name}_version` ]: { [ `esper_${name}_version` ]: {
@ -88,31 +89,31 @@ export const esper_statistics = (name: string,
{ {
type: "text", type: "text",
text: "Device Variant", text: "Device Variant",
icon: "chart-donut", icon: mdi("chart-donut"),
topic: `esper_${name}_device` topic: `esper_${name}_device`
}, },
{ {
type: "text", type: "text",
text: "Version", text: "Version",
icon: "source-branch", icon: mdi("source-branch"),
topic: `esper_${name}_version` topic: `esper_${name}_version`
}, },
{ {
type: "text", type: "text",
text: "IP", text: "IP",
icon: "access-point-network", icon: mdi("access-point-network"),
topic: `esper_${name}_ip` topic: `esper_${name}_ip`
}, },
{ {
type: "text", type: "text",
text: "RSSI", text: "RSSI",
icon: "wifi", icon: mdi("wifi"),
topic: `esper_${name}_rssi` topic: `esper_${name}_rssi`
}, },
{ {
type: "text", type: "text",
text: "Running since…", text: "Running since…",
icon: "av-timer", icon: mdi("av-timer"),
topic: `esper_${name}_uptime` topic: `esper_${name}_uptime`
} }
]) ])

View file

@ -5,6 +5,7 @@
.leaflet-container { .leaflet-container {
height: calc(100vh - 64px); height: calc(100vh - 64px);
max-height: 100%; max-height: 100%;
background: rgba(239,239,203,.59);
} }
body { body {
margin: 0; margin: 0;

View file

@ -4,9 +4,9 @@
"author": "uwap <me+mqttmap.package.json@uwap.name>", "author": "uwap <me+mqttmap.package.json@uwap.name>",
"description": "control devices via mqtt on a beautiful map of your space", "description": "control devices via mqtt on a beautiful map of your space",
"scripts": { "scripts": {
"build": "webpack --bail --config webpack.dev.js --env", "build": "webpack --bail --config webpack.config.js -p --env",
"production-build": "webpack --bail --config webpack.prod.js --env", "dev": "webpack --bail --config webpack.config.js --mode development --env",
"watch": "webpack-dev-server --open --config webpack.dev.js --env", "watch": "webpack-dev-server --open --config webpack.config.js --mode development --env",
"travis": "./travis.sh", "travis": "./travis.sh",
"lint": "eslint -- --ext js --ext jsx src/", "lint": "eslint -- --ext js --ext jsx src/",
"precommit": "yarn lint" "precommit": "yarn lint"
@ -14,10 +14,9 @@
"dependencies": { "dependencies": {
"@material-ui/core": "^1.2.1", "@material-ui/core": "^1.2.1",
"@material-ui/lab": "^1.0.0-alpha.5", "@material-ui/lab": "^1.0.0-alpha.5",
"babel-preset-env": "^1.6.0", "@mdi/font": "^2.0.46",
"leaflet": "^1.3.1", "leaflet": "^1.3.1",
"lodash-es": "^4.17.4", "lodash-es": "^4.17.4",
"mdi": "^2.0.46",
"mqtt": "^2.14.0", "mqtt": "^2.14.0",
"react": "^16.0.0", "react": "^16.0.0",
"react-dom": "^16.0.0", "react-dom": "^16.0.0",
@ -31,25 +30,23 @@
"babel-eslint": "^8.0.1", "babel-eslint": "^8.0.1",
"babel-loader": "^7.1.1", "babel-loader": "^7.1.1",
"babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"clean-webpack-plugin": "^0.1.18", "clean-webpack-plugin": "^0.1.18",
"css-loader": "^0.28.9", "css-loader": "^0.28.9",
"eslint": "^4.16.0", "eslint": "^4.16.0",
"eslint-plugin-flowtype": "^2.42.0", "eslint-plugin-flowtype": "^2.42.0",
"eslint-plugin-react": "^7.6.1", "eslint-plugin-react": "^7.6.1",
"extract-text-webpack-plugin": "next",
"file-loader": "^1.1.5", "file-loader": "^1.1.5",
"flow": "^0.2.3", "flow": "^0.2.3",
"flow-bin": "^0.70.0", "flow-bin": "^0.75.0",
"flow-typed": "^2.3.0", "flow-typed": "^2.3.0",
"html-webpack-plugin": "^3.1.0", "html-webpack-plugin": "^3.1.0",
"husky": "^0.14.3", "husky": "^0.14.3",
"lodash-webpack-plugin": "^0.11.4",
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"webpack": "^4.3.0", "webpack": "^4.3.0",
"webpack-cli": "^3.0.0", "webpack-cli": "^3.0.0",
"webpack-dev-server": "^3.1.1", "webpack-dev-server": "^3.1.1",
"webpack-merge": "^4.1.1",
"webpack-shell-plugin": "^0.5.0" "webpack-shell-plugin": "^0.5.0"
}, },
"license": "MIT" "license": "MIT"

View file

@ -19,7 +19,7 @@ import TopBar from "components/TopBar";
import UiItemList from "components/UiItemList"; import UiItemList from "components/UiItemList";
import keyOf from "utils/keyOf"; import keyOf from "utils/keyOf";
import { controlGetIcon } from "utils/parseIconName"; import { toRawIcon } from "config/icon";
import connectMqtt from "../connectMqtt"; import connectMqtt from "../connectMqtt";
@ -127,7 +127,7 @@ class App extends React.PureComponent<AppProps & Classes, AppState> {
control={this.state.selectedControl} control={this.state.selectedControl}
onCloseRequest={this.closeDrawer.bind(this)} onCloseRequest={this.closeDrawer.bind(this)}
icon={this.state.selectedControl == null ? null : icon={this.state.selectedControl == null ? null :
controlGetIcon(this.state.selectedControl, toRawIcon(this.state.selectedControl.icon,
this.state.mqttState)} this.state.mqttState)}
> >
{this.state.selectedControl == null {this.state.selectedControl == null

View file

@ -4,7 +4,7 @@ import { Map, ImageOverlay, Marker, LayersControl } from "react-leaflet";
import { CRS, point, divIcon } from "leaflet"; import { CRS, point, divIcon } from "leaflet";
import map from "lodash/map"; import map from "lodash/map";
import mapValues from "lodash/mapValues"; import mapValues from "lodash/mapValues";
import parseIconName, { controlGetIcon } from "utils/parseIconName"; import { toRawIcon } from "config/icon";
import type { Controls, Control } from "config/flowtypes"; import type { Controls, Control } from "config/flowtypes";
@ -50,8 +50,8 @@ export default class ControlMap extends React.PureComponent<ControlMapProps> {
} }
createLeafletIcon(control: Control) { createLeafletIcon(control: Control) {
const icon = controlGetIcon(control, this.props.state); const icon = toRawIcon(control.icon, this.props.state);
const iconClass = parseIconName(`${icon} 36px`); const iconClass = `${icon} mdi-36px`;
return divIcon({ return divIcon({
iconSize: point(36, 36), iconSize: point(36, 36),
iconAnchor: point(18, 18), iconAnchor: point(18, 18),

View file

@ -8,15 +8,16 @@ import IconButton from "@material-ui/core/IconButton";
import AppBar from "@material-ui/core/AppBar"; import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar"; import Toolbar from "@material-ui/core/Toolbar";
import List from "@material-ui/core/List"; import List from "@material-ui/core/List";
import { renderIcon } from "utils/parseIconName"; import { renderRawIcon } from "config/icon";
import type { RawIcon } from "config/icon";
import type { Control } from "config/flowtypes"; import type { Control } from "config/flowtypes";
export type SideBarProps = { export type SideBarProps = {
control: ?Control, control: ?Control,
open: boolean, open: boolean,
onCloseRequest: () => void, onCloseRequest: () => void,
icon?: ?string, icon?: ?RawIcon,
children?: React.Node children?: React.Node
}; };
@ -55,7 +56,7 @@ class SideBar extends React.PureComponent<SideBarProps & Classes, SideBarState>
<AppBar position="static"> <AppBar position="static">
<Toolbar> <Toolbar>
{this.props.icon == null {this.props.icon == null
|| renderIcon(this.props.icon, "mdi-36px")} || renderRawIcon(this.props.icon, "mdi-36px")}
<Typography variant="title" className={this.props.classes.flex}> <Typography variant="title" className={this.props.classes.flex}>
{this.props.control == null || this.props.control.name} {this.props.control == null || this.props.control.name}
</Typography> </Typography>

View file

@ -2,16 +2,15 @@
import React from "react"; import React from "react";
import keys from "lodash/keys"; import keys from "lodash/keys";
import map from "lodash/map"; import map from "lodash/map";
import { import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
ListItemSecondaryAction, import ListItemText from "@material-ui/core/ListItemText";
ListItemText, import ListSubheader from "@material-ui/core/ListSubheader";
ListSubheader
} from "@material-ui/core/List";
import Switch from "@material-ui/core/Switch"; import Switch from "@material-ui/core/Switch";
import Input, { InputLabel } from "@material-ui/core/Input"; import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import FormControl from "@material-ui/core/FormControl"; import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select"; import Select from "@material-ui/core/Select";
import { MenuItem } from "@material-ui/core/Menu"; import MenuItem from "@material-ui/core/MenuItem";
import Button from "@material-ui/core/Button"; import Button from "@material-ui/core/Button";
import LinearProgress from "@material-ui/core/LinearProgress"; import LinearProgress from "@material-ui/core/LinearProgress";
import SliderComponent from "@material-ui/lab/Slider"; import SliderComponent from "@material-ui/lab/Slider";
@ -186,7 +185,7 @@ export class DropDown extends UiControl<UIDropDown> {
} }
export class Slider extends UiControl<UISlider> { export class Slider extends UiControl<UISlider> {
runPrimaryAction = (_e: ?any, v: ?number) => { runPrimaryAction = (e: ?Event, v: ?number) => {
if (v != null) { if (v != null) {
this.changeState(v); this.changeState(v);
} }
@ -194,12 +193,13 @@ export class Slider extends UiControl<UISlider> {
render() { render() {
return [ return [
<ListItemText key="label" secondary={this.props.item.text} />, <ListItemText key="label" primary={this.props.item.text} />,
<SliderComponent key="slidercomponent" <SliderComponent key="slidercomponent"
value={this.getValue().internal || this.getValue().actual} value={this.getValue().internal || this.getValue().actual}
min={this.props.item.min || 0} max={this.props.item.max || 0} min={this.props.item.min || 0} max={this.props.item.max || 0}
step={this.props.item.step || 0} step={this.props.item.step || 1}
onChange={() => this.props.item.delayedApply || this.runPrimaryAction()} onChange={(e, v) =>
this.props.item.delayedApply || this.runPrimaryAction(e, v)}
onDragEnd={this.runPrimaryAction} onDragEnd={this.runPrimaryAction}
disabled={!this.isEnabled()} /> disabled={!this.isEnabled()} />
]; ];

View file

@ -1,10 +1,8 @@
// @flow // @flow
import React from "react"; import React from "react";
import { import ListItem from "@material-ui/core/ListItem";
ListItem, import ListItemIcon from "@material-ui/core/ListItemIcon";
ListItemIcon import { renderIcon } from "config/icon";
} from "@material-ui/core/List";
import { renderIcon } from "utils/parseIconName";
import type { ControlUI } from "config/flowtypes"; import type { ControlUI } from "config/flowtypes";
@ -35,7 +33,9 @@ export default class UiItemList extends React.PureComponent<UiItemListProps> {
return ( return (
<ListItem key={key}> <ListItem key={key}>
{control.icon == null || {control.icon == null ||
<ListItemIcon>{renderIcon(control.icon, "mdi-24px")}</ListItemIcon>} <ListItemIcon>
{renderIcon(control.icon, this.props.state, "mdi-24px")}
</ListItemIcon>}
{this.renderControl(control)} {this.renderControl(control)}
</ListItem> </ListItem>
); );

View file

@ -1,5 +1,6 @@
// @flow // @flow
import type { Color } from "config/colors"; import type { Color } from "config/colors";
import type { Icon } from "config/icon";
export type TopicType = (msg: Buffer) => any; export type TopicType = (msg: Buffer) => any;
@ -33,7 +34,7 @@ export type UIToggle = $ReadOnly<{|
type: "toggle", type: "toggle",
text: string, text: string,
topic: string, topic: string,
icon?: string, icon?: Icon,
enableCondition?: TopicDependentOption<boolean>, enableCondition?: TopicDependentOption<boolean>,
on?: Actual, on?: Actual,
off?: Actual, off?: Actual,
@ -44,7 +45,7 @@ export type UIDropDown = $ReadOnly<{|
type: "dropDown", type: "dropDown",
text: string, text: string,
topic: string, topic: string,
icon?: string, icon?: Icon,
enableCondition?: TopicDependentOption<boolean>, enableCondition?: TopicDependentOption<boolean>,
options: Map<string, any>, options: Map<string, any>,
renderValue?: (value: string) => string renderValue?: (value: string) => string
@ -54,7 +55,7 @@ export type UISlider = $ReadOnly<{|
type: "slider", type: "slider",
text: string, text: string,
topic: string, topic: string,
icon?: string, icon?: Icon,
enableCondition?: TopicDependentOption<boolean>, enableCondition?: TopicDependentOption<boolean>,
min?: number, min?: number,
max?: number, max?: number,
@ -74,21 +75,21 @@ export type UILink = $ReadOnly<{|
enableCondition?: StateDependentOption<boolean>, enableCondition?: StateDependentOption<boolean>,
// TODO: check if both the following options are implemented // TODO: check if both the following options are implemented
icon?: string icon?: Icon
|}>; |}>;
export type UIText = $ReadOnly<{| export type UIText = $ReadOnly<{|
type: "text", type: "text",
text: string, text: string,
topic: string, topic: string,
icon?: string icon?: Icon
|}>; |}>;
export type UIProgress = $ReadOnly<{| export type UIProgress = $ReadOnly<{|
type: "progress", type: "progress",
text: string, text: string,
topic: string, topic: string,
icon?: string, icon?: Icon,
min?: number, min?: number,
max?: number max?: number
|}>; |}>;
@ -105,11 +106,7 @@ export type ControlUI =
export type Control = { export type Control = {
name: string, name: string,
position: [number, number], position: [number, number],
icon: string | ( icon: Icon,
internals: Map<string, Internal>,
actuals: Map<string, Actual>,
state: State
) => string,
iconColor?: ( iconColor?: (
internals: Map<string, Internal>, internals: Map<string, Internal>,
actuals: Map<string, Actual>, actuals: Map<string, Actual>,

59
src/config/icon.js Normal file
View file

@ -0,0 +1,59 @@
// @flow
import * as React from "react";
import { getInternals, getActuals } from "utils/state";
export opaque type RawIcon: string = string;
export type Icon = (Map<string, Internal>, Map<string, Actual>, State) =>
RawIcon;
export const raw_mdi = (name: string): RawIcon => {
return `mdi ${name.split(" ").map((icon) => "mdi-".concat(icon)).join(" ")}`;
};
export const mdi = (icon: string) => () => raw_mdi(icon);
export const mdi_battery = (topic: string) =>
(state: Map<string, Internal>) => {
const rawval = state[topic];
const val = parseInt(rawval);
if (isNaN(val)) {
return raw_mdi("battery-unknown");
} else if (val > 95) {
return raw_mdi("battery");
} else if (val > 85) {
return raw_mdi("battery-90");
} else if (val > 75) {
return raw_mdi("battery-80");
} else if (val > 65) {
return raw_mdi("battery-70");
} else if (val > 55) {
return raw_mdi("battery-60");
} else if (val > 45) {
return raw_mdi("battery-50");
} else if (val > 35) {
return raw_mdi("battery-40");
} else if (val > 25) {
return raw_mdi("battery-30");
} else if (val > 15) {
return raw_mdi("battery-20");
} else {
return raw_mdi("battery-10");
}
};
export const toRawIcon = (icon: Icon, state: State): RawIcon => {
const internals: Map<string, Internal> = getInternals(state);
const actuals: Map<string, Actual> = getActuals(state);
return icon(internals, actuals, state);
};
export const renderRawIcon =
(icon: RawIcon, extraClass?: string): React.Node => {
return <i className={`${extraClass || ""} ${icon}`}></i>;
};
export const renderIcon =
(icon: Icon, state: State, extraClass?: string): React.Node => {
return renderRawIcon(toRawIcon(icon, state), extraClass);
};

View file

@ -5,7 +5,7 @@ import injectTapEventPlugin from "react-tap-event-plugin";
import App from "components/App"; import App from "components/App";
import "../node_modules/mdi/css/materialdesignicons.min.css"; import "../node_modules/@mdi/font/css/materialdesignicons.min.css";
import "../css/styles.css"; import "../css/styles.css";
const Config : Config = window.config; const Config : Config = window.config;

View file

@ -1,25 +0,0 @@
// @flow
import * as React from "react";
import { getInternals, getActuals } from "utils/state";
import type { Control } from "config/flowtypes";
export default function parseIconName(name: string): string {
return `mdi ${name.split(" ").map((icon) => "mdi-".concat(icon)).join(" ")}`;
}
export const renderIcon = (name: string, extraClass?: string): React.Node => {
return <i className={`${extraClass || ""} ${parseIconName(name)}`}></i>;
};
export const controlGetIcon = (control: Control, state: State): string => {
const internals: Map<string, Internal> = getInternals(state);
const actuals: Map<string, Actual> = getActuals(state);
return typeof control.icon !== "function" ? control.icon
: control.icon(internals, actuals, state);
};
export const renderControlIcon = (control: Control,
state: State, extraClass?: string): React.Node => {
return renderIcon(controlGetIcon(control, state), extraClass);
};

View file

@ -5,7 +5,7 @@ for conf in $(ls config/); do
if [ "$conf" = "utils.js" ]; then if [ "$conf" = "utils.js" ]; then
continue continue
fi fi
yarn dev $conf
yarn build $conf yarn build $conf
yarn production-build $conf
mv dist artifacts/$conf mv dist artifacts/$conf
done done

View file

@ -2,14 +2,23 @@ const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const WebpackShellPlugin = require('webpack-shell-plugin'); const WebpackShellPlugin = require('webpack-shell-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin');
const preBuildScripts = process.env.NO_FLOW == undefined ? const preBuildScripts = process.env.NO_FLOW == undefined ?
process.env.FLOW_PATH != undefined ? [process.env.FLOW_PATH] : ['flow'] process.env.FLOW_PATH != undefined ? [process.env.FLOW_PATH] : ['flow']
: []; : [];
module.exports = { const configPath = env => {
if (env === true) {
throw "No config file was provided.";
}
return path.resolve(__dirname, `config/${env}`);
};
module.exports = env => ({
entry: {
main: [configPath(env),
path.resolve(__dirname, 'src/index.jsx')]
},
resolve: { resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"], modules: [path.resolve(__dirname, "src"), "node_modules"],
extensions: ['.js', '.jsx'], extensions: ['.js', '.jsx'],
@ -23,7 +32,10 @@ module.exports = {
}, },
module: { module: {
rules: [ rules: [
{ test: /\.(woff2?|eot|ttf|svg)$/, loader: "file-loader" } // TODO: CSS follow imports and minify + sourcemap on production
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(woff2?|eot|ttf|svg)$/, loader: "file-loader" },
{ test: /\.js(x)?$/, exclude: /node_modules/, loader: "babel-loader?cacheDirectory=true" }
] ]
}, },
plugins: [ plugins: [
@ -33,6 +45,5 @@ module.exports = {
title: 'Space Map', title: 'Space Map',
template: 'index.ejs' template: 'index.ejs'
}), }),
new ExtractTextPlugin("styles.css"),
] ]
}; });

View file

@ -1,35 +0,0 @@
const merge = require('webpack-merge');
const path = require('path');
const common = require('./webpack.common.js');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const extractCSS = ExtractTextPlugin.extract({
fallback: "style-loader",
use: {
loader: "css-loader"
}
});
const configPath = env => {
if (env === true) {
throw "No config file was provided.";
}
return path.resolve(__dirname, `config/${env}`);
};
module.exports = env => merge(common, {
entry: {
main: [configPath(env),
path.resolve(__dirname, 'src/index.jsx')]
},
module: {
rules: [
{ test: /\.css$/, use: extractCSS },
{ test: /\.js(x)?$/, exclude: /node_modules/, loader: "babel-loader?cacheDirectory=true" }
]
},
devtool: "eval-cheap-module-source-map",
devServer: {
contentBase: './dist'
},
});

View file

@ -1,49 +0,0 @@
const webpack = require('webpack');
const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const extractCSS = ExtractTextPlugin.extract({
fallback: "style-loader",
use: {
loader: "css-loader",
options: {
sourceMap: true,
minimize: true
}
}
});
const configPath = env => {
if (env === true) {
throw "No config file was provided.";
}
return path.resolve(__dirname, `config/${env}`);
};
module.exports = env => merge(common, {
entry: {
main: [configPath(env),
path.resolve(__dirname, 'src/index.jsx')],
},
module: {
rules: [
{ test: /\.css$/, use: extractCSS },
{ test: /\.js(x)?$/, exclude: /node_modules/, loader: "babel-loader" }
]
},
devtool: "source-map",
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
// new LodashModuleReplacementPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.AggressiveMergingPlugin()
]
});

114
yarn.lock
View file

@ -121,6 +121,10 @@
version "1.0.0-alpha.5" version "1.0.0-alpha.5"
resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-1.0.0-alpha.5.tgz#2f53a76c4b53aca044c91392ad5e4b47f9a4b241" resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-1.0.0-alpha.5.tgz#2f53a76c4b53aca044c91392ad5e4b47f9a4b241"
"@mdi/font@^2.0.46":
version "2.4.85"
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-2.4.85.tgz#f257a2c3ed1dec3023f2dc12cd9210fab572ab42"
"@types/jss@^9.5.3": "@types/jss@^9.5.3":
version "9.5.3" version "9.5.3"
resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.3.tgz#0c106de3fe0b324cd4173fac7dab26c12cda624e" resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.3.tgz#0c106de3fe0b324cd4173fac7dab26c12cda624e"
@ -171,6 +175,10 @@ acorn@^5.0.0, acorn@^5.5.0:
version "5.5.3" version "5.5.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9"
acorn@^5.3.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
ajv-keywords@^2.1.0: ajv-keywords@^2.1.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
@ -370,12 +378,6 @@ async@^1.5.2:
version "1.5.2" version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.4.1:
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
lodash "^4.14.0"
asynckit@^0.4.0: asynckit@^0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@ -1028,6 +1030,14 @@ bcrypt-pbkdf@^1.0.0:
dependencies: dependencies:
tweetnacl "^0.14.3" tweetnacl "^0.14.3"
bfj-node4@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.3.1.tgz#e23d8b27057f1d0214fc561142ad9db998f26830"
dependencies:
bluebird "^3.5.1"
check-types "^7.3.0"
tryer "^1.0.0"
big-integer@^1.6.17: big-integer@^1.6.17:
version "1.6.27" version "1.6.27"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.27.tgz#8e56c6f8b2dd6c4fe8d32102b83d4f25868e4b3a" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.27.tgz#8e56c6f8b2dd6c4fe8d32102b83d4f25868e4b3a"
@ -1382,7 +1392,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
supports-color "^5.3.0" supports-color "^5.3.0"
chalk@^2.4.1: chalk@^2.3.0, chalk@^2.4.1:
version "2.4.1" version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies: dependencies:
@ -1406,6 +1416,10 @@ charenc@~0.0.1:
version "0.0.2" version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
check-types@^7.3.0:
version "7.4.0"
resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4"
chokidar@^1.6.1: chokidar@^1.6.1:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
@ -1590,7 +1604,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
commander@2.15.x, commander@^2.11.0, commander@~2.15.0: commander@2.15.x, commander@^2.11.0, commander@^2.13.0, commander@~2.15.0:
version "2.15.1" version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
@ -2143,6 +2157,10 @@ duplexer3@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.4.2, duplexify@^3.5.1, duplexify@^3.5.3: duplexify@^3.4.2, duplexify@^3.5.1, duplexify@^3.5.3:
version "3.5.4" version "3.5.4"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4"
@ -2162,6 +2180,10 @@ ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
ejs@^2.5.7:
version "2.6.1"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30: electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30:
version "1.3.42" version "1.3.42"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9"
@ -2500,15 +2522,6 @@ extglob@^2.0.4:
snapdragon "^0.8.1" snapdragon "^0.8.1"
to-regex "^3.0.1" to-regex "^3.0.1"
extract-text-webpack-plugin@next:
version "4.0.0-beta.0"
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz#f7361d7ff430b42961f8d1321ba8c1757b5d4c42"
dependencies:
async "^2.4.1"
loader-utils "^1.1.0"
schema-utils "^0.4.5"
webpack-sources "^1.1.0"
extsprintf@1.3.0: extsprintf@1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@ -2581,6 +2594,10 @@ filename-regex@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
filesize@^3.5.11:
version "3.6.1"
resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
fill-range@^2.1.0: fill-range@^2.1.0:
version "2.2.3" version "2.2.3"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
@ -2646,9 +2663,9 @@ flatten@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
flow-bin@^0.69.0: flow-bin@^0.70.0:
version "0.69.0" version "0.70.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.69.0.tgz#053159a684a6051fcbf0b71a2eb19a9679082da6" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.70.0.tgz#080ae83a997f2b4ddb3dc2649bf13336825292b5"
flow-typed@^2.3.0: flow-typed@^2.3.0:
version "2.4.0" version "2.4.0"
@ -2935,6 +2952,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6:
version "4.1.11" version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
gzip-size@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-4.1.0.tgz#8ae096257eabe7d69c45be2b67c448124ffb517c"
dependencies:
duplexer "^0.1.1"
pify "^3.0.0"
handle-thing@^1.2.5: handle-thing@^1.2.5:
version "1.2.5" version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
@ -3931,12 +3955,6 @@ lodash-es@^4.0.0, lodash-es@^4.17.4, lodash-es@^4.2.1:
version "4.17.8" version "4.17.8"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.8.tgz#6fa8c8c5d337481df0bdf1c0d899d42473121e45" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.8.tgz#6fa8c8c5d337481df0bdf1c0d899d42473121e45"
lodash-webpack-plugin@^0.11.4:
version "0.11.4"
resolved "https://registry.yarnpkg.com/lodash-webpack-plugin/-/lodash-webpack-plugin-0.11.4.tgz#6c3ecba3d4b8d24b53940b63542715c5ed3c4ac5"
dependencies:
lodash "^4.17.4"
lodash.assign@^4.0.3, lodash.assign@^4.0.6: lodash.assign@^4.0.3, lodash.assign@^4.0.6:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@ -3953,7 +3971,7 @@ lodash.uniq@^4.5.0:
version "4.5.0" version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.5" version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
@ -4042,10 +4060,6 @@ md5@^2.1.0:
crypt "~0.0.1" crypt "~0.0.1"
is-buffer "~1.1.1" is-buffer "~1.1.1"
mdi@^2.0.46:
version "2.2.43"
resolved "https://registry.yarnpkg.com/mdi/-/mdi-2.2.43.tgz#c5e419a6e5f48c82c7109328f52530fd187a0ec0"
media-typer@0.3.0: media-typer@0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -4514,6 +4528,10 @@ onetime@^2.0.0:
dependencies: dependencies:
mimic-fn "^1.0.0" mimic-fn "^1.0.0"
opener@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
opn@^5.1.0: opn@^5.1.0:
version "5.3.0" version "5.3.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c"
@ -6251,6 +6269,10 @@ trim-right@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
tryer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
tslib@^1.9.0: tslib@^1.9.0:
version "1.9.2" version "1.9.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e"
@ -6561,6 +6583,23 @@ wbuf@^1.1.0, wbuf@^1.7.2:
dependencies: dependencies:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
webpack-bundle-analyzer@^2.13.1:
version "2.13.1"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz#07d2176c6e86c3cdce4c23e56fae2a7b6b4ad526"
dependencies:
acorn "^5.3.0"
bfj-node4 "^5.2.0"
chalk "^2.3.0"
commander "^2.13.0"
ejs "^2.5.7"
express "^4.16.2"
filesize "^3.5.11"
gzip-size "^4.1.0"
lodash "^4.17.4"
mkdirp "^0.5.1"
opener "^1.4.3"
ws "^4.0.0"
webpack-cli@^3.0.0: webpack-cli@^3.0.0:
version "3.0.8" version "3.0.8"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.0.8.tgz#90eddcf04a4bfc31aa8c0edc4c76785bc4f1ccd9" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.0.8.tgz#90eddcf04a4bfc31aa8c0edc4c76785bc4f1ccd9"
@ -6631,12 +6670,6 @@ webpack-log@^1.0.1, webpack-log@^1.1.2:
loglevelnext "^1.0.1" loglevelnext "^1.0.1"
uuid "^3.1.0" uuid "^3.1.0"
webpack-merge@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.2.tgz#5d372dddd3e1e5f8874f5bf5a8e929db09feb216"
dependencies:
lodash "^4.17.5"
webpack-shell-plugin@^0.5.0: webpack-shell-plugin@^0.5.0:
version "0.5.0" version "0.5.0"
resolved "https://registry.yarnpkg.com/webpack-shell-plugin/-/webpack-shell-plugin-0.5.0.tgz#29b8a1d80ddeae0ddb10e729667f728653c2c742" resolved "https://registry.yarnpkg.com/webpack-shell-plugin/-/webpack-shell-plugin-0.5.0.tgz#29b8a1d80ddeae0ddb10e729667f728653c2c742"
@ -6761,6 +6794,13 @@ ws@^3.2.0:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
ultron "~1.1.0" ultron "~1.1.0"
ws@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289"
dependencies:
async-limiter "~1.0.0"
safe-buffer "~5.1.0"
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"