mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +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
|
||||
import voluptuous as vol
|
||||
import jinja2
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
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.loader import bind_hass
|
||||
|
||||
REQUIREMENTS = ['home-assistant-frontend==20171110.0']
|
||||
REQUIREMENTS = ['home-assistant-frontend==20171111.0']
|
||||
|
||||
DOMAIN = 'frontend'
|
||||
DEPENDENCIES = ['api', 'websocket_api', 'http']
|
||||
@ -171,8 +172,6 @@ class BuiltInPanel(AbstractPanel):
|
||||
If frontend_repository_path is set, will be prepended to path of
|
||||
built-in components.
|
||||
"""
|
||||
panel_path = 'panels/ha-panel-{}.html'.format(self.component_name)
|
||||
|
||||
if frontend_repository_path is None:
|
||||
import hass_frontend
|
||||
import hass_frontend_es5
|
||||
@ -180,11 +179,11 @@ class BuiltInPanel(AbstractPanel):
|
||||
self.webcomponent_url_latest = \
|
||||
'/frontend_latest/panels/ha-panel-{}-{}.html'.format(
|
||||
self.component_name,
|
||||
hass_frontend.FINGERPRINTS[panel_path])
|
||||
hass_frontend.FINGERPRINTS[self.component_name])
|
||||
self.webcomponent_url_es5 = \
|
||||
'/frontend_es5/panels/ha-panel-{}-{}.html'.format(
|
||||
self.component_name,
|
||||
hass_frontend_es5.FINGERPRINTS[panel_path])
|
||||
hass_frontend_es5.FINGERPRINTS[self.component_name])
|
||||
else:
|
||||
# Dev mode
|
||||
self.webcomponent_url_es5 = self.webcomponent_url_latest = \
|
||||
@ -335,7 +334,7 @@ def async_setup(hass, config):
|
||||
if os.path.isdir(local):
|
||||
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)
|
||||
|
||||
@asyncio.coroutine
|
||||
@ -435,50 +434,40 @@ class IndexView(HomeAssistantView):
|
||||
requires_auth = False
|
||||
extra_urls = ['/states', '/states/{extra}']
|
||||
|
||||
def __init__(self, use_repo, js_option):
|
||||
def __init__(self, repo_path, js_option):
|
||||
"""Initialize the frontend view."""
|
||||
from jinja2 import FileSystemLoader, Environment
|
||||
|
||||
self.use_repo = use_repo
|
||||
self.templates = Environment(
|
||||
autoescape=True,
|
||||
loader=FileSystemLoader(
|
||||
os.path.join(os.path.dirname(__file__), 'templates/')
|
||||
)
|
||||
)
|
||||
self.repo_path = repo_path
|
||||
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
|
||||
def get(self, request, extra=None):
|
||||
"""Serve the index view."""
|
||||
hass = request.app['hass']
|
||||
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 == '/':
|
||||
panel = 'states'
|
||||
@ -497,23 +486,17 @@ class IndexView(HomeAssistantView):
|
||||
# do not try to auto connect on load
|
||||
no_auth = 'false'
|
||||
|
||||
template = yield from hass.async_add_job(
|
||||
self.templates.get_template, 'index.html')
|
||||
template = yield from hass.async_add_job(self.get_template, latest)
|
||||
|
||||
# pylint is wrong
|
||||
# pylint: disable=no-member
|
||||
# This is a jinja2 template, not a HA template so we call 'render'.
|
||||
resp = template.render(
|
||||
core_url=core_url, ui_url=ui_url,
|
||||
compatibility_url=compatibility_url, no_auth=no_auth,
|
||||
icons_url=icons_url, icons=icons_fp,
|
||||
panel_url=panel_url, panels=hass.data[DATA_PANELS],
|
||||
dev_mode=self.use_repo,
|
||||
no_auth=no_auth,
|
||||
panel_url=panel_url,
|
||||
panels=hass.data[DATA_PANELS],
|
||||
dev_mode=self.repo_path is not None,
|
||||
theme_color=MANIFEST_JSON['theme_color'],
|
||||
extra_urls=hass.data[DATA_EXTRA_HTML_URL],
|
||||
latest=latest,
|
||||
service_worker_name='/service_worker.js' if latest else
|
||||
'/service_worker_es5.js')
|
||||
)
|
||||
|
||||
return web.Response(text=resp, content_type='text/html')
|
||||
|
||||
@ -528,8 +511,8 @@ class ManifestJSONView(HomeAssistantView):
|
||||
@asyncio.coroutine
|
||||
def get(self, request): # pylint: disable=no-self-use
|
||||
"""Return the manifest.json."""
|
||||
msg = json.dumps(MANIFEST_JSON, sort_keys=True).encode('UTF-8')
|
||||
return web.Response(body=msg, content_type="application/manifest+json")
|
||||
msg = json.dumps(MANIFEST_JSON, sort_keys=True)
|
||||
return web.Response(text=msg, content_type="application/manifest+json")
|
||||
|
||||
|
||||
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
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20171110.0
|
||||
home-assistant-frontend==20171111.0
|
||||
|
||||
# homeassistant.components.camera.onvif
|
||||
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
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20171110.0
|
||||
home-assistant-frontend==20171111.0
|
||||
|
||||
# homeassistant.components.influxdb
|
||||
# homeassistant.components.sensor.influxdb
|
||||
|
@ -34,7 +34,7 @@ class TestPanelIframe(unittest.TestCase):
|
||||
})
|
||||
|
||||
@patch.dict('hass_frontend_es5.FINGERPRINTS',
|
||||
{'panels/ha-panel-iframe.html': 'md5md5'})
|
||||
{'iframe': 'md5md5'})
|
||||
def test_correct_config(self):
|
||||
"""Test correct config."""
|
||||
assert setup.setup_component(
|
||||
|
Loading…
x
Reference in New Issue
Block a user