mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-15 12:19:25 +00:00
Compare commits
469 Commits
20221027.0
...
restructur
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d60639f99d | ||
![]() |
693b621dd5 | ||
![]() |
d96bb9cf20 | ||
![]() |
ec2d498334 | ||
![]() |
c9b1b92e70 | ||
![]() |
a4a2e1b99e | ||
![]() |
b31af60397 | ||
![]() |
01facc2254 | ||
![]() |
8b4587785c | ||
![]() |
89623aa7ec | ||
![]() |
afb9e826ef | ||
![]() |
ac075e44cc | ||
![]() |
fcf6bfc457 | ||
![]() |
3951646c7f | ||
![]() |
be6aabe23e | ||
![]() |
25f7a0602a | ||
![]() |
34ed446cd2 | ||
![]() |
ffd7a0c153 | ||
![]() |
b591c75377 | ||
![]() |
d2886b1ea7 | ||
![]() |
a3ba8210cf | ||
![]() |
d1a04349a4 | ||
![]() |
bb273b2b54 | ||
![]() |
00667f1296 | ||
![]() |
06368a6f0e | ||
![]() |
7c4a421e74 | ||
![]() |
3675a2b013 | ||
![]() |
0bbe6151ed | ||
![]() |
dace00ebf8 | ||
![]() |
a433ac48e9 | ||
![]() |
ddfaa67456 | ||
![]() |
8b4b19cc96 | ||
![]() |
c4183a9edb | ||
![]() |
363ad369fc | ||
![]() |
711286f7c0 | ||
![]() |
78857357f3 | ||
![]() |
3c23e6a1c3 | ||
![]() |
10369ff952 | ||
![]() |
134670604b | ||
![]() |
8935dbac20 | ||
![]() |
ccf15c7fb0 | ||
![]() |
5e4b673751 | ||
![]() |
98e799eda0 | ||
![]() |
5e9ae36577 | ||
![]() |
624bfbbaf1 | ||
![]() |
0e71eec937 | ||
![]() |
38562a42d6 | ||
![]() |
e242fbe148 | ||
![]() |
81e4f083f9 | ||
![]() |
533b4ec0b4 | ||
![]() |
50a4c0f7ce | ||
![]() |
dfee6c9b5b | ||
![]() |
fe2b4d9598 | ||
![]() |
e6dbb1da7e | ||
![]() |
095ebbc903 | ||
![]() |
9dcdf46316 | ||
![]() |
d6e0d57744 | ||
![]() |
38c1112308 | ||
![]() |
88ee409987 | ||
![]() |
8073555bf9 | ||
![]() |
b4cd4975c1 | ||
![]() |
518d4f9c5b | ||
![]() |
f991a1b819 | ||
![]() |
6fc5fd9cc4 | ||
![]() |
d15d339782 | ||
![]() |
1b922e0065 | ||
![]() |
c8883a6a8a | ||
![]() |
e14e27c01a | ||
![]() |
f101bd1a54 | ||
![]() |
3e14d825e3 | ||
![]() |
f34d9c3d75 | ||
![]() |
2b2dd74672 | ||
![]() |
815d4c165d | ||
![]() |
fd22afedd0 | ||
![]() |
522c7c08a9 | ||
![]() |
dc140f132d | ||
![]() |
4c76a2549b | ||
![]() |
a5c77928d2 | ||
![]() |
d3e20429a4 | ||
![]() |
2f1d783d22 | ||
![]() |
558f523207 | ||
![]() |
c7f4693f0a | ||
![]() |
282823ee83 | ||
![]() |
014ae06e85 | ||
![]() |
9e5442db18 | ||
![]() |
789a69fea5 | ||
![]() |
c7da1a95da | ||
![]() |
6d527d5ebe | ||
![]() |
9d529d8f13 | ||
![]() |
468aeda74a | ||
![]() |
f6a508683c | ||
![]() |
64fabbbf05 | ||
![]() |
9b95814f1b | ||
![]() |
2f2cde328c | ||
![]() |
8294e0e271 | ||
![]() |
f09859ab40 | ||
![]() |
e206e86fb3 | ||
![]() |
21f3eb9103 | ||
![]() |
932614e31a | ||
![]() |
1d20d6979e | ||
![]() |
207380d0da | ||
![]() |
d2c091536e | ||
![]() |
2eb5335a68 | ||
![]() |
1aa23d75b0 | ||
![]() |
663b6e0682 | ||
![]() |
c7f3293c1d | ||
![]() |
c63b64cff5 | ||
![]() |
7136142437 | ||
![]() |
af9a8fa3e7 | ||
![]() |
b74a2fd277 | ||
![]() |
e5350a4246 | ||
![]() |
9e5a59fbc4 | ||
![]() |
24e6b8483e | ||
![]() |
604c452ff4 | ||
![]() |
ba9551b61e | ||
![]() |
135af5bcaa | ||
![]() |
747f47524e | ||
![]() |
36b959dbc4 | ||
![]() |
1d15f81b6c | ||
![]() |
45e7f8ae06 | ||
![]() |
dcedafaef4 | ||
![]() |
8fac5f6d75 | ||
![]() |
5094e8f428 | ||
![]() |
74fb8b0427 | ||
![]() |
78768b1e2f | ||
![]() |
d55307098a | ||
![]() |
7286aa7dc4 | ||
![]() |
b44b22c723 | ||
![]() |
dcee89caeb | ||
![]() |
d1caeed05e | ||
![]() |
f2a67a5fa9 | ||
![]() |
b2d5304488 | ||
![]() |
e9aded77da | ||
![]() |
e1a94c679f | ||
![]() |
616bced37c | ||
![]() |
1585c6bf52 | ||
![]() |
caa852559f | ||
![]() |
f2fa433326 | ||
![]() |
dd109b0054 | ||
![]() |
9750e0e0b5 | ||
![]() |
b36eba0916 | ||
![]() |
18a69d633f | ||
![]() |
bf6ad3d0a5 | ||
![]() |
9836912efa | ||
![]() |
f31a7c3af0 | ||
![]() |
ebb19e4ed5 | ||
![]() |
44d91eaa4f | ||
![]() |
3cc1cb7893 | ||
![]() |
e7354ed5a2 | ||
![]() |
e3ac2c149d | ||
![]() |
afcd45a780 | ||
![]() |
fe87466351 | ||
![]() |
bdef924426 | ||
![]() |
86ea3082f7 | ||
![]() |
0374330676 | ||
![]() |
7cde3b66dd | ||
![]() |
d8a68326fb | ||
![]() |
4901d50918 | ||
![]() |
a16e41a7ac | ||
![]() |
f1d644ac51 | ||
![]() |
a9378abe31 | ||
![]() |
5c2fcd7f9b | ||
![]() |
2b8f7c46ff | ||
![]() |
0015559e24 | ||
![]() |
2fbe6809c1 | ||
![]() |
e926091e54 | ||
![]() |
1198f983aa | ||
![]() |
6a15216104 | ||
![]() |
b99a139f51 | ||
![]() |
0e9a013549 | ||
![]() |
1d1ff410b2 | ||
![]() |
d4d3a1cb65 | ||
![]() |
81e3652446 | ||
![]() |
adb61ab99b | ||
![]() |
1c139d0bc7 | ||
![]() |
419f23879a | ||
![]() |
e175c7ba3c | ||
![]() |
2575d35f2c | ||
![]() |
5eb45209e8 | ||
![]() |
0e70b866ae | ||
![]() |
c6aa2886ed | ||
![]() |
77e01812d1 | ||
![]() |
a5863a9a67 | ||
![]() |
526c34993c | ||
![]() |
3199319830 | ||
![]() |
6bb350b5ec | ||
![]() |
f41330a29b | ||
![]() |
7780ae8f76 | ||
![]() |
40cf15c1f3 | ||
![]() |
9be6a47d88 | ||
![]() |
5933c2eb8e | ||
![]() |
a8b7937d75 | ||
![]() |
4919341871 | ||
![]() |
36e99c3c0f | ||
![]() |
825008e24a | ||
![]() |
ae04a5457e | ||
![]() |
a7c3774c29 | ||
![]() |
9c24dbe333 | ||
![]() |
50f089fd4f | ||
![]() |
019ef4ba8f | ||
![]() |
b31a9d590e | ||
![]() |
43ea175a1a | ||
![]() |
b2f0b6a814 | ||
![]() |
614496d65c | ||
![]() |
d121c1cd18 | ||
![]() |
b18160d987 | ||
![]() |
5b17c59a56 | ||
![]() |
139cbb363c | ||
![]() |
e8e4733fc9 | ||
![]() |
b4d6fc3c20 | ||
![]() |
25a5bd568a | ||
![]() |
77b8152c55 | ||
![]() |
ebcbfda92d | ||
![]() |
01a4b55ed8 | ||
![]() |
311d11f2da | ||
![]() |
c400e771cb | ||
![]() |
7611a99f55 | ||
![]() |
1044b3c399 | ||
![]() |
239d3ca00c | ||
![]() |
00c2cb731b | ||
![]() |
ef7d839c0f | ||
![]() |
66a22ae102 | ||
![]() |
d48853fcdd | ||
![]() |
175a388822 | ||
![]() |
872395bec5 | ||
![]() |
5faf7cf0af | ||
![]() |
e768c78dce | ||
![]() |
50cc8594be | ||
![]() |
363092ff03 | ||
![]() |
1bce5efc9e | ||
![]() |
14513e5905 | ||
![]() |
b168f8d027 | ||
![]() |
e151520d74 | ||
![]() |
02b763e8f3 | ||
![]() |
498102ddd9 | ||
![]() |
6aba5c1017 | ||
![]() |
2176d4dcea | ||
![]() |
9fdef3df6d | ||
![]() |
d8b4611c24 | ||
![]() |
9c27bb37a0 | ||
![]() |
f2b7288e92 | ||
![]() |
f7aecb0d6d | ||
![]() |
1da8a974f8 | ||
![]() |
b82d6fd35f | ||
![]() |
62bc171b8c | ||
![]() |
2d7973af79 | ||
![]() |
d64bb98bb4 | ||
![]() |
5cabf1d041 | ||
![]() |
180357e0db | ||
![]() |
c1dba217da | ||
![]() |
8d1ecdb27e | ||
![]() |
f83544dd38 | ||
![]() |
2ae137bbc2 | ||
![]() |
9f8aa0b4bf | ||
![]() |
149fa5fca6 | ||
![]() |
0fb35fd0d0 | ||
![]() |
544272b4df | ||
![]() |
b939978de1 | ||
![]() |
d74fb8717c | ||
![]() |
f204a163d4 | ||
![]() |
bc9fb9a472 | ||
![]() |
1e654d9661 | ||
![]() |
03d33759b8 | ||
![]() |
ef7d696f9d | ||
![]() |
545141da92 | ||
![]() |
467957005d | ||
![]() |
348c3c9787 | ||
![]() |
fe0492c2e0 | ||
![]() |
0b377c060c | ||
![]() |
0f971e5868 | ||
![]() |
1dbe8c9b64 | ||
![]() |
6e4a6cb0db | ||
![]() |
3f1903bd87 | ||
![]() |
9643e0268f | ||
![]() |
23573d8c26 | ||
![]() |
3c8c1260b1 | ||
![]() |
b84de87688 | ||
![]() |
2d30994e56 | ||
![]() |
4ea19a6041 | ||
![]() |
af82c0d0c4 | ||
![]() |
2b5ef1207c | ||
![]() |
feddbdba96 | ||
![]() |
b581b95d9d | ||
![]() |
8c69c772d1 | ||
![]() |
ba09120ff3 | ||
![]() |
a8d242719f | ||
![]() |
0d0028fced | ||
![]() |
d1b1eecd92 | ||
![]() |
3b51050b52 | ||
![]() |
34e1d745be | ||
![]() |
efda2ab626 | ||
![]() |
ae354fa8da | ||
![]() |
ef130be352 | ||
![]() |
f1393e5f00 | ||
![]() |
dac784553e | ||
![]() |
d2ad67384f | ||
![]() |
69d16ab9b4 | ||
![]() |
a941ed4f90 | ||
![]() |
774259224b | ||
![]() |
8a5f781ca2 | ||
![]() |
dacef605c7 | ||
![]() |
2c279e2dec | ||
![]() |
06ee08db36 | ||
![]() |
34dfaa5a0f | ||
![]() |
b06db26540 | ||
![]() |
076a6c4459 | ||
![]() |
0001cad423 | ||
![]() |
d622d9d420 | ||
![]() |
228fd4b7fe | ||
![]() |
e6f2e8058b | ||
![]() |
83ba594cc4 | ||
![]() |
ff64dc2631 | ||
![]() |
745753c526 | ||
![]() |
f5385ba277 | ||
![]() |
1a69503eab | ||
![]() |
8ba46f7f57 | ||
![]() |
bbdb84482a | ||
![]() |
08ffe375b9 | ||
![]() |
8699f3e3a8 | ||
![]() |
ecdd07ff4d | ||
![]() |
f0f699a37e | ||
![]() |
75b1b1c9a0 | ||
![]() |
0ae8246d8a | ||
![]() |
b644407260 | ||
![]() |
b389127f78 | ||
![]() |
20dff9d25d | ||
![]() |
076ddb71b6 | ||
![]() |
f0127511b0 | ||
![]() |
07ad429f8c | ||
![]() |
ef3caf91f1 | ||
![]() |
4fcfcbeefb | ||
![]() |
f18997c7c3 | ||
![]() |
2ed8a4053b | ||
![]() |
1105c92569 | ||
![]() |
76a682fa28 | ||
![]() |
d059b97a2f | ||
![]() |
96080f3c78 | ||
![]() |
00274ebf66 | ||
![]() |
7e58bd59c3 | ||
![]() |
04ef783f5b | ||
![]() |
340449d064 | ||
![]() |
24f2ad8be9 | ||
![]() |
3eac53e209 | ||
![]() |
65cef9d996 | ||
![]() |
4c5f4508b2 | ||
![]() |
1aa6bd5577 | ||
![]() |
3dfd401036 | ||
![]() |
71a5d8c6f9 | ||
![]() |
a0bf582cc9 | ||
![]() |
77a53ffc6c | ||
![]() |
b6f1d78b7f | ||
![]() |
1fda303b23 | ||
![]() |
241645fe8d | ||
![]() |
faa57e4c02 | ||
![]() |
915563ce6c | ||
![]() |
44502d2c8d | ||
![]() |
b97a9ef311 | ||
![]() |
1a66b8a374 | ||
![]() |
4190ff5a2b | ||
![]() |
dfc461ce05 | ||
![]() |
dff7f653b1 | ||
![]() |
eccc6a8cdb | ||
![]() |
52235c6187 | ||
![]() |
594b402bd5 | ||
![]() |
684f6db4df | ||
![]() |
883e5e3a6c | ||
![]() |
29452841c2 | ||
![]() |
9b6e33cfec | ||
![]() |
e43f3b193e | ||
![]() |
40d0455936 | ||
![]() |
90a7c2d2ff | ||
![]() |
d4cda0c106 | ||
![]() |
92d022747b | ||
![]() |
ee6f97b802 | ||
![]() |
cb97918005 | ||
![]() |
f1f0baf787 | ||
![]() |
c0240eed67 | ||
![]() |
aeeacc6cad | ||
![]() |
fcfdad3d94 | ||
![]() |
566b93ec1f | ||
![]() |
5c452cb9e0 | ||
![]() |
06c1d9f6ef | ||
![]() |
bfd96944f9 | ||
![]() |
c119163422 | ||
![]() |
4846fa1a74 | ||
![]() |
aec0eb3c78 | ||
![]() |
92e7254c54 | ||
![]() |
bafe581562 | ||
![]() |
e6a153a802 | ||
![]() |
fce87ff0fe | ||
![]() |
e6b3475b5b | ||
![]() |
f969299567 | ||
![]() |
7a87dc4d8a | ||
![]() |
d6fa1427f1 | ||
![]() |
aa1e9cedca | ||
![]() |
147b1f34ac | ||
![]() |
0cfba81eae | ||
![]() |
a9d44fcb61 | ||
![]() |
0aa2c9044a | ||
![]() |
9bae4a646d | ||
![]() |
15a0847db8 | ||
![]() |
8b817b35b0 | ||
![]() |
f95a3c75f6 | ||
![]() |
2223ffd7ee | ||
![]() |
590ad5b8a0 | ||
![]() |
2bb9961fc2 | ||
![]() |
3e2fb09251 | ||
![]() |
fc80daa3e0 | ||
![]() |
2aa7b95a5a | ||
![]() |
c2436fb157 | ||
![]() |
a958c6296b | ||
![]() |
fe4191aea9 | ||
![]() |
49d9cf41fe | ||
![]() |
0bfb2b4a56 | ||
![]() |
1a68a2f4d7 | ||
![]() |
1197e5a35b | ||
![]() |
c6386284d1 | ||
![]() |
185d2f1d52 | ||
![]() |
c5ec1797f6 | ||
![]() |
048b345c75 | ||
![]() |
70868da305 | ||
![]() |
cef3dbfdf0 | ||
![]() |
bda5b97c91 | ||
![]() |
ae15dd678b | ||
![]() |
681c745e84 | ||
![]() |
23b59978ab | ||
![]() |
90b9eaeb19 | ||
![]() |
65426bd2d0 | ||
![]() |
1cb44ce857 | ||
![]() |
1c03dc9b77 | ||
![]() |
238e844068 | ||
![]() |
ec6a4b4e7a | ||
![]() |
ac65882fdd | ||
![]() |
c92e6423e8 | ||
![]() |
db0d24c807 | ||
![]() |
9e56ddcc69 | ||
![]() |
dd4c3c28ee | ||
![]() |
245202c125 | ||
![]() |
8b8a85b4b8 | ||
![]() |
0aae285236 | ||
![]() |
31ac274a51 | ||
![]() |
6f07e7ca59 | ||
![]() |
fa506202ac | ||
![]() |
c810c67a53 | ||
![]() |
663c58512d | ||
![]() |
3cd64675df | ||
![]() |
79c8b7dc27 | ||
![]() |
98a32041d4 | ||
![]() |
ffbcb0a343 | ||
![]() |
ab4dd47e51 | ||
![]() |
c7cb8cf762 | ||
![]() |
a5ab4eaf0e | ||
![]() |
d52dbde909 | ||
![]() |
1cde9e882e | ||
![]() |
8cb0d38d78 | ||
![]() |
9cb168c439 | ||
![]() |
2add29c4eb | ||
![]() |
e2104c1591 | ||
![]() |
17ac81a708 | ||
![]() |
42386c7dee | ||
![]() |
2e988bf5c3 | ||
![]() |
3356d559c9 | ||
![]() |
43755deb39 | ||
![]() |
9778c0731c | ||
![]() |
ebc0edac10 | ||
![]() |
effc9467c2 | ||
![]() |
68e94d7222 | ||
![]() |
c4992c477b | ||
![]() |
449c1f2469 |
50
.devcontainer.json
Normal file
50
.devcontainer.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "Home Assistant Frontend",
|
||||||
|
"image": "mcr.microsoft.com/devcontainers/python:0-3.10",
|
||||||
|
"appPort": "8124:8123",
|
||||||
|
"postCreateCommand": "script/bootstrap",
|
||||||
|
"containerEnv": {
|
||||||
|
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}",
|
||||||
|
"DEVCONTAINER": "true"
|
||||||
|
},
|
||||||
|
"remoteUser": "vscode",
|
||||||
|
"remoteEnv": {
|
||||||
|
"PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/node_modules/.bin:/home/vscode/.local/bin"
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
|
"version": "16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"runem.lit-plugin",
|
||||||
|
"github.vscode-pull-request-github",
|
||||||
|
"eamodio.gitlens"
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"files.eol": "\n",
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.formatOnPaste": false,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.formatOnType": true,
|
||||||
|
"editor.renderWhitespace": "boundary",
|
||||||
|
"editor.rulers": [80],
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"terminal.integrated.shell.linux": "/usr/bin/zsh",
|
||||||
|
"gitlens.showWelcomeOnInstall": false,
|
||||||
|
"gitlens.showWhatsNewAfterUpgrades": false,
|
||||||
|
"workbench.startupEditor": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +0,0 @@
|
|||||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.148.1/containers/python-3/.devcontainer/base.Dockerfile
|
|
||||||
FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.9
|
|
||||||
|
|
||||||
ENV \
|
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
|
||||||
DEVCONTAINER=true \
|
|
||||||
PATH=$PATH:./node_modules/.bin
|
|
||||||
|
|
||||||
# Install nvm
|
|
||||||
COPY .nvmrc /tmp/.nvmrc
|
|
||||||
RUN \
|
|
||||||
su vscode -c \
|
|
||||||
"source /usr/local/share/nvm/nvm.sh && nvm install $(cat /tmp/.nvmrc) 2>&1"
|
|
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Home Assistant Frontend",
|
|
||||||
"build": {
|
|
||||||
"dockerfile": "Dockerfile",
|
|
||||||
"context": ".."
|
|
||||||
},
|
|
||||||
"appPort": "8124:8123",
|
|
||||||
"context": "..",
|
|
||||||
"postCreateCommand": "script/bootstrap",
|
|
||||||
"extensions": [
|
|
||||||
"github.vscode-pull-request-github",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"bierner.lit-html",
|
|
||||||
"runem.lit-plugin",
|
|
||||||
"ms-python.vscode-pylance"
|
|
||||||
],
|
|
||||||
"containerEnv": {
|
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"terminal.integrated.shell.linux": "/bin/bash",
|
|
||||||
"files.eol": "\n",
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.formatOnPaste": false,
|
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"editor.formatOnType": true,
|
|
||||||
"[typescript]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"[javascript]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
||||||
},
|
|
||||||
"files.trimTrailingWhitespace": true
|
|
||||||
}
|
|
||||||
}
|
|
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@@ -6,3 +6,13 @@ updates:
|
|||||||
interval: weekly
|
interval: weekly
|
||||||
time: "06:00"
|
time: "06:00"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
time: "06:00"
|
||||||
|
open-pull-requests-limit: 5
|
||||||
|
ignore:
|
||||||
|
# Ignore rollup and plugins until everything else is updated
|
||||||
|
- dependency-name: "*rollup*"
|
||||||
|
- dependency-name: "@rollup/*"
|
||||||
|
90
.github/workflows/cast_deployment.yaml
vendored
Normal file
90
.github/workflows/cast_deployment.yaml
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
name: Cast deployment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy_dev:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Deploy Development
|
||||||
|
if: github.event_name != 'push'
|
||||||
|
environment:
|
||||||
|
name: Cast Development
|
||||||
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
with:
|
||||||
|
ref: dev
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Cast
|
||||||
|
run: ./node_modules/.bin/gulp build-cast
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=cast/dist --alias dev
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_CAST_SITE_ID }}
|
||||||
|
|
||||||
|
deploy_master:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Deploy Production
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
environment:
|
||||||
|
name: Cast Production
|
||||||
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
with:
|
||||||
|
ref: master
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Cast
|
||||||
|
run: ./node_modules/.bin/gulp build-cast
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=cast/dist --prod
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_CAST_SITE_ID }}
|
17
.github/workflows/ci.yaml
vendored
17
.github/workflows/ci.yaml
vendored
@@ -13,15 +13,16 @@ on:
|
|||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
NODE_VERSION: 16
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -43,9 +44,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -62,9 +63,9 @@ jobs:
|
|||||||
needs: [lint, test]
|
needs: [lint, test]
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -81,9 +82,9 @@ jobs:
|
|||||||
needs: [lint, test]
|
needs: [lint, test]
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head.
|
# a pull request then we can checkout the head.
|
||||||
|
33
.github/workflows/demo.yaml
vendored
33
.github/workflows/demo.yaml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: Demo
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out files from GitHub
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
cache: yarn
|
|
||||||
- name: Install dependencies
|
|
||||||
run: yarn install
|
|
||||||
env:
|
|
||||||
CI: true
|
|
||||||
- name: Build Demo
|
|
||||||
run: ./node_modules/.bin/gulp build-demo
|
|
||||||
- name: Deploy to Netlify
|
|
||||||
run: npx netlify-cli deploy --dir=demo/dist --prod
|
|
||||||
env:
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DEMO_DEV_SITE_ID }}
|
|
91
.github/workflows/demo_deployment.yaml
vendored
Normal file
91
.github/workflows/demo_deployment.yaml
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
name: Demo deployment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- master
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy_dev:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Demo Development
|
||||||
|
if: github.event_name != 'push' || github.ref != 'master'
|
||||||
|
environment:
|
||||||
|
name: Demo Development
|
||||||
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
with:
|
||||||
|
ref: dev
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Demo
|
||||||
|
run: ./node_modules/.bin/gulp build-demo
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=demo/dist --prod
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DEMO_DEV_SITE_ID }}
|
||||||
|
|
||||||
|
deploy_master:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Demo Production
|
||||||
|
if: github.event_name == 'push' && github.ref == 'master'
|
||||||
|
environment:
|
||||||
|
name: Demo Production
|
||||||
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
with:
|
||||||
|
ref: master
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Demo
|
||||||
|
run: ./node_modules/.bin/gulp build-demo
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=demo/dist --prod
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DEMO_SITE_ID }}
|
45
.github/workflows/design_deployment.yaml
vendored
Normal file
45
.github/workflows/design_deployment.yaml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Design deployment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: Design
|
||||||
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Gallery
|
||||||
|
run: ./node_modules/.bin/gulp build-gallery
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=gallery/dist --prod
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_GALLERY_SITE_ID }}
|
54
.github/workflows/design_preview.yaml
vendored
Normal file
54
.github/workflows/design_preview.yaml
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
name: Design preview
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
- labeled
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
preview:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Skip running on forks since it won't have access to secrets
|
||||||
|
# Skip running PRs without 'needs design preview' label
|
||||||
|
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
||||||
|
steps:
|
||||||
|
- name: Check out files from GitHub
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
|
uses: actions/setup-node@v3.6.0
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
- name: Build Gallery
|
||||||
|
run: ./node_modules/.bin/gulp build-gallery
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Deploy preview to Netlify
|
||||||
|
id: deploy
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
with:
|
||||||
|
args: deploy --dir=gallery/dist --alias "deploy-preview-${{ github.event.number }}"
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_GALLERY_SITE_ID }}
|
||||||
|
|
||||||
|
- name: Generate summary
|
||||||
|
run: |
|
||||||
|
echo "${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}" >> "$GITHUB_STEP_SUMMARY"
|
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
lock:
|
lock:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v3.0.0
|
- uses: dessant/lock-threads@v4.0.0
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
issue-lock-inactive-days: "30"
|
issue-lock-inactive-days: "30"
|
||||||
|
19
.github/workflows/netflify.yml
vendored
19
.github/workflows/netflify.yml
vendored
@@ -1,19 +0,0 @@
|
|||||||
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 Design build
|
|
||||||
run: curl -X POST -d "NIGHTLY" https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }}
|
|
7
.github/workflows/nightly.yaml
vendored
7
.github/workflows/nightly.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -49,9 +49,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pip install build
|
pip install build
|
||||||
yarn install
|
yarn install
|
||||||
|
export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1
|
||||||
script/build_frontend
|
script/build_frontend
|
||||||
|
|
||||||
rm -rf dist home_assistant_frontend.egg-info
|
rm -rf dist home_assistant_frontend.egg-info
|
||||||
python3 -m build
|
python3 -m build
|
||||||
|
|
||||||
|
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
contents: write # Required to upload release assets
|
contents: write # Required to upload release assets
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
- name: Verify version
|
- name: Verify version
|
||||||
uses: home-assistant/actions/helpers/verify-version@master
|
uses: home-assistant/actions/helpers/verify-version@master
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Set up Node ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -52,11 +52,11 @@ jobs:
|
|||||||
python3 -m pip install twine build
|
python3 -m pip install twine build
|
||||||
export TWINE_USERNAME="__token__"
|
export TWINE_USERNAME="__token__"
|
||||||
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
|
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
|
||||||
|
export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1
|
||||||
script/release
|
script/release
|
||||||
|
|
||||||
- name: Upload release assets
|
- name: Upload release assets
|
||||||
uses: softprops/action-gh-release@v0.1.14
|
uses: softprops/action-gh-release@v0.1.15
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
dist/*.whl
|
dist/*.whl
|
||||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 90 days stale policy
|
- name: 90 days stale policy
|
||||||
uses: actions/stale@v6.0.1
|
uses: actions/stale@v7.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 90
|
days-before-stale: 90
|
||||||
|
2
.github/workflows/translations.yaml
vendored
2
.github/workflows/translations.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
- name: Upload Translations
|
- name: Upload Translations
|
||||||
run: |
|
run: |
|
||||||
|
13
.gitignore
vendored
13
.gitignore
vendored
@@ -2,9 +2,10 @@
|
|||||||
.reify-cache
|
.reify-cache
|
||||||
|
|
||||||
# build
|
# build
|
||||||
build
|
build/
|
||||||
hass_frontend/*
|
dist/
|
||||||
dist
|
/hass_frontend/
|
||||||
|
/translations/
|
||||||
|
|
||||||
# yarn
|
# yarn
|
||||||
.yarn/*
|
.yarn/*
|
||||||
@@ -14,7 +15,7 @@ dist
|
|||||||
!.yarn/sdks
|
!.yarn/sdks
|
||||||
!.yarn/versions
|
!.yarn/versions
|
||||||
.pnp.*
|
.pnp.*
|
||||||
node_modules/*
|
/node_modules/
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ npm-debug.log
|
|||||||
# venv stuff
|
# venv stuff
|
||||||
pyvenv.cfg
|
pyvenv.cfg
|
||||||
pip-selfcheck.json
|
pip-selfcheck.json
|
||||||
venv/*
|
/venv/
|
||||||
.venv
|
.venv
|
||||||
|
|
||||||
# vscode
|
# vscode
|
||||||
@@ -45,4 +46,4 @@ src/cast/dev_const.ts
|
|||||||
.tool-versions
|
.tool-versions
|
||||||
|
|
||||||
# Home Assistant config
|
# Home Assistant config
|
||||||
/config
|
/config/
|
||||||
|
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
@@ -2,7 +2,8 @@
|
|||||||
"recommendations": [
|
"recommendations": [
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"bierner.lit-html",
|
"runem.lit-plugin",
|
||||||
"runem.lit-plugin"
|
"github.vscode-pull-request-github",
|
||||||
|
"eamodio.gitlens"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
8
.vscode/tasks.json
vendored
8
.vscode/tasks.json
vendored
@@ -191,7 +191,13 @@
|
|||||||
"runOptions": {
|
"runOptions": {
|
||||||
"instanceLimit": 1
|
"instanceLimit": 1
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"label": "Setup and fetch nightly translations",
|
||||||
|
"type": "gulp",
|
||||||
|
"task": "setup-and-fetch-nightly-translations",
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
diff --git a/polyfillLoaders/EventTarget.js b/polyfillLoaders/EventTarget.js
|
|
||||||
index 4e18ade7ba485849f17f28c94c42f0e0e01ac387..8f34f4f646c7f7becc208fb5a546c96034fc74dc 100644
|
|
||||||
--- a/polyfillLoaders/EventTarget.js
|
|
||||||
+++ b/polyfillLoaders/EventTarget.js
|
|
||||||
@@ -6,16 +6,15 @@
|
|
||||||
let _ET;
|
|
||||||
let ET;
|
|
||||||
export default async function EventTarget() {
|
|
||||||
- return ET || init();
|
|
||||||
+ return ET || init();
|
|
||||||
}
|
|
||||||
async function init() {
|
|
||||||
- _ET = window.EventTarget;
|
|
||||||
- try {
|
|
||||||
- new _ET();
|
|
||||||
- }
|
|
||||||
- catch (_a) {
|
|
||||||
- _ET = (await import('event-target-shim')).EventTarget;
|
|
||||||
- }
|
|
||||||
- return (ET = _ET);
|
|
||||||
+ _ET = window.EventTarget;
|
|
||||||
+ try {
|
|
||||||
+ new _ET();
|
|
||||||
+ } catch (_a) {
|
|
||||||
+ _ET = (await import("event-target-shim")).default.EventTarget;
|
|
||||||
+ }
|
|
||||||
+ return (ET = _ET);
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=EventTarget.js.map
|
|
@@ -1,12 +0,0 @@
|
|||||||
diff --git a/mwc-icon-button-base.js b/mwc-icon-button-base.js
|
|
||||||
index 45cdaab93ccc0a6daaaaabc01266dcdc32e46bfd..b3ea5b541597308d85f86ce6c23fd00785fda835 100644
|
|
||||||
--- a/mwc-icon-button-base.js
|
|
||||||
+++ b/mwc-icon-button-base.js
|
|
||||||
@@ -63,7 +63,6 @@ export class IconButtonBase extends LitElement {
|
|
||||||
@touchend="${this.handleRippleDeactivate}"
|
|
||||||
@touchcancel="${this.handleRippleDeactivate}"
|
|
||||||
>${this.renderRipple()}
|
|
||||||
- <i class="material-icons">${this.icon}</i>
|
|
||||||
<span
|
|
||||||
><slot></slot
|
|
||||||
></span>
|
|
566
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
566
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
File diff suppressed because one or more lines are too long
5
.yarn/plugins/@yarnpkg/plugin-typescript.cjs
vendored
5
.yarn/plugins/@yarnpkg/plugin-typescript.cjs
vendored
File diff suppressed because one or more lines are too long
783
.yarn/releases/yarn-3.2.3.cjs
vendored
783
.yarn/releases/yarn-3.2.3.cjs
vendored
File diff suppressed because one or more lines are too long
823
.yarn/releases/yarn-3.3.1.cjs
vendored
Executable file
823
.yarn/releases/yarn-3.3.1.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
@@ -6,4 +6,4 @@ plugins:
|
|||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
spec: "@yarnpkg/plugin-interactive-tools"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.2.3.cjs
|
yarnPath: .yarn/releases/yarn-3.3.1.cjs
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"rules": {
|
|
||||||
"import/no-extraneous-dependencies": 0,
|
|
||||||
"no-restricted-syntax": 0,
|
|
||||||
"no-console": 0
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +1,12 @@
|
|||||||
{
|
{
|
||||||
"extends": "../.eslintrc.json",
|
"extends": "../.eslintrc.json",
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/no-extraneous-dependencies": 0,
|
"no-console": "off",
|
||||||
"global-require": 0
|
"import/no-extraneous-dependencies": "off",
|
||||||
|
"import/extensions": "off",
|
||||||
|
"import/no-dynamic-require": "off",
|
||||||
|
"global-require": "off",
|
||||||
|
"@typescript-eslint/no-var-requires": "off",
|
||||||
|
"prefer-arrow-callback": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
// Currently only supports CommonJS modules, as require is synchronous. `import` would need babel running asynchronous.
|
// Currently only supports CommonJS modules, as require is synchronous. `import` would need babel running asynchronous.
|
||||||
@@ -29,7 +28,6 @@ module.exports = function inlineConstants(babel, options, cwd) {
|
|||||||
const absolute = module.startsWith(".")
|
const absolute = module.startsWith(".")
|
||||||
? require.resolve(module, { paths: [cwd] })
|
? require.resolve(module, { paths: [cwd] })
|
||||||
: module;
|
: module;
|
||||||
// eslint-disable-next-line import/no-dynamic-require
|
|
||||||
return [absolute, require(absolute)];
|
return [absolute, require(absolute)];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const env = require("./env.js");
|
const env = require("./env.js");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
|
|
||||||
// Files from NPM Packages that should not be imported
|
// Files from NPM Packages that should not be imported
|
||||||
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||||
module.exports.ignorePackages = ({ latestBuild }) => [
|
module.exports.ignorePackages = ({ latestBuild }) => [
|
||||||
// Part of yaml.js and only used for !!js functions that we don't use
|
// Part of yaml.js and only used for !!js functions that we don't use
|
||||||
require.resolve("esprima"),
|
require.resolve("esprima"),
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
|
@@ -1,36 +1,40 @@
|
|||||||
const del = require("del");
|
const del = import("del");
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const paths = require("../paths");
|
const paths = require("../paths");
|
||||||
require("./translations");
|
require("./translations");
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean",
|
"clean",
|
||||||
gulp.parallel("clean-translations", () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
del([paths.app_output_root, paths.build_dir])
|
(await del).deleteSync([paths.app_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-demo",
|
"clean-demo",
|
||||||
gulp.parallel("clean-translations", () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
del([paths.demo_output_root, paths.build_dir])
|
(await del).deleteSync([paths.demo_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-cast",
|
"clean-cast",
|
||||||
gulp.parallel("clean-translations", () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
del([paths.cast_output_root, paths.build_dir])
|
(await del).deleteSync([paths.cast_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("clean-hassio", () =>
|
gulp.task("clean-hassio", async () =>
|
||||||
del([paths.hassio_output_root, paths.build_dir])
|
(await del).deleteSync([paths.hassio_output_root, paths.build_dir])
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
gulp.parallel("clean-translations", () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
del([paths.gallery_output_root, paths.gallery_build, paths.build_dir])
|
(await del).deleteSync([
|
||||||
|
paths.gallery_output_root,
|
||||||
|
paths.gallery_build,
|
||||||
|
paths.build_dir,
|
||||||
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
const fs = require("fs/promises");
|
||||||
const mapStream = require("map-stream");
|
const mapStream = require("map-stream");
|
||||||
|
|
||||||
const inDirFrontend = "translations/frontend";
|
const inDirFrontend = "translations/frontend";
|
||||||
@@ -46,18 +46,21 @@ gulp.task("check-translations-html", function () {
|
|||||||
return gulp.src([`${inDirFrontend}/*.json`]).pipe(checkHtml());
|
return gulp.src([`${inDirFrontend}/*.json`]).pipe(checkHtml());
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("check-all-files-exist", function () {
|
gulp.task("check-all-files-exist", async function () {
|
||||||
const file = fs.readFileSync(srcMeta, { encoding });
|
const file = await fs.readFile(srcMeta, { encoding });
|
||||||
const meta = JSON.parse(file);
|
const meta = JSON.parse(file);
|
||||||
|
const writings = [];
|
||||||
Object.keys(meta).forEach((lang) => {
|
Object.keys(meta).forEach((lang) => {
|
||||||
if (!fs.existsSync(`${inDirFrontend}/${lang}.json`)) {
|
writings.push(
|
||||||
fs.writeFileSync(`${inDirFrontend}/${lang}.json`, JSON.stringify({}));
|
fs.writeFile(`${inDirFrontend}/${lang}.json`, JSON.stringify({}), {
|
||||||
}
|
flag: "wx",
|
||||||
if (!fs.existsSync(`${inDirBackend}/${lang}.json`)) {
|
}),
|
||||||
fs.writeFileSync(`${inDirBackend}/${lang}.json`, JSON.stringify({}));
|
fs.writeFile(`${inDirBackend}/${lang}.json`, JSON.stringify({}), {
|
||||||
}
|
flag: "wx",
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
return Promise.resolve();
|
await Promise.allSettled(writings);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
// Tasks to generate entry HTML
|
// Tasks to generate entry HTML
|
||||||
/* eslint-disable import/no-dynamic-require */
|
|
||||||
/* eslint-disable global-require */
|
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
@@ -91,7 +89,9 @@ gulp.task("gen-pages-prod", (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("gen-index-app-dev", (done) => {
|
gulp.task("gen-index-app-dev", (done) => {
|
||||||
let latestAppJS, latestCoreJS, latestCustomPanelJS;
|
let latestAppJS;
|
||||||
|
let latestCoreJS;
|
||||||
|
let latestCustomPanelJS;
|
||||||
|
|
||||||
if (env.useWDS()) {
|
if (env.useWDS()) {
|
||||||
latestAppJS = "http://localhost:8000/src/entrypoints/app.ts";
|
latestAppJS = "http://localhost:8000/src/entrypoints/app.ts";
|
||||||
|
174
build-scripts/gulp/fetch-nightly-translations.js
Normal file
174
build-scripts/gulp/fetch-nightly-translations.js
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
// Task to download the latest Lokalise translations from the nightly workflow artifacts
|
||||||
|
|
||||||
|
const del = import("del");
|
||||||
|
const fs = require("fs/promises");
|
||||||
|
const path = require("path");
|
||||||
|
const process = require("process");
|
||||||
|
const gulp = require("gulp");
|
||||||
|
const jszip = require("jszip");
|
||||||
|
const tar = require("tar");
|
||||||
|
const { Octokit } = require("@octokit/rest");
|
||||||
|
const { createOAuthDeviceAuth } = require("@octokit/auth-oauth-device");
|
||||||
|
|
||||||
|
const MAX_AGE = 24; // hours
|
||||||
|
const OWNER = "home-assistant";
|
||||||
|
const REPO = "frontend";
|
||||||
|
const WORKFLOW_NAME = "nightly.yaml";
|
||||||
|
const ARTIFACT_NAME = "translations";
|
||||||
|
const CLIENT_ID = "Iv1.3914e28cb27834d1";
|
||||||
|
const EXTRACT_DIR = "translations";
|
||||||
|
const TOKEN_FILE = path.posix.join(EXTRACT_DIR, "token.json");
|
||||||
|
const ARTIFACT_FILE = path.posix.join(EXTRACT_DIR, "artifact.json");
|
||||||
|
|
||||||
|
let allowTokenSetup = false;
|
||||||
|
gulp.task("allow-setup-fetch-nightly-translations", (done) => {
|
||||||
|
allowTokenSetup = true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("fetch-nightly-translations", async function () {
|
||||||
|
// Skip all when environment flag is set (assumes translations are already in place)
|
||||||
|
if (process.env?.SKIP_FETCH_NIGHTLY_TRANSLATIONS) {
|
||||||
|
console.log("Skipping fetch due to environment signal");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read current translations artifact info if it exists,
|
||||||
|
// and stop if they are not old enough
|
||||||
|
let currentArtifact;
|
||||||
|
try {
|
||||||
|
currentArtifact = JSON.parse(await fs.readFile(ARTIFACT_FILE, "utf-8"));
|
||||||
|
const currentAge =
|
||||||
|
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
|
||||||
|
if (currentAge < MAX_AGE) {
|
||||||
|
console.log(
|
||||||
|
"Keeping current translations (only %s hours old)",
|
||||||
|
currentAge.toFixed(1)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
currentArtifact = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To store file writing promises
|
||||||
|
const createExtractDir = fs.mkdir(EXTRACT_DIR, { recursive: true });
|
||||||
|
const writings = [];
|
||||||
|
|
||||||
|
// Authenticate to GitHub using GitHub action token if it exists,
|
||||||
|
// otherwise look for a saved user token or generate a new one if none
|
||||||
|
let tokenAuth;
|
||||||
|
if (process.env.GITHUB_TOKEN) {
|
||||||
|
tokenAuth = { token: process.env.GITHUB_TOKEN };
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
tokenAuth = JSON.parse(await fs.readFile(TOKEN_FILE, "utf-8"));
|
||||||
|
} catch {
|
||||||
|
if (!allowTokenSetup) {
|
||||||
|
console.log("No token found so build wil continue with English only");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auth = createOAuthDeviceAuth({
|
||||||
|
clientType: "github-app",
|
||||||
|
clientId: CLIENT_ID,
|
||||||
|
onVerification: (verification) => {
|
||||||
|
console.log(
|
||||||
|
"Task needs to authenticate to GitHub to fetch the translations from nightly workflow\n" +
|
||||||
|
"Please go to %s to authorize this task\n" +
|
||||||
|
"\nEnter user code: %s\n\n" +
|
||||||
|
"This code will expire in %s minutes\n" +
|
||||||
|
"Task will automatically continue after authorization and token will be saved for future use",
|
||||||
|
verification.verification_uri,
|
||||||
|
verification.user_code,
|
||||||
|
(verification.expires_in / 60).toFixed(0)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
tokenAuth = await auth({ type: "oauth" });
|
||||||
|
writings.push(
|
||||||
|
createExtractDir.then(
|
||||||
|
fs.writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate with token and request workflow runs from GitHub
|
||||||
|
console.log("Fetching new translations...");
|
||||||
|
const octokit = new Octokit({
|
||||||
|
userAgent: "Fetch Nightly Translations",
|
||||||
|
auth: tokenAuth.token,
|
||||||
|
});
|
||||||
|
|
||||||
|
const workflowRunsResponse = await octokit.rest.actions.listWorkflowRuns({
|
||||||
|
owner: OWNER,
|
||||||
|
repo: REPO,
|
||||||
|
workflow_id: WORKFLOW_NAME,
|
||||||
|
status: "success",
|
||||||
|
event: "schedule",
|
||||||
|
per_page: 1,
|
||||||
|
exclude_pull_requests: true,
|
||||||
|
});
|
||||||
|
if (workflowRunsResponse.data.total_count === 0) {
|
||||||
|
throw Error("No successful nightly workflow runs found");
|
||||||
|
}
|
||||||
|
const latestNightlyRun = workflowRunsResponse.data.workflow_runs[0];
|
||||||
|
|
||||||
|
// Stop if current is already the latest, otherwise Find the translations artifact
|
||||||
|
if (currentArtifact?.workflow_run.id === latestNightlyRun.id) {
|
||||||
|
console.log("Stopping because current translations are still the latest");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const latestArtifact = (
|
||||||
|
await octokit.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: OWNER,
|
||||||
|
repo: REPO,
|
||||||
|
run_id: latestNightlyRun.id,
|
||||||
|
})
|
||||||
|
).data.artifacts.find((artifact) => artifact.name === ARTIFACT_NAME);
|
||||||
|
if (!latestArtifact) {
|
||||||
|
throw Error("Latest nightly workflow run has no translations artifact");
|
||||||
|
}
|
||||||
|
writings.push(
|
||||||
|
createExtractDir.then(
|
||||||
|
fs.writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Remove the current translations
|
||||||
|
const deleteCurrent = Promise.all(writings).then(
|
||||||
|
(await del).deleteAsync([
|
||||||
|
`${EXTRACT_DIR}/*`,
|
||||||
|
`!${ARTIFACT_FILE}`,
|
||||||
|
`!${TOKEN_FILE}`,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
|
||||||
|
const downloadResponse = await octokit.actions.downloadArtifact({
|
||||||
|
owner: OWNER,
|
||||||
|
repo: REPO,
|
||||||
|
artifact_id: latestArtifact.id,
|
||||||
|
archive_format: "zip",
|
||||||
|
});
|
||||||
|
if (downloadResponse.status !== 200) {
|
||||||
|
throw Error("Failure downloading translations artifact");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Artifact is a tarball, but GitHub adds it to a zip file
|
||||||
|
console.log("Unpacking downloaded translations...");
|
||||||
|
const zip = await jszip.loadAsync(downloadResponse.data);
|
||||||
|
await deleteCurrent;
|
||||||
|
const extractStream = zip.file(/.*/)[0].nodeStream().pipe(tar.extract());
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
extractStream.on("close", resolve).on("error", reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task(
|
||||||
|
"setup-and-fetch-nightly-translations",
|
||||||
|
gulp.series(
|
||||||
|
"allow-setup-fetch-nightly-translations",
|
||||||
|
"fetch-nightly-translations"
|
||||||
|
)
|
||||||
|
);
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// Run demo develop mode
|
// Run demo develop mode
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
@@ -41,7 +40,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
|
|||||||
}
|
}
|
||||||
processed.add(pageId);
|
processed.add(pageId);
|
||||||
|
|
||||||
const [category, name] = pageId.split("/", 2);
|
const [category] = pageId.split("/", 2);
|
||||||
|
|
||||||
const demoFile = path.resolve(pageDir, `${pageId}.ts`);
|
const demoFile = path.resolve(pageDir, `${pageId}.ts`);
|
||||||
const descriptionFile = path.resolve(pageDir, `${pageId}.markdown`);
|
const descriptionFile = path.resolve(pageDir, `${pageId}.markdown`);
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
const del = import("del");
|
||||||
|
|
||||||
const del = require("del");
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
@@ -8,7 +6,7 @@ const paths = require("../paths");
|
|||||||
|
|
||||||
const outDir = "build/locale-data";
|
const outDir = "build/locale-data";
|
||||||
|
|
||||||
gulp.task("clean-locale-data", () => del([outDir]));
|
gulp.task("clean-locale-data", async () => (await del).deleteSync([outDir]));
|
||||||
|
|
||||||
gulp.task("ensure-locale-data-build-dir", (done) => {
|
gulp.task("ensure-locale-data-build-dir", (done) => {
|
||||||
if (!fs.existsSync(outDir)) {
|
if (!fs.existsSync(outDir)) {
|
||||||
|
@@ -5,9 +5,9 @@ const rollup = require("rollup");
|
|||||||
const handler = require("serve-handler");
|
const handler = require("serve-handler");
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
const log = require("fancy-log");
|
const log = require("fancy-log");
|
||||||
|
const open = require("open");
|
||||||
const rollupConfig = require("../rollup");
|
const rollupConfig = require("../rollup");
|
||||||
const paths = require("../paths");
|
const paths = require("../paths");
|
||||||
const open = require("open");
|
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) =>
|
const bothBuilds = (createConfigFunc, params) =>
|
||||||
gulp.series(
|
gulp.series(
|
||||||
@@ -30,11 +30,11 @@ const bothBuilds = (createConfigFunc, params) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
function createServer(serveOptions) {
|
function createServer(serveOptions) {
|
||||||
const server = http.createServer((request, response) => {
|
const server = http.createServer((request, response) =>
|
||||||
return handler(request, response, {
|
handler(request, response, {
|
||||||
public: serveOptions.root,
|
public: serveOptions.root,
|
||||||
});
|
})
|
||||||
});
|
);
|
||||||
|
|
||||||
server.listen(
|
server.listen(
|
||||||
serveOptions.port,
|
serveOptions.port,
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
// Generate service worker.
|
// Generate service worker.
|
||||||
// Based on manifest, create a file with the content as service_worker.js
|
// Based on manifest, create a file with the content as service_worker.js
|
||||||
/* eslint-disable import/no-dynamic-require */
|
|
||||||
/* eslint-disable global-require */
|
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
const del = import("del");
|
||||||
|
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
const del = require("del");
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const source = require("vinyl-source-stream");
|
const source = require("vinyl-source-stream");
|
||||||
const vinylBuffer = require("vinyl-buffer");
|
const vinylBuffer = require("vinyl-buffer");
|
||||||
@@ -15,6 +13,8 @@ const { mapFiles } = require("../util");
|
|||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
const paths = require("../paths");
|
const paths = require("../paths");
|
||||||
|
|
||||||
|
require("./fetch-nightly-translations");
|
||||||
|
|
||||||
const inFrontendDir = "translations/frontend";
|
const inFrontendDir = "translations/frontend";
|
||||||
const inBackendDir = "translations/backend";
|
const inBackendDir = "translations/backend";
|
||||||
const workDir = "build/translations";
|
const workDir = "build/translations";
|
||||||
@@ -23,10 +23,13 @@ const coreDir = workDir + "/core";
|
|||||||
const outDir = workDir + "/output";
|
const outDir = workDir + "/output";
|
||||||
let mergeBackend = false;
|
let mergeBackend = false;
|
||||||
|
|
||||||
gulp.task("translations-enable-merge-backend", (done) => {
|
gulp.task(
|
||||||
mergeBackend = true;
|
"translations-enable-merge-backend",
|
||||||
done();
|
gulp.parallel((done) => {
|
||||||
});
|
mergeBackend = true;
|
||||||
|
done();
|
||||||
|
}, "allow-setup-fetch-nightly-translations")
|
||||||
|
);
|
||||||
|
|
||||||
// Panel translations which should be split from the core translations.
|
// Panel translations which should be split from the core translations.
|
||||||
const TRANSLATION_FRAGMENTS = Object.keys(
|
const TRANSLATION_FRAGMENTS = Object.keys(
|
||||||
@@ -117,7 +120,7 @@ function lokaliseTransform(data, original, file) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task("clean-translations", () => del([workDir]));
|
gulp.task("clean-translations", async () => (await del).deleteSync([workDir]));
|
||||||
|
|
||||||
gulp.task("ensure-translations-build-dir", (done) => {
|
gulp.task("ensure-translations-build-dir", (done) => {
|
||||||
if (!fs.existsSync(workDir)) {
|
if (!fs.existsSync(workDir)) {
|
||||||
@@ -170,17 +173,24 @@ gulp.task("build-master-translation", () => {
|
|||||||
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
||||||
.pipe(
|
.pipe(
|
||||||
merge({
|
merge({
|
||||||
fileName: "translationMaster.json",
|
fileName: "en.json",
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.pipe(gulp.dest(workDir));
|
.pipe(gulp.dest(fullDir));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("build-merged-translations", () =>
|
gulp.task("build-merged-translations", () =>
|
||||||
gulp
|
gulp
|
||||||
.src([inFrontendDir + "/*.json", workDir + "/test.json"], {
|
.src(
|
||||||
allowEmpty: true,
|
[
|
||||||
})
|
inFrontendDir + "/*.json",
|
||||||
|
"!" + inFrontendDir + "/en.json",
|
||||||
|
workDir + "/test.json",
|
||||||
|
],
|
||||||
|
{
|
||||||
|
allowEmpty: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
||||||
.pipe(
|
.pipe(
|
||||||
flatmap((stream, file) => {
|
flatmap((stream, file) => {
|
||||||
@@ -193,7 +203,7 @@ gulp.task("build-merged-translations", () =>
|
|||||||
// than a base translation + region.
|
// than a base translation + region.
|
||||||
const tr = path.basename(file.history[0], ".json");
|
const tr = path.basename(file.history[0], ".json");
|
||||||
const subtags = tr.split("-");
|
const subtags = tr.split("-");
|
||||||
const src = [workDir + "/translationMaster.json"];
|
const src = [fullDir + "/en.json"];
|
||||||
for (let i = 1; i <= subtags.length; i++) {
|
for (let i = 1; i <= subtags.length; i++) {
|
||||||
const lang = subtags.slice(0, i).join("-");
|
const lang = subtags.slice(0, i).join("-");
|
||||||
if (lang === "test") {
|
if (lang === "test") {
|
||||||
@@ -378,7 +388,6 @@ gulp.task("build-translation-write-metadata", () =>
|
|||||||
if (value.nativeName) {
|
if (value.nativeName) {
|
||||||
newData[key] = value;
|
newData[key] = value;
|
||||||
} else {
|
} else {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.warn(
|
console.warn(
|
||||||
`Skipping language ${key}. Native name was not translated.`
|
`Skipping language ${key}. Native name was not translated.`
|
||||||
);
|
);
|
||||||
@@ -411,8 +420,10 @@ gulp.task(
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
"build-translations",
|
"build-translations",
|
||||||
gulp.series(
|
gulp.series(
|
||||||
"clean-translations",
|
gulp.parallel(
|
||||||
"ensure-translations-build-dir",
|
"fetch-nightly-translations",
|
||||||
|
gulp.series("clean-translations", "ensure-translations-build-dir")
|
||||||
|
),
|
||||||
"create-translations",
|
"create-translations",
|
||||||
"build-translation-fingerprints",
|
"build-translation-fingerprints",
|
||||||
"build-translation-write-metadata"
|
"build-translation-write-metadata"
|
||||||
@@ -422,8 +433,10 @@ gulp.task(
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
gulp.series(
|
gulp.series(
|
||||||
"clean-translations",
|
gulp.parallel(
|
||||||
"ensure-translations-build-dir",
|
"fetch-nightly-translations",
|
||||||
|
gulp.series("clean-translations", "ensure-translations-build-dir")
|
||||||
|
),
|
||||||
"build-master-translation",
|
"build-master-translation",
|
||||||
"build-merged-translations",
|
"build-merged-translations",
|
||||||
"build-translation-fragment-supervisor",
|
"build-translation-fragment-supervisor",
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Tasks to run webpack.
|
// Tasks to run webpack.
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
@@ -69,7 +68,6 @@ const doneHandler = (done) => (err, stats) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stats.hasErrors() || stats.hasWarnings()) {
|
if (stats.hasErrors() || stats.hasWarnings()) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(stats.toString("minimal"));
|
console.log(stats.toString("minimal"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@@ -81,13 +81,13 @@ module.exports = function (opts = {}) {
|
|||||||
opts.workerRegexp.flags
|
opts.workerRegexp.flags
|
||||||
);
|
);
|
||||||
if (!workerRegexp.test(code)) {
|
if (!workerRegexp.test(code)) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ms = new MagicString(code);
|
const ms = new MagicString(code);
|
||||||
// Reset the regexp
|
// Reset the regexp
|
||||||
workerRegexp.lastIndex = 0;
|
workerRegexp.lastIndex = 0;
|
||||||
while (true) {
|
for (;;) {
|
||||||
const match = workerRegexp.exec(code);
|
const match = workerRegexp.exec(code);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
break;
|
break;
|
||||||
@@ -98,6 +98,7 @@ module.exports = function (opts = {}) {
|
|||||||
// Parse the optional options object
|
// Parse the optional options object
|
||||||
if (match[3] && match[3].length > 0) {
|
if (match[3] && match[3].length > 0) {
|
||||||
// FIXME: ooooof!
|
// FIXME: ooooof!
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
||||||
optionsObject = new Function(`return ${match[3].slice(1)};`)();
|
optionsObject = new Function(`return ${match[3].slice(1)};`)();
|
||||||
}
|
}
|
||||||
delete optionsObject.type;
|
delete optionsObject.type;
|
||||||
@@ -110,12 +111,14 @@ module.exports = function (opts = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find worker file and store it as a chunk with ID prefixed for our loader
|
// Find worker file and store it as a chunk with ID prefixed for our loader
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const resolvedWorkerFile = (await this.resolve(workerFile, id)).id;
|
const resolvedWorkerFile = (await this.resolve(workerFile, id)).id;
|
||||||
let chunkRefId;
|
let chunkRefId;
|
||||||
if (resolvedWorkerFile in refIds) {
|
if (resolvedWorkerFile in refIds) {
|
||||||
chunkRefId = refIds[resolvedWorkerFile];
|
chunkRefId = refIds[resolvedWorkerFile];
|
||||||
} else {
|
} else {
|
||||||
this.addWatchFile(resolvedWorkerFile);
|
this.addWatchFile(resolvedWorkerFile);
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const source = await getBundledWorker(
|
const source = await getBundledWorker(
|
||||||
resolvedWorkerFile,
|
resolvedWorkerFile,
|
||||||
rollupOptions
|
rollupOptions
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const commonjs = require("@rollup/plugin-commonjs");
|
const commonjs = require("@rollup/plugin-commonjs");
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
@@ -103,7 +102,6 @@ const createWebpackConfig = ({
|
|||||||
? path.resolve(context, resource)
|
? path.resolve(context, resource)
|
||||||
: require.resolve(resource);
|
: require.resolve(resource);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(
|
console.error(
|
||||||
"Error in Home Assistant ignore plugin",
|
"Error in Home Assistant ignore plugin",
|
||||||
resource,
|
resource,
|
||||||
|
@@ -213,7 +213,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Google Chrome (all platforms except iOS)</li>
|
<li>Google Chrome (all platforms except iOS)</li>
|
||||||
<li>Microsoft Edge (all platforms)</li>
|
<li>Microsoft Edge (all platforms except iOS)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -88,7 +88,7 @@ class HcCast extends LitElement {
|
|||||||
>
|
>
|
||||||
${(this.lovelaceConfig
|
${(this.lovelaceConfig
|
||||||
? this.lovelaceConfig.views
|
? this.lovelaceConfig.views
|
||||||
: [generateDefaultViewConfig([], [], [], {}, () => "")]
|
: [generateDefaultViewConfig({}, {}, {}, {}, () => "")]
|
||||||
).map(
|
).map(
|
||||||
(view, idx) => html`
|
(view, idx) => html`
|
||||||
<paper-icon-item
|
<paper-icon-item
|
||||||
@@ -181,7 +181,7 @@ class HcCast extends LitElement {
|
|||||||
private async _handlePickView(ev: Event) {
|
private async _handlePickView(ev: Event) {
|
||||||
const path = (ev.currentTarget as any).getAttribute("data-path");
|
const path = (ev.currentTarget as any).getAttribute("data-path");
|
||||||
await ensureConnectedCastSession(this.castManager!, this.auth!);
|
await ensureConnectedCastSession(this.castManager!, this.auth!);
|
||||||
castSendShowLovelaceView(this.castManager, path);
|
castSendShowLovelaceView(this.castManager, path, this.auth.data.hassUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handleLogout() {
|
private async _handleLogout() {
|
||||||
|
@@ -22,7 +22,11 @@ class HcLayout extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<img class="hero" src="/images/google-nest-hub.png" />
|
<img
|
||||||
|
class="hero"
|
||||||
|
alt="A Google Nest Hub with a Home Assistant dashboard on its screen"
|
||||||
|
src="/images/google-nest-hub.png"
|
||||||
|
/>
|
||||||
<h1 class="card-header">
|
<h1 class="card-header">
|
||||||
Home Assistant Cast${this.subtitle ? ` – ${this.subtitle}` : ""}
|
Home Assistant Cast${this.subtitle ? ` – ${this.subtitle}` : ""}
|
||||||
${this.auth
|
${this.auth
|
||||||
@@ -44,7 +48,7 @@ class HcLayout extends LitElement {
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a href="./faq.html">Frequently Asked Questions</a> – Found a bug?
|
<a href="./faq.html">Frequently Asked Questions</a> – Found a bug?
|
||||||
<a
|
<a
|
||||||
href="https://github.com/home-assistant/home-assistant-polymer/issues"
|
href="https://github.com/home-assistant/frontend/issues"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>Let us know!</a
|
>Let us know!</a
|
||||||
>
|
>
|
||||||
|
@@ -12,6 +12,7 @@ class HcLaunchScreen extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img
|
<img
|
||||||
|
alt="Home Assistant logo on left, Nabu Casa logo on right, and red heart in center"
|
||||||
src="https://www.home-assistant.io/images/blog/2018-09-thinking-big/social.png"
|
src="https://www.home-assistant.io/images/blog/2018-09-thinking-big/social.png"
|
||||||
/>
|
/>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
|
@@ -33,7 +33,6 @@ import { castContext } from "../cast_context";
|
|||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
|
||||||
let resourcesLoaded = false;
|
let resourcesLoaded = false;
|
||||||
|
|
||||||
@customElement("hc-main")
|
@customElement("hc-main")
|
||||||
export class HcMain extends HassElement {
|
export class HcMain extends HassElement {
|
||||||
@state() private _showDemo = false;
|
@state() private _showDemo = false;
|
||||||
@@ -46,6 +45,8 @@ export class HcMain extends HassElement {
|
|||||||
|
|
||||||
@state() private _urlPath?: string | null;
|
@state() private _urlPath?: string | null;
|
||||||
|
|
||||||
|
private _hassUUID?: string;
|
||||||
|
|
||||||
private _unsubLovelace?: UnsubscribeFunc;
|
private _unsubLovelace?: UnsubscribeFunc;
|
||||||
|
|
||||||
public processIncomingMessage(msg: HassMessage) {
|
public processIncomingMessage(msg: HassMessage) {
|
||||||
@@ -125,6 +126,7 @@ export class HcMain extends HassElement {
|
|||||||
|
|
||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
status.hassUrl = this.hass.auth.data.hassUrl;
|
status.hassUrl = this.hass.auth.data.hassUrl;
|
||||||
|
status.hassUUID = this._hassUUID;
|
||||||
status.lovelacePath = this._lovelacePath;
|
status.lovelacePath = this._lovelacePath;
|
||||||
status.urlPath = this._urlPath;
|
status.urlPath = this._urlPath;
|
||||||
}
|
}
|
||||||
@@ -163,6 +165,18 @@ export class HcMain extends HassElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private async _handleGetStatusMessage(msg: GetStatusMessage) {
|
private async _handleGetStatusMessage(msg: GetStatusMessage) {
|
||||||
|
if (
|
||||||
|
(this.hass && msg.hassUUID && msg.hassUUID !== this._hassUUID) ||
|
||||||
|
(this.hass && msg.hassUrl && msg.hassUrl !== this.hass.auth.data.hassUrl)
|
||||||
|
) {
|
||||||
|
this._error = "Not connected to the same Home Assistant instance.";
|
||||||
|
this._sendError(
|
||||||
|
ReceiverErrorCode.WRONG_INSTANCE,
|
||||||
|
this._error,
|
||||||
|
msg.senderId!
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this._sendStatus(msg.senderId!);
|
this._sendStatus(msg.senderId!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +193,7 @@ export class HcMain extends HassElement {
|
|||||||
expires_in: 0,
|
expires_in: 0,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
this._hassUUID = msg.hassUUID;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const errorMessage = this._getErrorMessage(err);
|
const errorMessage = this._getErrorMessage(err);
|
||||||
this._error = errorMessage;
|
this._error = errorMessage;
|
||||||
@@ -209,9 +224,29 @@ export class HcMain extends HassElement {
|
|||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
this._sendStatus(msg.senderId!);
|
this._sendStatus(msg.senderId!);
|
||||||
this._error = "Cannot show Lovelace because we're not connected.";
|
this._error = "Cannot show Lovelace because we're not connected.";
|
||||||
this._sendError(ReceiverErrorCode.NOT_CONNECTED, this._error);
|
this._sendError(
|
||||||
|
ReceiverErrorCode.NOT_CONNECTED,
|
||||||
|
this._error,
|
||||||
|
msg.senderId!
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(msg.hassUUID && msg.hassUUID !== this._hassUUID) ||
|
||||||
|
(msg.hassUrl && msg.hassUrl !== this.hass.auth.data.hassUrl)
|
||||||
|
) {
|
||||||
|
this._sendStatus(msg.senderId!);
|
||||||
|
this._error =
|
||||||
|
"Cannot show Lovelace because we're not connected to the same Home Assistant instance.";
|
||||||
|
this._sendError(
|
||||||
|
ReceiverErrorCode.WRONG_INSTANCE,
|
||||||
|
this._error,
|
||||||
|
msg.senderId!
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
if (msg.urlPath === "lovelace") {
|
if (msg.urlPath === "lovelace") {
|
||||||
msg.urlPath = null;
|
msg.urlPath = null;
|
||||||
|
@@ -138,7 +138,7 @@ if (!window.cardTools) {
|
|||||||
return cardTools.createThing("row", config);
|
return cardTools.createThing("row", config);
|
||||||
|
|
||||||
const domain = config.entity.split(".", 1)[0];
|
const domain = config.entity.split(".", 1)[0];
|
||||||
Object.assign(config, { type: DEFAULT_ROWS[domain] || "text" });
|
Object.assign(config, { type: DEFAULT_ROWS[domain] || "simple" });
|
||||||
return cardTools.createThing("entity-row", config);
|
return cardTools.createThing("entity-row", config);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,7 +13,6 @@ import {
|
|||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
const generateMeanStatistics = (
|
const generateMeanStatistics = (
|
||||||
id: string,
|
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||||
@@ -29,13 +28,12 @@ const generateMeanStatistics = (
|
|||||||
const delta = Math.random() * maxDiff;
|
const delta = Math.random() * maxDiff;
|
||||||
const mean = lastVal + delta;
|
const mean = lastVal + delta;
|
||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
start: currentDate.getTime(),
|
||||||
start: currentDate.toISOString(),
|
end: currentDate.getTime(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean,
|
mean,
|
||||||
min: mean - Math.random() * maxDiff,
|
min: mean - Math.random() * maxDiff,
|
||||||
max: mean + Math.random() * maxDiff,
|
max: mean + Math.random() * maxDiff,
|
||||||
last_reset: "1970-01-01T00:00:00+00:00",
|
last_reset: 0,
|
||||||
state: mean,
|
state: mean,
|
||||||
sum: null,
|
sum: null,
|
||||||
});
|
});
|
||||||
@@ -51,7 +49,6 @@ const generateMeanStatistics = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const generateSumStatistics = (
|
const generateSumStatistics = (
|
||||||
id: string,
|
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||||
@@ -67,13 +64,12 @@ const generateSumStatistics = (
|
|||||||
const add = Math.random() * maxDiff;
|
const add = Math.random() * maxDiff;
|
||||||
sum += add;
|
sum += add;
|
||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
start: currentDate.getTime(),
|
||||||
start: currentDate.toISOString(),
|
end: currentDate.getTime(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean: null,
|
mean: null,
|
||||||
min: null,
|
min: null,
|
||||||
max: null,
|
max: null,
|
||||||
last_reset: "1970-01-01T00:00:00+00:00",
|
last_reset: 0,
|
||||||
state: initValue + sum,
|
state: initValue + sum,
|
||||||
sum,
|
sum,
|
||||||
});
|
});
|
||||||
@@ -88,7 +84,6 @@ const generateSumStatistics = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const generateCurvedStatistics = (
|
const generateCurvedStatistics = (
|
||||||
id: string,
|
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
_period: "5minute" | "hour" | "day" | "month" = "hour",
|
_period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||||
@@ -108,13 +103,12 @@ const generateCurvedStatistics = (
|
|||||||
const add = Math.random() * maxDiff;
|
const add = Math.random() * maxDiff;
|
||||||
sum += i * add;
|
sum += i * add;
|
||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
start: currentDate.getTime(),
|
||||||
start: currentDate.toISOString(),
|
end: currentDate.getTime(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean: null,
|
mean: null,
|
||||||
min: null,
|
min: null,
|
||||||
max: null,
|
max: null,
|
||||||
last_reset: "1970-01-01T00:00:00+00:00",
|
last_reset: 0,
|
||||||
state: initValue + sum,
|
state: initValue + sum,
|
||||||
sum: metered ? sum : null,
|
sum: metered ? sum : null,
|
||||||
});
|
});
|
||||||
@@ -137,14 +131,13 @@ const statisticsFunctions: Record<
|
|||||||
) => StatisticValue[]
|
) => StatisticValue[]
|
||||||
> = {
|
> = {
|
||||||
"sensor.energy_consumption_tarif_1": (
|
"sensor.energy_consumption_tarif_1": (
|
||||||
id: string,
|
_id: string,
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period = "hour"
|
period = "hour"
|
||||||
) => {
|
) => {
|
||||||
if (period !== "hour") {
|
if (period !== "hour") {
|
||||||
return generateSumStatistics(
|
return generateSumStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -153,20 +146,12 @@ const statisticsFunctions: Record<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
|
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
|
||||||
const morningLow = generateSumStatistics(
|
const morningLow = generateSumStatistics(start, morningEnd, period, 0, 0.7);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
morningEnd,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0.7
|
|
||||||
);
|
|
||||||
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
||||||
const morningFinalVal = morningLow.length
|
const morningFinalVal = morningLow.length
|
||||||
? morningLow[morningLow.length - 1].sum!
|
? morningLow[morningLow.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const empty = generateSumStatistics(
|
const empty = generateSumStatistics(
|
||||||
id,
|
|
||||||
morningEnd,
|
morningEnd,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
period,
|
period,
|
||||||
@@ -174,7 +159,6 @@ const statisticsFunctions: Record<
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
const eveningLow = generateSumStatistics(
|
const eveningLow = generateSumStatistics(
|
||||||
id,
|
|
||||||
eveningStart,
|
eveningStart,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -184,14 +168,13 @@ const statisticsFunctions: Record<
|
|||||||
return [...morningLow, ...empty, ...eveningLow];
|
return [...morningLow, ...empty, ...eveningLow];
|
||||||
},
|
},
|
||||||
"sensor.energy_consumption_tarif_2": (
|
"sensor.energy_consumption_tarif_2": (
|
||||||
id: string,
|
_id: string,
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period = "hour"
|
period = "hour"
|
||||||
) => {
|
) => {
|
||||||
if (period !== "hour") {
|
if (period !== "hour") {
|
||||||
return generateSumStatistics(
|
return generateSumStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -202,7 +185,6 @@ const statisticsFunctions: Record<
|
|||||||
const morningEnd = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
const morningEnd = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
||||||
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
||||||
const highTarif = generateSumStatistics(
|
const highTarif = generateSumStatistics(
|
||||||
id,
|
|
||||||
morningEnd,
|
morningEnd,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
period,
|
period,
|
||||||
@@ -212,9 +194,8 @@ const statisticsFunctions: Record<
|
|||||||
const highTarifFinalVal = highTarif.length
|
const highTarifFinalVal = highTarif.length
|
||||||
? highTarif[highTarif.length - 1].sum!
|
? highTarif[highTarif.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(id, start, morningEnd, period, 0, 0);
|
const morning = generateSumStatistics(start, morningEnd, period, 0, 0);
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
|
||||||
eveningStart,
|
eveningStart,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -223,18 +204,17 @@ const statisticsFunctions: Record<
|
|||||||
);
|
);
|
||||||
return [...morning, ...highTarif, ...evening];
|
return [...morning, ...highTarif, ...evening];
|
||||||
},
|
},
|
||||||
"sensor.energy_production_tarif_1": (id, start, end, period = "hour") =>
|
"sensor.energy_production_tarif_1": (_id, start, end, period = "hour") =>
|
||||||
generateSumStatistics(id, start, end, period, 0, 0),
|
generateSumStatistics(start, end, period, 0, 0),
|
||||||
"sensor.energy_production_tarif_1_compensation": (
|
"sensor.energy_production_tarif_1_compensation": (
|
||||||
id,
|
_id,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period = "hour"
|
period = "hour"
|
||||||
) => generateSumStatistics(id, start, end, period, 0, 0),
|
) => generateSumStatistics(start, end, period, 0, 0),
|
||||||
"sensor.energy_production_tarif_2": (id, start, end, period = "hour") => {
|
"sensor.energy_production_tarif_2": (_id, start, end, period = "hour") => {
|
||||||
if (period !== "hour") {
|
if (period !== "hour") {
|
||||||
return generateSumStatistics(
|
return generateSumStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -246,7 +226,6 @@ const statisticsFunctions: Record<
|
|||||||
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
|
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
|
||||||
const dayEnd = new Date(endOfDay(productionEnd));
|
const dayEnd = new Date(endOfDay(productionEnd));
|
||||||
const production = generateCurvedStatistics(
|
const production = generateCurvedStatistics(
|
||||||
id,
|
|
||||||
productionStart,
|
productionStart,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
period,
|
period,
|
||||||
@@ -257,16 +236,8 @@ const statisticsFunctions: Record<
|
|||||||
const productionFinalVal = production.length
|
const productionFinalVal = production.length
|
||||||
? production[production.length - 1].sum!
|
? production[production.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(
|
const morning = generateSumStatistics(start, productionStart, period, 0, 0);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
productionStart,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
|
||||||
productionEnd,
|
productionEnd,
|
||||||
dayEnd,
|
dayEnd,
|
||||||
period,
|
period,
|
||||||
@@ -274,7 +245,6 @@ const statisticsFunctions: Record<
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
const rest = generateSumStatistics(
|
const rest = generateSumStatistics(
|
||||||
id,
|
|
||||||
dayEnd,
|
dayEnd,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -283,10 +253,9 @@ const statisticsFunctions: Record<
|
|||||||
);
|
);
|
||||||
return [...morning, ...production, ...evening, ...rest];
|
return [...morning, ...production, ...evening, ...rest];
|
||||||
},
|
},
|
||||||
"sensor.solar_production": (id, start, end, period = "hour") => {
|
"sensor.solar_production": (_id, start, end, period = "hour") => {
|
||||||
if (period !== "hour") {
|
if (period !== "hour") {
|
||||||
return generateSumStatistics(
|
return generateSumStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -298,7 +267,6 @@ const statisticsFunctions: Record<
|
|||||||
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
|
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
|
||||||
const dayEnd = new Date(endOfDay(productionEnd));
|
const dayEnd = new Date(endOfDay(productionEnd));
|
||||||
const production = generateCurvedStatistics(
|
const production = generateCurvedStatistics(
|
||||||
id,
|
|
||||||
productionStart,
|
productionStart,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
period,
|
period,
|
||||||
@@ -309,16 +277,8 @@ const statisticsFunctions: Record<
|
|||||||
const productionFinalVal = production.length
|
const productionFinalVal = production.length
|
||||||
? production[production.length - 1].sum!
|
? production[production.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(
|
const morning = generateSumStatistics(start, productionStart, period, 0, 0);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
productionStart,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
|
||||||
productionEnd,
|
productionEnd,
|
||||||
dayEnd,
|
dayEnd,
|
||||||
period,
|
period,
|
||||||
@@ -326,7 +286,6 @@ const statisticsFunctions: Record<
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
const rest = generateSumStatistics(
|
const rest = generateSumStatistics(
|
||||||
id,
|
|
||||||
dayEnd,
|
dayEnd,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -362,7 +321,6 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
|
|||||||
statistics[id] =
|
statistics[id] =
|
||||||
entityState && "last_reset" in entityState.attributes
|
entityState && "last_reset" in entityState.attributes
|
||||||
? generateSumStatistics(
|
? generateSumStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
@@ -370,7 +328,6 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
|
|||||||
state * (state > 80 ? 0.01 : 0.05)
|
state * (state > 80 ? 0.01 : 0.05)
|
||||||
)
|
)
|
||||||
: generateMeanStatistics(
|
: generateMeanStatistics(
|
||||||
id,
|
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
period,
|
||||||
|
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
TARGET_LABEL="needs design preview"
|
|
||||||
|
|
||||||
if [[ "$NETLIFY" != "true" ]]; then
|
|
||||||
echo "This script can only be run on Netlify"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
function createStatus() {
|
|
||||||
state="$1"
|
|
||||||
description="$2"
|
|
||||||
target_url="$3"
|
|
||||||
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
"https://api.github.com/repos/home-assistant/frontend/statuses/$COMMIT_REF" \
|
|
||||||
-d '{"state": "'"${state}"'", "context": "Netlify/Design Preview Build", "description": "'"$description"'", "target_url": "'"$target_url"'"}'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if [[ "${PULL_REQUEST}" == "true" ]]; then
|
|
||||||
if [[ "$(curl -sSLf -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
|
||||||
"https://api.github.com/repos/home-assistant/frontend/pulls/${REVIEW_ID}" | jq '.labels[].name' -r)" =~ "$TARGET_LABEL" ]]; then
|
|
||||||
createStatus "pending" "Building design preview" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
|
||||||
gulp build-gallery
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
createStatus "success" "Build complete" "$DEPLOY_PRIME_URL"
|
|
||||||
else
|
|
||||||
createStatus "error" "Build failed" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
createStatus "success" "Build was not requested by PR label"
|
|
||||||
fi
|
|
||||||
elif [[ "$INCOMING_HOOK_BODY" == "NIGHTLY" ]]; then
|
|
||||||
gulp build-gallery
|
|
||||||
fi
|
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Alerts
|
title: Alert
|
||||||
subtitle: An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.
|
subtitle: An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -98,7 +98,9 @@ const alerts: {
|
|||||||
description: "Alert with slotted image",
|
description: "Alert with slotted image",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
iconSlot: html`<span slot="icon" class="image"
|
iconSlot: html`<span slot="icon" class="image"
|
||||||
><img src="https://www.home-assistant.io/images/home-assistant-logo.svg"
|
><img
|
||||||
|
alt="Home Assistant logo"
|
||||||
|
src="https://www.home-assistant.io/images/home-assistant-logo.svg"
|
||||||
/></span>`,
|
/></span>`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
---
|
---
|
||||||
title: Bar Sliders
|
title: Bar Slider
|
||||||
---
|
---
|
||||||
|
@@ -8,7 +8,7 @@ import "../../../../src/components/ha-card";
|
|||||||
const sliders: {
|
const sliders: {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
mode?: "start" | "end" | "indicator";
|
mode?: "start" | "end" | "cursor";
|
||||||
class?: string;
|
class?: string;
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
@@ -22,9 +22,9 @@ const sliders: {
|
|||||||
mode: "end",
|
mode: "end",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "slider-indicator",
|
id: "slider-cursor",
|
||||||
label: "Slider (indicator mode)",
|
label: "Slider (cursor mode)",
|
||||||
mode: "indicator",
|
mode: "cursor",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "slider-start-custom",
|
id: "slider-start-custom",
|
||||||
@@ -39,9 +39,9 @@ const sliders: {
|
|||||||
class: "custom",
|
class: "custom",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "slider-indicator-custom",
|
id: "slider-cursor-custom",
|
||||||
label: "Slider (indicator mode) and custom style",
|
label: "Slider (cursor mode) and custom style",
|
||||||
mode: "indicator",
|
mode: "cursor",
|
||||||
class: "custom",
|
class: "custom",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -142,7 +142,8 @@ export class DemoHaBarSlider extends LitElement {
|
|||||||
}
|
}
|
||||||
.custom {
|
.custom {
|
||||||
--slider-bar-color: #ffcf4c;
|
--slider-bar-color: #ffcf4c;
|
||||||
--slider-bar-background: #ffcf4c64;
|
--slider-bar-background: #ffcf4c;
|
||||||
|
--slider-bar-background-opacity: 0.2;
|
||||||
--slider-bar-thickness: 100px;
|
--slider-bar-thickness: 100px;
|
||||||
--slider-bar-border-radius: 24px;
|
--slider-bar-border-radius: 24px;
|
||||||
}
|
}
|
||||||
|
3
gallery/src/pages/components/ha-bar-switch.markdown
Normal file
3
gallery/src/pages/components/ha-bar-switch.markdown
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: Bar Switch
|
||||||
|
---
|
145
gallery/src/pages/components/ha-bar-switch.ts
Normal file
145
gallery/src/pages/components/ha-bar-switch.ts
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import {
|
||||||
|
mdiGarage,
|
||||||
|
mdiGarageOpen,
|
||||||
|
mdiLightbulb,
|
||||||
|
mdiLightbulbOff,
|
||||||
|
} from "@mdi/js";
|
||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
|
import { repeat } from "lit/directives/repeat";
|
||||||
|
import "../../../../src/components/ha-bar-switch";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
|
||||||
|
const switches: {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
class?: string;
|
||||||
|
reversed?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
id: "switch",
|
||||||
|
label: "Switch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "switch-reversed",
|
||||||
|
label: "Switch Reversed",
|
||||||
|
reversed: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "switch-custom",
|
||||||
|
label: "Switch and custom style",
|
||||||
|
class: "custom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "switch-disabled",
|
||||||
|
label: "Disabled Switch",
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("demo-components-ha-bar-switch")
|
||||||
|
export class DemoHaBarSwitch extends LitElement {
|
||||||
|
@state() private checked = false;
|
||||||
|
|
||||||
|
handleValueChanged(e: any) {
|
||||||
|
this.checked = e.target.checked as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${repeat(switches, (sw) => {
|
||||||
|
const { id, label, ...config } = sw;
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<label id=${id}>${label}</label>
|
||||||
|
<pre>Config: ${JSON.stringify(config)}</pre>
|
||||||
|
<ha-bar-switch
|
||||||
|
.checked=${this.checked}
|
||||||
|
class=${ifDefined(config.class)}
|
||||||
|
@change=${this.handleValueChanged}
|
||||||
|
.pathOn=${mdiLightbulb}
|
||||||
|
.pathOff=${mdiLightbulbOff}
|
||||||
|
aria-labelledby=${id}
|
||||||
|
disabled=${ifDefined(config.disabled)}
|
||||||
|
reversed=${ifDefined(config.reversed)}
|
||||||
|
>
|
||||||
|
</ha-bar-switch>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title"><b>Vertical</b></p>
|
||||||
|
<div class="vertical-switches">
|
||||||
|
${repeat(switches, (sw) => {
|
||||||
|
const { id, label, ...config } = sw;
|
||||||
|
return html`
|
||||||
|
<ha-bar-switch
|
||||||
|
.checked=${this.checked}
|
||||||
|
vertical
|
||||||
|
class=${ifDefined(config.class)}
|
||||||
|
@change=${this.handleValueChanged}
|
||||||
|
aria-label=${label}
|
||||||
|
.pathOn=${mdiGarageOpen}
|
||||||
|
.pathOff=${mdiGarage}
|
||||||
|
disabled=${ifDefined(config.disabled)}
|
||||||
|
reversed=${ifDefined(config.reversed)}
|
||||||
|
>
|
||||||
|
</ha-bar-switch>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-card {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.custom {
|
||||||
|
--switch-bar-on-color: var(--green-color);
|
||||||
|
--switch-bar-off-color: var(--red-color);
|
||||||
|
--switch-bar-thickness: 100px;
|
||||||
|
--switch-bar-border-radius: 24px;
|
||||||
|
--switch-bar-padding: 6px;
|
||||||
|
--mdc-icon-size: 24px;
|
||||||
|
}
|
||||||
|
.vertical-switches {
|
||||||
|
height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
p.title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.vertical-switches > *:not(:last-child) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-components-ha-bar-switch": DemoHaBarSwitch;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
---
|
---
|
||||||
title: Progress Bars
|
title: Bar
|
||||||
|
subtitle: Can be used to communicate progress of a task.
|
||||||
---
|
---
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
---
|
---
|
||||||
title: Chips
|
title: Chip
|
||||||
---
|
---
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
title: Dialogs
|
title: Dialog
|
||||||
subtitle: Dialogs provide important prompts in a user flow.
|
subtitle: Dialogs provide important prompts in a user flow.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Material Design 3
|
# Material Design 3
|
||||||
|
|
||||||
Our dialogs are based on the latest version of Material Design. Specs and guidelines can be found on it's [website](https://m3.material.io/components/dialogs/overview).
|
Our dialogs are based on the latest version of Material Design. Specs and guidelines can be found on its [website](https://m3.material.io/components/dialogs/overview).
|
||||||
|
|
||||||
# Highlighted guidelines
|
# Highlighted guidelines
|
||||||
|
|
@@ -99,16 +99,19 @@ const AREAS = [
|
|||||||
area_id: "backyard",
|
area_id: "backyard",
|
||||||
name: "Backyard",
|
name: "Backyard",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "bedroom",
|
area_id: "bedroom",
|
||||||
name: "Bedroom",
|
name: "Bedroom",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "livingroom",
|
area_id: "livingroom",
|
||||||
name: "Livingroom",
|
name: "Livingroom",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
61
gallery/src/pages/components/ha-gauge.markdown
Normal file
61
gallery/src/pages/components/ha-gauge.markdown
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
title: Gauge
|
||||||
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
ha-gauge {
|
||||||
|
display: block;
|
||||||
|
width: 200px;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
# Gauge `<ha-gauge>`
|
||||||
|
|
||||||
|
A gauge that can be used to represent sensor data and provide visual feedback about the value and the corresponding severity (success, warning, error).
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Info color gauge
|
||||||
|
<ha-gauge value="75" style="--gauge-color: var(--info-color)"></ha-gauge>
|
||||||
|
|
||||||
|
Success color gauge
|
||||||
|
<ha-gauge value="25" style="--gauge-color: var(--success-color)" label="°C"></ha-gauge>
|
||||||
|
|
||||||
|
Warning color gauge
|
||||||
|
<ha-gauge value="50" style="--gauge-color: var(--warning-color)" label="°C"></ha-gauge>
|
||||||
|
|
||||||
|
Error color gauge
|
||||||
|
<ha-gauge value="75" style="--gauge-color: var(--error-color)" label="°C"></ha-gauge>
|
||||||
|
|
||||||
|
Gauge with background color
|
||||||
|
<ha-gauge value="75" style="--gauge-color: var(--info-color); --primary-background-color: lightgray"></ha-gauge>
|
||||||
|
|
||||||
|
|
||||||
|
## CSS variables
|
||||||
|
|
||||||
|
### Gauge
|
||||||
|
|
||||||
|
`primary-background-color`
|
||||||
|
Background color of the dial (rounded arch)
|
||||||
|
|
||||||
|
`primary-text-color`
|
||||||
|
Text color below dial (value and unit of measurement) plus needle color (if gauge is in needle mode)
|
||||||
|
|
||||||
|
#### Dial colors
|
||||||
|
|
||||||
|
`gauge-color`
|
||||||
|
Used in the coding to control what color the gauge value is rendered with, but cannot be set via theme since its value will dynamically be set (either to `info-color` or to the matching severity variable if the severity color mode is used). To control the used colors, adjust the following variables.
|
||||||
|
|
||||||
|
`success-color`
|
||||||
|
Dial color for the "green" severity level
|
||||||
|
|
||||||
|
`warning-color`
|
||||||
|
Dial color for the "yellow" severity level
|
||||||
|
|
||||||
|
`error-color`
|
||||||
|
Dial color for the "red" severity level
|
||||||
|
|
||||||
|
`info-color`
|
||||||
|
Static dial color if not in severity color mode
|
1
gallery/src/pages/components/ha-gauge.ts
Normal file
1
gallery/src/pages/components/ha-gauge.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "../../../../src/components/ha-gauge";
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Selectors
|
title: Selector
|
||||||
---
|
---
|
||||||
|
|
||||||
See the website for [list of available selectors](https://www.home-assistant.io/docs/blueprint/selectors/).
|
See the website for [list of available selectors](https://www.home-assistant.io/docs/blueprint/selectors/).
|
||||||
|
@@ -95,16 +95,19 @@ const AREAS = [
|
|||||||
area_id: "backyard",
|
area_id: "backyard",
|
||||||
name: "Backyard",
|
name: "Backyard",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "bedroom",
|
area_id: "bedroom",
|
||||||
name: "Bedroom",
|
name: "Bedroom",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "livingroom",
|
area_id: "livingroom",
|
||||||
name: "Livingroom",
|
name: "Livingroom",
|
||||||
picture: null,
|
picture: null,
|
||||||
|
aliases: [],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
39
gallery/src/pages/components/ha-switch.markdown
Normal file
39
gallery/src/pages/components/ha-switch.markdown
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
title: Switch / Toggle
|
||||||
|
---
|
||||||
|
|
||||||
|
<style>
|
||||||
|
ha-switch {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
# Switch `<ha-switch>`
|
||||||
|
|
||||||
|
A toggle switch can represent two states: on and off.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Switch in on state
|
||||||
|
<ha-switch checked></ha-switch>
|
||||||
|
|
||||||
|
Switch in off state
|
||||||
|
<ha-switch></ha-switch>
|
||||||
|
|
||||||
|
Disabled switch
|
||||||
|
<ha-switch disabled></ha-switch>
|
||||||
|
|
||||||
|
## CSS variables
|
||||||
|
|
||||||
|
For the switch / toggle there are always two variables, one for the on / checked state and one for the off / unchecked state.
|
||||||
|
|
||||||
|
The track element (background rounded rectangle that the round circular handle travels on) is set to being half transparent, so the final color will also be impacted by the color behind the track.
|
||||||
|
|
||||||
|
`switch-checked-color` / `switch-unchecked-color`
|
||||||
|
Set both the color of the round handle and the track behind it. If you want to control them separately, use the variables below instead.
|
||||||
|
|
||||||
|
`switch-checked-button-color` / `switch-unchecked-button-color`
|
||||||
|
Color of the round handle
|
||||||
|
|
||||||
|
`switch-checked-track-color` / `switch-unchecked-track-color`
|
||||||
|
Color of the track behind the round handle
|
1
gallery/src/pages/components/ha-switch.ts
Normal file
1
gallery/src/pages/components/ha-switch.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "../../../../src/components/ha-switch";
|
@@ -1,3 +1,3 @@
|
|||||||
---
|
---
|
||||||
title: Tips
|
title: Tip
|
||||||
---
|
---
|
||||||
|
@@ -98,6 +98,9 @@ const ENTITIES = [
|
|||||||
minimum: 0,
|
minimum: 0,
|
||||||
maximum: 10,
|
maximum: 10,
|
||||||
}),
|
}),
|
||||||
|
getEntity("text", "message", "Hello!", {
|
||||||
|
friendly_name: "Message",
|
||||||
|
}),
|
||||||
|
|
||||||
getEntity("light", "unavailable", "unavailable", {
|
getEntity("light", "unavailable", "unavailable", {
|
||||||
friendly_name: "Bed Light",
|
friendly_name: "Bed Light",
|
||||||
@@ -129,6 +132,9 @@ const ENTITIES = [
|
|||||||
friendly_name: "Who cooks",
|
friendly_name: "Who cooks",
|
||||||
icon: "mdi:cheff",
|
icon: "mdi:cheff",
|
||||||
}),
|
}),
|
||||||
|
getEntity("text", "unavailable", "unavailable", {
|
||||||
|
friendly_name: "Message",
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
@@ -147,6 +153,26 @@ const CONFIGS = [
|
|||||||
- climate.ecobee
|
- climate.ecobee
|
||||||
- input_number.number
|
- input_number.number
|
||||||
- sensor.humidity
|
- sensor.humidity
|
||||||
|
- text.message
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "With enabled state color",
|
||||||
|
config: `
|
||||||
|
- type: entities
|
||||||
|
state_color: true
|
||||||
|
entities:
|
||||||
|
- scene.romantic_lights
|
||||||
|
- device_tracker.demo_paulus
|
||||||
|
- cover.kitchen_window
|
||||||
|
- group.kitchen
|
||||||
|
- lock.kitchen_door
|
||||||
|
- light.bed_light
|
||||||
|
- light.non_existing
|
||||||
|
- climate.ecobee
|
||||||
|
- input_number.number
|
||||||
|
- sensor.humidity
|
||||||
|
- text.message
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -219,6 +245,7 @@ const CONFIGS = [
|
|||||||
- climate.unavailable
|
- climate.unavailable
|
||||||
- input_number.unavailable
|
- input_number.unavailable
|
||||||
- input_select.unavailable
|
- input_select.unavailable
|
||||||
|
- text.unavailable
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -35,11 +35,11 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Without State",
|
heading: "With State",
|
||||||
config: `
|
config: `
|
||||||
- type: button
|
- type: button
|
||||||
entity: light.bed_light
|
entity: light.bed_light
|
||||||
show_state: false
|
show_state: true
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -23,13 +23,12 @@ const CONFIGS = [
|
|||||||
heading: "Basic example",
|
heading: "Basic example",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
title: Humidity
|
|
||||||
entity: sensor.outside_humidity
|
entity: sensor.outside_humidity
|
||||||
name: Outside Humidity
|
name: Outside Humidity
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Custom Unit of Measurement",
|
heading: "Custom unit of measurement",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.outside_temperature
|
entity: sensor.outside_temperature
|
||||||
@@ -38,7 +37,16 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Setting Severity Levels",
|
heading: "Rendering needle",
|
||||||
|
config: `
|
||||||
|
- type: gauge
|
||||||
|
entity: sensor.outside_humidity
|
||||||
|
name: Outside Humidity
|
||||||
|
needle: true
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "Setting severity levels",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.brightness
|
entity: sensor.brightness
|
||||||
@@ -50,7 +58,7 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Setting Severity Levels",
|
heading: "Setting severity levels",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.brightness_medium
|
entity: sensor.brightness_medium
|
||||||
@@ -62,7 +70,7 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Setting Severity Levels",
|
heading: "Setting severity levels",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.brightness_high
|
entity: sensor.brightness_high
|
||||||
@@ -74,7 +82,7 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Setting Min (0) and Max (15) Values",
|
heading: "Setting min (0) and mx (15) values",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.brightness
|
entity: sensor.brightness
|
||||||
@@ -84,14 +92,14 @@ const CONFIGS = [
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Invalid Entity",
|
heading: "Invalid entity",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: sensor.invalid_entity
|
entity: sensor.invalid_entity
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
heading: "Non-Numeric Value",
|
heading: "Non-numeric value",
|
||||||
config: `
|
config: `
|
||||||
- type: gauge
|
- type: gauge
|
||||||
entity: plant.bonsai
|
entity: plant.bonsai
|
||||||
|
@@ -62,6 +62,21 @@ const CONFIGS = [
|
|||||||
heading: "Basic example",
|
heading: "Basic example",
|
||||||
config: `
|
config: `
|
||||||
- type: glance
|
- type: glance
|
||||||
|
entities:
|
||||||
|
- device_tracker.demo_paulus
|
||||||
|
- media_player.living_room
|
||||||
|
- sun.sun
|
||||||
|
- cover.kitchen_window
|
||||||
|
- light.kitchen_lights
|
||||||
|
- lock.kitchen_door
|
||||||
|
- light.ceiling_lights
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "No state colors",
|
||||||
|
config: `
|
||||||
|
- type: glance
|
||||||
|
state_color: false
|
||||||
entities:
|
entities:
|
||||||
- device_tracker.demo_paulus
|
- device_tracker.demo_paulus
|
||||||
- media_player.living_room
|
- media_player.living_room
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
---
|
---
|
||||||
title: Grid And Stack Card
|
title: Grid and Stack Card
|
||||||
---
|
---
|
||||||
|
3
gallery/src/pages/misc/entity-state.markdown
Normal file
3
gallery/src/pages/misc/entity-state.markdown
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: Entity State
|
||||||
|
---
|
422
gallery/src/pages/misc/entity-state.ts
Normal file
422
gallery/src/pages/misc/entity-state.ts
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
import {
|
||||||
|
HassEntity,
|
||||||
|
HassEntityAttributeBase,
|
||||||
|
} from "home-assistant-js-websocket";
|
||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { computeDomain } from "../../../../src/common/entity/compute_domain";
|
||||||
|
import { computeStateDisplay } from "../../../../src/common/entity/compute_state_display";
|
||||||
|
import "../../../../src/components/data-table/ha-data-table";
|
||||||
|
import type { DataTableColumnContainer } from "../../../../src/components/data-table/ha-data-table";
|
||||||
|
import "../../../../src/components/entity/state-badge";
|
||||||
|
import "../../../../src/components/ha-chip";
|
||||||
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
|
|
||||||
|
const SENSOR_DEVICE_CLASSES = [
|
||||||
|
"apparent_power",
|
||||||
|
"aqi",
|
||||||
|
// "battery"
|
||||||
|
"carbon_dioxide",
|
||||||
|
"carbon_monoxide",
|
||||||
|
"current",
|
||||||
|
"date",
|
||||||
|
"distance",
|
||||||
|
"duration",
|
||||||
|
"energy",
|
||||||
|
"frequency",
|
||||||
|
"gas",
|
||||||
|
"humidity",
|
||||||
|
"illuminance",
|
||||||
|
"moisture",
|
||||||
|
"monetary",
|
||||||
|
"nitrogen_dioxide",
|
||||||
|
"nitrogen_monoxide",
|
||||||
|
"nitrous_oxide",
|
||||||
|
"ozone",
|
||||||
|
"pm1",
|
||||||
|
"pm10",
|
||||||
|
"pm25",
|
||||||
|
"power_factor",
|
||||||
|
"power",
|
||||||
|
"precipitation",
|
||||||
|
"precipitation_intensity",
|
||||||
|
"pressure",
|
||||||
|
"reactive_power",
|
||||||
|
"signal_strength",
|
||||||
|
"speed",
|
||||||
|
"sulphur_dioxide",
|
||||||
|
"temperature",
|
||||||
|
"timestamp",
|
||||||
|
"volatile_organic_compounds",
|
||||||
|
"voltage",
|
||||||
|
"volume",
|
||||||
|
"water",
|
||||||
|
"weight",
|
||||||
|
"wind_speed",
|
||||||
|
];
|
||||||
|
|
||||||
|
const BINARY_SENSOR_DEVICE_CLASSES = [
|
||||||
|
"battery",
|
||||||
|
"battery_charging",
|
||||||
|
"carbon_monoxide",
|
||||||
|
"cold",
|
||||||
|
"connectivity",
|
||||||
|
"door",
|
||||||
|
"garage_door",
|
||||||
|
"gas",
|
||||||
|
"heat",
|
||||||
|
"light",
|
||||||
|
"lock",
|
||||||
|
"moisture",
|
||||||
|
"motion",
|
||||||
|
"moving",
|
||||||
|
"occupancy",
|
||||||
|
"opening",
|
||||||
|
"plug",
|
||||||
|
"power",
|
||||||
|
"presence",
|
||||||
|
"problem",
|
||||||
|
"running",
|
||||||
|
"safety",
|
||||||
|
"smoke",
|
||||||
|
"sound",
|
||||||
|
"tamper",
|
||||||
|
"update",
|
||||||
|
"vibration",
|
||||||
|
"window",
|
||||||
|
];
|
||||||
|
|
||||||
|
const ENTITIES: HassEntity[] = [
|
||||||
|
// Alarm control panel
|
||||||
|
createEntity("alarm_control_panel.disarmed", "disarmed"),
|
||||||
|
createEntity("alarm_control_panel.armed_home", "armed_home"),
|
||||||
|
createEntity("alarm_control_panel.armed_away", "armed_away"),
|
||||||
|
createEntity("alarm_control_panel.armed_night", "armed_night"),
|
||||||
|
createEntity("alarm_control_panel.armed_vacation", "armed_vacation"),
|
||||||
|
createEntity(
|
||||||
|
"alarm_control_panel.armed_custom_bypass",
|
||||||
|
"armed_custom_bypass"
|
||||||
|
),
|
||||||
|
createEntity("alarm_control_panel.pending", "pending"),
|
||||||
|
createEntity("alarm_control_panel.arming", "arming"),
|
||||||
|
createEntity("alarm_control_panel.disarming", "disarming"),
|
||||||
|
createEntity("alarm_control_panel.triggered", "triggered"),
|
||||||
|
// Alert
|
||||||
|
createEntity("alert.idle", "idle"),
|
||||||
|
createEntity("alert.off", "off"),
|
||||||
|
createEntity("alert.on", "on"),
|
||||||
|
// Automation
|
||||||
|
createEntity("automation.off", "off"),
|
||||||
|
createEntity("automation.on", "on"),
|
||||||
|
// Binary Sensor
|
||||||
|
...BINARY_SENSOR_DEVICE_CLASSES.map((dc) => [
|
||||||
|
createEntity(`binary_sensor.${dc}`, "off", dc),
|
||||||
|
createEntity(`binary_sensor.${dc}`, "on", dc),
|
||||||
|
]).reduce((arr, item) => [...arr, ...item], []),
|
||||||
|
// Button
|
||||||
|
createEntity("button.restart", "unknown", "restart"),
|
||||||
|
createEntity("button.update", "unknown", "update"),
|
||||||
|
// Calendar
|
||||||
|
createEntity("calendar.off", "off"),
|
||||||
|
createEntity("calendar.on", "on"),
|
||||||
|
// Camera
|
||||||
|
createEntity("camera.idle", "idle"),
|
||||||
|
createEntity("camera.streaming", "streaming"),
|
||||||
|
// Climate
|
||||||
|
createEntity("climate.off", "off"),
|
||||||
|
createEntity("climate.heat", "heat"),
|
||||||
|
createEntity("climate.cool", "cool"),
|
||||||
|
createEntity("climate.heat_cool", "heat_cool"),
|
||||||
|
createEntity("climate.auto", "auto"),
|
||||||
|
createEntity("climate.dry", "dry"),
|
||||||
|
createEntity("climate.fan_only", "fan_only"),
|
||||||
|
createEntity("climate.auto_idle", "auto", undefined, { hvac_action: "idle" }),
|
||||||
|
createEntity("climate.auto_off", "auto", undefined, { hvac_action: "off" }),
|
||||||
|
createEntity("climate.auto_heating", "auto", undefined, {
|
||||||
|
hvac_action: "heating",
|
||||||
|
}),
|
||||||
|
createEntity("climate.auto_cooling", "auto", undefined, {
|
||||||
|
hvac_action: "cooling",
|
||||||
|
}),
|
||||||
|
createEntity("climate.auto_dry", "auto", undefined, {
|
||||||
|
hvac_action: "drying",
|
||||||
|
}),
|
||||||
|
createEntity("climate.auto_fan", "auto", undefined, {
|
||||||
|
hvac_action: "fan",
|
||||||
|
}),
|
||||||
|
// Cover
|
||||||
|
createEntity("cover.closing", "closing"),
|
||||||
|
createEntity("cover.closed", "closed"),
|
||||||
|
createEntity("cover.opening", "opening"),
|
||||||
|
createEntity("cover.open", "open"),
|
||||||
|
createEntity("cover.awning", "open", "awning"),
|
||||||
|
createEntity("cover.blind", "open", "blind"),
|
||||||
|
createEntity("cover.curtain", "open", "curtain"),
|
||||||
|
createEntity("cover.damper", "open", "damper"),
|
||||||
|
createEntity("cover.door", "open", "door"),
|
||||||
|
createEntity("cover.garage", "open", "garage"),
|
||||||
|
createEntity("cover.gate", "open", "gate"),
|
||||||
|
createEntity("cover.shade", "open", "shade"),
|
||||||
|
createEntity("cover.shutter", "open", "shutter"),
|
||||||
|
createEntity("cover.window", "open", "window"),
|
||||||
|
// Device tracker/person
|
||||||
|
createEntity("device_tracker.not_home", "not_home"),
|
||||||
|
createEntity("device_tracker.home", "home"),
|
||||||
|
createEntity("device_tracker.work", "work"),
|
||||||
|
createEntity("person.home", "home"),
|
||||||
|
createEntity("person.not_home", "not_home"),
|
||||||
|
createEntity("person.work", "work"),
|
||||||
|
// Fan
|
||||||
|
createEntity("fan.off", "off"),
|
||||||
|
createEntity("fan.on", "on"),
|
||||||
|
// Camera
|
||||||
|
createEntity("group.off", "off"),
|
||||||
|
createEntity("group.on", "on"),
|
||||||
|
// Humidifier
|
||||||
|
createEntity("humidifier.off", "off"),
|
||||||
|
createEntity("humidifier.on", "on"),
|
||||||
|
// Helpers
|
||||||
|
createEntity("input_boolean.off", "off"),
|
||||||
|
createEntity("input_boolean.on", "on"),
|
||||||
|
// Light
|
||||||
|
createEntity("light.off", "off"),
|
||||||
|
createEntity("light.on", "on"),
|
||||||
|
// Locks
|
||||||
|
createEntity("lock.locked", "locked"),
|
||||||
|
createEntity("lock.unlocked", "unlocked"),
|
||||||
|
createEntity("lock.locking", "locking"),
|
||||||
|
createEntity("lock.unlocking", "unlocking"),
|
||||||
|
createEntity("lock.jammed", "jammed"),
|
||||||
|
// Media Player
|
||||||
|
createEntity("media_player.off", "off"),
|
||||||
|
createEntity("media_player.on", "on"),
|
||||||
|
createEntity("media_player.idle", "idle"),
|
||||||
|
createEntity("media_player.playing", "playing"),
|
||||||
|
createEntity("media_player.paused", "paused"),
|
||||||
|
createEntity("media_player.standby", "standby"),
|
||||||
|
createEntity("media_player.buffering", "buffering"),
|
||||||
|
createEntity("media_player.tv_off", "off", "tv"),
|
||||||
|
createEntity("media_player.tv_playing", "playing", "tv"),
|
||||||
|
createEntity("media_player.tv_paused", "paused", "tv"),
|
||||||
|
createEntity("media_player.tv_standby", "standby", "tv"),
|
||||||
|
createEntity("media_player.receiver_off", "off", "receiver"),
|
||||||
|
createEntity("media_player.receiver_playing", "playing", "receiver"),
|
||||||
|
createEntity("media_player.receiver_paused", "paused", "receiver"),
|
||||||
|
createEntity("media_player.receiver_standby", "standby", "receiver"),
|
||||||
|
createEntity("media_player.speaker_off", "off", "speaker"),
|
||||||
|
createEntity("media_player.speaker_playing", "playing", "speaker"),
|
||||||
|
createEntity("media_player.speaker_paused", "paused", "speaker"),
|
||||||
|
createEntity("media_player.speaker_standby", "standby", "speaker"),
|
||||||
|
// Plant
|
||||||
|
createEntity("plant.ok", "ok"),
|
||||||
|
createEntity("plant.problem", "problem"),
|
||||||
|
// Remote
|
||||||
|
createEntity("remote.off", "off"),
|
||||||
|
createEntity("remote.on", "on"),
|
||||||
|
// Schedule
|
||||||
|
createEntity("schedule.off", "off"),
|
||||||
|
createEntity("schedule.on", "on"),
|
||||||
|
// Script
|
||||||
|
createEntity("script.off", "off"),
|
||||||
|
createEntity("script.on", "on"),
|
||||||
|
// Sensor
|
||||||
|
...SENSOR_DEVICE_CLASSES.map((dc) => createEntity(`sensor.${dc}`, "10", dc)),
|
||||||
|
// Battery sensor
|
||||||
|
...[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, "unknown", "not_valid"].map(
|
||||||
|
(value) =>
|
||||||
|
createEntity(`sensor.battery_${value}`, value.toString(), "battery")
|
||||||
|
),
|
||||||
|
// Siren
|
||||||
|
createEntity("siren.off", "off"),
|
||||||
|
createEntity("siren.on", "on"),
|
||||||
|
// Sun
|
||||||
|
createEntity("sun.below", "below_horizon"),
|
||||||
|
createEntity("sun.above", "above_horizon"),
|
||||||
|
createEntity("sun.unknown", "unknown"),
|
||||||
|
createEntity("sun.unavailable", "unavailable"),
|
||||||
|
// Switch
|
||||||
|
createEntity("switch.off", "off"),
|
||||||
|
createEntity("switch.on", "on"),
|
||||||
|
createEntity("switch.outlet_off", "off", "outlet"),
|
||||||
|
createEntity("switch.outlet_on", "on", "outlet"),
|
||||||
|
createEntity("switch.switch_off", "off", "switch"),
|
||||||
|
createEntity("switch.switch_on", "on", "switch"),
|
||||||
|
// Timer
|
||||||
|
createEntity("timer.idle", "idle"),
|
||||||
|
createEntity("timer.active", "active"),
|
||||||
|
createEntity("timer.paused", "paused"),
|
||||||
|
// Vacuum
|
||||||
|
createEntity("vacuum.docked", "docked"),
|
||||||
|
createEntity("vacuum.cleaning", "cleaning"),
|
||||||
|
createEntity("vacuum.paused", "paused"),
|
||||||
|
createEntity("vacuum.idle", "idle"),
|
||||||
|
createEntity("vacuum.returning", "returning"),
|
||||||
|
createEntity("vacuum.error", "error"),
|
||||||
|
createEntity("vacuum.cleaning", "cleaning"),
|
||||||
|
createEntity("vacuum.off", "off"),
|
||||||
|
createEntity("vacuum.on", "on"),
|
||||||
|
// Update
|
||||||
|
createEntity("update.off", "off", undefined, {
|
||||||
|
installed_version: "1.0.0",
|
||||||
|
latest_version: "2.0.0",
|
||||||
|
}),
|
||||||
|
createEntity("update.on", "on", undefined, {
|
||||||
|
installed_version: "1.0.0",
|
||||||
|
latest_version: "2.0.0",
|
||||||
|
}),
|
||||||
|
createEntity("update.installing", "on", undefined, {
|
||||||
|
installed_version: "1.0.0",
|
||||||
|
latest_version: "2.0.0",
|
||||||
|
in_progress: true,
|
||||||
|
}),
|
||||||
|
createEntity("update.off", "off", "firmware", {
|
||||||
|
installed_version: "1.0.0",
|
||||||
|
latest_version: "2.0.0",
|
||||||
|
}),
|
||||||
|
createEntity("update.on", "on", "firmware", {
|
||||||
|
installed_version: "1.0.0",
|
||||||
|
latest_version: "2.0.0",
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
function createEntity(
|
||||||
|
entity_id: string,
|
||||||
|
state: string,
|
||||||
|
device_class?: string,
|
||||||
|
attributes?: HassEntityAttributeBase | HassEntity["attributes"]
|
||||||
|
): HassEntity {
|
||||||
|
return {
|
||||||
|
entity_id,
|
||||||
|
state,
|
||||||
|
attributes: {
|
||||||
|
...attributes,
|
||||||
|
device_class: device_class,
|
||||||
|
},
|
||||||
|
last_changed: new Date().toString(),
|
||||||
|
last_updated: new Date().toString(),
|
||||||
|
context: {
|
||||||
|
id: "1",
|
||||||
|
parent_id: null,
|
||||||
|
user_id: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntityRowData = {
|
||||||
|
stateObj: HassEntity;
|
||||||
|
entity_id: string;
|
||||||
|
state: string;
|
||||||
|
device_class?: string;
|
||||||
|
domain: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function createRowData(stateObj: HassEntity): EntityRowData {
|
||||||
|
return {
|
||||||
|
stateObj,
|
||||||
|
entity_id: stateObj.entity_id,
|
||||||
|
state: stateObj.state,
|
||||||
|
device_class: stateObj.attributes.device_class,
|
||||||
|
domain: computeDomain(stateObj.entity_id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("demo-misc-entity-state")
|
||||||
|
export class DemoEntityState extends LitElement {
|
||||||
|
@property({ attribute: false }) hass?: HomeAssistant;
|
||||||
|
|
||||||
|
private _columns = memoizeOne(
|
||||||
|
(hass: HomeAssistant): DataTableColumnContainer => {
|
||||||
|
const columns: DataTableColumnContainer<EntityRowData> = {
|
||||||
|
icon: {
|
||||||
|
title: "Icon",
|
||||||
|
template: (_, entry) => html`
|
||||||
|
<state-badge
|
||||||
|
.stateObj=${entry.stateObj}
|
||||||
|
.stateColor=${true}
|
||||||
|
></state-badge>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
entity_id: {
|
||||||
|
title: "Entity ID",
|
||||||
|
width: "30%",
|
||||||
|
filterable: true,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
title: "State",
|
||||||
|
width: "20%",
|
||||||
|
sortable: true,
|
||||||
|
template: (_, entry) =>
|
||||||
|
html`${computeStateDisplay(
|
||||||
|
hass.localize,
|
||||||
|
entry.stateObj,
|
||||||
|
hass.locale,
|
||||||
|
hass.entities
|
||||||
|
)}`,
|
||||||
|
},
|
||||||
|
device_class: {
|
||||||
|
title: "Device class",
|
||||||
|
template: (dc) => html`${dc ?? "-"}`,
|
||||||
|
width: "20%",
|
||||||
|
filterable: true,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
title: "Domain",
|
||||||
|
template: (_, entry) => html`${computeDomain(entry.entity_id)}`,
|
||||||
|
width: "20%",
|
||||||
|
filterable: true,
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private _rows = memoizeOne((): EntityRowData[] =>
|
||||||
|
ENTITIES.map(createRowData)
|
||||||
|
);
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
const hass = provideHass(this);
|
||||||
|
hass.updateTranslations(null, "en");
|
||||||
|
hass.updateTranslations("config", "en");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.hass) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-data-table
|
||||||
|
.hass=${this.hass}
|
||||||
|
.columns=${this._columns(this.hass)}
|
||||||
|
.data=${this._rows()}
|
||||||
|
auto-height
|
||||||
|
></ha-data-table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
.color {
|
||||||
|
display: block;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: rgb(--color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-misc-entity-state": DemoEntityState;
|
||||||
|
}
|
||||||
|
}
|
@@ -283,7 +283,7 @@ export class DemoIntegrationCard extends LitElement {
|
|||||||
.deviceRegistryEntries=${createDeviceRegistryEntries(
|
.deviceRegistryEntries=${createDeviceRegistryEntries(
|
||||||
info.items[0]
|
info.items[0]
|
||||||
)}
|
)}
|
||||||
?disabled=${info.disabled}
|
?entryDisabled=${info.disabled}
|
||||||
.selectedConfigEntryId=${info.highlight}
|
.selectedConfigEntryId=${info.highlight}
|
||||||
></ha-integration-card>
|
></ha-integration-card>
|
||||||
`
|
`
|
||||||
|
@@ -29,7 +29,9 @@ class HassioAddonRepositoryEl extends LitElement {
|
|||||||
if (filter) {
|
if (filter) {
|
||||||
return filterAndSort(addons, filter);
|
return filterAndSort(addons, filter);
|
||||||
}
|
}
|
||||||
return addons.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name));
|
return addons.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(a.name, b.name, this.hass.locale.language)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
@@ -404,6 +404,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
? html`
|
? html`
|
||||||
<img
|
<img
|
||||||
class="logo"
|
class="logo"
|
||||||
|
alt=""
|
||||||
src="/api/hassio/addons/${this.addon.slug}/logo"
|
src="/api/hassio/addons/${this.addon.slug}/logo"
|
||||||
/>
|
/>
|
||||||
`
|
`
|
||||||
|
@@ -15,7 +15,7 @@ class SupervisorFormfieldLabel extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${this.imageUrl
|
${this.imageUrl
|
||||||
? html`<img loading="lazy" .src=${this.imageUrl} class="icon" />`
|
? html`<img loading="lazy" alt="" src=${this.imageUrl} class="icon" />`
|
||||||
: this.iconPath
|
: this.iconPath
|
||||||
? html`<ha-svg-icon .path=${this.iconPath} class="icon"></ha-svg-icon>`
|
? html`<ha-svg-icon .path=${this.iconPath} class="icon"></ha-svg-icon>`
|
||||||
: ""}
|
: ""}
|
||||||
|
@@ -35,7 +35,13 @@ class HassioAddons extends LitElement {
|
|||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
: this.supervisor.addon.addons
|
: this.supervisor.addon.addons
|
||||||
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(
|
||||||
|
a.name,
|
||||||
|
b.name,
|
||||||
|
this.hass.locale.language
|
||||||
|
)
|
||||||
|
)
|
||||||
.map(
|
.map(
|
||||||
(addon) => html`
|
(addon) => html`
|
||||||
<ha-card
|
<ha-card
|
||||||
|
@@ -28,6 +28,7 @@ class HassioDashboard extends LitElement {
|
|||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
|
back-path="/config"
|
||||||
.header=${this.supervisor.localize("panel.addons")}
|
.header=${this.supervisor.localize("panel.addons")}
|
||||||
>
|
>
|
||||||
<hassio-addons
|
<hassio-addons
|
||||||
|
@@ -15,7 +15,12 @@ import { HomeAssistant } from "../../../../src/types";
|
|||||||
import { HassioHardwareDialogParams } from "./show-dialog-hassio-hardware";
|
import { HassioHardwareDialogParams } from "./show-dialog-hassio-hardware";
|
||||||
|
|
||||||
const _filterDevices = memoizeOne(
|
const _filterDevices = memoizeOne(
|
||||||
(showAdvanced: boolean, hardware: HassioHardwareInfo, filter: string) =>
|
(
|
||||||
|
showAdvanced: boolean,
|
||||||
|
hardware: HassioHardwareInfo,
|
||||||
|
filter: string,
|
||||||
|
language: string
|
||||||
|
) =>
|
||||||
hardware.devices
|
hardware.devices
|
||||||
.filter(
|
.filter(
|
||||||
(device) =>
|
(device) =>
|
||||||
@@ -28,7 +33,7 @@ const _filterDevices = memoizeOne(
|
|||||||
.toLocaleLowerCase()
|
.toLocaleLowerCase()
|
||||||
.includes(filter))
|
.includes(filter))
|
||||||
)
|
)
|
||||||
.sort((a, b) => stringCompare(a.name, b.name))
|
.sort((a, b) => stringCompare(a.name, b.name, language))
|
||||||
);
|
);
|
||||||
|
|
||||||
@customElement("dialog-hassio-hardware")
|
@customElement("dialog-hassio-hardware")
|
||||||
@@ -56,7 +61,8 @@ class HassioHardwareDialog extends LitElement {
|
|||||||
const devices = _filterDevices(
|
const devices = _filterDevices(
|
||||||
this.hass.userData?.showAdvanced || false,
|
this.hass.userData?.showAdvanced || false,
|
||||||
this._dialogParams.hardware,
|
this._dialogParams.hardware,
|
||||||
(this._filter || "").toLowerCase()
|
(this._filter || "").toLowerCase(),
|
||||||
|
this.hass.locale.language
|
||||||
);
|
);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
@@ -68,7 +68,9 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
repo.slug !== "a0d7b954" && // Home Assistant Community Add-ons
|
repo.slug !== "a0d7b954" && // Home Assistant Community Add-ons
|
||||||
repo.slug !== "5c53de3b" // The ESPHome repository
|
repo.slug !== "5c53de3b" // The ESPHome repository
|
||||||
)
|
)
|
||||||
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(a.name, b.name, this.hass.locale.language)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
private _filteredUsedRepositories = memoizeOne(
|
private _filteredUsedRepositories = memoizeOne(
|
||||||
|
@@ -59,7 +59,11 @@ class HassioIngressView extends LitElement {
|
|||||||
return html` <hass-loading-screen></hass-loading-screen> `;
|
return html` <hass-loading-screen></hass-loading-screen> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
const iframe = html`<iframe src=${this._addon.ingress_url!}></iframe>`;
|
const iframe = html`<iframe
|
||||||
|
title=${this._addon.name}
|
||||||
|
src=${this._addon.ingress_url!}
|
||||||
|
>
|
||||||
|
</iframe>`;
|
||||||
|
|
||||||
if (!this.ingressPanel) {
|
if (!this.ingressPanel) {
|
||||||
return html`<hass-subpage
|
return html`<hass-subpage
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
"*.{js,ts}": [
|
"*.{js,ts}": ["prettier --write", "eslint --fix"],
|
||||||
"prettier --write",
|
|
||||||
'eslint --ignore-pattern "**/build-scripts/**/*.js" --fix',
|
|
||||||
],
|
|
||||||
"!(/translations)*.{json,css,md,html}": "prettier --write",
|
"!(/translations)*.{json,css,md,html}": "prettier --write",
|
||||||
"translations/*/*.json": (files) =>
|
"translations/*/*.json": (files) =>
|
||||||
'printf "%s\n" "These files should not be modified. Instead, make the necessary modifications in src/translations/en.json. Please see translations/README.md for details." ' +
|
'printf "%s\n" "Translation files should not be added or modified here. Instead, make the necessary modifications in src/translations/en.json. Other languages are managed externally. Please see https://developers.home-assistant.io/docs/translations/ for details." ' +
|
||||||
files.join(" ") +
|
files.join(" ") +
|
||||||
" >&2 && exit 1",
|
" >&2 && exit 1",
|
||||||
|
"/yarn.lock": () => "yarn dedupe",
|
||||||
};
|
};
|
||||||
|
212
package.json
212
package.json
@@ -24,22 +24,17 @@
|
|||||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^5.0.2",
|
"@braintree/sanitize-url": "^6.0.0",
|
||||||
"@codemirror/autocomplete": "^0.19.12",
|
"@codemirror/autocomplete": "^6.4.0",
|
||||||
"@codemirror/commands": "^0.19.8",
|
"@codemirror/commands": "^6.1.3",
|
||||||
"@codemirror/gutter": "^0.19.9",
|
"@codemirror/language": "^6.4.0",
|
||||||
"@codemirror/highlight": "^0.19.7",
|
"@codemirror/legacy-modes": "^6.3.1",
|
||||||
"@codemirror/history": "^0.19.2",
|
"@codemirror/search": "^6.2.3",
|
||||||
"@codemirror/legacy-modes": "^0.19.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/rectangular-selection": "^0.19.1",
|
"@codemirror/view": "^6.7.1",
|
||||||
"@codemirror/search": "^0.19.6",
|
|
||||||
"@codemirror/state": "^0.19.6",
|
|
||||||
"@codemirror/stream-parser": "^0.19.5",
|
|
||||||
"@codemirror/text": "^0.19.6",
|
|
||||||
"@codemirror/view": "^0.19.40",
|
|
||||||
"@formatjs/intl-datetimeformat": "^4.2.5",
|
"@formatjs/intl-datetimeformat": "^4.2.5",
|
||||||
"@formatjs/intl-getcanonicallocales": "^1.8.0",
|
"@formatjs/intl-getcanonicallocales": "^2.0.5",
|
||||||
"@formatjs/intl-locale": "^2.4.40",
|
"@formatjs/intl-locale": "^3.0.11",
|
||||||
"@formatjs/intl-numberformat": "^7.2.5",
|
"@formatjs/intl-numberformat": "^7.2.5",
|
||||||
"@formatjs/intl-pluralrules": "^4.1.5",
|
"@formatjs/intl-pluralrules": "^4.1.5",
|
||||||
"@formatjs/intl-relativetimeformat": "^9.3.2",
|
"@formatjs/intl-relativetimeformat": "^9.3.2",
|
||||||
@@ -49,34 +44,35 @@
|
|||||||
"@fullcalendar/interaction": "5.9.0",
|
"@fullcalendar/interaction": "5.9.0",
|
||||||
"@fullcalendar/list": "5.9.0",
|
"@fullcalendar/list": "5.9.0",
|
||||||
"@fullcalendar/timegrid": "5.9.0",
|
"@fullcalendar/timegrid": "5.9.0",
|
||||||
"@lit-labs/motion": "^1.0.2",
|
"@lezer/highlight": "^1.1.3",
|
||||||
"@lit-labs/virtualizer": "patch:@lit-labs/virtualizer@0.7.0-pre.2#./.yarn/patches/@lit-labs/virtualizer/event-target-shim.patch",
|
"@lit-labs/motion": "^1.0.3",
|
||||||
"@material/chips": "14.0.0-canary.261f2db59.0",
|
"@lit-labs/virtualizer": "^1.0.1",
|
||||||
"@material/data-table": "14.0.0-canary.261f2db59.0",
|
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/mwc-button": "0.25.3",
|
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/mwc-checkbox": "0.25.3",
|
"@material/mwc-button": "^0.27.0",
|
||||||
"@material/mwc-circular-progress": "0.25.3",
|
"@material/mwc-checkbox": "^0.27.0",
|
||||||
"@material/mwc-dialog": "0.25.3",
|
"@material/mwc-circular-progress": "^0.27.0",
|
||||||
"@material/mwc-drawer": "^0.25.3",
|
"@material/mwc-dialog": "^0.27.0",
|
||||||
"@material/mwc-fab": "0.25.3",
|
"@material/mwc-drawer": "^0.27.0",
|
||||||
"@material/mwc-formfield": "0.25.3",
|
"@material/mwc-fab": "^0.27.0",
|
||||||
"@material/mwc-icon-button": "patch:@material/mwc-icon-button@0.25.3#./.yarn/patches/@material/mwc-icon-button/remove-icon.patch",
|
"@material/mwc-formfield": "^0.27.0",
|
||||||
"@material/mwc-linear-progress": "0.25.3",
|
"@material/mwc-icon-button": "^0.27.0",
|
||||||
"@material/mwc-list": "^0.25.3",
|
"@material/mwc-linear-progress": "^0.27.0",
|
||||||
"@material/mwc-menu": "0.25.3",
|
"@material/mwc-list": "^0.27.0",
|
||||||
"@material/mwc-radio": "0.25.3",
|
"@material/mwc-menu": "^0.27.0",
|
||||||
"@material/mwc-ripple": "0.25.3",
|
"@material/mwc-radio": "^0.27.0",
|
||||||
"@material/mwc-select": "0.25.3",
|
"@material/mwc-ripple": "^0.27.0",
|
||||||
"@material/mwc-slider": "0.25.3",
|
"@material/mwc-select": "^0.27.0",
|
||||||
"@material/mwc-switch": "0.25.3",
|
"@material/mwc-slider": "^0.27.0",
|
||||||
"@material/mwc-tab": "0.25.3",
|
"@material/mwc-switch": "^0.27.0",
|
||||||
"@material/mwc-tab-bar": "0.25.3",
|
"@material/mwc-tab": "^0.27.0",
|
||||||
"@material/mwc-textarea": "^0.25.3",
|
"@material/mwc-tab-bar": "^0.27.0",
|
||||||
"@material/mwc-textfield": "0.25.3",
|
"@material/mwc-textarea": "^0.27.0",
|
||||||
"@material/mwc-top-app-bar-fixed": "^0.25.3",
|
"@material/mwc-textfield": "^0.27.0",
|
||||||
"@material/top-app-bar": "14.0.0-canary.261f2db59.0",
|
"@material/mwc-top-app-bar-fixed": "^0.27.0",
|
||||||
"@mdi/js": "7.0.96",
|
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@mdi/svg": "7.0.96",
|
"@mdi/js": "7.1.96",
|
||||||
|
"@mdi/svg": "7.1.96",
|
||||||
"@polymer/app-layout": "^3.1.0",
|
"@polymer/app-layout": "^3.1.0",
|
||||||
"@polymer/iron-flex-layout": "^3.0.1",
|
"@polymer/iron-flex-layout": "^3.0.1",
|
||||||
"@polymer/iron-icon": "^3.0.1",
|
"@polymer/iron-icon": "^3.0.1",
|
||||||
@@ -91,46 +87,48 @@
|
|||||||
"@polymer/paper-toast": "^3.0.1",
|
"@polymer/paper-toast": "^3.0.1",
|
||||||
"@polymer/paper-tooltip": "^3.0.1",
|
"@polymer/paper-tooltip": "^3.0.1",
|
||||||
"@polymer/polymer": "3.4.1",
|
"@polymer/polymer": "3.4.1",
|
||||||
"@thomasloven/round-slider": "0.5.4",
|
"@thomasloven/round-slider": "0.6.0",
|
||||||
"@vaadin/combo-box": "^23.2.0",
|
"@vaadin/combo-box": "^23.3.5",
|
||||||
"@vaadin/vaadin-themable-mixin": "^23.2.0",
|
"@vaadin/vaadin-themable-mixin": "^23.3.5",
|
||||||
"@vibrant/color": "^3.2.1-alpha.1",
|
"@vibrant/color": "^3.2.1-alpha.1",
|
||||||
"@vibrant/core": "^3.2.1-alpha.1",
|
"@vibrant/core": "^3.2.1-alpha.1",
|
||||||
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
|
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
|
||||||
"@vue/web-component-wrapper": "^1.2.0",
|
"@vue/web-component-wrapper": "^1.3.0",
|
||||||
"@webcomponents/scoped-custom-element-registry": "^0.0.5",
|
"@webcomponents/scoped-custom-element-registry": "^0.0.5",
|
||||||
"@webcomponents/webcomponentsjs": "^2.2.10",
|
"@webcomponents/webcomponentsjs": "^2.2.10",
|
||||||
"app-datepicker": "^5.0.1",
|
"app-datepicker": "^5.1.0",
|
||||||
"chart.js": "^3.3.2",
|
"chart.js": "^3.3.2",
|
||||||
"comlink": "^4.3.1",
|
"comlink": "^4.3.1",
|
||||||
"core-js": "^3.15.2",
|
"core-js": "^3.15.2",
|
||||||
"cropperjs": "^1.5.12",
|
"cropperjs": "^1.5.13",
|
||||||
"date-fns": "^2.23.0",
|
"date-fns": "^2.29.3",
|
||||||
|
"date-fns-tz": "^1.3.7",
|
||||||
"deep-clone-simple": "^1.1.1",
|
"deep-clone-simple": "^1.1.1",
|
||||||
"deep-freeze": "^0.0.1",
|
"deep-freeze": "^0.0.1",
|
||||||
"fuse.js": "^6.0.0",
|
"fuse.js": "^6.6.2",
|
||||||
"google-timezones-json": "^1.0.2",
|
"google-timezones-json": "^1.0.2",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"hls.js": "^1.2.3",
|
"hls.js": "^1.3.1",
|
||||||
"home-assistant-js-websocket": "^8.0.0",
|
"home-assistant-js-websocket": "^8.0.1",
|
||||||
"idb-keyval": "^5.1.3",
|
"idb-keyval": "^5.1.3",
|
||||||
"intl-messageformat": "^9.9.1",
|
"intl-messageformat": "^10.2.5",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"leaflet-draw": "^1.0.4",
|
"leaflet-draw": "^1.0.4",
|
||||||
"lit": "^2.1.2",
|
"lit": "^2.6.1",
|
||||||
"marked": "^4.0.12",
|
"marked": "^4.0.12",
|
||||||
"memoize-one": "^5.2.1",
|
"memoize-one": "^6.0.0",
|
||||||
"node-vibrant": "3.2.1-alpha.1",
|
"node-vibrant": "3.2.1-alpha.1",
|
||||||
"proxy-polyfill": "^0.3.2",
|
"proxy-polyfill": "^0.3.2",
|
||||||
"punycode": "^2.1.1",
|
"punycode": "^2.3.0",
|
||||||
"qr-scanner": "^1.3.0",
|
"qr-scanner": "^1.3.0",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.5.1",
|
||||||
"regenerator-runtime": "^0.13.8",
|
"regenerator-runtime": "^0.13.11",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"roboto-fontface": "^0.10.0",
|
"roboto-fontface": "^0.10.0",
|
||||||
|
"rrule": "^2.7.1",
|
||||||
"sortablejs": "^1.14.0",
|
"sortablejs": "^1.14.0",
|
||||||
"superstruct": "^0.15.2",
|
"superstruct": "^1.0.3",
|
||||||
"tinykeys": "^1.1.3",
|
"tinykeys": "^1.1.3",
|
||||||
"tsparticles": "^1.34.0",
|
"tsparticles": "^1.34.0",
|
||||||
"unfetch": "^4.1.0",
|
"unfetch": "^4.1.0",
|
||||||
@@ -139,28 +137,30 @@
|
|||||||
"vue": "^2.6.12",
|
"vue": "^2.6.12",
|
||||||
"vue2-daterange-picker": "^0.5.1",
|
"vue2-daterange-picker": "^0.5.1",
|
||||||
"weekstart": "^1.1.0",
|
"weekstart": "^1.1.0",
|
||||||
"workbox-cacheable-response": "^6.4.2",
|
"workbox-cacheable-response": "^6.5.4",
|
||||||
"workbox-core": "^6.4.2",
|
"workbox-core": "^6.5.4",
|
||||||
"workbox-expiration": "^6.4.2",
|
"workbox-expiration": "^6.5.4",
|
||||||
"workbox-precaching": "^6.4.2",
|
"workbox-precaching": "^6.5.4",
|
||||||
"workbox-routing": "^6.4.2",
|
"workbox-routing": "^6.5.4",
|
||||||
"workbox-strategies": "^6.4.2",
|
"workbox-strategies": "^6.5.4",
|
||||||
"xss": "^1.0.9"
|
"xss": "^1.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.15.5",
|
"@babel/core": "^7.20.2",
|
||||||
"@babel/plugin-external-helpers": "^7.14.5",
|
"@babel/plugin-external-helpers": "^7.18.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||||
"@babel/plugin-proposal-decorators": "^7.15.4",
|
"@babel/plugin-proposal-decorators": "^7.20.7",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.15.6",
|
"@babel/plugin-proposal-object-rest-spread": "^7.20.2",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
"@babel/plugin-proposal-optional-chaining": "^7.18.9",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
||||||
"@babel/preset-env": "^7.15.6",
|
"@babel/preset-env": "^7.20.2",
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
"@babel/preset-typescript": "^7.18.6",
|
||||||
"@koa/cors": "^3.1.0",
|
"@koa/cors": "^3.1.0",
|
||||||
|
"@octokit/auth-oauth-device": "^4.0.2",
|
||||||
|
"@octokit/rest": "^19.0.7",
|
||||||
"@open-wc/dev-server-hmr": "^0.0.2",
|
"@open-wc/dev-server-hmr": "^0.0.2",
|
||||||
"@rollup/plugin-babel": "^5.2.1",
|
"@rollup/plugin-babel": "^5.2.1",
|
||||||
"@rollup/plugin-commonjs": "^11.1.0",
|
"@rollup/plugin-commonjs": "^11.1.0",
|
||||||
@@ -169,91 +169,89 @@
|
|||||||
"@rollup/plugin-replace": "^2.3.2",
|
"@rollup/plugin-replace": "^2.3.2",
|
||||||
"@types/chromecast-caf-receiver": "5.0.12",
|
"@types/chromecast-caf-receiver": "5.0.12",
|
||||||
"@types/chromecast-caf-sender": "^1.0.3",
|
"@types/chromecast-caf-sender": "^1.0.3",
|
||||||
"@types/glob": "^7",
|
"@types/glob": "^8",
|
||||||
"@types/hammerjs": "^2.0.41",
|
"@types/hammerjs": "^2.0.41",
|
||||||
"@types/js-yaml": "^4",
|
"@types/js-yaml": "^4",
|
||||||
"@types/leaflet": "^1",
|
"@types/leaflet": "^1",
|
||||||
"@types/leaflet-draw": "^1",
|
"@types/leaflet-draw": "^1",
|
||||||
"@types/marked": "^4",
|
"@types/marked": "^4",
|
||||||
"@types/mocha": "^8",
|
"@types/mocha": "^8",
|
||||||
"@types/qrcode": "^1.4.2",
|
"@types/qrcode": "^1.5.0",
|
||||||
"@types/sortablejs": "^1",
|
"@types/sortablejs": "^1",
|
||||||
|
"@types/tar": "^6",
|
||||||
"@types/webspeechapi": "^0.0.29",
|
"@types/webspeechapi": "^0.0.29",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||||
"@typescript-eslint/parser": "^4.32.0",
|
"@typescript-eslint/parser": "^5.49.0",
|
||||||
"@web/dev-server": "^0.0.24",
|
"@web/dev-server": "^0.0.24",
|
||||||
"@web/dev-server-rollup": "^0.2.11",
|
"@web/dev-server-rollup": "^0.2.11",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^9.1.0",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"del": "^4.0.0",
|
"del": "^7.0.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-base": "^14.2.1",
|
||||||
"eslint-config-airbnb-typescript": "^14.0.0",
|
"eslint-config-airbnb-typescript": "^14.0.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-import-resolver-webpack": "^0.13.1",
|
"eslint-import-resolver-webpack": "^0.13.1",
|
||||||
"eslint-plugin-disable": "^2.0.1",
|
"eslint-plugin-disable": "^2.0.1",
|
||||||
"eslint-plugin-import": "^2.24.2",
|
"eslint-plugin-import": "^2.24.2",
|
||||||
"eslint-plugin-lit": "^1.6.1",
|
"eslint-plugin-lit": "^1.6.1",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
|
||||||
"eslint-plugin-unused-imports": "^1.1.5",
|
"eslint-plugin-unused-imports": "^1.1.5",
|
||||||
"eslint-plugin-wc": "^1.3.2",
|
"eslint-plugin-wc": "^1.4.0",
|
||||||
"fancy-log": "^1.3.3",
|
"fancy-log": "^2.0.0",
|
||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^11.1.0",
|
||||||
"glob": "^7.2.0",
|
"glob": "^8.1.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-flatmap": "^1.0.2",
|
"gulp-flatmap": "^1.0.2",
|
||||||
"gulp-json-transform": "^0.4.6",
|
"gulp-json-transform": "^0.4.6",
|
||||||
"gulp-merge-json": "^1.3.1",
|
"gulp-merge-json": "^2.1.2",
|
||||||
"gulp-rename": "^2.0.0",
|
"gulp-rename": "^2.0.0",
|
||||||
"gulp-zopfli-green": "^3.0.1",
|
"gulp-zopfli-green": "^3.0.1",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"husky": "^8.0.1",
|
"husky": "^8.0.3",
|
||||||
"instant-mocha": "^1.3.1",
|
"instant-mocha": "^1.3.1",
|
||||||
"lint-staged": "^13.0.3",
|
"jszip": "^3.10.1",
|
||||||
|
"lint-staged": "^13.1.0",
|
||||||
"lit-analyzer": "^1.2.1",
|
"lit-analyzer": "^1.2.1",
|
||||||
"lodash.template": "^4.5.0",
|
"lodash.template": "^4.5.0",
|
||||||
"magic-string": "^0.25.7",
|
"magic-string": "^0.25.7",
|
||||||
"map-stream": "^0.0.7",
|
"map-stream": "^0.0.7",
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
"mocha": "^8.4.0",
|
"mocha": "^8.4.0",
|
||||||
"object-hash": "^2.0.3",
|
"object-hash": "^3.0.0",
|
||||||
"open": "^7.0.4",
|
"open": "^8.4.0",
|
||||||
"pinst": "^3.0.0",
|
"pinst": "^3.0.0",
|
||||||
"prettier": "^2.4.1",
|
"prettier": "^2.8.3",
|
||||||
"require-dir": "^1.2.0",
|
"require-dir": "^1.2.0",
|
||||||
"rollup": "^2.8.2",
|
"rollup": "^2.8.2",
|
||||||
"rollup-plugin-string": "^3.0.0",
|
"rollup-plugin-string": "^3.0.0",
|
||||||
"rollup-plugin-terser": "^5.3.0",
|
"rollup-plugin-terser": "^5.3.0",
|
||||||
"rollup-plugin-visualizer": "^4.0.4",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
"serve": "^11.3.2",
|
"serve": "^11.3.2",
|
||||||
"sinon": "^11.0.0",
|
"sinon": "^15.0.1",
|
||||||
"source-map-url": "^0.4.0",
|
"source-map-url": "^0.4.0",
|
||||||
"systemjs": "^6.3.2",
|
"systemjs": "^6.3.2",
|
||||||
|
"tar": "^6.1.11",
|
||||||
"terser-webpack-plugin": "^5.2.4",
|
"terser-webpack-plugin": "^5.2.4",
|
||||||
"ts-lit-plugin": "^1.2.1",
|
"ts-lit-plugin": "^1.2.1",
|
||||||
"typescript": "^4.4.3",
|
"typescript": "^4.9.4",
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vinyl-source-stream": "^2.0.0",
|
"vinyl-source-stream": "^2.0.0",
|
||||||
"webpack": "^5.55.1",
|
"webpack": "^5.55.1",
|
||||||
"webpack-cli": "^4.8.0",
|
"webpack-cli": "^5.0.1",
|
||||||
"webpack-dev-server": "^4.3.0",
|
"webpack-dev-server": "^4.11.1",
|
||||||
"webpack-manifest-plugin": "^4.0.2",
|
"webpack-manifest-plugin": "^4.0.2",
|
||||||
"webpackbar": "^5.0.0-3",
|
"webpackbar": "^5.0.2",
|
||||||
"workbox-build": "^6.4.2"
|
"workbox-build": "^6.5.4"
|
||||||
},
|
},
|
||||||
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@polymer/polymer": "patch:@polymer/polymer@3.4.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
"@polymer/polymer": "patch:@polymer/polymer@3.4.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
||||||
"@webcomponents/webcomponentsjs": "^2.2.10",
|
"@webcomponents/webcomponentsjs": "^2.2.10"
|
||||||
"lit": "^2.1.2",
|
|
||||||
"lit-html": "2.1.2",
|
|
||||||
"lit-element": "3.1.2",
|
|
||||||
"@lit/reactive-element": "1.2.1"
|
|
||||||
},
|
},
|
||||||
"main": "src/home-assistant.js",
|
"main": "src/home-assistant.js",
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.2.3"
|
"packageManager": "yarn@3.3.1"
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20221027.0"
|
version = "20230128.0"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "The Home Assistant frontend"
|
description = "The Home Assistant frontend"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@@ -7,4 +7,4 @@ set -e
|
|||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
# Install node modules
|
# Install node modules
|
||||||
yarn install
|
yarn install
|
9
script/setup_translations
Executable file
9
script/setup_translations
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Setup translation fetching during development
|
||||||
|
|
||||||
|
# Stop on errors
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
./node_modules/.bin/gulp setup-and-fetch-nightly-translations
|
@@ -92,6 +92,7 @@ export class HaPasswordManagerPolyfill extends LitElement {
|
|||||||
<input
|
<input
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
.id=${schema.name}
|
.id=${schema.name}
|
||||||
|
.name=${schema.name}
|
||||||
.type=${inputType}
|
.type=${inputType}
|
||||||
.value=${this.stepData[schema.name] || ""}
|
.value=${this.stepData[schema.name] || ""}
|
||||||
.autocomplete=${schema.autocomplete}
|
.autocomplete=${schema.autocomplete}
|
||||||
|
@@ -8,6 +8,8 @@ import { BaseCastMessage } from "./types";
|
|||||||
|
|
||||||
export interface GetStatusMessage extends BaseCastMessage {
|
export interface GetStatusMessage extends BaseCastMessage {
|
||||||
type: "get_status";
|
type: "get_status";
|
||||||
|
hassUrl?: string;
|
||||||
|
hassUUID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnectMessage extends BaseCastMessage {
|
export interface ConnectMessage extends BaseCastMessage {
|
||||||
@@ -15,12 +17,15 @@ export interface ConnectMessage extends BaseCastMessage {
|
|||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
clientId: string | null;
|
clientId: string | null;
|
||||||
hassUrl: string;
|
hassUrl: string;
|
||||||
|
hassUUID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShowLovelaceViewMessage extends BaseCastMessage {
|
export interface ShowLovelaceViewMessage extends BaseCastMessage {
|
||||||
type: "show_lovelace_view";
|
type: "show_lovelace_view";
|
||||||
viewPath: string | number | null;
|
viewPath: string | number | null;
|
||||||
urlPath: string | null;
|
urlPath: string | null;
|
||||||
|
hassUrl: string;
|
||||||
|
hassUUID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShowDemoMessage extends BaseCastMessage {
|
export interface ShowDemoMessage extends BaseCastMessage {
|
||||||
@@ -43,6 +48,7 @@ export const castSendAuth = (cast: CastManager, auth: Auth) =>
|
|||||||
|
|
||||||
export const castSendShowLovelaceView = (
|
export const castSendShowLovelaceView = (
|
||||||
cast: CastManager,
|
cast: CastManager,
|
||||||
|
hassUrl: string,
|
||||||
viewPath: ShowLovelaceViewMessage["viewPath"],
|
viewPath: ShowLovelaceViewMessage["viewPath"],
|
||||||
urlPath?: string | null
|
urlPath?: string | null
|
||||||
) =>
|
) =>
|
||||||
@@ -50,6 +56,7 @@ export const castSendShowLovelaceView = (
|
|||||||
type: "show_lovelace_view",
|
type: "show_lovelace_view",
|
||||||
viewPath,
|
viewPath,
|
||||||
urlPath: urlPath || null,
|
urlPath: urlPath || null,
|
||||||
|
hassUrl: CAST_DEV ? CAST_DEV_HASS_URL : hassUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const castSendShowDemo = (cast: CastManager) =>
|
export const castSendShowDemo = (cast: CastManager) =>
|
||||||
|
@@ -7,6 +7,7 @@ export interface ReceiverStatusMessage extends BaseCastMessage {
|
|||||||
connected: boolean;
|
connected: boolean;
|
||||||
showDemo: boolean;
|
showDemo: boolean;
|
||||||
hassUrl?: string;
|
hassUrl?: string;
|
||||||
|
hassUUID?: string;
|
||||||
lovelacePath?: string | number | null;
|
lovelacePath?: string | number | null;
|
||||||
urlPath?: string | null;
|
urlPath?: string | null;
|
||||||
}
|
}
|
||||||
@@ -23,6 +24,7 @@ export const enum ReceiverErrorCode {
|
|||||||
CONNECTION_LOST = 3,
|
CONNECTION_LOST = 3,
|
||||||
HASS_URL_MISSING = 4,
|
HASS_URL_MISSING = 4,
|
||||||
NO_HTTPS = 5,
|
NO_HTTPS = 5,
|
||||||
|
WRONG_INSTANCE = 20,
|
||||||
NOT_CONNECTED = 21,
|
NOT_CONNECTED = 21,
|
||||||
FETCH_CONFIG_FAILED = 22,
|
FETCH_CONFIG_FAILED = 22,
|
||||||
}
|
}
|
||||||
|
5
src/common/array/literal-includes.ts
Normal file
5
src/common/array/literal-includes.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Creates a type predicate function for determining if an array literal includes a given value
|
||||||
|
export const arrayLiteralIncludes =
|
||||||
|
<T extends readonly unknown[]>(array: T) =>
|
||||||
|
(searchElement: unknown, fromIndex?: number): searchElement is T[number] =>
|
||||||
|
array.includes(searchElement as T[number], fromIndex);
|
@@ -1,5 +1,3 @@
|
|||||||
import { hex2rgb } from "./convert-color";
|
|
||||||
|
|
||||||
export const THEME_COLORS = new Set([
|
export const THEME_COLORS = new Set([
|
||||||
"primary",
|
"primary",
|
||||||
"accent",
|
"accent",
|
||||||
@@ -21,22 +19,17 @@ export const THEME_COLORS = new Set([
|
|||||||
"orange",
|
"orange",
|
||||||
"deep-orange",
|
"deep-orange",
|
||||||
"brown",
|
"brown",
|
||||||
|
"light-grey",
|
||||||
"grey",
|
"grey",
|
||||||
|
"dark-grey",
|
||||||
"blue-grey",
|
"blue-grey",
|
||||||
"black",
|
"black",
|
||||||
"white",
|
"white",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export function computeRgbColor(color: string): string {
|
export function computeCssColor(color: string): string {
|
||||||
if (THEME_COLORS.has(color)) {
|
if (THEME_COLORS.has(color)) {
|
||||||
return `var(--rgb-${color}-color)`;
|
return `var(--${color}-color)`;
|
||||||
}
|
|
||||||
if (color.startsWith("#")) {
|
|
||||||
try {
|
|
||||||
return hex2rgb(color).join(", ");
|
|
||||||
} catch (err) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,8 @@ import {
|
|||||||
mdiCommentAlert,
|
mdiCommentAlert,
|
||||||
mdiCounter,
|
mdiCounter,
|
||||||
mdiCurrentAc,
|
mdiCurrentAc,
|
||||||
|
mdiDatabase,
|
||||||
|
mdiEarHearing,
|
||||||
mdiEye,
|
mdiEye,
|
||||||
mdiFan,
|
mdiFan,
|
||||||
mdiFlash,
|
mdiFlash,
|
||||||
@@ -52,14 +54,18 @@ import {
|
|||||||
mdiScriptText,
|
mdiScriptText,
|
||||||
mdiSineWave,
|
mdiSineWave,
|
||||||
mdiSpeedometer,
|
mdiSpeedometer,
|
||||||
|
mdiSunWireless,
|
||||||
mdiThermometer,
|
mdiThermometer,
|
||||||
|
mdiThermometerLines,
|
||||||
mdiThermostat,
|
mdiThermostat,
|
||||||
mdiTimerOutline,
|
mdiTimerOutline,
|
||||||
|
mdiTransmissionTower,
|
||||||
mdiVideo,
|
mdiVideo,
|
||||||
mdiWater,
|
mdiWater,
|
||||||
mdiWaterPercent,
|
mdiWaterPercent,
|
||||||
mdiWeatherCloudy,
|
mdiWeatherCloudy,
|
||||||
mdiWeatherPouring,
|
mdiWeatherPouring,
|
||||||
|
mdiWeatherRainy,
|
||||||
mdiWeatherWindy,
|
mdiWeatherWindy,
|
||||||
mdiWeight,
|
mdiWeight,
|
||||||
mdiWhiteBalanceSunny,
|
mdiWhiteBalanceSunny,
|
||||||
@@ -113,6 +119,7 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
siren: mdiBullhorn,
|
siren: mdiBullhorn,
|
||||||
simple_alarm: mdiBell,
|
simple_alarm: mdiBell,
|
||||||
sun: mdiWhiteBalanceSunny,
|
sun: mdiWhiteBalanceSunny,
|
||||||
|
text: mdiFormTextbox,
|
||||||
timer: mdiTimerOutline,
|
timer: mdiTimerOutline,
|
||||||
updater: mdiCloudUpload,
|
updater: mdiCloudUpload,
|
||||||
vacuum: mdiRobotVacuum,
|
vacuum: mdiRobotVacuum,
|
||||||
@@ -124,10 +131,13 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
export const FIXED_DEVICE_CLASS_ICONS = {
|
export const FIXED_DEVICE_CLASS_ICONS = {
|
||||||
apparent_power: mdiFlash,
|
apparent_power: mdiFlash,
|
||||||
aqi: mdiAirFilter,
|
aqi: mdiAirFilter,
|
||||||
|
atmospheric_pressure: mdiThermometerLines,
|
||||||
// battery: mdiBattery, => not included by design since `sensorIcon()` will dynamically determine the icon
|
// battery: mdiBattery, => not included by design since `sensorIcon()` will dynamically determine the icon
|
||||||
carbon_dioxide: mdiMoleculeCo2,
|
carbon_dioxide: mdiMoleculeCo2,
|
||||||
carbon_monoxide: mdiMoleculeCo,
|
carbon_monoxide: mdiMoleculeCo,
|
||||||
current: mdiCurrentAc,
|
current: mdiCurrentAc,
|
||||||
|
data_rate: mdiTransmissionTower,
|
||||||
|
data_size: mdiDatabase,
|
||||||
date: mdiCalendar,
|
date: mdiCalendar,
|
||||||
distance: mdiArrowLeftRight,
|
distance: mdiArrowLeftRight,
|
||||||
duration: mdiProgressClock,
|
duration: mdiProgressClock,
|
||||||
@@ -136,6 +146,7 @@ export const FIXED_DEVICE_CLASS_ICONS = {
|
|||||||
gas: mdiMeterGas,
|
gas: mdiMeterGas,
|
||||||
humidity: mdiWaterPercent,
|
humidity: mdiWaterPercent,
|
||||||
illuminance: mdiBrightness5,
|
illuminance: mdiBrightness5,
|
||||||
|
irradiance: mdiSunWireless,
|
||||||
moisture: mdiWaterPercent,
|
moisture: mdiWaterPercent,
|
||||||
monetary: mdiCash,
|
monetary: mdiCash,
|
||||||
nitrogen_dioxide: mdiMolecule,
|
nitrogen_dioxide: mdiMolecule,
|
||||||
@@ -147,10 +158,12 @@ export const FIXED_DEVICE_CLASS_ICONS = {
|
|||||||
pm25: mdiMolecule,
|
pm25: mdiMolecule,
|
||||||
power: mdiFlash,
|
power: mdiFlash,
|
||||||
power_factor: mdiAngleAcute,
|
power_factor: mdiAngleAcute,
|
||||||
|
precipitation: mdiWeatherRainy,
|
||||||
precipitation_intensity: mdiWeatherPouring,
|
precipitation_intensity: mdiWeatherPouring,
|
||||||
pressure: mdiGauge,
|
pressure: mdiGauge,
|
||||||
reactive_power: mdiFlash,
|
reactive_power: mdiFlash,
|
||||||
signal_strength: mdiWifi,
|
signal_strength: mdiWifi,
|
||||||
|
sound_pressure: mdiEarHearing,
|
||||||
speed: mdiSpeedometer,
|
speed: mdiSpeedometer,
|
||||||
sulphur_dioxide: mdiMolecule,
|
sulphur_dioxide: mdiMolecule,
|
||||||
temperature: mdiThermometer,
|
temperature: mdiThermometer,
|
||||||
@@ -180,10 +193,20 @@ export const DOMAINS_WITH_CARD = [
|
|||||||
"script",
|
"script",
|
||||||
"select",
|
"select",
|
||||||
"timer",
|
"timer",
|
||||||
|
"text",
|
||||||
"vacuum",
|
"vacuum",
|
||||||
"water_heater",
|
"water_heater",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const SENSOR_ENTITIES = [
|
||||||
|
"sensor",
|
||||||
|
"binary_sensor",
|
||||||
|
"calendar",
|
||||||
|
"camera",
|
||||||
|
"device_tracker",
|
||||||
|
"weather",
|
||||||
|
];
|
||||||
|
|
||||||
/** Domains that render an input element instead of a text value when displayed in a row.
|
/** Domains that render an input element instead of a text value when displayed in a row.
|
||||||
* Those rows should then not show a cursor pointer when hovered (which would normally
|
* Those rows should then not show a cursor pointer when hovered (which would normally
|
||||||
* be the default) unless the element itself enforces it (e.g. a button). Also those elements
|
* be the default) unless the element itself enforces it (e.g. a button). Also those elements
|
||||||
@@ -212,6 +235,7 @@ export const DOMAINS_INPUT_ROW = [
|
|||||||
"script",
|
"script",
|
||||||
"select",
|
"select",
|
||||||
"switch",
|
"switch",
|
||||||
|
"text",
|
||||||
"vacuum",
|
"vacuum",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user