diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 2a741afcfbc7..73eb24d08cd4 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -70,8 +70,6 @@ MANIFEST_JSON = { DATA_PANELS = "frontend_panels" DATA_JS_VERSION = "frontend_js_version" -DATA_EXTRA_HTML_URL = "frontend_extra_html_url" -DATA_EXTRA_HTML_URL_ES5 = "frontend_extra_html_url_es5" DATA_EXTRA_MODULE_URL = "frontend_extra_module_url" DATA_EXTRA_JS_URL_ES5 = "frontend_extra_js_url_es5" @@ -91,29 +89,23 @@ _LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = vol.Schema( { - DOMAIN: vol.All( - cv.deprecated(CONF_EXTRA_HTML_URL, invalidation_version="0.115"), - cv.deprecated(CONF_EXTRA_HTML_URL_ES5, invalidation_version="0.115"), - vol.Schema( - { - vol.Optional(CONF_FRONTEND_REPO): cv.isdir, - vol.Optional(CONF_THEMES): vol.Schema( - {cv.string: {cv.string: cv.string}} - ), - vol.Optional(CONF_EXTRA_HTML_URL): vol.All( - cv.ensure_list, [cv.string] - ), - vol.Optional(CONF_EXTRA_MODULE_URL): vol.All( - cv.ensure_list, [cv.string] - ), - vol.Optional(CONF_EXTRA_JS_URL_ES5): vol.All( - cv.ensure_list, [cv.string] - ), - # We no longer use these options. - vol.Optional(CONF_EXTRA_HTML_URL_ES5): cv.match_all, - vol.Optional(CONF_JS_VERSION): cv.match_all, - }, - ), + DOMAIN: vol.Schema( + { + vol.Optional(CONF_FRONTEND_REPO): cv.isdir, + vol.Optional(CONF_THEMES): vol.Schema( + {cv.string: {cv.string: cv.string}} + ), + vol.Optional(CONF_EXTRA_MODULE_URL): vol.All( + cv.ensure_list, [cv.string] + ), + vol.Optional(CONF_EXTRA_JS_URL_ES5): vol.All( + cv.ensure_list, [cv.string] + ), + # We no longer use these options. + vol.Optional(CONF_EXTRA_HTML_URL): cv.match_all, + vol.Optional(CONF_EXTRA_HTML_URL_ES5): cv.match_all, + vol.Optional(CONF_JS_VERSION): cv.match_all, + }, ) }, extra=vol.ALLOW_EXTRA, @@ -220,17 +212,6 @@ def async_remove_panel(hass, frontend_url_path): hass.bus.async_fire(EVENT_PANELS_UPDATED) -@bind_hass -@callback -def add_extra_html_url(hass, url, es5=False): - """Register extra html url to load.""" - key = DATA_EXTRA_HTML_URL_ES5 if es5 else DATA_EXTRA_HTML_URL - url_set = hass.data.get(key) - if url_set is None: - url_set = hass.data[key] = set() - url_set.add(url) - - def add_extra_js_url(hass, url, es5=False): """Register extra js or module url to load.""" key = DATA_EXTRA_JS_URL_ES5 if es5 else DATA_EXTRA_MODULE_URL @@ -267,6 +248,13 @@ async def async_setup(hass, config): conf = config.get(DOMAIN, {}) + for key in (CONF_EXTRA_HTML_URL, CONF_EXTRA_HTML_URL_ES5, CONF_JS_VERSION): + if key in conf: + _LOGGER.error( + "Please remove %s from your frontend config. It is no longer supported", + key, + ) + repo_path = conf.get(CONF_FRONTEND_REPO) is_dev = repo_path is not None root_path = _frontend_root(repo_path) @@ -315,12 +303,6 @@ async def async_setup(hass, config): sidebar_icon="hass:hammer", ) - if DATA_EXTRA_HTML_URL not in hass.data: - hass.data[DATA_EXTRA_HTML_URL] = set() - - for url in conf.get(CONF_EXTRA_HTML_URL, []): - add_extra_html_url(hass, url, False) - if DATA_EXTRA_MODULE_URL not in hass.data: hass.data[DATA_EXTRA_MODULE_URL] = set() @@ -522,7 +504,6 @@ class IndexView(web_urldispatcher.AbstractResource): return web.Response( text=template.render( theme_color=MANIFEST_JSON["theme_color"], - extra_urls=hass.data[DATA_EXTRA_HTML_URL], extra_modules=hass.data[DATA_EXTRA_MODULE_URL], extra_js_es5=hass.data[DATA_EXTRA_JS_URL_ES5], ), diff --git a/homeassistant/components/panel_custom/__init__.py b/homeassistant/components/panel_custom/__init__.py index a2175253ce1f..8bab4d019e64 100644 --- a/homeassistant/components/panel_custom/__init__.py +++ b/homeassistant/components/panel_custom/__init__.py @@ -1,6 +1,5 @@ """Register a custom front end panel.""" import logging -import os import voluptuous as vol @@ -15,7 +14,6 @@ CONF_SIDEBAR_TITLE = "sidebar_title" CONF_SIDEBAR_ICON = "sidebar_icon" CONF_URL_PATH = "url_path" CONF_CONFIG = "config" -CONF_WEBCOMPONENT_PATH = "webcomponent_path" CONF_JS_URL = "js_url" CONF_MODULE_URL = "module_url" CONF_EMBED_IFRAME = "embed_iframe" @@ -32,55 +30,34 @@ LEGACY_URL = "/api/panel_custom/{}" PANEL_DIR = "panels" -def url_validator(value): - """Validate required urls are specified.""" - has_js_url = CONF_JS_URL in value - has_html_url = CONF_WEBCOMPONENT_PATH in value - has_module_url = CONF_MODULE_URL in value - - if has_html_url and (has_js_url or has_module_url): - raise vol.Invalid("You cannot specify other urls besides a webcomponent path") - - return value - - CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.All( cv.ensure_list, [ - vol.All( - cv.deprecated(CONF_WEBCOMPONENT_PATH), - vol.Schema( - { - vol.Required(CONF_COMPONENT_NAME): cv.string, - vol.Optional(CONF_SIDEBAR_TITLE): cv.string, - vol.Optional( - CONF_SIDEBAR_ICON, default=DEFAULT_ICON - ): cv.icon, - vol.Optional(CONF_URL_PATH): cv.string, - vol.Optional(CONF_CONFIG): dict, - vol.Optional( - CONF_WEBCOMPONENT_PATH, - ): cv.string, - vol.Optional( - CONF_JS_URL, - ): cv.string, - vol.Optional( - CONF_MODULE_URL, - ): cv.string, - vol.Optional( - CONF_EMBED_IFRAME, default=DEFAULT_EMBED_IFRAME - ): cv.boolean, - vol.Optional( - CONF_TRUST_EXTERNAL_SCRIPT, - default=DEFAULT_TRUST_EXTERNAL, - ): cv.boolean, - vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean, - } - ), - url_validator, - ) + vol.Schema( + { + vol.Required(CONF_COMPONENT_NAME): cv.string, + vol.Optional(CONF_SIDEBAR_TITLE): cv.string, + vol.Optional(CONF_SIDEBAR_ICON, default=DEFAULT_ICON): cv.icon, + vol.Optional(CONF_URL_PATH): cv.string, + vol.Optional(CONF_CONFIG): dict, + vol.Optional( + CONF_JS_URL, + ): cv.string, + vol.Optional( + CONF_MODULE_URL, + ): cv.string, + vol.Optional( + CONF_EMBED_IFRAME, default=DEFAULT_EMBED_IFRAME + ): cv.boolean, + vol.Optional( + CONF_TRUST_EXTERNAL_SCRIPT, + default=DEFAULT_TRUST_EXTERNAL, + ): cv.boolean, + vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean, + } + ), ], ) }, @@ -98,8 +75,6 @@ async def async_register_panel( # 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, # JS module of your panel @@ -114,16 +89,11 @@ async def async_register_panel( require_admin=False, ): """Register a new custom panel.""" - if js_url is None and html_url is None and module_url is None: + if js_url is None and module_url is None: raise ValueError("Either js_url, module_url or html_url is required.") - if html_url and (js_url or module_url): - raise ValueError("You cannot specify other paths with an HTML url") if config is not None and not isinstance(config, dict): raise ValueError("Config needs to be a dictionary.") - if html_url: - _LOGGER.warning("HTML custom panels have been deprecated") - custom_panel_config = { "name": webcomponent_name, "embed_iframe": embed_iframe, @@ -136,9 +106,6 @@ async def async_register_panel( if module_url is not None: custom_panel_config["module_url"] = module_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) @@ -162,8 +129,6 @@ async def async_setup(hass, config): if DOMAIN not in config: return True - seen = set() - for panel in config[DOMAIN]: name = panel[CONF_COMPONENT_NAME] @@ -184,29 +149,6 @@ async def async_setup(hass, config): if CONF_MODULE_URL in panel: kwargs["module_url"] = panel[CONF_MODULE_URL] - if CONF_MODULE_URL not in panel and CONF_JS_URL not in panel: - if name in seen: - _LOGGER.warning( - "Got HTML panel with duplicate name %s. Not registering", name - ) - continue - - seen.add(name) - panel_path = panel.get(CONF_WEBCOMPONENT_PATH) - - if panel_path is None: - panel_path = hass.config.path(PANEL_DIR, f"{name}.html") - - if not await hass.async_add_executor_job(os.path.isfile, panel_path): - _LOGGER.error( - "Unable to find webcomponent for %s: %s", name, panel_path - ) - continue - - url = LEGACY_URL.format(name) - hass.http.register_static_path(url, panel_path) - kwargs["html_url"] = url - try: await async_register_panel(hass, **kwargs) except ValueError as err: diff --git a/tests/components/frontend/test_init.py b/tests/components/frontend/test_init.py index a7ecbb0e5fec..7298ad753d28 100644 --- a/tests/components/frontend/test_init.py +++ b/tests/components/frontend/test_init.py @@ -334,14 +334,6 @@ async def test_missing_themes(hass, hass_ws_client): assert msg["result"]["themes"] == {} -async def test_extra_urls(mock_http_client_with_urls, mock_onboarded): - """Test that extra urls are loaded.""" - resp = await mock_http_client_with_urls.get("/lovelace?latest") - assert resp.status == 200 - text = await resp.text() - assert text.find('href="https://domain.com/my_extra_url.html"') >= 0 - - async def test_get_panels(hass, hass_ws_client, mock_http_client): """Test get_panels command.""" events = async_capture_events(hass, EVENT_PANELS_UPDATED) diff --git a/tests/components/panel_custom/test_init.py b/tests/components/panel_custom/test_init.py index caa55749c500..ddcb4079ef7b 100644 --- a/tests/components/panel_custom/test_init.py +++ b/tests/components/panel_custom/test_init.py @@ -30,52 +30,6 @@ async def test_webcomponent_custom_path_not_found(hass): assert "nice_url" not in panels -async def test_webcomponent_custom_path(hass, caplog): - """Test if a web component is found in config panels dir.""" - filename = "mock.file" - - config = { - "panel_custom": [ - { - "name": "todo-mvc", - "webcomponent_path": filename, - "sidebar_title": "Sidebar Title", - "sidebar_icon": "mdi:iconicon", - "url_path": "nice_url", - "config": {"hello": "world"}, - }, - {"name": "todo-mvc"}, - ] - } - - with patch("os.path.isfile", Mock(return_value=True)): - with patch("os.access", Mock(return_value=True)): - result = await setup.async_setup_component(hass, "panel_custom", config) - assert result - - panels = hass.data.get(frontend.DATA_PANELS, []) - - assert panels - assert "nice_url" in panels - - panel = panels["nice_url"] - - assert panel.config == { - "hello": "world", - "_panel_custom": { - "html_url": "/api/panel_custom/todo-mvc", - "name": "todo-mvc", - "embed_iframe": False, - "trust_external": False, - }, - } - assert panel.frontend_url_path == "nice_url" - assert panel.sidebar_icon == "mdi:iconicon" - assert panel.sidebar_title == "Sidebar Title" - - assert "Got HTML panel with duplicate name todo-mvc. Not registering" in caplog.text - - async def test_js_webcomponent(hass): """Test if a web component is found in config panels dir.""" config = { @@ -188,31 +142,6 @@ async def test_latest_and_es5_build(hass): assert panel.frontend_url_path == "nice_url" -async def test_url_option_conflict(hass): - """Test config with multiple url options.""" - to_try = [ - { - "panel_custom": { - "name": "todo-mvc", - "webcomponent_path": "/local/bla.html", - "js_url": "/local/bla.js", - } - }, - { - "panel_custom": { - "name": "todo-mvc", - "webcomponent_path": "/local/bla.html", - "module_url": "/local/bla.js", - "js_url": "/local/bla.js", - } - }, - ] - - for config in to_try: - result = await setup.async_setup_component(hass, "panel_custom", config) - assert not result - - async def test_url_path_conflict(hass): """Test config with overlapping url path.""" assert await setup.async_setup_component(