Compare commits

...

381 Commits

Author SHA1 Message Date
J. Nick Koston
ecba22d301 Merge branch 'dev' into persistent_notification_trigger 2023-06-22 01:44:19 +02:00
J. Nick Koston
72172cabc2 Migrate to using dismiss_all for persistent_notification 2023-06-22 01:41:49 +02:00
Bram Kragten
eb552530e2 Add support for image entity (#16877) 2023-06-21 17:46:40 +02:00
Paul Bottein
1fe5d66a68 Allow cards and tile features to provide a schema to create the editor (#16142)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-21 17:22:33 +02:00
Bram Kragten
7faa165558 Refactor Storage decorator (#16987) 2023-06-21 17:22:10 +02:00
karwosts
752bc192cd Fix types selection for statistics-graph-card (#16988) 2023-06-21 15:10:00 +00:00
Paul Bottein
e9961b93f9 Add circular slider (#16981)
* WIP Create round slider

* Fix interaction on iOS

* Add dual and simple gauge

* Add events

* Rename events

* Use low and high

* Improve dual slider selection

* Add min and max

* Rename component

* Prevents setting a high value lower than low and vice versa

* Add keyboard support

* Fix typings

* Use html

* Update current indicator

* Improve doc

* Fix keyboard focus after mouse interaction

* Don't fallback to value
2023-06-21 15:01:45 +00:00
c0ffeeca7
bbdcc021d4 TTS and STT: standardize spelling (#16685) 2023-06-21 13:46:08 +02:00
Vasilis Koulis
3d6cfc4037 open option for lock (#14852)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-21 09:59:28 +00:00
RoboMagus
9b35c06eef Add persistent_notification trigger (#16967)
Co-authored-by: J. Nick Koston <nick@koston.org>
2023-06-21 11:55:55 +02:00
Joakim Sørensen
b46c74fe76 Add haStyleScrollbar to hass-subpage (#16745) 2023-06-21 11:35:17 +02:00
Joakim Sørensen
5aa6ffe2e4 Map GitHub block quotes to our ha-alert component (#16757) 2023-06-21 11:35:02 +02:00
J. Nick Koston
4ffd31974c switch to schema 2023-06-21 10:38:57 +02:00
J. Nick Koston
1faef71dcb tweak 2023-06-21 10:25:53 +02:00
J. Nick Koston
1e5c35c158 Merge branch 'dev' into persistent_notification_trigger 2023-06-21 09:58:42 +02:00
J. Nick Koston
2e3ce4ae9e lint 2023-06-21 09:57:39 +02:00
karwosts
07d37dd89f Handle multiple triggers in trigger condition UI (#16983) 2023-06-21 08:50:01 +02:00
Lasse Bang Mikkelsen
33d6ad1b0b Add copy-to-clipboard button for long-lived tokens (#16956) 2023-06-21 06:19:25 +00:00
Simon Lamon
386ed2167f Make automation editor card headers translateable (triggers partly) (#16969) 2023-06-21 08:12:04 +02:00
karwosts
221f4f34a7 Use new automation dialog for new scripts (#16933) 2023-06-21 08:04:39 +02:00
karwosts
c63c717d9f Add 'Default' option to theme-picker (#16915) 2023-06-21 08:03:17 +02:00
Paul Bottein
1cb1bcf274 Open assist from dashboard (#16829) 2023-06-21 08:02:09 +02:00
RoboMagus
30f2a49fbf Simplified update_types localizations 2023-06-20 17:53:33 +02:00
karwosts
1cf24ffc8d Allow continue_on_error in the UI action editor (#16834) 2023-06-20 14:53:13 +00:00
Paul Bottein
13b864e261 Use ha-icon-button-group in more info cover (#16911) 2023-06-20 16:45:45 +02:00
Paul Bottein
7bc2ca3b65 Add more info lock (#15995)
* Add more info lock

* Use same height for pending state

* Fix attributes

* Add unlocking/locking to switch

* Improve code support
2023-06-20 15:25:26 +02:00
RoboMagus
101e9323a7 Review updates 2023-06-20 14:58:24 +02:00
Christoph Wen, B.Sc
922e95b895 Fix time and date-time 12h formats (#16692) (#16805)
* Fix time and date-time 12h formats  (#16692)

- am/pm check possible for other languages
- adjusted date format gallery page for consistency
- added gallery pages for date-time and time formats

* Fix typo in am/pm check (#16692)
2023-06-20 12:52:53 +02:00
renovate[bot]
baaa012101 Update octokit monorepo (#16979)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-20 12:07:01 +02:00
breakthestatic
3888b1c48b Use fuzzy filter/sort for target pickers (#16912)
* Use fuzzy filter/sort for target pickers

* PR suggestions

* Restore missed sort
2023-06-20 12:03:55 +02:00
karwosts
332af4003e History graph should start at requested time even if sensor is unavailable (#16850)
History graph should start at consistent time if sensor is unavailable
2023-06-20 12:00:33 +02:00
renovate[bot]
044a44e114 Update dependency @lit-labs/context to v0.3.3 (#16975)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-20 11:56:05 +02:00
c0ffeeca7
13c932a8f8 Thread: Rename "My network" to "Preferred network" (#16980)
- All networks in my household are my networks. Otherwise they are my neighbor's.
- within my networks, this one is my preferred one (as opposed to other networks)
2023-06-20 10:43:28 +02:00
renovate[bot]
be1089302f Update dependency @octokit/rest to v19.0.12 (#16973)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-19 17:52:51 +00:00
Steve Repsher
540df024d9 Upgrade to python 3.11 (#16948) 2023-06-19 19:50:45 +02:00
Bram Kragten
e7c8bd4c41 Bump Vaadin (#16971) 2023-06-19 13:48:54 -04:00
renovate[bot]
7c15a65bba Update dependency @lit-labs/virtualizer to v2.0.3 (#16761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-19 14:21:08 +00:00
karwosts
5381a467e5 Fix blueprint script editor erroneously setting mode field (#16934) 2023-06-19 13:43:04 +00:00
renovate[bot]
a96d3594ba Update dependency typescript to v5 (#15877)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-19 13:03:48 +00:00
RoboMagus
4526a46a56 Add persistent_notification trigger 2023-06-19 15:02:53 +02:00
Steve Repsher
1d0d4755d0 Update lit-analyzer and ts-lit-plugin to version 2 (#16954) 2023-06-19 14:30:16 +02:00
Till
fa75b18a6b Add self-sufficiency gauge card (#15704)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-19 13:59:20 +02:00
Joakim Sørensen
cdd29c8bf7 Add help button to get documentation from mount dialog (#16932) 2023-06-19 11:54:47 +00:00
Paul Bottein
215f5e341a Put color wheel at the root level for more info light (#16909) 2023-06-19 13:50:37 +02:00
Franck Nijhof
8abb58ae7d Add preheating HVAC action to climate (#16922) 2023-06-19 13:36:19 +02:00
karwosts
40c8301df0 Allow templates in service template/object selector (#16925) 2023-06-19 13:33:28 +02:00
Simon Lamon
80f3d6aacb Change all occurrences to use Intl.ListFormat (#16897) 2023-06-19 12:52:28 +02:00
dependabot[bot]
41310007fe Bump dessant/lock-threads from 4.0.0 to 4.0.1 (#16962)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 09:39:22 +02:00
renovate[bot]
195b1eef02 Lock file maintenance (#16961)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-19 05:26:18 +00:00
renovate[bot]
8e9b5ea66b Update dependency tsparticles-preset-links to v2.10.1 (#16802)
* Update dependency tsparticles-preset-links to v2.10.1

* Group future tsparticles updates

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
2023-06-19 05:10:21 +00:00
renovate[bot]
827d89628d Update dependency tsparticles-engine to v2.10.1 (#16790)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-18 23:52:23 -04:00
renovate[bot]
cac341a938 Update dependency hls.js to v1.4.6 (#16960)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-18 23:31:13 -04:00
J. Nick Koston
2b51228665 Fix notifications subscription leak when in narrow mode (#16953)
Fix persistent notifications subscription leak on mobile/narrow
2023-06-17 20:41:41 -04:00
renovate[bot]
79c010eb7b Update dependency webpack to v5.87.0 (#16949) 2023-06-17 20:34:43 -04:00
renovate[bot]
2a4356ce86 Update dependency tinykeys to v2.1.0 (#16951) 2023-06-17 20:33:36 -04:00
renovate[bot]
afdeb36258 Update vaadinWebComponents monorepo to v24.1.0 (#16844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 14:56:35 -04:00
renovate[bot]
d4f4ee1e59 Update dependency tinykeys to v2 (#16873)
* Update dependency tinykeys to v2

* Switch to named import

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
2023-06-17 16:53:36 +00:00
renovate[bot]
bcceef30bb Update dependency @octokit/auth-oauth-device to v5 (#16947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 12:46:30 -04:00
renovate[bot]
356935fefc Update formatjs monorepo (#16945)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 15:28:29 +00:00
renovate[bot]
49f59d7162 Update CodeMirror (#16942)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 11:17:37 -04:00
renovate[bot]
67e8357bb9 Update dependency sinon to v15.1.2 (#16940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 11:15:05 -04:00
renovate[bot]
b8da712186 Update typescript-eslint monorepo to v5.59.11 (#16941)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 11:13:30 -04:00
renovate[bot]
a409f494a2 Update dependency @types/leaflet-draw to v1.0.7 (#16939)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 05:55:36 +00:00
renovate[bot]
3b32825e2a Update dependency @octokit/plugin-retry to v5.0.3 (#16938)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 05:47:46 +00:00
renovate[bot]
12b7b903bc Update dependency core-js to v3.31.0 (#16913)
* Update dependency core-js to v3.31.0

* Update babel setting

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
2023-06-17 05:40:10 +00:00
Joakim Sørensen
3be601a3b9 Add location to backups table (#16813) 2023-06-15 16:08:32 +02:00
renovate[bot]
d0641d64bd Update dependency eslint-plugin-lit-a11y to v3 (#16910)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-14 16:03:53 -04:00
renovate[bot]
3a64f64894 Update dependency @material/web to v1.0.0-pre.10 (#16841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-14 18:08:19 +02:00
karwosts
7182abfec5 Fix history chart when final sensor state is unavailable (#16852) 2023-06-14 17:45:57 +02:00
JakobDNS
2076a083d3 en.json: Fix typo "recieved" -> "received" (#16903) 2023-06-14 16:18:02 +02:00
renovate[bot]
73317a48ee Update dependency rollup-plugin-visualizer to v5.9.2 (#16899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 17:27:30 -04:00
renovate[bot]
b891c53994 Update dependency webpack-dev-server to v4.15.1 (#16900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 17:26:26 -04:00
renovate[bot]
c1c18affbc Update dependency webpack to v5.86.0 (#16749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 16:09:57 -04:00
renovate[bot]
3bea2cf7f9 Update dependency @rollup/plugin-commonjs to v25.0.1 (#16892)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 15:28:58 -04:00
Steve Repsher
fa1a6affa7 Use ES modules and dynamic import for Webpack latest builds (#16849) 2023-06-13 18:12:44 +02:00
Bram Kragten
197638b282 Fix date demo in gallery (#16894) 2023-06-13 15:27:21 +00:00
karwosts
6e3cf0975b Fix mqtt debug info dialog too big (#16893) 2023-06-13 17:22:45 +02:00
Paul Bottein
9875cb2723 Only catch event inside color wheel (#16890) 2023-06-13 17:21:01 +02:00
Paul Bottein
f8ea7e0ef2 Make actions available as event (#16839) 2023-06-13 15:24:36 +02:00
renovate[bot]
c821f4296e Update dependency @octokit/auth-oauth-device to v4.0.5 (#16891)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 09:23:14 -04:00
Simon Lamon
5fc4e7a95d Introduce Intl.ListFormat (#16857)
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-13 15:22:23 +02:00
Paul Bottein
49fa7ec4ed Clear more info content when switching entity (#16846) 2023-06-13 12:20:02 +02:00
Bram Kragten
780de42e4b Allow to show times in the UI in the timezone of the server (#16799) 2023-06-13 12:12:13 +02:00
Paul Bottein
f7722a270f Add safe zone to reach min and max temperature easily with temperature (#16880)
Add safe zone to reach min and max temperature easily with temperature picker
2023-06-13 11:55:52 +02:00
Paul Bottein
e3faa618bf Use esm module for hls.js (#16878) 2023-06-12 07:49:39 -04:00
dependabot[bot]
655b630fa5 Bump actions/checkout from 3.5.2 to 3.5.3 (#16876)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 11:46:54 +02:00
renovate[bot]
983bba357a Update babel monorepo to v7.22.5 (#16872)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-11 17:42:06 -04:00
renovate[bot]
17a2560d94 Update dependency webpack-cli to v5.1.4 (#16862)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-11 13:28:12 -04:00
renovate[bot]
eaffed9ff8 Update dependency @octokit/plugin-retry to v5.0.2 (#16861)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-11 13:27:10 -04:00
Matthias Alphart
273992c8e9 Consolidate dependency updates in release-drafter (#16856) 2023-06-10 16:39:43 +02:00
renovate[bot]
c77905bd22 Update dependency glob to v10.2.7 (#16851) 2023-06-09 20:45:14 -04:00
renovate[bot]
15132783d4 Update formatjs monorepo (#16843)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 10:49:59 -04:00
Paul Bottein
2b6cf55638 Add paste to else automation action (#16840) 2023-06-09 16:38:01 +02:00
renovate[bot]
e4eaa52d53 Update dependency webpack-cli to v5.1.3 (#16809)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 09:04:55 -04:00
renovate[bot]
e1f73dac02 Update dependency hls.js to v1.4.5 (#16842)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 13:02:14 +00:00
renovate[bot]
36de0e5c8c Update CodeMirror (#16820)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 08:55:19 -04:00
renovate[bot]
549e4e7fb3 Update typescript-eslint monorepo to v5.59.9 (#16832)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 08:48:34 -04:00
renovate[bot]
dd9c4e35bf Update dependency @octokit/plugin-retry to v5.0.1 (#16835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 08:46:50 -04:00
Paul Bottein
8580d3f9bf Bumped version to 20230608.0 2023-06-08 15:08:18 +02:00
Bram Kragten
6d29b764d3 Integration page fixes (#16822) 2023-06-08 14:11:52 +02:00
Joakim Sørensen
78cff3a921 Use menu_options instead of menu_issues for translation (#16823) 2023-06-08 11:13:12 +00:00
Paul Bottein
e3c312feaf Sort related entities by name (#16821) 2023-06-08 13:01:46 +02:00
Paul Bottein
31e4166248 Make to full integration card header clickable (#16819) 2023-06-08 10:42:26 +02:00
Bram Kragten
0442e3e06e Bumped version to 20230607.0 2023-06-07 12:15:32 +02:00
english-ra
0a8252c16a Fixed issue where the cursor would not change to grabbing when a user… (#16808) 2023-06-07 09:44:54 +00:00
puddly
0a62d711f2 Allow the ZHA serial port path to wrap if it is too long (#16806)
Allow the serial port path to wrap if it is too long
2023-06-07 11:34:17 +02:00
karwosts
d7c3ff3e9d Fix cancel button in automation row alias rename dialog (#16810) 2023-06-07 11:27:50 +02:00
renovate[bot]
2767f866f3 Update dependency @octokit/plugin-retry to v5 (#16803)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 19:53:57 +00:00
renovate[bot]
040d5af0aa Update dependency eslint to v8.42.0 (#16789)
* Update dependency eslint to v8.42.0

* Update resize-observer.polyfill.ts

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-06 19:44:54 +00:00
renovate[bot]
06c6e312b0 Update workbox monorepo to v7 (major) (#16747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 21:41:04 +02:00
renovate[bot]
841dffe563 Update Yarn to v3.6.0 (#16759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 21:39:10 +02:00
renovate[bot]
a41e0d446f Update vaadinWebComponents monorepo to v24.0.8 (#16768)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 21:38:08 +02:00
renovate[bot]
9a0f24cd8b Update dependency @lrnwebcomponents/simple-tooltip to v7.0.2 (#16758)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 21:37:20 +02:00
puddly
2e531a9006 Add channel 26 to ZHA channel changing dialog dropdown (#16801)
Add 26 to list of valid ZHA network channels
2023-06-06 19:31:50 +00:00
karwosts
76255f2efb Fix ha-devices-picker when changing or deleting devices (#16739) 2023-06-06 21:28:07 +02:00
karwosts
19fc92419a Add miscellaneous UI elements for translation (#16797) 2023-06-06 16:37:58 +02:00
Bram Kragten
e7c2625cf1 Bumped version to 20230606.0 2023-06-06 16:32:45 +02:00
Bram Kragten
c39fdcda6e Fix 403 on state-badge connect (#16795) 2023-06-06 13:42:45 +02:00
Paul Bottein
fd1381ab3b Update history chart when entity change in the more info dialog (#16794) 2023-06-06 11:14:11 +02:00
Paul Bottein
7b8f4d1e72 Fix label for cover button mode (#16791) 2023-06-06 09:07:53 +02:00
renovate[bot]
b0a278df97 Update dependency @octokit/plugin-retry to v4.1.6 (#16788)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 01:25:59 -04:00
Bram Kragten
93e31df106 Use integration_type as header for config entries (#16786) 2023-06-05 19:18:42 +02:00
Bram Kragten
47fdae764f Improve display of disabled config entries (#16784) 2023-06-05 19:00:06 +02:00
Bram Kragten
b8efc06caa Bumped version to 20230605.0 2023-06-05 18:22:38 +02:00
Bram Kragten
fcacdf6534 Add all devices and entities link to integration page (#16781) 2023-06-05 15:52:11 +00:00
Paul Bottein
45d260f0ce Move add config entry button to card (#16783) 2023-06-05 15:49:05 +00:00
renovate[bot]
d5f46a69b0 Update dependency @octokit/plugin-retry to v4.1.5 (#16782)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 17:45:44 +02:00
Bram Kragten
fe8eb333b9 Limit integration card to 1 action row (#16780) 2023-06-05 17:23:28 +02:00
Paul Bottein
677cd2de10 Fix integration card tooltip (#16779)
* Fix integration card tooltip

* Update src/panels/config/integrations/ha-integration-header.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-05 14:13:27 +00:00
Bram Kragten
1470eb484f Add more info controls for date/time/datetime (#16775)
* Add more info controls for date/time/datetime

* Discard changes to src/panels/lovelace/entity-rows/hui-date-entity-row.ts

* handle unavailable
2023-06-05 16:10:38 +02:00
Bram Kragten
10ee8fda5b Improve protocol integration add device / integration (#16767) 2023-06-05 14:08:55 +00:00
Bram Kragten
e044ddcb57 Align+fix date time entity rows (#16774) 2023-06-05 13:55:15 +00:00
Bram Kragten
29c564bb69 Fix maps card with location sources (#16778) 2023-06-05 15:53:57 +02:00
Bram Kragten
1bf03f020e Fix closing notification drawer (#16769) 2023-06-05 14:26:51 +02:00
Bram Kragten
6c684fd8ee Show number config entries when no devices/entities (#16766) 2023-06-05 14:17:03 +02:00
Simon Lamon
ddaf403378 Fix dropdown selection in General Settings (#16754) 2023-06-05 11:57:20 +00:00
Paul Bottein
b337074758 Fix collapsed masonry view in safari (#16772) 2023-06-05 13:48:16 +02:00
Bram Kragten
a96eff4d25 Fix padding on thread config panel (#16770) 2023-06-05 13:06:54 +02:00
puddly
e6bdc3a15e Disable ZHA channel changing when multi-PAN is in use (#16731)
* Show baudrate and port in the ZHA network info

* Do not allow changing the Zigbee channel with the multiprotocol addon

* Include translations as well

* Update src/translations/en.json

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-06-05 10:27:36 +00:00
renovate[bot]
33e15eec22 Update dependency @lit-labs/context to v0.3.2 (#16760)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 09:50:00 +02:00
renovate[bot]
3c0afd6cde Update dependency lit to v2.7.5 (#16763)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 09:48:45 +02:00
Joakim Sørensen
31a3fa02d9 Allow for lazy loading images in markdown (#16746) 2023-06-05 09:46:38 +02:00
Paul Bottein
71954f545c Fix white brightness effect on color wheel (#16738) 2023-06-05 09:39:53 +02:00
Paul Bottein
9f3e8abe69 Don't show edit favorite colors button if the light doesn't support it (#16750) 2023-06-05 09:39:36 +02:00
renovate[bot]
21f983572c Update dependency @octokit/plugin-retry to v4.1.4 (#16762)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 01:20:24 -04:00
renovate[bot]
5667d71b02 Update dependency @rollup/plugin-node-resolve to v15.1.0 (#16741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-02 23:40:50 -04:00
Bram Kragten
0d0e5fdaaa Hide ignored entries (#16737) 2023-06-02 12:08:02 +02:00
karwosts
b1f5ff26d9 Fix device selector when picking devices with no entities (#16734) 2023-06-02 11:26:07 +02:00
renovate[bot]
27451ca30e Update typescript-eslint monorepo to v5.59.8 (#16730) 2023-06-01 22:09:45 -04:00
Paul Bottein
928b4e6f1e Add native color picker option (fix for firefox) (#16729) 2023-06-01 16:31:18 +00:00
Paul Bottein
b63a32109e Add native color picker option (#16726) 2023-06-01 18:06:26 +02:00
Bram Kragten
efb0098eac Merge branch 'master' into dev 2023-06-01 18:04:54 +02:00
Bram Kragten
a67b845812 Bumped version to 20230601.1 2023-06-01 18:01:55 +02:00
renovate[bot]
d29b7626f3 Update babel monorepo to v7.22.4 (#16724) 2023-06-01 17:13:30 +02:00
Paul Bottein
47ac7062dc Increase size of color wheel cursor on mobile (#16723) 2023-06-01 16:36:32 +02:00
Paul Bottein
e7f5d927b1 Open right mode when editing favorite color (#16719)
* Open right mode when editing favorite color

* Add missing type
2023-06-01 16:35:24 +02:00
Paul Bottein
6b06393559 Fix outlined button margin on iOS app (#16717) 2023-06-01 14:20:56 +02:00
Paul Bottein
efa02c309b Put button menu above toolbar in automation editor (#16716) 2023-06-01 13:35:23 +02:00
Bram Kragten
9b2e77e781 Align integration card, limit height of logo (#16714) 2023-06-01 12:01:09 +02:00
Joakim Sørensen
24b4060c97 Add missing imports in backup dialogs (#16715) 2023-06-01 09:54:53 +00:00
Paul Bottein
5e4c1ab4fc Share clipboard between automation and script (#16713) 2023-06-01 09:40:02 +00:00
Paul Bottein
287e6dbb60 Fix define variables action (#16712) 2023-06-01 11:38:59 +02:00
Paul Bottein
40c9292e16 Improve padding on integration logo (#16711) 2023-06-01 11:35:42 +02:00
Paul Bottein
d51dd00ec7 Add domain icon for time and datetime (#16710) 2023-06-01 09:07:18 +00:00
Paul Bottein
0db50d13d3 Clean helper config entry fetching in settings (#16709) 2023-06-01 10:37:34 +02:00
Paulus Schoutsen
9eb3618d97 20230601.0 (#16705)
* Fix fetching helper config entry (#16704)

* Fix fetching helper config entry

* willUpdate

* Bumped version to 20230601.0

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-31 20:54:02 -04:00
Paulus Schoutsen
03eee9c7d5 Bumped version to 20230601.0 2023-05-31 20:49:41 -04:00
Bram Kragten
a49d59f4c6 Fix fetching helper config entry (#16704)
* Fix fetching helper config entry

* willUpdate
2023-06-01 00:58:03 +02:00
Bram Kragten
990ade4294 20230531.0 (#16697) 2023-05-31 15:45:11 +02:00
Patrick ZAJDA
a4c57f09ad Set alt attribute to Assistant name in the exposed entities settings (#16698) 2023-05-31 13:36:16 +00:00
Bram Kragten
c1fa6d6f8c Merge branch 'master' into dev 2023-05-31 15:20:23 +02:00
Bram Kragten
3bfcb808f5 Bumped version to 20230531.0 2023-05-31 15:17:21 +02:00
Paul Bottein
9a30fe81c6 Use delete instead of remove for favorite colors (#16696) 2023-05-31 13:16:00 +00:00
Paul Bottein
c864edee72 Reset edit mode when closing more info dialog (#16695) 2023-05-31 13:11:10 +00:00
Bram Kragten
36268d5048 fix error messages of addon mount picker (#16694) 2023-05-31 15:00:32 +02:00
karwosts
5217d427e9 Support to|from null in UI for ha-automation-trigger-state (#15071)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-31 12:28:16 +00:00
karwosts
aea668e754 Minor UI bugfixes for selector-datetime and dialog-date-picker (#15759)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-31 12:26:01 +00:00
Bram Kragten
2219c9bbd3 Throttle replace state in restore scroll (#16693) 2023-05-31 12:18:48 +00:00
Bram Kragten
9b896c63b6 Fix my link for config flow start (#16689) 2023-05-31 14:05:11 +02:00
Bram Kragten
30af576ff5 Remove unused old code (#16691) 2023-05-31 12:04:45 +00:00
Bram Kragten
585db6ab3f Close dialog when clicked on link (#16690) 2023-05-31 14:01:47 +02:00
karwosts
046475e7ac Fix blueprint script editor defaults handling (#16196) 2023-05-31 12:58:22 +02:00
karwosts
648383addd Fix ha-combo-box open direction (#16119) 2023-05-31 12:55:44 +02:00
Paul Bottein
10018b4c32 Update default colors for more info light favorite colors (#16688)
Update default favorite color for more-info-light
2023-05-31 12:48:49 +02:00
Philip Allgaier
872d3e4875 Make badge colors use the generic error/warning/success/info colors (#14728) 2023-05-31 12:44:48 +02:00
Bram Kragten
881f5e5012 Fix energy compare (#16687) 2023-05-31 12:42:03 +02:00
Bram Kragten
9797950f32 Use memoize in formatDateNumeric (#16686) 2023-05-31 12:36:52 +02:00
Bram Kragten
25986f239e Blueprints: show error in alert dialog when clicked (#16684) 2023-05-31 12:35:38 +02:00
Raman Gupta
b586210ff1 Support zwave config parameters not on endpoint 0 (#16597)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-31 12:11:26 +02:00
karwosts
748925ede9 Localize time string in time trigger and condition (#16681) 2023-05-31 12:07:30 +02:00
Paul Bottein
a9f1c4a198 Add button bar for light modes (#16683)
* Add button bar for light modes

* Add disabled style

* Fix favorite colors display condition

* Fix color temp button
2023-05-31 11:48:22 +02:00
Bram Kragten
d914fb0cfc Revert "Use ES modules and dynamic import for Webpack latest builds (… (#16679)
Revert "Use ES modules and dynamic import for Webpack latest builds (#16620)"

This reverts commit 7b350e31dd.
2023-05-30 17:56:38 -04:00
Bram Kragten
5218e1352e async cleanup 2023-05-30 23:43:13 +02:00
Bram Kragten
eb0759a3b3 Fix integration translations (#16678) 2023-05-30 23:20:12 +02:00
Bram Kragten
88522ed155 change order 2023-05-30 22:59:34 +02:00
Bram Kragten
64e7fc6591 Fix my link for integration (#16676) 2023-05-30 22:02:52 +02:00
Christoph Wen, B.Sc
2ad6253b72 Add setting to localize numeric dates independent from language (#15770) (#16489) 2023-05-30 19:39:27 +00:00
Bram Kragten
7e5a85dbe7 Allow to change switch as x (#16671) 2023-05-30 21:32:06 +02:00
Paul Bottein
0771a780d9 Light more info enhancement (#16673)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-30 18:41:12 +00:00
Steve Repsher
7b350e31dd Use ES modules and dynamic import for Webpack latest builds (#16620) 2023-05-30 18:27:49 +00:00
Bram Kragten
70fbf68603 Overhaul Integrations page, add integration page (#16640)
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2023-05-30 20:09:26 +02:00
Bram Kragten
2b4f199337 Tweak style of related items (#16672) 2023-05-30 16:12:41 +00:00
Bram Kragten
a70d7d8de3 Related blueprints (#16618) 2023-05-30 15:04:45 +02:00
renovate[bot]
e0c1f98803 Update babel monorepo to v7.22.3 (#16668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-30 10:40:14 +00:00
Bram Kragten
4b7a517d98 Fix async update localize (#16667) 2023-05-30 10:25:21 +00:00
renovate[bot]
26d4839dfd Update dependency @types/chromecast-caf-receiver to v6 (#15724)
* Update dependency @types/chromecast-caf-receiver to v6

* Import cast namespace from receiver for receiver/media entry

* Use sender event types in manager and remove anonymous listeners

* Apply suggestions from code review

* prettier

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-30 09:30:04 +00:00
Jonas Bergler
c358d724a7 update hidden_description to explain the behavior of the visible setting more clearly. (#16662)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-30 09:27:22 +00:00
Allen Porter
0ab7934c09 Add a vertical scrollbar for the calendar list (#16657) 2023-05-30 10:49:14 +02:00
Allen Porter
6eac229901 Disable calendar selection when editing existing Calendar Events (#16656) 2023-05-30 10:48:34 +02:00
Joakim Sørensen
5006dfc138 Use __STATIC_PATH__ in more places so the supervisor panel can reach paths (#16665)
Use __STATIC_PATH__ in more places so the supervisor panel can reach paths
2023-05-30 10:45:58 +02:00
renovate[bot]
d9d38efd93 Update babel monorepo (#16658)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-30 00:40:11 -04:00
renovate[bot]
9fe3a500d5 Update workbox monorepo to v6.6.0 (#16659)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-30 00:29:12 -04:00
Raman Gupta
3df7c50690 Add frontend support for datetime platform (#14391)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-29 23:32:57 +02:00
Bram Kragten
38cf774a0d Use ESM version of hls.js (#16655) 2023-05-29 20:38:21 +02:00
renovate[bot]
98d22d38c3 Update vaadinWebComponents monorepo to v24.0.7 (#16653)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-29 16:30:29 +02:00
renovate[bot]
357dbb591b Update babel monorepo to v7.22.0 (#16654)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-29 16:29:54 +02:00
renovate[bot]
aa5df06bc3 Update dependency @lezer/highlight to v1.1.6 (#16652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-29 16:28:24 +02:00
rtm516
07a66b4bff Fix topbar overflowing card for add-on store (#16637) 2023-05-29 14:22:03 +00:00
renovate[bot]
f466196fa8 Update dependency hls.js to v1.4.4 (#16651)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-29 16:10:15 +02:00
Marvin Wichmann
04ae0b34af Update WS commands for config entries (#16647) 2023-05-29 16:08:25 +02:00
Joakim Sørensen
6f48267dae Include share as mount usage option (#16636) 2023-05-29 11:43:12 +02:00
renovate[bot]
be1f5d99c8 Update dependency webpack to v5.84.1 (#16649) 2023-05-28 20:46:25 +00:00
renovate[bot]
27b9b4dcc5 Update fullcalendar monorepo to v6.1.8 (#16644)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-28 13:48:53 -04:00
renovate[bot]
08b57d6168 Update dependency webpack to v5.84.0 (#16641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-28 13:46:32 -04:00
renovate[bot]
3e474daa32 Update dependency @lezer/highlight to v1.1.5 (#16638) 2023-05-27 13:11:42 -04:00
renovate[bot]
48c1e8b56c Update dependency @codemirror/state to v6.2.1 (#16632) 2023-05-27 13:09:19 -04:00
karwosts
fd0c0a95ca Add a description for time condition (#16499) 2023-05-27 18:27:24 +02:00
Paul Bottein
83570f2419 Add missing translations for effect and preset translation in more info (#16634) 2023-05-26 23:01:52 +02:00
Paul Bottein
633c6cfc9b Use colored slider background for more info (#16633) 2023-05-26 17:45:57 +02:00
Paul Bottein
54b4c9f347 Add favorite colors to more info light (#16592)
* Add default favorite colors

* Don't show favorite colors if no entity registry entry

* Move color picker in its own component

* Fix more info dialog width

* Make favorite color editable

* Don't include white mode as favorite

* Add label for favorite color button

* Add support for hs, rgbw and rgbww colors

* Adapt color wheel color according to white value

* Add translation

* Add keyboard control to color temp wheel

* Use bottom sheet style for edit favorite dialog

* Fix listener

* Edit color temp icon

* Disable favorite color when available

* Only admin can edit a color

* Refactor close action

* Clean css

* Use ha button

* Fix ha-border-radius for bottom sheet
2023-05-26 17:23:49 +02:00
starkillerOG
85e7986b44 Always show "polling for updates" switch (#16629)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-26 15:52:57 +02:00
Paul Bottein
da0cf9d950 Create outlined button component (#16631)
* Create outlined button component

* Fix css comment

* Don't use Md classes

* Simplify
2023-05-26 15:28:49 +02:00
Bram Kragten
ef51336770 Don't set name for entities that use device name already (#16613) 2023-05-26 14:54:49 +02:00
Bram Kragten
a09db75980 Bumped version to 20230526.0 2023-05-26 09:00:02 +02:00
J. Nick Koston
77d1b19ecb Complete persistent notifications migration (#16476)
* Complete migration of persistent notifications

* Complete migration of persistent notifications

* revert
2023-05-25 23:09:04 -04:00
renovate[bot]
fba12f35ac Update typescript-eslint monorepo to v5.59.7 (#16627) 2023-05-25 22:50:21 +00:00
renovate[bot]
00198c6937 Update vaadinWebComponents monorepo to v24.0.6 (#16621) 2023-05-25 18:35:51 -04:00
Paul Bottein
71bb540352 Use key instead of keycode for key event (#16625) 2023-05-25 18:47:57 +02:00
Bram Kragten
c4ff1a8646 fix keypress in code editor causing flow to submit (#16623) 2023-05-25 18:01:46 +02:00
Bram Kragten
a9c27ad8dd Save automation clipboard in session storage (#16624) 2023-05-25 17:58:05 +02:00
Joakim Sørensen
dacdc62672 Change OS version for mounts to placeholder (#16607) 2023-05-25 09:51:09 +02:00
karwosts
cccce5711c Fix displayed unit for fixed water price (#16616) 2023-05-24 18:21:41 +02:00
Joakim Sørensen
50bd9da94c Att tip to manage media dialog about network storage (#16612) 2023-05-24 17:18:46 +02:00
Bram Kragten
dde27c3524 Support entity reg id in device automations (#15387) 2023-05-24 14:37:45 +02:00
Joakim Sørensen
85acafe8a8 Fix reload mounts callback when doing changes in dialog (#16615) 2023-05-24 12:31:41 +00:00
Bram Kragten
c1748138a8 fix links to scripts from device and area pages (#16611)
Fixes #16602
2023-05-24 14:20:36 +02:00
Joakim Sørensen
9111f58e52 Add dialog to change default backup location (#16610)
* Add dialog to change default backup location

* Add guard

* Update src/components/ha-mount-picker.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-24 12:03:14 +02:00
karwosts
cefaaadf95 Fix line chart tooltips to use XY mode (#16605) 2023-05-24 11:52:26 +02:00
karwosts
29846a168e Add cut / copy / paste support to automation & script editor (#16488) 2023-05-24 11:47:33 +02:00
renovate[bot]
31c89d70c5 Update dependency @octokit/rest to v19.0.11 (#16606)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-23 22:37:51 -04:00
renovate[bot]
d5cea75fe4 Update dependency glob to v10.2.6 (#16608)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-23 22:36:12 -04:00
renovate[bot]
35d212e850 Update dependency @octokit/rest to v19.0.9 (#16598) 2023-05-23 12:07:01 -04:00
karwosts
aea098ff17 Fix compare button for energy cards on manual dashboard (#16579) 2023-05-23 14:55:12 +02:00
karwosts
c5205ae8db Add a description for time pattern trigger (#16520) 2023-05-23 14:47:41 +02:00
Paul Bottein
303087d049 Fix documentation form (#16601) 2023-05-23 14:45:53 +02:00
Paul Bottein
e9d9d89d79 New color picker for HS and color temp (#16549)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-23 14:45:23 +02:00
Bram Kragten
a5b5e61ed4 Add backup location selector (#16567)
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2023-05-23 13:35:31 +02:00
Joakim Sørensen
22dc757382 Add guards for network storage (#16591) 2023-05-23 12:33:12 +02:00
Bram Kragten
4ccfd6a3fc Add options flow button to conversation agent in assist pipeline dialog (#16595) 2023-05-23 12:32:18 +02:00
Erik Montnemery
5a36f100a9 Add WS command for getting a config entry (#16600)
* Add WS command for getting a config entry

* Correct typing
2023-05-23 10:43:53 +02:00
renovate[bot]
847c8407de Update dependency eslint to v8.41.0 (#16596) 2023-05-22 20:21:48 -04:00
J. Nick Koston
ed1784b70f Avoid entity registry subscribe for the media browser (#16537) 2023-05-22 19:43:01 +02:00
Trevor North
e8521c59eb Add sensor device class volatile_organic_compounds_parts (#16576)
Add support for volatile_organic_compounds_parts
2023-05-22 08:42:15 +00:00
Bram Kragten
34e59e543b Add support for offline db migration (#16566) 2023-05-22 10:39:06 +02:00
Steve Repsher
330aa23801 Use .nvmrc for GitHub actions (#16569) 2023-05-22 10:38:54 +02:00
Steve Repsher
06db338a15 Upgrade node to v18 (LTS) (#16589) 2023-05-22 10:38:24 +02:00
renovate[bot]
8cff4cda47 Update dependency sinon to v15.1.0 (#16587)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-21 22:25:40 -04:00
renovate[bot]
f7e7c916ba Update dependency @types/marked to v4.3.1 (#16588)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-21 22:24:02 -04:00
renovate[bot]
13ab5ab70a Update dependency leaflet to v1.9.4 (#16586)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-21 22:22:56 -04:00
renovate[bot]
cc61131e4b Lock file maintenance (#16578)
* Lock file maintenance

* Update @codemirror/language to eliminate issue with duplicate

* Update @codemirror/view to eliminate issue with duplicate

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Steve Repsher <steverep@users.noreply.github.com>
2023-05-21 04:15:17 +00:00
Bram Kragten
099aa54b80 Add support for external assist (#16556)
* Add support for external assist

* Update hui-root.ts
2023-05-20 21:37:08 -04:00
renovate[bot]
e35d795ba8 Update dependency terser-webpack-plugin to v5.3.9 (#16585) 2023-05-21 00:58:31 +00:00
renovate[bot]
39de8cd6ba Update dependency webpack to v5.83.1 (#16583) 2023-05-20 18:26:53 -04:00
renovate[bot]
fdddf27162 Update dependency glob to v10.2.5 (#16584) 2023-05-20 18:23:33 -04:00
renovate[bot]
cec7a24234 Update dependency @lrnwebcomponents/simple-tooltip to v7 (#16548)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-20 18:10:19 +02:00
renovate[bot]
ea2e9de37a Update dependency @codemirror/view to v6.11.3 (#16582) 2023-05-20 11:52:58 -04:00
renovate[bot]
d9cb288c1d Update dependency tar to v6.1.15 (#16581) 2023-05-20 10:48:03 -04:00
renovate[bot]
53bd4298e7 Update typescript-eslint monorepo to v5.59.6 (#16577) 2023-05-18 17:08:14 -04:00
renovate[bot]
5bea929c1e Update dependency glob to v10.2.4 (#16573)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-18 08:39:40 -04:00
Bram Kragten
eb220fa1a0 Fix overflow menu being above dialogs (#16558)
Fix device actions being above dialogs
2023-05-17 10:23:30 -04:00
Franck Nijhof
67b64b2d5c Add entity attribute value translations for media_player (#16559)
Add entity attribute translations for media_player
2023-05-17 15:27:32 +02:00
Franck Nijhof
42aa4ab7c2 Add entity attribute value translations for vacuum (#16564) 2023-05-17 15:27:05 +02:00
Franck Nijhof
d873f26db3 Add entity attribute value translations for humidifier (#16565) 2023-05-17 15:26:16 +02:00
Franck Nijhof
e354f5de12 Add entity attribute value translations for remote (#16563) 2023-05-17 15:25:21 +02:00
Bram Kragten
92ed62985d Focus pin input when adding zwave device (#16557) 2023-05-17 12:53:01 +02:00
Bram Kragten
cbcca6e190 Increase weight of name and domain in add integration search (#16562) 2023-05-17 12:51:31 +02:00
Franck Nijhof
2ed48d67c6 Exclude device trackers from person more info (#16554) 2023-05-17 08:33:19 +02:00
renovate[bot]
8fb2bf472a Update dependency @octokit/rest to v19.0.8 (#16555)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-16 23:47:09 -04:00
renovate[bot]
51bdf85642 Update dependency @codemirror/view to v6.11.2 (#16553)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-16 21:39:30 +00:00
renovate[bot]
b7a4eb33cf Update dependency @rollup/plugin-commonjs to v25 (#16551) 2023-05-16 09:53:59 -04:00
renovate[bot]
3c2d326b54 Update dependency @codemirror/autocomplete to v6.7.1 (#16547) 2023-05-16 07:51:05 -04:00
renovate[bot]
24e6d19e18 Update vaadinWebComponents monorepo to v24.0.5 (#16544)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-16 02:22:28 +00:00
renovate[bot]
9370411019 Update CodeMirror (#16545)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-16 02:22:09 +00:00
renovate[bot]
d5c7e7849e Update fullcalendar monorepo to v6.1.7 (#16542) 2023-05-15 22:09:45 -04:00
renovate[bot]
c5e62248b9 Update typescript-eslint monorepo to v5.59.5 (#16543) 2023-05-15 22:07:29 -04:00
renovate[bot]
c5e0efb8e0 Update dependency webpack to v5.82.1 (#16540) 2023-05-16 01:53:51 +00:00
renovate[bot]
82f88ca7d7 Update dependency webpack-cli to v5.1.1 (#16541) 2023-05-15 21:38:39 -04:00
renovate[bot]
c676cddb13 Update dependency glob to v10.2.3 (#16538) 2023-05-15 19:53:55 -04:00
renovate[bot]
036e2a9e46 Update dependency hls.js to v1.4.3 (#16539) 2023-05-15 19:51:44 -04:00
renovate[bot]
319d8bec29 Update dependency @types/tar to v6.1.5 (#16535)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-15 21:35:46 +00:00
renovate[bot]
aa864cf0b6 Update dependency @lit-labs/virtualizer to v2.0.2 (#16534)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-15 21:22:52 +00:00
Steve Repsher
eabd8b54f4 Correct Terser ECMA option (#16518) 2023-05-15 09:54:59 +02:00
Bram Kragten
aa063d0a3e Replace onboarding inputs with default inputs (#16514) 2023-05-12 13:15:28 +02:00
Paul Bottein
75f080ee85 Add last-changed date to more-info (#16509) 2023-05-12 10:58:52 +00:00
Bruno Luvizotto
557fe33807 Add interval duration to history tooltip (#16486) 2023-05-12 12:50:34 +02:00
Paul Bottein
5bd49c18d1 Update more info light actions (#16512) 2023-05-12 00:17:02 +02:00
Paul Bottein
a461d58df2 Fix more info dialog margin for material web button (#16513) 2023-05-11 17:16:15 +02:00
karwosts
ae8eafe8f9 Honor entity ordering in statistics graph card (#16504) 2023-05-11 11:21:18 +02:00
Paul Bottein
450565799e Allow adding variable action in the automation UI (#16502) 2023-05-11 11:19:36 +02:00
Erik Montnemery
72403f4276 Remove calculation of change from frontend (#16477) 2023-05-11 10:17:12 +02:00
renovate[bot]
d66ca0467e Update dependency webpack-dev-server to v4.15.0 (#16501) 2023-05-10 18:12:00 -04:00
Bram Kragten
d46201ebd8 fix supervisor ingress routing (#16474) 2023-05-10 16:03:19 +02:00
Bram Kragten
689d123890 Add search to add-ons page (#16459) 2023-05-10 14:59:24 +02:00
Bram Kragten
bcdb24849d Add support for filtering service fields (#16004)
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2023-05-10 14:59:13 +02:00
Paul Bottein
3838d76094 Ha dialog header (#16485) 2023-05-10 14:34:19 +02:00
Bram Kragten
3325cbfa28 Use entity id as label in entity picker dev tools (#16484) 2023-05-10 10:23:33 +02:00
renovate[bot]
24fc2a0ccc Update dependency webpack-cli to v5.1.0 (#16495)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-10 00:29:02 -04:00
renovate[bot]
d6ea6f8041 Update dependency terser-webpack-plugin to v5.3.8 (#16493) 2023-05-09 22:11:35 -04:00
renovate[bot]
8384ef7a5c Update dependency webpack-dev-server to v4.14.0 (#16494) 2023-05-09 22:09:49 -04:00
renovate[bot]
2869c5f26b Update dependency core-js to v3.30.2 (#16490) 2023-05-09 20:04:47 -04:00
renovate[bot]
c098c55b8f Update dependency idb-keyval to v6.2.1 (#16487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-09 16:20:53 -04:00
Bram Kragten
fec974712f Add any to number selector step typing (#16483) 2023-05-09 14:30:52 +02:00
Bruno Luvizotto
0be5aa108c Fix history redraw timer (#16472) 2023-05-09 12:32:13 +02:00
Joakim Sørensen
ec36d4a381 Use "any" as step for add-on configuration floats (#16478) 2023-05-09 12:22:17 +02:00
Joakim Sørensen
ccf3238318 Fix link to new automation (#16479) 2023-05-09 11:12:00 +02:00
renovate[bot]
bcfa6c5a4b Update dependency eslint to v8.40.0 (#16475) 2023-05-08 18:51:17 -04:00
G Johansson
e371f5d406 Lock entity options (#16344) 2023-05-08 22:06:21 +02:00
Bram Kragten
6d4e3a0de3 Allow supervisor panel to unsubscribe, cleanup (#16470) 2023-05-08 15:56:05 -04:00
renovate[bot]
b845c54948 Update dependency open to v9 (#15909)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-08 16:11:05 +00:00
renovate[bot]
87951ebf82 Pin dependency @types/babel__plugin-transform-runtime to 7.9.2 (#16471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-08 16:10:15 +00:00
Steve Repsher
586079917d Convert remaining gulp modules to ESM (#16430) 2023-05-08 17:43:29 +02:00
Steve Repsher
aa3fd70966 Use Babel runtime for helpers and regenerator (33%+ bundle reduction) (#16466) 2023-05-08 14:47:53 +02:00
bikeshop45
a5ba2499c0 Fix attribute url links (#16462) 2023-05-08 09:13:35 +00:00
Joakim Sørensen
36a87da1fe Add UI for network mounts (#16357)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2023-05-08 10:18:09 +02:00
Bram Kragten
8f75c314f5 Fix supervisor loading race (#16460) 2023-05-07 22:48:16 -04:00
renovate[bot]
d04fc53f08 Update dependency hls.js to v1.4.1 (#16461) 2023-05-07 17:36:26 -04:00
renovate[bot]
c65c6f8767 Update dependency lit to v2.7.4 (#16464)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-07 21:59:44 +02:00
renovate[bot]
b81668fbce Update dependency @codemirror/autocomplete to v6.6.1 (#16452)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-06 14:17:03 -04:00
renovate[bot]
2d8e23ba48 Update dependency eslint-plugin-wc to v1.5.0 (#16448) 2023-05-06 13:20:54 -04:00
renovate[bot]
e947f8120c Update dependency eslint to v8.39.0 (#16447) 2023-05-06 13:14:16 -04:00
renovate[bot]
6424020f64 Update dependency date-fns to v2.30.0 (#16446) 2023-05-06 17:06:08 +02:00
renovate[bot]
a611930fa7 Update formatjs monorepo (#16449) 2023-05-06 17:05:17 +02:00
renovate[bot]
f0e990f330 Update CodeMirror (#16443) 2023-05-06 10:13:27 -04:00
renovate[bot]
8c1d2362a4 Update CodeMirror (#16441) 2023-05-06 02:37:14 -04:00
renovate[bot]
69067010a3 Update dependency @types/marked to v4.3.0 (#16442) 2023-05-06 06:32:32 +00:00
renovate[bot]
0b0ba97aee Update fullcalendar monorepo to v6.1.6 (#16439) 2023-05-06 03:22:08 +00:00
renovate[bot]
792fe15dac Update typescript-eslint monorepo to v5.59.2 (#16440) 2023-05-06 03:21:24 +00:00
renovate[bot]
d5b8fa482c Update dependency lit to v2.7.3 (#16435) 2023-05-05 23:11:04 -04:00
renovate[bot]
2fefbbfe24 Update dependency tar to v6.1.14 (#16438) 2023-05-06 03:05:58 +00:00
renovate[bot]
22c509533a Update dependency qrcode to v1.5.3 (#16437) 2023-05-05 23:02:41 -04:00
renovate[bot]
544dfa0973 Update dependency @babel/core to v7.21.8 (#16432) 2023-05-05 22:56:07 -04:00
renovate[bot]
aac3ec353b Update dependency prettier to v2.8.8 (#16436) 2023-05-05 22:45:35 -04:00
renovate[bot]
efbc6d9069 Update dependency lint-staged to v13.2.2 (#16433) 2023-05-05 22:44:19 -04:00
renovate[bot]
4e390b4c57 Update dependency @lit-labs/virtualizer to v2 (#15932)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-05 15:51:12 +00:00
renovate[bot]
849e65a2b3 Update dependency @lit-labs/context to v0.3.1 (#16428)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 17:35:27 +02:00
renovate[bot]
a6fdb54697 Update dependency glob to v10.2.2 (#16429)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 15:32:34 +00:00
Sven Serlier
aa196704b7 Update URL (#16427) 2023-05-05 15:16:49 +00:00
renovate[bot]
c93fcb8a2a Update dependency @material/web to v1.0.0-pre.7 (#15940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-05 15:13:25 +00:00
renovate[bot]
5768764282 Update babel monorepo to v7.21.5 (#16426)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 14:55:01 +00:00
renovate[bot]
e6c8881b21 Update Yarn to v3.5.1 (#16425)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 14:48:45 +00:00
renovate[bot]
ac30335fc2 Update vaadinWebComponents monorepo to v24 (major) (#15778)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 16:33:29 +02:00
renovate[bot]
1e5c30a259 Update dependency @lrnwebcomponents/simple-tooltip to v4.2.0 (#16024)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 16:32:06 +02:00
renovate[bot]
1da009b473 Update dependency hls.js to v1.4.0 (#16191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-05 16:31:07 +02:00
Paul Bottein
02542e528e Fetch entries integration onboarding (#16424)
* Fetch loaded entries in integration onboarding

* Proper fix
2023-05-05 14:24:32 +00:00
puddly
c7ec6903fe ZHA channel changing dialog and settings redesign (#16381) 2023-05-05 15:05:08 +02:00
Raman Gupta
ecb2a73e2b Add frontend support for date platform (#14389)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2023-05-05 15:01:47 +02:00
Raman Gupta
59db31cdb5 Remove CSS component from time entity row (#16416) 2023-05-05 15:01:13 +02:00
Paul Bottein
643556ded3 Adapt unsupported microphone message (#16419) 2023-05-05 00:18:18 +02:00
Bram Kragten
4e5a18d272 Remove polymer types, cleanups (#16385)
* Remove polymer types, cleanups

* Delete updated.ts
2023-05-04 15:24:24 +00:00
Raman Gupta
ab237f19c0 Add frontend support for time platform (#14390) 2023-05-04 17:05:30 +02:00
Joe
3fa3d333c4 Collapse empty Masonry columns (#5315, #6632) (#16351) 2023-05-04 17:04:03 +02:00
Bram Kragten
1cb7e798da Bump webpack to 5.82 (#16412) 2023-05-04 11:02:31 -04:00
Bram Kragten
11640b31f6 Update tts media browser to use voices (#16362) 2023-05-04 16:33:52 +02:00
Steve Repsher
4740ce685f Redefine browser requirements for legacy (ES5) builds (#16384) 2023-05-04 16:33:13 +02:00
Steve Repsher
d2321b535c Refactor Intl polyfills and remove from ES5 entrypoints (#16349) 2023-05-04 15:49:56 +02:00
Steve Repsher
f185e886c3 Convert top gulp modules to ESM (#16387) 2023-05-04 15:49:41 +02:00
Bram Kragten
8695bbc490 Move globalThis polyfill to compatibility, add more compatibility (#16386) 2023-05-04 15:49:28 +02:00
Bram Kragten
060f6ce3d8 fix expose view for yaml config (#16408) 2023-05-04 15:30:47 +02:00
Bram Kragten
ed19cfeaaa Fix codemirror selection color (#16409) 2023-05-04 15:13:32 +02:00
Paul Bottein
79d6453c7e Don't hide battery entities in compute card function (#16373) 2023-05-03 19:44:01 +02:00
Bram Kragten
694fc7d4ba Fix entity areas in expose (#16402) 2023-05-03 19:02:20 +02:00
547 changed files with 22617 additions and 10819 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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}"
}, },

View File

@@ -1,3 +1,8 @@
categories:
- title: 'Dependency updates'
collapse-after: 3
labels:
- 'dependencies'
template: | template: |
## What's Changed ## What's Changed

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

2
.nvmrc
View File

@@ -1 +1 @@
16 18

View 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

View File

@@ -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

View File

@@ -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/"`,
}, },
}; };
}, },

View File

@@ -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",

View File

@@ -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",

View File

@@ -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,

View File

@@ -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 };

View File

@@ -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",

View File

@@ -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";

View File

@@ -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)) {

View File

@@ -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)

View File

@@ -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");

View File

@@ -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 () => {

View File

@@ -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";

View File

@@ -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

View File

@@ -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;
} }
} }

View File

@@ -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(

View File

@@ -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"]

View File

@@ -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

View File

@@ -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
View 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,
},
});
});

View File

@@ -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 }),

View File

@@ -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,
}, },
}; };
}; };

View File

@@ -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();
} }
} }

View File

@@ -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();

View File

@@ -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();

View File

@@ -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";

View File

@@ -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) { %>

View File

@@ -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",

View File

@@ -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",

View 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",
},
];

View File

@@ -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";

View File

@@ -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>
` `

View File

@@ -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>
` `

View File

@@ -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 }],

View File

@@ -0,0 +1,3 @@
---
title: Control Circular Slider
---

View 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;
}
}

View File

@@ -0,0 +1,3 @@
---
title: HS Color Picker
---

View 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;
}
}

View File

@@ -0,0 +1,3 @@
---
title: Temp Color Picker
---

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View File

@@ -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`

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View 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`

View 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;
}
}

View File

@@ -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

View File

@@ -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
)}`, )}`,
}, },

View File

@@ -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;

View File

@@ -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",

View File

@@ -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
) )

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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);
} }
`, `,
]; ];

View File

@@ -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,

View 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;
}
}

View File

@@ -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";

View File

@@ -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,
});
};

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -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"

View File

@@ -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-"]
} }
] ]
} }

View File

@@ -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

View File

@@ -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);
} }
}); });

View File

@@ -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