diff --git a/gulp/common/http.js b/gulp/common/http.js new file mode 100644 index 000000000000..2391156105a5 --- /dev/null +++ b/gulp/common/http.js @@ -0,0 +1,25 @@ +// From https://www.tomas-dvorak.cz/posts/nodejs-request-without-dependencies/ +const http = require('http'); +const https = require('https'); + +module.exports.getContent = function getContent(url) { + // return new pending promise + return new Promise((resolve, reject) => { + // select http or https module, depending on reqested url + const lib = url.startsWith('https') ? https : http; + const request = lib.get(url, (response) => { + // handle http errors + if (response.statusCode < 200 || response.statusCode > 299) { + reject(new Error('Failed to load page, status code: ' + response.statusCode)); + } + // temporary data holder + const body = []; + // on every content chunk, push it to the data array + response.on('data', chunk => body.push(chunk)); + // we are done, resolve promise with those joined chunks + response.on('end', () => resolve(body.join(''))); + }); + // handle connection errors of the request + request.on('error', err => reject(err)); + }); +}; diff --git a/gulp/tasks/gen-index-html.js b/gulp/tasks/gen-index-html.js index 4b91a9ac8f87..a70ad1c1ff5a 100644 --- a/gulp/tasks/gen-index-html.js +++ b/gulp/tasks/gen-index-html.js @@ -19,8 +19,8 @@ function generateIndex(es6) { const toReplace = [ // Needs to look like a color during CSS minifiaction ['{{ theme_color }}', '#THEME'], - ['/home-assistant-polymer/hass_frontend/mdi.html', - `/static/mdi-${md5(path.resolve(config.output, 'mdi.html'))}.html`], + ['/home-assistant-polymer/hass_frontend/hass_icons.html', + `/static/hass_icons-${md5(path.resolve(config.output, 'hass_icons.html'))}.html`], ]; if (!es6) { diff --git a/gulp/tasks/gen-service-worker.js b/gulp/tasks/gen-service-worker.js index 241637e10f42..9d874295d29b 100755 --- a/gulp/tasks/gen-service-worker.js +++ b/gulp/tasks/gen-service-worker.js @@ -23,7 +23,7 @@ const DEV = !!JSON.parse(process.env.BUILD_DEV || 'true'); const dynamicUrlToDependencies = {}; const staticFingerprinted = [ - 'mdi.html', + 'hass_icons.html', 'translations/en.json', ]; @@ -80,6 +80,7 @@ function generateServiceWorker(es6) { directoryIndex: '', dynamicUrlToDependencies: dynamicUrlToDependencies, staticFileGlobs: [ + baseRootDir + '/mdi.html', baseRootDir + '/icons/favicon.ico', baseRootDir + '/icons/favicon-192x192.png', baseRootDir + '/webcomponents-lite.min.js', diff --git a/gulp/tasks/hass-icons.js b/gulp/tasks/hass-icons.js new file mode 100644 index 000000000000..c70637464cff --- /dev/null +++ b/gulp/tasks/hass-icons.js @@ -0,0 +1,103 @@ +const gulp = require('gulp'); +const path = require('path'); +const fs = require('fs'); +const parse5 = require('parse5'); +const getContent = require('../common/http').getContent; + +const outputDir = 'hass_frontend'; +const iconRegEx = /hass:[\w-]+/g; + +const BUILT_IN_PANEL_ICONS = [ + 'settings', // Config + 'home-assistant', // Hass.io + 'poll-box', // History panel + 'format-list-bulleted-type', // Logbook + 'mailbox', // Mailbox + 'account-location', // Map + 'cart', // Shopping List +]; + +function mapFiles(startPath, filter, mapFunc) { + const files = fs.readdirSync(startPath); + for (let i = 0; i < files.length; i++) { + const filename = path.join(startPath, files[i]); + const stat = fs.lstatSync(filename); + if (stat.isDirectory()) { + mapFiles(filename, filter, mapFunc); + } else if (filename.indexOf(filter) >= 0) { + mapFunc(filename); + } + } +} + + +function findIcons() { + const icons = new Set(BUILT_IN_PANEL_ICONS); + function processFile(filename) { + const content = fs.readFileSync(filename); + let match; + // eslint-disable-next-line + while (match = iconRegEx.exec(content)) { + // strip off "hass:" and add to set + icons.add(match[0].substr(5)); + } + } + mapFiles('src', '.html', processFile); + mapFiles('panels', '.html', processFile); + mapFiles('hassio', '.html', processFile); + mapFiles('js', '.js', processFile); + return icons; +} + +function generateHassIcons() { + const icons = findIcons(); + + const iconDoc = parse5.parseFragment(fs.readFileSync(`${outputDir}/mdi.html`, { encoding: 'utf-8' })); + + const ironIconset = iconDoc.childNodes[0]; + ironIconset.attrs.forEach((attr) => { + if (attr.name === 'name') { + attr.value = 'hass'; + } + }); + + const defs = ironIconset.childNodes[0].childNodes[0]; + defs.childNodes = defs.childNodes.filter(icon => icons.has(icon.attrs[0].value)); + + fs.writeFileSync(`${outputDir}/hass_icons.html`, parse5.serialize(iconDoc)); + // eslint-disable-next-line + console.log(`Home Assistant has ${icons.size} icons.`); +} + +async function downloadMDIIcons() { + // Fetch website of MaterialDesignIcons.com + const content = await getContent('https://raw.githubusercontent.com/Templarian/MaterialDesign/master/site/getting-started.savvy'); + // Find link to Polymer v1 download + const downloadMatch = content.match('(/api/download/polymer/v1/([A-Z0-9-]{36}))'); + + if (!downloadMatch) { + // eslint-disable-next-line + console.error('Unable to find Polymer v1 download link'); + return null; + } + + // Download iconset + let iconSet = await getContent(`https://materialdesignicons.com${downloadMatch[0]}`); + + // Strip out the import statement + iconSet = iconSet.substr(iconSet.indexOf('
@@ -52,7 +52,7 @@
- +
diff --git a/hassio/addon-view/hassio-addon-info.html b/hassio/addon-view/hassio-addon-info.html index bfb8b9e4baa7..1b4d4445bb07 100644 --- a/hassio/addon-view/hassio-addon-info.html +++ b/hassio/addon-view/hassio-addon-info.html @@ -52,11 +52,11 @@ } iron-icon.stopped { color: var(--google-red-300); - } + } ha-call-api-button { font-weight: 500; color: var(--primary-color); - } + } .right { float: right; } @@ -67,7 +67,7 @@
@@ -93,14 +93,14 @@ diff --git a/hassio/addon-view/hassio-addon-view.html b/hassio/addon-view/hassio-addon-view.html index 75cc8a028c5f..907a82d2aa30 100644 --- a/hassio/addon-view/hassio-addon-view.html +++ b/hassio/addon-view/hassio-addon-view.html @@ -21,7 +21,7 @@ :host { color: var(--primary-text-color); --paper-card-header-color: var(--primary-text-color); - } + } .content { padding: 24px 0 32px; max-width: 600px; @@ -42,10 +42,10 @@ > - +
Hass.io: add-on details
diff --git a/hassio/dashboard/hassio-addons.html b/hassio/dashboard/hassio-addons.html index 51ae65ceb5c4..e5c70b327b48 100644 --- a/hassio/dashboard/hassio-addons.html +++ b/hassio/dashboard/hassio-addons.html @@ -54,7 +54,7 @@ } computeIcon(addon) { - return addon.installed !== addon.version ? 'mdi:arrow-up-bold-circle' : 'mdi:puzzle'; + return addon.installed !== addon.version ? 'hass:arrow-up-bold-circle' : 'hass:puzzle'; } computeIconTitle(addon) { diff --git a/hassio/dashboard/hassio-hass-update.html b/hassio/dashboard/hassio-hass-update.html index 9fb6874907b4..0f206dafb416 100644 --- a/hassio/dashboard/hassio-hass-update.html +++ b/hassio/dashboard/hassio-hass-update.html @@ -20,15 +20,15 @@ } - +
diff --git a/panels/config/dashboard/ha-config-entries-menu.html b/panels/config/dashboard/ha-config-entries-menu.html index e6a77a5964c3..6691adb5eab5 100644 --- a/panels/config/dashboard/ha-config-entries-menu.html +++ b/panels/config/dashboard/ha-config-entries-menu.html @@ -22,7 +22,7 @@ Integrations
EXPERIMENTAL – Manage connected devices and services
- + diff --git a/panels/config/dashboard/ha-config-navigation.html b/panels/config/dashboard/ha-config-navigation.html index 921960c16323..087a2f13ea12 100644 --- a/panels/config/dashboard/ha-config-navigation.html +++ b/panels/config/dashboard/ha-config-navigation.html @@ -24,7 +24,7 @@ [[_computeCaption(item, localize)]]
[[_computeDescription(item, localize)]]
- + diff --git a/panels/config/script/ha-script-editor.html b/panels/config/script/ha-script-editor.html index 59c75607757c..10816dcf1050 100644 --- a/panels/config/script/ha-script-editor.html +++ b/panels/config/script/ha-script-editor.html @@ -85,7 +85,7 @@
Script [[name]]
@@ -100,7 +100,7 @@ diff --git a/panels/config/script/ha-script-picker.html b/panels/config/script/ha-script-picker.html index 1be02521d2fc..18095ef93ed8 100644 --- a/panels/config/script/ha-script-picker.html +++ b/panels/config/script/ha-script-picker.html @@ -44,7 +44,7 @@
[[localize('ui.panel.config.script.caption')]]
@@ -72,7 +72,7 @@
[[computeName(script)]]
[[computeDescription(script)]]
- + @@ -80,7 +80,7 @@ diff --git a/panels/config/zwave/ha-config-zwave.html b/panels/config/zwave/ha-config-zwave.html index dc3fa927728d..4d0525e9788b 100644 --- a/panels/config/zwave/ha-config-zwave.html +++ b/panels/config/zwave/ha-config-zwave.html @@ -76,7 +76,7 @@
[[localize('ui.panel.config.zwave.caption')]]
@@ -96,7 +96,7 @@
diff --git a/panels/config/zwave/zwave-network.html b/panels/config/zwave/zwave-network.html index 53f75b634697..e15a525c1569 100644 --- a/panels/config/zwave/zwave-network.html +++ b/panels/config/zwave/zwave-network.html @@ -46,7 +46,7 @@ diff --git a/panels/dev-info/ha-panel-dev-info.html b/panels/dev-info/ha-panel-dev-info.html index 02c10c0dc5d8..0316adde5534 100644 --- a/panels/dev-info/ha-panel-dev-info.html +++ b/panels/dev-info/ha-panel-dev-info.html @@ -195,7 +195,7 @@

Press the button to load the full Home Assistant log. - +

[[errorLog]]
diff --git a/panels/dev-state/ha-panel-dev-state.html b/panels/dev-state/ha-panel-dev-state.html index d26ada4c5586..39763734b744 100644 --- a/panels/dev-state/ha-panel-dev-state.html +++ b/panels/dev-state/ha-panel-dev-state.html @@ -119,7 +119,7 @@

Current entities

diff --git a/panels/logbook/ha-panel-logbook.html b/panels/logbook/ha-panel-logbook.html index 2bb9ab8d1ad9..d097f639702b 100644 --- a/panels/logbook/ha-panel-logbook.html +++ b/panels/logbook/ha-panel-logbook.html @@ -57,7 +57,7 @@
[[localize('panel.logbook')]]
diff --git a/panels/mailbox/ha-panel-mailbox.html b/panels/mailbox/ha-panel-mailbox.html index b2476a687036..24ced83d026f 100644 --- a/panels/mailbox/ha-panel-mailbox.html +++ b/panels/mailbox/ha-panel-mailbox.html @@ -130,7 +130,7 @@

[[localize('ui.panel.mailbox.playback_title')]]

diff --git a/panels/shopping-list/ha-panel-shopping-list.html b/panels/shopping-list/ha-panel-shopping-list.html index 8409c3601a30..38d93479f8f7 100644 --- a/panels/shopping-list/ha-panel-shopping-list.html +++ b/panels/shopping-list/ha-panel-shopping-list.html @@ -74,7 +74,7 @@ vertical-offset="-5" > @@ -91,7 +91,7 @@ diff --git a/script/build_frontend b/script/build_frontend index afb778d8f22f..ab161605634c 100755 --- a/script/build_frontend +++ b/script/build_frontend @@ -42,7 +42,7 @@ cp bower_components/webcomponentsjs/webcomponents-lite.js $OUTPUT_DIR cp bower_components/webcomponentsjs/custom-elements-es5-adapter.js $OUTPUT_DIR_ES5 # Icons -script/update_mdi.py +BUILD_DEV=0 ./node_modules/.bin/gulp gen-icons # Leaflet mkdir $OUTPUT_DIR/images/leaflet @@ -55,7 +55,7 @@ cp build-es5/service_worker.js $OUTPUT_DIR_ES5 BUILD_DEV=0 ./node_modules/.bin/gulp gen-service-worker cp build/service_worker.js $OUTPUT_DIR -./node_modules/.bin/gulp compress +BUILD_DEV=0 ./node_modules/.bin/gulp compress # Generate the __init__ file echo "VERSION = '`git rev-parse HEAD`'" >> $OUTPUT_DIR/__init__.py @@ -66,5 +66,5 @@ echo "CREATED_AT = `date +%s`" >> $OUTPUT_DIR_ES5/__init__.py # Generate the MD5 hash of the new frontend script/fingerprint_frontend.py --base_dir $OUTPUT_DIR script/fingerprint_frontend.py --base_dir $OUTPUT_DIR_ES5 -./node_modules/.bin/gulp gen-index-html -./node_modules/.bin/gulp gen-index-html-es5 +BUILD_DEV=0 ./node_modules/.bin/gulp gen-index-html +BUILD_DEV=0 ./node_modules/.bin/gulp gen-index-html-es5 diff --git a/script/update_mdi.py b/script/update_mdi.py deleted file mode 100755 index ae9225773a4e..000000000000 --- a/script/update_mdi.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -"""Download the latest Polymer v1 iconset for materialdesignicons.com.""" -import os -import re -import sys -import urllib.request - -GETTING_STARTED_URL = ('https://raw.githubusercontent.com/Templarian/' - 'MaterialDesign/master/site/getting-started.savvy') -DOWNLOAD_LINK = re.compile(r'(/api/download/polymer/v1/([A-Z0-9-]{36}))') -START_ICONSET = ' @@ -322,9 +322,9 @@ computePlaybackControlIcon(playerObj) { if (playerObj.isPlaying) { - return playerObj.supportsPause ? 'mdi:pause' : 'mdi:stop'; + return playerObj.supportsPause ? 'hass:pause' : 'hass:stop'; } else if (playerObj.isPaused || playerObj.isOff || playerObj.isIdle) { - return playerObj.supportsPlay ? 'mdi:play' : null; + return playerObj.supportsPlay ? 'hass:play' : null; } return ''; } diff --git a/src/cards/ha-plant-card.html b/src/cards/ha-plant-card.html index 5b0a12cc6748..640beef56e73 100644 --- a/src/cards/ha-plant-card.html +++ b/src/cards/ha-plant-card.html @@ -59,11 +59,11 @@ constructor() { super(); this.sensors = { - moisture: 'mdi:water', - temperature: 'mdi:thermometer', - brightness: 'mdi:white-balance-sunny', - conductivity: 'mdi:emoticon-poop', - battery: 'mdi:battery' + moisture: 'hass:water', + temperature: 'hass:thermometer', + brightness: 'hass:white-balance-sunny', + conductivity: 'hass:emoticon-poop', + battery: 'hass:battery' }; } diff --git a/src/cards/ha-weather-card.html b/src/cards/ha-weather-card.html index 8c5145f1fe09..8ec99803339d 100644 --- a/src/cards/ha-weather-card.html +++ b/src/cards/ha-weather-card.html @@ -134,20 +134,20 @@ 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N' ]; this.weatherIcons = { - 'clear-night': 'mdi:weather-night', - cloudy: 'mdi:weather-cloudy', - fog: 'mdi:weather-fog', - hail: 'mdi:weather-hail', + 'clear-night': 'hass:weather-night', + cloudy: 'hass:weather-cloudy', + fog: 'hass:weather-fog', + hail: 'hass:weather-hail', lightning: 'mid:weather-lightning', - 'lightning-rainy': 'mdi:weather-lightning-rainy', - partlycloudy: 'mdi:weather-partlycloudy', - pouring: 'mdi:weather-pouring', - rainy: 'mdi:weather-rainy', - snowy: 'mdi:weather-snowy', - 'snowy-rainy': 'mdi:weather-snowy-rainy', - sunny: 'mdi:weather-sunny', - windy: 'mdi:weather-windy', - 'windy-variant': 'mdi:weather-windy-variant' + 'lightning-rainy': 'hass:weather-lightning-rainy', + partlycloudy: 'hass:weather-partlycloudy', + pouring: 'hass:weather-pouring', + rainy: 'hass:weather-rainy', + snowy: 'hass:weather-snowy', + 'snowy-rainy': 'hass:weather-snowy-rainy', + sunny: 'hass:weather-sunny', + windy: 'hass:weather-windy', + 'windy-variant': 'hass:weather-windy-variant' }; } diff --git a/src/components/entity/ha-entity-picker.html b/src/components/entity/ha-entity-picker.html index 10ffa37e124c..114e76cb45cd 100644 --- a/src/components/entity/ha-entity-picker.html +++ b/src/components/entity/ha-entity-picker.html @@ -40,7 +40,7 @@ Clear @@ -157,7 +157,7 @@ } _computeToggleIcon(opened) { - return opened ? 'mdi:menu-up' : 'mdi:menu-down'; + return opened ? 'hass:menu-up' : 'hass:menu-down'; } } diff --git a/src/components/entity/ha-entity-toggle.html b/src/components/entity/ha-entity-toggle.html index 0e9b41a96a4f..d328d74d8676 100644 --- a/src/components/entity/ha-entity-toggle.html +++ b/src/components/entity/ha-entity-toggle.html @@ -25,8 +25,8 @@ diff --git a/src/components/ha-combo-box.html b/src/components/ha-combo-box.html index 4f5e5e9c063c..c9adb994327e 100644 --- a/src/components/ha-combo-box.html +++ b/src/components/ha-combo-box.html @@ -34,7 +34,7 @@ Clear
- - -
diff --git a/src/components/ha-cover-tilt-controls.html b/src/components/ha-cover-tilt-controls.html index f751964791ab..b570177be5c0 100644 --- a/src/components/ha-cover-tilt-controls.html +++ b/src/components/ha-cover-tilt-controls.html @@ -16,14 +16,14 @@ visibility: hidden !important; } - - - diff --git a/src/components/ha-demo-badge.html b/src/components/ha-demo-badge.html index cf91b895b12d..193e17fc227e 100644 --- a/src/components/ha-demo-badge.html +++ b/src/components/ha-demo-badge.html @@ -11,7 +11,7 @@ diff --git a/src/components/ha-icon.html b/src/components/ha-icon.html new file mode 100644 index 000000000000..2f4b999e1254 --- /dev/null +++ b/src/components/ha-icon.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + diff --git a/src/components/ha-menu-button.html b/src/components/ha-menu-button.html index 2777b8bc5d79..907a3e77d19b 100644 --- a/src/components/ha-menu-button.html +++ b/src/components/ha-menu-button.html @@ -11,7 +11,7 @@ } diff --git a/src/components/ha-sidebar.html b/src/components/ha-sidebar.html index 57946ec062e6..a30adb5fedeb 100644 --- a/src/components/ha-sidebar.html +++ b/src/components/ha-sidebar.html @@ -8,6 +8,7 @@ + @@ -95,24 +96,24 @@
Home Assistant
- +
- + [[localize('panel.states')]] - + [[localize('ui.sidebar.log_out')]] @@ -124,29 +125,29 @@
diff --git a/src/components/ha-start-voice-button.html b/src/components/ha-start-voice-button.html index 95bd40013266..b183f508fe07 100644 --- a/src/components/ha-start-voice-button.html +++ b/src/components/ha-start-voice-button.html @@ -6,7 +6,7 @@
diff --git a/src/dialogs/more-info/controls/more-info-fan.html b/src/dialogs/more-info/controls/more-info-fan.html index a391d1367d08..d10ed70f4a46 100644 --- a/src/dialogs/more-info/controls/more-info-fan.html +++ b/src/dialogs/more-info/controls/more-info-fan.html @@ -62,10 +62,10 @@
Direction
- -
diff --git a/src/dialogs/more-info/controls/more-info-light.html b/src/dialogs/more-info/controls/more-info-light.html index ade233e5741e..787156bc4c6c 100644 --- a/src/dialogs/more-info/controls/more-info-light.html +++ b/src/dialogs/more-info/controls/more-info-light.html @@ -70,7 +70,7 @@
@@ -78,7 +78,7 @@
diff --git a/src/dialogs/more-info/controls/more-info-media_player.html b/src/dialogs/more-info/controls/more-info-media_player.html index 05c5a9169459..c49d2e84cc54 100644 --- a/src/dialogs/more-info/controls/more-info-media_player.html +++ b/src/dialogs/more-info/controls/more-info-media_player.html @@ -58,19 +58,19 @@
-
@@ -79,13 +79,13 @@
+ icon="hass:volume-off"> + icon="hass:volume-medium"> + icon="hass:volume-high">
- + @@ -179,7 +179,7 @@ } computeMuteVolumeIcon(playerObj) { - return playerObj.isMuted ? 'mdi:volume-off' : 'mdi:volume-high'; + return playerObj.isMuted ? 'hass:volume-off' : 'hass:volume-high'; } computeHideVolumeButtons(playerObj) { @@ -192,9 +192,9 @@ computePlaybackControlIcon(playerObj) { if (playerObj.isPlaying) { - return playerObj.supportsPause ? 'mdi:pause' : 'mdi:stop'; + return playerObj.supportsPause ? 'hass:pause' : 'hass:stop'; } - return playerObj.supportsPlay ? 'mdi:play' : null; + return playerObj.supportsPlay ? 'hass:play' : null; } computeHidePowerButton(playerObj) { diff --git a/src/dialogs/more-info/controls/more-info-vacuum.html b/src/dialogs/more-info/controls/more-info-vacuum.html index 0f0c5e8d9322..3f2763087735 100644 --- a/src/dialogs/more-info/controls/more-info-vacuum.html +++ b/src/dialogs/more-info/controls/more-info-vacuum.html @@ -43,23 +43,23 @@
Vacuum cleaner commands:
-
-
-
-
-
@@ -76,7 +76,7 @@
- [[stateObj.attributes.fan_speed]] + [[stateObj.attributes.fan_speed]]

diff --git a/src/dialogs/more-info/controls/more-info-weather.html b/src/dialogs/more-info/controls/more-info-weather.html index ce30c727c6ef..cf8c53073740 100644 --- a/src/dialogs/more-info/controls/more-info-weather.html +++ b/src/dialogs/more-info/controls/more-info-weather.html @@ -43,30 +43,30 @@
- +
[[localize('ui.card.weather.attributes.temperature')]]
[[stateObj.attributes.temperature]] [[getUnit('temperature')]]
- +
[[localize('ui.card.weather.attributes.humidity')]]
[[stateObj.attributes.humidity]] %
- +
[[localize('ui.card.weather.attributes.wind_speed')]]
[[getWind(stateObj.attributes.wind_speed, stateObj.attributes.wind_bearing, localize)]]