mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-25 00:59:29 +00:00
Compare commits
381 Commits
20230503.3
...
persistent
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ecba22d301 | ||
![]() |
72172cabc2 | ||
![]() |
eb552530e2 | ||
![]() |
1fe5d66a68 | ||
![]() |
7faa165558 | ||
![]() |
752bc192cd | ||
![]() |
e9961b93f9 | ||
![]() |
bbdcc021d4 | ||
![]() |
3d6cfc4037 | ||
![]() |
9b35c06eef | ||
![]() |
b46c74fe76 | ||
![]() |
5aa6ffe2e4 | ||
![]() |
4ffd31974c | ||
![]() |
1faef71dcb | ||
![]() |
1e5c35c158 | ||
![]() |
2e3ce4ae9e | ||
![]() |
07d37dd89f | ||
![]() |
33d6ad1b0b | ||
![]() |
386ed2167f | ||
![]() |
221f4f34a7 | ||
![]() |
c63c717d9f | ||
![]() |
1cb1bcf274 | ||
![]() |
30f2a49fbf | ||
![]() |
1cf24ffc8d | ||
![]() |
13b864e261 | ||
![]() |
7bc2ca3b65 | ||
![]() |
101e9323a7 | ||
![]() |
922e95b895 | ||
![]() |
baaa012101 | ||
![]() |
3888b1c48b | ||
![]() |
332af4003e | ||
![]() |
044a44e114 | ||
![]() |
13c932a8f8 | ||
![]() |
be1089302f | ||
![]() |
540df024d9 | ||
![]() |
e7c8bd4c41 | ||
![]() |
7c15a65bba | ||
![]() |
5381a467e5 | ||
![]() |
a96d3594ba | ||
![]() |
4526a46a56 | ||
![]() |
1d0d4755d0 | ||
![]() |
fa75b18a6b | ||
![]() |
cdd29c8bf7 | ||
![]() |
215f5e341a | ||
![]() |
8abb58ae7d | ||
![]() |
40c8301df0 | ||
![]() |
80f3d6aacb | ||
![]() |
41310007fe | ||
![]() |
195b1eef02 | ||
![]() |
8e9b5ea66b | ||
![]() |
827d89628d | ||
![]() |
cac341a938 | ||
![]() |
2b51228665 | ||
![]() |
79c010eb7b | ||
![]() |
2a4356ce86 | ||
![]() |
afdeb36258 | ||
![]() |
d4f4ee1e59 | ||
![]() |
bcceef30bb | ||
![]() |
356935fefc | ||
![]() |
49f59d7162 | ||
![]() |
67e8357bb9 | ||
![]() |
b8da712186 | ||
![]() |
a409f494a2 | ||
![]() |
3b32825e2a | ||
![]() |
12b7b903bc | ||
![]() |
3be601a3b9 | ||
![]() |
d0641d64bd | ||
![]() |
3a64f64894 | ||
![]() |
7182abfec5 | ||
![]() |
2076a083d3 | ||
![]() |
73317a48ee | ||
![]() |
b891c53994 | ||
![]() |
c1c18affbc | ||
![]() |
3bea2cf7f9 | ||
![]() |
fa1a6affa7 | ||
![]() |
197638b282 | ||
![]() |
6e3cf0975b | ||
![]() |
9875cb2723 | ||
![]() |
f8ea7e0ef2 | ||
![]() |
c821f4296e | ||
![]() |
5fc4e7a95d | ||
![]() |
49fa7ec4ed | ||
![]() |
780de42e4b | ||
![]() |
f7722a270f | ||
![]() |
e3faa618bf | ||
![]() |
655b630fa5 | ||
![]() |
983bba357a | ||
![]() |
17a2560d94 | ||
![]() |
eaffed9ff8 | ||
![]() |
273992c8e9 | ||
![]() |
c77905bd22 | ||
![]() |
15132783d4 | ||
![]() |
2b6cf55638 | ||
![]() |
e4eaa52d53 | ||
![]() |
e1f73dac02 | ||
![]() |
36de0e5c8c | ||
![]() |
549e4e7fb3 | ||
![]() |
dd9c4e35bf | ||
![]() |
8580d3f9bf | ||
![]() |
6d29b764d3 | ||
![]() |
78cff3a921 | ||
![]() |
e3c312feaf | ||
![]() |
31e4166248 | ||
![]() |
0442e3e06e | ||
![]() |
0a8252c16a | ||
![]() |
0a62d711f2 | ||
![]() |
d7c3ff3e9d | ||
![]() |
2767f866f3 | ||
![]() |
040d5af0aa | ||
![]() |
06c6e312b0 | ||
![]() |
841dffe563 | ||
![]() |
a41e0d446f | ||
![]() |
9a0f24cd8b | ||
![]() |
2e531a9006 | ||
![]() |
76255f2efb | ||
![]() |
19fc92419a | ||
![]() |
e7c2625cf1 | ||
![]() |
c39fdcda6e | ||
![]() |
fd1381ab3b | ||
![]() |
7b8f4d1e72 | ||
![]() |
b0a278df97 | ||
![]() |
93e31df106 | ||
![]() |
47fdae764f | ||
![]() |
b8efc06caa | ||
![]() |
fcacdf6534 | ||
![]() |
45d260f0ce | ||
![]() |
d5f46a69b0 | ||
![]() |
fe8eb333b9 | ||
![]() |
677cd2de10 | ||
![]() |
1470eb484f | ||
![]() |
10ee8fda5b | ||
![]() |
e044ddcb57 | ||
![]() |
29c564bb69 | ||
![]() |
1bf03f020e | ||
![]() |
6c684fd8ee | ||
![]() |
ddaf403378 | ||
![]() |
b337074758 | ||
![]() |
a96eff4d25 | ||
![]() |
e6bdc3a15e | ||
![]() |
33e15eec22 | ||
![]() |
3c0afd6cde | ||
![]() |
31a3fa02d9 | ||
![]() |
71954f545c | ||
![]() |
9f3e8abe69 | ||
![]() |
21f983572c | ||
![]() |
5667d71b02 | ||
![]() |
0d0e5fdaaa | ||
![]() |
b1f5ff26d9 | ||
![]() |
27451ca30e | ||
![]() |
928b4e6f1e | ||
![]() |
b63a32109e | ||
![]() |
efb0098eac | ||
![]() |
a67b845812 | ||
![]() |
d29b7626f3 | ||
![]() |
47ac7062dc | ||
![]() |
e7f5d927b1 | ||
![]() |
6b06393559 | ||
![]() |
efa02c309b | ||
![]() |
9b2e77e781 | ||
![]() |
24b4060c97 | ||
![]() |
5e4c1ab4fc | ||
![]() |
287e6dbb60 | ||
![]() |
40c9292e16 | ||
![]() |
d51dd00ec7 | ||
![]() |
0db50d13d3 | ||
![]() |
9eb3618d97 | ||
![]() |
03eee9c7d5 | ||
![]() |
a49d59f4c6 | ||
![]() |
990ade4294 | ||
![]() |
a4c57f09ad | ||
![]() |
c1fa6d6f8c | ||
![]() |
3bfcb808f5 | ||
![]() |
9a30fe81c6 | ||
![]() |
c864edee72 | ||
![]() |
36268d5048 | ||
![]() |
5217d427e9 | ||
![]() |
aea668e754 | ||
![]() |
2219c9bbd3 | ||
![]() |
9b896c63b6 | ||
![]() |
30af576ff5 | ||
![]() |
585db6ab3f | ||
![]() |
046475e7ac | ||
![]() |
648383addd | ||
![]() |
10018b4c32 | ||
![]() |
872d3e4875 | ||
![]() |
881f5e5012 | ||
![]() |
9797950f32 | ||
![]() |
25986f239e | ||
![]() |
b586210ff1 | ||
![]() |
748925ede9 | ||
![]() |
a9f1c4a198 | ||
![]() |
d914fb0cfc | ||
![]() |
5218e1352e | ||
![]() |
eb0759a3b3 | ||
![]() |
88522ed155 | ||
![]() |
64e7fc6591 | ||
![]() |
2ad6253b72 | ||
![]() |
7e5a85dbe7 | ||
![]() |
0771a780d9 | ||
![]() |
7b350e31dd | ||
![]() |
70fbf68603 | ||
![]() |
2b4f199337 | ||
![]() |
a70d7d8de3 | ||
![]() |
e0c1f98803 | ||
![]() |
4b7a517d98 | ||
![]() |
26d4839dfd | ||
![]() |
c358d724a7 | ||
![]() |
0ab7934c09 | ||
![]() |
6eac229901 | ||
![]() |
5006dfc138 | ||
![]() |
d9d38efd93 | ||
![]() |
9fe3a500d5 | ||
![]() |
3df7c50690 | ||
![]() |
38cf774a0d | ||
![]() |
98d22d38c3 | ||
![]() |
357dbb591b | ||
![]() |
aa5df06bc3 | ||
![]() |
07a66b4bff | ||
![]() |
f466196fa8 | ||
![]() |
04ae0b34af | ||
![]() |
6f48267dae | ||
![]() |
be1f5d99c8 | ||
![]() |
27b9b4dcc5 | ||
![]() |
08b57d6168 | ||
![]() |
3e474daa32 | ||
![]() |
48c1e8b56c | ||
![]() |
fd0c0a95ca | ||
![]() |
83570f2419 | ||
![]() |
633c6cfc9b | ||
![]() |
54b4c9f347 | ||
![]() |
85e7986b44 | ||
![]() |
da0cf9d950 | ||
![]() |
ef51336770 | ||
![]() |
a09db75980 | ||
![]() |
77d1b19ecb | ||
![]() |
fba12f35ac | ||
![]() |
00198c6937 | ||
![]() |
71bb540352 | ||
![]() |
c4ff1a8646 | ||
![]() |
a9c27ad8dd | ||
![]() |
dacdc62672 | ||
![]() |
cccce5711c | ||
![]() |
50bd9da94c | ||
![]() |
dde27c3524 | ||
![]() |
85acafe8a8 | ||
![]() |
c1748138a8 | ||
![]() |
9111f58e52 | ||
![]() |
cefaaadf95 | ||
![]() |
29846a168e | ||
![]() |
31c89d70c5 | ||
![]() |
d5cea75fe4 | ||
![]() |
35d212e850 | ||
![]() |
aea098ff17 | ||
![]() |
c5205ae8db | ||
![]() |
303087d049 | ||
![]() |
e9d9d89d79 | ||
![]() |
a5b5e61ed4 | ||
![]() |
22dc757382 | ||
![]() |
4ccfd6a3fc | ||
![]() |
5a36f100a9 | ||
![]() |
847c8407de | ||
![]() |
ed1784b70f | ||
![]() |
e8521c59eb | ||
![]() |
34e59e543b | ||
![]() |
330aa23801 | ||
![]() |
06db338a15 | ||
![]() |
8cff4cda47 | ||
![]() |
f7e7c916ba | ||
![]() |
13ab5ab70a | ||
![]() |
cc61131e4b | ||
![]() |
099aa54b80 | ||
![]() |
e35d795ba8 | ||
![]() |
39de8cd6ba | ||
![]() |
fdddf27162 | ||
![]() |
cec7a24234 | ||
![]() |
ea2e9de37a | ||
![]() |
d9cb288c1d | ||
![]() |
53bd4298e7 | ||
![]() |
5bea929c1e | ||
![]() |
eb220fa1a0 | ||
![]() |
67b64b2d5c | ||
![]() |
42aa4ab7c2 | ||
![]() |
d873f26db3 | ||
![]() |
e354f5de12 | ||
![]() |
92ed62985d | ||
![]() |
cbcca6e190 | ||
![]() |
2ed48d67c6 | ||
![]() |
8fb2bf472a | ||
![]() |
51bdf85642 | ||
![]() |
b7a4eb33cf | ||
![]() |
3c2d326b54 | ||
![]() |
24e6d19e18 | ||
![]() |
9370411019 | ||
![]() |
d5c7e7849e | ||
![]() |
c5e62248b9 | ||
![]() |
c5e0efb8e0 | ||
![]() |
82f88ca7d7 | ||
![]() |
c676cddb13 | ||
![]() |
036e2a9e46 | ||
![]() |
319d8bec29 | ||
![]() |
aa864cf0b6 | ||
![]() |
eabd8b54f4 | ||
![]() |
aa063d0a3e | ||
![]() |
75f080ee85 | ||
![]() |
557fe33807 | ||
![]() |
5bd49c18d1 | ||
![]() |
a461d58df2 | ||
![]() |
ae8eafe8f9 | ||
![]() |
450565799e | ||
![]() |
72403f4276 | ||
![]() |
d66ca0467e | ||
![]() |
d46201ebd8 | ||
![]() |
689d123890 | ||
![]() |
bcdb24849d | ||
![]() |
3838d76094 | ||
![]() |
3325cbfa28 | ||
![]() |
24fc2a0ccc | ||
![]() |
d6ea6f8041 | ||
![]() |
8384ef7a5c | ||
![]() |
2869c5f26b | ||
![]() |
c098c55b8f | ||
![]() |
fec974712f | ||
![]() |
0be5aa108c | ||
![]() |
ec36d4a381 | ||
![]() |
ccf3238318 | ||
![]() |
bcfa6c5a4b | ||
![]() |
e371f5d406 | ||
![]() |
6d4e3a0de3 | ||
![]() |
b845c54948 | ||
![]() |
87951ebf82 | ||
![]() |
586079917d | ||
![]() |
aa3fd70966 | ||
![]() |
a5ba2499c0 | ||
![]() |
36a87da1fe | ||
![]() |
8f75c314f5 | ||
![]() |
d04fc53f08 | ||
![]() |
c65c6f8767 | ||
![]() |
b81668fbce | ||
![]() |
2d8e23ba48 | ||
![]() |
e947f8120c | ||
![]() |
6424020f64 | ||
![]() |
a611930fa7 | ||
![]() |
f0e990f330 | ||
![]() |
8c1d2362a4 | ||
![]() |
69067010a3 | ||
![]() |
0b0ba97aee | ||
![]() |
792fe15dac | ||
![]() |
d5b8fa482c | ||
![]() |
2fefbbfe24 | ||
![]() |
22c509533a | ||
![]() |
544dfa0973 | ||
![]() |
aac3ec353b | ||
![]() |
efbc6d9069 | ||
![]() |
4e390b4c57 | ||
![]() |
849e65a2b3 | ||
![]() |
a6fdb54697 | ||
![]() |
aa196704b7 | ||
![]() |
c93fcb8a2a | ||
![]() |
5768764282 | ||
![]() |
e6c8881b21 | ||
![]() |
ac30335fc2 | ||
![]() |
1e5c30a259 | ||
![]() |
1da009b473 | ||
![]() |
02542e528e | ||
![]() |
c7ec6903fe | ||
![]() |
ecb2a73e2b | ||
![]() |
59db31cdb5 | ||
![]() |
643556ded3 | ||
![]() |
4e5a18d272 | ||
![]() |
ab237f19c0 | ||
![]() |
3fa3d333c4 | ||
![]() |
1cb7e798da | ||
![]() |
11640b31f6 | ||
![]() |
4740ce685f | ||
![]() |
d2321b535c | ||
![]() |
f185e886c3 | ||
![]() |
8695bbc490 | ||
![]() |
060f6ce3d8 | ||
![]() |
ed19cfeaaa | ||
![]() |
79d6453c7e | ||
![]() |
694fc7d4ba |
@@ -10,12 +10,30 @@ supports es6-module-dynamic-import
|
|||||||
not Safari < 13
|
not Safari < 13
|
||||||
not iOS < 13
|
not iOS < 13
|
||||||
|
|
||||||
|
# Exclude KaiOS, QQ, and UC browsers due to lack of sufficient feature support data
|
||||||
|
# Babel ignores these automatically, but we need here for Webpack to output ESM with dynamic imports
|
||||||
|
not KaiOS > 0
|
||||||
|
not QQAndroid > 0
|
||||||
|
not UCAndroid > 0
|
||||||
|
|
||||||
# Exclude unsupported browsers
|
# Exclude unsupported browsers
|
||||||
not dead
|
not dead
|
||||||
|
|
||||||
[legacy]
|
[legacy]
|
||||||
# Legacy builds are transpiled to ES5 (strict mode) but also must support some features that cannot be polyfilled:
|
# Legacy builds are served when modern requirements are not met and support browsers:
|
||||||
|
# - released in the last 7 years + current alpha/beta versionss
|
||||||
|
# - with global utilization above 0.05%
|
||||||
|
# The lattermost query ensures that support for popular old browsers is not dropped too early
|
||||||
|
# (e.g. IE 11, Android 4.4, or Samsung 4).
|
||||||
|
#
|
||||||
|
# In addition, legacy browsers must support some minimum features that cannot be polyfilled:
|
||||||
|
# - ES5 (strict mode)
|
||||||
# - web sockets to communicate with backend
|
# - web sockets to communicate with backend
|
||||||
# - inline SVG used widely in buttons, widgets, etc.
|
# - inline SVG used widely in buttons, widgets, etc.
|
||||||
# - custom events used for most user interactions
|
# - custom events used for most user interactions
|
||||||
supports use-strict and supports websockets and supports svg-html5 and supports customevent
|
# - CSS flexbox used in the majority of the layout
|
||||||
|
# Nearly all of these are redundant with the above rules.
|
||||||
|
# As of May 2023, only web sockets must be added to the query.
|
||||||
|
unreleased versions
|
||||||
|
last 7 years
|
||||||
|
> 0.05% and supports websockets
|
||||||
|
@@ -1,13 +1,7 @@
|
|||||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.148.1/containers/python-3/.devcontainer/base.Dockerfile
|
# 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.10
|
FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.11
|
||||||
|
|
||||||
ENV \
|
ENV \
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
DEBIAN_FRONTEND=noninteractive \
|
||||||
DEVCONTAINER=true \
|
DEVCONTAINER=true \
|
||||||
PATH=$PATH:./node_modules/.bin
|
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"
|
|
@@ -5,7 +5,7 @@
|
|||||||
"context": ".."
|
"context": ".."
|
||||||
},
|
},
|
||||||
"appPort": "8124:8123",
|
"appPort": "8124:8123",
|
||||||
"postCreateCommand": "script/bootstrap",
|
"postStartCommand": "script/bootstrap",
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
||||||
},
|
},
|
||||||
|
5
.github/release-drafter.yml
vendored
5
.github/release-drafter.yml
vendored
@@ -1,3 +1,8 @@
|
|||||||
|
categories:
|
||||||
|
- title: 'Dependency updates'
|
||||||
|
collapse-after: 3
|
||||||
|
labels:
|
||||||
|
- 'dependencies'
|
||||||
template: |
|
template: |
|
||||||
## What's Changed
|
## What's Changed
|
||||||
|
|
||||||
|
13
.github/workflows/cast_deployment.yaml
vendored
13
.github/workflows/cast_deployment.yaml
vendored
@@ -9,7 +9,6 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -22,14 +21,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -58,14 +57,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
25
.github/workflows/ci.yaml
vendored
25
.github/workflows/ci.yaml
vendored
@@ -11,7 +11,6 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@@ -25,11 +24,11 @@ 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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -48,11 +47,11 @@ 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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -66,11 +65,11 @@ 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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
@@ -84,11 +83,11 @@ 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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --immutable
|
run: yarn install --immutable
|
||||||
|
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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
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.
|
||||||
|
13
.github/workflows/demo_deployment.yaml
vendored
13
.github/workflows/demo_deployment.yaml
vendored
@@ -10,7 +10,6 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -23,14 +22,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
with:
|
with:
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -59,14 +58,14 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
7
.github/workflows/design_deployment.yaml
vendored
7
.github/workflows/design_deployment.yaml
vendored
@@ -6,7 +6,6 @@ on:
|
|||||||
- cron: "0 0 * * *"
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -17,12 +16,12 @@ jobs:
|
|||||||
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
7
.github/workflows/design_preview.yaml
vendored
7
.github/workflows/design_preview.yaml
vendored
@@ -11,7 +11,6 @@ on:
|
|||||||
- dev
|
- dev
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -22,12 +21,12 @@ jobs:
|
|||||||
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files from GitHub
|
- name: Check out files from GitHub
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
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@v4.0.0
|
- uses: dessant/lock-threads@v4.0.1
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
issue-lock-inactive-days: "30"
|
issue-lock-inactive-days: "30"
|
||||||
|
9
.github/workflows/nightly.yaml
vendored
9
.github/workflows/nightly.yaml
vendored
@@ -6,8 +6,7 @@ on:
|
|||||||
- cron: "0 1 * * *"
|
- cron: "0 1 * * *"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.10"
|
PYTHON_VERSION: "3.11"
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -21,17 +20,17 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
|
|
||||||
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
- name: Set up Python ${{ env.PYTHON_VERSION }}
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
|
9
.github/workflows/release-drafter.yaml
vendored
9
.github/workflows/release-drafter.yaml
vendored
@@ -5,8 +5,17 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update_release_draft:
|
update_release_draft:
|
||||||
|
permissions:
|
||||||
|
# write permission for contents is required to create a github release
|
||||||
|
contents: write
|
||||||
|
# write permission for pull-requests is required for autolabeler
|
||||||
|
# otherwise, read permission is required at least
|
||||||
|
pull-requests: read
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: release-drafter/release-drafter@v5
|
- uses: release-drafter/release-drafter@v5
|
||||||
|
11
.github/workflows/release.yaml
vendored
11
.github/workflows/release.yaml
vendored
@@ -6,8 +6,7 @@ on:
|
|||||||
- published
|
- published
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: "3.10"
|
PYTHON_VERSION: "3.11"
|
||||||
NODE_VERSION: 16
|
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
# Set default workflow permissions
|
# Set default workflow permissions
|
||||||
@@ -24,7 +23,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.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
|
|
||||||
- name: Verify version
|
- name: Verify version
|
||||||
uses: home-assistant/actions/helpers/verify-version@master
|
uses: home-assistant/actions/helpers/verify-version@master
|
||||||
@@ -34,10 +33,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: ${{ env.PYTHON_VERSION }}
|
||||||
|
|
||||||
- name: Set up Node ${{ env.NODE_VERSION }}
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3.6.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version-file: ".nvmrc"
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -77,7 +76,7 @@ jobs:
|
|||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: home-assistant/wheels@2023.04.0
|
uses: home-assistant/wheels@2023.04.0
|
||||||
with:
|
with:
|
||||||
abi: cp310
|
abi: cp311
|
||||||
tag: musllinux_1_2
|
tag: musllinux_1_2
|
||||||
arch: amd64
|
arch: amd64
|
||||||
wheels-key: ${{ secrets.WHEELS_KEY }}
|
wheels-key: ${{ secrets.WHEELS_KEY }}
|
||||||
|
6
.github/workflows/translations.yaml
vendored
6
.github/workflows/translations.yaml
vendored
@@ -7,19 +7,15 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- src/translations/en.json
|
- src/translations/en.json
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: 16
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
upload:
|
upload:
|
||||||
name: Upload
|
name: Upload
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v3.5.2
|
uses: actions/checkout@v3.5.3
|
||||||
|
|
||||||
- name: Upload Translations
|
- name: Upload Translations
|
||||||
run: |
|
run: |
|
||||||
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
|
||||||
|
|
||||||
./script/translations_upload_base
|
./script/translations_upload_base
|
||||||
|
39
.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch
Normal file
39
.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
diff --git a/modular/sortable.complete.esm.js b/modular/sortable.complete.esm.js
|
||||||
|
index 02e9f2d6bebeb430fe6e7c1cc3f9c3c9df051f14..bb8268b0844a1faa4108cc92c0be2a3dbaf23f83 100644
|
||||||
|
--- a/modular/sortable.complete.esm.js
|
||||||
|
+++ b/modular/sortable.complete.esm.js
|
||||||
|
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
||||||
|
target = parent; // store last element
|
||||||
|
}
|
||||||
|
/* jshint boss:true */
|
||||||
|
- while (parent = parent.parentNode);
|
||||||
|
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
||||||
|
}
|
||||||
|
|
||||||
|
_unhideGhostForTarget();
|
||||||
|
diff --git a/modular/sortable.core.esm.js b/modular/sortable.core.esm.js
|
||||||
|
index b04c8b4634f7c6b4ef1aadbb48afe6564306dea9..39a107163c8c336ebd669b5ea8a936af87e1c1e7 100644
|
||||||
|
--- a/modular/sortable.core.esm.js
|
||||||
|
+++ b/modular/sortable.core.esm.js
|
||||||
|
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
||||||
|
target = parent; // store last element
|
||||||
|
}
|
||||||
|
/* jshint boss:true */
|
||||||
|
- while (parent = parent.parentNode);
|
||||||
|
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
||||||
|
}
|
||||||
|
|
||||||
|
_unhideGhostForTarget();
|
||||||
|
diff --git a/modular/sortable.esm.js b/modular/sortable.esm.js
|
||||||
|
index 6ec7ed1bb557e21c2578200161e989c65d23150b..0a05475a22904472fac6c13f524c674da76584b0 100644
|
||||||
|
--- a/modular/sortable.esm.js
|
||||||
|
+++ b/modular/sortable.esm.js
|
||||||
|
@@ -1657,7 +1657,7 @@ Sortable.prototype =
|
||||||
|
target = parent; // store last element
|
||||||
|
}
|
||||||
|
/* jshint boss:true */
|
||||||
|
- while (parent = parent.parentNode);
|
||||||
|
+ while (parent = parent.parentNode || parent.getRootNode().host);
|
||||||
|
}
|
||||||
|
|
||||||
|
_unhideGhostForTarget();
|
File diff suppressed because one or more lines are too long
@@ -8,4 +8,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.5.0.cjs
|
yarnPath: .yarn/releases/yarn-3.6.0.cjs
|
||||||
|
@@ -76,7 +76,8 @@ module.exports.htmlMinifierOptions = {
|
|||||||
|
|
||||||
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
|
||||||
safari10: !latestBuild,
|
safari10: !latestBuild,
|
||||||
ecma: latestBuild ? undefined : 5,
|
ecma: latestBuild ? 2015 : 5,
|
||||||
|
module: latestBuild,
|
||||||
format: { comments: false },
|
format: { comments: false },
|
||||||
sourceMap: !isTestBuild,
|
sourceMap: !isTestBuild,
|
||||||
});
|
});
|
||||||
@@ -90,12 +91,14 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
setSpreadProperties: true,
|
setSpreadProperties: true,
|
||||||
},
|
},
|
||||||
browserslistEnv: latestBuild ? "modern" : "legacy",
|
browserslistEnv: latestBuild ? "modern" : "legacy",
|
||||||
|
// Must be unambiguous because some dependencies are CommonJS only
|
||||||
|
sourceType: "unambiguous",
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
"@babel/preset-env",
|
"@babel/preset-env",
|
||||||
{
|
{
|
||||||
useBuiltIns: latestBuild ? false : "entry",
|
useBuiltIns: latestBuild ? false : "entry",
|
||||||
corejs: latestBuild ? false : { version: "3.30", proposals: true },
|
corejs: latestBuild ? false : { version: "3.31", proposals: true },
|
||||||
bugfixes: true,
|
bugfixes: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -112,8 +115,6 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
ignoreModuleNotFound: true,
|
ignoreModuleNotFound: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// Support some proposals still in TC39 process
|
|
||||||
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
|
||||||
// Minify template literals for production
|
// Minify template literals for production
|
||||||
isProdBuild && [
|
isProdBuild && [
|
||||||
"template-html-minifier",
|
"template-html-minifier",
|
||||||
@@ -131,6 +132,13 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
|
|||||||
failOnError: true, // we can turn this off in case of false positives
|
failOnError: true, // we can turn this off in case of false positives
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
// Import helpers and regenerator from runtime package
|
||||||
|
[
|
||||||
|
"@babel/plugin-transform-runtime",
|
||||||
|
{ version: require("../package.json").dependencies["@babel/runtime"] },
|
||||||
|
],
|
||||||
|
// Support some proposals still in TC39 process
|
||||||
|
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
exclude: [
|
exclude: [
|
||||||
// \\ for Windows, / for Mac OS and Linux
|
// \\ for Windows, / for Mac OS and Linux
|
||||||
@@ -149,27 +157,27 @@ const publicPath = (latestBuild, root = "") =>
|
|||||||
latestBuild ? `${root}/frontend_latest/` : `${root}/frontend_es5/`;
|
latestBuild ? `${root}/frontend_latest/` : `${root}/frontend_es5/`;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BundleConfig {
|
BundleConfig {
|
||||||
// Object with entrypoints that need to be bundled
|
// Object with entrypoints that need to be bundled
|
||||||
entry: { [name: string]: pathToFile },
|
entry: { [name: string]: pathToFile },
|
||||||
// Folder where bundled files need to be written
|
// Folder where bundled files need to be written
|
||||||
outputPath: string,
|
outputPath: string,
|
||||||
// absolute url-path where bundled files can be found
|
// absolute url-path where bundled files can be found
|
||||||
publicPath: string,
|
publicPath: string,
|
||||||
// extra definitions that we need to replace in source
|
// extra definitions that we need to replace in source
|
||||||
defineOverlay: {[name: string]: value },
|
defineOverlay: {[name: string]: value },
|
||||||
// if this is a production build
|
// if this is a production build
|
||||||
isProdBuild: boolean,
|
isProdBuild: boolean,
|
||||||
// If we're targeting latest browsers
|
// If we're targeting latest browsers
|
||||||
latestBuild: boolean,
|
latestBuild: boolean,
|
||||||
// If we're doing a stats build (create nice chunk names)
|
// If we're doing a stats build (create nice chunk names)
|
||||||
isStatsBuild: boolean,
|
isStatsBuild: boolean,
|
||||||
// If it's just a test build in CI, skip time on source map generation
|
// If it's just a test build in CI, skip time on source map generation
|
||||||
isTestBuild: boolean,
|
isTestBuild: boolean,
|
||||||
// Names of entrypoints that should not be hashed
|
// Names of entrypoints that should not be hashed
|
||||||
dontHash: Set<string>
|
dontHash: Set<string>
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports.config = {
|
module.exports.config = {
|
||||||
app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild, isWDS }) {
|
app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild, isWDS }) {
|
||||||
@@ -252,6 +260,7 @@ module.exports.config = {
|
|||||||
isHassioBuild: true,
|
isHassioBuild: true,
|
||||||
defineOverlay: {
|
defineOverlay: {
|
||||||
__SUPERVISOR__: true,
|
__SUPERVISOR__: true,
|
||||||
|
__STATIC_PATH__: `"${paths.hassio_publicPath}/static/"`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@@ -1,18 +1,16 @@
|
|||||||
// Run HA develop mode
|
import gulp from "gulp";
|
||||||
|
import env from "../env.cjs";
|
||||||
const gulp = require("gulp");
|
import "./clean.js";
|
||||||
const env = require("../env.cjs");
|
import "./compress.js";
|
||||||
require("./clean.cjs");
|
import "./entry-html.js";
|
||||||
require("./translations.cjs");
|
import "./gather-static.js";
|
||||||
require("./locale-data.cjs");
|
import "./gen-icons-json.js";
|
||||||
require("./gen-icons-json.cjs");
|
import "./locale-data.js";
|
||||||
require("./gather-static.cjs");
|
import "./rollup.js";
|
||||||
require("./compress.cjs");
|
import "./service-worker.js";
|
||||||
require("./webpack.cjs");
|
import "./translations.js";
|
||||||
require("./service-worker.cjs");
|
import "./wds.js";
|
||||||
require("./entry-html.cjs");
|
import "./webpack.js";
|
||||||
require("./rollup.cjs");
|
|
||||||
require("./wds.cjs");
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-app",
|
"develop-app",
|
@@ -1,13 +1,12 @@
|
|||||||
const gulp = require("gulp");
|
import gulp from "gulp";
|
||||||
const env = require("../env.cjs");
|
import env from "../env.cjs";
|
||||||
|
import "./clean.js";
|
||||||
require("./clean.cjs");
|
import "./entry-html.js";
|
||||||
require("./translations.cjs");
|
import "./gather-static.js";
|
||||||
require("./gather-static.cjs");
|
import "./rollup.js";
|
||||||
require("./webpack.cjs");
|
import "./service-worker.js";
|
||||||
require("./service-worker.cjs");
|
import "./translations.js";
|
||||||
require("./entry-html.cjs");
|
import "./webpack.js";
|
||||||
require("./rollup.cjs");
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-cast",
|
"develop-cast",
|
@@ -1,37 +1,37 @@
|
|||||||
const del = import("del");
|
import { deleteSync } from "del";
|
||||||
const gulp = require("gulp");
|
import gulp from "gulp";
|
||||||
const paths = require("../paths.cjs");
|
import paths from "../paths.cjs";
|
||||||
require("./translations.cjs");
|
import "./translations.js";
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean",
|
"clean",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
(await del).deleteSync([paths.app_output_root, paths.build_dir])
|
deleteSync([paths.app_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-demo",
|
"clean-demo",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
(await del).deleteSync([paths.demo_output_root, paths.build_dir])
|
deleteSync([paths.demo_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-cast",
|
"clean-cast",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
(await del).deleteSync([paths.cast_output_root, paths.build_dir])
|
deleteSync([paths.cast_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("clean-hassio", async () =>
|
gulp.task("clean-hassio", async () =>
|
||||||
(await del).deleteSync([paths.hassio_output_root, paths.build_dir])
|
deleteSync([paths.hassio_output_root, paths.build_dir])
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
gulp.parallel("clean-translations", async () =>
|
gulp.parallel("clean-translations", async () =>
|
||||||
(await del).deleteSync([
|
deleteSync([
|
||||||
paths.gallery_output_root,
|
paths.gallery_output_root,
|
||||||
paths.gallery_build,
|
paths.gallery_build,
|
||||||
paths.build_dir,
|
paths.build_dir,
|
@@ -1,10 +1,10 @@
|
|||||||
// Tasks to compress
|
// Tasks to compress
|
||||||
|
|
||||||
const gulp = require("gulp");
|
import gulp from "gulp";
|
||||||
const zopfli = require("gulp-zopfli-green");
|
import zopfli from "gulp-zopfli-green";
|
||||||
const merge = require("merge-stream");
|
import merge from "merge-stream";
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
const paths = require("../paths.cjs");
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const zopfliOptions = { threshold: 150 };
|
const zopfliOptions = { threshold: 150 };
|
||||||
|
|
@@ -1,15 +1,13 @@
|
|||||||
// Run demo develop mode
|
import gulp from "gulp";
|
||||||
const gulp = require("gulp");
|
import env from "../env.cjs";
|
||||||
const env = require("../env.cjs");
|
import "./clean.js";
|
||||||
|
import "./entry-html.js";
|
||||||
require("./clean.cjs");
|
import "./gather-static.js";
|
||||||
require("./translations.cjs");
|
import "./gen-icons-json.js";
|
||||||
require("./gen-icons-json.cjs");
|
import "./rollup.js";
|
||||||
require("./gather-static.cjs");
|
import "./service-worker.js";
|
||||||
require("./webpack.cjs");
|
import "./translations.js";
|
||||||
require("./service-worker.cjs");
|
import "./webpack.js";
|
||||||
require("./entry-html.cjs");
|
|
||||||
require("./rollup.cjs");
|
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-demo",
|
"develop-demo",
|
@@ -1,6 +1,6 @@
|
|||||||
const gulp = require("gulp");
|
import fs from "fs/promises";
|
||||||
const fs = require("fs/promises");
|
import gulp from "gulp";
|
||||||
const mapStream = require("map-stream");
|
import mapStream from "map-stream";
|
||||||
|
|
||||||
const inDirFrontend = "translations/frontend";
|
const inDirFrontend = "translations/frontend";
|
||||||
const inDirBackend = "translations/backend";
|
const inDirBackend = "translations/backend";
|
@@ -1,12 +1,13 @@
|
|||||||
// Tasks to generate entry HTML
|
// Tasks to generate entry HTML
|
||||||
const gulp = require("gulp");
|
|
||||||
const fs = require("fs-extra");
|
import fs from "fs-extra";
|
||||||
const path = require("path");
|
import gulp from "gulp";
|
||||||
const template = require("lodash.template");
|
import { minify } from "html-minifier-terser";
|
||||||
const { minify } = require("html-minifier-terser");
|
import template from "lodash.template";
|
||||||
const paths = require("../paths.cjs");
|
import path from "path";
|
||||||
const env = require("../env.cjs");
|
import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
|
||||||
const { htmlMinifierOptions, terserOptions } = require("../bundle.cjs");
|
import env from "../env.cjs";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const renderTemplate = (templateFile, data = {}) => {
|
const renderTemplate = (templateFile, data = {}) => {
|
||||||
const compiled = template(
|
const compiled = template(
|
||||||
@@ -89,9 +90,11 @@ const genPagesProdTask =
|
|||||||
inputSub = "src/html"
|
inputSub = "src/html"
|
||||||
) =>
|
) =>
|
||||||
async () => {
|
async () => {
|
||||||
const latestManifest = require(path.resolve(outputLatest, "manifest.json"));
|
const latestManifest = fs.readJsonSync(
|
||||||
|
path.resolve(outputLatest, "manifest.json")
|
||||||
|
);
|
||||||
const es5Manifest = outputES5
|
const es5Manifest = outputES5
|
||||||
? require(path.resolve(outputES5, "manifest.json"))
|
? fs.readJsonSync(path.resolve(outputES5, "manifest.json"))
|
||||||
: {};
|
: {};
|
||||||
const minifiedHTML = [];
|
const minifiedHTML = [];
|
||||||
for (const [page, entries] of Object.entries(pageEntries)) {
|
for (const [page, entries] of Object.entries(pageEntries)) {
|
@@ -1,15 +1,15 @@
|
|||||||
// Task to download the latest Lokalise translations from the nightly workflow artifacts
|
// Task to download the latest Lokalise translations from the nightly workflow artifacts
|
||||||
|
|
||||||
const del = import("del");
|
import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
|
||||||
const fs = require("fs/promises");
|
import { retry } from "@octokit/plugin-retry";
|
||||||
const path = require("path");
|
import { Octokit } from "@octokit/rest";
|
||||||
const process = require("process");
|
import { deleteAsync } from "del";
|
||||||
const gulp = require("gulp");
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
||||||
const jszip = require("jszip");
|
import gulp from "gulp";
|
||||||
const tar = require("tar");
|
import jszip from "jszip";
|
||||||
const { Octokit } = require("@octokit/rest");
|
import path from "path";
|
||||||
const { retry } = require("@octokit/plugin-retry");
|
import process from "process";
|
||||||
const { createOAuthDeviceAuth } = require("@octokit/auth-oauth-device");
|
import tar from "tar";
|
||||||
|
|
||||||
const MAX_AGE = 24; // hours
|
const MAX_AGE = 24; // hours
|
||||||
const OWNER = "home-assistant";
|
const OWNER = "home-assistant";
|
||||||
@@ -38,7 +38,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
// and stop if they are not old enough
|
// and stop if they are not old enough
|
||||||
let currentArtifact;
|
let currentArtifact;
|
||||||
try {
|
try {
|
||||||
currentArtifact = JSON.parse(await fs.readFile(ARTIFACT_FILE, "utf-8"));
|
currentArtifact = JSON.parse(await readFile(ARTIFACT_FILE, "utf-8"));
|
||||||
const currentAge =
|
const currentAge =
|
||||||
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
|
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
|
||||||
if (currentAge < MAX_AGE) {
|
if (currentAge < MAX_AGE) {
|
||||||
@@ -53,7 +53,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To store file writing promises
|
// To store file writing promises
|
||||||
const createExtractDir = fs.mkdir(EXTRACT_DIR, { recursive: true });
|
const createExtractDir = mkdir(EXTRACT_DIR, { recursive: true });
|
||||||
const writings = [];
|
const writings = [];
|
||||||
|
|
||||||
// Authenticate to GitHub using GitHub action token if it exists,
|
// Authenticate to GitHub using GitHub action token if it exists,
|
||||||
@@ -63,7 +63,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
tokenAuth = { token: process.env.GITHUB_TOKEN };
|
tokenAuth = { token: process.env.GITHUB_TOKEN };
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
tokenAuth = JSON.parse(await fs.readFile(TOKEN_FILE, "utf-8"));
|
tokenAuth = JSON.parse(await readFile(TOKEN_FILE, "utf-8"));
|
||||||
} catch {
|
} catch {
|
||||||
if (!allowTokenSetup) {
|
if (!allowTokenSetup) {
|
||||||
console.log("No token found so build wil continue with English only");
|
console.log("No token found so build wil continue with English only");
|
||||||
@@ -88,7 +88,7 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
tokenAuth = await auth({ type: "oauth" });
|
tokenAuth = await auth({ type: "oauth" });
|
||||||
writings.push(
|
writings.push(
|
||||||
createExtractDir.then(
|
createExtractDir.then(
|
||||||
fs.writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
|
writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -132,17 +132,13 @@ gulp.task("fetch-nightly-translations", async function () {
|
|||||||
}
|
}
|
||||||
writings.push(
|
writings.push(
|
||||||
createExtractDir.then(
|
createExtractDir.then(
|
||||||
fs.writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
|
writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove the current translations
|
// Remove the current translations
|
||||||
const deleteCurrent = Promise.all(writings).then(
|
const deleteCurrent = Promise.all(writings).then(
|
||||||
(await del).deleteAsync([
|
deleteAsync([`${EXTRACT_DIR}/*`, `!${ARTIFACT_FILE}`, `!${TOKEN_FILE}`])
|
||||||
`${EXTRACT_DIR}/*`,
|
|
||||||
`!${ARTIFACT_FILE}`,
|
|
||||||
`!${TOKEN_FILE}`,
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
|
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
|
@@ -1,22 +1,19 @@
|
|||||||
// Run demo develop mode
|
import fs from "fs";
|
||||||
const gulp = require("gulp");
|
import { glob } from "glob";
|
||||||
const fs = require("fs");
|
import gulp from "gulp";
|
||||||
const path = require("path");
|
import yaml from "js-yaml";
|
||||||
const { marked } = require("marked");
|
import { marked } from "marked";
|
||||||
const { glob } = require("glob");
|
import path from "path";
|
||||||
const yaml = require("js-yaml");
|
import env from "../env.cjs";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
const env = require("../env.cjs");
|
import "./clean.js";
|
||||||
const paths = require("../paths.cjs");
|
import "./entry-html.js";
|
||||||
|
import "./gather-static.js";
|
||||||
require("./clean.cjs");
|
import "./gen-icons-json.js";
|
||||||
require("./translations.cjs");
|
import "./rollup.js";
|
||||||
require("./gen-icons-json.cjs");
|
import "./service-worker.js";
|
||||||
require("./gather-static.cjs");
|
import "./translations.js";
|
||||||
require("./webpack.cjs");
|
import "./webpack.js";
|
||||||
require("./service-worker.cjs");
|
|
||||||
require("./entry-html.cjs");
|
|
||||||
require("./rollup.cjs");
|
|
||||||
|
|
||||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
@@ -1,9 +1,9 @@
|
|||||||
// Gulp task to gather all static files.
|
// Gulp task to gather all static files.
|
||||||
|
|
||||||
const gulp = require("gulp");
|
import fs from "fs-extra";
|
||||||
const path = require("path");
|
import gulp from "gulp";
|
||||||
const fs = require("fs-extra");
|
import path from "path";
|
||||||
const paths = require("../paths.cjs");
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const npmPath = (...parts) =>
|
const npmPath = (...parts) =>
|
||||||
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
path.resolve(paths.polymer_dir, "node_modules", ...parts);
|
||||||
@@ -111,9 +111,10 @@ gulp.task("copy-translations-supervisor", async () => {
|
|||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-locale-data-supervisor", async () => {
|
gulp.task("copy-static-supervisor", async () => {
|
||||||
const staticDir = paths.hassio_output_static;
|
const staticDir = paths.hassio_output_static;
|
||||||
copyLocaleData(staticDir);
|
copyLocaleData(staticDir);
|
||||||
|
copyFonts(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-static-app", async () => {
|
gulp.task("copy-static-app", async () => {
|
@@ -1,17 +1,15 @@
|
|||||||
const gulp = require("gulp");
|
import fs from "fs";
|
||||||
const path = require("path");
|
import gulp from "gulp";
|
||||||
const fs = require("fs");
|
import hash from "object-hash";
|
||||||
const hash = require("object-hash");
|
import path from "path";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const ICON_PACKAGE_PATH = path.resolve(
|
const ICON_PACKAGE_PATH = path.resolve("node_modules/@mdi/svg/");
|
||||||
__dirname,
|
|
||||||
"../../node_modules/@mdi/svg/"
|
|
||||||
);
|
|
||||||
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
|
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
|
||||||
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
const PACKAGE_PATH = path.resolve(ICON_PACKAGE_PATH, "package.json");
|
||||||
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
const ICON_PATH = path.resolve(ICON_PACKAGE_PATH, "svg");
|
||||||
const OUTPUT_DIR = path.resolve(__dirname, "../../build/mdi");
|
const OUTPUT_DIR = path.resolve(paths.build_dir, "mdi");
|
||||||
const REMOVED_ICONS_PATH = path.resolve(__dirname, "../removedIcons.json");
|
const REMOVED_ICONS_PATH = new URL("../removedIcons.json", import.meta.url);
|
||||||
|
|
||||||
const encoding = "utf8";
|
const encoding = "utf8";
|
||||||
|
|
@@ -1,13 +1,13 @@
|
|||||||
const gulp = require("gulp");
|
import gulp from "gulp";
|
||||||
const env = require("../env.cjs");
|
import env from "../env.cjs";
|
||||||
require("./clean.cjs");
|
import "./clean.js";
|
||||||
require("./compress.cjs");
|
import "./compress.js";
|
||||||
require("./entry-html.cjs");
|
import "./entry-html.js";
|
||||||
require("./gather-static.cjs");
|
import "./gather-static.js";
|
||||||
require("./gen-icons-json.cjs");
|
import "./gen-icons-json.js";
|
||||||
require("./rollup.cjs");
|
import "./rollup.js";
|
||||||
require("./translations.cjs");
|
import "./translations.js";
|
||||||
require("./webpack.cjs");
|
import "./webpack.js";
|
||||||
|
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"develop-hassio",
|
"develop-hassio",
|
||||||
@@ -21,7 +21,7 @@ gulp.task(
|
|||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-locale-data-supervisor",
|
"copy-static-supervisor",
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -37,7 +37,7 @@ gulp.task(
|
|||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"copy-locale-data-supervisor",
|
"copy-static-supervisor",
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
||||||
"gen-pages-hassio-prod",
|
"gen-pages-hassio-prod",
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
@@ -1,18 +1,15 @@
|
|||||||
const del = import("del");
|
import { deleteSync } from "del";
|
||||||
const path = require("path");
|
import fs from "fs";
|
||||||
const gulp = require("gulp");
|
import gulp from "gulp";
|
||||||
const fs = require("fs");
|
import path from "path";
|
||||||
const paths = require("../paths.cjs");
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const outDir = "build/locale-data";
|
const outDir = "build/locale-data";
|
||||||
|
|
||||||
gulp.task("clean-locale-data", async () => (await del).deleteSync([outDir]));
|
gulp.task("clean-locale-data", async () => deleteSync([outDir]));
|
||||||
|
|
||||||
gulp.task("ensure-locale-data-build-dir", (done) => {
|
gulp.task("ensure-locale-data-build-dir", async () => {
|
||||||
if (!fs.existsSync(outDir)) {
|
fs.mkdirSync(outDir, { recursive: true });
|
||||||
fs.mkdirSync(outDir, { recursive: true });
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const modules = {
|
const modules = {
|
||||||
@@ -20,6 +17,7 @@ const modules = {
|
|||||||
"intl-datetimeformat": "DateTimeFormat",
|
"intl-datetimeformat": "DateTimeFormat",
|
||||||
"intl-numberformat": "NumberFormat",
|
"intl-numberformat": "NumberFormat",
|
||||||
"intl-displaynames": "DisplayNames",
|
"intl-displaynames": "DisplayNames",
|
||||||
|
"intl-listformat": "ListFormat",
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task("create-locale-data", (done) => {
|
gulp.task("create-locale-data", (done) => {
|
||||||
@@ -31,11 +29,14 @@ gulp.task("create-locale-data", (done) => {
|
|||||||
Object.entries(modules).forEach(([module, className]) => {
|
Object.entries(modules).forEach(([module, className]) => {
|
||||||
Object.keys(translationMeta).forEach((lang) => {
|
Object.keys(translationMeta).forEach((lang) => {
|
||||||
try {
|
try {
|
||||||
const localeData = String(
|
const localeData = fs
|
||||||
fs.readFileSync(
|
.readFileSync(
|
||||||
require.resolve(`@formatjs/${module}/locale-data/${lang}.js`)
|
path.resolve(
|
||||||
|
paths.polymer_dir,
|
||||||
|
`node_modules/@formatjs/${module}/locale-data/${lang}.js`
|
||||||
|
),
|
||||||
|
"utf-8"
|
||||||
)
|
)
|
||||||
)
|
|
||||||
.replace(
|
.replace(
|
||||||
new RegExp(
|
new RegExp(
|
||||||
`\\/\\*\\s*@generated\\s*\\*\\/\\s*\\/\\/\\s*prettier-ignore\\s*if\\s*\\(Intl\\.${className}\\s*&&\\s*typeof\\s*Intl\\.${className}\\.__addLocaleData\\s*===\\s*'function'\\)\\s*{\\s*Intl\\.${className}\\.__addLocaleData\\(`,
|
`\\/\\*\\s*@generated\\s*\\*\\/\\s*\\/\\/\\s*prettier-ignore\\s*if\\s*\\(Intl\\.${className}\\s*&&\\s*typeof\\s*Intl\\.${className}\\.__addLocaleData\\s*===\\s*'function'\\)\\s*{\\s*Intl\\.${className}\\.__addLocaleData\\(`,
|
||||||
@@ -46,15 +47,13 @@ gulp.task("create-locale-data", (done) => {
|
|||||||
.replace(/\)\s*}/im, "");
|
.replace(/\)\s*}/im, "");
|
||||||
// make sure we have valid JSON
|
// make sure we have valid JSON
|
||||||
JSON.parse(localeData);
|
JSON.parse(localeData);
|
||||||
if (!fs.existsSync(path.join(outDir, module))) {
|
fs.mkdirSync(path.join(outDir, module), { recursive: true });
|
||||||
fs.mkdirSync(path.join(outDir, module), { recursive: true });
|
|
||||||
}
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(outDir, `${module}/${lang}.json`),
|
path.join(outDir, `${module}/${lang}.json`),
|
||||||
localeData
|
localeData
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code !== "MODULE_NOT_FOUND") {
|
if (e.code !== "ENOENT") {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,13 +1,14 @@
|
|||||||
// Tasks to run Rollup
|
// Tasks to run Rollup
|
||||||
const path = require("path");
|
|
||||||
const gulp = require("gulp");
|
import log from "fancy-log";
|
||||||
const rollup = require("rollup");
|
import gulp from "gulp";
|
||||||
const handler = require("serve-handler");
|
import http from "http";
|
||||||
const http = require("http");
|
import open from "open";
|
||||||
const log = require("fancy-log");
|
import path from "path";
|
||||||
const open = require("open");
|
import { rollup } from "rollup";
|
||||||
const rollupConfig = require("../rollup.cjs");
|
import handler from "serve-handler";
|
||||||
const paths = require("../paths.cjs");
|
import paths from "../paths.cjs";
|
||||||
|
import rollupConfig from "../rollup.cjs";
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) =>
|
const bothBuilds = (createConfigFunc, params) =>
|
||||||
gulp.series(
|
gulp.series(
|
@@ -1,11 +1,12 @@
|
|||||||
// 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
|
||||||
const gulp = require("gulp");
|
|
||||||
const path = require("path");
|
import fs from "fs-extra";
|
||||||
const fs = require("fs-extra");
|
import gulp from "gulp";
|
||||||
const workboxBuild = require("workbox-build");
|
import path from "path";
|
||||||
const sourceMapUrl = require("source-map-url");
|
import sourceMapUrl from "source-map-url";
|
||||||
const paths = require("../paths.cjs");
|
import workboxBuild from "workbox-build";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
|
|
||||||
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
|
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
|
||||||
|
|
||||||
@@ -28,10 +29,9 @@ self.addEventListener('install', (event) => {
|
|||||||
|
|
||||||
gulp.task("gen-service-worker-app-prod", async () => {
|
gulp.task("gen-service-worker-app-prod", async () => {
|
||||||
// Read bundled source file
|
// Read bundled source file
|
||||||
const bundleManifestLatest = require(path.resolve(
|
const bundleManifestLatest = fs.readJsonSync(
|
||||||
paths.app_output_latest,
|
path.resolve(paths.app_output_latest, "manifest.json")
|
||||||
"manifest.json"
|
);
|
||||||
));
|
|
||||||
let serviceWorkerContent = fs.readFileSync(
|
let serviceWorkerContent = fs.readFileSync(
|
||||||
paths.app_output_root + bundleManifestLatest["service_worker.js"],
|
paths.app_output_root + bundleManifestLatest["service_worker.js"],
|
||||||
"utf-8"
|
"utf-8"
|
||||||
@@ -46,10 +46,9 @@ gulp.task("gen-service-worker-app-prod", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Remove ES5
|
// Remove ES5
|
||||||
const bundleManifestES5 = require(path.resolve(
|
const bundleManifestES5 = fs.readJsonSync(
|
||||||
paths.app_output_es5,
|
path.resolve(paths.app_output_es5, "manifest.json")
|
||||||
"manifest.json"
|
);
|
||||||
));
|
|
||||||
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
|
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
|
||||||
fs.removeSync(
|
fs.removeSync(
|
||||||
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
|
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
|
@@ -1,19 +1,24 @@
|
|||||||
const del = import("del");
|
import { createHash } from "crypto";
|
||||||
const crypto = require("crypto");
|
import { deleteSync } from "del";
|
||||||
const path = require("path");
|
import {
|
||||||
const source = require("vinyl-source-stream");
|
mkdirSync,
|
||||||
const vinylBuffer = require("vinyl-buffer");
|
readdirSync,
|
||||||
const gulp = require("gulp");
|
readFileSync,
|
||||||
const fs = require("fs");
|
renameSync,
|
||||||
const flatmap = require("gulp-flatmap");
|
writeFile,
|
||||||
const merge = require("gulp-merge-json");
|
} from "fs";
|
||||||
const rename = require("gulp-rename");
|
import gulp from "gulp";
|
||||||
const transform = require("gulp-json-transform");
|
import flatmap from "gulp-flatmap";
|
||||||
const { mapFiles } = require("../util.cjs");
|
import transform from "gulp-json-transform";
|
||||||
const env = require("../env.cjs");
|
import merge from "gulp-merge-json";
|
||||||
const paths = require("../paths.cjs");
|
import rename from "gulp-rename";
|
||||||
|
import path from "path";
|
||||||
require("./fetch-nightly-translations.cjs");
|
import vinylBuffer from "vinyl-buffer";
|
||||||
|
import source from "vinyl-source-stream";
|
||||||
|
import env from "../env.cjs";
|
||||||
|
import paths from "../paths.cjs";
|
||||||
|
import { mapFiles } from "../util.cjs";
|
||||||
|
import "./fetch-nightly-translations.js";
|
||||||
|
|
||||||
const inFrontendDir = "translations/frontend";
|
const inFrontendDir = "translations/frontend";
|
||||||
const inBackendDir = "translations/backend";
|
const inBackendDir = "translations/backend";
|
||||||
@@ -33,7 +38,12 @@ gulp.task(
|
|||||||
|
|
||||||
// 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(
|
||||||
require("../../src/translations/en.json").ui.panel
|
JSON.parse(
|
||||||
|
readFileSync(
|
||||||
|
path.resolve(paths.polymer_dir, "src/translations/en.json"),
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
).ui.panel
|
||||||
);
|
);
|
||||||
|
|
||||||
function recursiveFlatten(prefix, data) {
|
function recursiveFlatten(prefix, data) {
|
||||||
@@ -120,17 +130,14 @@ function lokaliseTransform(data, original, file) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task("clean-translations", async () => (await del).deleteSync([workDir]));
|
gulp.task("clean-translations", async () => deleteSync([workDir]));
|
||||||
|
|
||||||
gulp.task("ensure-translations-build-dir", (done) => {
|
gulp.task("ensure-translations-build-dir", async () => {
|
||||||
if (!fs.existsSync(workDir)) {
|
mkdirSync(workDir, { recursive: true });
|
||||||
fs.mkdirSync(workDir, { recursive: true });
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("create-test-metadata", (cb) => {
|
gulp.task("create-test-metadata", (cb) => {
|
||||||
fs.writeFile(
|
writeFile(
|
||||||
workDir + "/testMetadata.json",
|
workDir + "/testMetadata.json",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
test: {
|
test: {
|
||||||
@@ -303,15 +310,14 @@ const fingerprints = {};
|
|||||||
|
|
||||||
gulp.task("build-translation-fingerprints", () => {
|
gulp.task("build-translation-fingerprints", () => {
|
||||||
// Fingerprint full file of each language
|
// Fingerprint full file of each language
|
||||||
const files = fs.readdirSync(fullDir);
|
const files = readdirSync(fullDir);
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
fingerprints[files[i].split(".")[0]] = {
|
fingerprints[files[i].split(".")[0]] = {
|
||||||
// In dev we create fake hashes
|
// In dev we create fake hashes
|
||||||
hash: env.isProdBuild()
|
hash: env.isProdBuild()
|
||||||
? crypto
|
? createHash("md5")
|
||||||
.createHash("md5")
|
.update(readFileSync(path.join(fullDir, files[i]), "utf-8"))
|
||||||
.update(fs.readFileSync(path.join(fullDir, files[i]), "utf-8"))
|
|
||||||
.digest("hex")
|
.digest("hex")
|
||||||
: "dev",
|
: "dev",
|
||||||
};
|
};
|
||||||
@@ -327,7 +333,7 @@ gulp.task("build-translation-fingerprints", () => {
|
|||||||
throw new Error(`Unable to find hash for ${filename}`);
|
throw new Error(`Unable to find hash for ${filename}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.renameSync(
|
renameSync(
|
||||||
filename,
|
filename,
|
||||||
`${parsed.dir}/${parsed.name}-${fingerprints[parsed.name].hash}${
|
`${parsed.dir}/${parsed.name}-${fingerprints[parsed.name].hash}${
|
||||||
parsed.ext
|
parsed.ext
|
@@ -1,11 +0,0 @@
|
|||||||
// Tasks to run Rollup
|
|
||||||
const gulp = require("gulp");
|
|
||||||
const { startDevServer } = require("@web/dev-server");
|
|
||||||
|
|
||||||
gulp.task("wds-watch-app", () => {
|
|
||||||
startDevServer({
|
|
||||||
config: {
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
10
build-scripts/gulp/wds.js
Normal file
10
build-scripts/gulp/wds.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import gulp from "gulp";
|
||||||
|
import { startDevServer } from "@web/dev-server";
|
||||||
|
|
||||||
|
gulp.task("wds-watch-app", async () => {
|
||||||
|
startDevServer({
|
||||||
|
config: {
|
||||||
|
watch: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@@ -1,19 +1,20 @@
|
|||||||
// Tasks to run webpack.
|
// Tasks to run webpack.
|
||||||
const fs = require("fs");
|
|
||||||
const gulp = require("gulp");
|
import log from "fancy-log";
|
||||||
const webpack = require("webpack");
|
import fs from "fs";
|
||||||
const WebpackDevServer = require("webpack-dev-server");
|
import gulp from "gulp";
|
||||||
const log = require("fancy-log");
|
import path from "path";
|
||||||
const path = require("path");
|
import webpack from "webpack";
|
||||||
const env = require("../env.cjs");
|
import WebpackDevServer from "webpack-dev-server";
|
||||||
const paths = require("../paths.cjs");
|
import env from "../env.cjs";
|
||||||
const {
|
import paths from "../paths.cjs";
|
||||||
|
import {
|
||||||
createAppConfig,
|
createAppConfig,
|
||||||
createDemoConfig,
|
|
||||||
createCastConfig,
|
createCastConfig,
|
||||||
createHassioConfig,
|
createDemoConfig,
|
||||||
createGalleryConfig,
|
createGalleryConfig,
|
||||||
} = require("../webpack.cjs");
|
createHassioConfig,
|
||||||
|
} from "../webpack.cjs";
|
||||||
|
|
||||||
const bothBuilds = (createConfigFunc, params) => [
|
const bothBuilds = (createConfigFunc, params) => [
|
||||||
createConfigFunc({ ...params, latestBuild: true }),
|
createConfigFunc({ ...params, latestBuild: true }),
|
@@ -41,7 +41,7 @@ const createWebpackConfig = ({
|
|||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
mode: isProdBuild ? "production" : "development",
|
mode: isProdBuild ? "production" : "development",
|
||||||
target: ["web", latestBuild ? "es2017" : "es5"],
|
target: `browserslist:${latestBuild ? "modern" : "legacy"}`,
|
||||||
// For tests/CI, source maps are skipped to gain build speed
|
// For tests/CI, source maps are skipped to gain build speed
|
||||||
// For production, generate source maps for accurate stack traces without source code
|
// For production, generate source maps for accurate stack traces without source code
|
||||||
// For development, generate "cheap" versions that can map to original line numbers
|
// For development, generate "cheap" versions that can map to original line numbers
|
||||||
@@ -84,6 +84,13 @@ const createWebpackConfig = ({
|
|||||||
],
|
],
|
||||||
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
||||||
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
||||||
|
splitChunks: {
|
||||||
|
// Disable splitting for web workers with ESM output
|
||||||
|
// Imports of external chunks are broken
|
||||||
|
chunks: latestBuild
|
||||||
|
? (chunk) => !chunk.canBeInitial() && !/^.+-worker$/.test(chunk.name)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
|
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
|
||||||
@@ -132,6 +139,17 @@ const createWebpackConfig = ({
|
|||||||
),
|
),
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||||
),
|
),
|
||||||
|
// See `src/resources/intl-polyfill-legacy.ts` for explanation
|
||||||
|
!latestBuild &&
|
||||||
|
new webpack.NormalModuleReplacementPlugin(
|
||||||
|
new RegExp(
|
||||||
|
path.resolve(paths.polymer_dir, "src/resources/intl-polyfill.ts")
|
||||||
|
),
|
||||||
|
path.resolve(
|
||||||
|
paths.polymer_dir,
|
||||||
|
"src/resources/intl-polyfill-legacy.ts"
|
||||||
|
)
|
||||||
|
),
|
||||||
!isProdBuild && new LogStartCompilePlugin(),
|
!isProdBuild && new LogStartCompilePlugin(),
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -149,9 +167,12 @@ const createWebpackConfig = ({
|
|||||||
"lit/polyfill-support$": "lit/polyfill-support.js",
|
"lit/polyfill-support$": "lit/polyfill-support.js",
|
||||||
"@lit-labs/virtualizer/layouts/grid":
|
"@lit-labs/virtualizer/layouts/grid":
|
||||||
"@lit-labs/virtualizer/layouts/grid.js",
|
"@lit-labs/virtualizer/layouts/grid.js",
|
||||||
|
"@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver":
|
||||||
|
"@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver.js",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
module: latestBuild,
|
||||||
filename: ({ chunk }) =>
|
filename: ({ chunk }) =>
|
||||||
!isProdBuild || isStatsBuild || dontHash.has(chunk.name)
|
!isProdBuild || isStatsBuild || dontHash.has(chunk.name)
|
||||||
? "[name].js"
|
? "[name].js"
|
||||||
@@ -185,7 +206,7 @@ const createWebpackConfig = ({
|
|||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
experiments: {
|
experiments: {
|
||||||
topLevelAwait: true,
|
outputModule: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -190,7 +190,7 @@ export class HcConnect extends LitElement {
|
|||||||
|
|
||||||
private _handleInputKeyDown(ev: KeyboardEvent) {
|
private _handleInputKeyDown(ev: KeyboardEvent) {
|
||||||
// Handle pressing enter.
|
// Handle pressing enter.
|
||||||
if (ev.keyCode === 13) {
|
if (ev.key === "Enter") {
|
||||||
this._handleConnect();
|
this._handleConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import { cast } from "chromecast-caf-receiver";
|
||||||
|
|
||||||
const castContext = cast.framework.CastReceiverContext.getInstance();
|
const castContext = cast.framework.CastReceiverContext.getInstance();
|
||||||
|
|
||||||
const playerManager = castContext.getPlayerManager();
|
const playerManager = castContext.getPlayerManager();
|
||||||
|
@@ -1,2 +1,3 @@
|
|||||||
/* eslint-disable no-undef */
|
import { cast } from "chromecast-caf-receiver";
|
||||||
|
|
||||||
export const castContext = cast.framework.CastReceiverContext.getInstance();
|
export const castContext = cast.framework.CastReceiverContext.getInstance();
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable no-undef */
|
import { cast } from "chromecast-caf-receiver";
|
||||||
import { CAST_NS } from "../../../src/cast/const";
|
import { CAST_NS } from "../../../src/cast/const";
|
||||||
import { HassMessage } from "../../../src/cast/receiver_messages";
|
import { HassMessage } from "../../../src/cast/receiver_messages";
|
||||||
import "../../../src/resources/custom-card-support";
|
import "../../../src/resources/custom-card-support";
|
||||||
|
@@ -84,9 +84,6 @@
|
|||||||
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
<%= renderTemplate("../../../src/html/_js_base.html.template") %>
|
||||||
<%= renderTemplate("../../../src/html/_preload_roboto.html.template") %>
|
<%= renderTemplate("../../../src/html/_preload_roboto.html.template") %>
|
||||||
<script>
|
<script>
|
||||||
if (!window.globalThis) {
|
|
||||||
window.globalThis = window;
|
|
||||||
}
|
|
||||||
// Safari 12 and below does not have a compliant ES2015 implementation of template literals, so we ship ES5
|
// Safari 12 and below does not have a compliant ES2015 implementation of template literals, so we ship ES5
|
||||||
if (!isS11_12) {
|
if (!isS11_12) {
|
||||||
<% for (const entry of latestEntryJS) { %>
|
<% for (const entry of latestEntryJS) { %>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
export const mockConfigEntries = (hass: MockHomeAssistant) => {
|
export const mockConfigEntries = (hass: MockHomeAssistant) => {
|
||||||
hass.mockWS("config_entries/get", () => [
|
hass.mockWS("config_entries/get_matching", () => [
|
||||||
{
|
{
|
||||||
entry_id: "co2signal",
|
entry_id: "co2signal",
|
||||||
domain: "co2signal",
|
domain: "co2signal",
|
||||||
|
@@ -45,6 +45,10 @@ export default [
|
|||||||
header: "Users",
|
header: "Users",
|
||||||
pages: ["user-types", "configuration-menu"],
|
pages: ["user-types", "configuration-menu"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: "date-time",
|
||||||
|
header: "Date and Time",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
category: "design.home-assistant.io",
|
category: "design.home-assistant.io",
|
||||||
header: "About",
|
header: "About",
|
||||||
|
24
gallery/src/data/date-options.ts
Normal file
24
gallery/src/data/date-options.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import type { ControlSelectOption } from "../../../src/components/ha-control-select";
|
||||||
|
|
||||||
|
export const timeOptions: ControlSelectOption[] = [
|
||||||
|
{
|
||||||
|
value: "now",
|
||||||
|
label: "Now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "00:15:30",
|
||||||
|
label: "12:15:30 AM",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "06:15:30",
|
||||||
|
label: "06:15:30 AM",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "12:15:30",
|
||||||
|
label: "12:15:30 PM",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "18:15:30",
|
||||||
|
label: "06:15:30 PM",
|
||||||
|
},
|
||||||
|
];
|
@@ -1,5 +1,3 @@
|
|||||||
import "@polymer/polymer/lib/elements/dom-if";
|
|
||||||
import "@polymer/polymer/lib/elements/dom-repeat";
|
|
||||||
import "../../src/resources/ha-style";
|
import "../../src/resources/ha-style";
|
||||||
import "../../src/resources/roboto";
|
import "../../src/resources/roboto";
|
||||||
import "./ha-gallery";
|
import "./ha-gallery";
|
||||||
|
@@ -63,7 +63,7 @@ export class DemoAutomationDescribeCondition extends LitElement {
|
|||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>
|
<span>
|
||||||
${this._condition
|
${this._condition
|
||||||
? describeCondition(this._condition, this.hass)
|
? describeCondition(this._condition, this.hass, [])
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@@ -76,7 +76,7 @@ export class DemoAutomationDescribeCondition extends LitElement {
|
|||||||
${conditions.map(
|
${conditions.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>${describeCondition(conf as any, this.hass)}</span>
|
<span>${describeCondition(conf as any, this.hass, [])}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@@ -41,6 +41,7 @@ const triggers = [
|
|||||||
{ platform: "sun", event: "sunset" },
|
{ platform: "sun", event: "sunset" },
|
||||||
{ platform: "time_pattern" },
|
{ platform: "time_pattern" },
|
||||||
{ platform: "webhook" },
|
{ platform: "webhook" },
|
||||||
|
{ platform: "persistent_notification" },
|
||||||
{
|
{
|
||||||
platform: "zone",
|
platform: "zone",
|
||||||
entity_id: "person.person",
|
entity_id: "person.person",
|
||||||
@@ -74,7 +75,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
|||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
<span>
|
<span>
|
||||||
${this._trigger
|
${this._trigger
|
||||||
? describeTrigger(this._trigger, this.hass)
|
? describeTrigger(this._trigger, this.hass, [])
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@@ -86,7 +87,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
|
|||||||
${triggers.map(
|
${triggers.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="trigger">
|
<div class="trigger">
|
||||||
<span>${describeTrigger(conf as any, this.hass)}</span>
|
<span>${describeTrigger(conf as any, this.hass, [])}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
@@ -19,6 +19,7 @@ import { HaTemplateTrigger } from "../../../../src/panels/config/automation/trig
|
|||||||
import { HaTimeTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time";
|
import { HaTimeTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time";
|
||||||
import { HaTimePatternTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time_pattern";
|
import { HaTimePatternTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time_pattern";
|
||||||
import { HaWebhookTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-webhook";
|
import { HaWebhookTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-webhook";
|
||||||
|
import { HaPersistentNotificationTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-persistent_notification";
|
||||||
import { HaZoneTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-zone";
|
import { HaZoneTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-zone";
|
||||||
import { HaDeviceTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-device";
|
import { HaDeviceTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-device";
|
||||||
import { HaStateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-state";
|
import { HaStateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-state";
|
||||||
@@ -72,6 +73,16 @@ const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
|||||||
triggers: [{ platform: "webhook", ...HaWebhookTrigger.defaultConfig }],
|
triggers: [{ platform: "webhook", ...HaWebhookTrigger.defaultConfig }],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "Persistent Notification",
|
||||||
|
triggers: [
|
||||||
|
{
|
||||||
|
platform: "persistent_notification",
|
||||||
|
...HaPersistentNotificationTrigger.defaultConfig,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "Zone",
|
name: "Zone",
|
||||||
triggers: [{ platform: "zone", ...HaZoneTrigger.defaultConfig }],
|
triggers: [{ platform: "zone", ...HaZoneTrigger.defaultConfig }],
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: Control Circular Slider
|
||||||
|
---
|
153
gallery/src/pages/components/ha-control-circular-slider.ts
Normal file
153
gallery/src/pages/components/ha-control-circular-slider.ts
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-circular-slider";
|
||||||
|
import "../../../../src/components/ha-slider";
|
||||||
|
|
||||||
|
@customElement("demo-components-ha-control-circular-slider")
|
||||||
|
export class DemoHaCircularSlider extends LitElement {
|
||||||
|
@state()
|
||||||
|
private current = 22;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private value = 19;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private high = 25;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private changingValue?: number;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private changingHigh?: number;
|
||||||
|
|
||||||
|
private _valueChanged(ev) {
|
||||||
|
this.value = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanging(ev) {
|
||||||
|
this.changingValue = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _highChanged(ev) {
|
||||||
|
this.high = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _highChanging(ev) {
|
||||||
|
this.changingHigh = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _currentChanged(ev) {
|
||||||
|
this.current = ev.currentTarget.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title"><b>Config</b></p>
|
||||||
|
<div class="field">
|
||||||
|
<p>Current</p>
|
||||||
|
<ha-slider
|
||||||
|
min="10"
|
||||||
|
max="30"
|
||||||
|
.value=${this.current}
|
||||||
|
@change=${this._currentChanged}
|
||||||
|
pin
|
||||||
|
></ha-slider>
|
||||||
|
<p>${this.current} °C</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title"><b>Single</b></p>
|
||||||
|
<ha-control-circular-slider
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
@value-changing=${this._valueChanging}
|
||||||
|
.value=${this.value}
|
||||||
|
.current=${this.current}
|
||||||
|
step="1"
|
||||||
|
min="10"
|
||||||
|
max="30"
|
||||||
|
></ha-control-circular-slider>
|
||||||
|
<div>
|
||||||
|
Value: ${this.value} °C
|
||||||
|
<br />
|
||||||
|
Changing:
|
||||||
|
${this.changingValue != null ? `${this.changingValue} °C` : "-"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title"><b>Dual</b></p>
|
||||||
|
<ha-control-circular-slider
|
||||||
|
dual
|
||||||
|
@low-changed=${this._valueChanged}
|
||||||
|
@low-changing=${this._valueChanging}
|
||||||
|
@high-changed=${this._highChanged}
|
||||||
|
@high-changing=${this._highChanging}
|
||||||
|
.low=${this.value}
|
||||||
|
.high=${this.high}
|
||||||
|
.current=${this.current}
|
||||||
|
step="1"
|
||||||
|
min="10"
|
||||||
|
max="30"
|
||||||
|
></ha-control-circular-slider>
|
||||||
|
<div>
|
||||||
|
Low value: ${this.value} °C
|
||||||
|
<br />
|
||||||
|
Low changing:
|
||||||
|
${this.changingValue != null ? `${this.changingValue} °C` : "-"}
|
||||||
|
<br />
|
||||||
|
High value: ${this.high} °C
|
||||||
|
<br />
|
||||||
|
High changing:
|
||||||
|
${this.changingHigh != null ? `${this.changingHigh} °C` : "-"}
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
p.title {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
ha-control-circular-slider {
|
||||||
|
--control-circular-slider-color: #ff9800;
|
||||||
|
--control-circular-slider-background: #ff9800;
|
||||||
|
--control-circular-slider-background-opacity: 0.3;
|
||||||
|
}
|
||||||
|
ha-control-circular-slider[dual] {
|
||||||
|
--control-circular-slider-high-color: #2196f3;
|
||||||
|
--control-circular-slider-low-color: #ff9800;
|
||||||
|
--control-circular-slider-background: var(--disabled-color);
|
||||||
|
}
|
||||||
|
.field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-components-ha-control-circular-slider": DemoHaCircularSlider;
|
||||||
|
}
|
||||||
|
}
|
3
gallery/src/pages/components/ha-hs-color-picker.markdown
Normal file
3
gallery/src/pages/components/ha-hs-color-picker.markdown
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: HS Color Picker
|
||||||
|
---
|
120
gallery/src/pages/components/ha-hs-color-picker.ts
Normal file
120
gallery/src/pages/components/ha-hs-color-picker.ts
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import "../../../../src/components/ha-hs-color-picker";
|
||||||
|
|
||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-slider";
|
||||||
|
import { hsv2rgb } from "../../../../src/common/color/convert-color";
|
||||||
|
|
||||||
|
@customElement("demo-components-ha-hs-color-picker")
|
||||||
|
export class DemoHaHsColorPicker extends LitElement {
|
||||||
|
@state()
|
||||||
|
brightness = 255;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
value: [number, number] = [0, 0];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
liveValue?: [number, number];
|
||||||
|
|
||||||
|
private _brightnessChanged(ev) {
|
||||||
|
this.brightness = Number(ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hsColorCursor(ev) {
|
||||||
|
this.liveValue = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hsColorChanged(ev) {
|
||||||
|
this.value = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hueChanged(ev) {
|
||||||
|
this.value = [ev.target.value, this.value[1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
private _saturationChanged(ev) {
|
||||||
|
this.value = [this.value[0], ev.target.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
const h = (this.liveValue ?? this.value)[0];
|
||||||
|
const s = (this.liveValue ?? this.value)[1];
|
||||||
|
|
||||||
|
const rgb = hsv2rgb([h, s, this.brightness]);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="value">${h}° - ${Math.round(s * 100)}%</p>
|
||||||
|
<p class="value">${rgb.map((v) => Math.round(v)).join(", ")}</p>
|
||||||
|
<ha-hs-color-picker
|
||||||
|
colorBrightness=${this.brightness}
|
||||||
|
.value=${this.value}
|
||||||
|
@value-changed=${this._hsColorChanged}
|
||||||
|
@cursor-moved=${this._hsColorCursor}
|
||||||
|
></ha-hs-color-picker>
|
||||||
|
<p>Hue : ${this.value[0]}</p>
|
||||||
|
<ha-slider
|
||||||
|
step="1"
|
||||||
|
pin
|
||||||
|
min="0"
|
||||||
|
max="360"
|
||||||
|
.value=${this.value[0]}
|
||||||
|
@change=${this._hueChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
<p>Saturation : ${this.value[1]}</p>
|
||||||
|
<ha-slider
|
||||||
|
step="0.01"
|
||||||
|
pin
|
||||||
|
min="0"
|
||||||
|
max="1"
|
||||||
|
.value=${this.value[1]}
|
||||||
|
@change=${this._saturationChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
<p>Color Brighness : ${this.brightness}</p>
|
||||||
|
<ha-slider
|
||||||
|
step="1"
|
||||||
|
pin
|
||||||
|
min="0"
|
||||||
|
max="255"
|
||||||
|
.value=${this.brightness}
|
||||||
|
@change=${this._brightnessChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-card {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
.card-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
ha-hs-color-picker {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-components-ha-hs-color-picker": DemoHaHsColorPicker;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
title: Temp Color Picker
|
||||||
|
---
|
117
gallery/src/pages/components/ha-temp-color-picker.ts
Normal file
117
gallery/src/pages/components/ha-temp-color-picker.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import "../../../../src/components/ha-temp-color-picker";
|
||||||
|
|
||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-slider";
|
||||||
|
|
||||||
|
@customElement("demo-components-ha-temp-color-picker")
|
||||||
|
export class DemoHaTempColorPicker extends LitElement {
|
||||||
|
@state()
|
||||||
|
min = 3000;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
max = 7000;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
value = 4000;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
liveValue?: number;
|
||||||
|
|
||||||
|
private _minChanged(ev) {
|
||||||
|
this.min = Number(ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _maxChanged(ev) {
|
||||||
|
this.max = Number(ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev) {
|
||||||
|
this.value = Number(ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _tempColorCursor(ev) {
|
||||||
|
this.liveValue = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _tempColorChanged(ev) {
|
||||||
|
this.value = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="value">${this.liveValue ?? this.value} K</p>
|
||||||
|
<ha-temp-color-picker
|
||||||
|
.min=${this.min}
|
||||||
|
.max=${this.max}
|
||||||
|
.value=${this.value}
|
||||||
|
@value-changed=${this._tempColorChanged}
|
||||||
|
@cursor-moved=${this._tempColorCursor}
|
||||||
|
></ha-temp-color-picker>
|
||||||
|
<p>Min temp : ${this.min} K</p>
|
||||||
|
<ha-slider
|
||||||
|
step="1"
|
||||||
|
pin
|
||||||
|
min="2000"
|
||||||
|
max="10000"
|
||||||
|
.value=${this.min}
|
||||||
|
@change=${this._minChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
<p>Max temp : ${this.max} K</p>
|
||||||
|
<ha-slider
|
||||||
|
step="1"
|
||||||
|
pin
|
||||||
|
min="2000"
|
||||||
|
max="10000"
|
||||||
|
.value=${this.max}
|
||||||
|
@change=${this._maxChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
<p>Value : ${this.value} K</p>
|
||||||
|
<ha-slider
|
||||||
|
step="1"
|
||||||
|
pin
|
||||||
|
min=${this.min}
|
||||||
|
max=${this.max}
|
||||||
|
.value=${this.value}
|
||||||
|
@change=${this._valueChanged}
|
||||||
|
>
|
||||||
|
</ha-slider>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-card {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 24px auto;
|
||||||
|
}
|
||||||
|
.card-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
ha-temp-color-picker {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
.value {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-components-ha-temp-color-picker": DemoHaTempColorPicker;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/date-time-numeric.markdown
Normal file
7
gallery/src/pages/date-time/date-time-numeric.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date-Time Format (Numeric)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available date-time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatDateTimeNumeric: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/date-time-numeric.ts
Normal file
136
gallery/src/pages/date-time/date-time-numeric.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatDateTimeNumeric } from "../../../../src/common/datetime/format_date_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date-time-numeric")
|
||||||
|
export class DemoDateTimeDateTimeNumeric extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeNumeric(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeNumeric(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeNumeric(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date-time-numeric": DemoDateTimeDateTimeNumeric;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/date-time-seconds.markdown
Normal file
7
gallery/src/pages/date-time/date-time-seconds.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date-Time Format (Seconds)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available date-time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatDateTimeWithSeconds: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/date-time-seconds.ts
Normal file
136
gallery/src/pages/date-time/date-time-seconds.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatDateTimeWithSeconds } from "../../../../src/common/datetime/format_date_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date-time-seconds")
|
||||||
|
export class DemoDateTimeDateTimeSeconds extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date-time-seconds": DemoDateTimeDateTimeSeconds;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date-Time Format (Short w/ Year)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available date-time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatShortDateTimeWithYear: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/date-time-short-year.ts
Normal file
136
gallery/src/pages/date-time/date-time-short-year.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatShortDateTimeWithYear } from "../../../../src/common/datetime/format_date_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date-time-short-year")
|
||||||
|
export class DemoDateTimeDateTimeShortYear extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTimeWithYear(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTimeWithYear(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTimeWithYear(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date-time-short-year": DemoDateTimeDateTimeShortYear;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/date-time-short.markdown
Normal file
7
gallery/src/pages/date-time/date-time-short.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date-Time Format (Short)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available date-time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatShortDateTime: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/date-time-short.ts
Normal file
136
gallery/src/pages/date-time/date-time-short.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatShortDateTime } from "../../../../src/common/datetime/format_date_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date-time-short")
|
||||||
|
export class DemoDateTimeDateTimeShort extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatShortDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date-time-short": DemoDateTimeDateTimeShort;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/date-time.markdown
Normal file
7
gallery/src/pages/date-time/date-time.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date-Time Format
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available date-time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatDateTime: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/date-time.ts
Normal file
136
gallery/src/pages/date-time/date-time.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatDateTime } from "../../../../src/common/datetime/format_date_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date-time")
|
||||||
|
export class DemoDateTimeDateTime extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date-time": DemoDateTimeDateTime;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/date.markdown
Normal file
7
gallery/src/pages/date-time/date.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Date Format (Numeric)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available (numeric) date formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatDateNumeric: (dateObj: Date, locale: FrontendLocaleData) => string`
|
123
gallery/src/pages/date-time/date.ts
Normal file
123
gallery/src/pages/date-time/date.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { css, html, LitElement } from "lit";
|
||||||
|
import { customElement } from "lit/decorators";
|
||||||
|
import { formatDateNumeric } from "../../../../src/common/datetime/format_date";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-date")
|
||||||
|
export class DemoDateTimeDate extends LitElement {
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
};
|
||||||
|
const date = new Date();
|
||||||
|
return html`
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">Day-Month-Year</div>
|
||||||
|
<div class="center">Month-Day-Year</div>
|
||||||
|
<div class="center">Year-Month-Day</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateNumeric(
|
||||||
|
date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateNumeric(
|
||||||
|
date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
date_format: DateFormat.DMY,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateNumeric(
|
||||||
|
date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
date_format: DateFormat.MDY,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatDateNumeric(
|
||||||
|
date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
date_format: DateFormat.YMD,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-date": DemoDateTimeDate;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/time-seconds.markdown
Normal file
7
gallery/src/pages/date-time/time-seconds.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Time Format (Seconds)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatTimeWithSeconds: (dateObj: Date, locale: FrontendLocaleData) => string`
|
135
gallery/src/pages/date-time/time-seconds.ts
Normal file
135
gallery/src/pages/date-time/time-seconds.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatTimeWithSeconds } from "../../../../src/common/datetime/format_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-time-seconds")
|
||||||
|
export class DemoDateTimeTimeSeconds extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWithSeconds(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-time-seconds": DemoDateTimeTimeSeconds;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/time-weekday.markdown
Normal file
7
gallery/src/pages/date-time/time-weekday.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Time Format (Weekday)
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatTimeWeekday: (dateObj: Date, locale: FrontendLocaleData) => string`
|
135
gallery/src/pages/date-time/time-weekday.ts
Normal file
135
gallery/src/pages/date-time/time-weekday.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatTimeWeekday } from "../../../../src/common/datetime/format_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-time-weekday")
|
||||||
|
export class DemoDateTimeTimeWeekday extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWeekday(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWeekday(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTimeWeekday(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-time-weekday": DemoDateTimeTimeWeekday;
|
||||||
|
}
|
||||||
|
}
|
7
gallery/src/pages/date-time/time.markdown
Normal file
7
gallery/src/pages/date-time/time.markdown
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Time Format
|
||||||
|
---
|
||||||
|
|
||||||
|
This pages lists all supported languages with their available time formats.
|
||||||
|
|
||||||
|
Formatting function: `const formatTime: (dateObj: Date, locale: FrontendLocaleData) => string`
|
136
gallery/src/pages/date-time/time.ts
Normal file
136
gallery/src/pages/date-time/time.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { html, css, LitElement } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../../src/components/ha-card";
|
||||||
|
import "../../../../src/components/ha-control-select";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { formatTime } from "../../../../src/common/datetime/format_time";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import {
|
||||||
|
FrontendLocaleData,
|
||||||
|
NumberFormat,
|
||||||
|
TimeFormat,
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
|
TimeZone,
|
||||||
|
} from "../../../../src/data/translation";
|
||||||
|
|
||||||
|
@customElement("demo-date-time-time")
|
||||||
|
export class DemoDateTimeTime extends LitElement {
|
||||||
|
@state() private selection?: string = "now";
|
||||||
|
|
||||||
|
@state() private date: Date = new Date();
|
||||||
|
|
||||||
|
handleValueChanged(e: CustomEvent) {
|
||||||
|
this.selection = e.detail.value as string;
|
||||||
|
this.date = new Date();
|
||||||
|
if (this.selection !== "now") {
|
||||||
|
const [hours, minutes, seconds] = this.selection.split(":").map(Number);
|
||||||
|
this.date.setHours(hours);
|
||||||
|
this.date.setMinutes(minutes);
|
||||||
|
this.date.setSeconds(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const defaultLocale: FrontendLocaleData = {
|
||||||
|
language: "en",
|
||||||
|
number_format: NumberFormat.language,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
date_format: DateFormat.language,
|
||||||
|
first_weekday: FirstWeekday.language,
|
||||||
|
time_zone: TimeZone.local,
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<ha-control-select
|
||||||
|
.value=${this.selection}
|
||||||
|
.options=${timeOptions}
|
||||||
|
@value-changed=${this.handleValueChanged}
|
||||||
|
>
|
||||||
|
</ha-control-select>
|
||||||
|
<mwc-list>
|
||||||
|
<div class="container header">
|
||||||
|
<div>Language</div>
|
||||||
|
<div class="center">Default (lang)</div>
|
||||||
|
<div class="center">12 Hours</div>
|
||||||
|
<div class="center">24 Hours</div>
|
||||||
|
</div>
|
||||||
|
${Object.entries(translationMetadata.translations)
|
||||||
|
.filter(([key, _]) => key !== "test")
|
||||||
|
.map(
|
||||||
|
([key, value]) => html`
|
||||||
|
<div class="container">
|
||||||
|
<div>${value.nativeName}</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.language,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.am_pm,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
${formatTime(
|
||||||
|
this.date,
|
||||||
|
{
|
||||||
|
...defaultLocale,
|
||||||
|
language: key,
|
||||||
|
time_format: TimeFormat.twenty_four,
|
||||||
|
},
|
||||||
|
demoConfig
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
ha-control-select {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 12px auto;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 12px auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-date-time-time": DemoDateTimeTime;
|
||||||
|
}
|
||||||
|
}
|
@@ -9,7 +9,7 @@ const CONFIGS = [
|
|||||||
heading: "markdown-it demo",
|
heading: "markdown-it demo",
|
||||||
config: `
|
config: `
|
||||||
- type: markdown
|
- type: markdown
|
||||||
content: >-
|
content: |
|
||||||
# h1 Heading 8-)
|
# h1 Heading 8-)
|
||||||
|
|
||||||
## h2 Heading
|
## h2 Heading
|
||||||
@@ -65,6 +65,15 @@ const CONFIGS = [
|
|||||||
>> ...by using additional greater-than signs right next to each other...
|
>> ...by using additional greater-than signs right next to each other...
|
||||||
> > > ...or with spaces between arrows.
|
> > > ...or with spaces between arrows.
|
||||||
|
|
||||||
|
> **Warning** Hey there
|
||||||
|
> This is a warning with a title
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> This is a note
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> This is a multiline note
|
||||||
|
> Lorem ipsum...
|
||||||
|
|
||||||
## Lists
|
## Lists
|
||||||
|
|
||||||
|
@@ -50,6 +50,7 @@ const SENSOR_DEVICE_CLASSES = [
|
|||||||
"temperature",
|
"temperature",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
"volatile_organic_compounds",
|
"volatile_organic_compounds",
|
||||||
|
"volatile_organic_compounds_parts",
|
||||||
"voltage",
|
"voltage",
|
||||||
"volume",
|
"volume",
|
||||||
"water",
|
"water",
|
||||||
@@ -134,6 +135,9 @@ const ENTITIES: HassEntity[] = [
|
|||||||
createEntity("climate.fan_only", "fan_only"),
|
createEntity("climate.fan_only", "fan_only"),
|
||||||
createEntity("climate.auto_idle", "auto", undefined, { hvac_action: "idle" }),
|
createEntity("climate.auto_idle", "auto", undefined, { hvac_action: "idle" }),
|
||||||
createEntity("climate.auto_off", "auto", undefined, { hvac_action: "off" }),
|
createEntity("climate.auto_off", "auto", undefined, { hvac_action: "off" }),
|
||||||
|
createEntity("climate.auto_preheating", "auto", undefined, {
|
||||||
|
hvac_action: "preheating",
|
||||||
|
}),
|
||||||
createEntity("climate.auto_heating", "auto", undefined, {
|
createEntity("climate.auto_heating", "auto", undefined, {
|
||||||
hvac_action: "heating",
|
hvac_action: "heating",
|
||||||
}),
|
}),
|
||||||
@@ -353,6 +357,7 @@ export class DemoEntityState extends LitElement {
|
|||||||
hass.localize,
|
hass.localize,
|
||||||
entry.stateObj,
|
entry.stateObj,
|
||||||
hass.locale,
|
hass.locale,
|
||||||
|
hass.config,
|
||||||
hass.entities
|
hass.entities
|
||||||
)}`,
|
)}`,
|
||||||
},
|
},
|
||||||
|
@@ -130,6 +130,7 @@ export class HassioAddonRepositoryEl extends LitElement {
|
|||||||
css`
|
css`
|
||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.not_available {
|
.not_available {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
|
@@ -70,7 +70,7 @@ export class HassioAddonStore extends LitElement {
|
|||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
await this._loadData();
|
this._loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,10 +99,10 @@ export class HassioAddonStore extends LitElement {
|
|||||||
slot="trigger"
|
slot="trigger"
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("store.repositories")}
|
${this.supervisor.localize("store.check_updates")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("store.check_updates")}
|
${this.supervisor.localize("store.repositories")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
${this.hass.userData?.showAdvanced &&
|
${this.hass.userData?.showAdvanced &&
|
||||||
atLeastVersion(this.hass.config.version, 0, 117)
|
atLeastVersion(this.hass.config.version, 0, 117)
|
||||||
@@ -177,10 +177,10 @@ export class HassioAddonStore extends LitElement {
|
|||||||
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
private _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||||
switch (ev.detail.index) {
|
switch (ev.detail.index) {
|
||||||
case 0:
|
case 0:
|
||||||
this._manageRepositoriesClicked();
|
this.refreshData();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
this.refreshData();
|
this._manageRepositoriesClicked();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this._manageRegistries();
|
this._manageRegistries();
|
||||||
@@ -198,18 +198,18 @@ export class HassioAddonStore extends LitElement {
|
|||||||
this._manageRepositories();
|
this._manageRepositories();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _manageRepositories(url?: string) {
|
private _manageRepositories(url?: string) {
|
||||||
showRepositoriesDialog(this, {
|
showRepositoriesDialog(this, {
|
||||||
supervisor: this.supervisor,
|
supervisor: this.supervisor,
|
||||||
url,
|
url,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _manageRegistries() {
|
private _manageRegistries() {
|
||||||
showRegistriesDialog(this, { supervisor: this.supervisor });
|
showRegistriesDialog(this, { supervisor: this.supervisor });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadData() {
|
private _loadData() {
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: "supervisor",
|
collection: "supervisor",
|
||||||
|
@@ -140,7 +140,12 @@ class HassioAddonConfig extends LitElement {
|
|||||||
? {
|
? {
|
||||||
name: entry.name,
|
name: entry.name,
|
||||||
required: entry.required,
|
required: entry.required,
|
||||||
selector: { number: { mode: "box" } },
|
selector: {
|
||||||
|
number: {
|
||||||
|
mode: "box",
|
||||||
|
step: entry.type === "float" ? "any" : undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: entry
|
: entry
|
||||||
)
|
)
|
||||||
|
@@ -44,7 +44,10 @@ class HassioAddonDocumentationDashboard extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${this._content
|
${this._content
|
||||||
? html`<ha-markdown .content=${this._content}></ha-markdown>`
|
? html`<ha-markdown
|
||||||
|
.content=${this._content}
|
||||||
|
lazy-images
|
||||||
|
></ha-markdown>`
|
||||||
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
|
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
@@ -659,6 +659,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<ha-markdown
|
<ha-markdown
|
||||||
.content=${this.addon.long_description}
|
.content=${this.addon.long_description}
|
||||||
|
lazy-images
|
||||||
></ha-markdown>
|
></ha-markdown>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
|
@@ -3,11 +3,11 @@ import { ActionDetail } from "@material/mwc-list";
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
import { mdiBackupRestore, mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
@@ -26,9 +26,9 @@ import "../../../src/components/ha-fab";
|
|||||||
import "../../../src/components/ha-icon-button";
|
import "../../../src/components/ha-icon-button";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
|
HassioBackup,
|
||||||
fetchHassioBackups,
|
fetchHassioBackups,
|
||||||
friendlyFolderName,
|
friendlyFolderName,
|
||||||
HassioBackup,
|
|
||||||
reloadHassioBackups,
|
reloadHassioBackups,
|
||||||
removeBackup,
|
removeBackup,
|
||||||
} from "../../../src/data/hassio/backup";
|
} from "../../../src/data/hassio/backup";
|
||||||
@@ -43,6 +43,7 @@ import type { HaTabsSubpageDataTable } from "../../../src/layouts/hass-tabs-subp
|
|||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
|
import { showBackupUploadDialog } from "../dialogs/backup/show-dialog-backup-upload";
|
||||||
|
import { showHassioBackupLocationDialog } from "../dialogs/backup/show-dialog-hassio-backu-location";
|
||||||
import { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
|
import { showHassioBackupDialog } from "../dialogs/backup/show-dialog-hassio-backup";
|
||||||
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
import { showHassioCreateBackupDialog } from "../dialogs/backup/show-dialog-hassio-create-backup";
|
||||||
import { supervisorTabs } from "../hassio-tabs";
|
import { supervisorTabs } from "../hassio-tabs";
|
||||||
@@ -135,6 +136,15 @@ export class HassioBackups extends LitElement {
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
template: (entry: number) => Math.ceil(entry * 10) / 10 + " MB",
|
template: (entry: number) => Math.ceil(entry * 10) / 10 + " MB",
|
||||||
},
|
},
|
||||||
|
location: {
|
||||||
|
title: this.supervisor.localize("backup.location"),
|
||||||
|
width: "15%",
|
||||||
|
hidden: narrow,
|
||||||
|
filterable: true,
|
||||||
|
sortable: true,
|
||||||
|
template: (entry: string | null) =>
|
||||||
|
entry || this.supervisor.localize("backup.data_disk"),
|
||||||
|
},
|
||||||
date: {
|
date: {
|
||||||
title: this.supervisor.localize("backup.created"),
|
title: this.supervisor.localize("backup.created"),
|
||||||
width: "15%",
|
width: "15%",
|
||||||
@@ -204,6 +214,9 @@ export class HassioBackups extends LitElement {
|
|||||||
<mwc-list-item>
|
<mwc-list-item>
|
||||||
${this.supervisor.localize("common.reload")}
|
${this.supervisor.localize("common.reload")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
|
<mwc-list-item>
|
||||||
|
${this.supervisor.localize("dialog.backup_location.title")}
|
||||||
|
</mwc-list-item>
|
||||||
${atLeastVersion(this.hass.config.version, 0, 116)
|
${atLeastVersion(this.hass.config.version, 0, 116)
|
||||||
? html`<mwc-list-item>
|
? html`<mwc-list-item>
|
||||||
${this.supervisor.localize("backup.upload_backup")}
|
${this.supervisor.localize("backup.upload_backup")}
|
||||||
@@ -270,6 +283,9 @@ export class HassioBackups extends LitElement {
|
|||||||
this.refreshData();
|
this.refreshData();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
showHassioBackupLocationDialog(this, { supervisor: this.supervisor });
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
this._showUploadBackupDialog();
|
this._showUploadBackupDialog();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
import { mdiFolder, mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
|
import { mdiFolder, mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
TemplateResult,
|
|
||||||
nothing,
|
nothing,
|
||||||
|
TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property, query } from "lit/decorators";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
@@ -23,8 +24,11 @@ import {
|
|||||||
HassioPartialBackupCreateParams,
|
HassioPartialBackupCreateParams,
|
||||||
} from "../../../src/data/hassio/backup";
|
} from "../../../src/data/hassio/backup";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
import {
|
||||||
import { HomeAssistant, TranslationDict } from "../../../src/types";
|
HomeAssistant,
|
||||||
|
TranslationDict,
|
||||||
|
ValueChangedEvent,
|
||||||
|
} from "../../../src/types";
|
||||||
import "./supervisor-formfield-label";
|
import "./supervisor-formfield-label";
|
||||||
|
|
||||||
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
||||||
@@ -139,7 +143,11 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
: this._localize("partial_backup")}
|
: this._localize("partial_backup")}
|
||||||
(${Math.ceil(this.backup.size * 10) / 10 + " MB"})<br />
|
(${Math.ceil(this.backup.size * 10) / 10 + " MB"})<br />
|
||||||
${this.hass
|
${this.hass
|
||||||
? formatDateTime(new Date(this.backup.date), this.hass.locale)
|
? formatDateTime(
|
||||||
|
new Date(this.backup.date),
|
||||||
|
this.hass.locale,
|
||||||
|
this.hass.config
|
||||||
|
)
|
||||||
: this.backup.date}
|
: this.backup.date}
|
||||||
</div>`
|
</div>`
|
||||||
: html`<paper-input
|
: html`<paper-input
|
||||||
@@ -332,7 +340,9 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
const data: any = {};
|
const data: any = {};
|
||||||
|
|
||||||
if (!this.backup) {
|
if (!this.backup) {
|
||||||
data.name = this.backupName || formatDate(new Date(), this.hass.locale);
|
data.name =
|
||||||
|
this.backupName ||
|
||||||
|
formatDate(new Date(), this.hass.locale, this.hass.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.backupHasPassword) {
|
if (this.backupHasPassword) {
|
||||||
@@ -416,7 +426,7 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
this[input.name] = input.value;
|
this[input.name] = input.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleTextValueChanged(ev: PolymerChangedEvent<string>) {
|
private _handleTextValueChanged(ev: ValueChangedEvent<string>) {
|
||||||
const input = ev.currentTarget as PaperInputElement;
|
const input = ev.currentTarget as PaperInputElement;
|
||||||
this[input.name!] = ev.detail.value;
|
this[input.name!] = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
|
import "../../../src/components/search-input";
|
||||||
|
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
@@ -17,11 +20,25 @@ class HassioAddons extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
|
@state() private _filter?: string;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
<div class="search">
|
||||||
|
<search-input
|
||||||
|
.hass=${this.hass}
|
||||||
|
suffix
|
||||||
|
.filter=${this._filter}
|
||||||
|
@value-changed=${this._handleSearchChange}
|
||||||
|
.label=${this.supervisor.localize("dashboard.search_addons")}
|
||||||
|
>
|
||||||
|
</search-input>
|
||||||
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${!atLeastVersion(this.hass.config.version, 2021, 12)
|
${!atLeastVersion(this.hass.config.version, 2021, 12)
|
||||||
? html` <h1>${this.supervisor.localize("dashboard.addons")}</h1> `
|
? html`<h1>${this.supervisor.localize("dashboard.addons")}</h1>`
|
||||||
: ""}
|
: ""}
|
||||||
<div class="card-group">
|
<div class="card-group">
|
||||||
${!this.supervisor.addon.addons.length
|
${!this.supervisor.addon.addons.length
|
||||||
@@ -34,67 +51,73 @@ class HassioAddons extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
: this.supervisor.addon.addons
|
: this._getAddons(this.supervisor.addon.addons, this._filter).map(
|
||||||
.sort((a, b) =>
|
(addon) => html`
|
||||||
caseInsensitiveStringCompare(
|
<ha-card outlined .addon=${addon} @click=${this._addonTapped}>
|
||||||
a.name,
|
<div class="card-content">
|
||||||
b.name,
|
<hassio-card-content
|
||||||
this.hass.locale.language
|
.hass=${this.hass}
|
||||||
)
|
.title=${addon.name}
|
||||||
)
|
.description=${addon.description}
|
||||||
.map(
|
available
|
||||||
(addon) => html`
|
.showTopbar=${addon.update_available}
|
||||||
<ha-card
|
topbarClass="update"
|
||||||
outlined
|
.icon=${addon.update_available!
|
||||||
.addon=${addon}
|
? mdiArrowUpBoldCircle
|
||||||
@click=${this._addonTapped}
|
: mdiPuzzle}
|
||||||
>
|
.iconTitle=${addon.state !== "started"
|
||||||
<div class="card-content">
|
? this.supervisor.localize("dashboard.addon_stopped")
|
||||||
<hassio-card-content
|
: addon.update_available!
|
||||||
.hass=${this.hass}
|
? this.supervisor.localize(
|
||||||
.title=${addon.name}
|
"dashboard.addon_new_version"
|
||||||
.description=${addon.description}
|
)
|
||||||
available
|
: this.supervisor.localize("dashboard.addon_running")}
|
||||||
.showTopbar=${addon.update_available}
|
.iconClass=${addon.update_available
|
||||||
topbarClass="update"
|
? addon.state === "started"
|
||||||
.icon=${addon.update_available!
|
? "update"
|
||||||
? mdiArrowUpBoldCircle
|
: "update stopped"
|
||||||
: mdiPuzzle}
|
: addon.state === "started"
|
||||||
.iconTitle=${addon.state !== "started"
|
? "running"
|
||||||
? this.supervisor.localize(
|
: "stopped"}
|
||||||
"dashboard.addon_stopped"
|
.iconImage=${atLeastVersion(
|
||||||
)
|
this.hass.config.version,
|
||||||
: addon.update_available!
|
0,
|
||||||
? this.supervisor.localize(
|
105
|
||||||
"dashboard.addon_new_version"
|
) && addon.icon
|
||||||
)
|
? `/api/hassio/addons/${addon.slug}/icon`
|
||||||
: this.supervisor.localize(
|
: undefined}
|
||||||
"dashboard.addon_running"
|
></hassio-card-content>
|
||||||
)}
|
</div>
|
||||||
.iconClass=${addon.update_available
|
</ha-card>
|
||||||
? addon.state === "started"
|
`
|
||||||
? "update"
|
)}
|
||||||
: "update stopped"
|
|
||||||
: addon.state === "started"
|
|
||||||
? "running"
|
|
||||||
: "stopped"}
|
|
||||||
.iconImage=${atLeastVersion(
|
|
||||||
this.hass.config.version,
|
|
||||||
0,
|
|
||||||
105
|
|
||||||
) && addon.icon
|
|
||||||
? `/api/hassio/addons/${addon.slug}/icon`
|
|
||||||
: undefined}
|
|
||||||
></hassio-card-content>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getAddons = memoizeOne(
|
||||||
|
(addons: HassioAddonInfo[], filter?: string) => {
|
||||||
|
if (filter) {
|
||||||
|
addons = addons.filter((addon) => {
|
||||||
|
const lowerCaseFilter = filter.toLowerCase();
|
||||||
|
return (
|
||||||
|
addon.name.toLowerCase().includes(lowerCaseFilter) ||
|
||||||
|
addon.description.toLowerCase().includes(lowerCaseFilter) ||
|
||||||
|
addon.slug.toLowerCase().includes(lowerCaseFilter)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return addons.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(a.name, b.name, this.hass.locale.language)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private _handleSearchChange(ev: CustomEvent) {
|
||||||
|
this._filter = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@@ -102,6 +125,17 @@ class HassioAddons extends LitElement {
|
|||||||
css`
|
css`
|
||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
search-input {
|
||||||
|
display: block;
|
||||||
|
--mdc-text-field-fill-color: var(--sidebar-background-color);
|
||||||
|
--mdc-text-field-idle-line-color: var(--divider-color);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { mdiStorePlus } from "@mdi/js";
|
import { mdiStorePlus, mdiUpdate } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
@@ -10,6 +10,10 @@ import { HomeAssistant, Route } from "../../../src/types";
|
|||||||
import { supervisorTabs } from "../hassio-tabs";
|
import { supervisorTabs } from "../hassio-tabs";
|
||||||
import "./hassio-addons";
|
import "./hassio-addons";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
|
import { reloadHassioAddons } from "../../../src/data/hassio/addon";
|
||||||
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
|
import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
||||||
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
|
|
||||||
@customElement("hassio-dashboard")
|
@customElement("hassio-dashboard")
|
||||||
class HassioDashboard extends LitElement {
|
class HassioDashboard extends LitElement {
|
||||||
@@ -36,9 +40,16 @@ class HassioDashboard extends LitElement {
|
|||||||
back-path="/config"
|
back-path="/config"
|
||||||
.header=${this.supervisor.localize("panel.addons")}
|
.header=${this.supervisor.localize("panel.addons")}
|
||||||
>
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
slot="toolbar-icon"
|
||||||
|
@click=${this._handleCheckUpdates}
|
||||||
|
.path=${mdiUpdate}
|
||||||
|
.label=${this.supervisor.localize("store.check_updates")}
|
||||||
|
></ha-icon-button>
|
||||||
<hassio-addons
|
<hassio-addons
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.supervisor=${this.supervisor}
|
.supervisor=${this.supervisor}
|
||||||
|
.narrow=${this.narrow}
|
||||||
></hassio-addons>
|
></hassio-addons>
|
||||||
<a href="/hassio/store">
|
<a href="/hassio/store">
|
||||||
<ha-fab
|
<ha-fab
|
||||||
@@ -99,6 +110,18 @@ class HassioDashboard extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _handleCheckUpdates() {
|
||||||
|
try {
|
||||||
|
await reloadHassioAddons(this.hass);
|
||||||
|
} catch (err) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
text: extractApiErrorMessage(err),
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
|
154
hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
Normal file
154
hassio/src/dialogs/backup/dialog-hassio-backup-location.ts
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
|
import "../../../../src/components/ha-dialog";
|
||||||
|
import "../../../../src/components/ha-form/ha-form";
|
||||||
|
import type { SchemaUnion } from "../../../../src/components/ha-form/types";
|
||||||
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
|
import { changeMountOptions } from "../../../../src/data/supervisor/mounts";
|
||||||
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
|
import { HassioBackupLocationDialogParams } from "./show-dialog-hassio-backu-location";
|
||||||
|
|
||||||
|
const SCHEMA = memoizeOne(
|
||||||
|
() =>
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: "default_backup_mount",
|
||||||
|
required: true,
|
||||||
|
selector: { backup_location: {} },
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
);
|
||||||
|
|
||||||
|
@customElement("dialog-hassio-backup-location")
|
||||||
|
class HassioBackupLocationDialog extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public _dialogParams?: HassioBackupLocationDialogParams;
|
||||||
|
|
||||||
|
@state() private _data?: { default_backup_mount: string | null };
|
||||||
|
|
||||||
|
@state() private _waiting?: boolean;
|
||||||
|
|
||||||
|
@state() private _error?: string;
|
||||||
|
|
||||||
|
public async showDialog(
|
||||||
|
dialogParams: HassioBackupLocationDialogParams
|
||||||
|
): Promise<void> {
|
||||||
|
this._dialogParams = dialogParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this._data = undefined;
|
||||||
|
this._error = undefined;
|
||||||
|
this._waiting = undefined;
|
||||||
|
this._dialogParams = undefined;
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this._dialogParams) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
scrimClickAction
|
||||||
|
escapeKeyAction
|
||||||
|
.heading=${this._dialogParams.supervisor.localize(
|
||||||
|
"dialog.backup_location.title"
|
||||||
|
)}
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
>
|
||||||
|
${this._error
|
||||||
|
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
|
<ha-form
|
||||||
|
.hass=${this.hass}
|
||||||
|
.data=${this._data}
|
||||||
|
.schema=${SCHEMA()}
|
||||||
|
.computeLabel=${this._computeLabelCallback}
|
||||||
|
.computeHelper=${this._computeHelperCallback}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
dialogInitialFocus
|
||||||
|
></ha-form>
|
||||||
|
<mwc-button
|
||||||
|
slot="secondaryAction"
|
||||||
|
@click=${this.closeDialog}
|
||||||
|
dialogInitialFocus
|
||||||
|
>
|
||||||
|
${this._dialogParams.supervisor.localize("common.cancel")}
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
.disabled=${this._waiting || !this._data}
|
||||||
|
slot="primaryAction"
|
||||||
|
@click=${this._changeMount}
|
||||||
|
>
|
||||||
|
${this._dialogParams.supervisor.localize("common.save")}
|
||||||
|
</mwc-button>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeLabelCallback = (
|
||||||
|
// @ts-ignore
|
||||||
|
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
||||||
|
): string =>
|
||||||
|
this._dialogParams!.supervisor.localize(
|
||||||
|
`dialog.backup_location.options.${schema.name}.name`
|
||||||
|
) || schema.name;
|
||||||
|
|
||||||
|
private _computeHelperCallback = (
|
||||||
|
// @ts-ignore
|
||||||
|
schema: SchemaUnion<ReturnType<typeof SCHEMA>>
|
||||||
|
): string =>
|
||||||
|
this._dialogParams!.supervisor.localize(
|
||||||
|
`dialog.backup_location.options.${schema.name}.description`
|
||||||
|
);
|
||||||
|
|
||||||
|
private _valueChanged(ev: CustomEvent) {
|
||||||
|
const newLocation = ev.detail.value.default_backup_mount;
|
||||||
|
this._data = {
|
||||||
|
default_backup_mount: newLocation === "/backup" ? null : newLocation,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _changeMount() {
|
||||||
|
if (!this._data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._error = undefined;
|
||||||
|
this._waiting = true;
|
||||||
|
try {
|
||||||
|
await changeMountOptions(this.hass, this._data);
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = extractApiErrorMessage(err);
|
||||||
|
this._waiting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
.delete-btn {
|
||||||
|
--mdc-theme-primary: var(--error-color);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-hassio-backup-location": HassioBackupLocationDialog;
|
||||||
|
}
|
||||||
|
}
|
@@ -7,6 +7,7 @@ import { atLeastVersion } from "../../../../src/common/config/version";
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
||||||
import { slugify } from "../../../../src/common/string/slugify";
|
import { slugify } from "../../../../src/common/string/slugify";
|
||||||
|
import "../../../../src/components/ha-dialog";
|
||||||
import "../../../../src/components/buttons/ha-progress-button";
|
import "../../../../src/components/buttons/ha-progress-button";
|
||||||
import "../../../../src/components/ha-alert";
|
import "../../../../src/components/ha-alert";
|
||||||
import "../../../../src/components/ha-button-menu";
|
import "../../../../src/components/ha-button-menu";
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
|
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
||||||
|
|
||||||
|
export interface HassioBackupLocationDialogParams {
|
||||||
|
supervisor: Supervisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showHassioBackupLocationDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
dialogParams: HassioBackupLocationDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "dialog-hassio-backup-location",
|
||||||
|
dialogImport: () => import("./dialog-hassio-backup-location"),
|
||||||
|
dialogParams,
|
||||||
|
});
|
||||||
|
};
|
@@ -218,7 +218,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
private _handleKeyAdd(ev: KeyboardEvent) {
|
private _handleKeyAdd(ev: KeyboardEvent) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if (ev.keyCode !== 13) {
|
if (ev.key !== "Enter") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._addRepository();
|
this._addRepository();
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
|
||||||
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../src/data/supervisor/supervisor";
|
||||||
import {
|
import {
|
||||||
@@ -22,9 +23,15 @@ class HassioRouter extends HassRouterPage {
|
|||||||
protected routerOptions: RouterOptions = {
|
protected routerOptions: RouterOptions = {
|
||||||
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
// Hass.io has a page with tabs, so we route all non-matching routes to it.
|
||||||
defaultPage: "dashboard",
|
defaultPage: "dashboard",
|
||||||
beforeRender: (page: string) =>
|
beforeRender: (page: string) => {
|
||||||
page === "snapshots" ? "backups" : undefined,
|
if (page === "snapshots") {
|
||||||
initialLoad: () => this._redirectIngress(),
|
return "backups";
|
||||||
|
}
|
||||||
|
if (page === "dashboard" && this.panel.config?.ingress) {
|
||||||
|
return "ingress";
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
@@ -55,32 +62,28 @@ class HassioRouter extends HassRouterPage {
|
|||||||
|
|
||||||
protected updatePageEl(el) {
|
protected updatePageEl(el) {
|
||||||
// the tabs page does its own routing so needs full route.
|
// the tabs page does its own routing so needs full route.
|
||||||
const hassioPanel = el.nodeName === "HASSIO-PANEL";
|
const hassioPanel = el.localName === "hassio-panel";
|
||||||
const route = hassioPanel ? this.route : this.routeTail;
|
const ingressPanel = el.localName === "hassio-ingress-view";
|
||||||
|
const route = hassioPanel
|
||||||
if (hassioPanel && this.panel.config?.ingress) {
|
? this.route
|
||||||
this._redirectIngress();
|
: ingressPanel && this.panel.config?.ingress
|
||||||
return;
|
? this._ingressRoute(this.panel.config?.ingress)
|
||||||
}
|
: this.routeTail;
|
||||||
|
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
el.route = route;
|
el.route = route;
|
||||||
el.supervisor = this.supervisor;
|
el.supervisor = this.supervisor;
|
||||||
|
|
||||||
if (el.localName === "hassio-ingress-view") {
|
if (ingressPanel) {
|
||||||
el.ingressPanel = this.panel.config && this.panel.config.ingress;
|
el.ingressPanel = Boolean(this.panel.config?.ingress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _redirectIngress() {
|
private _ingressRoute = memoizeOne((ingress: string) => ({
|
||||||
if (this.panel.config && this.panel.config.ingress) {
|
prefix: "/hassio/ingress",
|
||||||
this.route = {
|
path: `/${ingress}`,
|
||||||
prefix: "/hassio",
|
}));
|
||||||
path: `/ingress/${this.panel.config.ingress}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@@ -53,78 +53,54 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
|
|
||||||
public connectedCallback(): void {
|
public connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this._initializeLocalize();
|
if (!this.hasUpdated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.route?.prefix === "/hassio") {
|
||||||
|
this._initSupervisor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnectedCallback() {
|
public disconnectedCallback() {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
Object.keys(this._unsubs).forEach((unsub) => {
|
Object.keys(this._unsubs).forEach((unsub) => {
|
||||||
this._unsubs[unsub]();
|
this._unsubs[unsub]();
|
||||||
|
delete this._unsubs[unsub];
|
||||||
});
|
});
|
||||||
|
this.removeEventListener(
|
||||||
|
"supervisor-collection-refresh",
|
||||||
|
this._handleSupervisorStoreRefreshEvent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues) {
|
protected willUpdate(changedProperties: PropertyValues) {
|
||||||
super.updated(changedProperties);
|
if (!this.hasUpdated) {
|
||||||
|
if (this.route?.prefix === "/hassio") {
|
||||||
|
this._initSupervisor();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (changedProperties.has("hass")) {
|
if (changedProperties.has("hass")) {
|
||||||
const oldHass = changedProperties.get("hass") as
|
const oldHass = changedProperties.get("hass") as
|
||||||
| HomeAssistant
|
| HomeAssistant
|
||||||
| undefined;
|
| undefined;
|
||||||
if (
|
if (oldHass?.language !== this.hass.language) {
|
||||||
oldHass !== undefined &&
|
|
||||||
oldHass.language !== undefined &&
|
|
||||||
oldHass.language !== this.hass.language
|
|
||||||
) {
|
|
||||||
this._language = this.hass.language;
|
this._language = this.hass.language;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProperties.has("_language")) {
|
if (changedProperties.has("_language") || !this.hasUpdated) {
|
||||||
if (changedProperties.get("_language") !== this._language) {
|
this._initializeLocalize();
|
||||||
this._initializeLocalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProperties.has("_collections")) {
|
|
||||||
if (this._collections) {
|
|
||||||
const unsubs = Object.keys(this._unsubs);
|
|
||||||
for (const collection of Object.keys(this._collections)) {
|
|
||||||
if (!unsubs.includes(collection)) {
|
|
||||||
this._unsubs[collection] = this._collections[collection].subscribe(
|
|
||||||
(data) => this._updateSupervisor({ [collection]: data })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _updateSupervisor(obj: Partial<Supervisor>): void {
|
protected _updateSupervisor(update: Partial<Supervisor>): void {
|
||||||
this.supervisor = { ...this.supervisor, ...obj };
|
this.supervisor = { ...this.supervisor, ...update };
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues): void {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
if (
|
|
||||||
this._language !== this.hass.language &&
|
|
||||||
this.hass.language !== undefined
|
|
||||||
) {
|
|
||||||
this._language = this.hass.language;
|
|
||||||
}
|
|
||||||
this._initializeLocalize();
|
|
||||||
if (this.route?.prefix === "/hassio") {
|
|
||||||
this._initSupervisor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _initializeLocalize() {
|
private async _initializeLocalize() {
|
||||||
const { language, data } = await getTranslation(
|
const { language, data } = await getTranslation(null, this._language);
|
||||||
null,
|
|
||||||
this._language,
|
|
||||||
"/api/hassio/app/static/translations"
|
|
||||||
);
|
|
||||||
|
|
||||||
this.supervisor = {
|
this._updateSupervisor({
|
||||||
...this.supervisor,
|
|
||||||
localize: await computeLocalize<SupervisorKeys>(
|
localize: await computeLocalize<SupervisorKeys>(
|
||||||
this.constructor.prototype,
|
this.constructor.prototype,
|
||||||
language,
|
language,
|
||||||
@@ -132,7 +108,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
[language]: data,
|
[language]: data,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _handleSupervisorStoreRefreshEvent(ev) {
|
private async _handleSupervisorStoreRefreshEvent(ev) {
|
||||||
@@ -149,6 +125,17 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
this._updateSupervisor({ [collection]: response.data });
|
this._updateSupervisor({ [collection]: response.data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _subscribeCollection(collection: string) {
|
||||||
|
if (this._unsubs[collection]) {
|
||||||
|
this._unsubs[collection]();
|
||||||
|
}
|
||||||
|
this._unsubs[collection] = this._collections[collection].subscribe((data) =>
|
||||||
|
this._updateSupervisor({
|
||||||
|
[collection]: data,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private async _initSupervisor(): Promise<void> {
|
private async _initSupervisor(): Promise<void> {
|
||||||
this.addEventListener(
|
this.addEventListener(
|
||||||
"supervisor-collection-refresh",
|
"supervisor-collection-refresh",
|
||||||
@@ -158,6 +145,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
||||||
Object.keys(supervisorCollection).forEach((collection) => {
|
Object.keys(supervisorCollection).forEach((collection) => {
|
||||||
if (collection in this._collections) {
|
if (collection in this._collections) {
|
||||||
|
this._subscribeCollection(collection);
|
||||||
this._collections[collection].refresh();
|
this._collections[collection].refresh();
|
||||||
} else {
|
} else {
|
||||||
this._collections[collection] = getSupervisorEventCollection(
|
this._collections[collection] = getSupervisorEventCollection(
|
||||||
@@ -165,17 +153,13 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
collection,
|
collection,
|
||||||
supervisorCollection[collection]
|
supervisorCollection[collection]
|
||||||
);
|
);
|
||||||
}
|
if (this._collections[collection].state) {
|
||||||
});
|
// happens when the grace period of the collection unsubscribe has not passed yet
|
||||||
|
this._updateSupervisor({
|
||||||
Object.keys(this._collections).forEach((collection) => {
|
[collection]: this._collections[collection].state,
|
||||||
if (
|
});
|
||||||
this.supervisor === undefined ||
|
}
|
||||||
this.supervisor[collection] === undefined
|
this._subscribeCollection(collection);
|
||||||
) {
|
|
||||||
this._updateSupervisor({
|
|
||||||
[collection]: this._collections[collection].state,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
160
package.json
160
package.json
@@ -25,32 +25,34 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/runtime": "7.22.5",
|
||||||
"@braintree/sanitize-url": "6.0.2",
|
"@braintree/sanitize-url": "6.0.2",
|
||||||
"@codemirror/autocomplete": "6.5.1",
|
"@codemirror/autocomplete": "6.8.0",
|
||||||
"@codemirror/commands": "6.2.3",
|
"@codemirror/commands": "6.2.4",
|
||||||
"@codemirror/language": "6.6.0",
|
"@codemirror/language": "6.8.0",
|
||||||
"@codemirror/legacy-modes": "6.3.2",
|
"@codemirror/legacy-modes": "6.3.2",
|
||||||
"@codemirror/search": "6.3.0",
|
"@codemirror/search": "6.5.0",
|
||||||
"@codemirror/state": "6.2.0",
|
"@codemirror/state": "6.2.1",
|
||||||
"@codemirror/view": "6.9.5",
|
"@codemirror/view": "6.13.2",
|
||||||
"@egjs/hammerjs": "2.0.17",
|
"@egjs/hammerjs": "2.0.17",
|
||||||
"@formatjs/intl-datetimeformat": "6.7.0",
|
"@formatjs/intl-datetimeformat": "6.10.0",
|
||||||
"@formatjs/intl-displaynames": "6.3.1",
|
"@formatjs/intl-displaynames": "6.5.0",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.1.0",
|
"@formatjs/intl-getcanonicallocales": "2.2.1",
|
||||||
"@formatjs/intl-locale": "3.2.1",
|
"@formatjs/intl-listformat": "7.4.0",
|
||||||
"@formatjs/intl-numberformat": "8.4.1",
|
"@formatjs/intl-locale": "3.3.2",
|
||||||
"@formatjs/intl-pluralrules": "5.2.1",
|
"@formatjs/intl-numberformat": "8.7.0",
|
||||||
"@formatjs/intl-relativetimeformat": "11.2.1",
|
"@formatjs/intl-pluralrules": "5.2.4",
|
||||||
"@fullcalendar/core": "6.1.5",
|
"@formatjs/intl-relativetimeformat": "11.2.4",
|
||||||
"@fullcalendar/daygrid": "6.1.5",
|
"@fullcalendar/core": "6.1.8",
|
||||||
"@fullcalendar/interaction": "6.1.5",
|
"@fullcalendar/daygrid": "6.1.8",
|
||||||
"@fullcalendar/list": "6.1.5",
|
"@fullcalendar/interaction": "6.1.8",
|
||||||
"@fullcalendar/timegrid": "6.1.5",
|
"@fullcalendar/list": "6.1.8",
|
||||||
"@lezer/highlight": "1.1.4",
|
"@fullcalendar/timegrid": "6.1.8",
|
||||||
"@lit-labs/context": "0.3.0",
|
"@lezer/highlight": "1.1.6",
|
||||||
|
"@lit-labs/context": "0.3.3",
|
||||||
"@lit-labs/motion": "1.0.3",
|
"@lit-labs/motion": "1.0.3",
|
||||||
"@lit-labs/virtualizer": "1.0.1",
|
"@lit-labs/virtualizer": "2.0.3",
|
||||||
"@lrnwebcomponents/simple-tooltip": "4.1.0",
|
"@lrnwebcomponents/simple-tooltip": "7.0.2",
|
||||||
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
|
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
|
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/mwc-button": "0.27.0",
|
"@material/mwc-button": "0.27.0",
|
||||||
@@ -76,7 +78,7 @@
|
|||||||
"@material/mwc-top-app-bar": "0.27.0",
|
"@material/mwc-top-app-bar": "0.27.0",
|
||||||
"@material/mwc-top-app-bar-fixed": "0.27.0",
|
"@material/mwc-top-app-bar-fixed": "0.27.0",
|
||||||
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
|
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
|
||||||
"@material/web": "=1.0.0-pre.4",
|
"@material/web": "=1.0.0-pre.10",
|
||||||
"@mdi/js": "7.2.96",
|
"@mdi/js": "7.2.96",
|
||||||
"@mdi/svg": "7.2.96",
|
"@mdi/svg": "7.2.96",
|
||||||
"@polymer/app-layout": "3.1.0",
|
"@polymer/app-layout": "3.1.0",
|
||||||
@@ -91,8 +93,8 @@
|
|||||||
"@polymer/paper-toast": "3.0.1",
|
"@polymer/paper-toast": "3.0.1",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.1",
|
||||||
"@thomasloven/round-slider": "0.6.0",
|
"@thomasloven/round-slider": "0.6.0",
|
||||||
"@vaadin/combo-box": "23.3.11",
|
"@vaadin/combo-box": "24.1.1",
|
||||||
"@vaadin/vaadin-themable-mixin": "23.3.11",
|
"@vaadin/vaadin-themable-mixin": "24.1.1",
|
||||||
"@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",
|
||||||
@@ -102,91 +104,92 @@
|
|||||||
"app-datepicker": "5.1.1",
|
"app-datepicker": "5.1.1",
|
||||||
"chart.js": "3.3.2",
|
"chart.js": "3.3.2",
|
||||||
"comlink": "4.4.1",
|
"comlink": "4.4.1",
|
||||||
"core-js": "3.30.1",
|
"core-js": "3.31.0",
|
||||||
"cropperjs": "1.5.13",
|
"cropperjs": "1.5.13",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "2.30.0",
|
||||||
"date-fns-tz": "2.0.0",
|
"date-fns-tz": "2.0.0",
|
||||||
"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.6.2",
|
"fuse.js": "6.6.2",
|
||||||
"google-timezones-json": "1.1.0",
|
"google-timezones-json": "1.1.0",
|
||||||
"hls.js": "1.3.5",
|
"hls.js": "1.4.6",
|
||||||
"home-assistant-js-websocket": "8.0.1",
|
"home-assistant-js-websocket": "8.0.1",
|
||||||
"idb-keyval": "6.2.0",
|
"idb-keyval": "6.2.1",
|
||||||
"intl-messageformat": "10.3.4",
|
"intl-messageformat": "10.5.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"leaflet": "1.9.3",
|
"leaflet": "1.9.4",
|
||||||
"leaflet-draw": "1.0.4",
|
"leaflet-draw": "1.0.4",
|
||||||
"lit": "2.7.2",
|
"lit": "2.7.5",
|
||||||
"marked": "4.3.0",
|
"marked": "4.3.0",
|
||||||
"memoize-one": "6.0.0",
|
"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.3.0",
|
"punycode": "2.3.0",
|
||||||
"qr-scanner": "1.4.2",
|
"qr-scanner": "1.4.2",
|
||||||
"qrcode": "1.5.1",
|
"qrcode": "1.5.3",
|
||||||
"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.2",
|
"rrule": "2.7.2",
|
||||||
"sortablejs": "1.15.0",
|
"sortablejs": "1.15.0",
|
||||||
"superstruct": "1.0.3",
|
"superstruct": "1.0.3",
|
||||||
"tinykeys": "1.4.0",
|
"tinykeys": "2.1.0",
|
||||||
"tsparticles-engine": "2.9.3",
|
"tsparticles-engine": "2.10.1",
|
||||||
"tsparticles-preset-links": "2.9.3",
|
"tsparticles-preset-links": "2.10.1",
|
||||||
"unfetch": "5.0.0",
|
"unfetch": "5.0.0",
|
||||||
"vis-data": "7.1.6",
|
"vis-data": "7.1.6",
|
||||||
"vis-network": "9.1.6",
|
"vis-network": "9.1.6",
|
||||||
"vue": "2.7.14",
|
"vue": "2.7.14",
|
||||||
"vue2-daterange-picker": "0.6.8",
|
"vue2-daterange-picker": "0.6.8",
|
||||||
"weekstart": "2.0.0",
|
"weekstart": "2.0.0",
|
||||||
"workbox-cacheable-response": "6.5.4",
|
"workbox-cacheable-response": "7.0.0",
|
||||||
"workbox-core": "6.5.4",
|
"workbox-core": "7.0.0",
|
||||||
"workbox-expiration": "6.5.4",
|
"workbox-expiration": "7.0.0",
|
||||||
"workbox-precaching": "6.5.4",
|
"workbox-precaching": "7.0.0",
|
||||||
"workbox-routing": "6.5.4",
|
"workbox-routing": "7.0.0",
|
||||||
"workbox-strategies": "6.5.4",
|
"workbox-strategies": "7.0.0",
|
||||||
"xss": "1.0.14"
|
"xss": "1.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.21.4",
|
"@babel/core": "7.22.5",
|
||||||
"@babel/plugin-proposal-decorators": "7.21.0",
|
"@babel/plugin-proposal-decorators": "7.22.5",
|
||||||
"@babel/preset-env": "7.21.4",
|
"@babel/plugin-transform-runtime": "7.22.5",
|
||||||
"@babel/preset-typescript": "7.21.4",
|
"@babel/preset-env": "7.22.5",
|
||||||
|
"@babel/preset-typescript": "7.22.5",
|
||||||
"@koa/cors": "4.0.0",
|
"@koa/cors": "4.0.0",
|
||||||
"@octokit/auth-oauth-device": "4.0.4",
|
"@octokit/auth-oauth-device": "5.0.2",
|
||||||
"@octokit/plugin-retry": "4.1.3",
|
"@octokit/plugin-retry": "5.0.4",
|
||||||
"@octokit/rest": "19.0.7",
|
"@octokit/rest": "19.0.13",
|
||||||
"@open-wc/dev-server-hmr": "0.1.4",
|
"@open-wc/dev-server-hmr": "0.1.4",
|
||||||
"@rollup/plugin-babel": "6.0.3",
|
"@rollup/plugin-babel": "6.0.3",
|
||||||
"@rollup/plugin-commonjs": "24.1.0",
|
"@rollup/plugin-commonjs": "25.0.1",
|
||||||
"@rollup/plugin-json": "6.0.0",
|
"@rollup/plugin-json": "6.0.0",
|
||||||
"@rollup/plugin-node-resolve": "15.0.2",
|
"@rollup/plugin-node-resolve": "15.1.0",
|
||||||
"@rollup/plugin-replace": "5.0.2",
|
"@rollup/plugin-replace": "5.0.2",
|
||||||
"@types/chromecast-caf-receiver": "5.0.12",
|
"@types/babel__plugin-transform-runtime": "7.9.2",
|
||||||
|
"@types/chromecast-caf-receiver": "6.0.9",
|
||||||
"@types/chromecast-caf-sender": "1.0.5",
|
"@types/chromecast-caf-sender": "1.0.5",
|
||||||
"@types/esprima": "4.0.3",
|
"@types/esprima": "4.0.3",
|
||||||
"@types/glob": "8.1.0",
|
"@types/glob": "8.1.0",
|
||||||
"@types/html-minifier-terser": "7.0.0",
|
"@types/html-minifier-terser": "7.0.0",
|
||||||
"@types/js-yaml": "4.0.5",
|
"@types/js-yaml": "4.0.5",
|
||||||
"@types/leaflet": "1.9.3",
|
"@types/leaflet": "1.9.3",
|
||||||
"@types/leaflet-draw": "1.0.6",
|
"@types/leaflet-draw": "1.0.7",
|
||||||
"@types/marked": "4.0.8",
|
"@types/marked": "4.3.1",
|
||||||
"@types/mocha": "10.0.1",
|
"@types/mocha": "10.0.1",
|
||||||
"@types/qrcode": "1.5.0",
|
"@types/qrcode": "1.5.0",
|
||||||
"@types/serve-handler": "6.1.1",
|
"@types/serve-handler": "6.1.1",
|
||||||
"@types/sortablejs": "1.15.1",
|
"@types/sortablejs": "1.15.1",
|
||||||
"@types/tar": "6.1.4",
|
"@types/tar": "6.1.5",
|
||||||
"@types/webspeechapi": "0.0.29",
|
"@types/webspeechapi": "0.0.29",
|
||||||
"@typescript-eslint/eslint-plugin": "5.59.0",
|
"@typescript-eslint/eslint-plugin": "5.59.11",
|
||||||
"@typescript-eslint/parser": "5.59.0",
|
"@typescript-eslint/parser": "5.59.11",
|
||||||
"@web/dev-server": "0.1.38",
|
"@web/dev-server": "0.1.38",
|
||||||
"@web/dev-server-rollup": "0.4.1",
|
"@web/dev-server-rollup": "0.4.1",
|
||||||
"babel-loader": "9.1.2",
|
"babel-loader": "9.1.2",
|
||||||
"babel-plugin-template-html-minifier": "4.1.0",
|
"babel-plugin-template-html-minifier": "4.1.0",
|
||||||
"chai": "4.3.7",
|
"chai": "4.3.7",
|
||||||
"del": "7.0.0",
|
"del": "7.0.0",
|
||||||
"eslint": "8.38.0",
|
"eslint": "8.43.0",
|
||||||
"eslint-config-airbnb-base": "15.0.0",
|
"eslint-config-airbnb-base": "15.0.0",
|
||||||
"eslint-config-airbnb-typescript": "17.0.0",
|
"eslint-config-airbnb-typescript": "17.0.0",
|
||||||
"eslint-config-prettier": "8.8.0",
|
"eslint-config-prettier": "8.8.0",
|
||||||
@@ -194,13 +197,13 @@
|
|||||||
"eslint-plugin-disable": "2.0.3",
|
"eslint-plugin-disable": "2.0.3",
|
||||||
"eslint-plugin-import": "2.27.5",
|
"eslint-plugin-import": "2.27.5",
|
||||||
"eslint-plugin-lit": "1.8.3",
|
"eslint-plugin-lit": "1.8.3",
|
||||||
"eslint-plugin-lit-a11y": "2.4.1",
|
"eslint-plugin-lit-a11y": "3.0.0",
|
||||||
"eslint-plugin-unused-imports": "2.0.0",
|
"eslint-plugin-unused-imports": "2.0.0",
|
||||||
"eslint-plugin-wc": "1.4.0",
|
"eslint-plugin-wc": "1.5.0",
|
||||||
"esprima": "4.0.1",
|
"esprima": "4.0.1",
|
||||||
"fancy-log": "2.0.0",
|
"fancy-log": "2.0.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
"glob": "10.2.1",
|
"glob": "10.2.7",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-flatmap": "1.0.2",
|
"gulp-flatmap": "1.0.2",
|
||||||
"gulp-json-transform": "0.4.8",
|
"gulp-json-transform": "0.4.8",
|
||||||
@@ -211,46 +214,47 @@
|
|||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"instant-mocha": "1.5.1",
|
"instant-mocha": "1.5.1",
|
||||||
"jszip": "3.10.1",
|
"jszip": "3.10.1",
|
||||||
"lint-staged": "13.2.1",
|
"lint-staged": "13.2.2",
|
||||||
"lit-analyzer": "1.2.1",
|
"lit-analyzer": "2.0.0-pre.3",
|
||||||
"lodash.template": "4.5.0",
|
"lodash.template": "4.5.0",
|
||||||
"magic-string": "0.30.0",
|
"magic-string": "0.30.0",
|
||||||
"map-stream": "0.0.7",
|
"map-stream": "0.0.7",
|
||||||
"merge-stream": "2.0.0",
|
"merge-stream": "2.0.0",
|
||||||
"mocha": "10.2.0",
|
"mocha": "10.2.0",
|
||||||
"object-hash": "3.0.0",
|
"object-hash": "3.0.0",
|
||||||
"open": "8.4.2",
|
"open": "9.1.0",
|
||||||
"pinst": "3.0.0",
|
"pinst": "3.0.0",
|
||||||
"prettier": "2.8.7",
|
"prettier": "2.8.8",
|
||||||
"rollup": "2.79.1",
|
"rollup": "2.79.1",
|
||||||
"rollup-plugin-string": "3.0.0",
|
"rollup-plugin-string": "3.0.0",
|
||||||
"rollup-plugin-terser": "7.0.2",
|
"rollup-plugin-terser": "7.0.2",
|
||||||
"rollup-plugin-visualizer": "5.9.0",
|
"rollup-plugin-visualizer": "5.9.2",
|
||||||
"serve-handler": "6.1.5",
|
"serve-handler": "6.1.5",
|
||||||
"sinon": "15.0.4",
|
"sinon": "15.1.2",
|
||||||
"source-map-url": "0.4.1",
|
"source-map-url": "0.4.1",
|
||||||
"systemjs": "6.14.1",
|
"systemjs": "6.14.1",
|
||||||
"tar": "6.1.13",
|
"tar": "6.1.15",
|
||||||
"terser-webpack-plugin": "5.3.7",
|
"terser-webpack-plugin": "5.3.9",
|
||||||
"ts-lit-plugin": "1.2.1",
|
"ts-lit-plugin": "2.0.0-pre.1",
|
||||||
"typescript": "4.9.5",
|
"typescript": "5.1.3",
|
||||||
"vinyl-buffer": "1.0.1",
|
"vinyl-buffer": "1.0.1",
|
||||||
"vinyl-source-stream": "2.0.0",
|
"vinyl-source-stream": "2.0.0",
|
||||||
"webpack": "=5.72.1",
|
"webpack": "5.87.0",
|
||||||
"webpack-cli": "5.0.1",
|
"webpack-cli": "5.1.4",
|
||||||
"webpack-dev-server": "4.13.3",
|
"webpack-dev-server": "4.15.1",
|
||||||
"webpack-manifest-plugin": "5.0.0",
|
"webpack-manifest-plugin": "5.0.0",
|
||||||
"webpackbar": "5.0.2",
|
"webpackbar": "5.0.2",
|
||||||
"workbox-build": "6.5.4"
|
"workbox-build": "7.0.0"
|
||||||
},
|
},
|
||||||
"_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.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
"@polymer/polymer": "patch:@polymer/polymer@3.5.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
||||||
"@material/mwc-button@^0.25.3": "^0.27.0"
|
"@material/mwc-button@^0.25.3": "^0.27.0",
|
||||||
|
"sortablejs@1.15.0": "patch:sortablejs@npm%3A1.15.0#./.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@3.5.0"
|
"packageManager": "yarn@3.6.0"
|
||||||
}
|
}
|
||||||
|
BIN
public/static/images/color_wheel.png
Normal file
BIN
public/static/images/color_wheel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20230503.3"
|
version = "20230608.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"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "The Home Assistant Authors", email = "hello@home-assistant.io"}
|
{name = "The Home Assistant Authors", email = "hello@home-assistant.io"}
|
||||||
]
|
]
|
||||||
requires-python = ">=3.4.0"
|
requires-python = ">=3.10.0"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
"Homepage" = "https://github.com/home-assistant/frontend"
|
"Homepage" = "https://github.com/home-assistant/frontend"
|
||||||
|
@@ -19,14 +19,20 @@
|
|||||||
},
|
},
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"description": ["MDC packages are pinned to the same version as MWC"],
|
"description": "MDC packages are pinned to the same version as MWC",
|
||||||
"extends": ["monorepo:material-components-web"],
|
"extends": ["monorepo:material-components-web"],
|
||||||
"enabled": false
|
"enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": ["Vue is only used by date range which is only v2"],
|
"description": "Vue is only used by date range which is only v2",
|
||||||
"matchPackageNames": ["vue"],
|
"matchPackageNames": ["vue"],
|
||||||
"allowedVersions": "< 3"
|
"allowedVersions": "< 3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Group tsparticles engine and presets",
|
||||||
|
"groupName": "tsparticles",
|
||||||
|
"matchPackageNames": ["tsparticles-engine"],
|
||||||
|
"matchPackagePrefixes": ["tsparticles-preset-"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash -i
|
||||||
# Resolve all frontend dependencies that the application requires to develop.
|
# Resolve all frontend dependencies that the application requires to develop.
|
||||||
|
|
||||||
# Stop on errors
|
# Stop on errors
|
||||||
@@ -6,5 +6,17 @@ set -e
|
|||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
# Install/upgrade node when inside devcontainer
|
||||||
|
if [[ -n "$DEVCONTAINER" ]]; then
|
||||||
|
nodeCurrent=$(nvm version default || :)
|
||||||
|
nodeLatest=$(nvm version-remote "$(cat .nvmrc)")
|
||||||
|
if [[ -z "$nodeCurrent" || "$nodeCurrent" == "N/A" ]]; then
|
||||||
|
nvm install
|
||||||
|
elif [[ "$nodeCurrent" != "$nodeLatest" ]]; then
|
||||||
|
nvm install --reinstall-packages-from="$nodeCurrent" --default
|
||||||
|
nvm uninstall "$nodeCurrent"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Install node modules
|
# Install node modules
|
||||||
yarn install
|
yarn install
|
||||||
|
@@ -105,7 +105,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.addEventListener("keypress", (ev) => {
|
this.addEventListener("keypress", (ev) => {
|
||||||
if (ev.keyCode === 13) {
|
if (ev.key === "Enter") {
|
||||||
this._handleSubmit(ev);
|
this._handleSubmit(ev);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
/* eslint-disable no-undef, no-console */
|
/* eslint-disable no-console */
|
||||||
import {
|
|
||||||
CastStateEventData,
|
|
||||||
SessionStateEventData,
|
|
||||||
} from "chromecast-caf-receiver/cast.framework";
|
|
||||||
import { Auth } from "home-assistant-js-websocket";
|
import { Auth } from "home-assistant-js-websocket";
|
||||||
import { castApiAvailable } from "./cast_framework";
|
import { castApiAvailable } from "./cast_framework";
|
||||||
import { CAST_APP_ID, CAST_DEV, CAST_NS } from "./const";
|
import { CAST_APP_ID, CAST_DEV, CAST_NS } from "./const";
|
||||||
@@ -48,11 +45,11 @@ export class CastManager {
|
|||||||
});
|
});
|
||||||
context.addEventListener(
|
context.addEventListener(
|
||||||
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
|
||||||
(ev) => this._sessionStateChanged(ev)
|
this._sessionStateChanged
|
||||||
);
|
);
|
||||||
context.addEventListener(
|
context.addEventListener(
|
||||||
cast.framework.CastContextEventType.CAST_STATE_CHANGED,
|
cast.framework.CastContextEventType.CAST_STATE_CHANGED,
|
||||||
(ev) => this._castStateChanged(ev)
|
this._castStateChanged
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +116,7 @@ export class CastManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sessionStateChanged(ev: SessionStateEventData) {
|
private _sessionStateChanged = (ev: cast.framework.SessionStateEventData) => {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.log("Cast session state changed", ev.sessionState);
|
console.log("Cast session state changed", ev.sessionState);
|
||||||
}
|
}
|
||||||
@@ -140,14 +137,14 @@ export class CastManager {
|
|||||||
this.status = undefined;
|
this.status = undefined;
|
||||||
this._fireEvent("connection-changed");
|
this._fireEvent("connection-changed");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
private _castStateChanged(ev: CastStateEventData) {
|
private _castStateChanged = (ev: cast.framework.CastStateEventData) => {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.log("Cast state changed", ev.castState);
|
console.log("Cast state changed", ev.castState);
|
||||||
}
|
}
|
||||||
this._fireEvent("state-changed");
|
this._fireEvent("state-changed");
|
||||||
}
|
};
|
||||||
|
|
||||||
private _attachMessageListener() {
|
private _attachMessageListener() {
|
||||||
const session = this.castSession;
|
const session = this.castSession;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user