panel_custom: Allow ES5+latest build, deprecate html (#36464)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Paulus Schoutsen 2020-06-05 10:39:18 -07:00 committed by GitHub
parent c0307dca3a
commit 6faf9e8bbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 97 additions and 50 deletions

View File

@ -23,8 +23,6 @@ CONF_TRUST_EXTERNAL_SCRIPT = "trust_external_script"
CONF_URL_EXCLUSIVE_GROUP = "url_exclusive_group" CONF_URL_EXCLUSIVE_GROUP = "url_exclusive_group"
CONF_REQUIRE_ADMIN = "require_admin" CONF_REQUIRE_ADMIN = "require_admin"
MSG_URL_CONFLICT = "Pass in only one of webcomponent_path, module_url or js_url"
DEFAULT_EMBED_IFRAME = False DEFAULT_EMBED_IFRAME = False
DEFAULT_TRUST_EXTERNAL = False DEFAULT_TRUST_EXTERNAL = False
@ -33,39 +31,58 @@ LEGACY_URL = "/api/panel_custom/{}"
PANEL_DIR = "panels" 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:
if has_js_url or has_module_url:
raise vol.Invalid(
"You cannot specify other urls besides a webcomponent path"
)
return value
if not has_js_url and not has_module_url:
raise vol.Invalid(
f"You need to specify either {CONF_MODULE_URL} or {CONF_JS_URL} or both."
)
return value
CONFIG_SCHEMA = vol.Schema( CONFIG_SCHEMA = vol.Schema(
{ {
DOMAIN: vol.All( DOMAIN: vol.All(
cv.ensure_list, cv.ensure_list,
[ [
vol.Schema( vol.All(
{ vol.Schema(
vol.Required(CONF_COMPONENT_NAME): cv.string, {
vol.Optional(CONF_SIDEBAR_TITLE): cv.string, vol.Required(CONF_COMPONENT_NAME): cv.string,
vol.Optional(CONF_SIDEBAR_ICON, default=DEFAULT_ICON): cv.icon, vol.Optional(CONF_SIDEBAR_TITLE): cv.string,
vol.Optional(CONF_URL_PATH): cv.string, vol.Optional(
vol.Optional(CONF_CONFIG): dict, CONF_SIDEBAR_ICON, default=DEFAULT_ICON
vol.Exclusive( ): cv.icon,
CONF_WEBCOMPONENT_PATH, vol.Optional(CONF_URL_PATH): cv.string,
CONF_URL_EXCLUSIVE_GROUP, vol.Optional(CONF_CONFIG): dict,
msg=MSG_URL_CONFLICT, vol.Optional(CONF_WEBCOMPONENT_PATH,): cv.string,
): cv.string, vol.Optional(CONF_JS_URL,): cv.string,
vol.Exclusive( vol.Optional(CONF_MODULE_URL,): cv.string,
CONF_JS_URL, CONF_URL_EXCLUSIVE_GROUP, msg=MSG_URL_CONFLICT vol.Optional(
): cv.string, CONF_EMBED_IFRAME, default=DEFAULT_EMBED_IFRAME
vol.Exclusive( ): cv.boolean,
CONF_MODULE_URL, vol.Optional(
CONF_URL_EXCLUSIVE_GROUP, CONF_TRUST_EXTERNAL_SCRIPT,
msg=MSG_URL_CONFLICT, default=DEFAULT_TRUST_EXTERNAL,
): cv.string, ): cv.boolean,
vol.Optional( vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean,
CONF_EMBED_IFRAME, default=DEFAULT_EMBED_IFRAME }
): cv.boolean, ),
vol.Optional( url_validator,
CONF_TRUST_EXTERNAL_SCRIPT, default=DEFAULT_TRUST_EXTERNAL
): cv.boolean,
vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean,
}
) )
], ],
) )
@ -102,12 +119,14 @@ async def async_register_panel(
"""Register a new custom panel.""" """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 html_url is None and module_url is None:
raise ValueError("Either js_url, module_url or html_url is required.") raise ValueError("Either js_url, module_url or html_url is required.")
if (js_url and html_url) or (module_url and html_url): if html_url and (js_url or module_url):
raise ValueError("Pass in only one of JS url, Module url or HTML url.") raise ValueError("You cannot specify other paths with an HTML url")
if config is not None and not isinstance(config, dict): if config is not None and not isinstance(config, dict):
raise ValueError("Config needs to be a dictionary.") raise ValueError("Config needs to be a dictionary.")
if html_url:
_LOGGER.warning("HTML custom panels have been deprecated")
custom_panel_config = { custom_panel_config = {
"name": webcomponent_name, "name": webcomponent_name,
"embed_iframe": embed_iframe, "embed_iframe": embed_iframe,
@ -160,22 +179,24 @@ async def async_setup(hass, config):
"require_admin": panel[CONF_REQUIRE_ADMIN], "require_admin": panel[CONF_REQUIRE_ADMIN],
} }
panel_path = panel.get(CONF_WEBCOMPONENT_PATH)
if panel_path is None:
panel_path = hass.config.path(PANEL_DIR, f"{name}.html")
if CONF_JS_URL in panel: if CONF_JS_URL in panel:
kwargs["js_url"] = panel[CONF_JS_URL] kwargs["js_url"] = panel[CONF_JS_URL]
elif CONF_MODULE_URL in panel: if CONF_MODULE_URL in panel:
kwargs["module_url"] = panel[CONF_MODULE_URL] kwargs["module_url"] = panel[CONF_MODULE_URL]
elif not await hass.async_add_job(os.path.isfile, panel_path): if CONF_WEBCOMPONENT_PATH in panel:
_LOGGER.error("Unable to find webcomponent for %s: %s", name, panel_path) panel_path = panel.get(CONF_WEBCOMPONENT_PATH)
continue
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
else:
url = LEGACY_URL.format(name) url = LEGACY_URL.format(name)
hass.http.register_static_path(url, panel_path) hass.http.register_static_path(url, panel_path)
kwargs["html_url"] = url kwargs["html_url"] = url

View File

@ -151,16 +151,42 @@ async def test_module_webcomponent(hass):
assert panel.sidebar_title == "Sidebar Title" assert panel.sidebar_title == "Sidebar Title"
async def test_latest_and_es5_build(hass):
"""Test specifying an es5 and latest build."""
config = {
"panel_custom": {
"name": "todo-mvc",
"js_url": "/local/es5.js",
"module_url": "/local/latest.js",
"url_path": "nice_url",
}
}
assert await setup.async_setup_component(hass, "panel_custom", config)
panels = hass.data.get(frontend.DATA_PANELS, {})
assert panels
assert "nice_url" in panels
panel = panels["nice_url"]
assert panel.config == {
"_panel_custom": {
"name": "todo-mvc",
"js_url": "/local/es5.js",
"module_url": "/local/latest.js",
"embed_iframe": False,
"trust_external": False,
},
}
assert panel.frontend_url_path == "nice_url"
async def test_url_option_conflict(hass): async def test_url_option_conflict(hass):
"""Test config with multiple url options.""" """Test config with multiple url options."""
to_try = [ to_try = [
{ {"panel_custom": {"name": "todo-mvc"}},
"panel_custom": {
"name": "todo-mvc",
"module_url": "/local/bla.js",
"js_url": "/local/bla.js",
}
},
{ {
"panel_custom": { "panel_custom": {
"name": "todo-mvc", "name": "todo-mvc",