mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-13 11:19:25 +00:00
Compare commits
1 Commits
revert-130
...
Use-autofi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
faf8e49c12 |
@@ -16,9 +16,6 @@
|
|||||||
"runem.lit-plugin",
|
"runem.lit-plugin",
|
||||||
"ms-python.vscode-pylance"
|
"ms-python.vscode-pylance"
|
||||||
],
|
],
|
||||||
"containerEnv": {
|
|
||||||
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
|
|
||||||
},
|
|
||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.shell.linux": "/bin/bash",
|
"terminal.integrated.shell.linux": "/bin/bash",
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -51,7 +51,7 @@ DO NOT DELETE ANY TEXT from this template! Otherwise, your issue may be closed w
|
|||||||
<!--
|
<!--
|
||||||
Provide details about the versions you are using, which helps us reproducing
|
Provide details about the versions you are using, which helps us reproducing
|
||||||
and finding the issue quicker. Version information is found in the
|
and finding the issue quicker. Version information is found in the
|
||||||
Home Assistant frontend: Settings -> About.
|
Home Assistant frontend: Configuration -> Info.
|
||||||
|
|
||||||
Browser version and operating system is important! Please try to replicate
|
Browser version and operating system is important! Please try to replicate
|
||||||
your issue in a different browser and be sure to include your findings.
|
your issue in a different browser and be sure to include your findings.
|
||||||
|
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Report a bug with the UI / Dashboards
|
name: Report a bug with the UI, Frontend or Lovelace
|
||||||
description: Report an issue related to the Home Assistant frontend.
|
description: Report an issue related to the Home Assistant frontend.
|
||||||
labels: bug
|
labels: bug
|
||||||
body:
|
body:
|
||||||
@@ -9,7 +9,7 @@ body:
|
|||||||
|
|
||||||
If you have a feature or enhancement request for the frontend, please [start an discussion][fr] instead of creating an issue.
|
If you have a feature or enhancement request for the frontend, please [start an discussion][fr] instead of creating an issue.
|
||||||
|
|
||||||
**Please not not report issues for custom cards.**
|
**Please not not report issues for custom Lovelace cards.**
|
||||||
|
|
||||||
[fr]: https://github.com/home-assistant/frontend/discussions
|
[fr]: https://github.com/home-assistant/frontend/discussions
|
||||||
[releases]: https://github.com/home-assistant/home-assistant/releases
|
[releases]: https://github.com/home-assistant/home-assistant/releases
|
||||||
@@ -64,7 +64,7 @@ body:
|
|||||||
label: What version of Home Assistant Core has the issue?
|
label: What version of Home Assistant Core has the issue?
|
||||||
placeholder: core-
|
placeholder: core-
|
||||||
description: >
|
description: >
|
||||||
Can be found in: [Settings -> About](https://my.home-assistant.io/redirect/info/).
|
Can be found in the Configuration panel -> Info.
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: What was the last working version of Home Assistant Core?
|
label: What was the last working version of Home Assistant Core?
|
||||||
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,17 +1,17 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Request a feature for the UI / Dashboards
|
- name: Request a feature for the UI, Frontend or Lovelace
|
||||||
url: https://github.com/home-assistant/frontend/discussions/category_choices
|
url: https://github.com/home-assistant/frontend/discussions/category_choices
|
||||||
about: Request an new feature for the Home Assistant frontend.
|
about: Request an new feature for the Home Assistant frontend.
|
||||||
- name: Report a bug that is NOT related to the UI / Dashboards
|
- name: Report a bug that is NOT related to the UI, Frontend or Lovelace
|
||||||
url: https://github.com/home-assistant/core/issues
|
url: https://github.com/home-assistant/core/issues
|
||||||
about: This is the issue tracker for our frontend. Please report other issues in the backend ("core") repository.
|
about: This is the issue tracker for our frontend. Please report other issues with the backend repository.
|
||||||
- name: Report incorrect or missing information on our website
|
- name: Report incorrect or missing information on our website
|
||||||
url: https://github.com/home-assistant/home-assistant.io/issues
|
url: https://github.com/home-assistant/home-assistant.io/issues
|
||||||
about: Our documentation has its own issue tracker. Please report issues with the website there.
|
about: Our documentation has its own issue tracker. Please report issues with the website there.
|
||||||
- name: I have a question or need support
|
- name: I have a question or need support
|
||||||
url: https://www.home-assistant.io/help
|
url: https://www.home-assistant.io/help
|
||||||
about: We use GitHub for tracking bugs. Check our website for resources on getting help.
|
about: We use GitHub for tracking bugs, check our website for resources on getting help.
|
||||||
- name: I'm unsure where to go
|
- name: I'm unsure where to go
|
||||||
url: https://www.home-assistant.io/join-chat
|
url: https://www.home-assistant.io/join-chat
|
||||||
about: If you are unsure where to go, then joining our chat is recommended; Just ask!
|
about: If you are unsure where to go, then joining our chat is recommended; Just ask!
|
||||||
|
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
- 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-demos
|
||||||
- name: Run eslint
|
- name: Run eslint
|
||||||
run: yarn run lint:eslint
|
run: yarn run lint:eslint
|
||||||
- name: Run tsc
|
- name: Run tsc
|
||||||
|
4
.github/workflows/netflify.yml
vendored
4
.github/workflows/netflify.yml
vendored
@@ -15,5 +15,5 @@ jobs:
|
|||||||
- name: Trigger Demo build
|
- name: Trigger Demo build
|
||||||
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }}
|
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }}
|
||||||
|
|
||||||
- name: Trigger Design build
|
- name: Trigger Gallery build
|
||||||
run: curl -X POST -d "NIGHTLY" https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }}
|
run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }}
|
||||||
|
17
.github/workflows/release.yaml
vendored
17
.github/workflows/release.yaml
vendored
@@ -10,18 +10,10 @@ env:
|
|||||||
NODE_VERSION: 14
|
NODE_VERSION: 14
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=6144
|
||||||
|
|
||||||
# Set default workflow permissions
|
|
||||||
# All scopes not mentioned here are set to no access
|
|
||||||
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
|
|
||||||
permissions:
|
|
||||||
actions: none
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: write # Required to upload release assets
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -49,19 +41,12 @@ jobs:
|
|||||||
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
|
||||||
- name: Build and release package
|
- name: Build and release package
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install twine build
|
python3 -m pip install twine
|
||||||
export TWINE_USERNAME="__token__"
|
export TWINE_USERNAME="__token__"
|
||||||
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
|
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
|
||||||
|
|
||||||
script/release
|
script/release
|
||||||
|
|
||||||
- name: Upload release assets
|
|
||||||
uses: softprops/action-gh-release@v0.1.14
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
dist/*.whl
|
|
||||||
dist/*.tar.gz
|
|
||||||
|
|
||||||
wheels-init:
|
wheels-init:
|
||||||
name: Init wheels build
|
name: Init wheels build
|
||||||
needs: release
|
needs: release
|
||||||
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@@ -181,7 +181,7 @@
|
|||||||
{
|
{
|
||||||
"label": "Run HA Core for Supervisor in devcontainer",
|
"label": "Run HA Core for Supervisor in devcontainer",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "SUPERVISOR=${input:supervisorHost} SUPERVISOR_TOKEN=${input:supervisorToken} script/core",
|
"command": "HASSIO=${input:supervisorHost} HASSIO_TOKEN=${input:supervisorToken} script/core",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
|
1536
.yarn/patches/@lit-labs/virtualizer/0.7.0.patch
Normal file
1536
.yarn/patches/@lit-labs/virtualizer/0.7.0.patch
Normal file
File diff suppressed because one or more lines are too long
@@ -1,10 +1,11 @@
|
|||||||
diff --git a/polyfillLoaders/EventTarget.js b/polyfillLoaders/EventTarget.js
|
diff --git a/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js b/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js
|
||||||
index 4e18ade7ba485849f17f28c94c42f0e0e01ac387..8f34f4f646c7f7becc208fb5a546c96034fc74dc 100644
|
index d92179f7fd5315203f870a6963e871dc8ddf6c0c..362e284121b97e0fba0925225777aebc32e26b8d 100644
|
||||||
--- a/polyfillLoaders/EventTarget.js
|
--- a/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js
|
||||||
+++ b/polyfillLoaders/EventTarget.js
|
+++ b/lib/uni-virtualizer/lib/polyfillLoaders/EventTarget.js
|
||||||
@@ -6,16 +6,15 @@
|
@@ -1,14 +1,15 @@
|
||||||
let _ET;
|
-let _ET, ET;
|
||||||
let ET;
|
+let _ET;
|
||||||
|
+let ET;
|
||||||
export default async function EventTarget() {
|
export default async function EventTarget() {
|
||||||
- return ET || init();
|
- return ET || init();
|
||||||
+ return ET || init();
|
+ return ET || init();
|
||||||
@@ -25,5 +26,4 @@ index 4e18ade7ba485849f17f28c94c42f0e0e01ac387..8f34f4f646c7f7becc208fb5a546c960
|
|||||||
+ _ET = (await import("event-target-shim")).default.EventTarget;
|
+ _ET = (await import("event-target-shim")).default.EventTarget;
|
||||||
+ }
|
+ }
|
||||||
+ return (ET = _ET);
|
+ return (ET = _ET);
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=EventTarget.js.map
|
|
631
.yarn/releases/yarn-3.0.2.cjs
vendored
Executable file
631
.yarn/releases/yarn-3.0.2.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
785
.yarn/releases/yarn-3.2.0.cjs
vendored
785
.yarn/releases/yarn-3.2.0.cjs
vendored
File diff suppressed because one or more lines are too long
@@ -6,4 +6,4 @@ plugins:
|
|||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
spec: "@yarnpkg/plugin-interactive-tools"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.2.0.cjs
|
yarnPath: .yarn/releases/yarn-3.0.2.cjs
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
include README.md
|
include README.md
|
||||||
|
include LICENSE.md
|
||||||
graft hass_frontend
|
graft hass_frontend
|
||||||
graft hass_frontend_es5
|
graft hass_frontend_es5
|
||||||
recursive-exclude * *.py[co]
|
recursive-exclude * *.py[co]
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is the repository for the official [Home Assistant](https://home-assistant.io) frontend.
|
This is the repository for the official [Home Assistant](https://home-assistant.io) frontend.
|
||||||
|
|
||||||
[](https://demo.home-assistant.io/)
|
[](https://demo.home-assistant.io/)
|
||||||
|
|
||||||
- [View demo of Home Assistant](https://demo.home-assistant.io/)
|
- [View demo of Home Assistant](https://demo.home-assistant.io/)
|
||||||
- [More information about Home Assistant](https://home-assistant.io)
|
- [More information about Home Assistant](https://home-assistant.io)
|
||||||
|
@@ -10,7 +10,7 @@ module.exports.ignorePackages = ({ latestBuild }) => [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Files from NPM packages that we should replace with empty file
|
// Files from NPM packages that we should replace with empty file
|
||||||
module.exports.emptyPackages = ({ latestBuild, isHassioBuild }) =>
|
module.exports.emptyPackages = ({ latestBuild }) =>
|
||||||
[
|
[
|
||||||
// Contains all color definitions for all material color sets.
|
// Contains all color definitions for all material color sets.
|
||||||
// We don't use it
|
// We don't use it
|
||||||
@@ -28,15 +28,6 @@ module.exports.emptyPackages = ({ latestBuild, isHassioBuild }) =>
|
|||||||
),
|
),
|
||||||
// This polyfill is loaded in workers to support ES5, filter it out.
|
// This polyfill is loaded in workers to support ES5, filter it out.
|
||||||
latestBuild && require.resolve("proxy-polyfill/src/index.js"),
|
latestBuild && require.resolve("proxy-polyfill/src/index.js"),
|
||||||
// Icons in supervisor conflict with icons in HA so we don't load.
|
|
||||||
isHassioBuild &&
|
|
||||||
require.resolve(
|
|
||||||
path.resolve(paths.polymer_dir, "src/components/ha-icon.ts")
|
|
||||||
),
|
|
||||||
isHassioBuild &&
|
|
||||||
require.resolve(
|
|
||||||
path.resolve(paths.polymer_dir, "src/components/ha-icon-picker.ts")
|
|
||||||
),
|
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
||||||
@@ -174,7 +165,6 @@ module.exports.config = {
|
|||||||
cast({ isProdBuild, latestBuild }) {
|
cast({ isProdBuild, latestBuild }) {
|
||||||
const entry = {
|
const entry = {
|
||||||
launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"),
|
launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"),
|
||||||
media: path.resolve(paths.cast_dir, "src/media/entrypoint.ts"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (latestBuild) {
|
if (latestBuild) {
|
||||||
@@ -205,7 +195,6 @@ module.exports.config = {
|
|||||||
publicPath: publicPath(latestBuild, paths.hassio_publicPath),
|
publicPath: publicPath(latestBuild, paths.hassio_publicPath),
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
isHassioBuild: true,
|
|
||||||
defineOverlay: {
|
defineOverlay: {
|
||||||
__SUPERVISOR__: true,
|
__SUPERVISOR__: true,
|
||||||
},
|
},
|
||||||
|
@@ -26,11 +26,11 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
version() {
|
version() {
|
||||||
const version = fs
|
const version = fs
|
||||||
.readFileSync(path.resolve(paths.polymer_dir, "pyproject.toml"), "utf8")
|
.readFileSync(path.resolve(paths.polymer_dir, "setup.py"), "utf8")
|
||||||
.match(/version\W+=\W"(\d{8}\.\d)"/);
|
.match(/\d{8}\.\d+/);
|
||||||
if (!version) {
|
if (!version) {
|
||||||
throw Error("Version not found");
|
throw Error("Version not found");
|
||||||
}
|
}
|
||||||
return version[1];
|
return version[0];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -31,6 +31,6 @@ gulp.task("clean-hassio", () =>
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
"clean-gallery",
|
"clean-gallery",
|
||||||
gulp.parallel("clean-translations", () =>
|
gulp.parallel("clean-translations", () =>
|
||||||
del([paths.gallery_output_root, paths.gallery_build, paths.build_dir])
|
del([paths.gallery_output_root, paths.build_dir])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -154,15 +154,6 @@ gulp.task("gen-index-cast-dev", (done) => {
|
|||||||
contentReceiver
|
contentReceiver
|
||||||
);
|
);
|
||||||
|
|
||||||
const contentMedia = renderCastTemplate("media", {
|
|
||||||
latestMediaJS: "/frontend_latest/media.js",
|
|
||||||
es5MediaJS: "/frontend_es5/media.js",
|
|
||||||
});
|
|
||||||
fs.outputFileSync(
|
|
||||||
path.resolve(paths.cast_output_root, "media.html"),
|
|
||||||
contentMedia
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentFAQ = renderCastTemplate("launcher-faq", {
|
const contentFAQ = renderCastTemplate("launcher-faq", {
|
||||||
latestLauncherJS: "/frontend_latest/launcher.js",
|
latestLauncherJS: "/frontend_latest/launcher.js",
|
||||||
es5LauncherJS: "/frontend_es5/launcher.js",
|
es5LauncherJS: "/frontend_es5/launcher.js",
|
||||||
@@ -201,15 +192,6 @@ gulp.task("gen-index-cast-prod", (done) => {
|
|||||||
contentReceiver
|
contentReceiver
|
||||||
);
|
);
|
||||||
|
|
||||||
const contentMedia = renderCastTemplate("media", {
|
|
||||||
latestMediaJS: latestManifest["media.js"],
|
|
||||||
es5MediaJS: es5Manifest["media.js"],
|
|
||||||
});
|
|
||||||
fs.outputFileSync(
|
|
||||||
path.resolve(paths.cast_output_root, "media.html"),
|
|
||||||
contentMedia
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentFAQ = renderCastTemplate("launcher-faq", {
|
const contentFAQ = renderCastTemplate("launcher-faq", {
|
||||||
latestLauncherJS: latestManifest["launcher.js"],
|
latestLauncherJS: latestManifest["launcher.js"],
|
||||||
es5LauncherJS: es5Manifest["launcher.js"],
|
es5LauncherJS: es5Manifest["launcher.js"],
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
/* eslint-disable */
|
|
||||||
// Run demo develop mode
|
// Run demo develop mode
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { marked } = require("marked");
|
|
||||||
const glob = require("glob");
|
|
||||||
const yaml = require("js-yaml");
|
|
||||||
|
|
||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
const paths = require("../paths");
|
const paths = require("../paths");
|
||||||
@@ -19,129 +15,26 @@ require("./service-worker.js");
|
|||||||
require("./entry-html.js");
|
require("./entry-html.js");
|
||||||
require("./rollup.js");
|
require("./rollup.js");
|
||||||
|
|
||||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
gulp.task("gather-gallery-demos", async function gatherDemos() {
|
||||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
const files = await fs.promises.readdir(
|
||||||
const files = glob.sync(path.resolve(pageDir, "**/*"));
|
path.resolve(paths.gallery_dir, "src/demos")
|
||||||
|
);
|
||||||
|
|
||||||
const galleryBuild = path.resolve(paths.gallery_dir, "build");
|
let content = "export const DEMOS = {\n";
|
||||||
fs.mkdirSync(galleryBuild, { recursive: true });
|
|
||||||
|
|
||||||
let content = "export const PAGES = {\n";
|
|
||||||
|
|
||||||
const processed = new Set();
|
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (fs.lstatSync(file).isDirectory()) {
|
const demoId = path.basename(file, ".ts");
|
||||||
continue;
|
const demoPath = "../src/demos/" + demoId;
|
||||||
}
|
content += ` "${demoId}": () => import("${demoPath}"),\n`;
|
||||||
const pageId = file.substring(pageDir.length + 1, file.lastIndexOf("."));
|
|
||||||
|
|
||||||
if (processed.has(pageId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
processed.add(pageId);
|
|
||||||
|
|
||||||
const [category, name] = pageId.split("/", 2);
|
|
||||||
|
|
||||||
const demoFile = path.resolve(pageDir, `${pageId}.ts`);
|
|
||||||
const descriptionFile = path.resolve(pageDir, `${pageId}.markdown`);
|
|
||||||
const hasDemo = fs.existsSync(demoFile);
|
|
||||||
let hasDescription = fs.existsSync(descriptionFile);
|
|
||||||
let metadata = {};
|
|
||||||
if (hasDescription) {
|
|
||||||
let descriptionContent = fs.readFileSync(descriptionFile, "utf-8");
|
|
||||||
|
|
||||||
if (descriptionContent.startsWith("---")) {
|
|
||||||
const metadataEnd = descriptionContent.indexOf("---", 3);
|
|
||||||
metadata = yaml.load(descriptionContent.substring(3, metadataEnd));
|
|
||||||
descriptionContent = descriptionContent
|
|
||||||
.substring(metadataEnd + 3)
|
|
||||||
.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If description is just metadata
|
|
||||||
if (descriptionContent === "") {
|
|
||||||
hasDescription = false;
|
|
||||||
} else {
|
|
||||||
descriptionContent = marked(descriptionContent).replace(/`/g, "\\`");
|
|
||||||
fs.mkdirSync(path.resolve(galleryBuild, category), { recursive: true });
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.resolve(galleryBuild, `${pageId}-description.ts`),
|
|
||||||
`
|
|
||||||
import {html} from "lit";
|
|
||||||
export default html\`${descriptionContent}\`
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content += ` "${pageId}": {
|
|
||||||
metadata: ${JSON.stringify(metadata)},
|
|
||||||
${
|
|
||||||
hasDescription
|
|
||||||
? `description: () => import("./${pageId}-description").then(m => m.default),`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
${hasDemo ? `demo: () => import("../src/pages/${pageId}")` : ""}
|
|
||||||
|
|
||||||
},\n`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content += "};\n";
|
content += "};";
|
||||||
|
|
||||||
// Generate sidebar
|
const galleryBuild = path.resolve(paths.gallery_dir, "build");
|
||||||
const sidebarPath = path.resolve(paths.gallery_dir, "sidebar.js");
|
|
||||||
// To make watch work during development
|
|
||||||
delete require.cache[sidebarPath];
|
|
||||||
const sidebar = require(sidebarPath);
|
|
||||||
|
|
||||||
const pagesToProcess = {};
|
|
||||||
for (const key of processed) {
|
|
||||||
const [category, page] = key.split("/", 2);
|
|
||||||
if (!(category in pagesToProcess)) {
|
|
||||||
pagesToProcess[category] = new Set();
|
|
||||||
}
|
|
||||||
pagesToProcess[category].add(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const group of Object.values(sidebar)) {
|
|
||||||
const toProcess = pagesToProcess[group.category];
|
|
||||||
delete pagesToProcess[group.category];
|
|
||||||
|
|
||||||
if (!toProcess) {
|
|
||||||
console.error("Unknown category", group.category);
|
|
||||||
if (!group.pages) {
|
|
||||||
group.pages = [];
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any pre-defined groups will not be sorted.
|
|
||||||
if (group.pages) {
|
|
||||||
for (const page of group.pages) {
|
|
||||||
if (!toProcess.delete(page)) {
|
|
||||||
console.error("Found unreferenced demo", page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
group.pages = [];
|
|
||||||
}
|
|
||||||
for (const page of Array.from(toProcess).sort()) {
|
|
||||||
group.pages.push(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [category, pages] of Object.entries(pagesToProcess)) {
|
|
||||||
sidebar.push({
|
|
||||||
category,
|
|
||||||
header: category,
|
|
||||||
pages: Array.from(pages).sort(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
content += `export const SIDEBAR = ${JSON.stringify(sidebar, null, 2)};\n`;
|
|
||||||
|
|
||||||
|
fs.mkdirSync(galleryBuild, { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.resolve(galleryBuild, "import-pages.ts"),
|
path.resolve(galleryBuild, "import-demos.ts"),
|
||||||
content,
|
content,
|
||||||
"utf-8"
|
"utf-8"
|
||||||
);
|
);
|
||||||
@@ -159,24 +52,11 @@ gulp.task(
|
|||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"gather-gallery-pages"
|
"gather-gallery-demos"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
"gen-index-gallery-dev",
|
"gen-index-gallery-dev",
|
||||||
gulp.parallel(
|
env.useRollup() ? "rollup-dev-server-gallery" : "webpack-dev-server-gallery"
|
||||||
env.useRollup()
|
|
||||||
? "rollup-dev-server-gallery"
|
|
||||||
: "webpack-dev-server-gallery",
|
|
||||||
async function watchMarkdownFiles() {
|
|
||||||
gulp.watch(
|
|
||||||
[
|
|
||||||
path.resolve(paths.gallery_dir, "src/pages/**/*.markdown"),
|
|
||||||
path.resolve(paths.gallery_dir, "sidebar.js"),
|
|
||||||
],
|
|
||||||
gulp.series("gather-gallery-pages")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -192,7 +72,7 @@ gulp.task(
|
|||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data",
|
"build-locale-data",
|
||||||
"gather-gallery-pages"
|
"gather-gallery-demos"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
env.useRollup() ? "rollup-prod-gallery" : "webpack-prod-gallery",
|
||||||
|
@@ -79,11 +79,6 @@ function copyFonts(staticDir) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyQrScannerWorker(staticDir) {
|
|
||||||
const staticPath = genStaticPath(staticDir);
|
|
||||||
copyFileDir(npmPath("qr-scanner/qr-scanner-worker.min.js"), staticPath("js"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyMapPanel(staticDir) {
|
function copyMapPanel(staticDir) {
|
||||||
const staticPath = genStaticPath(staticDir);
|
const staticPath = genStaticPath(staticDir);
|
||||||
copyFileDir(
|
copyFileDir(
|
||||||
@@ -130,9 +125,6 @@ gulp.task("copy-static-app", async () => {
|
|||||||
|
|
||||||
// Panel assets
|
// Panel assets
|
||||||
copyMapPanel(staticDir);
|
copyMapPanel(staticDir);
|
||||||
|
|
||||||
// Qr Scanner assets
|
|
||||||
copyQrScannerWorker(staticDir);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-static-demo", async () => {
|
gulp.task("copy-static-demo", async () => {
|
||||||
|
@@ -7,7 +7,7 @@ const source = require("vinyl-source-stream");
|
|||||||
const vinylBuffer = require("vinyl-buffer");
|
const vinylBuffer = require("vinyl-buffer");
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const flatmap = require("gulp-flatmap");
|
const foreach = require("gulp-foreach");
|
||||||
const merge = require("gulp-merge-json");
|
const merge = require("gulp-merge-json");
|
||||||
const rename = require("gulp-rename");
|
const rename = require("gulp-rename");
|
||||||
const transform = require("gulp-json-transform");
|
const transform = require("gulp-json-transform");
|
||||||
@@ -183,7 +183,7 @@ gulp.task("build-merged-translations", () =>
|
|||||||
})
|
})
|
||||||
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
.pipe(transform((data, file) => lokaliseTransform(data, data, file)))
|
||||||
.pipe(
|
.pipe(
|
||||||
flatmap((stream, file) => {
|
foreach((stream, file) => {
|
||||||
// For each language generate a merged json file. It begins with the master
|
// For each language generate a merged json file. It begins with the master
|
||||||
// translation as a failsafe for untranslated strings, and merges all parent
|
// translation as a failsafe for untranslated strings, and merges all parent
|
||||||
// tags into one file for each specific subtag
|
// tags into one file for each specific subtag
|
||||||
|
@@ -26,7 +26,6 @@ module.exports = {
|
|||||||
cast_output_es5: path.resolve(__dirname, "../cast/dist/frontend_es5"),
|
cast_output_es5: path.resolve(__dirname, "../cast/dist/frontend_es5"),
|
||||||
|
|
||||||
gallery_dir: path.resolve(__dirname, "../gallery"),
|
gallery_dir: path.resolve(__dirname, "../gallery"),
|
||||||
gallery_build: path.resolve(__dirname, "../gallery/build"),
|
|
||||||
gallery_output_root: path.resolve(__dirname, "../gallery/dist"),
|
gallery_output_root: path.resolve(__dirname, "../gallery/dist"),
|
||||||
gallery_output_latest: path.resolve(
|
gallery_output_latest: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -3,10 +3,10 @@ const webpack = require("webpack");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
||||||
const log = require("fancy-log");
|
|
||||||
const WebpackBar = require("webpackbar");
|
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
const bundle = require("./bundle.js");
|
const bundle = require("./bundle.js");
|
||||||
|
const log = require("fancy-log");
|
||||||
|
const WebpackBar = require("webpackbar");
|
||||||
|
|
||||||
class LogStartCompilePlugin {
|
class LogStartCompilePlugin {
|
||||||
ignoredFirst = false;
|
ignoredFirst = false;
|
||||||
@@ -30,7 +30,6 @@ const createWebpackConfig = ({
|
|||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
isStatsBuild,
|
isStatsBuild,
|
||||||
isHassioBuild,
|
|
||||||
dontHash,
|
dontHash,
|
||||||
}) => {
|
}) => {
|
||||||
if (!dontHash) {
|
if (!dontHash) {
|
||||||
@@ -118,9 +117,7 @@ const createWebpackConfig = ({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new webpack.NormalModuleReplacementPlugin(
|
new webpack.NormalModuleReplacementPlugin(
|
||||||
new RegExp(
|
new RegExp(bundle.emptyPackages({ latestBuild }).join("|")),
|
||||||
bundle.emptyPackages({ latestBuild, isHassioBuild }).join("|")
|
|
||||||
),
|
|
||||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||||
),
|
),
|
||||||
!isProdBuild && new LogStartCompilePlugin(),
|
!isProdBuild && new LogStartCompilePlugin(),
|
||||||
@@ -138,8 +135,6 @@ const createWebpackConfig = ({
|
|||||||
"lit/directives/cache$": "lit/directives/cache.js",
|
"lit/directives/cache$": "lit/directives/cache.js",
|
||||||
"lit/directives/repeat$": "lit/directives/repeat.js",
|
"lit/directives/repeat$": "lit/directives/repeat.js",
|
||||||
"lit/polyfill-support$": "lit/polyfill-support.js",
|
"lit/polyfill-support$": "lit/polyfill-support.js",
|
||||||
"@lit-labs/virtualizer/layouts/grid":
|
|
||||||
"@lit-labs/virtualizer/layouts/grid.js",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
# These redirects are handled by Netlify
|
|
||||||
#
|
|
||||||
|
|
||||||
# Some custom cards are not prefixing the instance URL when fetching data
|
|
||||||
# and can end up fetching the data from the Cast domain instead of HA.
|
|
||||||
# This will make sure that some common ones are replaced with a placeholder.
|
|
||||||
/api/camera_proxy/* /images/google-nest-hub.png
|
|
||||||
/api/camera_proxy_stream/* /images/google-nest-hub.png
|
|
||||||
/api/media_player_proxy/* /images/google-nest-hub.png
|
|
@@ -1,46 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
--logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
|
|
||||||
--logo-repeat: no-repeat;
|
|
||||||
--playback-logo-image: url('https://www.home-assistant.io/images/home-assistant-logo.svg');
|
|
||||||
--theme-hue: 200;
|
|
||||||
--progress-color: #03a9f4;
|
|
||||||
--splash-image: url('https://home-assistant.io/images/cast/splash.png');
|
|
||||||
--splash-size: cover;
|
|
||||||
--background-color: #41bdf5;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
var _gaq=[['_setAccount','UA-57927901-10'],['_trackPageview']];
|
|
||||||
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
|
|
||||||
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
|
|
||||||
s.parentNode.insertBefore(g,s)}(document,'script'));
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<%= renderTemplate('_js_base') %>
|
|
||||||
|
|
||||||
<cast-media-player></cast-media-player>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import("<%= latestMediaJS %>");
|
|
||||||
window.latestJS = true;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
if (!window.latestJS) {
|
|
||||||
<% if (useRollup) { %>
|
|
||||||
_ls("/static/js/s.min.js").onload = function() {
|
|
||||||
System.import("<%= es5MediaJS %>");
|
|
||||||
};
|
|
||||||
<% } else { %>
|
|
||||||
_ls("<%= es5MediaJS %>");
|
|
||||||
<% } %>
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,22 +0,0 @@
|
|||||||
const castContext = cast.framework.CastReceiverContext.getInstance();
|
|
||||||
|
|
||||||
const playerManager = castContext.getPlayerManager();
|
|
||||||
|
|
||||||
playerManager.setMessageInterceptor(
|
|
||||||
cast.framework.messages.MessageType.LOAD,
|
|
||||||
(loadRequestData) => {
|
|
||||||
const media = loadRequestData.media;
|
|
||||||
// Special handling if it came from Google Assistant
|
|
||||||
if (media.entity) {
|
|
||||||
media.contentId = media.entity;
|
|
||||||
media.streamType = cast.framework.messages.StreamType.LIVE;
|
|
||||||
media.contentType = "application/vnd.apple.mpegurl";
|
|
||||||
// @ts-ignore
|
|
||||||
media.hlsVideoSegmentFormat =
|
|
||||||
cast.framework.messages.HlsVideoSegmentFormat.FMP4;
|
|
||||||
}
|
|
||||||
return loadRequestData;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
castContext.start();
|
|
@@ -8,9 +8,6 @@ import { ReceivedMessage } from "./types";
|
|||||||
|
|
||||||
const lovelaceController = new HcMain();
|
const lovelaceController = new HcMain();
|
||||||
document.body.append(lovelaceController);
|
document.body.append(lovelaceController);
|
||||||
lovelaceController.addEventListener("cast-view-changed", (ev) => {
|
|
||||||
playDummyMedia(ev.detail.title);
|
|
||||||
});
|
|
||||||
|
|
||||||
const mediaPlayer = document.createElement("cast-media-player");
|
const mediaPlayer = document.createElement("cast-media-player");
|
||||||
mediaPlayer.style.display = "none";
|
mediaPlayer.style.display = "none";
|
||||||
@@ -31,31 +28,6 @@ const setTouchControlsVisibility = (visible: boolean) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let timeOut: number | undefined;
|
|
||||||
|
|
||||||
const playDummyMedia = (viewTitle?: string) => {
|
|
||||||
const loadRequestData = new cast.framework.messages.LoadRequestData();
|
|
||||||
loadRequestData.autoplay = true;
|
|
||||||
loadRequestData.media = new cast.framework.messages.MediaInformation();
|
|
||||||
loadRequestData.media.contentId =
|
|
||||||
"https://cast.home-assistant.io/images/google-nest-hub.png";
|
|
||||||
loadRequestData.media.contentType = "image/jpeg";
|
|
||||||
loadRequestData.media.streamType = cast.framework.messages.StreamType.NONE;
|
|
||||||
const metadata = new cast.framework.messages.GenericMediaMetadata();
|
|
||||||
metadata.title = viewTitle;
|
|
||||||
loadRequestData.media.metadata = metadata;
|
|
||||||
|
|
||||||
loadRequestData.requestId = 0;
|
|
||||||
playerManager.load(loadRequestData);
|
|
||||||
if (timeOut) {
|
|
||||||
clearTimeout(timeOut);
|
|
||||||
timeOut = undefined;
|
|
||||||
}
|
|
||||||
if (castContext.getDeviceCapabilities().touch_input_supported) {
|
|
||||||
timeOut = window.setTimeout(() => playDummyMedia(viewTitle), 540000); // repeat every 9 minutes to keep it active (gets deactivated after 10 minutes)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const showLovelaceController = () => {
|
const showLovelaceController = () => {
|
||||||
mediaPlayer.style.display = "none";
|
mediaPlayer.style.display = "none";
|
||||||
lovelaceController.style.display = "initial";
|
lovelaceController.style.display = "initial";
|
||||||
@@ -79,7 +51,6 @@ const showMediaPlayer = () => {
|
|||||||
--progress-color: #03a9f4;
|
--progress-color: #03a9f4;
|
||||||
--splash-image: url('https://home-assistant.io/images/cast/splash.png');
|
--splash-image: url('https://home-assistant.io/images/cast/splash.png');
|
||||||
--splash-size: cover;
|
--splash-size: cover;
|
||||||
--background-color: #41bdf5;
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
@@ -92,6 +63,22 @@ options.customNamespaces = {
|
|||||||
[CAST_NS]: cast.framework.system.MessageType.JSON,
|
[CAST_NS]: cast.framework.system.MessageType.JSON,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The docs say we need to set options.touchScreenOptimizeApp = true
|
||||||
|
// https://developers.google.com/cast/docs/caf_receiver/customize_ui#accessing_ui_controls
|
||||||
|
// This doesn't work.
|
||||||
|
// @ts-ignore
|
||||||
|
options.touchScreenOptimizedApp = true;
|
||||||
|
|
||||||
|
// The class reference say we can set a uiConfig in options to set it
|
||||||
|
// https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.CastReceiverOptions#uiConfig
|
||||||
|
// This doesn't work either.
|
||||||
|
// @ts-ignore
|
||||||
|
options.uiConfig = new cast.framework.ui.UiConfig();
|
||||||
|
// @ts-ignore
|
||||||
|
options.uiConfig.touchScreenOptimizedApp = true;
|
||||||
|
|
||||||
|
castContext.setInactivityTimeout(86400); // 1 day
|
||||||
|
|
||||||
castContext.addCustomMessageListener(
|
castContext.addCustomMessageListener(
|
||||||
CAST_NS,
|
CAST_NS,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -116,12 +103,6 @@ const playerManager = castContext.getPlayerManager();
|
|||||||
playerManager.setMessageInterceptor(
|
playerManager.setMessageInterceptor(
|
||||||
cast.framework.messages.MessageType.LOAD,
|
cast.framework.messages.MessageType.LOAD,
|
||||||
(loadRequestData) => {
|
(loadRequestData) => {
|
||||||
if (
|
|
||||||
loadRequestData.media.contentId ===
|
|
||||||
"https://cast.home-assistant.io/images/google-nest-hub.png"
|
|
||||||
) {
|
|
||||||
return loadRequestData;
|
|
||||||
}
|
|
||||||
// We received a play media command, hide Lovelace and show media player
|
// We received a play media command, hide Lovelace and show media player
|
||||||
showMediaPlayer();
|
showMediaPlayer();
|
||||||
const media = loadRequestData.media;
|
const media = loadRequestData.media;
|
||||||
|
@@ -1,15 +1,11 @@
|
|||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
import { LovelaceConfig } from "../../../../src/data/lovelace";
|
||||||
import { Lovelace } from "../../../../src/panels/lovelace/types";
|
import { Lovelace } from "../../../../src/panels/lovelace/types";
|
||||||
import "../../../../src/panels/lovelace/views/hui-view";
|
import "../../../../src/panels/lovelace/views/hui-view";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
|
||||||
(window as any).loadCardHelpers = () =>
|
|
||||||
import("../../../../src/panels/lovelace/custom-card-helpers");
|
|
||||||
|
|
||||||
@customElement("hc-lovelace")
|
@customElement("hc-lovelace")
|
||||||
class HcLovelace extends LitElement {
|
class HcLovelace extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@@ -18,9 +14,7 @@ class HcLovelace extends LitElement {
|
|||||||
|
|
||||||
@property() public viewPath?: string | number;
|
@property() public viewPath?: string | number;
|
||||||
|
|
||||||
@property() public urlPath: string | null = null;
|
public urlPath?: string | null;
|
||||||
|
|
||||||
@query("hui-view") private _huiView?: HTMLElement;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const index = this._viewIndex;
|
const index = this._viewIndex;
|
||||||
@@ -36,7 +30,7 @@ class HcLovelace extends LitElement {
|
|||||||
config: this.lovelaceConfig,
|
config: this.lovelaceConfig,
|
||||||
rawConfig: this.lovelaceConfig,
|
rawConfig: this.lovelaceConfig,
|
||||||
editMode: false,
|
editMode: false,
|
||||||
urlPath: this.urlPath,
|
urlPath: this.urlPath!,
|
||||||
enableFullEditMode: () => undefined,
|
enableFullEditMode: () => undefined,
|
||||||
mode: "storage",
|
mode: "storage",
|
||||||
locale: this.hass.locale,
|
locale: this.hass.locale,
|
||||||
@@ -60,32 +54,17 @@ class HcLovelace extends LitElement {
|
|||||||
const index = this._viewIndex;
|
const index = this._viewIndex;
|
||||||
|
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
const dashboardTitle = this.lovelaceConfig.title || this.urlPath;
|
|
||||||
|
|
||||||
const viewTitle =
|
|
||||||
this.lovelaceConfig.views[index].title ||
|
|
||||||
this.lovelaceConfig.views[index].path;
|
|
||||||
|
|
||||||
fireEvent(this, "cast-view-changed", {
|
|
||||||
title:
|
|
||||||
dashboardTitle || viewTitle
|
|
||||||
? `${dashboardTitle || ""}${
|
|
||||||
dashboardTitle && viewTitle ? ": " : ""
|
|
||||||
}${viewTitle || ""}`
|
|
||||||
: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const configBackground =
|
const configBackground =
|
||||||
this.lovelaceConfig.views[index].background ||
|
this.lovelaceConfig.views[index].background ||
|
||||||
this.lovelaceConfig.background;
|
this.lovelaceConfig.background;
|
||||||
|
|
||||||
if (configBackground) {
|
if (configBackground) {
|
||||||
this._huiView!.style.setProperty(
|
(this.shadowRoot!.querySelector(
|
||||||
|
"hui-view"
|
||||||
|
) as HTMLElement)!.style.setProperty(
|
||||||
"--lovelace-background",
|
"--lovelace-background",
|
||||||
configBackground
|
configBackground
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
this._huiView!.style.removeProperty("--lovelace-background");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,22 +97,12 @@ class HcLovelace extends LitElement {
|
|||||||
:host > * {
|
:host > * {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
hui-view {
|
|
||||||
background: var(--lovelace-background, var(--primary-background-color));
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CastViewChanged {
|
|
||||||
title: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"hc-lovelace": HcLovelace;
|
"hc-lovelace": HcLovelace;
|
||||||
}
|
}
|
||||||
interface HASSDomEvents {
|
|
||||||
"cast-view-changed": CastViewChanged;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -13,11 +13,7 @@ import {
|
|||||||
ShowDemoMessage,
|
ShowDemoMessage,
|
||||||
ShowLovelaceViewMessage,
|
ShowLovelaceViewMessage,
|
||||||
} from "../../../../src/cast/receiver_messages";
|
} from "../../../../src/cast/receiver_messages";
|
||||||
import {
|
import { ReceiverStatusMessage } from "../../../../src/cast/sender_messages";
|
||||||
ReceiverErrorCode,
|
|
||||||
ReceiverErrorMessage,
|
|
||||||
ReceiverStatusMessage,
|
|
||||||
} from "../../../../src/cast/sender_messages";
|
|
||||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||||
import { isNavigationClick } from "../../../../src/common/dom/is-navigation-click";
|
import { isNavigationClick } from "../../../../src/common/dom/is-navigation-click";
|
||||||
import {
|
import {
|
||||||
@@ -44,10 +40,10 @@ export class HcMain extends HassElement {
|
|||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
@state() private _urlPath?: string | null;
|
|
||||||
|
|
||||||
private _unsubLovelace?: UnsubscribeFunc;
|
private _unsubLovelace?: UnsubscribeFunc;
|
||||||
|
|
||||||
|
private _urlPath?: string | null;
|
||||||
|
|
||||||
public processIncomingMessage(msg: HassMessage) {
|
public processIncomingMessage(msg: HassMessage) {
|
||||||
if (msg.type === "connect") {
|
if (msg.type === "connect") {
|
||||||
this._handleConnectMessage(msg);
|
this._handleConnectMessage(msg);
|
||||||
@@ -72,10 +68,8 @@ export class HcMain extends HassElement {
|
|||||||
!this._lovelaceConfig ||
|
!this._lovelaceConfig ||
|
||||||
this._lovelacePath === null ||
|
this._lovelacePath === null ||
|
||||||
// Guard against part of HA not being loaded yet.
|
// Guard against part of HA not being loaded yet.
|
||||||
!this.hass ||
|
(this.hass &&
|
||||||
!this.hass.states ||
|
(!this.hass.states || !this.hass.config || !this.hass.services))
|
||||||
!this.hass.config ||
|
|
||||||
!this.hass.services
|
|
||||||
) {
|
) {
|
||||||
return html`
|
return html`
|
||||||
<hc-launch-screen
|
<hc-launch-screen
|
||||||
@@ -113,7 +107,6 @@ export class HcMain extends HassElement {
|
|||||||
this._sendStatus();
|
this._sendStatus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.addEventListener("dialog-closed", this._dialogClosed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sendStatus(senderId?: string) {
|
private _sendStatus(senderId?: string) {
|
||||||
@@ -125,7 +118,7 @@ export class HcMain extends HassElement {
|
|||||||
|
|
||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
status.hassUrl = this.hass.auth.data.hassUrl;
|
status.hassUrl = this.hass.auth.data.hassUrl;
|
||||||
status.lovelacePath = this._lovelacePath;
|
status.lovelacePath = this._lovelacePath!;
|
||||||
status.urlPath = this._urlPath;
|
status.urlPath = this._urlPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,30 +131,6 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sendError(
|
|
||||||
error_code: number,
|
|
||||||
error_message: string,
|
|
||||||
senderId?: string
|
|
||||||
) {
|
|
||||||
const error: ReceiverErrorMessage = {
|
|
||||||
type: "receiver_error",
|
|
||||||
error_code,
|
|
||||||
error_message,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (senderId) {
|
|
||||||
this.sendMessage(senderId, error);
|
|
||||||
} else {
|
|
||||||
for (const sender of castContext.getSenders()) {
|
|
||||||
this.sendMessage(sender.id, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _dialogClosed = () => {
|
|
||||||
document.body.setAttribute("style", "overflow-y: auto !important");
|
|
||||||
};
|
|
||||||
|
|
||||||
private async _handleGetStatusMessage(msg: GetStatusMessage) {
|
private async _handleGetStatusMessage(msg: GetStatusMessage) {
|
||||||
this._sendStatus(msg.senderId!);
|
this._sendStatus(msg.senderId!);
|
||||||
}
|
}
|
||||||
@@ -180,18 +149,14 @@ export class HcMain extends HassElement {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const errorMessage = this._getErrorMessage(err);
|
this._error = this._getErrorMessage(err);
|
||||||
this._error = errorMessage;
|
|
||||||
this._sendError(err, errorMessage);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let connection;
|
let connection;
|
||||||
try {
|
try {
|
||||||
connection = await createConnection({ auth });
|
connection = await createConnection({ auth });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const errorMessage = this._getErrorMessage(err);
|
this._error = this._getErrorMessage(err);
|
||||||
this._error = errorMessage;
|
|
||||||
this._sendError(err, errorMessage);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
@@ -203,29 +168,24 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _handleShowLovelaceMessage(msg: ShowLovelaceViewMessage) {
|
private async _handleShowLovelaceMessage(msg: ShowLovelaceViewMessage) {
|
||||||
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) {
|
||||||
this._sendStatus(msg.senderId!);
|
this._sendStatus(msg.senderId!);
|
||||||
this._error = "Cannot show Lovelace because we're not connected.";
|
this._error = "Cannot show Lovelace because we're not connected.";
|
||||||
this._sendError(ReceiverErrorCode.NOT_CONNECTED, this._error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._error = undefined;
|
|
||||||
if (msg.urlPath === "lovelace") {
|
if (msg.urlPath === "lovelace") {
|
||||||
msg.urlPath = null;
|
msg.urlPath = null;
|
||||||
}
|
}
|
||||||
this._lovelacePath = msg.viewPath;
|
|
||||||
if (!this._unsubLovelace || this._urlPath !== msg.urlPath) {
|
if (!this._unsubLovelace || this._urlPath !== msg.urlPath) {
|
||||||
this._urlPath = msg.urlPath;
|
this._urlPath = msg.urlPath;
|
||||||
this._lovelaceConfig = undefined;
|
|
||||||
if (this._unsubLovelace) {
|
if (this._unsubLovelace) {
|
||||||
this._unsubLovelace();
|
this._unsubLovelace();
|
||||||
}
|
}
|
||||||
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)
|
||||||
: getLegacyLovelaceCollection(this.hass.connection);
|
: getLegacyLovelaceCollection(this.hass!.connection);
|
||||||
// We first do a single refresh because we need to check if there is LL
|
// We first do a single refresh because we need to check if there is LL
|
||||||
// configuration.
|
// configuration.
|
||||||
try {
|
try {
|
||||||
@@ -234,16 +194,8 @@ export class HcMain extends HassElement {
|
|||||||
this._handleNewLovelaceConfig(lovelaceConfig)
|
this._handleNewLovelaceConfig(lovelaceConfig)
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (
|
// eslint-disable-next-line
|
||||||
atLeastVersion(this.hass.connection.haVersion, 0, 107) &&
|
console.log("Error fetching Lovelace configuration", err, msg);
|
||||||
err.code !== "config_not_found"
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log("Error fetching Lovelace configuration", err, msg);
|
|
||||||
this._error = `Error fetching Lovelace configuration: ${err.message}`;
|
|
||||||
this._sendError(ReceiverErrorCode.FETCH_CONFIG_FAILED, this._error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Generate a Lovelace config.
|
// Generate a Lovelace config.
|
||||||
this._unsubLovelace = () => undefined;
|
this._unsubLovelace = () => undefined;
|
||||||
await this._generateLovelaceConfig();
|
await this._generateLovelaceConfig();
|
||||||
@@ -258,6 +210,8 @@ export class HcMain extends HassElement {
|
|||||||
loadLovelaceResources(resources, this.hass!.auth.data.hassUrl);
|
loadLovelaceResources(resources, this.hass!.auth.data.hassUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this._showDemo = false;
|
||||||
|
this._lovelacePath = msg.viewPath;
|
||||||
|
|
||||||
this._sendStatus();
|
this._sendStatus();
|
||||||
}
|
}
|
||||||
@@ -278,7 +232,7 @@ export class HcMain extends HassElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _handleNewLovelaceConfig(lovelaceConfig: LovelaceConfig) {
|
private _handleNewLovelaceConfig(lovelaceConfig: LovelaceConfig) {
|
||||||
castContext.setApplicationState(lovelaceConfig.title || "");
|
castContext.setApplicationState(lovelaceConfig.title!);
|
||||||
this._lovelaceConfig = lovelaceConfig;
|
this._lovelaceConfig = lovelaceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import "web-animations-js/web-animations-next-lite.min";
|
||||||
import "../../../src/resources/ha-style";
|
import "../../../src/resources/ha-style";
|
||||||
import "../../../src/resources/roboto";
|
import "../../../src/resources/roboto";
|
||||||
import "./layout/hc-lovelace";
|
import "./layout/hc-lovelace";
|
||||||
|
@@ -194,7 +194,7 @@ export const demoLovelaceJimpower: DemoConfig["lovelace"] = () => ({
|
|||||||
type: "state-icon",
|
type: "state-icon",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "group.downstairs_lights",
|
entity_id: "group.downstairs_lights",
|
||||||
},
|
},
|
||||||
service: "homeassistant.toggle",
|
service: "homeassistant.toggle",
|
||||||
|
@@ -377,7 +377,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "AC bed",
|
name: "AC bed",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "script.air_cleaner_quiet",
|
entity_id: "script.air_cleaner_quiet",
|
||||||
},
|
},
|
||||||
service: "script.turn_on",
|
service: "script.turn_on",
|
||||||
@@ -390,7 +390,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "AC bed",
|
name: "AC bed",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "script.air_cleaner_auto",
|
entity_id: "script.air_cleaner_auto",
|
||||||
},
|
},
|
||||||
service: "script.turn_on",
|
service: "script.turn_on",
|
||||||
@@ -403,7 +403,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "AC bed",
|
name: "AC bed",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "script.air_cleaner_turbo",
|
entity_id: "script.air_cleaner_turbo",
|
||||||
},
|
},
|
||||||
service: "script.turn_on",
|
service: "script.turn_on",
|
||||||
@@ -416,7 +416,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "AC",
|
name: "AC",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "script.ac_off",
|
entity_id: "script.ac_off",
|
||||||
},
|
},
|
||||||
service: "script.turn_on",
|
service: "script.turn_on",
|
||||||
@@ -429,7 +429,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
name: "AC",
|
name: "AC",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "script.ac_on",
|
entity_id: "script.ac_on",
|
||||||
},
|
},
|
||||||
service: "script.turn_on",
|
service: "script.turn_on",
|
||||||
@@ -629,7 +629,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
entity: "scene.morning_lights",
|
entity: "scene.morning_lights",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "scene.morning_lights",
|
entity_id: "scene.morning_lights",
|
||||||
},
|
},
|
||||||
service: "scene.turn_on",
|
service: "scene.turn_on",
|
||||||
@@ -641,7 +641,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
entity: "scene.movie_time",
|
entity: "scene.movie_time",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "scene.movie_time",
|
entity_id: "scene.movie_time",
|
||||||
},
|
},
|
||||||
service: "scene.turn_on",
|
service: "scene.turn_on",
|
||||||
@@ -702,7 +702,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
entity: "light.downstairs_lights",
|
entity: "light.downstairs_lights",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "light.downstairs_lights",
|
entity_id: "light.downstairs_lights",
|
||||||
},
|
},
|
||||||
service: "light.toggle",
|
service: "light.toggle",
|
||||||
@@ -714,7 +714,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
|||||||
entity: "light.upstairs_lights",
|
entity: "light.upstairs_lights",
|
||||||
tap_action: {
|
tap_action: {
|
||||||
action: "call-service",
|
action: "call-service",
|
||||||
data: {
|
service_data: {
|
||||||
entity_id: "light.upstairs_lights",
|
entity_id: "light.upstairs_lights",
|
||||||
},
|
},
|
||||||
service: "light.toggle",
|
service: "light.toggle",
|
||||||
|
@@ -2,3 +2,8 @@ import "../../src/resources/ha-style";
|
|||||||
import "../../src/resources/roboto";
|
import "../../src/resources/roboto";
|
||||||
import "../../src/resources/safari-14-attachshadow-patch";
|
import "../../src/resources/safari-14-attachshadow-patch";
|
||||||
import "./ha-demo";
|
import "./ha-demo";
|
||||||
|
|
||||||
|
/* polyfill for paper-dropdown */
|
||||||
|
setTimeout(() => {
|
||||||
|
import("web-animations-js/web-animations-next-lite.min");
|
||||||
|
}, 1000);
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
import { format, startOfToday, startOfTomorrow } from "date-fns/esm";
|
import { format, startOfToday, startOfTomorrow } from "date-fns";
|
||||||
import { EnergySolarForecasts } from "../../../src/data/energy";
|
import { EnergySolarForecasts } from "../../../src/data/energy";
|
||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
@@ -82,9 +82,6 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
|
|||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
hass.mockWS("energy/info", () => ({ cost_sensors: [] }));
|
hass.mockWS("energy/info", () => ({ cost_sensors: [] }));
|
||||||
hass.mockWS("energy/fossil_energy_consumption", ({ period }) => ({
|
|
||||||
start: period === "month" ? 250 : period === "day" ? 10 : 2,
|
|
||||||
}));
|
|
||||||
const todayString = format(startOfToday(), "yyyy-MM-dd");
|
const todayString = format(startOfToday(), "yyyy-MM-dd");
|
||||||
const tomorrowString = format(startOfTomorrow(), "yyyy-MM-dd");
|
const tomorrowString = format(startOfTomorrow(), "yyyy-MM-dd");
|
||||||
hass.mockWS(
|
hass.mockWS(
|
||||||
|
@@ -31,7 +31,7 @@ export const mockHassioSupervisor = (hass: MockHomeAssistant) => {
|
|||||||
version_latest: "3.6.2",
|
version_latest: "3.6.2",
|
||||||
update_available: false,
|
update_available: false,
|
||||||
repository: "a0d7b954",
|
repository: "a0d7b954",
|
||||||
icon: false,
|
icon: true,
|
||||||
logo: true,
|
logo: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -1,10 +1,4 @@
|
|||||||
import {
|
import { addHours, differenceInHours, endOfDay } from "date-fns";
|
||||||
addDays,
|
|
||||||
addHours,
|
|
||||||
addMonths,
|
|
||||||
differenceInHours,
|
|
||||||
endOfDay,
|
|
||||||
} from "date-fns/esm";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { StatisticValue } from "../../../src/data/history";
|
import { StatisticValue } from "../../../src/data/history";
|
||||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
@@ -76,7 +70,6 @@ const generateMeanStatistics = (
|
|||||||
id: string,
|
id: string,
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
|
||||||
initValue: number,
|
initValue: number,
|
||||||
maxDiff: number
|
maxDiff: number
|
||||||
) => {
|
) => {
|
||||||
@@ -91,7 +84,6 @@ const generateMeanStatistics = (
|
|||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
statistic_id: id,
|
||||||
start: currentDate.toISOString(),
|
start: currentDate.toISOString(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean,
|
mean,
|
||||||
min: mean - Math.random() * maxDiff,
|
min: mean - Math.random() * maxDiff,
|
||||||
max: mean + Math.random() * maxDiff,
|
max: mean + Math.random() * maxDiff,
|
||||||
@@ -100,12 +92,7 @@ const generateMeanStatistics = (
|
|||||||
sum: null,
|
sum: null,
|
||||||
});
|
});
|
||||||
lastVal = mean;
|
lastVal = mean;
|
||||||
currentDate =
|
currentDate = addHours(currentDate, 1);
|
||||||
period === "day"
|
|
||||||
? addDays(currentDate, 1)
|
|
||||||
: period === "month"
|
|
||||||
? addMonths(currentDate, 1)
|
|
||||||
: addHours(currentDate, 1);
|
|
||||||
}
|
}
|
||||||
return statistics;
|
return statistics;
|
||||||
};
|
};
|
||||||
@@ -114,7 +101,6 @@ const generateSumStatistics = (
|
|||||||
id: string,
|
id: string,
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
|
||||||
initValue: number,
|
initValue: number,
|
||||||
maxDiff: number
|
maxDiff: number
|
||||||
) => {
|
) => {
|
||||||
@@ -129,7 +115,6 @@ const generateSumStatistics = (
|
|||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
statistic_id: id,
|
||||||
start: currentDate.toISOString(),
|
start: currentDate.toISOString(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean: null,
|
mean: null,
|
||||||
min: null,
|
min: null,
|
||||||
max: null,
|
max: null,
|
||||||
@@ -137,12 +122,7 @@ const generateSumStatistics = (
|
|||||||
state: initValue + sum,
|
state: initValue + sum,
|
||||||
sum,
|
sum,
|
||||||
});
|
});
|
||||||
currentDate =
|
currentDate = addHours(currentDate, 1);
|
||||||
period === "day"
|
|
||||||
? addDays(currentDate, 1)
|
|
||||||
: period === "month"
|
|
||||||
? addMonths(currentDate, 1)
|
|
||||||
: addHours(currentDate, 1);
|
|
||||||
}
|
}
|
||||||
return statistics;
|
return statistics;
|
||||||
};
|
};
|
||||||
@@ -151,7 +131,6 @@ const generateCurvedStatistics = (
|
|||||||
id: string,
|
id: string,
|
||||||
start: Date,
|
start: Date,
|
||||||
end: Date,
|
end: Date,
|
||||||
_period: "5minute" | "hour" | "day" | "month" = "hour",
|
|
||||||
initValue: number,
|
initValue: number,
|
||||||
maxDiff: number,
|
maxDiff: number,
|
||||||
metered: boolean
|
metered: boolean
|
||||||
@@ -170,7 +149,6 @@ const generateCurvedStatistics = (
|
|||||||
statistics.push({
|
statistics.push({
|
||||||
statistic_id: id,
|
statistic_id: id,
|
||||||
start: currentDate.toISOString(),
|
start: currentDate.toISOString(),
|
||||||
end: currentDate.toISOString(),
|
|
||||||
mean: null,
|
mean: null,
|
||||||
min: null,
|
min: null,
|
||||||
max: null,
|
max: null,
|
||||||
@@ -189,38 +167,11 @@ const generateCurvedStatistics = (
|
|||||||
|
|
||||||
const statisticsFunctions: Record<
|
const statisticsFunctions: Record<
|
||||||
string,
|
string,
|
||||||
(
|
(id: string, start: Date, end: Date) => StatisticValue[]
|
||||||
id: string,
|
|
||||||
start: Date,
|
|
||||||
end: Date,
|
|
||||||
period: "5minute" | "hour" | "day" | "month"
|
|
||||||
) => StatisticValue[]
|
|
||||||
> = {
|
> = {
|
||||||
"sensor.energy_consumption_tarif_1": (
|
"sensor.energy_consumption_tarif_1": (id: string, start: Date, end: Date) => {
|
||||||
id: string,
|
|
||||||
start: Date,
|
|
||||||
end: Date,
|
|
||||||
period = "hour"
|
|
||||||
) => {
|
|
||||||
if (period !== "hour") {
|
|
||||||
return generateSumStatistics(
|
|
||||||
id,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
period === "day" ? 17 : 504
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
|
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
|
||||||
const morningLow = generateSumStatistics(
|
const morningLow = generateSumStatistics(id, start, morningEnd, 0, 0.7);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
morningEnd,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0.7
|
|
||||||
);
|
|
||||||
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
||||||
const morningFinalVal = morningLow.length
|
const morningFinalVal = morningLow.length
|
||||||
? morningLow[morningLow.length - 1].sum!
|
? morningLow[morningLow.length - 1].sum!
|
||||||
@@ -229,7 +180,6 @@ const statisticsFunctions: Record<
|
|||||||
id,
|
id,
|
||||||
morningEnd,
|
morningEnd,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
period,
|
|
||||||
morningFinalVal,
|
morningFinalVal,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
@@ -237,71 +187,39 @@ const statisticsFunctions: Record<
|
|||||||
id,
|
id,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
end,
|
end,
|
||||||
period,
|
|
||||||
morningFinalVal,
|
morningFinalVal,
|
||||||
0.7
|
0.7
|
||||||
);
|
);
|
||||||
return [...morningLow, ...empty, ...eveningLow];
|
return [...morningLow, ...empty, ...eveningLow];
|
||||||
},
|
},
|
||||||
"sensor.energy_consumption_tarif_2": (
|
"sensor.energy_consumption_tarif_2": (id: string, start: Date, end: Date) => {
|
||||||
id: string,
|
|
||||||
start: Date,
|
|
||||||
end: Date,
|
|
||||||
period = "hour"
|
|
||||||
) => {
|
|
||||||
if (period !== "hour") {
|
|
||||||
return generateSumStatistics(
|
|
||||||
id,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
period === "day" ? 17 : 504
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const morningEnd = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
const morningEnd = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
||||||
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
|
||||||
const highTarif = generateSumStatistics(
|
const highTarif = generateSumStatistics(
|
||||||
id,
|
id,
|
||||||
morningEnd,
|
morningEnd,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
period,
|
|
||||||
0,
|
0,
|
||||||
0.3
|
0.3
|
||||||
);
|
);
|
||||||
const highTarifFinalVal = highTarif.length
|
const highTarifFinalVal = highTarif.length
|
||||||
? highTarif[highTarif.length - 1].sum!
|
? highTarif[highTarif.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(id, start, morningEnd, period, 0, 0);
|
const morning = generateSumStatistics(id, start, morningEnd, 0, 0);
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
id,
|
||||||
eveningStart,
|
eveningStart,
|
||||||
end,
|
end,
|
||||||
period,
|
|
||||||
highTarifFinalVal,
|
highTarifFinalVal,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
return [...morning, ...highTarif, ...evening];
|
return [...morning, ...highTarif, ...evening];
|
||||||
},
|
},
|
||||||
"sensor.energy_production_tarif_1": (id, start, end, period = "hour") =>
|
"sensor.energy_production_tarif_1": (id, start, end) =>
|
||||||
generateSumStatistics(id, start, end, period, 0, 0),
|
generateSumStatistics(id, start, end, 0, 0),
|
||||||
"sensor.energy_production_tarif_1_compensation": (
|
"sensor.energy_production_tarif_1_compensation": (id, start, end) =>
|
||||||
id,
|
generateSumStatistics(id, start, end, 0, 0),
|
||||||
start,
|
"sensor.energy_production_tarif_2": (id, start, end) => {
|
||||||
end,
|
|
||||||
period = "hour"
|
|
||||||
) => generateSumStatistics(id, start, end, period, 0, 0),
|
|
||||||
"sensor.energy_production_tarif_2": (id, start, end, period = "hour") => {
|
|
||||||
if (period !== "hour") {
|
|
||||||
return generateSumStatistics(
|
|
||||||
id,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
period === "day" ? 17 : 504
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const productionStart = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
const productionStart = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
||||||
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
|
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
|
||||||
const dayEnd = new Date(endOfDay(productionEnd));
|
const dayEnd = new Date(endOfDay(productionEnd));
|
||||||
@@ -309,7 +227,6 @@ const statisticsFunctions: Record<
|
|||||||
id,
|
id,
|
||||||
productionStart,
|
productionStart,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
period,
|
|
||||||
0,
|
0,
|
||||||
0.15,
|
0.15,
|
||||||
true
|
true
|
||||||
@@ -317,43 +234,18 @@ const statisticsFunctions: Record<
|
|||||||
const productionFinalVal = production.length
|
const productionFinalVal = production.length
|
||||||
? production[production.length - 1].sum!
|
? production[production.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(
|
const morning = generateSumStatistics(id, start, productionStart, 0, 0);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
productionStart,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
id,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
dayEnd,
|
dayEnd,
|
||||||
period,
|
|
||||||
productionFinalVal,
|
productionFinalVal,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const rest = generateSumStatistics(
|
const rest = generateSumStatistics(id, dayEnd, end, productionFinalVal, 1);
|
||||||
id,
|
|
||||||
dayEnd,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
productionFinalVal,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
return [...morning, ...production, ...evening, ...rest];
|
return [...morning, ...production, ...evening, ...rest];
|
||||||
},
|
},
|
||||||
"sensor.solar_production": (id, start, end, period = "hour") => {
|
"sensor.solar_production": (id, start, end) => {
|
||||||
if (period !== "hour") {
|
|
||||||
return generateSumStatistics(
|
|
||||||
id,
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
period === "day" ? 17 : 504
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const productionStart = new Date(start.getTime() + 7 * 60 * 60 * 1000);
|
const productionStart = new Date(start.getTime() + 7 * 60 * 60 * 1000);
|
||||||
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
|
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
|
||||||
const dayEnd = new Date(endOfDay(productionEnd));
|
const dayEnd = new Date(endOfDay(productionEnd));
|
||||||
@@ -361,7 +253,6 @@ const statisticsFunctions: Record<
|
|||||||
id,
|
id,
|
||||||
productionStart,
|
productionStart,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
period,
|
|
||||||
0,
|
0,
|
||||||
0.3,
|
0.3,
|
||||||
true
|
true
|
||||||
@@ -369,32 +260,19 @@ const statisticsFunctions: Record<
|
|||||||
const productionFinalVal = production.length
|
const productionFinalVal = production.length
|
||||||
? production[production.length - 1].sum!
|
? production[production.length - 1].sum!
|
||||||
: 0;
|
: 0;
|
||||||
const morning = generateSumStatistics(
|
const morning = generateSumStatistics(id, start, productionStart, 0, 0);
|
||||||
id,
|
|
||||||
start,
|
|
||||||
productionStart,
|
|
||||||
period,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
const evening = generateSumStatistics(
|
const evening = generateSumStatistics(
|
||||||
id,
|
id,
|
||||||
productionEnd,
|
productionEnd,
|
||||||
dayEnd,
|
dayEnd,
|
||||||
period,
|
|
||||||
productionFinalVal,
|
productionFinalVal,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const rest = generateSumStatistics(
|
const rest = generateSumStatistics(id, dayEnd, end, productionFinalVal, 2);
|
||||||
id,
|
|
||||||
dayEnd,
|
|
||||||
end,
|
|
||||||
period,
|
|
||||||
productionFinalVal,
|
|
||||||
2
|
|
||||||
);
|
|
||||||
return [...morning, ...production, ...evening, ...rest];
|
return [...morning, ...production, ...evening, ...rest];
|
||||||
},
|
},
|
||||||
|
"sensor.grid_fossil_fuel_percentage": (id, start, end) =>
|
||||||
|
generateMeanStatistics(id, start, end, 35, 1.3),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockHistory = (mockHass: MockHomeAssistant) => {
|
export const mockHistory = (mockHass: MockHomeAssistant) => {
|
||||||
@@ -469,7 +347,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||||||
mockHass.mockWS("history/list_statistic_ids", () => []);
|
mockHass.mockWS("history/list_statistic_ids", () => []);
|
||||||
mockHass.mockWS(
|
mockHass.mockWS(
|
||||||
"history/statistics_during_period",
|
"history/statistics_during_period",
|
||||||
({ statistic_ids, start_time, end_time, period }, hass) => {
|
({ statistic_ids, start_time, end_time }, hass) => {
|
||||||
const start = new Date(start_time);
|
const start = new Date(start_time);
|
||||||
const end = end_time ? new Date(end_time) : new Date();
|
const end = end_time ? new Date(end_time) : new Date();
|
||||||
|
|
||||||
@@ -477,7 +355,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||||||
|
|
||||||
statistic_ids.forEach((id: string) => {
|
statistic_ids.forEach((id: string) => {
|
||||||
if (id in statisticsFunctions) {
|
if (id in statisticsFunctions) {
|
||||||
statistics[id] = statisticsFunctions[id](id, start, end, period);
|
statistics[id] = statisticsFunctions[id](id, start, end);
|
||||||
} else {
|
} else {
|
||||||
const entityState = hass.states[id];
|
const entityState = hass.states[id];
|
||||||
const state = entityState ? Number(entityState.state) : 1;
|
const state = entityState ? Number(entityState.state) : 1;
|
||||||
@@ -487,7 +365,6 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||||||
id,
|
id,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
|
||||||
state,
|
state,
|
||||||
state * (state > 80 ? 0.01 : 0.05)
|
state * (state > 80 ? 0.01 : 0.05)
|
||||||
)
|
)
|
||||||
@@ -495,7 +372,6 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||||||
id,
|
id,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
period,
|
|
||||||
state,
|
state,
|
||||||
state * (state > 80 ? 0.05 : 0.1)
|
state * (state > 80 ? 0.05 : 0.1)
|
||||||
);
|
);
|
||||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 44 KiB |
Binary file not shown.
Before Width: | Height: | Size: 35 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
Before Width: | Height: | Size: 147 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
TARGET_LABEL="needs design preview"
|
TARGET_LABEL="Needs gallery preview"
|
||||||
|
|
||||||
if [[ "$NETLIFY" != "true" ]]; then
|
if [[ "$NETLIFY" != "true" ]]; then
|
||||||
echo "This script can only be run on Netlify"
|
echo "This script can only be run on Netlify"
|
||||||
@@ -13,23 +13,23 @@ function createStatus() {
|
|||||||
target_url="$3"
|
target_url="$3"
|
||||||
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/repos/home-assistant/frontend/statuses/$COMMIT_REF" \
|
"https://api.github.com/repos/home-assistant/frontend/statuses/$COMMIT_REF" \
|
||||||
-d '{"state": "'"${state}"'", "context": "Netlify/Design Preview Build", "description": "'"$description"'", "target_url": "'"$target_url"'"}'
|
-d '{"state": "'"${state}"'", "context": "Netlify/Gallery Preview Build", "description": "'"$description"'", "target_url": "'"$target_url"'"}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if [[ "${PULL_REQUEST}" == "true" ]]; then
|
if [[ "${PULL_REQUEST}" == "false" ]]; then
|
||||||
|
gulp build-gallery
|
||||||
|
else
|
||||||
if [[ "$(curl -sSLf -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
if [[ "$(curl -sSLf -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/repos/home-assistant/frontend/pulls/${REVIEW_ID}" | jq '.labels[].name' -r)" =~ "$TARGET_LABEL" ]]; then
|
"https://api.github.com/repos/home-assistant/frontend/pulls/${REVIEW_ID}" | jq '.labels[].name' -r)" =~ "$TARGET_LABEL" ]]; then
|
||||||
createStatus "pending" "Building design preview" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
createStatus "pending" "Building gallery preview" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
||||||
gulp build-gallery
|
gulp build-gallery
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
createStatus "success" "Build complete" "$DEPLOY_PRIME_URL"
|
createStatus "success" "Build complete" "$DEPLOY_URL"
|
||||||
else
|
else
|
||||||
createStatus "error" "Build failed" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
createStatus "error" "Build failed" "https://app.netlify.com/sites/home-assistant-gallery/deploys/$BUILD_ID"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
createStatus "success" "Build was not requested by PR label"
|
createStatus "success" "Build was not requested by PR label"
|
||||||
fi
|
fi
|
||||||
elif [[ "$INCOMING_HOOK_BODY" == "NIGHTLY" ]]; then
|
|
||||||
gulp build-gallery
|
|
||||||
fi
|
fi
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
module.exports = [
|
|
||||||
{
|
|
||||||
// This section has no header and so all page links are shown directly in the sidebar
|
|
||||||
category: "concepts",
|
|
||||||
pages: ["home"],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
category: "lovelace",
|
|
||||||
// Label for in the sidebar
|
|
||||||
header: "Lovelace",
|
|
||||||
// Specify order of pages. Any pages in the category folder but not listed here will
|
|
||||||
// automatically be added after the pages listed here.
|
|
||||||
pages: ["introduction"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "automation",
|
|
||||||
header: "Automation",
|
|
||||||
pages: [
|
|
||||||
"editor-trigger",
|
|
||||||
"editor-condition",
|
|
||||||
"editor-action",
|
|
||||||
"trace",
|
|
||||||
"trace-timeline",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "components",
|
|
||||||
header: "Components",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "more-info",
|
|
||||||
header: "More Info dialogs",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "misc",
|
|
||||||
header: "Miscelaneous",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "brand",
|
|
||||||
header: "Brand",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "user-test",
|
|
||||||
header: "Users",
|
|
||||||
pages: ["user-types", "configuration-menu"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: "design.home-assistant.io",
|
|
||||||
header: "About",
|
|
||||||
},
|
|
||||||
];
|
|
@@ -3,7 +3,6 @@ import { html, LitElement, css, TemplateResult } from "lit";
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
||||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||||
import "../../../src/components/ha-card";
|
|
||||||
|
|
||||||
@customElement("demo-black-white-row")
|
@customElement("demo-black-white-row")
|
||||||
class DemoBlackWhiteRow extends LitElement {
|
class DemoBlackWhiteRow extends LitElement {
|
||||||
@@ -59,12 +58,10 @@ class DemoBlackWhiteRow extends LitElement {
|
|||||||
default_theme: "default",
|
default_theme: "default",
|
||||||
default_dark_theme: "default",
|
default_dark_theme: "default",
|
||||||
themes: {},
|
themes: {},
|
||||||
darkMode: true,
|
darkMode: false,
|
||||||
theme: "default",
|
|
||||||
},
|
},
|
||||||
undefined,
|
"default",
|
||||||
undefined,
|
{ dark: true }
|
||||||
true
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
129
gallery/src/components/demo-card.js
Normal file
129
gallery/src/components/demo-card.js
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
|
/* eslint-plugin-disable lit */
|
||||||
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
import { load } from "js-yaml";
|
||||||
|
import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element";
|
||||||
|
|
||||||
|
class DemoCard extends PolymerElement {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
h2 small {
|
||||||
|
font-size: 0.5em;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
#card {
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
width: 400px;
|
||||||
|
margin: 0 16px;
|
||||||
|
overflow: auto;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
.root {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<h2>
|
||||||
|
[[config.heading]]
|
||||||
|
<template is="dom-if" if="[[_size]]">
|
||||||
|
<small>(size [[_size]])</small>
|
||||||
|
</template>
|
||||||
|
</h2>
|
||||||
|
<div class="root">
|
||||||
|
<div id="card"></div>
|
||||||
|
<template is="dom-if" if="[[showConfig]]">
|
||||||
|
<pre>[[_trim(config.config)]]</pre>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: {
|
||||||
|
type: Object,
|
||||||
|
observer: "_hassChanged",
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
type: Object,
|
||||||
|
observer: "_configChanged",
|
||||||
|
},
|
||||||
|
showConfig: Boolean,
|
||||||
|
_size: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
_configChanged(config) {
|
||||||
|
const card = this.$.card;
|
||||||
|
while (card.lastChild) {
|
||||||
|
card.removeChild(card.lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
const el = this._createCardElement(load(config.config)[0]);
|
||||||
|
card.appendChild(el);
|
||||||
|
this._getSize(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _getSize(el) {
|
||||||
|
await customElements.whenDefined(el.localName);
|
||||||
|
|
||||||
|
if (!("getCardSize" in el)) {
|
||||||
|
this._size = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._size = await el.getCardSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
_createCardElement(cardConfig) {
|
||||||
|
const element = createCardElement(cardConfig);
|
||||||
|
if (this.hass) {
|
||||||
|
element.hass = this.hass;
|
||||||
|
}
|
||||||
|
element.addEventListener(
|
||||||
|
"ll-rebuild",
|
||||||
|
(ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._rebuildCard(element, cardConfig);
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rebuildCard(cardElToReplace, config) {
|
||||||
|
const newCardEl = this._createCardElement(config);
|
||||||
|
cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hassChanged(hass) {
|
||||||
|
const card = this.$.card.lastChild;
|
||||||
|
if (card) card.hass = hass;
|
||||||
|
}
|
||||||
|
|
||||||
|
_trim(config) {
|
||||||
|
return config.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("demo-card", DemoCard);
|
@@ -1,129 +0,0 @@
|
|||||||
import { load } from "js-yaml";
|
|
||||||
import { html, css, LitElement, PropertyValues } from "lit";
|
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
|
||||||
import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element";
|
|
||||||
import { HomeAssistant } from "../../../src/types";
|
|
||||||
|
|
||||||
export interface DemoCardConfig {
|
|
||||||
heading: string;
|
|
||||||
config: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("demo-card")
|
|
||||||
class DemoCard extends LitElement {
|
|
||||||
@property() public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property() public config!: DemoCardConfig;
|
|
||||||
|
|
||||||
@property() public showConfig = false;
|
|
||||||
|
|
||||||
@state() private _size?: number;
|
|
||||||
|
|
||||||
@query("#card") private _card!: HTMLElement;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return html`
|
|
||||||
<h2>
|
|
||||||
${this.config.heading}
|
|
||||||
${this._size !== undefined
|
|
||||||
? html`<small>(size ${this._size})</small>`
|
|
||||||
: ""}
|
|
||||||
</h2>
|
|
||||||
<div class="root">
|
|
||||||
<div id="card"></div>
|
|
||||||
${this.showConfig ? html`<pre>${this.config.config.trim()}</pre>` : ""}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
updated(changedProps: PropertyValues) {
|
|
||||||
super.updated(changedProps);
|
|
||||||
|
|
||||||
if (changedProps.has("config")) {
|
|
||||||
const card = this._card;
|
|
||||||
while (card.lastChild) {
|
|
||||||
card.removeChild(card.lastChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
const el = this._createCardElement((load(this.config.config) as any)[0]);
|
|
||||||
card.appendChild(el);
|
|
||||||
this._getSize(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProps.has("hass")) {
|
|
||||||
const card = this._card.lastChild;
|
|
||||||
if (card) {
|
|
||||||
(card as any).hass = this.hass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _getSize(el) {
|
|
||||||
await customElements.whenDefined(el.localName);
|
|
||||||
|
|
||||||
if (!("getCardSize" in el)) {
|
|
||||||
this._size = undefined;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._size = await el.getCardSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
_createCardElement(cardConfig) {
|
|
||||||
const element = createCardElement(cardConfig);
|
|
||||||
if (this.hass) {
|
|
||||||
element.hass = this.hass;
|
|
||||||
}
|
|
||||||
element.addEventListener(
|
|
||||||
"ll-rebuild",
|
|
||||||
(ev) => {
|
|
||||||
ev.stopPropagation();
|
|
||||||
this._rebuildCard(element, cardConfig);
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
_rebuildCard(cardElToReplace, config) {
|
|
||||||
const newCardEl = this._createCardElement(config);
|
|
||||||
cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace);
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
.root {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
margin: 0 0 20px;
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
h2 small {
|
|
||||||
font-size: 0.5em;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
#card {
|
|
||||||
max-width: 400px;
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
width: 400px;
|
|
||||||
margin: 0 16px;
|
|
||||||
overflow: auto;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
.root {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-card": DemoCard;
|
|
||||||
}
|
|
||||||
}
|
|
83
gallery/src/components/demo-cards.js
Normal file
83
gallery/src/components/demo-cards.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
|
/* eslint-plugin-disable lit */
|
||||||
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
||||||
|
import "../../../src/components/ha-formfield";
|
||||||
|
import "../../../src/components/ha-switch";
|
||||||
|
import "./demo-card";
|
||||||
|
|
||||||
|
class DemoCards extends PolymerElement {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
#container {
|
||||||
|
min-height: calc(100vh - 128px);
|
||||||
|
background: var(--primary-background-color);
|
||||||
|
}
|
||||||
|
.cards {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
demo-card {
|
||||||
|
margin: 16px 16px 32px;
|
||||||
|
}
|
||||||
|
app-toolbar {
|
||||||
|
background-color: var(--light-primary-color);
|
||||||
|
}
|
||||||
|
.filters {
|
||||||
|
margin-left: 60px;
|
||||||
|
}
|
||||||
|
ha-formfield {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<app-toolbar>
|
||||||
|
<div class="filters">
|
||||||
|
<ha-formfield label="Show config">
|
||||||
|
<ha-switch checked="[[_showConfig]]" on-change="_showConfigToggled">
|
||||||
|
</ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield label="Dark theme">
|
||||||
|
<ha-switch on-change="_darkThemeToggled"> </ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
|
</div>
|
||||||
|
</app-toolbar>
|
||||||
|
<div id="container">
|
||||||
|
<div class="cards">
|
||||||
|
<template is="dom-repeat" items="[[configs]]">
|
||||||
|
<demo-card
|
||||||
|
config="[[item]]"
|
||||||
|
show-config="[[_showConfig]]"
|
||||||
|
hass="[[hass]]"
|
||||||
|
></demo-card>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
configs: Object,
|
||||||
|
hass: Object,
|
||||||
|
_showConfig: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_showConfigToggled(ev) {
|
||||||
|
this._showConfig = ev.target.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
_darkThemeToggled(ev) {
|
||||||
|
applyThemesOnElement(this.$.container, { themes: {} }, "default", {
|
||||||
|
dark: ev.target.checked,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("demo-cards", DemoCards);
|
@@ -1,91 +0,0 @@
|
|||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|
||||||
import { html, css, LitElement } from "lit";
|
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
|
||||||
import "../../../src/components/ha-formfield";
|
|
||||||
import "../../../src/components/ha-switch";
|
|
||||||
import { HomeAssistant } from "../../../src/types";
|
|
||||||
import "./demo-card";
|
|
||||||
import type { DemoCardConfig } from "./demo-card";
|
|
||||||
|
|
||||||
@customElement("demo-cards")
|
|
||||||
class DemoCards extends LitElement {
|
|
||||||
@property() public configs!: DemoCardConfig[];
|
|
||||||
|
|
||||||
@property() public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@state() private _showConfig = false;
|
|
||||||
|
|
||||||
@query("#container") private _container!: HTMLElement;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return html`
|
|
||||||
<app-toolbar>
|
|
||||||
<div class="filters">
|
|
||||||
<ha-formfield label="Show config">
|
|
||||||
<ha-switch
|
|
||||||
.checked=${this._showConfig}
|
|
||||||
@change=${this._showConfigToggled}
|
|
||||||
>
|
|
||||||
</ha-switch>
|
|
||||||
</ha-formfield>
|
|
||||||
<ha-formfield label="Dark theme">
|
|
||||||
<ha-switch @change=${this._darkThemeToggled}> </ha-switch>
|
|
||||||
</ha-formfield>
|
|
||||||
</div>
|
|
||||||
</app-toolbar>
|
|
||||||
<div id="container">
|
|
||||||
<div class="cards">
|
|
||||||
${this.configs.map(
|
|
||||||
(config) => html`
|
|
||||||
<demo-card
|
|
||||||
.config=${config}
|
|
||||||
.showConfig=${this._showConfig}
|
|
||||||
.hass=${this.hass}
|
|
||||||
></demo-card>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
_showConfigToggled(ev) {
|
|
||||||
this._showConfig = ev.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
_darkThemeToggled(ev) {
|
|
||||||
applyThemesOnElement(this._container, { themes: {} } as any, "default", {
|
|
||||||
dark: ev.target.checked,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
.cards {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
demo-card {
|
|
||||||
margin: 16px 16px 32px;
|
|
||||||
}
|
|
||||||
app-toolbar {
|
|
||||||
background-color: var(--light-primary-color);
|
|
||||||
}
|
|
||||||
.filters {
|
|
||||||
margin-left: 60px;
|
|
||||||
}
|
|
||||||
ha-formfield {
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
|
||||||
#container {
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-cards": DemoCards;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
import { html, css } from "lit";
|
|
||||||
import { customElement, property } from "lit/decorators";
|
|
||||||
import { until } from "lit/directives/until";
|
|
||||||
import { HaMarkdown } from "../../../src/components/ha-markdown";
|
|
||||||
import { PAGES } from "../../build/import-pages";
|
|
||||||
|
|
||||||
@customElement("page-description")
|
|
||||||
class PageDescription extends HaMarkdown {
|
|
||||||
@property() public page!: string;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (!PAGES[this.page].description) {
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="heading">
|
|
||||||
<div class="title">
|
|
||||||
${PAGES[this.page].metadata.title || this.page.split("/")[1]}
|
|
||||||
</div>
|
|
||||||
<div class="subtitle">${PAGES[this.page].metadata.subtitle}</div>
|
|
||||||
</div>
|
|
||||||
${until(
|
|
||||||
PAGES[this.page]
|
|
||||||
.description()
|
|
||||||
.then((content) => html`<div class="root">${content}</div>`),
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = [
|
|
||||||
HaMarkdown.styles,
|
|
||||||
css`
|
|
||||||
.heading {
|
|
||||||
padding: 16px;
|
|
||||||
border-bottom: 1px solid var(--secondary-background-color);
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
font-size: 42px;
|
|
||||||
line-height: 56px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
.subtitle {
|
|
||||||
font-size: 18px;
|
|
||||||
line-height: 24px;
|
|
||||||
}
|
|
||||||
.root {
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 16px auto;
|
|
||||||
}
|
|
||||||
.root > *:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
.root > *:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"page-description": PageDescription;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
export const LONG_TEXT = `
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc laoreet velit ut elit volutpat, eget ultrices odio lacinia. In imperdiet malesuada est, nec sagittis metus ultricies quis. Sed nisl ex, convallis porttitor ante quis, hendrerit tristique justo. Mauris pharetra venenatis augue, eu maximus sem cursus in. Quisque sed consequat risus. Suspendisse facilisis ligula a odio consectetur condimentum. Curabitur vehicula elit nec augue mollis, et volutpat massa dictum.
|
|
||||||
|
|
||||||
Nam pellentesque auctor rutrum. Suspendisse elit est, sodales vel diam nec, porttitor faucibus massa. Ut pretium ac orci eu pharetra. Praesent in nibh at magna viverra rutrum eu vitae tortor. Etiam eget sem ex. Fusce tristique odio nec lacus mattis, vitae tempor nunc malesuada. Maecenas faucibus magna vel libero maximus egestas. Vestibulum luctus semper velit, in lobortis risus tempus non. Curabitur bibendum ornare commodo. Quisque commodo neque sit amet tincidunt lacinia. Proin elementum ante velit, eu congue nulla semper quis. Pellentesque consequat vel nunc at scelerisque. Mauris sit amet venenatis diam, blandit viverra leo. Integer commodo laoreet orci.
|
|
||||||
|
|
||||||
Curabitur ipsum tortor, sodales ut augue sed, commodo porttitor libero. Pellentesque molestie vitae mi consectetur tempor. In sed lectus consequat, lobortis neque non, semper ipsum. Etiam eget ex et nibh sagittis pulvinar lacinia ac mauris. Aenean ligula eros, viverra ac nibh at, venenatis semper quam. Sed interdum ligula sit amet massa tincidunt tincidunt. Suspendisse potenti. Aliquam egestas facilisis est, sed faucibus erat scelerisque id. Duis dolor quam, viverra vitae orci euismod, laoreet pellentesque justo. Nunc malesuada non erat at ullamcorper. Mauris eget posuere odio. Vestibulum turpis nunc, pharetra eget ante in, feugiat mollis justo. Proin porttitor, diam nec vulputate pretium, tellus arcu rhoncus turpis, a blandit nisi nulla quis arcu. Nunc ac ullamcorper ligula, nec facilisis leo.
|
|
||||||
|
|
||||||
In vitae eros sollicitudin, iaculis ex eget, egestas orci. Etiam sed pretium lorem. Nam nisi enim, consectetur sit amet semper ac, semper pharetra diam. In pulvinar neque sapien, ac ullamcorper est lacinia a. Etiam tincidunt velit sed diam malesuada, eu ornare ex consectetur. Phasellus in imperdiet tellus. Sed bibendum, dui sit amet fringilla aliquet, enim odio sollicitudin lorem, vel semper turpis mauris vel mauris. Aenean congue magna ac massa cursus, in dictum orci commodo. Pellentesque mollis velit in sollicitudin tincidunt. Vestibulum et efficitur nulla.
|
|
||||||
|
|
||||||
Quisque posuere, velit sed porttitor dapibus, neque augue fringilla felis, eu luctus nisi nisl nec ipsum. Curabitur pellentesque ac lectus eget ultricies. Vestibulum est dolor, lacinia pharetra vulputate a, facilisis a magna. Nam vitae arcu nibh. Praesent finibus blandit ante, ac gravida ex mollis eget. Donec quam est, pulvinar vitae neque ut, bibendum aliquam erat. Nullam mollis arcu at sem tincidunt, in tristique lectus facilisis. Aenean ut lacus vel nisl finibus iaculis non a turpis. Integer eget ipsum ante. Donec nunc neque, vestibulum ac magna ac, posuere scelerisque dui. Pellentesque massa nibh, rhoncus id dolor quis, placerat posuere turpis. Donec aliquet augue nisi, eu finibus dui auctor et. Vestibulum eu varius lorem. Quisque lectus ante, malesuada pretium risus eget, interdum mattis enim.
|
|
||||||
`;
|
|
@@ -119,7 +119,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
params: {
|
params: {
|
||||||
domain: "input_boolean",
|
domain: "input_boolean",
|
||||||
service: "toggle",
|
service: "toggle",
|
||||||
data: {},
|
service_data: {},
|
||||||
target: {
|
target: {
|
||||||
entity_id: ["input_boolean.toggle_4"],
|
entity_id: ["input_boolean.toggle_4"],
|
||||||
},
|
},
|
||||||
@@ -164,7 +164,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
params: {
|
params: {
|
||||||
domain: "input_boolean",
|
domain: "input_boolean",
|
||||||
service: "toggle",
|
service: "toggle",
|
||||||
data: {},
|
service_data: {},
|
||||||
target: {
|
target: {
|
||||||
entity_id: ["input_boolean.toggle_2"],
|
entity_id: ["input_boolean.toggle_2"],
|
||||||
},
|
},
|
||||||
@@ -182,7 +182,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
params: {
|
params: {
|
||||||
domain: "input_boolean",
|
domain: "input_boolean",
|
||||||
service: "toggle",
|
service: "toggle",
|
||||||
data: {},
|
service_data: {},
|
||||||
target: {
|
target: {
|
||||||
entity_id: ["input_boolean.toggle_3"],
|
entity_id: ["input_boolean.toggle_3"],
|
||||||
},
|
},
|
||||||
@@ -200,7 +200,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
params: {
|
params: {
|
||||||
domain: "input_boolean",
|
domain: "input_boolean",
|
||||||
service: "toggle",
|
service: "toggle",
|
||||||
data: {},
|
service_data: {},
|
||||||
target: {
|
target: {
|
||||||
entity_id: ["input_boolean.toggle_4"],
|
entity_id: ["input_boolean.toggle_4"],
|
||||||
},
|
},
|
||||||
@@ -298,11 +298,11 @@ export const basicTrace: DemoTrace = {
|
|||||||
source: "state of input_boolean.toggle_1",
|
source: "state of input_boolean.toggle_1",
|
||||||
entity_id: "automation.toggle_toggles",
|
entity_id: "automation.toggle_toggles",
|
||||||
context_id: "6cfcae368e7b3686fad6c59e83ae76c9",
|
context_id: "6cfcae368e7b3686fad6c59e83ae76c9",
|
||||||
when: 1616647011.240832,
|
when: "2021-03-25T04:36:51.240832+00:00",
|
||||||
domain: "automation",
|
domain: "automation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1616647011.249828,
|
when: "2021-03-25T04:36:51.249828+00:00",
|
||||||
name: "Toggle 4",
|
name: "Toggle 4",
|
||||||
state: "on",
|
state: "on",
|
||||||
entity_id: "input_boolean.toggle_4",
|
entity_id: "input_boolean.toggle_4",
|
||||||
@@ -313,7 +313,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
context_name: "Ensure Party mode",
|
context_name: "Ensure Party mode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1616647011.258947,
|
when: "2021-03-25T04:36:51.258947+00:00",
|
||||||
name: "Toggle 2",
|
name: "Toggle 2",
|
||||||
state: "on",
|
state: "on",
|
||||||
entity_id: "input_boolean.toggle_2",
|
entity_id: "input_boolean.toggle_2",
|
||||||
@@ -324,7 +324,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
context_name: "Ensure Party mode",
|
context_name: "Ensure Party mode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1616647011.261806,
|
when: "2021-03-25T04:36:51.261806+00:00",
|
||||||
name: "Toggle 3",
|
name: "Toggle 3",
|
||||||
state: "off",
|
state: "off",
|
||||||
entity_id: "input_boolean.toggle_3",
|
entity_id: "input_boolean.toggle_3",
|
||||||
@@ -335,7 +335,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
context_name: "Ensure Party mode",
|
context_name: "Ensure Party mode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1616647011.265246,
|
when: "2021-03-25T04:36:51.265246+00:00",
|
||||||
name: "Toggle 4",
|
name: "Toggle 4",
|
||||||
state: "off",
|
state: "off",
|
||||||
entity_id: "input_boolean.toggle_4",
|
entity_id: "input_boolean.toggle_4",
|
||||||
|
@@ -185,11 +185,11 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
"has been triggered by state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
"has been triggered by state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||||
source: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
source: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||||
entity_id: "automation.auto_elgato",
|
entity_id: "automation.auto_elgato",
|
||||||
when: 1615702021.768492,
|
when: "2021-03-14T06:07:01.768492+00:00",
|
||||||
domain: "automation",
|
domain: "automation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1615702021.872187,
|
when: "2021-03-14T06:07:01.872187+00:00",
|
||||||
name: "Elgato Key Light Air",
|
name: "Elgato Key Light Air",
|
||||||
state: "on",
|
state: "on",
|
||||||
entity_id: "light.elgato_key_light_air",
|
entity_id: "light.elgato_key_light_air",
|
||||||
@@ -200,7 +200,7 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
context_name: "Auto Elgato",
|
context_name: "Auto Elgato",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: 1615702073.284505,
|
when: "2021-03-14T06:07:53.284505+00:00",
|
||||||
name: "Elgato Key Light Air",
|
name: "Elgato Key Light Air",
|
||||||
state: "off",
|
state: "off",
|
||||||
entity_id: "light.elgato_key_light_air",
|
entity_id: "light.elgato_key_light_air",
|
||||||
|
@@ -1,22 +1,12 @@
|
|||||||
import { dump } from "js-yaml";
|
import { dump } from "js-yaml";
|
||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import { describeAction } from "../../../../src/data/script_i18n";
|
import { describeAction } from "../../../src/data/script_i18n";
|
||||||
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";
|
|
||||||
|
|
||||||
const ENTITIES = [
|
const actions = [
|
||||||
getEntity("scene", "kitchen_morning", "scening", {
|
|
||||||
friendly_name: "Kitchen Morning",
|
|
||||||
}),
|
|
||||||
getEntity("media_player", "kitchen", "playing", {
|
|
||||||
friendly_name: "Sonos Kitchen",
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
const ACTIONS = [
|
|
||||||
{ wait_template: "{{ true }}", alias: "Something with an alias" },
|
{ wait_template: "{{ true }}", alias: "Something with an alias" },
|
||||||
{ delay: "0:05" },
|
{ delay: "0:05" },
|
||||||
{ wait_template: "{{ true }}" },
|
{ wait_template: "{{ true }}" },
|
||||||
@@ -29,20 +19,8 @@ const ACTIONS = [
|
|||||||
device_id: "abcdefgh",
|
device_id: "abcdefgh",
|
||||||
domain: "plex",
|
domain: "plex",
|
||||||
entity_id: "media_player.kitchen",
|
entity_id: "media_player.kitchen",
|
||||||
type: "turn_on",
|
|
||||||
},
|
},
|
||||||
{ scene: "scene.kitchen_morning" },
|
{ scene: "scene.kitchen_morning" },
|
||||||
{
|
|
||||||
service: "scene.turn_on",
|
|
||||||
target: { entity_id: "scene.kitchen_morning" },
|
|
||||||
metadata: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
service: "media_player.play_media",
|
|
||||||
target: { entity_id: "media_player.kitchen" },
|
|
||||||
data: { media_content_id: "", media_content_type: "" },
|
|
||||||
metadata: { title: "Happy Song" },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
wait_for_trigger: [
|
wait_for_trigger: [
|
||||||
{
|
{
|
||||||
@@ -62,45 +40,6 @@ const ACTIONS = [
|
|||||||
entity_id: "input_boolean.toggle_4",
|
entity_id: "input_boolean.toggle_4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
parallel: [
|
|
||||||
{ scene: "scene.kitchen_morning" },
|
|
||||||
{
|
|
||||||
service: "media_player.play_media",
|
|
||||||
target: { entity_id: "media_player.living_room" },
|
|
||||||
data: { media_content_id: "", media_content_type: "" },
|
|
||||||
metadata: { title: "Happy Song" },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
stop: "No one is home!",
|
|
||||||
},
|
|
||||||
{ repeat: { count: 3, sequence: [{ delay: "00:00:01" }] } },
|
|
||||||
{
|
|
||||||
repeat: {
|
|
||||||
for_each: ["bread", "butter", "cheese"],
|
|
||||||
sequence: [{ delay: "00:00:01" }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
if: [{ condition: "state" }],
|
|
||||||
then: [{ delay: "00:00:01" }],
|
|
||||||
else: [{ delay: "00:00:05" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
choose: [
|
|
||||||
{
|
|
||||||
conditions: [{ condition: "state" }],
|
|
||||||
sequence: [{ delay: "00:00:01" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
conditions: [{ condition: "sun" }],
|
|
||||||
sequence: [{ delay: "00:00:05" }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
default: [{ delay: "00:00:03" }],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-automation-describe-action")
|
@customElement("demo-automation-describe-action")
|
||||||
@@ -113,7 +52,7 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="Actions">
|
<ha-card header="Actions">
|
||||||
${ACTIONS.map(
|
${actions.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<span>${describeAction(this.hass, conf as any)}</span>
|
<span>${describeAction(this.hass, conf as any)}</span>
|
||||||
@@ -129,7 +68,6 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
super.firstUpdated(changedProps);
|
super.firstUpdated(changedProps);
|
||||||
const hass = provideHass(this);
|
const hass = provideHass(this);
|
||||||
hass.updateTranslations(null, "en");
|
hass.updateTranslations(null, "en");
|
||||||
hass.addEntities(ENTITIES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles() {
|
static get styles() {
|
@@ -1,8 +1,8 @@
|
|||||||
import { dump } from "js-yaml";
|
import { dump } from "js-yaml";
|
||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, 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 { describeCondition } from "../../../../src/data/automation_i18n";
|
import { describeCondition } from "../../../src/data/automation_i18n";
|
||||||
|
|
||||||
const conditions = [
|
const conditions = [
|
||||||
{ condition: "and" },
|
{ condition: "and" },
|
@@ -1,8 +1,8 @@
|
|||||||
import { dump } from "js-yaml";
|
import { dump } from "js-yaml";
|
||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, 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 { describeTrigger } from "../../../../src/data/automation_i18n";
|
import { describeTrigger } from "../../../src/data/automation_i18n";
|
||||||
|
|
||||||
const triggers = [
|
const triggers = [
|
||||||
{ platform: "state" },
|
{ platform: "state" },
|
91
gallery/src/demos/demo-automation-editor-action.ts
Normal file
91
gallery/src/demos/demo-automation-editor-action.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* eslint-disable lit/no-template-arrow */
|
||||||
|
import { LitElement, TemplateResult, html } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
|
import type { HomeAssistant } from "../../../src/types";
|
||||||
|
import "../components/demo-black-white-row";
|
||||||
|
import { mockEntityRegistry } from "../../../demo/src/stubs/entity_registry";
|
||||||
|
import { mockDeviceRegistry } from "../../../demo/src/stubs/device_registry";
|
||||||
|
import { mockAreaRegistry } from "../../../demo/src/stubs/area_registry";
|
||||||
|
import { mockHassioSupervisor } from "../../../demo/src/stubs/hassio_supervisor";
|
||||||
|
import "../../../src/panels/config/automation/action/ha-automation-action";
|
||||||
|
import { HaChooseAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-choose";
|
||||||
|
import { HaDelayAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-delay";
|
||||||
|
import { HaDeviceAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-device_id";
|
||||||
|
import { HaEventAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-event";
|
||||||
|
import { HaRepeatAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-repeat";
|
||||||
|
import { HaSceneAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-scene";
|
||||||
|
import { HaServiceAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-service";
|
||||||
|
import { HaWaitForTriggerAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-wait_for_trigger";
|
||||||
|
import { HaWaitAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-wait_template";
|
||||||
|
import { Action } from "../../../src/data/script";
|
||||||
|
import { HaConditionAction } from "../../../src/panels/config/automation/action/types/ha-automation-action-condition";
|
||||||
|
|
||||||
|
const SCHEMAS: { name: string; actions: Action[] }[] = [
|
||||||
|
{ name: "Event", actions: [HaEventAction.defaultConfig] },
|
||||||
|
{ name: "Device", actions: [HaDeviceAction.defaultConfig] },
|
||||||
|
{ name: "Service", actions: [HaServiceAction.defaultConfig] },
|
||||||
|
{ name: "Condition", actions: [HaConditionAction.defaultConfig] },
|
||||||
|
{ name: "Delay", actions: [HaDelayAction.defaultConfig] },
|
||||||
|
{ name: "Scene", actions: [HaSceneAction.defaultConfig] },
|
||||||
|
{ name: "Wait", actions: [HaWaitAction.defaultConfig] },
|
||||||
|
{ name: "WaitForTrigger", actions: [HaWaitForTriggerAction.defaultConfig] },
|
||||||
|
{ name: "Repeat", actions: [HaRepeatAction.defaultConfig] },
|
||||||
|
{ name: "Choose", actions: [HaChooseAction.defaultConfig] },
|
||||||
|
{ name: "Variables", actions: [{ variables: { hello: "1" } }] },
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("demo-automation-editor-action")
|
||||||
|
class DemoHaAutomationEditorAction extends LitElement {
|
||||||
|
@state() private hass!: HomeAssistant;
|
||||||
|
|
||||||
|
private data: any = SCHEMAS.map((info) => info.actions);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
const hass = provideHass(this);
|
||||||
|
hass.updateTranslations(null, "en");
|
||||||
|
hass.updateTranslations("config", "en");
|
||||||
|
mockEntityRegistry(hass);
|
||||||
|
mockDeviceRegistry(hass);
|
||||||
|
mockAreaRegistry(hass);
|
||||||
|
mockHassioSupervisor(hass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
const valueChanged = (ev) => {
|
||||||
|
const sampleIdx = ev.target.sampleIdx;
|
||||||
|
this.data[sampleIdx] = ev.detail.value;
|
||||||
|
this.requestUpdate();
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
${SCHEMAS.map(
|
||||||
|
(info, sampleIdx) => html`
|
||||||
|
<demo-black-white-row
|
||||||
|
.title=${info.name}
|
||||||
|
.value=${this.data[sampleIdx]}
|
||||||
|
>
|
||||||
|
${["light", "dark"].map(
|
||||||
|
(slot) =>
|
||||||
|
html`
|
||||||
|
<ha-automation-action
|
||||||
|
slot=${slot}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.actions=${this.data[sampleIdx]}
|
||||||
|
.sampleIdx=${sampleIdx}
|
||||||
|
@value-changed=${valueChanged}
|
||||||
|
></ha-automation-action>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</demo-black-white-row>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-ha-automation-editor-action": DemoHaAutomationEditorAction;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,26 +1,26 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import { LitElement, TemplateResult, html } from "lit";
|
import { LitElement, TemplateResult, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../src/types";
|
||||||
import "../../components/demo-black-white-row";
|
import "../components/demo-black-white-row";
|
||||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
import { mockEntityRegistry } from "../../../demo/src/stubs/entity_registry";
|
||||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
import { mockDeviceRegistry } from "../../../demo/src/stubs/device_registry";
|
||||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
import { mockAreaRegistry } from "../../../demo/src/stubs/area_registry";
|
||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
import { mockHassioSupervisor } from "../../../demo/src/stubs/hassio_supervisor";
|
||||||
import type { ConditionWithShorthand } from "../../../../src/data/automation";
|
import type { Condition } from "../../../src/data/automation";
|
||||||
import "../../../../src/panels/config/automation/condition/ha-automation-condition";
|
import "../../../src/panels/config/automation/condition/ha-automation-condition";
|
||||||
import { HaDeviceCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-device";
|
import { HaDeviceCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-device";
|
||||||
import { HaLogicalCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-logical";
|
import { HaLogicalCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-logical";
|
||||||
import HaNumericStateCondition from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-numeric_state";
|
import HaNumericStateCondition from "../../../src/panels/config/automation/condition/types/ha-automation-condition-numeric_state";
|
||||||
import { HaStateCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-state";
|
import { HaStateCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-state";
|
||||||
import { HaSunCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-sun";
|
import { HaSunCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-sun";
|
||||||
import { HaTemplateCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-template";
|
import { HaTemplateCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-template";
|
||||||
import { HaTimeCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-time";
|
import { HaTimeCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-time";
|
||||||
import { HaTriggerCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-trigger";
|
import { HaTriggerCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-trigger";
|
||||||
import { HaZoneCondition } from "../../../../src/panels/config/automation/condition/types/ha-automation-condition-zone";
|
import { HaZoneCondition } from "../../../src/panels/config/automation/condition/types/ha-automation-condition-zone";
|
||||||
|
|
||||||
const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [
|
const SCHEMAS: { name: string; conditions: Condition[] }[] = [
|
||||||
{
|
{
|
||||||
name: "State",
|
name: "State",
|
||||||
conditions: [{ condition: "state", ...HaStateCondition.defaultConfig }],
|
conditions: [{ condition: "state", ...HaStateCondition.defaultConfig }],
|
||||||
@@ -69,14 +69,6 @@ const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [
|
|||||||
name: "Trigger",
|
name: "Trigger",
|
||||||
conditions: [{ condition: "trigger", ...HaTriggerCondition.defaultConfig }],
|
conditions: [{ condition: "trigger", ...HaTriggerCondition.defaultConfig }],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Shorthand",
|
|
||||||
conditions: [
|
|
||||||
{ and: HaLogicalCondition.defaultConfig.conditions },
|
|
||||||
{ or: HaLogicalCondition.defaultConfig.conditions },
|
|
||||||
{ not: HaLogicalCondition.defaultConfig.conditions },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-automation-editor-condition")
|
@customElement("demo-automation-editor-condition")
|
@@ -1,29 +1,29 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import { LitElement, TemplateResult, html } from "lit";
|
import { LitElement, TemplateResult, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../src/types";
|
||||||
import "../../components/demo-black-white-row";
|
import "../components/demo-black-white-row";
|
||||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
import { mockEntityRegistry } from "../../../demo/src/stubs/entity_registry";
|
||||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
import { mockDeviceRegistry } from "../../../demo/src/stubs/device_registry";
|
||||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
import { mockAreaRegistry } from "../../../demo/src/stubs/area_registry";
|
||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
import { mockHassioSupervisor } from "../../../demo/src/stubs/hassio_supervisor";
|
||||||
import type { Trigger } from "../../../../src/data/automation";
|
import type { Trigger } from "../../../src/data/automation";
|
||||||
import { HaGeolocationTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-geo_location";
|
import { HaGeolocationTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-geo_location";
|
||||||
import { HaEventTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-event";
|
import { HaEventTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-event";
|
||||||
import { HaHassTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-homeassistant";
|
import { HaHassTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-homeassistant";
|
||||||
import { HaNumericStateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-numeric_state";
|
import { HaNumericStateTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-numeric_state";
|
||||||
import { HaSunTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-sun";
|
import { HaSunTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-sun";
|
||||||
import { HaTagTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-tag";
|
import { HaTagTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-tag";
|
||||||
import { HaTemplateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-template";
|
import { HaTemplateTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-template";
|
||||||
import { HaTimeTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time";
|
import { HaTimeTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time";
|
||||||
import { HaTimePatternTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time_pattern";
|
import { HaTimePatternTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-time_pattern";
|
||||||
import { HaWebhookTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-webhook";
|
import { HaWebhookTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-webhook";
|
||||||
import { HaZoneTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-zone";
|
import { HaZoneTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-zone";
|
||||||
import { HaDeviceTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-device";
|
import { HaDeviceTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-device";
|
||||||
import { HaStateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-state";
|
import { HaStateTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-state";
|
||||||
import { HaMQTTTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-mqtt";
|
import { HaMQTTTrigger } from "../../../src/panels/config/automation/trigger/types/ha-automation-trigger-mqtt";
|
||||||
import "../../../../src/panels/config/automation/trigger/ha-automation-trigger";
|
import "../../../src/panels/config/automation/trigger/ha-automation-trigger";
|
||||||
|
|
||||||
const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
||||||
{
|
{
|
@@ -1,13 +1,13 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../../src/components/trace/hat-script-graph";
|
import "../../../src/components/trace/hat-script-graph";
|
||||||
import "../../../../src/components/trace/hat-trace-timeline";
|
import "../../../src/components/trace/hat-trace-timeline";
|
||||||
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";
|
||||||
import { mockDemoTrace } from "../../data/traces/mock-demo-trace";
|
import { mockDemoTrace } from "../data/traces/mock-demo-trace";
|
||||||
import { DemoTrace } from "../../data/traces/types";
|
import { DemoTrace } from "../data/traces/types";
|
||||||
|
|
||||||
const traces: DemoTrace[] = [
|
const traces: DemoTrace[] = [
|
||||||
mockDemoTrace({ state: "running" }),
|
mockDemoTrace({ state: "running" }),
|
@@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../../src/components/trace/hat-script-graph";
|
import "../../../src/components/trace/hat-script-graph";
|
||||||
import "../../../../src/components/trace/hat-trace-timeline";
|
import "../../../src/components/trace/hat-trace-timeline";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
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";
|
||||||
import { DemoTrace } from "../../data/traces/types";
|
import { DemoTrace } from "../data/traces/types";
|
||||||
import { basicTrace } from "../../data/traces/basic_trace";
|
import { basicTrace } from "../data/traces/basic_trace";
|
||||||
import { motionLightTrace } from "../../data/traces/motion-light-trace";
|
import { motionLightTrace } from "../data/traces/motion-light-trace";
|
||||||
|
|
||||||
const traces: DemoTrace[] = [basicTrace, motionLightTrace];
|
const traces: DemoTrace[] = [basicTrace, motionLightTrace];
|
||||||
|
|
@@ -1,19 +1,15 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
|
import "../../../src/components/ha-alert";
|
||||||
import "../../../../src/components/ha-alert";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../../src/components/ha-card";
|
|
||||||
import "../../../../src/components/ha-logo-svg";
|
|
||||||
|
|
||||||
const alerts: {
|
const alerts: {
|
||||||
title?: string;
|
title?: string;
|
||||||
description: string | TemplateResult;
|
description: string | TemplateResult;
|
||||||
type: "info" | "warning" | "error" | "success";
|
type: "info" | "warning" | "error" | "success";
|
||||||
dismissable?: boolean;
|
dismissable?: boolean;
|
||||||
|
action?: string;
|
||||||
rtl?: boolean;
|
rtl?: boolean;
|
||||||
iconSlot?: TemplateResult;
|
|
||||||
actionSlot?: TemplateResult;
|
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
title: "Test info alert",
|
title: "Test info alert",
|
||||||
@@ -77,35 +73,13 @@ const alerts: {
|
|||||||
title: "Error with action",
|
title: "Error with action",
|
||||||
description: "This is a test error alert with action",
|
description: "This is a test error alert with action",
|
||||||
type: "error",
|
type: "error",
|
||||||
actionSlot: html`<mwc-button slot="action" label="restart"></mwc-button>`,
|
action: "restart",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Unsaved data",
|
title: "Unsaved data",
|
||||||
description: "You have unsaved data",
|
description: "You have unsaved data",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
actionSlot: html`<mwc-button slot="action" label="save"></mwc-button>`,
|
action: "save",
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Slotted icon",
|
|
||||||
description: "Alert with slotted icon",
|
|
||||||
type: "warning",
|
|
||||||
iconSlot: html`<span slot="icon" class="image">
|
|
||||||
<ha-logo-svg></ha-logo-svg>
|
|
||||||
</span>`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Slotted image",
|
|
||||||
description: "Alert with slotted image",
|
|
||||||
type: "warning",
|
|
||||||
iconSlot: html`<span slot="icon" class="image"
|
|
||||||
><img src="https://www.home-assistant.io/images/home-assistant-logo.svg"
|
|
||||||
/></span>`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Slotted action",
|
|
||||||
description: "Alert with slotted action",
|
|
||||||
type: "info",
|
|
||||||
actionSlot: html`<mwc-button slot="action" label="action"></mwc-button>`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Dismissable information (RTL)",
|
description: "Dismissable information (RTL)",
|
||||||
@@ -117,7 +91,7 @@ const alerts: {
|
|||||||
title: "Error with action",
|
title: "Error with action",
|
||||||
description: "This is a test error alert with action (RTL)",
|
description: "This is a test error alert with action (RTL)",
|
||||||
type: "error",
|
type: "error",
|
||||||
actionSlot: html`<mwc-button slot="action" label="restart"></mwc-button>`,
|
action: "restart",
|
||||||
rtl: true,
|
rtl: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -128,66 +102,34 @@ const alerts: {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-alert")
|
@customElement("demo-ha-alert")
|
||||||
export class DemoHaAlert extends LitElement {
|
export class DemoHaAlert extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${["light", "dark"].map(
|
<ha-card header="ha-alert demo">
|
||||||
(mode) => html`
|
<div class="card-content">
|
||||||
<div class=${mode}>
|
${alerts.map(
|
||||||
<ha-card header="ha-alert ${mode} demo">
|
(alert) => html`
|
||||||
<div class="card-content">
|
<ha-alert
|
||||||
${alerts.map(
|
.title=${alert.title || ""}
|
||||||
(alert) => html`
|
.alertType=${alert.type}
|
||||||
<ha-alert
|
.dismissable=${alert.dismissable || false}
|
||||||
.title=${alert.title || ""}
|
.actionText=${alert.action || ""}
|
||||||
.alertType=${alert.type}
|
.rtl=${alert.rtl || false}
|
||||||
.dismissable=${alert.dismissable || false}
|
>
|
||||||
.rtl=${alert.rtl || false}
|
${alert.description}
|
||||||
>
|
</ha-alert>
|
||||||
${alert.iconSlot} ${alert.description} ${alert.actionSlot}
|
`
|
||||||
</ha-alert>
|
)}
|
||||||
`
|
</div>
|
||||||
)}
|
</ha-card>
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated(changedProps) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
applyThemesOnElement(
|
|
||||||
this.shadowRoot!.querySelector(".dark"),
|
|
||||||
{
|
|
||||||
default_theme: "default",
|
|
||||||
default_dark_theme: "default",
|
|
||||||
themes: {},
|
|
||||||
darkMode: true,
|
|
||||||
theme: "default",
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles() {
|
static get styles() {
|
||||||
return css`
|
return css`
|
||||||
:host {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.dark,
|
|
||||||
.light {
|
|
||||||
display: block;
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
padding: 0 50px;
|
|
||||||
}
|
|
||||||
ha-card {
|
ha-card {
|
||||||
|
max-width: 600px;
|
||||||
margin: 24px auto;
|
margin: 24px auto;
|
||||||
}
|
}
|
||||||
ha-alert {
|
ha-alert {
|
||||||
@@ -200,17 +142,8 @@ export class DemoHaAlert extends LitElement {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.image {
|
span {
|
||||||
display: inline-flex;
|
margin-right: 16px;
|
||||||
height: 100%;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-height: 24px;
|
|
||||||
width: 24px;
|
|
||||||
}
|
|
||||||
mwc-button {
|
|
||||||
--mdc-theme-primary: var(--primary-text-color);
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -218,6 +151,6 @@ export class DemoHaAlert extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-components-ha-alert": DemoHaAlert;
|
"demo-ha-alert": DemoHaAlert;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import "../../../../src/components/ha-bar";
|
import "../../../src/components/ha-bar";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
|
|
||||||
const bars: {
|
const bars: {
|
||||||
min?: number;
|
min?: number;
|
||||||
@@ -34,7 +34,7 @@ const bars: {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-bar")
|
@customElement("demo-ha-bar")
|
||||||
export class DemoHaBar extends LitElement {
|
export class DemoHaBar extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
@@ -80,6 +80,6 @@ export class DemoHaBar extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-components-ha-bar": DemoHaBar;
|
"demo-ha-bar": DemoHaBar;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,10 +1,9 @@
|
|||||||
import { mdiHomeAssistant } from "@mdi/js";
|
import { mdiHomeAssistant } from "@mdi/js";
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
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-chip";
|
import "../../../src/components/ha-chip";
|
||||||
import "../../../../src/components/ha-chip-set";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import "../../../../src/components/ha-svg-icon";
|
|
||||||
|
|
||||||
const chips: {
|
const chips: {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
@@ -23,8 +22,8 @@ const chips: {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-chips")
|
@customElement("demo-ha-chip")
|
||||||
export class DemoHaChips extends LitElement {
|
export class DemoHaChip extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="ha-chip demo">
|
<ha-card header="ha-chip demo">
|
||||||
@@ -42,23 +41,6 @@ export class DemoHaChips extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
<ha-card header="ha-chip-set demo">
|
|
||||||
<div class="card-content">
|
|
||||||
<ha-chip-set>
|
|
||||||
${chips.map(
|
|
||||||
(chip) => html`
|
|
||||||
<ha-chip .hasIcon=${chip.icon !== undefined}>
|
|
||||||
${chip.icon
|
|
||||||
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
|
|
||||||
</ha-svg-icon>`
|
|
||||||
: ""}
|
|
||||||
${chip.content}
|
|
||||||
</ha-chip>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</ha-chip-set>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,19 +50,12 @@ export class DemoHaChips extends LitElement {
|
|||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: 24px auto;
|
margin: 24px auto;
|
||||||
}
|
}
|
||||||
ha-chip {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
.card-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-components-ha-chips": DemoHaChips;
|
"demo-ha-chip": DemoHaChip;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,109 +1,11 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { html, LitElement, TemplateResult } from "lit";
|
import { LitElement, TemplateResult, html } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
import { computeInitialHaFormData } from "../../../src/components/ha-form/compute-initial-ha-form-data";
|
||||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
import type { HaFormSchema } from "../../../src/components/ha-form/types";
|
||||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
import "../../../src/components/ha-form/ha-form";
|
||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
import "../components/demo-black-white-row";
|
||||||
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
|
|
||||||
import "../../../../src/components/ha-form/ha-form";
|
|
||||||
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
|
||||||
import "../../components/demo-black-white-row";
|
|
||||||
|
|
||||||
const ENTITIES = [
|
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
|
||||||
friendly_name: "Alarm",
|
|
||||||
}),
|
|
||||||
getEntity("media_player", "livingroom", "playing", {
|
|
||||||
friendly_name: "Livingroom",
|
|
||||||
}),
|
|
||||||
getEntity("media_player", "lounge", "idle", {
|
|
||||||
friendly_name: "Lounge",
|
|
||||||
supported_features: 444983,
|
|
||||||
}),
|
|
||||||
getEntity("light", "bedroom", "on", {
|
|
||||||
friendly_name: "Bedroom",
|
|
||||||
}),
|
|
||||||
getEntity("switch", "coffee", "off", {
|
|
||||||
friendly_name: "Coffee",
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
const DEVICES = [
|
|
||||||
{
|
|
||||||
area_id: "bedroom",
|
|
||||||
configuration_url: null,
|
|
||||||
config_entries: ["config_entry_1"],
|
|
||||||
connections: [],
|
|
||||||
disabled_by: null,
|
|
||||||
entry_type: null,
|
|
||||||
id: "device_1",
|
|
||||||
identifiers: [["demo", "volume1"] as [string, string]],
|
|
||||||
manufacturer: null,
|
|
||||||
model: null,
|
|
||||||
name_by_user: null,
|
|
||||||
name: "Dishwasher",
|
|
||||||
sw_version: null,
|
|
||||||
hw_version: null,
|
|
||||||
via_device_id: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
area_id: "backyard",
|
|
||||||
configuration_url: null,
|
|
||||||
config_entries: ["config_entry_2"],
|
|
||||||
connections: [],
|
|
||||||
disabled_by: null,
|
|
||||||
entry_type: null,
|
|
||||||
id: "device_2",
|
|
||||||
identifiers: [["demo", "pwm1"] as [string, string]],
|
|
||||||
manufacturer: null,
|
|
||||||
model: null,
|
|
||||||
name_by_user: null,
|
|
||||||
name: "Lamp",
|
|
||||||
sw_version: null,
|
|
||||||
hw_version: null,
|
|
||||||
via_device_id: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
area_id: null,
|
|
||||||
configuration_url: null,
|
|
||||||
config_entries: ["config_entry_3"],
|
|
||||||
connections: [],
|
|
||||||
disabled_by: null,
|
|
||||||
entry_type: null,
|
|
||||||
id: "device_3",
|
|
||||||
identifiers: [["demo", "pwm1"] as [string, string]],
|
|
||||||
manufacturer: null,
|
|
||||||
model: null,
|
|
||||||
name_by_user: "User name",
|
|
||||||
name: "Technical name",
|
|
||||||
sw_version: null,
|
|
||||||
hw_version: null,
|
|
||||||
via_device_id: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const AREAS = [
|
|
||||||
{
|
|
||||||
area_id: "backyard",
|
|
||||||
name: "Backyard",
|
|
||||||
picture: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
area_id: "bedroom",
|
|
||||||
name: "Bedroom",
|
|
||||||
picture: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
area_id: "livingroom",
|
|
||||||
name: "Livingroom",
|
|
||||||
picture: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const SCHEMAS: {
|
const SCHEMAS: {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -112,76 +14,6 @@ const SCHEMAS: {
|
|||||||
schema: HaFormSchema[];
|
schema: HaFormSchema[];
|
||||||
data?: Record<string, any>;
|
data?: Record<string, any>;
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
|
||||||
title: "Selectors",
|
|
||||||
translations: {
|
|
||||||
addon: "Addon",
|
|
||||||
entity: "Entity",
|
|
||||||
device: "Device",
|
|
||||||
area: "Area",
|
|
||||||
target: "Target",
|
|
||||||
number: "Number",
|
|
||||||
boolean: "Boolean",
|
|
||||||
time: "Time",
|
|
||||||
action: "Action",
|
|
||||||
text: "Text",
|
|
||||||
text_multiline: "Text Multiline",
|
|
||||||
object: "Object",
|
|
||||||
select: "Select",
|
|
||||||
icon: "Icon",
|
|
||||||
media: "Media",
|
|
||||||
location: "Location",
|
|
||||||
entities: "Entities",
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
{ name: "addon", selector: { addon: {} } },
|
|
||||||
{ name: "entity", selector: { entity: {} } },
|
|
||||||
{
|
|
||||||
name: "Attribute",
|
|
||||||
selector: { attribute: { entity_id: "" } },
|
|
||||||
context: { filter_entity: "entity" },
|
|
||||||
},
|
|
||||||
{ name: "Device", selector: { device: {} } },
|
|
||||||
{ name: "Duration", selector: { duration: {} } },
|
|
||||||
{ name: "area", selector: { area: {} } },
|
|
||||||
{ name: "target", selector: { target: {} } },
|
|
||||||
{ name: "number", selector: { number: { min: 0, max: 10 } } },
|
|
||||||
{ name: "boolean", selector: { boolean: {} } },
|
|
||||||
{ name: "time", required: true, selector: { time: {} } },
|
|
||||||
{ name: "datetime", required: true, selector: { datetime: {} } },
|
|
||||||
{ name: "date", required: true, selector: { date: {} } },
|
|
||||||
{ name: "action", selector: { action: {} } },
|
|
||||||
{ name: "text", selector: { text: { multiline: false } } },
|
|
||||||
{ name: "text_multiline", selector: { text: { multiline: true } } },
|
|
||||||
{ name: "object", selector: { object: {} } },
|
|
||||||
{
|
|
||||||
name: "select",
|
|
||||||
selector: {
|
|
||||||
select: { options: ["Everyone Home", "Some Home", "All gone"] },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "icon",
|
|
||||||
selector: {
|
|
||||||
icon: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "media",
|
|
||||||
selector: {
|
|
||||||
media: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "location",
|
|
||||||
selector: { location: { radius: true, icon: "mdi:home" } },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "entities",
|
|
||||||
selector: { entity: { multiple: true } },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "Authentication",
|
title: "Authentication",
|
||||||
translations: {
|
translations: {
|
||||||
@@ -218,11 +50,13 @@ const SCHEMAS: {
|
|||||||
{
|
{
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
name: "bool",
|
name: "bool",
|
||||||
|
optional: true,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "integer",
|
type: "integer",
|
||||||
name: "int",
|
name: "int",
|
||||||
|
optional: true,
|
||||||
default: 10,
|
default: 10,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -233,6 +67,7 @@ const SCHEMAS: {
|
|||||||
{
|
{
|
||||||
type: "string",
|
type: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
|
optional: true,
|
||||||
default: "Default",
|
default: "Default",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -242,6 +77,7 @@ const SCHEMAS: {
|
|||||||
["other", "other"],
|
["other", "other"],
|
||||||
],
|
],
|
||||||
name: "select",
|
name: "select",
|
||||||
|
optional: true,
|
||||||
default: "default",
|
default: "default",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -251,6 +87,7 @@ const SCHEMAS: {
|
|||||||
other: "Other",
|
other: "Other",
|
||||||
},
|
},
|
||||||
name: "multi",
|
name: "multi",
|
||||||
|
optional: true,
|
||||||
default: ["default"],
|
default: ["default"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -271,6 +108,7 @@ const SCHEMAS: {
|
|||||||
{
|
{
|
||||||
type: "integer",
|
type: "integer",
|
||||||
name: "int with default",
|
name: "int with default",
|
||||||
|
optional: true,
|
||||||
default: 10,
|
default: 10,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -284,6 +122,7 @@ const SCHEMAS: {
|
|||||||
{
|
{
|
||||||
type: "integer",
|
type: "integer",
|
||||||
name: "int range optional",
|
name: "int range optional",
|
||||||
|
optional: true,
|
||||||
valueMin: 0,
|
valueMin: 0,
|
||||||
valueMax: 10,
|
valueMax: 10,
|
||||||
},
|
},
|
||||||
@@ -309,6 +148,7 @@ const SCHEMAS: {
|
|||||||
["other", "Other"],
|
["other", "Other"],
|
||||||
],
|
],
|
||||||
name: "select optional",
|
name: "select optional",
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "select",
|
type: "select",
|
||||||
@@ -321,6 +161,7 @@ const SCHEMAS: {
|
|||||||
["option", "1000"],
|
["option", "1000"],
|
||||||
],
|
],
|
||||||
name: "select many otions",
|
name: "select many otions",
|
||||||
|
optional: true,
|
||||||
default: "default",
|
default: "default",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -349,6 +190,7 @@ const SCHEMAS: {
|
|||||||
option: "1000",
|
option: "1000",
|
||||||
},
|
},
|
||||||
name: "multi many otions",
|
name: "multi many otions",
|
||||||
|
optional: true,
|
||||||
default: ["default"],
|
default: ["default"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -397,36 +239,23 @@ const SCHEMAS: {
|
|||||||
valueMin: 1,
|
valueMin: 1,
|
||||||
valueMax: 65535,
|
valueMax: 65535,
|
||||||
name: "port",
|
name: "port",
|
||||||
|
optional: true,
|
||||||
default: 80,
|
default: 80,
|
||||||
},
|
},
|
||||||
{ type: "string", name: "path", default: "/" },
|
{ type: "string", name: "path", optional: true, default: "/" },
|
||||||
{ type: "boolean", name: "ssl", default: false },
|
{ type: "boolean", name: "ssl", optional: true, default: false },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-form")
|
@customElement("demo-ha-form")
|
||||||
class DemoHaForm extends LitElement {
|
class DemoHaForm extends LitElement {
|
||||||
@state() private hass!: HomeAssistant;
|
|
||||||
|
|
||||||
private data = SCHEMAS.map(
|
private data = SCHEMAS.map(
|
||||||
({ schema, data }) => data || computeInitialHaFormData(schema)
|
({ schema, data }) => data || computeInitialHaFormData(schema)
|
||||||
);
|
);
|
||||||
|
|
||||||
private disabled = SCHEMAS.map(() => false);
|
private disabled = SCHEMAS.map(() => false);
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
const hass = provideHass(this);
|
|
||||||
hass.updateTranslations(null, "en");
|
|
||||||
hass.updateTranslations("config", "en");
|
|
||||||
hass.addEntities(ENTITIES);
|
|
||||||
mockEntityRegistry(hass);
|
|
||||||
mockDeviceRegistry(hass, DEVICES);
|
|
||||||
mockAreaRegistry(hass, AREAS);
|
|
||||||
mockHassioSupervisor(hass);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
${SCHEMAS.map((info, idx) => {
|
${SCHEMAS.map((info, idx) => {
|
||||||
@@ -449,7 +278,6 @@ class DemoHaForm extends LitElement {
|
|||||||
(slot) => html`
|
(slot) => html`
|
||||||
<ha-form
|
<ha-form
|
||||||
slot=${slot}
|
slot=${slot}
|
||||||
.hass=${this.hass}
|
|
||||||
.data=${this.data[idx]}
|
.data=${this.data[idx]}
|
||||||
.schema=${info.schema}
|
.schema=${info.schema}
|
||||||
.error=${info.error}
|
.error=${info.error}
|
||||||
@@ -473,6 +301,6 @@ class DemoHaForm extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-components-ha-form": DemoHaForm;
|
"demo-ha-form": DemoHaForm;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-label-badge";
|
import "../../../src/components/ha-label-badge";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
|
|
||||||
const colors = ["#03a9f4", "#ffa600", "#43a047"];
|
const colors = ["#03a9f4", "#ffa600", "#43a047"];
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ const badges: {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-components-ha-label-badge")
|
@customElement("demo-ha-label-badge")
|
||||||
export class DemoHaLabelBadge extends LitElement {
|
export class DemoHaLabelBadge extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
@@ -117,6 +117,6 @@ export class DemoHaLabelBadge extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-components-ha-label-badge": DemoHaLabelBadge;
|
"demo-ha-label-badge": DemoHaLabelBadge;
|
||||||
}
|
}
|
||||||
}
|
}
|
131
gallery/src/demos/demo-ha-selector.ts
Normal file
131
gallery/src/demos/demo-ha-selector.ts
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/* eslint-disable lit/no-template-arrow */
|
||||||
|
import "@material/mwc-button";
|
||||||
|
import { LitElement, TemplateResult, css, html } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import "../../../src/components/ha-selector/ha-selector";
|
||||||
|
import "../../../src/components/ha-settings-row";
|
||||||
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
|
import type { HomeAssistant } from "../../../src/types";
|
||||||
|
import "../components/demo-black-white-row";
|
||||||
|
import { BlueprintInput } from "../../../src/data/blueprint";
|
||||||
|
import { mockEntityRegistry } from "../../../demo/src/stubs/entity_registry";
|
||||||
|
import { mockDeviceRegistry } from "../../../demo/src/stubs/device_registry";
|
||||||
|
import { mockAreaRegistry } from "../../../demo/src/stubs/area_registry";
|
||||||
|
import { mockHassioSupervisor } from "../../../demo/src/stubs/hassio_supervisor";
|
||||||
|
|
||||||
|
const SCHEMAS: {
|
||||||
|
name: string;
|
||||||
|
input: Record<string, BlueprintInput | null>;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
name: "One of each",
|
||||||
|
input: {
|
||||||
|
entity: { name: "Entity", selector: { entity: {} } },
|
||||||
|
device: { name: "Device", selector: { device: {} } },
|
||||||
|
addon: { name: "Addon", selector: { addon: {} } },
|
||||||
|
area: { name: "Area", selector: { area: {} } },
|
||||||
|
target: { name: "Target", selector: { target: {} } },
|
||||||
|
number_box: {
|
||||||
|
name: "Number Box",
|
||||||
|
selector: {
|
||||||
|
number: {
|
||||||
|
min: 0,
|
||||||
|
max: 10,
|
||||||
|
mode: "box",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
number_slider: {
|
||||||
|
name: "Number Slider",
|
||||||
|
selector: {
|
||||||
|
number: {
|
||||||
|
min: 0,
|
||||||
|
max: 10,
|
||||||
|
mode: "slider",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
boolean: { name: "Boolean", selector: { boolean: {} } },
|
||||||
|
time: { name: "Time", selector: { time: {} } },
|
||||||
|
action: { name: "Action", selector: { action: {} } },
|
||||||
|
text: { name: "Text", selector: { text: { multiline: false } } },
|
||||||
|
text_multiline: {
|
||||||
|
name: "Text multiline",
|
||||||
|
selector: { text: { multiline: true } },
|
||||||
|
},
|
||||||
|
object: { name: "Object", selector: { object: {} } },
|
||||||
|
select: {
|
||||||
|
name: "Select",
|
||||||
|
selector: { select: { options: ["Option 1", "Option 2"] } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("demo-ha-selector")
|
||||||
|
class DemoHaSelector extends LitElement {
|
||||||
|
@state() private hass!: HomeAssistant;
|
||||||
|
|
||||||
|
private data = SCHEMAS.map(() => ({}));
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
const hass = provideHass(this);
|
||||||
|
hass.updateTranslations(null, "en");
|
||||||
|
hass.updateTranslations("config", "en");
|
||||||
|
mockEntityRegistry(hass);
|
||||||
|
mockDeviceRegistry(hass);
|
||||||
|
mockAreaRegistry(hass);
|
||||||
|
mockHassioSupervisor(hass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${SCHEMAS.map((info, idx) => {
|
||||||
|
const data = this.data[idx];
|
||||||
|
const valueChanged = (ev) => {
|
||||||
|
this.data[idx] = {
|
||||||
|
...data,
|
||||||
|
[ev.target.key]: ev.detail.value,
|
||||||
|
};
|
||||||
|
this.requestUpdate();
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<demo-black-white-row .title=${info.name} .value=${this.data[idx]}>
|
||||||
|
${["light", "dark"].map((slot) =>
|
||||||
|
Object.entries(info.input).map(
|
||||||
|
([key, value]) =>
|
||||||
|
html`
|
||||||
|
<ha-settings-row narrow slot=${slot}>
|
||||||
|
<span slot="heading">${value?.name || key}</span>
|
||||||
|
<span slot="description">${value?.description}</span>
|
||||||
|
<ha-selector
|
||||||
|
.hass=${this.hass}
|
||||||
|
.selector=${value!.selector}
|
||||||
|
.key=${key}
|
||||||
|
.value=${data[key] ?? value!.default}
|
||||||
|
@value-changed=${valueChanged}
|
||||||
|
></ha-selector>
|
||||||
|
</ha-settings-row>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</demo-black-white-row>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
paper-input,
|
||||||
|
ha-selector {
|
||||||
|
width: 60;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"demo-ha-selector": DemoHaSelector;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||||
@@ -70,7 +70,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-alarm-panel-card")
|
@customElement("demo-hui-alarm-panel-card")
|
||||||
class DemoAlarmPanelEntity extends LitElement {
|
class DemoAlarmPanelEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -89,6 +89,6 @@ class DemoAlarmPanelEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-alarm-panel-card": DemoAlarmPanelEntity;
|
"demo-hui-alarm-panel-card": DemoAlarmPanelEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "controller_1", "on", {
|
getEntity("light", "controller_1", "on", {
|
||||||
@@ -52,7 +52,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-conditional-card")
|
@customElement("demo-hui-conditional-card")
|
||||||
class DemoConditional extends LitElement {
|
class DemoConditional extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -71,6 +71,6 @@ class DemoConditional extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-conditional-card": DemoConditional;
|
"demo-hui-conditional-card": DemoConditional;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
||||||
@@ -11,10 +11,10 @@ const ENTITIES = [
|
|||||||
getEntity("group", "kitchen", "on", {
|
getEntity("group", "kitchen", "on", {
|
||||||
entity_id: ["light.bed_light"],
|
entity_id: ["light.bed_light"],
|
||||||
order: 8,
|
order: 8,
|
||||||
friendly_name: "Kitchen Group",
|
friendly_name: "Kitchen",
|
||||||
}),
|
}),
|
||||||
getEntity("lock", "kitchen_door", "locked", {
|
getEntity("lock", "kitchen_door", "locked", {
|
||||||
friendly_name: "Kitchen Lock",
|
friendly_name: "Kitchen Door",
|
||||||
}),
|
}),
|
||||||
getEntity("cover", "kitchen_window", "open", {
|
getEntity("cover", "kitchen_window", "open", {
|
||||||
friendly_name: "Kitchen Window",
|
friendly_name: "Kitchen Window",
|
||||||
@@ -22,7 +22,7 @@ const ENTITIES = [
|
|||||||
}),
|
}),
|
||||||
getEntity("scene", "romantic_lights", "scening", {
|
getEntity("scene", "romantic_lights", "scening", {
|
||||||
entity_id: ["light.bed_light", "light.ceiling_lights"],
|
entity_id: ["light.bed_light", "light.ceiling_lights"],
|
||||||
friendly_name: "Romantic Scene",
|
friendly_name: "Romantic lights",
|
||||||
}),
|
}),
|
||||||
getEntity("device_tracker", "demo_paulus", "home", {
|
getEntity("device_tracker", "demo_paulus", "home", {
|
||||||
source_type: "gps",
|
source_type: "gps",
|
||||||
@@ -50,51 +50,15 @@ const ENTITIES = [
|
|||||||
friendly_name: "Ecobee",
|
friendly_name: "Ecobee",
|
||||||
supported_features: 1014,
|
supported_features: 1014,
|
||||||
}),
|
}),
|
||||||
getEntity("input_number", "number", 5, {
|
getEntity("input_number", "noise_allowance", 5, {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 10,
|
max: 10,
|
||||||
step: 1,
|
step: 1,
|
||||||
mode: "slider",
|
mode: "slider",
|
||||||
unit_of_measurement: "dB",
|
unit_of_measurement: "dB",
|
||||||
friendly_name: "Number",
|
friendly_name: "Allowed Noise",
|
||||||
icon: "mdi:bell-ring",
|
icon: "mdi:bell-ring",
|
||||||
}),
|
}),
|
||||||
getEntity("input_boolean", "toggle", "on", {
|
|
||||||
friendly_name: "Toggle",
|
|
||||||
}),
|
|
||||||
getEntity("input_datetime", "date_and_time", "2022-01-10 00:00:00", {
|
|
||||||
has_date: true,
|
|
||||||
has_time: true,
|
|
||||||
editable: true,
|
|
||||||
year: 2022,
|
|
||||||
month: 1,
|
|
||||||
day: 10,
|
|
||||||
hour: 0,
|
|
||||||
minute: 0,
|
|
||||||
second: 0,
|
|
||||||
timestamp: 1641801600,
|
|
||||||
friendly_name: "Date and Time",
|
|
||||||
}),
|
|
||||||
getEntity("input_select", "dropdown", "Soda", {
|
|
||||||
friendly_name: "Dropdown",
|
|
||||||
options: ["Soda", "Beer", "Wine"],
|
|
||||||
}),
|
|
||||||
getEntity("input_text", "text", "Inspiration", {
|
|
||||||
friendly_name: "Text",
|
|
||||||
mode: "text",
|
|
||||||
}),
|
|
||||||
getEntity("timer", "timer", "idle", {
|
|
||||||
friendly_name: "Timer",
|
|
||||||
duration: "0:05:00",
|
|
||||||
}),
|
|
||||||
getEntity("counter", "counter", "3", {
|
|
||||||
friendly_name: "Counter",
|
|
||||||
initial: 0,
|
|
||||||
step: 1,
|
|
||||||
minimum: 0,
|
|
||||||
maximum: 10,
|
|
||||||
}),
|
|
||||||
|
|
||||||
getEntity("light", "unavailable", "unavailable", {
|
getEntity("light", "unavailable", "unavailable", {
|
||||||
friendly_name: "Bed Light",
|
friendly_name: "Bed Light",
|
||||||
}),
|
}),
|
||||||
@@ -106,7 +70,7 @@ const ENTITIES = [
|
|||||||
supported_features: 11,
|
supported_features: 11,
|
||||||
}),
|
}),
|
||||||
getEntity("scene", "unavailable", "unavailable", {
|
getEntity("scene", "unavailable", "unavailable", {
|
||||||
friendly_name: "Romantic Scene",
|
friendly_name: "Romantic lights",
|
||||||
}),
|
}),
|
||||||
getEntity("device_tracker", "unavailable", "unavailable", {
|
getEntity("device_tracker", "unavailable", "unavailable", {
|
||||||
friendly_name: "Paulus",
|
friendly_name: "Paulus",
|
||||||
@@ -141,22 +105,7 @@ const CONFIGS = [
|
|||||||
- light.bed_light
|
- light.bed_light
|
||||||
- light.non_existing
|
- light.non_existing
|
||||||
- climate.ecobee
|
- climate.ecobee
|
||||||
- input_number.number
|
- input_number.noise_allowance
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
heading: "Helpers",
|
|
||||||
config: `
|
|
||||||
- type: entities
|
|
||||||
title: Helpers
|
|
||||||
entities:
|
|
||||||
- entity: input_boolean.toggle
|
|
||||||
- entity: input_datetime.date_and_time
|
|
||||||
- entity: input_number.number
|
|
||||||
- entity: input_select.dropdown
|
|
||||||
- entity: input_text.text
|
|
||||||
- entity: timer.timer
|
|
||||||
- entity: counter.counter
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -171,7 +120,7 @@ const CONFIGS = [
|
|||||||
- lock.kitchen_door
|
- lock.kitchen_door
|
||||||
- light.bed_light
|
- light.bed_light
|
||||||
- climate.ecobee
|
- climate.ecobee
|
||||||
- input_number.number
|
- input_number.noise_allowance
|
||||||
title: Random group
|
title: Random group
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -187,7 +136,7 @@ const CONFIGS = [
|
|||||||
- lock.kitchen_door
|
- lock.kitchen_door
|
||||||
- light.bed_light
|
- light.bed_light
|
||||||
- climate.ecobee
|
- climate.ecobee
|
||||||
- input_number.number
|
- input_number.noise_allowance
|
||||||
title: Random group
|
title: Random group
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
`,
|
`,
|
||||||
@@ -234,7 +183,7 @@ const CONFIGS = [
|
|||||||
icon: mdi:alarm-light
|
icon: mdi:alarm-light
|
||||||
name: Bed Light Custom Icon
|
name: Bed Light Custom Icon
|
||||||
- climate.ecobee
|
- climate.ecobee
|
||||||
- input_number.number
|
- input_number.noise_allowance
|
||||||
title: Random group
|
title: Random group
|
||||||
show_header_toggle: false
|
show_header_toggle: false
|
||||||
`,
|
`,
|
||||||
@@ -249,7 +198,7 @@ const CONFIGS = [
|
|||||||
name: Bed light
|
name: Bed light
|
||||||
action_name: Toggle light
|
action_name: Toggle light
|
||||||
service: light.toggle
|
service: light.toggle
|
||||||
data:
|
service_data:
|
||||||
entity_id: light.bed_light
|
entity_id: light.bed_light
|
||||||
- type: section
|
- type: section
|
||||||
label: Links
|
label: Links
|
||||||
@@ -267,7 +216,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-entities-card")
|
@customElement("demo-hui-entities-card")
|
||||||
class DemoEntities extends LitElement {
|
class DemoEntities extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -286,6 +235,6 @@ class DemoEntities extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-entities-card": DemoEntities;
|
"demo-hui-entities-card": DemoEntities;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
||||||
@@ -68,7 +68,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-entity-button-card")
|
@customElement("demo-hui-entity-button-card")
|
||||||
class DemoButtonEntity extends LitElement {
|
class DemoButtonEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -87,6 +87,6 @@ class DemoButtonEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-entity-button-card": DemoButtonEntity;
|
"demo-hui-entity-button-card": DemoButtonEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("device_tracker", "demo_paulus", "work", {
|
getEntity("device_tracker", "demo_paulus", "work", {
|
||||||
@@ -109,7 +109,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-entity-filter-card")
|
@customElement("demo-hui-entity-filter-card")
|
||||||
class DemoEntityFilter extends LitElement {
|
class DemoEntityFilter extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -128,6 +128,6 @@ class DemoEntityFilter extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-entity-filter-card": DemoEntityFilter;
|
"demo-hui-entity-filter-card": DemoEntityFilter;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("sensor", "brightness", "12", {}),
|
getEntity("sensor", "brightness", "12", {}),
|
||||||
@@ -106,7 +106,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-gauge-card")
|
@customElement("demo-hui-gauge-card")
|
||||||
class DemoGaugeEntity extends LitElement {
|
class DemoGaugeEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -125,6 +125,6 @@ class DemoGaugeEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-gauge-card": DemoGaugeEntity;
|
"demo-hui-gauge-card": DemoGaugeEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("device_tracker", "demo_paulus", "home", {
|
getEntity("device_tracker", "demo_paulus", "home", {
|
||||||
@@ -199,7 +199,7 @@ const CONFIGS = [
|
|||||||
tap_action:
|
tap_action:
|
||||||
action: call-service
|
action: call-service
|
||||||
service: light.turn_on
|
service: light.turn_on
|
||||||
data:
|
service_data:
|
||||||
entity_id: light.ceiling_lights
|
entity_id: light.ceiling_lights
|
||||||
- entity: sun.sun
|
- entity: sun.sun
|
||||||
name: Regular
|
name: Regular
|
||||||
@@ -209,7 +209,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-glance-card")
|
@customElement("demo-hui-glance-card")
|
||||||
class DemoGlanceEntity extends LitElement {
|
class DemoGlanceEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -228,6 +228,6 @@ class DemoGlanceEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-glance-card": DemoGlanceEntity;
|
"demo-hui-glance-card": DemoGlanceEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,9 +1,9 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { mockHistory } from "../../../../demo/src/stubs/history";
|
import { mockHistory } from "../../../demo/src/stubs/history";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "kitchen_lights", "on", {
|
getEntity("light", "kitchen_lights", "on", {
|
||||||
@@ -199,7 +199,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-grid-and-stack-card")
|
@customElement("demo-hui-grid-and-stack-card")
|
||||||
class DemoStack extends LitElement {
|
class DemoStack extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -219,6 +219,6 @@ class DemoStack extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-grid-and-stack-card": DemoStack;
|
"demo-hui-grid-and-stack-card": DemoStack;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import "../components/demo-cards";
|
||||||
import "../../components/demo-cards";
|
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
@@ -37,22 +36,15 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-iframe-card")
|
@customElement("demo-hui-iframe-card")
|
||||||
class DemoIframe extends LitElement {
|
class DemoIframe extends LitElement {
|
||||||
@query("demo-cards") private _demos!: HTMLElement;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
|
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProperties: PropertyValues) {
|
|
||||||
super.firstUpdated(changedProperties);
|
|
||||||
provideHass(this._demos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-iframe-card": DemoIframe;
|
"demo-hui-iframe-card": DemoIframe;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
||||||
@@ -62,7 +62,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-light-card")
|
@customElement("demo-hui-light-card")
|
||||||
class DemoLightEntity extends LitElement {
|
class DemoLightEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -81,6 +81,6 @@ class DemoLightEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-light-card": DemoLightEntity;
|
"demo-hui-light-card": DemoLightEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("device_tracker", "demo_paulus", "not_home", {
|
getEntity("device_tracker", "demo_paulus", "not_home", {
|
||||||
@@ -160,7 +160,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-map-card")
|
@customElement("demo-hui-map-card")
|
||||||
class DemoMap extends LitElement {
|
class DemoMap extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -179,6 +179,6 @@ class DemoMap extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-map-card": DemoMap;
|
"demo-hui-map-card": DemoMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,15 +1,15 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { mockTemplate } from "../../../../demo/src/stubs/template";
|
import { mockTemplate } from "../../../demo/src/stubs/template";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
heading: "markdown-it demo",
|
heading: "markdown-it demo",
|
||||||
config: `
|
config: `
|
||||||
- type: markdown
|
- type: markdown
|
||||||
content: >-
|
content: >
|
||||||
# h1 Heading 8-)
|
# h1 Heading 8-)
|
||||||
|
|
||||||
## h2 Heading
|
## h2 Heading
|
||||||
@@ -249,22 +249,11 @@ const CONFIGS = [
|
|||||||
::: warning
|
::: warning
|
||||||
*here be dragons*
|
*here be dragons*
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### ha-alert
|
|
||||||
|
|
||||||
You can use our [\`ha-alert\`](https://design.home-assistant.io/#components/ha-alert) component in markdown content rendered in the Home Assistant Frontend.
|
|
||||||
|
|
||||||
<ha-alert alert-type="error">This is an error alert — check it out!</ha-alert>
|
|
||||||
<ha-alert alert-type="warning">This is a warning alert — check it out!</ha-alert>
|
|
||||||
<ha-alert alert-type="info">This is an info alert — check it out!</ha-alert>
|
|
||||||
<ha-alert alert-type="success">This is a success alert — check it out!</ha-alert>
|
|
||||||
<ha-alert title="Test alert">This is an alert with a title</ha-alert>
|
|
||||||
|
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-markdown-card")
|
@customElement("demo-hui-markdown-card")
|
||||||
class DemoMarkdown extends LitElement {
|
class DemoMarkdown extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -283,6 +272,6 @@ class DemoMarkdown extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-markdown-card": DemoMarkdown;
|
"demo-hui-markdown-card": DemoMarkdown;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
import { createMediaPlayerEntities } from "../../data/media_players";
|
import { createMediaPlayerEntities } from "../data/media_players";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
@@ -157,7 +157,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-media-control-card")
|
@customElement("demo-hui-media-control-card")
|
||||||
class DemoHuiMediaControlCard extends LitElement {
|
class DemoHuiMediaControlCard extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -176,6 +176,6 @@ class DemoHuiMediaControlCard extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-media-control-card": DemoHuiMediaControlCard;
|
"demo-hui-media-control-card": DemoHuiMediaControlCard;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
import { createMediaPlayerEntities } from "../../data/media_players";
|
import { createMediaPlayerEntities } from "../data/media_players";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-media-player-row")
|
@customElement("demo-hui-media-player-row")
|
||||||
class DemoHuiMediaPlayerRow extends LitElement {
|
class DemoHuiMediaPlayerRow extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -73,6 +73,6 @@ class DemoHuiMediaPlayerRow extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-media-player-rows": DemoHuiMediaPlayerRow;
|
"demo-hui-media-player-row": DemoHuiMediaPlayerRow;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
||||||
@@ -40,7 +40,7 @@ const CONFIGS = [
|
|||||||
left: 90%
|
left: 90%
|
||||||
padding: 0px
|
padding: 0px
|
||||||
service: light.turn_off
|
service: light.turn_off
|
||||||
data:
|
service_data:
|
||||||
entity_id: group.all_lights
|
entity_id: group.all_lights
|
||||||
- type: icon
|
- type: icon
|
||||||
icon: mdi:cctv
|
icon: mdi:cctv
|
||||||
@@ -88,7 +88,7 @@ const CONFIGS = [
|
|||||||
left: 90%
|
left: 90%
|
||||||
padding: 0px
|
padding: 0px
|
||||||
service: light.turn_off
|
service: light.turn_off
|
||||||
data:
|
service_data:
|
||||||
entity_id: group.all_lights
|
entity_id: group.all_lights
|
||||||
- type: icon
|
- type: icon
|
||||||
icon: mdi:cctv
|
icon: mdi:cctv
|
||||||
@@ -124,7 +124,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-picture-elements-card")
|
@customElement("demo-hui-picture-elements-card")
|
||||||
class DemoPictureElements extends LitElement {
|
class DemoPictureElements extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -143,6 +143,6 @@ class DemoPictureElements extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-picture-elements-card": DemoPictureElements;
|
"demo-hui-picture-elements-card": DemoPictureElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "kitchen_lights", "on", {
|
getEntity("light", "kitchen_lights", "on", {
|
||||||
@@ -79,7 +79,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-picture-entity-card")
|
@customElement("demo-hui-picture-entity-card")
|
||||||
class DemoPictureEntity extends LitElement {
|
class DemoPictureEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -98,6 +98,6 @@ class DemoPictureEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-picture-entity-card": DemoPictureEntity;
|
"demo-hui-picture-entity-card": DemoPictureEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("switch", "decorative_lights", "on", {
|
getEntity("switch", "decorative_lights", "on", {
|
||||||
@@ -120,7 +120,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-picture-glance-card")
|
@customElement("demo-hui-picture-glance-card")
|
||||||
class DemoPictureGlance extends LitElement {
|
class DemoPictureGlance extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -139,6 +139,6 @@ class DemoPictureGlance extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-picture-glance-card": DemoPictureGlance;
|
"demo-hui-picture-glance-card": DemoPictureGlance;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
import { createPlantEntities } from "../../data/plants";
|
import { createPlantEntities } from "../data/plants";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-plant-card")
|
@customElement("demo-hui-plant-card")
|
||||||
export class DemoPlantEntity extends LitElement {
|
export class DemoPlantEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -48,6 +48,6 @@ export class DemoPlantEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-plant-card": DemoPlantEntity;
|
"demo-hui-plant-card": DemoPlantEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const CONFIGS = [
|
const CONFIGS = [
|
||||||
{
|
{
|
||||||
@@ -19,7 +19,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-shopping-list-card")
|
@customElement("demo-hui-shopping-list-card")
|
||||||
class DemoShoppingListEntity extends LitElement {
|
class DemoShoppingListEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -44,6 +44,6 @@ class DemoShoppingListEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-shopping-list-card": DemoShoppingListEntity;
|
"demo-hui-shopping-list-card": DemoShoppingListEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, query } from "lit/decorators";
|
import { customElement, query } from "lit/decorators";
|
||||||
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 "../../components/demo-cards";
|
import "../components/demo-cards";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("climate", "ecobee", "auto", {
|
getEntity("climate", "ecobee", "auto", {
|
||||||
@@ -73,7 +73,7 @@ const CONFIGS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-lovelace-thermostat-card")
|
@customElement("demo-hui-thermostat-card")
|
||||||
class DemoThermostatEntity extends LitElement {
|
class DemoThermostatEntity extends LitElement {
|
||||||
@query("#demos") private _demoRoot!: HTMLElement;
|
@query("#demos") private _demoRoot!: HTMLElement;
|
||||||
|
|
||||||
@@ -92,6 +92,6 @@ class DemoThermostatEntity extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-lovelace-thermostat-card": DemoThermostatEntity;
|
"demo-hui-thermostat-card": DemoThermostatEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,22 +1,22 @@
|
|||||||
import { html, css, LitElement, TemplateResult } from "lit";
|
import { html, css, LitElement, TemplateResult } from "lit";
|
||||||
import "../../../../src/components/ha-formfield";
|
import "../../../src/components/ha-formfield";
|
||||||
import "../../../../src/components/ha-switch";
|
import "../../../src/components/ha-switch";
|
||||||
|
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { IntegrationManifest } from "../../../../src/data/integration";
|
import { IntegrationManifest } from "../../../src/data/integration";
|
||||||
|
|
||||||
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";
|
||||||
import "../../../../src/panels/config/integrations/ha-integration-card";
|
import "../../../src/panels/config/integrations/ha-integration-card";
|
||||||
import "../../../../src/panels/config/integrations/ha-ignored-config-entry-card";
|
import "../../../src/panels/config/integrations/ha-ignored-config-entry-card";
|
||||||
import "../../../../src/panels/config/integrations/ha-config-flow-card";
|
import "../../../src/panels/config/integrations/ha-config-flow-card";
|
||||||
import type {
|
import type {
|
||||||
ConfigEntryExtended,
|
ConfigEntryExtended,
|
||||||
DataEntryFlowProgressExtended,
|
DataEntryFlowProgressExtended,
|
||||||
} from "../../../../src/panels/config/integrations/ha-config-integrations";
|
} from "../../../src/panels/config/integrations/ha-config-integrations";
|
||||||
import { DeviceRegistryEntry } from "../../../../src/data/device_registry";
|
import { DeviceRegistryEntry } from "../../../src/data/device_registry";
|
||||||
import { EntityRegistryEntry } from "../../../../src/data/entity_registry";
|
import { EntityRegistryEntry } from "../../../src/data/entity_registry";
|
||||||
|
|
||||||
const createConfigEntry = (
|
const createConfigEntry = (
|
||||||
title: string,
|
title: string,
|
||||||
@@ -29,7 +29,6 @@ const createConfigEntry = (
|
|||||||
source: "zeroconf",
|
source: "zeroconf",
|
||||||
state: "loaded",
|
state: "loaded",
|
||||||
supports_options: false,
|
supports_options: false,
|
||||||
supports_remove_device: false,
|
|
||||||
supports_unload: true,
|
supports_unload: true,
|
||||||
disabled_by: null,
|
disabled_by: null,
|
||||||
pref_disable_new_entities: false,
|
pref_disable_new_entities: false,
|
||||||
@@ -188,7 +187,6 @@ const createEntityRegistryEntries = (
|
|||||||
device_id: "mock-device-id",
|
device_id: "mock-device-id",
|
||||||
area_id: null,
|
area_id: null,
|
||||||
disabled_by: null,
|
disabled_by: null,
|
||||||
hidden_by: null,
|
|
||||||
entity_category: null,
|
entity_category: null,
|
||||||
entity_id: "binary_sensor.updater",
|
entity_id: "binary_sensor.updater",
|
||||||
name: null,
|
name: null,
|
||||||
@@ -208,7 +206,6 @@ const createDeviceRegistryEntries = (
|
|||||||
model: "Mock Device",
|
model: "Mock Device",
|
||||||
name: "Tag Reader",
|
name: "Tag Reader",
|
||||||
sw_version: null,
|
sw_version: null,
|
||||||
hw_version: "1.0.0",
|
|
||||||
id: "mock-device-id",
|
id: "mock-device-id",
|
||||||
identifiers: [],
|
identifiers: [],
|
||||||
via_device_id: null,
|
via_device_id: null,
|
||||||
@@ -219,7 +216,7 @@ const createDeviceRegistryEntries = (
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("demo-misc-integration-card")
|
@customElement("demo-integration-card")
|
||||||
export class DemoIntegrationCard extends LitElement {
|
export class DemoIntegrationCard extends LitElement {
|
||||||
@property({ attribute: false }) hass?: HomeAssistant;
|
@property({ attribute: false }) hass?: HomeAssistant;
|
||||||
|
|
||||||
@@ -354,6 +351,6 @@ export class DemoIntegrationCard extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"demo-misc-integration-card": DemoIntegrationCard;
|
"demo-integration-card": DemoIntegrationCard;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,19 +1,19 @@
|
|||||||
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||||
import { customElement, property, query } from "lit/decorators";
|
import { customElement, property, query } from "lit/decorators";
|
||||||
import "../../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import {
|
import {
|
||||||
LightColorModes,
|
LightColorModes,
|
||||||
SUPPORT_EFFECT,
|
SUPPORT_EFFECT,
|
||||||
SUPPORT_FLASH,
|
SUPPORT_FLASH,
|
||||||
SUPPORT_TRANSITION,
|
SUPPORT_TRANSITION,
|
||||||
} from "../../../../src/data/light";
|
} from "../../../src/data/light";
|
||||||
import "../../../../src/dialogs/more-info/more-info-content";
|
import "../../../src/dialogs/more-info/more-info-content";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import { getEntity } from "../../../src/fake_data/entity";
|
||||||
import {
|
import {
|
||||||
MockHomeAssistant,
|
MockHomeAssistant,
|
||||||
provideHass,
|
provideHass,
|
||||||
} from "../../../../src/fake_data/provide_hass";
|
} from "../../../src/fake_data/provide_hass";
|
||||||
import "../../components/demo-more-infos";
|
import "../components/demo-more-infos";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("light", "bed_light", "on", {
|
getEntity("light", "bed_light", "on", {
|
@@ -1,11 +1,11 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
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 { ActionHandlerEvent } from "../../../../src/data/lovelace";
|
import { ActionHandlerEvent } from "../../../src/data/lovelace";
|
||||||
import { actionHandler } from "../../../../src/panels/lovelace/common/directives/action-handler-directive";
|
import { actionHandler } from "../../../src/panels/lovelace/common/directives/action-handler-directive";
|
||||||
|
|
||||||
@customElement("demo-misc-util-long-press")
|
@customElement("demo-util-long-press")
|
||||||
export class DemoUtilLongPress extends LitElement {
|
export class DemoUtilLongPress extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
230
gallery/src/ha-gallery.js
Normal file
230
gallery/src/ha-gallery.js
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
import "@polymer/app-layout/app-header-layout/app-header-layout";
|
||||||
|
import "@polymer/app-layout/app-header/app-header";
|
||||||
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@polymer/paper-item/paper-item-body";
|
||||||
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
|
/* eslint-plugin-disable lit */
|
||||||
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
import "../../src/components/ha-card";
|
||||||
|
import "../../src/components/ha-icon";
|
||||||
|
import "../../src/components/ha-icon-button";
|
||||||
|
import "../../src/managers/notification-manager";
|
||||||
|
import "../../src/styles/polymer-ha-style";
|
||||||
|
// eslint-disable-next-line import/extensions
|
||||||
|
import { DEMOS } from "../build/import-demos";
|
||||||
|
|
||||||
|
class HaGallery extends PolymerElement {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style include="iron-positioning ha-style">
|
||||||
|
:host {
|
||||||
|
-ms-user-select: initial;
|
||||||
|
-webkit-user-select: initial;
|
||||||
|
-moz-user-select: initial;
|
||||||
|
}
|
||||||
|
app-header-layout {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
ha-icon-button.invisible {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickers {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickers ha-card {
|
||||||
|
width: 400px;
|
||||||
|
display: block;
|
||||||
|
margin: 16px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickers ha-card:last-child {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
margin: -1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<app-header-layout>
|
||||||
|
<app-header slot="header" fixed>
|
||||||
|
<app-toolbar>
|
||||||
|
<ha-icon-button
|
||||||
|
on-click="_backTapped"
|
||||||
|
class$="[[_computeHeaderButtonClass(_demo)]]"
|
||||||
|
>
|
||||||
|
<ha-icon icon="hass:arrow-left"></ha-icon>
|
||||||
|
</ha-icon-button>
|
||||||
|
<div main-title>
|
||||||
|
[[_withDefault(_demo, "Home Assistant Gallery")]]
|
||||||
|
</div>
|
||||||
|
</app-toolbar>
|
||||||
|
</app-header>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div id="demo"></div>
|
||||||
|
<template is="dom-if" if="[[!_demo]]">
|
||||||
|
<div class="pickers">
|
||||||
|
<ha-card header="Lovelace Card Demos">
|
||||||
|
<div class="card-content intro">
|
||||||
|
<p>
|
||||||
|
Lovelace has many different cards. Each card allows the user
|
||||||
|
to tell a different story about what is going on in their
|
||||||
|
house. These cards are very customizable, as no household is
|
||||||
|
the same.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This gallery helps our developers and designers to see all
|
||||||
|
the different states that each card can be in.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Check
|
||||||
|
<a href="https://www.home-assistant.io/lovelace"
|
||||||
|
>the official website</a
|
||||||
|
>
|
||||||
|
for instructions on how to get started with Lovelace.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<template is="dom-repeat" items="[[_lovelaceDemos]]">
|
||||||
|
<a href="#[[item]]">
|
||||||
|
<paper-item>
|
||||||
|
<paper-item-body>{{ item }}</paper-item-body>
|
||||||
|
<ha-icon icon="hass:chevron-right"></ha-icon>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</ha-card>
|
||||||
|
|
||||||
|
<ha-card header="Other Demos">
|
||||||
|
<div class="card-content intro"></div>
|
||||||
|
<template is="dom-repeat" items="[[_restDemos]]">
|
||||||
|
<a href="#[[item]]">
|
||||||
|
<paper-item>
|
||||||
|
<paper-item-body>{{ item }}</paper-item-body>
|
||||||
|
<ha-icon icon="hass:chevron-right"></ha-icon>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</ha-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</app-header-layout>
|
||||||
|
<notification-manager
|
||||||
|
hass="[[_fakeHass]]"
|
||||||
|
id="notifications"
|
||||||
|
></notification-manager>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
_fakeHass: {
|
||||||
|
type: Object,
|
||||||
|
// Just enough for computeRTL
|
||||||
|
value: {
|
||||||
|
language: "en",
|
||||||
|
translationMetadata: {
|
||||||
|
translations: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
_demo: {
|
||||||
|
type: String,
|
||||||
|
value: document.location.hash.substr(1),
|
||||||
|
observer: "_demoChanged",
|
||||||
|
},
|
||||||
|
_demos: {
|
||||||
|
type: Array,
|
||||||
|
value: Object.keys(DEMOS),
|
||||||
|
},
|
||||||
|
_lovelaceDemos: {
|
||||||
|
type: Array,
|
||||||
|
computed: "_computeLovelace(_demos)",
|
||||||
|
},
|
||||||
|
_restDemos: {
|
||||||
|
type: Array,
|
||||||
|
computed: "_computeRest(_demos)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
|
||||||
|
this.addEventListener("show-notification", (ev) =>
|
||||||
|
this.$.notifications.showDialog({ message: ev.detail.message })
|
||||||
|
);
|
||||||
|
|
||||||
|
this.addEventListener("alert-dismissed-clicked", () =>
|
||||||
|
this.$.notifications.showDialog({ message: "Alert dismissed clicked" })
|
||||||
|
);
|
||||||
|
|
||||||
|
this.addEventListener("alert-action-clicked", () =>
|
||||||
|
this.$.notifications.showDialog({ message: "Alert action clicked" })
|
||||||
|
);
|
||||||
|
|
||||||
|
this.addEventListener("hass-more-info", (ev) => {
|
||||||
|
if (ev.detail.entityId) {
|
||||||
|
this.$.notifications.showDialog({
|
||||||
|
message: `Showing more info for ${ev.detail.entityId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("hashchange", () => {
|
||||||
|
this._demo = document.location.hash.substr(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_withDefault(value, def) {
|
||||||
|
return value || def;
|
||||||
|
}
|
||||||
|
|
||||||
|
_demoChanged(demo) {
|
||||||
|
const root = this.$.demo;
|
||||||
|
|
||||||
|
while (root.lastChild) root.removeChild(root.lastChild);
|
||||||
|
|
||||||
|
if (demo) {
|
||||||
|
DEMOS[demo]();
|
||||||
|
const el = document.createElement(demo);
|
||||||
|
root.appendChild(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeHeaderButtonClass(demo) {
|
||||||
|
return demo ? "" : "invisible";
|
||||||
|
}
|
||||||
|
|
||||||
|
_backTapped() {
|
||||||
|
document.location.hash = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeLovelace(demos) {
|
||||||
|
return demos.filter((demo) => demo.includes("hui"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeRest(demos) {
|
||||||
|
return demos.filter((demo) => !demo.includes("hui"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("ha-gallery", HaGallery);
|
@@ -1,275 +0,0 @@
|
|||||||
import { mdiMenu } from "@mdi/js";
|
|
||||||
import "@material/mwc-drawer";
|
|
||||||
import "@material/mwc-top-app-bar-fixed";
|
|
||||||
import { html, css, LitElement, PropertyValues } from "lit";
|
|
||||||
import { customElement, property, query } from "lit/decorators";
|
|
||||||
import "../../src/components/ha-icon-button";
|
|
||||||
import "../../src/managers/notification-manager";
|
|
||||||
import "../../src/components/ha-expansion-panel";
|
|
||||||
import { haStyle } from "../../src/resources/styles";
|
|
||||||
import { PAGES, SIDEBAR } from "../build/import-pages";
|
|
||||||
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
|
|
||||||
import "./components/page-description";
|
|
||||||
|
|
||||||
const GITHUB_DEMO_URL =
|
|
||||||
"https://github.com/home-assistant/frontend/blob/dev/gallery/src/pages/";
|
|
||||||
|
|
||||||
const FAKE_HASS = {
|
|
||||||
// Just enough for computeRTL for notification-manager
|
|
||||||
language: "en",
|
|
||||||
translationMetadata: {
|
|
||||||
translations: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("ha-gallery")
|
|
||||||
class HaGallery extends LitElement {
|
|
||||||
@property() private _page =
|
|
||||||
document.location.hash.substring(1) ||
|
|
||||||
`${SIDEBAR[0].category}/${SIDEBAR[0].pages![0]}`;
|
|
||||||
|
|
||||||
@query("notification-manager")
|
|
||||||
private _notifications!: HTMLElementTagNameMap["notification-manager"];
|
|
||||||
|
|
||||||
@query("mwc-drawer")
|
|
||||||
private _drawer!: HTMLElementTagNameMap["mwc-drawer"];
|
|
||||||
|
|
||||||
private _narrow = window.matchMedia("(max-width: 600px)").matches;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const sidebar: unknown[] = [];
|
|
||||||
|
|
||||||
for (const group of SIDEBAR) {
|
|
||||||
const links: unknown[] = [];
|
|
||||||
|
|
||||||
for (const page of group.pages!) {
|
|
||||||
const key = `${group.category}/${page}`;
|
|
||||||
const active = this._page === key;
|
|
||||||
if (!(key in PAGES)) {
|
|
||||||
console.error("Undefined page referenced in sidebar.js:", key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const title = PAGES[key].metadata.title || page;
|
|
||||||
links.push(html`
|
|
||||||
<a ?active=${active} href=${`#${group.category}/${page}`}>${title}</a>
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
sidebar.push(
|
|
||||||
group.header
|
|
||||||
? html`
|
|
||||||
<ha-expansion-panel .header=${group.header}>
|
|
||||||
${links}
|
|
||||||
</ha-expansion-panel>
|
|
||||||
`
|
|
||||||
: links
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<mwc-drawer
|
|
||||||
hasHeader
|
|
||||||
.open=${!this._narrow}
|
|
||||||
.type=${this._narrow ? "modal" : "dismissible"}
|
|
||||||
>
|
|
||||||
<span slot="title">Home Assistant Design</span>
|
|
||||||
<!-- <span slot="subtitle">subtitle</span> -->
|
|
||||||
<div class="sidebar">${sidebar}</div>
|
|
||||||
<div slot="appContent">
|
|
||||||
<mwc-top-app-bar-fixed>
|
|
||||||
<ha-icon-button
|
|
||||||
slot="navigationIcon"
|
|
||||||
@click=${this._menuTapped}
|
|
||||||
.path=${mdiMenu}
|
|
||||||
></ha-icon-button>
|
|
||||||
|
|
||||||
<div slot="title">
|
|
||||||
${PAGES[this._page].metadata.title || this._page.split("/")[1]}
|
|
||||||
</div>
|
|
||||||
</mwc-top-app-bar-fixed>
|
|
||||||
<div class="content">
|
|
||||||
${PAGES[this._page].description
|
|
||||||
? html`
|
|
||||||
<page-description .page=${this._page}></page-description>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
|
|
||||||
</div>
|
|
||||||
<div class="page-footer">
|
|
||||||
<div class="header">Help us to improve our documentation</div>
|
|
||||||
<div class="secondary">
|
|
||||||
Suggest an edit to this page, or provide/view feedback for this
|
|
||||||
page.
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
${PAGES[this._page].description ||
|
|
||||||
Object.keys(PAGES[this._page].metadata).length > 0
|
|
||||||
? html`
|
|
||||||
<a
|
|
||||||
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Edit text
|
|
||||||
</a>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${PAGES[this._page].demo
|
|
||||||
? html`
|
|
||||||
<a
|
|
||||||
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Edit demo
|
|
||||||
</a>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mwc-drawer>
|
|
||||||
<notification-manager
|
|
||||||
.hass=${FAKE_HASS}
|
|
||||||
id="notifications"
|
|
||||||
></notification-manager>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
firstUpdated(changedProps: PropertyValues) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
|
|
||||||
this.addEventListener("show-notification", (ev) =>
|
|
||||||
this._notifications.showDialog({ message: ev.detail.message })
|
|
||||||
);
|
|
||||||
this.addEventListener("alert-dismissed-clicked", () =>
|
|
||||||
this._notifications.showDialog({ message: "Alert dismissed clicked" })
|
|
||||||
);
|
|
||||||
this.addEventListener("hass-more-info", (ev) => {
|
|
||||||
if (ev.detail.entityId) {
|
|
||||||
this._notifications.showDialog({
|
|
||||||
message: `Showing more info for ${ev.detail.entityId}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.location.hash = this._page;
|
|
||||||
|
|
||||||
window.addEventListener("hashchange", () => {
|
|
||||||
this._page = document.location.hash.substring(1);
|
|
||||||
if (this._narrow) {
|
|
||||||
this._drawer.open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updated(changedProps: PropertyValues) {
|
|
||||||
super.updated(changedProps);
|
|
||||||
if (!changedProps.has("_page")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PAGES[this._page].demo) {
|
|
||||||
PAGES[this._page].demo();
|
|
||||||
}
|
|
||||||
|
|
||||||
const menuItem = this.shadowRoot!.querySelector(
|
|
||||||
`a[href="#${this._page}"]`
|
|
||||||
)!;
|
|
||||||
// Make sure section is expanded
|
|
||||||
if (menuItem.parentElement instanceof HTMLDetailsElement) {
|
|
||||||
menuItem.parentElement.open = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_menuTapped() {
|
|
||||||
this._drawer.open = !this._drawer.open;
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = [
|
|
||||||
haStyle,
|
|
||||||
css`
|
|
||||||
:host {
|
|
||||||
-ms-user-select: initial;
|
|
||||||
-webkit-user-select: initial;
|
|
||||||
-moz-user-select: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a {
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
display: block;
|
|
||||||
padding: 12px;
|
|
||||||
text-decoration: none;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a[active]::before {
|
|
||||||
border-radius: 12px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 2px;
|
|
||||||
bottom: 0;
|
|
||||||
left: 2px;
|
|
||||||
pointer-events: none;
|
|
||||||
content: "";
|
|
||||||
transition: opacity 15ms linear;
|
|
||||||
will-change: opacity;
|
|
||||||
background-color: var(--sidebar-selected-icon-color);
|
|
||||||
opacity: 0.12;
|
|
||||||
}
|
|
||||||
|
|
||||||
div[slot="appContent"] {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: var(--primary-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
page-description {
|
|
||||||
margin: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer {
|
|
||||||
text-align: center;
|
|
||||||
margin: 16px;
|
|
||||||
padding: 16px;
|
|
||||||
border-radius: 12px;
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer div {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer .header {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 28px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer .secondary {
|
|
||||||
line-height: 23px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer a {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 8px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-gallery": HaGallery;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,7 +7,7 @@
|
|||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#2157BC" />
|
<meta name="theme-color" content="#2157BC" />
|
||||||
<title>Home Assistant Design</title>
|
<title>HAGallery</title>
|
||||||
|
|
||||||
<script type="module" src="<%= latestGalleryJS %>"></script>
|
<script type="module" src="<%= latestGalleryJS %>"></script>
|
||||||
<style>
|
<style>
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: Describe Action
|
|
||||||
---
|
|
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: Describe Condition
|
|
||||||
---
|
|
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: Describe Trigger
|
|
||||||
---
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user