diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index 0fbb2a57ca9..6ab86435371 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -171,14 +171,20 @@ def async_setup(hass, config): development_repo = config.get(DOMAIN, {}).get(CONF_FRONTEND_REPO) if development_repo is not None: hass.http.register_static_path( - '/api/hassio/app-es5', - os.path.join(development_repo, 'hassio/build-es5'), False) + '/api/hassio/app', + os.path.join(development_repo, 'hassio/build'), False) hass.http.register_view(HassIOView(host, websession)) if 'frontend' in hass.config.components: - yield from hass.components.frontend.async_register_built_in_panel( - 'hassio', 'Hass.io', 'hass:home-assistant') + yield from hass.components.panel_custom.async_register_panel( + frontend_url_path='hassio', + webcomponent_name='hassio-main', + sidebar_title='Hass.io', + sidebar_icon='hass:home-assistant', + js_url='/api/hassio/app/entrypoint.js', + embed_iframe=True, + ) if 'http' in config: yield from hassio.update_hass_api(config['http']) diff --git a/homeassistant/components/panel_custom.py b/homeassistant/components/panel_custom.py index 4659578ae27..0444e7a5b53 100644 --- a/homeassistant/components/panel_custom.py +++ b/homeassistant/components/panel_custom.py @@ -9,6 +9,7 @@ import os import voluptuous as vol +from homeassistant.loader import bind_hass import homeassistant.helpers.config_validation as cv DOMAIN = 'panel_custom' @@ -24,6 +25,9 @@ CONF_JS_URL = 'js_url' CONF_EMBED_IFRAME = 'embed_iframe' CONF_TRUST_EXTERNAL_SCRIPT = 'trust_external_script' +DEFAULT_EMBED_IFRAME = False +DEFAULT_TRUST_EXTERNAL = False + DEFAULT_ICON = 'mdi:bookmark' LEGACY_URL = '/api/panel_custom/{}' @@ -38,33 +42,99 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_CONFIG): dict, vol.Optional(CONF_WEBCOMPONENT_PATH): cv.isfile, vol.Optional(CONF_JS_URL): cv.string, - vol.Optional(CONF_EMBED_IFRAME, default=False): cv.boolean, - vol.Optional(CONF_TRUST_EXTERNAL_SCRIPT, default=False): cv.boolean, + vol.Optional(CONF_EMBED_IFRAME, + default=DEFAULT_EMBED_IFRAME): cv.boolean, + vol.Optional(CONF_TRUST_EXTERNAL_SCRIPT, + default=DEFAULT_TRUST_EXTERNAL): cv.boolean, })]) }, extra=vol.ALLOW_EXTRA) _LOGGER = logging.getLogger(__name__) +@bind_hass +async def async_register_panel( + hass, + # The url to serve the panel + frontend_url_path, + # The webcomponent name that loads your panel + webcomponent_name, + # Title/icon for sidebar + sidebar_title=None, + sidebar_icon=None, + # HTML source of your panel + html_url=None, + # JS source of your panel + js_url=None, + # If your panel should be run inside an iframe + embed_iframe=DEFAULT_EMBED_IFRAME, + # Should user be asked for confirmation when loading external source + trust_external=DEFAULT_TRUST_EXTERNAL, + # Configuration to be passed to the panel + config=None): + """Register a new custom panel.""" + if js_url is None and html_url is None: + raise ValueError('Either js_url or html_url is required.') + elif js_url and html_url: + raise ValueError('Pass in either JS url or HTML url, not both.') + + if config is not None and not isinstance(config, dict): + raise ValueError('Config needs to be a dictionary.') + + custom_panel_config = { + 'name': webcomponent_name, + 'embed_iframe': embed_iframe, + 'trust_external': trust_external, + } + + if js_url is not None: + custom_panel_config['js_url'] = js_url + + if html_url is not None: + custom_panel_config['html_url'] = html_url + + if config is not None: + # Make copy because we're mutating it + config = dict(config) + else: + config = {} + + config['_panel_custom'] = custom_panel_config + + await hass.components.frontend.async_register_built_in_panel( + component_name='custom', + sidebar_title=sidebar_title, + sidebar_icon=sidebar_icon, + frontend_url_path=frontend_url_path, + config=config + ) + + async def async_setup(hass, config): """Initialize custom panel.""" success = False for panel in config.get(DOMAIN): - name = panel.get(CONF_COMPONENT_NAME) + name = panel[CONF_COMPONENT_NAME] + + kwargs = { + 'webcomponent_name': panel[CONF_COMPONENT_NAME], + 'frontend_url_path': panel.get(CONF_URL_PATH, name), + 'sidebar_title': panel.get(CONF_SIDEBAR_TITLE), + 'sidebar_icon': panel.get(CONF_SIDEBAR_ICON), + 'config': panel.get(CONF_CONFIG), + 'trust_external': panel[CONF_TRUST_EXTERNAL_SCRIPT], + 'embed_iframe': panel[CONF_EMBED_IFRAME], + } + panel_path = panel.get(CONF_WEBCOMPONENT_PATH) if panel_path is None: - panel_path = hass.config.path(PANEL_DIR, '{}.html'.format(name)) - - custom_panel_config = { - 'name': name, - 'embed_iframe': panel[CONF_EMBED_IFRAME], - 'trust_external': panel[CONF_TRUST_EXTERNAL_SCRIPT], - } + panel_path = hass.config.path( + PANEL_DIR, '{}.html'.format(name)) if CONF_JS_URL in panel: - custom_panel_config['js_url'] = panel[CONF_JS_URL] + kwargs['js_url'] = panel[CONF_JS_URL] elif not await hass.async_add_job(os.path.isfile, panel_path): _LOGGER.error('Unable to find webcomponent for %s: %s', @@ -74,23 +144,9 @@ async def async_setup(hass, config): else: url = LEGACY_URL.format(name) hass.http.register_static_path(url, panel_path) - custom_panel_config['html_url'] = LEGACY_URL.format(name) + kwargs['html_url'] = url - if CONF_CONFIG in panel: - # Make copy because we're mutating it - config = dict(panel[CONF_CONFIG]) - else: - config = {} - - config['_panel_custom'] = custom_panel_config - - await hass.components.frontend.async_register_built_in_panel( - component_name='custom', - sidebar_title=panel.get(CONF_SIDEBAR_TITLE), - sidebar_icon=panel.get(CONF_SIDEBAR_ICON), - frontend_url_path=panel.get(CONF_URL_PATH), - config=config - ) + await async_register_panel(hass, **kwargs) success = True