diff --git a/homeassistant/components/panel_iframe/__init__.py b/homeassistant/components/panel_iframe/__init__.py index c51768952ebe77..1b6dfebd6b05b5 100644 --- a/homeassistant/components/panel_iframe/__init__.py +++ b/homeassistant/components/panel_iframe/__init__.py @@ -2,10 +2,13 @@ import voluptuous as vol -from homeassistant.components import frontend +from homeassistant.components import lovelace +from homeassistant.components.lovelace import dashboard from homeassistant.const import CONF_ICON, CONF_URL from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue +from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType DOMAIN = "panel_iframe" @@ -37,18 +40,59 @@ extra=vol.ALLOW_EXTRA, ) +STORAGE_KEY = DOMAIN +STORAGE_VERSION_MAJOR = 1 + async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the iFrame frontend panels.""" + async_create_issue( + hass, + DOMAIN, + "deprecated_yaml", + breaks_in_ha_version="2024.10.0", + is_fixable=False, + is_persistent=False, + issue_domain=DOMAIN, + severity=IssueSeverity.WARNING, + translation_key="deprecated_yaml", + translation_placeholders={ + "domain": DOMAIN, + "integration_title": "iframe Panel", + }, + ) + + store: Store[dict[str, bool]] = Store( + hass, + STORAGE_VERSION_MAJOR, + STORAGE_KEY, + ) + data = await store.async_load() + if data: + return True + + dashboards_collection: dashboard.DashboardsCollection = hass.data[lovelace.DOMAIN][ + "dashboards_collection" + ] + for url_path, info in config[DOMAIN].items(): - frontend.async_register_built_in_panel( - hass, - "iframe", - info.get(CONF_TITLE), - info.get(CONF_ICON), - url_path, - {"url": info[CONF_URL]}, - require_admin=info[CONF_REQUIRE_ADMIN], + dashboard_create_data = { + lovelace.CONF_ALLOW_SINGLE_WORD: True, + lovelace.CONF_URL_PATH: url_path, + } + for key in (CONF_ICON, CONF_REQUIRE_ADMIN, CONF_TITLE): + if key in info: + dashboard_create_data[key] = info[key] + + await dashboards_collection.async_create_item(dashboard_create_data) + + dashboard_store: dashboard.LovelaceStorage = hass.data[lovelace.DOMAIN][ + "dashboards" + ][url_path] + await dashboard_store.async_save( + {"strategy": {"type": "iframe", "url": info[CONF_URL]}} ) + await store.async_save({"migrated": True}) + return True diff --git a/homeassistant/components/panel_iframe/manifest.json b/homeassistant/components/panel_iframe/manifest.json index 04eeb93ffa6a35..7a39e0ba17dc3e 100644 --- a/homeassistant/components/panel_iframe/manifest.json +++ b/homeassistant/components/panel_iframe/manifest.json @@ -2,7 +2,7 @@ "domain": "panel_iframe", "name": "iframe Panel", "codeowners": ["@home-assistant/frontend"], - "dependencies": ["frontend"], + "dependencies": ["frontend", "lovelace"], "documentation": "https://www.home-assistant.io/integrations/panel_iframe", "quality_scale": "internal" } diff --git a/homeassistant/components/panel_iframe/strings.json b/homeassistant/components/panel_iframe/strings.json new file mode 100644 index 00000000000000..595b1f04818c78 --- /dev/null +++ b/homeassistant/components/panel_iframe/strings.json @@ -0,0 +1,8 @@ +{ + "issues": { + "deprecated_yaml": { + "title": "The {integration_title} YAML configuration is being removed", + "description": "Configuring {integration_title} using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically as a regular dashboard.\n\nRemove the `{domain}` configuration from your configuration.yaml file and restart Home Assistant to fix this issue." + } + } +} diff --git a/tests/components/panel_iframe/test_init.py b/tests/components/panel_iframe/test_init.py index a16d87f1838953..0e898fd626602f 100644 --- a/tests/components/panel_iframe/test_init.py +++ b/tests/components/panel_iframe/test_init.py @@ -1,11 +1,37 @@ """The tests for the panel_iframe component.""" +from typing import Any + import pytest -from homeassistant.components import frontend +from homeassistant.components.panel_iframe import DOMAIN from homeassistant.core import HomeAssistant +from homeassistant.helpers import issue_registry as ir from homeassistant.setup import async_setup_component +from tests.typing import WebSocketGenerator + +TEST_CONFIG = { + "router": { + "icon": "mdi:network-wireless", + "title": "Router", + "url": "http://192.168.1.1", + "require_admin": True, + }, + "weather": { + "icon": "mdi:weather", + "title": "Weather", + "url": "https://www.wunderground.com/us/ca/san-diego", + "require_admin": True, + }, + "api": {"icon": "mdi:weather", "title": "Api", "url": "/api"}, + "ftp": { + "icon": "mdi:weather", + "title": "FTP", + "url": "ftp://some/ftp", + }, +} + @pytest.mark.parametrize( "config_to_try", @@ -21,73 +47,107 @@ async def test_wrong_config(hass: HomeAssistant, config_to_try) -> None: ) -async def test_correct_config(hass: HomeAssistant) -> None: - """Test correct config.""" +async def test_import_config( + hass: HomeAssistant, + hass_storage: dict[str, Any], + hass_ws_client: WebSocketGenerator, +) -> None: + """Test import config.""" + client = await hass_ws_client(hass) + assert await async_setup_component( hass, "panel_iframe", + {"panel_iframe": TEST_CONFIG}, + ) + + # List dashboards + await client.send_json_auto_id({"type": "lovelace/dashboards/list"}) + response = await client.receive_json() + assert response["success"] + assert response["result"] == [ { - "panel_iframe": { - "router": { - "icon": "mdi:network-wireless", - "title": "Router", - "url": "http://192.168.1.1", - "require_admin": True, - }, - "weather": { - "icon": "mdi:weather", - "title": "Weather", - "url": "https://www.wunderground.com/us/ca/san-diego", - "require_admin": True, - }, - "api": {"icon": "mdi:weather", "title": "Api", "url": "/api"}, - "ftp": { - "icon": "mdi:weather", - "title": "FTP", - "url": "ftp://some/ftp", - }, - } + "icon": "mdi:network-wireless", + "id": "router", + "mode": "storage", + "require_admin": True, + "show_in_sidebar": True, + "title": "Router", + "url_path": "router", }, - ) + { + "icon": "mdi:weather", + "id": "weather", + "mode": "storage", + "require_admin": True, + "show_in_sidebar": True, + "title": "Weather", + "url_path": "weather", + }, + { + "icon": "mdi:weather", + "id": "api", + "mode": "storage", + "require_admin": False, + "show_in_sidebar": True, + "title": "Api", + "url_path": "api", + }, + { + "icon": "mdi:weather", + "id": "ftp", + "mode": "storage", + "require_admin": False, + "show_in_sidebar": True, + "title": "FTP", + "url_path": "ftp", + }, + ] - panels = hass.data[frontend.DATA_PANELS] + for url_path in ["api", "ftp", "router", "weather"]: + await client.send_json_auto_id( + {"type": "lovelace/config", "url_path": url_path} + ) + response = await client.receive_json() + assert response["success"] + assert response["result"] == { + "strategy": {"type": "iframe", "url": TEST_CONFIG[url_path]["url"]} + } - assert panels.get("router").to_response() == { - "component_name": "iframe", - "config": {"url": "http://192.168.1.1"}, - "config_panel_domain": None, - "icon": "mdi:network-wireless", - "title": "Router", - "url_path": "router", - "require_admin": True, - } + assert hass_storage[DOMAIN]["data"] == {"migrated": True} - assert panels.get("weather").to_response() == { - "component_name": "iframe", - "config": {"url": "https://www.wunderground.com/us/ca/san-diego"}, - "config_panel_domain": None, - "icon": "mdi:weather", - "title": "Weather", - "url_path": "weather", - "require_admin": True, - } - assert panels.get("api").to_response() == { - "component_name": "iframe", - "config": {"url": "/api"}, - "config_panel_domain": None, - "icon": "mdi:weather", - "title": "Api", - "url_path": "api", - "require_admin": False, - } +async def test_import_config_once( + hass: HomeAssistant, + hass_storage: dict[str, Any], + hass_ws_client: WebSocketGenerator, +) -> None: + """Test import config only happens once.""" + client = await hass_ws_client(hass) - assert panels.get("ftp").to_response() == { - "component_name": "iframe", - "config": {"url": "ftp://some/ftp"}, - "config_panel_domain": None, - "icon": "mdi:weather", - "title": "FTP", - "url_path": "ftp", - "require_admin": False, + hass_storage[DOMAIN] = { + "version": 1, + "minor_version": 1, + "key": "map", + "data": {"migrated": True}, } + + assert await async_setup_component( + hass, + "panel_iframe", + {"panel_iframe": TEST_CONFIG}, + ) + + # List dashboards + await client.send_json_auto_id({"type": "lovelace/dashboards/list"}) + response = await client.receive_json() + assert response["success"] + assert response["result"] == [] + + +async def test_create_issue_when_manually_configured(hass: HomeAssistant) -> None: + """Test creating issue registry issues.""" + assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) + + issue_registry = ir.async_get(hass) + assert issue_registry.async_get_issue(DOMAIN, "deprecated_yaml")