Compare commits

...

91 Commits

Author SHA1 Message Date
Bram Kragten
178605664e Bumped version to 20210127.1 2021-01-27 17:17:48 +01:00
Joakim Sørensen
0cf8004b8d Add twine to release flow (#8254) 2021-01-27 17:14:00 +01:00
Bram Kragten
00412c7216 Merge pull request #8252 from home-assistant/dev 2021-01-27 16:24:07 +01:00
Bram Kragten
6483f23558 Merge branch 'master' into dev 2021-01-27 16:10:48 +01:00
Bram Kragten
4234d51a29 Bumped version to 20210127.0 2021-01-27 16:09:35 +01:00
Bram Kragten
9243d300cc Zwave -> OZW migration (#7765)
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-01-27 16:01:18 +01:00
Thomas Lovén
2ce70206c6 Markdown format blueprint descriptions in import dialog (#8251) 2021-01-27 16:00:15 +01:00
Bram Kragten
b22455d2a5 Add simple try tts dialog (#8245) 2021-01-27 15:58:58 +01:00
Philip Allgaier
4f0bb9f6c3 Add icon support to gauge (#8081) 2021-01-27 13:36:03 +01:00
Philip Allgaier
7dfa1b0942 Convert state history chart to LitElement + add warning if history is disabled (#7994)
Co-authored-by: Ian Richardson <iantrich@gmail.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-27 13:13:40 +01:00
Philip Allgaier
093e23c006 Auto capitalize first letter of entity row name (#7962) 2021-01-27 12:38:39 +01:00
Philip Allgaier
5f003ccbe2 Add navigation to dashboard & resources to lovelace editor + icons (#8156) 2021-01-27 12:37:28 +01:00
Philip Allgaier
8d0608610f Entity registry: Translate advanced section + direct link to entity customization (#8181) 2021-01-27 12:35:25 +01:00
Philip Allgaier
8bfe583a20 Convert customize to LitElement + "real" entity picker + option to directly jump to entity (#8180)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-27 12:34:31 +01:00
Philip Allgaier
0a3172dfdb More comprehensive YAML config errors + dynamic checks for action configs (#8217) 2021-01-27 12:33:57 +01:00
Thomas Lovén
5c0e151bc2 Add selectors for text and arbitrary objects (#8152) 2021-01-27 11:45:51 +01:00
Ian Richardson
e69f36047d add actions to weather-forecast-card (#7659) 2021-01-27 10:59:09 +01:00
Philip Allgaier
ed368ddd9d Add support for delay values split into parts + millisecond time input (#7886)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-27 10:46:15 +01:00
GitHub Action
8400e90e34 Translation update 2021-01-27 01:32:26 +00:00
Paulus Schoutsen
4cd95b724b Use minified bundle of node vibrant (#7784)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-26 23:24:23 +01:00
Shulyaka
46b3836fbd Add number entity support (#7876) 2021-01-26 23:14:23 +01:00
Tim McCormick
9988227d93 Don't assume position of items in array (#7927) 2021-01-26 22:59:58 +01:00
Bram Kragten
9d289bfa34 Add download dump button to zwave_js panel (#8232)
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
2021-01-26 22:20:16 +01:00
Bram Kragten
048de6b388 Fix translation action (#8244) 2021-01-26 17:21:38 +01:00
Philip Allgaier
9b7d8934da Correctly handle "hours to show" for footer graph (#8071)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-26 16:15:32 +01:00
Philip Allgaier
0dd9b21c2d Add minutes to hourly weather forecast time display (#8182)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-26 16:14:34 +01:00
Philip Allgaier
417184525f Adjust calendar translations to fix loading issue in calendar card (#8235) 2021-01-26 10:42:13 +01:00
Philip Allgaier
0a09ec706f Visual alignment of automation and script more info dialogs (#8234) 2021-01-26 10:25:34 +01:00
Philip Allgaier
cf43b26e14 Prevent automation action row issue if event name gets cleared (#8213)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-25 20:01:30 +01:00
Philip Allgaier
a8b27e224f Allow themeing of media control card (#8209)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-25 20:00:50 +01:00
Philip Allgaier
dc5d14834d Added missing translations for some automation extra-fields (#8210) 2021-01-25 11:59:44 +01:00
Philip Allgaier
12c935f647 Show entity_picture in logbook (#8118) 2021-01-25 11:48:16 +01:00
Philip Allgaier
7710cb245c Use correct color for shopping list card section header (#8223) 2021-01-25 11:35:04 +01:00
b3nj1
a6b77c0457 entity-filter card allow state_filter.value == 0 (number 0) (#8225) 2021-01-25 10:54:22 +01:00
Philip Allgaier
748a05f355 Use app header color as default selected tab color + allow styling (#8227) 2021-01-25 10:53:53 +01:00
Philip Allgaier
831b9da0cf Various demo tweaks + cleanups (#8229) 2021-01-25 10:52:59 +01:00
Charles Garwood
a3339c9d5f Add wizards for adding and removing Z-Wave JS nodes (#8174) 2021-01-25 10:46:50 +01:00
Philip Allgaier
d228f38471 Correct URL to automation run modes documentation (#8230) 2021-01-25 01:51:00 +01:00
Philip Allgaier
fe13853b8b Allow timestamp attribute formatting + central timestamp formats (#8162) 2021-01-22 20:24:31 +01:00
Philip Allgaier
6f4dbdc959 Improve entity registry errors display (#8208) 2021-01-22 15:50:11 +01:00
Bram Kragten
870f0bcbb1 Fix some dialog close history issues (#8102)
Co-authored-by: Zack Barett <arnett.zackary@gmail.com>
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
2021-01-22 13:33:10 +01:00
Philip Allgaier
599dd81e3c Make "button row" name optional to be consistent with "button card" and "buttons row" (#8189) 2021-01-21 20:03:53 +01:00
Philip Allgaier
9e99d158fd Add error handling to action handling (#8187) 2021-01-21 19:38:19 +01:00
Philip Allgaier
136ebb5a07 Set sensible default tap_action (same logic as button row) (#8186) 2021-01-21 16:44:17 +01:00
Charles Garwood
707338b1aa Add Z-Wave info to device page for zwave_js devices (#8195) 2021-01-21 16:16:24 +01:00
Bram Kragten
7e06bd53b6 Change remote ui portal to account page (#8193) 2021-01-18 16:47:14 +01:00
Joakim Sørensen
08c1b864fc Fix missing addon list when creating partial snapshot (#8176) 2021-01-17 17:34:14 +01:00
Thomas Lovén
16e7a16d12 Fix date picker text color (#7776) 2021-01-16 20:48:18 +01:00
Thomas Lovén
45200da32f Helpful comment. See #8152 (#8160) 2021-01-16 16:40:59 +01:00
Philip Allgaier
84a9ca59ef Add "columns" and "square" to grid card editor (#7888) 2021-01-16 16:25:13 +01:00
Charles Garwood
40f4c35b42 Initial Z-Wave JS Config Panel (#8166) 2021-01-16 16:22:27 +01:00
Philip Allgaier
bb77d34017 Tweaks to cloud integration page (#7878) 2021-01-16 16:19:57 +01:00
Philip Allgaier
9659ebe59b Increase font size for alarm keypad number buttons (#8120) 2021-01-16 16:09:52 +01:00
Thomas Lovén
16c914b139 Show default value for selector-less blueprint inputs. (#8163) 2021-01-15 14:30:27 +01:00
Philip Allgaier
142f26add1 Align entities card section header styling (#8113) 2021-01-14 13:05:37 +01:00
Philip Allgaier
ef7d2aea8d Fix config update handling for map card editor (#8115) 2021-01-14 12:52:58 +01:00
Philip Allgaier
1aa40cb6df Convert state-card-display to LitElement and use timestamp display (#8150)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-14 12:49:29 +01:00
Philip Allgaier
cd06b931a9 Allow empty/undefined for counter min & max (#8154) 2021-01-14 12:25:06 +01:00
Mick Vleeshouwer
fd2df92000 Change supportsStop to supportsStopTilt (#8153) 2021-01-14 12:24:26 +01:00
Philip Allgaier
b565a8b8f7 Allow "idle" media players to be switched of in entity row (#8155) 2021-01-14 11:35:31 +01:00
Philip Allgaier
1aab656705 Make entity-filter and glances demo a bit clearer & cleaner (#8157) 2021-01-14 11:20:18 +01:00
Philip Allgaier
6919d0cde6 Ensure we always show backend error in automation and script editor (#8139)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-13 20:45:40 +01:00
Philip Allgaier
95fd8de1bc Adjust person / presence detection texts (#8117) 2021-01-13 20:13:37 +01:00
Philip Allgaier
28ca1a5193 Adjust / theme entity marker background color (#8116) 2021-01-13 17:40:15 +01:00
Joakim Sørensen
a1d07e5a00 Sort imports (#8104) 2021-01-13 17:17:12 +01:00
Philip Allgaier
131a7f3782 Clear entity ID during automation duplication (#8140) 2021-01-13 17:12:51 +01:00
Philip Allgaier
c28a7d6c10 Center align content of date input (#8134) 2021-01-13 17:10:08 +01:00
J. Nick Koston
6b20bb967b Add support for dhcp discovery (#8149) 2021-01-13 11:07:32 +01:00
Paulus Schoutsen
75f228418d Allow configuring default TTS voice for cloud (#8148) 2021-01-13 11:07:03 +01:00
Joakim Sørensen
41f8b0d19b Add verify-version step to release (#8138) 2021-01-12 10:32:38 +01:00
Paulus Schoutsen
cea3b8b010 Show name on ignored entries (#8135) 2021-01-12 09:26:31 +01:00
Nikfinn99
aba0e1f026 Automation - State Condition display 'for:' in frontend (#8124)
* Automation - State Condition display 'for:' in frontend

* rename variable to better name
2021-01-11 17:24:39 +01:00
Philip Allgaier
f42587af22 Format URL attribute as link (#8126)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2021-01-11 15:59:26 +01:00
Joakim Sørensen
edcb7e87bb Hide configuration card if the add-on does not expose options or schema (#8131) 2021-01-11 14:43:24 +01:00
Joakim Sørensen
96f0ceeb8c Update supervisor on add-on store refresh (#8132) 2021-01-11 14:42:58 +01:00
Joakim Sørensen
a9baa7f1c1 Move netlify preview builds from Azure to Github (#8105)
* Move netlify preview builds from Azure  to Github

* Remove checkout

* Update secret names
2021-01-11 14:03:21 +01:00
Joakim Sørensen
b1483287dc Add Core to supervisor/system (#8123) 2021-01-11 13:51:52 +01:00
Thomas Lovén
a4657541fc Show location name in auth page, if available. (#8119) 2021-01-11 13:11:30 +01:00
Pikles
56d88b4c56 Add CSS Variables for Menu (#7917) 2021-01-11 12:50:33 +01:00
Joakim Sørensen
02313e4be8 Move translations from Azure to Github (#8129)
* Move translations from Azure to Github

* remove [ci skip]
2021-01-11 12:27:10 +01:00
Joakim Sørensen
2a14a3a4dc Move release builds from Azure to Github (#8128)
* Move release builds from Azure to Github

* Fix syntax issue (YAML is hard)
2021-01-11 12:14:53 +01:00
Philip Allgaier
d02a2e8c2e Consistently use isComponentLoaded() helper (#7995) 2021-01-10 19:52:22 +01:00
Bram Kragten
0d281f8437 Fix for undefined stateObj in media player row (#8114) 2021-01-08 09:39:55 -06:00
Thomas Lovén
2b0f43f334 Format blueprint descriptions with markdown (#8109) 2021-01-08 12:22:12 +01:00
Philip Allgaier
f9d28fc124 Add blank between temperature and unit in weather card (#8111) 2021-01-08 11:10:39 +01:00
Philip Allgaier
da07173471 Prevent YAML mode if no entity is set in card editor (#8110) 2021-01-08 11:07:04 +01:00
Joakim Sørensen
4deeff7029 Prefix supervisor version with supervisor- (#8107) 2021-01-08 10:54:12 +01:00
Bram Kragten
a9d926e80a Bumped version to 20201229.1 2021-01-05 20:38:52 +01:00
Philip Allgaier
c41369c89c Add EN fallback text for dismiss button (#8068) 2021-01-05 20:38:36 +01:00
Philip Allgaier
656bef3da9 Prevent relative time text wrapping in more-info-sun (#8051) 2021-01-05 20:38:18 +01:00
Bram Kragten
3d7ee6a4df Merge pull request #8048 from home-assistant/dev 2020-12-29 23:23:58 +01:00
517 changed files with 11842 additions and 4394 deletions

View File

@@ -26,6 +26,9 @@
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"files.trimTrailingWhitespace": true
}
}

View File

@@ -77,8 +77,8 @@ DO NOT DELETE ANY TEXT from this template! Otherwise, your issue may be closed w
## Problem-relevant frontend configuration
<!--
An example configuration that caused the problem for you, e.g. the YAML configuration
of the used cards. Fill this out even if it seems unimportant to you. Please be sure
An example configuration that caused the problem for you, e.g. the YAML configuration
of the used cards. Fill this out even if it seems unimportant to you. Please be sure
to remove personal information like passwords, private URLs and other credentials.
-->

19
.github/workflows/netflify.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Netlify
on:
schedule:
- cron: "0 0 * * *"
jobs:
trigger_builds:
name: Trigger netlify build preview
runs-on: "ubuntu-latest"
steps:
- name: Trigger Cast build
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_CAST_DEV_BUILD_HOOK }}
- name: Trigger Demo build
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }}
- name: Trigger Gallery build
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }}

81
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,81 @@
name: Release
on:
release:
types:
- published
env:
WHEELS_TAG: 3.7-alpine3.11
PYTHON_VERSION: 3.7
NODE_VERSION: 12.1
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Verify version
uses: home-assistant/actions/helpers/verify-version@master
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Build and release package
run: |
python3 -m pip install twine
export TWINE_USERNAME="__token__"
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
script/release
wheels-init:
name: Init wheels build
needs: release
runs-on: ubuntu-latest
steps:
- name: Generate requirements.txt
run: |
# Sleep to give pypi time to populate the new version across mirrors
sleep 240
version=$(echo "${{ github.ref }}" | awk -F"/" '{print $NF}' )
echo "home-assistant-frontend==$version" > ./requirements.txt
- name: Upload requirements.txt
uses: actions/upload-artifact@v2
with:
name: requirements
path: ./requirements.txt
build-wheels:
name: Build wheels for ${{ matrix.arch }}
needs: wheels-init
runs-on: ubuntu-latest
strategy:
matrix:
arch: ["aarch64", "armhf", "armv7", "amd64", "i386"]
steps:
- name: Download requirements.txt
uses: actions/download-artifact@v2
with:
name: requirements
- name: Build wheels
uses: home-assistant/wheels@master
with:
tag: ${{ env.WHEELS_TAG }}
arch: ${{ matrix.arch }}
wheels-host: ${{ secrets.WHEELS_HOST }}
wheels-key: ${{ secrets.WHEELS_KEY }}
wheels-user: wheels
requirements: "requirements.txt"

65
.github/workflows/translations.yaml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Translations
on:
schedule:
- cron: "30 0 * * *"
push:
branches:
- dev
paths:
- translations/en.json
env:
NODE_VERSION: 12
jobs:
upload:
name: Upload
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Upload Translations
run: |
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
./script/translations_upload_base
download:
name: Download
needs: upload
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Download Translations
run: |
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
npm install
./script/translations_download
- name: Initialize git
uses: home-assistant/actions/helpers/git-init@master
with:
name: GitHub Action
email: github-action@users.noreply.github.com
- name: Update translation
run: |
git add translations
git commit -am "Translation update"
git push

View File

@@ -1,30 +0,0 @@
# https://dev.azure.com/home-assistant
trigger: none
pr: none
schedules:
- cron: "0 0 * * *"
displayName: "build preview"
branches:
include:
- dev
always: true
variables:
- group: netlify
jobs:
- job: 'Netlify_preview'
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
# Cast
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_CAST}
# Demo
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_DEMO}
# Gallery
curl -X POST -d {} https://api.netlify.com/build_hooks/${NETLIFY_GALLERY}
displayName: 'Trigger netlify build preview'

View File

@@ -1,59 +0,0 @@
# https://dev.azure.com/home-assistant
trigger:
batch: true
tags:
include:
- "*"
pr: none
variables:
- name: versionWheels
value: '1.10.1-3.7-alpine3.11'
- name: versionNode
value: '12.1'
- group: twine
resources:
repositories:
- repository: azure
type: github
name: 'home-assistant/ci-azure'
endpoint: 'home-assistant'
stages:
- stage: "Validate"
jobs:
- template: templates/azp-job-version.yaml@azure
- stage: "Build"
jobs:
- job: "ReleasePython"
pool:
vmImage: "ubuntu-latest"
steps:
- task: UsePythonVersion@0
displayName: "Use Python 3.7"
inputs:
versionSpec: "3.7"
- task: NodeTool@0
displayName: "Use Node $(versionNode)"
inputs:
versionSpec: "$(versionNode)"
- script: pip install twine wheel
displayName: "Install tools"
- script: |
export TWINE_USERNAME="$(twineUser)"
export TWINE_PASSWORD="$(twinePassword)"
script/release
displayName: "Build and release package"
- stage: "Wheels"
jobs:
- template: templates/azp-job-wheels.yaml@azure
parameters:
builderVersion: '$(versionWheels)'
wheelsRequirement: 'requirement.txt'
preBuild:
- script: |
sleep 240
echo "home-assistant-frontend==$(Build.SourceBranchName)" > requirement.txt

View File

@@ -1,70 +0,0 @@
# https://dev.azure.com/home-assistant
trigger:
batch: true
branches:
include:
- dev
paths:
include:
- translations/en.json
pr: none
schedules:
- cron: "30 0 * * *"
displayName: "frontend translation update"
branches:
include:
- dev
always: true
variables:
- group: translation
resources:
repositories:
- repository: azure
type: github
name: 'home-assistant/ci-azure'
endpoint: 'home-assistant'
jobs:
- job: 'Upload'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Use Node 12.x'
inputs:
versionSpec: '12.x'
- script: |
export LOKALISE_TOKEN="$(lokaliseToken)"
export AZURE_BRANCH="$(Build.SourceBranchName)"
./script/translations_upload_base
displayName: 'Upload Translation'
- job: 'Download'
dependsOn:
- 'Upload'
condition: or(eq(variables['Build.Reason'], 'Schedule'), eq(variables['Build.Reason'], 'Manual'))
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Use Node 12.x'
inputs:
versionSpec: '12.x'
- template: templates/azp-step-git-init.yaml@azure
- script: |
export LOKALISE_TOKEN="$(lokaliseToken)"
export AZURE_BRANCH="$(Build.SourceBranchName)"
npm install
./script/translations_download
displayName: 'Download Translation'
- script: |
git checkout dev
git add translation
git commit -am "[ci skip] Translation update"
git push
displayName: 'Update translation'

View File

@@ -1,8 +1,8 @@
import {
customElement,
html,
property,
internalProperty,
property,
TemplateResult,
} from "lit-element";
import { mockHistory } from "../../../../demo/src/stubs/history";

View File

@@ -1,4 +1,4 @@
import "web-animations-js/web-animations-next-lite.min";
import "../../../src/resources/roboto";
import "../../../src/resources/ha-style";
import "../../../src/resources/roboto";
import "./layout/hc-lovelace";

View File

@@ -54,6 +54,8 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
state: "21",
attributes: {
friendly_name: "Living room temperature",
device_class: "temperature",
unit_of_measurement: "°C",
},
},
"sensor.study_temp_rounded": {
@@ -61,6 +63,8 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
state: "23",
attributes: {
friendly_name: "Study temperature",
device_class: "temperature",
unit_of_measurement: "°C",
},
},
"sensor.living_room": {
@@ -261,7 +265,7 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
entity_id: "light.kitchen_lights",
state: "off",
attributes: {
friendly_name: "Kitchen lights",
friendly_name: "Kitchen Lights",
supported_features: 1,
},
},
@@ -484,7 +488,7 @@ export const demoEntitiesArsaboo: DemoConfig["entities"] = (localize) =>
attributes: {
min_mireds: 111,
max_mireds: 400,
friendly_name: "Garage lights",
friendly_name: "Garage Lights",
supported_features: 55,
},
},

View File

@@ -12,6 +12,7 @@ export const demoLovelaceArsaboo: DemoConfig["lovelace"] = (localize) => ({
{
type: "entities",
title: localize("ui.panel.page-demo.config.arsaboo.labels.lights"),
state_color: true,
entities: [
{
entity: "light.kitchen_lights",

View File

@@ -653,7 +653,7 @@ export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
entity_id: "binary_sensor.smoke_sensor_158d0001b8ddc7",
state: "off",
attributes: {
Density: 0,
density: 0,
battery_level: 59,
friendly_name: "Downstairs Smoke Detector",
device_class: "smoke",
@@ -663,7 +663,7 @@ export const demoEntitiesJimpower: DemoConfig["entities"] = () =>
entity_id: "binary_sensor.smoke_sensor_158d0001b8deba",
state: "off",
attributes: {
Density: 0,
density: 0,
battery_level: 65,
friendly_name: "Upstairs Smoke Detector",
device_class: "smoke",

View File

@@ -3,49 +3,7 @@ import { DemoConfig } from "../types";
export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
name: "Kingia Castle",
resources: [
// {
// url: "/local/custom_ui/dark-sky-weather-card.js?v=4",
// type: "js",
// },
// {
// url: "/local/custom_ui/mini-media-player-bundle.js?v=0.9.8",
// type: "module",
// },
// {
// url: "/local/custom_ui/tracker-card.js?v=0.1.5",
// type: "js",
// },
// {
// url: "/local/custom_ui/surveillance-card.js?v=0.0.1",
// type: "module",
// },
// {
// url: "/local/custom_ui/mini-graph-card-bundle.js?v=0.1.0",
// type: "module",
// },
// {
// url: "/local/custom_ui/slider-entity-row.js?v=d6da75",
// type: "js",
// },
// {
// url:
// "/local/custom_ui/compact-custom-header/compact-custom-header.js?v=0.2.7",
// type: "js",
// },
// {
// url: "/local/custom_ui/waze-card.js?v=1.1.1",
// type: "js",
// },
// {
// url: "/local/custom_ui/circle-sensor-card.js?v=1.2.0",
// type: "module",
// },
// {
// url: "/local/custom_ui/monster-card.js?v=0.2.3",
// type: "js",
// },
],
resources: [],
views: [
{
cards: [
@@ -603,89 +561,6 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
},
{
cards: [
// {
// style: {
// "background-image": 'url("/assets/jimpower/cardbackK.png")',
// "background-size": "100% 400px",
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
// "background-repeat": "no-repeat",
// color: "#999999",
// "border-radius": "20px",
// border: "solid 1px rgba(100,100,100,0.3)",
// "background-color": "rgba(50,50,50,0.3)",
// },
// type: "custom:card-modder",
// card: {
// entity_visibility: "sensor.dark_sky_visibility",
// entity_sun: "sun.sun",
// entity_daily_summary:
// "sensor.bom_gc_forecast_detailed_summary_0",
// entity_temperature: "sensor.bom_temp",
// entity_forecast_high_temp_3:
// "sensor.bom_gc_forecast_max_temp_c_3",
// entity_forecast_high_temp_2:
// "sensor.bom_gc_forecast_max_temp_c_2",
// entity_forecast_high_temp_5:
// "sensor.bom_gc_forecast_max_temp_c_5",
// entity_forecast_high_temp_4:
// "sensor.bom_gc_forecast_max_temp_c_4",
// entity_wind_speed: "sensor.bom_wind_sp",
// entity_forecast_icon_4: "sensor.dark_sky_icon_4",
// entity_forecast_icon_5: "sensor.dark_sky_icon_5",
// entity_forecast_icon_2: "sensor.dark_sky_icon_2",
// entity_forecast_icon_3: "sensor.dark_sky_icon_3",
// entity_forecast_icon_1: "sensor.dark_sky_icon_1",
// entity_forecast_high_temp_1:
// "sensor.bom_gc_forecast_max_temp_c_1",
// entity_wind_bearing: "sensor.bom_wind_bear",
// entity_forecast_low_temp_2:
// "sensor.bom_gc_forecast_min_temp_c_2",
// entity_forecast_low_temp_3:
// "sensor.bom_gc_forecast_min_temp_c_3",
// entity_pressure: "sensor.bom_pres",
// entity_forecast_low_temp_1:
// "sensor.bom_gc_forecast_min_temp_c_1",
// entity_forecast_low_temp_4:
// "sensor.bom_gc_forecast_min_temp_c_4",
// entity_forecast_low_temp_5:
// "sensor.bom_gc_forecast_min_temp_c_5",
// entity_humidity: "sensor.bom_humd",
// type: "custom:dark-sky-weather-card",
// entity_current_conditions: "sensor.dark_sky_icon",
// },
// },
// {
// style: {
// "background-image": 'url("/assets/jimpower/home/waze_5.png")',
// "background-size": "100% 400px",
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
// "background-repeat": "no-repeat",
// "border-radius": "20px",
// border: "solid 1px rgba(100,100,100,0.3)",
// "background-color": "rgba(50,50,50,0.3)",
// },
// type: "custom:card-modder",
// card: {
// entities: [
// {
// name: "James",
// zone: "zone.home",
// entity: "sensor.james_to_home",
// },
// {
// name: "Tina",
// zone: "zone.home",
// entity: "sensor.tina_to_home",
// },
// {
// name: "Work",
// zone: "zone.powertec",
// entity: "sensor.commute_to_work",
// },
// ],
// type: "custom:waze-card",
// },
// },
{
style: {
"border-radius": "20px",
@@ -722,46 +597,8 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
],
type: "vertical-stack",
},
// {
// cards: [
// {
// style: {
// "border-radius": "20px",
// color: "#999999",
// "box-shadow": "3px 3px rgba(0,0,0,0.4)",
// border: "solid 1px rgba(100,100,100,0.3)",
// },
// type: "custom:card-modder",
// card: {
// type: "picture-entity",
// entity: "camera.bom_radar",
// },
// },
// // {
// // style: {
// // "background-image": 'url("/assets/jimpower/cardbackK.png")',
// // "background-size": "100% 525px",
// // "box-shadow": "3px 3px rgba(0,0,0,0.4)",
// // "background-repeat": "no-repeat",
// // color: "#999999",
// // "border-radius": "20px",
// // border: "solid 1px rgba(100,100,100,0.3)",
// // "background-color": "rgba(50,50,50,0.3)",
// // },
// // type: "custom:card-modder",
// // card: {
// // title: null,
// // type: "custom:tracker-card",
// // trackers: [
// // "sensor.custom_card_tracker",
// // "sensor.custom_component_tracker",
// // ],
// // },
// // },
// ],
// type: "vertical-stack",
// },
],
path: "home",
icon: "mdi:castle",
name: "Home",
background:
@@ -881,26 +718,13 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
card: {
image: "/assets/jimpower/security/air_8.jpg",
elements: [
{
image:
"https://www.airvisual.com/assets/aqi/ic-face-1-green.svg",
type: "image",
style: {
width: "80px",
top: "30%",
left: "12%",
transform: "none",
height: "80px",
},
entity: "sensor.us_air_pollution_level_2",
},
{
style: {
color: "hsl(120, 41%, 39%)",
top: "50%",
"font-weight": 600,
"font-size": "20px",
left: "44%",
"font-size": "50px",
left: "30%",
},
type: "state-label",
entity: "sensor.us_air_pollution_level_2",
@@ -920,7 +744,7 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
style: {
color: "white",
top: "80%",
left: "52%",
left: "48%",
},
type: "state-icon",
entity: "sensor.us_main_pollutant_2",
@@ -1411,6 +1235,7 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
type: "vertical-stack",
},
],
path: "security",
icon: "hass:shield-home",
name: "Security",
background:

View File

@@ -101,7 +101,12 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
"sensor.zwave_battery_front_door": {
entity_id: "sensor.zwave_battery_front_door",
state: "63",
attributes: { friendly_name: "Battery", icon: "mdi:battery-60" },
attributes: {
friendly_name: "Battery",
icon: "mdi:battery-60",
unit_of_measurement: "%",
device_class: "battery",
},
},
"sensor.oskar_devices": {
entity_id: "sensor.oskar_devices",
@@ -164,7 +169,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
},
"input_select.christmas_pattern": {
entity_id: "input_select.christmas_pattern",
state: "None",
state: "Rainbow",
attributes: {
options: [
"None",
@@ -186,7 +191,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
},
"input_select.christmas_palette": {
entity_id: "input_select.christmas_palette",
state: "None",
state: "Party",
attributes: {
options: [
"None",
@@ -457,7 +462,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
state: "0.0",
attributes: {
unit_of_measurement: "kB/s",
friendly_name: "Nedladdning",
friendly_name: "Downloading",
icon: "mdi:file-download",
},
},
@@ -471,7 +476,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
state: "0.0",
attributes: {
unit_of_measurement: "kB/s",
friendly_name: "Uppladdning",
friendly_name: "Uploading",
icon: "mdi:file-upload",
},
},

View File

@@ -2,44 +2,7 @@ import { DemoConfig } from "../types";
export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
name: "Hem",
resources: [
// {
// url: "/local/custom-lovelace/monster-card.js",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/mini-media-player-bundle.js?v=0.9.8",
// type: "module",
// },
// {
// url: "/local/custom-lovelace/slideshow-card.js?=1.1.0",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/fold-entity-row.js?v=3ae2c4",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/swipe-card/swipe-card.js?v=2.0.0",
// type: "module",
// },
// {
// url: "/local/custom-lovelace/upcoming-media-card/upcoming-media-card.js",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/tracker-card.js?v=0.1.5",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/card-tools.js?v=6ce5d0",
// type: "js",
// },
// {
// url: "/local/custom-lovelace/krisinfo.js?=0.0.1",
// type: "js",
// },
],
resources: [],
views: [
{
cards: [
@@ -64,7 +27,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
style: {
color: "white",
top: "93%",
left: "90%",
left: "85%",
},
type: "state-label",
entity: "sensor.battery_oskar",
@@ -87,7 +50,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
{
style: {
color: "white",
top: "92%",
top: "93%",
left: "20%",
},
type: "state-label",
@@ -96,8 +59,8 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
{
style: {
color: "white",
top: "92%",
left: "90%",
top: "93%",
left: "85%",
},
type: "state-label",
entity: "sensor.battery_bella",
@@ -105,7 +68,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
{
style: {
color: "white",
top: "92%",
top: "93%",
left: "55%",
},
type: "state-label",
@@ -131,78 +94,6 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
type: "entities",
title: "Lock",
},
// {
// filter: {
// exclude: [
// {
// state: "not_home",
// },
// ],
// include: [
// {
// entity_id: "device_tracker.annasiphone",
// },
// {
// entity_id: "device_tracker.iphone_2",
// },
// ],
// },
// type: "custom:monster-card",
// card: {
// show_header_toggle: false,
// type: "entities",
// title: "G\u00e4ster",
// },
// show_empty: false,
// },
// {
// filter: {
// exclude: [
// {
// state: "Inget",
// },
// {
// state: "i.u.",
// },
// ],
// include: [
// {
// entity_id: "sensor.pollen_al",
// },
// {
// entity_id: "sensor.pollen_alm",
// },
// {
// entity_id: "sensor.pollen_salg_vide",
// },
// {
// entity_id: "sensor.pollen_bjork",
// },
// {
// entity_id: "sensor.pollen_bok",
// },
// {
// entity_id: "sensor.pollen_ek",
// },
// {
// entity_id: "sensor.pollen_grabo",
// },
// {
// entity_id: "sensor.pollen_gras",
// },
// {
// entity_id: "sensor.pollen_hassel",
// },
// ],
// },
// type: "custom:monster-card",
// card: {
// show_header_toggle: false,
// type: "entities",
// title: "Pollenniv\u00e5er",
// },
// show_empty: false,
// },
{
cards: [
{
@@ -226,10 +117,6 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
],
type: "vertical-stack",
},
// {
// url: "https://embed.windy.com/embed2.html",
// type: "iframe",
// },
{
entities: [
{
@@ -263,6 +150,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
],
type: "glance",
show_state: false,
columns: 4,
},
{
entities: ["sensor.oskar_bluetooth"],
@@ -270,32 +158,6 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
type: "entities",
title: "Occupancy",
},
// {
// filter: {
// exclude: [
// {
// state: false,
// },
// ],
// include: [
// {
// entity_id:
// "binary_sensor.fibaro_system_unknown_type0c02_id1003_sensor_2",
// },
// {
// entity_id:
// "binary_sensor.fibaro_system_unknown_type0c02_id1003_sensor_3",
// },
// ],
// },
// type: "custom:monster-card",
// card: {
// show_header_toggle: false,
// type: "entities",
// title: "Brandvarnare",
// },
// show_empty: false,
// },
{
type: "weather-forecast",
entity: "weather.smhi_vader",
@@ -378,41 +240,9 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
"binary_sensor.windows_server",
"binary_sensor.teamspeak",
"binary_sensor.harmony_hub",
// {
// style: {
// height: "1px",
// width: "85%",
// "margin-left": "auto",
// background: "#62717b",
// "margin-right": "auto",
// },
// type: "divider",
// },
// {
// items: ["sensor.uptime_router", "sensor.installerad_routeros"],
// head: {
// entity: "binary_sensor.router",
// },
// type: "custom:fold-entity-row",
// group_config: {
// icon: "mdi:router",
// },
// },
// {
// items: [
// "sensor.uptime_router_server",
// "sensor.installerad_routeros_server",
// ],
// head: {
// entity: "binary_sensor.router_server",
// },
// type: "custom:fold-entity-row",
// group_config: {
// icon: "mdi:router",
// },
// },
],
show_header_toggle: false,
state_color: true,
type: "entities",
title: "Network",
},
@@ -422,29 +252,10 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
"binary_sensor.ubiquiti_switch",
"binary_sensor.ubiquiti_nvr",
"binary_sensor.entre_kamera",
// {
// items: ["sensor.uptime_ap_1"],
// head: {
// entity: "binary_sensor.accesspunkt_1",
// },
// type: "custom:fold-entity-row",
// group_config: {
// icon: "router-wireless",
// },
// },
// {
// items: ["sensor.uptime_ap_2"],
// head: {
// entity: "binary_sensor.accesspunkt_2",
// },
// type: "custom:fold-entity-row",
// group_config: {
// icon: "router-wireless",
// },
// },
"sensor.total_clients_wireless",
],
show_header_toggle: false,
state_color: true,
type: "entities",
title: "Ubiquiti",
},

View File

@@ -215,6 +215,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
card: {
type: "glance",
show_state: false,
columns: 4,
},
state_filter: ["on"],
},
@@ -808,67 +809,6 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
],
type: "vertical-stack",
},
// {
// cards: [
// {
// entities: [
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Bedside",
// entity: "light.bedside_lamp",
// },
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Bedroom",
// entity: "light.bedroom_ceiling_light",
// },
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Isa",
// entity: "light.isa_ceiling_light",
// },
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Upstairs hallway",
// entity: "light.upstairs_hallway_ceiling_light_level",
// },
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Nightlight",
// entity: "light.gateway_light_34ce008bfc4b",
// },
// {
// hide_when_off: true,
// toggle: true,
// type: "custom:slider-entity-row",
// name: "Walk in closet",
// entity: "light.walk_in_closet_lights",
// },
// {
// hide_when_off: true,
// toggle: false,
// type: "custom:slider-entity-row",
// name: "Stefan",
// entity: "light.stefan_lightstrip",
// },
// ],
// show_header_toggle: false,
// type: "entities",
// title: "Upstairs",
// },
// ],
// type: "vertical-stack",
// },
],
path: "lights",
title: "Lights",
@@ -918,10 +858,6 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
name: "Dafang",
icon: "mdi:webcam",
},
{
name: "IR Hallway",
entity: "sensor.system_ir_blaster",
},
{
name: "IR Bedroom",
entity: "sensor.system_ir_blaster_bedroom",
@@ -940,7 +876,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
"sensor.system_ring_chime",
],
type: "glance",
columns: 5,
columns: 4,
show_state: false,
},
{

View File

@@ -3,8 +3,8 @@ import {
CSSResult,
customElement,
html,
LitElement,
internalProperty,
LitElement,
TemplateResult,
} from "lit-element";
import { CastManager } from "../../../src/cast/cast_manager";

View File

@@ -3,9 +3,9 @@ import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
internalProperty,
TemplateResult,
} from "lit-element";
import { until } from "lit-html/directives/until";

View File

@@ -1,8 +1,8 @@
import "../../src/resources/safari-14-attachshadow-patch";
import "@polymer/polymer/lib/elements/dom-if";
import "@polymer/polymer/lib/elements/dom-repeat";
import "../../src/resources/ha-style";
import "../../src/resources/roboto";
import "../../src/resources/safari-14-attachshadow-patch";
import "./ha-demo";
/* polyfill for paper-dropdown */

View File

@@ -1,3 +1,4 @@
// Compat needs to be first import
import "../../src/resources/compatibility";
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
import { navigate } from "../../src/common/navigate";

View File

@@ -2,10 +2,10 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../src/components/ha-switch";
import "../../../src/components/ha-formfield";
import "./demo-card";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
import "../../../src/components/ha-formfield";
import "../../../src/components/ha-switch";
import "./demo-card";
class DemoCards extends PolymerElement {
static get template() {

View File

@@ -2,8 +2,8 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../src/components/ha-card";
import "../../../src/state-summary/state-card-content";
import "../../../src/dialogs/more-info/more-info-content";
import "../../../src/state-summary/state-card-content";
class DemoMoreInfo extends PolymerElement {
static get template() {

View File

@@ -2,10 +2,10 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../src/components/ha-switch";
import "../../../src/components/ha-formfield";
import "./demo-more-info";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
import "../../../src/components/ha-formfield";
import "../../../src/components/ha-switch";
import "./demo-more-info";
class DemoMoreInfos extends PolymerElement {
static get template() {

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,
@@ -53,7 +53,7 @@ const CONFIGS = [
config: `
- type: button
entity: light.bed_light
tap_action:
tap_action:
action: toggle
`,
},

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,
@@ -48,7 +48,7 @@ const ENTITIES = [
const CONFIGS = [
{
heading: "Controller",
heading: "Unfiltered controller",
config: `
- type: entities
entities:
@@ -58,7 +58,7 @@ const CONFIGS = [
`,
},
{
heading: "Basic",
heading: "Filtered entities card",
config: `
- type: entity-filter
entities:
@@ -74,7 +74,27 @@ const CONFIGS = [
`,
},
{
heading: "With card config",
heading: 'With "entities" card config',
config: `
- type: entity-filter
entities:
- device_tracker.demo_anne_therese
- device_tracker.demo_home_boy
- device_tracker.demo_paulus
- light.bed_light
- light.ceiling_lights
- light.kitchen_lights
state_filter:
- "on"
- not_home
card:
type: entities
title: Custom Title
show_header_toggle: false
`,
},
{
heading: 'With "glance" card config',
config: `
- type: entity-filter
entities:
@@ -89,7 +109,8 @@ const CONFIGS = [
- not_home
card:
type: glance
show_state: false
show_state: true
title: Custom Title
`,
},
];

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,
@@ -82,7 +82,8 @@ const CONFIGS = [
heading: "With title",
config: `
- type: glance
title: This is glance
title: Custom title
columns: 4
entities:
- device_tracker.demo_paulus
- media_player.living_room
@@ -109,9 +110,10 @@ const CONFIGS = [
`,
},
{
heading: "No name",
heading: "No entity names",
config: `
- type: glance
columns: 4
show_name: false
entities:
- device_tracker.demo_paulus
@@ -124,9 +126,10 @@ const CONFIGS = [
`,
},
{
heading: "No state",
heading: "No state labels",
config: `
- type: glance
columns: 4
show_state: false
entities:
- device_tracker.demo_paulus
@@ -139,9 +142,10 @@ const CONFIGS = [
`,
},
{
heading: "No name and no state",
heading: "No names and no state labels",
config: `
- type: glance
columns: 4
show_name: false
show_state: false
entities:
@@ -155,47 +159,24 @@ const CONFIGS = [
`,
},
{
heading: "Custom name, custom icon",
heading: "Custom name + custom icon",
config: `
- type: glance
columns: 4
entities:
- entity: device_tracker.demo_paulus
name: ¯\\_(ツ)_/¯
icon: mdi:home-assistant
- media_player.living_room
- sun.sun
- cover.kitchen_window
- entity: light.kitchen_lights
icon: mdi:alarm-light
- lock.kitchen_door
- light.ceiling_lights
`,
},
{
heading: "Custom tap action",
config: `
- type: glance
entities:
- entity: lock.kitchen_door
tap_action:
type: toggle
- entity: light.ceiling_lights
tap_action:
action: call-service
service: light.turn_on
service_data:
entity_id: light.ceiling_lights
- device_tracker.demo_paulus
- media_player.living_room
- sun.sun
- cover.kitchen_window
- light.kitchen_lights
- entity: media_player.living_room
name: ¯\\_(ツ)_/¯
icon: mdi:home-assistant
`,
},
{
heading: "Selectively hidden name",
config: `
- type: glance
columns: 4
entities:
- device_tracker.demo_paulus
- entity: media_player.living_room
@@ -204,21 +185,32 @@ const CONFIGS = [
- entity: cover.kitchen_window
name:
- light.kitchen_lights
- entity: lock.kitchen_door
name:
- light.ceiling_lights
`,
},
{
heading: "Primary theme",
heading: "Custom tap action",
config: `
- type: glance
theming: primary
columns: 4
entities:
- device_tracker.demo_paulus
- media_player.living_room
- sun.sun
- cover.kitchen_window
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
- entity: lock.kitchen_door
name: Custom
tap_action:
type: toggle
- entity: light.ceiling_lights
name: Custom
tap_action:
action: call-service
service: light.turn_on
service_data:
entity_id: light.ceiling_lights
- entity: sun.sun
name: Regular
- entity: light.kitchen_lights
name: Regular
`,
},
];

View File

@@ -1,4 +1,4 @@
import { html, LitElement, customElement, TemplateResult } from "lit-element";
import { customElement, html, LitElement, TemplateResult } from "lit-element";
import "../components/demo-cards";
const CONFIGS = [

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,
@@ -31,9 +31,9 @@ const CONFIGS = [
- entity: media_player.android_cast
name: Screen casting
- entity: media_player.image_display
name: Digital Picture Frame
name: Digital Picture Frame
- entity: media_player.sonos_idle
name: Sonos Idle
name: Sonos Idle
- entity: media_player.idle_browse_media
name: Idle waiting for Browse Media
- entity: media_player.theater_off
@@ -43,7 +43,7 @@ const CONFIGS = [
- entity: media_player.theater_off_static
name: Player Off (cannot be switched on)
- entity: media_player.theater_on_static
name: Player On (cannot be switched off)
name: Player On (cannot be switched off)
- entity: media_player.idle
name: Player Idle
- entity: media_player.playing

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
PropertyValues,
query,
TemplateResult,

View File

@@ -1,7 +1,7 @@
import {
customElement,
html,
LitElement,
customElement,
property,
PropertyValues,
query,
@@ -10,20 +10,20 @@ import {
import "../../../src/components/ha-card";
import {
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
SUPPORT_EFFECT,
SUPPORT_FLASH,
SUPPORT_COLOR,
SUPPORT_TRANSITION,
SUPPORT_WHITE_VALUE,
} from "../../../src/data/light";
import "../../../src/dialogs/more-info/more-info-content";
import { getEntity } from "../../../src/fake_data/entity";
import {
provideHass,
MockHomeAssistant,
provideHass,
} from "../../../src/fake_data/provide_hass";
import "../components/demo-more-infos";
import "../../../src/dialogs/more-info/more-info-content";
const ENTITIES = [
getEntity("light", "bed_light", "on", {

View File

@@ -12,6 +12,7 @@ import {
} from "lit-element";
import { html, TemplateResult } from "lit-html";
import { atLeastVersion } from "../../../src/common/config/version";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/common/search/search-input";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-svg-icon";
@@ -22,6 +23,7 @@ import {
reloadHassioAddons,
} from "../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import { fetchHassioSupervisorInfo } from "../../../src/data/hassio/supervisor";
import "../../../src/layouts/hass-loading-screen";
import "../../../src/layouts/hass-tabs-subpage";
import { HomeAssistant, Route } from "../../../src/types";
@@ -190,7 +192,11 @@ class HassioAddonStore extends LitElement {
private async _loadData() {
try {
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
const [addonsInfo, supervisor] = await Promise.all([
fetchHassioAddonsInfo(this.hass),
fetchHassioSupervisorInfo(this.hass),
]);
fireEvent(this, "supervisor-update", { supervisor });
this._repos = addonsInfo.repositories;
this._repos.sort(sortRepos);
this._addons = addonsInfo.addons;

View File

@@ -7,13 +7,14 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";
import "web-animations-js/web-animations-next-lite.min";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
import {
HassioAddonDetails,
@@ -28,7 +29,6 @@ import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
import { hassioStyle } from "../../resources/hassio-style";
import "../../../../src/components/buttons/ha-progress-button";
@customElement("hassio-addon-audio")
class HassioAddonAudio extends LitElement {

View File

@@ -7,11 +7,11 @@ import {
property,
TemplateResult,
} from "lit-element";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { hassioStyle } from "../../resources/hassio-style";
import "../../../../src/components/ha-circular-progress";
import "./hassio-addon-audio";
import "./hassio-addon-config";
import "./hassio-addon-network";
@@ -26,28 +26,41 @@ class HassioAddonConfigDashboard extends LitElement {
if (!this.addon) {
return html`<ha-circular-progress active></ha-circular-progress>`;
}
const hasOptions =
this.addon.options && Object.keys(this.addon.options).length;
const hasSchema =
this.addon.schema && Object.keys(this.addon.schema).length;
return html`
<div class="content">
<hassio-addon-config
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-config>
${this.addon.network
${hasOptions || hasSchema || this.addon.network || this.addon.audio
? html`
<hassio-addon-network
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-network>
${hasOptions || hasSchema
? html`
<hassio-addon-config
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-config>
`
: ""}
${this.addon.network
? html`
<hassio-addon-network
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-network>
`
: ""}
${this.addon.audio
? html`
<hassio-addon-audio
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-audio>
`
: ""}
`
: ""}
${this.addon.audio
? html`
<hassio-addon-audio
.hass=${this.hass}
.addon=${this.addon}
></hassio-addon-audio>
`
: ""}
: "This add-on does not expose configuration for you to mess with.... 👋"}
</div>
`;
}

View File

@@ -14,12 +14,12 @@ import {
TemplateResult,
} from "lit-element";
import memoizeOne from "memoize-one";
import "../../../src/components/ha-circular-progress";
import {
fetchHassioAddonInfo,
HassioAddonDetails,
} from "../../../src/data/hassio/addon";
import "../../../src/layouts/hass-tabs-subpage";
import "../../../src/components/ha-circular-progress";
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types";

View File

@@ -7,8 +7,8 @@ import {
property,
TemplateResult,
} from "lit-element";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { hassioStyle } from "../../resources/hassio-style";

View File

@@ -7,8 +7,8 @@ import {
property,
TemplateResult,
} from "lit-element";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import "../../../../src/components/ha-circular-progress";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { hassioStyle } from "../../resources/hassio-style";

View File

@@ -0,0 +1,87 @@
import {
css,
CSSResult,
customElement,
html,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import "../../../src/components/ha-bar";
import "../../../src/components/ha-settings-row";
import { roundWithOneDecimal } from "../../../src/util/calculate";
@customElement("supervisor-metric")
class SupervisorMetric extends LitElement {
@property({ type: Number }) public value!: number;
@property({ type: String }) public description!: string;
@property({ type: String }) public tooltip?: string;
protected render(): TemplateResult {
const roundedValue = roundWithOneDecimal(this.value);
return html`<ha-settings-row>
<span slot="heading">
${this.description}
</span>
<div slot="description" title="${this.tooltip ?? ""}">
<span class="value">
${roundedValue}%
</span>
<ha-bar
class="${classMap({
"target-warning": roundedValue > 50,
"target-critical": roundedValue > 85,
})}"
.value=${this.value}
></ha-bar>
</div>
</ha-settings-row>`;
}
static get styles(): CSSResult {
return css`
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row > div[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
display: flex;
justify-content: space-between;
}
ha-bar {
--ha-bar-primary-color: var(
--hassio-bar-ok-color,
var(--success-color)
);
}
.target-warning {
--ha-bar-primary-color: var(
--hassio-bar-warning-color,
var(--warning-color)
);
}
.target-critical {
--ha-bar-primary-color: var(
--hassio-bar-critical-color,
var(--error-color)
);
}
.value {
width: 42px;
padding-right: 4px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"supervisor-metric": SupervisorMetric;
}
}

View File

@@ -3,9 +3,9 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
TemplateResult,
} from "lit-element";
import { createCloseHeading } from "../../../../src/components/ha-dialog";

View File

@@ -1,6 +1,7 @@
// Compat needs to be first import
import "../../src/resources/compatibility";
import "../../src/resources/safari-14-attachshadow-patch";
import "../../src/resources/roboto";
import "../../src/resources/safari-14-attachshadow-patch";
import "./hassio-main";
const styleEl = document.createElement("style");

View File

@@ -1,11 +1,11 @@
import { html, PropertyValues, customElement, property } from "lit-element";
import "./hassio-router";
import { HomeAssistant, Route } from "../../src/types";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
import { customElement, html, property, PropertyValues } from "lit-element";
import { atLeastVersion } from "../../src/common/config/version";
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
import { atLeastVersion } from "../../src/common/config/version";
import { HomeAssistant, Route } from "../../src/types";
import "./hassio-router";
import { SupervisorBaseElement } from "./supervisor-base-element";
@customElement("hassio-main")

View File

@@ -1,14 +1,17 @@
import { mdiMenu } from "@mdi/js";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";
import { fireEvent } from "../../../src/common/dom/fire_event";
import { navigate } from "../../../src/common/navigate";
import {
fetchHassioAddonInfo,
HassioAddonDetails,
@@ -17,13 +20,10 @@ import {
createHassioSession,
validateHassioSession,
} from "../../../src/data/hassio/ingress";
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/layouts/hass-loading-screen";
import "../../../src/layouts/hass-subpage";
import { HomeAssistant, Route } from "../../../src/types";
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
import { navigate } from "../../../src/common/navigate";
import { mdiMenu } from "@mdi/js";
import { fireEvent } from "../../../src/common/dom/fire_event";
@customElement("hassio-ingress-view")
class HassioIngressView extends LitElement {

View File

@@ -264,7 +264,7 @@ class HassioSnapshots extends LitElement {
}
protected updated(changedProps: PropertyValues) {
if (changedProps.has("supervisorInfo")) {
if (changedProps.has("supervisor")) {
this._addonList = this.supervisor.supervisor.addons
.map((addon) => ({
slug: addon.slug,

View File

@@ -0,0 +1,246 @@
import "@material/mwc-button";
import "@material/mwc-list/mwc-list-item";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
import {
extractApiErrorMessage,
fetchHassioStats,
HassioStats,
} from "../../../src/data/hassio/common";
import { restartCore, updateCore } from "../../../src/data/supervisor/core";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import {
showAlertDialog,
showConfirmationDialog,
} from "../../../src/dialogs/generic/show-dialog-box";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import { bytesToString } from "../../../src/util/bytes-to-string";
import "../components/supervisor-metric";
import { hassioStyle } from "../resources/hassio-style";
@customElement("hassio-core-info")
class HassioCoreInfo extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public supervisor!: Supervisor;
@internalProperty() private _metrics?: HassioStats;
protected render(): TemplateResult | void {
const metrics = [
{
description: "Core CPU Usage",
value: this._metrics?.cpu_percent,
},
{
description: "Core RAM Usage",
value: this._metrics?.memory_percent,
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
this._metrics?.memory_limit
)}`,
},
];
return html`
<ha-card header="Core">
<div class="card-content">
<div>
<ha-settings-row>
<span slot="heading">
Version
</span>
<span slot="description">
core-${this.supervisor.core.version}
</span>
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Newest Version
</span>
<span slot="description">
core-${this.supervisor.core.version_latest}
</span>
${this.supervisor.core.update_available
? html`
<ha-progress-button
title="Update the core"
@click=${this._coreUpdate}
>
Update
</ha-progress-button>
`
: ""}
</ha-settings-row>
</div>
<div>
${metrics.map(
(metric) =>
html`
<supervisor-metric
.description=${metric.description}
.value=${metric.value ?? 0}
.tooltip=${metric.tooltip}
></supervisor-metric>
`
)}
</div>
</div>
<div class="card-actions">
<ha-progress-button
slot="primaryAction"
class="warning"
@click=${this._coreRestart}
title="Restart Home Assistant Core"
>
Restart Core
</ha-progress-button>
</div>
</ha-card>
`;
}
protected firstUpdated(): void {
this._loadData();
}
private async _loadData(): Promise<void> {
this._metrics = await fetchHassioStats(this.hass, "core");
}
private async _coreRestart(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Restart Home Assistant Core",
text: "Are you sure you want to restart Home Assistant Core",
confirmText: "restart",
dismissText: "cancel",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await restartCore(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to restart Home Assistant Core",
text: extractApiErrorMessage(err),
});
} finally {
button.progress = false;
}
}
private async _coreUpdate(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Update Home Assistant Core",
text: `Are you sure you want to update Home Assistant Core to version ${this.supervisor.core.version_latest}?`,
confirmText: "update",
dismissText: "cancel",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await updateCore(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to update Home Assistant Core",
text: extractApiErrorMessage(err),
});
} finally {
button.progress = false;
}
}
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
ha-card {
height: 100%;
justify-content: space-between;
flex-direction: column;
display: flex;
}
.card-actions {
height: 48px;
border-top: none;
display: flex;
justify-content: flex-end;
align-items: center;
}
.card-content {
display: flex;
flex-direction: column;
height: calc(100% - 124px);
justify-content: space-between;
}
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row[three-line] {
height: 74px;
}
ha-settings-row > span[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
}
.warning {
--mdc-theme-primary: var(--error-color);
}
ha-button-menu {
color: var(--secondary-text-color);
--mdc-menu-min-width: 200px;
}
@media (min-width: 563px) {
paper-listbox {
max-height: 150px;
overflow: auto;
}
}
paper-item {
cursor: pointer;
min-height: 35px;
}
mwc-list-item ha-svg-icon {
color: var(--secondary-text-color);
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"hassio-core-info": HassioCoreInfo;
}
}

View File

@@ -43,6 +43,11 @@ import {
} from "../../../src/dialogs/generic/show-dialog-box";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import {
getValueInPercentage,
roundWithOneDecimal,
} from "../../../src/util/calculate";
import "../components/supervisor-metric";
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
import { hassioStyle } from "../resources/hassio-style";
@@ -57,80 +62,105 @@ class HassioHostInfo extends LitElement {
const primaryIpAddress = this.supervisor.host.features.includes("network")
? this._primaryIpAddress(this.supervisor.network!)
: "";
return html`
<ha-card header="Host System">
<div class="card-content">
${this.supervisor.host.features.includes("hostname")
? html`<ha-settings-row>
<span slot="heading">
Hostname
</span>
<span slot="description">
${this.supervisor.host.hostname}
</span>
<mwc-button
title="Change the hostname"
label="Change"
@click=${this._changeHostnameClicked}
>
</mwc-button>
</ha-settings-row>`
: ""}
${this.supervisor.host.features.includes("network")
? html` <ha-settings-row>
<span slot="heading">
IP Address
</span>
<span slot="description">
${primaryIpAddress}
</span>
<mwc-button
title="Change the network"
label="Change"
@click=${this._changeNetworkClicked}
>
</mwc-button>
</ha-settings-row>`
: ""}
<ha-settings-row>
<span slot="heading">
Operating System
</span>
<span slot="description">
${this.supervisor.host.operating_system}
</span>
${this.supervisor.os.update_available
? html`
<ha-progress-button
title="Update the host OS"
@click=${this._osUpdate}
const metrics = [
{
description: "Used Space",
value: this._getUsedSpace(
this.supervisor.host.disk_used,
this.supervisor.host.disk_total
),
tooltip: `${this.supervisor.host.disk_used} GB/${this.supervisor.host.disk_total} GB`,
},
];
return html`
<ha-card header="Host">
<div class="card-content">
<div>
${this.supervisor.host.features.includes("hostname")
? html`<ha-settings-row>
<span slot="heading">
Hostname
</span>
<span slot="description">
${this.supervisor.host.hostname}
</span>
<mwc-button
title="Change the hostname"
label="Change"
@click=${this._changeHostnameClicked}
>
Update
</ha-progress-button>
`
</mwc-button>
</ha-settings-row>`
: ""}
</ha-settings-row>
${!this.supervisor.host.features.includes("hassos")
? html`<ha-settings-row>
<span slot="heading">
Docker version
</span>
<span slot="description">
${this.supervisor.info.docker}
</span>
</ha-settings-row>`
: ""}
${this.supervisor.host.deployment
? html`<ha-settings-row>
<span slot="heading">
Deployment
</span>
<span slot="description">
${this.supervisor.host.deployment}
</span>
</ha-settings-row>`
: ""}
${this.supervisor.host.features.includes("network")
? html` <ha-settings-row>
<span slot="heading">
IP Address
</span>
<span slot="description">
${primaryIpAddress}
</span>
<mwc-button
title="Change the network"
label="Change"
@click=${this._changeNetworkClicked}
>
</mwc-button>
</ha-settings-row>`
: ""}
<ha-settings-row>
<span slot="heading">
Operating System
</span>
<span slot="description">
${this.supervisor.host.operating_system}
</span>
${this.supervisor.os.update_available
? html`
<ha-progress-button
title="Update the host OS"
@click=${this._osUpdate}
>
Update
</ha-progress-button>
`
: ""}
</ha-settings-row>
${!this.supervisor.host.features.includes("hassos")
? html`<ha-settings-row>
<span slot="heading">
Docker version
</span>
<span slot="description">
${this.supervisor.info.docker}
</span>
</ha-settings-row>`
: ""}
${this.supervisor.host.deployment
? html`<ha-settings-row>
<span slot="heading">
Deployment
</span>
<span slot="description">
${this.supervisor.host.deployment}
</span>
</ha-settings-row>`
: ""}
</div>
<div>
${metrics.map(
(metric) =>
html`
<supervisor-metric
.description=${metric.description}
.value=${metric.value ?? 0}
.tooltip=${metric.tooltip}
></supervisor-metric>
`
)}
</div>
</div>
<div class="card-actions">
${this.supervisor.host.features.includes("reboot")
@@ -140,7 +170,7 @@ class HassioHostInfo extends LitElement {
class="warning"
@click=${this._hostReboot}
>
Reboot
Reboot Host
</ha-progress-button>
`
: ""}
@@ -151,7 +181,7 @@ class HassioHostInfo extends LitElement {
class="warning"
@click=${this._hostShutdown}
>
Shutdown
Shutdown Host
</ha-progress-button>
`
: ""}
@@ -183,6 +213,10 @@ class HassioHostInfo extends LitElement {
this._loadData();
}
private _getUsedSpace = memoizeOne((used: number, total: number) =>
roundWithOneDecimal(getValueInPercentage(used, 0, total))
);
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
if (!network_info || !network_info.interfaces) {
return "";
@@ -369,6 +403,12 @@ class HassioHostInfo extends LitElement {
justify-content: space-between;
align-items: center;
}
.card-content {
display: flex;
flex-direction: column;
height: calc(100% - 124px);
justify-content: space-between;
}
ha-settings-row {
padding: 0;
height: 54px;

View File

@@ -3,6 +3,7 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
@@ -12,7 +13,11 @@ import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
import "../../../src/components/ha-switch";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import {
extractApiErrorMessage,
fetchHassioStats,
HassioStats,
} from "../../../src/data/hassio/common";
import {
fetchHassioSupervisorInfo,
reloadSupervisor,
@@ -28,7 +33,9 @@ import {
} from "../../../src/dialogs/generic/show-dialog-box";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import { bytesToString } from "../../../src/util/bytes-to-string";
import { documentationUrl } from "../../../src/util/documentation-url";
import "../components/supervisor-metric";
import { hassioStyle } from "../resources/hassio-style";
const UNSUPPORTED_REASON = {
@@ -87,127 +94,164 @@ class HassioSupervisorInfo extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
@internalProperty() private _metrics?: HassioStats;
protected render(): TemplateResult | void {
const metrics = [
{
description: "Supervisor CPU Usage",
value: this._metrics?.cpu_percent,
},
{
description: "Supervisor RAM Usage",
value: this._metrics?.memory_percent,
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
this._metrics?.memory_limit
)}`,
},
];
return html`
<ha-card header="Supervisor">
<div class="card-content">
<ha-settings-row>
<span slot="heading">
Version
</span>
<span slot="description">
${this.supervisor.supervisor.version}
</span>
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Newest Version
</span>
<span slot="description">
${this.supervisor.supervisor.version_latest}
</span>
${this.supervisor.supervisor.update_available
? html`
<ha-progress-button
title="Update the supervisor"
@click=${this._supervisorUpdate}
>
Update
</ha-progress-button>
`
: ""}
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Channel
</span>
<span slot="description">
${this.supervisor.supervisor.channel}
</span>
${this.supervisor.supervisor.channel === "beta"
? html`
<ha-progress-button
@click=${this._toggleBeta}
title="Get stable updates for Home Assistant, supervisor and host"
>
Leave beta channel
</ha-progress-button>
`
: this.supervisor.supervisor.channel === "stable"
? html`
<ha-progress-button
@click=${this._toggleBeta}
title="Get beta updates for Home Assistant (RCs), supervisor and host"
>
Join beta channel
</ha-progress-button>
`
: ""}
</ha-settings-row>
<div>
<ha-settings-row>
<span slot="heading">
Version
</span>
<span slot="description">
supervisor-${this.supervisor.supervisor.version}
</span>
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Newest Version
</span>
<span slot="description">
supervisor-${this.supervisor.supervisor.version_latest}
</span>
${this.supervisor.supervisor.update_available
? html`
<ha-progress-button
title="Update the supervisor"
@click=${this._supervisorUpdate}
>
Update
</ha-progress-button>
`
: ""}
</ha-settings-row>
<ha-settings-row>
<span slot="heading">
Channel
</span>
<span slot="description">
${this.supervisor.supervisor.channel}
</span>
${this.supervisor.supervisor.channel === "beta"
? html`
<ha-progress-button
@click=${this._toggleBeta}
title="Get stable updates for Home Assistant, supervisor and host"
>
Leave beta channel
</ha-progress-button>
`
: this.supervisor.supervisor.channel === "stable"
? html`
<ha-progress-button
@click=${this._toggleBeta}
title="Get beta updates for Home Assistant (RCs), supervisor and host"
>
Join beta channel
</ha-progress-button>
`
: ""}
</ha-settings-row>
${this.supervisor.supervisor.supported
? html` <ha-settings-row three-line>
<span slot="heading">
Share Diagnostics
</span>
<div slot="description" class="diagnostics-description">
Share crash reports and diagnostic information.
${this.supervisor.supervisor.supported
? html` <ha-settings-row three-line>
<span slot="heading">
Share Diagnostics
</span>
<div slot="description" class="diagnostics-description">
Share crash reports and diagnostic information.
<button
class="link"
title="Show more information about this"
@click=${this._diagnosticsInformationDialog}
>
Learn more
</button>
</div>
<ha-switch
haptic
.checked=${this.supervisor.supervisor.diagnostics}
@change=${this._toggleDiagnostics}
></ha-switch>
</ha-settings-row>`
: html`<div class="error">
You are running an unsupported installation.
<button
class="link"
title="Show more information about this"
@click=${this._diagnosticsInformationDialog}
title="Learn more about how you can make your system compliant"
@click=${this._unsupportedDialog}
>
Learn more
</button>
</div>
<ha-switch
haptic
.checked=${this.supervisor.supervisor.diagnostics}
@change=${this._toggleDiagnostics}
></ha-switch>
</ha-settings-row>`
: html`<div class="error">
You are running an unsupported installation.
<button
class="link"
title="Learn more about how you can make your system compliant"
@click=${this._unsupportedDialog}
>
Learn more
</button>
</div>`}
${!this.supervisor.supervisor.healthy
? html`<div class="error">
Your installation is running in an unhealthy state.
<button
class="link"
title="Learn more about why your system is marked as unhealthy"
@click=${this._unhealthyDialog}
>
Learn more
</button>
</div>`
: ""}
</div>`}
${!this.supervisor.supervisor.healthy
? html`<div class="error">
Your installation is running in an unhealthy state.
<button
class="link"
title="Learn more about why your system is marked as unhealthy"
@click=${this._unhealthyDialog}
>
Learn more
</button>
</div>`
: ""}
</div>
<div class="metrics-block">
${metrics.map(
(metric) =>
html`
<supervisor-metric
.description=${metric.description}
.value=${metric.value ?? 0}
.tooltip=${metric.tooltip}
></supervisor-metric>
`
)}
</div>
</div>
<div class="card-actions">
<ha-progress-button
@click=${this._supervisorReload}
title="Reload parts of the Supervisor"
>
Reload
Reload Supervisor
</ha-progress-button>
<ha-progress-button
class="warning"
@click=${this._supervisorRestart}
title="Restart the Supervisor"
>
Restart
Restart Supervisor
</ha-progress-button>
</div>
</ha-card>
`;
}
protected firstUpdated(): void {
this._loadData();
}
private async _loadData(): Promise<void> {
this._metrics = await fetchHassioStats(this.hass, "supervisor");
}
private async _toggleBeta(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;
@@ -282,6 +326,18 @@ class HassioSupervisorInfo extends LitElement {
const button = ev.currentTarget as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Restart the Supervisor",
text: "Are you sure you want to restart the Supervisor",
confirmText: "restart",
dismissText: "cancel",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await restartSupervisor(this.hass);
} catch (err) {
@@ -426,6 +482,15 @@ class HassioSupervisorInfo extends LitElement {
justify-content: space-between;
align-items: center;
}
.card-content {
display: flex;
flex-direction: column;
height: calc(100% - 124px);
justify-content: space-between;
}
.metrics-block {
margin-top: 16px;
}
button.link {
color: var(--primary-color);
}

View File

@@ -1,185 +0,0 @@
import "@material/mwc-button";
import "@material/mwc-list/mwc-list-item";
import {
css,
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
TemplateResult,
} from "lit-element";
import { classMap } from "lit-html/directives/class-map";
import memoizeOne from "memoize-one";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-bar";
import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row";
import { fetchHassioStats, HassioStats } from "../../../src/data/hassio/common";
import { HassioHostInfo } from "../../../src/data/hassio/host";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types";
import { bytesToString } from "../../../src/util/bytes-to-string";
import {
getValueInPercentage,
roundWithOneDecimal,
} from "../../../src/util/calculate";
import { hassioStyle } from "../resources/hassio-style";
@customElement("hassio-system-metrics")
class HassioSystemMetrics extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public supervisor!: Supervisor;
@internalProperty() private _supervisorMetrics?: HassioStats;
@internalProperty() private _coreMetrics?: HassioStats;
protected render(): TemplateResult | void {
const metrics = [
{
description: "Core CPU Usage",
value: this._coreMetrics?.cpu_percent,
},
{
description: "Core RAM Usage",
value: this._coreMetrics?.memory_percent,
tooltip: `${bytesToString(
this._coreMetrics?.memory_usage
)}/${bytesToString(this._coreMetrics?.memory_limit)}`,
},
{
description: "Supervisor CPU Usage",
value: this._supervisorMetrics?.cpu_percent,
},
{
description: "Supervisor RAM Usage",
value: this._supervisorMetrics?.memory_percent,
tooltip: `${bytesToString(
this._supervisorMetrics?.memory_usage
)}/${bytesToString(this._supervisorMetrics?.memory_limit)}`,
},
{
description: "Used Space",
value: this._getUsedSpace(this.supervisor.host),
tooltip: `${this.supervisor.host.disk_used} GB/${this.supervisor.host.disk_total} GB`,
},
];
return html`
<ha-card header="System Metrics">
<div class="card-content">
${metrics.map((metric) =>
this._renderMetric(
metric.description,
metric.value ?? 0,
metric.tooltip
)
)}
</div>
</ha-card>
`;
}
protected firstUpdated(): void {
this._loadData();
}
private _renderMetric(
description: string,
value: number,
tooltip?: string
): TemplateResult {
const roundedValue = roundWithOneDecimal(value);
return html`<ha-settings-row>
<span slot="heading">
${description}
</span>
<div slot="description" title="${tooltip ?? ""}">
<span class="value">
${roundedValue}%
</span>
<ha-bar
class="${classMap({
"target-warning": roundedValue > 50,
"target-critical": roundedValue > 85,
})}"
.value=${value}
></ha-bar>
</div>
</ha-settings-row>`;
}
private _getUsedSpace = memoizeOne((hostInfo: HassioHostInfo) =>
roundWithOneDecimal(
getValueInPercentage(hostInfo.disk_used, 0, hostInfo.disk_total)
)
);
private async _loadData(): Promise<void> {
const [supervisor, core] = await Promise.all([
fetchHassioStats(this.hass, "supervisor"),
fetchHassioStats(this.hass, "core"),
]);
this._supervisorMetrics = supervisor;
this._coreMetrics = core;
}
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
ha-card {
height: 100%;
justify-content: space-between;
flex-direction: column;
display: flex;
}
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row > div[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
display: flex;
justify-content: space-between;
}
ha-bar {
--ha-bar-primary-color: var(
--hassio-bar-ok-color,
var(--success-color)
);
}
.target-warning {
--ha-bar-primary-color: var(
--hassio-bar-warning-color,
var(--warning-color)
);
}
.target-critical {
--ha-bar-primary-color: var(
--hassio-bar-critical-color,
var(--error-color)
);
}
.value {
width: 42px;
padding-right: 4px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"hassio-system-metrics": HassioSystemMetrics;
}
}

View File

@@ -13,10 +13,10 @@ import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types";
import { supervisorTabs } from "../hassio-tabs";
import { hassioStyle } from "../resources/hassio-style";
import "./hassio-core-info";
import "./hassio-host-info";
import "./hassio-supervisor-info";
import "./hassio-supervisor-log";
import "./hassio-system-metrics";
@customElement("hassio-system")
class HassioSystem extends LitElement {
@@ -41,6 +41,10 @@ class HassioSystem extends LitElement {
<span slot="header">System</span>
<div class="content">
<div class="card-group">
<hassio-core-info
.hass=${this.hass}
.supervisor=${this.supervisor}
></hassio-core-info>
<hassio-supervisor-info
.hass=${this.hass}
.supervisor=${this.supervisor}
@@ -49,10 +53,6 @@ class HassioSystem extends LitElement {
.hass=${this.hass}
.supervisor=${this.supervisor}
></hassio-host-info>
<hassio-system-metrics
.hass=${this.hass}
.supervisor=${this.supervisor}
></hassio-system-metrics>
</div>
<hassio-supervisor-log .hass=${this.hass}></hassio-supervisor-log>
</div>

View File

@@ -120,7 +120,7 @@
"resize-observer-polyfill": "^1.5.1",
"roboto-fontface": "^0.10.0",
"sortablejs": "^1.10.2",
"superstruct": "^0.10.12",
"superstruct": "^0.10.13",
"tinykeys": "^1.1.1",
"unfetch": "^4.1.0",
"vis-data": "^7.1.1",

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20201229.0",
version="20210127.1",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@@ -3,9 +3,9 @@ import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";

View File

@@ -2,21 +2,25 @@ import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
} from "lit-element";
import punycode from "punycode";
import { extractSearchParamsObject } from "../common/url/search-params";
import {
AuthProvider,
fetchAuthProviders,
AuthUrlSearchParams,
fetchAuthProviders,
} from "../data/auth";
import {
DiscoveryInformation,
fetchDiscoveryInformation,
} from "../data/discovery";
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
import { registerServiceWorker } from "../util/register-service-worker";
import "./ha-auth-flow";
import { extractSearchParamsObject } from "../common/url/search-params";
import punycode from "punycode";
import("./ha-pick-auth-provider");
@@ -31,6 +35,8 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
@internalProperty() private _authProviders?: AuthProvider[];
@internalProperty() private _discovery?: DiscoveryInformation;
constructor() {
super();
this.translationFragment = "page-authorize";
@@ -58,14 +64,17 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
// the name with a bold tag.
const loggingInWith = document.createElement("div");
loggingInWith.innerText = this.localize(
"ui.panel.page-authorize.logging_in_with",
this._discovery?.location_name
? "ui.panel.page-authorize.logging_in_to_with"
: "ui.panel.page-authorize.logging_in_with",
"locationName",
"LOCATION",
"authProviderName",
"NAME"
);
loggingInWith.innerHTML = loggingInWith.innerHTML.replace(
"**NAME**",
`<b>${this._authProvider!.name}</b>`
);
loggingInWith.innerHTML = loggingInWith.innerHTML
.replace("**LOCATION**", `<b>${this._discovery?.location_name}</b>`)
.replace("**NAME**", `<b>${this._authProvider!.name}</b>`);
const inactiveProviders = this._authProviders.filter(
(prv) => prv !== this._authProvider
@@ -105,6 +114,7 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this._fetchAuthProviders();
this._fetchDiscoveryInfo();
if (!this.redirectUri) {
return;
@@ -126,6 +136,10 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
}
}
private async _fetchDiscoveryInfo() {
this._discovery = await fetchDiscoveryInformation();
}
private async _fetchAuthProviders() {
// Fetch auth providers
try {

View File

@@ -1,6 +1,6 @@
import { isComponentLoaded } from "./is_component_loaded";
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
import { HomeAssistant } from "../../types";
import { isComponentLoaded } from "./is_component_loaded";
export const canShowPage = (hass: HomeAssistant, page: PageNavigation) => {
return (

View File

@@ -34,6 +34,7 @@ export const FIXED_DOMAIN_ICONS = {
light: "hass:lightbulb",
mailbox: "hass:mailbox",
notify: "hass:comment-alert",
number: "hass:ray-vertex",
persistent_notification: "hass:bell",
person: "hass:account",
plant: "hass:flower",
@@ -77,6 +78,7 @@ export const DOMAINS_WITH_CARD = [
"input_text",
"lock",
"media_player",
"number",
"scene",
"script",
"timer",
@@ -114,6 +116,7 @@ export const DOMAINS_HIDE_MORE_INFO = [
"input_number",
"input_select",
"input_text",
"number",
"scene",
];
@@ -138,6 +141,9 @@ export const DOMAINS_TOGGLE = new Set([
"humidifier",
]);
/** Domains that have a dynamic entity image / picture. */
export const DOMAINS_WITH_DYNAMIC_PICTURE = new Set(["camera", "media_player"]);
/** Temperature units. */
export const UNIT_C = "°C";
export const UNIT_F = "°F";

View File

@@ -0,0 +1,7 @@
export default function checkValidDate(date?: Date): boolean {
if (!date) {
return false;
}
return date instanceof Date && !isNaN(date.valueOf());
}

View File

@@ -9,3 +9,12 @@ export const formatDate = toLocaleDateStringSupportsOptions
day: "numeric",
})
: (dateObj: Date) => format(dateObj, "longDate");
export const formatDateWeekday = toLocaleDateStringSupportsOptions
? (dateObj: Date, locales: string) =>
dateObj.toLocaleDateString(locales, {
weekday: "long",
month: "short",
day: "numeric",
})
: (dateObj: Date) => format(dateObj, "dddd, MMM D");

View File

@@ -17,3 +17,12 @@ export const formatTimeWithSeconds = toLocaleTimeStringSupportsOptions
second: "2-digit",
})
: (dateObj: Date) => format(dateObj, "mediumTime");
export const formatTimeWeekday = toLocaleTimeStringSupportsOptions
? (dateObj: Date, locales: string) =>
dateObj.toLocaleTimeString(locales, {
weekday: "long",
hour: "numeric",
minute: "2-digit",
})
: (dateObj: Date) => format(dateObj, "dddd, HH:mm");

View File

@@ -3,9 +3,9 @@ import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { formatDate } from "../datetime/format_date";
import { formatDateTime } from "../datetime/format_date_time";
import { formatTime } from "../datetime/format_time";
import { formatNumber } from "../string/format_number";
import { LocalizeFunc } from "../translations/localize";
import { computeStateDomain } from "./compute_state_domain";
import { formatNumber } from "../string/format_number";
export const computeStateDisplay = (
localize: LocalizeFunc,
@@ -63,7 +63,7 @@ export const computeStateDisplay = (
if (domain === "humidifier") {
if (compareState === "on" && stateObj.attributes.humidity) {
return `${stateObj.attributes.humidity}%`;
return `${stateObj.attributes.humidity} %`;
}
}

View File

@@ -1,9 +1,9 @@
import { HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE } from "../../data/entity";
import { HomeAssistant } from "../../types";
import { DOMAINS_WITH_CARD } from "../const";
import { canToggleState } from "./can_toggle_state";
import { computeStateDomain } from "./compute_state_domain";
import { UNAVAILABLE } from "../../data/entity";
export const stateCardType = (hass: HomeAssistant, stateObj: HassEntity) => {
if (stateObj.state === UNAVAILABLE) {

View File

@@ -1,7 +1,7 @@
import Vibrant from "node-vibrant/lib/browser";
import MMCQ from "@vibrant/quantizer-mmcq";
import { BasicPipeline } from "@vibrant/core/lib/pipeline";
import { Swatch, Vec3 } from "@vibrant/color";
// We import the minified bundle because the unminified bundle
// has some quirks that break wds. See #7784 for unminified version.
import Vibrant from "node-vibrant/dist/vibrant";
import type { Swatch, Vec3 } from "@vibrant/color";
import { getRGBContrastRatio } from "../color/rgb";
const CONTRAST_RATIO = 4.5;
@@ -104,23 +104,15 @@ const customGenerator = (colors: Swatch[]) => {
}
return {
foreground: new Swatch(foregroundColor, 0),
// We can't import Swatch constructor from the minified bundle, take it from background color.
// @ts-expect-error
foreground: new backgroundColor.constructor(foregroundColor, 0),
background: backgroundColor,
};
};
Vibrant.use(
new BasicPipeline().filter
.register(
"default",
(r: number, g: number, b: number, a: number) =>
a >= 125 && !(r > 250 && g > 250 && b > 250)
)
.quantizer.register("mmcq", MMCQ)
// Our generator has different output
// @ts-expect-error
.generator.register("default", customGenerator)
);
// Set our custom generator as the default.
Vibrant._pipeline.generator.register("default", customGenerator);
export const extractColors = (url: string, downsampleColors = 16) =>
new Vibrant(url, {

View File

@@ -1,3 +1,5 @@
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMagnify } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import {
css,
@@ -10,8 +12,6 @@ import { html, TemplateResult } from "lit-html";
import { classMap } from "lit-html/directives/class-map";
import "../../components/ha-svg-icon";
import { fireEvent } from "../dom/fire_event";
import { mdiMagnify, mdiClose } from "@mdi/js";
import "@material/mwc-icon-button/mwc-icon-button";
@customElement("search-input")
class SearchInput extends LitElement {

View File

@@ -0,0 +1,45 @@
import { StructError } from "superstruct";
import type { HomeAssistant } from "../../types";
export const handleStructError = (
hass: HomeAssistant,
err: Error
): { warnings: string[]; errors?: string[] } => {
if (!(err instanceof StructError)) {
return { warnings: [err.message], errors: undefined };
}
const errors: string[] = [];
const warnings: string[] = [];
for (const failure of err.failures()) {
if (failure.value === undefined) {
errors.push(
hass.localize(
"ui.errors.config.key_missing",
"key",
failure.path.join(".")
)
);
} else if (failure.type === "never") {
warnings.push(
hass.localize(
"ui.errors.config.key_not_expected",
"key",
failure.path.join(".")
)
);
} else {
warnings.push(
hass.localize(
"ui.errors.config.key_wrong_type",
"key",
failure.path.join("."),
"type_correct",
failure.type,
"type_wrong",
JSON.stringify(failure.value)
)
);
}
}
return { warnings, errors };
};

View File

@@ -1,4 +1,4 @@
import { StructResult, StructContext, struct } from "superstruct";
import { struct, StructContext, StructResult } from "superstruct";
const isEntityId = (value: unknown, context: StructContext): StructResult => {
if (typeof value !== "string") {

View File

@@ -1,4 +1,4 @@
import { StructContext, StructResult, struct } from "superstruct";
import { struct, StructContext, StructResult } from "superstruct";
const isIcon = (value: unknown, context: StructContext): StructResult => {
if (typeof value !== "string") {

View File

@@ -1,5 +1,5 @@
import IntlMessageFormat from "intl-messageformat";
import { shouldPolyfill } from "@formatjs/intl-pluralrules/should-polyfill";
import IntlMessageFormat from "intl-messageformat";
import { Resources } from "../../types";
export type LocalizeFunc = (key: string, ...args: any[]) => string;

View File

@@ -7,10 +7,9 @@ import {
html,
LitElement,
property,
TemplateResult,
query,
TemplateResult,
} from "lit-element";
import "../ha-circular-progress";
@customElement("ha-progress-button")

View File

@@ -1,5 +1,4 @@
import { wrap } from "comlink";
import type { api } from "./sort_filter_worker";
type FilterDataType = api["filterData"];

View File

@@ -1,11 +1,11 @@
// @ts-nocheck
import Vue from "vue";
import wrap from "@vue/web-component-wrapper";
import { customElement } from "lit-element/lib/decorators";
import Vue from "vue";
import DateRangePicker from "vue2-daterange-picker";
import dateRangePickerStyles from "vue2-daterange-picker/dist/vue2-daterange-picker.css";
import { fireEvent } from "../common/dom/fire_event";
import { Constructor } from "../types";
import { customElement } from "lit-element/lib/decorators";
const Component = Vue.extend({
props: {
@@ -210,7 +210,7 @@ class DateRangePickerElement extends WrappedElement {
}
.calendar-table {
padding: 0 !important;
}
}
`;
const shadowRoot = this.shadowRoot!;
shadowRoot.appendChild(style);

View File

@@ -1,5 +1,6 @@
import "@material/mwc-icon-button/mwc-icon-button";
import "@material/mwc-button/mwc-button";
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
@@ -11,9 +12,9 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";
@@ -37,9 +38,8 @@ import {
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
import { PolymerChangedEvent } from "../../polymer-types";
import { HomeAssistant } from "../../types";
import "./ha-devices-picker";
import "../ha-svg-icon";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "./ha-devices-picker";
interface DevicesByArea {
[areaId: string]: AreaDevices;

View File

@@ -6,9 +6,9 @@ import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
internalProperty,
TemplateResult,
} from "lit-element";
import { fireEvent } from "../../common/dom/fire_event";

View File

@@ -1,5 +1,5 @@
import "../ha-svg-icon";
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
@@ -38,7 +38,7 @@ import {
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
import { PolymerChangedEvent } from "../../polymer-types";
import { HomeAssistant } from "../../types";
import { mdiClose, mdiMenuUp, mdiMenuDown } from "@mdi/js";
import "../ha-svg-icon";
interface Device {
name: string;

View File

@@ -1,6 +1,6 @@
import { customElement, html, LitElement, property } from "lit-element";
import { batteryIcon } from "../../common/entity/battery_icon";
import "../ha-icon";
import { customElement, html, property, LitElement } from "lit-element";
@customElement("ha-battery-icon")
export class HaBatteryIcon extends LitElement {

View File

@@ -1,3 +1,4 @@
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
@@ -17,10 +18,9 @@ import {
import { fireEvent } from "../../common/dom/fire_event";
import { PolymerChangedEvent } from "../../polymer-types";
import { HomeAssistant } from "../../types";
import { formatAttributeName } from "../../util/hass-attributes-util";
import "../ha-svg-icon";
import "./state-badge";
import { formatAttributeName } from "../../util/hass-attributes-util";
import "@material/mwc-icon-button/mwc-icon-button";
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;

View File

@@ -1,21 +1,21 @@
import "../ha-icon-button";
import { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResult,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";
import { STATES_OFF } from "../../common/const";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { computeStateName } from "../../common/entity/compute_state_name";
import { UNAVAILABLE_STATES, UNAVAILABLE } from "../../data/entity";
import { UNAVAILABLE, UNAVAILABLE_STATES } from "../../data/entity";
import { forwardHaptic } from "../../data/haptics";
import { HomeAssistant } from "../../types";
import "../ha-icon-button";
import "../ha-switch";
const isOn = (stateObj?: HassEntity) =>

View File

@@ -4,9 +4,9 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
PropertyValues,
TemplateResult,
} from "lit-element";
@@ -18,10 +18,10 @@ import { computeStateName } from "../../common/entity/compute_state_name";
import { domainIcon } from "../../common/entity/domain_icon";
import { stateIcon } from "../../common/entity/state_icon";
import { timerTimeRemaining } from "../../common/entity/timer_time_remaining";
import { formatNumber } from "../../common/string/format_number";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { HomeAssistant } from "../../types";
import "../ha-label-badge";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { formatNumber } from "../../common/string/format_number";
@customElement("ha-state-label-badge")
export class HaStateLabelBadge extends LitElement {

View File

@@ -11,14 +11,11 @@ import {
} from "lit-element";
import { ifDefined } from "lit-html/directives/if-defined";
import { styleMap } from "lit-html/directives/style-map";
import { computeActiveState } from "../../common/entity/compute_active_state";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { stateIcon } from "../../common/entity/state_icon";
import { iconColorCSS } from "../../common/style/icon_color_css";
import type { HomeAssistant } from "../../types";
import "../ha-icon";
export class StateBadge extends LitElement {
@@ -40,7 +37,8 @@ export class StateBadge extends LitElement {
protected render(): TemplateResult {
const stateObj = this.stateObj;
if (!stateObj) {
// We either need a `stateObj` or one override
if (!stateObj && !this.overrideIcon && !this.overrideImage) {
return html`<div class="missing">
<ha-icon icon="hass:alert"></ha-icon>
</div>`;
@@ -50,7 +48,7 @@ export class StateBadge extends LitElement {
return html``;
}
const domain = computeStateDomain(stateObj);
const domain = stateObj ? computeStateDomain(stateObj) : undefined;
return html`
<ha-icon
@@ -60,14 +58,18 @@ export class StateBadge extends LitElement {
? domain
: undefined
)}
data-state=${computeActiveState(stateObj)}
.icon=${this.overrideIcon || stateIcon(stateObj)}
data-state=${stateObj ? computeActiveState(stateObj) : ""}
.icon=${this.overrideIcon || (stateObj ? stateIcon(stateObj) : "")}
></ha-icon>
`;
}
protected updated(changedProps: PropertyValues) {
if (!changedProps.has("stateObj") || !this.stateObj) {
if (
!changedProps.has("stateObj") &&
!changedProps.has("overrideImage") &&
!changedProps.has("overrideIcon")
) {
return;
}
const stateObj = this.stateObj;
@@ -117,7 +119,15 @@ export class StateBadge extends LitElement {
iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`;
}
}
} else if (this.overrideImage) {
let imageUrl = this.overrideImage;
if (this.hass) {
imageUrl = this.hass.hassUrl(imageUrl);
}
hostStyle.backgroundImage = `url(${imageUrl})`;
this._showIcon = false;
}
this._iconStyle = iconStyle;
Object.assign(this.style, hostStyle);
}

View File

@@ -1,4 +1,5 @@
import "@polymer/paper-tooltip/paper-tooltip";
import type { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResult,
@@ -8,12 +9,9 @@ import {
property,
TemplateResult,
} from "lit-element";
import type { HassEntity } from "home-assistant-js-websocket";
import { computeStateName } from "../../common/entity/compute_state_name";
import { computeRTL } from "../../common/util/compute_rtl";
import type { HomeAssistant } from "../../types";
import "../ha-relative-time";
import "./state-badge";
@@ -25,7 +23,7 @@ class StateInfo extends LitElement {
@property({ type: Boolean }) public inDialog = false;
// property used only in css
// property used only in CSS
@property({ type: Boolean, reflect: true }) public rtl = false;
protected render(): TemplateResult {

View File

@@ -1,5 +1,5 @@
import "./ha-svg-icon";
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
@@ -11,27 +11,21 @@ import {
CSSResult,
customElement,
html,
internalProperty,
LitElement,
property,
internalProperty,
TemplateResult,
PropertyValues,
query,
TemplateResult,
} from "lit-element";
import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
import { computeDomain } from "../common/entity/compute_domain";
import {
AreaRegistryEntry,
createAreaRegistryEntry,
subscribeAreaRegistry,
} from "../data/area_registry";
import {
showAlertDialog,
showPromptDialog,
} from "../dialogs/generic/show-dialog-box";
import { SubscribeMixin } from "../mixins/subscribe-mixin";
import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types";
import memoizeOne from "memoize-one";
import {
DeviceEntityLookup,
DeviceRegistryEntry,
@@ -41,9 +35,15 @@ import {
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../data/entity_registry";
import { computeDomain } from "../common/entity/compute_domain";
import {
showAlertDialog,
showPromptDialog,
} from "../dialogs/generic/show-dialog-box";
import { SubscribeMixin } from "../mixins/subscribe-mixin";
import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types";
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "./ha-svg-icon";
const rowRenderer = (
root: HTMLElement,

View File

@@ -12,6 +12,7 @@ import { until } from "lit-html/directives/until";
import hassAttributeUtil, {
formatAttributeName,
} from "../util/hass-attributes-util";
import { haStyle } from "../resources/styles";
let jsYamlPromise: Promise<typeof import("js-yaml")>;
@@ -55,33 +56,36 @@ class HaAttributes extends LitElement {
`;
}
static get styles(): CSSResult {
return css`
.data-entry {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.data-entry .value {
max-width: 60%;
overflow-wrap: break-word;
text-align: right;
}
.key {
flex-grow: 1;
}
.attribution {
color: var(--secondary-text-color);
text-align: center;
}
pre {
font-family: inherit;
font-size: inherit;
margin: 0px;
overflow-wrap: break-word;
white-space: pre-line;
}
`;
static get styles(): CSSResult[] {
return [
haStyle,
css`
.data-entry {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.data-entry .value {
max-width: 60%;
overflow-wrap: break-word;
text-align: right;
}
.key {
flex-grow: 1;
}
.attribution {
color: var(--secondary-text-color);
text-align: center;
}
pre {
font-family: inherit;
font-size: inherit;
margin: 0px;
overflow-wrap: break-word;
white-space: pre-line;
}
`,
];
}
private computeDisplayAttributes(filtersArray: string[]): string[] {
@@ -105,6 +109,7 @@ class HaAttributes extends LitElement {
if (value === null) {
return "-";
}
// YAML handling
if (
(Array.isArray(value) && value.some((val) => val instanceof Object)) ||
(!Array.isArray(value) && value instanceof Object)
@@ -115,6 +120,19 @@ class HaAttributes extends LitElement {
const yaml = jsYamlPromise.then((jsYaml) => jsYaml.safeDump(value));
return html` <pre>${until(yaml, "")}</pre> `;
}
// URL handling
if (typeof value === "string" && value.startsWith("http")) {
try {
// If invalid URL, exception will be raised
const url = new URL(value);
if (url.protocol === "http:" || url.protocol === "https:")
return html`<a target="_blank" rel="noreferrer" href="${value}"
>${value}</a
>`;
} catch (_) {
// Nothing to do here
}
}
return Array.isArray(value) ? value.join(", ") : value;
}
}

View File

@@ -7,7 +7,6 @@ import {
svg,
TemplateResult,
} from "lit-element";
import {
getValueInPercentage,
normalize,

View File

@@ -1,3 +1,4 @@
import "@material/mwc-button/mwc-button";
import "@material/mwc-icon-button/mwc-icon-button";
import {
css,
@@ -11,7 +12,6 @@ import {
import { fireEvent } from "../common/dom/fire_event";
import type { ToggleButton } from "../types";
import "./ha-svg-icon";
import "@material/mwc-button/mwc-button";
@customElement("ha-button-toggle-group")
export class HaButtonToggleGroup extends LitElement {

View File

@@ -12,6 +12,7 @@ import {
import { fireEvent } from "../common/dom/fire_event";
import { computeStateName } from "../common/entity/compute_state_name";
import { supportsFeature } from "../common/entity/supports-feature";
import { isComponentLoaded } from "../common/config/is_component_loaded";
import {
CameraEntity,
CAMERA_SUPPORT_STREAM,
@@ -86,7 +87,7 @@ class HaCameraStream extends LitElement {
private get _shouldRenderMJPEG() {
return (
this._forceMJPEG === this.stateObj!.entity_id ||
!this.hass!.config.components.includes("stream") ||
!isComponentLoaded(this.hass!, "stream") ||
!supportsFeature(this.stateObj!, CAMERA_SUPPORT_STREAM)
);
}

View File

@@ -1,5 +1,5 @@
import { customElement, property } from "lit-element";
import { CircularProgress } from "@material/mwc-circular-progress";
import { customElement, property } from "lit-element";
@customElement("ha-circular-progress")
// @ts-ignore

View File

@@ -1,9 +1,9 @@
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
import "./ha-icon-button";
import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { EventsMixin } from "../mixins/events-mixin";
import "./ha-icon-button";
/*
* @appliesMixin EventsMixin

View File

@@ -1,3 +1,4 @@
import { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResult,
@@ -7,11 +8,9 @@ import {
property,
TemplateResult,
} from "lit-element";
import { HassEntity } from "home-assistant-js-websocket";
import { formatNumber } from "../common/string/format_number";
import { CLIMATE_PRESET_NONE } from "../data/climate";
import type { HomeAssistant } from "../types";
import { formatNumber } from "../common/string/format_number";
@customElement("ha-climate-state")
class HaClimateState extends LitElement {

View File

@@ -131,81 +131,81 @@ export class HaCodeEditor extends UpdatingElement {
.cm-s-default .CodeMirror-cursor {
border-left: 1px solid var(--secondary-text-color);
}
.cm-s-default div.CodeMirror-selected, .cm-s-default.CodeMirror-focused div.CodeMirror-selected {
background: rgba(var(--rgb-primary-color), 0.2);
}
.cm-s-default .CodeMirror-line::selection,
.cm-s-default .CodeMirror-line>span::selection,
.cm-s-default .CodeMirror-line>span>span::selection {
background: rgba(var(--rgb-primary-color), 0.2);
}
.cm-s-default .cm-keyword {
color: var(--codemirror-keyword, #6262FF);
}
.cm-s-default .cm-operator {
color: var(--codemirror-operator, #cda869);
}
.cm-s-default .cm-variable-2 {
color: var(--codemirror-variable-2, #690);
}
.cm-s-default .cm-builtin {
color: var(--codemirror-builtin, #9B7536);
}
.cm-s-default .cm-atom {
color: var(--codemirror-atom, #F90);
}
.cm-s-default .cm-number {
color: var(--codemirror-number, #ca7841);
}
.cm-s-default .cm-def {
color: var(--codemirror-def, #8DA6CE);
}
.cm-s-default .cm-string {
color: var(--codemirror-string, #07a);
}
.cm-s-default .cm-string-2 {
color: var(--codemirror-string-2, #bd6b18);
}
.cm-s-default .cm-comment {
color: var(--codemirror-comment, #777);
}
.cm-s-default .cm-variable {
color: var(--codemirror-variable, #07a);
}
.cm-s-default .cm-tag {
color: var(--codemirror-tag, #997643);
}
.cm-s-default .cm-meta {
color: var(--codemirror-meta, var(--primary-text-color));
}
.cm-s-default .cm-attribute {
color: var(--codemirror-attribute, #d6bb6d);
}
.cm-s-default .cm-property {
color: var(--codemirror-property, #905);
}
.cm-s-default .cm-qualifier {
color: var(--codemirror-qualifier, #690);
}
.cm-s-default .cm-variable-3 {
color: var(--codemirror-variable-3, #07a);
}

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