diff --git a/.gitignore b/.gitignore index 26ad120ea..41395a7ea 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,6 @@ ENV/ # pylint .pylint.d/ + +# VS Code +.vscode/ diff --git a/API.md b/API.md index 4a9955a03..b8d719a39 100644 --- a/API.md +++ b/API.md @@ -428,11 +428,11 @@ Get all available addons. "name": "xy bla", "slug": "xy", "description": "description", - "arch": ["armhf", "aarch64", "i386", "amd64"], "repository": "core|local|REP_ID", "version": "LAST_VERSION", "installed": "none|INSTALL_VERSION", "detached": "bool", + "available": "bool", "build": "bool", "url": "null|url", "icon": "bool", @@ -463,6 +463,9 @@ Get all available addons. "auto_update": "bool", "url": "null|url of addon", "detached": "bool", + "available": "bool", + "arch": ["armhf", "aarch64", "i386", "amd64"], + "machine": "[raspberrypi2, tinker]", "repository": "12345678|null", "version": "null|VERSION_INSTALLED", "last_version": "LAST_VERSION", @@ -496,8 +499,8 @@ Get all available addons. "audio": "bool", "audio_input": "null|0,0", "audio_output": "null|0,0", - "services": "null|['mqtt']", - "discovery": "null|['component/platform']" + "services_role": "['service:access']", + "discovery": "['service']" } ``` @@ -573,12 +576,13 @@ Write data to add-on stdin ### Service discovery -- GET `/services/discovery` +- GET `/discovery` ```json { "discovery": [ { - "provider": "name", + "addon": "slug", + "service": "name", "uuid": "uuid", "component": "component", "platform": "null|platform", @@ -588,10 +592,11 @@ Write data to add-on stdin } ``` -- GET `/services/discovery/{UUID}` +- GET `/discovery/{UUID}` ```json { - "provider": "name", + "addon": "slug", + "service": "name", "uuid": "uuid", "component": "component", "platform": "null|platform", @@ -599,9 +604,10 @@ Write data to add-on stdin } ``` -- POST `/services/discovery` +- POST `/discovery` ```json { + "service": "name", "component": "component", "platform": "null|platform", "config": {} @@ -615,7 +621,7 @@ return: } ``` -- DEL `/services/discovery/{UUID}` +- DEL `/discovery/{UUID}` - GET `/services` ```json @@ -624,7 +630,7 @@ return: { "slug": "name", "available": "bool", - "provider": "null|name|list" + "providers": "list" } ] } @@ -632,12 +638,10 @@ return: #### MQTT -This service performs an auto discovery to Home-Assistant. - - GET `/services/mqtt` ```json { - "provider": "name", + "addon": "name", "host": "xy", "port": "8883", "ssl": "bool", @@ -660,3 +664,17 @@ This service performs an auto discovery to Home-Assistant. ``` - DEL `/services/mqtt` + +### Misc + +- GET `/version` +```json +{ + "supervisor": "version", + "homeassistant": "version", + "hassos": "null|version", + "machine": "type", + "arch": "arch", + "channel": "stable|beta|dev" +} +``` diff --git a/hassio/addons/__init__.py b/hassio/addons/__init__.py index d22884a2a..4fb01969b 100644 --- a/hassio/addons/__init__.py +++ b/hassio/addons/__init__.py @@ -1,4 +1,4 @@ -"""Init file for HassIO addons.""" +"""Init file for Hass.io add-ons.""" import asyncio import logging @@ -14,10 +14,10 @@ BUILTIN_REPOSITORIES = set((REPOSITORY_CORE, REPOSITORY_LOCAL)) class AddonManager(CoreSysAttributes): - """Manage addons inside HassIO.""" + """Manage add-ons inside Hass.io.""" def __init__(self, coresys): - """Initialize docker base wrapper.""" + """Initialize Docker base wrapper.""" self.coresys = coresys self.data = AddonsData(coresys) self.addons_obj = {} @@ -25,51 +25,44 @@ class AddonManager(CoreSysAttributes): @property def list_addons(self): - """Return a list of all addons.""" + """Return a list of all add-ons.""" return list(self.addons_obj.values()) @property def list_installed(self): - """Return a list of installed addons.""" + """Return a list of installed add-ons.""" return [addon for addon in self.addons_obj.values() if addon.is_installed] @property def list_repositories(self): - """Return list of addon repositories.""" + """Return list of add-on repositories.""" return list(self.repositories_obj.values()) def get(self, addon_slug): """Return an add-on from slug.""" return self.addons_obj.get(addon_slug) - def from_uuid(self, uuid): - """Return an add-on from uuid.""" - for addon in self.list_addons: - if addon.is_installed and uuid == addon.uuid: - return addon - return None - def from_token(self, token): - """Return an add-on from hassio token.""" + """Return an add-on from Hass.io token.""" for addon in self.list_addons: if addon.is_installed and token == addon.hassio_token: return addon return None async def load(self): - """Startup addon management.""" + """Start up add-on management.""" self.data.reload() - # init hassio built-in repositories + # Init Hass.io built-in repositories repositories = \ set(self.sys_config.addons_repositories) | BUILTIN_REPOSITORIES - # init custom repositories & load addons + # Init custom repositories and load add-ons await self.load_repositories(repositories) async def reload(self): - """Update addons from repo and reload list.""" + """Update add-ons from repository and reload list.""" tasks = [repository.update() for repository in self.repositories_obj.values()] if tasks: @@ -113,14 +106,14 @@ class AddonManager(CoreSysAttributes): await self.load_addons() async def load_addons(self): - """Update/add internal addon store.""" + """Update/add internal add-on store.""" all_addons = set(self.data.system) | set(self.data.cache) # calc diff add_addons = all_addons - set(self.addons_obj) del_addons = set(self.addons_obj) - all_addons - _LOGGER.info("Load addons: %d all - %d new - %d remove", + _LOGGER.info("Load add-ons: %d all - %d new - %d remove", len(all_addons), len(add_addons), len(del_addons)) # new addons @@ -139,14 +132,14 @@ class AddonManager(CoreSysAttributes): self.addons_obj.pop(addon_slug) async def boot(self, stage): - """Boot addons with mode auto.""" + """Boot add-ons with mode auto.""" tasks = [] for addon in self.addons_obj.values(): if addon.is_installed and addon.boot == BOOT_AUTO and \ addon.startup == stage: tasks.append(addon.start()) - _LOGGER.info("Startup %s run %d addons", stage, len(tasks)) + _LOGGER.info("Startup %s run %d add-ons", stage, len(tasks)) if tasks: await asyncio.wait(tasks) await asyncio.sleep(self.sys_config.wait_boot) @@ -160,6 +153,6 @@ class AddonManager(CoreSysAttributes): addon.startup == stage: tasks.append(addon.stop()) - _LOGGER.info("Shutdown %s stop %d addons", stage, len(tasks)) + _LOGGER.info("Shutdown %s stop %d add-ons", stage, len(tasks)) if tasks: await asyncio.wait(tasks) diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index b58ea9404..c9f81d547 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -1,4 +1,4 @@ -"""Init file for HassIO addons.""" +"""Init file for Hass.io add-ons.""" from contextlib import suppress from copy import deepcopy import logging @@ -13,7 +13,8 @@ import voluptuous as vol from voluptuous.humanize import humanize_error from .validate import ( - validate_options, SCHEMA_ADDON_SNAPSHOT, RE_VOLUME, RE_SERVICE) + validate_options, SCHEMA_ADDON_SNAPSHOT, RE_VOLUME, RE_SERVICE, + MACHINE_ALL) from .utils import check_installed, remove_data from ..const import ( ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON, ATTR_BOOT, ATTR_MAP, @@ -27,6 +28,7 @@ from ..const import ( ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, ATTR_FULL_ACCESS, ATTR_PROTECTED, ATTR_ACCESS_TOKEN, ATTR_HOST_PID, ATTR_HASSIO_ROLE, + ATTR_MACHINE, SECURITY_PROFILE, SECURITY_DISABLE, SECURITY_DEFAULT) from ..coresys import CoreSysAttributes from ..docker.addon import DockerAddon @@ -43,7 +45,7 @@ RE_WEBUI = re.compile( class Addon(CoreSysAttributes): - """Hold data for addon inside HassIO.""" + """Hold data for add-on inside Hass.io.""" def __init__(self, coresys, slug): """Initialize data holder.""" @@ -59,29 +61,38 @@ class Addon(CoreSysAttributes): @property def slug(self): - """Return slug/id of addon.""" + """Return slug/id of add-on.""" return self._id @property def _mesh(self): - """Return addon data from system or cache.""" + """Return add-on data from system or cache.""" return self._data.system.get(self._id, self._data.cache.get(self._id)) @property def _data(self): - """Return addons data storage.""" + """Return add-ons data storage.""" return self.sys_addons.data @property def is_installed(self): - """Return True if an addon is installed.""" + """Return True if an add-on is installed.""" return self._id in self._data.system @property def is_detached(self): - """Return True if addon is detached.""" + """Return True if add-on is detached.""" return self._id not in self._data.cache + @property + def available(self): + """Return True if this add-on is available on this platform.""" + if self.sys_arch not in self.supported_arch: + return False + if self.sys_machine not in self.supported_machine: + return False + return True + @property def version_installed(self): """Return installed version.""" @@ -97,19 +108,19 @@ class Addon(CoreSysAttributes): self._data.save_data() def _set_uninstall(self): - """Set addon as uninstalled.""" + """Set add-on as uninstalled.""" self._data.system.pop(self._id, None) self._data.user.pop(self._id, None) self._data.save_data() def _set_update(self, version): - """Update version of addon.""" + """Update version of add-on.""" self._data.system[self._id] = deepcopy(self._data.cache[self._id]) self._data.user[self._id][ATTR_VERSION] = version self._data.save_data() def _restore_data(self, user, system): - """Restore data to addon.""" + """Restore data to add-on.""" self._data.user[self._id] = deepcopy(user) self._data.system[self._id] = deepcopy(system) self._data.save_data() @@ -126,7 +137,7 @@ class Addon(CoreSysAttributes): @options.setter def options(self, value): - """Store user addon options.""" + """Store user add-on options.""" if value is None: self._data.user[self._id][ATTR_OPTIONS] = {} else: @@ -158,7 +169,7 @@ class Addon(CoreSysAttributes): @property def name(self): - """Return name of addon.""" + """Return name of add-on.""" return self._mesh[ATTR_NAME] @property @@ -175,14 +186,14 @@ class Addon(CoreSysAttributes): @property def hassio_token(self): - """Return access token for hass.io API.""" + """Return access token for Hass.io API.""" if self.is_installed: return self._data.user[self._id].get(ATTR_ACCESS_TOKEN) return None @property def description(self): - """Return description of addon.""" + """Return description of add-on.""" return self._mesh[ATTR_DESCRIPTON] @property @@ -200,56 +211,55 @@ class Addon(CoreSysAttributes): @property def repository(self): - """Return repository of addon.""" + """Return repository of add-on.""" return self._mesh[ATTR_REPOSITORY] @property def last_version(self): - """Return version of addon.""" + """Return version of add-on.""" if self._id in self._data.cache: return self._data.cache[self._id][ATTR_VERSION] return self.version_installed @property def protected(self): - """Return if addon is in protected mode.""" + """Return if add-on is in protected mode.""" if self.is_installed: return self._data.user[self._id][ATTR_PROTECTED] return True @protected.setter def protected(self, value): - """Set addon in protected mode.""" + """Set add-on in protected mode.""" self._data.user[self._id][ATTR_PROTECTED] = value @property def startup(self): - """Return startup type of addon.""" + """Return startup type of add-on.""" return self._mesh.get(ATTR_STARTUP) @property - def services(self): + def services_role(self): """Return dict of services with rights.""" raw_services = self._mesh.get(ATTR_SERVICES) if not raw_services: - return None + return {} - formated_services = {} + services = {} for data in raw_services: service = RE_SERVICE.match(data) - formated_services[service.group('service')] = \ - service.group('rights') or 'ro' + services[service.group('service')] = service.group('rights') - return formated_services + return services @property def discovery(self): """Return list of discoverable components/platforms.""" - return self._mesh.get(ATTR_DISCOVERY) + return self._mesh.get(ATTR_DISCOVERY, []) @property def ports(self): - """Return ports of addon.""" + """Return ports of add-on.""" if self.host_network or ATTR_PORTS not in self._mesh: return None @@ -260,7 +270,7 @@ class Addon(CoreSysAttributes): @ports.setter def ports(self, value): - """Set custom ports of addon.""" + """Set custom ports of add-on.""" if value is None: self._data.user[self._id].pop(ATTR_NETWORK, None) else: @@ -304,42 +314,42 @@ class Addon(CoreSysAttributes): @property def host_network(self): - """Return True if addon run on host network.""" + """Return True if add-on run on host network.""" return self._mesh[ATTR_HOST_NETWORK] @property def host_pid(self): - """Return True if addon run on host PID namespace.""" + """Return True if add-on run on host PID namespace.""" return self._mesh[ATTR_HOST_PID] @property def host_ipc(self): - """Return True if addon run on host IPC namespace.""" + """Return True if add-on run on host IPC namespace.""" return self._mesh[ATTR_HOST_IPC] @property def host_dbus(self): - """Return True if addon run on host DBUS.""" + """Return True if add-on run on host D-BUS.""" return self._mesh[ATTR_HOST_DBUS] @property def devices(self): - """Return devices of addon.""" + """Return devices of add-on.""" return self._mesh.get(ATTR_DEVICES) @property def auto_uart(self): - """Return True if we should map all uart device.""" + """Return True if we should map all UART device.""" return self._mesh.get(ATTR_AUTO_UART) @property def tmpfs(self): - """Return tmpfs of addon.""" + """Return tmpfs of add-on.""" return self._mesh.get(ATTR_TMPFS) @property def environment(self): - """Return environment of addon.""" + """Return environment of add-on.""" return self._mesh.get(ATTR_ENVIRONMENT) @property @@ -349,7 +359,7 @@ class Addon(CoreSysAttributes): @property def apparmor(self): - """Return True if apparmor is enabled.""" + """Return True if AppArmor is enabled.""" if not self._mesh.get(ATTR_APPARMOR): return SECURITY_DISABLE elif self.sys_host.apparmor.exists(self.slug): @@ -358,22 +368,22 @@ class Addon(CoreSysAttributes): @property def legacy(self): - """Return if the add-on don't support hass labels.""" + """Return if the add-on don't support Home Assistant labels.""" return self._mesh.get(ATTR_LEGACY) @property def access_docker_api(self): - """Return if the add-on need read-only docker API access.""" + """Return if the add-on need read-only Docker API access.""" return self._mesh.get(ATTR_DOCKER_API) @property def access_hassio_api(self): - """Return True if the add-on access to hassio api.""" + """Return True if the add-on access to Hass.io REASTful API.""" return self._mesh[ATTR_HASSIO_API] @property def access_homeassistant_api(self): - """Return True if the add-on access to Home-Assistant api proxy.""" + """Return True if the add-on access to Home Assistant API proxy.""" return self._mesh[ATTR_HOMEASSISTANT_API] @property @@ -388,7 +398,7 @@ class Addon(CoreSysAttributes): @property def with_gpio(self): - """Return True if the add-on access to gpio interface.""" + """Return True if the add-on access to GPIO interface.""" return self._mesh[ATTR_GPIO] @property @@ -445,7 +455,7 @@ class Addon(CoreSysAttributes): @property def url(self): - """Return url of addon.""" + """Return URL of add-on.""" return self._mesh.get(ATTR_URL) @property @@ -468,12 +478,17 @@ class Addon(CoreSysAttributes): """Return list of supported arch.""" return self._mesh[ATTR_ARCH] + @property + def supported_machine(self): + """Return list of supported machine.""" + return self._mesh.get(ATTR_MACHINE) or MACHINE_ALL + @property def image(self): - """Return image name of addon.""" + """Return image name of add-on.""" addon_data = self._mesh - # Repository with dockerhub images + # Repository with Dockerhub images if ATTR_IMAGE in addon_data: return addon_data[ATTR_IMAGE].format(arch=self.sys_arch) @@ -484,12 +499,12 @@ class Addon(CoreSysAttributes): @property def need_build(self): - """Return True if this addon need a local build.""" + """Return True if this add-on need a local build.""" return ATTR_IMAGE not in self._mesh @property def map_volumes(self): - """Return a dict of {volume: policy} from addon.""" + """Return a dict of {volume: policy} from add-on.""" volumes = {} for volume in self._mesh[ATTR_MAP]: result = RE_VOLUME.match(volume) @@ -499,37 +514,37 @@ class Addon(CoreSysAttributes): @property def path_data(self): - """Return addon data path inside supervisor.""" + """Return add-on data path inside Supervisor.""" return Path(self.sys_config.path_addons_data, self._id) @property def path_extern_data(self): - """Return addon data path external for docker.""" + """Return add-on data path external for Docker.""" return PurePath(self.sys_config.path_extern_addons_data, self._id) @property def path_options(self): - """Return path to addons options.""" + """Return path to add-on options.""" return Path(self.path_data, "options.json") @property def path_location(self): - """Return path to this addon.""" + """Return path to this add-on.""" return Path(self._mesh[ATTR_LOCATON]) @property def path_icon(self): - """Return path to addon icon.""" + """Return path to add-on icon.""" return Path(self.path_location, 'icon.png') @property def path_logo(self): - """Return path to addon logo.""" + """Return path to add-on logo.""" return Path(self.path_location, 'logo.png') @property def path_changelog(self): - """Return path to addon changelog.""" + """Return path to add-on changelog.""" return Path(self.path_location, 'CHANGELOG.md') @property @@ -544,15 +559,15 @@ class Addon(CoreSysAttributes): @property def path_extern_asound(self): - """Return path to asound config for docker.""" + """Return path to asound config for Docker.""" return Path(self.sys_config.path_extern_tmp, f"{self.slug}_asound") def save_data(self): - """Save data of addon.""" + """Save data of add-on.""" self.sys_addons.data.save_data() def write_options(self): - """Return True if addon options is written to data.""" + """Return True if add-on options is written to data.""" schema = self.schema options = self.options @@ -560,15 +575,22 @@ class Addon(CoreSysAttributes): schema(options) write_json_file(self.path_options, options) except vol.Invalid as ex: - _LOGGER.error("Addon %s have wrong options: %s", self._id, + _LOGGER.error("Add-on %s have wrong options: %s", self._id, humanize_error(options, ex)) except (OSError, json.JSONDecodeError) as err: - _LOGGER.error("Addon %s can't write options: %s", self._id, err) + _LOGGER.error("Add-on %s can't write options: %s", self._id, err) else: return True return False + def remove_discovery(self): + """Remove all discovery message from add-on.""" + for message in self.sys_discovery.list_messages: + if message.addon != self.slug: + continue + self.sys_discovery.remove(message) + def write_asound(self): """Write asound config to file and return True on success.""" asound_config = self.sys_host.alsa.asound( @@ -578,7 +600,7 @@ class Addon(CoreSysAttributes): with self.path_asound.open('w') as config_file: config_file.write(asound_config) except OSError as err: - _LOGGER.error("Addon %s can't write asound: %s", self._id, err) + _LOGGER.error("Add-on %s can't write asound: %s", self._id, err) return False return True @@ -606,7 +628,7 @@ class Addon(CoreSysAttributes): @property def schema(self): - """Create a schema for addon options.""" + """Create a schema for add-on options.""" raw_schema = self._mesh[ATTR_SCHEMA] if isinstance(raw_schema, bool): @@ -614,7 +636,7 @@ class Addon(CoreSysAttributes): return vol.Schema(vol.All(dict, validate_options(raw_schema))) def test_update_schema(self): - """Check if the exists config valid after update.""" + """Check if the existing configuration is valid after update.""" if not self.is_installed or self.is_detached: return True @@ -644,19 +666,19 @@ class Addon(CoreSysAttributes): return True async def install(self): - """Install an addon.""" - if self.sys_arch not in self.supported_arch: + """Install an add-on.""" + if not self.available: _LOGGER.error( - "Addon %s not supported on %s", self._id, self.sys_arch) + "Add-on %s not supported on %s", self._id, self.sys_arch) return False if self.is_installed: - _LOGGER.error("Addon %s is already installed", self._id) + _LOGGER.error("Add-on %s is already installed", self._id) return False if not self.path_data.is_dir(): _LOGGER.info( - "Create Home-Assistant addon data folder %s", self.path_data) + "Create Home Assistant add-on data folder %s", self.path_data) self.path_data.mkdir() # Setup/Fix AppArmor profile @@ -670,13 +692,13 @@ class Addon(CoreSysAttributes): @check_installed async def uninstall(self): - """Remove an addon.""" + """Remove an add-on.""" if not await self.instance.remove(): return False if self.path_data.is_dir(): _LOGGER.info( - "Remove Home-Assistant addon data folder %s", self.path_data) + "Remove Home Assistant add-on data folder %s", self.path_data) await remove_data(self.path_data) # Cleanup audio settings @@ -684,16 +706,19 @@ class Addon(CoreSysAttributes): with suppress(OSError): self.path_asound.unlink() - # Cleanup apparmor profile + # Cleanup AppArmor profile if self.sys_host.apparmor.exists(self.slug): with suppress(HostAppArmorError): await self.sys_host.apparmor.remove_profile(self.slug) + # Remove discovery messages + self.remove_discovery() + self._set_uninstall() return True async def state(self): - """Return running state of addon.""" + """Return running state of add-on.""" if not self.is_installed: return STATE_NONE @@ -703,9 +728,9 @@ class Addon(CoreSysAttributes): @check_installed async def start(self): - """Set options and start addon.""" + """Set options and start add-on.""" if await self.instance.is_running(): - _LOGGER.warning("%s allready running!", self.slug) + _LOGGER.warning("%s already running!", self.slug) return # Access Token @@ -724,7 +749,7 @@ class Addon(CoreSysAttributes): @check_installed def stop(self): - """Stop addon. + """Stop add-on. Return a coroutine. """ @@ -732,11 +757,11 @@ class Addon(CoreSysAttributes): @check_installed async def update(self): - """Update addon.""" + """Update add-on.""" last_state = await self.state() if self.last_version == self.version_installed: - _LOGGER.warning("No update available for Addon %s", self._id) + _LOGGER.warning("No update available for add-on %s", self._id) return False if not await self.instance.update(self.last_version): @@ -753,13 +778,13 @@ class Addon(CoreSysAttributes): @check_installed async def restart(self): - """Restart addon.""" + """Restart add-on.""" await self.stop() return await self.start() @check_installed def logs(self): - """Return addons log output. + """Return add-ons log output. Return a coroutine. """ @@ -775,11 +800,11 @@ class Addon(CoreSysAttributes): @check_installed async def rebuild(self): - """Performe a rebuild of local build addon.""" + """Perform a rebuild of local build add-on.""" last_state = await self.state() if not self.need_build: - _LOGGER.error("Can't rebuild a none local build addon!") + _LOGGER.error("Can't rebuild a none local build add-on!") return False # remove docker container but not addon config @@ -808,7 +833,7 @@ class Addon(CoreSysAttributes): @check_installed async def snapshot(self, tar_file): - """Snapshot state of an addon.""" + """Snapshot state of an add-on.""" with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp: # store local image if self.need_build and not await \ @@ -822,7 +847,7 @@ class Addon(CoreSysAttributes): ATTR_STATE: await self.state(), } - # store local configs/state + # Store local configs/state try: write_json_file(Path(temp, 'addon.json'), data) except (OSError, json.JSONDecodeError) as err: @@ -846,7 +871,7 @@ class Addon(CoreSysAttributes): snapshot.add(self.path_data, arcname="data") try: - _LOGGER.info("Build snapshot for addon %s", self._id) + _LOGGER.info("Build snapshot for add-on %s", self._id) await self.sys_run_in_executor(_write_tarfile) except (tarfile.TarError, OSError) as err: _LOGGER.error("Can't write tarfile %s: %s", tar_file, err) @@ -856,7 +881,7 @@ class Addon(CoreSysAttributes): return True async def restore(self, tar_file): - """Restore state of an addon.""" + """Restore state of an add-on.""" with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp: # extract snapshot def _extract_tarfile(): @@ -870,13 +895,13 @@ class Addon(CoreSysAttributes): _LOGGER.error("Can't read tarfile %s: %s", tar_file, err) return False - # read snapshot data + # Read snapshot data try: data = read_json_file(Path(temp, 'addon.json')) except (OSError, json.JSONDecodeError) as err: _LOGGER.error("Can't read addon.json: %s", err) - # validate + # Validate try: data = SCHEMA_ADDON_SNAPSHOT(data) except vol.Invalid as err: @@ -884,11 +909,11 @@ class Addon(CoreSysAttributes): self._id, humanize_error(data, err)) return False - # restore data / reload addon + # Restore data or reload add-on _LOGGER.info("Restore config for addon %s", self._id) self._restore_data(data[ATTR_USER], data[ATTR_SYSTEM]) - # check version / restore image + # Check version / restore image version = data[ATTR_VERSION] if not await self.instance.exists(): _LOGGER.info("Restore image for addon %s", self._id) @@ -902,7 +927,7 @@ class Addon(CoreSysAttributes): else: await self.instance.stop() - # restore data + # Restore data def _restore_data(): """Restore data.""" shutil.copytree(str(Path(temp, "data")), str(self.path_data)) @@ -926,9 +951,9 @@ class Addon(CoreSysAttributes): _LOGGER.error("Can't restore AppArmor profile") return False - # run addon + # Run add-on if data[ATTR_STATE] == STATE_STARTED: return await self.start() - _LOGGER.info("Finish restore for addon %s", self._id) + _LOGGER.info("Finish restore for add-on %s", self._id) return True diff --git a/hassio/addons/build.py b/hassio/addons/build.py index 4d9a37618..b857b01ef 100644 --- a/hassio/addons/build.py +++ b/hassio/addons/build.py @@ -1,4 +1,4 @@ -"""HassIO addons build environment.""" +"""Hass.io add-on build environment.""" from pathlib import Path from .validate import SCHEMA_BUILD_CONFIG, BASE_IMAGE @@ -8,10 +8,10 @@ from ..utils.json import JsonConfig class AddonBuild(JsonConfig, CoreSysAttributes): - """Handle build options for addons.""" + """Handle build options for add-ons.""" def __init__(self, coresys, slug): - """Initialize addon builder.""" + """Initialize Hass.io add-on builder.""" self.coresys = coresys self._id = slug @@ -24,12 +24,12 @@ class AddonBuild(JsonConfig, CoreSysAttributes): @property def addon(self): - """Return addon of build data.""" + """Return add-on of build data.""" return self.sys_addons.get(self._id) @property def base_image(self): - """Base images for this addon.""" + """Base images for this add-on.""" return self._data[ATTR_BUILD_FROM].get( self.sys_arch, BASE_IMAGE[self.sys_arch]) @@ -40,11 +40,11 @@ class AddonBuild(JsonConfig, CoreSysAttributes): @property def additional_args(self): - """Return additional docker build arguments.""" + """Return additional Docker build arguments.""" return self._data[ATTR_ARGS] def get_docker_args(self, version): - """Create a dict with docker build arguments.""" + """Create a dict with Docker build arguments.""" args = { 'path': str(self.addon.path_location), 'tag': f"{self.addon.image}:{version}", diff --git a/hassio/addons/data.py b/hassio/addons/data.py index 185f2f33a..86ad63cce 100644 --- a/hassio/addons/data.py +++ b/hassio/addons/data.py @@ -1,4 +1,4 @@ -"""Init file for HassIO addons.""" +"""Init file for Hass.io add-on data.""" import logging import json from pathlib import Path @@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__) class AddonsData(JsonConfig, CoreSysAttributes): - """Hold data for addons inside HassIO.""" + """Hold data for Add-ons inside Hass.io.""" def __init__(self, coresys): """Initialize data holder.""" @@ -30,26 +30,26 @@ class AddonsData(JsonConfig, CoreSysAttributes): @property def user(self): - """Return local addon user data.""" + """Return local add-on user data.""" return self._data[ATTR_USER] @property def system(self): - """Return local addon data.""" + """Return local add-on data.""" return self._data[ATTR_SYSTEM] @property def cache(self): - """Return addon data from cache/repositories.""" + """Return add-on data from cache/repositories.""" return self._cache @property def repositories(self): - """Return addon data from repositories.""" + """Return add-on data from repositories.""" return self._repositories def reload(self): - """Read data from addons repository.""" + """Read data from add-on repository.""" self._cache = {} self._repositories = {} @@ -94,7 +94,7 @@ class AddonsData(JsonConfig, CoreSysAttributes): self._read_addons_folder(path, slug) def _read_addons_folder(self, path, repository): - """Read data from addons folder.""" + """Read data from add-ons folder.""" for addon in path.glob("**/config.json"): try: addon_config = read_json_file(addon) diff --git a/hassio/addons/git.py b/hassio/addons/git.py index 71f80160b..4fb16dc51 100644 --- a/hassio/addons/git.py +++ b/hassio/addons/git.py @@ -1,4 +1,4 @@ -"""Init file for HassIO addons git.""" +"""Init file for Hass.io add-on Git.""" import asyncio import logging import functools as ft @@ -16,10 +16,10 @@ _LOGGER = logging.getLogger(__name__) class GitRepo(CoreSysAttributes): - """Manage addons git repo.""" + """Manage Add-on Git repository.""" def __init__(self, coresys, path, url): - """Initialize git base wrapper.""" + """Initialize Git base wrapper.""" self.coresys = coresys self.repo = None self.path = path @@ -38,13 +38,13 @@ class GitRepo(CoreSysAttributes): return self._data[ATTR_BRANCH] async def load(self): - """Init git addon repo.""" + """Init Git add-on repository.""" if not self.path.is_dir(): return await self.clone() async with self.lock: try: - _LOGGER.info("Load addon %s repository", self.path) + _LOGGER.info("Load add-on %s repository", self.path) self.repo = await self.sys_run_in_executor( git.Repo, str(self.path)) @@ -57,7 +57,7 @@ class GitRepo(CoreSysAttributes): return True async def clone(self): - """Clone git addon repo.""" + """Clone git add-on repository.""" async with self.lock: git_args = { attribute: value @@ -70,7 +70,7 @@ class GitRepo(CoreSysAttributes): } try: - _LOGGER.info("Clone addon %s repository", self.url) + _LOGGER.info("Clone add-on %s repository", self.url) self.repo = await self.sys_run_in_executor(ft.partial( git.Repo.clone_from, self.url, str(self.path), **git_args @@ -78,20 +78,20 @@ class GitRepo(CoreSysAttributes): except (git.InvalidGitRepositoryError, git.NoSuchPathError, git.GitCommandError) as err: - _LOGGER.error("Can't clone %s repo: %s.", self.url, err) + _LOGGER.error("Can't clone %s repository: %s.", self.url, err) self._remove() return False return True async def pull(self): - """Pull git addon repo.""" + """Pull Git add-on repo.""" if self.lock.locked(): - _LOGGER.warning("It is already a task in progress.") + _LOGGER.warning("It is already a task in progress") return False async with self.lock: - _LOGGER.info("Update addon %s repository", self.url) + _LOGGER.info("Update add-on %s repository", self.url) branch = self.repo.active_branch.name try: @@ -130,19 +130,19 @@ class GitRepo(CoreSysAttributes): class GitRepoHassIO(GitRepo): - """HassIO addons repository.""" + """Hass.io add-ons repository.""" def __init__(self, coresys): - """Initialize git hassio addon repository.""" + """Initialize Git Hass.io add-on repository.""" super().__init__( coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS) class GitRepoCustom(GitRepo): - """Custom addons repository.""" + """Custom add-ons repository.""" def __init__(self, coresys, url): - """Initialize git hassio addon repository.""" + """Initialize custom Git Hass.io addo-n repository.""" path = Path( coresys.config.path_addons_git, get_hash_from_repository(url)) @@ -151,5 +151,5 @@ class GitRepoCustom(GitRepo): def remove(self): """Remove a custom repository.""" - _LOGGER.info("Remove custom addon repository %s", self.url) + _LOGGER.info("Remove custom add-on repository %s", self.url) self._remove() diff --git a/hassio/addons/repository.py b/hassio/addons/repository.py index 37d75ea75..89273c48a 100644 --- a/hassio/addons/repository.py +++ b/hassio/addons/repository.py @@ -1,15 +1,16 @@ -"""Represent a HassIO repository.""" +"""Represent a Hass.io repository.""" from .git import GitRepoHassIO, GitRepoCustom from .utils import get_hash_from_repository from ..const import ( REPOSITORY_CORE, REPOSITORY_LOCAL, ATTR_NAME, ATTR_URL, ATTR_MAINTAINER) from ..coresys import CoreSysAttributes +from ..exceptions import APIError UNKNOWN = 'unknown' class Repository(CoreSysAttributes): - """Repository in HassIO.""" + """Repository in Hass.io.""" def __init__(self, coresys, repository): """Initialize repository object.""" @@ -44,7 +45,7 @@ class Repository(CoreSysAttributes): @property def url(self): - """Return url of repository.""" + """Return URL of repository.""" return self._mesh.get(ATTR_URL, self.source) @property @@ -59,14 +60,14 @@ class Repository(CoreSysAttributes): return True async def update(self): - """Update addon repository.""" + """Update add-on repository.""" if self.git: return await self.git.pull() return True def remove(self): - """Remove addon repository.""" + """Remove add-on repository.""" if self._id in (REPOSITORY_CORE, REPOSITORY_LOCAL): - raise RuntimeError("Can't remove built-in repositories!") + raise APIError("Can't remove built-in repositories!") self.git.remove() diff --git a/hassio/addons/utils.py b/hassio/addons/utils.py index e937e5bc1..ac272ba46 100644 --- a/hassio/addons/utils.py +++ b/hassio/addons/utils.py @@ -1,4 +1,4 @@ -"""Util addons functions.""" +"""Util add-ons functions.""" import asyncio import hashlib import logging @@ -28,10 +28,6 @@ def rating_security(addon): elif addon.apparmor == SECURITY_PROFILE: rating += 1 - # API Access - if addon.access_hassio_api or addon.access_homeassistant_api: - rating += -1 - # Privileged options if addon.privileged in (PRIVILEGED_NET_ADMIN, PRIVILEGED_SYS_ADMIN, PRIVILEGED_SYS_RAWIO, PRIVILEGED_SYS_PTRACE): @@ -78,7 +74,7 @@ def extract_hash_from_path(path): def check_installed(method): - """Wrap function with check if addon is installed.""" + """Wrap function with check if add-on is installed.""" async def wrap_check(addon, *args, **kwargs): """Return False if not installed or the function.""" if not addon.is_installed: diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 794c00d9c..0e25e365f 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -1,4 +1,4 @@ -"""Validate addons options schema.""" +"""Validate add-ons options schema.""" import logging import re import uuid @@ -20,18 +20,19 @@ from ..const import ( ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, ATTR_PROTECTED, ATTR_FULL_ACCESS, ATTR_ACCESS_TOKEN, ATTR_HOST_PID, ATTR_HASSIO_ROLE, + ATTR_MACHINE, PRIVILEGED_NET_ADMIN, PRIVILEGED_SYS_ADMIN, PRIVILEGED_SYS_RAWIO, PRIVILEGED_IPC_LOCK, PRIVILEGED_SYS_TIME, PRIVILEGED_SYS_NICE, PRIVILEGED_SYS_RESOURCE, PRIVILEGED_SYS_PTRACE, ROLE_DEFAULT, ROLE_HOMEASSISTANT, ROLE_MANAGER, ROLE_ADMIN) -from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE +from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE, UUID_MATCH +from ..services.validate import DISCOVERY_SERVICES _LOGGER = logging.getLogger(__name__) RE_VOLUME = re.compile(r"^(config|ssl|addons|backup|share)(?::(rw|:ro))?$") -RE_SERVICE = re.compile(r"^(?Pmqtt)(?::(?Prw|:ro))?$") -RE_DISCOVERY = re.compile(r"^(?P\w*)(?:/(?P\w*>))?$") +RE_SERVICE = re.compile(r"^(?Pmqtt):(?Pprovide|want|need)$") V_STR = 'str' V_INT = 'int' @@ -57,6 +58,12 @@ ARCH_ALL = [ ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386 ] +MACHINE_ALL = [ + 'intel-nuc', 'qemux86', 'qemux86-64', 'qemuarm', 'qemuarm-64', + 'raspberrypi', 'raspberrypi2', 'raspberrypi3', 'raspberrypi3-64', + 'odroid-cu2', 'odroid-xu', +] + STARTUP_ALL = [ STARTUP_ONCE, STARTUP_INITIALIZE, STARTUP_SYSTEM, STARTUP_SERVICES, STARTUP_APPLICATION @@ -105,6 +112,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Required(ATTR_DESCRIPTON): vol.Coerce(str), vol.Optional(ATTR_URL): vol.Url(), vol.Optional(ATTR_ARCH, default=ARCH_ALL): [vol.In(ARCH_ALL)], + vol.Optional(ATTR_MACHINE): [vol.In(MACHINE_ALL)], vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.In(STARTUP_ALL)), vol.Required(ATTR_BOOT): @@ -135,7 +143,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Optional(ATTR_LEGACY, default=False): vol.Boolean(), vol.Optional(ATTR_DOCKER_API, default=False): vol.Boolean(), vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)], - vol.Optional(ATTR_DISCOVERY): [vol.Match(RE_DISCOVERY)], + vol.Optional(ATTR_DISCOVERY): [vol.In(DISCOVERY_SERVICES)], vol.Required(ATTR_OPTIONS): dict, vol.Required(ATTR_SCHEMA): vol.Any(vol.Schema({ vol.Coerce(str): vol.Any(SCHEMA_ELEMENT, [ @@ -177,8 +185,7 @@ SCHEMA_BUILD_CONFIG = vol.Schema({ # pylint: disable=no-value-for-parameter SCHEMA_ADDON_USER = vol.Schema({ vol.Required(ATTR_VERSION): vol.Coerce(str), - vol.Optional(ATTR_UUID, default=lambda: uuid.uuid4().hex): - vol.Match(r"^[0-9a-f]{32}$"), + vol.Optional(ATTR_UUID, default=lambda: uuid.uuid4().hex): UUID_MATCH, vol.Optional(ATTR_ACCESS_TOKEN): vol.Match(r"^[0-9a-f]{64}$"), vol.Optional(ATTR_OPTIONS, default=dict): dict, vol.Optional(ATTR_AUTO_UPDATE, default=False): vol.Boolean(), @@ -218,7 +225,7 @@ SCHEMA_ADDON_SNAPSHOT = vol.Schema({ def validate_options(raw_schema): """Validate schema.""" def validate(struct): - """Create schema validator for addons options.""" + """Create schema validator for add-ons options.""" options = {} # read options diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index 94d04833b..4f86a58ac 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -1,4 +1,4 @@ -"""Init file for HassIO rest api.""" +"""Init file for Hass.io RESTful API.""" import logging from pathlib import Path @@ -14,6 +14,7 @@ from .proxy import APIProxy from .supervisor import APISupervisor from .snapshots import APISnapshots from .services import APIServices +from .version import APIVersion from .security import SecurityMiddleware from ..coresys import CoreSysAttributes @@ -21,10 +22,10 @@ _LOGGER = logging.getLogger(__name__) class RestAPI(CoreSysAttributes): - """Handle rest api for hassio.""" + """Handle RESTful API for Hass.io.""" def __init__(self, coresys): - """Initialize docker base wrapper.""" + """Initialize Docker base wrapper.""" self.coresys = coresys self.security = SecurityMiddleware(coresys) self.webapp = web.Application( @@ -47,9 +48,10 @@ class RestAPI(CoreSysAttributes): self._register_snapshots() self._register_discovery() self._register_services() + self._register_version() def _register_host(self): - """Register hostcontrol function.""" + """Register hostcontrol functions.""" api_host = APIHost() api_host.coresys = self.coresys @@ -69,7 +71,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_hassos(self): - """Register hassos function.""" + """Register HassOS functions.""" api_hassos = APIHassOS() api_hassos.coresys = self.coresys @@ -81,7 +83,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_hardware(self): - """Register hardware function.""" + """Register hardware functions.""" api_hardware = APIHardware() api_hardware.coresys = self.coresys @@ -90,8 +92,17 @@ class RestAPI(CoreSysAttributes): web.get('/hardware/audio', api_hardware.audio), ]) + def _register_version(self): + """Register version functions.""" + api_version = APIVersion() + api_version.coresys = self.coresys + + self.webapp.add_routes([ + web.get('/version', api_version.info), + ]) + def _register_supervisor(self): - """Register supervisor function.""" + """Register Supervisor functions.""" api_supervisor = APISupervisor() api_supervisor.coresys = self.coresys @@ -106,7 +117,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_homeassistant(self): - """Register homeassistant function.""" + """Register Home Assistant functions.""" api_hass = APIHomeAssistant() api_hass.coresys = self.coresys @@ -123,7 +134,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_proxy(self): - """Register HomeAssistant API Proxy.""" + """Register Home Assistant API Proxy.""" api_proxy = APIProxy() api_proxy.coresys = self.coresys @@ -137,7 +148,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_addons(self): - """Register homeassistant function.""" + """Register Add-on functions.""" api_addons = APIAddons() api_addons.coresys = self.coresys @@ -163,7 +174,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_snapshots(self): - """Register snapshots function.""" + """Register snapshots functions.""" api_snapshots = APISnapshots() api_snapshots.coresys = self.coresys @@ -183,6 +194,7 @@ class RestAPI(CoreSysAttributes): ]) def _register_services(self): + """Register services functions.""" api_services = APIServices() api_services.coresys = self.coresys @@ -194,19 +206,20 @@ class RestAPI(CoreSysAttributes): ]) def _register_discovery(self): + """Register discovery functions.""" api_discovery = APIDiscovery() api_discovery.coresys = self.coresys self.webapp.add_routes([ - web.get('/services/discovery', api_discovery.list), - web.get('/services/discovery/{uuid}', api_discovery.get_discovery), - web.delete('/services/discovery/{uuid}', + web.get('/discovery', api_discovery.list), + web.get('/discovery/{uuid}', api_discovery.get_discovery), + web.delete('/discovery/{uuid}', api_discovery.del_discovery), - web.post('/services/discovery', api_discovery.set_discovery), + web.post('/discovery', api_discovery.set_discovery), ]) def _register_panel(self): - """Register panel for homeassistant.""" + """Register panel for Home Assistant.""" panel_dir = Path(__file__).parent.joinpath("panel") def create_response(panel_file): @@ -234,7 +247,7 @@ class RestAPI(CoreSysAttributes): self.webapp.add_routes([web.static('/app', panel_dir)]) async def start(self): - """Run rest api webserver.""" + """Run RESTful API webserver.""" await self._runner.setup() self._site = web.TCPSite( self._runner, host="0.0.0.0", port=80, shutdown_timeout=5) @@ -248,7 +261,7 @@ class RestAPI(CoreSysAttributes): _LOGGER.info("Start API on %s", self.sys_docker.network.supervisor) async def stop(self): - """Stop rest api webserver.""" + """Stop RESTful API webserver.""" if not self._site: return diff --git a/hassio/api/addons.py b/hassio/api/addons.py index e95ec063a..4b2ae3a21 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -1,4 +1,4 @@ -"""Init file for HassIO homeassistant rest api.""" +"""Init file for Hass.io Home Assistant RESTful API.""" import asyncio import logging @@ -20,11 +20,10 @@ from ..const import ( ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES, ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, ATTR_FULL_ACCESS, ATTR_PROTECTED, ATTR_RATING, ATTR_HOST_PID, - ATTR_HASSIO_ROLE, + ATTR_HASSIO_ROLE, ATTR_MACHINE, ATTR_AVAILABLE, CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT, REQUEST_FROM) from ..coresys import CoreSysAttributes from ..validate import DOCKER_PORTS, ALSA_DEVICE -from ..exceptions import APINotSupportedError _LOGGER = logging.getLogger(__name__) @@ -48,7 +47,7 @@ SCHEMA_SECURITY = vol.Schema({ class APIAddons(CoreSysAttributes): - """Handle rest api for addons functions.""" + """Handle RESTful API for add-on functions.""" def _extract_addon(self, request, check_installed=True): """Return addon, throw an exception it it doesn't exist.""" @@ -56,7 +55,7 @@ class APIAddons(CoreSysAttributes): # Lookup itself if addon_slug == 'self': - addon_slug = request.get(REQUEST_FROM) + return request.get(REQUEST_FROM) addon = self.sys_addons.get(addon_slug) if not addon: @@ -67,17 +66,9 @@ class APIAddons(CoreSysAttributes): return addon - @staticmethod - def _pretty_devices(addon): - """Return a simplified device list.""" - dev_list = addon.devices - if not dev_list: - return None - return [row.split(':')[0] for row in dev_list] - @api_process async def list(self, request): - """Return all addons / repositories .""" + """Return all add-ons or repositories.""" data_addons = [] for addon in self.sys_addons.list_addons: data_addons.append({ @@ -86,7 +77,7 @@ class APIAddons(CoreSysAttributes): ATTR_DESCRIPTON: addon.description, ATTR_VERSION: addon.last_version, ATTR_INSTALLED: addon.version_installed, - ATTR_ARCH: addon.supported_arch, + ATTR_AVAILABLE: addon.available, ATTR_DETACHED: addon.is_detached, ATTR_REPOSITORY: addon.repository, ATTR_BUILD: addon.need_build, @@ -112,13 +103,13 @@ class APIAddons(CoreSysAttributes): @api_process async def reload(self, request): - """Reload all addons data.""" + """Reload all add-on data.""" await asyncio.shield(self.sys_addons.reload()) return True @api_process async def info(self, request): - """Return addon information.""" + """Return add-on information.""" addon = self._extract_addon(request, check_installed=False) return { @@ -135,8 +126,11 @@ class APIAddons(CoreSysAttributes): ATTR_RATING: rating_security(addon), ATTR_BOOT: addon.boot, ATTR_OPTIONS: addon.options, + ATTR_ARCH: addon.supported_arch, + ATTR_MACHINE: addon.supported_machine, ATTR_URL: addon.url, ATTR_DETACHED: addon.is_detached, + ATTR_AVAILABLE: addon.available, ATTR_BUILD: addon.need_build, ATTR_NETWORK: addon.ports, ATTR_HOST_NETWORK: addon.host_network, @@ -146,7 +140,7 @@ class APIAddons(CoreSysAttributes): ATTR_PRIVILEGED: addon.privileged, ATTR_FULL_ACCESS: addon.with_full_access, ATTR_APPARMOR: addon.apparmor, - ATTR_DEVICES: self._pretty_devices(addon), + ATTR_DEVICES: _pretty_devices(addon), ATTR_ICON: addon.with_icon, ATTR_LOGO: addon.with_logo, ATTR_CHANGELOG: addon.with_changelog, @@ -161,13 +155,13 @@ class APIAddons(CoreSysAttributes): ATTR_AUDIO: addon.with_audio, ATTR_AUDIO_INPUT: addon.audio_input, ATTR_AUDIO_OUTPUT: addon.audio_output, - ATTR_SERVICES: addon.services, + ATTR_SERVICES: _pretty_services(addon), ATTR_DISCOVERY: addon.discovery, } @api_process async def options(self, request): - """Store user options for addon.""" + """Store user options for add-on.""" addon = self._extract_addon(request) addon_schema = SCHEMA_OPTIONS.extend({ @@ -194,15 +188,8 @@ class APIAddons(CoreSysAttributes): @api_process async def security(self, request): - """Store security options for addon.""" + """Store security options for add-on.""" addon = self._extract_addon(request) - - # Have Access - # REMOVE: don't needed anymore - if addon.slug == request[REQUEST_FROM]: - _LOGGER.error("Can't self modify his security!") - raise APINotSupportedError() - body = await api_validate(SCHEMA_SECURITY, request) if ATTR_PROTECTED in body: @@ -233,19 +220,19 @@ class APIAddons(CoreSysAttributes): @api_process def install(self, request): - """Install addon.""" + """Install add-on.""" addon = self._extract_addon(request, check_installed=False) return asyncio.shield(addon.install()) @api_process def uninstall(self, request): - """Uninstall addon.""" + """Uninstall add-on.""" addon = self._extract_addon(request) return asyncio.shield(addon.uninstall()) @api_process def start(self, request): - """Start addon.""" + """Start add-on.""" addon = self._extract_addon(request) # check options @@ -259,13 +246,13 @@ class APIAddons(CoreSysAttributes): @api_process def stop(self, request): - """Stop addon.""" + """Stop add-on.""" addon = self._extract_addon(request) return asyncio.shield(addon.stop()) @api_process def update(self, request): - """Update addon.""" + """Update add-on.""" addon = self._extract_addon(request) if addon.last_version == addon.version_installed: @@ -275,13 +262,13 @@ class APIAddons(CoreSysAttributes): @api_process def restart(self, request): - """Restart addon.""" + """Restart add-on.""" addon = self._extract_addon(request) return asyncio.shield(addon.restart()) @api_process def rebuild(self, request): - """Rebuild local build addon.""" + """Rebuild local build add-on.""" addon = self._extract_addon(request) if not addon.need_build: raise RuntimeError("Only local build addons are supported") @@ -290,13 +277,13 @@ class APIAddons(CoreSysAttributes): @api_process_raw(CONTENT_TYPE_BINARY) def logs(self, request): - """Return logs from addon.""" + """Return logs from add-on.""" addon = self._extract_addon(request) return addon.logs() @api_process_raw(CONTENT_TYPE_PNG) async def icon(self, request): - """Return icon from addon.""" + """Return icon from add-on.""" addon = self._extract_addon(request, check_installed=False) if not addon.with_icon: raise RuntimeError("No icon found!") @@ -306,7 +293,7 @@ class APIAddons(CoreSysAttributes): @api_process_raw(CONTENT_TYPE_PNG) async def logo(self, request): - """Return logo from addon.""" + """Return logo from add-on.""" addon = self._extract_addon(request, check_installed=False) if not addon.with_logo: raise RuntimeError("No logo found!") @@ -316,7 +303,7 @@ class APIAddons(CoreSysAttributes): @api_process_raw(CONTENT_TYPE_TEXT) async def changelog(self, request): - """Return changelog from addon.""" + """Return changelog from add-on.""" addon = self._extract_addon(request, check_installed=False) if not addon.with_changelog: raise RuntimeError("No changelog found!") @@ -326,10 +313,26 @@ class APIAddons(CoreSysAttributes): @api_process async def stdin(self, request): - """Write to stdin of addon.""" + """Write to stdin of add-on.""" addon = self._extract_addon(request) if not addon.with_stdin: - raise RuntimeError("STDIN not supported by addon") + raise RuntimeError("STDIN not supported by add-on") data = await request.read() return await asyncio.shield(addon.write_stdin(data)) + + +def _pretty_devices(addon): + """Return a simplified device list.""" + dev_list = addon.devices + if not dev_list: + return None + return [row.split(':')[0] for row in dev_list] + + +def _pretty_services(addon): + """Return a simplified services role list.""" + services = [] + for name, access in addon.services_role.items(): + services.append(f"{name}:{access}") + return services diff --git a/hassio/api/discovery.py b/hassio/api/discovery.py index 7ab5f8d2a..0acf972a9 100644 --- a/hassio/api/discovery.py +++ b/hassio/api/discovery.py @@ -1,38 +1,48 @@ -"""Init file for HassIO network rest api.""" - +"""Init file for Hass.io network RESTful API.""" import voluptuous as vol from .utils import api_process, api_validate from ..const import ( - ATTR_PROVIDER, ATTR_UUID, ATTR_COMPONENT, ATTR_PLATFORM, ATTR_CONFIG, - ATTR_DISCOVERY, REQUEST_FROM) + ATTR_ADDON, ATTR_UUID, ATTR_COMPONENT, ATTR_PLATFORM, ATTR_CONFIG, + ATTR_DISCOVERY, ATTR_SERVICE, REQUEST_FROM) from ..coresys import CoreSysAttributes +from ..exceptions import APIError, APIForbidden +from ..validate import SERVICE_ALL SCHEMA_DISCOVERY = vol.Schema({ + vol.Required(ATTR_SERVICE): SERVICE_ALL, vol.Required(ATTR_COMPONENT): vol.Coerce(str), - vol.Optional(ATTR_PLATFORM): vol.Any(None, vol.Coerce(str)), - vol.Optional(ATTR_CONFIG): vol.Any(None, dict), + vol.Optional(ATTR_PLATFORM): vol.Maybe(vol.Coerce(str)), + vol.Optional(ATTR_CONFIG): vol.Maybe(dict), }) class APIDiscovery(CoreSysAttributes): - """Handle rest api for discovery functions.""" + """Handle RESTful API for discovery functions.""" def _extract_message(self, request): """Extract discovery message from URL.""" message = self.sys_discovery.get(request.match_info.get('uuid')) if not message: - raise RuntimeError("Discovery message not found") + raise APIError("Discovery message not found") return message + def _check_permission_ha(self, request): + """Check permission for API call / Home Assistant.""" + if request[REQUEST_FROM] != self.sys_homeassistant: + raise APIForbidden("Only HomeAssistant can use this API!") + @api_process async def list(self, request): """Show register services.""" + self._check_permission_ha(request) + discovery = [] for message in self.sys_discovery.list_messages: discovery.append({ - ATTR_PROVIDER: message.provider, + ATTR_ADDON: message.addon, + ATTR_SERVICE: message.service, ATTR_UUID: message.uuid, ATTR_COMPONENT: message.component, ATTR_PLATFORM: message.platform, @@ -45,8 +55,14 @@ class APIDiscovery(CoreSysAttributes): async def set_discovery(self, request): """Write data into a discovery pipeline.""" body = await api_validate(SCHEMA_DISCOVERY, request) - message = self.sys_discovery.send( - provider=request[REQUEST_FROM], **body) + addon = request[REQUEST_FROM] + + # Access? + if body[ATTR_SERVICE] not in addon.discovery: + raise APIForbidden(f"Can't use discovery!") + + # Process discovery message + message = self.sys_discovery.send(addon, **body) return {ATTR_UUID: message.uuid} @@ -55,8 +71,12 @@ class APIDiscovery(CoreSysAttributes): """Read data into a discovery message.""" message = self._extract_message(request) + # HomeAssistant? + self._check_permission_ha(request) + return { - ATTR_PROVIDER: message.provider, + ATTR_ADDON: message.addon, + ATTR_SERVICE: message.service, ATTR_UUID: message.uuid, ATTR_COMPONENT: message.component, ATTR_PLATFORM: message.platform, @@ -67,6 +87,11 @@ class APIDiscovery(CoreSysAttributes): async def del_discovery(self, request): """Delete data into a discovery message.""" message = self._extract_message(request) + addon = request[REQUEST_FROM] + + # Permission + if message.addon != addon.slug: + raise APIForbidden(f"Can't remove discovery message") self.sys_discovery.remove(message) return True diff --git a/hassio/api/hardware.py b/hassio/api/hardware.py index 7830b9675..f9676209d 100644 --- a/hassio/api/hardware.py +++ b/hassio/api/hardware.py @@ -1,4 +1,4 @@ -"""Init file for HassIO hardware rest api.""" +"""Init file for Hass.io hardware RESTful API.""" import logging from .utils import api_process @@ -10,7 +10,7 @@ _LOGGER = logging.getLogger(__name__) class APIHardware(CoreSysAttributes): - """Handle rest api for hardware functions.""" + """Handle RESTful API for hardware functions.""" @api_process async def info(self, request): diff --git a/hassio/api/hassos.py b/hassio/api/hassos.py index ac8166027..eb2d8ccdd 100644 --- a/hassio/api/hassos.py +++ b/hassio/api/hassos.py @@ -1,4 +1,4 @@ -"""Init file for Hass.io hassos rest api.""" +"""Init file for Hass.io HassOS RESTful API.""" import asyncio import logging @@ -18,11 +18,11 @@ SCHEMA_VERSION = vol.Schema({ class APIHassOS(CoreSysAttributes): - """Handle rest api for hassos functions.""" + """Handle RESTful API for HassOS functions.""" @api_process async def info(self, request): - """Return hassos information.""" + """Return HassOS information.""" return { ATTR_VERSION: self.sys_hassos.version, ATTR_VERSION_CLI: self.sys_hassos.version_cli, diff --git a/hassio/api/homeassistant.py b/hassio/api/homeassistant.py index e0a1b158c..78d92b3f7 100644 --- a/hassio/api/homeassistant.py +++ b/hassio/api/homeassistant.py @@ -1,4 +1,4 @@ -"""Init file for HassIO homeassistant rest api.""" +"""Init file for Hass.io Home Assistant RESTful API.""" import asyncio import logging @@ -13,6 +13,7 @@ from ..const import ( ATTR_REFRESH_TOKEN, CONTENT_TYPE_BINARY) from ..coresys import CoreSysAttributes from ..validate import NETWORK_PORT, DOCKER_IMAGE +from ..exceptions import APIError _LOGGER = logging.getLogger(__name__) @@ -39,7 +40,7 @@ SCHEMA_VERSION = vol.Schema({ class APIHomeAssistant(CoreSysAttributes): - """Handle rest api for homeassistant functions.""" + """Handle RESTful API for Home Assistant functions.""" @api_process async def info(self, request): @@ -59,7 +60,7 @@ class APIHomeAssistant(CoreSysAttributes): @api_process async def options(self, request): - """Set homeassistant options.""" + """Set Home Assistant options.""" body = await api_validate(SCHEMA_OPTIONS, request) if ATTR_IMAGE in body and ATTR_LAST_VERSION in body: @@ -94,7 +95,7 @@ class APIHomeAssistant(CoreSysAttributes): """Return resource information.""" stats = await self.sys_homeassistant.stats() if not stats: - raise RuntimeError("No stats available") + raise APIError("No stats available") return { ATTR_CPU_PERCENT: stats.cpu_percent, @@ -108,7 +109,7 @@ class APIHomeAssistant(CoreSysAttributes): @api_process async def update(self, request): - """Update homeassistant.""" + """Update Home Assistant.""" body = await api_validate(SCHEMA_VERSION, request) version = body.get(ATTR_VERSION, self.sys_homeassistant.last_version) @@ -116,29 +117,29 @@ class APIHomeAssistant(CoreSysAttributes): @api_process def stop(self, request): - """Stop homeassistant.""" + """Stop Home Assistant.""" return asyncio.shield(self.sys_homeassistant.stop()) @api_process def start(self, request): - """Start homeassistant.""" + """Start Home Assistant.""" return asyncio.shield(self.sys_homeassistant.start()) @api_process def restart(self, request): - """Restart homeassistant.""" + """Restart Home Assistant.""" return asyncio.shield(self.sys_homeassistant.restart()) @api_process_raw(CONTENT_TYPE_BINARY) def logs(self, request): - """Return homeassistant docker logs.""" + """Return Home Assistant Docker logs.""" return self.sys_homeassistant.logs() @api_process async def check(self, request): - """Check config of homeassistant.""" + """Check configuration of Home Assistant.""" result = await self.sys_homeassistant.check_config() if not result.valid: - raise RuntimeError(result.log) + raise APIError(result.log) return True diff --git a/hassio/api/host.py b/hassio/api/host.py index 49352dfc9..7d04e9112 100644 --- a/hassio/api/host.py +++ b/hassio/api/host.py @@ -1,4 +1,4 @@ -"""Init file for HassIO host rest api.""" +"""Init file for Hass.io host RESTful API.""" import asyncio import logging @@ -21,7 +21,7 @@ SCHEMA_OPTIONS = vol.Schema({ class APIHost(CoreSysAttributes): - """Handle rest api for host functions.""" + """Handle RESTful API for host functions.""" @api_process async def info(self, request): diff --git a/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js b/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js deleted file mode 100644 index e5a0089c4..000000000 --- a/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{2:function(e,n,t){"use strict";t.r(n),t(75);var o=t(4),a=t(6),r=(t(27),t(74),t(56),t(20),t(11)),s=function(){function e(e,n){for(var t=0;t\n .invisible {\n visibility: hidden;\n }\n \n \n'],{raw:{value:Object.freeze(['\n \n \n'])}})),c=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),l(n,[{key:"computeMenuButtonClass",value:function(e,n){return!e&&n?"invisible":""}},{key:"toggleMenu",value:function(e){e.stopPropagation(),this.fire("hass-open-menu")}},{key:"_getIcon",value:function(e){return(e?"hassio":"hass")+":menu"}}],[{key:"template",get:function(){return Object(o.a)(p)}},{key:"properties",get:function(){return{narrow:{type:Boolean,value:!1},showMenu:{type:Boolean,value:!1},hassio:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-menu-button",c);var d=function(){function e(e,n){for(var t=0;t\n .placeholder {\n height: 100%;\n }\n\n .layout {\n height: calc(100% - 64px);\n }\n \n\n
\n \n \n
[[title]]
\n
\n
\n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n\n
\n \n \n
[[title]]
\n
\n
\n \n
\n
\n'])}})),h=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),d(n,null,[{key:"template",get:function(){return Object(o.a)(u)}},{key:"properties",get:function(){return{narrow:{type:Boolean,value:!1},showMenu:{type:Boolean,value:!1},title:{type:String,value:""}}}}]),n}();customElements.define("hass-loading-screen",h),t(72),t(57),t(101),t(3);var f=document.createElement("template");f.setAttribute("style","display: none;"),f.innerHTML='\n \n\n \n\n \n\n \n',document.head.appendChild(f.content),t(70),t(55);var b=function(){function e(e,n){for(var t=0;t\n paper-dialog {\n min-width: 350px;\n font-size: 14px;\n border-radius: 2px;\n }\n app-toolbar {\n margin: 0;\n padding: 0 16px;\n color: var(--primary-text-color);\n background-color: var(--secondary-background-color);\n }\n app-toolbar [main-title] {\n margin-left: 16px;\n }\n paper-checkbox {\n display: block;\n margin: 4px;\n }\n @media all and (max-width: 450px), all and (max-height: 500px) {\n paper-dialog {\n max-height: 100%;\n }\n paper-dialog::before {\n content: "";\n position: fixed;\n z-index: -1;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n background-color: inherit;\n }\n app-toolbar {\n color: var(--text-primary-color);\n background-color: var(--primary-color);\n }\n }\n \n \n \n \n
[[title]]
\n
\n \n \n \n
\n'],{raw:{value:Object.freeze(['\n \n \n \n \n
[[title]]
\n
\n \n \n \n
\n'])}})),w=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),v(n,[{key:"openDialog",value:function(){this.$.dialog.open()}}],[{key:"template",get:function(){return Object(o.a)(g)}},{key:"properties",get:function(){return{title:String,content:String}}}]),n}();customElements.define("hassio-markdown-dialog",w),t(93),t(13),t(12),t(86),t(84),t(92);var k=function(){function e(e,n){for(var t=0;t\n :host,\n paper-card,\n paper-dropdown-menu {\n display: block;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n paper-item {\n width: 450px;\n }\n .card-actions {\n text-align: right;\n }\n \n \n
\n \n\n \n \n \n \n \n \n \n \n \n \n
\n
\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n\n \n \n \n \n \n \n \n \n \n \n
\n
\n Save\n
\n
\n'])}})),_=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),k(n,[{key:"addonChanged",value:function(e){var n=this;if(this.setProperties({selectedInput:e.audio_input||"null",selectedOutput:e.audio_output||"null"}),!this.outputDevices){var t=[{device:"null",name:"-"}];this.hass.callApi("get","hassio/hardware/audio").then(function(e){var o=e.data.audio,a=Object.keys(o.input).map(function(e){return{device:e,name:o.input[e]}}),r=Object.keys(o.output).map(function(e){return{device:e,name:o.output[e]}});n.setProperties({inputDevices:t.concat(a),outputDevices:t.concat(r)})},function(){n.setProperties({inputDevices:t,outputDevices:t})})}}},{key:"_saveSettings",value:function(){var e=this;this.error=null;var n="hassio/addons/"+this.addon.slug+"/options";this.hass.callApi("post",n,{audio_input:"null"===this.selectedInput?null:this.selectedInput,audio_output:"null"===this.selectedOutput?null:this.selectedOutput}).then(function(){e.fire("hass-api-called",{success:!0,path:n})},function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(o.a)(O)}},{key:"properties",get:function(){return{hass:Object,addon:{type:Object,observer:"addonChanged"},inputDevices:Array,outputDevices:Array,selectedInput:String,selectedOutput:String,error:String}}}]),n}();customElements.define("hassio-addon-audio",_),t(91);var j=function(){function e(e,n){for(var t=0;t\n .container {\n position: relative;\n display: inline-block;\n }\n\n paper-button {\n transition: all 1s;\n }\n\n .success paper-button {\n color: white;\n background-color: var(--google-green-500);\n transition: none;\n }\n\n .error paper-button {\n color: white;\n background-color: var(--google-red-500);\n transition: none;\n }\n\n paper-button[disabled] {\n color: #c8c8c8;\n }\n\n .progress {\n @apply --layout;\n @apply --layout-center-center;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n \n
\n \n \n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n \n \n \n \n
\n'])}})),S=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),j(n,[{key:"tempClass",value:function(e){var n=this.$.container.classList;n.add(e),setTimeout(function(){n.remove(e)},1e3)}},{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("click",function(n){return e.buttonTapped(n)})}},{key:"buttonTapped",value:function(e){this.progress&&e.stopPropagation()}},{key:"actionSuccess",value:function(){this.tempClass("success")}},{key:"actionError",value:function(){this.tempClass("error")}},{key:"computeDisabled",value:function(e,n){return e||n}}],[{key:"template",get:function(){return Object(o.a)(x)}},{key:"properties",get:function(){return{hass:{type:Object},progress:{type:Boolean,value:!1},disabled:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-progress-button",S);var P=function(){function e(e,n){for(var t=0;t\n'],{raw:{value:Object.freeze(['\n \n'])}})),E=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),P(n,[{key:"buttonTapped",value:function(){var e=this;this.progress=!0;var n={method:this.method,path:this.path,data:this.data};this.hass.callApi(this.method,this.path,this.data).then(function(t){e.progress=!1,e.$.progress.actionSuccess(),n.success=!0,n.response=t},function(t){e.progress=!1,e.$.progress.actionError(),n.success=!1,n.response=t}).then(function(){e.fire("hass-api-called",n)})}}],[{key:"template",get:function(){return Object(o.a)(C)}},{key:"properties",get:function(){return{hass:Object,progress:{type:Boolean,value:!1},path:String,method:{type:String,value:"POST"},data:{type:Object,value:{}},disabled:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-call-api-button",E);var T=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n }\n .card-actions {\n @apply --layout;\n @apply --layout-justified;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n iron-autogrow-textarea {\n width: 100%;\n font-family: monospace;\n }\n .syntaxerror {\n color: var(--google-red-500);\n }\n \n \n
\n \n \n
\n
\n Reset to defaults\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n \n
\n
\n Reset to defaults\n Save\n
\n
\n'])}})),D=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),T(n,[{key:"addonChanged",value:function(e){this.config=e?JSON.stringify(e.options,null,2):""}},{key:"configChanged",value:function(e){try{this.$.config.classList.remove("syntaxerror"),this.configParsed=JSON.parse(e)}catch(e){this.$.config.classList.add("syntaxerror"),this.configParsed=null}}},{key:"saveTapped",value:function(){var e=this;this.error=null,this.hass.callApi("post","hassio/addons/"+this.addonSlug+"/options",{options:this.configParsed}).catch(function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(o.a)(A)}},{key:"properties",get:function(){return{hass:Object,addon:{type:Object,observer:"addonChanged"},addonSlug:String,config:{type:String,observer:"configChanged"},configParsed:Object,error:String,resetData:{type:Object,value:{options:null}}}}}]),n}();customElements.define("hassio-addon-config",D),t(19),t(90);var R=t(7),I=[60,"second",60,"minute",24,"hour",7,"day"],z=t(76),q=(t(82),t(85)),L={__localizationCache:{requests:{},messages:{},ajax:null},properties:{language:{type:String},resources:{type:Object},formats:{type:Object,value:function(){return{}}},useKeyIfMissing:{type:Boolean,value:!1},localize:{type:Function,computed:"__computeLocalize(language, resources, formats)"},bubbleEvent:{type:Boolean,value:!1}},loadResources:function(e,n,t){var o=this.constructor.prototype;this.__checkLocalizationCache(o);var a,r=o.__localizationCache.ajax;function s(e){this.__onRequestResponse(e,n,t)}r||(r=o.__localizationCache.ajax=document.createElement("iron-ajax")),(a=o.__localizationCache.requests[e])?a.completes.then(s.bind(this),this.__onRequestError.bind(this)):(r.url=e,(a=r.generateRequest()).completes.then(s.bind(this),this.__onRequestError.bind(this)),o.__localizationCache.requests[e]=a)},__computeLocalize:function(e,n,t){var o=this.constructor.prototype;return this.__checkLocalizationCache(o),o.__localizationCache||(o.__localizationCache={requests:{},messages:{},ajax:null}),o.__localizationCache.messages={},function(){var a=arguments[0];if(a&&n&&e&&n[e]){var r=n[e][a];if(!r)return this.useKeyIfMissing?a:"";var s=a+r,i=o.__localizationCache.messages[s];i||(i=new q.a(r,e,t),o.__localizationCache.messages[s]=i);for(var l={},p=1;p=0?"past":"future";n=Math.abs(n);for(var o=0;o\n iron-icon {\n margin-right: 16px;\n margin-top: 16px;\n float: left;\n color: var(--secondary-text-color);\n }\n iron-icon.update {\n color: var(--paper-orange-400);\n }\n iron-icon.running,\n iron-icon.installed {\n color: var(--paper-green-400);\n }\n iron-icon.hassupdate,\n iron-icon.snapshot {\n color: var(--paper-item-icon-color);\n }\n .title {\n color: var(--primary-text-color);\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n .addition {\n color: var(--secondary-text-color);\n overflow: hidden;\n position: relative;\n height: 2.4em;\n line-height: 1.2em;\n }\n ha-relative-time {\n display: block;\n }\n \n \n
\n
[[title]]
\n
\n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[title]]
\n
\n \n \n
\n
\n'])}})),W=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),N(n,null,[{key:"template",get:function(){return Object(o.a)($)}},{key:"properties",get:function(){return{hass:Object,title:String,description:String,datetime:String,icon:{type:String,value:"hass:help-circle"},iconTitle:String,iconClass:String}}}]),n}();customElements.define("hassio-card-content",W);var Y=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n margin-bottom: 16px;\n }\n .addon-header {\n @apply --paper-font-headline;\n }\n .light-color {\n color: var(--secondary-text-color);\n }\n .addon-version {\n float: right;\n font-size: 15px;\n vertical-align: middle;\n }\n .description {\n margin-bottom: 16px;\n }\n .logo img {\n max-height: 60px;\n margin: 16px 0;\n display: block;\n }\n .state div{\n width: 150px;\n display: inline-block;\n }\n paper-toggle-button {\n display: inline;\n }\n iron-icon.running {\n color: var(--paper-green-400);\n }\n iron-icon.stopped {\n color: var(--google-red-300);\n }\n ha-call-api-button {\n font-weight: 500;\n color: var(--primary-color);\n }\n .right {\n float: right;\n }\n ha-markdown img {\n max-width: 100%;\n }\n \n \n\n \n
\n
[[addon.name]]\n
\n \n \n
\n
\n
\n [[addon.description]].
\n Visit [[addon.name]] page for details.\n
\n \n \n
\n
\n \n \n
\n
\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n
\n
[[addon.name]]\n
\n \n \n
\n
\n
\n [[addon.description]].
\n Visit [[addon.name]] page for details.\n
\n \n \n
\n
\n \n \n
\n
\n \n'])}})),G=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),Y(n,[{key:"computeIsRunning",value:function(e){return e&&"started"===e.state}},{key:"computeUpdateAvailable",value:function(e){return e&&!e.detached&&e.version&&e.version!==e.last_version}},{key:"pathWebui",value:function(e){return e&&e.replace("[HOST]",document.location.hostname)}},{key:"computeShowWebUI",value:function(e,n){return e&&n}},{key:"computeStartOnBoot",value:function(e){return"auto"===e}},{key:"startOnBootToggled",value:function(){var e={boot:"auto"===this.addon.boot?"manual":"auto"};this.hass.callApi("POST","hassio/addons/"+this.addonSlug+"/options",e)}},{key:"autoUpdateToggled",value:function(){var e={auto_update:!this.addon.auto_update};this.hass.callApi("POST","hassio/addons/"+this.addonSlug+"/options",e)}},{key:"openChangelog",value:function(){var e=this;this.hass.callApi("get","hassio/addons/"+this.addonSlug+"/changelog").then(function(e){return e},function(){return"Error getting changelog"}).then(function(n){e.fire("hassio-markdown-dialog",{title:"Changelog",content:n})})}},{key:"_unistallClicked",value:function(){var e=this;if(confirm("Are you sure you want to uninstall this add-on?")){var n="hassio/addons/"+this.addonSlug+"/uninstall",t={path:n};this.hass.callApi("post",n).then(function(e){t.success=!0,t.response=e},function(e){t.success=!1,t.response=e}).then(function(){e.fire("hass-api-called",t)})}}}],[{key:"template",get:function(){return Object(o.a)(J)}},{key:"properties",get:function(){return{hass:Object,addon:Object,addonSlug:String,isRunning:{type:Boolean,computed:"computeIsRunning(addon)"}}}}]),n}();customElements.define("hassio-addon-info",G);var V=function(){function e(e,n){for(var t=0;t\n :host,\n paper-card {\n display: block;\n }\n pre {\n overflow-x: auto;\n }\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'])}})),K=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),V(n,[{key:"addonSlugChanged",value:function(e){var n=this;this.hass?this.refresh():setTimeout(function(){n.addonChanged(e)},0)}},{key:"refresh",value:function(){var e=this;this.hass.callApi("get","hassio/addons/"+this.addonSlug+"/logs").then(function(n){e.log=n})}}],[{key:"template",get:function(){return Object(o.a)(X)}},{key:"properties",get:function(){return{hass:Object,addonSlug:{type:String,observer:"addonSlugChanged"},log:String}}}]),n}();customElements.define("hassio-addon-logs",K),t(24);var Q=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n .card-actions {\n @apply --layout;\n @apply --layout-justified;\n }\n \n \n
\n \n\n \n \n \n \n \n \n
ContainerHost
\n
\n
\n Reset to defaults\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n\n \n \n \n \n \n \n
ContainerHost
\n
\n
\n Reset to defaults\n Save\n
\n
\n'])}})),ee=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),Q(n,[{key:"addonChanged",value:function(e){if(e){var n=e.network||{},t=Object.keys(n).map(function(e){return{container:e,host:n[e]}});this.config=t.sort(function(e,n){return e.host-n.host})}}},{key:"saveTapped",value:function(){var e=this;this.error=null;var n={};this.config.forEach(function(e){n[e.container]=parseInt(e.host)});var t="hassio/addons/"+this.addonSlug+"/options";this.hass.callApi("post",t,{network:n}).then(function(){e.fire("hass-api-called",{success:!0,path:t})},function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(o.a)(Z)}},{key:"properties",get:function(){return{hass:Object,addonSlug:String,config:Object,addon:{type:Object,observer:"addonChanged"},error:String,resetData:{type:Object,value:{network:null}}}}}]),n}();customElements.define("hassio-addon-network",ee);var ne=function(){function e(e,n){for(var t=0;t\n :host {\n color: var(--primary-text-color);\n --paper-card-header-color: var(--primary-text-color);\n }\n .content {\n padding: 24px 0 32px;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n hassio-addon-info,\n hassio-addon-network,\n hassio-addon-audio,\n hassio-addon-config {\n margin-bottom: 24px;\n width: 600px;\n }\n hassio-addon-logs {\n max-width: calc(100% - 8px);\n min-width: 600px;\n }\n @media only screen and (max-width: 600px) {\n hassio-addon-info,\n hassio-addon-network,\n hassio-addon-audio,\n hassio-addon-config,\n hassio-addon-logs {\n max-width: 100%;\n min-width: 100%;\n }\n }\n \n \n \n \n \n \n \n
Hass.io: add-on details
\n
\n
\n
\n \n\n \n
\n
\n\n \n'],{raw:{value:Object.freeze(['\n \n \n \n \n \n \n \n
Hass.io: add-on details
\n
\n
\n
\n \n\n \n
\n
\n\n \n'])}})),oe=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),ne(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)}),this.addEventListener("hassio-markdown-dialog",function(n){return e.openMarkdown(n)})}},{key:"apiCalled",value:function(e){var n=e.detail.path;n&&("uninstall"===n.substr(n.lastIndexOf("/")+1)?this.backTapped():this.routeDataChanged(this.routeData))}},{key:"routeDataChanged",value:function(e){var n=this;this.routeMatches&&e&&e.slug&&this.hass.callApi("get","hassio/addons/"+e.slug+"/info").then(function(e){n.addon=e.data},function(){n.addon=null})}},{key:"backTapped",value:function(){history.back()}},{key:"openMarkdown",value:function(e){this.setProperties({markdownTitle:e.detail.title,markdownContent:e.detail.content}),this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog()}}],[{key:"template",get:function(){return Object(o.a)(te)}},{key:"properties",get:function(){return{hass:Object,showMenu:Boolean,narrow:Boolean,route:Object,routeData:{type:Object,observer:"routeDataChanged"},routeMatches:Boolean,addon:Object,markdownTitle:String,markdownContent:{type:String,value:""}}}}]),n}();customElements.define("hassio-addon-view",oe);var ae=function(){function e(e,n){for(var t=0;t1&&void 0!==arguments[1]&&arguments[1]?history.replaceState(null,null,e):history.pushState(null,null,e),this.fire("location-changed")}}]),t}()}),le=function(){function e(e,n){for(var t=0;t\n paper-card {\n cursor: pointer;\n }\n a.repo {\n display: block;\n color: var(--primary-text-color);\n }\n \n \n'],{raw:{value:Object.freeze(['\n \n \n'])}})),ce=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ie(a.a)),le(n,[{key:"sortAddons",value:function(e,n){return e.name\n .add {\n padding: 12px 16px;\n }\n iron-icon {\n color: var(--secondary-text-color);\n margin-right: 16px;\n display: inline-block;\n }\n paper-input {\n width: calc(100% - 49px);\n display: inline-block;\n }\n \n
\n
\n Repositories\n
\n Configure which add-on repositories to fetch data from:\n
\n
\n \n \n
\n \n \n
\n
\n Add\n
\n
\n
\n'],{raw:{value:Object.freeze(['\n \n
\n
\n Repositories\n
\n Configure which add-on repositories to fetch data from:\n
\n
\n \n \n
\n \n \n
\n
\n Add\n
\n
\n
\n'])}})),he=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),de(n,[{key:"reposChanged",value:function(e){this.repoList=e.filter(function(e){return"core"!==e.slug&&"local"!==e.slug}),this.repoUrl=""}},{key:"sortRepos",value:function(e,n){return e.name\n hassio-addon-repository {\n margin-top: 24px;\n }\n \n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n'])}})),me=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),fe(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)}),this.loadData()}},{key:"apiCalled",value:function(e){e.detail.success&&this.loadData()}},{key:"sortRepos",value:function(e,n){return"local"===e.slug?-1:"local"===n.slug?1:"core"===e.slug?-1:"core"===n.slug?1:e.name\n paper-card {\n cursor: pointer;\n }\n \n
\n
Add-ons
\n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n
Add-ons
\n \n \n
\n'])}})),ge=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ie(a.a)),ye(n,[{key:"sortAddons",value:function(e,n){return e.name\n paper-card {\n display: block;\n margin-bottom: 32px;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n \n \n'],{raw:{value:Object.freeze(['\n \n \n'])}})),_e=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),ke(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===we(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"computeUpdateAvailable",value:function(e){return e.version!==e.last_version}}],[{key:"template",get:function(){return Object(o.a)(Oe)}},{key:"properties",get:function(){return{hass:Object,hassInfo:Object,error:String}}}]),n}();customElements.define("hassio-hass-update",_e);var je=function(){function e(e,n){for(var t=0;t\n .content {\n margin: 0 auto;\n }\n \n
\n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n \n \n
\n'])}})),Se=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),je(n,null,[{key:"template",get:function(){return Object(o.a)(xe)}},{key:"properties",get:function(){return{hass:Object,supervisorInfo:Object,hassInfo:Object}}}]),n}();customElements.define("hassio-dashboard",Se),t(61);var Pe=function(){function e(e,n){for(var t=0;t\n paper-dialog {\n min-width: 350px;\n font-size: 14px;\n border-radius: 2px;\n }\n app-toolbar {\n margin: 0;\n padding: 0 16px;\n color: var(--primary-text-color);\n background-color: var(--secondary-background-color);\n }\n app-toolbar [main-title] {\n margin-left: 16px;\n }\n paper-dialog-scrollable {\n margin: 0;\n }\n paper-checkbox {\n display: block;\n margin: 4px;\n }\n @media all and (max-width: 450px), all and (max-height: 500px) {\n paper-dialog {\n max-height: 100%;\n height: 100%;\n }\n app-toolbar {\n color: var(--text-primary-color);\n background-color: var(--primary-color);\n }\n }\n .details {\n color: var(--secondary-text-color);\n }\n .download {\n color: var(--primary-color);\n }\n .warning,\n .error {\n color: var(--google-red-500);\n }\n \n \n \n \n
[[_computeName(snapshot)]]
\n
\n
\n [[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])
\n [[_formatDatetime(snapshot.date)]]\n
\n
Home Assistant:
\n \n Home Assistant [[snapshot.homeassistant]]\n \n \n \n \n \n
\n \n \n \n \n Restore selected\n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n \n \n
[[_computeName(snapshot)]]
\n
\n
\n [[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])
\n [[_formatDatetime(snapshot.date)]]\n
\n
Home Assistant:
\n \n Home Assistant [[snapshot.homeassistant]]\n \n \n \n \n \n
\n \n \n \n \n Restore selected\n \n
\n
\n'])}})),Ee=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),Pe(n,[{key:"_snapshotSlugChanged",value:function(e){var n=this;e&&"update"!==e&&this.hass.callApi("get","hassio/snapshots/"+e+"/info").then(function(e){e.data.folders=n._computeFolders(e.data.folders),e.data.addons=n._computeAddons(e.data.addons),n.snapshot=e.data,n.$.dialog.open()},function(){n.snapshot=null})}},{key:"_computeFolders",value:function(e){var n=[];return e.includes("homeassistant")&&n.push({slug:"homeassistant",name:"Home Assistant configuration",checked:!0}),e.includes("ssl")&&n.push({slug:"ssl",name:"SSL",checked:!0}),e.includes("share")&&n.push({slug:"share",name:"Share",checked:!0}),e.includes("addons/local")&&n.push({slug:"addons/local",name:"Local add-ons",checked:!0}),n}},{key:"_computeAddons",value:function(e){return e.map(function(e){return{slug:e.slug,name:e.name,version:e.version,checked:!0}})}},{key:"_isFullSnapshot",value:function(e){return"full"===e}},{key:"_partialRestoreClicked",value:function(){var e=this;if(confirm("Are you sure you want to restore this snapshot?")){var n=this.snapshot.addons.filter(function(e){return e.checked}).map(function(e){return e.slug}),t=this.snapshot.folders.filter(function(e){return e.checked}).map(function(e){return e.slug}),o={homeassistant:this.restoreHass,addons:n,folders:t};this.snapshot.protected&&(o.password=this.snapshotPassword),this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/restore/partial",o).then(function(){alert("Snapshot restored!"),e.$.dialog.close()},function(n){e.error=n.body.message})}}},{key:"_fullRestoreClicked",value:function(){var e=this;if(confirm("Are you sure you want to restore this snapshot?")){var n=this.snapshot.protected?{password:this.snapshotPassword}:null;this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/restore/full",n).then(function(){alert("Snapshot restored!"),e.$.dialog.close()},function(n){e.error=n.body.message})}}},{key:"_deleteClicked",value:function(){var e=this;confirm("Are you sure you want to delete this snapshot?")&&this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/remove").then(function(){e.$.dialog.close(),e.snapshotDeleted=!0},function(n){e.error=n.body.message})}},{key:"_computeDownloadUrl",value:function(e){return"/api/hassio/snapshots/"+e+"/download?api_password="+encodeURIComponent(this.hass.connection.options.authToken)}},{key:"_computeDownloadName",value:function(e){return"Hass_io_"+this._computeName(e).replace(/[^a-z0-9]+/gi,"_")+".tar"}},{key:"_computeName",value:function(e){return e.name||e.slug}},{key:"_computeType",value:function(e){return"full"===e?"Full snapshot":"Partial snapshot"}},{key:"_computeSize",value:function(e){return Math.ceil(10*e)/10+" MB"}},{key:"_sortAddons",value:function(e,n){return e.name\n paper-radio-group {\n display: block;\n }\n paper-radio-button {\n padding: 0 0 2px 2px;\n }\n paper-radio-button,\n paper-checkbox,\n paper-input[type="password"] {\n display: block;\n margin: 4px 0 4px 48px;\n }\n .pointer {\n cursor: pointer;\n }\n \n
\n
\n
\n Create snapshot\n
\n Snapshots allow you to easily backup and\n restore all data of your Hass.io instance.\n
\n
\n \n
\n \n Type:\n \n \n Full snapshot\n \n \n Partial snapshot\n \n \n \n Security:\n Password protection\n \n \n
\n
\n Create\n
\n
\n
\n\n
\n
Available snapshots
\n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n
\n
\n
\n Create snapshot\n
\n Snapshots allow you to easily backup and\n restore all data of your Hass.io instance.\n
\n
\n \n
\n \n Type:\n \n \n Full snapshot\n \n \n Partial snapshot\n \n \n \n Security:\n Password protection\n \n \n
\n
\n Create\n
\n
\n
\n\n
\n
Available snapshots
\n \n \n
\n
\n'])}})),De=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),Te(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e._apiCalled(n)}),this._updateSnapshots()}},{key:"_apiCalled",value:function(e){e.detail.success&&this._updateSnapshots()}},{key:"_updateSnapshots",value:function(){var e=this;this.hass.callApi("get","hassio/snapshots").then(function(n){e.snapshots=n.data.snapshots},function(n){e.error=n.message})}},{key:"_createSnapshot",value:function(){var e=this;if(this.error="",!this.snapshotHasPassword||this.snapshotPassword.length){this.creatingSnapshot=!0;var n=this.snapshotName;n.length||(n=(new Date).toLocaleDateString(navigator.language,{weekday:"long",year:"numeric",month:"short",day:"numeric"}));var t=void 0,o=void 0;if("full"===this.snapshotType)t={name:n},o="hassio/snapshots/new/full";else{var a=this.addonList.filter(function(e){return e.checked}).map(function(e){return e.slug});t={name:n,folders:this.folderList.filter(function(e){return e.checked}).map(function(e){return e.slug}),addons:a},o="hassio/snapshots/new/partial"}this.snapshotHasPassword&&(t.password=this.snapshotPassword),this.hass.callApi("post",o,t).then(function(){e.creatingSnapshot=!1,e.fire("hass-api-called",{success:!0})},function(n){e.creatingSnapshot=!1,e.error=n.message})}else this.error="Please enter a password."}},{key:"_installedAddonsChanged",value:function(e){this.addonList=e.map(function(e){return{slug:e.slug,name:e.name,checked:!0}})}},{key:"_sortAddons",value:function(e,n){return e.name\n paper-card {\n display: inline-block;\n width: 400px;\n margin-left: 8px;\n }\n .card-content {\n height: 200px;\n }\n @media screen and (max-width: 830px) {\n paper-card {\n margin-top: 8px;\n margin-left: 0;\n width: 100%;\n }\n .card-content {\n height: 100%;\n }\n }\n .info {\n width: 100%;\n }\n .info td:nth-child(2) {\n text-align: right;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n paper-button.info {\n max-width: calc(50% - 12px);\n }\n \n \n
\n

Host system

\n \n \n \n \n \n \n \n \n \n \n
Hostname[[data.hostname]]
System[[data.operating_system]]
\n \n Hardware\n \n \n \n
\n
\n \n \n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n

Host system

\n \n \n \n \n \n \n \n \n \n \n
Hostname[[data.hostname]]
System[[data.operating_system]]
\n \n Hardware\n \n \n \n
\n
\n \n \n \n \n
\n
\n'])}})),qe=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),Ie(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===Re(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"_dataChanged",value:function(e){var n=this;e.features&&e.features.includes("hassos")?this.hass.callApi("get","hassio/hassos/info").then(function(e){n._hassOs=e.data}):this._hassOs={}}},{key:"_computeUpdateAvailable",value:function(e){return e&&e.version!==e.version_latest}},{key:"_featureAvailable",value:function(e,n){return e&&e.features&&e.features.includes(n)}},{key:"_showHardware",value:function(){var e=this;this.hass.callApi("get","hassio/hardware/info").then(function(n){return e._objectToMarkdown(n.data)},function(){return"Error getting hardware info"}).then(function(n){e.fire("hassio-markdown-dialog",{title:"Hardware",content:n})})}},{key:"_objectToMarkdown",value:function(e){var n=this,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o="";return Object.keys(e).forEach(function(a){"object"!==Re(e[a])?o+=t+"- "+a+": "+e[a]+"\n":(o+=t+"- "+a+":\n",Array.isArray(e[a])?e[a].length&&(o+=t+" - "+e[a].join("\n"+t+" - ")+"\n"):o+=n._objectToMarkdown(e[a]," "+t))}),o}},{key:"_changeHostnameClicked",value:function(){var e=this.data.hostname,n=prompt("Please enter a new hostname:",e);n&&n!==e&&this.hass.callApi("post","hassio/host/options",{hostname:n})}}],[{key:"template",get:function(){return Object(o.a)(ze)}},{key:"properties",get:function(){return{hass:Object,data:{type:Object,observer:"_dataChanged"},errors:String,_hassOs:Object}}}]),n}();customElements.define("hassio-host-info",qe);var Le="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},He=function(){function e(e,n){for(var t=0;t\n paper-card {\n display: inline-block;\n width: 400px;\n }\n .card-content {\n height: 200px;\n }\n @media screen and (max-width: 830px) {\n paper-card {\n width: 100%;\n }\n .card-content {\n height: 100%;\n }\n }\n .info {\n width: 100%;\n }\n .info td:nth-child(2) {\n text-align: right;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n \n \n
\n

Hass.io supervisor

\n \n \n \n \n \n \n \n \n \n \n
Version\n [[data.version]]\n
Latest version[[data.last_version]]
\n \n
\n
\n Reload\n \n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n

Hass.io supervisor

\n \n \n \n \n \n \n \n \n \n \n
Version\n [[data.version]]\n
Latest version[[data.last_version]]
\n \n
\n
\n Reload\n \n \n \n
\n
\n'])}})),Ue=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,i(a.a)),He(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===Le(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"computeUpdateAvailable",value:function(e){return e.version!==e.last_version}},{key:"_equals",value:function(e,n){return e===n}},{key:"_joinBeta",value:function(){var e=this;if(confirm("WARNING:\nBeta releases are for testers and early adopters and can contain unstable code changes. Make sure you have backups of your data before you activate this feature.\n\nThis inludes beta releases for:\n- Home Assistant (Release Candidates)\n- Hass.io supervisor\n- Host system")){var n="hassio/supervisor/options",t={channel:"beta"},o={method:"post",path:n,data:t};this.hass.callApi("post",n,t).then(function(e){o.success=!0,o.response=e},function(e){o.success=!1,o.response=e}).then(function(){e.fire("hass-api-called",o)})}}}],[{key:"template",get:function(){return Object(o.a)(Me)}},{key:"properties",get:function(){return{hass:Object,data:Object,errors:String,leaveBeta:{type:Object,value:{channel:"stable"}}}}}]),n}();customElements.define("hassio-supervisor-info",Ue);var Be=function(){function e(e,n){for(var t=0;t\n paper-card {\n display: block;\n }\n pre {\n overflow-x: auto;\n }\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'])}})),Ne=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),Be(n,[{key:"ready",value:function(){(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.loadData()}},{key:"loadData",value:function(){var e=this;this.hass.callApi("get","hassio/supervisor/logs").then(function(n){e.log=n},function(){e.log="Error fetching logs"})}},{key:"refreshTapped",value:function(){this.loadData()}}],[{key:"template",get:function(){return Object(o.a)(Fe)}},{key:"properties",get:function(){return{hass:Object,log:String}}}]),n}();customElements.define("hassio-supervisor-log",Ne);var $e=function(){function e(e,n){for(var t=0;t\n .content {\n margin: 4px;\n }\n .title {\n margin-top: 24px;\n color: var(--primary-text-color);\n font-size: 2em;\n padding-left: 8px;\n margin-bottom: 8px;\n }\n \n
\n
Information
\n \n \n
System log
\n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n
Information
\n \n \n
System log
\n \n
\n'])}})),Ye=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,a.a),$e(n,null,[{key:"template",get:function(){return Object(o.a)(We)}},{key:"properties",get:function(){return{hass:Object,supervisorInfo:Object,hostInfo:Object}}}]),n}();customElements.define("hassio-system",Ye);var Je=function(){function e(e,n){for(var t=0;t\n :host {\n color: var(--primary-text-color);\n --paper-card-header-color: var(--primary-text-color);\n }\n paper-tabs {\n margin-left: 12px;\n --paper-tabs-selection-bar-color: #FFF;\n text-transform: uppercase;\n }\n \n \n \n \n \n
Hass.io
\n \n
\n \n Dashboard\n Snapshots\n Add-on store\n System\n \n
\n \n \n \n \n
\n\n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n \n \n \n
Hass.io
\n \n
\n \n Dashboard\n Snapshots\n Add-on store\n System\n \n
\n \n \n \n \n
\n\n \n\n \n'])}})),Ve=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ie(a.a)),Je(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hassio-markdown-dialog",function(n){return e.openMarkdown(n)})}},{key:"handlePageSelected",value:function(e){var n,t,o,a,r,s,i,l=e.detail.item.getAttribute("page-name");l!==this.page&&this.navigate("/hassio/"+l),n=this,t=this.$.layout.header.scrollTarget,o=t,a=Math.random(),r=Date.now(),s=o.scrollTop,i=0-s,n._currentAnimationId=a,function e(){var t,l=Date.now()-r;l>200?o.scrollTop=0:n._currentAnimationId===a&&(o.scrollTop=(t=l,-i*(t/=200)*(t-2)+s),requestAnimationFrame(e.bind(n)))}.call(n)}},{key:"equals",value:function(e,n){return e===n}},{key:"showRefreshButton",value:function(e){return"store"===e||"snapshots"===e}},{key:"refreshClicked",value:function(){"snapshots"===this.page?this.shadowRoot.querySelector("hassio-snapshots").refreshData():this.shadowRoot.querySelector("hassio-addon-store").refreshData()}},{key:"openMarkdown",value:function(e){this.setProperties({markdownTitle:e.detail.title,markdownContent:e.detail.content}),this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog()}}],[{key:"template",get:function(){return Object(o.a)(Ge)}},{key:"properties",get:function(){return{hass:Object,showMenu:Boolean,narrow:Boolean,page:String,supervisorInfo:Object,hostInfo:Object,hassInfo:Object,snapshotSlug:String,snapshotDeleted:Boolean,markdownTitle:String,markdownContent:{type:String,value:""}}}}]),n}();customElements.define("hassio-pages-with-tabs",Ve);var Xe=function(){function e(e,n){for(var t=0;t\n \n\n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n\n \n'])}})),Ze=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ie(a.a)),Xe(n,[{key:"ready",value:function(){var e=this;Ke(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),function(e,n,t){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];e._themes||(e._themes={});var a=n.default_theme;("default"===t||t&&n.themes[t])&&(a=t);var r=Object.assign({},e._themes);if("default"!==a){var s=n.themes[a];Object.keys(s).forEach(function(n){var t="--"+n;e._themes[t]="",r[t]=s[n]})}if(e.updateStyles?e.updateStyles(r):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,r),o){var i=document.querySelector("meta[name=theme-color]");if(i){i.hasAttribute("default-content")||i.setAttribute("default-content",i.getAttribute("content"));var l=r["--primary-color"]||i.getAttribute("default-content");i.setAttribute("content",l)}}}(this,this.hass.themes,this.hass.selectedTheme,!0),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"connectedCallback",value:function(){Ke(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"connectedCallback",this).call(this),this.routeChanged(this.route)}},{key:"apiCalled",value:function(e){var n=this;if(e.detail.success){var t=1;!function e(){n.$.data.refresh().catch(function(){t+=1,setTimeout(e,1e3*Math.min(t,5))})}()}}},{key:"computeIsLoaded",value:function(e,n,t){return null!==e&&null!==n&&null!==t}},{key:"routeChanged",value:function(e){""===e.path&&"/hassio"===e.prefix&&this.navigate("/hassio/dashboard",!0)}},{key:"equalsAddon",value:function(e){return e&&"addon"===e}}],[{key:"template",get:function(){return Object(o.a)(Qe)}},{key:"properties",get:function(){return{hass:Object,narrow:Boolean,showMenu:Boolean,route:{type:Object,value:{prefix:"/hassio",path:"/dashboard",__queryParams:{}},observer:"routeChanged"},routeData:Object,supervisorInfo:Object,hostInfo:Object,hassInfo:Object,loaded:{type:Boolean,computed:"computeIsLoaded(supervisorInfo, hostInfo, hassInfo)"}}}}]),n}();customElements.define("hassio-main",Ze)},25:function(e,n){var t=document.createElement("template");t.setAttribute("style","display: none;"),t.innerHTML='\n \n',document.head.appendChild(t.content)}}]); \ No newline at end of file diff --git a/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js.gz b/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js.gz deleted file mode 100644 index 68abb0644..000000000 Binary files a/hassio/api/panel/chunk.0ef4ef1053fe3d5107b5.js.gz and /dev/null differ diff --git a/hassio/api/panel/chunk.457ac71b0904d7243237.js b/hassio/api/panel/chunk.457ac71b0904d7243237.js new file mode 100644 index 000000000..f0f03e081 --- /dev/null +++ b/hassio/api/panel/chunk.457ac71b0904d7243237.js @@ -0,0 +1,2 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{2:function(e,t,n){"use strict";n.r(t),n(36);var C=function(){function e(e,t){for(var n=0;n this.fire('iron-iconset-added', this, { node: window }));\n }\n\n /**\n *\n * When name is changed, register iconset metadata\n *\n */\n _nameChanged() {\n this._meta.value = null;\n this._meta.key = this.name;\n this._meta.value = this;\n if (this.ownerDocument && this.ownerDocument.readyState === 'loading') {\n // Document still loading. It could be that not all icons in the iconset are parsed yet.\n this.ownerDocument.addEventListener('DOMContentLoaded', () => {\n this._fireIronIconsetAdded();\n });\n } else {\n this._fireIronIconsetAdded();\n }\n }\n}\n\ncustomElements.define('ha-iconset-svg', HaIconset);\n","export default \"\";","import '../../../src/components/ha-iconset-svg.js';\nimport iconSetContent from '../../hassio-icons.html';\n\nconst documentContainer = document.createElement('template');\ndocumentContainer.setAttribute('style', 'display: none;');\ndocumentContainer.innerHTML = iconSetContent;\ndocument.head.appendChild(documentContainer.content);\n"],"sourceRoot":""} \ No newline at end of file diff --git a/hassio/api/panel/chunk.57f5b43a82b988080555.js b/hassio/api/panel/chunk.57f5b43a82b988080555.js new file mode 100644 index 000000000..d321b04d4 --- /dev/null +++ b/hassio/api/panel/chunk.57f5b43a82b988080555.js @@ -0,0 +1,2 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{1:function(e,n,t){"use strict";t.r(n),t(58);var o,a,r=t(4),s=t(6),i=(t(28),t(59),t(80),t(20),t(10)),l=function(){function e(e,n){for(var t=0;t\n'],a=['\n \n'],Object.freeze(Object.defineProperties(o,{raw:{value:Object.freeze(a)}}))),u=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),c(n,[{key:"toggleMenu",value:function(e){e.stopPropagation(),this.fire(this.showMenu?"hass-close-menu":"hass-open-menu")}},{key:"_getIcon",value:function(e){return(e?"hassio":"hass")+":menu"}}],[{key:"template",get:function(){return Object(r.a)(d)}},{key:"properties",get:function(){return{narrow:{type:Boolean,value:!1},showMenu:{type:Boolean,value:!1},hassio:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-menu-button",u);var h=function(){function e(e,n){for(var t=0;t\n .placeholder {\n height: 100%;\n }\n\n .layout {\n height: calc(100% - 64px);\n }\n \n\n
\n \n \n
[[title]]
\n
\n
\n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n\n
\n \n \n
[[title]]
\n
\n
\n \n
\n
\n'])}})),b=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),h(n,null,[{key:"template",get:function(){return Object(r.a)(f)}},{key:"properties",get:function(){return{narrow:{type:Boolean,value:!1},showMenu:{type:Boolean,value:!1},title:{type:String,value:""}}}}]),n}();customElements.define("hass-loading-screen",b),t(61),t(76),t(83),t(3);var m=document.createElement("template");m.setAttribute("style","display: none;"),m.innerHTML='\n \n\n \n\n \n\n \n',document.head.appendChild(m.content),t(63),t(78);var y=function(){function e(e,n){for(var t=0;t=0?n:null}:null}),e._resize();for(var n=document.createTreeWalker(e,1,null,!1);n.nextNode();){var t=n.currentNode;"A"===t.tagName&&t.host!==document.location.host?t.target="_blank":"IMG"===t.tagName&&t.addEventListener("load",e._resize)}}else 2===e._scriptLoaded&&(e.innerText=e.content)}))}}],[{key:"properties",get:function(){return{content:{type:String,observer:"_render"},allowSvg:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-markdown",w);var k=function(){function e(e,n){for(var t=0;t\n paper-dialog {\n min-width: 350px;\n font-size: 14px;\n border-radius: 2px;\n }\n app-toolbar {\n margin: 0;\n padding: 0 16px;\n color: var(--primary-text-color);\n background-color: var(--secondary-background-color);\n }\n app-toolbar [main-title] {\n margin-left: 16px;\n }\n paper-checkbox {\n display: block;\n margin: 4px;\n }\n @media all and (max-width: 450px), all and (max-height: 500px) {\n paper-dialog {\n max-height: 100%;\n }\n paper-dialog::before {\n content: "";\n position: fixed;\n z-index: -1;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n background-color: inherit;\n }\n app-toolbar {\n color: var(--text-primary-color);\n background-color: var(--primary-color);\n }\n }\n \n \n \n \n
[[title]]
\n
\n \n \n \n
\n'],{raw:{value:Object.freeze(['\n \n \n \n \n
[[title]]
\n
\n \n \n \n
\n'])}})),O=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),k(n,[{key:"openDialog",value:function(){this.$.dialog.open()}}],[{key:"template",get:function(){return Object(r.a)(_)}},{key:"properties",get:function(){return{title:String,content:String}}}]),n}();customElements.define("hassio-markdown-dialog",O),t(84),t(13),t(12),t(97),t(99),t(85);var j=function(){function e(e,n){for(var t=0;t\n :host,\n paper-card,\n paper-dropdown-menu {\n display: block;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n paper-item {\n width: 450px;\n }\n .card-actions {\n text-align: right;\n }\n \n \n
\n \n\n \n \n \n \n \n \n \n \n \n \n
\n
\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n\n \n \n \n \n \n \n \n \n \n \n
\n
\n Save\n
\n
\n'])}})),S=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),j(n,[{key:"addonChanged",value:function(e){var n=this;if(this.setProperties({selectedInput:e.audio_input||"null",selectedOutput:e.audio_output||"null"}),!this.outputDevices){var t=[{device:"null",name:"-"}];this.hass.callApi("get","hassio/hardware/audio").then(function(e){var o=e.data.audio,a=Object.keys(o.input).map(function(e){return{device:e,name:o.input[e]}}),r=Object.keys(o.output).map(function(e){return{device:e,name:o.output[e]}});n.setProperties({inputDevices:t.concat(a),outputDevices:t.concat(r)})},function(){n.setProperties({inputDevices:t,outputDevices:t})})}}},{key:"_saveSettings",value:function(){var e=this;this.error=null;var n="hassio/addons/"+this.addon.slug+"/options";this.hass.callApi("post",n,{audio_input:"null"===this.selectedInput?null:this.selectedInput,audio_output:"null"===this.selectedOutput?null:this.selectedOutput}).then(function(){e.fire("hass-api-called",{success:!0,path:n})},function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(r.a)(x)}},{key:"properties",get:function(){return{hass:Object,addon:{type:Object,observer:"addonChanged"},inputDevices:Array,outputDevices:Array,selectedInput:String,selectedOutput:String,error:String}}}]),n}();customElements.define("hassio-addon-audio",S),t(86);var P=function(){function e(e,n){for(var t=0;t\n .container {\n position: relative;\n display: inline-block;\n }\n\n paper-button {\n transition: all 1s;\n }\n\n .success paper-button {\n color: white;\n background-color: var(--google-green-500);\n transition: none;\n }\n\n .error paper-button {\n color: white;\n background-color: var(--google-red-500);\n transition: none;\n }\n\n paper-button[disabled] {\n color: #c8c8c8;\n }\n\n .progress {\n @apply --layout;\n @apply --layout-center-center;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n \n
\n \n \n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n \n \n \n \n
\n'])}})),E=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),P(n,[{key:"tempClass",value:function(e){var n=this.$.container.classList;n.add(e),setTimeout(function(){n.remove(e)},1e3)}},{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("click",function(n){return e.buttonTapped(n)})}},{key:"buttonTapped",value:function(e){this.progress&&e.stopPropagation()}},{key:"actionSuccess",value:function(){this.tempClass("success")}},{key:"actionError",value:function(){this.tempClass("error")}},{key:"computeDisabled",value:function(e,n){return e||n}}],[{key:"template",get:function(){return Object(r.a)(C)}},{key:"properties",get:function(){return{hass:{type:Object},progress:{type:Boolean,value:!1},disabled:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-progress-button",E);var T=function(){function e(e,n){for(var t=0;t\n'],{raw:{value:Object.freeze(['\n \n'])}})),D=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),T(n,[{key:"buttonTapped",value:function(){var e=this;this.progress=!0;var n={method:this.method,path:this.path,data:this.data};this.hass.callApi(this.method,this.path,this.data).then(function(t){e.progress=!1,e.$.progress.actionSuccess(),n.success=!0,n.response=t},function(t){e.progress=!1,e.$.progress.actionError(),n.success=!1,n.response=t}).then(function(){e.fire("hass-api-called",n)})}}],[{key:"template",get:function(){return Object(r.a)(A)}},{key:"properties",get:function(){return{hass:Object,progress:{type:Boolean,value:!1},path:String,method:{type:String,value:"POST"},data:{type:Object,value:{}},disabled:{type:Boolean,value:!1}}}}]),n}();customElements.define("ha-call-api-button",D);var R=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n }\n .card-actions {\n @apply --layout;\n @apply --layout-justified;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n iron-autogrow-textarea {\n width: 100%;\n font-family: monospace;\n }\n .syntaxerror {\n color: var(--google-red-500);\n }\n \n \n
\n \n \n
\n
\n Reset to defaults\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n \n
\n
\n Reset to defaults\n Save\n
\n
\n'])}})),z=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),R(n,[{key:"addonChanged",value:function(e){this.config=e?JSON.stringify(e.options,null,2):""}},{key:"configChanged",value:function(e){try{this.$.config.classList.remove("syntaxerror"),this.configParsed=JSON.parse(e)}catch(e){this.$.config.classList.add("syntaxerror"),this.configParsed=null}}},{key:"saveTapped",value:function(){var e=this;this.error=null,this.hass.callApi("post","hassio/addons/"+this.addonSlug+"/options",{options:this.configParsed}).catch(function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(r.a)(I)}},{key:"properties",get:function(){return{hass:Object,addon:{type:Object,observer:"addonChanged"},addonSlug:String,config:{type:String,observer:"configChanged"},configParsed:Object,error:String,resetData:{type:Object,value:{options:null}}}}}]),n}();customElements.define("hassio-addon-config",z),t(21),t(87);var q=t(7),L=[60,"second",60,"minute",24,"hour",7,"day"],H=t(57),U=(t(101),t(98)),B={__localizationCache:{requests:{},messages:{},ajax:null},properties:{language:{type:String},resources:{type:Object},formats:{type:Object,value:function(){return{}}},useKeyIfMissing:{type:Boolean,value:!1},localize:{type:Function,computed:"__computeLocalize(language, resources, formats)"},bubbleEvent:{type:Boolean,value:!1}},loadResources:function(e,n,t){var o=this.constructor.prototype;this.__checkLocalizationCache(o);var a,r=o.__localizationCache.ajax;function s(e){this.__onRequestResponse(e,n,t)}r||(r=o.__localizationCache.ajax=document.createElement("iron-ajax")),(a=o.__localizationCache.requests[e])?a.completes.then(s.bind(this),this.__onRequestError.bind(this)):(r.url=e,(a=r.generateRequest()).completes.then(s.bind(this),this.__onRequestError.bind(this)),o.__localizationCache.requests[e]=a)},__computeLocalize:function(e,n,t){var o=this.constructor.prototype;return this.__checkLocalizationCache(o),o.__localizationCache||(o.__localizationCache={requests:{},messages:{},ajax:null}),o.__localizationCache.messages={},function(){var a=arguments[0];if(a&&n&&e&&n[e]){var r=n[e][a];if(!r)return this.useKeyIfMissing?a:"";var s=a+r,i=o.__localizationCache.messages[s];i||(i=new U.a(r,e,t),o.__localizationCache.messages[s]=i);for(var l={},p=1;p=0?"past":"future";t=Math.abs(t);for(var a=0;a\n iron-icon {\n margin-right: 16px;\n margin-top: 16px;\n float: left;\n color: var(--secondary-text-color);\n }\n iron-icon.update {\n color: var(--paper-orange-400);\n }\n iron-icon.running,\n iron-icon.installed {\n color: var(--paper-green-400);\n }\n iron-icon.hassupdate,\n iron-icon.snapshot {\n color: var(--paper-item-icon-color);\n }\n .title {\n color: var(--primary-text-color);\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n .addition {\n color: var(--secondary-text-color);\n overflow: hidden;\n position: relative;\n height: 2.4em;\n line-height: 1.2em;\n }\n ha-relative-time {\n display: block;\n }\n \n \n
\n
[[title]]
\n
\n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[title]]
\n
\n \n \n
\n
\n'])}})),G=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),Y(n,null,[{key:"template",get:function(){return Object(r.a)(J)}},{key:"properties",get:function(){return{hass:Object,title:String,description:String,datetime:String,icon:{type:String,value:"hass:help-circle"},iconTitle:String,iconClass:String}}}]),n}();customElements.define("hassio-card-content",G);var V=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n margin-bottom: 16px;\n }\n .addon-header {\n @apply --paper-font-headline;\n }\n .light-color {\n color: var(--secondary-text-color);\n }\n .addon-version {\n float: right;\n font-size: 15px;\n vertical-align: middle;\n }\n .description {\n margin-bottom: 16px;\n }\n .logo img {\n max-height: 60px;\n margin: 16px 0;\n display: block;\n }\n .state div{\n width: 150px;\n display: inline-block;\n }\n paper-toggle-button {\n display: inline;\n }\n iron-icon.running {\n color: var(--paper-green-400);\n }\n iron-icon.stopped {\n color: var(--google-red-300);\n }\n ha-call-api-button {\n font-weight: 500;\n color: var(--primary-color);\n }\n .right {\n float: right;\n }\n ha-markdown img {\n max-width: 100%;\n }\n \n \n\n \n
\n
[[addon.name]]\n
\n \n \n
\n
\n
\n [[addon.description]].
\n Visit [[addon.name]] page for details.\n
\n \n \n
\n
\n \n \n
\n
\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n
\n
[[addon.name]]\n
\n \n \n
\n
\n
\n [[addon.description]].
\n Visit [[addon.name]] page for details.\n
\n \n \n
\n
\n \n \n
\n
\n \n'])}})),K=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),V(n,[{key:"computeIsRunning",value:function(e){return e&&"started"===e.state}},{key:"computeUpdateAvailable",value:function(e){return e&&!e.detached&&e.version&&e.version!==e.last_version}},{key:"pathWebui",value:function(e){return e&&e.replace("[HOST]",document.location.hostname)}},{key:"computeShowWebUI",value:function(e,n){return e&&n}},{key:"computeStartOnBoot",value:function(e){return"auto"===e}},{key:"startOnBootToggled",value:function(){var e={boot:"auto"===this.addon.boot?"manual":"auto"};this.hass.callApi("POST","hassio/addons/"+this.addonSlug+"/options",e)}},{key:"autoUpdateToggled",value:function(){var e={auto_update:!this.addon.auto_update};this.hass.callApi("POST","hassio/addons/"+this.addonSlug+"/options",e)}},{key:"openChangelog",value:function(){var e=this;this.hass.callApi("get","hassio/addons/"+this.addonSlug+"/changelog").then(function(e){return e},function(){return"Error getting changelog"}).then(function(n){e.fire("hassio-markdown-dialog",{title:"Changelog",content:n})})}},{key:"_unistallClicked",value:function(){var e=this;if(confirm("Are you sure you want to uninstall this add-on?")){var n="hassio/addons/"+this.addonSlug+"/uninstall",t={path:n};this.hass.callApi("post",n).then(function(e){t.success=!0,t.response=e},function(e){t.success=!1,t.response=e}).then(function(){e.fire("hass-api-called",t)})}}}],[{key:"template",get:function(){return Object(r.a)(X)}},{key:"properties",get:function(){return{hass:Object,addon:Object,addonSlug:String,isRunning:{type:Boolean,computed:"computeIsRunning(addon)"}}}}]),n}();customElements.define("hassio-addon-info",K);var Q=function(){function e(e,n){for(var t=0;t\n :host,\n paper-card {\n display: block;\n }\n pre {\n overflow-x: auto;\n }\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'])}})),ee=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),Q(n,[{key:"addonSlugChanged",value:function(e){var n=this;this.hass?this.refresh():setTimeout(function(){n.addonChanged(e)},0)}},{key:"refresh",value:function(){var e=this;this.hass.callApi("get","hassio/addons/"+this.addonSlug+"/logs").then(function(n){e.log=n})}}],[{key:"template",get:function(){return Object(r.a)(Z)}},{key:"properties",get:function(){return{hass:Object,addonSlug:{type:String,observer:"addonSlugChanged"},log:String}}}]),n}();customElements.define("hassio-addon-logs",ee),t(31);var ne=function(){function e(e,n){for(var t=0;t\n :host {\n display: block;\n }\n paper-card {\n display: block;\n }\n .errors {\n color: var(--google-red-500);\n margin-bottom: 16px;\n }\n .card-actions {\n @apply --layout;\n @apply --layout-justified;\n }\n \n \n
\n \n\n \n \n \n \n \n \n
ContainerHost
\n
\n
\n Reset to defaults\n Save\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n \n\n \n \n \n \n \n \n
ContainerHost
\n
\n
\n Reset to defaults\n Save\n
\n
\n'])}})),oe=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),ne(n,[{key:"addonChanged",value:function(e){if(e){var n=e.network||{},t=Object.keys(n).map(function(e){return{container:e,host:n[e]}});this.config=t.sort(function(e,n){return e.host-n.host})}}},{key:"saveTapped",value:function(){var e=this;this.error=null;var n={};this.config.forEach(function(e){n[e.container]=parseInt(e.host)});var t="hassio/addons/"+this.addonSlug+"/options";this.hass.callApi("post",t,{network:n}).then(function(){e.fire("hass-api-called",{success:!0,path:t})},function(n){e.error=n.body.message})}}],[{key:"template",get:function(){return Object(r.a)(te)}},{key:"properties",get:function(){return{hass:Object,addonSlug:String,config:Object,addon:{type:Object,observer:"addonChanged"},error:String,resetData:{type:Object,value:{network:null}}}}}]),n}();customElements.define("hassio-addon-network",oe);var ae=function(){function e(e,n){for(var t=0;t\n :host {\n color: var(--primary-text-color);\n --paper-card-header-color: var(--primary-text-color);\n }\n .content {\n padding: 24px 0 32px;\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n hassio-addon-info,\n hassio-addon-network,\n hassio-addon-audio,\n hassio-addon-config {\n margin-bottom: 24px;\n width: 600px;\n }\n hassio-addon-logs {\n max-width: calc(100% - 8px);\n min-width: 600px;\n }\n @media only screen and (max-width: 600px) {\n hassio-addon-info,\n hassio-addon-network,\n hassio-addon-audio,\n hassio-addon-config,\n hassio-addon-logs {\n max-width: 100%;\n min-width: 100%;\n }\n }\n \n \n \n \n \n \n \n
Hass.io: add-on details
\n
\n
\n
\n \n\n \n
\n
\n\n \n'],{raw:{value:Object.freeze(['\n \n \n \n \n \n \n \n
Hass.io: add-on details
\n
\n
\n
\n \n\n \n
\n
\n\n \n'])}})),se=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),ae(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)}),this.addEventListener("hassio-markdown-dialog",function(n){return e.openMarkdown(n)})}},{key:"apiCalled",value:function(e){var n=e.detail.path;n&&("uninstall"===n.substr(n.lastIndexOf("/")+1)?this.backTapped():this.routeDataChanged(this.routeData))}},{key:"routeDataChanged",value:function(e){var n=this;this.routeMatches&&e&&e.slug&&this.hass.callApi("get","hassio/addons/"+e.slug+"/info").then(function(e){n.addon=e.data},function(){n.addon=null})}},{key:"backTapped",value:function(){history.back()}},{key:"openMarkdown",value:function(e){this.setProperties({markdownTitle:e.detail.title,markdownContent:e.detail.content}),this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog()}}],[{key:"template",get:function(){return Object(r.a)(re)}},{key:"properties",get:function(){return{hass:Object,showMenu:Boolean,narrow:Boolean,route:Object,routeData:{type:Object,observer:"routeDataChanged"},routeMatches:Boolean,addon:Object,markdownTitle:String,markdownContent:{type:String,value:""}}}}]),n}();customElements.define("hassio-addon-view",se);var ie=function(){function e(e,n){for(var t=0;t1&&void 0!==arguments[1]&&arguments[1]?history.replaceState(null,null,e):history.pushState(null,null,e),this.fire("location-changed")}}]),t}()}),de=function(){function e(e,n){for(var t=0;t\n paper-card {\n cursor: pointer;\n }\n a.repo {\n display: block;\n color: var(--primary-text-color);\n }\n \n \n'],{raw:{value:Object.freeze(['\n \n \n'])}})),he=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ce(s.a)),de(n,[{key:"sortAddons",value:function(e,n){return e.name\n .add {\n padding: 12px 16px;\n }\n iron-icon {\n color: var(--secondary-text-color);\n margin-right: 16px;\n display: inline-block;\n }\n paper-input {\n width: calc(100% - 49px);\n display: inline-block;\n }\n \n
\n
\n Repositories\n
\n Configure which add-on repositories to fetch data from:\n
\n
\n \n \n
\n \n \n
\n
\n Add\n
\n
\n
\n'],{raw:{value:Object.freeze(['\n \n
\n
\n Repositories\n
\n Configure which add-on repositories to fetch data from:\n
\n
\n \n \n
\n \n \n
\n
\n Add\n
\n
\n
\n'])}})),me=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),fe(n,[{key:"reposChanged",value:function(e){this.repoList=e.filter(function(e){return"core"!==e.slug&&"local"!==e.slug}),this.repoUrl=""}},{key:"sortRepos",value:function(e,n){return e.name\n hassio-addon-repository {\n margin-top: 24px;\n }\n \n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n'])}})),ge=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),ye(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)}),this.loadData()}},{key:"apiCalled",value:function(e){e.detail.success&&this.loadData()}},{key:"sortRepos",value:function(e,n){return"local"===e.slug?-1:"local"===n.slug?1:"core"===e.slug?-1:"core"===n.slug?1:e.name\n paper-card {\n cursor: pointer;\n }\n \n
\n
Add-ons
\n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n
Add-ons
\n \n \n
\n'])}})),_e=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ce(s.a)),we(n,[{key:"sortAddons",value:function(e,n){return e.name\n paper-card {\n display: block;\n margin-bottom: 32px;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n \n \n'],{raw:{value:Object.freeze(['\n \n \n'])}})),Se=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),je(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===Oe(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"computeUpdateAvailable",value:function(e){return e.version!==e.last_version}}],[{key:"template",get:function(){return Object(r.a)(xe)}},{key:"properties",get:function(){return{hass:Object,hassInfo:Object,error:String}}}]),n}();customElements.define("hassio-hass-update",Se);var Pe=function(){function e(e,n){for(var t=0;t\n .content {\n margin: 0 auto;\n }\n \n
\n \n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n \n \n
\n'])}})),Ee=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),Pe(n,null,[{key:"template",get:function(){return Object(r.a)(Ce)}},{key:"properties",get:function(){return{hass:Object,supervisorInfo:Object,hassInfo:Object}}}]),n}();customElements.define("hassio-dashboard",Ee),t(68);var Te=function(){function e(e,n){for(var t=0;t\n paper-dialog {\n min-width: 350px;\n font-size: 14px;\n border-radius: 2px;\n }\n app-toolbar {\n margin: 0;\n padding: 0 16px;\n color: var(--primary-text-color);\n background-color: var(--secondary-background-color);\n }\n app-toolbar [main-title] {\n margin-left: 16px;\n }\n paper-dialog-scrollable {\n margin: 0;\n }\n paper-checkbox {\n display: block;\n margin: 4px;\n }\n @media all and (max-width: 450px), all and (max-height: 500px) {\n paper-dialog {\n max-height: 100%;\n height: 100%;\n }\n app-toolbar {\n color: var(--text-primary-color);\n background-color: var(--primary-color);\n }\n }\n .details {\n color: var(--secondary-text-color);\n }\n .download {\n color: var(--primary-color);\n }\n .warning,\n .error {\n color: var(--google-red-500);\n }\n \n \n \n \n
[[_computeName(snapshot)]]
\n
\n
\n [[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])
\n [[_formatDatetime(snapshot.date)]]\n
\n
Home Assistant:
\n \n Home Assistant [[snapshot.homeassistant]]\n \n \n \n \n \n
\n \n \n \n \n Restore selected\n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n \n \n
[[_computeName(snapshot)]]
\n
\n
\n [[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])
\n [[_formatDatetime(snapshot.date)]]\n
\n
Home Assistant:
\n \n Home Assistant [[snapshot.homeassistant]]\n \n \n \n \n \n
\n \n \n \n \n Restore selected\n \n
\n
\n'])}})),De=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),Te(n,[{key:"_snapshotSlugChanged",value:function(e){var n=this;e&&"update"!==e&&this.hass.callApi("get","hassio/snapshots/"+e+"/info").then(function(e){e.data.folders=n._computeFolders(e.data.folders),e.data.addons=n._computeAddons(e.data.addons),n.snapshot=e.data,n.$.dialog.open()},function(){n.snapshot=null})}},{key:"_computeFolders",value:function(e){var n=[];return e.includes("homeassistant")&&n.push({slug:"homeassistant",name:"Home Assistant configuration",checked:!0}),e.includes("ssl")&&n.push({slug:"ssl",name:"SSL",checked:!0}),e.includes("share")&&n.push({slug:"share",name:"Share",checked:!0}),e.includes("addons/local")&&n.push({slug:"addons/local",name:"Local add-ons",checked:!0}),n}},{key:"_computeAddons",value:function(e){return e.map(function(e){return{slug:e.slug,name:e.name,version:e.version,checked:!0}})}},{key:"_isFullSnapshot",value:function(e){return"full"===e}},{key:"_partialRestoreClicked",value:function(){var e=this;if(confirm("Are you sure you want to restore this snapshot?")){var n=this.snapshot.addons.filter(function(e){return e.checked}).map(function(e){return e.slug}),t=this.snapshot.folders.filter(function(e){return e.checked}).map(function(e){return e.slug}),o={homeassistant:this.restoreHass,addons:n,folders:t};this.snapshot.protected&&(o.password=this.snapshotPassword),this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/restore/partial",o).then(function(){alert("Snapshot restored!"),e.$.dialog.close()},function(n){e.error=n.body.message})}}},{key:"_fullRestoreClicked",value:function(){var e=this;if(confirm("Are you sure you want to restore this snapshot?")){var n=this.snapshot.protected?{password:this.snapshotPassword}:null;this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/restore/full",n).then(function(){alert("Snapshot restored!"),e.$.dialog.close()},function(n){e.error=n.body.message})}}},{key:"_deleteClicked",value:function(){var e=this;confirm("Are you sure you want to delete this snapshot?")&&this.hass.callApi("post","hassio/snapshots/"+this.snapshotSlug+"/remove").then(function(){e.$.dialog.close(),e.snapshotDeleted=!0},function(n){e.error=n.body.message})}},{key:"_computeDownloadUrl",value:function(e){return"/api/hassio/snapshots/"+e+"/download?api_password="+encodeURIComponent(this.hass.connection.options.authToken)}},{key:"_computeDownloadName",value:function(e){return"Hass_io_"+this._computeName(e).replace(/[^a-z0-9]+/gi,"_")+".tar"}},{key:"_computeName",value:function(e){return e.name||e.slug}},{key:"_computeType",value:function(e){return"full"===e?"Full snapshot":"Partial snapshot"}},{key:"_computeSize",value:function(e){return Math.ceil(10*e)/10+" MB"}},{key:"_sortAddons",value:function(e,n){return e.name\n paper-radio-group {\n display: block;\n }\n paper-radio-button {\n padding: 0 0 2px 2px;\n }\n paper-radio-button,\n paper-checkbox,\n paper-input[type="password"] {\n display: block;\n margin: 4px 0 4px 48px;\n }\n .pointer {\n cursor: pointer;\n }\n \n
\n
\n
\n Create snapshot\n
\n Snapshots allow you to easily backup and\n restore all data of your Hass.io instance.\n
\n
\n \n
\n \n Type:\n \n \n Full snapshot\n \n \n Partial snapshot\n \n \n \n Security:\n Password protection\n \n \n
\n
\n Create\n
\n
\n
\n\n
\n
Available snapshots
\n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n
\n
\n
\n Create snapshot\n
\n Snapshots allow you to easily backup and\n restore all data of your Hass.io instance.\n
\n
\n \n
\n \n Type:\n \n \n Full snapshot\n \n \n Partial snapshot\n \n \n \n Security:\n Password protection\n \n \n
\n
\n Create\n
\n
\n
\n\n
\n
Available snapshots
\n \n \n
\n
\n'])}})),ze=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),Re(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e._apiCalled(n)}),this._updateSnapshots()}},{key:"_apiCalled",value:function(e){e.detail.success&&this._updateSnapshots()}},{key:"_updateSnapshots",value:function(){var e=this;this.hass.callApi("get","hassio/snapshots").then(function(n){e.snapshots=n.data.snapshots},function(n){e.error=n.message})}},{key:"_createSnapshot",value:function(){var e=this;if(this.error="",!this.snapshotHasPassword||this.snapshotPassword.length){this.creatingSnapshot=!0;var n=this.snapshotName;n.length||(n=(new Date).toLocaleDateString(navigator.language,{weekday:"long",year:"numeric",month:"short",day:"numeric"}));var t=void 0,o=void 0;if("full"===this.snapshotType)t={name:n},o="hassio/snapshots/new/full";else{var a=this.addonList.filter(function(e){return e.checked}).map(function(e){return e.slug});t={name:n,folders:this.folderList.filter(function(e){return e.checked}).map(function(e){return e.slug}),addons:a},o="hassio/snapshots/new/partial"}this.snapshotHasPassword&&(t.password=this.snapshotPassword),this.hass.callApi("post",o,t).then(function(){e.creatingSnapshot=!1,e.fire("hass-api-called",{success:!0})},function(n){e.creatingSnapshot=!1,e.error=n.message})}else this.error="Please enter a password."}},{key:"_installedAddonsChanged",value:function(e){this.addonList=e.map(function(e){return{slug:e.slug,name:e.name,checked:!0}})}},{key:"_sortAddons",value:function(e,n){return e.name\n paper-card {\n display: inline-block;\n width: 400px;\n margin-left: 8px;\n }\n .card-content {\n height: 200px;\n color: var(--primary-text-color);\n }\n @media screen and (max-width: 830px) {\n paper-card {\n margin-top: 8px;\n margin-left: 0;\n width: 100%;\n }\n .card-content {\n height: 100%;\n }\n }\n .info {\n width: 100%;\n }\n .info td:nth-child(2) {\n text-align: right;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n paper-button.info {\n max-width: calc(50% - 12px);\n }\n \n \n
\n

Host system

\n \n \n \n \n \n \n \n \n \n \n
Hostname[[data.hostname]]
System[[data.operating_system]]
\n \n Hardware\n \n \n \n
\n
\n \n \n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n

Host system

\n \n \n \n \n \n \n \n \n \n \n
Hostname[[data.hostname]]
System[[data.operating_system]]
\n \n Hardware\n \n \n \n
\n
\n \n \n \n \n
\n
\n'])}})),Ue=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),Le(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===qe(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"_dataChanged",value:function(e){var n=this;e.features&&e.features.includes("hassos")?this.hass.callApi("get","hassio/hassos/info").then(function(e){n._hassOs=e.data}):this._hassOs={}}},{key:"_computeUpdateAvailable",value:function(e){return e&&e.version!==e.version_latest}},{key:"_featureAvailable",value:function(e,n){return e&&e.features&&e.features.includes(n)}},{key:"_showHardware",value:function(){var e=this;this.hass.callApi("get","hassio/hardware/info").then(function(n){return e._objectToMarkdown(n.data)},function(){return"Error getting hardware info"}).then(function(n){e.fire("hassio-markdown-dialog",{title:"Hardware",content:n})})}},{key:"_objectToMarkdown",value:function(e){var n=this,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o="";return Object.keys(e).forEach(function(a){"object"!==qe(e[a])?o+=t+"- "+a+": "+e[a]+"\n":(o+=t+"- "+a+":\n",Array.isArray(e[a])?e[a].length&&(o+=t+" - "+e[a].join("\n"+t+" - ")+"\n"):o+=n._objectToMarkdown(e[a]," "+t))}),o}},{key:"_changeHostnameClicked",value:function(){var e=this.data.hostname,n=prompt("Please enter a new hostname:",e);n&&n!==e&&this.hass.callApi("post","hassio/host/options",{hostname:n})}}],[{key:"template",get:function(){return Object(r.a)(He)}},{key:"properties",get:function(){return{hass:Object,data:{type:Object,observer:"_dataChanged"},errors:String,_hassOs:Object}}}]),n}();customElements.define("hassio-host-info",Ue);var Be="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Me=function(){function e(e,n){for(var t=0;t\n paper-card {\n display: inline-block;\n width: 400px;\n }\n .card-content {\n height: 200px;\n color: var(--primary-text-color);\n }\n @media screen and (max-width: 830px) {\n paper-card {\n width: 100%;\n }\n .card-content {\n height: 100%;\n }\n }\n .info {\n width: 100%;\n }\n .info td:nth-child(2) {\n text-align: right;\n }\n .errors {\n color: var(--google-red-500);\n margin-top: 16px;\n }\n \n \n
\n

Hass.io supervisor

\n \n \n \n \n \n \n \n \n \n \n
Version\n [[data.version]]\n
Latest version[[data.last_version]]
\n \n
\n
\n Reload\n \n \n \n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n

Hass.io supervisor

\n \n \n \n \n \n \n \n \n \n \n
Version\n [[data.version]]\n
Latest version[[data.last_version]]
\n \n
\n
\n Reload\n \n \n \n
\n
\n'])}})),Ne=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(s.a)),Me(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"apiCalled",value:function(e){if(e.detail.success)this.errors=null;else{var n=e.detail.response;"object"===Be(n.body)?this.errors=n.body.message||"Unknown error":this.errors=n.body}}},{key:"computeUpdateAvailable",value:function(e){return e.version!==e.last_version}},{key:"_equals",value:function(e,n){return e===n}},{key:"_joinBeta",value:function(){var e=this;if(confirm("WARNING:\nBeta releases are for testers and early adopters and can contain unstable code changes. Make sure you have backups of your data before you activate this feature.\n\nThis inludes beta releases for:\n- Home Assistant (Release Candidates)\n- Hass.io supervisor\n- Host system")){var n="hassio/supervisor/options",t={channel:"beta"},o={method:"post",path:n,data:t};this.hass.callApi("post",n,t).then(function(e){o.success=!0,o.response=e},function(e){o.success=!1,o.response=e}).then(function(){e.fire("hass-api-called",o)})}}}],[{key:"template",get:function(){return Object(r.a)(Fe)}},{key:"properties",get:function(){return{hass:Object,data:Object,errors:String,leaveBeta:{type:Object,value:{channel:"stable"}}}}}]),n}();customElements.define("hassio-supervisor-info",Ne);var $e=function(){function e(e,n){for(var t=0;t\n paper-card {\n display: block;\n }\n pre {\n overflow-x: auto;\n }\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'],{raw:{value:Object.freeze(['\n \n \n
\n
[[log]]
\n
\n
\n Refresh\n
\n
\n'])}})),Ye=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),$e(n,[{key:"ready",value:function(){(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.loadData()}},{key:"loadData",value:function(){var e=this;this.hass.callApi("get","hassio/supervisor/logs").then(function(n){e.log=n},function(){e.log="Error fetching logs"})}},{key:"refreshTapped",value:function(){this.loadData()}}],[{key:"template",get:function(){return Object(r.a)(We)}},{key:"properties",get:function(){return{hass:Object,log:String}}}]),n}();customElements.define("hassio-supervisor-log",Ye);var Je=function(){function e(e,n){for(var t=0;t\n .content {\n margin: 4px;\n }\n .title {\n margin-top: 24px;\n color: var(--primary-text-color);\n font-size: 2em;\n padding-left: 8px;\n margin-bottom: 8px;\n }\n \n
\n
Information
\n \n \n
System log
\n \n
\n'],{raw:{value:Object.freeze(['\n \n
\n
Information
\n \n \n
System log
\n \n
\n'])}})),Ve=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,s.a),Je(n,null,[{key:"template",get:function(){return Object(r.a)(Ge)}},{key:"properties",get:function(){return{hass:Object,supervisorInfo:Object,hostInfo:Object}}}]),n}();customElements.define("hassio-system",Ve);var Xe=function(){function e(e,n){for(var t=0;t\n :host {\n color: var(--primary-text-color);\n --paper-card-header-color: var(--primary-text-color);\n }\n paper-tabs {\n margin-left: 12px;\n --paper-tabs-selection-bar-color: #FFF;\n text-transform: uppercase;\n }\n \n \n \n \n \n
Hass.io
\n \n
\n \n Dashboard\n Snapshots\n Add-on store\n System\n \n
\n \n \n \n \n
\n\n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n \n \n \n
Hass.io
\n \n
\n \n Dashboard\n Snapshots\n Add-on store\n System\n \n
\n \n \n \n \n
\n\n \n\n \n'])}})),Qe=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,ce(s.a)),Xe(n,[{key:"ready",value:function(){var e=this;(function e(n,t,o){null===n&&(n=Function.prototype);var a=Object.getOwnPropertyDescriptor(n,t);if(void 0===a){var r=Object.getPrototypeOf(n);return null===r?void 0:e(r,t,o)}if("value"in a)return a.value;var s=a.get;return void 0!==s?s.call(o):void 0})(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),this.addEventListener("hassio-markdown-dialog",function(n){return e.openMarkdown(n)})}},{key:"handlePageSelected",value:function(e){var n,t,o,a,r,s,i,l=e.detail.item.getAttribute("page-name");l!==this.page&&this.navigate("/hassio/"+l),n=this,t=this.$.layout.header.scrollTarget,o=t,a=Math.random(),r=Date.now(),s=o.scrollTop,i=0-s,n._currentAnimationId=a,function e(){var t,l=Date.now()-r;l>200?o.scrollTop=0:n._currentAnimationId===a&&(o.scrollTop=(t=l,-i*(t/=200)*(t-2)+s),requestAnimationFrame(e.bind(n)))}.call(n)}},{key:"equals",value:function(e,n){return e===n}},{key:"showRefreshButton",value:function(e){return"store"===e||"snapshots"===e}},{key:"refreshClicked",value:function(){"snapshots"===this.page?this.shadowRoot.querySelector("hassio-snapshots").refreshData():this.shadowRoot.querySelector("hassio-addon-store").refreshData()}},{key:"openMarkdown",value:function(e){this.setProperties({markdownTitle:e.detail.title,markdownContent:e.detail.content}),this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog()}}],[{key:"template",get:function(){return Object(r.a)(Ke)}},{key:"properties",get:function(){return{hass:Object,showMenu:Boolean,narrow:Boolean,page:String,supervisorInfo:Object,hostInfo:Object,hassInfo:Object,snapshotSlug:String,snapshotDeleted:Boolean,markdownTitle:String,markdownContent:{type:String,value:""}}}}]),n}();customElements.define("hassio-pages-with-tabs",Qe);var Ze=function(){function e(e,n){for(var t=0;t\n \n\n \n\n \n'],{raw:{value:Object.freeze(['\n \n \n\n \n\n \n'])}})),tn=function(e){function n(){return function(e,t){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this),function(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}(this,(n.__proto__||Object.getPrototypeOf(n)).apply(this,arguments))}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}(n,p(ce(s.a))),Ze(n,[{key:"ready",value:function(){var e=this;en(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"ready",this).call(this),function(e,n,t){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];e._themes||(e._themes={});var a=n.default_theme;("default"===t||t&&n.themes[t])&&(a=t);var r=Object.assign({},e._themes);if("default"!==a){var s=n.themes[a];Object.keys(s).forEach(function(n){var t="--"+n;e._themes[t]="",r[t]=s[n]})}if(e.updateStyles?e.updateStyles(r):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,r),o){var i=document.querySelector("meta[name=theme-color]");if(i){i.hasAttribute("default-content")||i.setAttribute("default-content",i.getAttribute("content"));var l=r["--primary-color"]||i.getAttribute("default-content");i.setAttribute("content",l)}}}(this,this.hass.themes,this.hass.selectedTheme,!0),this.addEventListener("hass-api-called",function(n){return e.apiCalled(n)})}},{key:"connectedCallback",value:function(){en(n.prototype.__proto__||Object.getPrototypeOf(n.prototype),"connectedCallback",this).call(this),this.routeChanged(this.route)}},{key:"apiCalled",value:function(e){var n=this;if(e.detail.success){var t=1;!function e(){n.$.data.refresh().catch(function(){t+=1,setTimeout(e,1e3*Math.min(t,5))})}()}}},{key:"computeIsLoaded",value:function(e,n,t){return null!==e&&null!==n&&null!==t}},{key:"routeChanged",value:function(e){""===e.path&&"/hassio"===e.prefix&&this.navigate("/hassio/dashboard",!0),this.fire("iron-resize")}},{key:"equalsAddon",value:function(e){return e&&"addon"===e}}],[{key:"template",get:function(){return Object(r.a)(nn)}},{key:"properties",get:function(){return{hass:Object,narrow:Boolean,showMenu:Boolean,route:{type:Object,value:{prefix:"/hassio",path:"/dashboard",__queryParams:{}},observer:"routeChanged"},routeData:Object,supervisorInfo:Object,hostInfo:Object,hassInfo:Object,loaded:{type:Boolean,computed:"computeIsLoaded(supervisorInfo, hostInfo, hassInfo)"}}}}]),n}();customElements.define("hassio-main",tn)},30:function(e,n){var t=document.createElement("template");t.setAttribute("style","display: none;"),t.innerHTML='\n \n',document.head.appendChild(t.content)}}]); +//# sourceMappingURL=chunk.57f5b43a82b988080555.js.map \ No newline at end of file diff --git a/hassio/api/panel/chunk.57f5b43a82b988080555.js.gz b/hassio/api/panel/chunk.57f5b43a82b988080555.js.gz new file mode 100644 index 000000000..1c46c036b Binary files /dev/null and b/hassio/api/panel/chunk.57f5b43a82b988080555.js.gz differ diff --git a/hassio/api/panel/chunk.57f5b43a82b988080555.js.map b/hassio/api/panel/chunk.57f5b43a82b988080555.js.map new file mode 100644 index 000000000..20d4f13b1 --- /dev/null +++ b/hassio/api/panel/chunk.57f5b43a82b988080555.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///../src/mixins/events-mixin.js","webpack:///../src/common/dom/fire_event.js","webpack:///../src/components/ha-menu-button.js","webpack:///../src/layouts/hass-loading-screen.js","webpack:///../src/resources/ha-style.js","webpack:///../src/components/ha-markdown.js","webpack:///./src/hassio-markdown-dialog.js","webpack:///./src/addon-view/hassio-addon-audio.js","webpack:///../src/components/buttons/ha-progress-button.js","webpack:///../src/components/buttons/ha-call-api-button.js","webpack:///./src/addon-view/hassio-addon-config.js","webpack:///../src/common/datetime/relative_time.js","webpack:///../src/util/app-localize-behavior.js","webpack:///../src/mixins/localize-mixin.js","webpack:///../src/components/ha-relative-time.js","webpack:///./src/components/hassio-card-content.js","webpack:///./src/addon-view/hassio-addon-info.js","webpack:///./src/addon-view/hassio-addon-logs.js","webpack:///./src/addon-view/hassio-addon-network.js","webpack:///./src/addon-view/hassio-addon-view.js","webpack:///./src/hassio-data.js","webpack:///../src/mixins/navigate-mixin.js","webpack:///./src/addon-store/hassio-addon-repository.js","webpack:///./src/addon-store/hassio-repositories-editor.js","webpack:///./src/addon-store/hassio-addon-store.js","webpack:///./src/dashboard/hassio-addons.js","webpack:///./src/dashboard/hassio-hass-update.js","webpack:///./src/dashboard/hassio-dashboard.js","webpack:///./src/snapshots/hassio-snapshot.js","webpack:///./src/snapshots/hassio-snapshots.js","webpack:///./src/system/hassio-host-info.js","webpack:///./src/system/hassio-supervisor-info.js","webpack:///./src/system/hassio-supervisor-log.js","webpack:///./src/system/hassio-system.js","webpack:///./src/hassio-pages-with-tabs.js","webpack:///../src/common/dom/scroll-to-target.js","webpack:///./src/hassio-main.js","webpack:///../src/common/dom/apply_themes_on_element.js","webpack:///./src/resources/hassio-style.js"],"names":["strings","raw","events_mixin","Object","mixin","a","superClass","_superClass","_class","instance","Constructor","TypeError","this","__proto__","getPrototypeOf","apply","arguments","subClass","prototype","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","_createClass","key","type","detail","options","node","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","ha_menu_button_createClass","defineProperties","target","props","i","length","descriptor","defineProperty","protoProps","staticProps","_templateObject","freeze","ha_menu_button_HaMenuButton","polymer_element","HaMenuButton","ev","stopPropagation","fire","showMenu","hassio","get","html_tag","narrow","customElements","define","hass_loading_screen_HassLoadingScreen","hass_loading_screen_createClass","HassLoadingScreen","hass_loading_screen_templateObject","title","String","documentContainer","document","createElement","setAttribute","innerHTML","head","appendChild","content","loaded","svgWhiteList","HaMarkdown","ha_markdown_createClass","_this2","call","_scriptLoaded","_renderScheduled","_resize","Promise","all","__webpack_require__","e","then","bind","_ref","marked","filterXSS","_render","_this3","resolve","gfm","tables","breaks","onIgnoreTag","allowSvg","tag","html","indexOf","walker","createTreeWalker","nextNode","currentNode","tagName","host","location","addEventListener","innerText","observer","hassio_markdown_dialog_HassioMarkdownDialog","hassio_markdown_dialog_createClass","HassioMarkdownDialog","$","dialog","open","hassio_markdown_dialog_templateObject","hassio_addon_audio_HassioAddonAudio","hassio_addon_audio_createClass","HassioAddonAudio","addon","setProperties","selectedInput","audio_input","selectedOutput","audio_output","outputDevices","noDevice","device","name","hass","callApi","resp","dev","data","audio","input","keys","map","output","inputDevices","concat","error","path","slug","success","body","message","hassio_addon_audio_templateObject","Array","ha_progress_button_HaProgressButton","ha_progress_button_createClass","HaProgressButton","className","classList","container","add","setTimeout","remove","buttonTapped","progress","tempClass","disabled","ha_progress_button_templateObject","ha_call_api_button_HaCallApiButton","ha_call_api_button_createClass","HaCallApiButton","eventData","method","actionSuccess","response","actionError","ha_call_api_button_templateObject","hassio_addon_config_HassioAddonConfig","hassio_addon_config_createClass","HassioAddonConfig","config","JSON","stringify","configParsed","parse","err","addonSlug","catch","hassio_addon_config_templateObject","resetData","tests","legacy_class","main","AppLocalizeBehavior","__localizationCache","requests","messages","ajax","properties","language","resources","formats","useKeyIfMissing","localize","Function","computed","bubbleEvent","loadResources","merge","proto","__checkLocalizationCache","request","onRequestResponse","__onRequestResponse","completes","__onRequestError","url","generateRequest","__computeLocalize","translatedValue","messageKey","translatedMessage","args","format","propertyUpdates","newResources","assign","set","localize_mixin_createClass","localize_mixin","_mixinBehaviors","ha_relative_time_get","object","property","receiver","desc","getOwnPropertyDescriptor","parent","getter","ha_relative_time_createClass","ha_relative_time_HaRelativeTime","HaRelativeTime","_this","updateRelative","datetime","datetimeObj","parsedDateTime","updateInterval","setInterval","clearInterval","newVal","Date","root","polymer_dom","dateObj","delta","tense","Math","abs","floor","hassio_card_content_HassioCardContent","hassio_card_content_createClass","HassioCardContent","hassio_card_content_templateObject","description","icon","iconTitle","iconClass","hassio_addon_info_HassioAddonInfo","hassio_addon_info_createClass","HassioAddonInfo","state","detached","version","last_version","webui","replace","hostname","isRunning","boot","auto_update","confirm","hassio_addon_info_templateObject","hassio_addon_logs_HassioAddonLogs","hassio_addon_logs_createClass","HassioAddonLogs","refresh","addonChanged","info","log","hassio_addon_logs_templateObject","hassio_addon_network_HassioAddonNetwork","hassio_addon_network_createClass","HassioAddonNetwork","network","items","sort","el1","el2","forEach","item","parseInt","hassio_addon_network_templateObject","hassio_addon_view_HassioAddonView","hassio_addon_view_createClass","HassioAddonView","apiCalled","openMarkdown","substr","lastIndexOf","backTapped","routeDataChanged","routeData","routeMatches","history","back","markdownTitle","markdownContent","shadowRoot","querySelector","openDialog","hassio_addon_view_templateObject","route","HassioData","hassio_data_createClass","fetchSupervisorInfo","fetchHostInfo","fetchHassInfo","supervisor","_this4","homeassistant","notify","navigate_mixin","_EventsMixin","navigate_mixin_createClass","replaceState","pushState","hassio_addon_repository_createClass","hassio_addon_repository_templateObject","hassio_addon_repository_HassioAddonRepository","HassioAddonRepository","b","installed","navigate","model","repo","addons","hassio_repositories_editor_HassioRepositoriesEditor","hassio_repositories_editor_createClass","HassioRepositoriesEditor","repos","repoList","filter","repoUrl","addons_repositories","list","push","hassio_repositories_editor_templateObject","hassio_addon_store_HassioAddonStore","hassio_addon_store_createClass","HassioAddonStore","loadData","repository","repositories","hassio_addon_store_templateObject","hassio_addons_HassioAddons","hassio_addons_createClass","HassioAddons","blur","hassio_addons_templateObject","hassio_hass_update_HassioHassUpdate","hassio_hass_update_createClass","HassioHassUpdate","errors","_typeof","hassInfo","hassio_hass_update_templateObject","hassio_dashboard_HassioDashboard","hassio_dashboard_createClass","HassioDashboard","hassio_dashboard_templateObject","supervisorInfo","hassio_snapshot_HassioSnapshot","hassio_snapshot_createClass","HassioSnapshot","snapshotSlug","folders","_computeFolders","_computeAddons","snapshot","includes","checked","folder","restoreHass","protected","password","snapshotPassword","alert","close","_this5","snapshotDeleted","encodeURIComponent","connection","authToken","_computeName","size","ceil","toLocaleDateString","navigator","weekday","year","month","day","hour","minute","hassio_snapshot_templateObject","hassio_snapshots_HassioSnapshots","hassio_snapshots_createClass","HassioSnapshots","_apiCalled","_updateSnapshots","result","snapshots","snapshotHasPassword","creatingSnapshot","snapshotName","snapshotType","addonList","folderList","date","hassio_snapshots_templateObject","installedAddons","dialogOpened","hassio_host_info_HassioHostInfo","hassio_host_info_createClass","HassioHostInfo","hassio_host_info_typeof","features","_hassOs","version_latest","feature","_objectToMarkdown","obj","indent","isArray","join","curHostname","prompt","hassio_host_info_templateObject","hassio_supervisor_info_HassioSupervisorInfo","hassio_supervisor_info_createClass","HassioSupervisorInfo","hassio_supervisor_info_typeof","channel","hassio_supervisor_info_templateObject","leaveBeta","hassio_supervisor_log_HassioSupervisorLog","hassio_supervisor_log_createClass","HassioSupervisorLog","hassio_supervisor_log_templateObject","hassio_system_HassioSystem","hassio_system_createClass","HassioSystem","hassio_system_templateObject","hostInfo","hassio_pages_with_tabs_HassioPagesWithTabs","hassio_pages_with_tabs_createClass","HassioPagesWithTabs","element","scroller","animationId","startTime","currentScrollTop","deltaScrollTop","newPage","getAttribute","page","layout","header","scrollTarget","random","now","scrollTop","_currentAnimationId","updateFrame","t","elapsedTime","requestAnimationFrame","refreshData","hassio_pages_with_tabs_templateObject","hassio_main_HassioMain","hassio_main_createClass","HassioMain","hassio_main_get","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","prefixedKey","updateStyles","window","ShadyCSS","styleSubtree","meta","hasAttribute","themeColor","selectedTheme","routeChanged","tries","tryUpdate","min","prefix","hassio_main_templateObject","__queryParams"],"mappings":"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","file":"chunk.57f5b43a82b988080555.js","sourcesContent":["import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';\n\nimport fireEvent from '../common/dom/fire_event.js';\n\n// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n/* @polymerMixin */\nexport default dedupingMixin(superClass => class extends superClass {\n /**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n cancelable: (boolean|undefined),\n composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\n fire(type, detail, options) {\n options = options || {};\n return fireEvent(options.node || this, type, detail, options);\n }\n});\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n cancelable: (boolean|undefined),\n composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport default function fire(node, type, detail, options) {\n options = options || {};\n detail = (detail === null || detail === undefined) ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n event.detail = detail;\n node.dispatchEvent(event);\n return event;\n}\n","import '@polymer/paper-icon-button/paper-icon-button.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nimport EventsMixin from '../mixins/events-mixin.js';\n\n/*\n * @appliesMixin EventsMixin\n */\nclass HaMenuButton extends EventsMixin(PolymerElement) {\n static get template() {\n return html`\n \n`;\n }\n\n static get properties() {\n return {\n narrow: {\n type: Boolean,\n value: false,\n },\n\n showMenu: {\n type: Boolean,\n value: false,\n },\n\n hassio: {\n type: Boolean,\n value: false,\n }\n };\n }\n\n toggleMenu(ev) {\n ev.stopPropagation();\n this.fire(this.showMenu ? 'hass-close-menu' : 'hass-open-menu');\n }\n\n _getIcon(hassio) {\n // hass:menu\n return `${hassio ? 'hassio' : 'hass'}:menu`;\n }\n}\n\ncustomElements.define('ha-menu-button', HaMenuButton);\n","import '@polymer/app-layout/app-toolbar/app-toolbar.js';\nimport '@polymer/iron-flex-layout/iron-flex-layout-classes.js';\nimport '@polymer/paper-spinner/paper-spinner.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nimport '../components/ha-menu-button.js';\n\nclass HassLoadingScreen extends PolymerElement {\n static get template() {\n return html`\n \n\n
\n \n \n
[[title]]
\n
\n
\n \n
\n
\n`;\n }\n\n static get properties() {\n return {\n narrow: {\n type: Boolean,\n value: false,\n },\n\n showMenu: {\n type: Boolean,\n value: false,\n },\n\n title: {\n type: String,\n value: '',\n },\n };\n }\n}\n\ncustomElements.define('hass-loading-screen', HassLoadingScreen);\n","import '@polymer/paper-styles/paper-styles.js';\nimport '@polymer/polymer/polymer-legacy.js';\n\nconst documentContainer = document.createElement('template');\ndocumentContainer.setAttribute('style', 'display: none;');\n\ndocumentContainer.innerHTML = `\n \n\n \n\n \n\n \n`;\n\ndocument.head.appendChild(documentContainer.content);\n","import { PolymerElement } from '@polymer/polymer/polymer-element.js';\nimport EventsMixin from '../mixins/events-mixin.js';\n\nlet loaded = null;\n\n/**\n * White list allowed svg tag.\n * Only put in the tag used in QR code, can be extend in future.\n */\nconst svgWhiteList = ['svg', 'path'];\n\n/*\n * @appliesMixin EventsMixin\n */\nclass HaMarkdown extends EventsMixin(PolymerElement) {\n static get properties() {\n return {\n content: {\n type: String,\n observer: '_render',\n },\n allowSvg: {\n type: Boolean,\n value: false,\n },\n };\n }\n\n connectedCallback() {\n super.connectedCallback();\n // 0 = not loaded, 1 = success, 2 = error\n this._scriptLoaded = 0;\n this._renderScheduled = false;\n this._resize = () => this.fire('iron-resize');\n\n if (!loaded) {\n loaded = import(/* webpackChunkName: \"load_markdown\" */ '../resources/load_markdown.js');\n }\n loaded.then(\n ({ marked, filterXSS }) => {\n this.marked = marked;\n this.filterXSS = filterXSS;\n this._scriptLoaded = 1;\n },\n () => { this._scriptLoaded = 2; },\n ).then(() => this._render());\n }\n\n _render() {\n if (this._scriptLoaded === 0 || this._renderScheduled) return;\n\n this._renderScheduled = true;\n\n // debounce it to next microtask.\n Promise.resolve().then(() => {\n this._renderScheduled = false;\n\n if (this._scriptLoaded === 1) {\n this.innerHTML = this.filterXSS(this.marked(this.content, {\n gfm: true,\n tables: true,\n breaks: true\n }), {\n onIgnoreTag: this.allowSvg\n ? (tag, html) => (svgWhiteList.indexOf(tag) >= 0 ? html : null)\n : null\n });\n this._resize();\n\n const walker = document.createTreeWalker(this, 1 /* SHOW_ELEMENT */, null, false);\n\n while (walker.nextNode()) {\n const node = walker.currentNode;\n\n // Open external links in a new window\n if (node.tagName === 'A'\n && node.host !== document.location.host) {\n node.target = '_blank';\n\n // Fire a resize event when images loaded to notify content resized\n } else if (node.tagName === 'IMG') {\n node.addEventListener('load', this._resize);\n }\n }\n } else if (this._scriptLoaded === 2) {\n this.innerText = this.content;\n }\n });\n }\n}\n\ncustomElements.define('ha-markdown', HaMarkdown);\n","import '@polymer/app-layout/app-toolbar/app-toolbar.js';\nimport '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';\nimport '@polymer/paper-dialog/paper-dialog.js';\nimport '@polymer/paper-icon-button/paper-icon-button.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nimport '../../src/components/ha-markdown.js';\nimport '../../src/resources/ha-style.js';\n\nclass HassioMarkdownDialog extends PolymerElement {\n static get template() {\n return html`\n \n \n \n \n
[[title]]
\n
\n \n \n \n
\n`;\n }\n\n static get properties() {\n return {\n title: String,\n content: String,\n };\n }\n\n openDialog() {\n this.$.dialog.open();\n }\n}\ncustomElements.define('hassio-markdown-dialog', HassioMarkdownDialog);\n","import 'web-animations-js/web-animations-next-lite.min.js';\n\nimport '@polymer/paper-button/paper-button.js';\nimport '@polymer/paper-card/paper-card.js';\nimport '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';\nimport '@polymer/paper-item/paper-item.js';\nimport '@polymer/paper-listbox/paper-listbox.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nimport '../../../src/resources/ha-style.js';\nimport EventsMixin from '../../../src/mixins/events-mixin.js';\n\nclass HassioAddonAudio extends EventsMixin(PolymerElement) {\n static get template() {\n return html`\n \n \n
\n \n\n \n \n \n \n \n \n \n \n \n \n
\n
\n Save\n
\n
\n`;\n }\n\n static get properties() {\n return {\n hass: Object,\n addon: {\n type: Object,\n observer: 'addonChanged'\n },\n inputDevices: Array,\n outputDevices: Array,\n selectedInput: String,\n selectedOutput: String,\n error: String,\n };\n }\n\n addonChanged(addon) {\n this.setProperties({\n selectedInput: addon.audio_input || 'null',\n selectedOutput: addon.audio_output || 'null'\n });\n if (this.outputDevices) return;\n\n const noDevice = [{ device: 'null', name: '-' }];\n this.hass.callApi('get', 'hassio/hardware/audio').then((resp) => {\n const dev = resp.data.audio;\n const input = Object.keys(dev.input).map(key => ({ device: key, name: dev.input[key] }));\n const output = Object.keys(dev.output).map(key => ({ device: key, name: dev.output[key] }));\n this.setProperties({\n inputDevices: noDevice.concat(input),\n outputDevices: noDevice.concat(output)\n });\n }, () => {\n this.setProperties({\n inputDevices: noDevice,\n outputDevices: noDevice\n });\n });\n }\n\n _saveSettings() {\n this.error = null;\n const path = `hassio/addons/${this.addon.slug}/options`;\n this.hass.callApi('post', path, {\n audio_input: this.selectedInput === 'null' ? null : this.selectedInput,\n audio_output: this.selectedOutput === 'null' ? null : this.selectedOutput\n }).then(() => {\n this.fire('hass-api-called', { success: true, path: path });\n }, (resp) => {\n this.error = resp.body.message;\n });\n }\n}\n\ncustomElements.define('hassio-addon-audio', HassioAddonAudio);\n","import '@polymer/paper-button/paper-button.js';\nimport '@polymer/paper-spinner/paper-spinner.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nclass HaProgressButton extends PolymerElement {\n static get template() {\n return html`\n \n
\n \n \n \n \n
\n`;\n }\n\n static get properties() {\n return {\n hass: {\n type: Object,\n },\n\n progress: {\n type: Boolean,\n value: false,\n },\n\n disabled: {\n type: Boolean,\n value: false,\n },\n };\n }\n\n tempClass(className) {\n var classList = this.$.container.classList;\n classList.add(className);\n setTimeout(() => {\n classList.remove(className);\n }, 1000);\n }\n\n ready() {\n super.ready();\n this.addEventListener('click', ev => this.buttonTapped(ev));\n }\n\n buttonTapped(ev) {\n if (this.progress) ev.stopPropagation();\n }\n\n actionSuccess() {\n this.tempClass('success');\n }\n\n actionError() {\n this.tempClass('error');\n }\n\n computeDisabled(disabled, progress) {\n return disabled || progress;\n }\n}\n\ncustomElements.define('ha-progress-button', HaProgressButton);\n","import { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\n\nimport './ha-progress-button.js';\nimport EventsMixin from '../../mixins/events-mixin.js';\n\n/*\n * @appliesMixin EventsMixin\n */\nclass HaCallApiButton extends EventsMixin(PolymerElement) {\n static get template() {\n return html`\n \n`;\n }\n\n static get properties() {\n return {\n hass: Object,\n\n progress: {\n type: Boolean,\n value: false,\n },\n\n path: String,\n\n method: {\n type: String,\n value: 'POST',\n },\n\n data: {\n type: Object,\n value: {},\n },\n\n disabled: {\n type: Boolean,\n value: false,\n },\n };\n }\n\n buttonTapped() {\n this.progress = true;\n const eventData = {\n method: this.method,\n path: this.path,\n data: this.data,\n };\n\n this.hass.callApi(this.method, this.path, this.data)\n .then((resp) => {\n this.progress = false;\n this.$.progress.actionSuccess();\n eventData.success = true;\n eventData.response = resp;\n }, (resp) => {\n this.progress = false;\n this.$.progress.actionError();\n eventData.success = false;\n eventData.response = resp;\n }).then(() => {\n this.fire('hass-api-called', eventData);\n });\n }\n}\n\ncustomElements.define('ha-call-api-button', HaCallApiButton);\n","import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';\nimport '@polymer/paper-button/paper-button.js';\nimport '@polymer/paper-card/paper-card.js';\nimport { html } from '@polymer/polymer/lib/utils/html-tag.js';\nimport { PolymerElement } from '@polymer/polymer/polymer-element.js';\n\nimport '../../../src/components/buttons/ha-call-api-button.js';\n\nclass HassioAddonConfig extends PolymerElement {\n static get template() {\n return html`\n \n \n
\n \n \n
\n
\n Reset to defaults\n Save\n
\n
\n`;\n }\n\n static get properties() {\n return {\n hass: Object,\n addon: {\n type: Object,\n observer: 'addonChanged',\n },\n addonSlug: String,\n config: {\n type: String,\n observer: 'configChanged',\n },\n configParsed: Object,\n error: String,\n resetData: {\n type: Object,\n value: {\n options: null,\n },\n },\n };\n }\n\n addonChanged(addon) {\n this.config = addon ? JSON.stringify(addon.options, null, 2) : '';\n }\n\n configChanged(config) {\n try {\n this.$.config.classList.remove('syntaxerror');\n this.configParsed = JSON.parse(config);\n } catch (err) {\n this.$.config.classList.add('syntaxerror');\n this.configParsed = null;\n }\n }\n\n saveTapped() {\n this.error = null;\n\n this.hass.callApi('post', `hassio/addons/${this.addonSlug}/options`, {\n options: this.configParsed\n }).catch((resp) => {\n this.error = resp.body.message;\n });\n }\n}\n\ncustomElements.define('hassio-addon-config', HassioAddonConfig);\n","/** Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n*/\nconst tests = [\n 60, 'second',\n 60, 'minute',\n 24, 'hour',\n 7, 'day',\n];\n\nexport default function relativeTime(dateObj, localize) {\n let delta = (new Date() - dateObj) / 1000;\n const tense = delta >= 0 ? 'past' : 'future';\n delta = Math.abs(delta);\n\n for (let i = 0; i < tests.length; i += 2) {\n if (delta < tests[i]) {\n delta = Math.floor(delta);\n const time = localize(`ui.components.relative_time.duration.${tests[i + 1]}`, 'count', delta);\n return localize(`ui.components.relative_time.${tense}`, 'time', time);\n }\n\n delta /= tests[i];\n }\n\n delta = Math.floor(delta);\n const time = localize('ui.components.relative_time.duration.week', 'count', delta);\n return localize(`ui.components.relative_time.${tense}`, 'time', time);\n}\n","/* Forked to fix the import of IntlMessageFormat */\n/* eslint-disable */\n/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\nThe complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\nThe complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\nCode distributed by Google as part of the polymer project is also\nsubject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport '@polymer/iron-ajax/iron-ajax.js';\nimport IntlMessageFormat from 'intl-messageformat/src/main.js';\n\n/**\n* `Polymer.AppLocalizeBehavior` wraps the [format.js](http://formatjs.io/) library to\n* help you internationalize your application. Note that if you're on a browser that\n* does not natively support the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)\n* object, you must load the polyfill yourself. An example polyfill can\n* be found [here](https://github.com/andyearnshaw/Intl.js/).\n*\n* `Polymer.AppLocalizeBehavior` supports the same [message-syntax](http://formatjs.io/guides/message-syntax/)\n* of format.js, in its entirety; use the library docs as reference for the\n* available message formats and options.\n*\n* Sample application loading resources from an external file:\n*\n* \n* \n* \n \n \n \n ```\n\n ```js\n import {html} from '@polymer/polymer/lib/utils/html-tag.js';\n import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';\n\n const template = html`\n \n \n
\n
horizontal layout center alignment
\n
\n `;\n document.body.appendChild(template.content);\n ```\n\n2. [Custom CSS\nmixins](https://github.com/PolymerElements/iron-flex-layout/blob/master/iron-flex-layout.html).\nThe mixin stylesheet includes custom CSS mixins that can be applied inside a CSS\nrule using the `@apply` function.\n\nPlease note that the old [/deep/ layout\nclasses](https://github.com/PolymerElements/iron-flex-layout/tree/master/classes)\nare deprecated, and should not be used. To continue using layout properties\ndirectly in markup, please switch to using the new `dom-module`-based\n[layout\nclasses](https://github.com/PolymerElements/iron-flex-layout/tree/master/iron-flex-layout-classes.html).\nPlease note that the new version does not use `/deep/`, and therefore requires\nyou to import the `dom-modules` in every element that needs to use them.\n\n@group Iron Elements\n@pseudoElement iron-flex-layout\n@demo demo/index.html\n*/\nconst template = html`\n\n \n\n\n \n`;\n\ntemplate.setAttribute('style', 'display: none;');\ndocument.head.appendChild(template.content);\n\nvar style = document.createElement('style');\nstyle.textContent = '[hidden] { display: none !important; }';\ndocument.head.appendChild(style);\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\n/* Taken from\n * https://www.google.com/design/spec/style/color.html#color-ui-color-application\n */\nimport '@polymer/polymer/polymer-legacy.js';\nimport './color.js';\n\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nconst template = html`\n\n \n`;\ntemplate.setAttribute('style', 'display: none;');\ndocument.head.appendChild(template.content);\n","/**\n@license\nCopyright (c) 2016 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt\nThe complete set of authors may be found at http://polymer.github.io/AUTHORS.txt\nThe complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt\nCode distributed by Google as part of the polymer project is also\nsubject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nimport {resolveUrl} from '@polymer/polymer/lib/utils/resolve-url.js';\n\n/**\n`iron-image` is an element for displaying an image that provides useful sizing and\npreloading options not found on the standard `` tag.\n\nThe `sizing` option allows the image to be either cropped (`cover`) or\nletterboxed (`contain`) to fill a fixed user-size placed on the element.\n\nThe `preload` option prevents the browser from rendering the image until the\nimage is fully loaded. In the interim, either the element's CSS `background-color`\ncan be be used as the placeholder, or the `placeholder` property can be\nset to a URL (preferably a data-URI, for instant rendering) for an\nplaceholder image.\n\nThe `fade` option (only valid when `preload` is set) will cause the placeholder\nimage/color to be faded out once the image is rendered.\n\nExamples:\n\n Basically identical to `` tag:\n\n \n\n Will letterbox the image to fit:\n\n \n\n Will crop the image to fit:\n\n \n\n Will show light-gray background until the image loads:\n\n \n\n Will show a base-64 encoded placeholder image until the image loads:\n\n \n\n Will fade the light-gray background out once the image is loaded:\n\n \n\nCustom property | Description | Default\n----------------|-------------|----------\n`--iron-image-placeholder` | Mixin applied to #placeholder | `{}`\n`--iron-image-width` | Sets the width of the wrapped image | `auto`\n`--iron-image-height` | Sets the height of the wrapped image | `auto`\n\n@group Iron Elements\n@element iron-image\n@demo demo/index.html\n*/\nPolymer({\n _template: html`\n \n\n \n
\n \n
\n`,\n\n is: 'iron-image',\n\n properties: {\n /**\n * The URL of an image.\n */\n src: {type: String, value: ''},\n\n /**\n * A short text alternative for the image.\n */\n alt: {type: String, value: null},\n\n /**\n * CORS enabled images support:\n * https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image\n */\n crossorigin: {type: String, value: null},\n\n /**\n * When true, the image is prevented from loading and any placeholder is\n * shown. This may be useful when a binding to the src property is known to\n * be invalid, to prevent 404 requests.\n */\n preventLoad: {type: Boolean, value: false},\n\n /**\n * Sets a sizing option for the image. Valid values are `contain` (full\n * aspect ratio of the image is contained within the element and\n * letterboxed) or `cover` (image is cropped in order to fully cover the\n * bounds of the element), or `null` (default: image takes natural size).\n */\n sizing: {type: String, value: null, reflectToAttribute: true},\n\n /**\n * When a sizing option is used (`cover` or `contain`), this determines\n * how the image is aligned within the element bounds.\n */\n position: {type: String, value: 'center'},\n\n /**\n * When `true`, any change to the `src` property will cause the\n * `placeholder` image to be shown until the new image has loaded.\n */\n preload: {type: Boolean, value: false},\n\n /**\n * This image will be used as a background/placeholder until the src image\n * has loaded. Use of a data-URI for placeholder is encouraged for instant\n * rendering.\n */\n placeholder: {type: String, value: null, observer: '_placeholderChanged'},\n\n /**\n * When `preload` is true, setting `fade` to true will cause the image to\n * fade into place.\n */\n fade: {type: Boolean, value: false},\n\n /**\n * Read-only value that is true when the image is loaded.\n */\n loaded: {notify: true, readOnly: true, type: Boolean, value: false},\n\n /**\n * Read-only value that tracks the loading state of the image when the\n * `preload` option is used.\n */\n loading: {notify: true, readOnly: true, type: Boolean, value: false},\n\n /**\n * Read-only value that indicates that the last set `src` failed to load.\n */\n error: {notify: true, readOnly: true, type: Boolean, value: false},\n\n /**\n * Can be used to set the width of image (e.g. via binding); size may also\n * be set via CSS.\n */\n width: {observer: '_widthChanged', type: Number, value: null},\n\n /**\n * Can be used to set the height of image (e.g. via binding); size may also\n * be set via CSS.\n *\n * @attribute height\n * @type number\n * @default null\n */\n height: {observer: '_heightChanged', type: Number, value: null},\n },\n\n observers: [\n '_transformChanged(sizing, position)',\n '_loadStateObserver(src, preventLoad)'\n ],\n\n created: function() {\n this._resolvedSrc = '';\n },\n\n _imgOnLoad: function() {\n if (this.$.img.src !== this._resolveSrc(this.src)) {\n return;\n }\n\n this._setLoading(false);\n this._setLoaded(true);\n this._setError(false);\n },\n\n _imgOnError: function() {\n if (this.$.img.src !== this._resolveSrc(this.src)) {\n return;\n }\n\n this.$.img.removeAttribute('src');\n this.$.sizedImgDiv.style.backgroundImage = '';\n\n this._setLoading(false);\n this._setLoaded(false);\n this._setError(true);\n },\n\n _computePlaceholderHidden: function() {\n return !this.preload || (!this.fade && !this.loading && this.loaded);\n },\n\n _computePlaceholderClassName: function() {\n return (this.preload && this.fade && !this.loading && this.loaded) ?\n 'faded-out' :\n '';\n },\n\n _computeImgDivHidden: function() {\n return !this.sizing;\n },\n\n _computeImgDivARIAHidden: function() {\n return this.alt === '' ? 'true' : undefined;\n },\n\n _computeImgDivARIALabel: function() {\n if (this.alt !== null) {\n return this.alt;\n }\n\n // Polymer.ResolveUrl.resolveUrl will resolve '' relative to a URL x to\n // that URL x, but '' is the default for src.\n if (this.src === '') {\n return '';\n }\n\n // NOTE: Use of `URL` was removed here because IE11 doesn't support\n // constructing it. If this ends up being problematic, we should\n // consider reverting and adding the URL polyfill as a dev dependency.\n var resolved = this._resolveSrc(this.src);\n // Remove query parts, get file name.\n return resolved.replace(/[?|#].*/g, '').split('/').pop();\n },\n\n _computeImgHidden: function() {\n return !!this.sizing;\n },\n\n _widthChanged: function() {\n this.style.width = isNaN(this.width) ? this.width : this.width + 'px';\n },\n\n _heightChanged: function() {\n this.style.height = isNaN(this.height) ? this.height : this.height + 'px';\n },\n\n _loadStateObserver: function(src, preventLoad) {\n var newResolvedSrc = this._resolveSrc(src);\n if (newResolvedSrc === this._resolvedSrc) {\n return;\n }\n\n this._resolvedSrc = '';\n this.$.img.removeAttribute('src');\n this.$.sizedImgDiv.style.backgroundImage = '';\n\n if (src === '' || preventLoad) {\n this._setLoading(false);\n this._setLoaded(false);\n this._setError(false);\n } else {\n this._resolvedSrc = newResolvedSrc;\n this.$.img.src = this._resolvedSrc;\n this.$.sizedImgDiv.style.backgroundImage =\n 'url(\"' + this._resolvedSrc + '\")';\n\n this._setLoading(true);\n this._setLoaded(false);\n this._setError(false);\n }\n },\n\n _placeholderChanged: function() {\n this.$.placeholder.style.backgroundImage =\n this.placeholder ? 'url(\"' + this.placeholder + '\")' : '';\n },\n\n _transformChanged: function() {\n var sizedImgDivStyle = this.$.sizedImgDiv.style;\n var placeholderStyle = this.$.placeholder.style;\n\n sizedImgDivStyle.backgroundSize = placeholderStyle.backgroundSize =\n this.sizing;\n\n sizedImgDivStyle.backgroundPosition = placeholderStyle.backgroundPosition =\n this.sizing ? this.position : '';\n\n sizedImgDivStyle.backgroundRepeat = placeholderStyle.backgroundRepeat =\n this.sizing ? 'no-repeat' : '';\n },\n\n _resolveSrc: function(testSrc) {\n var resolved = resolveUrl(testSrc, this.$.baseURIAnchor.href);\n // NOTE: Use of `URL` was removed here because IE11 doesn't support\n // constructing it. If this ends up being problematic, we should\n // consider reverting and adding the URL polyfill as a dev dependency.\n if (resolved[0] === '/') {\n // In IE location.origin might not work\n // https://connect.microsoft.com/IE/feedback/details/1763802/location-origin-is-undefined-in-ie-11-on-windows-10-but-works-on-windows-7\n resolved = (location.origin || location.protocol + '//' + location.host) +\n resolved;\n }\n return resolved;\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport '@polymer/iron-flex-layout/iron-flex-layout.js';\nimport '@polymer/iron-image/iron-image.js';\nimport '@polymer/paper-styles/element-styles/paper-material-styles.js';\nimport '@polymer/paper-styles/default-theme.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\n/**\nMaterial design:\n[Cards](https://www.google.com/design/spec/components/cards.html)\n\n`paper-card` is a container with a drop shadow.\n\nExample:\n\n \n
Some content
\n
\n Some action\n
\n
\n\nExample - top card image:\n\n \n ...\n \n\n### Accessibility\n\nBy default, the `aria-label` will be set to the value of the `heading`\nattribute.\n\n### Styling\n\nThe following custom properties and mixins are available for styling:\n\nCustom property | Description | Default\n----------------|-------------|----------\n`--paper-card-background-color` | The background color of the card | `--primary-background-color`\n`--paper-card-header-color` | The color of the header text | `#000`\n`--paper-card-header` | Mixin applied to the card header section | `{}`\n`--paper-card-header-text` | Mixin applied to the title in the card header section | `{}`\n`--paper-card-header-image` | Mixin applied to the image in the card header section | `{}`\n`--paper-card-header-image-text` | Mixin applied to the text overlapping the image in the card header section | `{}`\n`--paper-card-content` | Mixin applied to the card content section| `{}`\n`--paper-card-actions` | Mixin applied to the card action section | `{}`\n`--paper-card` | Mixin applied to the card | `{}`\n\n@group Paper Elements\n@element paper-card\n@demo demo/index.html\n*/\nPolymer({\n _template: html`\n \n\n
\n \n
[[heading]]
\n
\n\n \n`,\n\n is: 'paper-card',\n\n properties: {\n /**\n * The title of the card.\n */\n heading: {type: String, value: '', observer: '_headingChanged'},\n\n /**\n * The url of the title image of the card.\n */\n image: {type: String, value: ''},\n\n /**\n * The text alternative of the card's title image.\n */\n alt: {type: String},\n\n /**\n * When `true`, any change to the image url property will cause the\n * `placeholder` image to be shown until the image is fully rendered.\n */\n preloadImage: {type: Boolean, value: false},\n\n /**\n * When `preloadImage` is true, setting `fadeImage` to true will cause the\n * image to fade into place.\n */\n fadeImage: {type: Boolean, value: false},\n\n /**\n * This image will be used as a background/placeholder until the src image\n * has loaded. Use of a data-URI for placeholder is encouraged for instant\n * rendering.\n */\n placeholderImage: {type: String, value: null},\n\n /**\n * The z-depth of the card, from 0-5.\n */\n elevation: {type: Number, value: 1, reflectToAttribute: true},\n\n /**\n * Set this to true to animate the card shadow when setting a new\n * `z` value.\n */\n animatedShadow: {type: Boolean, value: false},\n\n /**\n * Read-only property used to pass down the `animatedShadow` value to\n * the underlying paper-material style (since they have different names).\n */\n animated: {\n type: Boolean,\n reflectToAttribute: true,\n readOnly: true,\n computed: '_computeAnimated(animatedShadow)'\n }\n },\n\n /**\n * Format function for aria-hidden. Use the ! operator results in the\n * empty string when given a falsy value.\n */\n _isHidden: function(image) {\n return image ? 'false' : 'true';\n },\n\n _headingChanged: function(heading) {\n var currentHeading = this.getAttribute('heading'),\n currentLabel = this.getAttribute('aria-label');\n\n if (typeof currentLabel !== 'string' || currentLabel === currentHeading) {\n this.setAttribute('aria-label', heading);\n }\n },\n\n _computeHeadingClass: function(image) {\n return image ? ' over-image' : '';\n },\n\n _computeAnimated: function(animatedShadow) {\n return animatedShadow;\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {IronButtonState, IronButtonStateImpl} from '@polymer/iron-behaviors/iron-button-state.js';\nimport {IronControlState} from '@polymer/iron-behaviors/iron-control-state.js';\n\nimport {PaperRippleBehavior} from './paper-ripple-behavior.js';\n\n/** @polymerBehavior PaperButtonBehavior */\nexport const PaperButtonBehaviorImpl = {\n properties: {\n /**\n * The z-depth of this element, from 0-5. Setting to 0 will remove the\n * shadow, and each increasing number greater than 0 will be \"deeper\"\n * than the last.\n *\n * @attribute elevation\n * @type number\n * @default 1\n */\n elevation: {type: Number, reflectToAttribute: true, readOnly: true}\n },\n\n observers: [\n '_calculateElevation(focused, disabled, active, pressed, receivedFocusFromKeyboard)',\n '_computeKeyboardClass(receivedFocusFromKeyboard)'\n ],\n\n hostAttributes: {role: 'button', tabindex: '0', animated: true},\n\n _calculateElevation: function() {\n var e = 1;\n if (this.disabled) {\n e = 0;\n } else if (this.active || this.pressed) {\n e = 4;\n } else if (this.receivedFocusFromKeyboard) {\n e = 3;\n }\n this._setElevation(e);\n },\n\n _computeKeyboardClass: function(receivedFocusFromKeyboard) {\n this.toggleClass('keyboard-focus', receivedFocusFromKeyboard);\n },\n\n /**\n * In addition to `IronButtonState` behavior, when space key goes down,\n * create a ripple down effect.\n *\n * @param {!KeyboardEvent} event .\n */\n _spaceKeyDownHandler: function(event) {\n IronButtonStateImpl._spaceKeyDownHandler.call(this, event);\n // Ensure that there is at most one ripple when the space key is held down.\n if (this.hasRipple() && this.getRipple().ripples.length < 1) {\n this._ripple.uiDownAction();\n }\n },\n\n /**\n * In addition to `IronButtonState` behavior, when space key goes up,\n * create a ripple up effect.\n *\n * @param {!KeyboardEvent} event .\n */\n _spaceKeyUpHandler: function(event) {\n IronButtonStateImpl._spaceKeyUpHandler.call(this, event);\n if (this.hasRipple()) {\n this._ripple.uiUpAction();\n }\n }\n};\n\n/** @polymerBehavior */\nexport const PaperButtonBehavior = [\n IronButtonState,\n IronControlState,\n PaperRippleBehavior,\n PaperButtonBehaviorImpl\n];\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/iron-flex-layout/iron-flex-layout.js';\nimport '@polymer/paper-styles/element-styles/paper-material-styles.js';\n\nimport {PaperButtonBehavior, PaperButtonBehaviorImpl} from '@polymer/paper-behaviors/paper-button-behavior.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/polymer-legacy.js';\n\nconst template = html`\n \n\n `;\n\ntemplate.setAttribute('strip-whitespace', '');\n\n/**\nMaterial design:\n[Buttons](https://www.google.com/design/spec/components/buttons.html)\n\n`paper-button` is a button. When the user touches the button, a ripple effect\nemanates from the point of contact. It may be flat or raised. A raised button is\nstyled with a shadow.\n\nExample:\n\n Flat button\n Raised button\n No ripple effect\n Toggle-able button\n\nA button that has `toggles` true will remain `active` after being clicked (and\nwill have an `active` attribute set). For more information, see the\n`IronButtonState` behavior.\n\nYou may use custom DOM in the button body to create a variety of buttons. For\nexample, to create a button with an icon and some text:\n\n \n \n custom button content\n \n\nTo use `paper-button` as a link, wrap it in an anchor tag. Since `paper-button`\nwill already receive focus, you may want to prevent the anchor tag from\nreceiving focus as well by setting its tabindex to -1.\n\n \n Polymer Project\n \n\n### Styling\n\nStyle the button with CSS as you would a normal DOM element.\n\n paper-button.fancy {\n background: green;\n color: yellow;\n }\n\n paper-button.fancy:hover {\n background: lime;\n }\n\n paper-button[disabled],\n paper-button[toggles][active] {\n background: red;\n }\n\nBy default, the ripple is the same color as the foreground at 25% opacity. You\nmay customize the color using the `--paper-button-ink-color` custom property.\n\nThe following custom properties and mixins are also available for styling:\n\nCustom property | Description | Default\n----------------|-------------|----------\n`--paper-button-ink-color` | Background color of the ripple | `Based on the button's color`\n`--paper-button` | Mixin applied to the button | `{}`\n`--paper-button-disabled` | Mixin applied to the disabled button. Note that you can also use the `paper-button[disabled]` selector | `{}`\n`--paper-button-flat-keyboard-focus` | Mixin applied to a flat button after it's been focused using the keyboard | `{}`\n`--paper-button-raised-keyboard-focus` | Mixin applied to a raised button after it's been focused using the keyboard | `{}`\n\n@demo demo/index.html\n*/\nPolymer({\n _template: template,\n\n is: 'paper-button',\n\n behaviors: [PaperButtonBehavior],\n\n properties: {\n /**\n * If true, the button should be styled with a shadow.\n */\n raised: {\n type: Boolean,\n reflectToAttribute: true,\n value: false,\n observer: '_calculateElevation',\n }\n },\n\n _calculateElevation: function() {\n if (!this.raised) {\n this._setElevation(0);\n } else {\n PaperButtonBehaviorImpl._calculateElevation.apply(this);\n }\n }\n\n /**\n Fired when the animation finishes.\n This is useful if you want to wait until\n the ripple animation finishes to perform some action.\n\n @event transitionend\n Event param: {{node: Object}} detail Contains the animated node.\n */\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\n\n/**\n * @demo demo/index.html\n * @polymerBehavior\n */\nexport const IronControlState = {\n\n properties: {\n\n /**\n * If true, the element currently has focus.\n */\n focused: {\n type: Boolean,\n value: false,\n notify: true,\n readOnly: true,\n reflectToAttribute: true\n },\n\n /**\n * If true, the user cannot interact with this element.\n */\n disabled: {\n type: Boolean,\n value: false,\n notify: true,\n observer: '_disabledChanged',\n reflectToAttribute: true\n },\n\n /**\n * Value of the `tabindex` attribute before `disabled` was activated.\n * `null` means the attribute was not present.\n * @type {?string|undefined}\n */\n _oldTabIndex: {type: String},\n\n _boundFocusBlurHandler: {\n type: Function,\n value: function() {\n return this._focusBlurHandler.bind(this);\n }\n }\n },\n\n observers: ['_changedControlState(focused, disabled)'],\n\n /**\n * @return {void}\n */\n ready: function() {\n this.addEventListener('focus', this._boundFocusBlurHandler, true);\n this.addEventListener('blur', this._boundFocusBlurHandler, true);\n },\n\n _focusBlurHandler: function(event) {\n // Polymer takes care of retargeting events.\n this._setFocused(event.type === 'focus');\n return;\n },\n\n _disabledChanged: function(disabled, old) {\n this.setAttribute('aria-disabled', disabled ? 'true' : 'false');\n this.style.pointerEvents = disabled ? 'none' : '';\n if (disabled) {\n // Read the `tabindex` attribute instead of the `tabIndex` property.\n // The property returns `-1` if there is no `tabindex` attribute.\n // This distinction is important when restoring the value because\n // leaving `-1` hides shadow root children from the tab order.\n this._oldTabIndex = this.getAttribute('tabindex');\n this._setFocused(false);\n this.tabIndex = -1;\n this.blur();\n } else if (this._oldTabIndex !== undefined) {\n if (this._oldTabIndex === null) {\n this.removeAttribute('tabindex');\n } else {\n this.setAttribute('tabindex', this._oldTabIndex);\n }\n }\n },\n\n _changedControlState: function() {\n // _controlStateChanged is abstract, follow-on behaviors may implement it\n if (this._controlStateChanged) {\n this._controlStateChanged();\n }\n }\n\n};\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\n/**\n * Chrome uses an older version of DOM Level 3 Keyboard Events\n *\n * Most keys are labeled as text, but some are Unicode codepoints.\n * Values taken from:\n * http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set\n */\nvar KEY_IDENTIFIER = {\n 'U+0008': 'backspace',\n 'U+0009': 'tab',\n 'U+001B': 'esc',\n 'U+0020': 'space',\n 'U+007F': 'del'\n};\n\n/**\n * Special table for KeyboardEvent.keyCode.\n * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better\n * than that.\n *\n * Values from:\n * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode\n */\nvar KEY_CODE = {\n 8: 'backspace',\n 9: 'tab',\n 13: 'enter',\n 27: 'esc',\n 33: 'pageup',\n 34: 'pagedown',\n 35: 'end',\n 36: 'home',\n 32: 'space',\n 37: 'left',\n 38: 'up',\n 39: 'right',\n 40: 'down',\n 46: 'del',\n 106: '*'\n};\n\n/**\n * MODIFIER_KEYS maps the short name for modifier keys used in a key\n * combo string to the property name that references those same keys\n * in a KeyboardEvent instance.\n */\nvar MODIFIER_KEYS = {\n 'shift': 'shiftKey',\n 'ctrl': 'ctrlKey',\n 'alt': 'altKey',\n 'meta': 'metaKey'\n};\n\n/**\n * KeyboardEvent.key is mostly represented by printable character made by\n * the keyboard, with unprintable keys labeled nicely.\n *\n * However, on OS X, Alt+char can make a Unicode character that follows an\n * Apple-specific mapping. In this case, we fall back to .keyCode.\n */\nvar KEY_CHAR = /[a-z0-9*]/;\n\n/**\n * Matches a keyIdentifier string.\n */\nvar IDENT_CHAR = /U\\+/;\n\n/**\n * Matches arrow keys in Gecko 27.0+\n */\nvar ARROW_KEY = /^arrow/;\n\n/**\n * Matches space keys everywhere (notably including IE10's exceptional name\n * `spacebar`).\n */\nvar SPACE_KEY = /^space(bar)?/;\n\n/**\n * Matches ESC key.\n *\n * Value from: http://w3c.github.io/uievents-key/#key-Escape\n */\nvar ESC_KEY = /^escape$/;\n\n/**\n * Transforms the key.\n * @param {string} key The KeyBoardEvent.key\n * @param {Boolean} [noSpecialChars] Limits the transformation to\n * alpha-numeric characters.\n */\nfunction transformKey(key, noSpecialChars) {\n var validKey = '';\n if (key) {\n var lKey = key.toLowerCase();\n if (lKey === ' ' || SPACE_KEY.test(lKey)) {\n validKey = 'space';\n } else if (ESC_KEY.test(lKey)) {\n validKey = 'esc';\n } else if (lKey.length == 1) {\n if (!noSpecialChars || KEY_CHAR.test(lKey)) {\n validKey = lKey;\n }\n } else if (ARROW_KEY.test(lKey)) {\n validKey = lKey.replace('arrow', '');\n } else if (lKey == 'multiply') {\n // numpad '*' can map to Multiply on IE/Windows\n validKey = '*';\n } else {\n validKey = lKey;\n }\n }\n return validKey;\n}\n\nfunction transformKeyIdentifier(keyIdent) {\n var validKey = '';\n if (keyIdent) {\n if (keyIdent in KEY_IDENTIFIER) {\n validKey = KEY_IDENTIFIER[keyIdent];\n } else if (IDENT_CHAR.test(keyIdent)) {\n keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16);\n validKey = String.fromCharCode(keyIdent).toLowerCase();\n } else {\n validKey = keyIdent.toLowerCase();\n }\n }\n return validKey;\n}\n\nfunction transformKeyCode(keyCode) {\n var validKey = '';\n if (Number(keyCode)) {\n if (keyCode >= 65 && keyCode <= 90) {\n // ascii a-z\n // lowercase is 32 offset from uppercase\n validKey = String.fromCharCode(32 + keyCode);\n } else if (keyCode >= 112 && keyCode <= 123) {\n // function keys f1-f12\n validKey = 'f' + (keyCode - 112 + 1);\n } else if (keyCode >= 48 && keyCode <= 57) {\n // top 0-9 keys\n validKey = String(keyCode - 48);\n } else if (keyCode >= 96 && keyCode <= 105) {\n // num pad 0-9\n validKey = String(keyCode - 96);\n } else {\n validKey = KEY_CODE[keyCode];\n }\n }\n return validKey;\n}\n\n/**\n * Calculates the normalized key for a KeyboardEvent.\n * @param {KeyboardEvent} keyEvent\n * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key\n * transformation to alpha-numeric chars. This is useful with key\n * combinations like shift + 2, which on FF for MacOS produces\n * keyEvent.key = @\n * To get 2 returned, set noSpecialChars = true\n * To get @ returned, set noSpecialChars = false\n */\nfunction normalizedKeyForEvent(keyEvent, noSpecialChars) {\n // Fall back from .key, to .detail.key for artifical keyboard events,\n // and then to deprecated .keyIdentifier and .keyCode.\n if (keyEvent.key) {\n return transformKey(keyEvent.key, noSpecialChars);\n }\n if (keyEvent.detail && keyEvent.detail.key) {\n return transformKey(keyEvent.detail.key, noSpecialChars);\n }\n return transformKeyIdentifier(keyEvent.keyIdentifier) ||\n transformKeyCode(keyEvent.keyCode) || '';\n}\n\nfunction keyComboMatchesEvent(keyCombo, event) {\n // For combos with modifiers we support only alpha-numeric keys\n var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers);\n return keyEvent === keyCombo.key &&\n (!keyCombo.hasModifiers ||\n (!!event.shiftKey === !!keyCombo.shiftKey &&\n !!event.ctrlKey === !!keyCombo.ctrlKey &&\n !!event.altKey === !!keyCombo.altKey &&\n !!event.metaKey === !!keyCombo.metaKey));\n}\n\nfunction parseKeyComboString(keyComboString) {\n if (keyComboString.length === 1) {\n return {combo: keyComboString, key: keyComboString, event: 'keydown'};\n }\n return keyComboString.split('+')\n .reduce(function(parsedKeyCombo, keyComboPart) {\n var eventParts = keyComboPart.split(':');\n var keyName = eventParts[0];\n var event = eventParts[1];\n\n if (keyName in MODIFIER_KEYS) {\n parsedKeyCombo[MODIFIER_KEYS[keyName]] = true;\n parsedKeyCombo.hasModifiers = true;\n } else {\n parsedKeyCombo.key = keyName;\n parsedKeyCombo.event = event || 'keydown';\n }\n\n return parsedKeyCombo;\n }, {combo: keyComboString.split(':').shift()});\n}\n\nfunction parseEventString(eventString) {\n return eventString.trim().split(' ').map(function(keyComboString) {\n return parseKeyComboString(keyComboString);\n });\n}\n\n/**\n * `Polymer.IronA11yKeysBehavior` provides a normalized interface for processing\n * keyboard commands that pertain to [WAI-ARIA best\n * practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). The\n * element takes care of browser differences with respect to Keyboard events and\n * uses an expressive syntax to filter key presses.\n *\n * Use the `keyBindings` prototype property to express what combination of keys\n * will trigger the callback. A key binding has the format\n * `\"KEY+MODIFIER:EVENT\": \"callback\"` (`\"KEY\": \"callback\"` or\n * `\"KEY:EVENT\": \"callback\"` are valid as well). Some examples:\n *\n * keyBindings: {\n * 'space': '_onKeydown', // same as 'space:keydown'\n * 'shift+tab': '_onKeydown',\n * 'enter:keypress': '_onKeypress',\n * 'esc:keyup': '_onKeyup'\n * }\n *\n * The callback will receive with an event containing the following information\n * in `event.detail`:\n *\n * _onKeydown: function(event) {\n * console.log(event.detail.combo); // KEY+MODIFIER, e.g. \"shift+tab\"\n * console.log(event.detail.key); // KEY only, e.g. \"tab\"\n * console.log(event.detail.event); // EVENT, e.g. \"keydown\"\n * console.log(event.detail.keyboardEvent); // the original KeyboardEvent\n * }\n *\n * Use the `keyEventTarget` attribute to set up event handlers on a specific\n * node.\n *\n * See the [demo source\n * code](https://github.com/PolymerElements/iron-a11y-keys-behavior/blob/master/demo/x-key-aware.html)\n * for an example.\n *\n * @demo demo/index.html\n * @polymerBehavior\n */\nexport const IronA11yKeysBehavior = {\n properties: {\n /**\n * The EventTarget that will be firing relevant KeyboardEvents. Set it to\n * `null` to disable the listeners.\n * @type {?EventTarget}\n */\n keyEventTarget: {\n type: Object,\n value: function() {\n return this;\n }\n },\n\n /**\n * If true, this property will cause the implementing element to\n * automatically stop propagation on any handled KeyboardEvents.\n */\n stopKeyboardEventPropagation: {type: Boolean, value: false},\n\n _boundKeyHandlers: {\n type: Array,\n value: function() {\n return [];\n }\n },\n\n // We use this due to a limitation in IE10 where instances will have\n // own properties of everything on the \"prototype\".\n _imperativeKeyBindings: {\n type: Object,\n value: function() {\n return {};\n }\n }\n },\n\n observers: ['_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)'],\n\n\n /**\n * To be used to express what combination of keys will trigger the relative\n * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}`\n * @type {!Object}\n */\n keyBindings: {},\n\n registered: function() {\n this._prepKeyBindings();\n },\n\n attached: function() {\n this._listenKeyEventListeners();\n },\n\n detached: function() {\n this._unlistenKeyEventListeners();\n },\n\n /**\n * Can be used to imperatively add a key binding to the implementing\n * element. This is the imperative equivalent of declaring a keybinding\n * in the `keyBindings` prototype property.\n *\n * @param {string} eventString\n * @param {string} handlerName\n */\n addOwnKeyBinding: function(eventString, handlerName) {\n this._imperativeKeyBindings[eventString] = handlerName;\n this._prepKeyBindings();\n this._resetKeyEventListeners();\n },\n\n /**\n * When called, will remove all imperatively-added key bindings.\n */\n removeOwnKeyBindings: function() {\n this._imperativeKeyBindings = {};\n this._prepKeyBindings();\n this._resetKeyEventListeners();\n },\n\n /**\n * Returns true if a keyboard event matches `eventString`.\n *\n * @param {KeyboardEvent} event\n * @param {string} eventString\n * @return {boolean}\n */\n keyboardEventMatchesKeys: function(event, eventString) {\n var keyCombos = parseEventString(eventString);\n for (var i = 0; i < keyCombos.length; ++i) {\n if (keyComboMatchesEvent(keyCombos[i], event)) {\n return true;\n }\n }\n return false;\n },\n\n _collectKeyBindings: function() {\n var keyBindings = this.behaviors.map(function(behavior) {\n return behavior.keyBindings;\n });\n\n if (keyBindings.indexOf(this.keyBindings) === -1) {\n keyBindings.push(this.keyBindings);\n }\n\n return keyBindings;\n },\n\n _prepKeyBindings: function() {\n this._keyBindings = {};\n\n this._collectKeyBindings().forEach(function(keyBindings) {\n for (var eventString in keyBindings) {\n this._addKeyBinding(eventString, keyBindings[eventString]);\n }\n }, this);\n\n for (var eventString in this._imperativeKeyBindings) {\n this._addKeyBinding(\n eventString, this._imperativeKeyBindings[eventString]);\n }\n\n // Give precedence to combos with modifiers to be checked first.\n for (var eventName in this._keyBindings) {\n this._keyBindings[eventName].sort(function(kb1, kb2) {\n var b1 = kb1[0].hasModifiers;\n var b2 = kb2[0].hasModifiers;\n return (b1 === b2) ? 0 : b1 ? -1 : 1;\n })\n }\n },\n\n _addKeyBinding: function(eventString, handlerName) {\n parseEventString(eventString).forEach(function(keyCombo) {\n this._keyBindings[keyCombo.event] =\n this._keyBindings[keyCombo.event] || [];\n\n this._keyBindings[keyCombo.event].push([keyCombo, handlerName]);\n }, this);\n },\n\n _resetKeyEventListeners: function() {\n this._unlistenKeyEventListeners();\n\n if (this.isAttached) {\n this._listenKeyEventListeners();\n }\n },\n\n _listenKeyEventListeners: function() {\n if (!this.keyEventTarget) {\n return;\n }\n Object.keys(this._keyBindings).forEach(function(eventName) {\n var keyBindings = this._keyBindings[eventName];\n var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings);\n\n this._boundKeyHandlers.push(\n [this.keyEventTarget, eventName, boundKeyHandler]);\n\n this.keyEventTarget.addEventListener(eventName, boundKeyHandler);\n }, this);\n },\n\n _unlistenKeyEventListeners: function() {\n var keyHandlerTuple;\n var keyEventTarget;\n var eventName;\n var boundKeyHandler;\n\n while (this._boundKeyHandlers.length) {\n // My kingdom for block-scope binding and destructuring assignment..\n keyHandlerTuple = this._boundKeyHandlers.pop();\n keyEventTarget = keyHandlerTuple[0];\n eventName = keyHandlerTuple[1];\n boundKeyHandler = keyHandlerTuple[2];\n\n keyEventTarget.removeEventListener(eventName, boundKeyHandler);\n }\n },\n\n _onKeyBindingEvent: function(keyBindings, event) {\n if (this.stopKeyboardEventPropagation) {\n event.stopPropagation();\n }\n\n // if event has been already prevented, don't do anything\n if (event.defaultPrevented) {\n return;\n }\n\n for (var i = 0; i < keyBindings.length; i++) {\n var keyCombo = keyBindings[i][0];\n var handlerName = keyBindings[i][1];\n if (keyComboMatchesEvent(keyCombo, event)) {\n this._triggerKeyHandler(keyCombo, handlerName, event);\n // exit the loop if eventDefault was prevented\n if (event.defaultPrevented) {\n return;\n }\n }\n }\n },\n\n _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) {\n var detail = Object.create(keyCombo);\n detail.keyboardEvent = keyboardEvent;\n var event =\n new CustomEvent(keyCombo.event, {detail: detail, cancelable: true});\n this[handlerName].call(this, event);\n if (event.defaultPrevented) {\n keyboardEvent.preventDefault();\n }\n }\n};\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\n\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nconst template = html`\n\n \n\n`;\ntemplate.setAttribute('style', 'display: none;');\ndocument.head.appendChild(template.content);\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\nimport '@polymer/iron-icon/iron-icon.js';\nimport '@polymer/paper-styles/default-theme.js';\n\nimport {PaperInkyFocusBehavior} from '@polymer/paper-behaviors/paper-inky-focus-behavior.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\nconst template = html`\n\n \n\n`;\ntemplate.setAttribute('style', 'display: none;');\ndocument.body.appendChild(template.content);\n\n/**\nMaterial design: [Icon\ntoggles](https://www.google.com/design/spec/components/buttons.html#buttons-toggle-buttons)\n\n`paper-icon-button` is a button with an image placed at the center. When the\nuser touches the button, a ripple effect emanates from the center of the button.\n\n`paper-icon-button` does not include a default icon set. To use icons from the\ndefault set, include `PolymerElements/iron-icons/iron-icons.html`, and use the\n`icon` attribute to specify which icon from the icon set to use.\n\n \n\nSee [`iron-iconset`](iron-iconset) for more information about\nhow to use a custom icon set.\n\nExample:\n\n \n\n \n \n\nTo use `paper-icon-button` as a link, wrap it in an anchor tag. Since\n`paper-icon-button` will already receive focus, you may want to prevent the\nanchor tag from receiving focus as well by setting its tabindex to -1.\n\n \n \n \n\n### Styling\n\nStyle the button with CSS as you would a normal DOM element. If you are using\nthe icons provided by `iron-icons`, they will inherit the foreground color of\nthe button.\n\n /* make a red \"favorite\" button *\\/\n \n\nBy default, the ripple is the same color as the foreground at 25% opacity. You\nmay customize the color using the `--paper-icon-button-ink-color` custom\nproperty.\n\nThe following custom properties and mixins are available for styling:\n\nCustom property | Description | Default\n----------------|-------------|----------\n`--paper-icon-button-disabled-text` | The color of the disabled button | `--disabled-text-color`\n`--paper-icon-button-ink-color` | Selected/focus ripple color | `--primary-text-color`\n`--paper-icon-button` | Mixin for a button | `{}`\n`--paper-icon-button-disabled` | Mixin for a disabled button | `{}`\n`--paper-icon-button-hover` | Mixin for button on hover | `{}`\n\n@group Paper Elements\n@element paper-icon-button\n@demo demo/index.html\n*/\nPolymer({\n is: 'paper-icon-button',\n\n hostAttributes: {role: 'button', tabindex: '0'},\n\n behaviors: [PaperInkyFocusBehavior],\n\n properties: {\n /**\n * The URL of an image for the icon. If the src property is specified,\n * the icon property should not be.\n */\n src: {type: String},\n\n /**\n * Specifies the icon name or index in the set of icons available in\n * the icon's icon set. If the icon property is specified,\n * the src property should not be.\n */\n icon: {type: String},\n\n /**\n * Specifies the alternate text for the button, for accessibility.\n */\n alt: {type: String, observer: '_altChanged'}\n },\n\n _altChanged: function(newValue, oldValue) {\n var label = this.getAttribute('aria-label');\n\n // Don't stomp over a user-set aria-label.\n if (!label || oldValue == label) {\n this.setAttribute('aria-label', newValue);\n }\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/iron-flex-layout/iron-flex-layout.js';\n\nimport {IronMeta} from '@polymer/iron-meta/iron-meta.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nimport {Base} from '@polymer/polymer/polymer-legacy.js';\n\n/**\n\nThe `iron-icon` element displays an icon. By default an icon renders as a 24px\nsquare.\n\nExample using src:\n\n \n\nExample setting size to 32px x 32px:\n\n \n\n \n\nThe iron elements include several sets of icons. To use the default set of\nicons, import `iron-icons.js` and use the `icon` attribute to specify an icon:\n\n \n\n \n\nTo use a different built-in set of icons, import the specific\n`iron-icons/-icons.js`, and specify the icon as `:`.\nFor example, to use a communication icon, you would use:\n\n \n\n \n\nYou can also create custom icon sets of bitmap or SVG icons.\n\nExample of using an icon named `cherry` from a custom iconset with the ID\n`fruit`:\n\n \n\nSee `` and `` for more information about how to\ncreate a custom iconset.\n\nSee the `iron-icons` demo to see the icons available in the various iconsets.\n\n### Styling\n\nThe following custom properties are available for styling:\n\nCustom property | Description | Default\n----------------|-------------|----------\n`--iron-icon` | Mixin applied to the icon | {}\n`--iron-icon-width` | Width of the icon | `24px`\n`--iron-icon-height` | Height of the icon | `24px`\n`--iron-icon-fill-color` | Fill color of the svg icon | `currentcolor`\n`--iron-icon-stroke-color` | Stroke color of the svg icon | none\n\n@group Iron Elements\n@element iron-icon\n@demo demo/index.html\n@hero hero.svg\n@homepage polymer.github.io\n*/\nPolymer({\n _template: html`\n \n`,\n\n is: 'iron-icon',\n\n properties: {\n\n /**\n * The name of the icon to use. The name should be of the form:\n * `iconset_name:icon_name`.\n */\n icon: {type: String},\n\n /**\n * The name of the theme to used, if one is specified by the\n * iconset.\n */\n theme: {type: String},\n\n /**\n * If using iron-icon without an iconset, you can set the src to be\n * the URL of an individual icon image file. Note that this will take\n * precedence over a given icon attribute.\n */\n src: {type: String},\n\n /**\n * @type {!IronMeta}\n */\n _meta: {value: Base.create('iron-meta', {type: 'iconset'})}\n\n },\n\n observers: [\n '_updateIcon(_meta, isAttached)',\n '_updateIcon(theme, isAttached)',\n '_srcChanged(src, isAttached)',\n '_iconChanged(icon, isAttached)'\n ],\n\n _DEFAULT_ICONSET: 'icons',\n\n _iconChanged: function(icon) {\n var parts = (icon || '').split(':');\n this._iconName = parts.pop();\n this._iconsetName = parts.pop() || this._DEFAULT_ICONSET;\n this._updateIcon();\n },\n\n _srcChanged: function(src) {\n this._updateIcon();\n },\n\n _usesIconset: function() {\n return this.icon || !this.src;\n },\n\n /** @suppress {visibility} */\n _updateIcon: function() {\n if (this._usesIconset()) {\n if (this._img && this._img.parentNode) {\n dom(this.root).removeChild(this._img);\n }\n if (this._iconName === '') {\n if (this._iconset) {\n this._iconset.removeIcon(this);\n }\n } else if (this._iconsetName && this._meta) {\n this._iconset = /** @type {?Polymer.Iconset} */ (\n this._meta.byKey(this._iconsetName));\n if (this._iconset) {\n this._iconset.applyIcon(this, this._iconName, this.theme);\n this.unlisten(window, 'iron-iconset-added', '_updateIcon');\n } else {\n this.listen(window, 'iron-iconset-added', '_updateIcon');\n }\n }\n } else {\n if (this._iconset) {\n this._iconset.removeIcon(this);\n }\n if (!this._img) {\n this._img = document.createElement('img');\n this._img.style.width = '100%';\n this._img.style.height = '100%';\n this._img.draggable = false;\n }\n this._img.src = this.src;\n dom(this.root).appendChild(this._img);\n }\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\nimport './iron-control-state.js';\n\nimport {IronA11yKeysBehavior} from '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\n\n/**\n * @demo demo/index.html\n * @polymerBehavior IronButtonState\n */\nexport const IronButtonStateImpl = {\n\n properties: {\n\n /**\n * If true, the user is currently holding down the button.\n */\n pressed: {\n type: Boolean,\n readOnly: true,\n value: false,\n reflectToAttribute: true,\n observer: '_pressedChanged'\n },\n\n /**\n * If true, the button toggles the active state with each tap or press\n * of the spacebar.\n */\n toggles: {type: Boolean, value: false, reflectToAttribute: true},\n\n /**\n * If true, the button is a toggle and is currently in the active state.\n */\n active:\n {type: Boolean, value: false, notify: true, reflectToAttribute: true},\n\n /**\n * True if the element is currently being pressed by a \"pointer,\" which\n * is loosely defined as mouse or touch input (but specifically excluding\n * keyboard input).\n */\n pointerDown: {type: Boolean, readOnly: true, value: false},\n\n /**\n * True if the input device that caused the element to receive focus\n * was a keyboard.\n */\n receivedFocusFromKeyboard: {type: Boolean, readOnly: true},\n\n /**\n * The aria attribute to be set if the button is a toggle and in the\n * active state.\n */\n ariaActiveAttribute: {\n type: String,\n value: 'aria-pressed',\n observer: '_ariaActiveAttributeChanged'\n }\n },\n\n listeners: {down: '_downHandler', up: '_upHandler', tap: '_tapHandler'},\n\n observers:\n ['_focusChanged(focused)', '_activeChanged(active, ariaActiveAttribute)'],\n\n /**\n * @type {!Object}\n */\n keyBindings: {\n 'enter:keydown': '_asyncClick',\n 'space:keydown': '_spaceKeyDownHandler',\n 'space:keyup': '_spaceKeyUpHandler',\n },\n\n _mouseEventRe: /^mouse/,\n\n _tapHandler: function() {\n if (this.toggles) {\n // a tap is needed to toggle the active state\n this._userActivate(!this.active);\n } else {\n this.active = false;\n }\n },\n\n _focusChanged: function(focused) {\n this._detectKeyboardFocus(focused);\n\n if (!focused) {\n this._setPressed(false);\n }\n },\n\n _detectKeyboardFocus: function(focused) {\n this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);\n },\n\n // to emulate native checkbox, (de-)activations from a user interaction fire\n // 'change' events\n _userActivate: function(active) {\n if (this.active !== active) {\n this.active = active;\n this.fire('change');\n }\n },\n\n _downHandler: function(event) {\n this._setPointerDown(true);\n this._setPressed(true);\n this._setReceivedFocusFromKeyboard(false);\n },\n\n _upHandler: function() {\n this._setPointerDown(false);\n this._setPressed(false);\n },\n\n /**\n * @param {!KeyboardEvent} event .\n */\n _spaceKeyDownHandler: function(event) {\n var keyboardEvent = event.detail.keyboardEvent;\n var target = dom(keyboardEvent).localTarget;\n\n // Ignore the event if this is coming from a focused light child, since that\n // element will deal with it.\n if (this.isLightDescendant(/** @type {Node} */ (target)))\n return;\n\n keyboardEvent.preventDefault();\n keyboardEvent.stopImmediatePropagation();\n this._setPressed(true);\n },\n\n /**\n * @param {!KeyboardEvent} event .\n */\n _spaceKeyUpHandler: function(event) {\n var keyboardEvent = event.detail.keyboardEvent;\n var target = dom(keyboardEvent).localTarget;\n\n // Ignore the event if this is coming from a focused light child, since that\n // element will deal with it.\n if (this.isLightDescendant(/** @type {Node} */ (target)))\n return;\n\n if (this.pressed) {\n this._asyncClick();\n }\n this._setPressed(false);\n },\n\n // trigger click asynchronously, the asynchrony is useful to allow one\n // event handler to unwind before triggering another event\n _asyncClick: function() {\n this.async(function() {\n this.click();\n }, 1);\n },\n\n // any of these changes are considered a change to button state\n\n _pressedChanged: function(pressed) {\n this._changedButtonState();\n },\n\n _ariaActiveAttributeChanged: function(value, oldValue) {\n if (oldValue && oldValue != value && this.hasAttribute(oldValue)) {\n this.removeAttribute(oldValue);\n }\n },\n\n _activeChanged: function(active, ariaActiveAttribute) {\n if (this.toggles) {\n this.setAttribute(this.ariaActiveAttribute, active ? 'true' : 'false');\n } else {\n this.removeAttribute(this.ariaActiveAttribute);\n }\n this._changedButtonState();\n },\n\n _controlStateChanged: function() {\n if (this.disabled) {\n this._setPressed(false);\n } else {\n this._changedButtonState();\n }\n },\n\n // provide hook for follow-on behaviors to react to button-state\n\n _changedButtonState: function() {\n if (this._buttonStateChanged) {\n this._buttonStateChanged(); // abstract\n }\n }\n\n};\n\n/** @polymerBehavior */\nexport const IronButtonState = [IronA11yKeysBehavior, IronButtonStateImpl];\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\n\nexport {}; // ensure this file can only be parsed as a module.\n\n// Give the user the choice to opt out of font loading.\nif (!window.polymerSkipLoadingFontRoboto) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.type = 'text/css';\n link.crossOrigin = 'anonymous';\n link.href =\n 'https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto:400,300,300italic,400italic,500,500italic,700,700italic';\n document.head.appendChild(link);\n}\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\n/*\nTypographic styles are provided matching the Material Design standard styles:\nhttp://www.google.com/design/spec/style/typography.html#typography-standard-styles\n\nNote that these are English/Latin centric styles. You may need to further adjust\nline heights and weights for CJK typesetting. See the notes in the Material\nDesign typography section.\n*/\n\nimport '@polymer/polymer/polymer-legacy.js';\nimport '@polymer/font-roboto/roboto.js';\n\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nconst template = html`\n \n`;\ntemplate.setAttribute('style', 'display: none;');\ndocument.head.appendChild(template.content);\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport '@polymer/iron-flex-layout/iron-flex-layout.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\n/**\napp-toolbar is a horizontal toolbar containing items that can be used for\nlabel, navigation, search and actions.\n\n### Example\n\nAdd a title to the toolbar.\n\n```html\n\n
App name
\n
\n```\n\nAdd a button to the left and right side of the toolbar.\n\n```html\n\n \n
App name
\n \n
\n```\n\nYou can use the attributes `top-item` or `bottom-item` to completely fit an\nelement to the top or bottom of the toolbar respectively.\n\n### Content attributes\n\nAttribute | Description\n---------------------|---------------------------------------------------------\n`main-title` | The main title element.\n`condensed-title` | The title element if used inside a condensed app-header.\n`spacer` | Adds a left margin of `64px`.\n`bottom-item` | Sticks the element to the bottom of the toolbar.\n`top-item` | Sticks the element to the top of the toolbar.\n\n### Styling\n\nCustom property | Description | Default\n-----------------------------|------------------------------|-----------------------\n`--app-toolbar-font-size` | Toolbar font size | 20px\n\n@group App Elements\n@element app-toolbar\n@demo app-toolbar/demo/index.html\n*/\nPolymer({\n _template: html`\n \n\n \n`,\n\n is: 'app-toolbar'\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\nimport '@polymer/paper-ripple/paper-ripple.js';\n\nimport {IronButtonStateImpl} from '@polymer/iron-behaviors/iron-button-state.js';\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\n\n/**\n * `PaperRippleBehavior` dynamically implements a ripple when the element has\n * focus via pointer or keyboard.\n *\n * NOTE: This behavior is intended to be used in conjunction with and after\n * `IronButtonState` and `IronControlState`.\n *\n * @polymerBehavior PaperRippleBehavior\n */\nexport const PaperRippleBehavior = {\n properties: {\n /**\n * If true, the element will not produce a ripple effect when interacted\n * with via the pointer.\n */\n noink: {type: Boolean, observer: '_noinkChanged'},\n\n /**\n * @type {Element|undefined}\n */\n _rippleContainer: {\n type: Object,\n }\n },\n\n /**\n * Ensures a `` element is available when the element is\n * focused.\n */\n _buttonStateChanged: function() {\n if (this.focused) {\n this.ensureRipple();\n }\n },\n\n /**\n * In addition to the functionality provided in `IronButtonState`, ensures\n * a ripple effect is created when the element is in a `pressed` state.\n */\n _downHandler: function(event) {\n IronButtonStateImpl._downHandler.call(this, event);\n if (this.pressed) {\n this.ensureRipple(event);\n }\n },\n\n /**\n * Ensures this element contains a ripple effect. For startup efficiency\n * the ripple effect is dynamically on demand when needed.\n * @param {!Event=} optTriggeringEvent (optional) event that triggered the\n * ripple.\n */\n ensureRipple: function(optTriggeringEvent) {\n if (!this.hasRipple()) {\n this._ripple = this._createRipple();\n this._ripple.noink = this.noink;\n var rippleContainer = this._rippleContainer || this.root;\n if (rippleContainer) {\n dom(rippleContainer).appendChild(this._ripple);\n }\n if (optTriggeringEvent) {\n // Check if the event happened inside of the ripple container\n // Fall back to host instead of the root because distributed text\n // nodes are not valid event targets\n var domContainer = dom(this._rippleContainer || this);\n var target = dom(optTriggeringEvent).rootTarget;\n if (domContainer.deepContains(/** @type {Node} */ (target))) {\n this._ripple.uiDownAction(optTriggeringEvent);\n }\n }\n }\n },\n\n /**\n * Returns the `` element used by this element to create\n * ripple effects. The element's ripple is created on demand, when\n * necessary, and calling this method will force the\n * ripple to be created.\n */\n getRipple: function() {\n this.ensureRipple();\n return this._ripple;\n },\n\n /**\n * Returns true if this element currently contains a ripple effect.\n * @return {boolean}\n */\n hasRipple: function() {\n return Boolean(this._ripple);\n },\n\n /**\n * Create the element's ripple effect via creating a ``.\n * Override this method to customize the ripple element.\n * @return {!PaperRippleElement} Returns a `` element.\n */\n _createRipple: function() {\n var element = /** @type {!PaperRippleElement} */ (\n document.createElement('paper-ripple'));\n return element;\n },\n\n _noinkChanged: function(noink) {\n if (this.hasRipple()) {\n this._ripple.noink = noink;\n }\n }\n};\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\n/**\n`iron-a11y-announcer` is a singleton element that is intended to add a11y\nto features that require on-demand announcement from screen readers. In\norder to make use of the announcer, it is best to request its availability\nin the announcing element.\n\nExample:\n\n Polymer({\n\n is: 'x-chatty',\n\n attached: function() {\n // This will create the singleton element if it has not\n // been created yet:\n Polymer.IronA11yAnnouncer.requestAvailability();\n }\n });\n\nAfter the `iron-a11y-announcer` has been made available, elements can\nmake announces by firing bubbling `iron-announce` events.\n\nExample:\n\n this.fire('iron-announce', {\n text: 'This is an announcement!'\n }, { bubbles: true });\n\nNote: announcements are only audible if you have a screen reader enabled.\n\n@group Iron Elements\n@demo demo/index.html\n*/\nexport const IronA11yAnnouncer = Polymer({\n _template: html`\n \n
[[_text]]
\n`,\n\n is: 'iron-a11y-announcer',\n\n properties: {\n\n /**\n * The value of mode is used to set the `aria-live` attribute\n * for the element that will be announced. Valid values are: `off`,\n * `polite` and `assertive`.\n */\n mode: {type: String, value: 'polite'},\n\n _text: {type: String, value: ''}\n },\n\n created: function() {\n if (!IronA11yAnnouncer.instance) {\n IronA11yAnnouncer.instance = this;\n }\n\n document.body.addEventListener(\n 'iron-announce', this._onIronAnnounce.bind(this));\n },\n\n /**\n * Cause a text string to be announced by screen readers.\n *\n * @param {string} text The text that should be announced.\n */\n announce: function(text) {\n this._text = '';\n this.async(function() {\n this._text = text;\n }, 100);\n },\n\n _onIronAnnounce: function(event) {\n if (event.detail && event.detail.text) {\n this.announce(event.detail.text);\n }\n }\n});\n\nIronA11yAnnouncer.instance = null;\n\nIronA11yAnnouncer.requestAvailability = function() {\n if (!IronA11yAnnouncer.instance) {\n IronA11yAnnouncer.instance = document.createElement('iron-a11y-announcer');\n }\n\n document.body.appendChild(IronA11yAnnouncer.instance);\n};\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\nimport {IronA11yAnnouncer} from '@polymer/iron-a11y-announcer/iron-a11y-announcer.js';\nimport {IronValidatableBehavior} from '@polymer/iron-validatable-behavior/iron-validatable-behavior.js';\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\n/**\n`` is a wrapper to a native `` element, that adds two-way\nbinding and prevention of invalid input. To use it, you must distribute a native\n`` yourself. You can continue to use the native `input` as you would\nnormally:\n\n \n \n \n\n \n \n \n\n### Two-way binding\n\nBy default you can only get notified of changes to a native ``'s `value`\ndue to user input:\n\n \n\nThis means that if you imperatively set the value (i.e. `someNativeInput.value =\n'foo'`), no events will be fired and this change cannot be observed.\n\n`iron-input` adds the `bind-value` property that mirrors the native `input`'s\n'`value` property; this property can be used for two-way data binding.\n`bind-value` will notify if it is changed either by user input or by script.\n\n \n \n \n\nNote: this means that if you want to imperatively set the native `input`'s, you\n_must_ set `bind-value` instead, so that the wrapper `iron-input` can be\nnotified.\n\n### Validation\n\n`iron-input` uses the native `input`'s validation. For simplicity, `iron-input`\nhas a `validate()` method (which internally just checks the distributed\n`input`'s validity), which sets an `invalid` attribute that can also be used for\nstyling.\n\nTo validate automatically as you type, you can use the `auto-validate`\nattribute.\n\n`iron-input` also fires an `iron-input-validate` event after `validate()` is\ncalled. You can use it to implement a custom validator:\n\n var CatsOnlyValidator = {\n validate: function(ironInput) {\n var valid = !ironInput.bindValue || ironInput.bindValue === 'cat';\n ironInput.invalid = !valid;\n return valid;\n }\n }\n ironInput.addEventListener('iron-input-validate', function() {\n CatsOnly.validate(input2);\n });\n\nYou can also use an element implementing an\n[`IronValidatorBehavior`](/element/PolymerElements/iron-validatable-behavior).\nThis example can also be found in the demo for this element:\n\n \n \n \n\n### Preventing invalid input\n\nIt may be desirable to only allow users to enter certain characters. You can use\nthe `allowed-pattern` attribute to accomplish this. This feature is separate\nfrom validation, and `allowed-pattern` does not affect how the input is\nvalidated.\n\n // Only allow typing digits, but a valid input has exactly 5 digits.\n \n \n \n\n@demo demo/index.html\n*/\nPolymer({\n _template: html`\n \n \n`,\n\n is: 'iron-input',\n behaviors: [IronValidatableBehavior],\n\n /**\n * Fired whenever `validate()` is called.\n *\n * @event iron-input-validate\n */\n\n properties: {\n\n /**\n * Use this property instead of `value` for two-way data binding, or to\n * set a default value for the input. **Do not** use the distributed\n * input's `value` property to set a default value.\n */\n bindValue: {type: String, value: ''},\n\n /**\n * Computed property that echoes `bindValue` (mostly used for Polymer 1.0\n * backcompatibility, if you were one-way binding to the Polymer 1.0\n * `input is=\"iron-input\"` value attribute).\n */\n value: {type: String, computed: '_computeValue(bindValue)'},\n\n /**\n * Regex-like list of characters allowed as input; all characters not in the\n * list will be rejected. The recommended format should be a list of allowed\n * characters, for example, `[a-zA-Z0-9.+-!;:]`.\n *\n * This pattern represents the allowed characters for the field; as the user\n * inputs text, each individual character will be checked against the\n * pattern (rather than checking the entire value as a whole). If a\n * character is not a match, it will be rejected.\n *\n * Pasted input will have each character checked individually; if any\n * character doesn't match `allowedPattern`, the entire pasted string will\n * be rejected.\n *\n * Note: if you were using `iron-input` in 1.0, you were also required to\n * set `prevent-invalid-input`. This is no longer needed as of Polymer 2.0,\n * and will be set automatically for you if an `allowedPattern` is provided.\n *\n */\n allowedPattern: {type: String},\n\n /**\n * Set to true to auto-validate the input value as you type.\n */\n autoValidate: {type: Boolean, value: false},\n\n /**\n * The native input element.\n */\n _inputElement: Object,\n },\n\n observers: ['_bindValueChanged(bindValue, _inputElement)'],\n listeners: {'input': '_onInput', 'keypress': '_onKeypress'},\n\n created: function() {\n IronA11yAnnouncer.requestAvailability();\n this._previousValidInput = '';\n this._patternAlreadyChecked = false;\n },\n\n attached: function() {\n // If the input is added at a later time, update the internal reference.\n this._observer = dom(this).observeNodes(function(info) {\n this._initSlottedInput();\n }.bind(this));\n },\n\n detached: function() {\n if (this._observer) {\n dom(this).unobserveNodes(this._observer);\n this._observer = null;\n }\n },\n\n /**\n * Returns the distributed input element.\n */\n get inputElement() {\n return this._inputElement;\n },\n\n _initSlottedInput: function() {\n this._inputElement = this.getEffectiveChildren()[0];\n\n if (this.inputElement && this.inputElement.value) {\n this.bindValue = this.inputElement.value;\n }\n\n this.fire('iron-input-ready');\n },\n\n get _patternRegExp() {\n var pattern;\n if (this.allowedPattern) {\n pattern = new RegExp(this.allowedPattern);\n } else {\n switch (this.inputElement.type) {\n case 'number':\n pattern = /[0-9.,e-]/;\n break;\n }\n }\n return pattern;\n },\n\n /**\n * @suppress {checkTypes}\n */\n _bindValueChanged: function(bindValue, inputElement) {\n // The observer could have run before attached() when we have actually\n // initialized this property.\n if (!inputElement) {\n return;\n }\n\n if (bindValue === undefined) {\n inputElement.value = null;\n } else if (bindValue !== inputElement.value) {\n this.inputElement.value = bindValue;\n }\n\n if (this.autoValidate) {\n this.validate();\n }\n\n // manually notify because we don't want to notify until after setting value\n this.fire('bind-value-changed', {value: bindValue});\n },\n\n _onInput: function() {\n // Need to validate each of the characters pasted if they haven't\n // been validated inside `_onKeypress` already.\n if (this.allowedPattern && !this._patternAlreadyChecked) {\n var valid = this._checkPatternValidity();\n if (!valid) {\n this._announceInvalidCharacter(\n 'Invalid string of characters not entered.');\n this.inputElement.value = this._previousValidInput;\n }\n }\n this.bindValue = this._previousValidInput = this.inputElement.value;\n this._patternAlreadyChecked = false;\n },\n\n _isPrintable: function(event) {\n // What a control/printable character is varies wildly based on the browser.\n // - most control characters (arrows, backspace) do not send a `keypress`\n // event\n // in Chrome, but the *do* on Firefox\n // - in Firefox, when they do send a `keypress` event, control chars have\n // a charCode = 0, keyCode = xx (for ex. 40 for down arrow)\n // - printable characters always send a keypress event.\n // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the\n // keyCode\n // always matches the charCode.\n // None of this makes any sense.\n\n // For these keys, ASCII code == browser keycode.\n var anyNonPrintable = (event.keyCode == 8) || // backspace\n (event.keyCode == 9) || // tab\n (event.keyCode == 13) || // enter\n (event.keyCode == 27); // escape\n\n // For these keys, make sure it's a browser keycode and not an ASCII code.\n var mozNonPrintable = (event.keyCode == 19) || // pause\n (event.keyCode == 20) || // caps lock\n (event.keyCode == 45) || // insert\n (event.keyCode == 46) || // delete\n (event.keyCode == 144) || // num lock\n (event.keyCode == 145) || // scroll lock\n (event.keyCode > 32 &&\n event.keyCode < 41) || // page up/down, end, home, arrows\n (event.keyCode > 111 && event.keyCode < 124); // fn keys\n\n return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);\n },\n\n _onKeypress: function(event) {\n if (!this.allowedPattern && this.inputElement.type !== 'number') {\n return;\n }\n var regexp = this._patternRegExp;\n if (!regexp) {\n return;\n }\n\n // Handle special keys and backspace\n if (event.metaKey || event.ctrlKey || event.altKey) {\n return;\n }\n\n // Check the pattern either here or in `_onInput`, but not in both.\n this._patternAlreadyChecked = true;\n\n var thisChar = String.fromCharCode(event.charCode);\n if (this._isPrintable(event) && !regexp.test(thisChar)) {\n event.preventDefault();\n this._announceInvalidCharacter(\n 'Invalid character ' + thisChar + ' not entered.');\n }\n },\n\n _checkPatternValidity: function() {\n var regexp = this._patternRegExp;\n if (!regexp) {\n return true;\n }\n for (var i = 0; i < this.inputElement.value.length; i++) {\n if (!regexp.test(this.inputElement.value[i])) {\n return false;\n }\n }\n return true;\n },\n\n /**\n * Returns true if `value` is valid. The validator provided in `validator`\n * will be used first, then any constraints.\n * @return {boolean} True if the value is valid.\n */\n validate: function() {\n if (!this.inputElement) {\n this.invalid = false;\n return true;\n }\n\n // Use the nested input's native validity.\n var valid = this.inputElement.checkValidity();\n\n // Only do extra checking if the browser thought this was valid.\n if (valid) {\n // Empty, required input is invalid\n if (this.required && this.bindValue === '') {\n valid = false;\n } else if (this.hasValidator()) {\n valid = IronValidatableBehavior.validate.call(this, this.bindValue);\n }\n }\n\n this.invalid = !valid;\n this.fire('iron-input-validate');\n return valid;\n },\n\n _announceInvalidCharacter: function(message) {\n this.fire('iron-announce', {text: message});\n },\n\n _computeValue: function(bindValue) {\n return bindValue;\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\n\n/**\n * Use `Polymer.PaperInputAddonBehavior` to implement an add-on for\n * ``. A add-on appears below the input, and may display\n * information based on the input value and validity such as a character counter\n * or an error message.\n * @polymerBehavior\n */\nexport const PaperInputAddonBehavior = {\n attached: function() {\n this.fire('addon-attached');\n },\n\n /**\n * The function called by `` when the input value or\n * validity changes.\n * @param {{\n * invalid: boolean,\n * inputElement: (Element|undefined),\n * value: (string|undefined)\n * }} state -\n * inputElement: The input element.\n * value: The input value.\n * invalid: True if the input value is invalid.\n */\n update: function(state) {}\n\n};\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\nimport '@polymer/paper-styles/typography.js';\n\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\n\nimport {PaperInputAddonBehavior} from './paper-input-addon-behavior.js';\n\n/*\n`` is a character counter for use with\n``. It shows the number of characters entered in the\ninput and the max length if it is specified.\n\n \n \n \n \n\n### Styling\n\nThe following mixin is available for styling:\n\nCustom property | Description | Default\n----------------|-------------|----------\n`--paper-input-char-counter` | Mixin applied to the element | `{}`\n*/\nPolymer({\n _template: html`\n \n\n [[_charCounterStr]]\n`,\n\n is: 'paper-input-char-counter',\n behaviors: [PaperInputAddonBehavior],\n properties: {_charCounterStr: {type: String, value: '0'}},\n\n /**\n * This overrides the update function in PaperInputAddonBehavior.\n * @param {{\n * inputElement: (Element|undefined),\n * value: (string|undefined),\n * invalid: boolean\n * }} state -\n * inputElement: The input element.\n * value: The input value.\n * invalid: True if the input value is invalid.\n */\n update: function(state) {\n if (!state.inputElement) {\n return;\n }\n\n state.value = state.value || '';\n\n var counter = state.value.toString().length.toString();\n\n if (state.inputElement.hasAttribute('maxlength')) {\n counter += '/' + state.inputElement.getAttribute('maxlength');\n }\n\n this._charCounterStr = counter;\n }\n});\n","/**\n@license\nCopyright (c) 2015 The Polymer Project Authors. All rights reserved.\nThis code may only be used under the BSD style license found at\nhttp://polymer.github.io/LICENSE.txt The complete set of authors may be found at\nhttp://polymer.github.io/AUTHORS.txt The complete set of contributors may be\nfound at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as\npart of the polymer project is also subject to an additional IP rights grant\nfound at http://polymer.github.io/PATENTS.txt\n*/\nimport '@polymer/polymer/polymer-legacy.js';\nimport '@polymer/iron-flex-layout/iron-flex-layout.js';\nimport '@polymer/paper-styles/default-theme.js';\nimport '@polymer/paper-styles/typography.js';\n\nimport {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';\nimport {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';\nimport {dashToCamelCase} from '@polymer/polymer/lib/utils/case-map.js';\nimport {html} from '@polymer/polymer/lib/utils/html-tag.js';\nconst template = html`\n\n \n\n`;\ntemplate.setAttribute('style', 'display: none;');\ndocument.head.appendChild(template.content);\n\n/*\n`` is a container for a `