diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000000..986bebd04798 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +bower_components +hass_frontend +build +build-temp +.git diff --git a/.gitignore b/.gitignore index 73c957952dd1..c9d8f269e245 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,18 @@ node_modules/* bower_components/* npm-debug.log .DS_Store +hass_frontend/* + +# Python stuff +*.py[cod] +*.egg +*.egg-info + +# venv stuff +pyvenv.cfg +pip-selfcheck.json +venv +.venv +lib +bin +dist diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000000..073f04853254 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM node:8.2.1-alpine + +# install yarn +ENV PATH /root/.yarn/bin:$PATH + +RUN apk update \ + && apk add curl bash binutils tar git python3 \ + && rm -rf /var/cache/apk/* \ + && /bin/bash \ + && touch ~/.bashrc \ + && curl -o- -L https://yarnpkg.com/install.sh | bash + +RUN mkdir -p /frontend +WORKDIR /frontend + +ENV NODE_ENV production + +COPY package.json ./ +RUN yarn + +COPY bower.json ./ +RUN ./node_modules/.bin/bower install --allow-root + +COPY . . +CMD [ "/bin/bash", "./script/build_frontend" ] diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000000..eac9fad475bb --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include README.md +include LICENSE.md +graft hass_frontend +recursive-exclude * *.py[co] diff --git a/gulp/tasks/gen-service-worker.js b/gulp/tasks/gen-service-worker.js index 74a8e39382b9..a1851608ef10 100755 --- a/gulp/tasks/gen-service-worker.js +++ b/gulp/tasks/gen-service-worker.js @@ -23,7 +23,7 @@ const config = require('../config'); const DEV = !!JSON.parse(process.env.BUILD_DEV || 'true'); -var rootDir = '..'; +var rootDir = 'hass_frontend'; var panelDir = path.resolve(rootDir, 'panels'); var dynamicUrlToDependencies = { @@ -44,8 +44,8 @@ var staticFingerprinted = [ // These panels will always be registered inside HA and thus can // be safely assumed to be able to preload. var panelsFingerprinted = [ - 'map', 'dev-event', 'dev-info', 'dev-service', 'dev-state', 'dev-template', - 'dev-mqtt', + 'dev-event', 'dev-info', 'dev-service', 'dev-state', 'dev-template', + 'dev-mqtt', 'kiosk', ]; function md5(filename) { @@ -71,7 +71,7 @@ gulp.task('gen-service-worker', () => { panelsFingerprinted.forEach(panel => { var fpath = panelDir + '/ha-panel-' + panel + '.html'; var hash = md5(fpath); - var url = '/frontend/panels/' + panel + '-' + hash + '.html'; + var url = '/static/panels/ha-panel-' + panel + '-' + hash + '.html'; dynamicUrlToDependencies[url] = [fpath]; }); @@ -89,9 +89,11 @@ gulp.task('gen-service-worker', () => { rootDir + '/fonts/roboto/Roboto-Bold.ttf', rootDir + '/images/card_media_player_bg.png', ], - stripPrefix: '..', + stripPrefix: 'hass_frontend', replacePrefix: 'static', verbose: true, + // Allow our users to refresh to get latest version. + clientsClaim: true, }; genPromise = swPrecache.generate(options); diff --git a/package.json b/package.json index de91e63cd438..16e6017adc98 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,6 @@ "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", "dependencies": { - "es6-object-assign": "^1.1.0", - "home-assistant-js-websocket": "^1.1.0", - "preact": "^8.2.5" - }, - "devDependencies": { "babel-core": "^6.26.0", "babel-plugin-external-helpers": "^6.22.0", "babel-plugin-transform-object-rest-spread": "^6.26.0", @@ -34,6 +29,7 @@ "bower": "^1.8.2", "css-slam": "^2.0.2", "del": "^3.0.0", + "es6-object-assign": "^1.1.0", "eslint": "^4.8.0", "eslint-config-airbnb-base": "^12.0.2", "eslint-plugin-html": "^3.2.2", @@ -49,6 +45,7 @@ "gulp-rollup-each": "^2.0.0", "gulp-uglify": "^3.0.0", "gulp-util": "^3.0.8", + "home-assistant-js-websocket": "^1.1.0", "html-minifier": "^3.5.5", "merge-stream": "^1.0.1", "parse5": "^3.0.2", @@ -56,6 +53,7 @@ "polymer-build": "^2.1.0", "polymer-bundler": "^3.1.0", "polymer-cli": "^1.5.6", + "preact": "^8.2.5", "require-dir": "^0.3.2", "rollup": "^0.50.0", "rollup-plugin-babel": "^3.0.2", @@ -67,7 +65,9 @@ "run-sequence": "^2.2.0", "sw-precache": "^5.2.0", "uglify-js": "^3.1.3", - "vulcanize": "^1.16.0", + "vulcanize": "^1.16.0" + }, + "devDependencies": { "web-component-tester": "^6.3.0" } } diff --git a/public/__init__.py b/public/__init__.py new file mode 100644 index 000000000000..c7603274c2d9 --- /dev/null +++ b/public/__init__.py @@ -0,0 +1,8 @@ +"""AUTO-GENERATED. DO NOT MODIFY""" +import os + + +def where(): + """Return path to the frontend.""" + return os.path.dirname(__file__) + diff --git a/public/icons/favicon-1024x1024.png b/public/icons/favicon-1024x1024.png new file mode 100644 index 000000000000..4bcc7924726b Binary files /dev/null and b/public/icons/favicon-1024x1024.png differ diff --git a/public/icons/favicon-192x192.png b/public/icons/favicon-192x192.png new file mode 100644 index 000000000000..2959efdf89d8 Binary files /dev/null and b/public/icons/favicon-192x192.png differ diff --git a/public/icons/favicon-384x384.png b/public/icons/favicon-384x384.png new file mode 100644 index 000000000000..51f677707900 Binary files /dev/null and b/public/icons/favicon-384x384.png differ diff --git a/public/icons/favicon-512x512.png b/public/icons/favicon-512x512.png new file mode 100644 index 000000000000..28239a05ad57 Binary files /dev/null and b/public/icons/favicon-512x512.png differ diff --git a/public/icons/favicon-apple-180x180.png b/public/icons/favicon-apple-180x180.png new file mode 100644 index 000000000000..20117d00f227 Binary files /dev/null and b/public/icons/favicon-apple-180x180.png differ diff --git a/public/icons/favicon.ico b/public/icons/favicon.ico new file mode 100644 index 000000000000..6d12158c18b1 Binary files /dev/null and b/public/icons/favicon.ico differ diff --git a/public/icons/home-assistant-icon.svg b/public/icons/home-assistant-icon.svg new file mode 100644 index 000000000000..1ff4c190f593 --- /dev/null +++ b/public/icons/home-assistant-icon.svg @@ -0,0 +1,2814 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/tile-win-150x150.png b/public/icons/tile-win-150x150.png new file mode 100644 index 000000000000..20039166df63 Binary files /dev/null and b/public/icons/tile-win-150x150.png differ diff --git a/public/icons/tile-win-310x150.png b/public/icons/tile-win-310x150.png new file mode 100644 index 000000000000..6320cb6b2105 Binary files /dev/null and b/public/icons/tile-win-310x150.png differ diff --git a/public/icons/tile-win-310x310.png b/public/icons/tile-win-310x310.png new file mode 100644 index 000000000000..33bb1223c757 Binary files /dev/null and b/public/icons/tile-win-310x310.png differ diff --git a/public/icons/tile-win-70x70.png b/public/icons/tile-win-70x70.png new file mode 100644 index 000000000000..9adf95d56d59 Binary files /dev/null and b/public/icons/tile-win-70x70.png differ diff --git a/public/images/card_media_player_bg.png b/public/images/card_media_player_bg.png new file mode 100644 index 000000000000..6c97dd2f511e Binary files /dev/null and b/public/images/card_media_player_bg.png differ diff --git a/public/images/config_ecobee_thermostat.png b/public/images/config_ecobee_thermostat.png new file mode 100644 index 000000000000..e62a4165c9be Binary files /dev/null and b/public/images/config_ecobee_thermostat.png differ diff --git a/public/images/config_fitbit_app.png b/public/images/config_fitbit_app.png new file mode 100644 index 000000000000..271a0c6dd479 Binary files /dev/null and b/public/images/config_fitbit_app.png differ diff --git a/public/images/config_icloud.png b/public/images/config_icloud.png new file mode 100644 index 000000000000..2058986018b9 Binary files /dev/null and b/public/images/config_icloud.png differ diff --git a/public/images/config_insteon.png b/public/images/config_insteon.png new file mode 100644 index 000000000000..0039cf3d160f Binary files /dev/null and b/public/images/config_insteon.png differ diff --git a/public/images/config_philips_hue.jpg b/public/images/config_philips_hue.jpg new file mode 100644 index 000000000000..f10d258bf34f Binary files /dev/null and b/public/images/config_philips_hue.jpg differ diff --git a/public/images/config_webos.png b/public/images/config_webos.png new file mode 100644 index 000000000000..757aec76270b Binary files /dev/null and b/public/images/config_webos.png differ diff --git a/public/images/config_wink.png b/public/images/config_wink.png new file mode 100644 index 000000000000..6b91f8cb58ee Binary files /dev/null and b/public/images/config_wink.png differ diff --git a/public/images/darksky/weather-cloudy.svg b/public/images/darksky/weather-cloudy.svg new file mode 100644 index 000000000000..a0c80c53611a --- /dev/null +++ b/public/images/darksky/weather-cloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-fog.svg b/public/images/darksky/weather-fog.svg new file mode 100644 index 000000000000..42571dfb7385 --- /dev/null +++ b/public/images/darksky/weather-fog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-hail.svg b/public/images/darksky/weather-hail.svg new file mode 100644 index 000000000000..7934e54f7ae0 --- /dev/null +++ b/public/images/darksky/weather-hail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-night.svg b/public/images/darksky/weather-night.svg new file mode 100644 index 000000000000..d880912be93b --- /dev/null +++ b/public/images/darksky/weather-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-partlycloudy.svg b/public/images/darksky/weather-partlycloudy.svg new file mode 100644 index 000000000000..af93dfa0b2a0 --- /dev/null +++ b/public/images/darksky/weather-partlycloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-pouring.svg b/public/images/darksky/weather-pouring.svg new file mode 100644 index 000000000000..bf20e9bc0c95 --- /dev/null +++ b/public/images/darksky/weather-pouring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-rainy.svg b/public/images/darksky/weather-rainy.svg new file mode 100644 index 000000000000..27ae4d033ffb --- /dev/null +++ b/public/images/darksky/weather-rainy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-snowy.svg b/public/images/darksky/weather-snowy.svg new file mode 100644 index 000000000000..9c56c2bb4697 --- /dev/null +++ b/public/images/darksky/weather-snowy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-sunny.svg b/public/images/darksky/weather-sunny.svg new file mode 100644 index 000000000000..8f9733041a1f --- /dev/null +++ b/public/images/darksky/weather-sunny.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/darksky/weather-windy.svg b/public/images/darksky/weather-windy.svg new file mode 100644 index 000000000000..de0b444fd01f --- /dev/null +++ b/public/images/darksky/weather-windy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/logo_automatic.png b/public/images/logo_automatic.png new file mode 100644 index 000000000000..ab03fa93b4c6 Binary files /dev/null and b/public/images/logo_automatic.png differ diff --git a/public/images/logo_axis.png b/public/images/logo_axis.png new file mode 100644 index 000000000000..5eeb9b7b2a78 Binary files /dev/null and b/public/images/logo_axis.png differ diff --git a/public/images/logo_philips_hue.png b/public/images/logo_philips_hue.png new file mode 100644 index 000000000000..ae4df811fa8d Binary files /dev/null and b/public/images/logo_philips_hue.png differ diff --git a/public/images/logo_plex_mediaserver.png b/public/images/logo_plex_mediaserver.png new file mode 100644 index 000000000000..97a1b4b352cd Binary files /dev/null and b/public/images/logo_plex_mediaserver.png differ diff --git a/public/images/notification-badge.png b/public/images/notification-badge.png new file mode 100644 index 000000000000..2d254444915e Binary files /dev/null and b/public/images/notification-badge.png differ diff --git a/public/images/smart-tv.png b/public/images/smart-tv.png new file mode 100644 index 000000000000..5ecda68b4029 Binary files /dev/null and b/public/images/smart-tv.png differ diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 000000000000..77470cb39f05 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/script/bootstrap b/script/bootstrap new file mode 100755 index 000000000000..632ee812e2fe --- /dev/null +++ b/script/bootstrap @@ -0,0 +1,16 @@ +#!/bin/sh +# Resolve all frontend dependencies that the application requires to develop. + +# Stop on errors +set -e + +cd "$(dirname "$0")/.." + +# Install node modules +yarn install + +# Install bower web components. Allow to download the components as root since the user in docker is root. +./node_modules/.bin/bower install --allow-root + +# Build files that need to be generated to run development mode +yarn dev diff --git a/script/build_frontend b/script/build_frontend new file mode 100755 index 000000000000..06f34948408a --- /dev/null +++ b/script/build_frontend @@ -0,0 +1,54 @@ +#!/bin/sh +# Builds the frontend for production + +# Stop on errors +set -e + +cd "$(dirname "$0")/.." + +OUTPUT_DIR=hass_frontend + +rm -rf $OUTPUT_DIR +cp -r public $OUTPUT_DIR + +# Build frontend +BUILD_DEV=0 ./node_modules/.bin/gulp + +# Entry points +cp build/*.js build/*.html $OUTPUT_DIR + +# Panels +mkdir $OUTPUT_DIR/panels +cp build/panels/*.html $OUTPUT_DIR/panels + +# Local Roboto +cp -r bower_components/font-roboto-local/fonts $OUTPUT_DIR + +# Polyfill web components +cp bower_components/webcomponentsjs/webcomponents-lite.js $OUTPUT_DIR +cp bower_components/webcomponentsjs/custom-elements-es5-adapter.js $OUTPUT_DIR + +# Icons +script/update_mdi.py + +# Leaflet +mkdir $OUTPUT_DIR/images/leaflet +cp bower_components/leaflet/dist/leaflet.css $OUTPUT_DIR/images/leaflet +cp -r bower_components/leaflet/dist/images $OUTPUT_DIR/images/leaflet/ + +# Generate service worker +BUILD_DEV=0 ./node_modules/.bin/gulp gen-service-worker +cp build/service_worker.js $OUTPUT_DIR + + +# GZIP frontend +cd $OUTPUT_DIR +gzip -f -n -k -9 *.html *.js ./panels/*.html ./fonts/roboto/*.ttf ./fonts/robotomono/*.ttf +cd .. + +# Generate the __init__ file +echo "VERSION = '`git rev-parse HEAD`'" >> $OUTPUT_DIR/__init__.py +echo "CREATED_AT = `date +%s`" >> $OUTPUT_DIR/__init__.py + +# Generate the MD5 hash of the new frontend +script/fingerprint_frontend.py diff --git a/script/fingerprint_frontend.py b/script/fingerprint_frontend.py new file mode 100755 index 000000000000..f9bb43e8d9ee --- /dev/null +++ b/script/fingerprint_frontend.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Generate a file with all md5 hashes of the assets.""" + +from collections import OrderedDict +import glob +import hashlib +import json + +fingerprint_file = './hass_frontend/__init__.py' +base_dir = 'hass_frontend/' + + +def fingerprint(): + """Fingerprint the frontend files.""" + files = (glob.glob(base_dir + '**/*.html') + + glob.glob(base_dir + '*.html') + + glob.glob(base_dir + 'core.js') + + glob.glob(base_dir + 'compatibility.js')) + + md5s = OrderedDict() + + for fil in sorted(files): + name = fil[len(base_dir):] + with open(fil) as fp: + md5 = hashlib.md5(fp.read().encode('utf-8')).hexdigest() + md5s[name] = md5 + + template = "FINGERPRINTS = {}\n" + result = template.format(json.dumps(md5s, indent=4)) + + with open(fingerprint_file, 'at') as fp: + fp.write(result) + + +if __name__ == '__main__': + fingerprint() diff --git a/script/release b/script/release new file mode 100644 index 000000000000..dd01be6297ea --- /dev/null +++ b/script/release @@ -0,0 +1,6 @@ +#!/bin/sh +# Pushes a new version to PyPi. + +cd "$(dirname "$0")/.." + +python3 setup.py sdist upload diff --git a/script/update_mdi.py b/script/update_mdi.py new file mode 100755 index 000000000000..ae9225773a4e --- /dev/null +++ b/script/update_mdi.py @@ -0,0 +1,63 @@ +#!/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 = '