diff --git a/homeassistant/components/lovelace/__init__.py b/homeassistant/components/lovelace/__init__.py index 65c3b11b369..23e8a14e511 100644 --- a/homeassistant/components/lovelace/__init__.py +++ b/homeassistant/components/lovelace/__init__.py @@ -16,10 +16,11 @@ from .const import ( CONF_MODE, CONF_REQUIRE_ADMIN, CONF_RESOURCES, - CONF_SIDEBAR, + CONF_SHOW_IN_SIDEBAR, CONF_TITLE, CONF_URL_PATH, DASHBOARD_BASE_CREATE_FIELDS, + DEFAULT_ICON, DOMAIN, MODE_STORAGE, MODE_YAML, @@ -171,6 +172,7 @@ async def async_setup(hass, config): update = False else: + hass.data[DOMAIN]["dashboards"][url_path].config = item update = True try: @@ -207,8 +209,8 @@ def _register_panel(hass, url_path, mode, config, update): "update": update, } - if CONF_SIDEBAR in config: - kwargs["sidebar_title"] = config[CONF_SIDEBAR][CONF_TITLE] - kwargs["sidebar_icon"] = config[CONF_SIDEBAR][CONF_ICON] + if config[CONF_SHOW_IN_SIDEBAR]: + kwargs["sidebar_title"] = config[CONF_TITLE] + kwargs["sidebar_icon"] = config.get(CONF_ICON, DEFAULT_ICON) frontend.async_register_built_in_panel(hass, DOMAIN, **kwargs) diff --git a/homeassistant/components/lovelace/const.py b/homeassistant/components/lovelace/const.py index de6aa99894a..7205ae21cbe 100644 --- a/homeassistant/components/lovelace/const.py +++ b/homeassistant/components/lovelace/const.py @@ -11,6 +11,8 @@ from homeassistant.util import slugify DOMAIN = "lovelace" EVENT_LOVELACE_UPDATED = "lovelace_updated" +DEFAULT_ICON = "hass:view-dashboard" + CONF_MODE = "mode" MODE_YAML = "yaml" MODE_STORAGE = "storage" @@ -39,24 +41,23 @@ RESOURCE_UPDATE_FIELDS = { vol.Optional(CONF_URL): cv.string, } -CONF_SIDEBAR = "sidebar" CONF_TITLE = "title" CONF_REQUIRE_ADMIN = "require_admin" - -SIDEBAR_FIELDS = { - vol.Required(CONF_ICON): cv.icon, - vol.Required(CONF_TITLE): cv.string, -} +CONF_SHOW_IN_SIDEBAR = "show_in_sidebar" DASHBOARD_BASE_CREATE_FIELDS = { vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean, - vol.Optional(CONF_SIDEBAR): SIDEBAR_FIELDS, + vol.Optional(CONF_ICON): cv.icon, + vol.Required(CONF_TITLE): cv.string, + vol.Optional(CONF_SHOW_IN_SIDEBAR, default=True): cv.boolean, } DASHBOARD_BASE_UPDATE_FIELDS = { vol.Optional(CONF_REQUIRE_ADMIN): cv.boolean, - vol.Optional(CONF_SIDEBAR): vol.Any(None, SIDEBAR_FIELDS), + vol.Optional(CONF_ICON): vol.Any(cv.icon, None), + vol.Optional(CONF_TITLE): cv.string, + vol.Optional(CONF_SHOW_IN_SIDEBAR): cv.boolean, } @@ -68,9 +69,7 @@ STORAGE_DASHBOARD_CREATE_FIELDS = { vol.Optional(CONF_MODE, default=MODE_STORAGE): MODE_STORAGE, } -STORAGE_DASHBOARD_UPDATE_FIELDS = { - **DASHBOARD_BASE_UPDATE_FIELDS, -} +STORAGE_DASHBOARD_UPDATE_FIELDS = DASHBOARD_BASE_UPDATE_FIELDS def url_slug(value: Any) -> str: diff --git a/homeassistant/components/lovelace/dashboard.py b/homeassistant/components/lovelace/dashboard.py index cd0d4a6fea8..514f1eb87b6 100644 --- a/homeassistant/components/lovelace/dashboard.py +++ b/homeassistant/components/lovelace/dashboard.py @@ -13,7 +13,7 @@ from homeassistant.helpers import collection, storage from homeassistant.util.yaml import load_yaml from .const import ( - CONF_SIDEBAR, + CONF_ICON, CONF_URL_PATH, DOMAIN, EVENT_LOVELACE_UPDATED, @@ -246,7 +246,7 @@ class DashboardsCollection(collection.StorageCollection): update_data = self.UPDATE_SCHEMA(update_data) updated = {**data, **update_data} - if CONF_SIDEBAR in updated and updated[CONF_SIDEBAR] is None: - updated.pop(CONF_SIDEBAR) + if CONF_ICON in updated and updated[CONF_ICON] is None: + updated.pop(CONF_ICON) return updated diff --git a/tests/components/lovelace/test_dashboard.py b/tests/components/lovelace/test_dashboard.py index 0b6d6806cb0..21a44bc771d 100644 --- a/tests/components/lovelace/test_dashboard.py +++ b/tests/components/lovelace/test_dashboard.py @@ -209,10 +209,16 @@ async def test_dashboard_from_yaml(hass, hass_ws_client, url_path): "test-panel": { "mode": "yaml", "filename": "bla.yaml", - "sidebar": {"title": "Test Panel", "icon": "mdi:test-icon"}, + "title": "Test Panel", + "icon": "mdi:test-icon", + "show_in_sidebar": False, "require_admin": True, }, - "test-panel-no-sidebar": {"mode": "yaml", "filename": "bla2.yaml"}, + "test-panel-no-sidebar": { + "title": "Title No Sidebar", + "mode": "yaml", + "filename": "bla2.yaml", + }, } } }, @@ -233,13 +239,15 @@ async def test_dashboard_from_yaml(hass, hass_ws_client, url_path): assert with_sb["mode"] == "yaml" assert with_sb["filename"] == "bla.yaml" - assert with_sb["sidebar"] == {"title": "Test Panel", "icon": "mdi:test-icon"} + assert with_sb["title"] == "Test Panel" + assert with_sb["icon"] == "mdi:test-icon" + assert with_sb["show_in_sidebar"] is False assert with_sb["require_admin"] is True assert with_sb["url_path"] == "test-panel" assert without_sb["mode"] == "yaml" assert without_sb["filename"] == "bla2.yaml" - assert "sidebar" not in without_sb + assert without_sb["show_in_sidebar"] is True assert without_sb["require_admin"] is False assert without_sb["url_path"] == "test-panel-no-sidebar" @@ -315,16 +323,15 @@ async def test_storage_dashboards(hass, hass_ws_client, hass_storage): "type": "lovelace/dashboards/create", "url_path": "created_url_path", "require_admin": True, - "sidebar": {"title": "Updated Title", "icon": "mdi:map"}, + "title": "New Title", + "icon": "mdi:map", } ) response = await client.receive_json() assert response["success"] assert response["result"]["require_admin"] is True - assert response["result"]["sidebar"] == { - "title": "Updated Title", - "icon": "mdi:map", - } + assert response["result"]["title"] == "New Title" + assert response["result"]["icon"] == "mdi:map" dashboard_id = response["result"]["id"] @@ -335,10 +342,9 @@ async def test_storage_dashboards(hass, hass_ws_client, hass_storage): assert response["success"] assert len(response["result"]) == 1 assert response["result"][0]["mode"] == "storage" - assert response["result"][0]["sidebar"] == { - "title": "Updated Title", - "icon": "mdi:map", - } + assert response["result"][0]["title"] == "New Title" + assert response["result"][0]["icon"] == "mdi:map" + assert response["result"][0]["show_in_sidebar"] is True assert response["result"][0]["require_admin"] is True # Fetch config @@ -382,24 +388,42 @@ async def test_storage_dashboards(hass, hass_ws_client, hass_storage): "type": "lovelace/dashboards/update", "dashboard_id": dashboard_id, "require_admin": False, - "sidebar": None, + "icon": "mdi:updated", + "show_in_sidebar": False, + "title": "Updated Title", } ) response = await client.receive_json() assert response["success"] + assert response["result"]["mode"] == "storage" + assert response["result"]["url_path"] == "created_url_path" + assert response["result"]["title"] == "Updated Title" + assert response["result"]["icon"] == "mdi:updated" + assert response["result"]["show_in_sidebar"] is False assert response["result"]["require_admin"] is False - assert "sidebar" not in response["result"] + + # List dashboards again and make sure we see latest config + await client.send_json({"id": 12, "type": "lovelace/dashboards/list"}) + response = await client.receive_json() + assert response["success"] + assert len(response["result"]) == 1 + assert response["result"][0]["mode"] == "storage" + assert response["result"][0]["url_path"] == "created_url_path" + assert response["result"][0]["title"] == "Updated Title" + assert response["result"][0]["icon"] == "mdi:updated" + assert response["result"][0]["show_in_sidebar"] is False + assert response["result"][0]["require_admin"] is False # Add dashboard with existing url path await client.send_json( - {"id": 12, "type": "lovelace/dashboards/create", "url_path": "created_url_path"} + {"id": 13, "type": "lovelace/dashboards/create", "url_path": "created_url_path"} ) response = await client.receive_json() assert not response["success"] # Delete dashboards await client.send_json( - {"id": 13, "type": "lovelace/dashboards/delete", "dashboard_id": dashboard_id} + {"id": 14, "type": "lovelace/dashboards/delete", "dashboard_id": dashboard_id} ) response = await client.receive_json() assert response["success"] @@ -416,7 +440,11 @@ async def test_websocket_list_dashboards(hass, hass_ws_client): { "lovelace": { "dashboards": { - "test-panel-no-sidebar": {"mode": "yaml", "filename": "bla.yaml"}, + "test-panel-no-sidebar": { + "title": "Test YAML", + "mode": "yaml", + "filename": "bla.yaml", + }, } } }, @@ -426,7 +454,12 @@ async def test_websocket_list_dashboards(hass, hass_ws_client): # Create a storage dashboard await client.send_json( - {"id": 6, "type": "lovelace/dashboards/create", "url_path": "created_url_path"} + { + "id": 6, + "type": "lovelace/dashboards/create", + "url_path": "created_url_path", + "title": "Test Storage", + } ) response = await client.receive_json() assert response["success"] @@ -439,8 +472,10 @@ async def test_websocket_list_dashboards(hass, hass_ws_client): with_sb, without_sb = response["result"] assert with_sb["mode"] == "yaml" + assert with_sb["title"] == "Test YAML" assert with_sb["filename"] == "bla.yaml" assert with_sb["url_path"] == "test-panel-no-sidebar" assert without_sb["mode"] == "storage" + assert without_sb["title"] == "Test Storage" assert without_sb["url_path"] == "created_url_path"