Skip to content

Commit

Permalink
Add panel custom to load any webcomponent (home-assistant#2747)
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob committed Aug 9, 2016
1 parent 9a575eb commit 8081fe7
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 31 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 0 additions & 30 deletions config/custom_components/react_panel/__init__.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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>

Expand Down
64 changes: 64 additions & 0 deletions homeassistant/components/panel_custom.py
Original file line number Diff line number Diff line change
@@ -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
77 changes: 77 additions & 0 deletions tests/components/test_panel_custom.py
Original file line number Diff line number Diff line change
@@ -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'
}

0 comments on commit 8081fe7

Please sign in to comment.