Add panel custom to load any webcomponent (#2747)
parent
9a575eb6d6
commit
8081fe794e
|
@ -7,7 +7,9 @@ config/custom_components/*
|
|||
!config/custom_components/example.py
|
||||
!config/custom_components/hello_world.py
|
||||
!config/custom_components/mqtt_example.py
|
||||
!config/custom_components/react_panel
|
||||
!config/panels
|
||||
config/panels/*
|
||||
!config/panels/react.html
|
||||
|
||||
tests/testing_config/deps
|
||||
tests/testing_config/home-assistant.log
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
"""
|
||||
Custom panel example showing TodoMVC using React.
|
||||
|
||||
Will add a panel to control lights and switches using React. Allows configuring
|
||||
the title via configuration.yaml:
|
||||
|
||||
react_panel:
|
||||
title: 'home'
|
||||
|
||||
"""
|
||||
import os
|
||||
|
||||
from homeassistant.components.frontend import register_panel
|
||||
|
||||
DOMAIN = 'react_panel'
|
||||
DEPENDENCIES = ['frontend']
|
||||
|
||||
PANEL_PATH = os.path.join(os.path.dirname(__file__), 'panel.html')
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Initialize custom panel."""
|
||||
title = config.get(DOMAIN, {}).get('title')
|
||||
|
||||
config = None if title is None else {'title': title}
|
||||
|
||||
register_panel(hass, 'react', PANEL_PATH,
|
||||
title='TodoMVC', icon='mdi:checkbox-marked-outline',
|
||||
config=config)
|
||||
return True
|
|
@ -1,3 +1,20 @@
|
|||
<!--
|
||||
Custom Home Assistant panel example.
|
||||
|
||||
Currently only works in Firefox and Chrome because it uses ES6.
|
||||
|
||||
Make sure this file is in <config>/panels/react.html
|
||||
|
||||
Add to your configuration.yaml:
|
||||
|
||||
panel_custom:
|
||||
- name: react
|
||||
sidebar_title: TodoMVC
|
||||
sidebar_icon: mdi:checkbox-marked-outline
|
||||
config:
|
||||
title: Wow hello!
|
||||
-->
|
||||
|
||||
<script src="https://fb.me/react-15.2.1.min.js"></script>
|
||||
<script src="https://fb.me/react-dom-15.2.1.min.js"></script>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
"""Register a custom front end panel."""
|
||||
import logging
|
||||
import os
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.components.frontend import register_panel
|
||||
|
||||
DOMAIN = 'panel_custom'
|
||||
DEPENDENCIES = ['frontend']
|
||||
|
||||
CONF_COMPONENT_NAME = 'name'
|
||||
CONF_SIDEBAR_TITLE = 'sidebar_title'
|
||||
CONF_SIDEBAR_ICON = 'sidebar_icon'
|
||||
CONF_URL_PATH = 'url_path'
|
||||
CONF_CONFIG = 'config'
|
||||
CONF_WEBCOMPONENT_PATH = 'webcomponent_path'
|
||||
|
||||
DEFAULT_ICON = 'mdi:bookmark'
|
||||
|
||||
PANEL_DIR = 'panels'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.All(cv.ensure_list, [{
|
||||
vol.Required(CONF_COMPONENT_NAME): cv.slug,
|
||||
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): cv.match_all,
|
||||
vol.Optional(CONF_WEBCOMPONENT_PATH): cv.isfile,
|
||||
}])
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Initialize custom panel."""
|
||||
success = False
|
||||
|
||||
for panel in config.get(DOMAIN):
|
||||
name = panel.get(CONF_COMPONENT_NAME)
|
||||
panel_path = panel.get(CONF_WEBCOMPONENT_PATH)
|
||||
|
||||
if panel_path is None:
|
||||
panel_path = hass.config.path(PANEL_DIR, '{}.html'.format(name))
|
||||
|
||||
if not os.path.isfile(panel_path):
|
||||
_LOGGER.error('Unable to find webcomponent for %s: %s',
|
||||
name, panel_path)
|
||||
continue
|
||||
|
||||
register_panel(
|
||||
hass, name, panel_path,
|
||||
sidebar_title=panel.get(CONF_SIDEBAR_TITLE),
|
||||
sidebar_icon=panel.get(CONF_SIDEBAR_ICON),
|
||||
url_path=panel.get(CONF_URL_PATH),
|
||||
config=panel.get(CONF_CONFIG),
|
||||
)
|
||||
|
||||
success = True
|
||||
|
||||
return success
|
|
@ -0,0 +1,77 @@
|
|||
"""The tests for the panel_custom component."""
|
||||
import os
|
||||
import shutil
|
||||
from tempfile import NamedTemporaryFile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import bootstrap
|
||||
from homeassistant.components import panel_custom
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
@patch('homeassistant.components.frontend.setup', return_value=True)
|
||||
class TestPanelCustom(unittest.TestCase):
|
||||
"""Test the panel_custom component."""
|
||||
|
||||
def setup_method(self, method):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def teardown_method(self, method):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
shutil.rmtree(self.hass.config.path(panel_custom.PANEL_DIR),
|
||||
ignore_errors=True)
|
||||
|
||||
@patch('homeassistant.components.panel_custom.register_panel')
|
||||
def test_webcomponent_in_panels_dir(self, mock_register, _mock_setup):
|
||||
"""Test if a web component is found in config panels dir."""
|
||||
config = {
|
||||
'panel_custom': {
|
||||
'name': 'todomvc',
|
||||
}
|
||||
}
|
||||
|
||||
assert not bootstrap.setup_component(self.hass, 'panel_custom', config)
|
||||
assert not mock_register.called
|
||||
|
||||
path = self.hass.config.path(panel_custom.PANEL_DIR)
|
||||
os.mkdir(path)
|
||||
|
||||
with open(os.path.join(path, 'todomvc.html'), 'a'):
|
||||
assert bootstrap.setup_component(self.hass, 'panel_custom', config)
|
||||
assert mock_register.called
|
||||
|
||||
@patch('homeassistant.components.panel_custom.register_panel')
|
||||
def test_webcomponent_custom_path(self, mock_register, _mock_setup):
|
||||
"""Test if a web component is found in config panels dir."""
|
||||
with NamedTemporaryFile() as fp:
|
||||
config = {
|
||||
'panel_custom': {
|
||||
'name': 'todomvc',
|
||||
'webcomponent_path': fp.name,
|
||||
'sidebar_title': 'Sidebar Title',
|
||||
'sidebar_icon': 'mdi:iconicon',
|
||||
'url_path': 'nice_url',
|
||||
'config': 5,
|
||||
}
|
||||
}
|
||||
|
||||
with patch('os.path.isfile', return_value=False):
|
||||
assert not bootstrap.setup_component(self.hass, 'panel_custom',
|
||||
config)
|
||||
assert not mock_register.called
|
||||
|
||||
assert bootstrap.setup_component(self.hass, 'panel_custom', config)
|
||||
assert mock_register.called
|
||||
args = mock_register.mock_calls[0][1]
|
||||
kwargs = mock_register.mock_calls[0][2]
|
||||
assert args == (self.hass, 'todomvc', fp.name)
|
||||
assert kwargs == {
|
||||
'config': 5,
|
||||
'url_path': 'nice_url',
|
||||
'sidebar_icon': 'mdi:iconicon',
|
||||
'sidebar_title': 'Sidebar Title'
|
||||
}
|
Loading…
Reference in New Issue