mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-27 01:59:26 +00:00
Compare commits
1 Commits
20211007.1
...
data_disk_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d1605ba196 |
@@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"airbnb-base",
|
|
||||||
"airbnb-typescript/base",
|
"airbnb-typescript/base",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:wc/recommended",
|
"plugin:wc/recommended",
|
||||||
"plugin:lit/all",
|
"plugin:lit/recommended",
|
||||||
"prettier"
|
"prettier"
|
||||||
],
|
],
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
@@ -29,7 +28,6 @@
|
|||||||
"__BUILD__": false,
|
"__BUILD__": false,
|
||||||
"__VERSION__": false,
|
"__VERSION__": false,
|
||||||
"__STATIC_PATH__": false,
|
"__STATIC_PATH__": false,
|
||||||
"__SUPERVISOR__": false,
|
|
||||||
"Polymer": true
|
"Polymer": true
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
@@ -111,8 +109,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"unused-imports/no-unused-imports": "error",
|
"unused-imports/no-unused-imports": "error",
|
||||||
"lit/attribute-value-entities": "off",
|
"lit/attribute-value-entities": "off"
|
||||||
"lit/no-template-map": "off"
|
|
||||||
},
|
},
|
||||||
"plugins": ["disable", "unused-imports"],
|
"plugins": ["disable", "unused-imports"],
|
||||||
"processor": "disable/disable"
|
"processor": "disable/disable"
|
||||||
|
10
.github/workflows/ci.yaml
vendored
10
.github/workflows/ci.yaml
vendored
@@ -12,7 +12,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 14
|
NODE_VERSION: 14
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=4096
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
@@ -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-demos
|
run: ./node_modules/.bin/gulp gen-icons-json build-translations 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
|
||||||
@@ -53,10 +53,8 @@ jobs:
|
|||||||
run: yarn install
|
run: yarn install
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
- name: Build resources
|
- name: Run Mocha
|
||||||
run: ./node_modules/.bin/gulp build-translations build-locale-data
|
run: yarn run mocha
|
||||||
- name: Run Tests
|
|
||||||
run: yarn run test
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [lint, test]
|
needs: [lint, test]
|
||||||
|
2
.github/workflows/demo.yaml
vendored
2
.github/workflows/demo.yaml
vendored
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: 14
|
NODE_VERSION: 14
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=4096
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
|
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -8,7 +8,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
PYTHON_VERSION: 3.8
|
PYTHON_VERSION: 3.8
|
||||||
NODE_VERSION: 14
|
NODE_VERSION: 14
|
||||||
NODE_OPTIONS: --max_old_space_size=6144
|
NODE_OPTIONS: --max_old_space_size=4096
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
# build
|
# build
|
||||||
build
|
build
|
||||||
|
build-translations/*
|
||||||
hass_frontend/*
|
hass_frontend/*
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
4
.mocharc.cjs
Normal file
4
.mocharc.cjs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
require: "test-mocha/testconf.js",
|
||||||
|
timeout: 10000,
|
||||||
|
};
|
@@ -1,4 +1,5 @@
|
|||||||
build
|
build
|
||||||
|
build-translations/*
|
||||||
translations/*
|
translations/*
|
||||||
node_modules/*
|
node_modules/*
|
||||||
hass_frontend/*
|
hass_frontend/*
|
||||||
|
55
.yarn/releases/yarn-2.4.2.cjs
vendored
Executable file
55
.yarn/releases/yarn-2.4.2.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
631
.yarn/releases/yarn-3.0.2.cjs
vendored
631
.yarn/releases/yarn-3.0.2.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.0.2.cjs
|
yarnPath: .yarn/releases/yarn-2.4.2.cjs
|
||||||
|
@@ -35,7 +35,6 @@ module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
|
|||||||
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
|
||||||
__VERSION__: JSON.stringify(env.version()),
|
__VERSION__: JSON.stringify(env.version()),
|
||||||
__DEMO__: false,
|
__DEMO__: false,
|
||||||
__SUPERVISOR__: false,
|
|
||||||
__BACKWARDS_COMPAT__: false,
|
__BACKWARDS_COMPAT__: false,
|
||||||
__STATIC_PATH__: "/static/",
|
__STATIC_PATH__: "/static/",
|
||||||
"process.env.NODE_ENV": JSON.stringify(
|
"process.env.NODE_ENV": JSON.stringify(
|
||||||
@@ -83,7 +82,6 @@ module.exports.babelOptions = ({ latestBuild }) => ({
|
|||||||
// Only support the syntax, Webpack will handle it.
|
// Only support the syntax, Webpack will handle it.
|
||||||
"@babel/plugin-syntax-import-meta",
|
"@babel/plugin-syntax-import-meta",
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
"@babel/plugin-syntax-top-level-await",
|
|
||||||
"@babel/plugin-proposal-optional-chaining",
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
|
||||||
@@ -195,9 +193,6 @@ module.exports.config = {
|
|||||||
publicPath: publicPath(latestBuild, paths.hassio_publicPath),
|
publicPath: publicPath(latestBuild, paths.hassio_publicPath),
|
||||||
isProdBuild,
|
isProdBuild,
|
||||||
latestBuild,
|
latestBuild,
|
||||||
defineOverlay: {
|
|
||||||
__SUPERVISOR__: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ const env = require("../env");
|
|||||||
|
|
||||||
require("./clean.js");
|
require("./clean.js");
|
||||||
require("./translations.js");
|
require("./translations.js");
|
||||||
require("./locale-data.js");
|
|
||||||
require("./gen-icons-json.js");
|
require("./gen-icons-json.js");
|
||||||
require("./gather-static.js");
|
require("./gather-static.js");
|
||||||
require("./compress.js");
|
require("./compress.js");
|
||||||
@@ -27,8 +26,7 @@ gulp.task(
|
|||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"gen-pages-dev",
|
"gen-pages-dev",
|
||||||
"gen-index-app-dev",
|
"gen-index-app-dev",
|
||||||
"build-translations",
|
"build-translations"
|
||||||
"build-locale-data"
|
|
||||||
),
|
),
|
||||||
"copy-static-app",
|
"copy-static-app",
|
||||||
env.useWDS()
|
env.useWDS()
|
||||||
@@ -46,7 +44,7 @@ gulp.task(
|
|||||||
process.env.NODE_ENV = "production";
|
process.env.NODE_ENV = "production";
|
||||||
},
|
},
|
||||||
"clean",
|
"clean",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"copy-static-app",
|
"copy-static-app",
|
||||||
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
|
env.useRollup() ? "rollup-prod-app" : "webpack-prod-app",
|
||||||
// Don't compress running tests
|
// Don't compress running tests
|
||||||
|
@@ -18,7 +18,7 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-cast",
|
"clean-cast",
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
"gen-index-cast-dev",
|
"gen-index-cast-dev",
|
||||||
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
env.useRollup() ? "rollup-dev-server-cast" : "webpack-dev-server-cast"
|
||||||
@@ -33,7 +33,7 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-cast",
|
"clean-cast",
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"copy-static-cast",
|
"copy-static-cast",
|
||||||
env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast",
|
env.useRollup() ? "rollup-prod-cast" : "webpack-prod-cast",
|
||||||
"gen-index-cast-prod"
|
"gen-index-cast-prod"
|
||||||
|
@@ -20,12 +20,7 @@ gulp.task(
|
|||||||
},
|
},
|
||||||
"clean-demo",
|
"clean-demo",
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel(
|
gulp.parallel("gen-icons-json", "gen-index-demo-dev", "build-translations"),
|
||||||
"gen-icons-json",
|
|
||||||
"gen-index-demo-dev",
|
|
||||||
"build-translations",
|
|
||||||
"build-locale-data"
|
|
||||||
),
|
|
||||||
"copy-static-demo",
|
"copy-static-demo",
|
||||||
env.useRollup() ? "rollup-dev-server-demo" : "webpack-dev-server-demo"
|
env.useRollup() ? "rollup-dev-server-demo" : "webpack-dev-server-demo"
|
||||||
)
|
)
|
||||||
@@ -40,7 +35,7 @@ gulp.task(
|
|||||||
"clean-demo",
|
"clean-demo",
|
||||||
// Cast needs to be backwards compatible and older HA has no translations
|
// Cast needs to be backwards compatible and older HA has no translations
|
||||||
"translations-enable-merge-backend",
|
"translations-enable-merge-backend",
|
||||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
gulp.parallel("gen-icons-json", "build-translations"),
|
||||||
"copy-static-demo",
|
"copy-static-demo",
|
||||||
env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo",
|
env.useRollup() ? "rollup-prod-demo" : "webpack-prod-demo",
|
||||||
"gen-index-demo-prod"
|
"gen-index-demo-prod"
|
||||||
|
@@ -51,7 +51,6 @@ gulp.task(
|
|||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data",
|
|
||||||
"gather-gallery-demos"
|
"gather-gallery-demos"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
@@ -71,7 +70,6 @@ gulp.task(
|
|||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-translations",
|
"build-translations",
|
||||||
"build-locale-data",
|
|
||||||
"gather-gallery-demos"
|
"gather-gallery-demos"
|
||||||
),
|
),
|
||||||
"copy-static-gallery",
|
"copy-static-gallery",
|
||||||
|
@@ -22,18 +22,11 @@ function copyTranslations(staticDir) {
|
|||||||
|
|
||||||
// Translation output
|
// Translation output
|
||||||
fs.copySync(
|
fs.copySync(
|
||||||
polyPath("build/translations/output"),
|
polyPath("build-translations/output"),
|
||||||
staticPath("translations")
|
staticPath("translations")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyLocaleData(staticDir) {
|
|
||||||
const staticPath = genStaticPath(staticDir);
|
|
||||||
|
|
||||||
// Locale data output
|
|
||||||
fs.copySync(polyPath("build/locale-data"), staticPath("locale-data"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyMdiIcons(staticDir) {
|
function copyMdiIcons(staticDir) {
|
||||||
const staticPath = genStaticPath(staticDir);
|
const staticPath = genStaticPath(staticDir);
|
||||||
|
|
||||||
@@ -91,11 +84,6 @@ function copyMapPanel(staticDir) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task("copy-locale-data", async () => {
|
|
||||||
const staticDir = paths.app_output_static;
|
|
||||||
copyLocaleData(staticDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("copy-translations-app", async () => {
|
gulp.task("copy-translations-app", async () => {
|
||||||
const staticDir = paths.app_output_static;
|
const staticDir = paths.app_output_static;
|
||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
@@ -106,11 +94,6 @@ gulp.task("copy-translations-supervisor", async () => {
|
|||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task("copy-locale-data-supervisor", async () => {
|
|
||||||
const staticDir = paths.hassio_output_static;
|
|
||||||
copyLocaleData(staticDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task("copy-static-app", async () => {
|
gulp.task("copy-static-app", async () => {
|
||||||
const staticDir = paths.app_output_static;
|
const staticDir = paths.app_output_static;
|
||||||
// Basic static files
|
// Basic static files
|
||||||
@@ -120,7 +103,6 @@ gulp.task("copy-static-app", async () => {
|
|||||||
copyPolyfills(staticDir);
|
copyPolyfills(staticDir);
|
||||||
copyFonts(staticDir);
|
copyFonts(staticDir);
|
||||||
copyTranslations(staticDir);
|
copyTranslations(staticDir);
|
||||||
copyLocaleData(staticDir);
|
|
||||||
copyMdiIcons(staticDir);
|
copyMdiIcons(staticDir);
|
||||||
|
|
||||||
// Panel assets
|
// Panel assets
|
||||||
@@ -141,7 +123,6 @@ gulp.task("copy-static-demo", async () => {
|
|||||||
copyMapPanel(paths.demo_output_static);
|
copyMapPanel(paths.demo_output_static);
|
||||||
copyFonts(paths.demo_output_static);
|
copyFonts(paths.demo_output_static);
|
||||||
copyTranslations(paths.demo_output_static);
|
copyTranslations(paths.demo_output_static);
|
||||||
copyLocaleData(paths.demo_output_static);
|
|
||||||
copyMdiIcons(paths.demo_output_static);
|
copyMdiIcons(paths.demo_output_static);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,7 +137,6 @@ gulp.task("copy-static-cast", async () => {
|
|||||||
copyMapPanel(paths.cast_output_static);
|
copyMapPanel(paths.cast_output_static);
|
||||||
copyFonts(paths.cast_output_static);
|
copyFonts(paths.cast_output_static);
|
||||||
copyTranslations(paths.cast_output_static);
|
copyTranslations(paths.cast_output_static);
|
||||||
copyLocaleData(paths.cast_output_static);
|
|
||||||
copyMdiIcons(paths.cast_output_static);
|
copyMdiIcons(paths.cast_output_static);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -172,6 +152,5 @@ gulp.task("copy-static-gallery", async () => {
|
|||||||
copyMapPanel(paths.gallery_output_static);
|
copyMapPanel(paths.gallery_output_static);
|
||||||
copyFonts(paths.gallery_output_static);
|
copyFonts(paths.gallery_output_static);
|
||||||
copyTranslations(paths.gallery_output_static);
|
copyTranslations(paths.gallery_output_static);
|
||||||
copyLocaleData(paths.gallery_output_static);
|
|
||||||
copyMdiIcons(paths.gallery_output_static);
|
copyMdiIcons(paths.gallery_output_static);
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
|
const paths = require("../paths");
|
||||||
|
|
||||||
require("./clean.js");
|
require("./clean.js");
|
||||||
require("./gen-icons-json.js");
|
require("./gen-icons-json.js");
|
||||||
@@ -21,8 +24,6 @@ gulp.task(
|
|||||||
"gen-index-hassio-dev",
|
"gen-index-hassio-dev",
|
||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
|
||||||
"copy-locale-data-supervisor",
|
|
||||||
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
env.useRollup() ? "rollup-watch-hassio" : "webpack-watch-hassio"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -37,8 +38,6 @@ gulp.task(
|
|||||||
"gen-icons-json",
|
"gen-icons-json",
|
||||||
"build-supervisor-translations",
|
"build-supervisor-translations",
|
||||||
"copy-translations-supervisor",
|
"copy-translations-supervisor",
|
||||||
"build-locale-data",
|
|
||||||
"copy-locale-data-supervisor",
|
|
||||||
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
env.useRollup() ? "rollup-prod-hassio" : "webpack-prod-hassio",
|
||||||
"gen-index-hassio-prod",
|
"gen-index-hassio-prod",
|
||||||
...// Don't compress running tests
|
...// Don't compress running tests
|
||||||
|
@@ -1,74 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
|
|
||||||
const del = require("del");
|
|
||||||
const path = require("path");
|
|
||||||
const gulp = require("gulp");
|
|
||||||
const fs = require("fs");
|
|
||||||
const paths = require("../paths");
|
|
||||||
|
|
||||||
const outDir = "build/locale-data";
|
|
||||||
|
|
||||||
gulp.task("clean-locale-data", () => del([outDir]));
|
|
||||||
|
|
||||||
gulp.task("ensure-locale-data-build-dir", (done) => {
|
|
||||||
if (!fs.existsSync(outDir)) {
|
|
||||||
fs.mkdirSync(outDir, { recursive: true });
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
const modules = {
|
|
||||||
"intl-relativetimeformat": "RelativeTimeFormat",
|
|
||||||
"intl-datetimeformat": "DateTimeFormat",
|
|
||||||
"intl-numberformat": "NumberFormat",
|
|
||||||
};
|
|
||||||
|
|
||||||
gulp.task("create-locale-data", (done) => {
|
|
||||||
const translationMeta = JSON.parse(
|
|
||||||
fs.readFileSync(
|
|
||||||
path.join(paths.translations_src, "translationMetadata.json")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
Object.entries(modules).forEach(([module, className]) => {
|
|
||||||
Object.keys(translationMeta).forEach((lang) => {
|
|
||||||
try {
|
|
||||||
const localeData = String(
|
|
||||||
fs.readFileSync(
|
|
||||||
require.resolve(`@formatjs/${module}/locale-data/${lang}.js`)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
new RegExp(
|
|
||||||
`\\/\\*\\s*@generated\\s*\\*\\/\\s*\\/\\/\\s*prettier-ignore\\s*if\\s*\\(Intl\\.${className}\\s*&&\\s*typeof\\s*Intl\\.${className}\\.__addLocaleData\\s*===\\s*'function'\\)\\s*{\\s*Intl\\.${className}\\.__addLocaleData\\(`,
|
|
||||||
"im"
|
|
||||||
),
|
|
||||||
""
|
|
||||||
)
|
|
||||||
.replace(/\)\s*}/im, "");
|
|
||||||
// make sure we have valid JSON
|
|
||||||
JSON.parse(localeData);
|
|
||||||
if (!fs.existsSync(path.join(outDir, module))) {
|
|
||||||
fs.mkdirSync(path.join(outDir, module), { recursive: true });
|
|
||||||
}
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(outDir, `${module}/${lang}.json`),
|
|
||||||
localeData
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code !== "MODULE_NOT_FOUND") {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(
|
|
||||||
"build-locale-data",
|
|
||||||
gulp.series(
|
|
||||||
"clean-locale-data",
|
|
||||||
"ensure-locale-data-build-dir",
|
|
||||||
"create-locale-data"
|
|
||||||
)
|
|
||||||
);
|
|
@@ -17,7 +17,7 @@ const paths = require("../paths");
|
|||||||
|
|
||||||
const inFrontendDir = "translations/frontend";
|
const inFrontendDir = "translations/frontend";
|
||||||
const inBackendDir = "translations/backend";
|
const inBackendDir = "translations/backend";
|
||||||
const workDir = "build/translations";
|
const workDir = "build-translations";
|
||||||
const fullDir = workDir + "/full";
|
const fullDir = workDir + "/full";
|
||||||
const coreDir = workDir + "/core";
|
const coreDir = workDir + "/core";
|
||||||
const outDir = workDir + "/output";
|
const outDir = workDir + "/output";
|
||||||
@@ -121,7 +121,7 @@ gulp.task("clean-translations", () => del([workDir]));
|
|||||||
|
|
||||||
gulp.task("ensure-translations-build-dir", (done) => {
|
gulp.task("ensure-translations-build-dir", (done) => {
|
||||||
if (!fs.existsSync(workDir)) {
|
if (!fs.existsSync(workDir)) {
|
||||||
fs.mkdirSync(workDir, { recursive: true });
|
fs.mkdirSync(workDir);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -336,14 +336,6 @@ gulp.task("build-translation-fragment-supervisor", () =>
|
|||||||
gulp
|
gulp
|
||||||
.src(fullDir + "/*.json")
|
.src(fullDir + "/*.json")
|
||||||
.pipe(transform((data) => data.supervisor))
|
.pipe(transform((data) => data.supervisor))
|
||||||
.pipe(
|
|
||||||
rename((filePath) => {
|
|
||||||
// In dev we create the file with the fake hash in the filename
|
|
||||||
if (!env.isProdBuild()) {
|
|
||||||
filePath.basename += "-dev";
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.pipe(gulp.dest(workDir + "/supervisor"))
|
.pipe(gulp.dest(workDir + "/supervisor"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -35,29 +35,26 @@ const isWsl =
|
|||||||
* listenHost?: string
|
* listenHost?: string
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
const runDevServer = async ({
|
const runDevServer = ({
|
||||||
compiler,
|
compiler,
|
||||||
contentBase,
|
contentBase,
|
||||||
port,
|
port,
|
||||||
listenHost = "localhost",
|
listenHost = "localhost",
|
||||||
}) => {
|
}) =>
|
||||||
const server = new WebpackDevServer(
|
new WebpackDevServer(compiler, {
|
||||||
{
|
open: true,
|
||||||
open: true,
|
watchContentBase: true,
|
||||||
host: listenHost,
|
contentBase,
|
||||||
port,
|
}).listen(port, listenHost, (err) => {
|
||||||
static: {
|
if (err) {
|
||||||
directory: contentBase,
|
throw err;
|
||||||
watch: true,
|
}
|
||||||
},
|
// Server listening
|
||||||
},
|
log(
|
||||||
compiler
|
"[webpack-dev-server]",
|
||||||
);
|
`Project is running at http://localhost:${port}`
|
||||||
|
);
|
||||||
await server.start();
|
});
|
||||||
// Server listening
|
|
||||||
log("[webpack-dev-server]", `Project is running at http://localhost:${port}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const doneHandler = (done) => (err, stats) => {
|
const doneHandler = (done) => (err, stats) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -110,13 +107,13 @@ gulp.task("webpack-prod-app", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-demo", () =>
|
gulp.task("webpack-dev-server-demo", () => {
|
||||||
runDevServer({
|
runDevServer({
|
||||||
compiler: webpack(bothBuilds(createDemoConfig, { isProdBuild: false })),
|
compiler: webpack(bothBuilds(createDemoConfig, { isProdBuild: false })),
|
||||||
contentBase: paths.demo_output_root,
|
contentBase: paths.demo_output_root,
|
||||||
port: 8090,
|
port: 8090,
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-demo", () =>
|
gulp.task("webpack-prod-demo", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
@@ -126,15 +123,15 @@ gulp.task("webpack-prod-demo", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-cast", () =>
|
gulp.task("webpack-dev-server-cast", () => {
|
||||||
runDevServer({
|
runDevServer({
|
||||||
compiler: webpack(bothBuilds(createCastConfig, { isProdBuild: false })),
|
compiler: webpack(bothBuilds(createCastConfig, { isProdBuild: false })),
|
||||||
contentBase: paths.cast_output_root,
|
contentBase: paths.cast_output_root,
|
||||||
port: 8080,
|
port: 8080,
|
||||||
// Accessible from the network, because that's how Cast hits it.
|
// Accessible from the network, because that's how Cast hits it.
|
||||||
listenHost: "0.0.0.0",
|
listenHost: "0.0.0.0",
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-cast", () =>
|
gulp.task("webpack-prod-cast", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
@@ -151,7 +148,7 @@ gulp.task("webpack-watch-hassio", () => {
|
|||||||
isProdBuild: false,
|
isProdBuild: false,
|
||||||
latestBuild: true,
|
latestBuild: true,
|
||||||
})
|
})
|
||||||
).watch({ ignored: /build/, poll: isWsl }, doneHandler());
|
).watch({ ignored: /build-translations/, poll: isWsl }, doneHandler());
|
||||||
|
|
||||||
gulp.watch(
|
gulp.watch(
|
||||||
path.join(paths.translations_src, "en.json"),
|
path.join(paths.translations_src, "en.json"),
|
||||||
@@ -167,14 +164,14 @@ gulp.task("webpack-prod-hassio", () =>
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
gulp.task("webpack-dev-server-gallery", () =>
|
gulp.task("webpack-dev-server-gallery", () => {
|
||||||
runDevServer({
|
runDevServer({
|
||||||
// We don't use the es5 build, but the dev server will fuck up the publicPath if we don't
|
// We don't use the es5 build, but the dev server will fuck up the publicPath if we don't
|
||||||
compiler: webpack(bothBuilds(createGalleryConfig, { isProdBuild: false })),
|
compiler: webpack(bothBuilds(createGalleryConfig, { isProdBuild: false })),
|
||||||
contentBase: paths.gallery_output_root,
|
contentBase: paths.gallery_output_root,
|
||||||
port: 8100,
|
port: 8100,
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
|
|
||||||
gulp.task("webpack-prod-gallery", () =>
|
gulp.task("webpack-prod-gallery", () =>
|
||||||
prodBuild(
|
prodBuild(
|
||||||
|
@@ -6,7 +6,6 @@ const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
|||||||
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 log = require("fancy-log");
|
||||||
const WebpackBar = require("webpackbar");
|
|
||||||
|
|
||||||
class LogStartCompilePlugin {
|
class LogStartCompilePlugin {
|
||||||
ignoredFirst = false;
|
ignoredFirst = false;
|
||||||
@@ -75,7 +74,6 @@ const createWebpackConfig = ({
|
|||||||
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
chunkIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new WebpackBar({ fancy: !isProdBuild }),
|
|
||||||
new WebpackManifestPlugin({
|
new WebpackManifestPlugin({
|
||||||
// Only include the JS of entrypoints
|
// Only include the JS of entrypoints
|
||||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||||
@@ -127,13 +125,6 @@ const createWebpackConfig = ({
|
|||||||
alias: {
|
alias: {
|
||||||
"lit/decorators$": "lit/decorators.js",
|
"lit/decorators$": "lit/decorators.js",
|
||||||
"lit/directive$": "lit/directive.js",
|
"lit/directive$": "lit/directive.js",
|
||||||
"lit/directives/until$": "lit/directives/until.js",
|
|
||||||
"lit/directives/class-map$": "lit/directives/class-map.js",
|
|
||||||
"lit/directives/style-map$": "lit/directives/style-map.js",
|
|
||||||
"lit/directives/if-defined$": "lit/directives/if-defined.js",
|
|
||||||
"lit/directives/guard$": "lit/directives/guard.js",
|
|
||||||
"lit/directives/cache$": "lit/directives/cache.js",
|
|
||||||
"lit/directives/repeat$": "lit/directives/repeat.js",
|
|
||||||
"lit/polyfill-support$": "lit/polyfill-support.js",
|
"lit/polyfill-support$": "lit/polyfill-support.js",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -151,9 +142,6 @@ const createWebpackConfig = ({
|
|||||||
// To silence warning in worker plugin
|
// To silence warning in worker plugin
|
||||||
globalObject: "self",
|
globalObject: "self",
|
||||||
},
|
},
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -191,7 +191,7 @@ class HcCast extends LitElement {
|
|||||||
}
|
}
|
||||||
this.connection.close();
|
this.connection.close();
|
||||||
location.reload();
|
location.reload();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
alert("Unable to log out!");
|
alert("Unable to log out!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -212,7 +212,7 @@ export class HcConnect extends LitElement {
|
|||||||
let url: URL;
|
let url: URL;
|
||||||
try {
|
try {
|
||||||
url = new URL(value);
|
url = new URL(value);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this.error = "Invalid URL";
|
this.error = "Invalid URL";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ export class HcConnect extends LitElement {
|
|||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
auth = await getAuth(options);
|
auth = await getAuth(options);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
if (init === "saved-tokens" && err === ERR_CANNOT_CONNECT) {
|
if (init === "saved-tokens" && err === ERR_CANNOT_CONNECT) {
|
||||||
this.cannotConnect = true;
|
this.cannotConnect = true;
|
||||||
return;
|
return;
|
||||||
@@ -259,7 +259,7 @@ export class HcConnect extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
conn = await createConnection({ auth });
|
conn = await createConnection({ auth });
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// In case of saved tokens, silently solve problems.
|
// In case of saved tokens, silently solve problems.
|
||||||
if (init === "saved-tokens") {
|
if (init === "saved-tokens") {
|
||||||
if (err === ERR_CANNOT_CONNECT) {
|
if (err === ERR_CANNOT_CONNECT) {
|
||||||
@@ -285,7 +285,7 @@ export class HcConnect extends LitElement {
|
|||||||
try {
|
try {
|
||||||
saveTokens(null);
|
saveTokens(null);
|
||||||
location.reload();
|
location.reload();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
alert("Unable to log out!");
|
alert("Unable to log out!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -148,14 +148,14 @@ export class HcMain extends HassElement {
|
|||||||
expires_in: 0,
|
expires_in: 0,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this._getErrorMessage(err);
|
this._error = this._getErrorMessage(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let connection;
|
let connection;
|
||||||
try {
|
try {
|
||||||
connection = await createConnection({ auth });
|
connection = await createConnection({ auth });
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this._getErrorMessage(err);
|
this._error = this._getErrorMessage(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ export class HcMain extends HassElement {
|
|||||||
this._unsubLovelace = llColl.subscribe((lovelaceConfig) =>
|
this._unsubLovelace = llColl.subscribe((lovelaceConfig) =>
|
||||||
this._handleNewLovelaceConfig(lovelaceConfig)
|
this._handleNewLovelaceConfig(lovelaceConfig)
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log("Error fetching Lovelace configuration", err, msg);
|
console.log("Error fetching Lovelace configuration", err, msg);
|
||||||
// Generate a Lovelace config.
|
// Generate a Lovelace config.
|
||||||
|
@@ -44,7 +44,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
(conf) => html`
|
(conf) => html`
|
||||||
${conf.name}
|
${conf.name}
|
||||||
<small>
|
<small>
|
||||||
<a target="_blank" href=${conf.authorUrl}>
|
<a target="_blank" href="${conf.authorUrl}">
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.page-demo.cards.demo.demo_by",
|
"ui.panel.page-demo.cards.demo.demo_by",
|
||||||
"name",
|
"name",
|
||||||
@@ -94,7 +94,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
|
|||||||
this._switching = true;
|
this._switching = true;
|
||||||
try {
|
try {
|
||||||
await setDemoConfig(this.hass, this.lovelace!, index);
|
await setDemoConfig(this.hass, this.lovelace!, index);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
alert("Failed to switch config :-(");
|
alert("Failed to switch config :-(");
|
||||||
} finally {
|
} finally {
|
||||||
this._switching = false;
|
this._switching = false;
|
||||||
|
@@ -23,9 +23,9 @@ customElements.whenDefined("hui-view").then(() => {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const HUIView = customElements.get("hui-view");
|
const HUIView = customElements.get("hui-view");
|
||||||
// Patch HUI-VIEW to make the lovelace object available to the demo card
|
// Patch HUI-VIEW to make the lovelace object available to the demo card
|
||||||
const oldCreateCard = HUIView!.prototype.createCardElement;
|
const oldCreateCard = HUIView.prototype.createCardElement;
|
||||||
|
|
||||||
HUIView!.prototype.createCardElement = function (config) {
|
HUIView.prototype.createCardElement = function (config) {
|
||||||
const el = oldCreateCard.call(this, config);
|
const el = oldCreateCard.call(this, config);
|
||||||
if (el.tagName === "HA-DEMO-CARD") {
|
if (el.tagName === "HA-DEMO-CARD") {
|
||||||
(el as HADemoCard).lovelace = this.lovelace;
|
(el as HADemoCard).lovelace = this.lovelace;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* 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";
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* 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";
|
||||||
|
@@ -107,21 +107,19 @@ export class DemoHaAlert extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-card header="ha-alert demo">
|
<ha-card header="ha-alert demo">
|
||||||
<div class="card-content">
|
${alerts.map(
|
||||||
${alerts.map(
|
(alert) => html`
|
||||||
(alert) => html`
|
<ha-alert
|
||||||
<ha-alert
|
.title=${alert.title || ""}
|
||||||
.title=${alert.title || ""}
|
.alertType=${alert.type}
|
||||||
.alertType=${alert.type}
|
.dismissable=${alert.dismissable || false}
|
||||||
.dismissable=${alert.dismissable || false}
|
.actionText=${alert.action || ""}
|
||||||
.actionText=${alert.action || ""}
|
.rtl=${alert.rtl || false}
|
||||||
.rtl=${alert.rtl || false}
|
>
|
||||||
>
|
${alert.description}
|
||||||
${alert.description}
|
</ha-alert>
|
||||||
</ha-alert>
|
`
|
||||||
`
|
)}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -132,10 +130,6 @@ export class DemoHaAlert extends LitElement {
|
|||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: 24px auto;
|
margin: 24px auto;
|
||||||
}
|
}
|
||||||
ha-alert {
|
|
||||||
display: block;
|
|
||||||
margin: 24px 0;
|
|
||||||
}
|
|
||||||
.condition {
|
.condition {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -1,212 +0,0 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
|
||||||
import { LitElement, TemplateResult, css, html } from "lit";
|
|
||||||
import { customElement } from "lit/decorators";
|
|
||||||
import "../../../src/components/ha-form/ha-form";
|
|
||||||
import "../../../src/components/ha-card";
|
|
||||||
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
|
|
||||||
import type { HaFormSchema } from "../../../src/components/ha-form/ha-form";
|
|
||||||
|
|
||||||
const SCHEMAS: {
|
|
||||||
title: string;
|
|
||||||
translations?: Record<string, string>;
|
|
||||||
error?: Record<string, string>;
|
|
||||||
schema: HaFormSchema[];
|
|
||||||
}[] = [
|
|
||||||
{
|
|
||||||
title: "Authentication",
|
|
||||||
translations: {
|
|
||||||
username: "Username",
|
|
||||||
password: "Password",
|
|
||||||
invalid_login: "Invalid login",
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
base: "invalid_login",
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
type: "string",
|
|
||||||
name: "username",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "string",
|
|
||||||
name: "password",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: "One of each",
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
type: "constant",
|
|
||||||
value: "Constant Value",
|
|
||||||
name: "constant",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "boolean",
|
|
||||||
name: "bool",
|
|
||||||
optional: true,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "integer",
|
|
||||||
name: "int",
|
|
||||||
optional: true,
|
|
||||||
default: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "string",
|
|
||||||
name: "string",
|
|
||||||
optional: true,
|
|
||||||
default: "Default",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "select",
|
|
||||||
options: [
|
|
||||||
["default", "default"],
|
|
||||||
["other", "other"],
|
|
||||||
],
|
|
||||||
name: "select",
|
|
||||||
optional: true,
|
|
||||||
default: "default",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "multi_select",
|
|
||||||
options: {
|
|
||||||
default: "Default",
|
|
||||||
other: "Other",
|
|
||||||
},
|
|
||||||
name: "multi",
|
|
||||||
optional: true,
|
|
||||||
default: ["default"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Multi select",
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
type: "multi_select",
|
|
||||||
options: {
|
|
||||||
default: "Default",
|
|
||||||
other: "Other",
|
|
||||||
},
|
|
||||||
name: "multi",
|
|
||||||
optional: true,
|
|
||||||
default: ["default"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "multi_select",
|
|
||||||
options: {
|
|
||||||
default: "Default",
|
|
||||||
other: "Other",
|
|
||||||
uno: "mas",
|
|
||||||
one: "more",
|
|
||||||
and: "another_one",
|
|
||||||
option: "1000",
|
|
||||||
},
|
|
||||||
name: "multi",
|
|
||||||
optional: true,
|
|
||||||
default: ["default"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@customElement("demo-ha-form")
|
|
||||||
class DemoHaForm extends LitElement {
|
|
||||||
private lightModeData: any = [];
|
|
||||||
|
|
||||||
private darkModeData: any = [];
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
return html`
|
|
||||||
${SCHEMAS.map((info, idx) => {
|
|
||||||
const translations = info.translations || {};
|
|
||||||
const computeLabel = (schema) =>
|
|
||||||
translations[schema.name] || schema.name;
|
|
||||||
const computeError = (error) => translations[error] || error;
|
|
||||||
|
|
||||||
return [
|
|
||||||
[this.lightModeData, "light"],
|
|
||||||
[this.darkModeData, "dark"],
|
|
||||||
].map(
|
|
||||||
([data, type]) => html`
|
|
||||||
<div class="row" data-type=${type}>
|
|
||||||
<ha-card .header=${info.title}>
|
|
||||||
<div class="card-content">
|
|
||||||
<ha-form
|
|
||||||
.data=${data[idx]}
|
|
||||||
.schema=${info.schema}
|
|
||||||
.error=${info.error}
|
|
||||||
.computeError=${computeError}
|
|
||||||
.computeLabel=${computeLabel}
|
|
||||||
@value-changed=${(e) => {
|
|
||||||
data[idx] = e.detail.value;
|
|
||||||
this.requestUpdate();
|
|
||||||
}}
|
|
||||||
></ha-form>
|
|
||||||
</div>
|
|
||||||
</ha-card>
|
|
||||||
<pre>${JSON.stringify(data[idx], undefined, 2)}</pre>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
firstUpdated(changedProps) {
|
|
||||||
super.firstUpdated(changedProps);
|
|
||||||
this.shadowRoot!.querySelectorAll("[data-type=dark]").forEach((el) => {
|
|
||||||
applyThemesOnElement(
|
|
||||||
el,
|
|
||||||
{
|
|
||||||
default_theme: "default",
|
|
||||||
default_dark_theme: "default",
|
|
||||||
themes: {},
|
|
||||||
darkMode: false,
|
|
||||||
},
|
|
||||||
"default",
|
|
||||||
{ dark: true }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
.row {
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 800px;
|
|
||||||
display: flex;
|
|
||||||
padding: 50px;
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
}
|
|
||||||
ha-card {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 384px;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
width: 400px;
|
|
||||||
margin: 0 16px;
|
|
||||||
overflow: auto;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
.row {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"demo-ha-form": DemoHaForm;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,5 +1,5 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { css, html, LitElement, TemplateResult } from "lit";
|
import { 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";
|
||||||
@@ -9,6 +9,7 @@ import { actionHandler } from "../../../src/panels/lovelace/common/directives/ac
|
|||||||
export class DemoUtilLongPress extends LitElement {
|
export class DemoUtilLongPress extends LitElement {
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
|
${this.renderStyle()}
|
||||||
${[1, 2, 3].map(
|
${[1, 2, 3].map(
|
||||||
() => html`
|
() => html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
@@ -40,22 +41,26 @@ export class DemoUtilLongPress extends LitElement {
|
|||||||
area.scrollTop = area.scrollHeight;
|
area.scrollTop = area.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
private renderStyle() {
|
||||||
ha-card {
|
return html`
|
||||||
width: 200px;
|
<style>
|
||||||
margin: calc(42vh - 140px) auto;
|
ha-card {
|
||||||
padding: 8px;
|
width: 200px;
|
||||||
text-align: center;
|
margin: calc(42vh - 140px) auto;
|
||||||
}
|
padding: 8px;
|
||||||
ha-card:first-of-type {
|
text-align: center;
|
||||||
margin-top: 16px;
|
}
|
||||||
}
|
ha-card:first-of-type {
|
||||||
ha-card:last-of-type {
|
margin-top: 16px;
|
||||||
margin-bottom: 16px;
|
}
|
||||||
}
|
ha-card:last-of-type {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
`;
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import { property } from "lit/decorators";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import {
|
import {
|
||||||
HassioAddonInfo,
|
HassioAddonInfo,
|
||||||
@@ -33,7 +32,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
|||||||
return filterAndSort(addons, filter);
|
return filterAndSort(addons, filter);
|
||||||
}
|
}
|
||||||
return addons.sort((a, b) =>
|
return addons.sort((a, b) =>
|
||||||
caseInsensitiveStringCompare(a.name, b.name)
|
a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -259,7 +259,7 @@ class HassioAddonConfig extends LitElement {
|
|||||||
path: "options",
|
path: "options",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.common.update_available",
|
"addon.common.update_available",
|
||||||
"error",
|
"error",
|
||||||
@@ -300,7 +300,7 @@ class HassioAddonConfig extends LitElement {
|
|||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
|
@@ -89,9 +89,9 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
<td>
|
<td>
|
||||||
<paper-input
|
<paper-input
|
||||||
@value-changed=${this._configChanged}
|
@value-changed=${this._configChanged}
|
||||||
placeholder=${this.supervisor.localize(
|
placeholder="${this.supervisor.localize(
|
||||||
"addon.configuration.network.disabled"
|
"addon.configuration.network.disabled"
|
||||||
)}
|
)}"
|
||||||
.value=${item.host ? String(item.host) : ""}
|
.value=${item.host ? String(item.host) : ""}
|
||||||
.container=${item.container}
|
.container=${item.container}
|
||||||
no-label-float
|
no-label-float
|
||||||
@@ -171,7 +171,7 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_reset",
|
"addon.failed_to_reset",
|
||||||
"error",
|
"error",
|
||||||
@@ -207,7 +207,7 @@ class HassioAddonNetwork extends LitElement {
|
|||||||
if (this.addon?.state === "started") {
|
if (this.addon?.state === "started") {
|
||||||
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
|
@@ -79,7 +79,7 @@ class HassioAddonDocumentationDashboard extends LitElement {
|
|||||||
this.hass,
|
this.hass,
|
||||||
this.addon!.slug
|
this.addon!.slug
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.documentation.get_logs",
|
"addon.documentation.get_logs",
|
||||||
"error",
|
"error",
|
||||||
|
@@ -222,7 +222,7 @@ class HassioAddonDashboard extends LitElement {
|
|||||||
try {
|
try {
|
||||||
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
|
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
|
||||||
this.addon = addoninfo;
|
this.addon = addoninfo;
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
|
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
|
||||||
this.addon = undefined;
|
this.addon = undefined;
|
||||||
}
|
}
|
||||||
|
@@ -123,18 +123,18 @@ class HassioAddonInfo extends LitElement {
|
|||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<hassio-card-content
|
<hassio-card-content
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.title=${this.supervisor.localize(
|
.title="${this.supervisor.localize(
|
||||||
"addon.dashboard.new_update_available",
|
"addon.dashboard.new_update_available",
|
||||||
"name",
|
"name",
|
||||||
this.addon.name,
|
this.addon.name,
|
||||||
"version",
|
"version",
|
||||||
this.addon.version_latest
|
this.addon.version_latest
|
||||||
)}
|
)}"
|
||||||
.description=${this.supervisor.localize(
|
.description="${this.supervisor.localize(
|
||||||
"common.running_version",
|
"common.running_version",
|
||||||
"version",
|
"version",
|
||||||
this.addon.version
|
this.addon.version
|
||||||
)}
|
)}"
|
||||||
icon=${mdiArrowUpBoldCircle}
|
icon=${mdiArrowUpBoldCircle}
|
||||||
iconClass="update"
|
iconClass="update"
|
||||||
></hassio-card-content>
|
></hassio-card-content>
|
||||||
@@ -254,7 +254,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
${this.supervisor.localize(
|
${this.supervisor.localize(
|
||||||
"addon.dashboard.visit_addon_page",
|
"addon.dashboard.visit_addon_page",
|
||||||
"name",
|
"name",
|
||||||
html`<a href=${this.addon.url!} target="_blank" rel="noreferrer"
|
html`<a href="${this.addon.url!}" target="_blank" rel="noreferrer"
|
||||||
>${this.addon.name}</a
|
>${this.addon.name}</a
|
||||||
>`
|
>`
|
||||||
)}
|
)}
|
||||||
@@ -297,11 +297,10 @@ class HassioAddonInfo extends LitElement {
|
|||||||
})}
|
})}
|
||||||
@click=${this._showMoreInfo}
|
@click=${this._showMoreInfo}
|
||||||
id="rating"
|
id="rating"
|
||||||
|
.value=${this.addon.rating}
|
||||||
label="rating"
|
label="rating"
|
||||||
description=""
|
description=""
|
||||||
>
|
></ha-label-badge>
|
||||||
${this.addon.rating}
|
|
||||||
</ha-label-badge>
|
|
||||||
${this.addon.host_network
|
${this.addon.host_network
|
||||||
? html`
|
? html`
|
||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
@@ -438,10 +437,10 @@ class HassioAddonInfo extends LitElement {
|
|||||||
${this.addon.version
|
${this.addon.version
|
||||||
? html`
|
? html`
|
||||||
<div
|
<div
|
||||||
class=${classMap({
|
class="${classMap({
|
||||||
"addon-options": true,
|
"addon-options": true,
|
||||||
started: this.addon.state === "started",
|
started: this.addon.state === "started",
|
||||||
})}
|
})}"
|
||||||
>
|
>
|
||||||
<ha-settings-row ?three-line=${this.narrow}>
|
<ha-settings-row ?three-line=${this.narrow}>
|
||||||
<span slot="heading">
|
<span slot="heading">
|
||||||
@@ -797,7 +796,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "option",
|
path: "option",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
@@ -819,7 +818,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "option",
|
path: "option",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
@@ -841,7 +840,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "option",
|
path: "option",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
@@ -863,7 +862,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "security",
|
path: "security",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
@@ -885,7 +884,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "option",
|
path: "option",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.failed_to_save",
|
"addon.failed_to_save",
|
||||||
"error",
|
"error",
|
||||||
@@ -913,7 +912,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
title: this.supervisor.localize("addon.dashboard.changelog"),
|
title: this.supervisor.localize("addon.dashboard.changelog"),
|
||||||
content,
|
content,
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"addon.dashboard.action_error.get_changelog"
|
"addon.dashboard.action_error.get_changelog"
|
||||||
@@ -935,7 +934,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "install",
|
path: "install",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.install"),
|
title: this.supervisor.localize("addon.dashboard.action_error.install"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -956,7 +955,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "stop",
|
path: "stop",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.stop"),
|
title: this.supervisor.localize("addon.dashboard.action_error.stop"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -977,7 +976,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "stop",
|
path: "stop",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.restart"),
|
title: this.supervisor.localize("addon.dashboard.action_error.restart"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -1036,7 +1035,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
button.progress = false;
|
button.progress = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: "Failed to validate addon configuration",
|
title: "Failed to validate addon configuration",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -1054,7 +1053,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "start",
|
path: "start",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("addon.dashboard.action_error.start"),
|
title: this.supervisor.localize("addon.dashboard.action_error.start"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -1092,7 +1091,7 @@ class HassioAddonInfo extends LitElement {
|
|||||||
path: "uninstall",
|
path: "uninstall",
|
||||||
};
|
};
|
||||||
fireEvent(this, "hass-api-called", eventdata);
|
fireEvent(this, "hass-api-called", eventdata);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"addon.dashboard.action_error.uninstall"
|
"addon.dashboard.action_error.uninstall"
|
||||||
|
@@ -71,7 +71,7 @@ class HassioAddonLogs extends LitElement {
|
|||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
try {
|
try {
|
||||||
this._content = await fetchHassioAddonLogs(this.hass, this.addon.slug);
|
this._content = await fetchHassioAddonLogs(this.hass, this.addon.slug);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"addon.logs.get_logs",
|
"addon.logs.get_logs",
|
||||||
"error",
|
"error",
|
||||||
|
@@ -14,7 +14,7 @@ import { customElement, property, query, state } from "lit/decorators";
|
|||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { relativeTime } from "../../../src/common/datetime/relative_time";
|
import relativeTime from "../../../src/common/datetime/relative_time";
|
||||||
import { HASSDomEvent } from "../../../src/common/dom/fire_event";
|
import { HASSDomEvent } from "../../../src/common/dom/fire_event";
|
||||||
import {
|
import {
|
||||||
DataTableColumnContainer,
|
DataTableColumnContainer,
|
||||||
@@ -133,7 +133,7 @@ export class HassioBackups extends LitElement {
|
|||||||
filterable: true,
|
filterable: true,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
template: (entry: string) =>
|
template: (entry: string) =>
|
||||||
relativeTime(new Date(entry), this.hass.locale),
|
relativeTime(new Date(entry), this.hass.localize),
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
title: "",
|
title: "",
|
||||||
@@ -294,7 +294,7 @@ export class HassioBackups extends LitElement {
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
this._selectedBackups.map((slug) => removeBackup(this.hass, slug))
|
this._selectedBackups.map((slug) => removeBackup(this.hass, slug))
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("backup.failed_to_delete"),
|
title: this.supervisor.localize("backup.failed_to_delete"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { mdiHelpCircle } from "@mdi/js";
|
import { mdiHelpCircle } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import "../../../src/components/ha-relative-time";
|
||||||
import "../../../src/components/ha-svg-icon";
|
import "../../../src/components/ha-svg-icon";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@ class HassioCardContent extends LitElement {
|
|||||||
|
|
||||||
@property() public topbarClass?: string;
|
@property() public topbarClass?: string;
|
||||||
|
|
||||||
|
@property() public datetime?: string;
|
||||||
|
|
||||||
@property() public iconTitle?: string;
|
@property() public iconTitle?: string;
|
||||||
|
|
||||||
@property() public iconClass?: string;
|
@property() public iconClass?: string;
|
||||||
@@ -34,7 +37,7 @@ class HassioCardContent extends LitElement {
|
|||||||
${this.iconImage
|
${this.iconImage
|
||||||
? html`
|
? html`
|
||||||
<div class="icon_image ${this.iconClass}">
|
<div class="icon_image ${this.iconClass}">
|
||||||
<img src=${this.iconImage} .title=${this.iconTitle} />
|
<img src="${this.iconImage}" .title=${this.iconTitle} />
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
@@ -53,6 +56,15 @@ class HassioCardContent extends LitElement {
|
|||||||
/* treat as available when undefined */
|
/* treat as available when undefined */
|
||||||
this.available === false ? " (Not available)" : ""
|
this.available === false ? " (Not available)" : ""
|
||||||
}
|
}
|
||||||
|
${this.datetime
|
||||||
|
? html`
|
||||||
|
<ha-relative-time
|
||||||
|
.hass=${this.hass}
|
||||||
|
class="addition"
|
||||||
|
.datetime=${this.datetime}
|
||||||
|
></ha-relative-time>
|
||||||
|
`
|
||||||
|
: undefined}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -94,6 +106,9 @@ class HassioCardContent extends LitElement {
|
|||||||
height: 2.4em;
|
height: 2.4em;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
}
|
}
|
||||||
|
ha-relative-time {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.icon_image img {
|
.icon_image img {
|
||||||
max-height: 40px;
|
max-height: 40px;
|
||||||
max-width: 40px;
|
max-width: 40px;
|
||||||
|
@@ -70,7 +70,7 @@ export class HassioUploadBackup extends LitElement {
|
|||||||
try {
|
try {
|
||||||
const backup = await uploadBackup(this.hass, file);
|
const backup = await uploadBackup(this.hass, file);
|
||||||
fireEvent(this, "backup-uploaded", { backup: backup.data });
|
fireEvent(this, "backup-uploaded", { backup: backup.data });
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: "Upload failed",
|
title: "Upload failed",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
|
@@ -181,7 +181,9 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
>
|
>
|
||||||
<ha-checkbox
|
<ha-checkbox
|
||||||
.checked=${this.homeAssistant}
|
.checked=${this.homeAssistant}
|
||||||
@click=${this.toggleHomeAssistant}
|
@click=${() => {
|
||||||
|
this.homeAssistant = !this.homeAssistant;
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
</ha-checkbox>
|
</ha-checkbox>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
@@ -270,10 +272,6 @@ export class SupervisorBackupContent extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleHomeAssistant() {
|
|
||||||
this.homeAssistant = !this.homeAssistant;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
.partial-picker ha-formfield {
|
.partial-picker ha-formfield {
|
||||||
|
@@ -20,10 +20,10 @@ class SupervisorMetric extends LitElement {
|
|||||||
<div slot="description" .title=${this.tooltip ?? ""}>
|
<div slot="description" .title=${this.tooltip ?? ""}>
|
||||||
<span class="value"> ${roundedValue} % </span>
|
<span class="value"> ${roundedValue} % </span>
|
||||||
<ha-bar
|
<ha-bar
|
||||||
class=${classMap({
|
class="${classMap({
|
||||||
"target-warning": roundedValue > 50,
|
"target-warning": roundedValue > 50,
|
||||||
"target-critical": roundedValue > 85,
|
"target-critical": roundedValue > 85,
|
||||||
})}
|
})}"
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
></ha-bar>
|
></ha-bar>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -3,7 +3,7 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { atLeastVersion } from "../../../src/common/config/version";
|
import { atLeastVersion } from "../../../src/common/config/version";
|
||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
import { stringCompare } from "../../../src/common/string/compare";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import { haStyle } from "../../../src/resources/styles";
|
import { haStyle } from "../../../src/resources/styles";
|
||||||
@@ -33,7 +33,7 @@ class HassioAddons extends LitElement {
|
|||||||
</ha-card>
|
</ha-card>
|
||||||
`
|
`
|
||||||
: this.supervisor.supervisor.addons
|
: this.supervisor.supervisor.addons
|
||||||
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
.sort((a, b) => stringCompare(a.name, b.name))
|
||||||
.map(
|
.map(
|
||||||
(addon) => html`
|
(addon) => html`
|
||||||
<ha-card .addon=${addon} @click=${this._addonTapped}>
|
<ha-card .addon=${addon} @click=${this._addonTapped}>
|
||||||
|
@@ -136,7 +136,7 @@ export class HassioUpdate extends LitElement {
|
|||||||
</ha-settings-row>
|
</ha-settings-row>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions">
|
<div class="card-actions">
|
||||||
<a href=${releaseNotesUrl} target="_blank" rel="noreferrer">
|
<a href="${releaseNotesUrl}" target="_blank" rel="noreferrer">
|
||||||
<mwc-button>
|
<mwc-button>
|
||||||
${this.supervisor.localize("common.release_notes")}
|
${this.supervisor.localize("common.release_notes")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
@@ -206,7 +206,7 @@ export class HassioUpdate extends LitElement {
|
|||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: item.key,
|
collection: item.key,
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// Only show an error if the status code was not expected (user behind proxy)
|
// Only show an error if the status code was not expected (user behind proxy)
|
||||||
// or no status at all(connection terminated)
|
// or no status at all(connection terminated)
|
||||||
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
||||||
|
@@ -28,7 +28,6 @@ import "../../components/supervisor-backup-content";
|
|||||||
import type { SupervisorBackupContent } from "../../components/supervisor-backup-content";
|
import type { SupervisorBackupContent } from "../../components/supervisor-backup-content";
|
||||||
import { HassioBackupDialogParams } from "./show-dialog-hassio-backup";
|
import { HassioBackupDialogParams } from "./show-dialog-hassio-backup";
|
||||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||||
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
|
||||||
|
|
||||||
@customElement("dialog-hassio-backup")
|
@customElement("dialog-hassio-backup")
|
||||||
class HassioBackupDialog
|
class HassioBackupDialog
|
||||||
@@ -108,7 +107,7 @@ class HassioBackupDialog
|
|||||||
fixed
|
fixed
|
||||||
slot="primaryAction"
|
slot="primaryAction"
|
||||||
@action=${this._handleMenuAction}
|
@action=${this._handleMenuAction}
|
||||||
@closed=${stopPropagation}
|
@closed=${(ev: Event) => ev.stopPropagation()}
|
||||||
>
|
>
|
||||||
<mwc-icon-button slot="trigger" alt="menu">
|
<mwc-icon-button slot="trigger" alt="menu">
|
||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||||
@@ -312,7 +311,7 @@ class HassioBackupDialog
|
|||||||
: "snapshots"
|
: "snapshots"
|
||||||
}/${this._backup!.slug}/download`
|
}/${this._backup!.slug}/download`
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
});
|
});
|
||||||
|
@@ -127,7 +127,7 @@ class HassioCreateBackupDialog extends LitElement {
|
|||||||
|
|
||||||
this._dialogParams!.onCreate();
|
this._dialogParams!.onCreate();
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
}
|
}
|
||||||
this._creatingBackup = false;
|
this._creatingBackup = false;
|
||||||
|
@@ -1,180 +0,0 @@
|
|||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
|
||||||
import "@polymer/paper-item/paper-item";
|
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import "../../../../src/components/ha-circular-progress";
|
|
||||||
import "../../../../src/components/ha-markdown";
|
|
||||||
import {
|
|
||||||
extractApiErrorMessage,
|
|
||||||
ignoreSupervisorError,
|
|
||||||
} from "../../../../src/data/hassio/common";
|
|
||||||
import {
|
|
||||||
DatadiskList,
|
|
||||||
listDatadisks,
|
|
||||||
moveDatadisk,
|
|
||||||
} from "../../../../src/data/hassio/host";
|
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
import { showAlertDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
|
||||||
import { HassioDatatiskDialogParams } from "./show-dialog-hassio-datadisk";
|
|
||||||
|
|
||||||
const calculateMoveTime = memoizeOne((supervisor: Supervisor): number => {
|
|
||||||
const speed = supervisor.host.disk_life_time !== "" ? 30 : 10;
|
|
||||||
const moveTime = (supervisor.host.disk_used * 1000) / 60 / speed;
|
|
||||||
const rebootTime = (supervisor.host.startup_time * 4) / 60;
|
|
||||||
return Math.ceil((moveTime + rebootTime) / 10) * 10;
|
|
||||||
});
|
|
||||||
|
|
||||||
@customElement("dialog-hassio-datadisk")
|
|
||||||
class HassioDatadiskDialog extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@state() private dialogParams?: HassioDatatiskDialogParams;
|
|
||||||
|
|
||||||
@state() private selectedDevice?: string;
|
|
||||||
|
|
||||||
@state() private devices?: DatadiskList["devices"];
|
|
||||||
|
|
||||||
@state() private moving = false;
|
|
||||||
|
|
||||||
public showDialog(params: HassioDatatiskDialogParams) {
|
|
||||||
this.dialogParams = params;
|
|
||||||
listDatadisks(this.hass).then((data) => {
|
|
||||||
this.devices = data.devices;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeDialog(): void {
|
|
||||||
this.dialogParams = undefined;
|
|
||||||
this.selectedDevice = undefined;
|
|
||||||
this.devices = undefined;
|
|
||||||
this.moving = false;
|
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
|
||||||
if (!this.dialogParams) {
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
return html`
|
|
||||||
<ha-dialog
|
|
||||||
open
|
|
||||||
scrimClickAction
|
|
||||||
escapeKeyAction
|
|
||||||
.heading=${this.moving
|
|
||||||
? this.dialogParams.supervisor.localize("dialog.datadisk_move.moving")
|
|
||||||
: this.dialogParams.supervisor.localize("dialog.datadisk_move.title")}
|
|
||||||
@closed=${this.closeDialog}
|
|
||||||
?hideActions=${this.moving}
|
|
||||||
>
|
|
||||||
${this.moving
|
|
||||||
? html` <ha-circular-progress alt="Moving" size="large" active>
|
|
||||||
</ha-circular-progress>
|
|
||||||
<p class="progress-text">
|
|
||||||
${this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.moving_desc"
|
|
||||||
)}
|
|
||||||
</p>`
|
|
||||||
: html` ${this.devices?.length
|
|
||||||
? html`
|
|
||||||
${this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.description",
|
|
||||||
{
|
|
||||||
current_path: this.dialogParams.supervisor.os.data_disk,
|
|
||||||
time: calculateMoveTime(this.dialogParams.supervisor),
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
<br /><br />
|
|
||||||
|
|
||||||
<paper-dropdown-menu
|
|
||||||
.label=${this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.select_device"
|
|
||||||
)}
|
|
||||||
@value-changed=${this._select_device}
|
|
||||||
>
|
|
||||||
<paper-listbox slot="dropdown-content">
|
|
||||||
${this.devices.map(
|
|
||||||
(device) => html`<paper-item>${device}</paper-item>`
|
|
||||||
)}
|
|
||||||
</paper-listbox>
|
|
||||||
</paper-dropdown-menu>
|
|
||||||
`
|
|
||||||
: this.devices === undefined
|
|
||||||
? this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.loading_devices"
|
|
||||||
)
|
|
||||||
: this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.no_devices"
|
|
||||||
)}
|
|
||||||
|
|
||||||
<mwc-button slot="secondaryAction" @click=${this.closeDialog}>
|
|
||||||
${this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.cancel"
|
|
||||||
)}
|
|
||||||
</mwc-button>
|
|
||||||
|
|
||||||
<mwc-button
|
|
||||||
.disabled=${!this.selectedDevice}
|
|
||||||
slot="primaryAction"
|
|
||||||
@click=${this._moveDatadisk}
|
|
||||||
>
|
|
||||||
${this.dialogParams.supervisor.localize(
|
|
||||||
"dialog.datadisk_move.move"
|
|
||||||
)}
|
|
||||||
</mwc-button>`}
|
|
||||||
</ha-dialog>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _select_device(event) {
|
|
||||||
this.selectedDevice = event.detail.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _moveDatadisk() {
|
|
||||||
this.moving = true;
|
|
||||||
try {
|
|
||||||
await moveDatadisk(this.hass, this.selectedDevice!);
|
|
||||||
} catch (err: any) {
|
|
||||||
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.dialogParams!.supervisor.localize(
|
|
||||||
"system.host.failed_to_move"
|
|
||||||
),
|
|
||||||
text: extractApiErrorMessage(err),
|
|
||||||
});
|
|
||||||
this.closeDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
|
||||||
return [
|
|
||||||
haStyle,
|
|
||||||
haStyleDialog,
|
|
||||||
css`
|
|
||||||
paper-dropdown-menu {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
ha-circular-progress {
|
|
||||||
display: block;
|
|
||||||
margin: 32px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-text {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"dialog-hassio-datadisk": HassioDatadiskDialog;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,17 +0,0 @@
|
|||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
|
||||||
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
|
||||||
|
|
||||||
export interface HassioDatatiskDialogParams {
|
|
||||||
supervisor: Supervisor;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const showHassioDatadiskDialog = (
|
|
||||||
element: HTMLElement,
|
|
||||||
dialogParams: HassioDatatiskDialogParams
|
|
||||||
): void => {
|
|
||||||
fireEvent(element, "show-dialog", {
|
|
||||||
dialogTag: "dialog-hassio-datadisk",
|
|
||||||
dialogImport: () => import("./dialog-hassio-datadisk"),
|
|
||||||
dialogParams,
|
|
||||||
});
|
|
||||||
};
|
|
@@ -287,7 +287,7 @@ export class DialogHassioNetwork
|
|||||||
this.hass,
|
this.hass,
|
||||||
this._interface.interface
|
this._interface.interface
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: "Failed to scan for accesspoints",
|
title: "Failed to scan for accesspoints",
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -448,7 +448,7 @@ export class DialogHassioNetwork
|
|||||||
this._interface!.interface,
|
this._interface!.interface,
|
||||||
interfaceOptions
|
interfaceOptions
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.network.failed_to_change"),
|
title: this.supervisor.localize("dialog.network.failed_to_change"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
|
@@ -190,7 +190,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
await addHassioDockerRegistry(this.hass, data);
|
await addHassioDockerRegistry(this.hass, data);
|
||||||
await this._loadRegistries();
|
await this._loadRegistries();
|
||||||
this._addingRegistry = false;
|
this._addingRegistry = false;
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.registries.failed_to_add"),
|
title: this.supervisor.localize("dialog.registries.failed_to_add"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -204,7 +204,7 @@ class HassioRegistriesDialog extends LitElement {
|
|||||||
try {
|
try {
|
||||||
await removeHassioDockerRegistry(this.hass, entry.registry);
|
await removeHassioDockerRegistry(this.hass, entry.registry);
|
||||||
await this._loadRegistries();
|
await this._loadRegistries();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("dialog.registries.failed_to_remove"),
|
title: this.supervisor.localize("dialog.registries.failed_to_remove"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
|
@@ -9,7 +9,6 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
|||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||||
import { caseInsensitiveStringCompare } from "../../../../src/common/string/compare";
|
|
||||||
import "../../../../src/components/ha-alert";
|
import "../../../../src/components/ha-alert";
|
||||||
import "../../../../src/components/ha-circular-progress";
|
import "../../../../src/components/ha-circular-progress";
|
||||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
||||||
@@ -58,7 +57,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
private _filteredRepositories = memoizeOne((repos: HassioAddonRepository[]) =>
|
private _filteredRepositories = memoizeOne((repos: HassioAddonRepository[]) =>
|
||||||
repos
|
repos
|
||||||
.filter((repo) => repo.slug !== "core" && repo.slug !== "local")
|
.filter((repo) => repo.slug !== "core" && repo.slug !== "local")
|
||||||
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
.sort((a, b) => (a.name < b.name ? -1 : 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@@ -186,7 +185,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
this._repositories = addonsinfo.repositories;
|
this._repositories = addonsinfo.repositories;
|
||||||
|
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +207,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
await this._loadData();
|
await this._loadData();
|
||||||
|
|
||||||
input.value = "";
|
input.value = "";
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
}
|
}
|
||||||
this._processing = false;
|
this._processing = false;
|
||||||
@@ -230,7 +229,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
addons_repositories: newRepositories,
|
addons_repositories: newRepositories,
|
||||||
});
|
});
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ export const suggestAddonRestart = async (
|
|||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
try {
|
try {
|
||||||
await restartHassioAddon(hass, addon.slug);
|
await restartHassioAddon(hass, addon.slug);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(element, {
|
showAlertDialog(element, {
|
||||||
title: supervisor.localize(
|
title: supervisor.localize(
|
||||||
"common.failed_to_restart_name",
|
"common.failed_to_restart_name",
|
||||||
|
@@ -148,7 +148,7 @@ class DialogSupervisorUpdate extends LitElement {
|
|||||||
this.hass,
|
this.hass,
|
||||||
this._dialogParams!.backupParams
|
this._dialogParams!.backupParams
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
this._action = null;
|
this._action = null;
|
||||||
return;
|
return;
|
||||||
@@ -158,7 +158,7 @@ class DialogSupervisorUpdate extends LitElement {
|
|||||||
this._action = "update";
|
this._action = "update";
|
||||||
try {
|
try {
|
||||||
await this._dialogParams!.updateHandler!();
|
await this._dialogParams!.updateHandler!();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
this._action = null;
|
this._action = null;
|
||||||
|
@@ -87,7 +87,7 @@ class HassioMyRedirect extends LitElement {
|
|||||||
let url: string;
|
let url: string;
|
||||||
try {
|
try {
|
||||||
url = this._createRedirectUrl(redirect);
|
url = this._createRedirectUrl(redirect);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize("my.error");
|
this._error = this.supervisor.localize("my.error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,7 @@ class HassioIngressView extends LitElement {
|
|||||||
if (requestedAddon) {
|
if (requestedAddon) {
|
||||||
try {
|
try {
|
||||||
addonInfo = await fetchHassioAddonInfo(this.hass, requestedAddon);
|
addonInfo = await fetchHassioAddonInfo(this.hass, requestedAddon);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
title: requestedAddon,
|
title: requestedAddon,
|
||||||
@@ -145,7 +145,7 @@ class HassioIngressView extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
addon = await fetchHassioAddonInfo(this.hass, addonSlug);
|
addon = await fetchHassioAddonInfo(this.hass, addonSlug);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
text: "Unable to fetch add-on info to start Ingress",
|
text: "Unable to fetch add-on info to start Ingress",
|
||||||
title: "Supervisor",
|
title: "Supervisor",
|
||||||
@@ -179,7 +179,7 @@ class HassioIngressView extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
session = await createSessionPromise;
|
session = await createSessionPromise;
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
text: "Unable to create an Ingress session",
|
text: "Unable to create an Ingress session",
|
||||||
title: addon.name,
|
title: addon.name,
|
||||||
@@ -195,7 +195,7 @@ class HassioIngressView extends LitElement {
|
|||||||
this._sessionKeepAlive = window.setInterval(async () => {
|
this._sessionKeepAlive = window.setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
await validateHassioSession(this.hass, session);
|
await validateHassioSession(this.hass, session);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
session = await createHassioSession(this.hass);
|
session = await createHassioSession(this.hass);
|
||||||
}
|
}
|
||||||
}, 60000);
|
}, 60000);
|
||||||
|
@@ -144,7 +144,7 @@ class HassioCoreInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await restartCore(this.hass);
|
await restartCore(this.hass);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
if (this.hass.connection.connected) {
|
if (this.hass.connection.connected) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
|
@@ -18,6 +18,7 @@ import { fetchHassioHardwareInfo } from "../../../src/data/hassio/hardware";
|
|||||||
import {
|
import {
|
||||||
changeHostOptions,
|
changeHostOptions,
|
||||||
configSyncOS,
|
configSyncOS,
|
||||||
|
dataDiskMove,
|
||||||
rebootHost,
|
rebootHost,
|
||||||
shutdownHost,
|
shutdownHost,
|
||||||
updateOS,
|
updateOS,
|
||||||
@@ -39,9 +40,8 @@ import {
|
|||||||
roundWithOneDecimal,
|
roundWithOneDecimal,
|
||||||
} from "../../../src/util/calculate";
|
} from "../../../src/util/calculate";
|
||||||
import "../components/supervisor-metric";
|
import "../components/supervisor-metric";
|
||||||
import { showHassioDatadiskDialog } from "../dialogs/datadisk/show-dialog-hassio-datadisk";
|
|
||||||
import { showHassioHardwareDialog } from "../dialogs/hardware/show-dialog-hassio-hardware";
|
|
||||||
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
|
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
|
||||||
|
import { showHassioHardwareDialog } from "../dialogs/hardware/show-dialog-hassio-hardware";
|
||||||
import { hassioStyle } from "../resources/hassio-style";
|
import { hassioStyle } from "../resources/hassio-style";
|
||||||
|
|
||||||
@customElement("hassio-host-info")
|
@customElement("hassio-host-info")
|
||||||
@@ -184,34 +184,22 @@ class HassioHostInfo extends LitElement {
|
|||||||
<mwc-icon-button slot="trigger">
|
<mwc-icon-button slot="trigger">
|
||||||
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiDotsVertical}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
<mwc-list-item
|
<mwc-list-item @click=${() => this._handleMenuAction("hardware")}>
|
||||||
.action=${"hardware"}
|
|
||||||
@click=${this._handleMenuAction}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize("system.host.hardware")}
|
${this.supervisor.localize("system.host.hardware")}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
${this.supervisor.host.features.includes("haos")
|
${this.supervisor.host.features.includes("haos")
|
||||||
? html`
|
? html`<mwc-list-item
|
||||||
<mwc-list-item
|
@click=${() => this._handleMenuAction("import_from_usb")}
|
||||||
.action=${"import_from_usb"}
|
>
|
||||||
@click=${this._handleMenuAction}
|
${this.supervisor.localize("system.host.import_from_usb")}
|
||||||
>
|
</mwc-list-item>`
|
||||||
${this.supervisor.localize("system.host.import_from_usb")}
|
: ""}
|
||||||
</mwc-list-item>
|
${this.supervisor.host.features.includes("agent")
|
||||||
${this.supervisor.host.features.includes("os_agent") &&
|
? html`<mwc-list-item
|
||||||
atLeastVersion(this.supervisor.host.agent_version, 1, 2, 0)
|
@click=${() => this._handleMenuAction("data_disk_move")}
|
||||||
? html`
|
>
|
||||||
<mwc-list-item
|
${this.supervisor.localize("system.host.data_disk_move")}
|
||||||
.action=${"move_datadisk"}
|
</mwc-list-item>`
|
||||||
@click=${this._handleMenuAction}
|
|
||||||
>
|
|
||||||
${this.supervisor.localize(
|
|
||||||
"system.host.move_datadisk"
|
|
||||||
)}
|
|
||||||
</mwc-list-item>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
`
|
|
||||||
: ""}
|
: ""}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
</div>
|
</div>
|
||||||
@@ -234,31 +222,25 @@ class HassioHostInfo extends LitElement {
|
|||||||
return network_info.interfaces.find((a) => a.primary)?.ipv4?.address![0];
|
return network_info.interfaces.find((a) => a.primary)?.ipv4?.address![0];
|
||||||
});
|
});
|
||||||
|
|
||||||
private async _handleMenuAction(ev) {
|
private async _handleMenuAction(action: string) {
|
||||||
switch ((ev.target as any).action) {
|
switch (action) {
|
||||||
case "hardware":
|
case "hardware":
|
||||||
await this._showHardware();
|
await this._showHardware();
|
||||||
break;
|
break;
|
||||||
case "import_from_usb":
|
case "import_from_usb":
|
||||||
await this._importFromUSB();
|
await this._importFromUSB();
|
||||||
break;
|
break;
|
||||||
case "move_datadisk":
|
case "data_disk_move":
|
||||||
await this._moveDatadisk();
|
await this._dataDiskMove();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _moveDatadisk(): void {
|
|
||||||
showHassioDatadiskDialog(this, {
|
|
||||||
supervisor: this.supervisor,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _showHardware(): Promise<void> {
|
private async _showHardware(): Promise<void> {
|
||||||
let hardware;
|
let hardware;
|
||||||
try {
|
try {
|
||||||
hardware = await fetchHassioHardwareInfo(this.hass);
|
hardware = await fetchHassioHardwareInfo(this.hass);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
await showAlertDialog(this, {
|
await showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"system.host.failed_to_get_hardware_list"
|
"system.host.failed_to_get_hardware_list"
|
||||||
@@ -288,7 +270,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await rebootHost(this.hass);
|
await rebootHost(this.hass);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// Ignore connection errors, these are all expected
|
// Ignore connection errors, these are all expected
|
||||||
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
@@ -318,7 +300,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await shutdownHost(this.hass);
|
await shutdownHost(this.hass);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// Ignore connection errors, these are all expected
|
// Ignore connection errors, these are all expected
|
||||||
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
@@ -359,7 +341,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
try {
|
try {
|
||||||
await updateOS(this.hass);
|
await updateOS(this.hass);
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "os" });
|
fireEvent(this, "supervisor-collection-refresh", { collection: "os" });
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
if (this.hass.connection.connected) {
|
if (this.hass.connection.connected) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
@@ -397,7 +379,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: "host",
|
collection: "host",
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.host.failed_to_set_hostname"),
|
title: this.supervisor.localize("system.host.failed_to_set_hostname"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -412,7 +394,7 @@ class HassioHostInfo extends LitElement {
|
|||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: "host",
|
collection: "host",
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"system.host.failed_to_import_from_usb"
|
"system.host.failed_to_import_from_usb"
|
||||||
@@ -422,6 +404,34 @@ class HassioHostInfo extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _dataDiskMove(): Promise<void> {
|
||||||
|
const confirmed = await showConfirmationDialog(this, {
|
||||||
|
title: this.supervisor.localize("system.host.data_disk_move"),
|
||||||
|
text: html`${this.supervisor.localize(
|
||||||
|
"dialog.data_disk_move.description",
|
||||||
|
{ current_path: this.supervisor.os.data_disk }
|
||||||
|
)} <br /><br />${this.supervisor.localize(
|
||||||
|
"dialog.data_disk_move.confirm_text"
|
||||||
|
)}`,
|
||||||
|
confirmText: this.supervisor.localize("dialog.data_disk_move.move"),
|
||||||
|
dismissText: this.supervisor.localize("dialog.data_disk_move.cancel"),
|
||||||
|
});
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dataDiskMove(this.hass);
|
||||||
|
} catch (err) {
|
||||||
|
if (this.hass.connection.connected && !ignoreSupervisorError(err)) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: this.supervisor.localize("system.host.failed_to_move"),
|
||||||
|
text: extractApiErrorMessage(err),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
private async _loadData(): Promise<void> {
|
||||||
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
|
||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
|
@@ -34,18 +34,16 @@ import { hassioStyle } from "../resources/hassio-style";
|
|||||||
const UNSUPPORTED_REASON_URL = {
|
const UNSUPPORTED_REASON_URL = {
|
||||||
apparmor: "/more-info/unsupported/apparmor",
|
apparmor: "/more-info/unsupported/apparmor",
|
||||||
container: "/more-info/unsupported/container",
|
container: "/more-info/unsupported/container",
|
||||||
content_trust: "/more-info/unsupported/content_trust",
|
|
||||||
dbus: "/more-info/unsupported/dbus",
|
dbus: "/more-info/unsupported/dbus",
|
||||||
docker_configuration: "/more-info/unsupported/docker_configuration",
|
docker_configuration: "/more-info/unsupported/docker_configuration",
|
||||||
docker_version: "/more-info/unsupported/docker_version",
|
docker_version: "/more-info/unsupported/docker_version",
|
||||||
job_conditions: "/more-info/unsupported/job_conditions",
|
job_conditions: "/more-info/unsupported/job_conditions",
|
||||||
lxc: "/more-info/unsupported/lxc",
|
lxc: "/more-info/unsupported/lxc",
|
||||||
network_manager: "/more-info/unsupported/network_manager",
|
network_manager: "/more-info/unsupported/network_manager",
|
||||||
os_agent: "/more-info/unsupported/os_agent",
|
|
||||||
os: "/more-info/unsupported/os",
|
os: "/more-info/unsupported/os",
|
||||||
privileged: "/more-info/unsupported/privileged",
|
privileged: "/more-info/unsupported/privileged",
|
||||||
source_mods: "/more-info/unsupported/source_mods",
|
|
||||||
systemd: "/more-info/unsupported/systemd",
|
systemd: "/more-info/unsupported/systemd",
|
||||||
|
content_trust: "/more-info/unsupported/content_trust",
|
||||||
};
|
};
|
||||||
|
|
||||||
const UNHEALTHY_REASON_URL = {
|
const UNHEALTHY_REASON_URL = {
|
||||||
@@ -282,7 +280,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
};
|
};
|
||||||
await setSupervisorOption(this.hass, data);
|
await setSupervisorOption(this.hass, data);
|
||||||
await this._reloadSupervisor();
|
await this._reloadSupervisor();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"system.supervisor.failed_to_set_option"
|
"system.supervisor.failed_to_set_option"
|
||||||
@@ -300,7 +298,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this._reloadSupervisor();
|
await this._reloadSupervisor();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize("system.supervisor.failed_to_reload"),
|
title: this.supervisor.localize("system.supervisor.failed_to_reload"),
|
||||||
text: extractApiErrorMessage(err),
|
text: extractApiErrorMessage(err),
|
||||||
@@ -343,7 +341,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await restartSupervisor(this.hass);
|
await restartSupervisor(this.hass);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"common.failed_to_restart_name",
|
"common.failed_to_restart_name",
|
||||||
@@ -388,7 +386,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
fireEvent(this, "supervisor-collection-refresh", {
|
fireEvent(this, "supervisor-collection-refresh", {
|
||||||
collection: "supervisor",
|
collection: "supervisor",
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"common.failed_to_update_name",
|
"common.failed_to_update_name",
|
||||||
@@ -427,10 +425,10 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
<li>
|
<li>
|
||||||
${UNSUPPORTED_REASON_URL[reason]
|
${UNSUPPORTED_REASON_URL[reason]
|
||||||
? html`<a
|
? html`<a
|
||||||
href=${documentationUrl(
|
href="${documentationUrl(
|
||||||
this.hass,
|
this.hass,
|
||||||
UNSUPPORTED_REASON_URL[reason]
|
UNSUPPORTED_REASON_URL[reason]
|
||||||
)}
|
)}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -458,10 +456,10 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
<li>
|
<li>
|
||||||
${UNHEALTHY_REASON_URL[reason]
|
${UNHEALTHY_REASON_URL[reason]
|
||||||
? html`<a
|
? html`<a
|
||||||
href=${documentationUrl(
|
href="${documentationUrl(
|
||||||
this.hass,
|
this.hass,
|
||||||
UNHEALTHY_REASON_URL[reason]
|
UNHEALTHY_REASON_URL[reason]
|
||||||
)}
|
)}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -483,7 +481,7 @@ class HassioSupervisorInfo extends LitElement {
|
|||||||
diagnostics: !this.supervisor.supervisor?.diagnostics,
|
diagnostics: !this.supervisor.supervisor?.diagnostics,
|
||||||
};
|
};
|
||||||
await setSupervisorOption(this.hass, data);
|
await setSupervisorOption(this.hass, data);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.supervisor.localize(
|
title: this.supervisor.localize(
|
||||||
"system.supervisor.failed_to_set_option"
|
"system.supervisor.failed_to_set_option"
|
||||||
|
@@ -130,7 +130,7 @@ class HassioSupervisorLog extends LitElement {
|
|||||||
this.hass,
|
this.hass,
|
||||||
this._selectedLogProvider
|
this._selectedLogProvider
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this._error = this.supervisor.localize(
|
this._error = this.supervisor.localize(
|
||||||
"system.log.get_logs",
|
"system.log.get_logs",
|
||||||
"provider",
|
"provider",
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
[build.environment]
|
[build.environment]
|
||||||
YARN_VERSION = "1.22.11"
|
YARN_VERSION = "1.22.11"
|
||||||
NODE_OPTIONS = "--max_old_space_size=6144"
|
NODE_OPTIONS = "--max_old_space_size=4096"
|
||||||
|
117
package.json
117
package.json
@@ -16,7 +16,8 @@
|
|||||||
"lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md",
|
"lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md",
|
||||||
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types",
|
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types",
|
||||||
"format": "yarn run format:eslint && yarn run format:prettier",
|
"format": "yarn run format:eslint && yarn run format:prettier",
|
||||||
"test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.js \"test/**/*.ts\""
|
"mocha": "ts-mocha -p test-mocha/tsconfig.test.json \"test-mocha/**/*.ts\"",
|
||||||
|
"test": "yarn run mocha"
|
||||||
},
|
},
|
||||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -33,39 +34,35 @@
|
|||||||
"@codemirror/stream-parser": "^0.19.1",
|
"@codemirror/stream-parser": "^0.19.1",
|
||||||
"@codemirror/text": "^0.19.2",
|
"@codemirror/text": "^0.19.2",
|
||||||
"@codemirror/view": "^0.19.4",
|
"@codemirror/view": "^0.19.4",
|
||||||
"@formatjs/intl-datetimeformat": "^4.2.4",
|
|
||||||
"@formatjs/intl-getcanonicallocales": "^1.7.3",
|
"@formatjs/intl-getcanonicallocales": "^1.7.3",
|
||||||
"@formatjs/intl-locale": "^2.4.38",
|
"@formatjs/intl-locale": "^2.4.37",
|
||||||
"@formatjs/intl-numberformat": "^7.2.4",
|
"@formatjs/intl-pluralrules": "^4.1.3",
|
||||||
"@formatjs/intl-pluralrules": "^4.1.4",
|
|
||||||
"@formatjs/intl-relativetimeformat": "^9.3.1",
|
|
||||||
"@formatjs/intl-utils": "^3.8.4",
|
|
||||||
"@fullcalendar/common": "5.9.0",
|
"@fullcalendar/common": "5.9.0",
|
||||||
"@fullcalendar/core": "5.9.0",
|
"@fullcalendar/core": "5.9.0",
|
||||||
"@fullcalendar/daygrid": "5.9.0",
|
"@fullcalendar/daygrid": "5.9.0",
|
||||||
"@fullcalendar/interaction": "5.9.0",
|
"@fullcalendar/interaction": "5.9.0",
|
||||||
"@fullcalendar/list": "5.9.0",
|
"@fullcalendar/list": "5.9.0",
|
||||||
"@lit-labs/virtualizer": "patch:@lit-labs/virtualizer@0.6.0#./.yarn/patches/@lit-labs/virtualizer/0.7.0.patch",
|
"@lit-labs/virtualizer": "patch:@lit-labs/virtualizer@0.6.0#./.yarn/patches/@lit-labs/virtualizer/0.7.0.patch",
|
||||||
"@material/chips": "13.0.0-canary.65125b3a6.0",
|
"@material/chips": "12.0.0-canary.22d29cbb4.0",
|
||||||
"@material/data-table": "13.0.0-canary.65125b3a6.0",
|
"@material/data-table": "12.0.0-canary.22d29cbb4.0",
|
||||||
"@material/mwc-button": "0.25.1",
|
"@material/mwc-button": "0.22.1",
|
||||||
"@material/mwc-checkbox": "0.25.1",
|
"@material/mwc-checkbox": "0.22.1",
|
||||||
"@material/mwc-circular-progress": "0.25.1",
|
"@material/mwc-circular-progress": "0.22.1",
|
||||||
"@material/mwc-dialog": "0.25.1",
|
"@material/mwc-dialog": "0.22.1",
|
||||||
"@material/mwc-fab": "0.25.1",
|
"@material/mwc-fab": "0.22.1",
|
||||||
"@material/mwc-formfield": "0.25.1",
|
"@material/mwc-formfield": "0.22.1",
|
||||||
"@material/mwc-icon-button": "0.25.1",
|
"@material/mwc-icon-button": "0.22.1",
|
||||||
"@material/mwc-linear-progress": "0.25.1",
|
"@material/mwc-linear-progress": "0.22.1",
|
||||||
"@material/mwc-list": "0.25.1",
|
"@material/mwc-list": "0.22.1",
|
||||||
"@material/mwc-menu": "0.25.1",
|
"@material/mwc-menu": "0.22.1",
|
||||||
"@material/mwc-radio": "0.25.1",
|
"@material/mwc-radio": "0.22.1",
|
||||||
"@material/mwc-ripple": "0.25.1",
|
"@material/mwc-ripple": "0.22.1",
|
||||||
"@material/mwc-switch": "0.25.1",
|
"@material/mwc-switch": "0.22.1",
|
||||||
"@material/mwc-tab": "0.25.1",
|
"@material/mwc-tab": "0.22.1",
|
||||||
"@material/mwc-tab-bar": "0.25.1",
|
"@material/mwc-tab-bar": "0.22.1",
|
||||||
"@material/top-app-bar": "13.0.0-canary.65125b3a6.0",
|
"@material/top-app-bar": "12.0.0-canary.22d29cbb4.0",
|
||||||
"@mdi/js": "6.2.95",
|
"@mdi/js": "6.1.95",
|
||||||
"@mdi/svg": "6.2.95",
|
"@mdi/svg": "6.1.95",
|
||||||
"@polymer/app-layout": "^3.1.0",
|
"@polymer/app-layout": "^3.1.0",
|
||||||
"@polymer/iron-flex-layout": "^3.0.1",
|
"@polymer/iron-flex-layout": "^3.0.1",
|
||||||
"@polymer/iron-icon": "^3.0.1",
|
"@polymer/iron-icon": "^3.0.1",
|
||||||
@@ -92,8 +89,8 @@
|
|||||||
"@polymer/paper-tooltip": "^3.0.1",
|
"@polymer/paper-tooltip": "^3.0.1",
|
||||||
"@polymer/polymer": "3.4.1",
|
"@polymer/polymer": "3.4.1",
|
||||||
"@thomasloven/round-slider": "0.5.4",
|
"@thomasloven/round-slider": "0.5.4",
|
||||||
"@vaadin/vaadin-combo-box": "^21.0.2",
|
"@vaadin/vaadin-combo-box": "^20.0.4",
|
||||||
"@vaadin/vaadin-date-picker": "^21.0.2",
|
"@vaadin/vaadin-date-picker": "^20.0.4",
|
||||||
"@vibrant/color": "^3.2.1-alpha.1",
|
"@vibrant/color": "^3.2.1-alpha.1",
|
||||||
"@vibrant/core": "^3.2.1-alpha.1",
|
"@vibrant/core": "^3.2.1-alpha.1",
|
||||||
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
|
"@vibrant/quantizer-mmcq": "^3.2.1-alpha.1",
|
||||||
@@ -106,17 +103,18 @@
|
|||||||
"date-fns": "^2.23.0",
|
"date-fns": "^2.23.0",
|
||||||
"deep-clone-simple": "^1.1.1",
|
"deep-clone-simple": "^1.1.1",
|
||||||
"deep-freeze": "^0.0.1",
|
"deep-freeze": "^0.0.1",
|
||||||
|
"fecha": "^4.2.0",
|
||||||
"fuse.js": "^6.0.0",
|
"fuse.js": "^6.0.0",
|
||||||
"google-timezones-json": "^1.0.2",
|
"google-timezones-json": "^1.0.2",
|
||||||
"hls.js": "^1.0.11",
|
"hls.js": "^1.0.10",
|
||||||
"home-assistant-js-websocket": "^5.11.1",
|
"home-assistant-js-websocket": "^5.11.1",
|
||||||
"idb-keyval": "^5.1.3",
|
"idb-keyval": "^5.1.3",
|
||||||
"intl-messageformat": "^9.9.1",
|
"intl-messageformat": "^9.9.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"leaflet-draw": "^1.0.4",
|
"leaflet-draw": "^1.0.4",
|
||||||
"lit": "^2.0.0",
|
"lit": "^2.0.0-rc.3",
|
||||||
"lit-vaadin-helpers": "^0.2.1",
|
"lit-vaadin-helpers": "^0.1.3",
|
||||||
"marked": "^3.0.2",
|
"marked": "^3.0.2",
|
||||||
"memoize-one": "^5.2.1",
|
"memoize-one": "^5.2.1",
|
||||||
"node-vibrant": "3.2.1-alpha.1",
|
"node-vibrant": "3.2.1-alpha.1",
|
||||||
@@ -145,18 +143,17 @@
|
|||||||
"xss": "^1.0.9"
|
"xss": "^1.0.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.15.5",
|
"@babel/core": "^7.14.6",
|
||||||
"@babel/plugin-external-helpers": "^7.14.5",
|
"@babel/plugin-external-helpers": "^7.14.5",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
"@babel/plugin-proposal-decorators": "^7.15.4",
|
"@babel/plugin-proposal-decorators": "^7.14.5",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.15.6",
|
"@babel/plugin-proposal-object-rest-spread": "^7.14.7",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
"@babel/preset-env": "^7.14.7",
|
||||||
"@babel/preset-env": "^7.15.6",
|
"@babel/preset-typescript": "^7.14.5",
|
||||||
"@babel/preset-typescript": "^7.15.0",
|
|
||||||
"@koa/cors": "^3.1.0",
|
"@koa/cors": "^3.1.0",
|
||||||
"@open-wc/dev-server-hmr": "^0.0.2",
|
"@open-wc/dev-server-hmr": "^0.0.2",
|
||||||
"@rollup/plugin-babel": "^5.2.1",
|
"@rollup/plugin-babel": "^5.2.1",
|
||||||
@@ -173,24 +170,23 @@
|
|||||||
"@types/mocha": "^8",
|
"@types/mocha": "^8",
|
||||||
"@types/sortablejs": "^1",
|
"@types/sortablejs": "^1",
|
||||||
"@types/webspeechapi": "^0.0.29",
|
"@types/webspeechapi": "^0.0.29",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
"@typescript-eslint/eslint-plugin": "^4.28.3",
|
||||||
"@typescript-eslint/parser": "^4.32.0",
|
"@typescript-eslint/parser": "^4.28.3",
|
||||||
"@web/dev-server": "^0.0.24",
|
"@web/dev-server": "^0.0.24",
|
||||||
"@web/dev-server-rollup": "^0.2.11",
|
"@web/dev-server-rollup": "^0.2.11",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"del": "^4.0.0",
|
"del": "^4.0.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.30.0",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-typescript": "^12.3.1",
|
||||||
"eslint-config-airbnb-typescript": "^14.0.0",
|
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-import-resolver-webpack": "^0.13.1",
|
"eslint-import-resolver-webpack": "^0.13.1",
|
||||||
"eslint-plugin-disable": "^2.0.1",
|
"eslint-plugin-disable": "^2.0.1",
|
||||||
"eslint-plugin-import": "^2.24.2",
|
"eslint-plugin-import": "^2.23.4",
|
||||||
"eslint-plugin-lit": "^1.5.1",
|
"eslint-plugin-lit": "^1.5.1",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
"eslint-plugin-unused-imports": "^1.1.5",
|
"eslint-plugin-unused-imports": "^1.1.2",
|
||||||
"eslint-plugin-wc": "^1.3.2",
|
"eslint-plugin-wc": "^1.3.0",
|
||||||
"fancy-log": "^1.3.3",
|
"fancy-log": "^1.3.3",
|
||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^7.0.1",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
@@ -201,8 +197,7 @@
|
|||||||
"gulp-zopfli-green": "^3.0.1",
|
"gulp-zopfli-green": "^3.0.1",
|
||||||
"html-minifier": "^4.0.0",
|
"html-minifier": "^4.0.0",
|
||||||
"husky": "^1.3.1",
|
"husky": "^1.3.1",
|
||||||
"instant-mocha": "^1.3.1",
|
"lint-staged": "^11.0.1",
|
||||||
"lint-staged": "^11.1.2",
|
|
||||||
"lit-analyzer": "^1.2.1",
|
"lit-analyzer": "^1.2.1",
|
||||||
"lodash.template": "^4.5.0",
|
"lodash.template": "^4.5.0",
|
||||||
"magic-string": "^0.25.7",
|
"magic-string": "^0.25.7",
|
||||||
@@ -211,7 +206,7 @@
|
|||||||
"mocha": "^8.4.0",
|
"mocha": "^8.4.0",
|
||||||
"object-hash": "^2.0.3",
|
"object-hash": "^2.0.3",
|
||||||
"open": "^7.0.4",
|
"open": "^7.0.4",
|
||||||
"prettier": "^2.4.1",
|
"prettier": "^2.3.2",
|
||||||
"require-dir": "^1.2.0",
|
"require-dir": "^1.2.0",
|
||||||
"rollup": "^2.8.2",
|
"rollup": "^2.8.2",
|
||||||
"rollup-plugin-string": "^3.0.0",
|
"rollup-plugin-string": "^3.0.0",
|
||||||
@@ -221,26 +216,26 @@
|
|||||||
"sinon": "^11.0.0",
|
"sinon": "^11.0.0",
|
||||||
"source-map-url": "^0.4.0",
|
"source-map-url": "^0.4.0",
|
||||||
"systemjs": "^6.3.2",
|
"systemjs": "^6.3.2",
|
||||||
"terser-webpack-plugin": "^5.2.4",
|
"terser-webpack-plugin": "^5.1.4",
|
||||||
"ts-lit-plugin": "^1.2.1",
|
"ts-lit-plugin": "^1.2.1",
|
||||||
"typescript": "^4.4.3",
|
"ts-mocha": "^8.0.0",
|
||||||
|
"typescript": "^4.3.5",
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vinyl-source-stream": "^2.0.0",
|
"vinyl-source-stream": "^2.0.0",
|
||||||
"webpack": "^5.55.1",
|
"webpack": "^5.43.0",
|
||||||
"webpack-cli": "^4.8.0",
|
"webpack-cli": "^4.7.2",
|
||||||
"webpack-dev-server": "^4.3.0",
|
"webpack-dev-server": "^3.11.2",
|
||||||
"webpack-manifest-plugin": "^4.0.2",
|
"webpack-manifest-plugin": "^3.1.1",
|
||||||
"webpackbar": "^5.0.0-3",
|
|
||||||
"workbox-build": "^6.1.5"
|
"workbox-build": "^6.1.5"
|
||||||
},
|
},
|
||||||
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@polymer/polymer": "patch:@polymer/polymer@3.4.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
"@polymer/polymer": "patch:@polymer/polymer@3.4.1#./.yarn/patches/@polymer/polymer/pr-5569.patch",
|
||||||
"@webcomponents/webcomponentsjs": "^2.2.10",
|
"@webcomponents/webcomponentsjs": "^2.2.10",
|
||||||
"lit": "^2.0.0",
|
"lit": "^2.0.0-rc.3",
|
||||||
"lit-html": "2.0.0",
|
"lit-html": "2.0.0-rc.4",
|
||||||
"lit-element": "3.0.0",
|
"lit-element": "3.0.0-rc.3",
|
||||||
"@lit/reactive-element": "1.0.0"
|
"@lit/reactive-element": "1.0.0-rc.3"
|
||||||
},
|
},
|
||||||
"main": "src/home-assistant.js",
|
"main": "src/home-assistant.js",
|
||||||
"husky": {
|
"husky": {
|
||||||
|
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20211007.1",
|
version="20210911.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/frontend",
|
url="https://github.com/home-assistant/frontend",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@@ -194,7 +194,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
this._state = "error";
|
this._state = "error";
|
||||||
this._errorMessage = data.message;
|
this._errorMessage = data.message;
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error("Error starting auth flow", err);
|
console.error("Error starting auth flow", err);
|
||||||
this._state = "error";
|
this._state = "error";
|
||||||
@@ -317,7 +317,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this._updateStep(newStep);
|
await this._updateStep(newStep);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error("Error submitting step", err);
|
console.error("Error submitting step", err);
|
||||||
this._state = "error";
|
this._state = "error";
|
||||||
|
@@ -76,20 +76,20 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
${loggingInWith}
|
${loggingInWith}
|
||||||
|
|
||||||
<ha-auth-flow
|
<ha-auth-flow
|
||||||
.resources=${this.resources}
|
.resources="${this.resources}"
|
||||||
.clientId=${this.clientId}
|
.clientId="${this.clientId}"
|
||||||
.redirectUri=${this.redirectUri}
|
.redirectUri="${this.redirectUri}"
|
||||||
.oauth2State=${this.oauth2State}
|
.oauth2State="${this.oauth2State}"
|
||||||
.authProvider=${this._authProvider}
|
.authProvider="${this._authProvider}"
|
||||||
></ha-auth-flow>
|
></ha-auth-flow>
|
||||||
|
|
||||||
${inactiveProviders.length > 0
|
${inactiveProviders.length > 0
|
||||||
? html`
|
? html`
|
||||||
<ha-pick-auth-provider
|
<ha-pick-auth-provider
|
||||||
.resources=${this.resources}
|
.resources="${this.resources}"
|
||||||
.clientId=${this.clientId}
|
.clientId="${this.clientId}"
|
||||||
.authProviders=${inactiveProviders}
|
.authProviders="${inactiveProviders}"
|
||||||
@pick-auth-provider=${this._handleAuthProviderPick}
|
@pick-auth-provider="${this._handleAuthProviderPick}"
|
||||||
></ha-pick-auth-provider>
|
></ha-pick-auth-provider>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@@ -158,7 +158,7 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
|||||||
|
|
||||||
this._authProviders = authProviders;
|
this._authProviders = authProviders;
|
||||||
this._authProvider = authProviders[0];
|
this._authProvider = authProviders[0];
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.error("Error loading auth providers", err);
|
console.error("Error loading auth providers", err);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable lit/prefer-static-styles */
|
|
||||||
import { html, LitElement, TemplateResult } from "lit";
|
import { html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
import { css, html, LitElement } from "lit";
|
import { html, LitElement } from "lit";
|
||||||
import { property } from "lit/decorators";
|
import { property } from "lit/decorators";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import "../components/ha-icon-next";
|
import "../components/ha-icon-next";
|
||||||
@@ -18,6 +18,14 @@ class HaPickAuthProvider extends litLocalizeLiteMixin(LitElement) {
|
|||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
|
<style>
|
||||||
|
paper-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<p>${this.localize("ui.panel.page-authorize.pick_auth_provider")}:</p>
|
<p>${this.localize("ui.panel.page-authorize.pick_auth_provider")}:</p>
|
||||||
${this.authProviders.map(
|
${this.authProviders.map(
|
||||||
(provider) => html`
|
(provider) => html`
|
||||||
@@ -33,14 +41,5 @@ class HaPickAuthProvider extends litLocalizeLiteMixin(LitElement) {
|
|||||||
private _handlePick(ev) {
|
private _handlePick(ev) {
|
||||||
fireEvent(this, "pick-auth-provider", ev.currentTarget.auth_provider);
|
fireEvent(this, "pick-auth-provider", ev.currentTarget.auth_provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
|
||||||
paper-item {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
customElements.define("ha-pick-auth-provider", HaPickAuthProvider);
|
customElements.define("ha-pick-auth-provider", HaPickAuthProvider);
|
||||||
|
@@ -33,7 +33,7 @@ export function saveTokens(tokens: AuthData | null) {
|
|||||||
if (tokenCache.writeEnabled) {
|
if (tokenCache.writeEnabled) {
|
||||||
try {
|
try {
|
||||||
storage.hassTokens = JSON.stringify(tokens);
|
storage.hassTokens = JSON.stringify(tokens);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// write failed, ignore it. Happens if storage is full or private mode.
|
// write failed, ignore it. Happens if storage is full or private mode.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ export function loadTokens() {
|
|||||||
} else {
|
} else {
|
||||||
tokenCache.tokens = null;
|
tokenCache.tokens = null;
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
tokenCache.tokens = null;
|
tokenCache.tokens = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,29 +57,28 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
|
|
||||||
export const FIXED_DEVICE_CLASS_ICONS = {
|
export const FIXED_DEVICE_CLASS_ICONS = {
|
||||||
aqi: "hass:air-filter",
|
aqi: "hass:air-filter",
|
||||||
battery: "hass:battery",
|
current: "hass:current-ac",
|
||||||
carbon_dioxide: "mdi:molecule-co2",
|
carbon_dioxide: "mdi:molecule-co2",
|
||||||
carbon_monoxide: "mdi:molecule-co",
|
carbon_monoxide: "mdi:molecule-co",
|
||||||
current: "hass:current-ac",
|
|
||||||
date: "hass:calendar",
|
date: "hass:calendar",
|
||||||
energy: "hass:lightning-bolt",
|
energy: "hass:lightning-bolt",
|
||||||
gas: "hass:gas-cylinder",
|
gas: "hass:gas-cylinder",
|
||||||
humidity: "hass:water-percent",
|
humidity: "hass:water-percent",
|
||||||
illuminance: "hass:brightness-5",
|
illuminance: "hass:brightness-5",
|
||||||
monetary: "mdi:cash",
|
|
||||||
nitrogen_dioxide: "mdi:molecule",
|
nitrogen_dioxide: "mdi:molecule",
|
||||||
nitrogen_monoxide: "mdi:molecule",
|
nitrogen_monoxide: "mdi:molecule",
|
||||||
nitrous_oxide: "mdi:molecule",
|
nitrous_oxide: "mdi:molecule",
|
||||||
ozone: "mdi:molecule",
|
ozone: "mdi:molecule",
|
||||||
|
temperature: "hass:thermometer",
|
||||||
|
monetary: "mdi:cash",
|
||||||
|
pm25: "mdi:molecule",
|
||||||
pm1: "mdi:molecule",
|
pm1: "mdi:molecule",
|
||||||
pm10: "mdi:molecule",
|
pm10: "mdi:molecule",
|
||||||
pm25: "mdi:molecule",
|
pressure: "hass:gauge",
|
||||||
power: "hass:flash",
|
power: "hass:flash",
|
||||||
power_factor: "hass:angle-acute",
|
power_factor: "hass:angle-acute",
|
||||||
pressure: "hass:gauge",
|
|
||||||
signal_strength: "hass:wifi",
|
signal_strength: "hass:wifi",
|
||||||
sulphur_dioxide: "mdi:molecule",
|
sulphur_dioxide: "mdi:molecule",
|
||||||
temperature: "hass:thermometer",
|
|
||||||
timestamp: "hass:clock",
|
timestamp: "hass:clock",
|
||||||
volatile_organic_compounds: "mdi:molecule",
|
volatile_organic_compounds: "mdi:molecule",
|
||||||
voltage: "hass:sine-wave",
|
voltage: "hass:sine-wave",
|
||||||
|
34
src/common/datetime/check_options_support.ts
Normal file
34
src/common/datetime/check_options_support.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Check for support of native locale string options
|
||||||
|
function checkToLocaleDateStringSupportsOptions() {
|
||||||
|
try {
|
||||||
|
new Date().toLocaleDateString("i");
|
||||||
|
} catch (e) {
|
||||||
|
return e.name === "RangeError";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkToLocaleTimeStringSupportsOptions() {
|
||||||
|
try {
|
||||||
|
new Date().toLocaleTimeString("i");
|
||||||
|
} catch (e) {
|
||||||
|
return e.name === "RangeError";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkToLocaleStringSupportsOptions() {
|
||||||
|
try {
|
||||||
|
new Date().toLocaleString("i");
|
||||||
|
} catch (e) {
|
||||||
|
return e.name === "RangeError";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toLocaleDateStringSupportsOptions =
|
||||||
|
checkToLocaleDateStringSupportsOptions();
|
||||||
|
export const toLocaleTimeStringSupportsOptions =
|
||||||
|
checkToLocaleTimeStringSupportsOptions();
|
||||||
|
export const toLocaleStringSupportsOptions =
|
||||||
|
checkToLocaleStringSupportsOptions();
|
@@ -1,15 +1,13 @@
|
|||||||
|
import { format } from "fecha";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
import { FrontendLocaleData } from "../../data/translation";
|
||||||
import { polyfillsLoaded } from "../translations/localize";
|
import { toLocaleDateStringSupportsOptions } from "./check_options_support";
|
||||||
|
|
||||||
if (__BUILD__ === "latest" && polyfillsLoaded) {
|
|
||||||
await polyfillsLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tuesday, August 10
|
// Tuesday, August 10
|
||||||
export const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateWeekday = toLocaleDateStringSupportsOptions
|
||||||
formatDateWeekdayMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateWeekdayMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "dddd, MMMM D");
|
||||||
const formatDateWeekdayMem = memoizeOne(
|
const formatDateWeekdayMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -20,9 +18,10 @@ const formatDateWeekdayMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// August 10, 2021
|
// August 10, 2021
|
||||||
export const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDate = toLocaleDateStringSupportsOptions
|
||||||
formatDateMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "MMMM D, YYYY");
|
||||||
const formatDateMem = memoizeOne(
|
const formatDateMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -33,9 +32,10 @@ const formatDateMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 10/08/2021
|
// 10/08/2021
|
||||||
export const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateNumeric = toLocaleDateStringSupportsOptions
|
||||||
formatDateNumericMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateNumericMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "M/D/YYYY");
|
||||||
const formatDateNumericMem = memoizeOne(
|
const formatDateNumericMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -46,9 +46,10 @@ const formatDateNumericMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Aug 10
|
// Aug 10
|
||||||
export const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateShort = toLocaleDateStringSupportsOptions
|
||||||
formatDateShortMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateShortMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "MMM D");
|
||||||
const formatDateShortMem = memoizeOne(
|
const formatDateShortMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -58,11 +59,10 @@ const formatDateShortMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// August 2021
|
// August 2021
|
||||||
export const formatDateMonthYear = (
|
export const formatDateMonthYear = toLocaleDateStringSupportsOptions
|
||||||
dateObj: Date,
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
locale: FrontendLocaleData
|
formatDateMonthYearMem(locale).format(dateObj)
|
||||||
) => formatDateMonthYearMem(locale).format(dateObj);
|
: (dateObj: Date) => format(dateObj, "MMMM YYYY");
|
||||||
|
|
||||||
const formatDateMonthYearMem = memoizeOne(
|
const formatDateMonthYearMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -72,9 +72,10 @@ const formatDateMonthYearMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// August
|
// August
|
||||||
export const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateMonth = toLocaleDateStringSupportsOptions
|
||||||
formatDateMonthMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateMonthMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "MMMM");
|
||||||
const formatDateMonthMem = memoizeOne(
|
const formatDateMonthMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -83,9 +84,10 @@ const formatDateMonthMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 2021
|
// 2021
|
||||||
export const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateYear = toLocaleDateStringSupportsOptions
|
||||||
formatDateYearMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateYearMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date) => format(dateObj, "YYYY");
|
||||||
const formatDateYearMem = memoizeOne(
|
const formatDateYearMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
|
@@ -1,16 +1,15 @@
|
|||||||
|
import { format } from "fecha";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
import { FrontendLocaleData } from "../../data/translation";
|
||||||
|
import { toLocaleStringSupportsOptions } from "./check_options_support";
|
||||||
import { useAmPm } from "./use_am_pm";
|
import { useAmPm } from "./use_am_pm";
|
||||||
import { polyfillsLoaded } from "../translations/localize";
|
|
||||||
|
|
||||||
if (__BUILD__ === "latest" && polyfillsLoaded) {
|
|
||||||
await polyfillsLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// August 9, 2021, 8:23 AM
|
// August 9, 2021, 8:23 AM
|
||||||
export const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatDateTime = toLocaleStringSupportsOptions
|
||||||
formatDateTimeMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatDateTimeMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "MMMM D, YYYY, HH:mm" + useAmPm(locale) ? " A" : "");
|
||||||
const formatDateTimeMem = memoizeOne(
|
const formatDateTimeMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -24,11 +23,11 @@ const formatDateTimeMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// August 9, 2021, 8:23:15 AM
|
// August 9, 2021, 8:23:15 AM
|
||||||
export const formatDateTimeWithSeconds = (
|
export const formatDateTimeWithSeconds = toLocaleStringSupportsOptions
|
||||||
dateObj: Date,
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
locale: FrontendLocaleData
|
formatDateTimeWithSecondsMem(locale).format(dateObj)
|
||||||
) => formatDateTimeWithSecondsMem(locale).format(dateObj);
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "MMMM D, YYYY, HH:mm:ss" + useAmPm(locale) ? " A" : "");
|
||||||
const formatDateTimeWithSecondsMem = memoizeOne(
|
const formatDateTimeWithSecondsMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -43,11 +42,11 @@ const formatDateTimeWithSecondsMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 9/8/2021, 8:23 AM
|
// 9/8/2021, 8:23 AM
|
||||||
export const formatDateTimeNumeric = (
|
export const formatDateTimeNumeric = toLocaleStringSupportsOptions
|
||||||
dateObj: Date,
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
locale: FrontendLocaleData
|
formatDateTimeNumericMem(locale).format(dateObj)
|
||||||
) => formatDateTimeNumericMem(locale).format(dateObj);
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "M/D/YYYY, HH:mm" + useAmPm(locale) ? " A" : "");
|
||||||
const formatDateTimeNumericMem = memoizeOne(
|
const formatDateTimeNumericMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
|
@@ -1,31 +1,30 @@
|
|||||||
|
import { format } from "fecha";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
import { FrontendLocaleData } from "../../data/translation";
|
||||||
|
import { toLocaleTimeStringSupportsOptions } from "./check_options_support";
|
||||||
import { useAmPm } from "./use_am_pm";
|
import { useAmPm } from "./use_am_pm";
|
||||||
import { polyfillsLoaded } from "../translations/localize";
|
|
||||||
|
|
||||||
if (__BUILD__ === "latest" && polyfillsLoaded) {
|
|
||||||
await polyfillsLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 9:15 PM || 21:15
|
// 9:15 PM || 21:15
|
||||||
export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatTime = toLocaleTimeStringSupportsOptions
|
||||||
formatTimeMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatTimeMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "shortTime" + useAmPm(locale) ? " A" : "");
|
||||||
const formatTimeMem = memoizeOne(
|
const formatTimeMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
hour: "numeric",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
hour12: useAmPm(locale),
|
hour12: useAmPm(locale),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// 9:15:24 PM || 21:15:24
|
// 9:15:24 PM || 21:15:24
|
||||||
export const formatTimeWithSeconds = (
|
export const formatTimeWithSeconds = toLocaleTimeStringSupportsOptions
|
||||||
dateObj: Date,
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
locale: FrontendLocaleData
|
formatTimeWithSecondsMem(locale).format(dateObj)
|
||||||
) => formatTimeWithSecondsMem(locale).format(dateObj);
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "mediumTime" + useAmPm(locale) ? " A" : "");
|
||||||
const formatTimeWithSecondsMem = memoizeOne(
|
const formatTimeWithSecondsMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
@@ -37,15 +36,17 @@ const formatTimeWithSecondsMem = memoizeOne(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Tuesday 7:00 PM || Tuesday 19:00
|
// Tuesday 7:00 PM || Tuesday 19:00
|
||||||
export const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>
|
export const formatTimeWeekday = toLocaleTimeStringSupportsOptions
|
||||||
formatTimeWeekdayMem(locale).format(dateObj);
|
? (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
formatTimeWeekdayMem(locale).format(dateObj)
|
||||||
|
: (dateObj: Date, locale: FrontendLocaleData) =>
|
||||||
|
format(dateObj, "dddd, HH:mm" + useAmPm(locale) ? " A" : "");
|
||||||
const formatTimeWeekdayMem = memoizeOne(
|
const formatTimeWeekdayMem = memoizeOne(
|
||||||
(locale: FrontendLocaleData) =>
|
(locale: FrontendLocaleData) =>
|
||||||
new Intl.DateTimeFormat(locale.language, {
|
new Intl.DateTimeFormat(locale.language, {
|
||||||
|
weekday: "long",
|
||||||
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
hour: useAmPm(locale) ? "numeric" : "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
second: "2-digit",
|
|
||||||
hour12: useAmPm(locale),
|
hour12: useAmPm(locale),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -1,32 +1,48 @@
|
|||||||
import { selectUnit } from "@formatjs/intl-utils";
|
import { LocalizeFunc } from "../translations/localize";
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { FrontendLocaleData } from "../../data/translation";
|
|
||||||
import { polyfillsLoaded } from "../translations/localize";
|
|
||||||
|
|
||||||
if (__BUILD__ === "latest" && polyfillsLoaded) {
|
/**
|
||||||
await polyfillsLoaded;
|
* Calculate a string representing a date object as relative time from now.
|
||||||
}
|
*
|
||||||
|
* Example output: 5 minutes ago, in 3 days.
|
||||||
|
*/
|
||||||
|
const tests = [60, 60, 24, 7];
|
||||||
|
const langKey = ["second", "minute", "hour", "day"];
|
||||||
|
|
||||||
const formatRelTimeMem = memoizeOne(
|
export default function relativeTime(
|
||||||
(locale: FrontendLocaleData) =>
|
dateObj: Date,
|
||||||
// @ts-expect-error
|
localize: LocalizeFunc,
|
||||||
new Intl.RelativeTimeFormat(locale.language, { numeric: "auto" })
|
options: {
|
||||||
);
|
compareTime?: Date;
|
||||||
|
includeTense?: boolean;
|
||||||
|
} = {}
|
||||||
|
): string {
|
||||||
|
const compareTime = options.compareTime || new Date();
|
||||||
|
let delta = (compareTime.getTime() - dateObj.getTime()) / 1000;
|
||||||
|
const tense = delta >= 0 ? "past" : "future";
|
||||||
|
delta = Math.abs(delta);
|
||||||
|
let roundedDelta = Math.round(delta);
|
||||||
|
|
||||||
export const relativeTime = (
|
if (roundedDelta === 0) {
|
||||||
from: Date,
|
return localize("ui.components.relative_time.just_now");
|
||||||
locale: FrontendLocaleData,
|
|
||||||
to?: Date,
|
|
||||||
includeTense = true
|
|
||||||
): string => {
|
|
||||||
const diff = selectUnit(from, to);
|
|
||||||
if (includeTense) {
|
|
||||||
return formatRelTimeMem(locale).format(diff.value, diff.unit);
|
|
||||||
}
|
}
|
||||||
return Intl.NumberFormat(locale.language, {
|
|
||||||
style: "unit",
|
let unit = "week";
|
||||||
// @ts-expect-error
|
|
||||||
unit: diff.unit,
|
for (let i = 0; i < tests.length; i++) {
|
||||||
unitDisplay: "long",
|
if (roundedDelta < tests[i]) {
|
||||||
}).format(Math.abs(diff.value));
|
unit = langKey[i];
|
||||||
};
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delta /= tests[i];
|
||||||
|
roundedDelta = Math.round(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return localize(
|
||||||
|
options.includeTense === false
|
||||||
|
? `ui.components.relative_time.duration.${unit}`
|
||||||
|
: `ui.components.relative_time.${tense}_duration.${unit}`,
|
||||||
|
"count",
|
||||||
|
roundedDelta
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@@ -74,7 +74,7 @@ class Storage {
|
|||||||
this._storage[storageKey] = value;
|
this._storage[storageKey] = value;
|
||||||
try {
|
try {
|
||||||
window.localStorage.setItem(storageKey, JSON.stringify(value));
|
window.localStorage.setItem(storageKey, JSON.stringify(value));
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// Safari in private mode doesn't allow localstorage
|
// Safari in private mode doesn't allow localstorage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -115,7 +115,7 @@ export const applyThemesOnElement = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newTheme =
|
const newTheme =
|
||||||
Object.keys(themeRules).length && cacheKey
|
themeRules && cacheKey
|
||||||
? PROCESSED_THEMES[cacheKey] || processTheme(cacheKey, themeRules)
|
? PROCESSED_THEMES[cacheKey] || processTheme(cacheKey, themeRules)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ const processTheme = (
|
|||||||
const prefixedRgbKey = `--${rgbKey}`;
|
const prefixedRgbKey = `--${rgbKey}`;
|
||||||
styles[prefixedRgbKey] = rgbValue;
|
styles[prefixedRgbKey] = rgbValue;
|
||||||
keys[prefixedRgbKey] = "";
|
keys[prefixedRgbKey] = "";
|
||||||
} catch (err: any) {
|
} catch (e) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,4 +5,4 @@ export const mainWindow =
|
|||||||
? window
|
? window
|
||||||
: parent.name === MAIN_WINDOW_NAME
|
: parent.name === MAIN_WINDOW_NAME
|
||||||
? parent
|
? parent
|
||||||
: top!;
|
: top;
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
/** Return an icon representing a alarm panel state. */
|
|
||||||
|
|
||||||
export const alarmPanelIcon = (state?: string) => {
|
|
||||||
switch (state) {
|
|
||||||
case "armed_away":
|
|
||||||
return "hass:shield-lock";
|
|
||||||
case "armed_vacation":
|
|
||||||
return "hass:shield-airplane";
|
|
||||||
case "armed_home":
|
|
||||||
return "hass:shield-home";
|
|
||||||
case "armed_night":
|
|
||||||
return "hass:shield-moon";
|
|
||||||
case "armed_custom_bypass":
|
|
||||||
return "hass:security";
|
|
||||||
case "pending":
|
|
||||||
return "hass:shield-outline";
|
|
||||||
case "triggered":
|
|
||||||
return "hass:bell-ring";
|
|
||||||
case "disarmed":
|
|
||||||
return "hass:shield-off";
|
|
||||||
default:
|
|
||||||
return "hass:shield";
|
|
||||||
}
|
|
||||||
};
|
|
@@ -4,7 +4,7 @@ import { FrontendLocaleData } from "../../data/translation";
|
|||||||
import { formatDate } from "../datetime/format_date";
|
import { formatDate } from "../datetime/format_date";
|
||||||
import { formatDateTime } from "../datetime/format_date_time";
|
import { formatDateTime } from "../datetime/format_date_time";
|
||||||
import { formatTime } from "../datetime/format_time";
|
import { formatTime } from "../datetime/format_time";
|
||||||
import { formatNumber } from "../number/format_number";
|
import { formatNumber } from "../string/format_number";
|
||||||
import { LocalizeFunc } from "../translations/localize";
|
import { LocalizeFunc } from "../translations/localize";
|
||||||
import { computeStateDomain } from "./compute_state_domain";
|
import { computeStateDomain } from "./compute_state_domain";
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ import { HassEntity } from "home-assistant-js-websocket";
|
|||||||
* Optionally pass in a state to influence the domain icon.
|
* Optionally pass in a state to influence the domain icon.
|
||||||
*/
|
*/
|
||||||
import { DEFAULT_DOMAIN_ICON, FIXED_DOMAIN_ICONS } from "../const";
|
import { DEFAULT_DOMAIN_ICON, FIXED_DOMAIN_ICONS } from "../const";
|
||||||
import { alarmPanelIcon } from "./alarm_panel_icon";
|
|
||||||
import { binarySensorIcon } from "./binary_sensor_icon";
|
import { binarySensorIcon } from "./binary_sensor_icon";
|
||||||
import { coverIcon } from "./cover_icon";
|
import { coverIcon } from "./cover_icon";
|
||||||
import { sensorIcon } from "./sensor_icon";
|
import { sensorIcon } from "./sensor_icon";
|
||||||
@@ -19,7 +18,18 @@ export const domainIcon = (
|
|||||||
|
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
case "alarm_control_panel":
|
case "alarm_control_panel":
|
||||||
return alarmPanelIcon(compareState);
|
switch (compareState) {
|
||||||
|
case "armed_home":
|
||||||
|
return "hass:bell-plus";
|
||||||
|
case "armed_night":
|
||||||
|
return "hass:bell-sleep";
|
||||||
|
case "disarmed":
|
||||||
|
return "hass:bell-outline";
|
||||||
|
case "triggered":
|
||||||
|
return "hass:bell-ring";
|
||||||
|
default:
|
||||||
|
return "hass:bell";
|
||||||
|
}
|
||||||
|
|
||||||
case "binary_sensor":
|
case "binary_sensor":
|
||||||
return binarySensorIcon(compareState, stateObj);
|
return binarySensorIcon(compareState, stateObj);
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
export const capitalizeFirstLetter = (str: string) =>
|
|
||||||
str.charAt(0).toUpperCase() + str.slice(1);
|
|
@@ -180,10 +180,10 @@ export function fuzzyScore(
|
|||||||
wordLow
|
wordLow
|
||||||
);
|
);
|
||||||
|
|
||||||
let row: number;
|
let row = 1;
|
||||||
let column = 1;
|
let column = 1;
|
||||||
let patternPos: number;
|
let patternPos = patternStart;
|
||||||
let wordPos: number;
|
let wordPos = wordStart;
|
||||||
|
|
||||||
const hasStrongFirstMatch = [false];
|
const hasStrongFirstMatch = [false];
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { FrontendLocaleData, NumberFormat } from "../../data/translation";
|
import { FrontendLocaleData, NumberFormat } from "../../data/translation";
|
||||||
import { round } from "./round";
|
import { round } from "../number/round";
|
||||||
|
|
||||||
export const numberFormatToLocale = (
|
export const numberFormatToLocale = (
|
||||||
localeOptions: FrontendLocaleData
|
localeOptions: FrontendLocaleData
|
||||||
@@ -51,10 +51,10 @@ export const formatNumber = (
|
|||||||
locale,
|
locale,
|
||||||
getDefaultFormatOptions(num, options)
|
getDefaultFormatOptions(num, options)
|
||||||
).format(Number(num));
|
).format(Number(num));
|
||||||
} catch (err: any) {
|
} catch (error) {
|
||||||
// Don't fail when using "TEST" language
|
// Don't fail when using "TEST" language
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(err);
|
console.error(error);
|
||||||
return new Intl.NumberFormat(
|
return new Intl.NumberFormat(
|
||||||
undefined,
|
undefined,
|
||||||
getDefaultFormatOptions(num, options)
|
getDefaultFormatOptions(num, options)
|
@@ -1,10 +1,6 @@
|
|||||||
import { shouldPolyfill as shouldPolyfillLocale } from "@formatjs/intl-locale/lib/should-polyfill";
|
import { shouldPolyfill } from "@formatjs/intl-pluralrules/lib/should-polyfill";
|
||||||
import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-pluralrules/lib/should-polyfill";
|
|
||||||
import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/lib/should-polyfill";
|
|
||||||
import { shouldPolyfill as shouldPolyfillDateTime } from "@formatjs/intl-datetimeformat/lib/should-polyfill";
|
|
||||||
import IntlMessageFormat from "intl-messageformat";
|
import IntlMessageFormat from "intl-messageformat";
|
||||||
import { Resources } from "../../types";
|
import { Resources } from "../../types";
|
||||||
import { getLocalLanguage } from "../../util/common-translation";
|
|
||||||
|
|
||||||
export type LocalizeFunc = (key: string, ...args: any[]) => string;
|
export type LocalizeFunc = (key: string, ...args: any[]) => string;
|
||||||
interface FormatType {
|
interface FormatType {
|
||||||
@@ -16,32 +12,17 @@ export interface FormatsType {
|
|||||||
time: FormatType;
|
time: FormatType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadedPolyfillLocale = new Set();
|
let loadedPolyfillLocale: Set<string> | undefined;
|
||||||
|
|
||||||
const polyfills: Promise<any>[] = [];
|
let polyfillLoaded = !shouldPolyfill();
|
||||||
if (__BUILD__ === "latest") {
|
const polyfillProm = polyfillLoaded
|
||||||
if (shouldPolyfillLocale()) {
|
? undefined
|
||||||
polyfills.push(import("@formatjs/intl-locale/polyfill"));
|
: import("@formatjs/intl-locale/polyfill")
|
||||||
}
|
.then(() => import("@formatjs/intl-pluralrules/polyfill"))
|
||||||
if (shouldPolyfillPluralRules()) {
|
.then(() => {
|
||||||
polyfills.push(import("@formatjs/intl-pluralrules/polyfill"));
|
loadedPolyfillLocale = new Set();
|
||||||
polyfills.push(import("@formatjs/intl-pluralrules/locale-data/en"));
|
polyfillLoaded = true;
|
||||||
}
|
});
|
||||||
if (shouldPolyfillRelativeTime()) {
|
|
||||||
polyfills.push(import("@formatjs/intl-relativetimeformat/polyfill"));
|
|
||||||
}
|
|
||||||
if (shouldPolyfillDateTime()) {
|
|
||||||
polyfills.push(import("@formatjs/intl-datetimeformat/polyfill"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const polyfillsLoaded =
|
|
||||||
polyfills.length === 0
|
|
||||||
? undefined
|
|
||||||
: Promise.all(polyfills).then(() =>
|
|
||||||
// Load the default language
|
|
||||||
loadPolyfillLocales(getLocalLanguage())
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from Polymer app-localize-behavior.
|
* Adapted from Polymer app-localize-behavior.
|
||||||
@@ -70,11 +51,18 @@ export const computeLocalize = async (
|
|||||||
resources: Resources,
|
resources: Resources,
|
||||||
formats?: FormatsType
|
formats?: FormatsType
|
||||||
): Promise<LocalizeFunc> => {
|
): Promise<LocalizeFunc> => {
|
||||||
if (polyfillsLoaded) {
|
if (!polyfillLoaded) {
|
||||||
await polyfillsLoaded;
|
await polyfillProm;
|
||||||
}
|
}
|
||||||
|
|
||||||
await loadPolyfillLocales(language);
|
if (loadedPolyfillLocale && !loadedPolyfillLocale.has(language)) {
|
||||||
|
try {
|
||||||
|
loadedPolyfillLocale.add(language);
|
||||||
|
await import("@formatjs/intl-pluralrules/locale-data/en");
|
||||||
|
} catch (_e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Everytime any of the parameters change, invalidate the strings cache.
|
// Everytime any of the parameters change, invalidate the strings cache.
|
||||||
cache._localizationCache = {};
|
cache._localizationCache = {};
|
||||||
@@ -104,7 +92,7 @@ export const computeLocalize = async (
|
|||||||
language,
|
language,
|
||||||
formats
|
formats
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
return "Translation error: " + err.message;
|
return "Translation error: " + err.message;
|
||||||
}
|
}
|
||||||
cache._localizationCache[messageKey] = translatedMessage;
|
cache._localizationCache[messageKey] = translatedMessage;
|
||||||
@@ -121,53 +109,8 @@ export const computeLocalize = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return translatedMessage.format<string>(argObject) as string;
|
return translatedMessage.format<string>(argObject) as string;
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
return "Translation " + err;
|
return "Translation " + err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadPolyfillLocales = async (language: string) => {
|
|
||||||
if (loadedPolyfillLocale.has(language)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loadedPolyfillLocale.add(language);
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
Intl.NumberFormat &&
|
|
||||||
// @ts-ignore
|
|
||||||
typeof Intl.NumberFormat.__addLocaleData === "function"
|
|
||||||
) {
|
|
||||||
const result = await fetch(
|
|
||||||
`/static/locale-data/intl-numberformat/${language}.json`
|
|
||||||
);
|
|
||||||
// @ts-ignore
|
|
||||||
Intl.NumberFormat.__addLocaleData(await result.json());
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
// @ts-expect-error
|
|
||||||
Intl.RelativeTimeFormat &&
|
|
||||||
// @ts-ignore
|
|
||||||
typeof Intl.RelativeTimeFormat.__addLocaleData === "function"
|
|
||||||
) {
|
|
||||||
const result = await fetch(
|
|
||||||
`/static/locale-data/intl-relativetimeformat/${language}.json`
|
|
||||||
);
|
|
||||||
// @ts-ignore
|
|
||||||
Intl.RelativeTimeFormat.__addLocaleData(await result.json());
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
Intl.DateTimeFormat &&
|
|
||||||
// @ts-ignore
|
|
||||||
typeof Intl.DateTimeFormat.__addLocaleData === "function"
|
|
||||||
) {
|
|
||||||
const result = await fetch(
|
|
||||||
`/static/locale-data/intl-datetimeformat/${language}.json`
|
|
||||||
);
|
|
||||||
// @ts-ignore
|
|
||||||
Intl.DateTimeFormat.__addLocaleData(await result.json());
|
|
||||||
}
|
|
||||||
} catch (_e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@@ -25,7 +25,7 @@ export default function parseAspectRatio(input: string) {
|
|||||||
return arr.length === 1
|
return arr.length === 1
|
||||||
? { w: parseOrThrow(arr[0]), h: 1 }
|
? { w: parseOrThrow(arr[0]), h: 1 }
|
||||||
: { w: parseOrThrow(arr[0]), h: parseOrThrow(arr[1]) };
|
: { w: parseOrThrow(arr[0]), h: parseOrThrow(arr[1]) };
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
// Ignore the error
|
// Ignore the error
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -50,7 +50,7 @@ class HaCallApiButton extends LitElement {
|
|||||||
this._progressButton.actionSuccess();
|
this._progressButton.actionSuccess();
|
||||||
eventData.success = true;
|
eventData.success = true;
|
||||||
eventData.response = resp;
|
eventData.response = resp;
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
this.progress = false;
|
this.progress = false;
|
||||||
this._progressButton.actionError();
|
this._progressButton.actionError();
|
||||||
eventData.success = false;
|
eventData.success = false;
|
||||||
|
@@ -86,7 +86,6 @@ export default class HaChartBase extends LitElement {
|
|||||||
class=${classMap({
|
class=${classMap({
|
||||||
hidden: this._hiddenDatasets.has(index),
|
hidden: this._hiddenDatasets.has(index),
|
||||||
})}
|
})}
|
||||||
.title=${dataset.label}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="bullet"
|
class="bullet"
|
||||||
|
@@ -5,7 +5,7 @@ import { getColorByIndex } from "../../common/color/colors";
|
|||||||
import {
|
import {
|
||||||
formatNumber,
|
formatNumber,
|
||||||
numberFormatToLocale,
|
numberFormatToLocale,
|
||||||
} from "../../common/number/format_number";
|
} from "../../common/string/format_number";
|
||||||
import { LineChartEntity, LineChartState } from "../../data/history";
|
import { LineChartEntity, LineChartState } from "../../data/history";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "./ha-chart-base";
|
import "./ha-chart-base";
|
||||||
|
@@ -5,7 +5,7 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { getColorByIndex } from "../../common/color/colors";
|
import { getColorByIndex } from "../../common/color/colors";
|
||||||
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { numberFormatToLocale } from "../../common/number/format_number";
|
import { numberFormatToLocale } from "../../common/string/format_number";
|
||||||
import { computeRTL } from "../../common/util/compute_rtl";
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
import { TimelineEntity } from "../../data/history";
|
import { TimelineEntity } from "../../data/history";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
@@ -21,7 +21,6 @@ const BINARY_SENSOR_DEVICE_CLASS_COLOR_INVERTED = new Set([
|
|||||||
"garage_door",
|
"garage_door",
|
||||||
"gas",
|
"gas",
|
||||||
"lock",
|
"lock",
|
||||||
"motion",
|
|
||||||
"opening",
|
"opening",
|
||||||
"problem",
|
"problem",
|
||||||
"safety",
|
"safety",
|
||||||
@@ -56,11 +55,7 @@ const getColor = (
|
|||||||
entityState: HassEntity,
|
entityState: HassEntity,
|
||||||
computedStyles: CSSStyleDeclaration
|
computedStyles: CSSStyleDeclaration
|
||||||
) => {
|
) => {
|
||||||
// Inversion is only valid for "on" or "off" state
|
if (invertOnOff(entityState)) {
|
||||||
if (
|
|
||||||
(stateString === "on" || stateString === "off") &&
|
|
||||||
invertOnOff(entityState)
|
|
||||||
) {
|
|
||||||
stateString = stateString === "on" ? "off" : "on";
|
stateString = stateString === "on" ? "off" : "on";
|
||||||
}
|
}
|
||||||
if (stateColorMap.has(stateString)) {
|
if (stateColorMap.has(stateString)) {
|
||||||
|
@@ -19,7 +19,7 @@ import { computeStateName } from "../../common/entity/compute_state_name";
|
|||||||
import {
|
import {
|
||||||
formatNumber,
|
formatNumber,
|
||||||
numberFormatToLocale,
|
numberFormatToLocale,
|
||||||
} from "../../common/number/format_number";
|
} from "../../common/string/format_number";
|
||||||
import {
|
import {
|
||||||
getStatisticIds,
|
getStatisticIds,
|
||||||
Statistics,
|
Statistics,
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { Layout1d, scroll } from "@lit-labs/virtualizer";
|
import { Layout1d, scroll } from "@lit-labs/virtualizer";
|
||||||
import { mdiArrowDown, mdiArrowUp } from "@mdi/js";
|
|
||||||
import deepClone from "deep-clone-simple";
|
import deepClone from "deep-clone-simple";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@@ -28,7 +27,7 @@ import { nextRender } from "../../common/util/render-status";
|
|||||||
import { haStyleScrollbar } from "../../resources/styles";
|
import { haStyleScrollbar } from "../../resources/styles";
|
||||||
import "../ha-checkbox";
|
import "../ha-checkbox";
|
||||||
import type { HaCheckbox } from "../ha-checkbox";
|
import type { HaCheckbox } from "../ha-checkbox";
|
||||||
import "../ha-svg-icon";
|
import "../ha-icon";
|
||||||
import { filterData, sortData } from "./sort-filter";
|
import { filterData, sortData } from "./sort-filter";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -312,11 +311,11 @@ export class HaDataTable extends LitElement {
|
|||||||
>
|
>
|
||||||
${column.sortable
|
${column.sortable
|
||||||
? html`
|
? html`
|
||||||
<ha-svg-icon
|
<ha-icon
|
||||||
.path=${sorted && this._sortDirection === "desc"
|
.icon=${sorted && this._sortDirection === "desc"
|
||||||
? mdiArrowDown
|
? "hass:arrow-down"
|
||||||
: mdiArrowUp}
|
: "hass:arrow-up"}
|
||||||
></ha-svg-icon>
|
></ha-icon>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
<span>${column.title}</span>
|
<span>${column.title}</span>
|
||||||
@@ -551,7 +550,7 @@ export class HaDataTable extends LitElement {
|
|||||||
|
|
||||||
private _handleRowClick(ev: Event) {
|
private _handleRowClick(ev: Event) {
|
||||||
const target = ev.target as HTMLElement;
|
const target = ev.target as HTMLElement;
|
||||||
if (["HA-CHECKBOX", "MWC-BUTTON"].includes(target.tagName)) {
|
if (target.tagName === "HA-CHECKBOX") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rowId = (ev.currentTarget as any).rowId;
|
const rowId = (ev.currentTarget as any).rowId;
|
||||||
@@ -864,14 +863,14 @@ export class HaDataTable extends LitElement {
|
|||||||
:host([dir="rtl"]) .mdc-data-table__header-cell > * {
|
:host([dir="rtl"]) .mdc-data-table__header-cell > * {
|
||||||
transition: right 0.2s ease;
|
transition: right 0.2s ease;
|
||||||
}
|
}
|
||||||
.mdc-data-table__header-cell ha-svg-icon {
|
.mdc-data-table__header-cell ha-icon {
|
||||||
top: -3px;
|
top: -3px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
.mdc-data-table__header-cell.not-sorted ha-svg-icon {
|
.mdc-data-table__header-cell.not-sorted ha-icon {
|
||||||
left: -20px;
|
left: -20px;
|
||||||
}
|
}
|
||||||
:host([dir="rtl"]) .mdc-data-table__header-cell.not-sorted ha-svg-icon {
|
:host([dir="rtl"]) .mdc-data-table__header-cell.not-sorted ha-icon {
|
||||||
right: -20px;
|
right: -20px;
|
||||||
}
|
}
|
||||||
.mdc-data-table__header-cell.sortable:not(.not-sorted) span,
|
.mdc-data-table__header-cell.sortable:not(.not-sorted) span,
|
||||||
@@ -887,16 +886,16 @@ export class HaDataTable extends LitElement {
|
|||||||
left: auto;
|
left: auto;
|
||||||
right: 24px;
|
right: 24px;
|
||||||
}
|
}
|
||||||
.mdc-data-table__header-cell.sortable:not(.not-sorted) ha-svg-icon,
|
.mdc-data-table__header-cell.sortable:not(.not-sorted) ha-icon,
|
||||||
.mdc-data-table__header-cell.sortable:hover.not-sorted ha-svg-icon {
|
.mdc-data-table__header-cell.sortable:hover.not-sorted ha-icon {
|
||||||
left: 12px;
|
left: 12px;
|
||||||
}
|
}
|
||||||
:host([dir="rtl"])
|
:host([dir="rtl"])
|
||||||
.mdc-data-table__header-cell.sortable:not(.not-sorted)
|
.mdc-data-table__header-cell.sortable:not(.not-sorted)
|
||||||
ha-svg-icon,
|
ha-icon,
|
||||||
:host([dir="rtl"])
|
:host([dir="rtl"])
|
||||||
.mdc-data-table__header-cell.sortable:hover.not-sorted
|
.mdc-data-table__header-cell.sortable:hover.not-sorted
|
||||||
ha-svg-icon {
|
ha-icon {
|
||||||
left: auto;
|
left: auto;
|
||||||
right: 12px;
|
right: 12px;
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,6 @@ interface AreaDevices {
|
|||||||
devices: string[];
|
devices: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<AreaDevices> = (item) => html`<style>
|
const rowRenderer: ComboBoxLitRenderer<AreaDevices> = (item) => html`<style>
|
||||||
paper-item {
|
paper-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@@ -46,7 +46,6 @@ export type HaDevicePickerDeviceFilterFunc = (
|
|||||||
device: DeviceRegistryEntry
|
device: DeviceRegistryEntry
|
||||||
) => boolean;
|
) => boolean;
|
||||||
|
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<Device> = (item) => html`<style>
|
const rowRenderer: ComboBoxLitRenderer<Device> = (item) => html`<style>
|
||||||
paper-item {
|
paper-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@@ -15,7 +15,7 @@ const haTabFixBehaviorImpl = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// paper-dialog that uses the haTabFixBehaviorImpl behavior
|
// paper-dialog that uses the haTabFixBehaviorImpl behvaior
|
||||||
// export class HaPaperDialog extends paperDialogClass {}
|
// export class HaPaperDialog extends paperDialogClass {}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export class HaPaperDialog
|
export class HaPaperDialog
|
||||||
|
@@ -23,7 +23,6 @@ import "./state-badge";
|
|||||||
|
|
||||||
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||||
|
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<string> = (item) => html`<style>
|
const rowRenderer: ComboBoxLitRenderer<string> = (item) => html`<style>
|
||||||
paper-item {
|
paper-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@@ -26,7 +26,6 @@ import "./state-badge";
|
|||||||
|
|
||||||
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||||
|
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<HassEntity> = (item) => html`<style>
|
const rowRenderer: ComboBoxLitRenderer<HassEntity> = (item) => html`<style>
|
||||||
paper-icon-item {
|
paper-icon-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import { mdiAlert } from "@mdi/js";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@@ -14,13 +13,13 @@ import secondsToDuration from "../../common/datetime/seconds_to_duration";
|
|||||||
import { computeStateDisplay } from "../../common/entity/compute_state_display";
|
import { computeStateDisplay } from "../../common/entity/compute_state_display";
|
||||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { domainIcon } from "../../common/entity/domain_icon";
|
||||||
import { stateIcon } from "../../common/entity/state_icon";
|
import { stateIcon } from "../../common/entity/state_icon";
|
||||||
import { formatNumber } from "../../common/number/format_number";
|
|
||||||
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
|
|
||||||
import { timerTimeRemaining } from "../../data/timer";
|
import { timerTimeRemaining } from "../../data/timer";
|
||||||
|
import { formatNumber } from "../../common/string/format_number";
|
||||||
|
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "../ha-label-badge";
|
import "../ha-label-badge";
|
||||||
import "../ha-icon";
|
|
||||||
|
|
||||||
@customElement("ha-state-label-badge")
|
@customElement("ha-state-label-badge")
|
||||||
export class HaStateLabelBadge extends LitElement {
|
export class HaStateLabelBadge extends LitElement {
|
||||||
@@ -59,49 +58,41 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
class="warning"
|
class="warning"
|
||||||
label=${this.hass!.localize("state_badge.default.error")}
|
label="${this.hass!.localize("state_badge.default.error")}"
|
||||||
description=${this.hass!.localize(
|
icon="hass:alert"
|
||||||
|
description="${this.hass!.localize(
|
||||||
"state_badge.default.entity_not_found"
|
"state_badge.default.entity_not_found"
|
||||||
)}
|
)}"
|
||||||
>
|
></ha-label-badge>
|
||||||
<ha-svg-icon .path=${mdiAlert}></ha-svg-icon>
|
|
||||||
</ha-label-badge>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const domain = computeStateDomain(entityState);
|
const domain = computeStateDomain(entityState);
|
||||||
|
|
||||||
const value = this._computeValue(domain, entityState);
|
|
||||||
const icon = this.icon ? this.icon : this._computeIcon(domain, entityState);
|
|
||||||
const image = this.icon
|
|
||||||
? ""
|
|
||||||
: this.image
|
|
||||||
? this.image
|
|
||||||
: entityState.attributes.entity_picture_local ||
|
|
||||||
entityState.attributes.entity_picture;
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-label-badge
|
<ha-label-badge
|
||||||
class=${classMap({
|
class="${classMap({
|
||||||
[domain]: true,
|
[domain]: true,
|
||||||
"has-unit_of_measurement":
|
"has-unit_of_measurement":
|
||||||
"unit_of_measurement" in entityState.attributes,
|
"unit_of_measurement" in entityState.attributes,
|
||||||
})}
|
})}"
|
||||||
.image=${image}
|
.value="${this._computeValue(domain, entityState)}"
|
||||||
.label=${this._computeLabel(
|
.icon="${this.icon
|
||||||
|
? this.icon
|
||||||
|
: this._computeIcon(domain, entityState)}"
|
||||||
|
.image="${this.icon
|
||||||
|
? ""
|
||||||
|
: this.image
|
||||||
|
? this.image
|
||||||
|
: entityState.attributes.entity_picture_local ||
|
||||||
|
entityState.attributes.entity_picture}"
|
||||||
|
.label="${this._computeLabel(
|
||||||
domain,
|
domain,
|
||||||
entityState,
|
entityState,
|
||||||
this._timerTimeRemaining
|
this._timerTimeRemaining
|
||||||
)}
|
)}"
|
||||||
.description=${this.name ?? computeStateName(entityState)}
|
.description="${this.name ? this.name : computeStateName(entityState)}"
|
||||||
>
|
></ha-label-badge>
|
||||||
${!image && icon ? html`<ha-icon .icon=${icon}></ha-icon>` : ""}
|
|
||||||
${value && (this.icon || !this.image)
|
|
||||||
? html`<span class=${value && value.length > 4 ? "big" : ""}
|
|
||||||
>${value}</span
|
|
||||||
>`
|
|
||||||
: ""}
|
|
||||||
</ha-label-badge>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +141,26 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
}
|
}
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
case "alarm_control_panel":
|
case "alarm_control_panel":
|
||||||
|
if (entityState.state === "pending") {
|
||||||
|
return "hass:clock-fast";
|
||||||
|
}
|
||||||
|
if (entityState.state === "armed_away") {
|
||||||
|
return "hass:nature";
|
||||||
|
}
|
||||||
|
if (entityState.state === "armed_home") {
|
||||||
|
return "hass:home-variant";
|
||||||
|
}
|
||||||
|
if (entityState.state === "armed_night") {
|
||||||
|
return "hass:weather-night";
|
||||||
|
}
|
||||||
|
if (entityState.state === "armed_custom_bypass") {
|
||||||
|
return "hass:shield-home";
|
||||||
|
}
|
||||||
|
if (entityState.state === "triggered") {
|
||||||
|
return "hass:alert-circle";
|
||||||
|
}
|
||||||
|
// state == 'disarmed'
|
||||||
|
return domainIcon(domain, entityState);
|
||||||
case "binary_sensor":
|
case "binary_sensor":
|
||||||
case "device_tracker":
|
case "device_tracker":
|
||||||
case "updater":
|
case "updater":
|
||||||
@@ -220,9 +231,7 @@ export class HaStateLabelBadge extends LitElement {
|
|||||||
:host {
|
:host {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.big {
|
|
||||||
font-size: 70%;
|
|
||||||
}
|
|
||||||
ha-label-badge {
|
ha-label-badge {
|
||||||
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
||||||
}
|
}
|
||||||
|
@@ -51,14 +51,6 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
@property({ type: Array, attribute: "include-unit-of-measurement" })
|
@property({ type: Array, attribute: "include-unit-of-measurement" })
|
||||||
public includeUnitOfMeasurement?: string[];
|
public includeUnitOfMeasurement?: string[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Show only statistics with these device classes.
|
|
||||||
* @type {Array}
|
|
||||||
* @attr include-device-classes
|
|
||||||
*/
|
|
||||||
@property({ type: Array, attribute: "include-device-classes" })
|
|
||||||
public includeDeviceClasses?: string[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show only statistics on entities.
|
* Show only statistics on entities.
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
@@ -77,7 +69,6 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
state?: HassEntity;
|
state?: HassEntity;
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
}> = (item) => html`<style>
|
}> = (item) => html`<style>
|
||||||
paper-icon-item {
|
paper-icon-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -111,7 +102,7 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
? html`<a
|
? html`<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
href=${documentationUrl(this.hass, "/more-info/statistics/")}
|
href="${documentationUrl(this.hass, "/more-info/statistics/")}"
|
||||||
>${this.hass.localize(
|
>${this.hass.localize(
|
||||||
"ui.components.statistic-picker.learn_more"
|
"ui.components.statistic-picker.learn_more"
|
||||||
)}</a
|
)}</a
|
||||||
@@ -125,7 +116,6 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
(
|
(
|
||||||
statisticIds: StatisticsMetaData[],
|
statisticIds: StatisticsMetaData[],
|
||||||
includeUnitOfMeasurement?: string[],
|
includeUnitOfMeasurement?: string[],
|
||||||
includeDeviceClasses?: string[],
|
|
||||||
entitiesOnly?: boolean
|
entitiesOnly?: boolean
|
||||||
): Array<{ id: string; name: string; state?: HassEntity }> => {
|
): Array<{ id: string; name: string; state?: HassEntity }> => {
|
||||||
if (!statisticIds.length) {
|
if (!statisticIds.length) {
|
||||||
@@ -158,18 +148,11 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (
|
output.push({
|
||||||
!includeDeviceClasses ||
|
id: meta.statistic_id,
|
||||||
includeDeviceClasses.includes(
|
name: computeStateName(entityState),
|
||||||
entityState!.attributes.device_class || ""
|
state: entityState,
|
||||||
)
|
});
|
||||||
) {
|
|
||||||
output.push({
|
|
||||||
id: meta.statistic_id,
|
|
||||||
name: computeStateName(entityState),
|
|
||||||
state: entityState,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!output.length) {
|
if (!output.length) {
|
||||||
@@ -220,7 +203,6 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
(this.comboBox as any).items = this._getStatistics(
|
(this.comboBox as any).items = this._getStatistics(
|
||||||
this.statisticIds!,
|
this.statisticIds!,
|
||||||
this.includeUnitOfMeasurement,
|
this.includeUnitOfMeasurement,
|
||||||
this.includeDeviceClasses,
|
|
||||||
this.entitiesOnly
|
this.entitiesOnly
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -228,7 +210,6 @@ export class HaStatisticPicker extends LitElement {
|
|||||||
(this.comboBox as any).items = this._getStatistics(
|
(this.comboBox as any).items = this._getStatistics(
|
||||||
this.statisticIds!,
|
this.statisticIds!,
|
||||||
this.includeUnitOfMeasurement,
|
this.includeUnitOfMeasurement,
|
||||||
this.includeDeviceClasses,
|
|
||||||
this.entitiesOnly
|
this.entitiesOnly
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@@ -24,15 +24,13 @@ class StateInfo extends LitElement {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = computeStateName(this.stateObj);
|
|
||||||
|
|
||||||
return html`<state-badge
|
return html`<state-badge
|
||||||
.stateObj=${this.stateObj}
|
.stateObj=${this.stateObj}
|
||||||
.stateColor=${true}
|
.stateColor=${true}
|
||||||
></state-badge>
|
></state-badge>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="name" .title=${name} .inDialog=${this.inDialog}>
|
<div class="name" .inDialog=${this.inDialog}>
|
||||||
${name}
|
${computeStateName(this.stateObj)}
|
||||||
</div>
|
</div>
|
||||||
${this.inDialog
|
${this.inDialog
|
||||||
? html`<div class="time-ago">
|
? html`<div class="time-ago">
|
||||||
@@ -40,7 +38,6 @@ class StateInfo extends LitElement {
|
|||||||
id="last_changed"
|
id="last_changed"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.datetime=${this.stateObj.last_changed}
|
.datetime=${this.stateObj.last_changed}
|
||||||
capitalize
|
|
||||||
></ha-relative-time>
|
></ha-relative-time>
|
||||||
<paper-tooltip animation-delay="0" for="last_changed">
|
<paper-tooltip animation-delay="0" for="last_changed">
|
||||||
<div>
|
<div>
|
||||||
@@ -95,6 +92,7 @@ class StateInfo extends LitElement {
|
|||||||
state-badge {
|
state-badge {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([rtl]) state-badge {
|
:host([rtl]) state-badge {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,6 @@ import { PolymerChangedEvent } from "../polymer-types";
|
|||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { HaComboBox } from "./ha-combo-box";
|
import { HaComboBox } from "./ha-combo-box";
|
||||||
|
|
||||||
// eslint-disable-next-line lit/prefer-static-styles
|
|
||||||
const rowRenderer: ComboBoxLitRenderer<HassioAddonInfo> = (item) => html`<style>
|
const rowRenderer: ComboBoxLitRenderer<HassioAddonInfo> = (item) => html`<style>
|
||||||
paper-item {
|
paper-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -110,7 +109,7 @@ class HaAddonPicker extends LitElement {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (error) {
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.hass.localize(
|
title: this.hass.localize(
|
||||||
"ui.componencts.addon-picker.error.fetch_addons.title"
|
"ui.componencts.addon-picker.error.fetch_addons.title"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user