mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
20240131.0 (#19594)
This commit is contained in:
commit
ce32de6e23
@ -2,12 +2,12 @@
|
|||||||
"name": "Home Assistant Frontend",
|
"name": "Home Assistant Frontend",
|
||||||
"build": {
|
"build": {
|
||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"context": ".."
|
"context": "..",
|
||||||
},
|
},
|
||||||
"appPort": "8124:8123",
|
"appPort": "8124:8123",
|
||||||
"postStartCommand": "script/bootstrap",
|
"postStartCommand": "script/bootstrap",
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}",
|
||||||
},
|
},
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"runem.lit-plugin",
|
"runem.lit-plugin",
|
||||||
"github.vscode-pull-request-github",
|
"github.vscode-pull-request-github",
|
||||||
"eamodio.gitlens"
|
"eamodio.gitlens",
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
@ -27,17 +27,17 @@
|
|||||||
"editor.renderWhitespace": "boundary",
|
"editor.renderWhitespace": "boundary",
|
||||||
"editor.rulers": [80],
|
"editor.rulers": [80],
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
},
|
},
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
},
|
},
|
||||||
"files.trimTrailingWhitespace": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"terminal.integrated.shell.linux": "/usr/bin/zsh",
|
"terminal.integrated.shell.linux": "/usr/bin/zsh",
|
||||||
"gitlens.showWelcomeOnInstall": false,
|
"gitlens.showWelcomeOnInstall": false,
|
||||||
"gitlens.showWhatsNewAfterUpgrades": false,
|
"gitlens.showWhatsNewAfterUpgrades": false,
|
||||||
"workbench.startupEditor": "none"
|
"workbench.startupEditor": "none",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
22
.github/labeler.yml
vendored
22
.github/labeler.yml
vendored
@ -24,14 +24,20 @@ Design:
|
|||||||
- src/fake_data/**
|
- src/fake_data/**
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- changed-files:
|
- any:
|
||||||
- any-glob-to-any-file:
|
- changed-files:
|
||||||
- package.json
|
# Match when only these files are changed (i.e. don't match PRs that happen to add or remove packages)
|
||||||
- renovate.json
|
- any-glob-to-all-files:
|
||||||
- yarn.lock
|
- package.json
|
||||||
- .yarn/**
|
- renovate.json
|
||||||
- .yarnrc.yml
|
- yarn.lock
|
||||||
- .nvmrc
|
- .yarn/**
|
||||||
|
- .yarnrc.yml
|
||||||
|
- .nvmrc
|
||||||
|
# Dependabot and Renovate branches always match (i.e. compatibility tweaks by members considered minor)
|
||||||
|
- head-branch:
|
||||||
|
- "^renovate/"
|
||||||
|
- "^dependabot/"
|
||||||
|
|
||||||
GitHub Actions:
|
GitHub Actions:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
9
.github/workflows/ci.yaml
vendored
9
.github/workflows/ci.yaml
vendored
@ -37,17 +37,20 @@ jobs:
|
|||||||
- name: Build resources
|
- name: Build resources
|
||||||
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
|
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
|
||||||
- name: Setup lint cache
|
- name: Setup lint cache
|
||||||
uses: actions/cache@v3.3.2
|
uses: actions/cache@v4.0.0
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
node_modules/.cache/prettier
|
node_modules/.cache/prettier
|
||||||
node_modules/.cache/eslint
|
node_modules/.cache/eslint
|
||||||
|
node_modules/.cache/typescript
|
||||||
key: lint-${{ github.sha }}
|
key: lint-${{ github.sha }}
|
||||||
restore-keys: lint-
|
restore-keys: lint-
|
||||||
- name: Run eslint
|
- name: Run eslint
|
||||||
run: yarn run lint:eslint --quiet
|
run: yarn run lint:eslint --quiet
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
run: yarn run lint:types
|
run: yarn run lint:types
|
||||||
|
- name: Run lit-analyzer
|
||||||
|
run: yarn run lint:lit --quiet
|
||||||
- name: Run prettier
|
- name: Run prettier
|
||||||
run: yarn run lint:prettier
|
run: yarn run lint:prettier
|
||||||
test:
|
test:
|
||||||
@ -86,7 +89,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IS_TEST: "true"
|
IS_TEST: "true"
|
||||||
- name: Upload bundle stats
|
- name: Upload bundle stats
|
||||||
uses: actions/upload-artifact@v3.1.3
|
uses: actions/upload-artifact@v4.3.0
|
||||||
with:
|
with:
|
||||||
name: frontend-bundle-stats
|
name: frontend-bundle-stats
|
||||||
path: build/stats/*.json
|
path: build/stats/*.json
|
||||||
@ -110,7 +113,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IS_TEST: "true"
|
IS_TEST: "true"
|
||||||
- name: Upload bundle stats
|
- name: Upload bundle stats
|
||||||
uses: actions/upload-artifact@v3.1.3
|
uses: actions/upload-artifact@v4.3.0
|
||||||
with:
|
with:
|
||||||
name: supervisor-bundle-stats
|
name: supervisor-bundle-stats
|
||||||
path: build/stats/*.json
|
path: build/stats/*.json
|
||||||
|
6
.github/workflows/nightly.yaml
vendored
6
.github/workflows/nightly.yaml
vendored
@ -42,7 +42,7 @@ jobs:
|
|||||||
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
run: script/version_bump.cjs nightly
|
run: script/version_bump.js nightly
|
||||||
|
|
||||||
- name: Build nightly Python wheels
|
- name: Build nightly Python wheels
|
||||||
run: |
|
run: |
|
||||||
@ -57,14 +57,14 @@ jobs:
|
|||||||
run: tar -czvf translations.tar.gz translations
|
run: tar -czvf translations.tar.gz translations
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v3.1.3
|
uses: actions/upload-artifact@v4.3.0
|
||||||
with:
|
with:
|
||||||
name: wheels
|
name: wheels
|
||||||
path: dist/home_assistant_frontend*.whl
|
path: dist/home_assistant_frontend*.whl
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload translations
|
- name: Upload translations
|
||||||
uses: actions/upload-artifact@v3.1.3
|
uses: actions/upload-artifact@v4.3.0
|
||||||
with:
|
with:
|
||||||
name: translations
|
name: translations
|
||||||
path: translations.tar.gz
|
path: translations.tar.gz
|
||||||
|
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@ -74,7 +74,7 @@ jobs:
|
|||||||
echo "home-assistant-frontend==$version" > ./requirements.txt
|
echo "home-assistant-frontend==$version" > ./requirements.txt
|
||||||
|
|
||||||
- name: Build wheels
|
- name: Build wheels
|
||||||
uses: home-assistant/wheels@2023.10.5
|
uses: home-assistant/wheels@2024.01.0
|
||||||
with:
|
with:
|
||||||
abi: cp311
|
abi: cp311
|
||||||
tag: musllinux_1_2
|
tag: musllinux_1_2
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
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();
|
|
73
.yarn/patches/sortablejs-npm-1.15.2-73347ae85a.patch
Normal file
73
.yarn/patches/sortablejs-npm-1.15.2-73347ae85a.patch
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
diff --git a/modular/sortable.core.esm.js b/modular/sortable.core.esm.js
|
||||||
|
index 93ba17509e2e8583ab241fea6845fbe714c584a2..de0651ddb5dced30d36f7d764da0dd0b441f523f 100644
|
||||||
|
--- a/modular/sortable.core.esm.js
|
||||||
|
+++ b/modular/sortable.core.esm.js
|
||||||
|
@@ -1461,7 +1461,7 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
|
}
|
||||||
|
target = parent; // store last element
|
||||||
|
}
|
||||||
|
- /* jshint boss:true */ while (parent = parent.parentNode);
|
||||||
|
+ /* jshint boss:true */ while (parent = parent.parentNode || parent.getRootNode().host);
|
||||||
|
}
|
||||||
|
_unhideGhostForTarget();
|
||||||
|
}
|
||||||
|
@@ -1781,11 +1781,16 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
|
}
|
||||||
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
|
||||||
|
capture();
|
||||||
|
- if (elLastChild && elLastChild.nextSibling) {
|
||||||
|
- // the last draggable element is not the last node
|
||||||
|
- el.insertBefore(dragEl, elLastChild.nextSibling);
|
||||||
|
- } else {
|
||||||
|
- el.appendChild(dragEl);
|
||||||
|
+ try {
|
||||||
|
+ if (elLastChild && elLastChild.nextSibling) {
|
||||||
|
+ // the last draggable element is not the last node
|
||||||
|
+ el.insertBefore(dragEl, elLastChild.nextSibling);
|
||||||
|
+ } else {
|
||||||
|
+ el.appendChild(dragEl);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ catch(err) {
|
||||||
|
+ return completed(false);
|
||||||
|
}
|
||||||
|
parentEl = el; // actualization
|
||||||
|
|
||||||
|
@@ -1802,7 +1807,13 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
|
targetRect = getRect(target);
|
||||||
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
|
||||||
|
capture();
|
||||||
|
- el.insertBefore(dragEl, firstChild);
|
||||||
|
+ try {
|
||||||
|
+ el.insertBefore(dragEl, firstChild);
|
||||||
|
+ }
|
||||||
|
+ catch(err) {
|
||||||
|
+ return completed(false);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
parentEl = el; // actualization
|
||||||
|
|
||||||
|
changed();
|
||||||
|
@@ -1849,12 +1860,17 @@ Sortable.prototype = /** @lends Sortable.prototype */{
|
||||||
|
_silent = true;
|
||||||
|
setTimeout(_unsilent, 30);
|
||||||
|
capture();
|
||||||
|
- if (after && !nextSibling) {
|
||||||
|
- el.appendChild(dragEl);
|
||||||
|
- } else {
|
||||||
|
- target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
|
||||||
|
- }
|
||||||
|
|
||||||
|
+ try {
|
||||||
|
+ if (after && !nextSibling) {
|
||||||
|
+ el.appendChild(dragEl);
|
||||||
|
+ } else {
|
||||||
|
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ catch(err) {
|
||||||
|
+ return completed(false);
|
||||||
|
+ }
|
||||||
|
// Undo chrome's scroll adjustment (has no effect on other browsers)
|
||||||
|
if (scrolledPastTop) {
|
||||||
|
scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
|
@ -8,7 +8,10 @@ const zopfliOptions = { threshold: 150 };
|
|||||||
|
|
||||||
const compressDist = (rootDir) =>
|
const compressDist = (rootDir) =>
|
||||||
gulp
|
gulp
|
||||||
.src([`${rootDir}/**/*.{js,json,css,svg}`])
|
.src([
|
||||||
|
`${rootDir}/**/*.{js,json,css,svg,xml}`,
|
||||||
|
`${rootDir}/{authorize,onboarding}.html`,
|
||||||
|
])
|
||||||
.pipe(zopfli(zopfliOptions))
|
.pipe(zopfli(zopfliOptions))
|
||||||
.pipe(gulp.dest(rootDir));
|
.pipe(gulp.dest(rootDir));
|
||||||
|
|
||||||
|
@ -426,6 +426,7 @@ gulp.task(
|
|||||||
"fetch-nightly-translations",
|
"fetch-nightly-translations",
|
||||||
gulp.series("clean-translations", "ensure-translations-build-dir")
|
gulp.series("clean-translations", "ensure-translations-build-dir")
|
||||||
),
|
),
|
||||||
|
gulp.parallel("create-test-metadata", "create-test-translation"),
|
||||||
"build-master-translation",
|
"build-master-translation",
|
||||||
"build-merged-translations",
|
"build-merged-translations",
|
||||||
"build-translation-fragment-supervisor",
|
"build-translation-fragment-supervisor",
|
||||||
|
@ -7,6 +7,9 @@ const TerserPlugin = require("terser-webpack-plugin");
|
|||||||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
||||||
const log = require("fancy-log");
|
const log = require("fancy-log");
|
||||||
const WebpackBar = require("webpackbar");
|
const WebpackBar = require("webpackbar");
|
||||||
|
const {
|
||||||
|
TransformAsyncModulesPlugin,
|
||||||
|
} = require("transform-async-modules-webpack-plugin");
|
||||||
const paths = require("./paths.cjs");
|
const paths = require("./paths.cjs");
|
||||||
const bundle = require("./bundle.cjs");
|
const bundle = require("./bundle.cjs");
|
||||||
|
|
||||||
@ -142,17 +145,6 @@ 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(),
|
||||||
isProdBuild &&
|
isProdBuild &&
|
||||||
new StatsWriterPlugin({
|
new StatsWriterPlugin({
|
||||||
@ -163,6 +155,8 @@ const createWebpackConfig = ({
|
|||||||
stats: { assets: true, chunks: true, modules: true },
|
stats: { assets: true, chunks: true, modules: true },
|
||||||
transform: (stats) => JSON.stringify(filterStats(stats)),
|
transform: (stats) => JSON.stringify(filterStats(stats)),
|
||||||
}),
|
}),
|
||||||
|
!latestBuild &&
|
||||||
|
new TransformAsyncModulesPlugin({ browserslistEnv: "legacy" }),
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".ts", ".js", ".json"],
|
extensions: [".ts", ".js", ".json"],
|
||||||
|
BIN
cast/public/images/nabu-loves-hass.png
Normal file
BIN
cast/public/images/nabu-loves-hass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
@ -31,11 +31,11 @@ import "./hc-layout";
|
|||||||
|
|
||||||
@customElement("hc-cast")
|
@customElement("hc-cast")
|
||||||
class HcCast extends LitElement {
|
class HcCast extends LitElement {
|
||||||
@property() public auth!: Auth;
|
@property({ attribute: false }) public auth!: Auth;
|
||||||
|
|
||||||
@property() public connection!: Connection;
|
@property({ attribute: false }) public connection!: Connection;
|
||||||
|
|
||||||
@property() public castManager!: CastManager;
|
@property({ attribute: false }) public castManager!: CastManager;
|
||||||
|
|
||||||
@state() private askWrite = false;
|
@state() private askWrite = false;
|
||||||
|
|
||||||
@ -241,6 +241,8 @@ class HcCast extends LitElement {
|
|||||||
|
|
||||||
mwc-button ha-svg-icon {
|
mwc-button ha-svg-icon {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
margin-inline-start: initial;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,13 @@ import "../../../../src/components/ha-card";
|
|||||||
|
|
||||||
@customElement("hc-layout")
|
@customElement("hc-layout")
|
||||||
class HcLayout extends LitElement {
|
class HcLayout extends LitElement {
|
||||||
@property() public subtitle?: string | undefined;
|
@property() public subtitle?: string;
|
||||||
|
|
||||||
@property() public auth?: Auth;
|
@property({ attribute: false }) public auth?: Auth;
|
||||||
|
|
||||||
@property() public connection?: Connection;
|
@property({ attribute: false }) public connection?: Connection;
|
||||||
|
|
||||||
@property() public user?: HassUser;
|
@property({ attribute: false }) public user?: HassUser;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
@ -12,8 +12,8 @@ class HcLaunchScreen extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img
|
<img
|
||||||
alt="Home Assistant logo on left, Nabu Casa logo on right, and red heart in center"
|
alt="Nabu Casa logo on left, Home Assistant logo on right, and red heart in center"
|
||||||
src="https://www.home-assistant.io/images/blog/2018-09-thinking-big/social.png"
|
src="https://cast.home-assistant.io/images/nabu-loves-hass.png"
|
||||||
/>
|
/>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
${this.hass ? "Connected" : "Not Connected"}
|
${this.hass ? "Connected" : "Not Connected"}
|
||||||
@ -45,6 +45,8 @@ class HcLaunchScreen extends LitElement {
|
|||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
padding-right: 54px;
|
padding-right: 54px;
|
||||||
|
padding-inline-end: 54px;
|
||||||
|
padding-inline-start: initial;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,6 @@ export class HcMain extends HassElement {
|
|||||||
expires_in: 0,
|
expires_in: 0,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
this._hassUUID = msg.hassUUID;
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const errorMessage = this._getErrorMessage(err);
|
const errorMessage = this._getErrorMessage(err);
|
||||||
this._error = errorMessage;
|
this._error = errorMessage;
|
||||||
@ -225,6 +224,17 @@ export class HcMain extends HassElement {
|
|||||||
this.hass.connection.close();
|
this.hass.connection.close();
|
||||||
}
|
}
|
||||||
this.initializeHass(auth, connection);
|
this.initializeHass(auth, connection);
|
||||||
|
if (this._hassUUID !== msg.hassUUID) {
|
||||||
|
this._hassUUID = msg.hassUUID;
|
||||||
|
this._lovelacePath = null;
|
||||||
|
this._urlPath = undefined;
|
||||||
|
this._lovelaceConfig = undefined;
|
||||||
|
if (this._unsubLovelace) {
|
||||||
|
this._unsubLovelace();
|
||||||
|
this._unsubLovelace = undefined;
|
||||||
|
}
|
||||||
|
resourcesLoaded = false;
|
||||||
|
}
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._sendStatus();
|
this._sendStatus();
|
||||||
}
|
}
|
||||||
@ -233,7 +243,7 @@ export class HcMain extends HassElement {
|
|||||||
this._showDemo = false;
|
this._showDemo = false;
|
||||||
// We should not get this command before we are connected.
|
// We should not get this command before we are connected.
|
||||||
// Means a client got out of sync. Let's send status to them.
|
// Means a client got out of sync. Let's send status to them.
|
||||||
if (!this.hass) {
|
if (!this.hass?.connected) {
|
||||||
this._sendStatus(msg.senderId!);
|
this._sendStatus(msg.senderId!);
|
||||||
this._error = "Cannot show Lovelace because we're not connected.";
|
this._error = "Cannot show Lovelace because we're not connected.";
|
||||||
this._sendError(
|
this._sendError(
|
||||||
@ -284,6 +294,7 @@ export class HcMain extends HassElement {
|
|||||||
this._lovelaceConfig = undefined;
|
this._lovelaceConfig = undefined;
|
||||||
if (this._unsubLovelace) {
|
if (this._unsubLovelace) {
|
||||||
this._unsubLovelace();
|
this._unsubLovelace();
|
||||||
|
this._unsubLovelace = undefined;
|
||||||
}
|
}
|
||||||
const llColl = atLeastVersion(this.hass.connection.haVersion, 0, 107)
|
const llColl = atLeastVersion(this.hass.connection.haVersion, 0, 107)
|
||||||
? getLovelaceCollection(this.hass.connection, msg.urlPath)
|
? getLovelaceCollection(this.hass.connection, msg.urlPath)
|
||||||
|
@ -11,7 +11,7 @@ class DemoBlackWhiteRow extends LitElement {
|
|||||||
|
|
||||||
@property() value!: any;
|
@property() value!: any;
|
||||||
|
|
||||||
@property() disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
@ -11,11 +11,11 @@ export interface DemoCardConfig {
|
|||||||
|
|
||||||
@customElement("demo-card")
|
@customElement("demo-card")
|
||||||
class DemoCard extends LitElement {
|
class DemoCard extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public config!: DemoCardConfig;
|
@property({ attribute: false }) public config!: DemoCardConfig;
|
||||||
|
|
||||||
@property() public showConfig = false;
|
@property({ type: Boolean }) public showConfig = false;
|
||||||
|
|
||||||
@state() private _size?: number;
|
@state() private _size?: number;
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ import "../ha-demo-options";
|
|||||||
|
|
||||||
@customElement("demo-cards")
|
@customElement("demo-cards")
|
||||||
class DemoCards extends LitElement {
|
class DemoCards extends LitElement {
|
||||||
@property() public configs!: DemoCardConfig[];
|
@property({ attribute: false }) public configs!: DemoCardConfig[];
|
||||||
|
|
||||||
@property() public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@state() private _showConfig = false;
|
@state() private _showConfig = false;
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ import { HomeAssistant } from "../../../src/types";
|
|||||||
|
|
||||||
@customElement("demo-more-info")
|
@customElement("demo-more-info")
|
||||||
class DemoMoreInfo extends LitElement {
|
class DemoMoreInfo extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public entityId!: string;
|
@property() public entityId!: string;
|
||||||
|
|
||||||
@property() public showConfig!: boolean;
|
@property({ type: Boolean }) public showConfig = false;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const state = this._getState(this.entityId, this.hass.states);
|
const state = this._getState(this.entityId, this.hass.states);
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { LitElement, css, html } from "lit";
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
||||||
import "../../../src/components/ha-formfield";
|
import "../../../src/components/ha-formfield";
|
||||||
import "../../../src/components/ha-switch";
|
import "../../../src/components/ha-switch";
|
||||||
import "./demo-more-info";
|
|
||||||
import "../ha-demo-options";
|
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
|
import "../ha-demo-options";
|
||||||
|
import "./demo-more-info";
|
||||||
|
|
||||||
@customElement("demo-more-infos")
|
@customElement("demo-more-infos")
|
||||||
class DemoMoreInfos extends LitElement {
|
class DemoMoreInfos extends LitElement {
|
||||||
@property() public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public entities!: [];
|
@property({ type: Array }) public entities!: string[];
|
||||||
|
|
||||||
@property({ attribute: false }) _showConfig: boolean = false;
|
@state() private _showConfig = false;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { mdiMenu } from "@mdi/js";
|
|
||||||
import "@material/mwc-drawer";
|
import "@material/mwc-drawer";
|
||||||
import "@material/mwc-top-app-bar-fixed";
|
import "@material/mwc-top-app-bar-fixed";
|
||||||
import { html, css, LitElement, PropertyValues } from "lit";
|
import { mdiMenu } from "@mdi/js";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { LitElement, PropertyValues, css, html } from "lit";
|
||||||
|
import { customElement, query, state } from "lit/decorators";
|
||||||
|
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
|
||||||
|
import { HaExpansionPanel } from "../../src/components/ha-expansion-panel";
|
||||||
import "../../src/components/ha-icon-button";
|
import "../../src/components/ha-icon-button";
|
||||||
import "../../src/managers/notification-manager";
|
import "../../src/managers/notification-manager";
|
||||||
import { HaExpansionPanel } from "../../src/components/ha-expansion-panel";
|
|
||||||
import { haStyle } from "../../src/resources/styles";
|
import { haStyle } from "../../src/resources/styles";
|
||||||
import { PAGES, SIDEBAR } from "../build/import-pages";
|
import { PAGES, SIDEBAR } from "../build/import-pages";
|
||||||
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
|
|
||||||
import "./components/page-description";
|
import "./components/page-description";
|
||||||
|
|
||||||
const GITHUB_DEMO_URL =
|
const GITHUB_DEMO_URL =
|
||||||
@ -24,7 +24,7 @@ const FAKE_HASS = {
|
|||||||
|
|
||||||
@customElement("ha-gallery")
|
@customElement("ha-gallery")
|
||||||
class HaGallery extends LitElement {
|
class HaGallery extends LitElement {
|
||||||
@property() private _page =
|
@state() private _page =
|
||||||
document.location.hash.substring(1) ||
|
document.location.hash.substring(1) ||
|
||||||
`${SIDEBAR[0].category}/${SIDEBAR[0].pages![0]}`;
|
`${SIDEBAR[0].category}/${SIDEBAR[0].pages![0]}`;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-automation-editor-condition")
|
@customElement("demo-automation-editor-condition")
|
||||||
class DemoHaAutomationEditorCondition extends LitElement {
|
export class DemoAutomationEditorCondition extends LitElement {
|
||||||
@state() private hass!: HomeAssistant;
|
@state() private hass!: HomeAssistant;
|
||||||
|
|
||||||
@state() private _disabled = false;
|
@state() private _disabled = false;
|
||||||
@ -155,6 +155,6 @@ class DemoHaAutomationEditorCondition extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-ha-automation-editor-condition": DemoHaAutomationEditorCondition;
|
"demo-automation-editor-condition": DemoAutomationEditorCondition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-automation-editor-trigger")
|
@customElement("demo-automation-editor-trigger")
|
||||||
class DemoHaAutomationEditorTrigger extends LitElement {
|
export class DemoAutomationEditorTrigger extends LitElement {
|
||||||
@state() private hass!: HomeAssistant;
|
@state() private hass!: HomeAssistant;
|
||||||
|
|
||||||
@state() private _disabled = false;
|
@state() private _disabled = false;
|
||||||
@ -201,6 +201,6 @@ class DemoHaAutomationEditorTrigger extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-ha-automation-editor-trigger": DemoHaAutomationEditorTrigger;
|
"demo-automation-editor-trigger": DemoAutomationEditorTrigger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ export class DemoHaBarButton extends LitElement {
|
|||||||
<ha-control-button
|
<ha-control-button
|
||||||
class=${ifDefined(btn.class)}
|
class=${ifDefined(btn.class)}
|
||||||
label=${ifDefined(btn.label)}
|
label=${ifDefined(btn.label)}
|
||||||
disabled=${ifDefined(btn.disabled)}
|
?disabled=${btn.disabled}
|
||||||
>
|
>
|
||||||
<ha-svg-icon .path=${btn.icon || mdiLightbulb}></ha-svg-icon>
|
<ha-svg-icon .path=${btn.icon || mdiLightbulb}></ha-svg-icon>
|
||||||
</ha-control-button>
|
</ha-control-button>
|
||||||
|
@ -135,7 +135,7 @@ export class DemoHaControlSelect extends LitElement {
|
|||||||
class=${ifDefined(config.class)}
|
class=${ifDefined(config.class)}
|
||||||
@value-changed=${this.handleValueChanged}
|
@value-changed=${this.handleValueChanged}
|
||||||
aria-labelledby=${id}
|
aria-labelledby=${id}
|
||||||
disabled=${ifDefined(config.disabled)}
|
?disabled=${config.disabled}
|
||||||
>
|
>
|
||||||
</ha-control-select>
|
</ha-control-select>
|
||||||
</div>
|
</div>
|
||||||
@ -156,7 +156,7 @@ export class DemoHaControlSelect extends LitElement {
|
|||||||
class=${ifDefined(config.class)}
|
class=${ifDefined(config.class)}
|
||||||
@value-changed=${this.handleValueChanged}
|
@value-changed=${this.handleValueChanged}
|
||||||
aria-labelledby=${id}
|
aria-labelledby=${id}
|
||||||
disabled=${ifDefined(config.disabled)}
|
?disabled=${config.disabled}
|
||||||
>
|
>
|
||||||
</ha-control-select>
|
</ha-control-select>
|
||||||
`;
|
`;
|
||||||
|
@ -63,8 +63,8 @@ export class DemoHaControlSwitch extends LitElement {
|
|||||||
.pathOn=${mdiLightbulb}
|
.pathOn=${mdiLightbulb}
|
||||||
.pathOff=${mdiLightbulbOff}
|
.pathOff=${mdiLightbulbOff}
|
||||||
aria-labelledby=${id}
|
aria-labelledby=${id}
|
||||||
disabled=${ifDefined(config.disabled)}
|
?disabled=${config.disabled}
|
||||||
reversed=${ifDefined(config.reversed)}
|
?reversed=${config.reversed}
|
||||||
>
|
>
|
||||||
</ha-control-switch>
|
</ha-control-switch>
|
||||||
</div>
|
</div>
|
||||||
@ -86,8 +86,8 @@ export class DemoHaControlSwitch extends LitElement {
|
|||||||
aria-label=${label}
|
aria-label=${label}
|
||||||
.pathOn=${mdiGarageOpen}
|
.pathOn=${mdiGarageOpen}
|
||||||
.pathOff=${mdiGarage}
|
.pathOff=${mdiGarage}
|
||||||
disabled=${ifDefined(config.disabled)}
|
?disabled=${config.disabled}
|
||||||
reversed=${ifDefined(config.reversed)}
|
?reversed=${config.reversed}
|
||||||
>
|
>
|
||||||
</ha-control-switch>
|
</ha-control-switch>
|
||||||
`;
|
`;
|
||||||
|
@ -3,6 +3,7 @@ import { css, html, LitElement, TemplateResult } from "lit";
|
|||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-expansion-panel";
|
import "../../../../src/components/ha-expansion-panel";
|
||||||
|
import "../../../../src/components/ha-icon-button";
|
||||||
import "../../../../src/components/ha-markdown";
|
import "../../../../src/components/ha-markdown";
|
||||||
import "../../components/demo-black-white-row";
|
import "../../components/demo-black-white-row";
|
||||||
import { LONG_TEXT } from "../../data/text";
|
import { LONG_TEXT } from "../../data/text";
|
||||||
|
@ -10,6 +10,7 @@ import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervis
|
|||||||
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
|
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
|
||||||
import "../../../../src/components/ha-form/ha-form";
|
import "../../../../src/components/ha-form/ha-form";
|
||||||
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
||||||
|
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import { getEntity } from "../../../../src/fake_data/entity";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
@ -97,22 +98,25 @@ const DEVICES = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const AREAS = [
|
const AREAS: AreaRegistryEntry[] = [
|
||||||
{
|
{
|
||||||
area_id: "backyard",
|
area_id: "backyard",
|
||||||
name: "Backyard",
|
name: "Backyard",
|
||||||
|
icon: null,
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "bedroom",
|
area_id: "bedroom",
|
||||||
name: "Bedroom",
|
name: "Bedroom",
|
||||||
|
icon: "mdi:bed",
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "livingroom",
|
area_id: "livingroom",
|
||||||
name: "Livingroom",
|
name: "Livingroom",
|
||||||
|
icon: "mdi:sofa",
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,7 @@ import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
|||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
||||||
import "../../../../src/components/ha-selector/ha-selector";
|
import "../../../../src/components/ha-selector/ha-selector";
|
||||||
import "../../../../src/components/ha-settings-row";
|
import "../../../../src/components/ha-settings-row";
|
||||||
|
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
||||||
import { BlueprintInput } from "../../../../src/data/blueprint";
|
import { BlueprintInput } from "../../../../src/data/blueprint";
|
||||||
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import { getEntity } from "../../../../src/fake_data/entity";
|
||||||
@ -93,22 +94,25 @@ const DEVICES = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const AREAS = [
|
const AREAS: AreaRegistryEntry[] = [
|
||||||
{
|
{
|
||||||
area_id: "backyard",
|
area_id: "backyard",
|
||||||
name: "Backyard",
|
name: "Backyard",
|
||||||
|
icon: null,
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "bedroom",
|
area_id: "bedroom",
|
||||||
name: "Bedroom",
|
name: "Bedroom",
|
||||||
|
icon: "mdi:bed",
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
area_id: "livingroom",
|
area_id: "livingroom",
|
||||||
name: "Livingroom",
|
name: "Livingroom",
|
||||||
|
icon: "mdi:sofa",
|
||||||
picture: null,
|
picture: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
},
|
},
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatDateTimeNumeric } from "../../../../src/common/datetime/format_date_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-date-time-numeric")
|
@customElement("demo-date-time-date-time-numeric")
|
||||||
export class DemoDateTimeDateTimeNumeric extends LitElement {
|
export class DemoDateTimeDateTimeNumeric extends LitElement {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatDateTimeWithSeconds } from "../../../../src/common/datetime/format_date_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-date-time-seconds")
|
@customElement("demo-date-time-date-time-seconds")
|
||||||
export class DemoDateTimeDateTimeSeconds extends LitElement {
|
export class DemoDateTimeDateTimeSeconds extends LitElement {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatShortDateTimeWithYear } from "../../../../src/common/datetime/format_date_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-date-time-short-year")
|
@customElement("demo-date-time-date-time-short-year")
|
||||||
export class DemoDateTimeDateTimeShortYear extends LitElement {
|
export class DemoDateTimeDateTimeShortYear extends LitElement {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatShortDateTime } from "../../../../src/common/datetime/format_date_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-date-time-short")
|
@customElement("demo-date-time-date-time-short")
|
||||||
export class DemoDateTimeDateTimeShort extends LitElement {
|
export class DemoDateTimeDateTimeShort extends LitElement {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatDateTime } from "../../../../src/common/datetime/format_date_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-date-time")
|
@customElement("demo-date-time-date-time")
|
||||||
export class DemoDateTimeDateTime extends LitElement {
|
export class DemoDateTimeDateTime extends LitElement {
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
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 { formatTimeWithSeconds } from "../../../../src/common/datetime/format_time";
|
||||||
import { timeOptions } from "../../data/date-options";
|
import "../../../../src/components/ha-card";
|
||||||
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
import "../../../../src/components/ha-control-select";
|
||||||
import {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-time-seconds")
|
@customElement("demo-date-time-time-seconds")
|
||||||
export class DemoDateTimeTimeSeconds extends LitElement {
|
export class DemoDateTimeTimeSeconds extends LitElement {
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
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 { formatTimeWeekday } from "../../../../src/common/datetime/format_time";
|
||||||
import { timeOptions } from "../../data/date-options";
|
import "../../../../src/components/ha-card";
|
||||||
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
import "../../../../src/components/ha-control-select";
|
||||||
import {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-time-weekday")
|
@customElement("demo-date-time-time-weekday")
|
||||||
export class DemoDateTimeTimeWeekday extends LitElement {
|
export class DemoDateTimeTimeWeekday extends LitElement {
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { html, css, LitElement } from "lit";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { formatTime } from "../../../../src/common/datetime/format_time";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-control-select";
|
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 {
|
import {
|
||||||
|
DateFormat,
|
||||||
|
FirstWeekday,
|
||||||
FrontendLocaleData,
|
FrontendLocaleData,
|
||||||
NumberFormat,
|
NumberFormat,
|
||||||
TimeFormat,
|
TimeFormat,
|
||||||
DateFormat,
|
|
||||||
FirstWeekday,
|
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from "../../../../src/data/translation";
|
} from "../../../../src/data/translation";
|
||||||
|
import { demoConfig } from "../../../../src/fake_data/demo_config";
|
||||||
|
import { translationMetadata } from "../../../../src/resources/translations-metadata";
|
||||||
|
import { timeOptions } from "../../data/date-options";
|
||||||
|
|
||||||
@customElement("demo-date-time-time")
|
@customElement("demo-date-time-time")
|
||||||
export class DemoDateTimeTime extends LitElement {
|
export class DemoDateTimeTime extends LitElement {
|
||||||
|
@ -65,15 +65,23 @@ 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
|
> [!NOTE]
|
||||||
> This is a warning with a title
|
> This is a GitHub note alert
|
||||||
|
|
||||||
> **Note**
|
> [!TIP]
|
||||||
> This is a note
|
> This is a GitHub tip alert
|
||||||
|
|
||||||
> **Note**
|
> [!IMPORTANT]
|
||||||
> This is a multiline note
|
> This is a GitHub important alert
|
||||||
> Lorem ipsum...
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This is a GitHub warning alert
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> This is a GitHub caution alert
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> - This is a list entry in GitHub tip alert
|
||||||
|
|
||||||
## Lists
|
## Lists
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ const CONFIGS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-media-player-row")
|
@customElement("demo-lovelace-media-player-row")
|
||||||
class DemoHuiMediaPlayerRow extends LitElement {
|
export class DemoLovelaceMediaPlayerRow extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@ -73,6 +73,6 @@ class DemoHuiMediaPlayerRow extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-media-player-rows": DemoHuiMediaPlayerRow;
|
"demo-lovelace-media-player-row": DemoLovelaceMediaPlayerRow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,18 @@ const CONFIGS = [
|
|||||||
color: pink
|
color: pink
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
heading: "Whole tile tap action",
|
||||||
|
config: `
|
||||||
|
- type: tile
|
||||||
|
entity: switch.tv_outlet
|
||||||
|
color: pink
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
icon_tap_action:
|
||||||
|
action: none
|
||||||
|
`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
heading: "Unknown entity",
|
heading: "Unknown entity",
|
||||||
config: `
|
config: `
|
||||||
|
@ -53,6 +53,7 @@ const SENSOR_DEVICE_CLASSES = [
|
|||||||
"volatile_organic_compounds_parts",
|
"volatile_organic_compounds_parts",
|
||||||
"voltage",
|
"voltage",
|
||||||
"volume",
|
"volume",
|
||||||
|
"volume_flow_rate",
|
||||||
"water",
|
"water",
|
||||||
"weight",
|
"weight",
|
||||||
"wind_speed",
|
"wind_speed",
|
||||||
@ -344,6 +345,7 @@ export class DemoEntityState extends LitElement {
|
|||||||
title: "Icon",
|
title: "Icon",
|
||||||
template: (entry) => html`
|
template: (entry) => html`
|
||||||
<state-badge
|
<state-badge
|
||||||
|
.hass=${hass}
|
||||||
.stateObj=${entry.stateObj}
|
.stateObj=${entry.stateObj}
|
||||||
.stateColor=${true}
|
.stateColor=${true}
|
||||||
></state-badge>
|
></state-badge>
|
||||||
|
@ -59,3 +59,9 @@ export class DemoUtilLongPress extends LitElement {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-misc-util-long-press": DemoUtilLongPress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -92,7 +92,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-climate")
|
@customElement("demo-more-info-climate")
|
||||||
class DemoMoreInfoClimate extends LitElement {
|
class DemoMoreInfoClimate extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-cover")
|
@customElement("demo-more-info-cover")
|
||||||
class DemoMoreInfoCover extends LitElement {
|
class DemoMoreInfoCover extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-humidifier")
|
@customElement("demo-more-info-humidifier")
|
||||||
class DemoMoreInfoHumidifier extends LitElement {
|
class DemoMoreInfoHumidifier extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-input-number")
|
@customElement("demo-more-info-input-number")
|
||||||
class DemoMoreInfoInputNumber extends LitElement {
|
class DemoMoreInfoInputNumber extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-input-text")
|
@customElement("demo-more-info-input-text")
|
||||||
class DemoMoreInfoInputText extends LitElement {
|
class DemoMoreInfoInputText extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-light")
|
@customElement("demo-more-info-light")
|
||||||
class DemoMoreInfoLight extends LitElement {
|
class DemoMoreInfoLight extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-lock")
|
@customElement("demo-more-info-lock")
|
||||||
class DemoMoreInfoLock extends LitElement {
|
class DemoMoreInfoLock extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ const ENTITIES = createMediaPlayerEntities();
|
|||||||
|
|
||||||
@customElement("demo-more-info-media-player")
|
@customElement("demo-more-info-media-player")
|
||||||
class DemoMoreInfoMediaPlayer extends LitElement {
|
class DemoMoreInfoMediaPlayer extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-number")
|
@customElement("demo-more-info-number")
|
||||||
class DemoMoreInfoNumber extends LitElement {
|
class DemoMoreInfoNumber extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-scene")
|
@customElement("demo-more-info-scene")
|
||||||
class DemoMoreInfoScene extends LitElement {
|
class DemoMoreInfoScene extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-timer")
|
@customElement("demo-more-info-timer")
|
||||||
class DemoMoreInfoTimer extends LitElement {
|
class DemoMoreInfoTimer extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-update")
|
@customElement("demo-more-info-update")
|
||||||
class DemoMoreInfoUpdate extends LitElement {
|
class DemoMoreInfoUpdate extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-vacuum")
|
@customElement("demo-more-info-vacuum")
|
||||||
class DemoMoreInfoVacuum extends LitElement {
|
class DemoMoreInfoVacuum extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ const ENTITIES = [
|
|||||||
|
|
||||||
@customElement("demo-more-info-water-heater")
|
@customElement("demo-more-info-water-heater")
|
||||||
class DemoMoreInfoWaterHeater extends LitElement {
|
class DemoMoreInfoWaterHeater extends LitElement {
|
||||||
@property() public hass!: MockHomeAssistant;
|
@property({ attribute: false }) public hass!: MockHomeAssistant;
|
||||||
|
|
||||||
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
@query("demo-more-infos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
|
@ -140,3 +140,9 @@ export class HassioAddonRepositoryEl extends LitElement {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hassio-addon-repository": HassioAddonRepositoryEl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -56,7 +56,7 @@ export class HassioAddonStore extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@ -243,8 +243,16 @@ export class HassioAddonStore extends LitElement {
|
|||||||
}
|
}
|
||||||
.advanced a {
|
.advanced a {
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
|
margin-inline-start: 0.5em;
|
||||||
|
margin-inline-end: initial;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hassio-addon-store": HassioAddonStore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -65,9 +65,9 @@ class HassioAddonConfig extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) private _configHasChanged = false;
|
@state() private _configHasChanged = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) private _valid = true;
|
@state() private _valid = true;
|
||||||
|
|
||||||
@state() private _canShowSchema = false;
|
@state() private _canShowSchema = false;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
| HassioAddonDetails
|
| HassioAddonDetails
|
||||||
| StoreAddonDetails;
|
| StoreAddonDetails;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
@ -250,7 +250,9 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path === "uninstall") {
|
if (path === "uninstall") {
|
||||||
window.history.back();
|
if (this.isConnected) {
|
||||||
|
navigate(this._backPath);
|
||||||
|
}
|
||||||
} else if (path === "install") {
|
} else if (path === "install") {
|
||||||
this.addon = await fetchHassioAddonInfo(this.hass, this.addon!.slug);
|
this.addon = await fetchHassioAddonInfo(this.hass, this.addon!.slug);
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,7 +10,7 @@ import "./hassio-addon-info";
|
|||||||
|
|
||||||
@customElement("hassio-addon-info-tab")
|
@customElement("hassio-addon-info-tab")
|
||||||
class HassioAddonInfoDashboard extends LitElement {
|
class HassioAddonInfoDashboard extends LitElement {
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ const RATING_ICON = {
|
|||||||
|
|
||||||
@customElement("hassio-addon-info")
|
@customElement("hassio-addon-info")
|
||||||
class HassioAddonInfo extends LitElement {
|
class HassioAddonInfo extends LitElement {
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@ -1188,11 +1188,13 @@ class HassioAddonInfo extends LitElement {
|
|||||||
}
|
}
|
||||||
.addon-header {
|
.addon-header {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-inline-start: 8px;
|
||||||
|
padding-inline-end: initial;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: var(--ha-card-header-color, --primary-text-color);
|
color: var(--ha-card-header-color, --primary-text-color);
|
||||||
}
|
}
|
||||||
.addon-version {
|
.addon-version {
|
||||||
float: right;
|
float: var(--float-end);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
@ -59,11 +59,11 @@ export class HassioBackups extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Object }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) public isWide!: boolean;
|
@property({ type: Boolean }) public isWide = false;
|
||||||
|
|
||||||
@state() private _selectedBackups: string[] = [];
|
@state() private _selectedBackups: string[] = [];
|
||||||
|
|
||||||
@ -395,6 +395,8 @@ export class HassioBackups extends LitElement {
|
|||||||
.selected-txt {
|
.selected-txt {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
padding-inline-start: 16px;
|
||||||
|
padding-inline-end: initial;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
.table-header .selected-txt {
|
.table-header .selected-txt {
|
||||||
@ -405,6 +407,8 @@ export class HassioBackups extends LitElement {
|
|||||||
}
|
}
|
||||||
.header-toolbar .header-btns {
|
.header-toolbar .header-btns {
|
||||||
margin-right: -12px;
|
margin-right: -12px;
|
||||||
|
margin-inline-end: -12px;
|
||||||
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
.header-btns > mwc-button,
|
.header-btns > mwc-button,
|
||||||
.header-btns > ha-icon-button {
|
.header-btns > ha-icon-button {
|
||||||
|
@ -60,6 +60,10 @@ class HassioCardContent extends LitElement {
|
|||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
|
:host {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
ha-svg-icon {
|
ha-svg-icon {
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { mdiFolder, mdiPuzzle } from "@mdi/js";
|
import { mdiFolder, mdiPuzzle } from "@mdi/js";
|
||||||
import "@polymer/paper-input/paper-input";
|
|
||||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|
||||||
import {
|
import {
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
LitElement,
|
LitElement,
|
||||||
@ -16,6 +14,7 @@ import { formatDateTime } from "../../../src/common/datetime/format_date_time";
|
|||||||
import { LocalizeFunc } from "../../../src/common/translations/localize";
|
import { LocalizeFunc } from "../../../src/common/translations/localize";
|
||||||
import "../../../src/components/ha-checkbox";
|
import "../../../src/components/ha-checkbox";
|
||||||
import "../../../src/components/ha-formfield";
|
import "../../../src/components/ha-formfield";
|
||||||
|
import "../../../src/components/ha-textfield";
|
||||||
import "../../../src/components/ha-radio";
|
import "../../../src/components/ha-radio";
|
||||||
import type { HaRadio } from "../../../src/components/ha-radio";
|
import type { HaRadio } from "../../../src/components/ha-radio";
|
||||||
import {
|
import {
|
||||||
@ -25,12 +24,9 @@ import {
|
|||||||
} 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 { mdiHomeAssistant } from "../../../src/resources/home-assistant-logo-svg";
|
import { mdiHomeAssistant } from "../../../src/resources/home-assistant-logo-svg";
|
||||||
import {
|
import { HomeAssistant, TranslationDict } from "../../../src/types";
|
||||||
HomeAssistant,
|
|
||||||
TranslationDict,
|
|
||||||
ValueChangedEvent,
|
|
||||||
} from "../../../src/types";
|
|
||||||
import "./supervisor-formfield-label";
|
import "./supervisor-formfield-label";
|
||||||
|
import type { HaTextField } from "../../../src/components/ha-textfield";
|
||||||
|
|
||||||
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] &
|
||||||
keyof TranslationDict["ui"]["panel"]["page-onboarding"]["restore"];
|
keyof TranslationDict["ui"]["panel"]["page-onboarding"]["restore"];
|
||||||
@ -76,7 +72,7 @@ const _computeAddons = (addons): AddonCheckboxItem[] =>
|
|||||||
export class SupervisorBackupContent extends LitElement {
|
export class SupervisorBackupContent extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public localize?: LocalizeFunc;
|
@property({ attribute: false }) public localize?: LocalizeFunc;
|
||||||
|
|
||||||
@property({ attribute: false }) public supervisor?: Supervisor;
|
@property({ attribute: false }) public supervisor?: Supervisor;
|
||||||
|
|
||||||
@ -100,7 +96,7 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
|
|
||||||
@property() public confirmBackupPassword = "";
|
@property() public confirmBackupPassword = "";
|
||||||
|
|
||||||
@query("paper-input, ha-radio, ha-checkbox", true) private _focusTarget;
|
@query("ha-textfield, ha-radio, ha-checkbox", true) private _focusTarget;
|
||||||
|
|
||||||
public willUpdate(changedProps) {
|
public willUpdate(changedProps) {
|
||||||
super.willUpdate(changedProps);
|
super.willUpdate(changedProps);
|
||||||
@ -151,13 +147,13 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
)
|
)
|
||||||
: this.backup.date}
|
: this.backup.date}
|
||||||
</div>`
|
</div>`
|
||||||
: html`<paper-input
|
: html`<ha-textfield
|
||||||
name="backupName"
|
name="backupName"
|
||||||
.label=${this._localize("name")}
|
.label=${this._localize("name")}
|
||||||
.value=${this.backupName}
|
.value=${this.backupName}
|
||||||
@value-changed=${this._handleTextValueChanged}
|
@change=${this._handleTextValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>`}
|
</ha-textfield>`}
|
||||||
${!this.backup || this.backup.type === "full"
|
${!this.backup || this.backup.type === "full"
|
||||||
? html`<div class="sub-header">
|
? html`<div class="sub-header">
|
||||||
${!this.backup
|
${!this.backup
|
||||||
@ -265,23 +261,23 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
${this.backupHasPassword
|
${this.backupHasPassword
|
||||||
? html`
|
? html`
|
||||||
<paper-input
|
<ha-textfield
|
||||||
.label=${this._localize("password")}
|
.label=${this._localize("password")}
|
||||||
type="password"
|
type="password"
|
||||||
name="backupPassword"
|
name="backupPassword"
|
||||||
.value=${this.backupPassword}
|
.value=${this.backupPassword}
|
||||||
@value-changed=${this._handleTextValueChanged}
|
@change=${this._handleTextValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>
|
</ha-textfield>
|
||||||
${!this.backup
|
${!this.backup
|
||||||
? html` <paper-input
|
? html`<ha-textfield
|
||||||
.label=${this._localize("confirm_password")}
|
.label=${this._localize("confirm_password")}
|
||||||
type="password"
|
type="password"
|
||||||
name="confirmBackupPassword"
|
name="confirmBackupPassword"
|
||||||
.value=${this.confirmBackupPassword}
|
.value=${this.confirmBackupPassword}
|
||||||
@value-changed=${this._handleTextValueChanged}
|
@change=${this._handleTextValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>`
|
</ha-textfield>`
|
||||||
: ""}
|
: ""}
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -320,6 +316,8 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-left: 30px;
|
margin-left: 30px;
|
||||||
|
margin-inline-start: 30px;
|
||||||
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
ha-formfield.password {
|
ha-formfield.password {
|
||||||
display: block;
|
display: block;
|
||||||
@ -328,6 +326,8 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
.backup-types {
|
.backup-types {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: -13px;
|
margin-left: -13px;
|
||||||
|
margin-inline-start: -13px;
|
||||||
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
.sub-header {
|
.sub-header {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
@ -429,9 +429,9 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
this[input.name] = input.value;
|
this[input.name] = input.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleTextValueChanged(ev: ValueChangedEvent<string>) {
|
private _handleTextValueChanged(ev: InputEvent) {
|
||||||
const input = ev.currentTarget as PaperInputElement;
|
const input = ev.currentTarget as HaTextField;
|
||||||
this[input.name!] = ev.detail.value;
|
this[input.name!] = input.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toggleHasPassword(): void {
|
private _toggleHasPassword(): void {
|
||||||
|
@ -37,6 +37,8 @@ class SupervisorFormfieldLabel extends LitElement {
|
|||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
margin-inline-end: 4px;
|
||||||
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
.version {
|
.version {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
@ -45,6 +47,8 @@ class SupervisorFormfieldLabel extends LitElement {
|
|||||||
max-height: 22px;
|
max-height: 22px;
|
||||||
max-width: 22px;
|
max-width: 22px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
margin-inline-end: 8px;
|
||||||
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ class SupervisorMetric extends LitElement {
|
|||||||
.value {
|
.value {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
padding-right: 4px;
|
padding-right: 4px;
|
||||||
|
padding-inline-start: initial;
|
||||||
|
padding-inline-end: 4px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -20,7 +20,7 @@ class HassioAddons extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _filter?: string;
|
@state() private _filter?: string;
|
||||||
|
|
||||||
@ -128,6 +128,7 @@ class HassioAddons extends LitElement {
|
|||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
direction: ltr;
|
||||||
}
|
}
|
||||||
.search {
|
.search {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
@ -21,7 +21,7 @@ class HassioDashboard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@ -133,6 +133,8 @@ class HassioDashboard extends LitElement {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
right: calc(16px + env(safe-area-inset-right));
|
right: calc(16px + env(safe-area-inset-right));
|
||||||
bottom: calc(16px + env(safe-area-inset-bottom));
|
bottom: calc(16px + env(safe-area-inset-bottom));
|
||||||
|
inset-inline-end: calc(16px + env(safe-area-inset-right));
|
||||||
|
inset-inline-start: initial;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@ -151,3 +151,9 @@ export class HassioUpdate extends LitElement {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hassio-update": HassioUpdate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,8 +27,7 @@ const SCHEMA = memoizeOne(
|
|||||||
class HassioBackupLocationDialog extends LitElement {
|
class HassioBackupLocationDialog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@state() private _dialogParams?: HassioBackupLocationDialogParams;
|
||||||
public _dialogParams?: HassioBackupLocationDialogParams;
|
|
||||||
|
|
||||||
@state() private _data?: { default_backup_mount: string | null };
|
@state() private _data?: { default_backup_mount: string | null };
|
||||||
|
|
||||||
|
@ -138,6 +138,9 @@ class HassioCreateBackupDialog extends LitElement {
|
|||||||
haStyle,
|
haStyle,
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
|
:host {
|
||||||
|
direction: var(--direction);
|
||||||
|
}
|
||||||
ha-circular-progress {
|
ha-circular-progress {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -4,7 +4,6 @@ import "@material/mwc-list/mwc-list-item";
|
|||||||
import "@material/mwc-tab";
|
import "@material/mwc-tab";
|
||||||
import "@material/mwc-tab-bar";
|
import "@material/mwc-tab-bar";
|
||||||
import { mdiClose } from "@mdi/js";
|
import { mdiClose } from "@mdi/js";
|
||||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { cache } from "lit/directives/cache";
|
import { cache } from "lit/directives/cache";
|
||||||
@ -14,6 +13,7 @@ import "../../../../src/components/ha-circular-progress";
|
|||||||
import "../../../../src/components/ha-dialog";
|
import "../../../../src/components/ha-dialog";
|
||||||
import "../../../../src/components/ha-expansion-panel";
|
import "../../../../src/components/ha-expansion-panel";
|
||||||
import "../../../../src/components/ha-formfield";
|
import "../../../../src/components/ha-formfield";
|
||||||
|
import "../../../../src/components/ha-textfield";
|
||||||
import "../../../../src/components/ha-header-bar";
|
import "../../../../src/components/ha-header-bar";
|
||||||
import "../../../../src/components/ha-icon-button";
|
import "../../../../src/components/ha-icon-button";
|
||||||
import "../../../../src/components/ha-radio";
|
import "../../../../src/components/ha-radio";
|
||||||
@ -34,6 +34,7 @@ import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
|
|||||||
import { haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { HassioNetworkDialogParams } from "./show-dialog-network";
|
import { HassioNetworkDialogParams } from "./show-dialog-network";
|
||||||
|
import type { HaTextField } from "../../../../src/components/ha-textfield";
|
||||||
|
|
||||||
const IP_VERSIONS = ["ipv4", "ipv6"];
|
const IP_VERSIONS = ["ipv4", "ipv6"];
|
||||||
|
|
||||||
@ -245,7 +246,7 @@ export class DialogHassioNetwork
|
|||||||
${this._wifiConfiguration.auth === "wpa-psk" ||
|
${this._wifiConfiguration.auth === "wpa-psk" ||
|
||||||
this._wifiConfiguration.auth === "wep"
|
this._wifiConfiguration.auth === "wep"
|
||||||
? html`
|
? html`
|
||||||
<paper-input
|
<ha-textfield
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
type="password"
|
type="password"
|
||||||
id="psk"
|
id="psk"
|
||||||
@ -253,10 +254,9 @@ export class DialogHassioNetwork
|
|||||||
"dialog.network.wifi_password"
|
"dialog.network.wifi_password"
|
||||||
)}
|
)}
|
||||||
version="wifi"
|
version="wifi"
|
||||||
@value-changed=${this
|
@change=${this._handleInputValueChangedWifi}
|
||||||
._handleInputValueChangedWifi}
|
|
||||||
>
|
>
|
||||||
</paper-input>
|
</ha-textfield>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
`
|
`
|
||||||
@ -358,33 +358,33 @@ export class DialogHassioNetwork
|
|||||||
</div>
|
</div>
|
||||||
${this._interface![version].method === "static"
|
${this._interface![version].method === "static"
|
||||||
? html`
|
? html`
|
||||||
<paper-input
|
<ha-textfield
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="address"
|
id="address"
|
||||||
.label=${this.supervisor.localize("dialog.network.ip_netmask")}
|
.label=${this.supervisor.localize("dialog.network.ip_netmask")}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._toString(this._interface![version].address)}
|
.value=${this._toString(this._interface![version].address)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@change=${this._handleInputValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>
|
</ha-textfield>
|
||||||
<paper-input
|
<ha-textfield
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="gateway"
|
id="gateway"
|
||||||
.label=${this.supervisor.localize("dialog.network.gateway")}
|
.label=${this.supervisor.localize("dialog.network.gateway")}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._interface![version].gateway}
|
.value=${this._interface![version].gateway}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@change=${this._handleInputValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>
|
</ha-textfield>
|
||||||
<paper-input
|
<ha-textfield
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="nameservers"
|
id="nameservers"
|
||||||
.label=${this.supervisor.localize("dialog.network.dns_servers")}
|
.label=${this.supervisor.localize("dialog.network.dns_servers")}
|
||||||
.version=${version}
|
.version=${version}
|
||||||
.value=${this._toString(this._interface![version].nameservers)}
|
.value=${this._toString(this._interface![version].nameservers)}
|
||||||
@value-changed=${this._handleInputValueChanged}
|
@change=${this._handleInputValueChanged}
|
||||||
>
|
>
|
||||||
</paper-input>
|
</ha-textfield>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</ha-expansion-panel>
|
</ha-expansion-panel>
|
||||||
@ -517,11 +517,11 @@ export class DialogHassioNetwork
|
|||||||
this.requestUpdate("_wifiConfiguration");
|
this.requestUpdate("_wifiConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleInputValueChanged(ev: CustomEvent): void {
|
private _handleInputValueChanged(ev: Event): void {
|
||||||
const value: string | null | undefined = (ev.target as PaperInputElement)
|
const source = ev.target as HaTextField;
|
||||||
.value;
|
const value = source.value;
|
||||||
const version = (ev.target as any).version as "ipv4" | "ipv6";
|
const version = (ev.target as any).version as "ipv4" | "ipv6";
|
||||||
const id = (ev.target as PaperInputElement).id;
|
const id = source.id;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!value ||
|
!value ||
|
||||||
@ -535,10 +535,10 @@ export class DialogHassioNetwork
|
|||||||
this._interface[version]![id] = value;
|
this._interface[version]![id] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleInputValueChangedWifi(ev: CustomEvent): void {
|
private _handleInputValueChangedWifi(ev: Event): void {
|
||||||
const value: string | null | undefined = (ev.target as PaperInputElement)
|
const source = ev.target as HaTextField;
|
||||||
.value;
|
const value = source.value;
|
||||||
const id = (ev.target as PaperInputElement).id;
|
const id = source.id;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!value ||
|
!value ||
|
||||||
@ -597,6 +597,8 @@ export class DialogHassioNetwork
|
|||||||
|
|
||||||
mwc-button.scan {
|
mwc-button.scan {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
margin-inline-start: 8px;
|
||||||
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
@ -630,7 +632,7 @@ export class DialogHassioNetwork
|
|||||||
--expansion-panel-summary-padding: 0 16px;
|
--expansion-panel-summary-padding: 0 16px;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
paper-input {
|
ha-textfield {
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
}
|
}
|
||||||
mwc-list-item {
|
mwc-list-item {
|
||||||
|
@ -157,11 +157,10 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
this.updateComplete.then(
|
this.updateComplete.then(() =>
|
||||||
() =>
|
(
|
||||||
(
|
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
|
||||||
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
|
)?.focus()
|
||||||
)?.focus()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +229,8 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
ha-icon-button {
|
ha-icon-button {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
margin-right: -10px;
|
margin-right: -10px;
|
||||||
|
margin-inline-end: -10px;
|
||||||
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import { mdiDelete, mdiDeleteOff } from "@mdi/js";
|
import { mdiDelete, mdiDeleteOff } from "@mdi/js";
|
||||||
import "@polymer/paper-input/paper-input";
|
|
||||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
||||||
@ -27,12 +25,14 @@ import {
|
|||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
||||||
|
import type { HaTextField } from "../../../../src/components/ha-textfield";
|
||||||
|
import "../../../../src/components/ha-textfield";
|
||||||
|
|
||||||
@customElement("dialog-hassio-repositories")
|
@customElement("dialog-hassio-repositories")
|
||||||
class HassioRepositoriesDialog extends LitElement {
|
class HassioRepositoriesDialog extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@query("#repository_input", true) private _optionInput?: PaperInputElement;
|
@query("#repository_input", true) private _optionInput?: HaTextField;
|
||||||
|
|
||||||
@state() private _repositories?: HassioAddonRepository[];
|
@state() private _repositories?: HassioAddonRepository[];
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
)
|
)
|
||||||
: html`<paper-item> No repositories </paper-item>`}
|
: html`<paper-item> No repositories </paper-item>`}
|
||||||
<div class="layout horizontal bottom">
|
<div class="layout horizontal bottom">
|
||||||
<paper-input
|
<ha-textfield
|
||||||
class="flex-auto"
|
class="flex-auto"
|
||||||
id="repository_input"
|
id="repository_input"
|
||||||
.value=${this._dialogParams!.url || ""}
|
.value=${this._dialogParams!.url || ""}
|
||||||
@ -154,7 +154,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
)}
|
)}
|
||||||
@keydown=${this._handleKeyAdd}
|
@keydown=${this._handleKeyAdd}
|
||||||
dialogInitialFocus
|
dialogInitialFocus
|
||||||
></paper-input>
|
></ha-textfield>
|
||||||
<mwc-button @click=${this._addRepository}>
|
<mwc-button @click=${this._addRepository}>
|
||||||
${this._processing
|
${this._processing
|
||||||
? html`<ha-circular-progress
|
? html`<ha-circular-progress
|
||||||
@ -195,6 +195,8 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
mwc-button {
|
mwc-button {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
margin-inline-start: 8px;
|
||||||
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
ha-circular-progress {
|
ha-circular-progress {
|
||||||
display: block;
|
display: block;
|
||||||
@ -209,11 +211,10 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public focus() {
|
public focus() {
|
||||||
this.updateComplete.then(
|
this.updateComplete.then(() =>
|
||||||
() =>
|
(
|
||||||
(
|
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
|
||||||
this.shadowRoot?.querySelector("[dialogInitialFocus]") as HTMLElement
|
)?.focus()
|
||||||
)?.focus()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ export class HassioMain extends SupervisorBaseElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues) {
|
protected firstUpdated(changedProps: PropertyValues) {
|
||||||
super.firstUpdated(changedProps);
|
super.firstUpdated(changedProps);
|
||||||
|
@ -16,7 +16,7 @@ class HassioPanelRouter extends HassRouterPage {
|
|||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
protected routerOptions: RouterOptions = {
|
protected routerOptions: RouterOptions = {
|
||||||
beforeRender: (page: string) =>
|
beforeRender: (page: string) =>
|
||||||
|
@ -14,7 +14,7 @@ class HassioPanel extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class HassioRouter extends HassRouterPage {
|
|||||||
|
|
||||||
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
@property({ attribute: false }) public panel!: HassioPanelInfo;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
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.
|
||||||
|
@ -360,7 +360,7 @@ class HassioIngressView extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-title {
|
.main-title {
|
||||||
margin: 0 0 0 24px;
|
margin: var(--margin-title);
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,14 @@ export const hassioStyle = css`
|
|||||||
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||||
line-height: var(--paper-font-headline_-_line-height);
|
line-height: var(--paper-font-headline_-_line-height);
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-inline-start: 8px;
|
||||||
|
padding-inline-end: initial;
|
||||||
}
|
}
|
||||||
.description {
|
.description {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-inline-start: 8px;
|
||||||
|
padding-inline-end: initial;
|
||||||
}
|
}
|
||||||
.card-group {
|
.card-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -29,6 +29,10 @@ import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
|
|||||||
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
|
import { urlSyncMixin } from "../../src/state/url-sync-mixin";
|
||||||
import { HomeAssistant, Route } from "../../src/types";
|
import { HomeAssistant, Route } from "../../src/types";
|
||||||
import { getTranslation } from "../../src/util/common-translation";
|
import { getTranslation } from "../../src/util/common-translation";
|
||||||
|
import {
|
||||||
|
computeRTLDirection,
|
||||||
|
setDirectionStyles,
|
||||||
|
} from "../../src/common/util/compute_rtl";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@ -95,6 +99,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
|
|
||||||
if (changedProperties.has("_language") || !this.hasUpdated) {
|
if (changedProperties.has("_language") || !this.hasUpdated) {
|
||||||
this._initializeLocalize();
|
this._initializeLocalize();
|
||||||
|
this._applyDirection(this.hass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,4 +220,9 @@ export class SupervisorBaseElement extends urlSyncMixin(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _applyDirection(hass: HomeAssistant) {
|
||||||
|
const direction = computeRTLDirection(hass);
|
||||||
|
setDirectionStyles(direction, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import "../../../src/components/ha-ansi-to-html";
|
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
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-ansi-to-html";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/components/ha-select";
|
import "../../../src/components/ha-select";
|
||||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||||
|
@ -18,7 +18,7 @@ class HassioSystem extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@ -73,6 +73,8 @@ class HassioSystem extends LitElement {
|
|||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
padding-inline-start: 8px;
|
||||||
|
padding-inline-end: initial;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
hassio-supervisor-log {
|
hassio-supervisor-log {
|
||||||
|
@ -94,7 +94,7 @@ class UpdateAvailableCard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public addonSlug?: string;
|
@property({ attribute: false }) public addonSlug?: string;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ class UpdateAvailableDashboard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@property({ attribute: false }) public route!: Route;
|
@property({ attribute: false }) public route!: Route;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ export default {
|
|||||||
"*.?(c|m){js,ts}": [
|
"*.?(c|m){js,ts}": [
|
||||||
"eslint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslintcache --fix",
|
"eslint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslintcache --fix",
|
||||||
"prettier --cache --write",
|
"prettier --cache --write",
|
||||||
|
"lit-analyzer --quiet",
|
||||||
],
|
],
|
||||||
"*.{json,css,md,markdown,html,y?aml}": "prettier --cache --write",
|
"*.{json,css,md,markdown,html,y?aml}": "prettier --cache --write",
|
||||||
"translations/*/*.json": (files) =>
|
"translations/*/*.json": (files) =>
|
||||||
|
92
package.json
92
package.json
@ -13,8 +13,8 @@
|
|||||||
"lint:prettier": "prettier . --cache --check",
|
"lint:prettier": "prettier . --cache --check",
|
||||||
"format:prettier": "prettier . --cache --write",
|
"format:prettier": "prettier . --cache --write",
|
||||||
"lint:types": "tsc",
|
"lint:types": "tsc",
|
||||||
"lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md",
|
"lint:lit": "lit-analyzer \"{.,*}/src/**/*.ts\"",
|
||||||
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types",
|
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types && yarn run lint:lit",
|
||||||
"format": "yarn run format:eslint && yarn run format:prettier",
|
"format": "yarn run format:eslint && yarn run format:prettier",
|
||||||
"postinstall": "husky install",
|
"postinstall": "husky install",
|
||||||
"prepack": "pinst --disable",
|
"prepack": "pinst --disable",
|
||||||
@ -25,24 +25,24 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "7.23.6",
|
"@babel/runtime": "7.23.9",
|
||||||
"@braintree/sanitize-url": "7.0.0",
|
"@braintree/sanitize-url": "7.0.0",
|
||||||
"@codemirror/autocomplete": "6.11.1",
|
"@codemirror/autocomplete": "6.12.0",
|
||||||
"@codemirror/commands": "6.3.2",
|
"@codemirror/commands": "6.3.3",
|
||||||
"@codemirror/language": "6.9.3",
|
"@codemirror/language": "6.10.0",
|
||||||
"@codemirror/legacy-modes": "6.3.3",
|
"@codemirror/legacy-modes": "6.3.3",
|
||||||
"@codemirror/search": "6.5.5",
|
"@codemirror/search": "6.5.5",
|
||||||
"@codemirror/state": "6.3.3",
|
"@codemirror/state": "6.4.0",
|
||||||
"@codemirror/view": "6.22.3",
|
"@codemirror/view": "6.23.1",
|
||||||
"@egjs/hammerjs": "2.0.17",
|
"@egjs/hammerjs": "2.0.17",
|
||||||
"@formatjs/intl-datetimeformat": "6.12.0",
|
"@formatjs/intl-datetimeformat": "6.12.2",
|
||||||
"@formatjs/intl-displaynames": "6.6.4",
|
"@formatjs/intl-displaynames": "6.6.6",
|
||||||
"@formatjs/intl-getcanonicallocales": "2.3.0",
|
"@formatjs/intl-getcanonicallocales": "2.3.0",
|
||||||
"@formatjs/intl-listformat": "7.5.3",
|
"@formatjs/intl-listformat": "7.5.5",
|
||||||
"@formatjs/intl-locale": "3.4.3",
|
"@formatjs/intl-locale": "3.4.5",
|
||||||
"@formatjs/intl-numberformat": "8.9.0",
|
"@formatjs/intl-numberformat": "8.10.0",
|
||||||
"@formatjs/intl-pluralrules": "5.2.10",
|
"@formatjs/intl-pluralrules": "5.2.12",
|
||||||
"@formatjs/intl-relativetimeformat": "11.2.10",
|
"@formatjs/intl-relativetimeformat": "11.2.12",
|
||||||
"@fullcalendar/core": "6.1.10",
|
"@fullcalendar/core": "6.1.10",
|
||||||
"@fullcalendar/daygrid": "6.1.10",
|
"@fullcalendar/daygrid": "6.1.10",
|
||||||
"@fullcalendar/interaction": "6.1.10",
|
"@fullcalendar/interaction": "6.1.10",
|
||||||
@ -53,8 +53,8 @@
|
|||||||
"@lit-labs/context": "0.4.1",
|
"@lit-labs/context": "0.4.1",
|
||||||
"@lit-labs/motion": "1.0.6",
|
"@lit-labs/motion": "1.0.6",
|
||||||
"@lit-labs/observers": "2.0.2",
|
"@lit-labs/observers": "2.0.2",
|
||||||
"@lit-labs/virtualizer": "2.0.11",
|
"@lit-labs/virtualizer": "2.0.12",
|
||||||
"@lrnwebcomponents/simple-tooltip": "7.0.18",
|
"@lrnwebcomponents/simple-tooltip": "8.0.0",
|
||||||
"@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-base": "0.27.0",
|
"@material/mwc-base": "0.27.0",
|
||||||
@ -80,18 +80,17 @@
|
|||||||
"@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.1.1",
|
"@material/web": "=1.2.0",
|
||||||
"@mdi/js": "7.4.47",
|
"@mdi/js": "7.4.47",
|
||||||
"@mdi/svg": "7.4.47",
|
"@mdi/svg": "7.4.47",
|
||||||
"@polymer/paper-input": "3.2.1",
|
|
||||||
"@polymer/paper-item": "3.0.1",
|
"@polymer/paper-item": "3.0.1",
|
||||||
"@polymer/paper-listbox": "3.0.1",
|
"@polymer/paper-listbox": "3.0.1",
|
||||||
"@polymer/paper-tabs": "3.1.0",
|
"@polymer/paper-tabs": "3.1.0",
|
||||||
"@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": "24.3.2",
|
"@vaadin/combo-box": "24.3.4",
|
||||||
"@vaadin/vaadin-themable-mixin": "24.3.2",
|
"@vaadin/vaadin-themable-mixin": "24.3.4",
|
||||||
"@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",
|
||||||
@ -101,7 +100,7 @@
|
|||||||
"app-datepicker": "5.1.1",
|
"app-datepicker": "5.1.1",
|
||||||
"chart.js": "4.4.1",
|
"chart.js": "4.4.1",
|
||||||
"comlink": "4.4.1",
|
"comlink": "4.4.1",
|
||||||
"core-js": "3.34.0",
|
"core-js": "3.35.1",
|
||||||
"cropperjs": "1.6.1",
|
"cropperjs": "1.6.1",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
"date-fns-tz": "2.0.0",
|
"date-fns-tz": "2.0.0",
|
||||||
@ -110,16 +109,16 @@
|
|||||||
"element-internals-polyfill": "1.3.10",
|
"element-internals-polyfill": "1.3.10",
|
||||||
"fuse.js": "7.0.0",
|
"fuse.js": "7.0.0",
|
||||||
"google-timezones-json": "1.2.0",
|
"google-timezones-json": "1.2.0",
|
||||||
"hls.js": "1.4.14",
|
"hls.js": "1.5.2",
|
||||||
"home-assistant-js-websocket": "9.1.0",
|
"home-assistant-js-websocket": "9.1.0",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.1",
|
||||||
"intl-messageformat": "10.5.8",
|
"intl-messageformat": "10.5.11",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"leaflet": "1.9.4",
|
"leaflet": "1.9.4",
|
||||||
"leaflet-draw": "1.0.4",
|
"leaflet-draw": "1.0.4",
|
||||||
"lit": "2.8.0",
|
"lit": "2.8.0",
|
||||||
"luxon": "3.4.4",
|
"luxon": "3.4.4",
|
||||||
"marked": "11.1.1",
|
"marked": "11.2.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",
|
||||||
@ -128,7 +127,7 @@
|
|||||||
"qrcode": "1.5.3",
|
"qrcode": "1.5.3",
|
||||||
"roboto-fontface": "0.10.0",
|
"roboto-fontface": "0.10.0",
|
||||||
"rrule": "2.8.1",
|
"rrule": "2.8.1",
|
||||||
"sortablejs": "1.15.1",
|
"sortablejs": "1.15.2",
|
||||||
"stacktrace-js": "2.0.2",
|
"stacktrace-js": "2.0.2",
|
||||||
"superstruct": "1.0.3",
|
"superstruct": "1.0.3",
|
||||||
"tinykeys": "2.1.0",
|
"tinykeys": "2.1.0",
|
||||||
@ -150,13 +149,13 @@
|
|||||||
"xss": "1.0.14"
|
"xss": "1.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.6",
|
"@babel/core": "7.23.9",
|
||||||
"@babel/helper-define-polyfill-provider": "0.4.4",
|
"@babel/helper-define-polyfill-provider": "0.5.0",
|
||||||
"@babel/plugin-proposal-decorators": "7.23.6",
|
"@babel/plugin-proposal-decorators": "7.23.9",
|
||||||
"@babel/plugin-transform-runtime": "7.23.6",
|
"@babel/plugin-transform-runtime": "7.23.9",
|
||||||
"@babel/preset-env": "7.23.6",
|
"@babel/preset-env": "7.23.9",
|
||||||
"@babel/preset-typescript": "7.23.3",
|
"@babel/preset-typescript": "7.23.3",
|
||||||
"@bundle-stats/plugin-webpack-filter": "4.8.3",
|
"@bundle-stats/plugin-webpack-filter": "4.9.2",
|
||||||
"@koa/cors": "5.0.0",
|
"@koa/cors": "5.0.0",
|
||||||
"@lokalise/node-api": "12.1.0",
|
"@lokalise/node-api": "12.1.0",
|
||||||
"@octokit/auth-oauth-device": "6.0.1",
|
"@octokit/auth-oauth-device": "6.0.1",
|
||||||
@ -169,28 +168,28 @@
|
|||||||
"@rollup/plugin-node-resolve": "15.2.3",
|
"@rollup/plugin-node-resolve": "15.2.3",
|
||||||
"@rollup/plugin-replace": "5.0.5",
|
"@rollup/plugin-replace": "5.0.5",
|
||||||
"@types/babel__plugin-transform-runtime": "7.9.5",
|
"@types/babel__plugin-transform-runtime": "7.9.5",
|
||||||
"@types/chromecast-caf-receiver": "6.0.12",
|
"@types/chromecast-caf-receiver": "6.0.13",
|
||||||
"@types/chromecast-caf-sender": "1.0.8",
|
"@types/chromecast-caf-sender": "1.0.8",
|
||||||
"@types/glob": "8.1.0",
|
"@types/glob": "8.1.0",
|
||||||
"@types/html-minifier-terser": "7.0.2",
|
"@types/html-minifier-terser": "7.0.2",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/leaflet": "1.9.8",
|
"@types/leaflet": "1.9.8",
|
||||||
"@types/leaflet-draw": "1.0.11",
|
"@types/leaflet-draw": "1.0.11",
|
||||||
"@types/luxon": "3.3.7",
|
"@types/luxon": "3.4.2",
|
||||||
"@types/mocha": "10.0.6",
|
"@types/mocha": "10.0.6",
|
||||||
"@types/qrcode": "1.5.5",
|
"@types/qrcode": "1.5.5",
|
||||||
"@types/serve-handler": "6.1.4",
|
"@types/serve-handler": "6.1.4",
|
||||||
"@types/sortablejs": "1.15.7",
|
"@types/sortablejs": "1.15.7",
|
||||||
"@types/tar": "6.1.10",
|
"@types/tar": "6.1.11",
|
||||||
"@types/ua-parser-js": "0.7.39",
|
"@types/ua-parser-js": "0.7.39",
|
||||||
"@types/webspeechapi": "0.0.29",
|
"@types/webspeechapi": "0.0.29",
|
||||||
"@typescript-eslint/eslint-plugin": "6.16.0",
|
"@typescript-eslint/eslint-plugin": "6.19.1",
|
||||||
"@typescript-eslint/parser": "6.16.0",
|
"@typescript-eslint/parser": "6.19.1",
|
||||||
"@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.3",
|
"babel-loader": "9.1.3",
|
||||||
"babel-plugin-template-html-minifier": "4.1.0",
|
"babel-plugin-template-html-minifier": "4.1.0",
|
||||||
"chai": "5.0.0",
|
"chai": "5.0.3",
|
||||||
"del": "7.1.0",
|
"del": "7.1.0",
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.56.0",
|
||||||
"eslint-config-airbnb-base": "15.0.0",
|
"eslint-config-airbnb-base": "15.0.0",
|
||||||
@ -213,19 +212,19 @@
|
|||||||
"gulp-rename": "2.0.0",
|
"gulp-rename": "2.0.0",
|
||||||
"gulp-zopfli-green": "6.0.1",
|
"gulp-zopfli-green": "6.0.1",
|
||||||
"html-minifier-terser": "7.2.0",
|
"html-minifier-terser": "7.2.0",
|
||||||
"husky": "8.0.3",
|
"husky": "9.0.6",
|
||||||
"instant-mocha": "1.5.2",
|
"instant-mocha": "1.5.2",
|
||||||
"jszip": "3.10.1",
|
"jszip": "3.10.1",
|
||||||
"lint-staged": "15.2.0",
|
"lint-staged": "15.2.0",
|
||||||
"lit-analyzer": "2.0.2",
|
"lit-analyzer": "2.0.3",
|
||||||
"lodash.template": "4.5.0",
|
"lodash.template": "4.5.0",
|
||||||
"magic-string": "0.30.5",
|
"magic-string": "0.30.5",
|
||||||
"map-stream": "0.0.7",
|
"map-stream": "0.0.7",
|
||||||
"mocha": "10.2.0",
|
"mocha": "10.2.0",
|
||||||
"object-hash": "3.0.0",
|
"object-hash": "3.0.0",
|
||||||
"open": "10.0.2",
|
"open": "10.0.3",
|
||||||
"pinst": "3.0.0",
|
"pinst": "3.0.0",
|
||||||
"prettier": "3.1.1",
|
"prettier": "3.2.4",
|
||||||
"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",
|
||||||
@ -233,14 +232,15 @@
|
|||||||
"serve-handler": "6.1.5",
|
"serve-handler": "6.1.5",
|
||||||
"sinon": "17.0.1",
|
"sinon": "17.0.1",
|
||||||
"source-map-url": "0.4.1",
|
"source-map-url": "0.4.1",
|
||||||
"systemjs": "6.14.2",
|
"systemjs": "6.14.3",
|
||||||
"tar": "6.2.0",
|
"tar": "6.2.0",
|
||||||
"terser-webpack-plugin": "5.3.10",
|
"terser-webpack-plugin": "5.3.10",
|
||||||
"ts-lit-plugin": "2.0.1",
|
"transform-async-modules-webpack-plugin": "1.0.2",
|
||||||
|
"ts-lit-plugin": "2.0.2",
|
||||||
"typescript": "5.3.3",
|
"typescript": "5.3.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.89.0",
|
"webpack": "5.90.0",
|
||||||
"webpack-cli": "5.1.4",
|
"webpack-cli": "5.1.4",
|
||||||
"webpack-dev-server": "4.15.1",
|
"webpack-dev-server": "4.15.1",
|
||||||
"webpack-manifest-plugin": "5.0.0",
|
"webpack-manifest-plugin": "5.0.0",
|
||||||
@ -255,7 +255,7 @@
|
|||||||
"lit": "2.8.0",
|
"lit": "2.8.0",
|
||||||
"clean-css": "5.3.3",
|
"clean-css": "5.3.3",
|
||||||
"@lit/reactive-element": "1.6.3",
|
"@lit/reactive-element": "1.6.3",
|
||||||
"sortablejs@1.15.0": "patch:sortablejs@npm%3A1.15.0#./.yarn/patches/sortablejs-npm-1.15.0-f3a393abcc.patch",
|
"sortablejs@1.15.2": "patch:sortablejs@npm%3A1.15.2#~/.yarn/patches/sortablejs-npm-1.15.2-73347ae85a.patch",
|
||||||
"leaflet-draw@1.0.4": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch"
|
"leaflet-draw@1.0.4": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.0.2"
|
"packageManager": "yarn@4.0.2"
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "home-assistant-frontend"
|
name = "home-assistant-frontend"
|
||||||
version = "20240104.0"
|
version = "20240131.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"
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const fs = require("fs");
|
/* eslint-disable no-console */
|
||||||
const util = require("util");
|
import fs from "fs";
|
||||||
const exec = util.promisify(require("child_process").exec);
|
import util from "util";
|
||||||
|
import child_process from "child_process";
|
||||||
|
|
||||||
|
const exec = util.promisify(child_process.exec);
|
||||||
|
|
||||||
function patch(version) {
|
function patch(version) {
|
||||||
const parts = version.split(".");
|
const parts = version.split(".");
|
||||||
@ -18,7 +21,7 @@ function today() {
|
|||||||
|
|
||||||
function auto(version) {
|
function auto(version) {
|
||||||
const todayVersion = today();
|
const todayVersion = today();
|
||||||
if (todayVersion !== version) {
|
if (todayVersion.split(".")[0] !== version.split(".")[0]) {
|
||||||
return todayVersion;
|
return todayVersion;
|
||||||
}
|
}
|
||||||
return patch(version);
|
return patch(version);
|
||||||
@ -44,7 +47,7 @@ async function main(args) {
|
|||||||
commit = true;
|
commit = true;
|
||||||
} else {
|
} else {
|
||||||
method = args.length > 0 && methods[args[0]];
|
method = args.length > 0 && methods[args[0]];
|
||||||
commit = args.length > 1 && args[1] == "--commit";
|
commit = args.length > 1 && args[1] === "--commit";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!method) {
|
if (!method) {
|
@ -21,7 +21,6 @@ import {
|
|||||||
DataEntryFlowStepForm,
|
DataEntryFlowStepForm,
|
||||||
} from "../data/data_entry_flow";
|
} from "../data/data_entry_flow";
|
||||||
import "./ha-auth-form";
|
import "./ha-auth-form";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
|
||||||
|
|
||||||
type State = "loading" | "error" | "step";
|
type State = "loading" | "error" | "step";
|
||||||
|
|
||||||
@ -35,11 +34,13 @@ export class HaAuthFlow extends LitElement {
|
|||||||
|
|
||||||
@property() public oauth2State?: string;
|
@property() public oauth2State?: string;
|
||||||
|
|
||||||
@property() public localize!: LocalizeFunc;
|
@property({ attribute: false }) public localize!: LocalizeFunc;
|
||||||
|
|
||||||
@property({ attribute: false }) public step?: DataEntryFlowStep;
|
@property({ attribute: false }) public step?: DataEntryFlowStep;
|
||||||
|
|
||||||
@property({ type: Boolean }) private storeToken = false;
|
@property({ type: Boolean }) public initStoreToken = false;
|
||||||
|
|
||||||
|
@state() private _storeToken = false;
|
||||||
|
|
||||||
@state() private _state: State = "loading";
|
@state() private _state: State = "loading";
|
||||||
|
|
||||||
@ -56,6 +57,10 @@ export class HaAuthFlow extends LitElement {
|
|||||||
willUpdate(changedProps: PropertyValues) {
|
willUpdate(changedProps: PropertyValues) {
|
||||||
super.willUpdate(changedProps);
|
super.willUpdate(changedProps);
|
||||||
|
|
||||||
|
if (!this.hasUpdated) {
|
||||||
|
this._storeToken = this.initStoreToken;
|
||||||
|
}
|
||||||
|
|
||||||
if (!changedProps.has("step")) {
|
if (!changedProps.has("step")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -88,6 +93,8 @@ export class HaAuthFlow extends LitElement {
|
|||||||
<style>
|
<style>
|
||||||
ha-auth-flow .store-token {
|
ha-auth-flow .store-token {
|
||||||
margin-left: -16px;
|
margin-left: -16px;
|
||||||
|
margin-inline-start: -16px;
|
||||||
|
margin-inline-end: initial;
|
||||||
}
|
}
|
||||||
a.forgot-password {
|
a.forgot-password {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
@ -155,11 +162,6 @@ export class HaAuthFlow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderForm() {
|
private _renderForm() {
|
||||||
const showBack =
|
|
||||||
this.step?.type === "form" &&
|
|
||||||
this.authProvider?.users &&
|
|
||||||
!["select_mfa_module", "mfa"].includes(this.step.step_id);
|
|
||||||
|
|
||||||
switch (this._state) {
|
switch (this._state) {
|
||||||
case "step":
|
case "step":
|
||||||
if (this.step == null) {
|
if (this.step == null) {
|
||||||
@ -168,12 +170,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
|
|
||||||
return html`
|
return html`
|
||||||
${this._renderStep(this.step)}
|
${this._renderStep(this.step)}
|
||||||
<div class="action ${showBack ? "space-between" : ""}">
|
<div class="action">
|
||||||
${showBack
|
|
||||||
? html`<mwc-button @click=${this._localFlow}>
|
|
||||||
${this.localize("ui.panel.page-authorize.form.previous")}
|
|
||||||
</mwc-button>`
|
|
||||||
: nothing}
|
|
||||||
<mwc-button
|
<mwc-button
|
||||||
raised
|
raised
|
||||||
@click=${this._handleSubmit}
|
@click=${this._handleSubmit}
|
||||||
@ -227,7 +224,8 @@ export class HaAuthFlow extends LitElement {
|
|||||||
</h1>
|
</h1>
|
||||||
${this._computeStepDescription(step)}
|
${this._computeStepDescription(step)}
|
||||||
<ha-auth-form
|
<ha-auth-form
|
||||||
.data=${this._stepData}
|
.localize=${this.localize}
|
||||||
|
.data=${this._stepData!}
|
||||||
.schema=${autocompleteLoginFields(step.data_schema)}
|
.schema=${autocompleteLoginFields(step.data_schema)}
|
||||||
.error=${step.errors}
|
.error=${step.errors}
|
||||||
.disabled=${this._submitting}
|
.disabled=${this._submitting}
|
||||||
@ -246,7 +244,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ha-checkbox
|
<ha-checkbox
|
||||||
.checked=${this.storeToken}
|
.checked=${this._storeToken}
|
||||||
@change=${this._storeTokenChanged}
|
@change=${this._storeTokenChanged}
|
||||||
></ha-checkbox>
|
></ha-checkbox>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
@ -269,7 +267,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _storeTokenChanged(e: CustomEvent<HTMLInputElement>) {
|
private _storeTokenChanged(e: CustomEvent<HTMLInputElement>) {
|
||||||
this.storeToken = (e.currentTarget as HTMLInputElement).checked;
|
this._storeToken = (e.currentTarget as HTMLInputElement).checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _providerChanged(newProvider?: AuthProvider) {
|
private async _providerChanged(newProvider?: AuthProvider) {
|
||||||
@ -303,7 +301,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
this.redirectUri!,
|
this.redirectUri!,
|
||||||
data.result,
|
data.result,
|
||||||
this.oauth2State,
|
this.oauth2State,
|
||||||
this.storeToken
|
this._storeToken
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -385,7 +383,7 @@ export class HaAuthFlow extends LitElement {
|
|||||||
this.redirectUri!,
|
this.redirectUri!,
|
||||||
newStep.result,
|
newStep.result,
|
||||||
this.oauth2State,
|
this.oauth2State,
|
||||||
this.storeToken
|
this._storeToken
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -400,10 +398,6 @@ export class HaAuthFlow extends LitElement {
|
|||||||
this._submitting = false;
|
this._submitting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _localFlow() {
|
|
||||||
fireEvent(this, "default-login-flow", { value: false });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -59,7 +59,7 @@ export class HaAuthFormString extends HaFormString {
|
|||||||
html`<div style="width: 24px"></div>`
|
html`<div style="width: 24px"></div>`
|
||||||
: this.schema.description?.suffix
|
: this.schema.description?.suffix
|
||||||
}
|
}
|
||||||
.validationMessage=${this.schema.required ? "Required" : undefined}
|
.validationMessage=${this.schema.required ? this.localize?.("ui.panel.page-authorize.form.error_required") : undefined}
|
||||||
@input=${this._valueChanged}
|
@input=${this._valueChanged}
|
||||||
@change=${this._valueChanged}
|
@change=${this._valueChanged}
|
||||||
></ha-auth-textfield>
|
></ha-auth-textfield>
|
||||||
|
@ -1,11 +1,23 @@
|
|||||||
/* eslint-disable lit/prefer-static-styles */
|
/* eslint-disable lit/prefer-static-styles */
|
||||||
import { html } from "lit";
|
import { html } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { HaForm } from "../components/ha-form/ha-form";
|
import { HaForm } from "../components/ha-form/ha-form";
|
||||||
import "./ha-auth-form-string";
|
import "./ha-auth-form-string";
|
||||||
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
|
|
||||||
|
const localizeBaseKey = "ui.panel.page-authorize.form";
|
||||||
|
|
||||||
@customElement("ha-auth-form")
|
@customElement("ha-auth-form")
|
||||||
export class HaAuthForm extends HaForm {
|
export class HaAuthForm extends HaForm {
|
||||||
|
@property({ attribute: false }) public localize?: LocalizeFunc;
|
||||||
|
|
||||||
|
protected getFormProperties(): Record<string, any> {
|
||||||
|
return {
|
||||||
|
localize: this.localize,
|
||||||
|
localizeBaseKey,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected fieldElementName(type: string): string {
|
protected fieldElementName(type: string): string {
|
||||||
if (type === "string") {
|
if (type === "string") {
|
||||||
return `ha-auth-form-${type}`;
|
return `ha-auth-form-${type}`;
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
import { registerServiceWorker } from "../util/register-service-worker";
|
import { registerServiceWorker } from "../util/register-service-worker";
|
||||||
import "./ha-auth-flow";
|
import "./ha-auth-flow";
|
||||||
import "./ha-local-auth-flow";
|
|
||||||
|
|
||||||
import("./ha-pick-auth-provider");
|
import("./ha-pick-auth-provider");
|
||||||
|
|
||||||
@ -36,12 +35,12 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
|
|
||||||
@state() private _authProviders?: AuthProvider[];
|
@state() private _authProviders?: AuthProvider[];
|
||||||
|
|
||||||
|
@state() private _preselectStoreToken = false;
|
||||||
|
|
||||||
@state() private _ownInstance = false;
|
@state() private _ownInstance = false;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
@state() private _forceDefaultLogin = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
const query = extractSearchParamsObject() as AuthUrlSearchParams;
|
const query = extractSearchParamsObject() as AuthUrlSearchParams;
|
||||||
@ -84,8 +83,7 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
display: block;
|
display: block;
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
ha-auth-flow,
|
ha-auth-flow {
|
||||||
ha-local-auth-flow {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -151,6 +149,8 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
margin-inline-end: 16px;
|
||||||
|
margin-inline-start: initial;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
@ -176,44 +176,29 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
</ha-alert>`
|
</ha-alert>`
|
||||||
: nothing}
|
: nothing}
|
||||||
|
|
||||||
<div
|
<div class="card-content">
|
||||||
class="card-content"
|
|
||||||
@default-login-flow=${this._handleDefaultLoginFlow}
|
|
||||||
>
|
|
||||||
${!this._authProvider
|
${!this._authProvider
|
||||||
? html`<p>
|
? html`<p>
|
||||||
${this.localize("ui.panel.page-authorize.initializing")}
|
${this.localize("ui.panel.page-authorize.initializing")}
|
||||||
</p> `
|
</p> `
|
||||||
: !this._forceDefaultLogin &&
|
: html`<ha-auth-flow
|
||||||
this._authProvider!.users &&
|
|
||||||
this.clientId != null &&
|
|
||||||
this.redirectUri != null
|
|
||||||
? html`<ha-local-auth-flow
|
|
||||||
.clientId=${this.clientId}
|
.clientId=${this.clientId}
|
||||||
.redirectUri=${this.redirectUri}
|
.redirectUri=${this.redirectUri}
|
||||||
.oauth2State=${this.oauth2State}
|
.oauth2State=${this.oauth2State}
|
||||||
.authProvider=${this._authProvider}
|
.authProvider=${this._authProvider}
|
||||||
.authProviders=${this._authProviders}
|
|
||||||
.localize=${this.localize}
|
.localize=${this.localize}
|
||||||
.ownInstance=${this._ownInstance}
|
.initStoreToken=${this._preselectStoreToken}
|
||||||
></ha-local-auth-flow>`
|
></ha-auth-flow>
|
||||||
: html`<ha-auth-flow
|
${inactiveProviders!.length > 0
|
||||||
.clientId=${this.clientId}
|
? html`
|
||||||
.redirectUri=${this.redirectUri}
|
<ha-pick-auth-provider
|
||||||
.oauth2State=${this.oauth2State}
|
.localize=${this.localize}
|
||||||
.authProvider=${this._authProvider}
|
.clientId=${this.clientId}
|
||||||
.localize=${this.localize}
|
.authProviders=${inactiveProviders!}
|
||||||
></ha-auth-flow>
|
@pick-auth-provider=${this._handleAuthProviderPick}
|
||||||
${inactiveProviders!.length > 0
|
></ha-pick-auth-provider>
|
||||||
? html`
|
`
|
||||||
<ha-pick-auth-provider
|
: ""}`}
|
||||||
.localize=${this.localize}
|
|
||||||
.clientId=${this.clientId}
|
|
||||||
.authProviders=${inactiveProviders}
|
|
||||||
@pick-auth-provider=${this._handleAuthProviderPick}
|
|
||||||
></ha-pick-auth-provider>
|
|
||||||
`
|
|
||||||
: ""}`}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<ha-language-picker
|
<ha-language-picker
|
||||||
@ -319,13 +304,14 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authProviders.length === 0) {
|
if (authProviders.providers.length === 0) {
|
||||||
this._error = "No auth providers returned. Unable to finish login.";
|
this._error = "No auth providers returned. Unable to finish login.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._authProviders = authProviders;
|
this._authProviders = authProviders.providers;
|
||||||
this._authProvider = authProviders[0];
|
this._authProvider = authProviders.providers[0];
|
||||||
|
this._preselectStoreToken = authProviders.preselect_remember_me;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this._error = "Unable to fetch auth providers.";
|
this._error = "Unable to fetch auth providers.";
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
@ -333,10 +319,6 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleDefaultLoginFlow(ev) {
|
|
||||||
this._forceDefaultLogin = ev.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _handleAuthProviderPick(ev) {
|
private async _handleAuthProviderPick(ev) {
|
||||||
this._authProvider = ev.detail;
|
this._authProvider = ev.detail;
|
||||||
}
|
}
|
||||||
@ -352,3 +334,9 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-authorize": HaAuthorize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,485 +0,0 @@
|
|||||||
/* eslint-disable lit/prefer-static-styles */
|
|
||||||
import "@material/mwc-button";
|
|
||||||
import { mdiEye, mdiEyeOff } from "@mdi/js";
|
|
||||||
import { html, LitElement, nothing, PropertyValues } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
|
||||||
import { LocalizeFunc } from "../common/translations/localize";
|
|
||||||
import "../components/ha-alert";
|
|
||||||
import "../components/ha-button";
|
|
||||||
import "../components/ha-icon-button";
|
|
||||||
import "../components/user/ha-person-badge";
|
|
||||||
import {
|
|
||||||
AuthProvider,
|
|
||||||
createLoginFlow,
|
|
||||||
deleteLoginFlow,
|
|
||||||
redirectWithAuthCode,
|
|
||||||
submitLoginFlow,
|
|
||||||
} from "../data/auth";
|
|
||||||
import { DataEntryFlowStep } from "../data/data_entry_flow";
|
|
||||||
import { BasePerson, listUserPersons } from "../data/person";
|
|
||||||
import "./ha-auth-textfield";
|
|
||||||
import type { HaAuthTextField } from "./ha-auth-textfield";
|
|
||||||
|
|
||||||
@customElement("ha-local-auth-flow")
|
|
||||||
export class HaLocalAuthFlow extends LitElement {
|
|
||||||
@property({ attribute: false }) public authProvider?: AuthProvider;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public authProviders?: AuthProvider[];
|
|
||||||
|
|
||||||
@property() public clientId?: string;
|
|
||||||
|
|
||||||
@property() public redirectUri?: string;
|
|
||||||
|
|
||||||
@property() public oauth2State?: string;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public ownInstance = false;
|
|
||||||
|
|
||||||
@property() public localize!: LocalizeFunc;
|
|
||||||
|
|
||||||
@state() private _error?: string;
|
|
||||||
|
|
||||||
@state() private _step?: DataEntryFlowStep;
|
|
||||||
|
|
||||||
@state() private _submitting = false;
|
|
||||||
|
|
||||||
@state() private _persons?: Record<string, BasePerson>;
|
|
||||||
|
|
||||||
@state() private _selectedUser?: string;
|
|
||||||
|
|
||||||
@state() private _unmaskedPassword = false;
|
|
||||||
|
|
||||||
createRenderRoot() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
willUpdate(changedProps: PropertyValues) {
|
|
||||||
super.willUpdate(changedProps);
|
|
||||||
|
|
||||||
if (!this.hasUpdated) {
|
|
||||||
this._load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
if (!this.authProvider?.users || !this._persons) {
|
|
||||||
return nothing;
|
|
||||||
}
|
|
||||||
const userIds = Object.keys(this.authProvider.users).filter(
|
|
||||||
(userId) => userId in this._persons!
|
|
||||||
);
|
|
||||||
return html`
|
|
||||||
<style>
|
|
||||||
.content {
|
|
||||||
max-width: 560px;
|
|
||||||
}
|
|
||||||
.persons {
|
|
||||||
margin-top: 24px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 16px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.persons.force-small {
|
|
||||||
max-width: 350px;
|
|
||||||
}
|
|
||||||
.person {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
.person[role="button"] {
|
|
||||||
outline: none;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.person[role="button"]:focus-visible {
|
|
||||||
background: rgba(var(--rgb-primary-color), 0.1);
|
|
||||||
}
|
|
||||||
.person p {
|
|
||||||
margin-bottom: 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
ha-person-badge {
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
--person-badge-font-size: 2em;
|
|
||||||
}
|
|
||||||
form {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
ha-auth-textfield {
|
|
||||||
display: block !important;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
ha-auth-textfield ha-icon-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 4px;
|
|
||||||
right: 4px;
|
|
||||||
z-index: 9;
|
|
||||||
}
|
|
||||||
.login-form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 336px;
|
|
||||||
margin-top: 24px;
|
|
||||||
}
|
|
||||||
.login-form .person {
|
|
||||||
cursor: default;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
.login-form .person p {
|
|
||||||
font-size: 28px;
|
|
||||||
margin-top: 24px;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
.login-form ha-person-badge {
|
|
||||||
width: 120px;
|
|
||||||
height: 120px;
|
|
||||||
--person-badge-font-size: 3em;
|
|
||||||
}
|
|
||||||
ha-list-item {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
ha-button {
|
|
||||||
--mdc-typography-button-text-transform: none;
|
|
||||||
}
|
|
||||||
.forgot-password-container {
|
|
||||||
text-align: right;
|
|
||||||
padding: 8px 0 16px 0;
|
|
||||||
}
|
|
||||||
a.forgot-password {
|
|
||||||
color: var(--primary-color);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
color: var(--primary-color);
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
padding: 8px;
|
|
||||||
font: inherit;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
text-align: left;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
button:focus-visible {
|
|
||||||
background: rgba(var(--rgb-primary-color), 0.1);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
${this._error
|
|
||||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
|
||||||
: nothing}
|
|
||||||
${this._step
|
|
||||||
? html`<ha-auth-flow
|
|
||||||
.clientId=${this.clientId}
|
|
||||||
.redirectUri=${this.redirectUri}
|
|
||||||
.oauth2State=${this.oauth2State}
|
|
||||||
.step=${this._step}
|
|
||||||
storeToken
|
|
||||||
.localize=${this.localize}
|
|
||||||
></ha-auth-flow>`
|
|
||||||
: this._selectedUser
|
|
||||||
? html`<div class="login-form">
|
|
||||||
<div class="person">
|
|
||||||
<ha-person-badge
|
|
||||||
.person=${this._persons[this._selectedUser]}
|
|
||||||
></ha-person-badge>
|
|
||||||
<p>${this._persons[this._selectedUser].name}</p>
|
|
||||||
</div>
|
|
||||||
<form>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="username"
|
|
||||||
autocomplete="username"
|
|
||||||
readonly
|
|
||||||
.value=${this.authProvider.users[this._selectedUser]}
|
|
||||||
/>
|
|
||||||
<ha-auth-textfield
|
|
||||||
.type=${this._unmaskedPassword ? "text" : "password"}
|
|
||||||
autocomplete="current-password"
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
.label=${this.localize(
|
|
||||||
"ui.panel.page-authorize.form.providers.homeassistant.step.init.data.password"
|
|
||||||
)}
|
|
||||||
required
|
|
||||||
autoValidate
|
|
||||||
iconTrailing
|
|
||||||
validationMessage="Required"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
|
||||||
toggles
|
|
||||||
.label=${this.localize(
|
|
||||||
this._unmaskedPassword
|
|
||||||
? "ui.panel.page-authorize.form.hide_password"
|
|
||||||
: "ui.panel.page-authorize.form.show_password"
|
|
||||||
) ||
|
|
||||||
(this._unmaskedPassword
|
|
||||||
? "Hide password"
|
|
||||||
: "Show password")}
|
|
||||||
@click=${this._toggleUnmaskedPassword}
|
|
||||||
.path=${this._unmaskedPassword ? mdiEyeOff : mdiEye}
|
|
||||||
></ha-icon-button>
|
|
||||||
</ha-auth-textfield>
|
|
||||||
<div class="forgot-password-container">
|
|
||||||
<a
|
|
||||||
class="forgot-password"
|
|
||||||
href="https://www.home-assistant.io/docs/locked_out/#forgot-password"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>${this.localize(
|
|
||||||
"ui.panel.page-authorize.forgot_password"
|
|
||||||
)}</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="action space-between">
|
|
||||||
<mwc-button
|
|
||||||
@click=${this._restart}
|
|
||||||
.disabled=${this._submitting}
|
|
||||||
>
|
|
||||||
${this.localize("ui.panel.page-authorize.form.previous")}
|
|
||||||
</mwc-button>
|
|
||||||
<mwc-button
|
|
||||||
raised
|
|
||||||
@click=${this._handleSubmit}
|
|
||||||
.disabled=${this._submitting}
|
|
||||||
>
|
|
||||||
${this.localize("ui.panel.page-authorize.form.next")}
|
|
||||||
</mwc-button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>`
|
|
||||||
: html`<h1>
|
|
||||||
${this.localize("ui.panel.page-authorize.welcome_home")}
|
|
||||||
</h1>
|
|
||||||
${this.localize("ui.panel.page-authorize.who_is_logging_in")}
|
|
||||||
<div
|
|
||||||
class="persons ${userIds.length < 10 && userIds.length % 4 === 1
|
|
||||||
? "force-small"
|
|
||||||
: ""}"
|
|
||||||
>
|
|
||||||
${userIds.map((userId) => {
|
|
||||||
const person = this._persons![userId];
|
|
||||||
|
|
||||||
return html`<div
|
|
||||||
class="person"
|
|
||||||
.userId=${userId}
|
|
||||||
@click=${this._personSelected}
|
|
||||||
@keyup=${this._handleKeyUp}
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<ha-person-badge .person=${person}></ha-person-badge>
|
|
||||||
<p>${person.name}</p>
|
|
||||||
</div>`;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div class="action">
|
|
||||||
<button @click=${this._otherLogin} tabindex="0">
|
|
||||||
${this.localize("ui.panel.page-authorize.other_options")}
|
|
||||||
</button>
|
|
||||||
</div>`}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
|
|
||||||
this.addEventListener("keypress", (ev) => {
|
|
||||||
if (ev.key === "Enter") {
|
|
||||||
this._handleSubmit(ev);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
|
||||||
if (changedProps.has("_selectedUser") && this._selectedUser) {
|
|
||||||
const passwordElement = this.renderRoot.querySelector(
|
|
||||||
"#password"
|
|
||||||
) as HaAuthTextField;
|
|
||||||
passwordElement.updateComplete.then(() => {
|
|
||||||
passwordElement.focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _load() {
|
|
||||||
try {
|
|
||||||
this._persons = await listUserPersons();
|
|
||||||
} catch {
|
|
||||||
this._persons = {};
|
|
||||||
this._error = "Failed to fetch persons";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _restart() {
|
|
||||||
this._selectedUser = undefined;
|
|
||||||
this._error = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _toggleUnmaskedPassword() {
|
|
||||||
this._unmaskedPassword = !this._unmaskedPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _handleKeyUp(ev: KeyboardEvent) {
|
|
||||||
if (ev.key === "Enter" || ev.key === " ") {
|
|
||||||
this._personSelected(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _personSelected(ev) {
|
|
||||||
const userId = ev.currentTarget.userId;
|
|
||||||
if (
|
|
||||||
this.ownInstance &&
|
|
||||||
this.authProviders?.find((prv) => prv.type === "trusted_networks")
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const flowResponse = await createLoginFlow(
|
|
||||||
this.clientId,
|
|
||||||
this.redirectUri,
|
|
||||||
["trusted_networks", null]
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = await flowResponse.json();
|
|
||||||
|
|
||||||
if (data.type === "create_entry") {
|
|
||||||
redirectWithAuthCode(
|
|
||||||
this.redirectUri!,
|
|
||||||
data.result,
|
|
||||||
this.oauth2State,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!data.data_schema[0].options.find((opt) => opt[0] === userId)) {
|
|
||||||
throw new Error("User not available");
|
|
||||||
}
|
|
||||||
|
|
||||||
const postData = { user: userId, client_id: this.clientId };
|
|
||||||
|
|
||||||
const response = await submitLoginFlow(data.flow_id, postData);
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.type === "create_entry") {
|
|
||||||
redirectWithAuthCode(
|
|
||||||
this.redirectUri!,
|
|
||||||
result.result,
|
|
||||||
this.oauth2State,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid response");
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
deleteLoginFlow(data.flow_id).catch((err) => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error("Error delete obsoleted auth flow", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._selectedUser = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _handleSubmit(ev: Event) {
|
|
||||||
ev.preventDefault();
|
|
||||||
|
|
||||||
if (!this.authProvider?.users || !this._selectedUser) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._error = undefined;
|
|
||||||
this._submitting = true;
|
|
||||||
|
|
||||||
const flowResponse = await createLoginFlow(
|
|
||||||
this.clientId,
|
|
||||||
this.redirectUri,
|
|
||||||
["homeassistant", null]
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = await flowResponse.json();
|
|
||||||
|
|
||||||
const postData = {
|
|
||||||
username: this.authProvider.users[this._selectedUser],
|
|
||||||
password: (this.renderRoot.querySelector("#password") as HaAuthTextField)
|
|
||||||
.value,
|
|
||||||
client_id: this.clientId,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await submitLoginFlow(data.flow_id, postData);
|
|
||||||
|
|
||||||
const newStep = await response.json();
|
|
||||||
|
|
||||||
if (response.status === 403) {
|
|
||||||
this._error = newStep.message;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newStep.type === "create_entry") {
|
|
||||||
redirectWithAuthCode(
|
|
||||||
this.redirectUri!,
|
|
||||||
newStep.result,
|
|
||||||
this.oauth2State,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newStep.errors.base) {
|
|
||||||
this._error = this.localize(
|
|
||||||
`ui.panel.page-authorize.form.providers.homeassistant.error.${newStep.errors.base}`
|
|
||||||
);
|
|
||||||
throw new Error(this._error);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._step = newStep;
|
|
||||||
} catch {
|
|
||||||
deleteLoginFlow(data.flow_id).catch((err) => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error("Error delete obsoleted auth flow", err);
|
|
||||||
});
|
|
||||||
if (!this._error) {
|
|
||||||
this._error = this.localize(
|
|
||||||
"ui.panel.page-authorize.form.unknown_error"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this._submitting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _otherLogin() {
|
|
||||||
fireEvent(this, "default-login-flow", { value: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-local-auth-flow": HaLocalAuthFlow;
|
|
||||||
}
|
|
||||||
interface HASSDomEvents {
|
|
||||||
"default-login-flow": { value: boolean };
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,9 @@ import "../components/ha-list-item";
|
|||||||
import { AuthProvider } from "../data/auth";
|
import { AuthProvider } from "../data/auth";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-pick-auth-provider": HaPickAuthProvider;
|
||||||
|
}
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"pick-auth-provider": AuthProvider;
|
"pick-auth-provider": AuthProvider;
|
||||||
}
|
}
|
||||||
@ -15,9 +18,9 @@ declare global {
|
|||||||
|
|
||||||
@customElement("ha-pick-auth-provider")
|
@customElement("ha-pick-auth-provider")
|
||||||
export class HaPickAuthProvider extends LitElement {
|
export class HaPickAuthProvider extends LitElement {
|
||||||
@property() public authProviders: AuthProvider[] = [];
|
@property({ attribute: false }) public authProviders: AuthProvider[] = [];
|
||||||
|
|
||||||
@property() public localize!: LocalizeFunc;
|
@property({ attribute: false }) public localize!: LocalizeFunc;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/** Constants to be used in the frontend. */
|
/** Constants to be used in the frontend. */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
mdiAccount,
|
||||||
mdiAirFilter,
|
mdiAirFilter,
|
||||||
mdiAlert,
|
mdiAlert,
|
||||||
mdiAngleAcute,
|
mdiAngleAcute,
|
||||||
@ -18,7 +19,6 @@ import {
|
|||||||
mdiChatSleep,
|
mdiChatSleep,
|
||||||
mdiClipboardList,
|
mdiClipboardList,
|
||||||
mdiClock,
|
mdiClock,
|
||||||
mdiCloudUpload,
|
|
||||||
mdiCog,
|
mdiCog,
|
||||||
mdiCommentAlert,
|
mdiCommentAlert,
|
||||||
mdiCounter,
|
mdiCounter,
|
||||||
@ -48,11 +48,14 @@ import {
|
|||||||
mdiMoleculeCo2,
|
mdiMoleculeCo2,
|
||||||
mdiPalette,
|
mdiPalette,
|
||||||
mdiPh,
|
mdiPh,
|
||||||
|
mdiPipe,
|
||||||
mdiProgressClock,
|
mdiProgressClock,
|
||||||
mdiRayVertex,
|
mdiRayVertex,
|
||||||
mdiRemote,
|
mdiRemote,
|
||||||
|
mdiRobot,
|
||||||
mdiRobotMower,
|
mdiRobotMower,
|
||||||
mdiRobotVacuum,
|
mdiRobotVacuum,
|
||||||
|
mdiRoomService,
|
||||||
mdiScriptText,
|
mdiScriptText,
|
||||||
mdiSineWave,
|
mdiSineWave,
|
||||||
mdiSpeakerMessage,
|
mdiSpeakerMessage,
|
||||||
@ -62,6 +65,7 @@ import {
|
|||||||
mdiThermometerLines,
|
mdiThermometerLines,
|
||||||
mdiThermostat,
|
mdiThermostat,
|
||||||
mdiTimerOutline,
|
mdiTimerOutline,
|
||||||
|
mdiToggleSwitch,
|
||||||
mdiTransmissionTower,
|
mdiTransmissionTower,
|
||||||
mdiWater,
|
mdiWater,
|
||||||
mdiWaterPercent,
|
mdiWaterPercent,
|
||||||
@ -70,6 +74,7 @@ import {
|
|||||||
mdiWeatherRainy,
|
mdiWeatherRainy,
|
||||||
mdiWeatherWindy,
|
mdiWeatherWindy,
|
||||||
mdiWeight,
|
mdiWeight,
|
||||||
|
mdiWhiteBalanceSunny,
|
||||||
mdiWifi,
|
mdiWifi,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
|
|
||||||
@ -79,6 +84,9 @@ import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg";
|
|||||||
// Arrays with values should be alphabetically sorted if order doesn't matter.
|
// Arrays with values should be alphabetically sorted if order doesn't matter.
|
||||||
// Each constant should have a description what it is supposed to be used for.
|
// Each constant should have a description what it is supposed to be used for.
|
||||||
|
|
||||||
|
/** Icon to use when no icon specified for service. */
|
||||||
|
export const DEFAULT_SERVICE_ICON = mdiRoomService;
|
||||||
|
|
||||||
/** Icon to use when no icon specified for domain. */
|
/** Icon to use when no icon specified for domain. */
|
||||||
export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
||||||
|
|
||||||
@ -86,20 +94,23 @@ export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
|||||||
export const FIXED_DOMAIN_ICONS = {
|
export const FIXED_DOMAIN_ICONS = {
|
||||||
air_quality: mdiAirFilter,
|
air_quality: mdiAirFilter,
|
||||||
alert: mdiAlert,
|
alert: mdiAlert,
|
||||||
|
automation: mdiRobot,
|
||||||
calendar: mdiCalendar,
|
calendar: mdiCalendar,
|
||||||
climate: mdiThermostat,
|
climate: mdiThermostat,
|
||||||
configurator: mdiCog,
|
configurator: mdiCog,
|
||||||
conversation: mdiMicrophoneMessage,
|
conversation: mdiMicrophoneMessage,
|
||||||
counter: mdiCounter,
|
counter: mdiCounter,
|
||||||
datetime: mdiCalendarClock,
|
|
||||||
date: mdiCalendar,
|
date: mdiCalendar,
|
||||||
|
datetime: mdiCalendarClock,
|
||||||
demo: mdiHomeAssistant,
|
demo: mdiHomeAssistant,
|
||||||
|
device_tracker: mdiAccount,
|
||||||
google_assistant: mdiGoogleAssistant,
|
google_assistant: mdiGoogleAssistant,
|
||||||
group: mdiGoogleCirclesCommunities,
|
group: mdiGoogleCirclesCommunities,
|
||||||
homeassistant: mdiHomeAssistant,
|
homeassistant: mdiHomeAssistant,
|
||||||
homekit: mdiHomeAutomation,
|
homekit: mdiHomeAutomation,
|
||||||
image: mdiImage,
|
|
||||||
image_processing: mdiImageFilterFrames,
|
image_processing: mdiImageFilterFrames,
|
||||||
|
image: mdiImage,
|
||||||
|
input_boolean: mdiToggleSwitch,
|
||||||
input_button: mdiButtonPointer,
|
input_button: mdiButtonPointer,
|
||||||
input_datetime: mdiCalendarClock,
|
input_datetime: mdiCalendarClock,
|
||||||
input_number: mdiRayVertex,
|
input_number: mdiRayVertex,
|
||||||
@ -111,6 +122,7 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
notify: mdiCommentAlert,
|
notify: mdiCommentAlert,
|
||||||
number: mdiRayVertex,
|
number: mdiRayVertex,
|
||||||
persistent_notification: mdiBell,
|
persistent_notification: mdiBell,
|
||||||
|
person: mdiAccount,
|
||||||
plant: mdiFlower,
|
plant: mdiFlower,
|
||||||
proximity: mdiAppleSafari,
|
proximity: mdiAppleSafari,
|
||||||
remote: mdiRemote,
|
remote: mdiRemote,
|
||||||
@ -122,12 +134,12 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
simple_alarm: mdiBell,
|
simple_alarm: mdiBell,
|
||||||
siren: mdiBullhorn,
|
siren: mdiBullhorn,
|
||||||
stt: mdiMicrophoneMessage,
|
stt: mdiMicrophoneMessage,
|
||||||
|
sun: mdiWhiteBalanceSunny,
|
||||||
text: mdiFormTextbox,
|
text: mdiFormTextbox,
|
||||||
todo: mdiClipboardList,
|
|
||||||
time: mdiClock,
|
time: mdiClock,
|
||||||
timer: mdiTimerOutline,
|
timer: mdiTimerOutline,
|
||||||
|
todo: mdiClipboardList,
|
||||||
tts: mdiSpeakerMessage,
|
tts: mdiSpeakerMessage,
|
||||||
updater: mdiCloudUpload,
|
|
||||||
vacuum: mdiRobotVacuum,
|
vacuum: mdiRobotVacuum,
|
||||||
wake_word: mdiChatSleep,
|
wake_word: mdiChatSleep,
|
||||||
weather: mdiWeatherPartlyCloudy,
|
weather: mdiWeatherPartlyCloudy,
|
||||||
@ -180,6 +192,7 @@ export const FIXED_DEVICE_CLASS_ICONS = {
|
|||||||
volatile_organic_compounds_parts: mdiMolecule,
|
volatile_organic_compounds_parts: mdiMolecule,
|
||||||
voltage: mdiSineWave,
|
voltage: mdiSineWave,
|
||||||
volume: mdiCarCoolantLevel,
|
volume: mdiCarCoolantLevel,
|
||||||
|
volume_flow_rate: mdiPipe,
|
||||||
water: mdiWater,
|
water: mdiWater,
|
||||||
weight: mdiWeight,
|
weight: mdiWeight,
|
||||||
wind_speed: mdiWeatherWindy,
|
wind_speed: mdiWeatherWindy,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { HassConfig } from "home-assistant-js-websocket";
|
import { HassConfig } from "home-assistant-js-websocket";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FrontendLocaleData, DateFormat } from "../../data/translation";
|
import { DateFormat, FrontendLocaleData } from "../../data/translation";
|
||||||
import "../../resources/intl-polyfill";
|
import "../../resources/intl-polyfill";
|
||||||
|
import { resolveTimeZone } from "./resolve-time-zone";
|
||||||
|
|
||||||
// Tuesday, August 10
|
// Tuesday, August 10
|
||||||
export const formatDateWeekdayDay = (
|
export const formatDateWeekdayDay = (
|
||||||
@ -16,7 +17,7 @@ const formatDateWeekdayDayMem = memoizeOne(
|
|||||||
weekday: "long",
|
weekday: "long",
|
||||||
month: "long",
|
month: "long",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ const formatDateMem = memoizeOne(
|
|||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ const formatDateShortMem = memoizeOne(
|
|||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "short",
|
month: "short",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -105,7 +106,7 @@ const formatDateNumericMem = memoizeOne(
|
|||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "numeric",
|
month: "numeric",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ const formatDateNumericMem = memoizeOne(
|
|||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "numeric",
|
month: "numeric",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -130,7 +131,7 @@ const formatDateVeryShortMem = memoizeOne(
|
|||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
month: "short",
|
month: "short",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ const formatDateMonthYearMem = memoizeOne(
|
|||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -161,7 +162,7 @@ const formatDateMonthMem = memoizeOne(
|
|||||||
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
month: "long",
|
month: "long",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -176,7 +177,7 @@ const formatDateYearMem = memoizeOne(
|
|||||||
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ const formatDateWeekdayMem = memoizeOne(
|
|||||||
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
weekday: "long",
|
weekday: "long",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -206,6 +207,6 @@ const formatDateWeekdayShortMem = memoizeOne(
|
|||||||
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
(locale: FrontendLocaleData, serverTimeZone: string) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
weekday: "short",
|
weekday: "short",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -4,6 +4,7 @@ import { FrontendLocaleData } from "../../data/translation";
|
|||||||
import "../../resources/intl-polyfill";
|
import "../../resources/intl-polyfill";
|
||||||
import { formatDateNumeric } from "./format_date";
|
import { formatDateNumeric } from "./format_date";
|
||||||
import { formatTime } from "./format_time";
|
import { formatTime } from "./format_time";
|
||||||
|
import { resolveTimeZone } from "./resolve-time-zone";
|
||||||
import { useAmPm } from "./use_am_pm";
|
import { useAmPm } from "./use_am_pm";
|
||||||
|
|
||||||
// August 9, 2021, 8:23 AM
|
// August 9, 2021, 8:23 AM
|
||||||
@ -22,7 +23,7 @@ const formatDateTimeMem = memoizeOne(
|
|||||||
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ const formatShortDateTimeWithYearMem = memoizeOne(
|
|||||||
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ const formatShortDateTimeMem = memoizeOne(
|
|||||||
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ const formatDateTimeWithSecondsMem = memoizeOne(
|
|||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { HassConfig } from "home-assistant-js-websocket";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
import { FrontendLocaleData } from "../../data/translation";
|
||||||
import "../../resources/intl-polyfill";
|
import "../../resources/intl-polyfill";
|
||||||
|
import { resolveTimeZone } from "./resolve-time-zone";
|
||||||
import { useAmPm } from "./use_am_pm";
|
import { useAmPm } from "./use_am_pm";
|
||||||
|
|
||||||
// 9:15 PM || 21:15
|
// 9:15 PM || 21:15
|
||||||
@ -17,7 +18,7 @@ const formatTimeMem = memoizeOne(
|
|||||||
hour: "numeric",
|
hour: "numeric",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ const formatTimeWithSecondsMem = memoizeOne(
|
|||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
second: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ const formatTimeWeekdayMem = memoizeOne(
|
|||||||
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
hourCycle: useAmPm(locale) ? "h12" : "h23",
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -71,6 +72,6 @@ const formatTime24hMem = memoizeOne(
|
|||||||
hour: "numeric",
|
hour: "numeric",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hour12: false,
|
hour12: false,
|
||||||
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
|
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user