mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Pre-construct frontend index.html (#10520)
* Pre-construct frontend index.html * Cache templates * Update frontend to 20171111.0 * Fix iframe panel test
This commit is contained in:
parent
96e7944fa8
commit
c8648fbfb8
@ -13,6 +13,7 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
import jinja2
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
@ -22,7 +23,7 @@ from homeassistant.const import CONF_NAME, EVENT_THEMES_UPDATED
|
|||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
|
|
||||||
REQUIREMENTS = ['home-assistant-frontend==20171110.0']
|
REQUIREMENTS = ['home-assistant-frontend==20171111.0']
|
||||||
|
|
||||||
DOMAIN = 'frontend'
|
DOMAIN = 'frontend'
|
||||||
DEPENDENCIES = ['api', 'websocket_api', 'http']
|
DEPENDENCIES = ['api', 'websocket_api', 'http']
|
||||||
@ -171,8 +172,6 @@ class BuiltInPanel(AbstractPanel):
|
|||||||
If frontend_repository_path is set, will be prepended to path of
|
If frontend_repository_path is set, will be prepended to path of
|
||||||
built-in components.
|
built-in components.
|
||||||
"""
|
"""
|
||||||
panel_path = 'panels/ha-panel-{}.html'.format(self.component_name)
|
|
||||||
|
|
||||||
if frontend_repository_path is None:
|
if frontend_repository_path is None:
|
||||||
import hass_frontend
|
import hass_frontend
|
||||||
import hass_frontend_es5
|
import hass_frontend_es5
|
||||||
@ -180,11 +179,11 @@ class BuiltInPanel(AbstractPanel):
|
|||||||
self.webcomponent_url_latest = \
|
self.webcomponent_url_latest = \
|
||||||
'/frontend_latest/panels/ha-panel-{}-{}.html'.format(
|
'/frontend_latest/panels/ha-panel-{}-{}.html'.format(
|
||||||
self.component_name,
|
self.component_name,
|
||||||
hass_frontend.FINGERPRINTS[panel_path])
|
hass_frontend.FINGERPRINTS[self.component_name])
|
||||||
self.webcomponent_url_es5 = \
|
self.webcomponent_url_es5 = \
|
||||||
'/frontend_es5/panels/ha-panel-{}-{}.html'.format(
|
'/frontend_es5/panels/ha-panel-{}-{}.html'.format(
|
||||||
self.component_name,
|
self.component_name,
|
||||||
hass_frontend_es5.FINGERPRINTS[panel_path])
|
hass_frontend_es5.FINGERPRINTS[self.component_name])
|
||||||
else:
|
else:
|
||||||
# Dev mode
|
# Dev mode
|
||||||
self.webcomponent_url_es5 = self.webcomponent_url_latest = \
|
self.webcomponent_url_es5 = self.webcomponent_url_latest = \
|
||||||
@ -335,7 +334,7 @@ def async_setup(hass, config):
|
|||||||
if os.path.isdir(local):
|
if os.path.isdir(local):
|
||||||
hass.http.register_static_path("/local", local, not is_dev)
|
hass.http.register_static_path("/local", local, not is_dev)
|
||||||
|
|
||||||
index_view = IndexView(is_dev, js_version)
|
index_view = IndexView(repo_path, js_version)
|
||||||
hass.http.register_view(index_view)
|
hass.http.register_view(index_view)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -435,50 +434,40 @@ class IndexView(HomeAssistantView):
|
|||||||
requires_auth = False
|
requires_auth = False
|
||||||
extra_urls = ['/states', '/states/{extra}']
|
extra_urls = ['/states', '/states/{extra}']
|
||||||
|
|
||||||
def __init__(self, use_repo, js_option):
|
def __init__(self, repo_path, js_option):
|
||||||
"""Initialize the frontend view."""
|
"""Initialize the frontend view."""
|
||||||
from jinja2 import FileSystemLoader, Environment
|
self.repo_path = repo_path
|
||||||
|
|
||||||
self.use_repo = use_repo
|
|
||||||
self.templates = Environment(
|
|
||||||
autoescape=True,
|
|
||||||
loader=FileSystemLoader(
|
|
||||||
os.path.join(os.path.dirname(__file__), 'templates/')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.js_option = js_option
|
self.js_option = js_option
|
||||||
|
self._template_cache = {}
|
||||||
|
|
||||||
|
def get_template(self, latest):
|
||||||
|
"""Get template."""
|
||||||
|
if self.repo_path is not None:
|
||||||
|
root = self.repo_path
|
||||||
|
elif latest:
|
||||||
|
import hass_frontend
|
||||||
|
root = hass_frontend.where()
|
||||||
|
else:
|
||||||
|
import hass_frontend_es5
|
||||||
|
root = hass_frontend_es5.where()
|
||||||
|
|
||||||
|
tpl = self._template_cache.get(root)
|
||||||
|
|
||||||
|
if tpl is None:
|
||||||
|
with open(os.path.join(root, 'index.html')) as file:
|
||||||
|
tpl = jinja2.Template(file.read())
|
||||||
|
|
||||||
|
# Cache template if not running from repository
|
||||||
|
if self.repo_path is None:
|
||||||
|
self._template_cache[root] = tpl
|
||||||
|
|
||||||
|
return tpl
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def get(self, request, extra=None):
|
def get(self, request, extra=None):
|
||||||
"""Serve the index view."""
|
"""Serve the index view."""
|
||||||
hass = request.app['hass']
|
hass = request.app['hass']
|
||||||
latest = _is_latest(self.js_option, request)
|
latest = _is_latest(self.js_option, request)
|
||||||
compatibility_url = None
|
|
||||||
|
|
||||||
if self.use_repo:
|
|
||||||
core_url = '/home-assistant-polymer/{}/core.js'.format(
|
|
||||||
'build' if latest else 'build-es5')
|
|
||||||
ui_url = '/home-assistant-polymer/src/home-assistant.html'
|
|
||||||
icons_fp = ''
|
|
||||||
icons_url = '/static/mdi.html'
|
|
||||||
else:
|
|
||||||
if latest:
|
|
||||||
import hass_frontend
|
|
||||||
core_url = '/frontend_latest/core-{}.js'.format(
|
|
||||||
hass_frontend.FINGERPRINTS['core.js'])
|
|
||||||
ui_url = '/frontend_latest/frontend-{}.html'.format(
|
|
||||||
hass_frontend.FINGERPRINTS['frontend.html'])
|
|
||||||
else:
|
|
||||||
import hass_frontend_es5
|
|
||||||
core_url = '/frontend_es5/core-{}.js'.format(
|
|
||||||
hass_frontend_es5.FINGERPRINTS['core.js'])
|
|
||||||
compatibility_url = '/frontend_es5/compatibility-{}.js'.format(
|
|
||||||
hass_frontend_es5.FINGERPRINTS['compatibility.js'])
|
|
||||||
ui_url = '/frontend_es5/frontend-{}.html'.format(
|
|
||||||
hass_frontend_es5.FINGERPRINTS['frontend.html'])
|
|
||||||
import hass_frontend
|
|
||||||
icons_fp = '-{}'.format(hass_frontend.FINGERPRINTS['mdi.html'])
|
|
||||||
icons_url = '/static/mdi{}.html'.format(icons_fp)
|
|
||||||
|
|
||||||
if request.path == '/':
|
if request.path == '/':
|
||||||
panel = 'states'
|
panel = 'states'
|
||||||
@ -497,23 +486,17 @@ class IndexView(HomeAssistantView):
|
|||||||
# do not try to auto connect on load
|
# do not try to auto connect on load
|
||||||
no_auth = 'false'
|
no_auth = 'false'
|
||||||
|
|
||||||
template = yield from hass.async_add_job(
|
template = yield from hass.async_add_job(self.get_template, latest)
|
||||||
self.templates.get_template, 'index.html')
|
|
||||||
|
|
||||||
# pylint is wrong
|
|
||||||
# pylint: disable=no-member
|
|
||||||
# This is a jinja2 template, not a HA template so we call 'render'.
|
|
||||||
resp = template.render(
|
resp = template.render(
|
||||||
core_url=core_url, ui_url=ui_url,
|
no_auth=no_auth,
|
||||||
compatibility_url=compatibility_url, no_auth=no_auth,
|
panel_url=panel_url,
|
||||||
icons_url=icons_url, icons=icons_fp,
|
panels=hass.data[DATA_PANELS],
|
||||||
panel_url=panel_url, panels=hass.data[DATA_PANELS],
|
dev_mode=self.repo_path is not None,
|
||||||
dev_mode=self.use_repo,
|
|
||||||
theme_color=MANIFEST_JSON['theme_color'],
|
theme_color=MANIFEST_JSON['theme_color'],
|
||||||
extra_urls=hass.data[DATA_EXTRA_HTML_URL],
|
extra_urls=hass.data[DATA_EXTRA_HTML_URL],
|
||||||
latest=latest,
|
latest=latest,
|
||||||
service_worker_name='/service_worker.js' if latest else
|
)
|
||||||
'/service_worker_es5.js')
|
|
||||||
|
|
||||||
return web.Response(text=resp, content_type='text/html')
|
return web.Response(text=resp, content_type='text/html')
|
||||||
|
|
||||||
@ -528,8 +511,8 @@ class ManifestJSONView(HomeAssistantView):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def get(self, request): # pylint: disable=no-self-use
|
def get(self, request): # pylint: disable=no-self-use
|
||||||
"""Return the manifest.json."""
|
"""Return the manifest.json."""
|
||||||
msg = json.dumps(MANIFEST_JSON, sort_keys=True).encode('UTF-8')
|
msg = json.dumps(MANIFEST_JSON, sort_keys=True)
|
||||||
return web.Response(body=msg, content_type="application/manifest+json")
|
return web.Response(text=msg, content_type="application/manifest+json")
|
||||||
|
|
||||||
|
|
||||||
class ThemesView(HomeAssistantView):
|
class ThemesView(HomeAssistantView):
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Home Assistant</title>
|
|
||||||
|
|
||||||
<link rel='manifest' href='/manifest.json'>
|
|
||||||
<link rel='icon' href='/static/icons/favicon.ico'>
|
|
||||||
<link rel='apple-touch-icon' sizes='180x180'
|
|
||||||
href='/static/icons/favicon-apple-180x180.png'>
|
|
||||||
<link rel="mask-icon" href="/static/icons/mask-icon.svg" color="#3fbbf4">
|
|
||||||
{% if not dev_mode %}
|
|
||||||
<link rel='preload' href='{{ core_url }}' as='script'/>
|
|
||||||
{% for panel in panels.values() -%}
|
|
||||||
<link rel='prefetch' href='{{ panel.webcomponent_url }}'>
|
|
||||||
{% endfor -%}
|
|
||||||
{% endif %}
|
|
||||||
<meta name='apple-mobile-web-app-capable' content='yes'>
|
|
||||||
<meta name="msapplication-square70x70logo" content="/static/icons/tile-win-70x70.png"/>
|
|
||||||
<meta name="msapplication-square150x150logo" content="/static/icons/tile-win-150x150.png"/>
|
|
||||||
<meta name="msapplication-wide310x150logo" content="/static/icons/tile-win-310x150.png"/>
|
|
||||||
<meta name="msapplication-square310x310logo" content="/static/icons/tile-win-310x310.png"/>
|
|
||||||
<meta name="msapplication-TileColor" content="#3fbbf4ff"/>
|
|
||||||
<meta name='mobile-web-app-capable' content='yes'>
|
|
||||||
<meta name='viewport' content='width=device-width, user-scalable=no'>
|
|
||||||
<meta name='theme-color' content='{{ theme_color }}'>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: 'Roboto', 'Noto', sans-serif;
|
|
||||||
font-weight: 400;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ha-init-skeleton::before {
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
height: 48px;
|
|
||||||
background-color: {{ theme_color }};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ha-init-skeleton .message {
|
|
||||||
transition: font-size 2s;
|
|
||||||
font-size: 0;
|
|
||||||
padding: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ha-init-skeleton.error .message {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ha-init-skeleton a {
|
|
||||||
color: {{ theme_color }};
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
function initError() {
|
|
||||||
document.getElementById('ha-init-skeleton').classList.add('error');
|
|
||||||
};
|
|
||||||
window.noAuth = {{ no_auth }};
|
|
||||||
window.Polymer = {
|
|
||||||
lazyRegister: true,
|
|
||||||
useNativeCSSProperties: true,
|
|
||||||
dom: 'shadow',
|
|
||||||
suppressTemplateNotifications: true,
|
|
||||||
suppressBindingNotifications: true,
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id='ha-init-skeleton'>
|
|
||||||
<div class='message'>
|
|
||||||
Home Assistant had trouble<br>connecting to the server.<br><br>
|
|
||||||
<a href='/'>TRY AGAIN</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<home-assistant></home-assistant>
|
|
||||||
{# <script src='/static/home-assistant-polymer/build/_demo_data_compiled.js'></script> -#}
|
|
||||||
{% if not latest -%}
|
|
||||||
<script>
|
|
||||||
var compatibilityRequired = (typeof Object.assign != 'function');
|
|
||||||
if (compatibilityRequired) {
|
|
||||||
var e = document.createElement('script');
|
|
||||||
e.onerror = initError;
|
|
||||||
e.src = '{{ compatibility_url }}';
|
|
||||||
document.head.appendChild(e);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endif -%}
|
|
||||||
<script src='{{ core_url }}'></script>
|
|
||||||
{% if not dev_mode and not latest -%}
|
|
||||||
<script src='/frontend_es5/custom-elements-es5-adapter.js'></script>
|
|
||||||
{% endif -%}
|
|
||||||
<script>
|
|
||||||
var webComponentsSupported = (
|
|
||||||
'customElements' in window &&
|
|
||||||
'import' in document.createElement('link') &&
|
|
||||||
'content' in document.createElement('template'));
|
|
||||||
if (!webComponentsSupported) {
|
|
||||||
var e = document.createElement('script');
|
|
||||||
e.onerror = initError;
|
|
||||||
e.src = '/static/webcomponents-lite.js';
|
|
||||||
document.head.appendChild(e);
|
|
||||||
}
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', function () {
|
|
||||||
navigator.serviceWorker.register('{{ service_worker_name }}');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<link rel='import' href='{{ ui_url }}' onerror='initError()'>
|
|
||||||
{% if panel_url -%}
|
|
||||||
<link rel='import' href='{{ panel_url }}' onerror='initError()' async>
|
|
||||||
{% endif -%}
|
|
||||||
<link rel='import' href='{{ icons_url }}' async>
|
|
||||||
{% for extra_url in extra_urls -%}
|
|
||||||
<link rel='import' href='{{ extra_url }}' async>
|
|
||||||
{% endfor -%}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -331,7 +331,7 @@ hipnotify==1.0.8
|
|||||||
holidays==0.8.1
|
holidays==0.8.1
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20171110.0
|
home-assistant-frontend==20171111.0
|
||||||
|
|
||||||
# homeassistant.components.camera.onvif
|
# homeassistant.components.camera.onvif
|
||||||
http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b8997481967d6a7fe1c57118999.zip#suds-passworddigest-py3==0.1.2a
|
http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b8997481967d6a7fe1c57118999.zip#suds-passworddigest-py3==0.1.2a
|
||||||
|
@ -74,7 +74,7 @@ hbmqtt==0.8
|
|||||||
holidays==0.8.1
|
holidays==0.8.1
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20171110.0
|
home-assistant-frontend==20171111.0
|
||||||
|
|
||||||
# homeassistant.components.influxdb
|
# homeassistant.components.influxdb
|
||||||
# homeassistant.components.sensor.influxdb
|
# homeassistant.components.sensor.influxdb
|
||||||
|
@ -34,7 +34,7 @@ class TestPanelIframe(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
@patch.dict('hass_frontend_es5.FINGERPRINTS',
|
@patch.dict('hass_frontend_es5.FINGERPRINTS',
|
||||||
{'panels/ha-panel-iframe.html': 'md5md5'})
|
{'iframe': 'md5md5'})
|
||||||
def test_correct_config(self):
|
def test_correct_config(self):
|
||||||
"""Test correct config."""
|
"""Test correct config."""
|
||||||
assert setup.setup_component(
|
assert setup.setup_component(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user