From b6c0181b3e871c3e34f4b366fcce1c3391731ad8 Mon Sep 17 00:00:00 2001 From: uwap Date: Tue, 19 Jun 2018 10:47:14 +0200 Subject: [PATCH 1/5] fix broken imports --- config/rzl.js | 6 +++--- package.json | 2 +- src/components/UiItemList/UiItem.js | 15 +++++++-------- src/components/UiItemList/index.js | 6 ++---- src/index.jsx | 2 +- yarn.lock | 8 ++++---- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/config/rzl.js b/config/rzl.js index b9a8e7b..d759582 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -344,7 +344,7 @@ const config : Config = { position: [350, 650], iconColor: ({onkyo_connection, onkyo_power}) => onkyo_connection != "connected" ? hex("#888888") : (onkyo_power == "on" ? hex("#00FF00") : hex("#000000")), - icon: "volume-high", + icon: "audio-video", ui: [ { type: "toggle", @@ -648,8 +648,8 @@ const config : Config = { }, kitchen_sink_light: { name: "Licht Spüle", - position: [300, 348], - icon: "ceiling-light", + position: [300, 345], + icon: "wall-sconce-flat", ui: [ { type: "toggle", diff --git a/package.json b/package.json index ebeb800..46733ca 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,10 @@ "dependencies": { "@material-ui/core": "^1.2.1", "@material-ui/lab": "^1.0.0-alpha.5", + "@mdi/font": "^2.0.46", "babel-preset-env": "^1.6.0", "leaflet": "^1.3.1", "lodash-es": "^4.17.4", - "mdi": "^2.0.46", "mqtt": "^2.14.0", "react": "^16.0.0", "react-dom": "^16.0.0", diff --git a/src/components/UiItemList/UiItem.js b/src/components/UiItemList/UiItem.js index 8a39b40..3821c18 100644 --- a/src/components/UiItemList/UiItem.js +++ b/src/components/UiItemList/UiItem.js @@ -2,16 +2,15 @@ import React from "react"; import keys from "lodash/keys"; import map from "lodash/map"; -import { - ListItemSecondaryAction, - ListItemText, - ListSubheader -} from "@material-ui/core/List"; +import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"; +import ListItemText from "@material-ui/core/ListItemText"; +import ListSubheader from "@material-ui/core/ListSubheader"; 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 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 LinearProgress from "@material-ui/core/LinearProgress"; import SliderComponent from "@material-ui/lab/Slider"; @@ -194,7 +193,7 @@ export class Slider extends UiControl { render() { return [ - , + , Date: Tue, 19 Jun 2018 12:35:10 +0200 Subject: [PATCH 2/5] refactor webpack config --- README.md | 4 +-- config/rzl.js | 3 +- css/styles.css | 1 + package.json | 11 +++--- travis.sh | 2 +- webpack.common.js => webpack.config.js | 22 +++++++++--- webpack.dev.js | 35 ------------------ webpack.prod.js | 49 -------------------------- yarn.lock | 35 +++--------------- 9 files changed, 31 insertions(+), 131 deletions(-) rename webpack.common.js => webpack.config.js (65%) delete mode 100644 webpack.dev.js delete mode 100644 webpack.prod.js diff --git a/README.md b/README.md index 9756d72..eca38da 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ 1. run `yarn` to install all dependencies. 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. -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. -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 diff --git a/config/rzl.js b/config/rzl.js index d759582..304c6e7 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -697,7 +697,8 @@ const config : Config = { { image: require("../img/layers/rzl/labels.svg"), name: "Labels", - defaultVisibility: "visible", + defaultVisibility: "hidden", + opacity: 0.8, bounds: { topLeft: [0, 0], bottomRight: [1000, 700] diff --git a/css/styles.css b/css/styles.css index 7dcb9af..a695c22 100644 --- a/css/styles.css +++ b/css/styles.css @@ -5,6 +5,7 @@ .leaflet-container { height: calc(100vh - 64px); max-height: 100%; + background: rgba(239,239,203,.59); } body { margin: 0; diff --git a/package.json b/package.json index bad2e6a..b269e53 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "author": "uwap ", "description": "control devices via mqtt on a beautiful map of your space", "scripts": { - "build": "webpack --bail --config webpack.dev.js --env", - "production-build": "webpack --bail --config webpack.prod.js --env", - "watch": "webpack-dev-server --open --config webpack.dev.js --env", + "build": "webpack --bail --config webpack.config.js -p --env", + "dev": "webpack --bail --config webpack.config.js --mode development --env", + "watch": "webpack-dev-server --open --config webpack.dev.js --mode development --env", "travis": "./travis.sh", "lint": "eslint -- --ext js --ext jsx src/", "precommit": "yarn lint" @@ -15,7 +15,6 @@ "@material-ui/core": "^1.2.1", "@material-ui/lab": "^1.0.0-alpha.5", "@mdi/font": "^2.0.46", - "babel-preset-env": "^1.6.0", "leaflet": "^1.3.1", "lodash-es": "^4.17.4", "mqtt": "^2.14.0", @@ -32,24 +31,22 @@ "babel-loader": "^7.1.1", "babel-plugin-transform-class-properties": "^6.24.1", "babel-preset-react": "^6.24.1", + "babel-preset-env": "^1.6.0", "clean-webpack-plugin": "^0.1.18", "css-loader": "^0.28.9", "eslint": "^4.16.0", "eslint-plugin-flowtype": "^2.42.0", "eslint-plugin-react": "^7.6.1", - "extract-text-webpack-plugin": "next", "file-loader": "^1.1.5", "flow": "^0.2.3", "flow-bin": "^0.70.0", "flow-typed": "^2.3.0", "html-webpack-plugin": "^3.1.0", "husky": "^0.14.3", - "lodash-webpack-plugin": "^0.11.4", "style-loader": "^0.21.0", "webpack": "^4.3.0", "webpack-cli": "^3.0.0", "webpack-dev-server": "^3.1.1", - "webpack-merge": "^4.1.1", "webpack-shell-plugin": "^0.5.0" }, "license": "MIT" diff --git a/travis.sh b/travis.sh index 1a94da2..d0f1c83 100755 --- a/travis.sh +++ b/travis.sh @@ -5,7 +5,7 @@ for conf in $(ls config/); do if [ "$conf" = "utils.js" ]; then continue fi + yarn dev $conf yarn build $conf - yarn production-build $conf mv dist artifacts/$conf done diff --git a/webpack.common.js b/webpack.config.js similarity index 65% rename from webpack.common.js rename to webpack.config.js index a016dc2..71d7f96 100644 --- a/webpack.common.js +++ b/webpack.config.js @@ -2,14 +2,24 @@ const path = require('path'); const webpack = require('webpack'); const WebpackShellPlugin = require('webpack-shell-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const ExtractTextPlugin = require("extract-text-webpack-plugin"); const CleanWebpackPlugin = require('clean-webpack-plugin'); const preBuildScripts = process.env.NO_FLOW == undefined ? 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: { modules: [path.resolve(__dirname, "src"), "node_modules"], extensions: ['.js', '.jsx'], @@ -23,7 +33,10 @@ module.exports = { }, module: { 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: [ @@ -33,6 +46,5 @@ module.exports = { title: 'Space Map', template: 'index.ejs' }), - new ExtractTextPlugin("styles.css"), ] -}; +}); diff --git a/webpack.dev.js b/webpack.dev.js deleted file mode 100644 index a8135f2..0000000 --- a/webpack.dev.js +++ /dev/null @@ -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' - }, -}); diff --git a/webpack.prod.js b/webpack.prod.js deleted file mode 100644 index 7f4896a..0000000 --- a/webpack.prod.js +++ /dev/null @@ -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() - ] -}); diff --git a/yarn.lock b/yarn.lock index 4331192..592ad3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -374,12 +374,6 @@ async@^1.5.2: version "1.5.2" 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: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2504,15 +2498,6 @@ extglob@^2.0.4: snapdragon "^0.8.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: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -2650,9 +2635,9 @@ flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" -flow-bin@^0.69.0: - version "0.69.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.69.0.tgz#053159a684a6051fcbf0b71a2eb19a9679082da6" +flow-bin@^0.70.0: + version "0.70.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.70.0.tgz#080ae83a997f2b4ddb3dc2649bf13336825292b5" flow-typed@^2.3.0: version "2.4.0" @@ -3935,12 +3920,6 @@ lodash-es@^4.0.0, lodash-es@^4.17.4, lodash-es@^4.2.1: version "4.17.8" 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: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -3957,7 +3936,7 @@ lodash.uniq@^4.5.0: version "4.5.0" 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" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" @@ -6631,12 +6610,6 @@ webpack-log@^1.0.1, webpack-log@^1.1.2: loglevelnext "^1.0.1" 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: version "0.5.0" resolved "https://registry.yarnpkg.com/webpack-shell-plugin/-/webpack-shell-plugin-0.5.0.tgz#29b8a1d80ddeae0ddb10e729667f728653c2c742" From d749e8107ac908dba5b5817df0c92c7c557f42f3 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 21 Jun 2018 17:02:28 +0000 Subject: [PATCH 3/5] chore(package): update flow-bin to version 0.75.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b269e53..bbfa7f0 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "eslint-plugin-react": "^7.6.1", "file-loader": "^1.1.5", "flow": "^0.2.3", - "flow-bin": "^0.70.0", + "flow-bin": "^0.75.0", "flow-typed": "^2.3.0", "html-webpack-plugin": "^3.1.0", "husky": "^0.14.3", From 2df52f75be860b299a12331cf5ea872c42a80b26 Mon Sep 17 00:00:00 2001 From: Ranlvor Date: Sun, 24 Jun 2018 14:24:42 +0200 Subject: [PATCH 4/5] Rechner und Drucker aufgeteilt auf 2 Funkdosen. Fixes #14 --- config/rzl.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/config/rzl.js b/config/rzl.js index b9a8e7b..7736479 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -48,6 +48,12 @@ const config : Config = { defaultValue: "OFF", values: { on: "ON", off: "OFF" } }, + olymp_printer: { + state: "stat/sonoff2/POWER", + command: "cmnd/sonoff2/power", + defaultValue: "OFF", + values: { on: "ON", off: "OFF" } + }, flyfry: { state: "/service/openhab/out/wifi_flyfry/state", command: "/service/openhab/in/wifi_flyfry/command", @@ -274,19 +280,38 @@ const config : Config = { ] }, olymp_pc: { - name: "Rechner und Drucker", + name: "Rechner", position: [297, 90], icon: "desktop-classic", iconColor: ({olymp_pc}) => olymp_pc == "on" ? hex("#00FF00") : hex("#000000"), ui: [ { type: "toggle", - text: "Rechner und Drucker", + text: "Rechner", topic: "olymp_pc", icon: "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" + }, + { + type: "link", + link: "http://annette.rzl/", + text: "Open Annette" + } + ] + }, flyfry: { name: "Fliegenbratgerät", position: [450, 590], From ed0f22645e7f939c29318fa05a52e147db470224 Mon Sep 17 00:00:00 2001 From: uwap Date: Sun, 24 Jun 2018 16:34:59 +0200 Subject: [PATCH 5/5] Completely rework how icons work in mqtt control map --- config/entropia.js | 7 +- config/rzl.js | 100 ++++++++++++++-------------- config/utils.js | 11 +-- package.json | 4 +- src/components/App.js | 4 +- src/components/ControlMap.js | 6 +- src/components/SideBar.js | 7 +- src/components/UiItemList/UiItem.js | 7 +- src/components/UiItemList/index.js | 6 +- src/config/flowtypes.js | 19 +++--- src/config/icon.js | 59 ++++++++++++++++ src/utils/parseIconName.js | 25 ------- webpack.config.js | 1 - yarn.lock | 71 +++++++++++++++++++- 14 files changed, 216 insertions(+), 111 deletions(-) create mode 100644 src/config/icon.js delete mode 100644 src/utils/parseIconName.js diff --git a/config/entropia.js b/config/entropia.js index 36e25d9..fc2f6ca 100644 --- a/config/entropia.js +++ b/config/entropia.js @@ -1,6 +1,7 @@ // @flow import type { Config } from "config/flowtypes"; import { hex, rgb, rgba, rainbow } from "config/colors"; +import { mdi } from "config/icon"; import { esper_topics, esper_statistics } from "./utils"; const config : Config = { @@ -29,20 +30,20 @@ const config : Config = { hauptraum_table_light: { name: "Hauptraum Tisch", position: [450, 450], - icon: "white-balance-iridescent", + icon: mdi("white-balance-iridescent"), iconColor: () => hex("#000000"), ui: [ { type: "toggle", text: "Licht", topic: "hauptraum_table_light", - icon: "power" + icon: mdi("power") }, { type: "toggle", text: "Licht", topic: "hauptraum_table_light_on_hack", - icon: "power" + icon: mdi("power") } ] } diff --git a/config/rzl.js b/config/rzl.js index 304c6e7..1180912 100644 --- a/config/rzl.js +++ b/config/rzl.js @@ -2,6 +2,7 @@ import type { Config } from "config/flowtypes"; import * as types from "config/types"; import { hex, rgb, rgba, rainbow } from "config/colors"; +import { mdi, raw_mdi } from "config/icon"; import { esper_topics, esper_statistics, floalt } from "./utils"; const config : Config = { @@ -194,63 +195,64 @@ const config : Config = { led_stahltrager: { name: "LED Stahlträger", position: [380, 590], - icon: "white-balance-iridescent", + icon: mdi("white-balance-iridescent"), iconColor: ({led_stahltraeger}) => led_stahltraeger == "on" ? rainbow : hex("#000000"), ui: [ { type: "toggle", text: "Stahlträger LED", topic: "led_stahltraeger", - icon: "power" + icon: mdi("power") }, ] }, snackbar: { name: "Snackbar", position: [510, 500], - icon: "fridge", + icon: mdi("fridge"), iconColor: ({snackbar}) => snackbar == "on" ? hex("#E20074") : hex("#000000"), ui: [ { type: "toggle", text: "Snackbar", topic: "snackbar", - icon: "power" + icon: mdi("power") } ] }, twinkle: { name: "Twinkle", 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"), ui: [ { type: "toggle", text: "Twinkle", topic: "twinkle", - icon: "power" + icon: mdi("power") } ] }, fan: { name: "Ventilator", position: [520, 450], - icon: "fan", + icon: mdi("fan"), iconColor: ({fan}) => fan == "on" ? hex("#00FF00") : hex("#000000"), ui: [ { type: "toggle", text: "Ventilator", topic: "fan", - icon: "power" + icon: mdi("power") } ] }, cashdesk: { name: "Cashdesk", position: [500, 470], - icon: "coin", + icon: mdi("coin"), ui: [ { type: "link", @@ -262,49 +264,49 @@ const config : Config = { videogames: { name: "Videospiele", position: [100, 100], - icon: "gamepad-variant", + icon: mdi("gamepad-variant"), iconColor: ({videogames}) => videogames == "on" ? hex("#00FF00") : hex("#000000"), ui: [ { type: "toggle", text: "Videospiele", topic: "videogames", - icon: "power" + icon: mdi("power") } ] }, olymp_pc: { name: "Rechner und Drucker", position: [297, 90], - icon: "desktop-classic", + icon: mdi("desktop-classic"), iconColor: ({olymp_pc}) => olymp_pc == "on" ? hex("#00FF00") : hex("#000000"), ui: [ { type: "toggle", text: "Rechner und Drucker", topic: "olymp_pc", - icon: "power" + icon: mdi("power") } ] }, flyfry: { name: "Fliegenbratgerät", position: [450, 590], - icon: "fire", + icon: mdi("fire"), iconColor: ({flyfry}) => flyfry == "on" ? hex("#6666FF") : hex("#000000"), ui: esper_statistics("flyfry", [ { type: "toggle", text: "Fliegenbratgerät", topic: "flyfry", - icon: "power" + icon: mdi("power") } ]) }, artnet: { name: "Artnet", position: [535,480], - icon: "spotlight", + icon: mdi("spotlight"), iconColor: ({artnet}) => ({ off: hex("#000000"), @@ -321,7 +323,7 @@ const config : Config = { topic: "artnet", on: "cycle", toggled: val => val != "off", - icon: "power" + icon: mdi("power") }, { type: "dropDown", @@ -335,7 +337,7 @@ const config : Config = { cycle: "Farbwechsel" }, enableCondition: val => val != "off", - icon: "palette" + icon: mdi("palette") } ] }, @@ -344,12 +346,12 @@ const config : Config = { position: [350, 650], iconColor: ({onkyo_connection, onkyo_power}) => onkyo_connection != "connected" ? hex("#888888") : (onkyo_power == "on" ? hex("#00FF00") : hex("#000000")), - icon: "audio-video", + icon: mdi("audio-video"), ui: [ { type: "toggle", text: "Power", - icon: "power", + icon: mdi("power"), topic: "onkyo_power", enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" }, @@ -363,14 +365,14 @@ const config : Config = { topic: "onkyo_volume", min: 0, max: 50, - icon: "volume-high", + icon: mdi("volume-high"), enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" }, { type: "toggle", text: "Mute", topic: "onkyo_mute", - icon: "volume-off", + icon: mdi("volume-off"), enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" }, { @@ -388,7 +390,7 @@ const config : Config = { pult: "Pult", front: "Front HDMI" }, - icon: "usb", + icon: mdi("usb"), enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" }, { @@ -407,7 +409,7 @@ const config : Config = { somafm_beatblender: "Beat Blender (Soma FM)", ponyville: "Ponyville FM" }, - icon: "radio", + icon: mdi("radio"), enableCondition: (a, b, state) => state.onkyo_connection.internal == "connected" && state.onkyo_inputs.internal == "netzwerk" }, { @@ -424,28 +426,28 @@ const config : Config = { rundumleuchte: { name: "Rundumleuchte", position: [310,275], - icon: "alarm-light", + icon: mdi("alarm-light"), iconColor: ({rundumleuchte}) => rundumleuchte == "on" ? hex("#F0DF10") : hex("#000000"), ui: [ { type: "toggle", text: "Rundumleuchte", topic: "rundumleuchte", - icon: "power" + icon: mdi("power") } ] }, alarm: { name: "Alarm", position: [340, 250], - icon: "alarm-bell", + icon: mdi("alarm-bell"), iconColor: () => hex("#000000"), ui: esper_statistics("alarm") }, door: { name: "Tür", position: [455,350], - icon: "swap-vertical", + icon: mdi("swap-vertical"), iconColor: ({door_status}) => door_status == "on" ? hex("#00FF00") : hex("#FF0000"), ui: [ { @@ -457,21 +459,21 @@ const config : Config = { type: "text", text: "Anwesend", topic: "presence_status", - icon: "account" + icon: mdi("account") } ] }, infoscreen: { name: "Infoscreen", position: [255, 495], - icon: "television-guide flip-v", + icon: mdi("television-guide flip-v"), iconColor: ({infoscreen}) => infoscreen == "on" ? hex("#4444FF") : hex("#000000"), ui: [ { type: "toggle", text: "Infoscreen", topic: "infoscreen", - icon: "power" + icon: mdi("power") }, { type: "link", @@ -483,7 +485,7 @@ const config : Config = { printer_3d: { name: "Ultimaker 3", position: [754, 560], - icon: "printer-3d", + icon: mdi("printer-3d"), iconColor: ({printer_3d_status}) => ({ awaiting_interaction: hex("#b3b300"), @@ -504,7 +506,7 @@ const config : Config = { }, { type: "progress", - icon: "rotate-right", + icon: mdi("rotate-right"), min: 0, max: 1, text: "Printing Progress", @@ -515,7 +517,7 @@ const config : Config = { partkeepr: { name: "Partkeepr", position: [48, 450], - icon: "chip", + icon: mdi("chip"), ui: [ { type: "link", @@ -527,7 +529,7 @@ const config : Config = { kitchen_light: { name: "Deckenlicht Küche", position: [325, 407], - icon: "ceiling-light", + icon: mdi("ceiling-light"), ui: [ { type: "toggle", @@ -536,14 +538,14 @@ const config : Config = { toggled: n => parseInt(n) > 0, topic: "kitchen_light_brightness", text: "Ein/Ausschalten", - icon: "power" + icon: mdi("power") }, { type: "slider", min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: "kitchen_light_brightness", delayedApply: true }, @@ -552,7 +554,7 @@ const config : Config = { min: 0, max: 100, text: "Farbtemperatur", - icon: "weather-sunset-down", + icon: mdi("weather-sunset-down"), topic: "kitchen_light_color", delayedApply: true }, @@ -565,7 +567,7 @@ const config : Config = { min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: floalt.brightness("65537"), delayedApply: true }, @@ -574,7 +576,7 @@ const config : Config = { min: 0, max: 100, text: "Farbtemperatur", - icon: "weather-sunset-down", + icon: mdi("weather-sunset-down"), topic: floalt.color("65537"), delayedApply: true }, @@ -587,7 +589,7 @@ const config : Config = { min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: floalt.brightness("65538"), delayedApply: true }, @@ -596,7 +598,7 @@ const config : Config = { min: 0, max: 100, text: "Farbtemperatur", - icon: "weather-sunset-down", + icon: mdi("weather-sunset-down"), topic: floalt.color("65538"), delayedApply: true }, @@ -609,7 +611,7 @@ const config : Config = { min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: floalt.brightness("65539"), delayedApply: true }, @@ -618,7 +620,7 @@ const config : Config = { min: 0, max: 100, text: "Farbtemperatur", - icon: "weather-sunset-down", + icon: mdi("weather-sunset-down"), topic: floalt.color("65539"), delayedApply: true }, @@ -631,7 +633,7 @@ const config : Config = { min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: floalt.brightness("65540"), delayedApply: true }, @@ -640,7 +642,7 @@ const config : Config = { min: 0, max: 100, text: "Farbtemperatur", - icon: "weather-sunset-down", + icon: mdi("weather-sunset-down"), topic: floalt.color("65540"), delayedApply: true } @@ -649,7 +651,7 @@ const config : Config = { kitchen_sink_light: { name: "Licht Spüle", position: [300, 345], - icon: "wall-sconce-flat", + icon: mdi("wall-sconce-flat"), ui: [ { type: "toggle", @@ -658,14 +660,14 @@ const config : Config = { toggled: n => parseInt(n) > 0, topic: "kitchen_sink_light_brightness", text: "Ein/Ausschalten", - icon: "power" + icon: mdi("power") }, { type: "slider", min: 0, max: 100, text: "Helligkeit", - icon: "brightness-7", + icon: mdi("brightness-7"), topic: "kitchen_sink_light_brightness", delayedApply: true } diff --git a/config/utils.js b/config/utils.js index 20cc656..1738354 100644 --- a/config/utils.js +++ b/config/utils.js @@ -1,5 +1,6 @@ // @flow import type { ControlUI } from "config/flowtypes"; +import { mdi } from "config/icon"; export const esper_topics = (chip_id: string, name: string) => ({ [ `esper_${name}_version` ]: { @@ -69,31 +70,31 @@ export const esper_statistics = (name: string, { type: "text", text: "Device Variant", - icon: "chart-donut", + icon: mdi("chart-donut"), topic: `esper_${name}_device` }, { type: "text", text: "Version", - icon: "source-branch", + icon: mdi("source-branch"), topic: `esper_${name}_version` }, { type: "text", text: "IP", - icon: "access-point-network", + icon: mdi("access-point-network"), topic: `esper_${name}_ip` }, { type: "text", text: "RSSI", - icon: "wifi", + icon: mdi("wifi"), topic: `esper_${name}_rssi` }, { type: "text", text: "Running since…", - icon: "av-timer", + icon: mdi("av-timer"), topic: `esper_${name}_uptime` } ]) diff --git a/package.json b/package.json index b269e53..ec57d5f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "webpack --bail --config webpack.config.js -p --env", "dev": "webpack --bail --config webpack.config.js --mode development --env", - "watch": "webpack-dev-server --open --config webpack.dev.js --mode development --env", + "watch": "webpack-dev-server --open --config webpack.config.js --mode development --env", "travis": "./travis.sh", "lint": "eslint -- --ext js --ext jsx src/", "precommit": "yarn lint" @@ -30,8 +30,8 @@ "babel-eslint": "^8.0.1", "babel-loader": "^7.1.1", "babel-plugin-transform-class-properties": "^6.24.1", - "babel-preset-react": "^6.24.1", "babel-preset-env": "^1.6.0", + "babel-preset-react": "^6.24.1", "clean-webpack-plugin": "^0.1.18", "css-loader": "^0.28.9", "eslint": "^4.16.0", diff --git a/src/components/App.js b/src/components/App.js index fc5becd..7d6fb2f 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -19,7 +19,7 @@ import TopBar from "components/TopBar"; import UiItemList from "components/UiItemList"; import keyOf from "utils/keyOf"; -import { controlGetIcon } from "utils/parseIconName"; +import { toRawIcon } from "config/icon"; import connectMqtt from "../connectMqtt"; @@ -127,7 +127,7 @@ class App extends React.PureComponent { control={this.state.selectedControl} onCloseRequest={this.closeDrawer.bind(this)} icon={this.state.selectedControl == null ? null : - controlGetIcon(this.state.selectedControl, + toRawIcon(this.state.selectedControl.icon, this.state.mqttState)} > {this.state.selectedControl == null diff --git a/src/components/ControlMap.js b/src/components/ControlMap.js index 7524673..2606561 100644 --- a/src/components/ControlMap.js +++ b/src/components/ControlMap.js @@ -4,7 +4,7 @@ import { Map, ImageOverlay, Marker, LayersControl } from "react-leaflet"; import { CRS, point, divIcon } from "leaflet"; import map from "lodash/map"; import mapValues from "lodash/mapValues"; -import parseIconName, { controlGetIcon } from "utils/parseIconName"; +import { toRawIcon } from "config/icon"; import type { Controls, Control } from "config/flowtypes"; @@ -50,8 +50,8 @@ export default class ControlMap extends React.PureComponent { } createLeafletIcon(control: Control) { - const icon = controlGetIcon(control, this.props.state); - const iconClass = parseIconName(`${icon} 36px`); + const icon = toRawIcon(control.icon, this.props.state); + const iconClass = `${icon} mdi-36px`; return divIcon({ iconSize: point(36, 36), iconAnchor: point(18, 18), diff --git a/src/components/SideBar.js b/src/components/SideBar.js index a94e62e..5015bdc 100644 --- a/src/components/SideBar.js +++ b/src/components/SideBar.js @@ -8,15 +8,16 @@ import IconButton from "@material-ui/core/IconButton"; import AppBar from "@material-ui/core/AppBar"; import Toolbar from "@material-ui/core/Toolbar"; 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"; export type SideBarProps = { control: ?Control, open: boolean, onCloseRequest: () => void, - icon?: ?string, + icon?: ?RawIcon, children?: React.Node }; @@ -55,7 +56,7 @@ class SideBar extends React.PureComponent {this.props.icon == null - || renderIcon(this.props.icon, "mdi-36px")} + || renderRawIcon(this.props.icon, "mdi-36px")} {this.props.control == null || this.props.control.name} diff --git a/src/components/UiItemList/UiItem.js b/src/components/UiItemList/UiItem.js index 3821c18..886f47c 100644 --- a/src/components/UiItemList/UiItem.js +++ b/src/components/UiItemList/UiItem.js @@ -185,7 +185,7 @@ export class DropDown extends UiControl { } export class Slider extends UiControl { - runPrimaryAction = (_e: ?any, v: ?number) => { + runPrimaryAction = (e: ?Event, v: ?number) => { if (v != null) { this.changeState(v); } @@ -197,8 +197,9 @@ export class Slider extends UiControl { this.props.item.delayedApply || this.runPrimaryAction()} + step={this.props.item.step || 1} + onChange={(e, v) => + this.props.item.delayedApply || this.runPrimaryAction(e, v)} onDragEnd={this.runPrimaryAction} disabled={!this.isEnabled()} /> ]; diff --git a/src/components/UiItemList/index.js b/src/components/UiItemList/index.js index eef50ec..b23b3cc 100644 --- a/src/components/UiItemList/index.js +++ b/src/components/UiItemList/index.js @@ -2,7 +2,7 @@ import React from "react"; import ListItem from "@material-ui/core/ListItem"; import ListItemIcon from "@material-ui/core/ListItemIcon"; -import { renderIcon } from "utils/parseIconName"; +import { renderIcon } from "config/icon"; import type { ControlUI } from "config/flowtypes"; @@ -33,7 +33,9 @@ export default class UiItemList extends React.PureComponent { return ( {control.icon == null || - {renderIcon(control.icon, "mdi-24px")}} + + {renderIcon(control.icon, this.props.state, "mdi-24px")} + } {this.renderControl(control)} ); diff --git a/src/config/flowtypes.js b/src/config/flowtypes.js index bef0562..6e58f3b 100644 --- a/src/config/flowtypes.js +++ b/src/config/flowtypes.js @@ -1,5 +1,6 @@ // @flow import type { Color } from "config/colors"; +import type { Icon } from "config/icon"; export type TopicType = (msg: Buffer) => any; @@ -33,7 +34,7 @@ export type UIToggle = $ReadOnly<{| type: "toggle", text: string, topic: string, - icon?: string, + icon?: Icon, enableCondition?: TopicDependentOption, on?: Actual, off?: Actual, @@ -44,7 +45,7 @@ export type UIDropDown = $ReadOnly<{| type: "dropDown", text: string, topic: string, - icon?: string, + icon?: Icon, enableCondition?: TopicDependentOption, options: Map, renderValue?: (value: string) => string @@ -54,7 +55,7 @@ export type UISlider = $ReadOnly<{| type: "slider", text: string, topic: string, - icon?: string, + icon?: Icon, enableCondition?: TopicDependentOption, min?: number, max?: number, @@ -74,21 +75,21 @@ export type UILink = $ReadOnly<{| enableCondition?: StateDependentOption, // TODO: check if both the following options are implemented - icon?: string + icon?: Icon |}>; export type UIText = $ReadOnly<{| type: "text", text: string, topic: string, - icon?: string + icon?: Icon |}>; export type UIProgress = $ReadOnly<{| type: "progress", text: string, topic: string, - icon?: string, + icon?: Icon, min?: number, max?: number |}>; @@ -105,11 +106,7 @@ export type ControlUI = export type Control = { name: string, position: [number, number], - icon: string | ( - internals: Map, - actuals: Map, - state: State - ) => string, + icon: Icon, iconColor?: ( internals: Map, actuals: Map, diff --git a/src/config/icon.js b/src/config/icon.js new file mode 100644 index 0000000..524395e --- /dev/null +++ b/src/config/icon.js @@ -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, Map, 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) => { + 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 = getInternals(state); + const actuals: Map = getActuals(state); + return icon(internals, actuals, state); +}; + +export const renderRawIcon = + (icon: RawIcon, extraClass?: string): React.Node => { + return ; + }; + +export const renderIcon = + (icon: Icon, state: State, extraClass?: string): React.Node => { + return renderRawIcon(toRawIcon(icon, state), extraClass); + }; diff --git a/src/utils/parseIconName.js b/src/utils/parseIconName.js deleted file mode 100644 index 96d290f..0000000 --- a/src/utils/parseIconName.js +++ /dev/null @@ -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 ; -}; - -export const controlGetIcon = (control: Control, state: State): string => { - const internals: Map = getInternals(state); - const actuals: Map = 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); -}; diff --git a/webpack.config.js b/webpack.config.js index 71d7f96..0c38752 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,7 +3,6 @@ const webpack = require('webpack'); const WebpackShellPlugin = require('webpack-shell-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); - const preBuildScripts = process.env.NO_FLOW == undefined ? process.env.FLOW_PATH != undefined ? [process.env.FLOW_PATH] : ['flow'] : []; diff --git a/yarn.lock b/yarn.lock index 592ad3d..935b0e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -175,6 +175,10 @@ acorn@^5.0.0, acorn@^5.5.0: version "5.5.3" 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: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" @@ -1026,6 +1030,14 @@ bcrypt-pbkdf@^1.0.0: dependencies: 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: version "1.6.27" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.27.tgz#8e56c6f8b2dd6c4fe8d32102b83d4f25868e4b3a" @@ -1380,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" supports-color "^5.3.0" -chalk@^2.4.1: +chalk@^2.3.0, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -1404,6 +1416,10 @@ charenc@~0.0.1: version "0.0.2" 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: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" @@ -1588,7 +1604,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: 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" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" @@ -2141,6 +2157,10 @@ duplexer3@^0.1.4: version "0.1.4" 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: version "3.5.4" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" @@ -2160,6 +2180,10 @@ ee-first@1.1.1: version "1.1.1" 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: version "1.3.42" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9" @@ -2570,6 +2594,10 @@ filename-regex@^2.0.0: version "2.0.1" 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: version "2.2.3" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" @@ -2924,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" 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: version "1.2.5" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" @@ -4493,6 +4528,10 @@ onetime@^2.0.0: dependencies: 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: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" @@ -6230,6 +6269,10 @@ trim-right@^1.0.1: version "1.0.1" 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: version "1.9.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" @@ -6540,6 +6583,23 @@ wbuf@^1.1.0, wbuf@^1.7.2: dependencies: 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: version "3.0.8" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.0.8.tgz#90eddcf04a4bfc31aa8c0edc4c76785bc4f1ccd9" @@ -6734,6 +6794,13 @@ ws@^3.2.0: safe-buffer "~5.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: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"