Prettier 💎 (#1737)

* Add prettier

* Apply Prettier
This commit is contained in:
Paulus Schoutsen
2018-10-11 12:22:11 +02:00
committed by GitHub
parent 3b425c3e14
commit 34bfc12647
472 changed files with 12402 additions and 9875 deletions

View File

@@ -1,5 +1,5 @@
{
"extends": "airbnb-base",
"extends": ["airbnb-base", "prettier"],
"parserOptions": {
"ecmaFeatures": {
"jsx": true,
@@ -67,13 +67,11 @@
"react/no-find-dom-node": 2,
"react/no-is-mounted": 2,
"react/jsx-no-comment-textnodes": 2,
"react/jsx-curly-spacing": 2,
"react/jsx-no-undef": 2,
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"no-restricted-syntax": [0, "ForOfStatement"]
"no-restricted-syntax": [0, "ForOfStatement"],
"prettier/prettier": "error"
},
"plugins": [
"react"
]
"plugins": ["react", "prettier"]
}

View File

@@ -1,12 +1,12 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import JsYaml from 'js-yaml';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import JsYaml from "js-yaml";
import HomeAssistant from '../data/hass.js';
import demoConfig from '../data/demo_config.js';
import demoResources from '../data/demo_resources.js';
import demoStates from '../data/demo_states.js';
import createCardElement from '../../../src/panels/lovelace/common/create-card-element.js';
import HomeAssistant from "../data/hass.js";
import demoConfig from "../data/demo_config.js";
import demoResources from "../data/demo_resources.js";
import demoStates from "../data/demo_states.js";
import createCardElement from "../../../src/panels/lovelace/common/create-card-element.js";
class DemoCard extends PolymerElement {
static get template() {
@@ -50,11 +50,11 @@ class DemoCard extends PolymerElement {
return {
hass: {
type: Object,
observer: '_hassChanged',
observer: "_hassChanged",
},
config: {
type: Object,
observer: '_configChanged'
observer: "_configChanged",
},
showConfig: Boolean,
};
@@ -74,7 +74,7 @@ class DemoCard extends PolymerElement {
const hass = new HomeAssistant(demoStates);
hass.config = demoConfig;
hass.resources = demoResources;
hass.language = 'en';
hass.language = "en";
hass.states = demoStates;
el.hass = hass;
}
@@ -92,4 +92,4 @@ class DemoCard extends PolymerElement {
}
}
customElements.define('demo-card', DemoCard);
customElements.define("demo-card", DemoCard);

View File

@@ -1,9 +1,9 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/paper-toggle-button/paper-toggle-button.js";
import './demo-card.js';
import "./demo-card.js";
class DemoCards extends PolymerElement {
static get template() {
@@ -50,9 +50,9 @@ class DemoCards extends PolymerElement {
_showConfig: {
type: Boolean,
value: false,
}
},
};
}
}
customElements.define('demo-cards', DemoCards);
customElements.define("demo-cards", DemoCards);

View File

@@ -1,10 +1,9 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/state-summary/state-card-content.js';
import '../../../src/dialogs/more-info/controls/more-info-content.js';
import '../../../src/components/ha-card.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import "../../../src/state-summary/state-card-content.js";
import "../../../src/dialogs/more-info/controls/more-info-content.js";
import "../../../src/components/ha-card.js";
class DemoMoreInfo extends PolymerElement {
static get template() {
@@ -68,8 +67,8 @@ class DemoMoreInfo extends PolymerElement {
showConfig: Boolean,
_stateObj: {
type: Object,
computed: '_getState(entityId, hass.states)'
}
computed: "_getState(entityId, hass.states)",
},
};
}
@@ -82,7 +81,7 @@ class DemoMoreInfo extends PolymerElement {
// (it sucks, we will remove in the future)
const tmp = {};
Object.keys(stateObj).forEach((key) => {
if (key[0] !== '_') {
if (key[0] !== "_") {
tmp[key] = stateObj[key];
}
});
@@ -90,4 +89,4 @@ class DemoMoreInfo extends PolymerElement {
}
}
customElements.define('demo-more-info', DemoMoreInfo);
customElements.define("demo-more-info", DemoMoreInfo);

View File

@@ -1,9 +1,9 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/paper-toggle-button/paper-toggle-button.js";
import './demo-more-info.js';
import "./demo-more-info.js";
class DemoMoreInfos extends PolymerElement {
static get template() {
@@ -50,9 +50,9 @@ class DemoMoreInfos extends PolymerElement {
_showConfig: {
type: Boolean,
value: false,
}
},
};
}
}
customElements.define('demo-more-infos', DemoMoreInfos);
customElements.define("demo-more-infos", DemoMoreInfos);

View File

@@ -4,172 +4,106 @@ export default {
latitude: 51.5287352,
longitude: -0.381773,
unit_system: {
length: 'km',
mass: 'kg',
temperature: '°C',
volume: 'L'
}
length: "km",
mass: "kg",
temperature: "°C",
volume: "L",
},
},
services: {
configurator: [
'configure'
],
tts: [
'demo_say',
'clear_cache'
],
configurator: ["configure"],
tts: ["demo_say", "clear_cache"],
cover: [
'open_cover',
'close_cover',
'open_cover_tilt',
'close_cover_tilt',
'set_cover_tilt_position',
'set_cover_position',
'stop_cover_tilt',
'stop_cover'
],
group: [
'set',
'reload',
'remove',
'set_visibility'
"open_cover",
"close_cover",
"open_cover_tilt",
"close_cover_tilt",
"set_cover_tilt_position",
"set_cover_position",
"stop_cover_tilt",
"stop_cover",
],
group: ["set", "reload", "remove", "set_visibility"],
alarm_control_panel: [
'alarm_arm_night',
'alarm_disarm',
'alarm_trigger',
'alarm_arm_home',
'alarm_arm_away',
'alarm_arm_custom_bypass'
],
conversation: [
'process'
],
notify: [
'demo_test_target_name',
'notify'
],
lock: [
'open',
'lock',
'unlock'
"alarm_arm_night",
"alarm_disarm",
"alarm_trigger",
"alarm_arm_home",
"alarm_arm_away",
"alarm_arm_custom_bypass",
],
conversation: ["process"],
notify: ["demo_test_target_name", "notify"],
lock: ["open", "lock", "unlock"],
input_select: [
'select_previous',
'set_options',
'select_next',
'select_option'
],
recorder: [
'purge'
],
persistent_notification: [
'create',
'dismiss'
],
timer: [
'pause',
'cancel',
'finish',
'start'
],
input_boolean: [
'turn_off',
'toggle',
'turn_on'
"select_previous",
"set_options",
"select_next",
"select_option",
],
recorder: ["purge"],
persistent_notification: ["create", "dismiss"],
timer: ["pause", "cancel", "finish", "start"],
input_boolean: ["turn_off", "toggle", "turn_on"],
fan: [
'set_speed',
'turn_on',
'turn_off',
'set_direction',
'oscillate',
'toggle'
"set_speed",
"turn_on",
"turn_off",
"set_direction",
"oscillate",
"toggle",
],
climate: [
'set_humidity',
'set_operation_mode',
'set_aux_heat',
'turn_on',
'set_hold_mode',
'set_away_mode',
'turn_off',
'set_fan_mode',
'set_temperature',
'set_swing_mode'
],
switch: [
'turn_off',
'toggle',
'turn_on'
],
script: [
'turn_off',
'demo',
'reload',
'toggle',
'turn_on'
],
scene: [
'turn_on'
],
system_log: [
'clear',
'write'
],
camera: [
'disable_motion_detection',
'enable_motion_detection',
'snapshot'
],
image_processing: [
'scan'
"set_humidity",
"set_operation_mode",
"set_aux_heat",
"turn_on",
"set_hold_mode",
"set_away_mode",
"turn_off",
"set_fan_mode",
"set_temperature",
"set_swing_mode",
],
switch: ["turn_off", "toggle", "turn_on"],
script: ["turn_off", "demo", "reload", "toggle", "turn_on"],
scene: ["turn_on"],
system_log: ["clear", "write"],
camera: ["disable_motion_detection", "enable_motion_detection", "snapshot"],
image_processing: ["scan"],
media_player: [
'media_previous_track',
'clear_playlist',
'shuffle_set',
'media_seek',
'turn_on',
'media_play_pause',
'media_next_track',
'media_pause',
'volume_down',
'volume_set',
'media_stop',
'toggle',
'media_play',
'play_media',
'volume_mute',
'turn_off',
'select_sound_mode',
'select_source',
'volume_up'
],
input_number: [
'set_value',
'increment',
'decrement'
],
device_tracker: [
'see'
"media_previous_track",
"clear_playlist",
"shuffle_set",
"media_seek",
"turn_on",
"media_play_pause",
"media_next_track",
"media_pause",
"volume_down",
"volume_set",
"media_stop",
"toggle",
"media_play",
"play_media",
"volume_mute",
"turn_off",
"select_sound_mode",
"select_source",
"volume_up",
],
input_number: ["set_value", "increment", "decrement"],
device_tracker: ["see"],
homeassistant: [
'stop',
'check_config',
'reload_core_config',
'turn_on',
'turn_off',
'restart',
'toggle'
"stop",
"check_config",
"reload_core_config",
"turn_on",
"turn_off",
"restart",
"toggle",
],
light: [
'turn_off',
'toggle',
'turn_on'
],
input_text: [
'set_value'
]
}
light: ["turn_off", "toggle", "turn_on"],
input_text: ["set_value"],
},
};

View File

@@ -1,253 +1,264 @@
export default {
en: {
'state.default.off': 'Off',
'state.default.on': 'On',
'state.default.unknown': 'Unknown',
'state.default.unavailable': 'Unavailable',
'state.alarm_control_panel.armed': 'Armed',
'state.alarm_control_panel.disarmed': 'Disarmed',
'state.alarm_control_panel.armed_home': 'Armed home',
'state.alarm_control_panel.armed_away': 'Armed away',
'state.alarm_control_panel.armed_night': 'Armed night',
'state.alarm_control_panel.armed_custom_bypass': 'Armed custom bypass',
'state.alarm_control_panel.pending': 'Pending',
'state.alarm_control_panel.arming': 'Arming',
'state.alarm_control_panel.disarming': 'Disarming',
'state.alarm_control_panel.triggered': 'Triggered',
'state.automation.off': 'Off',
'state.automation.on': 'On',
'state.binary_sensor.default.off': 'Off',
'state.binary_sensor.default.on': 'On',
'state.binary_sensor.battery.off': 'Normal',
'state.binary_sensor.battery.on': 'Low',
'state.binary_sensor.cold.off': 'Normal',
'state.binary_sensor.cold.on': 'Cold',
'state.binary_sensor.connectivity.off': 'Disconnected',
'state.binary_sensor.connectivity.on': 'Connected',
'state.binary_sensor.door.off': 'Closed',
'state.binary_sensor.door.on': 'Open',
'state.binary_sensor.garage_door.off': 'Closed',
'state.binary_sensor.garage_door.on': 'Open',
'state.binary_sensor.gas.off': 'Clear',
'state.binary_sensor.gas.on': 'Detected',
'state.binary_sensor.heat.off': 'Normal',
'state.binary_sensor.heat.on': 'Hot',
'state.binary_sensor.lock.off': 'Locked',
'state.binary_sensor.lock.on': 'Unlocked',
'state.binary_sensor.moisture.off': 'Dry',
'state.binary_sensor.moisture.on': 'Wet',
'state.binary_sensor.motion.off': 'Clear',
'state.binary_sensor.motion.on': 'Detected',
'state.binary_sensor.occupancy.off': 'Clear',
'state.binary_sensor.occupancy.on': 'Detected',
'state.binary_sensor.opening.off': 'Closed',
'state.binary_sensor.opening.on': 'Open',
'state.binary_sensor.presence.off': 'Away',
'state.binary_sensor.presence.on': 'Home',
'state.binary_sensor.problem.off': 'OK',
'state.binary_sensor.problem.on': 'Problem',
'state.binary_sensor.safety.off': 'Safe',
'state.binary_sensor.safety.on': 'Unsafe',
'state.binary_sensor.smoke.off': 'Clear',
'state.binary_sensor.smoke.on': 'Detected',
'state.binary_sensor.sound.off': 'Clear',
'state.binary_sensor.sound.on': 'Detected',
'state.binary_sensor.vibration.off': 'Clear',
'state.binary_sensor.vibration.on': 'Detected',
'state.binary_sensor.window.off': 'Closed',
'state.binary_sensor.window.on': 'Open',
'state.calendar.off': 'Off',
'state.calendar.on': 'On',
'state.camera.recording': 'Recording',
'state.camera.streaming': 'Streaming',
'state.camera.idle': 'Idle',
'state.climate.off': 'Off',
'state.climate.on': 'On',
'state.climate.heat': 'Heat',
'state.climate.cool': 'Cool',
'state.climate.idle': 'Idle',
'state.climate.auto': 'Auto',
'state.climate.dry': 'Dry',
'state.climate.fan_only': 'Fan only',
'state.climate.eco': 'Eco',
'state.climate.electric': 'Electric',
'state.climate.performance': 'Performance',
'state.climate.high_demand': 'High demand',
'state.climate.heat_pump': 'Heat pump',
'state.climate.gas': 'Gas',
'state.configurator.configure': 'Configure',
'state.configurator.configured': 'Configured',
'state.cover.open': 'Open',
'state.cover.opening': 'Opening',
'state.cover.closed': 'Closed',
'state.cover.closing': 'Closing',
'state.cover.stopped': 'Stopped',
'state.device_tracker.home': 'Home',
'state.device_tracker.not_home': 'Away',
'state.fan.off': 'Off',
'state.fan.on': 'On',
'state.group.off': 'Off',
'state.group.on': 'On',
'state.group.home': 'Home',
'state.group.not_home': 'Away',
'state.group.open': 'Open',
'state.group.opening': 'Opening',
'state.group.closed': 'Closed',
'state.group.closing': 'Closing',
'state.group.stopped': 'Stopped',
'state.group.locked': 'Locked',
'state.group.unlocked': 'Unlocked',
'state.group.ok': 'OK',
'state.group.problem': 'Problem',
'state.input_boolean.off': 'Off',
'state.input_boolean.on': 'On',
'state.light.off': 'Off',
'state.light.on': 'On',
'state.lock.locked': 'Locked',
'state.lock.unlocked': 'Unlocked',
'state.media_player.off': 'Off',
'state.media_player.on': 'On',
'state.media_player.playing': 'Playing',
'state.media_player.paused': 'Paused',
'state.media_player.idle': 'Idle',
'state.media_player.standby': 'Standby',
'state.plant.ok': 'OK',
'state.plant.problem': 'Problem',
'state.remote.off': 'Off',
'state.remote.on': 'On',
'state.scene.scening': 'Scening',
'state.script.off': 'Off',
'state.script.on': 'On',
'state.sensor.off': 'Off',
'state.sensor.on': 'On',
'state.sun.above_horizon': 'Above horizon',
'state.sun.below_horizon': 'Below horizon',
'state.switch.off': 'Off',
'state.switch.on': 'On',
'state.weather.clear-night': 'Clear, night',
'state.weather.cloudy': 'Cloudy',
'state.weather.fog': 'Fog',
'state.weather.hail': 'Hail',
'state.weather.lightning': 'Lightning',
'state.weather.lightning-rainy': 'Lightning, rainy',
'state.weather.partlycloudy': 'Partly cloudy',
'state.weather.pouring': 'Pouring',
'state.weather.rainy': 'Rainy',
'state.weather.snowy': 'Snowy',
'state.weather.snowy-rainy': 'Snowy, rainy',
'state.weather.sunny': 'Sunny',
'state.weather.windy': 'Windy',
'state.weather.windy-variant': 'Windy',
'state.zwave.default.initializing': 'Initializing',
'state.zwave.default.dead': 'Dead',
'state.zwave.default.sleeping': 'Sleeping',
'state.zwave.default.ready': 'Ready',
'state.zwave.query_stage.initializing': 'Initializing ({query_stage})',
'state.zwave.query_stage.dead': 'Dead ({query_stage})',
'state_badge.default.unknown': 'Unk',
'state_badge.default.unavailable': 'Unavai',
'state_badge.alarm_control_panel.armed': 'Armed',
'state_badge.alarm_control_panel.disarmed': 'Disarm',
'state_badge.alarm_control_panel.armed_home': 'Armed',
'state_badge.alarm_control_panel.armed_away': 'Armed',
'state_badge.alarm_control_panel.armed_night': 'Armed',
'state_badge.alarm_control_panel.armed_custom_bypass': 'Armed',
'state_badge.alarm_control_panel.pending': 'Pend',
'state_badge.alarm_control_panel.arming': 'Arming',
'state_badge.alarm_control_panel.disarming': 'Disarm',
'state_badge.alarm_control_panel.triggered': 'Trig',
'state_badge.device_tracker.home': 'Home',
'state_badge.device_tracker.not_home': 'Away',
'ui.card.alarm_control_panel.code': 'Code',
'ui.card.alarm_control_panel.clear_code': 'Clear',
'ui.card.alarm_control_panel.disarm': 'Disarm',
'ui.card.alarm_control_panel.arm_home': 'Arm home',
'ui.card.alarm_control_panel.arm_away': 'Arm away',
'ui.card.automation.last_triggered': 'Last triggered',
'ui.card.automation.trigger': 'Trigger',
'ui.card.camera.not_available': 'Image not available',
'ui.card.climate.currently': 'Currently',
'ui.card.climate.on_off': 'On / off',
'ui.card.climate.target_temperature': 'Target temperature',
'ui.card.climate.target_humidity': 'Target humidity',
'ui.card.climate.operation': 'Operation',
'ui.card.climate.fan_mode': 'Fan mode',
'ui.card.climate.swing_mode': 'Swing mode',
'ui.card.climate.away_mode': 'Away mode',
'ui.card.climate.aux_heat': 'Aux heat',
'ui.card.cover.position': 'Position',
'ui.card.cover.tilt_position': 'Tilt position',
'ui.card.fan.speed': 'Speed',
'ui.card.fan.oscillate': 'Oscillate',
'ui.card.fan.direction': 'Direction',
'ui.card.light.brightness': 'Brightness',
'ui.card.light.color_temperature': 'Color temperature',
'ui.card.light.white_value': 'White value',
'ui.card.light.effect': 'Effect',
'ui.card.lock.code': 'Code',
'ui.card.lock.lock': 'Lock',
'ui.card.lock.unlock': 'Unlock',
'ui.card.media_player.source': 'Source',
'ui.card.media_player.sound_mode': 'Sound mode',
'ui.card.media_player.text_to_speak': 'Text to speak',
'ui.card.persistent_notification.dismiss': 'Dismiss',
'ui.card.scene.activate': 'Activate',
'ui.card.script.execute': 'Execute',
'ui.card.weather.attributes.air_pressure': 'Air pressure',
'ui.card.weather.attributes.humidity': 'Humidity',
'ui.card.weather.attributes.temperature': 'Temperature',
'ui.card.weather.attributes.visibility': 'Visibility',
'ui.card.weather.attributes.wind_speed': 'Wind speed',
'ui.card.weather.cardinal_direction.e': 'E',
'ui.card.weather.cardinal_direction.ene': 'ENE',
'ui.card.weather.cardinal_direction.ese': 'ESE',
'ui.card.weather.cardinal_direction.n': 'N',
'ui.card.weather.cardinal_direction.ne': 'NE',
'ui.card.weather.cardinal_direction.nne': 'NNE',
'ui.card.weather.cardinal_direction.nw': 'NW',
'ui.card.weather.cardinal_direction.nnw': 'NNW',
'ui.card.weather.cardinal_direction.s': 'S',
'ui.card.weather.cardinal_direction.se': 'SE',
'ui.card.weather.cardinal_direction.sse': 'SSE',
'ui.card.weather.cardinal_direction.ssw': 'SSW',
'ui.card.weather.cardinal_direction.sw': 'SW',
'ui.card.weather.cardinal_direction.w': 'W',
'ui.card.weather.cardinal_direction.wnw': 'WNW',
'ui.card.weather.cardinal_direction.wsw': 'WSW',
'ui.card.weather.forecast': 'Forecast',
'ui.common.loading': 'Loading',
'ui.common.cancel': 'Cancel',
'ui.components.entity.entity-picker.entity': 'Entity',
'ui.components.relative_time.past': '{time} ago',
'ui.components.relative_time.future': 'In {time}',
'ui.components.relative_time.never': 'Never',
'ui.components.relative_time.duration.second': '{count} {count, plural,\n one {second}\n other {seconds}\n}',
'ui.components.relative_time.duration.minute': '{count} {count, plural,\n one {minute}\n other {minutes}\n}',
'ui.components.relative_time.duration.hour': '{count} {count, plural,\n one {hour}\n other {hours}\n}',
'ui.components.relative_time.duration.day': '{count} {count, plural,\n one {day}\n other {days}\n}',
'ui.components.relative_time.duration.week': '{count} {count, plural,\n one {week}\n other {weeks}\n}',
'ui.components.history_charts.loading_history': 'Loading state history...',
'ui.components.history_charts.no_history_found': 'No state history found.',
'ui.components.service-picker.service': 'Service',
'ui.dialogs.more_info_settings.save': 'Save',
'ui.dialogs.more_info_settings.name': 'Name',
'ui.duration.second': '{count} {count, plural,\n one {second}\n other {seconds}\n}',
'ui.duration.minute': '{count} {count, plural,\n one {minute}\n other {minutes}\n}',
'ui.duration.hour': '{count} {count, plural,\n one {hour}\n other {hours}\n}',
'ui.duration.day': '{count} {count, plural,\n one {day}\n other {days}\n}',
'ui.duration.week': '{count} {count, plural,\n one {week}\n other {weeks}\n}',
'ui.login-form.password': 'Password',
'ui.login-form.remember': 'Remember',
'ui.login-form.log_in': 'Log in',
'ui.notification_toast.entity_turned_on': 'Turned on {entity}.',
'ui.notification_toast.entity_turned_off': 'Turned off {entity}.',
'ui.notification_toast.service_called': 'Service {service} called.',
'ui.notification_toast.service_call_failed': 'Failed to call service {service}.',
'ui.notification_toast.connection_lost': 'Connection lost. Reconnecting…',
'ui.sidebar.developer_tools': 'Developer tools',
'ui.sidebar.log_out': 'Log out',
'attribute.weather.humidity': 'Humidity',
'attribute.weather.visibility': 'Visibility',
'attribute.weather.wind_speed': 'Wind speed',
}
"state.default.off": "Off",
"state.default.on": "On",
"state.default.unknown": "Unknown",
"state.default.unavailable": "Unavailable",
"state.alarm_control_panel.armed": "Armed",
"state.alarm_control_panel.disarmed": "Disarmed",
"state.alarm_control_panel.armed_home": "Armed home",
"state.alarm_control_panel.armed_away": "Armed away",
"state.alarm_control_panel.armed_night": "Armed night",
"state.alarm_control_panel.armed_custom_bypass": "Armed custom bypass",
"state.alarm_control_panel.pending": "Pending",
"state.alarm_control_panel.arming": "Arming",
"state.alarm_control_panel.disarming": "Disarming",
"state.alarm_control_panel.triggered": "Triggered",
"state.automation.off": "Off",
"state.automation.on": "On",
"state.binary_sensor.default.off": "Off",
"state.binary_sensor.default.on": "On",
"state.binary_sensor.battery.off": "Normal",
"state.binary_sensor.battery.on": "Low",
"state.binary_sensor.cold.off": "Normal",
"state.binary_sensor.cold.on": "Cold",
"state.binary_sensor.connectivity.off": "Disconnected",
"state.binary_sensor.connectivity.on": "Connected",
"state.binary_sensor.door.off": "Closed",
"state.binary_sensor.door.on": "Open",
"state.binary_sensor.garage_door.off": "Closed",
"state.binary_sensor.garage_door.on": "Open",
"state.binary_sensor.gas.off": "Clear",
"state.binary_sensor.gas.on": "Detected",
"state.binary_sensor.heat.off": "Normal",
"state.binary_sensor.heat.on": "Hot",
"state.binary_sensor.lock.off": "Locked",
"state.binary_sensor.lock.on": "Unlocked",
"state.binary_sensor.moisture.off": "Dry",
"state.binary_sensor.moisture.on": "Wet",
"state.binary_sensor.motion.off": "Clear",
"state.binary_sensor.motion.on": "Detected",
"state.binary_sensor.occupancy.off": "Clear",
"state.binary_sensor.occupancy.on": "Detected",
"state.binary_sensor.opening.off": "Closed",
"state.binary_sensor.opening.on": "Open",
"state.binary_sensor.presence.off": "Away",
"state.binary_sensor.presence.on": "Home",
"state.binary_sensor.problem.off": "OK",
"state.binary_sensor.problem.on": "Problem",
"state.binary_sensor.safety.off": "Safe",
"state.binary_sensor.safety.on": "Unsafe",
"state.binary_sensor.smoke.off": "Clear",
"state.binary_sensor.smoke.on": "Detected",
"state.binary_sensor.sound.off": "Clear",
"state.binary_sensor.sound.on": "Detected",
"state.binary_sensor.vibration.off": "Clear",
"state.binary_sensor.vibration.on": "Detected",
"state.binary_sensor.window.off": "Closed",
"state.binary_sensor.window.on": "Open",
"state.calendar.off": "Off",
"state.calendar.on": "On",
"state.camera.recording": "Recording",
"state.camera.streaming": "Streaming",
"state.camera.idle": "Idle",
"state.climate.off": "Off",
"state.climate.on": "On",
"state.climate.heat": "Heat",
"state.climate.cool": "Cool",
"state.climate.idle": "Idle",
"state.climate.auto": "Auto",
"state.climate.dry": "Dry",
"state.climate.fan_only": "Fan only",
"state.climate.eco": "Eco",
"state.climate.electric": "Electric",
"state.climate.performance": "Performance",
"state.climate.high_demand": "High demand",
"state.climate.heat_pump": "Heat pump",
"state.climate.gas": "Gas",
"state.configurator.configure": "Configure",
"state.configurator.configured": "Configured",
"state.cover.open": "Open",
"state.cover.opening": "Opening",
"state.cover.closed": "Closed",
"state.cover.closing": "Closing",
"state.cover.stopped": "Stopped",
"state.device_tracker.home": "Home",
"state.device_tracker.not_home": "Away",
"state.fan.off": "Off",
"state.fan.on": "On",
"state.group.off": "Off",
"state.group.on": "On",
"state.group.home": "Home",
"state.group.not_home": "Away",
"state.group.open": "Open",
"state.group.opening": "Opening",
"state.group.closed": "Closed",
"state.group.closing": "Closing",
"state.group.stopped": "Stopped",
"state.group.locked": "Locked",
"state.group.unlocked": "Unlocked",
"state.group.ok": "OK",
"state.group.problem": "Problem",
"state.input_boolean.off": "Off",
"state.input_boolean.on": "On",
"state.light.off": "Off",
"state.light.on": "On",
"state.lock.locked": "Locked",
"state.lock.unlocked": "Unlocked",
"state.media_player.off": "Off",
"state.media_player.on": "On",
"state.media_player.playing": "Playing",
"state.media_player.paused": "Paused",
"state.media_player.idle": "Idle",
"state.media_player.standby": "Standby",
"state.plant.ok": "OK",
"state.plant.problem": "Problem",
"state.remote.off": "Off",
"state.remote.on": "On",
"state.scene.scening": "Scening",
"state.script.off": "Off",
"state.script.on": "On",
"state.sensor.off": "Off",
"state.sensor.on": "On",
"state.sun.above_horizon": "Above horizon",
"state.sun.below_horizon": "Below horizon",
"state.switch.off": "Off",
"state.switch.on": "On",
"state.weather.clear-night": "Clear, night",
"state.weather.cloudy": "Cloudy",
"state.weather.fog": "Fog",
"state.weather.hail": "Hail",
"state.weather.lightning": "Lightning",
"state.weather.lightning-rainy": "Lightning, rainy",
"state.weather.partlycloudy": "Partly cloudy",
"state.weather.pouring": "Pouring",
"state.weather.rainy": "Rainy",
"state.weather.snowy": "Snowy",
"state.weather.snowy-rainy": "Snowy, rainy",
"state.weather.sunny": "Sunny",
"state.weather.windy": "Windy",
"state.weather.windy-variant": "Windy",
"state.zwave.default.initializing": "Initializing",
"state.zwave.default.dead": "Dead",
"state.zwave.default.sleeping": "Sleeping",
"state.zwave.default.ready": "Ready",
"state.zwave.query_stage.initializing": "Initializing ({query_stage})",
"state.zwave.query_stage.dead": "Dead ({query_stage})",
"state_badge.default.unknown": "Unk",
"state_badge.default.unavailable": "Unavai",
"state_badge.alarm_control_panel.armed": "Armed",
"state_badge.alarm_control_panel.disarmed": "Disarm",
"state_badge.alarm_control_panel.armed_home": "Armed",
"state_badge.alarm_control_panel.armed_away": "Armed",
"state_badge.alarm_control_panel.armed_night": "Armed",
"state_badge.alarm_control_panel.armed_custom_bypass": "Armed",
"state_badge.alarm_control_panel.pending": "Pend",
"state_badge.alarm_control_panel.arming": "Arming",
"state_badge.alarm_control_panel.disarming": "Disarm",
"state_badge.alarm_control_panel.triggered": "Trig",
"state_badge.device_tracker.home": "Home",
"state_badge.device_tracker.not_home": "Away",
"ui.card.alarm_control_panel.code": "Code",
"ui.card.alarm_control_panel.clear_code": "Clear",
"ui.card.alarm_control_panel.disarm": "Disarm",
"ui.card.alarm_control_panel.arm_home": "Arm home",
"ui.card.alarm_control_panel.arm_away": "Arm away",
"ui.card.automation.last_triggered": "Last triggered",
"ui.card.automation.trigger": "Trigger",
"ui.card.camera.not_available": "Image not available",
"ui.card.climate.currently": "Currently",
"ui.card.climate.on_off": "On / off",
"ui.card.climate.target_temperature": "Target temperature",
"ui.card.climate.target_humidity": "Target humidity",
"ui.card.climate.operation": "Operation",
"ui.card.climate.fan_mode": "Fan mode",
"ui.card.climate.swing_mode": "Swing mode",
"ui.card.climate.away_mode": "Away mode",
"ui.card.climate.aux_heat": "Aux heat",
"ui.card.cover.position": "Position",
"ui.card.cover.tilt_position": "Tilt position",
"ui.card.fan.speed": "Speed",
"ui.card.fan.oscillate": "Oscillate",
"ui.card.fan.direction": "Direction",
"ui.card.light.brightness": "Brightness",
"ui.card.light.color_temperature": "Color temperature",
"ui.card.light.white_value": "White value",
"ui.card.light.effect": "Effect",
"ui.card.lock.code": "Code",
"ui.card.lock.lock": "Lock",
"ui.card.lock.unlock": "Unlock",
"ui.card.media_player.source": "Source",
"ui.card.media_player.sound_mode": "Sound mode",
"ui.card.media_player.text_to_speak": "Text to speak",
"ui.card.persistent_notification.dismiss": "Dismiss",
"ui.card.scene.activate": "Activate",
"ui.card.script.execute": "Execute",
"ui.card.weather.attributes.air_pressure": "Air pressure",
"ui.card.weather.attributes.humidity": "Humidity",
"ui.card.weather.attributes.temperature": "Temperature",
"ui.card.weather.attributes.visibility": "Visibility",
"ui.card.weather.attributes.wind_speed": "Wind speed",
"ui.card.weather.cardinal_direction.e": "E",
"ui.card.weather.cardinal_direction.ene": "ENE",
"ui.card.weather.cardinal_direction.ese": "ESE",
"ui.card.weather.cardinal_direction.n": "N",
"ui.card.weather.cardinal_direction.ne": "NE",
"ui.card.weather.cardinal_direction.nne": "NNE",
"ui.card.weather.cardinal_direction.nw": "NW",
"ui.card.weather.cardinal_direction.nnw": "NNW",
"ui.card.weather.cardinal_direction.s": "S",
"ui.card.weather.cardinal_direction.se": "SE",
"ui.card.weather.cardinal_direction.sse": "SSE",
"ui.card.weather.cardinal_direction.ssw": "SSW",
"ui.card.weather.cardinal_direction.sw": "SW",
"ui.card.weather.cardinal_direction.w": "W",
"ui.card.weather.cardinal_direction.wnw": "WNW",
"ui.card.weather.cardinal_direction.wsw": "WSW",
"ui.card.weather.forecast": "Forecast",
"ui.common.loading": "Loading",
"ui.common.cancel": "Cancel",
"ui.components.entity.entity-picker.entity": "Entity",
"ui.components.relative_time.past": "{time} ago",
"ui.components.relative_time.future": "In {time}",
"ui.components.relative_time.never": "Never",
"ui.components.relative_time.duration.second":
"{count} {count, plural,\n one {second}\n other {seconds}\n}",
"ui.components.relative_time.duration.minute":
"{count} {count, plural,\n one {minute}\n other {minutes}\n}",
"ui.components.relative_time.duration.hour":
"{count} {count, plural,\n one {hour}\n other {hours}\n}",
"ui.components.relative_time.duration.day":
"{count} {count, plural,\n one {day}\n other {days}\n}",
"ui.components.relative_time.duration.week":
"{count} {count, plural,\n one {week}\n other {weeks}\n}",
"ui.components.history_charts.loading_history": "Loading state history...",
"ui.components.history_charts.no_history_found": "No state history found.",
"ui.components.service-picker.service": "Service",
"ui.dialogs.more_info_settings.save": "Save",
"ui.dialogs.more_info_settings.name": "Name",
"ui.duration.second":
"{count} {count, plural,\n one {second}\n other {seconds}\n}",
"ui.duration.minute":
"{count} {count, plural,\n one {minute}\n other {minutes}\n}",
"ui.duration.hour":
"{count} {count, plural,\n one {hour}\n other {hours}\n}",
"ui.duration.day":
"{count} {count, plural,\n one {day}\n other {days}\n}",
"ui.duration.week":
"{count} {count, plural,\n one {week}\n other {weeks}\n}",
"ui.login-form.password": "Password",
"ui.login-form.remember": "Remember",
"ui.login-form.log_in": "Log in",
"ui.notification_toast.entity_turned_on": "Turned on {entity}.",
"ui.notification_toast.entity_turned_off": "Turned off {entity}.",
"ui.notification_toast.service_called": "Service {service} called.",
"ui.notification_toast.service_call_failed":
"Failed to call service {service}.",
"ui.notification_toast.connection_lost": "Connection lost. Reconnecting…",
"ui.sidebar.developer_tools": "Developer tools",
"ui.sidebar.log_out": "Log out",
"attribute.weather.humidity": "Humidity",
"attribute.weather.visibility": "Visibility",
"attribute.weather.wind_speed": "Wind speed",
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
const now = () => new Date().toISOString();
const randomTime = () =>
new Date(new Date().getTime() - (Math.random() * 80 * 60 * 1000)).toISOString();
new Date(new Date().getTime() - Math.random() * 80 * 60 * 1000).toISOString();
/* eslint-disable no-unused-vars */
@@ -18,19 +18,23 @@ export class Entity {
}
async handleService(domain, service, data) {
console.log(`Unmocked service for ${this.entityId}: ${domain}/${service}`, data);
console.log(
`Unmocked service for ${this.entityId}: ${domain}/${service}`,
data
);
}
update(state, attributes = {}) {
this.state = state;
this.lastUpdated = now();
this.lastChanged = state === this.state ? this.lastChanged : this.lastUpdated;
this.lastChanged =
state === this.state ? this.lastChanged : this.lastUpdated;
this.attributes = Object.assign({}, this.baseAttributes, attributes);
console.log('update', this.entityId, this);
console.log("update", this.entityId, this);
this.hass.updateStates({
[this.entityId]: this.toState()
[this.entityId]: this.toState(),
});
}
@@ -47,22 +51,25 @@ export class Entity {
export class LightEntity extends Entity {
async handleService(domain, service, data) {
if (!['homeassistant', this.domain].includes(domain)) return;
if (!["homeassistant", this.domain].includes(domain)) return;
if (service === 'turn_on') {
if (service === "turn_on") {
// eslint-disable-next-line
const { brightness, hs_color } = data;
this.update('on', Object.assign(this.attributes, {
this.update(
"on",
Object.assign(this.attributes, {
brightness,
hs_color,
}));
} else if (service === 'turn_off') {
this.update('off');
} else if (service === 'toggle') {
if (this.state === 'on') {
this.handleService(domain, 'turn_off', data);
})
);
} else if (service === "turn_off") {
this.update("off");
} else if (service === "toggle") {
if (this.state === "on") {
this.handleService(domain, "turn_off", data);
} else {
this.handleService(domain, 'turn_on', data);
this.handleService(domain, "turn_on", data);
}
}
}
@@ -72,10 +79,10 @@ export class LockEntity extends Entity {
async handleService(domain, service, data) {
if (domain !== this.domain) return;
if (service === 'lock') {
this.update('locked');
} else if (service === 'unlock') {
this.update('unlocked');
if (service === "lock") {
this.update("locked");
} else if (service === "unlock") {
this.update("unlocked");
}
}
}
@@ -84,24 +91,26 @@ export class CoverEntity extends Entity {
async handleService(domain, service, data) {
if (domain !== this.domain) return;
if (service === 'open_cover') {
this.update('open');
} else if (service === 'close_cover') {
this.update('closing');
if (service === "open_cover") {
this.update("open");
} else if (service === "close_cover") {
this.update("closing");
}
}
}
export class GroupEntity extends Entity {
async handleService(domain, service, data) {
if (!['homeassistant', this.domain].includes(domain)) return;
if (!["homeassistant", this.domain].includes(domain)) return;
await Promise.all(this.attributes.entity_id.map((ent) => {
await Promise.all(
this.attributes.entity_id.map((ent) => {
const entity = this.hass.mockEntities[ent];
return entity.handleService(entity.domain, service, data);
}));
})
);
this.update(service === 'turn_on' ? 'on' : 'off');
this.update(service === "turn_on" ? "on" : "off");
}
}

View File

@@ -9,15 +9,17 @@ export default class FakeHass {
}
async callService(domain, service, serviceData) {
console.log('callService', { domain, service, serviceData });
console.log("callService", { domain, service, serviceData });
return Promise.resolve();
}
async callWS(msg) {
const callback = this._wsCommands[msg.type];
return callback ? callback(msg) : Promise.reject({
code: 'command_not_mocked',
message: 'This command is not implemented in the gallery.',
return callback
? callback(msg)
: Promise.reject({
code: "command_not_mocked",
message: "This command is not implemented in the gallery.",
});
}
@@ -29,6 +31,6 @@ export default class FakeHass {
} else {
console.error(`Unknown command: ${msg.type}`);
}
console.log('sendWS', msg);
console.log("sendWS", msg);
}
}

View File

@@ -1,9 +1,9 @@
import fireEvent from '../../../src/common/dom/fire_event.js';
import fireEvent from "../../../src/common/dom/fire_event.js";
import demoConfig from './demo_config.js';
import demoResources from './demo_resources.js';
import demoConfig from "./demo_config.js";
import demoResources from "./demo_resources.js";
const ensureArray = val => (Array.isArray(val) ? val : [val]);
const ensureArray = (val) => (Array.isArray(val) ? val : [val]);
export default (elements, { initialStates = {} } = {}) => {
elements = ensureArray(elements);
@@ -14,13 +14,15 @@ export default (elements, { initialStates = {} } = {}) => {
function updateHass(obj) {
hass = Object.assign({}, hass, obj);
elements.forEach((el) => { el.hass = hass; });
elements.forEach((el) => {
el.hass = hass;
});
}
updateHass({
// Home Assistant properties
config: demoConfig,
language: 'en',
language: "en",
resources: demoResources,
states: initialStates,
@@ -29,20 +31,27 @@ export default (elements, { initialStates = {} } = {}) => {
// Home Assistant functions
async callService(domain, service, data) {
fireEvent(elements[0], 'show-notification', { message: `Called service ${domain}/${service}` });
fireEvent(elements[0], "show-notification", {
message: `Called service ${domain}/${service}`,
});
if (data.entity_id) {
await Promise.all(ensureArray(data.entity_id).map(ent =>
entities[ent].handleService(domain, service, data)));
await Promise.all(
ensureArray(data.entity_id).map((ent) =>
entities[ent].handleService(domain, service, data)
)
);
} else {
console.log('unmocked callService', domain, service, data);
console.log("unmocked callService", domain, service, data);
}
},
async callWS(msg) {
const callback = wsCommands[msg.type];
return callback ? callback(msg) : Promise.reject({
code: 'command_not_mocked',
message: 'This command is not implemented in the gallery.',
return callback
? callback(msg)
: Promise.reject({
code: "command_not_mocked",
message: "This command is not implemented in the gallery.",
});
},
@@ -54,7 +63,7 @@ export default (elements, { initialStates = {} } = {}) => {
} else {
console.error(`Unknown command: ${msg.type}`);
}
console.log('sendWS', msg);
console.log("sendWS", msg);
},
// Mock functions
@@ -72,7 +81,7 @@ export default (elements, { initialStates = {} } = {}) => {
states[ent.entityId] = ent.toState();
});
this.updateStates(states);
}
},
});
return hass;

View File

@@ -1,28 +1,28 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import getEntity from '../data/entity.js';
import provideHass from '../data/provide_hass.js';
import '../components/demo-cards.js';
import getEntity from "../data/entity.js";
import provideHass from "../data/provide_hass.js";
import "../components/demo-cards.js";
const ENTITIES = [
getEntity('light', 'controller_1', 'on', {
friendly_name: 'Controller 1'
getEntity("light", "controller_1", "on", {
friendly_name: "Controller 1",
}),
getEntity('light', 'controller_2', 'on', {
friendly_name: 'Controller 2'
getEntity("light", "controller_2", "on", {
friendly_name: "Controller 2",
}),
getEntity('light', 'floor', 'off', {
friendly_name: 'Floor light'
getEntity("light", "floor", "off", {
friendly_name: "Floor light",
}),
getEntity('light', 'kitchen', 'on', {
friendly_name: 'Kitchen light'
getEntity("light", "kitchen", "on", {
friendly_name: "Kitchen light",
}),
];
const CONFIGS = [
{
heading: 'Controller',
heading: "Controller",
config: `
- type: entities
entities:
@@ -31,10 +31,10 @@ const CONFIGS = [
- type: divider
- light.floor
- light.kitchen
`
`,
},
{
heading: 'Demo',
heading: "Demo",
config: `
- type: conditional
conditions:
@@ -49,7 +49,7 @@ const CONFIGS = [
- light.controller_2
- light.floor
- light.kitchen
`
`,
},
];
@@ -68,7 +68,7 @@ class DemoConditional extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
value: CONFIGS,
},
hass: Object,
};
@@ -81,4 +81,4 @@ class DemoConditional extends PolymerElement {
}
}
customElements.define('demo-hui-conditional-card', DemoConditional);
customElements.define("demo-hui-conditional-card", DemoConditional);

View File

@@ -1,75 +1,70 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import getEntity from '../data/entity.js';
import provideHass from '../data/provide_hass.js';
import '../components/demo-cards.js';
import getEntity from "../data/entity.js";
import provideHass from "../data/provide_hass.js";
import "../components/demo-cards.js";
const ENTITIES = [
getEntity('light', 'bed_light', 'on', {
friendly_name: 'Bed Light'
getEntity("light", "bed_light", "on", {
friendly_name: "Bed Light",
}),
getEntity('group', 'kitchen', 'on', {
entity_id: [
'light.bed_light',
],
getEntity("group", "kitchen", "on", {
entity_id: ["light.bed_light"],
order: 8,
friendly_name: 'Kitchen'
friendly_name: "Kitchen",
}),
getEntity('lock', 'kitchen_door', 'locked', {
friendly_name: 'Kitchen Door'
getEntity("lock", "kitchen_door", "locked", {
friendly_name: "Kitchen Door",
}),
getEntity('cover', 'kitchen_window', 'open', {
friendly_name: 'Kitchen Window',
supported_features: 11
getEntity("cover", "kitchen_window", "open", {
friendly_name: "Kitchen Window",
supported_features: 11,
}),
getEntity('scene', 'romantic_lights', 'scening', {
entity_id: [
'light.bed_light',
'light.ceiling_lights'
],
friendly_name: 'Romantic lights'
getEntity("scene", "romantic_lights", "scening", {
entity_id: ["light.bed_light", "light.ceiling_lights"],
friendly_name: "Romantic lights",
}),
getEntity('device_tracker', 'demo_paulus', 'home', {
source_type: 'gps',
getEntity("device_tracker", "demo_paulus", "home", {
source_type: "gps",
latitude: 32.877105,
longitude: 117.232185,
gps_accuracy: 91,
battery: 71,
friendly_name: 'Paulus'
friendly_name: "Paulus",
}),
getEntity('climate', 'ecobee', 'auto', {
getEntity("climate", "ecobee", "auto", {
current_temperature: 73,
min_temp: 45,
max_temp: 95,
temperature: null,
target_temp_high: 75,
target_temp_low: 70,
fan_mode: 'Auto Low',
fan_list: ['On Low', 'On High', 'Auto Low', 'Auto High', 'Off'],
operation_mode: 'auto',
operation_list: ['heat', 'cool', 'auto', 'off'],
hold_mode: 'home',
swing_mode: 'Auto',
swing_list: ['Auto', '1', '2', '3', 'Off'],
unit_of_measurement: '°F',
friendly_name: 'Ecobee',
supported_features: 1014
fan_mode: "Auto Low",
fan_list: ["On Low", "On High", "Auto Low", "Auto High", "Off"],
operation_mode: "auto",
operation_list: ["heat", "cool", "auto", "off"],
hold_mode: "home",
swing_mode: "Auto",
swing_list: ["Auto", "1", "2", "3", "Off"],
unit_of_measurement: "°F",
friendly_name: "Ecobee",
supported_features: 1014,
}),
getEntity('input_number', 'noise_allowance', 5, {
getEntity("input_number", "noise_allowance", 5, {
min: 0,
max: 10,
step: 1,
mode: 'slider',
unit_of_measurement: 'dB',
friendly_name: 'Allowed Noise',
icon: 'mdi:bell-ring'
})
mode: "slider",
unit_of_measurement: "dB",
friendly_name: "Allowed Noise",
icon: "mdi:bell-ring",
}),
];
const CONFIGS = [
{
heading: 'Basic',
heading: "Basic",
config: `
- type: entities
entities:
@@ -82,10 +77,10 @@ const CONFIGS = [
- light.non_existing
- climate.ecobee
- input_number.noise_allowance
`
`,
},
{
heading: 'With title, toggle-able',
heading: "With title, toggle-able",
config: `
- type: entities
entities:
@@ -98,10 +93,10 @@ const CONFIGS = [
- climate.ecobee
- input_number.noise_allowance
title: Random group
`
`,
},
{
heading: 'With title, toggle = false',
heading: "With title, toggle = false",
config: `
- type: entities
entities:
@@ -115,19 +110,19 @@ const CONFIGS = [
- input_number.noise_allowance
title: Random group
show_header_toggle: false
`
`,
},
{
heading: 'With title, can\'t toggle',
heading: "With title, can't toggle",
config: `
- type: entities
entities:
- device_tracker.demo_paulus
title: Random group
`
`,
},
{
heading: 'Custom name, secondary info, custom icon',
heading: "Custom name, secondary info, custom icon",
config: `
- type: entities
entities:
@@ -147,10 +142,10 @@ const CONFIGS = [
- input_number.noise_allowance
title: Random group
show_header_toggle: false
`
`,
},
{
heading: 'Special rows',
heading: "Special rows",
config: `
- type: entities
entities:
@@ -171,7 +166,7 @@ const CONFIGS = [
height: 30px
margin: 4px 0
background: center / contain url("/images/divider.png") no-repeat
`
`,
},
];
@@ -190,7 +185,7 @@ class DemoEntities extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
value: CONFIGS,
},
hass: Object,
};
@@ -203,4 +198,4 @@ class DemoEntities extends PolymerElement {
}
}
customElements.define('demo-hui-entities-card', DemoEntities);
customElements.define("demo-hui-entities-card", DemoEntities);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Basic',
heading: "Basic",
config: `
- type: entity-filter
entities:
@@ -18,10 +18,10 @@ const CONFIGS = [
state_filter:
- "on"
- not_home
`
`,
},
{
heading: 'With card config',
heading: "With card config",
config: `
- type: entity-filter
entities:
@@ -37,10 +37,10 @@ const CONFIGS = [
card:
type: glance
show_state: false
`
`,
},
{
heading: 'Showing single entity conditionally',
heading: "Showing single entity conditionally",
config: `
- type: entity-filter
entities:
@@ -50,8 +50,8 @@ const CONFIGS = [
card:
type: media-control
entity: media_player.lounge_room
`
}
`,
},
];
class DemoFilter extends PolymerElement {
@@ -65,10 +65,10 @@ class DemoFilter extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-entity-filter-card', DemoFilter);
customElements.define("demo-hui-entity-filter-card", DemoFilter);

View File

@@ -1,34 +1,34 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Basic example',
heading: "Basic example",
config: `
- type: gauge
entity: sensor.brightness
`
`,
},
{
heading: 'With title',
heading: "With title",
config: `
- type: gauge
title: Humidity
entity: sensor.outside_humidity
`
`,
},
{
heading: 'Custom Unit of Measurement',
heading: "Custom Unit of Measurement",
config: `
- type: gauge
entity: sensor.outside_temperature
unit_of_measurement: C
`
`,
},
{
heading: 'Setting Severity Levels',
heading: "Setting Severity Levels",
config: `
- type: gauge
entity: sensor.brightness
@@ -36,30 +36,30 @@ const CONFIGS = [
red: 32
green: 0
yellow: 23
`
`,
},
{
heading: 'Setting Min and Max Values',
heading: "Setting Min and Max Values",
config: `
- type: gauge
entity: sensor.brightness
min: 0
max: 38
`
`,
},
{
heading: 'Invalid Entity',
heading: "Invalid Entity",
config: `
- type: gauge
entity: sensor.invalid_entity
`
`,
},
{
heading: 'Non-Numeric Value',
heading: "Non-Numeric Value",
config: `
- type: gauge
entity: plant.bonsai
`
`,
},
];
@@ -74,10 +74,10 @@ class DemoGaugeEntity extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-gauge-card', DemoGaugeEntity);
customElements.define("demo-hui-gauge-card", DemoGaugeEntity);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Basic example',
heading: "Basic example",
config: `
- type: glance
entities:
@@ -16,10 +16,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'With title',
heading: "With title",
config: `
- type: glance
title: This is glance
@@ -31,10 +31,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'Custom column width',
heading: "Custom column width",
config: `
- type: glance
column_width: calc(100% / 7)
@@ -46,10 +46,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'No name',
heading: "No name",
config: `
- type: glance
show_name: false
@@ -61,10 +61,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'No state',
heading: "No state",
config: `
- type: glance
show_state: false
@@ -76,10 +76,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'No name and no state',
heading: "No name and no state",
config: `
- type: glance
show_name: false
@@ -92,10 +92,10 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'Custom name, custom icon',
heading: "Custom name, custom icon",
config: `
- type: glance
entities:
@@ -109,10 +109,10 @@ const CONFIGS = [
icon: mdi:alarm-light
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
{
heading: 'Custom tap action',
heading: "Custom tap action",
config: `
- type: glance
entities:
@@ -126,10 +126,10 @@ const CONFIGS = [
- sun.sun
- cover.kitchen_window
- light.kitchen_lights
`
`,
},
{
heading: 'Selectively hidden name',
heading: "Selectively hidden name",
config: `
- type: glance
entities:
@@ -140,10 +140,10 @@ const CONFIGS = [
- entity: cover.kitchen_window
name:
- light.kitchen_lights
`
`,
},
{
heading: 'Primary theme',
heading: "Primary theme",
config: `
- type: glance
theming: primary
@@ -155,7 +155,7 @@ const CONFIGS = [
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`
`,
},
];
@@ -170,10 +170,10 @@ class DemoPicEntity extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-glance-card', DemoPicEntity);
customElements.define("demo-hui-glance-card", DemoPicEntity);

View File

@@ -1,39 +1,39 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Without title',
heading: "Without title",
config: `
- type: iframe
url: https://embed.windy.com/embed2.html
`
`,
},
{
heading: 'With title',
heading: "With title",
config: `
- type: iframe
url: https://embed.windy.com/embed2.html
title: Weather radar
`
`,
},
{
heading: 'Height-Width 3:4',
heading: "Height-Width 3:4",
config: `
- type: iframe
url: https://embed.windy.com/embed2.html
aspect_ratio: 75%
`
`,
},
{
heading: 'Height-Width 1:1',
heading: "Height-Width 1:1",
config: `
- type: iframe
url: https://embed.windy.com/embed2.html
aspect_ratio: 100%
`
`,
},
];
@@ -48,10 +48,10 @@ class DemoIframe extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-iframe-card', DemoIframe);
customElements.define("demo-hui-iframe-card", DemoIframe);

View File

@@ -1,120 +1,120 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import getEntity from '../data/entity.js';
import provideHass from '../data/provide_hass.js';
import '../components/demo-cards.js';
import getEntity from "../data/entity.js";
import provideHass from "../data/provide_hass.js";
import "../components/demo-cards.js";
const ENTITIES = [
getEntity('device_tracker', 'demo_paulus', 'not_home', {
source_type: 'gps',
getEntity("device_tracker", "demo_paulus", "not_home", {
source_type: "gps",
latitude: 32.877105,
longitude: 117.232185,
gps_accuracy: 91,
battery: 71,
friendly_name: 'Paulus'
friendly_name: "Paulus",
}),
getEntity('device_tracker', 'demo_home_boy', 'home', {
source_type: 'gps',
getEntity("device_tracker", "demo_home_boy", "home", {
source_type: "gps",
latitude: 32.87334,
longitude: 117.22745,
gps_accuracy: 20,
battery: 53,
friendly_name: 'Home Boy'
friendly_name: "Home Boy",
}),
getEntity('zone', 'home', 'zoning', {
getEntity("zone", "home", "zoning", {
latitude: 32.87354,
longitude: 117.22765,
radius: 100,
friendly_name: 'Home',
icon: 'mdi:home'
})
friendly_name: "Home",
icon: "mdi:home",
}),
];
const CONFIGS = [
{
heading: 'Without title',
heading: "Without title",
config: `
- type: map
entities:
- entity: device_tracker.demo_paulus
- device_tracker.demo_home_boy
- zone.home
`
`,
},
{
heading: 'With title',
heading: "With title",
config: `
- type: map
entities:
- entity: device_tracker.demo_paulus
- zone.home
title: Where is Paulus?
`
`,
},
{
heading: 'Height-Width 1:2',
heading: "Height-Width 1:2",
config: `
- type: map
entities:
- entity: device_tracker.demo_paulus
- zone.home
aspect_ratio: 50%
`
`,
},
{
heading: 'Default Zoom',
heading: "Default Zoom",
config: `
- type: map
default_zoom: 12
entities:
- entity: device_tracker.demo_paulus
- zone.home
`
`,
},
{
heading: 'Default Zoom too High',
heading: "Default Zoom too High",
config: `
- type: map
default_zoom: 20
entities:
- entity: device_tracker.demo_paulus
- zone.home
`
`,
},
{
heading: 'Single Marker',
heading: "Single Marker",
config: `
- type: map
entities:
- device_tracker.demo_paulus
`
`,
},
{
heading: 'Single Marker Default Zoom',
heading: "Single Marker Default Zoom",
config: `
- type: map
default_zoom: 8
entities:
- device_tracker.demo_paulus
`
`,
},
{
heading: 'No Entities',
heading: "No Entities",
config: `
- type: map
entities:
- light.bed_light
`
`,
},
{
heading: 'No Entities, Default Zoom',
heading: "No Entities, Default Zoom",
config: `
- type: map
default_zoom: 8
entities:
- light.bed_light
`
`,
},
];
@@ -133,9 +133,9 @@ class DemoMap extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
value: CONFIGS,
},
hass: Object
hass: Object,
};
}
@@ -146,4 +146,4 @@ class DemoMap extends PolymerElement {
}
}
customElements.define('demo-hui-map-card', DemoMap);
customElements.define("demo-hui-map-card", DemoMap);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'markdown-it demo',
heading: "markdown-it demo",
config: `
- type: markdown
content: >
@@ -248,7 +248,7 @@ const CONFIGS = [
::: warning
*here be dragons*
:::
`
`,
},
];
@@ -263,10 +263,10 @@ class DemoMarkdown extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-markdown-card', DemoMarkdown);
customElements.define("demo-hui-markdown-card", DemoMarkdown);

View File

@@ -1,58 +1,58 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import getEntity from '../data/entity.js';
import provideHass from '../data/provide_hass.js';
import '../components/demo-cards.js';
import getEntity from "../data/entity.js";
import provideHass from "../data/provide_hass.js";
import "../components/demo-cards.js";
const ENTITIES = [
getEntity('media_player', 'bedroom', 'playing', {
media_content_type: 'movie',
media_title: 'Epic sax guy 10 hours',
app_name: 'YouTube',
supported_features: 32
getEntity("media_player", "bedroom", "playing", {
media_content_type: "movie",
media_title: "Epic sax guy 10 hours",
app_name: "YouTube",
supported_features: 32,
}),
getEntity('media_player', 'family_room', 'paused', {
media_content_type: 'music',
media_title: 'I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)',
media_artist: 'Technohead',
supported_features: 16417
getEntity("media_player", "family_room", "paused", {
media_content_type: "music",
media_title: "I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)",
media_artist: "Technohead",
supported_features: 16417,
}),
getEntity('media_player', 'family_room_no_play', 'paused', {
media_content_type: 'movie',
media_title: 'Epic sax guy 10 hours',
app_name: 'YouTube',
supported_features: 33
getEntity("media_player", "family_room_no_play", "paused", {
media_content_type: "movie",
media_title: "Epic sax guy 10 hours",
app_name: "YouTube",
supported_features: 33,
}),
getEntity('media_player', 'living_room', 'playing', {
media_content_type: 'tvshow',
media_title: 'Chapter 1',
media_series_title: 'House of Cards',
app_name: 'Netflix',
supported_features: 1
}),
getEntity('media_player', 'lounge_room', 'idle', {
media_content_type: 'music',
media_title: 'I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)',
media_artist: 'Technohead',
getEntity("media_player", "living_room", "playing", {
media_content_type: "tvshow",
media_title: "Chapter 1",
media_series_title: "House of Cards",
app_name: "Netflix",
supported_features: 1,
}),
getEntity('media_player', 'theater', 'off', {
media_content_type: 'movie',
media_title: 'Epic sax guy 10 hours',
app_name: 'YouTube',
supported_features: 33
getEntity("media_player", "lounge_room", "idle", {
media_content_type: "music",
media_title: "I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)",
media_artist: "Technohead",
supported_features: 1,
}),
getEntity('media_player', 'android_cast', 'playing', {
media_title: 'Android Screen Casting',
app_name: 'Screen Mirroring',
supported_features: 21437
getEntity("media_player", "theater", "off", {
media_content_type: "movie",
media_title: "Epic sax guy 10 hours",
app_name: "YouTube",
supported_features: 33,
}),
getEntity("media_player", "android_cast", "playing", {
media_title: "Android Screen Casting",
app_name: "Screen Mirroring",
supported_features: 21437,
}),
];
const CONFIGS = [
{
heading: 'Media Players',
heading: "Media Players",
config: `
- type: entities
entities:
@@ -70,8 +70,8 @@ const CONFIGS = [
name: Chromcast Idle
- entity: media_player.theater
name: 'Player Off'
`
}
`,
},
];
class DemoHuiMediaPlayerRows extends PolymerElement {
@@ -89,7 +89,7 @@ class DemoHuiMediaPlayerRows extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
value: CONFIGS,
},
hass: Object,
};
@@ -102,4 +102,4 @@ class DemoHuiMediaPlayerRows extends PolymerElement {
}
}
customElements.define('demo-hui-media-player-rows', DemoHuiMediaPlayerRows);
customElements.define("demo-hui-media-player-rows", DemoHuiMediaPlayerRows);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Card with few elements',
heading: "Card with few elements",
config: `
- type: picture-elements
image: /images/floorplan.png
@@ -49,7 +49,7 @@ const CONFIGS = [
style:
top: 8%
left: 35%
`
`,
},
];
@@ -64,10 +64,10 @@ class DemoPicElements extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-picture-elements-card', DemoPicElements);
customElements.define("demo-hui-picture-elements-card", DemoPicElements);

View File

@@ -1,67 +1,67 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'State on',
heading: "State on",
config: `
- type: picture-entity
image: /images/kitchen.png
entity: light.kitchen_lights
`
`,
},
{
heading: 'State off',
heading: "State off",
config: `
- type: picture-entity
image: /images/bed.png
entity: light.bed_light
`
`,
},
{
heading: 'Entity unavailable',
heading: "Entity unavailable",
config: `
- type: picture-entity
image: /images/living_room.png
entity: light.non_existing
`
`,
},
{
heading: 'Camera entity',
heading: "Camera entity",
config: `
- type: picture-entity
entity: camera.demo_camera
`
`,
},
{
heading: 'Hidden name',
heading: "Hidden name",
config: `
- type: picture-entity
image: /images/kitchen.png
entity: light.kitchen_lights
show_name: false
`
`,
},
{
heading: 'Hidden state',
heading: "Hidden state",
config: `
- type: picture-entity
image: /images/kitchen.png
entity: light.kitchen_lights
show_state: false
`
`,
},
{
heading: 'Both hidden',
heading: "Both hidden",
config: `
- type: picture-entity
image: /images/kitchen.png
entity: light.kitchen_lights
show_name: false
show_state: false
`
`,
},
];
@@ -76,10 +76,10 @@ class DemoPicEntity extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-picture-entity-card', DemoPicEntity);
customElements.define("demo-hui-picture-entity-card", DemoPicEntity);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Title, dialog, toggle',
heading: "Title, dialog, toggle",
config: `
- type: picture-glance
image: /images/living_room.png
@@ -15,10 +15,10 @@ const CONFIGS = [
- light.ceiling_lights
- binary_sensor.movement_backyard
- binary_sensor.basement_floor_wet
`
`,
},
{
heading: 'Title, dialog, no toggle',
heading: "Title, dialog, no toggle",
config: `
- type: picture-glance
image: /images/living_room.png
@@ -26,10 +26,10 @@ const CONFIGS = [
entities:
- binary_sensor.movement_backyard
- binary_sensor.basement_floor_wet
`
`,
},
{
heading: 'Title, no dialog, toggle',
heading: "Title, no dialog, toggle",
config: `
- type: picture-glance
image: /images/living_room.png
@@ -37,10 +37,10 @@ const CONFIGS = [
entities:
- switch.decorative_lights
- light.ceiling_lights
`
`,
},
{
heading: 'No title, dialog, toggle',
heading: "No title, dialog, toggle",
config: `
- type: picture-glance
image: /images/living_room.png
@@ -49,30 +49,30 @@ const CONFIGS = [
- light.ceiling_lights
- binary_sensor.movement_backyard
- binary_sensor.basement_floor_wet
`
`,
},
{
heading: 'No title, dialog, no toggle',
heading: "No title, dialog, no toggle",
config: `
- type: picture-glance
image: /images/living_room.png
entities:
- binary_sensor.movement_backyard
- binary_sensor.basement_floor_wet
`
`,
},
{
heading: 'No title, no dialog, toggle',
heading: "No title, no dialog, toggle",
config: `
- type: picture-glance
image: /images/living_room.png
entities:
- switch.decorative_lights
- light.ceiling_lights
`
`,
},
{
heading: 'Custom icon',
heading: "Custom icon",
config: `
- type: picture-glance
image: /images/living_room.png
@@ -81,7 +81,7 @@ const CONFIGS = [
- entity: switch.decorative_lights
icon: mdi:power
- binary_sensor.basement_floor_wet
`
`,
},
];
@@ -96,10 +96,10 @@ class DemoPicGlance extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-picture-glance-card', DemoPicGlance);
customElements.define("demo-hui-picture-glance-card", DemoPicGlance);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/demo-cards.js';
import "../components/demo-cards.js";
const CONFIGS = [
{
heading: 'Vertical Stack',
heading: "Vertical Stack",
config: `
- type: vertical-stack
cards:
@@ -17,10 +17,10 @@ const CONFIGS = [
- device_tracker.demo_anne_therese
- device_tracker.demo_home_boy
- device_tracker.demo_paulus
`
`,
},
{
heading: 'Horizontal Stack',
heading: "Horizontal Stack",
config: `
- type: horizontal-stack
cards:
@@ -32,10 +32,10 @@ const CONFIGS = [
- device_tracker.demo_anne_therese
- device_tracker.demo_home_boy
- device_tracker.demo_paulus
`
`,
},
{
heading: 'Combination of both',
heading: "Combination of both",
config: `
- type: vertical-stack
cards:
@@ -52,7 +52,7 @@ const CONFIGS = [
- type: picture-entity
image: /images/bed.png
entity: light.bed_light
`
`,
},
];
@@ -67,10 +67,10 @@ class DemoStack extends PolymerElement {
return {
_configs: {
type: Object,
value: CONFIGS
}
value: CONFIGS,
},
};
}
}
customElements.define('demo-hui-stack-card', DemoStack);
customElements.define("demo-hui-stack-card", DemoStack);

View File

@@ -1,13 +1,13 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/dialogs/more-info/controls/more-info-content.js';
import '../../../src/components/ha-card.js';
import "../../../src/dialogs/more-info/controls/more-info-content.js";
import "../../../src/components/ha-card.js";
import getEntity from '../data/entity.js';
import provideHass from '../data/provide_hass.js';
import getEntity from "../data/entity.js";
import provideHass from "../data/provide_hass.js";
import '../components/demo-more-infos.js';
import "../components/demo-more-infos.js";
/* eslint-disable no-unused-vars */
@@ -20,17 +20,16 @@ const SUPPORT_TRANSITION = 32;
const SUPPORT_WHITE_VALUE = 128;
const ENTITIES = [
getEntity('light', 'bed_light', 'on', {
friendly_name: 'Basic Light'
getEntity("light", "bed_light", "on", {
friendly_name: "Basic Light",
}),
getEntity('light', 'kitchen_light', 'on', {
friendly_name: 'Brightness Light',
getEntity("light", "kitchen_light", "on", {
friendly_name: "Brightness Light",
brightness: 80,
supported_features: SUPPORT_BRIGHTNESS,
}),
];
class DemoMoreInfoLight extends PolymerElement {
static get template() {
return html`
@@ -45,7 +44,7 @@ class DemoMoreInfoLight extends PolymerElement {
return {
_entities: {
type: Array,
value: ENTITIES.map(ent => ent.entityId),
value: ENTITIES.map((ent) => ent.entityId),
},
};
}
@@ -57,4 +56,4 @@ class DemoMoreInfoLight extends PolymerElement {
}
}
customElements.define('demo-more-info-light', DemoMoreInfoLight);
customElements.define("demo-more-info-light", DemoMoreInfoLight);

View File

@@ -1,12 +1,12 @@
import '@polymer/paper-styles/typography.js';
import '@polymer/polymer/lib/elements/dom-if.js';
import '@polymer/polymer/lib/elements/dom-repeat.js';
import "@polymer/paper-styles/typography.js";
import "@polymer/polymer/lib/elements/dom-if.js";
import "@polymer/polymer/lib/elements/dom-repeat.js";
import '../../src/resources/hass-icons.js';
import '../../src/resources/ha-style.js';
import '../../src/resources/roboto.js';
import '../../src/components/ha-iconset-svg.js';
import "../../src/resources/hass-icons.js";
import "../../src/resources/ha-style.js";
import "../../src/resources/roboto.js";
import "../../src/components/ha-iconset-svg.js";
import './ha-gallery.js';
import "./ha-gallery.js";
document.body.appendChild(document.createElement('ha-gallery'));
document.body.appendChild(document.createElement("ha-gallery"));

View File

@@ -1,19 +1,19 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-layout/app-header-layout/app-header-layout.js";
import "@polymer/app-layout/app-header/app-header.js";
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/iron-icon/iron-icon.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-item/paper-item.js";
import "@polymer/paper-item/paper-item-body.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../src/managers/notification-manager.js';
import "../../src/managers/notification-manager.js";
const DEMOS = require.context('./demos', true, /^(.*\.(js$))[^.]*$/im);
const DEMOS = require.context("./demos", true, /^(.*\.(js$))[^.]*$/im);
const fixPath = path => path.substr(2, path.length - 5);
const fixPath = (path) => path.substr(2, path.length - 5);
class HaGallery extends PolymerElement {
static get template() {
@@ -131,19 +131,19 @@ class HaGallery extends PolymerElement {
_demo: {
type: String,
value: document.location.hash.substr(1),
observer: '_demoChanged',
observer: "_demoChanged",
},
_demos: {
type: Array,
value: DEMOS.keys().map(fixPath)
value: DEMOS.keys().map(fixPath),
},
_lovelaceDemos: {
type: Array,
computed: '_computeLovelace(_demos)',
computed: "_computeLovelace(_demos)",
},
_moreInfoDemos: {
type: Array,
computed: '_computeMoreInfos(_demos)',
computed: "_computeMoreInfos(_demos)",
},
};
}
@@ -151,18 +151,21 @@ class HaGallery extends PolymerElement {
ready() {
super.ready();
this.addEventListener(
'show-notification',
ev => this.$.notifications.showNotification(ev.detail.message)
this.addEventListener("show-notification", (ev) =>
this.$.notifications.showNotification(ev.detail.message)
);
this.addEventListener('hass-more-info', (ev) => {
this.addEventListener("hass-more-info", (ev) => {
if (ev.detail.entityId) {
this.$.notifications.showNotification(`Showing more info for ${ev.detail.entityId}`);
this.$.notifications.showNotification(
`Showing more info for ${ev.detail.entityId}`
);
}
});
window.addEventListener('hashchange', () => { this._demo = document.location.hash.substr(1); });
window.addEventListener("hashchange", () => {
this._demo = document.location.hash.substr(1);
});
}
_withDefault(value, def) {
@@ -182,20 +185,20 @@ class HaGallery extends PolymerElement {
}
_computeHeaderButtonClass(demo) {
return demo ? '' : 'invisible';
return demo ? "" : "invisible";
}
_backTapped() {
document.location.hash = '';
document.location.hash = "";
}
_computeLovelace(demos) {
return demos.filter(demo => demo.includes('hui'));
return demos.filter((demo) => demo.includes("hui"));
}
_computeMoreInfos(demos) {
return demos.filter(demo => demo.includes('more-info'));
return demos.filter((demo) => demo.includes("more-info"));
}
}
customElements.define('ha-gallery', HaGallery);
customElements.define("ha-gallery", HaGallery);

View File

@@ -1,36 +1,34 @@
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require("path");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const isProd = process.env.NODE_ENV === 'production';
const chunkFilename = isProd ?
'chunk.[chunkhash].js' : '[name].chunk.js';
const buildPath = path.resolve(__dirname, 'dist');
const publicPath = isProd ? './' : 'http://localhost:8080/';
const isProd = process.env.NODE_ENV === "production";
const chunkFilename = isProd ? "chunk.[chunkhash].js" : "[name].chunk.js";
const buildPath = path.resolve(__dirname, "dist");
const publicPath = isProd ? "./" : "http://localhost:8080/";
module.exports = {
mode: isProd ? 'production' : 'development',
mode: isProd ? "production" : "development",
// Disabled in prod while we make Home Assistant able to serve the right files.
// Was source-map
devtool: isProd ? 'none' : 'inline-source-map',
entry: './src/entrypoint.js',
devtool: isProd ? "none" : "inline-source-map",
entry: "./src/entrypoint.js",
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
loader: "babel-loader",
options: {
plugins: [
// Only support the syntax, Webpack will handle it.
'syntax-dynamic-import',
"syntax-dynamic-import",
[
'transform-react-jsx',
"transform-react-jsx",
{
pragma: 'h'
}
pragma: "h",
},
],
],
},
},
@@ -38,39 +36,49 @@ module.exports = {
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
loader: "html-loader",
options: {
exportAsEs6Default: true,
}
}
},
]
},
},
],
},
plugins: [
new CopyWebpackPlugin([
'public',
{ from: '../public', to: 'static' },
{ from: '../build-translations/output', to: 'static/translations' },
{ from: '../node_modules/leaflet/dist/leaflet.css', to: 'static/images/leaflet/' },
{ from: '../node_modules/@polymer/font-roboto-local/fonts', to: 'static/fonts' },
{ from: '../node_modules/leaflet/dist/images', to: 'static/images/leaflet/' },
"public",
{ from: "../public", to: "static" },
{ from: "../build-translations/output", to: "static/translations" },
{
from: "../node_modules/leaflet/dist/leaflet.css",
to: "static/images/leaflet/",
},
{
from: "../node_modules/@polymer/font-roboto-local/fonts",
to: "static/fonts",
},
{
from: "../node_modules/leaflet/dist/images",
to: "static/images/leaflet/",
},
]),
isProd && new UglifyJsPlugin({
isProd &&
new UglifyJsPlugin({
extractComments: true,
sourceMap: true,
uglifyOptions: {
// Disabling because it broke output
mangle: false,
}
},
}),
].filter(Boolean),
output: {
filename: '[name].js',
filename: "[name].js",
chunkFilename: chunkFilename,
path: buildPath,
publicPath,
},
devServer: {
contentBase: './public',
}
contentBase: "./public",
},
};

View File

@@ -1,8 +1,8 @@
var path = require('path');
var path = require("path");
module.exports = {
polymer_dir: path.resolve(__dirname, '..'),
build_dir: path.resolve(__dirname, '../build'),
output: path.resolve(__dirname, '../hass_frontend'),
output_es5: path.resolve(__dirname, '../hass_frontend_es5'),
polymer_dir: path.resolve(__dirname, ".."),
build_dir: path.resolve(__dirname, "../build"),
output: path.resolve(__dirname, "../hass_frontend"),
output_es5: path.resolve(__dirname, "../hass_frontend_es5"),
};

View File

@@ -1,31 +1,34 @@
const gulp = require('gulp');
const path = require('path');
const fs = require('fs');
const config = require('../config');
const gulp = require("gulp");
const path = require("path");
const fs = require("fs");
const config = require("../config");
const ICON_PACKAGE_PATH = path.resolve(__dirname, '../../node_modules/@mdi/svg/');
const META_PATH = path.resolve(ICON_PACKAGE_PATH, 'meta.json');
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, 'svg');
const OUTPUT_DIR = path.resolve(__dirname, '../../build');
const MDI_OUTPUT_PATH = path.resolve(OUTPUT_DIR, 'mdi.html');
const HASS_OUTPUT_PATH = path.resolve(OUTPUT_DIR, 'hass-icons.html');
const ICON_PACKAGE_PATH = path.resolve(
__dirname,
"../../node_modules/@mdi/svg/"
);
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
const OUTPUT_DIR = path.resolve(__dirname, "../../build");
const MDI_OUTPUT_PATH = path.resolve(OUTPUT_DIR, "mdi.html");
const HASS_OUTPUT_PATH = path.resolve(OUTPUT_DIR, "hass-icons.html");
const BUILT_IN_PANEL_ICONS = [
'calendar', // Calendar
'settings', // Config
'home-assistant', // Hass.io
'poll-box', // History panel
'format-list-bulleted-type', // Logbook
'mailbox', // Mailbox
'account-location', // Map
'cart', // Shopping List
"calendar", // Calendar
"settings", // Config
"home-assistant", // Hass.io
"poll-box", // History panel
"format-list-bulleted-type", // Logbook
"mailbox", // Mailbox
"account-location", // Map
"cart", // Shopping List
];
// Given an icon name, load the SVG file
function loadIcon(name) {
const iconPath = path.resolve(ICON_PATH, `${name}.svg`);
try {
return fs.readFileSync(iconPath, 'utf-8');
return fs.readFileSync(iconPath, "utf-8");
} catch (err) {
return null;
}
@@ -33,7 +36,7 @@ function loadIcon(name) {
// Given an SVG file, convert it to an iron-iconset-svg definition
function transformXMLtoPolymer(name, xml) {
const start = xml.indexOf('><path') + 1;
const start = xml.indexOf("><path") + 1;
const end = xml.length - start - 6;
const path = xml.substr(start, end);
return `<g id="${name}">${path}</g>`;
@@ -41,22 +44,26 @@ function transformXMLtoPolymer(name, xml) {
// Given an iconset name and icon names, generate a polymer iconset
function generateIconset(name, iconNames) {
const iconDefs = iconNames.map(name => {
const iconDefs = iconNames
.map((name) => {
const iconDef = loadIcon(name);
if (!iconDef) {
throw new Error(`Unknown icon referenced: ${name}`);
}
return transformXMLtoPolymer(name, iconDef)
}).join('');
return transformXMLtoPolymer(name, iconDef);
})
.join("");
return `<ha-iconset-svg name="${name}" size="24"><svg><defs>${iconDefs}</defs></svg></ha-iconset-svg>`;
}
// Generate the full MDI iconset
function genMDIIcons() {
const meta = JSON.parse(fs.readFileSync(path.resolve(ICON_PACKAGE_PATH, META_PATH), 'UTF-8'));
const iconNames = meta.map(iconInfo => iconInfo.name);
const meta = JSON.parse(
fs.readFileSync(path.resolve(ICON_PACKAGE_PATH, META_PATH), "UTF-8")
);
const iconNames = meta.map((iconInfo) => iconInfo.name);
fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR);
fs.writeFileSync(MDI_OUTPUT_PATH, generateIconset('mdi', iconNames));
fs.writeFileSync(MDI_OUTPUT_PATH, generateIconset("mdi", iconNames));
}
// Helper function to map recursively over files in a folder and it's subfolders
@@ -75,30 +82,30 @@ function mapFiles(startPath, filter, mapFunc) {
// Find all icons used by the project.
function findIcons(path, iconsetName) {
const iconRegex = new RegExp(`${iconsetName}:[\\w-]+`, 'g');
const iconRegex = new RegExp(`${iconsetName}:[\\w-]+`, "g");
const icons = new Set();
function processFile(filename) {
const content = fs.readFileSync(filename);
let match;
// eslint-disable-next-line
while (match = iconRegex.exec(content)) {
while ((match = iconRegex.exec(content))) {
// strip off "hass:" and add to set
icons.add(match[0].substr(iconsetName.length + 1));
}
}
mapFiles(path, '.js', processFile);
mapFiles(path, ".js", processFile);
return Array.from(icons);
}
function genHassIcons() {
const iconNames = findIcons('./src', 'hass').concat(BUILT_IN_PANEL_ICONS);
const iconNames = findIcons("./src", "hass").concat(BUILT_IN_PANEL_ICONS);
fs.existsSync(OUTPUT_DIR) || fs.mkdirSync(OUTPUT_DIR);
fs.writeFileSync(HASS_OUTPUT_PATH, generateIconset('hass', iconNames));
fs.writeFileSync(HASS_OUTPUT_PATH, generateIconset("hass", iconNames));
}
gulp.task('gen-icons-mdi', () => genMDIIcons());
gulp.task('gen-icons-hass', () => genHassIcons());
gulp.task('gen-icons', ['gen-icons-hass', 'gen-icons-mdi'], () => {});
gulp.task("gen-icons-mdi", () => genMDIIcons());
gulp.task("gen-icons-hass", () => genHassIcons());
gulp.task("gen-icons", ["gen-icons-hass", "gen-icons-mdi"], () => {});
module.exports = {
findIcons,

View File

@@ -1,40 +1,44 @@
const path = require('path');
const gulp = require('gulp');
const foreach = require('gulp-foreach');
const hash = require('gulp-hash');
const insert = require('gulp-insert');
const merge = require('gulp-merge-json');
const minify = require('gulp-jsonminify');
const rename = require('gulp-rename');
const transform = require('gulp-json-transform');
const path = require("path");
const gulp = require("gulp");
const foreach = require("gulp-foreach");
const hash = require("gulp-hash");
const insert = require("gulp-insert");
const merge = require("gulp-merge-json");
const minify = require("gulp-jsonminify");
const rename = require("gulp-rename");
const transform = require("gulp-json-transform");
const inDir = 'translations';
const workDir = 'build-translations';
const fullDir = workDir + '/full';
const coreDir = workDir + '/core';
const outDir = workDir + '/output';
const inDir = "translations";
const workDir = "build-translations";
const fullDir = workDir + "/full";
const coreDir = workDir + "/core";
const outDir = workDir + "/output";
// Panel translations which should be split from the core translations. These
// should mirror the fragment definitions in polymer.json, so that we load
// additional resources at equivalent points.
const TRANSLATION_FRAGMENTS = [
'config',
'history',
'logbook',
'mailbox',
'profile',
'shopping-list',
'page-authorize',
'page-onboarding',
"config",
"history",
"logbook",
"mailbox",
"profile",
"shopping-list",
"page-authorize",
"page-onboarding",
];
const tasks = [];
function recursiveFlatten(prefix, data) {
let output = {};
Object.keys(data).forEach(function (key) {
if (typeof (data[key]) === 'object') {
output = Object.assign({}, output, recursiveFlatten(prefix + key + '.', data[key]));
Object.keys(data).forEach(function(key) {
if (typeof data[key] === "object") {
output = Object.assign(
{},
output,
recursiveFlatten(prefix + key + ".", data[key])
);
} else {
output[prefix + key] = data[key];
}
@@ -43,14 +47,14 @@ function recursiveFlatten(prefix, data) {
}
function flatten(data) {
return recursiveFlatten('', data);
return recursiveFlatten("", data);
}
function emptyFilter(data) {
const newData = {};
Object.keys(data).forEach((key) => {
if (data[key]) {
if (typeof (data[key]) === 'object') {
if (typeof data[key] === "object") {
newData[key] = emptyFilter(data[key]);
} else {
newData[key] = data[key];
@@ -70,16 +74,18 @@ function emptyFilter(data) {
* @link https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing
*/
const re_key_reference = /\[%key:([^%]+)%\]/;
function lokalise_transform (data, original) {
function lokalise_transform(data, original) {
const output = {};
Object.entries(data).forEach(([key, value]) => {
if (value instanceof Object) {
output[key] = lokalise_transform(value, original);
} else {
output[key] = value.replace(re_key_reference, (match, key) => {
const replace = key.split('::').reduce((tr, k) => tr[k], original);
if (typeof replace !== 'string') {
throw Error(`Invalid key placeholder ${key} in src/translations/en.json`);
const replace = key.split("::").reduce((tr, k) => tr[k], original);
if (typeof replace !== "string") {
throw Error(
`Invalid key placeholder ${key} in src/translations/en.json`
);
}
return replace;
});
@@ -97,21 +103,24 @@ function lokalise_transform (data, original) {
* project is buildable immediately after merging new translation keys, since
* the Lokalise update to translations/en.json will not happen immediately.
*/
let taskName = 'build-master-translation';
gulp.task(taskName, function () {
return gulp.src('src/translations/en.json')
.pipe(transform(function(data, file) {
let taskName = "build-master-translation";
gulp.task(taskName, function() {
return gulp
.src("src/translations/en.json")
.pipe(
transform(function(data, file) {
return lokalise_transform(data, data);
}))
.pipe(rename('translationMaster.json'))
})
)
.pipe(rename("translationMaster.json"))
.pipe(gulp.dest(workDir));
});
tasks.push(taskName);
taskName = 'build-merged-translations';
gulp.task(taskName, ['build-master-translation'], function () {
return gulp.src(inDir + '/*.json')
.pipe(foreach(function(stream, file) {
taskName = "build-merged-translations";
gulp.task(taskName, ["build-master-translation"], function() {
return gulp.src(inDir + "/*.json").pipe(
foreach(function(stream, file) {
// For each language generate a merged json file. It begins with the master
// translation as a failsafe for untranslated strings, and merges all parent
// tags into one file for each specific subtag
@@ -119,97 +128,119 @@ gulp.task(taskName, ['build-master-translation'], function () {
// TODO: This is a naive interpretation of BCP47 that should be improved.
// Will be OK for now as long as we don't have anything more complicated
// than a base translation + region.
const tr = path.basename(file.history[0], '.json');
const subtags = tr.split('-');
const src = [workDir + '/translationMaster.json'];
const tr = path.basename(file.history[0], ".json");
const subtags = tr.split("-");
const src = [workDir + "/translationMaster.json"];
for (let i = 1; i <= subtags.length; i++) {
const lang = subtags.slice(0, i).join('-');
src.push(inDir + '/' + lang + '.json');
const lang = subtags.slice(0, i).join("-");
src.push(inDir + "/" + lang + ".json");
}
return gulp.src(src)
.pipe(transform(data => emptyFilter(data)))
.pipe(merge({
fileName: tr + '.json',
}))
return gulp
.src(src)
.pipe(transform((data) => emptyFilter(data)))
.pipe(
merge({
fileName: tr + ".json",
})
)
.pipe(gulp.dest(fullDir));
}));
})
);
});
tasks.push(taskName);
const splitTasks = [];
TRANSLATION_FRAGMENTS.forEach((fragment) => {
taskName = 'build-translation-fragment-' + fragment;
gulp.task(taskName, ['build-merged-translations'], function () {
taskName = "build-translation-fragment-" + fragment;
gulp.task(taskName, ["build-merged-translations"], function() {
// Return only the translations for this fragment.
return gulp.src(fullDir + '/*.json')
.pipe(transform(data => ({
return gulp
.src(fullDir + "/*.json")
.pipe(
transform((data) => ({
ui: {
panel: {
[fragment]: data.ui.panel[fragment],
},
},
})))
.pipe(gulp.dest(workDir + '/' + fragment));
}))
)
.pipe(gulp.dest(workDir + "/" + fragment));
});
tasks.push(taskName);
splitTasks.push(taskName);
});
taskName = 'build-translation-core';
gulp.task(taskName, ['build-merged-translations'], function () {
taskName = "build-translation-core";
gulp.task(taskName, ["build-merged-translations"], function() {
// Remove the fragment translations from the core translation.
return gulp.src(fullDir + '/*.json')
.pipe(transform((data) => {
return gulp
.src(fullDir + "/*.json")
.pipe(
transform((data) => {
TRANSLATION_FRAGMENTS.forEach((fragment) => {
delete data.ui.panel[fragment];
});
return data;
}))
})
)
.pipe(gulp.dest(coreDir));
});
tasks.push(taskName);
splitTasks.push(taskName);
taskName = 'build-flattened-translations';
gulp.task(taskName, splitTasks, function () {
taskName = "build-flattened-translations";
gulp.task(taskName, splitTasks, function() {
// Flatten the split versions of our translations, and move them into outDir
return gulp.src(
TRANSLATION_FRAGMENTS.map(fragment => workDir + '/' + fragment + '/*.json')
.concat(coreDir + '/*.json'),
{ base: workDir },
return gulp
.src(
TRANSLATION_FRAGMENTS.map(
(fragment) => workDir + "/" + fragment + "/*.json"
).concat(coreDir + "/*.json"),
{ base: workDir }
)
.pipe(transform(function (data) {
.pipe(
transform(function(data) {
// Polymer.AppLocalizeBehavior requires flattened json
return flatten(data);
}))
})
)
.pipe(minify())
.pipe(rename((filePath) => {
if (filePath.dirname === 'core') {
filePath.dirname = '';
.pipe(
rename((filePath) => {
if (filePath.dirname === "core") {
filePath.dirname = "";
}
}))
})
)
.pipe(gulp.dest(outDir));
});
tasks.push(taskName);
taskName = 'build-translation-fingerprints';
gulp.task(taskName, ['build-flattened-translations'], function () {
return gulp.src(outDir + '/**/*.json')
.pipe(rename({
extname: '',
}))
.pipe(hash({
algorithm: 'md5',
taskName = "build-translation-fingerprints";
gulp.task(taskName, ["build-flattened-translations"], function() {
return gulp
.src(outDir + "/**/*.json")
.pipe(
rename({
extname: "",
})
)
.pipe(
hash({
algorithm: "md5",
hashLength: 32,
template: '<%= name %>-<%= hash %>.json',
}))
.pipe(hash.manifest('translationFingerprints.json'))
.pipe(transform(function (data) {
template: "<%= name %>-<%= hash %>.json",
})
)
.pipe(hash.manifest("translationFingerprints.json"))
.pipe(
transform(function(data) {
// After generating fingerprints of our translation files, consolidate
// all translation fragment fingerprints under the translation name key
const newData = {};
Object.entries(data).forEach(([key, value]) => {
const parts = key.split('/');
const parts = key.split("/");
let translation = key;
if (parts.length === 2) {
translation = parts[1];
@@ -222,36 +253,44 @@ gulp.task(taskName, ['build-flattened-translations'], function () {
newData[translation].fingerprints[key] = value;
});
return newData;
}))
})
)
.pipe(gulp.dest(workDir));
});
tasks.push(taskName);
taskName = 'build-translations';
gulp.task(taskName, ['build-translation-fingerprints'], function () {
return gulp.src([
'src/translations/translationMetadata.json',
workDir + '/translationFingerprints.json',
taskName = "build-translations";
gulp.task(taskName, ["build-translation-fingerprints"], function() {
return gulp
.src([
"src/translations/translationMetadata.json",
workDir + "/translationFingerprints.json",
])
.pipe(merge({}))
.pipe(transform(function (data) {
.pipe(
transform(function(data) {
const newData = {};
Object.entries(data).forEach(([key, value]) => {
// Filter out translations without native name.
if (data[key].nativeName) {
newData[key] = data[key];
} else {
console.warn(`Skipping language ${key}. Native name was not translated.`);
console.warn(
`Skipping language ${key}. Native name was not translated.`
);
}
if (data[key]) newData[key] = value;
});
return newData;
}))
.pipe(transform(data => ({
})
)
.pipe(
transform((data) => ({
fragments: TRANSLATION_FRAGMENTS,
translations: data,
})))
.pipe(rename('translationMetadata.json'))
}))
)
.pipe(rename("translationMetadata.json"))
.pipe(gulp.dest(workDir));
});
tasks.push(taskName);

View File

@@ -1,8 +1,8 @@
const path = require('path');
const path = require("path");
module.exports = {
// Target directory for the build.
buildDir: path.resolve(__dirname, 'build'),
buildDir: path.resolve(__dirname, "build"),
// Path where the Hass.io frontend will be publicly available.
publicPath: '/api/hassio/app',
}
publicPath: "/api/hassio/app",
};

View File

@@ -1,15 +1,12 @@
#!/usr/bin/env node
const fs = require('fs');
const {
findIcons,
generateIconset,
} = require('../../gulp/tasks/gen-icons.js');
const fs = require("fs");
const { findIcons, generateIconset } = require("../../gulp/tasks/gen-icons.js");
const MENU_BUTTON_ICON = 'menu';
const MENU_BUTTON_ICON = "menu";
function genHassioIcons() {
const iconNames = findIcons('./src', 'hassio').concat(MENU_BUTTON_ICON);
fs.writeFileSync('./hassio-icons.html', generateIconset('hassio', iconNames));
const iconNames = findIcons("./src", "hassio").concat(MENU_BUTTON_ICON);
fs.writeFileSync("./hassio-icons.html", generateIconset("hassio", iconNames));
}
genHassioIcons();

View File

@@ -1,10 +1,10 @@
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/hassio-card-content.js';
import '../resources/hassio-style.js';
import NavigateMixin from '../../../src/mixins/navigate-mixin.js';
import "../components/hassio-card-content.js";
import "../resources/hassio-style.js";
import NavigateMixin from "../../../src/mixins/navigate-mixin.js";
class HassioAddonRepository extends NavigateMixin(PolymerElement) {
static get template() {
@@ -52,17 +52,23 @@ class HassioAddonRepository extends NavigateMixin(PolymerElement) {
}
computeIcon(addon) {
return addon.installed && addon.installed !== addon.version ? 'hassio:arrow-up-bold-circle' : 'hassio:puzzle';
return addon.installed && addon.installed !== addon.version
? "hassio:arrow-up-bold-circle"
: "hassio:puzzle";
}
computeIconTitle(addon) {
if (addon.installed) return addon.installed !== addon.version ? 'New version available' : 'Add-on is installed';
return 'Add-on is not installed';
if (addon.installed)
return addon.installed !== addon.version
? "New version available"
: "Add-on is installed";
return "Add-on is not installed";
}
computeIconClass(addon) {
if (addon.installed) return addon.installed !== addon.version ? 'update' : 'installed';
return '';
if (addon.installed)
return addon.installed !== addon.version ? "update" : "installed";
return "";
}
addonTapped(ev) {
@@ -70,4 +76,4 @@ class HassioAddonRepository extends NavigateMixin(PolymerElement) {
}
}
customElements.define('hassio-addon-repository', HassioAddonRepository);
customElements.define("hassio-addon-repository", HassioAddonRepository);

View File

@@ -1,8 +1,8 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import './hassio-addon-repository.js';
import './hassio-repositories-editor.js';
import "./hassio-addon-repository.js";
import "./hassio-repositories-editor.js";
class HassioAddonStore extends PolymerElement {
static get template() {
@@ -30,7 +30,7 @@ class HassioAddonStore extends PolymerElement {
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
this.loadData();
}
@@ -41,42 +41,45 @@ class HassioAddonStore extends PolymerElement {
}
sortRepos(a, b) {
if (a.slug === 'local') {
if (a.slug === "local") {
return -1;
} if (b.slug === 'local') {
}
if (b.slug === "local") {
return 1;
} if (a.slug === 'core') {
}
if (a.slug === "core") {
return -1;
} if (b.slug === 'core') {
}
if (b.slug === "core") {
return 1;
}
return a.name < b.name ? -1 : 1;
}
computeAddons(repo) {
return this.addons.filter(function (addon) {
return this.addons.filter(function(addon) {
return addon.repository === repo;
});
}
loadData() {
this.hass.callApi('get', 'hassio/addons')
.then((info) => {
this.hass.callApi("get", "hassio/addons").then(
(info) => {
this.addons = info.data.addons;
this.repos = info.data.repositories;
}, () => {
},
() => {
this.addons = [];
this.repos = [];
});
}
);
}
refreshData() {
this.hass.callApi('post', 'hassio/addons/reload')
.then(() => {
this.hass.callApi("post", "hassio/addons/reload").then(() => {
this.loadData();
});
}
}
customElements.define('hassio-addon-store', HassioAddonStore);
customElements.define("hassio-addon-store", HassioAddonStore);

View File

@@ -1,12 +1,12 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-icon/iron-icon.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-input/paper-input.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import '../components/hassio-card-content.js';
import '../resources/hassio-style.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import "../components/hassio-card-content.js";
import "../resources/hassio-style.js";
class HassioRepositoriesEditor extends PolymerElement {
static get template() {
@@ -60,7 +60,7 @@ class HassioRepositoriesEditor extends PolymerElement {
hass: Object,
repos: {
type: Array,
observer: 'reposChanged',
observer: "reposChanged",
},
repoList: Array,
repoUrl: String,
@@ -68,8 +68,10 @@ class HassioRepositoriesEditor extends PolymerElement {
}
reposChanged(repos) {
this.repoList = repos.filter(repo => repo.slug !== 'core' && repo.slug !== 'local');
this.repoUrl = '';
this.repoList = repos.filter(
(repo) => repo.slug !== "core" && repo.slug !== "local"
);
this.repoUrl = "";
}
sortRepos(a, b) {
@@ -77,15 +79,17 @@ class HassioRepositoriesEditor extends PolymerElement {
}
computeRemoveRepoData(repoList, url) {
const list = repoList.filter(repo => repo.url !== url).map(repo => repo.url);
const list = repoList
.filter((repo) => repo.url !== url)
.map((repo) => repo.url);
return { addons_repositories: list };
}
computeAddRepoData(repoList, url) {
const list = repoList ? repoList.map(repo => repo.url) : [];
const list = repoList ? repoList.map((repo) => repo.url) : [];
list.push(url);
return { addons_repositories: list };
}
}
customElements.define('hassio-repositories-editor', HassioRepositoriesEditor);
customElements.define("hassio-repositories-editor", HassioRepositoriesEditor);

View File

@@ -1,15 +1,15 @@
import 'web-animations-js/web-animations-next-lite.min.js';
import "web-animations-js/web-animations-next-lite.min.js";
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu.js";
import "@polymer/paper-item/paper-item.js";
import "@polymer/paper-listbox/paper-listbox.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/resources/ha-style.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../../../src/resources/ha-style.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioAddonAudio extends EventsMixin(PolymerElement) {
static get template() {
@@ -64,7 +64,7 @@ class HassioAddonAudio extends EventsMixin(PolymerElement) {
hass: Object,
addon: {
type: Object,
observer: 'addonChanged'
observer: "addonChanged",
},
inputDevices: Array,
outputDevices: Array,
@@ -76,40 +76,55 @@ class HassioAddonAudio extends EventsMixin(PolymerElement) {
addonChanged(addon) {
this.setProperties({
selectedInput: addon.audio_input || 'null',
selectedOutput: addon.audio_output || 'null'
selectedInput: addon.audio_input || "null",
selectedOutput: addon.audio_output || "null",
});
if (this.outputDevices) return;
const noDevice = [{ device: 'null', name: '-' }];
this.hass.callApi('get', 'hassio/hardware/audio').then((resp) => {
const noDevice = [{ device: "null", name: "-" }];
this.hass.callApi("get", "hassio/hardware/audio").then(
(resp) => {
const dev = resp.data.audio;
const input = Object.keys(dev.input).map(key => ({ device: key, name: dev.input[key] }));
const output = Object.keys(dev.output).map(key => ({ device: key, name: dev.output[key] }));
const input = Object.keys(dev.input).map((key) => ({
device: key,
name: dev.input[key],
}));
const output = Object.keys(dev.output).map((key) => ({
device: key,
name: dev.output[key],
}));
this.setProperties({
inputDevices: noDevice.concat(input),
outputDevices: noDevice.concat(output)
outputDevices: noDevice.concat(output),
});
}, () => {
},
() => {
this.setProperties({
inputDevices: noDevice,
outputDevices: noDevice
});
outputDevices: noDevice,
});
}
);
}
_saveSettings() {
this.error = null;
const path = `hassio/addons/${this.addon.slug}/options`;
this.hass.callApi('post', path, {
audio_input: this.selectedInput === 'null' ? null : this.selectedInput,
audio_output: this.selectedOutput === 'null' ? null : this.selectedOutput
}).then(() => {
this.fire('hass-api-called', { success: true, path: path });
}, (resp) => {
this.hass
.callApi("post", path, {
audio_input: this.selectedInput === "null" ? null : this.selectedInput,
audio_output:
this.selectedOutput === "null" ? null : this.selectedOutput,
})
.then(
() => {
this.fire("hass-api-called", { success: true, path: path });
},
(resp) => {
this.error = resp.body.message;
});
}
);
}
}
customElements.define('hassio-addon-audio', HassioAddonAudio);
customElements.define("hassio-addon-audio", HassioAddonAudio);

View File

@@ -1,10 +1,10 @@
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js";
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import "../../../src/components/buttons/ha-call-api-button.js";
class HassioAddonConfig extends PolymerElement {
static get template() {
@@ -52,12 +52,12 @@ class HassioAddonConfig extends PolymerElement {
hass: Object,
addon: {
type: Object,
observer: 'addonChanged',
observer: "addonChanged",
},
addonSlug: String,
config: {
type: String,
observer: 'configChanged',
observer: "configChanged",
},
configParsed: Object,
error: String,
@@ -71,15 +71,15 @@ class HassioAddonConfig extends PolymerElement {
}
addonChanged(addon) {
this.config = addon ? JSON.stringify(addon.options, null, 2) : '';
this.config = addon ? JSON.stringify(addon.options, null, 2) : "";
}
configChanged(config) {
try {
this.$.config.classList.remove('syntaxerror');
this.$.config.classList.remove("syntaxerror");
this.configParsed = JSON.parse(config);
} catch (err) {
this.$.config.classList.add('syntaxerror');
this.$.config.classList.add("syntaxerror");
this.configParsed = null;
}
}
@@ -87,12 +87,14 @@ class HassioAddonConfig extends PolymerElement {
saveTapped() {
this.error = null;
this.hass.callApi('post', `hassio/addons/${this.addonSlug}/options`, {
options: this.configParsed
}).catch((resp) => {
this.hass
.callApi("post", `hassio/addons/${this.addonSlug}/options`, {
options: this.configParsed,
})
.catch((resp) => {
this.error = resp.body.message;
});
}
}
customElements.define('hassio-addon-config', HassioAddonConfig);
customElements.define("hassio-addon-config", HassioAddonConfig);

View File

@@ -1,16 +1,16 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-icon/iron-icon.js";
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-toggle-button/paper-toggle-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import '../../../src/components/ha-markdown.js';
import '../../../src/resources/ha-style.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import "../../../src/components/ha-markdown.js";
import "../../../src/resources/ha-style.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
import '../components/hassio-card-content.js';
import "../components/hassio-card-content.js";
class HassioAddonInfo extends EventsMixin(PolymerElement) {
static get template() {
@@ -157,21 +157,26 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
addonSlug: String,
isRunning: {
type: Boolean,
computed: 'computeIsRunning(addon)',
computed: "computeIsRunning(addon)",
},
};
}
computeIsRunning(addon) {
return addon && addon.state === 'started';
return addon && addon.state === "started";
}
computeUpdateAvailable(addon) {
return addon && !addon.detached && addon.version && addon.version !== addon.last_version;
return (
addon &&
!addon.detached &&
addon.version &&
addon.version !== addon.last_version
);
}
pathWebui(webui) {
return webui && webui.replace('[HOST]', document.location.hostname);
return webui && webui.replace("[HOST]", document.location.hostname);
}
computeShowWebUI(webui, isRunning) {
@@ -179,49 +184,54 @@ class HassioAddonInfo extends EventsMixin(PolymerElement) {
}
computeStartOnBoot(state) {
return state === 'auto';
return state === "auto";
}
startOnBootToggled() {
const data = { boot: this.addon.boot === 'auto' ? 'manual' : 'auto' };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
const data = { boot: this.addon.boot === "auto" ? "manual" : "auto" };
this.hass.callApi("POST", `hassio/addons/${this.addonSlug}/options`, data);
}
autoUpdateToggled() {
const data = { auto_update: !this.addon.auto_update };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
this.hass.callApi("POST", `hassio/addons/${this.addonSlug}/options`, data);
}
openChangelog() {
this.hass.callApi('get', `hassio/addons/${this.addonSlug}/changelog`)
.then(
resp => resp,
() => 'Error getting changelog'
).then((content) => {
this.fire('hassio-markdown-dialog', {
title: 'Changelog',
this.hass
.callApi("get", `hassio/addons/${this.addonSlug}/changelog`)
.then((resp) => resp, () => "Error getting changelog")
.then((content) => {
this.fire("hassio-markdown-dialog", {
title: "Changelog",
content: content,
});
});
}
_unistallClicked() {
if (!confirm('Are you sure you want to uninstall this add-on?')) {
if (!confirm("Are you sure you want to uninstall this add-on?")) {
return;
}
const path = `hassio/addons/${this.addonSlug}/uninstall`;
const eventData = {
path: path,
};
this.hass.callApi('post', path).then((resp) => {
this.hass
.callApi("post", path)
.then(
(resp) => {
eventData.success = true;
eventData.response = resp;
}, (resp) => {
},
(resp) => {
eventData.success = false;
eventData.response = resp;
}).then(() => {
this.fire('hass-api-called', eventData);
}
)
.then(() => {
this.fire("hass-api-called", eventData);
});
}
}
customElements.define('hassio-addon-info', HassioAddonInfo);
customElements.define("hassio-addon-info", HassioAddonInfo);

View File

@@ -1,9 +1,9 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/resources/ha-style.js';
import "../../../src/resources/ha-style.js";
class HassioAddonLogs extends PolymerElement {
static get template() {
@@ -33,7 +33,7 @@ class HassioAddonLogs extends PolymerElement {
hass: Object,
addonSlug: {
type: String,
observer: 'addonSlugChanged',
observer: "addonSlugChanged",
},
log: String,
};
@@ -41,7 +41,9 @@ class HassioAddonLogs extends PolymerElement {
addonSlugChanged(slug) {
if (!this.hass) {
setTimeout(() => { this.addonChanged(slug); }, 0);
setTimeout(() => {
this.addonChanged(slug);
}, 0);
return;
}
@@ -49,11 +51,12 @@ class HassioAddonLogs extends PolymerElement {
}
refresh() {
this.hass.callApi('get', `hassio/addons/${this.addonSlug}/logs`)
this.hass
.callApi("get", `hassio/addons/${this.addonSlug}/logs`)
.then((info) => {
this.log = info;
});
}
}
customElements.define('hassio-addon-logs', HassioAddonLogs);
customElements.define("hassio-addon-logs", HassioAddonLogs);

View File

@@ -1,11 +1,11 @@
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-input/paper-input.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import '../../../src/resources/ha-style.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import "../../../src/resources/ha-style.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioAddonNetwork extends EventsMixin(PolymerElement) {
static get template() {
@@ -64,7 +64,7 @@ class HassioAddonNetwork extends EventsMixin(PolymerElement) {
config: Object,
addon: {
type: Object,
observer: 'addonChanged',
observer: "addonChanged",
},
error: String,
resetData: {
@@ -80,29 +80,36 @@ class HassioAddonNetwork extends EventsMixin(PolymerElement) {
if (!addon) return;
const network = addon.network || {};
const items = Object.keys(network).map(key => ({
const items = Object.keys(network).map((key) => ({
container: key,
host: network[key]
host: network[key],
}));
this.config = items.sort(function (el1, el2) { return el1.host - el2.host; });
this.config = items.sort(function(el1, el2) {
return el1.host - el2.host;
});
}
saveTapped() {
this.error = null;
const data = {};
this.config.forEach(function (item) {
this.config.forEach(function(item) {
data[item.container] = parseInt(item.host);
});
const path = `hassio/addons/${this.addonSlug}/options`;
this.hass.callApi('post', path, {
network: data
}).then(() => {
this.fire('hass-api-called', { success: true, path: path });
}, (resp) => {
this.hass
.callApi("post", path, {
network: data,
})
.then(
() => {
this.fire("hass-api-called", { success: true, path: path });
},
(resp) => {
this.error = resp.body.message;
});
}
);
}
}
customElements.define('hassio-addon-network', HassioAddonNetwork);
customElements.define("hassio-addon-network", HassioAddonNetwork);

View File

@@ -1,19 +1,19 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/app-route/app-route.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-layout/app-header-layout/app-header-layout.js";
import "@polymer/app-layout/app-header/app-header.js";
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/app-route/app-route.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/ha-menu-button.js';
import '../../../src/resources/ha-style.js';
import '../hassio-markdown-dialog.js';
import './hassio-addon-audio.js';
import './hassio-addon-config.js';
import './hassio-addon-info.js';
import './hassio-addon-logs.js';
import './hassio-addon-network.js';
import "../../../src/components/ha-menu-button.js";
import "../../../src/resources/ha-style.js";
import "../hassio-markdown-dialog.js";
import "./hassio-addon-audio.js";
import "./hassio-addon-config.js";
import "./hassio-addon-info.js";
import "./hassio-addon-logs.js";
import "./hassio-addon-network.js";
class HassioAddonView extends PolymerElement {
static get template() {
@@ -91,7 +91,7 @@ class HassioAddonView extends PolymerElement {
route: Object,
routeData: {
type: Object,
observer: 'routeDataChanged',
observer: "routeDataChanged",
},
routeMatches: Boolean,
addon: Object,
@@ -99,15 +99,17 @@ class HassioAddonView extends PolymerElement {
markdownTitle: String,
markdownContent: {
type: String,
value: '',
value: "",
},
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
this.addEventListener("hassio-markdown-dialog", (ev) =>
this.openMarkdown(ev)
);
}
apiCalled(ev) {
@@ -115,7 +117,7 @@ class HassioAddonView extends PolymerElement {
if (!path) return;
if (path.substr(path.lastIndexOf('/') + 1) === 'uninstall') {
if (path.substr(path.lastIndexOf("/") + 1) === "uninstall") {
this.backTapped();
} else {
this.routeDataChanged(this.routeData);
@@ -124,12 +126,14 @@ class HassioAddonView extends PolymerElement {
routeDataChanged(routeData) {
if (!this.routeMatches || !routeData || !routeData.slug) return;
this.hass.callApi('get', `hassio/addons/${routeData.slug}/info`)
.then((info) => {
this.hass.callApi("get", `hassio/addons/${routeData.slug}/info`).then(
(info) => {
this.addon = info.data;
}, () => {
},
() => {
this.addon = null;
});
}
);
}
backTapped() {
@@ -141,8 +145,8 @@ class HassioAddonView extends PolymerElement {
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog();
}
}
customElements.define('hassio-addon-view', HassioAddonView);
customElements.define("hassio-addon-view", HassioAddonView);

View File

@@ -1,8 +1,8 @@
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-icon/iron-icon.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/ha-relative-time.js';
import "../../../src/components/ha-relative-time.js";
class HassioCardContent extends PolymerElement {
static get template() {
@@ -65,11 +65,11 @@ class HassioCardContent extends PolymerElement {
datetime: String,
icon: {
type: String,
value: 'hass:help-circle'
value: "hass:help-circle",
},
iconTitle: String,
iconClass: String,
};
}
}
customElements.define('hassio-card-content', HassioCardContent);
customElements.define("hassio-card-content", HassioCardContent);

View File

@@ -1,10 +1,10 @@
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/hassio-card-content.js';
import '../resources/hassio-style.js';
import NavigateMixin from '../../../src/mixins/navigate-mixin.js';
import "../components/hassio-card-content.js";
import "../resources/hassio-style.js";
import NavigateMixin from "../../../src/mixins/navigate-mixin.js";
class HassioAddons extends NavigateMixin(PolymerElement) {
static get template() {
@@ -46,28 +46,32 @@ class HassioAddons extends NavigateMixin(PolymerElement) {
}
computeIcon(addon) {
return addon.installed !== addon.version ? 'hassio:arrow-up-bold-circle' : 'hassio:puzzle';
return addon.installed !== addon.version
? "hassio:arrow-up-bold-circle"
: "hassio:puzzle";
}
computeIconTitle(addon) {
if (addon.installed !== addon.version) return 'New version available';
return addon.state === 'started' ? 'Add-on is running' : 'Add-on is stopped';
if (addon.installed !== addon.version) return "New version available";
return addon.state === "started"
? "Add-on is running"
: "Add-on is stopped";
}
computeIconClass(addon) {
if (addon.installed !== addon.version) return 'update';
return addon.state === 'started' ? 'running' : '';
if (addon.installed !== addon.version) return "update";
return addon.state === "started" ? "running" : "";
}
addonTapped(ev) {
this.navigate('/hassio/addon/' + ev.model.addon.slug);
this.navigate("/hassio/addon/" + ev.model.addon.slug);
ev.target.blur();
}
openStore(ev) {
this.navigate('/hassio/store');
this.navigate("/hassio/store");
ev.target.blur();
}
}
customElements.define('hassio-addons', HassioAddons);
customElements.define("hassio-addons", HassioAddons);

View File

@@ -1,9 +1,9 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import './hassio-addons.js';
import './hassio-hass-update.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "./hassio-addons.js";
import "./hassio-hass-update.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioDashboard extends EventsMixin(PolymerElement) {
static get template() {
@@ -29,4 +29,4 @@ class HassioDashboard extends EventsMixin(PolymerElement) {
}
}
customElements.define('hassio-dashboard', HassioDashboard);
customElements.define("hassio-dashboard", HassioDashboard);

View File

@@ -1,11 +1,11 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import '../components/hassio-card-content.js';
import '../resources/hassio-style.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import "../components/hassio-card-content.js";
import "../resources/hassio-style.js";
class HassioHassUpdate extends PolymerElement {
static get template() {
@@ -56,7 +56,7 @@ class HassioHassUpdate extends PolymerElement {
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
}
apiCalled(ev) {
@@ -67,8 +67,8 @@ class HassioHassUpdate extends PolymerElement {
const response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
if (typeof response.body === "object") {
this.errors = response.body.message || "Unknown error";
} else {
this.errors = response.body;
}
@@ -79,4 +79,4 @@ class HassioHassUpdate extends PolymerElement {
}
}
customElements.define('hassio-hass-update', HassioHassUpdate);
customElements.define("hassio-hass-update", HassioHassUpdate);

View File

@@ -1,4 +1,4 @@
window.loadES5Adapter().then(() => {
import(/* webpackChunkName: "hassio-icons" */ './resources/hassio-icons.js');
import(/* webpackChunkName: "hassio-main" */ './hassio-main.js');
import(/* webpackChunkName: "hassio-icons" */ "./resources/hassio-icons.js");
import(/* webpackChunkName: "hassio-main" */ "./hassio-main.js");
});

View File

@@ -1,8 +1,8 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import './hassio-main.js';
import './resources/hassio-icons.js';
import "./hassio-main.js";
import "./resources/hassio-icons.js";
class HassioApp extends PolymerElement {
static get template() {
@@ -29,13 +29,13 @@ class HassioApp extends PolymerElement {
ready() {
super.ready();
window.setProperties = this.setProperties.bind(this);
this.addEventListener('location-changed', () => this._locationChanged());
this.addEventListener('hass-open-menu', () => this._menuEvent(true));
this.addEventListener('hass-close-menu', () => this._menuEvent(false));
this.addEventListener("location-changed", () => this._locationChanged());
this.addEventListener("hass-open-menu", () => this._menuEvent(true));
this.addEventListener("hass-close-menu", () => this._menuEvent(false));
}
_menuEvent(shouldOpen) {
this.hassioPanel.fire(shouldOpen ? 'hass-open-menu' : 'hass-close-menu');
this.hassioPanel.fire(shouldOpen ? "hass-open-menu" : "hass-close-menu");
}
_locationChanged() {
@@ -43,4 +43,4 @@ class HassioApp extends PolymerElement {
}
}
customElements.define('hassio-app', HassioApp);
customElements.define("hassio-app", HassioApp);

View File

@@ -1,4 +1,4 @@
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
class HassioData extends PolymerElement {
static get properties() {
@@ -36,25 +36,24 @@ class HassioData extends PolymerElement {
}
fetchSupervisorInfo() {
return this.hass.callApi('get', 'hassio/supervisor/info')
.then((info) => {
return this.hass.callApi("get", "hassio/supervisor/info").then((info) => {
this.supervisor = info.data;
});
}
fetchHostInfo() {
return this.hass.callApi('get', 'hassio/host/info')
.then((info) => {
return this.hass.callApi("get", "hassio/host/info").then((info) => {
this.host = info.data;
});
}
fetchHassInfo() {
return this.hass.callApi('get', 'hassio/homeassistant/info')
return this.hass
.callApi("get", "hassio/homeassistant/info")
.then((info) => {
this.homeassistant = info.data;
});
}
}
customElements.define('hassio-data', HassioData);
customElements.define("hassio-data", HassioData);

View File

@@ -1,15 +1,15 @@
import '@polymer/app-route/app-route.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-route/app-route.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../src/layouts/hass-loading-screen.js';
import './addon-view/hassio-addon-view.js';
import './hassio-data.js';
import './hassio-pages-with-tabs.js';
import "../../src/layouts/hass-loading-screen.js";
import "./addon-view/hassio-addon-view.js";
import "./hassio-data.js";
import "./hassio-pages-with-tabs.js";
import applyThemesOnElement from '../../src/common/dom/apply_themes_on_element.js';
import EventsMixin from '../../src/mixins/events-mixin.js';
import NavigateMixin from '../../src/mixins/navigate-mixin.js';
import applyThemesOnElement from "../../src/common/dom/apply_themes_on_element.js";
import EventsMixin from "../../src/mixins/events-mixin.js";
import NavigateMixin from "../../src/mixins/navigate-mixin.js";
class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
static get template() {
@@ -41,11 +41,11 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
type: Object,
// Fake route object
value: {
prefix: '/hassio',
path: '/dashboard',
__queryParams: {}
prefix: "/hassio",
path: "/dashboard",
__queryParams: {},
},
observer: 'routeChanged',
observer: "routeChanged",
},
routeData: Object,
supervisorInfo: Object,
@@ -53,7 +53,7 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
hassInfo: Object,
loaded: {
type: Boolean,
computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo)',
computed: "computeIsLoaded(supervisorInfo, hostInfo, hassInfo)",
},
};
}
@@ -61,7 +61,7 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
ready() {
super.ready();
applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
}
connectedCallback() {
@@ -74,7 +74,7 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
let tries = 1;
const tryUpdate = () => {
this.$.data.refresh().catch(function () {
this.$.data.refresh().catch(function() {
tries += 1;
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
});
@@ -85,21 +85,19 @@ class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
}
computeIsLoaded(supervisorInfo, hostInfo, hassInfo) {
return (supervisorInfo !== null
&& hostInfo !== null
&& hassInfo !== null);
return supervisorInfo !== null && hostInfo !== null && hassInfo !== null;
}
routeChanged(route) {
if (route.path === '' && route.prefix === '/hassio') {
this.navigate('/hassio/dashboard', true);
if (route.path === "" && route.prefix === "/hassio") {
this.navigate("/hassio/dashboard", true);
}
this.fire('iron-resize');
this.fire("iron-resize");
}
equalsAddon(page) {
return page && page === 'addon';
return page && page === "addon";
}
}
customElements.define('hassio-main', HassioMain);
customElements.define("hassio-main", HassioMain);

View File

@@ -1,12 +1,12 @@
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js";
import "@polymer/paper-dialog/paper-dialog.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../src/components/ha-markdown.js';
import '../../src/resources/ha-style.js';
import "../../src/components/ha-markdown.js";
import "../../src/resources/ha-style.js";
class HassioMarkdownDialog extends PolymerElement {
static get template() {
@@ -73,4 +73,4 @@ class HassioMarkdownDialog extends PolymerElement {
this.$.dialog.open();
}
}
customElements.define('hassio-markdown-dialog', HassioMarkdownDialog);
customElements.define("hassio-markdown-dialog", HassioMarkdownDialog);

View File

@@ -1,24 +1,24 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-tabs/paper-tab.js';
import '@polymer/paper-tabs/paper-tabs.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-layout/app-header-layout/app-header-layout.js";
import "@polymer/app-layout/app-header/app-header.js";
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import "@polymer/paper-tabs/paper-tab.js";
import "@polymer/paper-tabs/paper-tabs.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import './addon-store/hassio-addon-store.js';
import './dashboard/hassio-dashboard.js';
import './hassio-markdown-dialog.js';
import './snapshots/hassio-snapshot.js';
import './snapshots/hassio-snapshots.js';
import './system/hassio-system.js';
import "../../src/components/ha-menu-button.js";
import "../../src/resources/ha-style.js";
import "./addon-store/hassio-addon-store.js";
import "./dashboard/hassio-dashboard.js";
import "./hassio-markdown-dialog.js";
import "./snapshots/hassio-snapshot.js";
import "./snapshots/hassio-snapshots.js";
import "./system/hassio-system.js";
import scrollToTarget from '../../src/common/dom/scroll-to-target.js';
import scrollToTarget from "../../src/common/dom/scroll-to-target.js";
import NavigateMixin from '../../src/mixins/navigate-mixin.js';
import NavigateMixin from "../../src/mixins/navigate-mixin.js";
class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
static get template() {
@@ -87,18 +87,20 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
markdownTitle: String,
markdownContent: {
type: String,
value: '',
value: "",
},
};
}
ready() {
super.ready();
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
this.addEventListener("hassio-markdown-dialog", (ev) =>
this.openMarkdown(ev)
);
}
handlePageSelected(ev) {
const newPage = ev.detail.item.getAttribute('page-name');
const newPage = ev.detail.item.getAttribute("page-name");
if (newPage !== this.page) {
this.navigate(`/hassio/${newPage}`);
}
@@ -110,14 +112,14 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
}
showRefreshButton(page) {
return page === 'store' || page === 'snapshots';
return page === "store" || page === "snapshots";
}
refreshClicked() {
if (this.page === 'snapshots') {
this.shadowRoot.querySelector('hassio-snapshots').refreshData();
if (this.page === "snapshots") {
this.shadowRoot.querySelector("hassio-snapshots").refreshData();
} else {
this.shadowRoot.querySelector('hassio-addon-store').refreshData();
this.shadowRoot.querySelector("hassio-addon-store").refreshData();
}
}
@@ -126,8 +128,8 @@ class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
this.shadowRoot.querySelector("hassio-markdown-dialog").openDialog();
}
}
customElements.define('hassio-pages-with-tabs', HassioPagesWithTabs);
customElements.define("hassio-pages-with-tabs", HassioPagesWithTabs);

View File

@@ -1,7 +1,7 @@
import '../../../src/components/ha-iconset-svg.js';
import iconSetContent from '../../hassio-icons.html';
import "../../../src/components/ha-iconset-svg.js";
import iconSetContent from "../../hassio-icons.html";
const documentContainer = document.createElement('template');
documentContainer.setAttribute('style', 'display: none;');
const documentContainer = document.createElement("template");
documentContainer.setAttribute("style", "display: none;");
documentContainer.innerHTML = iconSetContent;
document.head.appendChild(documentContainer.content);

View File

@@ -1,5 +1,5 @@
const documentContainer = document.createElement('template');
documentContainer.setAttribute('style', 'display: none;');
const documentContainer = document.createElement("template");
documentContainer.setAttribute("style", "display: none;");
documentContainer.innerHTML = `<dom-module id="hassio-style">
<template>

View File

@@ -1,14 +1,14 @@
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/app-layout/app-toolbar/app-toolbar.js";
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-checkbox/paper-checkbox.js";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js";
import "@polymer/paper-dialog/paper-dialog.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import "@polymer/paper-input/paper-input.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/resources/ha-style.js';
import "../../../src/resources/ha-style.js";
class HassioSnapshot extends PolymerElement {
static get template() {
@@ -114,7 +114,7 @@ class HassioSnapshot extends PolymerElement {
snapshotSlug: {
type: String,
notify: true,
observer: '_snapshotSlugChanged',
observer: "_snapshotSlugChanged",
},
snapshotDeleted: {
type: Boolean,
@@ -131,85 +131,124 @@ class HassioSnapshot extends PolymerElement {
}
_snapshotSlugChanged(snapshotSlug) {
if (!snapshotSlug || snapshotSlug === 'update') return;
this.hass.callApi('get', `hassio/snapshots/${snapshotSlug}/info`)
.then((info) => {
if (!snapshotSlug || snapshotSlug === "update") return;
this.hass.callApi("get", `hassio/snapshots/${snapshotSlug}/info`).then(
(info) => {
info.data.folders = this._computeFolders(info.data.folders);
info.data.addons = this._computeAddons(info.data.addons);
this.snapshot = info.data;
this.$.dialog.open();
}, () => {
},
() => {
this.snapshot = null;
});
}
);
}
_computeFolders(folders) {
const list = [];
if (folders.includes('homeassistant')) list.push({ slug: 'homeassistant', name: 'Home Assistant configuration', checked: true });
if (folders.includes('ssl')) list.push({ slug: 'ssl', name: 'SSL', checked: true });
if (folders.includes('share')) list.push({ slug: 'share', name: 'Share', checked: true });
if (folders.includes('addons/local')) list.push({ slug: 'addons/local', name: 'Local add-ons', checked: true });
if (folders.includes("homeassistant"))
list.push({
slug: "homeassistant",
name: "Home Assistant configuration",
checked: true,
});
if (folders.includes("ssl"))
list.push({ slug: "ssl", name: "SSL", checked: true });
if (folders.includes("share"))
list.push({ slug: "share", name: "Share", checked: true });
if (folders.includes("addons/local"))
list.push({ slug: "addons/local", name: "Local add-ons", checked: true });
return list;
}
_computeAddons(addons) {
return addons.map(addon => (
{ slug: addon.slug, name: addon.name, version: addon.version, checked: true }));
return addons.map((addon) => ({
slug: addon.slug,
name: addon.name,
version: addon.version,
checked: true,
}));
}
_isFullSnapshot(type) {
return type === 'full';
return type === "full";
}
_partialRestoreClicked() {
if (!confirm('Are you sure you want to restore this snapshot?')) {
if (!confirm("Are you sure you want to restore this snapshot?")) {
return;
}
const addons = this.snapshot.addons.filter(addon => addon.checked).map(addon => addon.slug);
const folders = this.snapshot.folders.filter(
folder => folder.checked
).map(folder => folder.slug);
const addons = this.snapshot.addons
.filter((addon) => addon.checked)
.map((addon) => addon.slug);
const folders = this.snapshot.folders
.filter((folder) => folder.checked)
.map((folder) => folder.slug);
const data = {
homeassistant: this.restoreHass,
addons: addons,
folders: folders
folders: folders,
};
if (this.snapshot.protected) data.password = this.snapshotPassword;
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/partial`, data).then(() => {
alert('Snapshot restored!');
this.hass
.callApi(
"post",
`hassio/snapshots/${this.snapshotSlug}/restore/partial`,
data
)
.then(
() => {
alert("Snapshot restored!");
this.$.dialog.close();
}, (error) => {
},
(error) => {
this.error = error.body.message;
});
}
);
}
_fullRestoreClicked() {
if (!confirm('Are you sure you want to restore this snapshot?')) {
if (!confirm("Are you sure you want to restore this snapshot?")) {
return;
}
const data = this.snapshot.protected ? { password: this.snapshotPassword } : null;
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/full`, data)
.then(() => {
alert('Snapshot restored!');
const data = this.snapshot.protected
? { password: this.snapshotPassword }
: null;
this.hass
.callApi(
"post",
`hassio/snapshots/${this.snapshotSlug}/restore/full`,
data
)
.then(
() => {
alert("Snapshot restored!");
this.$.dialog.close();
}, (error) => {
},
(error) => {
this.error = error.body.message;
});
}
);
}
_deleteClicked() {
if (!confirm('Are you sure you want to delete this snapshot?')) {
if (!confirm("Are you sure you want to delete this snapshot?")) {
return;
}
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/remove`)
.then(() => {
this.hass
.callApi("post", `hassio/snapshots/${this.snapshotSlug}/remove`)
.then(
() => {
this.$.dialog.close();
this.snapshotDeleted = true;
}, (error) => {
},
(error) => {
this.error = error.body.message;
});
}
);
}
_computeDownloadUrl(snapshotSlug) {
@@ -218,7 +257,7 @@ class HassioSnapshot extends PolymerElement {
}
_computeDownloadName(snapshot) {
const name = this._computeName(snapshot).replace(/[^a-z0-9]+/gi, '_');
const name = this._computeName(snapshot).replace(/[^a-z0-9]+/gi, "_");
return `Hass_io_${name}.tar`;
}
@@ -227,11 +266,11 @@ class HassioSnapshot extends PolymerElement {
}
_computeType(type) {
return type === 'full' ? 'Full snapshot' : 'Partial snapshot';
return type === "full" ? "Full snapshot" : "Partial snapshot";
}
_computeSize(size) {
return (Math.ceil(size * 10) / 10) + ' MB';
return Math.ceil(size * 10) / 10 + " MB";
}
_sortAddons(a, b) {
@@ -240,12 +279,12 @@ class HassioSnapshot extends PolymerElement {
_formatDatetime(datetime) {
return new Date(datetime).toLocaleDateString(navigator.language, {
weekday: 'long',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
weekday: "long",
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
});
}
@@ -253,4 +292,4 @@ class HassioSnapshot extends PolymerElement {
this.snapshotSlug = null;
}
}
customElements.define('hassio-snapshot', HassioSnapshot);
customElements.define("hassio-snapshot", HassioSnapshot);

View File

@@ -1,15 +1,15 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-radio-button/paper-radio-button.js';
import '@polymer/paper-radio-group/paper-radio-group.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-checkbox/paper-checkbox.js";
import "@polymer/paper-input/paper-input.js";
import "@polymer/paper-radio-button/paper-radio-button.js";
import "@polymer/paper-radio-group/paper-radio-group.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/hassio-card-content.js';
import '../resources/hassio-style.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../components/hassio-card-content.js";
import "../resources/hassio-style.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioSnapshots extends EventsMixin(PolymerElement) {
static get template() {
@@ -105,16 +105,16 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
hass: Object,
snapshotName: {
type: String,
value: '',
value: "",
},
snapshotPassword: {
type: String,
value: '',
value: "",
},
snapshotHasPassword: Boolean,
snapshotType: {
type: String,
value: 'full',
value: "full",
},
snapshots: {
type: Array,
@@ -122,16 +122,20 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
},
installedAddons: {
type: Array,
observer: '_installedAddonsChanged',
observer: "_installedAddonsChanged",
},
addonList: Array,
folderList: {
type: Array,
value: [
{ slug: 'homeassistant', name: 'Home Assistant configuration', checked: true },
{ slug: 'ssl', name: 'SSL', checked: true },
{ slug: 'share', name: 'Share', checked: true },
{ slug: 'addons/local', name: 'Local add-ons', checked: true },
{
slug: "homeassistant",
name: "Home Assistant configuration",
checked: true,
},
{ slug: "ssl", name: "SSL", checked: true },
{ slug: "share", name: "Share", checked: true },
{ slug: "addons/local", name: "Local add-ons", checked: true },
],
},
snapshotSlug: {
@@ -141,7 +145,7 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
snapshotDeleted: {
type: Boolean,
notify: true,
observer: '_snapshotDeletedChanged',
observer: "_snapshotDeletedChanged",
},
creatingSnapshot: Boolean,
dialogOpened: Boolean,
@@ -151,7 +155,7 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this._apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this._apiCalled(ev));
this._updateSnapshots();
}
@@ -162,57 +166,70 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
}
_updateSnapshots() {
this.hass.callApi('get', 'hassio/snapshots')
.then((result) => {
this.hass.callApi("get", "hassio/snapshots").then(
(result) => {
this.snapshots = result.data.snapshots;
}, (error) => {
},
(error) => {
this.error = error.message;
});
}
);
}
_createSnapshot() {
this.error = '';
this.error = "";
if (this.snapshotHasPassword && !this.snapshotPassword.length) {
this.error = 'Please enter a password.';
this.error = "Please enter a password.";
return;
}
this.creatingSnapshot = true;
let name = this.snapshotName;
if (!name.length) {
name = new Date().toLocaleDateString(navigator.language, {
weekday: 'long',
year: 'numeric',
month: 'short',
day: 'numeric' });
weekday: "long",
year: "numeric",
month: "short",
day: "numeric",
});
}
let data;
let path;
if (this.snapshotType === 'full') {
if (this.snapshotType === "full") {
data = { name: name };
path = 'hassio/snapshots/new/full';
path = "hassio/snapshots/new/full";
} else {
const addons = this.addonList.filter(addon => addon.checked).map(addon => addon.slug);
const folders = this.folderList.filter(folder => folder.checked).map(folder => folder.slug);
const addons = this.addonList
.filter((addon) => addon.checked)
.map((addon) => addon.slug);
const folders = this.folderList
.filter((folder) => folder.checked)
.map((folder) => folder.slug);
data = { name: name, folders: folders, addons: addons };
path = 'hassio/snapshots/new/partial';
path = "hassio/snapshots/new/partial";
}
if (this.snapshotHasPassword) {
data.password = this.snapshotPassword;
}
this.hass.callApi('post', path, data)
.then(() => {
this.hass.callApi("post", path, data).then(
() => {
this.creatingSnapshot = false;
this.fire('hass-api-called', { success: true });
}, (error) => {
this.fire("hass-api-called", { success: true });
},
(error) => {
this.creatingSnapshot = false;
this.error = error.message;
});
}
);
}
_installedAddonsChanged(addons) {
this.addonList = addons.map(addon => ({ slug: addon.slug, name: addon.name, checked: true }));
this.addonList = addons.map((addon) => ({
slug: addon.slug,
name: addon.name,
checked: true,
}));
}
_sortAddons(a, b) {
@@ -228,12 +245,15 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
}
_computeDetails(snapshot) {
const type = snapshot.type === 'full' ? 'Full snapshot' : 'Partial snapshot';
const type =
snapshot.type === "full" ? "Full snapshot" : "Partial snapshot";
return snapshot.protected ? `${type}, password protected` : type;
}
_computeIcon(type) {
return type === 'full' ? 'hassio:package-variant-closed' : 'hassio:package-variant';
return type === "full"
? "hassio:package-variant-closed"
: "hassio:package-variant";
}
_snapshotClicked(ev) {
@@ -241,7 +261,7 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
}
_fullSelected(type) {
return type === 'full';
return type === "full";
}
_snapshotDeletedChanged(snapshotDeleted) {
@@ -252,11 +272,10 @@ class HassioSnapshots extends EventsMixin(PolymerElement) {
}
refreshData() {
this.hass.callApi('post', 'hassio/snapshots/reload')
.then(() => {
this.hass.callApi("post", "hassio/snapshots/reload").then(() => {
this._updateSnapshots();
});
}
}
customElements.define('hassio-snapshots', HassioSnapshots);
customElements.define("hassio-snapshots", HassioSnapshots);

View File

@@ -1,10 +1,10 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioHostInfo extends EventsMixin(PolymerElement) {
static get template() {
@@ -97,16 +97,16 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
hass: Object,
data: {
type: Object,
observer: '_dataChanged'
observer: "_dataChanged",
},
errors: String,
_hassOs: Object
_hassOs: Object,
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
}
apiCalled(ev) {
@@ -117,17 +117,16 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
var response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
if (typeof response.body === "object") {
this.errors = response.body.message || "Unknown error";
} else {
this.errors = response.body;
}
}
_dataChanged(data) {
if (data.features && data.features.includes('hassos')) {
this.hass.callApi('get', 'hassio/hassos/info')
.then((resp) => {
if (data.features && data.features.includes("hassos")) {
this.hass.callApi("get", "hassio/hassos/info").then((resp) => {
this._hassOs = resp.data;
});
} else {
@@ -144,28 +143,31 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
}
_showHardware() {
this.hass.callApi('get', 'hassio/hardware/info')
this.hass
.callApi("get", "hassio/hardware/info")
.then(
resp => this._objectToMarkdown(resp.data),
() => 'Error getting hardware info'
).then((content) => {
this.fire('hassio-markdown-dialog', {
title: 'Hardware',
(resp) => this._objectToMarkdown(resp.data),
() => "Error getting hardware info"
)
.then((content) => {
this.fire("hassio-markdown-dialog", {
title: "Hardware",
content: content,
});
});
}
_objectToMarkdown(obj, indent = '') {
let data = '';
_objectToMarkdown(obj, indent = "") {
let data = "";
Object.keys(obj).forEach((key) => {
if (typeof obj[key] !== 'object') {
if (typeof obj[key] !== "object") {
data += `${indent}- ${key}: ${obj[key]}\n`;
} else {
data += `${indent}- ${key}:\n`;
if (Array.isArray(obj[key])) {
if (obj[key].length) {
data += `${indent} - ` + obj[key].join(`\n${indent} - `) + '\n';
data +=
`${indent} - ` + obj[key].join(`\n${indent} - `) + "\n";
}
} else {
data += this._objectToMarkdown(obj[key], ` ${indent}`);
@@ -177,11 +179,11 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
_changeHostnameClicked() {
const curHostname = this.data.hostname;
const hostname = prompt('Please enter a new hostname:', curHostname);
const hostname = prompt("Please enter a new hostname:", curHostname);
if (hostname && hostname !== curHostname) {
this.hass.callApi('post', 'hassio/host/options', { hostname });
this.hass.callApi("post", "hassio/host/options", { hostname });
}
}
}
customElements.define('hassio-host-info', HassioHostInfo);
customElements.define("hassio-host-info", HassioHostInfo);

View File

@@ -1,10 +1,10 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../../../src/components/buttons/ha-call-api-button.js';
import EventsMixin from '../../../src/mixins/events-mixin.js';
import "../../../src/components/buttons/ha-call-api-button.js";
import EventsMixin from "../../../src/mixins/events-mixin.js";
class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
static get template() {
@@ -85,14 +85,14 @@ class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
errors: String,
leaveBeta: {
type: Object,
value: { channel: 'stable' },
value: { channel: "stable" },
},
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
}
apiCalled(ev) {
@@ -103,8 +103,8 @@ class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
var response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
if (typeof response.body === "object") {
this.errors = response.body.message || "Unknown error";
} else {
this.errors = response.body;
}
@@ -119,18 +119,20 @@ class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
}
_joinBeta() {
if (!confirm(`WARNING:
if (
!confirm(`WARNING:
Beta 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.
This inludes beta releases for:
- Home Assistant (Release Candidates)
- Hass.io supervisor
- Host system`)) {
- Host system`)
) {
return;
}
const method = 'post';
const path = 'hassio/supervisor/options';
const data = { channel: 'beta' };
const method = "post";
const path = "hassio/supervisor/options";
const data = { channel: "beta" };
const eventData = {
method: method,
@@ -138,17 +140,22 @@ This inludes beta releases for:
data: data,
};
this.hass.callApi(method, path, data)
.then((resp) => {
this.hass
.callApi(method, path, data)
.then(
(resp) => {
eventData.success = true;
eventData.response = resp;
}, (resp) => {
},
(resp) => {
eventData.success = false;
eventData.response = resp;
}).then(() => {
this.fire('hass-api-called', eventData);
}
)
.then(() => {
this.fire("hass-api-called", eventData);
});
}
}
customElements.define('hassio-supervisor-info', HassioSupervisorInfo);
customElements.define("hassio-supervisor-info", HassioSupervisorInfo);

View File

@@ -1,7 +1,7 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
class HassioSupervisorLog extends PolymerElement {
static get template() {
@@ -38,12 +38,14 @@ class HassioSupervisorLog extends PolymerElement {
}
loadData() {
this.hass.callApi('get', 'hassio/supervisor/logs')
.then((info) => {
this.hass.callApi("get", "hassio/supervisor/logs").then(
(info) => {
this.log = info;
}, () => {
this.log = 'Error fetching logs';
});
},
() => {
this.log = "Error fetching logs";
}
);
}
refreshTapped() {
@@ -51,4 +53,4 @@ class HassioSupervisorLog extends PolymerElement {
}
}
customElements.define('hassio-supervisor-log', HassioSupervisorLog);
customElements.define("hassio-supervisor-log", HassioSupervisorLog);

View File

@@ -1,10 +1,10 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-flex-layout/iron-flex-layout-classes.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import './hassio-host-info.js';
import './hassio-supervisor-info.js';
import './hassio-supervisor-log.js';
import "./hassio-host-info.js";
import "./hassio-supervisor-info.js";
import "./hassio-supervisor-log.js";
class HassioSystem extends PolymerElement {
static get template() {
@@ -40,4 +40,4 @@ class HassioSystem extends PolymerElement {
}
}
customElements.define('hassio-system', HassioSystem);
customElements.define("hassio-system", HassioSystem);

View File

@@ -1,26 +1,25 @@
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const config = require('./config.js');
const config = require("./config.js");
const isProdBuild = process.env.NODE_ENV === 'production'
const chunkFilename = isProdBuild ?
'chunk.[chunkhash].js' : '[name].chunk.js';
const isProdBuild = process.env.NODE_ENV === "production";
const chunkFilename = isProdBuild ? "chunk.[chunkhash].js" : "[name].chunk.js";
module.exports = {
mode: isProdBuild ? 'production' : 'development',
devtool: isProdBuild ? 'source-map' : 'inline-source-map',
mode: isProdBuild ? "production" : "development",
devtool: isProdBuild ? "source-map" : "inline-source-map",
entry: {
entrypoint: './src/entrypoint.js',
entrypoint: "./src/entrypoint.js",
},
module: {
rules: [
{
test: /\.m?js$/,
use: {
loader: 'babel-loader',
loader: "babel-loader",
options: {
presets: [
[require('babel-preset-env').default, { modules: false }]
[require("babel-preset-env").default, { modules: false }],
],
plugins: [
// Only support the syntax, Webpack will handle it.
@@ -32,38 +31,34 @@ module.exports = {
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
loader: "html-loader",
options: {
exportAsEs6Default: true,
}
}
}
]
},
},
},
],
},
plugins: [
isProdBuild && new UglifyJsPlugin({
isProdBuild &&
new UglifyJsPlugin({
extractComments: true,
sourceMap: true,
uglifyOptions: {
// Disabling because it broke output
mangle: false,
}
},
}),
isProdBuild && new CompressionPlugin({
isProdBuild &&
new CompressionPlugin({
cache: true,
exclude: [
/\.js\.map$/,
/\.LICENSE$/,
/\.py$/,
/\.txt$/,
]
exclude: [/\.js\.map$/, /\.LICENSE$/, /\.py$/, /\.txt$/],
}),
].filter(Boolean),
output: {
filename: '[name].js',
filename: "[name].js",
chunkFilename,
path: config.buildDir,
publicPath: `${config.publicPath}/`,
}
},
};

View File

@@ -104,7 +104,9 @@
"del": "^3.0.0",
"eslint": "^5.6.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^3.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.11.1",
"gulp": "^3.9.1",
"gulp-foreach": "^0.1.0",
@@ -117,12 +119,15 @@
"html-loader": "^0.5.5",
"html-minifier": "^3.5.20",
"html-webpack-plugin": "^3.2.0",
"husky": "^1.1.0",
"lint-staged": "^7.3.0",
"merge-stream": "^1.0.1",
"mocha": "^5.2.0",
"parse5": "^5.1.0",
"polymer-analyzer": "^3.1.2",
"polymer-bundler": "^4.0.2",
"polymer-cli": "^1.8.0",
"prettier": "^1.14.3",
"raw-loader": "^0.5.1",
"reify": "^0.17.3",
"require-dir": "^1.0.0",
@@ -146,5 +151,20 @@
"@vaadin/vaadin-lumo-styles": "1.2.0",
"fecha": "https://github.com/balloob/fecha/archive/51d14fd0eb4781e2ecf265d1c3080706259133b5.tar.gz"
},
"main": "src/home-assistant.js"
"main": "src/home-assistant.js",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,json,css,md}": [
"prettier --write",
"git add"
]
},
"prettier": {
"trailingComma": "es5",
"arrowParens": "always"
}
}

View File

@@ -1,8 +1,8 @@
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import '../components/ha-form.js';
import LocalizeLiteMixin from '../mixins/localize-lite-mixin.js';
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import "@polymer/paper-button/paper-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import "../components/ha-form.js";
import LocalizeLiteMixin from "../mixins/localize-lite-mixin.js";
class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
static get template() {
@@ -61,14 +61,14 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
return {
authProvider: {
type: Object,
observer: '_providerChanged',
observer: "_providerChanged",
},
clientId: String,
redirectUri: String,
oauth2State: String,
_state: {
type: String,
value: 'loading'
value: "loading",
},
_stepData: {
type: Object,
@@ -85,7 +85,7 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
ready() {
super.ready();
this.addEventListener('keypress', (ev) => {
this.addEventListener("keypress", (ev) => {
if (ev.keyCode === 13) {
this._handleSubmit();
}
@@ -93,22 +93,22 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
}
async _providerChanged(newProvider, oldProvider) {
if (oldProvider && this._step && this._step.type === 'form') {
if (oldProvider && this._step && this._step.type === "form") {
fetch(`/auth/login_flow/${this._step.flow_id}`, {
method: 'DELETE',
credentials: 'same-origin',
method: "DELETE",
credentials: "same-origin",
}).catch(() => {});
}
try {
const response = await fetch('/auth/login_flow', {
method: 'POST',
credentials: 'same-origin',
const response = await fetch("/auth/login_flow", {
method: "POST",
credentials: "same-origin",
body: JSON.stringify({
client_id: this.clientId,
handler: [newProvider.type, newProvider.id],
redirect_uri: this.redirectUri,
})
}),
});
const data = await response.json();
@@ -117,16 +117,16 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
this._updateStep(data);
} else {
this.setProperties({
_state: 'error',
_state: "error",
_errorMsg: data.message,
});
}
} catch (err) {
// eslint-disable-next-line
console.error('Error starting auth flow', err);
console.error("Error starting auth flow", err);
this.setProperties({
_state: 'error',
_errorMsg: this.localize('ui.panel.page-authorize.form.unknown_error'),
_state: "error",
_errorMsg: this.localize("ui.panel.page-authorize.form.unknown_error"),
});
}
}
@@ -134,11 +134,14 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
_updateStep(step) {
const props = {
_step: step,
_state: 'step',
_state: "step",
};
if (this._step
&& (step.flow_id !== this._step.flow_id || step.step_id !== this._step.step_id)) {
if (
this._step &&
(step.flow_id !== this._step.flow_id ||
step.step_id !== this._step.step_id)
) {
props._stepData = {};
}
@@ -150,15 +153,23 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
}
_computeSubmitCaption(stepType) {
return stepType === 'form' ? 'Next' : 'Start over';
return stepType === "form" ? "Next" : "Start over";
}
_computeStepAbortedReason(localize, step) {
return localize(`ui.panel.page-authorize.form.providers.${step.handler[0]}.abort.${step.reason}`);
return localize(
`ui.panel.page-authorize.form.providers.${step.handler[0]}.abort.${
step.reason
}`
);
}
_computeStepDescription(localize, step) {
const args = [`ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${step.step_id}.description`];
const args = [
`ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${
step.step_id
}.description`,
];
const placeholders = step.description_placeholders || {};
Object.keys(placeholders).forEach((key) => {
args.push(key);
@@ -169,22 +180,32 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
_computeLabelCallback(localize, step) {
// Returns a callback for ha-form to calculate labels per schema object
return schema => localize(`ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${step.step_id}.data.${schema.name}`);
return (schema) =>
localize(
`ui.panel.page-authorize.form.providers.${step.handler[0]}.step.${
step.step_id
}.data.${schema.name}`
);
}
_computeErrorCallback(localize, step) {
// Returns a callback for ha-form to calculate error messages
return error => localize(`ui.panel.page-authorize.form.providers.${step.handler[0]}.error.${error}`);
return (error) =>
localize(
`ui.panel.page-authorize.form.providers.${
step.handler[0]
}.error.${error}`
);
}
async _handleSubmit() {
if (this._step.type !== 'form') {
if (this._step.type !== "form") {
this._providerChanged(this.authProvider, null);
return;
}
this._state = 'loading';
this._state = "loading";
// To avoid a jumping UI.
this.style.setProperty('min-height', `${this.offsetHeight}px`);
this.style.setProperty("min-height", `${this.offsetHeight}px`);
const postData = Object.assign({}, this._stepData, {
client_id: this.clientId,
@@ -192,20 +213,20 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
try {
const response = await fetch(`/auth/login_flow/${this._step.flow_id}`, {
method: 'POST',
credentials: 'same-origin',
body: JSON.stringify(postData)
method: "POST",
credentials: "same-origin",
body: JSON.stringify(postData),
});
const newStep = await response.json();
if (newStep.type === 'create_entry') {
if (newStep.type === "create_entry") {
// OAuth 2: 3.1.2 we need to retain query component of a redirect URI
let url = this.redirectUri;
if (!url.includes('?')) {
url += '?';
} else if (!url.endsWith('&')) {
url += '&';
if (!url.includes("?")) {
url += "?";
} else if (!url.endsWith("&")) {
url += "&";
}
url += `code=${encodeURIComponent(newStep.result)}`;
@@ -220,11 +241,11 @@ class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
this._updateStep(newStep);
} catch (err) {
// eslint-disable-next-line
console.error('Error submitting step', err);
this._state = 'error-loading';
console.error("Error submitting step", err);
this._state = "error-loading";
} finally {
this.style.setProperty('min-height', '');
this.style.setProperty("min-height", "");
}
}
}
customElements.define('ha-auth-flow', HaAuthFlow);
customElements.define("ha-auth-flow", HaAuthFlow);

View File

@@ -1,13 +1,13 @@
import '@polymer/polymer/lib/elements/dom-if.js';
import '@polymer/polymer/lib/elements/dom-repeat.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/polymer/lib/elements/dom-if.js";
import "@polymer/polymer/lib/elements/dom-repeat.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/ha-markdown.js';
import "../components/ha-markdown.js";
import LocalizeLiteMixin from '../mixins/localize-lite-mixin.js';
import LocalizeLiteMixin from "../mixins/localize-lite-mixin.js";
import './ha-auth-flow.js';
import "./ha-auth-flow.js";
class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
static get template() {
@@ -66,17 +66,17 @@ class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
oauth2State: String,
translationFragment: {
type: String,
value: 'page-authorize',
}
value: "page-authorize",
},
};
}
async ready() {
super.ready();
const query = {};
const values = location.search.substr(1).split('&');
const values = location.search.substr(1).split("&");
for (let i = 0; i < values.length; i++) {
const value = values[i].split('=');
const value = values[i].split("=");
if (value.length > 1) {
query[decodeURIComponent(value[0])] = decodeURIComponent(value[1]);
}
@@ -87,7 +87,7 @@ class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
if (query.state) props.oauth2State = query.state;
this.setProperties(props);
import(/* webpackChunkName: "pick-auth-provider" */ '../auth/ha-pick-auth-provider.js');
import(/* webpackChunkName: "pick-auth-provider" */ "../auth/ha-pick-auth-provider.js");
// Fetch auth providers
try {
@@ -95,13 +95,16 @@ class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
const authProviders = await response.json();
// Forward to main screen which will redirect to right onboarding page.
if (response.status === 400 && authProviders.code === 'onboarding_required') {
location.href = '/';
if (
response.status === 400 &&
authProviders.code === "onboarding_required"
) {
location.href = "/";
return;
}
if (authProviders.length === 0) {
alert('No auth providers returned. Unable to finish login.');
alert("No auth providers returned. Unable to finish login.");
return;
}
@@ -111,8 +114,8 @@ class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
});
} catch (err) {
// eslint-disable-next-line
console.error('Error loading auth providers', err);
this._state = 'error-loading';
console.error("Error loading auth providers", err);
this._state = "error-loading";
}
}
@@ -125,15 +128,25 @@ class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
}
_computeInactiveProvders(curProvider, providers) {
return providers.filter(prv => prv.type !== curProvider.type || prv.id !== curProvider.id);
return providers.filter(
(prv) => prv.type !== curProvider.type || prv.id !== curProvider.id
);
}
_computeIntro(localize, clientId, authProvider) {
return (
localize('ui.panel.page-authorize.authorizing_client', 'clientId', clientId)
+ '\n\n'
+ localize('ui.panel.page-authorize.logging_in_with', 'authProviderName', authProvider.name)
localize(
"ui.panel.page-authorize.authorizing_client",
"clientId",
clientId
) +
"\n\n" +
localize(
"ui.panel.page-authorize.logging_in_with",
"authProviderName",
authProvider.name
)
);
}
}
customElements.define('ha-authorize', HaAuthorize);
customElements.define("ha-authorize", HaAuthorize);

View File

@@ -1,15 +1,17 @@
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-item/paper-item-body.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-item/paper-item.js";
import "@polymer/paper-item/paper-item-body.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import EventsMixin from '../mixins/events-mixin.js';
import LocalizeLiteMixin from '../mixins/localize-lite-mixin.js';
import EventsMixin from "../mixins/events-mixin.js";
import LocalizeLiteMixin from "../mixins/localize-lite-mixin.js";
/*
* @appliesMixin EventsMixin
*/
class HaPickAuthProvider extends EventsMixin(LocalizeLiteMixin(PolymerElement)) {
class HaPickAuthProvider extends EventsMixin(
LocalizeLiteMixin(PolymerElement)
) {
static get template() {
return html`
<style>
@@ -34,18 +36,18 @@ class HaPickAuthProvider extends EventsMixin(LocalizeLiteMixin(PolymerElement))
return {
_state: {
type: String,
value: 'loading'
value: "loading",
},
authProviders: Array,
};
}
_handlePick(ev) {
this.fire('pick', ev.model.item);
this.fire("pick", ev.model.item);
}
_equal(a, b) {
return a === b;
}
}
customElements.define('ha-pick-auth-provider', HaPickAuthProvider);
customElements.define("ha-pick-auth-provider", HaPickAuthProvider);

View File

@@ -1,7 +1,7 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/entity/ha-state-label-badge.js';
import "../components/entity/ha-state-label-badge.js";
class HaBadgesCard extends PolymerElement {
static get template() {
@@ -25,4 +25,4 @@ class HaBadgesCard extends PolymerElement {
};
}
}
customElements.define('ha-badges-card', HaBadgesCard);
customElements.define("ha-badges-card", HaBadgesCard);

View File

@@ -1,11 +1,10 @@
import '@polymer/paper-styles/element-styles/paper-material-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-styles/element-styles/paper-material-styles.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import computeStateName from '../common/entity/compute_state_name.js';
import EventsMixin from '../mixins/events-mixin.js';
import LocalizeMixin from '../mixins/localize-mixin.js';
import computeStateName from "../common/entity/compute_state_name.js";
import EventsMixin from "../mixins/events-mixin.js";
import LocalizeMixin from "../mixins/localize-mixin.js";
const UPDATE_INTERVAL = 10000; // ms
/*
@@ -67,11 +66,11 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
hass: Object,
stateObj: {
type: Object,
observer: 'updateCameraFeedSrc',
observer: "updateCameraFeedSrc",
},
cameraFeedSrc: {
type: String,
value: '',
value: "",
},
imageLoaded: {
type: Boolean,
@@ -82,7 +81,7 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
ready() {
super.ready();
this.addEventListener('click', () => this.cardTapped());
this.addEventListener("click", () => this.cardTapped());
}
connectedCallback() {
@@ -96,13 +95,13 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
cardTapped() {
this.fire('hass-more-info', { entityId: this.stateObj.entity_id });
this.fire("hass-more-info", { entityId: this.stateObj.entity_id });
}
async updateCameraFeedSrc() {
try {
const { content_type: contentType, content } = await this.hass.callWS({
type: 'camera_thumbnail',
type: "camera_thumbnail",
entity_id: this.stateObj.entity_id,
});
this.setProperties({
@@ -118,4 +117,4 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
return computeStateName(stateObj);
}
}
customElements.define('ha-camera-card', HaCameraCard);
customElements.define("ha-camera-card", HaCameraCard);

View File

@@ -1,28 +1,29 @@
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import './ha-camera-card.js';
import './ha-entities-card.js';
import './ha-history_graph-card.js';
import './ha-media_player-card.js';
import './ha-persistent_notification-card.js';
import './ha-plant-card.js';
import './ha-weather-card.js';
import "./ha-camera-card.js";
import "./ha-entities-card.js";
import "./ha-history_graph-card.js";
import "./ha-media_player-card.js";
import "./ha-persistent_notification-card.js";
import "./ha-plant-card.js";
import "./ha-weather-card.js";
import dynamicContentUpdater from '../common/dom/dynamic_content_updater.js';
import dynamicContentUpdater from "../common/dom/dynamic_content_updater.js";
class HaCardChooser extends PolymerElement {
static get properties() {
return {
cardData: {
type: Object,
observer: 'cardDataChanged',
observer: "cardDataChanged",
},
};
}
_updateCard(newData) {
dynamicContentUpdater(
this, 'HA-' + newData.cardType.toUpperCase() + '-CARD',
this,
"HA-" + newData.cardType.toUpperCase() + "-CARD",
newData
);
}
@@ -32,7 +33,7 @@ class HaCardChooser extends PolymerElement {
this.observer = new IntersectionObserver((entries) => {
if (!entries.length) return;
if (entries[0].isIntersecting) {
this.style.height = '';
this.style.height = "";
if (this._detachedChild) {
this.appendChild(this._detachedChild);
this._detachedChild = null;
@@ -58,13 +59,14 @@ class HaCardChooser extends PolymerElement {
if (!newData) return;
// ha-entities-card is exempt from observer as it doesn't load heavy resources.
// and usually doesn't load external resources (except for entity_picture).
const eligibleToObserver = (window.IntersectionObserver && newData.cardType !== 'entities');
const eligibleToObserver =
window.IntersectionObserver && newData.cardType !== "entities";
if (!eligibleToObserver) {
if (this.observer) {
this.observer.unobserve(this);
this.observer = null;
}
this.style.height = '';
this.style.height = "";
this._updateCard(newData);
return;
}
@@ -76,4 +78,4 @@ class HaCardChooser extends PolymerElement {
}
}
}
customElements.define('ha-card-chooser', HaCardChooser);
customElements.define("ha-card-chooser", HaCardChooser);

View File

@@ -1,18 +1,17 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-flex-layout/iron-flex-layout-classes.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/entity/ha-entity-toggle.js';
import '../components/ha-card.js';
import '../state-summary/state-card-content.js';
import "../components/entity/ha-entity-toggle.js";
import "../components/ha-card.js";
import "../state-summary/state-card-content.js";
import computeStateDomain from '../common/entity/compute_state_domain.js';
import computeStateName from '../common/entity/compute_state_name.js';
import stateMoreInfoType from '../common/entity/state_more_info_type.js';
import canToggleState from '../common/entity/can_toggle_state.js';
import EventsMixin from '../mixins/events-mixin.js';
import LocalizeMixin from '../mixins/localize-mixin.js';
import computeStateDomain from "../common/entity/compute_state_domain.js";
import computeStateName from "../common/entity/compute_state_name.js";
import stateMoreInfoType from "../common/entity/state_more_info_type.js";
import canToggleState from "../common/entity/can_toggle_state.js";
import EventsMixin from "../mixins/events-mixin.js";
import LocalizeMixin from "../mixins/localize-mixin.js";
class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get template() {
@@ -74,7 +73,7 @@ class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
groupEntity: Object,
title: {
type: String,
computed: 'computeTitle(states, groupEntity, localize)',
computed: "computeTitle(states, groupEntity, localize)",
},
};
}
@@ -91,34 +90,40 @@ class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
return computeStateName(groupEntity).trim();
}
const domain = computeStateDomain(states[0]);
return (localize && localize(`domain.${domain}`)) || domain.replace(/_/g, ' ');
return (
(localize && localize(`domain.${domain}`)) || domain.replace(/_/g, " ")
);
}
computeTitleClass(groupEntity) {
let classes = 'header horizontal layout center ';
let classes = "header horizontal layout center ";
if (groupEntity) {
classes += 'more-info';
classes += "more-info";
}
return classes;
}
computeStateClass(stateObj) {
return stateMoreInfoType(stateObj) !== 'hidden' ? 'state more-info' : 'state';
return stateMoreInfoType(stateObj) !== "hidden"
? "state more-info"
: "state";
}
addTapEvents() {
const cards = this.root.querySelectorAll('.state');
const cards = this.root.querySelectorAll(".state");
cards.forEach((card) => {
if (card.classList.contains('more-info')) {
card.addEventListener('click', this.entityTapped);
if (card.classList.contains("more-info")) {
card.addEventListener("click", this.entityTapped);
} else {
card.removeEventListener('click', this.entityTapped);
card.removeEventListener("click", this.entityTapped);
}
});
}
entityTapped(ev) {
const item = this.root.querySelector('dom-repeat').itemForElement(ev.target);
const item = this.root
.querySelector("dom-repeat")
.itemForElement(ev.target);
let entityId;
if (!item && !this.groupEntity) {
return;
@@ -130,12 +135,16 @@ class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
} else {
entityId = this.groupEntity.entity_id;
}
this.fire('hass-more-info', { entityId: entityId });
this.fire("hass-more-info", { entityId: entityId });
}
showGroupToggle(groupEntity, states) {
if (!groupEntity || !states || groupEntity.attributes.control === 'hidden'
|| (groupEntity.state !== 'on' && groupEntity.state !== 'off')) {
if (
!groupEntity ||
!states ||
groupEntity.attributes.control === "hidden" ||
(groupEntity.state !== "on" && groupEntity.state !== "off")
) {
return false;
}
@@ -156,4 +165,4 @@ class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
return canToggleCount > 1;
}
}
customElements.define('ha-entities-card', HaEntitiesCard);
customElements.define("ha-entities-card", HaEntitiesCard);

View File

@@ -1,13 +1,12 @@
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-card/paper-card.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/state-history-charts.js';
import '../data/ha-state-history-data.js';
import "../components/state-history-charts.js";
import "../data/ha-state-history-data.js";
import computeStateName from '../common/entity/compute_state_name.js';
import EventsMixin from '../mixins/events-mixin.js';
import computeStateName from "../common/entity/compute_state_name.js";
import EventsMixin from "../mixins/events-mixin.js";
/*
* @appliesMixin EventsMixin
@@ -55,7 +54,7 @@ class HaHistoryGraphCard extends EventsMixin(PolymerElement) {
hass: Object,
stateObj: {
type: Object,
observer: 'stateObjObserver',
observer: "stateObjObserver",
},
inDialog: {
type: Boolean,
@@ -76,14 +75,19 @@ class HaHistoryGraphCard extends EventsMixin(PolymerElement) {
stateObjObserver(stateObj) {
if (!stateObj) return;
if (this.cacheConfig.cacheKey !== stateObj.entity_id
|| this.cacheConfig.refresh !== (stateObj.attributes.refresh || 0)
|| this.cacheConfig.hoursToShow !== (stateObj.attributes.hours_to_show || 24)) {
this.cacheConfig = Object.assign({}, {
if (
this.cacheConfig.cacheKey !== stateObj.entity_id ||
this.cacheConfig.refresh !== (stateObj.attributes.refresh || 0) ||
this.cacheConfig.hoursToShow !== (stateObj.attributes.hours_to_show || 24)
) {
this.cacheConfig = Object.assign(
{},
{
refresh: stateObj.attributes.refresh || 0,
cacheKey: stateObj.entity_id,
hoursToShow: stateObj.attributes.hours_to_show || 24
});
hoursToShow: stateObj.attributes.hours_to_show || 24,
}
);
}
}
@@ -92,7 +96,7 @@ class HaHistoryGraphCard extends EventsMixin(PolymerElement) {
}
computeContentClass(inDialog) {
return inDialog ? '' : 'content';
return inDialog ? "" : "content";
}
computeHistoryEntities(stateObj) {
@@ -104,11 +108,11 @@ class HaHistoryGraphCard extends EventsMixin(PolymerElement) {
}
cardTapped(ev) {
const mq = window.matchMedia('(min-width: 610px) and (min-height: 550px)');
const mq = window.matchMedia("(min-width: 610px) and (min-height: 550px)");
if (mq.matches) {
ev.stopPropagation();
this.fire('hass-more-info', { entityId: this.stateObj.entity_id });
this.fire("hass-more-info", { entityId: this.stateObj.entity_id });
}
}
}
customElements.define('ha-history_graph-card', HaHistoryGraphCard);
customElements.define("ha-history_graph-card", HaHistoryGraphCard);

View File

@@ -1,15 +1,15 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-progress/paper-progress.js';
import '@polymer/paper-styles/element-styles/paper-material-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/iron-flex-layout/iron-flex-layout-classes.js";
import "@polymer/paper-icon-button/paper-icon-button.js";
import "@polymer/paper-progress/paper-progress.js";
import "@polymer/paper-styles/element-styles/paper-material-styles.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import HassMediaPlayerEntity from '../util/hass-media-player-model.js';
import HassMediaPlayerEntity from "../util/hass-media-player-model.js";
import computeStateName from '../common/entity/compute_state_name.js';
import EventsMixin from '../mixins/events-mixin.js';
import LocalizeMixin from '../mixins/localize-mixin.js';
import computeStateName from "../common/entity/compute_state_name.js";
import EventsMixin from "../mixins/events-mixin.js";
import LocalizeMixin from "../mixins/localize-mixin.js";
/*
* @appliesMixin LocalizeMixin
@@ -189,12 +189,12 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
stateObj: Object,
playerObj: {
type: Object,
computed: 'computePlayerObj(hass, stateObj)',
observer: 'playerObjChanged',
computed: "computePlayerObj(hass, stateObj)",
observer: "playerObjChanged",
},
playbackControlIcon: {
type: String,
computed: 'computePlaybackControlIcon(playerObj)',
computed: "computePlaybackControlIcon(playerObj)",
},
playbackPosition: Number,
};
@@ -203,7 +203,10 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
async playerObjChanged(playerObj, oldPlayerObj) {
if (playerObj.isPlaying && playerObj.showProgress) {
if (!this._positionTracking) {
this._positionTracking = setInterval(() => this.updatePlaybackPosition(), 1000);
this._positionTracking = setInterval(
() => this.updatePlaybackPosition(),
1000
);
}
} else if (this._positionTracking) {
clearInterval(this._positionTracking);
@@ -214,25 +217,27 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
const picture = playerObj.stateObj.attributes.entity_picture;
const oldPicture = oldPlayerObj && oldPlayerObj.stateObj.attributes.entity_picture;
const oldPicture =
oldPlayerObj && oldPlayerObj.stateObj.attributes.entity_picture;
if (picture !== oldPicture && !picture) {
this.$.cover.style.backgroundImage = '';
this.$.cover.style.backgroundImage = "";
return;
} if (picture === oldPicture) {
}
if (picture === oldPicture) {
return;
}
// We have a new picture url
try {
const { content_type: contentType, content } = await this.hass.callWS({
type: 'media_player_thumbnail',
type: "media_player_thumbnail",
entity_id: playerObj.stateObj.entity_id,
});
this.$.cover.style.backgroundImage = `url(data:${contentType};base64,${content})`;
} catch (err) {
this.$.cover.style.backgroundImage = '';
this.$.cover.parentElement.classList.add('no-cover');
this.$.cover.style.backgroundImage = "";
this.$.cover.parentElement.classList.add("no-cover");
}
}
@@ -241,14 +246,14 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
computeBannerClasses(playerObj) {
var cls = 'banner';
var cls = "banner";
if (playerObj.isOff || playerObj.isIdle) {
cls += ' is-off no-cover';
cls += " is-off no-cover";
} else if (!playerObj.stateObj.attributes.entity_picture) {
cls += ' no-cover';
} else if (playerObj.stateObj.attributes.media_content_type === 'music') {
cls += ' content-type-music';
cls += " no-cover";
} else if (playerObj.stateObj.attributes.media_content_type === "music") {
cls += " content-type-music";
}
return cls;
@@ -259,7 +264,9 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
computeHidePowerButton(playerObj) {
return playerObj.isOff ? !playerObj.supportsTurnOn : !playerObj.supportsTurnOff;
return playerObj.isOff
? !playerObj.supportsTurnOn
: !playerObj.supportsTurnOff;
}
computePlayerObj(hass, stateObj) {
@@ -267,21 +274,29 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
}
computePrimaryText(localize, playerObj) {
return playerObj.primaryTitle
|| localize(`state.media_player.${playerObj.stateObj.state}`)
|| localize(`state.default.${playerObj.stateObj.state}`) || playerObj.stateObj.state;
return (
playerObj.primaryTitle ||
localize(`state.media_player.${playerObj.stateObj.state}`) ||
localize(`state.default.${playerObj.stateObj.state}`) ||
playerObj.stateObj.state
);
}
computePlaybackControlIcon(playerObj) {
if (playerObj.isPlaying) {
return playerObj.supportsPause ? 'hass:pause' : 'hass:stop';
} if (playerObj.hasMediaControl || playerObj.isOff || playerObj.isIdle) {
if (playerObj.hasMediaControl && playerObj.supportsPause && !playerObj.isPaused) {
return 'hass:play-pause';
return playerObj.supportsPause ? "hass:pause" : "hass:stop";
}
return playerObj.supportsPlay ? 'hass:play' : null;
if (playerObj.hasMediaControl || playerObj.isOff || playerObj.isIdle) {
if (
playerObj.hasMediaControl &&
playerObj.supportsPause &&
!playerObj.isPaused
) {
return "hass:play-pause";
}
return '';
return playerObj.supportsPlay ? "hass:play" : null;
}
return "";
}
_computeStateName(stateObj) {
@@ -295,7 +310,7 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
handleOpenMoreInfo(ev) {
ev.stopPropagation();
this.fire('hass-more-info', { entityId: this.stateObj.entity_id });
this.fire("hass-more-info", { entityId: this.stateObj.entity_id });
}
handlePlaybackControl(ev) {
@@ -313,4 +328,4 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
this.playerObj.togglePower();
}
}
customElements.define('ha-media_player-card', HaMediaPlayerCard);
customElements.define("ha-media_player-card", HaMediaPlayerCard);

View File

@@ -1,14 +1,13 @@
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import "@polymer/paper-button/paper-button.js";
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/ha-card.js';
import '../components/ha-markdown.js';
import "../components/ha-card.js";
import "../components/ha-markdown.js";
import computeStateName from '../common/entity/compute_state_name.js';
import LocalizeMixin from '../mixins/localize-mixin.js';
import computeObjectId from '../common/entity/compute_object_id';
import computeStateName from "../common/entity/compute_state_name.js";
import LocalizeMixin from "../mixins/localize-mixin.js";
import computeObjectId from "../common/entity/compute_object_id";
/*
* @appliesMixin LocalizeMixin
@@ -60,15 +59,17 @@ class HaPersistentNotificationCard extends LocalizeMixin(PolymerElement) {
}
computeTitle(stateObj) {
return (stateObj.attributes.title
|| computeStateName(stateObj));
return stateObj.attributes.title || computeStateName(stateObj);
}
dismissTap(ev) {
ev.preventDefault();
this.hass.callService('persistent_notification', 'dismiss', {
notification_id: computeObjectId(this.stateObj.entity_id)
this.hass.callService("persistent_notification", "dismiss", {
notification_id: computeObjectId(this.stateObj.entity_id),
});
}
}
customElements.define('ha-persistent_notification-card', HaPersistentNotificationCard);
customElements.define(
"ha-persistent_notification-card",
HaPersistentNotificationCard
);

View File

@@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/ha-card.js';
import '../components/ha-icon.js';
import "../components/ha-card.js";
import "../components/ha-icon.js";
import computeStateName from '../common/entity/compute_state_name.js';
import EventsMixin from '../mixins/events-mixin.js';
import computeStateName from "../common/entity/compute_state_name.js";
import EventsMixin from "../mixins/events-mixin.js";
class HaPlantCard extends EventsMixin(PolymerElement) {
static get template() {
@@ -85,18 +85,18 @@ class HaPlantCard extends EventsMixin(PolymerElement) {
static get properties() {
return {
hass: Object,
stateObj: Object
stateObj: Object,
};
}
constructor() {
super();
this.sensors = {
moisture: 'hass:water',
temperature: 'hass:thermometer',
brightness: 'hass:white-balance-sunny',
conductivity: 'hass:emoticon-poop',
battery: 'hass:battery'
moisture: "hass:water",
temperature: "hass:thermometer",
brightness: "hass:white-balance-sunny",
conductivity: "hass:emoticon-poop",
battery: "hass:battery",
};
}
@@ -105,16 +105,17 @@ class HaPlantCard extends EventsMixin(PolymerElement) {
}
computeAttributes(data) {
return Object.keys(this.sensors).filter(key => key in data);
return Object.keys(this.sensors).filter((key) => key in data);
}
computeIcon(attr, batLvl) {
const icon = this.sensors[attr];
if (attr === 'battery') {
if (attr === "battery") {
if (batLvl <= 5) {
return `${icon}-alert`;
} if (batLvl < 95) {
return `${icon}-${Math.round((batLvl / 10) - 0.01) * 10}`;
}
if (batLvl < 95) {
return `${icon}-${Math.round(batLvl / 10 - 0.01) * 10}`;
}
}
return icon;
@@ -125,20 +126,22 @@ class HaPlantCard extends EventsMixin(PolymerElement) {
}
computeUom(dict, attr) {
return dict[attr] || '';
return dict[attr] || "";
}
computeAttributeClass(problem, attr) {
return problem.indexOf(attr) === -1 ? '' : 'problem';
return problem.indexOf(attr) === -1 ? "" : "problem";
}
computeImageClass(entityPicture) {
return entityPicture ? 'has-plant-image' : '';
return entityPicture ? "has-plant-image" : "";
}
attributeClicked(ev) {
this.fire('hass-more-info', { entityId: this.stateObj.attributes.sensors[ev.model.item] });
this.fire("hass-more-info", {
entityId: this.stateObj.attributes.sensors[ev.model.item],
});
}
}
customElements.define('ha-plant-card', HaPlantCard);
customElements.define("ha-plant-card", HaPlantCard);

View File

@@ -1,17 +1,16 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
import '../components/ha-card.js';
import '../components/ha-icon.js';
import "../components/ha-card.js";
import "../components/ha-icon.js";
import EventsMixin from '../mixins/events-mixin.js';
import LocalizeMixin from '../mixins/localize-mixin.js';
import EventsMixin from "../mixins/events-mixin.js";
import LocalizeMixin from "../mixins/localize-mixin.js";
/*
* @appliesMixin LocalizeMixin
*/
class HaWeatherCard extends
LocalizeMixin(EventsMixin(PolymerElement)) {
class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
@@ -160,42 +159,57 @@ class HaWeatherCard extends
stateObj: Object,
forecast: {
type: Array,
computed: 'computeForecast(stateObj.attributes.forecast)'
}
computed: "computeForecast(stateObj.attributes.forecast)",
},
};
}
constructor() {
super();
this.cardinalDirections = [
'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'
"N",
"NNE",
"NE",
"ENE",
"E",
"ESE",
"SE",
"SSE",
"S",
"SSW",
"SW",
"WSW",
"W",
"WNW",
"NW",
"NNW",
"N",
];
this.weatherIcons = {
'clear-night': 'hass:weather-night',
cloudy: 'hass:weather-cloudy',
fog: 'hass:weather-fog',
hail: 'hass:weather-hail',
lightning: 'hass:weather-lightning',
'lightning-rainy': 'hass:weather-lightning-rainy',
partlycloudy: 'hass:weather-partlycloudy',
pouring: 'hass:weather-pouring',
rainy: 'hass:weather-rainy',
snowy: 'hass:weather-snowy',
'snowy-rainy': 'hass:weather-snowy-rainy',
sunny: 'hass:weather-sunny',
windy: 'hass:weather-windy',
'windy-variant': 'hass:weather-windy-variant'
"clear-night": "hass:weather-night",
cloudy: "hass:weather-cloudy",
fog: "hass:weather-fog",
hail: "hass:weather-hail",
lightning: "hass:weather-lightning",
"lightning-rainy": "hass:weather-lightning-rainy",
partlycloudy: "hass:weather-partlycloudy",
pouring: "hass:weather-pouring",
rainy: "hass:weather-rainy",
snowy: "hass:weather-snowy",
"snowy-rainy": "hass:weather-snowy-rainy",
sunny: "hass:weather-sunny",
windy: "hass:weather-windy",
"windy-variant": "hass:weather-windy-variant",
};
}
ready() {
this.addEventListener('click', this._onClick);
this.addEventListener("click", this._onClick);
super.ready();
}
_onClick() {
this.fire('hass-more-info', { entityId: this.stateObj.entity_id });
this.fire("hass-more-info", { entityId: this.stateObj.entity_id });
}
computeForecast(forecast) {
@@ -203,16 +217,16 @@ class HaWeatherCard extends
}
getUnit(measure) {
const lengthUnit = this.hass.config.unit_system.length || '';
const lengthUnit = this.hass.config.unit_system.length || "";
switch (measure) {
case 'air_pressure':
return lengthUnit === 'km' ? 'hPa' : 'inHg';
case 'length':
case "air_pressure":
return lengthUnit === "km" ? "hPa" : "inHg";
case "length":
return lengthUnit;
case 'precipitation':
return lengthUnit === 'km' ? 'mm' : 'in';
case "precipitation":
return lengthUnit === "km" ? "mm" : "in";
default:
return this.hass.config.unit_system[measure] || '';
return this.hass.config.unit_system[measure] || "";
}
}
@@ -239,20 +253,22 @@ class HaWeatherCard extends
getWind(speed, bearing, localize) {
if (bearing != null) {
const cardinalDirection = this.windBearingToText(bearing);
return `${speed} ${this.getUnit('length')}/h (${localize(`ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`) || cardinalDirection})`;
return `${speed} ${this.getUnit("length")}/h (${localize(
`ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
) || cardinalDirection})`;
}
return `${speed} ${this.getUnit('length')}/h`;
return `${speed} ${this.getUnit("length")}/h`;
}
_showValue(item) {
return typeof item !== 'undefined' && item !== null;
return typeof item !== "undefined" && item !== null;
}
computeDate(data) {
const date = new Date(data);
return date.toLocaleDateString(
this.hass.selectedLanguage || this.hass.language,
{ weekday: 'short' }
{ weekday: "short" }
);
}
@@ -260,8 +276,8 @@ class HaWeatherCard extends
const date = new Date(data);
return date.toLocaleTimeString(
this.hass.selectedLanguage || this.hass.language,
{ hour: 'numeric' }
{ hour: "numeric" }
);
}
}
customElements.define('ha-weather-card', HaWeatherCard);
customElements.define("ha-weather-card", HaWeatherCard);

View File

@@ -1,13 +1,15 @@
/**
* Auth class that connects to a native app for authentication.
*/
import { Auth } from 'home-assistant-js-websocket';
import { Auth } from "home-assistant-js-websocket";
const CALLBACK_SET_TOKEN = 'externalAuthSetToken';
const CALLBACK_REVOKE_TOKEN = 'externalAuthRevokeToken';
const CALLBACK_SET_TOKEN = "externalAuthSetToken";
const CALLBACK_REVOKE_TOKEN = "externalAuthRevokeToken";
if (!window.externalApp && !window.webkit) {
throw new Error('External auth requires either externalApp or webkit defined on Window object.');
throw new Error(
"External auth requires either externalApp or webkit defined on Window object."
);
}
export default class ExternalAuth extends Auth {
@@ -16,7 +18,7 @@ export default class ExternalAuth extends Auth {
this.data = {
hassUrl,
access_token: '',
access_token: "",
// This will trigger connection to do a refresh right away
expires: 0,
};
@@ -24,7 +26,8 @@ export default class ExternalAuth extends Auth {
async refreshAccessToken() {
const responseProm = new Promise((resolve, reject) => {
window[CALLBACK_SET_TOKEN] = (success, data) => (success ? resolve(data) : reject(data));
window[CALLBACK_SET_TOKEN] = (success, data) =>
success ? resolve(data) : reject(data);
});
// Allow promise to set resolve on window object.
@@ -35,7 +38,9 @@ export default class ExternalAuth extends Auth {
if (window.externalApp) {
window.externalApp.getExternalAuth(callbackPayload);
} else {
window.webkit.messageHandlers.getExternalAuth.postMessage(callbackPayload);
window.webkit.messageHandlers.getExternalAuth.postMessage(
callbackPayload
);
}
// Response we expect back:
@@ -46,12 +51,13 @@ export default class ExternalAuth extends Auth {
const tokens = await responseProm;
this.data.access_token = tokens.access_token;
this.data.expires = (tokens.expires_in * 1000) + Date.now();
this.data.expires = tokens.expires_in * 1000 + Date.now();
}
async revoke() {
const responseProm = new Promise((resolve, reject) => {
window[CALLBACK_REVOKE_TOKEN] = (success, data) => (success ? resolve(data) : reject(data));
window[CALLBACK_REVOKE_TOKEN] = (success, data) =>
success ? resolve(data) : reject(data);
});
// Allow promise to set resolve on window object.
@@ -62,7 +68,9 @@ export default class ExternalAuth extends Auth {
if (window.externalApp) {
window.externalApp.revokeExternalAuth(callbackPayload);
} else {
window.webkit.messageHandlers.revokeExternalAuth.postMessage(callbackPayload);
window.webkit.messageHandlers.revokeExternalAuth.postMessage(
callbackPayload
);
}
await responseProm;

View File

@@ -10,7 +10,9 @@ if (!tokenCache) {
}
export function askWrite() {
return tokenCache.tokens !== undefined && tokenCache.writeEnabled === undefined;
return (
tokenCache.tokens !== undefined && tokenCache.writeEnabled === undefined
);
}
export function saveTokens(tokens) {

View File

@@ -1,4 +1,4 @@
/** Return if the displaymode is in standalone mode (PWA). */
export default function isPwa() {
return (window.matchMedia('(display-mode: standalone)').matches);
return window.matchMedia("(display-mode: standalone)").matches;
}

View File

@@ -5,84 +5,80 @@
// Each constant should have a description what it is supposed to be used for.
/** Icon to use when no icon specified for domain. */
export const DEFAULT_DOMAIN_ICON = 'hass:bookmark';
export const DEFAULT_DOMAIN_ICON = "hass:bookmark";
/** Domains that have a state card. */
export const DOMAINS_WITH_CARD = [
'climate',
'cover',
'configurator',
'input_select',
'input_number',
'input_text',
'lock',
'media_player',
'scene',
'script',
'timer',
'vacuum',
'water_heater',
'weblink',
"climate",
"cover",
"configurator",
"input_select",
"input_number",
"input_text",
"lock",
"media_player",
"scene",
"script",
"timer",
"vacuum",
"water_heater",
"weblink",
];
/** Domains with separate more info dialog. */
export const DOMAINS_WITH_MORE_INFO = [
'alarm_control_panel',
'automation',
'camera',
'climate',
'configurator',
'cover',
'fan',
'group',
'history_graph',
'input_datetime',
'light',
'lock',
'media_player',
'script',
'sun',
'updater',
'vacuum',
'water_heater',
'weather'
"alarm_control_panel",
"automation",
"camera",
"climate",
"configurator",
"cover",
"fan",
"group",
"history_graph",
"input_datetime",
"light",
"lock",
"media_player",
"script",
"sun",
"updater",
"vacuum",
"water_heater",
"weather",
];
/** Domains that show no more info dialog. */
export const DOMAINS_HIDE_MORE_INFO = [
'input_number',
'input_select',
'input_text',
'scene',
'weblink'
"input_number",
"input_select",
"input_text",
"scene",
"weblink",
];
/** Domains that should have the history hidden in the more info dialog. */
export const DOMAINS_MORE_INFO_NO_HISTORY = [
'camera',
'configurator',
'history_graph',
'scene',
"camera",
"configurator",
"history_graph",
"scene",
];
/** States that we consider "off". */
export const STATES_OFF = [
'closed',
'locked',
'off'
];
export const STATES_OFF = ["closed", "locked", "off"];
/** Domains where we allow toggle in Lovelace. */
export const DOMAINS_TOGGLE = new Set([
'fan',
'input_boolean',
'light',
'switch'
"fan",
"input_boolean",
"light",
"switch",
]);
/** Temperature units. */
export const UNIT_C = '°C';
export const UNIT_F = '°F';
export const UNIT_C = "°C";
export const UNIT_F = "°F";
/** Entity ID of the default view. */
export const DEFAULT_VIEW_ENTITY_ID = 'group.default_view';
export const DEFAULT_VIEW_ENTITY_ID = "group.default_view";

View File

@@ -1,4 +1,4 @@
export default function durationToSeconds(duration) {
const parts = duration.split(':').map(Number);
return (parts[0] * 3600) + (parts[1] * 60) + parts[2];
const parts = duration.split(":").map(Number);
return parts[0] * 3600 + parts[1] * 60 + parts[2];
}

View File

@@ -1,21 +1,21 @@
import fecha from 'fecha';
import fecha from "fecha";
// Check for support of native locale string options
function toLocaleDateStringSupportsOptions() {
try {
new Date().toLocaleDateString('i');
new Date().toLocaleDateString("i");
} catch (e) {
return e.name === 'RangeError';
return e.name === "RangeError";
}
return false;
}
export default (toLocaleDateStringSupportsOptions()
? function (dateObj, locales) {
return dateObj.toLocaleDateString(
locales,
{ year: 'numeric', month: 'long', day: 'numeric' },
);
} : function (dateObj, locales) { // eslint-disable-line no-unused-vars
return fecha.format(dateObj, 'mediumDate');
});
? (dateObj, locales) =>
dateObj.toLocaleDateString(locales, {
year: "numeric",
month: "long",
day: "numeric",
})
: // eslint-disable-next-line no-unused-vars
(dateObj, locales) => fecha.format(dateObj, "mediumDate"));

View File

@@ -1,24 +1,23 @@
import fecha from 'fecha';
import fecha from "fecha";
// Check for support of native locale string options
function toLocaleStringSupportsOptions() {
try {
new Date().toLocaleString('i');
new Date().toLocaleString("i");
} catch (e) {
return e.name === 'RangeError';
return e.name === "RangeError";
}
return false;
}
export default (toLocaleStringSupportsOptions()
? function (dateObj, locales) {
return dateObj.toLocaleString(locales, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
});
} : function (dateObj, locales) { // eslint-disable-line no-unused-vars
return fecha.format(dateObj, 'haDateTime');
});
? (dateObj, locales) =>
dateObj.toLocaleString(locales, {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "2-digit",
})
: // eslint-disable-next-line no-unused-vars
(dateObj, locales) => fecha.format(dateObj, "haDateTime"));

View File

@@ -1,21 +1,20 @@
import fecha from 'fecha';
import fecha from "fecha";
// Check for support of native locale string options
function toLocaleTimeStringSupportsOptions() {
try {
new Date().toLocaleTimeString('i');
new Date().toLocaleTimeString("i");
} catch (e) {
return e.name === 'RangeError';
return e.name === "RangeError";
}
return false;
}
export default (toLocaleTimeStringSupportsOptions()
? function (dateObj, locales) {
return dateObj.toLocaleTimeString(
locales,
{ hour: 'numeric', minute: '2-digit' }
);
} : function (dateObj, locales) { // eslint-disable-line no-unused-vars
return fecha.format(dateObj, 'shortTime');
});
? (dateObj, locales) =>
dateObj.toLocaleTimeString(locales, {
hour: "numeric",
minute: "2-digit",
})
: // eslint-disable-next-line no-unused-vars
(dateObj, locales) => fecha.format(dateObj, "shortTime"));

View File

@@ -1,30 +1,33 @@
/** Calculate a string representing a date object as relative time from now.
*
* Example output: 5 minutes ago, in 3 days.
*/
const tests = [
60, 'second',
60, 'minute',
24, 'hour',
7, 'day',
];
*/
const tests = [60, "second", 60, "minute", 24, "hour", 7, "day"];
export default function relativeTime(dateObj, localize) {
let delta = (new Date() - dateObj) / 1000;
const tense = delta >= 0 ? 'past' : 'future';
const tense = delta >= 0 ? "past" : "future";
delta = Math.abs(delta);
for (let i = 0; i < tests.length; i += 2) {
if (delta < tests[i]) {
delta = Math.floor(delta);
const time = localize(`ui.components.relative_time.duration.${tests[i + 1]}`, 'count', delta);
return localize(`ui.components.relative_time.${tense}`, 'time', time);
const time = localize(
`ui.components.relative_time.duration.${tests[i + 1]}`,
"count",
delta
);
return localize(`ui.components.relative_time.${tense}`, "time", time);
}
delta /= tests[i];
}
delta = Math.floor(delta);
const time = localize('ui.components.relative_time.duration.week', 'count', delta);
return localize(`ui.components.relative_time.${tense}`, 'time', time);
const time = localize(
"ui.components.relative_time.duration.week",
"count",
delta
);
return localize(`ui.components.relative_time.${tense}`, "time", time);
}

View File

@@ -1,16 +1,18 @@
const leftPad = number => (number < 10 ? `0${number}` : number);
const leftPad = (number) => (number < 10 ? `0${number}` : number);
export default function secondsToDuration(d) {
const h = Math.floor(d / 3600);
const m = Math.floor((d % 3600) / 60);
const s = Math.floor(d % 3600 % 60);
const s = Math.floor((d % 3600) % 60);
if (h > 0) {
return `${h}:${leftPad(m)}:${leftPad(s)}`;
} if (m > 0) {
}
if (m > 0) {
return `${m}:${leftPad(s)}`;
} if (s > 0) {
return '' + s;
}
if (s > 0) {
return "" + s;
}
return null;
}

View File

@@ -5,21 +5,26 @@
* themes: HASS Theme information
* localTheme: selected theme.
* updateMeta: boolean if we should update the theme-color meta element.
*/
export default function applyThemesOnElement(element, themes, localTheme, updateMeta = false) {
*/
export default function applyThemesOnElement(
element,
themes,
localTheme,
updateMeta = false
) {
if (!element._themes) {
element._themes = {};
}
let themeName = themes.default_theme;
if (localTheme === 'default' || (localTheme && themes.themes[localTheme])) {
if (localTheme === "default" || (localTheme && themes.themes[localTheme])) {
themeName = localTheme;
}
const styles = Object.assign({}, element._themes);
if (themeName !== 'default') {
if (themeName !== "default") {
var theme = themes.themes[themeName];
Object.keys(theme).forEach((key) => {
var prefixedKey = '--' + key;
element._themes[prefixedKey] = '';
var prefixedKey = "--" + key;
element._themes[prefixedKey] = "";
styles[prefixedKey] = theme[key];
});
}
@@ -27,17 +32,18 @@ export default function applyThemesOnElement(element, themes, localTheme, update
element.updateStyles(styles);
} else if (window.ShadyCSS) {
// implement updateStyles() method of Polemer elements
window.ShadyCSS.styleSubtree(/** @type {!HTMLElement} */(element), styles);
window.ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);
}
if (!updateMeta) return;
const meta = document.querySelector('meta[name=theme-color]');
const meta = document.querySelector("meta[name=theme-color]");
if (meta) {
if (!meta.hasAttribute('default-content')) {
meta.setAttribute('default-content', meta.getAttribute('content'));
if (!meta.hasAttribute("default-content")) {
meta.setAttribute("default-content", meta.getAttribute("content"));
}
const themeColor = styles['--primary-color'] || meta.getAttribute('default-content');
meta.setAttribute('content', themeColor);
const themeColor =
styles["--primary-color"] || meta.getAttribute("default-content");
meta.setAttribute("content", themeColor);
}
}

View File

@@ -45,11 +45,11 @@
*/
export default function fire(node, type, detail, options) {
options = options || {};
detail = (detail === null || detail === undefined) ? {} : detail;
detail = detail === null || detail === undefined ? {} : detail;
const event = new Event(type, {
bubbles: options.bubbles === undefined ? true : options.bubbles,
cancelable: Boolean(options.cancelable),
composed: options.composed === undefined ? true : options.composed
composed: options.composed === undefined ? true : options.composed,
});
event.detail = detail;
node.dispatchEvent(event);

View File

@@ -3,10 +3,10 @@
function _load(tag, url, type) {
// This promise will be used by Promise.all to determine success or failure
return new Promise(function (resolve, reject) {
return new Promise(function(resolve, reject) {
const element = document.createElement(tag);
let attr = 'src';
let parent = 'body';
let attr = "src";
let parent = "body";
// Important success and error for the promise
element.onload = () => resolve(url);
@@ -14,17 +14,17 @@ function _load(tag, url, type) {
// Need to set different attributes depending on tag type
switch (tag) {
case 'script':
case "script":
element.async = true;
if (type) {
element.type = type;
}
break;
case 'link':
element.type = 'text/css';
element.rel = 'stylesheet';
attr = 'href';
parent = 'head';
case "link":
element.type = "text/css";
element.rel = "stylesheet";
attr = "href";
parent = "head";
}
// Inject into document to kick off loading
@@ -33,7 +33,7 @@ function _load(tag, url, type) {
});
}
export const loadCSS = url => _load('link', url);
export const loadJS = url => _load('script', url);
export const loadImg = url => _load('img', url);
export const loadModule = url => _load('script', url, 'module');
export const loadCSS = (url) => _load("link", url);
export const loadJS = (url) => _load("script", url);
export const loadImg = (url) => _load("img", url);
export const loadModule = (url) => _load("script", url, "module");

View File

@@ -16,7 +16,7 @@ export default function scrollToTarget(element, target) {
var easingFn = function easeOutQuad(t, b, c, d) {
/* eslint-disable no-param-reassign, space-infix-ops, no-mixed-operators */
t /= d;
return -c * t*(t-2) + b;
return -c * t * (t - 2) + b;
/* eslint-enable no-param-reassign, space-infix-ops, no-mixed-operators */
};
var animationId = Math.random();
@@ -31,8 +31,13 @@ export default function scrollToTarget(element, target) {
if (elapsedTime > duration) {
scroller.scrollTop = top;
} else if (element._currentAnimationId === animationId) {
scroller.scrollTop = easingFn(elapsedTime, currentScrollTop, deltaScrollTop, duration);
scroller.scrollTop = easingFn(
elapsedTime,
currentScrollTop,
deltaScrollTop,
duration
);
requestAnimationFrame(updateFrame.bind(element));
}
}).call(element);
}.call(element));
}

View File

@@ -1,18 +1,21 @@
import Leaflet from 'leaflet';
import Leaflet from "leaflet";
// Sets up a Leaflet map on the provided DOM element
export default function setupLeafletMap(mapElement) {
const map = Leaflet.map(mapElement);
const style = document.createElement('link');
style.setAttribute('href', '/static/images/leaflet/leaflet.css');
style.setAttribute('rel', 'stylesheet');
const style = document.createElement("link");
style.setAttribute("href", "/static/images/leaflet/leaflet.css");
style.setAttribute("rel", "stylesheet");
mapElement.parentNode.appendChild(style);
map.setView([51.505, -0.09], 13);
Leaflet.tileLayer(
`https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}${Leaflet.Browser.retina ? '@2x.png' : '.png'}`,
`https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}${
Leaflet.Browser.retina ? "@2x.png" : ".png"
}`,
{
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: 'abcd',
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: "abcd",
minZoom: 0,
maxZoom: 20,
}

View File

@@ -1,2 +1,2 @@
/** An empty image which can be set as src of an img element. */
export default 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
export default "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";

View File

@@ -1,6 +1,9 @@
export default function attributeClassNames(stateObj, attributes) {
if (!stateObj) return '';
return attributes.map(function (attribute) {
return attribute in stateObj.attributes ? 'has-' + attribute : '';
}).filter(attr => attr !== '').join(' ');
if (!stateObj) return "";
return attributes
.map(function(attribute) {
return attribute in stateObj.attributes ? "has-" + attribute : "";
})
.filter((attr) => attr !== "")
.join(" ");
}

View File

@@ -1,49 +1,49 @@
/** Return an icon representing a binary sensor state. */
export default function binarySensorIcon(state) {
var activated = state.state && state.state === 'off';
var activated = state.state && state.state === "off";
switch (state.attributes.device_class) {
case 'battery':
return activated ? 'hass:battery' : 'hass:battery-outline';
case 'cold':
return activated ? 'hass:thermometer' : 'hass:snowflake';
case 'connectivity':
return activated ? 'hass:server-network-off' : 'hass:server-network';
case 'door':
return activated ? 'hass:door-closed' : 'hass:door-open';
case 'garage_door':
return activated ? 'hass:garage' : 'hass:garage-open';
case 'gas':
case 'power':
case 'problem':
case 'safety':
case 'smoke':
return activated ? 'hass:verified' : 'hass:alert';
case 'heat':
return activated ? 'hass:thermometer' : 'hass:fire';
case 'light':
return activated ? 'hass:brightness-5' : 'hass:brightness-7';
case 'lock':
return activated ? 'hass:lock' : 'hass:lock-open';
case 'moisture':
return activated ? 'hass:water-off' : 'hass:water';
case 'motion':
return activated ? 'hass:walk' : 'hass:run';
case 'occupancy':
return activated ? 'hass:home-outline' : 'hass:home';
case 'opening':
return activated ? 'hass:square' : 'hass:square-outline';
case 'plug':
return activated ? 'hass:power-plug-off' : 'hass:power-plug';
case 'presence':
return activated ? 'hass:home-outline' : 'hass:home';
case 'sound':
return activated ? 'hass:music-note-off' : 'hass:music-note';
case 'vibration':
return activated ? 'hass:crop-portrait' : 'hass:vibrate';
case 'window':
return activated ? 'hass:window-closed' : 'hass:window-open';
case "battery":
return activated ? "hass:battery" : "hass:battery-outline";
case "cold":
return activated ? "hass:thermometer" : "hass:snowflake";
case "connectivity":
return activated ? "hass:server-network-off" : "hass:server-network";
case "door":
return activated ? "hass:door-closed" : "hass:door-open";
case "garage_door":
return activated ? "hass:garage" : "hass:garage-open";
case "gas":
case "power":
case "problem":
case "safety":
case "smoke":
return activated ? "hass:verified" : "hass:alert";
case "heat":
return activated ? "hass:thermometer" : "hass:fire";
case "light":
return activated ? "hass:brightness-5" : "hass:brightness-7";
case "lock":
return activated ? "hass:lock" : "hass:lock-open";
case "moisture":
return activated ? "hass:water-off" : "hass:water";
case "motion":
return activated ? "hass:walk" : "hass:run";
case "occupancy":
return activated ? "hass:home-outline" : "hass:home";
case "opening":
return activated ? "hass:square" : "hass:square-outline";
case "plug":
return activated ? "hass:power-plug-off" : "hass:power-plug";
case "presence":
return activated ? "hass:home-outline" : "hass:home";
case "sound":
return activated ? "hass:music-note-off" : "hass:music-note";
case "vibration":
return activated ? "hass:crop-portrait" : "hass:vibrate";
case "window":
return activated ? "hass:window-closed" : "hass:window-open";
default:
return activated ? 'hass:radiobox-blank' : 'hass:checkbox-marked-circle';
return activated ? "hass:radiobox-blank" : "hass:checkbox-marked-circle";
}
}

View File

@@ -1,11 +1,14 @@
export default function canToggleDomain(hass, domain) {
const services = hass.services[domain];
if (!services) { return false; }
if (domain === 'lock') {
return 'lock' in services;
} if (domain === 'cover') {
return 'open_cover' in services;
if (!services) {
return false;
}
return 'turn_on' in services;
if (domain === "lock") {
return "lock" in services;
}
if (domain === "cover") {
return "open_cover" in services;
}
return "turn_on" in services;
}

View File

@@ -1,12 +1,12 @@
import canToggleDomain from './can_toggle_domain.js';
import computeStateDomain from './compute_state_domain.js';
import canToggleDomain from "./can_toggle_domain.js";
import computeStateDomain from "./compute_state_domain.js";
export default function canToggleState(hass, stateObj) {
const domain = computeStateDomain(stateObj);
if (domain === 'group') {
return stateObj.state === 'on' || stateObj.state === 'off';
if (domain === "group") {
return stateObj.state === "on" || stateObj.state === "off";
}
if (domain === 'climate') {
if (domain === "climate") {
return !!((stateObj.attributes || {}).supported_features & 4096);
}

View File

@@ -1,3 +1,3 @@
export default function computeDomain(entityId) {
return entityId.substr(0, entityId.indexOf('.'));
return entityId.substr(0, entityId.indexOf("."));
}

View File

@@ -1,4 +1,4 @@
/** Compute the object ID of a state. */
export default function computeObjectId(entityId) {
return entityId.substr(entityId.indexOf('.') + 1);
return entityId.substr(entityId.indexOf(".") + 1);
}

View File

@@ -1,22 +1,32 @@
import computeStateDomain from './compute_state_domain.js';
import formatDateTime from '../datetime/format_date_time.js';
import formatDate from '../datetime/format_date.js';
import formatTime from '../datetime/format_time.js';
import computeStateDomain from "./compute_state_domain.js";
import formatDateTime from "../datetime/format_date_time.js";
import formatDate from "../datetime/format_date.js";
import formatTime from "../datetime/format_time.js";
export default function computeStateDisplay(localize, stateObj, language) {
if (!stateObj._stateDisplay) {
const domain = computeStateDomain(stateObj);
if (domain === 'binary_sensor') {
if (domain === "binary_sensor") {
// Try device class translation, then default binary sensor translation
if (stateObj.attributes.device_class) {
stateObj._stateDisplay = localize(`state.${domain}.${stateObj.attributes.device_class}.${stateObj.state}`);
stateObj._stateDisplay = localize(
`state.${domain}.${stateObj.attributes.device_class}.${
stateObj.state
}`
);
}
if (!stateObj._stateDisplay) {
stateObj._stateDisplay = localize(`state.${domain}.default.${stateObj.state}`);
stateObj._stateDisplay = localize(
`state.${domain}.default.${stateObj.state}`
);
}
} else if (stateObj.attributes.unit_of_measurement && !['unknown', 'unavailable'].includes(stateObj.state)) {
stateObj._stateDisplay = stateObj.state + ' ' + stateObj.attributes.unit_of_measurement;
} else if (domain === 'input_datetime') {
} else if (
stateObj.attributes.unit_of_measurement &&
!["unknown", "unavailable"].includes(stateObj.state)
) {
stateObj._stateDisplay =
stateObj.state + " " + stateObj.attributes.unit_of_measurement;
} else if (domain === "input_datetime") {
let date;
if (!stateObj.attributes.has_time) {
date = new Date(
@@ -30,33 +40,44 @@ export default function computeStateDisplay(localize, stateObj, language) {
date = new Date(
// Due to bugs.chromium.org/p/chromium/issues/detail?id=797548
// don't use artificial 1970 year.
now.getFullYear(), now.getMonth(), now.getDay(),
now.getFullYear(),
now.getMonth(),
now.getDay(),
stateObj.attributes.hour,
stateObj.attributes.minute
);
stateObj._stateDisplay = formatTime(date, language);
} else {
date = new Date(
stateObj.attributes.year, stateObj.attributes.month - 1,
stateObj.attributes.day, stateObj.attributes.hour,
stateObj.attributes.year,
stateObj.attributes.month - 1,
stateObj.attributes.day,
stateObj.attributes.hour,
stateObj.attributes.minute
);
stateObj._stateDisplay = formatDateTime(date, language);
}
} else if (domain === 'zwave') {
if (['initializing', 'dead'].includes(stateObj.state)) {
stateObj._stateDisplay = localize(`state.zwave.query_stage.${stateObj.state}`, 'query_stage', stateObj.attributes.query_stage);
} else if (domain === "zwave") {
if (["initializing", "dead"].includes(stateObj.state)) {
stateObj._stateDisplay = localize(
`state.zwave.query_stage.${stateObj.state}`,
"query_stage",
stateObj.attributes.query_stage
);
} else {
stateObj._stateDisplay = localize(`state.zwave.default.${stateObj.state}`);
stateObj._stateDisplay = localize(
`state.zwave.default.${stateObj.state}`
);
}
} else {
stateObj._stateDisplay = localize(`state.${domain}.${stateObj.state}`);
}
// Fall back to default, component backend translation, or raw state if nothing else matches.
stateObj._stateDisplay = stateObj._stateDisplay
|| localize(`state.default.${stateObj.state}`)
|| localize(`component.${domain}.state.${stateObj.state}`)
|| stateObj.state;
stateObj._stateDisplay =
stateObj._stateDisplay ||
localize(`state.default.${stateObj.state}`) ||
localize(`component.${domain}.state.${stateObj.state}`) ||
stateObj.state;
}
return stateObj._stateDisplay;

View File

@@ -1,4 +1,4 @@
import computeDomain from './compute_domain.js';
import computeDomain from "./compute_domain.js";
export default function computeStateDomain(stateObj) {
return computeDomain(stateObj.entity_id);

View File

@@ -1,10 +1,10 @@
import computeObjectId from './compute_object_id';
import computeObjectId from "./compute_object_id";
export default function computeStateName(stateObj) {
if (stateObj._entityDisplay === undefined) {
stateObj._entityDisplay = (
stateObj.attributes.friendly_name
|| computeObjectId(stateObj.entity_id).replace(/_/g, ' '));
stateObj._entityDisplay =
stateObj.attributes.friendly_name ||
computeObjectId(stateObj.entity_id).replace(/_/g, " ");
}
return stateObj._entityDisplay;

View File

@@ -1,12 +1,12 @@
/** Return an icon representing a cover state. */
import domainIcon from './domain_icon.js';
import domainIcon from "./domain_icon.js";
export default function coverIcon(state) {
var open = state.state && state.state !== 'closed';
var open = state.state && state.state !== "closed";
switch (state.attributes.device_class) {
case 'garage':
return open ? 'hass:garage-open' : 'hass:garage';
case "garage":
return open ? "hass:garage-open" : "hass:garage";
default:
return domainIcon('cover', state.state);
return domainIcon("cover", state.state);
}
}

Some files were not shown because too many files have changed in this diff Show More