Compare commits
1 Commits
20200518.0
...
add-import
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f995d8d525 |
@@ -69,7 +69,7 @@
|
||||
"import/extensions": [
|
||||
2,
|
||||
"ignorePackages",
|
||||
{ "ts": "never", "js": "never" }
|
||||
{ "ts": "ignorePackages", "js": "ignorePackages" }
|
||||
],
|
||||
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
|
||||
"object-curly-newline": 0,
|
||||
|
@@ -24,6 +24,7 @@ const options = ({ latestBuild }) => ({
|
||||
],
|
||||
});
|
||||
|
||||
module.exports.options = options;
|
||||
module.exports.babelLoaderConfig = ({ latestBuild }) => {
|
||||
if (latestBuild === undefined) {
|
||||
throw Error("latestBuild not defined for babel loader config");
|
||||
|
@@ -20,7 +20,7 @@ gulp.task(
|
||||
},
|
||||
"clean",
|
||||
gulp.parallel(
|
||||
"gen-service-worker-app-dev",
|
||||
"gen-service-worker-dev",
|
||||
"gen-icons-json",
|
||||
"gen-pages-dev",
|
||||
"gen-index-app-dev",
|
||||
@@ -46,7 +46,7 @@ gulp.task(
|
||||
gulp.parallel(
|
||||
"gen-pages-prod",
|
||||
"gen-index-app-prod",
|
||||
"gen-service-worker-app-prod"
|
||||
"gen-service-worker-prod"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@@ -9,30 +9,25 @@ const paths = require("../paths");
|
||||
gulp.task("compress-app", function compressApp() {
|
||||
const jsLatest = gulp
|
||||
.src(path.resolve(paths.output, "**/*.js"))
|
||||
.pipe(zopfli({ threshold: 150 }))
|
||||
.pipe(zopfli())
|
||||
.pipe(gulp.dest(paths.output));
|
||||
|
||||
const jsEs5 = gulp
|
||||
.src(path.resolve(paths.output_es5, "**/*.js"))
|
||||
.pipe(zopfli({ threshold: 150 }))
|
||||
.pipe(zopfli())
|
||||
.pipe(gulp.dest(paths.output_es5));
|
||||
|
||||
const polyfills = gulp
|
||||
.src(path.resolve(paths.static, "polyfills/*.js"))
|
||||
.pipe(zopfli({ threshold: 150 }))
|
||||
.pipe(zopfli())
|
||||
.pipe(gulp.dest(path.resolve(paths.static, "polyfills")));
|
||||
|
||||
const translations = gulp
|
||||
.src(path.resolve(paths.static, "translations/**/*.json"))
|
||||
.pipe(zopfli({ threshold: 150 }))
|
||||
.src(path.resolve(paths.static, "translations/*.json"))
|
||||
.pipe(zopfli())
|
||||
.pipe(gulp.dest(path.resolve(paths.static, "translations")));
|
||||
|
||||
const icons = gulp
|
||||
.src(path.resolve(paths.static, "mdi/*.json"))
|
||||
.pipe(zopfli({ threshold: 150 }))
|
||||
.pipe(gulp.dest(path.resolve(paths.static, "mdi")));
|
||||
|
||||
return merge(jsLatest, jsEs5, polyfills, translations, icons);
|
||||
return merge(jsLatest, jsEs5, polyfills, translations);
|
||||
});
|
||||
|
||||
gulp.task("compress-hassio", function compressApp() {
|
||||
|
@@ -1,14 +1,9 @@
|
||||
const del = require("del");
|
||||
const gulp = require("gulp");
|
||||
const fs = require("fs");
|
||||
const mapStream = require("map-stream");
|
||||
|
||||
const inDirFrontend = "translations/frontend";
|
||||
const inDirBackend = "translations/backend";
|
||||
const downloadDir = "translations/downloads";
|
||||
const srcMeta = "src/translations/translationMetadata.json";
|
||||
|
||||
const encoding = "utf8";
|
||||
const inDir = "translations/frontend";
|
||||
const downloadDir = inDir + "/downloads";
|
||||
|
||||
const tasks = [];
|
||||
|
||||
@@ -58,25 +53,9 @@ gulp.task(taskName, function () {
|
||||
});
|
||||
tasks.push(taskName);
|
||||
|
||||
taskName = "check-all-files-exist";
|
||||
gulp.task(taskName, function () {
|
||||
const file = fs.readFileSync(srcMeta, { encoding });
|
||||
const meta = JSON.parse(file);
|
||||
Object.keys(meta).forEach((lang) => {
|
||||
if (!fs.existsSync(`${inDirFrontend}/${lang}.json`)) {
|
||||
fs.writeFileSync(`${inDirFrontend}/${lang}.json`, JSON.stringify({}));
|
||||
}
|
||||
if (!fs.existsSync(`${inDirBackend}/${lang}.json`)) {
|
||||
fs.writeFileSync(`${inDirBackend}/${lang}.json`, JSON.stringify({}));
|
||||
}
|
||||
});
|
||||
return Promise.resolve();
|
||||
});
|
||||
tasks.push(taskName);
|
||||
|
||||
taskName = "move-downloaded-translations";
|
||||
gulp.task(taskName, function () {
|
||||
return gulp.src(`${downloadDir}/*.json`).pipe(gulp.dest(inDirFrontend));
|
||||
return gulp.src(`${downloadDir}/*.json`).pipe(gulp.dest(inDir));
|
||||
});
|
||||
tasks.push(taskName);
|
||||
|
||||
@@ -86,7 +65,6 @@ gulp.task(
|
||||
gulp.series(
|
||||
"check-translations-html",
|
||||
"move-downloaded-translations",
|
||||
"check-all-files-exist",
|
||||
"clean-downloaded-translations"
|
||||
)
|
||||
);
|
||||
|
@@ -5,22 +5,18 @@
|
||||
const gulp = require("gulp");
|
||||
const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const workboxBuild = require("workbox-build");
|
||||
const sourceMapUrl = require("source-map-url");
|
||||
const paths = require("../paths.js");
|
||||
const config = require("../paths.js");
|
||||
|
||||
const swDest = path.resolve(paths.root, "service_worker.js");
|
||||
const swPath = path.resolve(config.root, "service_worker.js");
|
||||
|
||||
const writeSW = (content) => fs.outputFileSync(swDest, content.trim() + "\n");
|
||||
const writeSW = (content) => fs.outputFileSync(swPath, content.trim() + "\n");
|
||||
|
||||
gulp.task("gen-service-worker-app-dev", (done) => {
|
||||
gulp.task("gen-service-worker-dev", (done) => {
|
||||
writeSW(
|
||||
`
|
||||
console.debug('Service worker disabled in development');
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
// This will activate the dev service worker,
|
||||
// removing any prod service worker the dev might have running
|
||||
self.skipWaiting();
|
||||
});
|
||||
`
|
||||
@@ -28,63 +24,10 @@ self.addEventListener('install', (event) => {
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task("gen-service-worker-app-prod", async () => {
|
||||
// Read bundled source file
|
||||
const bundleManifestLatest = require(path.resolve(
|
||||
paths.output,
|
||||
"manifest.json"
|
||||
));
|
||||
let serviceWorkerContent = fs.readFileSync(
|
||||
paths.root + bundleManifestLatest["service_worker.js"],
|
||||
"utf-8"
|
||||
gulp.task("gen-service-worker-prod", (done) => {
|
||||
fs.copySync(
|
||||
path.resolve(config.output, "service_worker.js"),
|
||||
path.resolve(config.root, "service_worker.js")
|
||||
);
|
||||
|
||||
// Delete old file from frontend_latest so manifest won't pick it up
|
||||
fs.removeSync(paths.root + bundleManifestLatest["service_worker.js"]);
|
||||
fs.removeSync(paths.root + bundleManifestLatest["service_worker.js.map"]);
|
||||
|
||||
// Remove ES5
|
||||
const bundleManifestES5 = require(path.resolve(
|
||||
paths.output_es5,
|
||||
"manifest.json"
|
||||
));
|
||||
fs.removeSync(paths.root + bundleManifestES5["service_worker.js"]);
|
||||
fs.removeSync(paths.root + bundleManifestES5["service_worker.js.map"]);
|
||||
|
||||
const workboxManifest = await workboxBuild.getManifest({
|
||||
// Files that mach this pattern will be considered unique and skip revision check
|
||||
// ignore JS files + translation files
|
||||
dontCacheBustURLsMatching: /(frontend_latest\/.+|static\/translations\/.+)/,
|
||||
|
||||
globDirectory: paths.root,
|
||||
globPatterns: [
|
||||
"frontend_latest/*.js",
|
||||
// Cache all English translations because we catch them as fallback
|
||||
// Using pattern to match hash instead of * to avoid caching en-GB
|
||||
// 'v' added as valid hash letter because in dev we hash with 'dev'
|
||||
"static/translations/**/en-+([a-fv0-9]).json",
|
||||
// Icon shown on splash screen
|
||||
"static/icons/favicon-192x192.png",
|
||||
"static/icons/favicon.ico",
|
||||
// Common fonts
|
||||
"static/fonts/roboto/Roboto-Light.woff2",
|
||||
"static/fonts/roboto/Roboto-Medium.woff2",
|
||||
"static/fonts/roboto/Roboto-Regular.woff2",
|
||||
"static/fonts/roboto/Roboto-Bold.woff2",
|
||||
],
|
||||
});
|
||||
|
||||
for (const warning of workboxManifest.warnings) {
|
||||
console.warn(warning);
|
||||
}
|
||||
|
||||
// remove source map and add WB manifest
|
||||
serviceWorkerContent = sourceMapUrl.removeFrom(serviceWorkerContent);
|
||||
serviceWorkerContent = serviceWorkerContent.replace(
|
||||
"WB_MANIFEST",
|
||||
JSON.stringify(workboxManifest.manifestEntries)
|
||||
);
|
||||
|
||||
// Write new file to root
|
||||
fs.writeFileSync(swDest, serviceWorkerContent);
|
||||
done();
|
||||
});
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const webpack = require("webpack");
|
||||
const path = require("path");
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const WorkboxPlugin = require("workbox-webpack-plugin");
|
||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||
const WorkerPlugin = require("worker-plugin");
|
||||
const paths = require("./paths.js");
|
||||
const env = require("./env.js");
|
||||
const { babelLoaderConfig } = require("./babel.js");
|
||||
@@ -21,9 +21,7 @@ const createWebpackConfig = ({
|
||||
}
|
||||
return {
|
||||
mode: isProdBuild ? "production" : "development",
|
||||
devtool: isProdBuild
|
||||
? "cheap-module-source-map"
|
||||
: "eval-cheap-module-source-map",
|
||||
devtool: isProdBuild ? "source-map" : "inline-cheap-module-source-map",
|
||||
entry,
|
||||
module: {
|
||||
rules: [
|
||||
@@ -52,7 +50,6 @@ const createWebpackConfig = ({
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new WorkerPlugin(),
|
||||
new ManifestPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
__DEV__: !isProdBuild,
|
||||
@@ -78,10 +75,6 @@ const createWebpackConfig = ({
|
||||
/@polymer\/font-roboto\/roboto\.js$/,
|
||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||
),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/@vaadin\/vaadin-material-styles\/font-roboto\.js$/,
|
||||
path.resolve(paths.polymer_dir, "src/util/empty.js")
|
||||
),
|
||||
// Ignore mwc icons pointing at CDN.
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/@material\/mwc-icon\/mwc-icon-font\.js$/,
|
||||
@@ -107,16 +100,15 @@ const createWebpackConfig = ({
|
||||
latestBuild ? "frontend_latest" : "frontend_es5"
|
||||
),
|
||||
publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/",
|
||||
// To silence warning in worker plugin
|
||||
// For workerize loader
|
||||
globalObject: "self",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||
return createWebpackConfig({
|
||||
const config = createWebpackConfig({
|
||||
entry: {
|
||||
service_worker: "./src/entrypoints/service_worker.ts",
|
||||
app: "./src/entrypoints/app.ts",
|
||||
authorize: "./src/entrypoints/authorize.ts",
|
||||
onboarding: "./src/entrypoints/onboarding.ts",
|
||||
@@ -129,6 +121,48 @@ const createAppConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||
latestBuild,
|
||||
isStatsBuild,
|
||||
});
|
||||
|
||||
if (latestBuild) {
|
||||
// Create an object mapping browser urls to their paths during build
|
||||
const translationMetadata = require("../build-translations/translationMetadata.json");
|
||||
const workBoxTranslationsTemplatedURLs = {};
|
||||
const englishFilename = `en-${translationMetadata.translations.en.hash}.json`;
|
||||
|
||||
// core
|
||||
workBoxTranslationsTemplatedURLs[
|
||||
`/static/translations/${englishFilename}`
|
||||
] = `build-translations/output/${englishFilename}`;
|
||||
|
||||
translationMetadata.fragments.forEach((fragment) => {
|
||||
workBoxTranslationsTemplatedURLs[
|
||||
`/static/translations/${fragment}/${englishFilename}`
|
||||
] = `build-translations/output/${fragment}/${englishFilename}`;
|
||||
});
|
||||
|
||||
config.plugins.push(
|
||||
new WorkboxPlugin.InjectManifest({
|
||||
swSrc: "./src/entrypoints/service-worker-hass.js",
|
||||
swDest: "service_worker.js",
|
||||
importWorkboxFrom: "local",
|
||||
include: [/\.js$/],
|
||||
templatedURLs: {
|
||||
...workBoxTranslationsTemplatedURLs,
|
||||
"/static/icons/favicon-192x192.png":
|
||||
"public/icons/favicon-192x192.png",
|
||||
"/static/fonts/roboto/Roboto-Light.woff2":
|
||||
"node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2",
|
||||
"/static/fonts/roboto/Roboto-Medium.woff2":
|
||||
"node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2",
|
||||
"/static/fonts/roboto/Roboto-Regular.woff2":
|
||||
"node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2",
|
||||
"/static/fonts/roboto/Roboto-Bold.woff2":
|
||||
"node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2",
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) => {
|
||||
|
@@ -184,7 +184,7 @@ export class HcConnect extends LitElement {
|
||||
this.castManager = null;
|
||||
}
|
||||
);
|
||||
registerServiceWorker(this, false);
|
||||
registerServiceWorker(false);
|
||||
}
|
||||
|
||||
private async _handleDemo() {
|
||||
|
@@ -7,5 +7,5 @@ set -e
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
STATS=1 NODE_ENV=production ../node_modules/.bin/webpack --profile --json > compilation-stats.json
|
||||
npx webpack-bundle-analyzer compilation-stats.json dist/frontend_latest
|
||||
npx webpack-bundle-analyzer compilation-stats.json dist
|
||||
rm compilation-stats.json
|
||||
|
@@ -63,7 +63,7 @@ export const demoLovelaceTeachingbirds: DemoConfig["lovelace"] = () => ({
|
||||
elements: [
|
||||
{
|
||||
style: {
|
||||
"--mdc-icon-size": "100%",
|
||||
"--mdc-icon-size": "100px",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
},
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
import memoizeOne from "memoize-one";
|
||||
import { atLeastVersion } from "../../../src/common/config/version";
|
||||
import { navigate } from "../../../src/common/navigate";
|
||||
import "../../../src/components/ha-card";
|
||||
import {
|
||||
HassioAddonInfo,
|
||||
HassioAddonRepository,
|
||||
@@ -67,7 +66,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
<div class="card-group">
|
||||
${addons.map(
|
||||
(addon) => html`
|
||||
<ha-card
|
||||
<paper-card
|
||||
.addon=${addon}
|
||||
class=${addon.available ? "" : "not_available"}
|
||||
@click=${this._addonTapped}
|
||||
@@ -79,8 +78,8 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
.description=${addon.description}
|
||||
.available=${addon.available}
|
||||
.icon=${addon.installed && addon.installed !== addon.version
|
||||
? mdiArrowUpBoldCircle
|
||||
: mdiPuzzle}
|
||||
? "hassio:arrow-up-bold-circle"
|
||||
: "hassio:puzzle"}
|
||||
.iconTitle=${addon.installed
|
||||
? addon.installed !== addon.version
|
||||
? "New version available"
|
||||
@@ -112,7 +111,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
: ""}
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
@@ -128,7 +127,7 @@ class HassioAddonRepositoryEl extends LitElement {
|
||||
return [
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
.not_available {
|
||||
|
@@ -1,6 +1,3 @@
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { mdiDotsVertical } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -9,22 +6,23 @@ import {
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { html, TemplateResult } from "lit-html";
|
||||
import "../../../src/common/search/search-input";
|
||||
import "../../../src/components/ha-button-menu";
|
||||
import "../../../src/components/ha-svg-icon";
|
||||
import {
|
||||
fetchHassioAddonsInfo,
|
||||
HassioAddonInfo,
|
||||
HassioAddonRepository,
|
||||
reloadHassioAddons,
|
||||
} from "../../../src/data/hassio/addon";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import "../../../src/components/ha-icon-button";
|
||||
import "../../../src/layouts/loading-screen";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import { showRepositoriesDialog } from "../dialogs/repositories/show-dialog-repositories";
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
import "../../../src/common/search/search-input";
|
||||
import "./hassio-addon-repository";
|
||||
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
|
||||
import { showRepositoriesDialog } from "../dialogs/repositories/show-dialog-repositories";
|
||||
|
||||
const sortRepos = (a: HassioAddonRepository, b: HassioAddonRepository) => {
|
||||
if (a.slug === "local") {
|
||||
return -1;
|
||||
@@ -96,17 +94,27 @@ class HassioAddonStore extends LitElement {
|
||||
.tabs=${supervisorTabs}
|
||||
>
|
||||
<span slot="header">Add-on store</span>
|
||||
<ha-button-menu corner="BOTTOM_START" slot="toolbar-icon">
|
||||
<mwc-icon-button slot="trigger" alt="menu">
|
||||
<ha-svg-icon path=${mdiDotsVertical}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-list-item @tap=${this._manageRepositories}>
|
||||
Repositories
|
||||
</mwc-list-item>
|
||||
<mwc-list-item @tap=${this.refreshData}>
|
||||
Reload
|
||||
</mwc-list-item>
|
||||
</ha-button-menu>
|
||||
<paper-menu-button
|
||||
close-on-activate
|
||||
no-animations
|
||||
horizontal-align="right"
|
||||
horizontal-offset="-5"
|
||||
slot="toolbar-icon"
|
||||
>
|
||||
<ha-icon-button
|
||||
icon="hassio:dots-vertical"
|
||||
slot="dropdown-trigger"
|
||||
alt="menu"
|
||||
></ha-icon-button>
|
||||
<paper-listbox slot="dropdown-content" role="listbox">
|
||||
<paper-item @tap=${this._manageRepositories}>
|
||||
Repositories
|
||||
</paper-item>
|
||||
<paper-item @tap=${this.refreshData}>
|
||||
Reload
|
||||
</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-menu-button>
|
||||
${repos.length === 0
|
||||
? html`<loading-screen></loading-screen>`
|
||||
: html`
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "web-animations-js/web-animations-next-lite.min";
|
||||
import "../../../../src/components/ha-card";
|
||||
import {
|
||||
HassioAddonDetails,
|
||||
HassioAddonSetOptionParams,
|
||||
@@ -23,9 +23,9 @@ import {
|
||||
fetchHassioHardwareAudio,
|
||||
HassioHardwareAudioDevice,
|
||||
} from "../../../../src/data/hassio/hardware";
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
|
||||
@customElement("hassio-addon-audio")
|
||||
@@ -46,7 +46,7 @@ class HassioAddonAudio extends LitElement {
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-card header="Audio">
|
||||
<paper-card heading="Audio">
|
||||
<div class="card-content">
|
||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||
|
||||
@@ -92,7 +92,7 @@ class HassioAddonAudio extends LitElement {
|
||||
<div class="card-actions">
|
||||
<mwc-button @click=${this._saveSettings}>Save</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ class HassioAddonAudio extends LitElement {
|
||||
hassioStyle,
|
||||
css`
|
||||
:host,
|
||||
ha-card,
|
||||
paper-card,
|
||||
paper-dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
@@ -8,10 +8,12 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import "./hassio-addon-audio";
|
||||
import "./hassio-addon-config";
|
||||
import "./hassio-addon-network";
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -12,7 +13,6 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "../../../../src/components/ha-yaml-editor";
|
||||
import {
|
||||
@@ -23,9 +23,10 @@ import {
|
||||
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import type { HomeAssistant } from "../../../../src/types";
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
|
||||
@customElement("hassio-addon-config")
|
||||
class HassioAddonConfig extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -45,7 +46,7 @@ class HassioAddonConfig extends LitElement {
|
||||
|
||||
return html`
|
||||
<h1>${this.addon.name}</h1>
|
||||
<ha-card header="Configuration">
|
||||
<paper-card heading="Configuration">
|
||||
<div class="card-content">
|
||||
<ha-yaml-editor
|
||||
@value-changed=${this._configChanged}
|
||||
@@ -64,7 +65,7 @@ class HassioAddonConfig extends LitElement {
|
||||
Save
|
||||
</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ class HassioAddonConfig extends LitElement {
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
ha-card {
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.card-actions {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import {
|
||||
css,
|
||||
@@ -10,15 +11,15 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import "../../../../src/components/ha-card";
|
||||
import {
|
||||
HassioAddonDetails,
|
||||
HassioAddonSetOptionParams,
|
||||
setHassioAddonOption,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
|
||||
interface NetworkItem {
|
||||
@@ -52,7 +53,7 @@ class HassioAddonNetwork extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-card header="Network">
|
||||
<paper-card heading="Network">
|
||||
<div class="card-content">
|
||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||
|
||||
@@ -89,7 +90,7 @@ class HassioAddonNetwork extends LitElement {
|
||||
</mwc-button>
|
||||
<mwc-button @click=${this._saveTapped}>Save</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -101,7 +102,7 @@ class HassioAddonNetwork extends LitElement {
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
ha-card {
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -8,15 +9,16 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "../../../../src/components/ha-markdown";
|
||||
import {
|
||||
fetchHassioAddonDocumentation,
|
||||
HassioAddonDetails,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
import "../../../../src/layouts/loading-screen";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import {
|
||||
HassioAddonDetails,
|
||||
fetchHassioAddonDocumentation,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
import "../../../../src/components/ha-markdown";
|
||||
import "../../../../src/layouts/loading-screen";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
@customElement("hassio-addon-documentation-tab")
|
||||
class HassioAddonDocumentationDashboard extends LitElement {
|
||||
@@ -39,14 +41,14 @@ class HassioAddonDocumentationDashboard extends LitElement {
|
||||
}
|
||||
return html`
|
||||
<div class="content">
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||
<div class="card-content">
|
||||
${this._content
|
||||
? html`<ha-markdown .content=${this._content}></ha-markdown>`
|
||||
: html`<loading-screen></loading-screen>`}
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -56,7 +58,7 @@ class HassioAddonDocumentationDashboard extends LitElement {
|
||||
haStyle,
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.content {
|
||||
|
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
mdiCogs,
|
||||
mdiFileDocument,
|
||||
mdiInformationVariant,
|
||||
mdiMathLog,
|
||||
} from "@mdi/js";
|
||||
import "../../../src/components/ha-icon-button";
|
||||
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||
import {
|
||||
css,
|
||||
@@ -19,17 +14,18 @@ import {
|
||||
fetchHassioAddonInfo,
|
||||
HassioAddonDetails,
|
||||
} from "../../../src/data/hassio/addon";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import "./config/hassio-addon-audio";
|
||||
import "./config/hassio-addon-config";
|
||||
import "./config/hassio-addon-network";
|
||||
import "./hassio-addon-router";
|
||||
import "./info/hassio-addon-info";
|
||||
import "./log/hassio-addon-logs";
|
||||
import "./config/hassio-addon-network";
|
||||
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
|
||||
import "./hassio-addon-router";
|
||||
|
||||
@customElement("hassio-addon-dashboard")
|
||||
class HassioAddonDashboard extends LitElement {
|
||||
@@ -63,7 +59,7 @@ class HassioAddonDashboard extends LitElement {
|
||||
{
|
||||
name: "Info",
|
||||
path: `/hassio/addon/${this.addon.slug}/info`,
|
||||
iconPath: mdiInformationVariant,
|
||||
icon: "hassio:information-variant",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -71,7 +67,7 @@ class HassioAddonDashboard extends LitElement {
|
||||
addonTabs.push({
|
||||
name: "Documentation",
|
||||
path: `/hassio/addon/${this.addon.slug}/documentation`,
|
||||
iconPath: mdiFileDocument,
|
||||
icon: "hassio:file-document",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -80,12 +76,12 @@ class HassioAddonDashboard extends LitElement {
|
||||
{
|
||||
name: "Configuration",
|
||||
path: `/hassio/addon/${this.addon.slug}/config`,
|
||||
iconPath: mdiCogs,
|
||||
icon: "hassio:cogs",
|
||||
},
|
||||
{
|
||||
name: "Log",
|
||||
path: `/hassio/addon/${this.addon.slug}/logs`,
|
||||
iconPath: mdiMathLog,
|
||||
icon: "hassio:math-log",
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -119,6 +115,7 @@ class HassioAddonDashboard extends LitElement {
|
||||
css`
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
--paper-card-header-color: var(--primary-text-color);
|
||||
}
|
||||
.content {
|
||||
padding: 24px 0 32px;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import { customElement, property } from "lit-element";
|
||||
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
||||
import {
|
||||
HassRouterPage,
|
||||
RouterOptions,
|
||||
} from "../../../src/layouts/hass-router-page";
|
||||
import { customElement, property } from "lit-element";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import "./config/hassio-addon-config-tab";
|
||||
import "./documentation/hassio-addon-documentation-tab";
|
||||
// Don't codesplit the others, because it breaks the UI when pushed to a Pi
|
||||
import "./info/hassio-addon-info-tab";
|
||||
import "./config/hassio-addon-config-tab";
|
||||
import "./log/hassio-addon-log-tab";
|
||||
import "./documentation/hassio-addon-documentation-tab";
|
||||
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
|
||||
|
||||
@customElement("hassio-addon-router")
|
||||
class HassioAddonRouter extends HassRouterPage {
|
||||
|
@@ -8,10 +8,12 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import "./hassio-addon-info";
|
||||
|
||||
@customElement("hassio-addon-info-tab")
|
||||
|
@@ -1,20 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import {
|
||||
mdiArrowUpBoldCircle,
|
||||
mdiCheckCircle,
|
||||
mdiChip,
|
||||
mdiCircle,
|
||||
mdiCursorDefaultClickOutline,
|
||||
mdiDocker,
|
||||
mdiExclamationThick,
|
||||
mdiFlask,
|
||||
mdiHomeAssistant,
|
||||
mdiInformation,
|
||||
mdiKey,
|
||||
mdiNetwork,
|
||||
mdiPound,
|
||||
mdiShield,
|
||||
} from "@mdi/js";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
import {
|
||||
css,
|
||||
@@ -31,11 +16,10 @@ import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import { navigate } from "../../../../src/common/navigate";
|
||||
import "../../../../src/components/buttons/ha-call-api-button";
|
||||
import "../../../../src/components/buttons/ha-progress-button";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-label-badge";
|
||||
import "../../../../src/components/ha-markdown";
|
||||
import "../../../../src/components/ha-svg-icon";
|
||||
import "../../../../src/components/ha-switch";
|
||||
import "../../../../src/components/ha-icon";
|
||||
import {
|
||||
fetchHassioAddonChangelog,
|
||||
HassioAddonDetails,
|
||||
@@ -46,23 +30,23 @@ import {
|
||||
setHassioAddonSecurity,
|
||||
uninstallHassioAddon,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import "../../components/hassio-card-content";
|
||||
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
|
||||
|
||||
const STAGE_ICON = {
|
||||
stable: mdiCheckCircle,
|
||||
experimental: mdiFlask,
|
||||
deprecated: mdiExclamationThick,
|
||||
stable: "mdi:check-circle",
|
||||
experimental: "mdi:flask",
|
||||
deprecated: "mdi:exclamation-thick",
|
||||
};
|
||||
|
||||
const PERMIS_DESC = {
|
||||
stage: {
|
||||
title: "Add-on Stage",
|
||||
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon path='${STAGE_ICON.stable}'></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon path='${STAGE_ICON.experimental}'></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon path='${STAGE_ICON.deprecated}'></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
|
||||
description: `Add-ons can have one of three stages:\n\n<ha-icon icon='${STAGE_ICON.stable}'></ha-icon>**Stable**: These are add-ons ready to be used in production.\n<ha-icon icon='${STAGE_ICON.experimental}'></ha-icon>**Experimental**: These may contain bugs, and may be unfinished.\n<ha-icon icon='${STAGE_ICON.deprecated}'></ha-icon>**Deprecated**: These add-ons will no longer receive any updates.`,
|
||||
},
|
||||
rating: {
|
||||
title: "Add-on Security Rating",
|
||||
@@ -132,7 +116,7 @@ class HassioAddonInfo extends LitElement {
|
||||
return html`
|
||||
${this._computeUpdateAvailable
|
||||
? html`
|
||||
<ha-card header="Update available! 🎉">
|
||||
<paper-card heading="Update available! 🎉">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
.hass=${this.hass}
|
||||
@@ -140,7 +124,7 @@ class HassioAddonInfo extends LitElement {
|
||||
.version_latest} is available"
|
||||
.description="You are currently running version ${this.addon
|
||||
.version}"
|
||||
icon=${mdiArrowUpBoldCircle}
|
||||
icon="hassio:arrow-up-bold-circle"
|
||||
iconClass="update"
|
||||
></hassio-card-content>
|
||||
${!this.addon.available
|
||||
@@ -167,13 +151,12 @@ class HassioAddonInfo extends LitElement {
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
: ""}
|
||||
${!this.addon.protected
|
||||
? html`
|
||||
<ha-card class="warning">
|
||||
<div class="card-header">Warning: Protection mode is disabled!</div>
|
||||
<paper-card heading="Warning: Protection mode is disabled!" class="warning">
|
||||
<div class="card-content">
|
||||
Protection mode on this add-on is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this add-on.
|
||||
</div>
|
||||
@@ -181,11 +164,11 @@ class HassioAddonInfo extends LitElement {
|
||||
<mwc-button @click=${this._protectionToggled}>Enable Protection mode</mwc-button>
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<div class="addon-header">
|
||||
${!this.narrow ? this.addon.name : ""}
|
||||
@@ -194,18 +177,18 @@ class HassioAddonInfo extends LitElement {
|
||||
? html`
|
||||
${this._computeIsRunning
|
||||
? html`
|
||||
<ha-svg-icon
|
||||
<ha-icon
|
||||
title="Add-on is running"
|
||||
class="running"
|
||||
path=${mdiCircle}
|
||||
></ha-svg-icon>
|
||||
icon="hassio:circle"
|
||||
></ha-icon>
|
||||
`
|
||||
: html`
|
||||
<ha-svg-icon
|
||||
<ha-icon
|
||||
title="Add-on is stopped"
|
||||
class="stopped"
|
||||
path=${mdiCircle}
|
||||
></ha-svg-icon>
|
||||
icon="hassio:circle"
|
||||
></ha-icon>
|
||||
`}
|
||||
`
|
||||
: html` ${this.addon.version_latest} `}
|
||||
@@ -249,11 +232,10 @@ class HassioAddonInfo extends LitElement {
|
||||
})}
|
||||
@click=${this._showMoreInfo}
|
||||
id="stage"
|
||||
.icon=${STAGE_ICON[this.addon.stage]}
|
||||
label="stage"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon .path=${STAGE_ICON[this.addon.stage]}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
<ha-label-badge
|
||||
class=${classMap({
|
||||
green: [5, 6].includes(Number(this.addon.rating)),
|
||||
@@ -271,11 +253,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="host_network"
|
||||
icon="hassio:network"
|
||||
label="host"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiNetwork}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.full_access
|
||||
@@ -283,11 +264,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="full_access"
|
||||
icon="hassio:chip"
|
||||
label="hardware"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiChip}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.homeassistant_api
|
||||
@@ -295,11 +275,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="homeassistant_api"
|
||||
icon="hassio:home-assistant"
|
||||
label="hass"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiHomeAssistant}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this._computeHassioApi
|
||||
@@ -307,11 +286,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="hassio_api"
|
||||
icon="hassio:home-assistant"
|
||||
label="hassio"
|
||||
.description=${this.addon.hassio_role}
|
||||
>
|
||||
<ha-svg-icon path=${mdiHomeAssistant}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.docker_api
|
||||
@@ -319,11 +297,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="docker_api"
|
||||
icon="hassio:docker"
|
||||
label="docker"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiDocker}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.host_pid
|
||||
@@ -331,11 +308,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="host_pid"
|
||||
icon="hassio:pound"
|
||||
label="host pid"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiPound}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.apparmor
|
||||
@@ -344,11 +320,10 @@ class HassioAddonInfo extends LitElement {
|
||||
@click=${this._showMoreInfo}
|
||||
class=${this._computeApparmorClassName}
|
||||
id="apparmor"
|
||||
icon="hassio:shield"
|
||||
label="apparmor"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiShield}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.auth_api
|
||||
@@ -356,11 +331,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="auth_api"
|
||||
icon="hassio:key"
|
||||
label="auth"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon path=${mdiKey}></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
${this.addon.ingress
|
||||
@@ -368,13 +342,10 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-label-badge
|
||||
@click=${this._showMoreInfo}
|
||||
id="ingress"
|
||||
icon="hassio:cursor-default-click-outline"
|
||||
label="ingress"
|
||||
description=""
|
||||
>
|
||||
<ha-svg-icon
|
||||
path=${mdiCursorDefaultClickOutline}
|
||||
></ha-svg-icon>
|
||||
</ha-label-badge>
|
||||
></ha-label-badge>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
@@ -428,7 +399,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<div>
|
||||
Protection mode
|
||||
<span>
|
||||
<ha-svg-icon path=${mdiInformation}></ha-svg-icon>
|
||||
<ha-icon icon="hassio:information"></ha-icon>
|
||||
<paper-tooltip>
|
||||
Grant the add-on elevated system access.
|
||||
</paper-tooltip>
|
||||
@@ -531,17 +502,17 @@ class HassioAddonInfo extends LitElement {
|
||||
</ha-progress-button>
|
||||
`}
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
|
||||
${this.addon.long_description
|
||||
? html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<ha-markdown
|
||||
.content=${this.addon.long_description}
|
||||
></ha-markdown>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
@@ -555,21 +526,16 @@ class HassioAddonInfo extends LitElement {
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
ha-card {
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
ha-card.warning {
|
||||
paper-card.warning {
|
||||
background-color: var(--google-red-500);
|
||||
color: white;
|
||||
--paper-card-header-color: white;
|
||||
}
|
||||
ha-card.warning .card-header {
|
||||
color: white;
|
||||
}
|
||||
ha-card.warning .card-content {
|
||||
color: white;
|
||||
}
|
||||
ha-card.warning mwc-button {
|
||||
paper-card.warning mwc-button {
|
||||
--mdc-theme-primary: white !important;
|
||||
}
|
||||
.warning {
|
||||
@@ -582,7 +548,7 @@ class HassioAddonInfo extends LitElement {
|
||||
.addon-header {
|
||||
padding-left: 8px;
|
||||
font-size: 24px;
|
||||
color: var(--ha-card-header-color, --primary-text-color);
|
||||
color: var(--paper-card-header-color, --primary-text-color);
|
||||
}
|
||||
.addon-version {
|
||||
float: right;
|
||||
@@ -609,7 +575,7 @@ class HassioAddonInfo extends LitElement {
|
||||
width: 180px;
|
||||
display: inline-block;
|
||||
}
|
||||
.state ha-svg-icon {
|
||||
.state ha-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--secondary-text-color);
|
||||
@@ -617,10 +583,10 @@ class HassioAddonInfo extends LitElement {
|
||||
ha-switch {
|
||||
display: flex;
|
||||
}
|
||||
ha-svg-icon.running {
|
||||
ha-icon.running {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
ha-svg-icon.stopped {
|
||||
ha-icon.stopped {
|
||||
color: var(--google-red-300);
|
||||
}
|
||||
ha-call-api-button {
|
||||
@@ -698,7 +664,7 @@ class HassioAddonInfo extends LitElement {
|
||||
}
|
||||
|
||||
private _showMoreInfo(ev): void {
|
||||
const id = ev.currentTarget.id;
|
||||
const id = ev.target.getAttribute("id");
|
||||
showHassioMarkdownDialog(this, {
|
||||
title: PERMIS_DESC[id].title,
|
||||
content: PERMIS_DESC[id].description,
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -8,10 +9,12 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
|
||||
import "./hassio-addon-logs";
|
||||
|
||||
@customElement("hassio-addon-log-tab")
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -8,7 +9,6 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "../../../../src/components/ha-card";
|
||||
import {
|
||||
fetchHassioAddonLogs,
|
||||
HassioAddonDetails,
|
||||
@@ -36,7 +36,7 @@ class HassioAddonLogs extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<h1>${this.addon.name}</h1>
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||
<div class="card-content">
|
||||
${this._content
|
||||
@@ -48,7 +48,7 @@ class HassioAddonLogs extends LitElement {
|
||||
<div class="card-actions">
|
||||
<mwc-button @click=${this._refresh}>Refresh</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class HassioAddonLogs extends LitElement {
|
||||
hassioStyle,
|
||||
css`
|
||||
:host,
|
||||
ha-card {
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import { mdiHelpCircle } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -9,7 +8,7 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "../../../src/components/ha-relative-time";
|
||||
import "../../../src/components/ha-svg-icon";
|
||||
import "../../../src/components/ha-icon";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
|
||||
@customElement("hassio-card-content")
|
||||
@@ -32,7 +31,7 @@ class HassioCardContent extends LitElement {
|
||||
|
||||
@property() public iconClass?: string;
|
||||
|
||||
@property() public icon = mdiHelpCircle;
|
||||
@property() public icon = "hass:help-circle";
|
||||
|
||||
@property() public iconImage?: string;
|
||||
|
||||
@@ -49,11 +48,11 @@ class HassioCardContent extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
<ha-svg-icon
|
||||
<ha-icon
|
||||
class=${this.iconClass}
|
||||
.path=${this.icon}
|
||||
.icon=${this.icon}
|
||||
.title=${this.iconTitle}
|
||||
></ha-svg-icon>
|
||||
></ha-icon>
|
||||
`}
|
||||
<div>
|
||||
<div class="title">
|
||||
@@ -79,25 +78,25 @@ class HassioCardContent extends LitElement {
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-svg-icon {
|
||||
ha-icon {
|
||||
margin-right: 24px;
|
||||
margin-left: 8px;
|
||||
margin-top: 12px;
|
||||
float: left;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
ha-svg-icon.update {
|
||||
ha-icon.update {
|
||||
color: var(--paper-orange-400);
|
||||
}
|
||||
ha-svg-icon.running,
|
||||
ha-svg-icon.installed {
|
||||
ha-icon.running,
|
||||
ha-icon.installed {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
ha-svg-icon.hassupdate,
|
||||
ha-svg-icon.snapshot {
|
||||
ha-icon.hassupdate,
|
||||
ha-icon.snapshot {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
ha-svg-icon.not_available {
|
||||
ha-icon.not_available {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.title {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
} from "lit-element";
|
||||
import { atLeastVersion } from "../../../src/common/config/version";
|
||||
import { navigate } from "../../../src/common/navigate";
|
||||
import "../../../src/components/ha-card";
|
||||
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
@@ -30,19 +29,19 @@ class HassioAddons extends LitElement {
|
||||
<div class="card-group">
|
||||
${!this.addons
|
||||
? html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
You don't have any add-ons installed yet. Head over to
|
||||
<a href="#" @click=${this._openStore}>the add-on store</a>
|
||||
to get started!
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
: this.addons
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1))
|
||||
.map(
|
||||
(addon) => html`
|
||||
<ha-card .addon=${addon} @click=${this._addonTapped}>
|
||||
<paper-card .addon=${addon} @click=${this._addonTapped}>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
.hass=${this.hass}
|
||||
@@ -52,8 +51,8 @@ class HassioAddons extends LitElement {
|
||||
.showTopbar=${addon.installed !== addon.version}
|
||||
topbarClass="update"
|
||||
.icon=${addon.installed !== addon.version
|
||||
? mdiArrowUpBoldCircle
|
||||
: mdiPuzzle}
|
||||
? "hassio:arrow-up-bold-circle"
|
||||
: "hassio:puzzle"}
|
||||
.iconTitle=${addon.state !== "started"
|
||||
? "Add-on is stopped"
|
||||
: addon.installed !== addon.version
|
||||
@@ -76,7 +75,7 @@ class HassioAddons extends LitElement {
|
||||
: undefined}
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
@@ -89,7 +88,7 @@ class HassioAddons extends LitElement {
|
||||
haStyle,
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
`,
|
||||
|
@@ -12,13 +12,14 @@ import {
|
||||
HassioHomeAssistantInfo,
|
||||
HassioSupervisorInfo,
|
||||
} from "../../../src/data/hassio/supervisor";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import "./hassio-addons";
|
||||
import "./hassio-update";
|
||||
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
|
||||
@customElement("hassio-dashboard")
|
||||
class HassioDashboard extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import { mdiHomeAssistant } from "@mdi/js";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -10,15 +10,15 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../../../src/components/ha-card";
|
||||
import "../../../src/components/ha-svg-icon";
|
||||
import { HassioHassOSInfo } from "../../../src/data/hassio/host";
|
||||
import {
|
||||
HassioHomeAssistantInfo,
|
||||
HassioSupervisorInfo,
|
||||
} from "../../../src/data/hassio/supervisor";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import "../../../src/components/ha-icon";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import "../components/hassio-card-content";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
|
||||
@customElement("hassio-update")
|
||||
@@ -72,7 +72,7 @@ export class HassioUpdate extends LitElement {
|
||||
`https://${
|
||||
this.hassInfo.version_latest.includes("b") ? "rc" : "www"
|
||||
}.home-assistant.io/latest-release-notes/`,
|
||||
mdiHomeAssistant
|
||||
"hassio:home-assistant"
|
||||
)}
|
||||
${this._renderUpdateCard(
|
||||
"Supervisor",
|
||||
@@ -107,12 +107,12 @@ export class HassioUpdate extends LitElement {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
${icon
|
||||
? html`
|
||||
<div class="icon">
|
||||
<ha-svg-icon .path=${icon}></ha-svg-icon>
|
||||
<ha-icon .icon=${icon}></ha-icon>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
@@ -133,7 +133,7 @@ export class HassioUpdate extends LitElement {
|
||||
Update
|
||||
</ha-call-api-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,7 @@
|
||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||
import { PaperDialogElement } from "@polymer/paper-dialog";
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import "../../../../src/components/ha-icon-button";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -5,50 +9,46 @@ import {
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
||||
import "../../../../src/components/dialog/ha-paper-dialog";
|
||||
import "../../../../src/components/ha-markdown";
|
||||
import { haStyleDialog } from "../../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import { HassioMarkdownDialogParams } from "./show-dialog-hassio-markdown";
|
||||
|
||||
@customElement("dialog-hassio-markdown")
|
||||
class HassioMarkdownDialog extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public title!: string;
|
||||
|
||||
@property() public content!: string;
|
||||
|
||||
@property() private _opened = false;
|
||||
@query("#dialog") private _dialog!: PaperDialogElement;
|
||||
|
||||
public showDialog(params: HassioMarkdownDialogParams) {
|
||||
this.title = params.title;
|
||||
this.content = params.content;
|
||||
this._opened = true;
|
||||
this._dialog.open();
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._opened) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@closing=${this._closeDialog}
|
||||
.heading=${createCloseHeading(this.hass, this.title)}
|
||||
>
|
||||
<ha-markdown .content=${this.content || ""}></ha-markdown>
|
||||
</ha-dialog>
|
||||
<ha-paper-dialog id="dialog" with-backdrop="">
|
||||
<app-toolbar>
|
||||
<ha-icon-button
|
||||
icon="hassio:close"
|
||||
dialog-dismiss=""
|
||||
></ha-icon-button>
|
||||
<div main-title="">${this.title}</div>
|
||||
</app-toolbar>
|
||||
<paper-dialog-scrollable>
|
||||
<ha-markdown .content=${this.content || ""}></ha-markdown>
|
||||
</paper-dialog-scrollable>
|
||||
</ha-paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _closeDialog(): void {
|
||||
this._opened = false;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyleDialog,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import { mdiDelete } from "@mdi/js";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-spinner/paper-spinner";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-spinner/paper-spinner";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -18,14 +16,16 @@ import {
|
||||
} from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
import "../../../../src/components/ha-dialog";
|
||||
import "../../../../src/components/ha-svg-icon";
|
||||
import {
|
||||
fetchHassioAddonsInfo,
|
||||
HassioAddonRepository,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
|
||||
import "../../../../src/components/ha-icon-button";
|
||||
|
||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||
import type { HomeAssistant } from "../../../../src/types";
|
||||
import {
|
||||
HassioAddonRepository,
|
||||
fetchHassioAddonsInfo,
|
||||
} from "../../../../src/data/hassio/addon";
|
||||
|
||||
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
|
||||
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
||||
|
||||
@customElement("dialog-hassio-repositories")
|
||||
@@ -84,13 +84,12 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
<div secondary>${repo.maintainer}</div>
|
||||
<div secondary>${repo.url}</div>
|
||||
</paper-item-body>
|
||||
<mwc-icon-button
|
||||
<ha-icon-button
|
||||
.slug=${repo.slug}
|
||||
title="Remove"
|
||||
@click=${this._removeRepository}
|
||||
>
|
||||
<ha-svg-icon path=${mdiDelete}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
icon="hassio:delete"
|
||||
></ha-icon-button>
|
||||
</paper-item>
|
||||
`;
|
||||
})
|
||||
@@ -195,7 +194,7 @@ class HassioRepositoriesDialog extends LitElement {
|
||||
}
|
||||
|
||||
private async _removeRepository(ev: Event) {
|
||||
const slug = (ev.currentTarget as any).slug;
|
||||
const slug = (ev.target as any).slug;
|
||||
const repositories = this._filteredRepositories(this._repos);
|
||||
const repository = repositories.find((repo) => {
|
||||
return repo.slug === slug;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import { HassioAddonRepository } from "../../../../src/data/hassio/addon";
|
||||
import "./dialog-hassio-repositories";
|
||||
import { HassioAddonRepository } from "../../../../src/data/hassio/addon";
|
||||
|
||||
export interface HassioRepositoryDialogParams {
|
||||
repos: HassioAddonRepository[];
|
||||
|
@@ -1,6 +1,10 @@
|
||||
import "@material/mwc-button";
|
||||
import { mdiDelete, mdiDownload, mdiHistory } from "@mdi/js";
|
||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||
import { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
|
||||
import { PaperDialogElement } from "@polymer/paper-dialog";
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import "../../../../src/components/ha-icon-button";
|
||||
import "../../../../src/components/ha-icon";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import {
|
||||
css,
|
||||
@@ -9,10 +13,10 @@ import {
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
||||
import "../../../../src/components/ha-svg-icon";
|
||||
import "../../../../src/components/dialog/ha-paper-dialog";
|
||||
import { getSignedPath } from "../../../../src/data/auth";
|
||||
import {
|
||||
fetchHassioSnapshotInfo,
|
||||
@@ -72,7 +76,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
|
||||
@property() private _error?: string;
|
||||
|
||||
@property() private _snapshot?: HassioSnapshotDetail;
|
||||
@property() private snapshot?: HassioSnapshotDetail;
|
||||
|
||||
@property() private _folders!: FolderItem[];
|
||||
|
||||
@@ -84,35 +88,49 @@ class HassioSnapshotDialog extends LitElement {
|
||||
|
||||
@property() private _restoreHass: boolean | null | undefined = true;
|
||||
|
||||
@query("#dialog") private _dialog!: PaperDialogElement;
|
||||
|
||||
public async showDialog(params: HassioSnapshotDialogParams) {
|
||||
this._snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
|
||||
this.snapshot = await fetchHassioSnapshotInfo(this.hass, params.slug);
|
||||
this._folders = _computeFolders(
|
||||
this._snapshot.folders
|
||||
this.snapshot.folders
|
||||
).sort((a: FolderItem, b: FolderItem) => (a.name > b.name ? 1 : -1));
|
||||
this._addons = _computeAddons(
|
||||
this._snapshot.addons
|
||||
this.snapshot.addons
|
||||
).sort((a: AddonItem, b: AddonItem) => (a.name > b.name ? 1 : -1));
|
||||
|
||||
this._dialogParams = params;
|
||||
|
||||
try {
|
||||
this._dialog.open();
|
||||
} catch {
|
||||
await this.showDialog(params);
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._dialogParams || !this._snapshot) {
|
||||
if (!this.snapshot) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
stacked
|
||||
@closing=${this._closeDialog}
|
||||
.heading=${createCloseHeading(this.hass, this._computeName)}
|
||||
<ha-paper-dialog
|
||||
id="dialog"
|
||||
with-backdrop=""
|
||||
.on-iron-overlay-closed=${this._dialogClosed}
|
||||
>
|
||||
<app-toolbar>
|
||||
<ha-icon-button
|
||||
icon="hassio:close"
|
||||
dialog-dismiss=""
|
||||
></ha-icon-button>
|
||||
<div main-title="">${this._computeName}</div>
|
||||
</app-toolbar>
|
||||
<div class="details">
|
||||
${this._snapshot.type === "full"
|
||||
${this.snapshot.type === "full"
|
||||
? "Full snapshot"
|
||||
: "Partial snapshot"}
|
||||
(${this._computeSize})<br />
|
||||
${this._formatDatetime(this._snapshot.date)}
|
||||
${this._formatDatetime(this.snapshot.date)}
|
||||
</div>
|
||||
<div>Home Assistant:</div>
|
||||
<paper-checkbox
|
||||
@@ -121,7 +139,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
this._restoreHass = (ev.target as PaperCheckboxElement).checked;
|
||||
}}"
|
||||
>
|
||||
Home Assistant ${this._snapshot.homeassistant}
|
||||
Home Assistant ${this.snapshot.homeassistant}
|
||||
</paper-checkbox>
|
||||
${this._folders.length
|
||||
? html`
|
||||
@@ -165,7 +183,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
</paper-dialog-scrollable>
|
||||
`
|
||||
: ""}
|
||||
${this._snapshot.protected
|
||||
${this.snapshot.protected
|
||||
? html`
|
||||
<paper-input
|
||||
autofocus=""
|
||||
@@ -179,35 +197,37 @@ class HassioSnapshotDialog extends LitElement {
|
||||
${this._error ? html` <p class="error">Error: ${this._error}</p> ` : ""}
|
||||
|
||||
<div>Actions:</div>
|
||||
|
||||
<mwc-button @click=${this._downloadClicked} slot="primaryAction">
|
||||
<ha-svg-icon path=${mdiDownload} class="icon"></ha-svg-icon>
|
||||
Download Snapshot
|
||||
</mwc-button>
|
||||
|
||||
<mwc-button
|
||||
@click=${this._partialRestoreClicked}
|
||||
slot="secondaryAction"
|
||||
>
|
||||
<ha-svg-icon path=${mdiHistory} class="icon"></ha-svg-icon>
|
||||
Restore Selected
|
||||
</mwc-button>
|
||||
${this._snapshot.type === "full"
|
||||
? html`
|
||||
<mwc-button
|
||||
@click=${this._fullRestoreClicked}
|
||||
slot="secondaryAction"
|
||||
>
|
||||
<ha-svg-icon path=${mdiHistory} class="icon"></ha-svg-icon>
|
||||
Wipe & restore
|
||||
</mwc-button>
|
||||
`
|
||||
: ""}
|
||||
<mwc-button @click=${this._deleteClicked} slot="secondaryAction">
|
||||
<ha-svg-icon path=${mdiDelete} class="icon warning"></ha-svg-icon>
|
||||
<span class="warning">Delete Snapshot</span>
|
||||
</mwc-button>
|
||||
</ha-dialog>
|
||||
<ul class="buttons">
|
||||
<li>
|
||||
<mwc-button @click=${this._downloadClicked}>
|
||||
<ha-icon icon="hassio:download" class="icon"></ha-icon>
|
||||
Download Snapshot
|
||||
</mwc-button>
|
||||
</li>
|
||||
<li>
|
||||
<mwc-button @click=${this._partialRestoreClicked}>
|
||||
<ha-icon icon="hassio:history" class="icon"> </ha-icon>
|
||||
Restore Selected
|
||||
</mwc-button>
|
||||
</li>
|
||||
${this.snapshot.type === "full"
|
||||
? html`
|
||||
<li>
|
||||
<mwc-button @click=${this._fullRestoreClicked}>
|
||||
<ha-icon icon="hassio:history" class="icon"> </ha-icon>
|
||||
Wipe & restore
|
||||
</mwc-button>
|
||||
</li>
|
||||
`
|
||||
: ""}
|
||||
<li>
|
||||
<mwc-button @click=${this._deleteClicked}>
|
||||
<ha-icon icon="hassio:delete" class="icon warning"> </ha-icon>
|
||||
<span class="warning">Delete Snapshot</span>
|
||||
</mwc-button>
|
||||
</li>
|
||||
</ul>
|
||||
</ha-paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -215,10 +235,37 @@ class HassioSnapshotDialog extends LitElement {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-paper-dialog {
|
||||
min-width: 350px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
app-toolbar {
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
app-toolbar [main-title] {
|
||||
margin-left: 16px;
|
||||
}
|
||||
ha-paper-dialog-scrollable {
|
||||
margin: 0;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
}
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
ha-paper-dialog {
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
app-toolbar {
|
||||
color: var(--text-primary-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
.details {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
@@ -289,7 +336,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
folders,
|
||||
};
|
||||
|
||||
if (this._snapshot!.protected) {
|
||||
if (this.snapshot!.protected) {
|
||||
data.password = this._snapshotPassword;
|
||||
}
|
||||
|
||||
@@ -297,13 +344,13 @@ class HassioSnapshotDialog extends LitElement {
|
||||
.callApi(
|
||||
"POST",
|
||||
|
||||
`hassio/snapshots/${this._snapshot!.slug}/restore/partial`,
|
||||
`hassio/snapshots/${this.snapshot!.slug}/restore/partial`,
|
||||
data
|
||||
)
|
||||
.then(
|
||||
() => {
|
||||
alert("Snapshot restored!");
|
||||
this._closeDialog();
|
||||
this._dialog.close();
|
||||
},
|
||||
(error) => {
|
||||
this._error = error.body.message;
|
||||
@@ -316,20 +363,20 @@ class HassioSnapshotDialog extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = this._snapshot!.protected
|
||||
const data = this.snapshot!.protected
|
||||
? { password: this._snapshotPassword }
|
||||
: undefined;
|
||||
|
||||
this.hass
|
||||
.callApi(
|
||||
"POST",
|
||||
`hassio/snapshots/${this._snapshot!.slug}/restore/full`,
|
||||
`hassio/snapshots/${this.snapshot!.slug}/restore/full`,
|
||||
data
|
||||
)
|
||||
.then(
|
||||
() => {
|
||||
alert("Snapshot restored!");
|
||||
this._closeDialog();
|
||||
this._dialog.close();
|
||||
},
|
||||
(error) => {
|
||||
this._error = error.body.message;
|
||||
@@ -344,11 +391,11 @@ class HassioSnapshotDialog extends LitElement {
|
||||
|
||||
this.hass
|
||||
|
||||
.callApi("POST", `hassio/snapshots/${this._snapshot!.slug}/remove`)
|
||||
.callApi("POST", `hassio/snapshots/${this.snapshot!.slug}/remove`)
|
||||
.then(
|
||||
() => {
|
||||
this._dialog.close();
|
||||
this._dialogParams!.onDelete();
|
||||
this._closeDialog();
|
||||
},
|
||||
(error) => {
|
||||
this._error = error.body.message;
|
||||
@@ -361,7 +408,7 @@ class HassioSnapshotDialog extends LitElement {
|
||||
try {
|
||||
signedPath = await getSignedPath(
|
||||
this.hass,
|
||||
`/api/hassio/snapshots/${this._snapshot!.slug}/download`
|
||||
`/api/hassio/snapshots/${this.snapshot!.slug}/download`
|
||||
);
|
||||
} catch (err) {
|
||||
alert(`Error: ${err.message}`);
|
||||
@@ -372,19 +419,19 @@ class HassioSnapshotDialog extends LitElement {
|
||||
const a = document.createElement("a");
|
||||
a.href = signedPath.path;
|
||||
a.download = `Hass_io_${name}.tar`;
|
||||
this.shadowRoot!.appendChild(a);
|
||||
this._dialog.appendChild(a);
|
||||
a.click();
|
||||
this.shadowRoot!.removeChild(a);
|
||||
this._dialog.removeChild(a);
|
||||
}
|
||||
|
||||
private get _computeName() {
|
||||
return this._snapshot
|
||||
? this._snapshot.name || this._snapshot.slug
|
||||
return this.snapshot
|
||||
? this.snapshot.name || this.snapshot.slug
|
||||
: "Unnamed snapshot";
|
||||
}
|
||||
|
||||
private get _computeSize() {
|
||||
return Math.ceil(this._snapshot!.size * 10) / 10 + " MB";
|
||||
return Math.ceil(this.snapshot!.size * 10) / 10 + " MB";
|
||||
}
|
||||
|
||||
private _formatDatetime(datetime) {
|
||||
@@ -398,9 +445,9 @@ class HassioSnapshotDialog extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _closeDialog() {
|
||||
private _dialogClosed() {
|
||||
this._dialogParams = undefined;
|
||||
this._snapshot = undefined;
|
||||
this.snapshot = undefined;
|
||||
this._snapshotPassword = "";
|
||||
this._folders = [];
|
||||
this._addons = [];
|
||||
|
@@ -3,11 +3,11 @@ import {
|
||||
HassioAddonDetails,
|
||||
restartHassioAddon,
|
||||
} from "../../../src/data/hassio/addon";
|
||||
import {
|
||||
showAlertDialog,
|
||||
showConfirmationDialog,
|
||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
showConfirmationDialog,
|
||||
showAlertDialog,
|
||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||
|
||||
export const suggestAddonRestart = async (
|
||||
element: LitElement,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import "../../src/components/ha-icon-button";
|
||||
import { PolymerElement } from "@polymer/polymer";
|
||||
import { customElement, property, PropertyValues } from "lit-element";
|
||||
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
|
||||
@@ -33,6 +34,12 @@ import { HomeAssistant } from "../../src/types";
|
||||
// Don't codesplit it, that way the dashboard always loads fast.
|
||||
import "./hassio-panel";
|
||||
|
||||
// The register callback of the IronA11yKeysBehavior inside ha-icon-button
|
||||
// is not called, causing _keyBindings to be uninitiliazed for ha-icon-button,
|
||||
// causing an exception when added to DOM. When transpiled to ES5, this will
|
||||
// break the build.
|
||||
customElements.get("ha-icon-button").prototype._keyBindings = {};
|
||||
|
||||
@customElement("hassio-main")
|
||||
class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import { mdiBackupRestore, mdiCogs, mdiStore, mdiViewDashboard } from "@mdi/js";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
@@ -6,36 +5,37 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
|
||||
import { HassioHassOSInfo, HassioHostInfo } from "../../src/data/hassio/host";
|
||||
import {
|
||||
HassioHomeAssistantInfo,
|
||||
HassioSupervisorInfo,
|
||||
} from "../../src/data/hassio/supervisor";
|
||||
import type { PageNavigation } from "../../src/layouts/hass-tabs-subpage";
|
||||
import "../../src/resources/ha-style";
|
||||
import { HomeAssistant, Route } from "../../src/types";
|
||||
import "./hassio-panel-router";
|
||||
import type { PageNavigation } from "../../src/layouts/hass-tabs-subpage";
|
||||
|
||||
export const supervisorTabs: PageNavigation[] = [
|
||||
{
|
||||
name: "Dashboard",
|
||||
path: `/hassio/dashboard`,
|
||||
iconPath: mdiViewDashboard,
|
||||
icon: "hassio:view-dashboard",
|
||||
},
|
||||
{
|
||||
name: "Add-on store",
|
||||
path: `/hassio/store`,
|
||||
iconPath: mdiStore,
|
||||
icon: "hassio:store",
|
||||
},
|
||||
{
|
||||
name: "Snapshots",
|
||||
path: `/hassio/snapshots`,
|
||||
iconPath: mdiBackupRestore,
|
||||
icon: "hassio:backup-restore",
|
||||
},
|
||||
{
|
||||
name: "System",
|
||||
path: `/hassio/system`,
|
||||
iconPath: mdiCogs,
|
||||
icon: "hassio:cogs",
|
||||
},
|
||||
];
|
||||
|
||||
|
@@ -86,6 +86,9 @@ class HassioIngressView extends LitElement {
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
ha-icon-button {
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-icon-button";
|
||||
import { mdiPackageVariant, mdiPackageVariantClosed, mdiReload } from "@mdi/js";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "@polymer/paper-checkbox/paper-checkbox";
|
||||
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
@@ -19,8 +18,6 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||
import "../../../src/components/ha-card";
|
||||
import "../../../src/components/ha-svg-icon";
|
||||
import {
|
||||
createHassioFullSnapshot,
|
||||
createHassioPartialSnapshot,
|
||||
@@ -31,15 +28,16 @@ import {
|
||||
reloadHassioSnapshots,
|
||||
} from "../../../src/data/hassio/snapshot";
|
||||
import { HassioSupervisorInfo } from "../../../src/data/hassio/supervisor";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import { PolymerChangedEvent } from "../../../src/polymer-types";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import "../components/hassio-card-content";
|
||||
import { showHassioSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-snapshot";
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
|
||||
interface CheckboxItem {
|
||||
slug: string;
|
||||
name: string;
|
||||
@@ -100,13 +98,12 @@ class HassioSnapshots extends LitElement {
|
||||
>
|
||||
<span slot="header">Snapshots</span>
|
||||
|
||||
<mwc-icon-button
|
||||
<ha-icon-button
|
||||
icon="hassio:reload"
|
||||
slot="toolbar-icon"
|
||||
aria-label="Reload snapshots"
|
||||
@click=${this.refreshData}
|
||||
>
|
||||
<ha-svg-icon path=${mdiReload}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
></ha-icon-button>
|
||||
|
||||
<div class="content">
|
||||
<h1>
|
||||
@@ -117,7 +114,7 @@ class HassioSnapshots extends LitElement {
|
||||
Home Assistant instance.
|
||||
</p>
|
||||
<div class="card-group">
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<paper-input
|
||||
autofocus
|
||||
@@ -198,7 +195,7 @@ class HassioSnapshots extends LitElement {
|
||||
Create
|
||||
</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
</div>
|
||||
|
||||
<h1>Available snapshots</h1>
|
||||
@@ -207,15 +204,15 @@ class HassioSnapshots extends LitElement {
|
||||
? undefined
|
||||
: this._snapshots.length === 0
|
||||
? html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
You don't have any snapshots yet.
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
: this._snapshots.map(
|
||||
(snapshot) => html`
|
||||
<ha-card
|
||||
<paper-card
|
||||
class="pointer"
|
||||
.snapshot=${snapshot}
|
||||
@click=${this._snapshotClicked}
|
||||
@@ -227,12 +224,12 @@ class HassioSnapshots extends LitElement {
|
||||
.description=${this._computeDetails(snapshot)}
|
||||
.datetime=${snapshot.date}
|
||||
.icon=${snapshot.type === "full"
|
||||
? mdiPackageVariantClosed
|
||||
: mdiPackageVariant}
|
||||
? "hassio:package-variant-closed"
|
||||
: "hassio:package-variant"}
|
||||
.icon-class="snapshot"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -11,23 +12,23 @@ import {
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import { fetchHassioHardwareInfo } from "../../../src/data/hassio/hardware";
|
||||
import {
|
||||
changeHostOptions,
|
||||
fetchHassioHostInfo,
|
||||
HassioHassOSInfo,
|
||||
HassioHostInfo as HassioHostInfoType,
|
||||
rebootHost,
|
||||
shutdownHost,
|
||||
updateOS,
|
||||
changeHostOptions,
|
||||
} from "../../../src/data/hassio/host";
|
||||
import {
|
||||
showAlertDialog,
|
||||
showConfirmationDialog,
|
||||
showPromptDialog,
|
||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import {
|
||||
showConfirmationDialog,
|
||||
showAlertDialog,
|
||||
showPromptDialog,
|
||||
} from "../../../src/dialogs/generic/show-dialog-box";
|
||||
|
||||
@customElement("hassio-host-info")
|
||||
class HassioHostInfo extends LitElement {
|
||||
@@ -41,7 +42,7 @@ class HassioHostInfo extends LitElement {
|
||||
|
||||
public render(): TemplateResult | void {
|
||||
return html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Host system</h2>
|
||||
<table class="info">
|
||||
@@ -112,7 +113,7 @@ class HassioHostInfo extends LitElement {
|
||||
? html` <mwc-button @click=${this._updateOS}>Update</mwc-button> `
|
||||
: ""}
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -121,7 +122,7 @@ class HassioHostInfo extends LitElement {
|
||||
haStyle,
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -10,16 +11,15 @@ import {
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../src/common/dom/fire_event";
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../../../src/components/ha-card";
|
||||
import {
|
||||
HassioSupervisorInfo as HassioSupervisorInfoType,
|
||||
setSupervisorOption,
|
||||
SupervisorOptions,
|
||||
} from "../../../src/data/hassio/supervisor";
|
||||
import { showConfirmationDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import { showConfirmationDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
||||
|
||||
@customElement("hassio-supervisor-info")
|
||||
class HassioSupervisorInfo extends LitElement {
|
||||
@@ -31,7 +31,7 @@ class HassioSupervisorInfo extends LitElement {
|
||||
|
||||
public render(): TemplateResult | void {
|
||||
return html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Supervisor</h2>
|
||||
<table class="info">
|
||||
@@ -92,7 +92,7 @@ class HassioSupervisorInfo extends LitElement {
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ class HassioSupervisorInfo extends LitElement {
|
||||
haStyle,
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import "@material/mwc-button";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -11,13 +12,14 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "../../../src/components/ha-card";
|
||||
import { fetchHassioLogs } from "../../../src/data/hassio/supervisor";
|
||||
import "../../../src/layouts/loading-screen";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
|
||||
import { fetchHassioLogs } from "../../../src/data/hassio/supervisor";
|
||||
|
||||
import "../components/hassio-ansi-to-html";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import "../../../src/layouts/loading-screen";
|
||||
|
||||
interface LogProvider {
|
||||
key: string;
|
||||
@@ -68,7 +70,7 @@ class HassioSupervisorLog extends LitElement {
|
||||
|
||||
public render(): TemplateResult | void {
|
||||
return html`
|
||||
<ha-card>
|
||||
<paper-card>
|
||||
${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
|
||||
${this.hass.userData?.showAdvanced
|
||||
? html`
|
||||
@@ -103,7 +105,7 @@ class HassioSupervisorLog extends LitElement {
|
||||
<div class="card-actions">
|
||||
<mwc-button @click=${this._refresh}>Refresh</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@ class HassioSupervisorLog extends LitElement {
|
||||
haStyle,
|
||||
hassioStyle,
|
||||
css`
|
||||
ha-card {
|
||||
paper-card {
|
||||
width: 100%;
|
||||
}
|
||||
pre {
|
||||
|
@@ -13,15 +13,16 @@ import {
|
||||
HassioHostInfo,
|
||||
} from "../../../src/data/hassio/host";
|
||||
import { HassioSupervisorInfo } from "../../../src/data/hassio/supervisor";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import { HomeAssistant, Route } from "../../../src/types";
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
import "./hassio-host-info";
|
||||
import "./hassio-supervisor-info";
|
||||
import "./hassio-supervisor-log";
|
||||
|
||||
import { supervisorTabs } from "../hassio-panel";
|
||||
|
||||
@customElement("hassio-system")
|
||||
class HassioSystem extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
75
package.json
@@ -24,20 +24,19 @@
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@formatjs/intl-pluralrules": "^1.5.8",
|
||||
"@fullcalendar/core": "^5.0.0-beta.2",
|
||||
"@fullcalendar/daygrid": "^5.0.0-beta.2",
|
||||
"@material/chips": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/mwc-button": "^0.15.0",
|
||||
"@material/mwc-checkbox": "^0.15.0",
|
||||
"@material/mwc-dialog": "^0.15.0",
|
||||
"@material/mwc-fab": "^0.15.0",
|
||||
"@material/mwc-formfield": "^0.15.0",
|
||||
"@material/mwc-icon-button": "^0.15.0",
|
||||
"@material/mwc-list": "^0.15.0",
|
||||
"@material/mwc-menu": "^0.15.0",
|
||||
"@material/mwc-ripple": "^0.15.0",
|
||||
"@material/mwc-switch": "^0.15.0",
|
||||
"@fullcalendar/core": "5.0.0-beta.2",
|
||||
"@fullcalendar/daygrid": "5.0.0-beta.2",
|
||||
"@material/chips": "^6.0.0-canary.35a32aaea.0",
|
||||
"@material/mwc-button": "0.14.1",
|
||||
"@material/mwc-checkbox": "0.14.1",
|
||||
"@material/mwc-dialog": "0.14.1",
|
||||
"@material/mwc-fab": "0.14.1",
|
||||
"@material/mwc-formfield": "0.14.1",
|
||||
"@material/mwc-icon-button": "0.14.1",
|
||||
"@material/mwc-list": "0.14.1",
|
||||
"@material/mwc-menu": "0.14.1",
|
||||
"@material/mwc-ripple": "0.14.1",
|
||||
"@material/mwc-switch": "0.14.1",
|
||||
"@mdi/js": "4.9.95",
|
||||
"@mdi/svg": "4.9.95",
|
||||
"@polymer/app-layout": "^3.0.2",
|
||||
@@ -78,7 +77,7 @@
|
||||
"@polymer/paper-toast": "^3.0.1",
|
||||
"@polymer/paper-tooltip": "^3.0.1",
|
||||
"@polymer/polymer": "3.1.0",
|
||||
"@thomasloven/round-slider": "0.4.1",
|
||||
"@thomasloven/round-slider": "0.3.7",
|
||||
"@vaadin/vaadin-combo-box": "^5.0.10",
|
||||
"@vaadin/vaadin-date-picker": "^4.0.7",
|
||||
"@webcomponents/shadycss": "^1.9.0",
|
||||
@@ -86,7 +85,6 @@
|
||||
"chart.js": "~2.8.0",
|
||||
"chartjs-chart-timeline": "^0.3.0",
|
||||
"codemirror": "^5.49.0",
|
||||
"comlink": "^4.3.0",
|
||||
"cpx": "^1.5.0",
|
||||
"deep-clone-simple": "^1.1.1",
|
||||
"deep-freeze": "^0.0.1",
|
||||
@@ -95,21 +93,20 @@
|
||||
"fuse.js": "^3.4.4",
|
||||
"google-timezones-json": "^1.0.2",
|
||||
"hls.js": "^0.12.4",
|
||||
"home-assistant-js-websocket": "^5.1.2",
|
||||
"home-assistant-js-websocket": "5.0.0",
|
||||
"idb-keyval": "^3.2.0",
|
||||
"intl-messageformat": "^8.3.9",
|
||||
"js-yaml": "^3.13.1",
|
||||
"leaflet": "^1.4.0",
|
||||
"leaflet-draw": "^1.0.4",
|
||||
"lit-element": "^2.3.1",
|
||||
"lit-html": "^1.2.1",
|
||||
"lit-element": "^2.2.1",
|
||||
"lit-html": "^1.1.0",
|
||||
"lit-virtualizer": "^0.4.2",
|
||||
"marked": "^0.6.1",
|
||||
"mdn-polyfills": "^5.16.0",
|
||||
"memoize-one": "^5.0.2",
|
||||
"moment": "^2.24.0",
|
||||
"node-vibrant": "^3.1.5",
|
||||
"proxy-polyfill": "^0.3.1",
|
||||
"regenerator-runtime": "^0.13.2",
|
||||
"resize-observer": "^1.0.0",
|
||||
"roboto-fontface": "^0.10.0",
|
||||
@@ -117,10 +114,6 @@
|
||||
"tslib": "^1.10.0",
|
||||
"unfetch": "^4.1.0",
|
||||
"web-animations-js": "^2.3.2",
|
||||
"workbox-core": "^5.1.3",
|
||||
"workbox-precaching": "^5.1.3",
|
||||
"workbox-routing": "^5.1.3",
|
||||
"workbox-strategies": "^5.1.3",
|
||||
"xss": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -184,7 +177,6 @@
|
||||
"reify": "^0.18.1",
|
||||
"require-dir": "^1.2.0",
|
||||
"sinon": "^7.3.1",
|
||||
"source-map-url": "^0.4.0",
|
||||
"terser-webpack-plugin": "^1.2.3",
|
||||
"ts-lit-plugin": "^1.1.10",
|
||||
"ts-mocha": "^6.0.0",
|
||||
@@ -196,29 +188,28 @@
|
||||
"webpack-cli": "^3.3.9",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.0.4",
|
||||
"workbox-build": "^5.1.3",
|
||||
"worker-plugin": "^4.0.3"
|
||||
"workbox-webpack-plugin": "^4.1.1",
|
||||
"workerize-loader": "^1.1.0"
|
||||
},
|
||||
"_comment": "Polymer fixed to 3.1 because 3.2 throws on logbook page",
|
||||
"_comment_2": "Fix in https://github.com/Polymer/polymer/pull/5569",
|
||||
"resolutions": {
|
||||
"@webcomponents/webcomponentsjs": "^2.2.10",
|
||||
"@polymer/polymer": "3.1.0",
|
||||
"lit-html": "1.2.1",
|
||||
"lit-element": "2.3.1",
|
||||
"@material/animation": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/base": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/checkbox": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/density": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/dom": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/elevation": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/feature-targeting": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/ripple": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/rtl": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/shape": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/theme": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/touch-target": "7.0.0-canary.d92d8c93e.0",
|
||||
"@material/typography": "7.0.0-canary.d92d8c93e.0"
|
||||
"lit-html": "^1.1.2",
|
||||
"@material/animation": "6.0.0",
|
||||
"@material/base": "6.0.0",
|
||||
"@material/checkbox": "6.0.0",
|
||||
"@material/density": "6.0.0",
|
||||
"@material/dom": "6.0.0",
|
||||
"@material/elevation": "6.0.0",
|
||||
"@material/feature-targeting": "6.0.0",
|
||||
"@material/ripple": "6.0.0",
|
||||
"@material/rtl": "6.0.0",
|
||||
"@material/shape": "6.0.0",
|
||||
"@material/theme": "6.0.0",
|
||||
"@material/touch-target": "6.0.0",
|
||||
"@material/typography": "6.0.0"
|
||||
},
|
||||
"main": "src/home-assistant.js",
|
||||
"husky": {
|
||||
|
BIN
public/static/images/weather/cloudy.png
Normal file
After Width: | Height: | Size: 655 B |
BIN
public/static/images/weather/lightning-rainy.png
Normal file
After Width: | Height: | Size: 888 B |
BIN
public/static/images/weather/lightning.png
Normal file
After Width: | Height: | Size: 807 B |
BIN
public/static/images/weather/night.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
public/static/images/weather/partly-cloudy.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/static/images/weather/pouring.png
Normal file
After Width: | Height: | Size: 840 B |
BIN
public/static/images/weather/rainy.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
public/static/images/weather/snowy.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/static/images/weather/sunny.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
public/static/images/weather/windy.png
Normal file
After Width: | Height: | Size: 774 B |
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20200518.0",
|
||||
version="20200505.0",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
|
@@ -121,7 +121,7 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
||||
const tempA = document.createElement("a");
|
||||
tempA.href = this.redirectUri!;
|
||||
if (tempA.host === location.host) {
|
||||
registerServiceWorker(this, false);
|
||||
registerServiceWorker(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import { html, LitElement, property } from "lit-element";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import "../components/ha-icon-next";
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import "@polymer/paper-card";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import "../components/state-history-charts";
|
||||
import "../data/ha-state-history-data";
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "../../components/ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -7,11 +8,9 @@ import {
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { html, TemplateResult } from "lit-html";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import "../../components/ha-svg-icon";
|
||||
import { classMap } from "lit-html/directives/class-map.js";
|
||||
import "../../components/ha-icon";
|
||||
import { fireEvent } from "../dom/fire_event";
|
||||
import { mdiMagnify, mdiClose } from "@mdi/js";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
|
||||
@customElement("search-input")
|
||||
class SearchInput extends LitElement {
|
||||
@@ -48,22 +47,17 @@ class SearchInput extends LitElement {
|
||||
@value-changed=${this._filterInputChanged}
|
||||
.noLabelFloat=${this.noLabelFloat}
|
||||
>
|
||||
<ha-svg-icon
|
||||
path=${mdiMagnify}
|
||||
slot="prefix"
|
||||
class="prefix"
|
||||
></ha-svg-icon>
|
||||
<ha-icon icon="hass:magnify" slot="prefix" class="prefix"></ha-icon>
|
||||
${this.filter &&
|
||||
html`
|
||||
<mwc-icon-button
|
||||
<ha-icon-button
|
||||
slot="suffix"
|
||||
class="suffix"
|
||||
@click=${this._clearSearch}
|
||||
icon="hass:close"
|
||||
alt="Clear"
|
||||
title="Clear"
|
||||
>
|
||||
<ha-svg-icon path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
></ha-icon-button>
|
||||
`}
|
||||
</paper-input>
|
||||
`;
|
||||
@@ -83,14 +77,11 @@ class SearchInput extends LitElement {
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-svg-icon,
|
||||
mwc-icon-button {
|
||||
ha-icon,
|
||||
ha-icon-button {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
mwc-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
}
|
||||
ha-svg-icon.prefix {
|
||||
ha-icon {
|
||||
margin: 8px;
|
||||
}
|
||||
`;
|
||||
|
@@ -12,10 +12,6 @@ export interface FormatsType {
|
||||
time: FormatType;
|
||||
}
|
||||
|
||||
if (!Intl.PluralRules) {
|
||||
import("@formatjs/intl-pluralrules/polyfill-locales");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from Polymer app-localize-behavior.
|
||||
*
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
|
||||
import { EventsMixin } from "../../mixins/events-mixin";
|
||||
import "./ha-progress-button";
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-spinner/paper-spinner";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import "@polymer/paper-spinner/paper-spinner.js";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
|
||||
class HaProgressButton extends PolymerElement {
|
||||
static get template() {
|
||||
|
@@ -10,10 +10,13 @@ import {
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
import { classMap } from "lit-html/directives/class-map.js";
|
||||
import { ifDefined } from "lit-html/directives/if-defined.js";
|
||||
import { styleMap } from "lit-html/directives/style-map.js";
|
||||
import { scroll } from "lit-virtualizer";
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line import/no-webpack-loader-syntax
|
||||
import sortFilterWorker from "workerize-loader!./sort_filter_worker";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import "../../common/search/search-input";
|
||||
import { debounce } from "../../common/util/debounce";
|
||||
@@ -21,7 +24,6 @@ import { nextRender } from "../../common/util/render-status";
|
||||
import "../ha-checkbox";
|
||||
import type { HaCheckbox } from "../ha-checkbox";
|
||||
import "../ha-icon";
|
||||
import { filterSortData } from "./sort-filter";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
@@ -115,6 +117,8 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
private curRequest = 0;
|
||||
|
||||
private _worker: any | undefined;
|
||||
|
||||
private _debounceSearch = debounce(
|
||||
(value: string) => {
|
||||
this._filter = value;
|
||||
@@ -136,6 +140,11 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(properties: PropertyValues) {
|
||||
super.firstUpdated(properties);
|
||||
this._worker = sortFilterWorker();
|
||||
}
|
||||
|
||||
protected updated(properties: PropertyValues) {
|
||||
super.updated(properties);
|
||||
|
||||
@@ -374,7 +383,7 @@ export class HaDataTable extends LitElement {
|
||||
this.curRequest++;
|
||||
const curRequest = this.curRequest;
|
||||
|
||||
const filterProm = filterSortData(
|
||||
const filterProm = this._worker.filterSortData(
|
||||
this.data,
|
||||
this._sortColumns,
|
||||
this._filter,
|
||||
@@ -637,11 +646,6 @@ export class HaDataTable extends LitElement {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--icon-button {
|
||||
color: var(--secondary-text-color);
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.mdc-data-table__header-cell--icon-button:first-child,
|
||||
.mdc-data-table__cell--icon-button:first-child {
|
||||
width: 64px;
|
||||
@@ -655,7 +659,7 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
|
||||
.mdc-data-table__cell--icon-button a {
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.mdc-data-table__header-cell {
|
||||
|
@@ -1,26 +0,0 @@
|
||||
import { wrap } from "comlink";
|
||||
|
||||
type FilterSortDataType = typeof import("./sort_filter_worker").api["filterSortData"];
|
||||
type filterSortDataParamTypes = Parameters<FilterSortDataType>;
|
||||
|
||||
let worker: any | undefined;
|
||||
|
||||
export const filterSortData = async (
|
||||
data: filterSortDataParamTypes[0],
|
||||
columns: filterSortDataParamTypes[1],
|
||||
filter: filterSortDataParamTypes[2],
|
||||
direction: filterSortDataParamTypes[3],
|
||||
sortColumn: filterSortDataParamTypes[4]
|
||||
): Promise<ReturnType<FilterSortDataType>> => {
|
||||
if (!worker) {
|
||||
worker = wrap(new Worker("./sort_filter_worker", { type: "module" }));
|
||||
}
|
||||
|
||||
return await worker.filterSortData(
|
||||
data,
|
||||
columns,
|
||||
filter,
|
||||
direction,
|
||||
sortColumn
|
||||
);
|
||||
};
|
@@ -1,34 +1,57 @@
|
||||
// To use comlink under ES5
|
||||
import "proxy-polyfill";
|
||||
import { expose } from "comlink";
|
||||
import type {
|
||||
DataTableSortColumnData,
|
||||
import memoizeOne from "memoize-one";
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
DataTableColumnData,
|
||||
DataTableRowData,
|
||||
SortingDirection,
|
||||
HaDataTable,
|
||||
} from "./ha-data-table";
|
||||
|
||||
type SortableColumnContainer = HaDataTable["_sortColumns"];
|
||||
export const filterSortData = memoizeOne(
|
||||
async (
|
||||
data: DataTableRowData[],
|
||||
columns: DataTableColumnContainer,
|
||||
filter: string,
|
||||
direction: SortingDirection,
|
||||
sortColumn?: string
|
||||
) =>
|
||||
sortColumn
|
||||
? _memSortData(
|
||||
await _memFilterData(data, columns, filter),
|
||||
columns,
|
||||
direction,
|
||||
sortColumn
|
||||
)
|
||||
: _memFilterData(data, columns, filter)
|
||||
);
|
||||
|
||||
const filterSortData = (
|
||||
data: DataTableRowData[],
|
||||
columns: SortableColumnContainer,
|
||||
filter: string,
|
||||
direction: SortingDirection,
|
||||
sortColumn?: string
|
||||
) => {
|
||||
const filteredData = filter ? filterData(data, columns, filter) : data;
|
||||
|
||||
if (!sortColumn) {
|
||||
return filteredData;
|
||||
const _memFilterData = memoizeOne(
|
||||
async (
|
||||
data: DataTableRowData[],
|
||||
columns: DataTableColumnContainer,
|
||||
filter: string
|
||||
) => {
|
||||
if (!filter) {
|
||||
return data;
|
||||
}
|
||||
return filterData(data, columns, filter.toUpperCase());
|
||||
}
|
||||
);
|
||||
|
||||
return sortData(filteredData, columns, direction, sortColumn);
|
||||
};
|
||||
const _memSortData = memoizeOne(
|
||||
(
|
||||
data: DataTableRowData[],
|
||||
columns: DataTableColumnContainer,
|
||||
direction: SortingDirection,
|
||||
sortColumn: string
|
||||
) => {
|
||||
return sortData(data, columns[sortColumn], direction, sortColumn);
|
||||
}
|
||||
);
|
||||
|
||||
const filterData = (
|
||||
export const filterData = (
|
||||
data: DataTableRowData[],
|
||||
columns: SortableColumnContainer,
|
||||
columns: DataTableColumnContainer,
|
||||
filter: string
|
||||
) =>
|
||||
data.filter((row) => {
|
||||
@@ -47,9 +70,9 @@ const filterData = (
|
||||
});
|
||||
});
|
||||
|
||||
const sortData = (
|
||||
export const sortData = (
|
||||
data: DataTableRowData[],
|
||||
column: DataTableSortColumnData,
|
||||
column: DataTableColumnData,
|
||||
direction: SortingDirection,
|
||||
sortColumn: string
|
||||
) =>
|
||||
@@ -82,10 +105,3 @@ const sortData = (
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Export for types
|
||||
export const api = {
|
||||
filterSortData,
|
||||
};
|
||||
|
||||
expose(api);
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-button";
|
||||
import "../ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light.js";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
css,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import "../ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light.js";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
css,
|
||||
@@ -52,7 +52,7 @@ const rowRenderer = (root: HTMLElement, _owner, model: { item: Device }) => {
|
||||
}
|
||||
</style>
|
||||
<paper-item>
|
||||
<paper-item-body two-line="">
|
||||
<paper-item-body two-line="">
|
||||
<div class='name'>[[item.name]]</div>
|
||||
<div secondary>[[item.area]]</div>
|
||||
</paper-item-body>
|
||||
|
@@ -11,8 +11,8 @@ found at http://polymer.github.io/PATENTS.txt
|
||||
/*
|
||||
Fixes issue with not using shadow dom properly in iron-overlay-behavior/icon-focusables-helper.js
|
||||
*/
|
||||
import { IronFocusablesHelper } from "@polymer/iron-overlay-behavior/iron-focusables-helper";
|
||||
import { dom } from "@polymer/polymer/lib/legacy/polymer.dom";
|
||||
import { IronFocusablesHelper } from "@polymer/iron-overlay-behavior/iron-focusables-helper.js";
|
||||
import { dom } from "@polymer/polymer/lib/legacy/polymer.dom.js";
|
||||
|
||||
export const HaIronFocusablesHelper = {
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import "@polymer/paper-dialog/paper-dialog";
|
||||
import type { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
||||
import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class";
|
||||
import "@polymer/paper-dialog";
|
||||
import type { PaperDialogElement } from "@polymer/paper-dialog";
|
||||
import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class.js";
|
||||
import type { Constructor } from "../../types";
|
||||
import { HaIronFocusablesHelper } from "./ha-iron-focusables-helper";
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
/* eslint-plugin-disable lit */
|
||||
import { IronResizableBehavior } from "@polymer/iron-resizable-behavior/iron-resizable-behavior";
|
||||
import { IronResizableBehavior } from "@polymer/iron-resizable-behavior";
|
||||
import "../ha-icon-button";
|
||||
import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class";
|
||||
import { timeOut } from "@polymer/polymer/lib/utils/async";
|
||||
import { Debouncer } from "@polymer/polymer/lib/utils/debounce";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class.js";
|
||||
import { timeOut } from "@polymer/polymer/lib/utils/async.js";
|
||||
import { Debouncer } from "@polymer/polymer/lib/utils/debounce.js";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { formatTime } from "../../common/datetime/format_time";
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import "../ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-icon-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-icon-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light.js";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import {
|
||||
css,
|
||||
@@ -38,14 +38,15 @@ const rowRenderer = (
|
||||
}
|
||||
</style>
|
||||
<paper-icon-item>
|
||||
<state-badge slot="item-icon"></state-badge>
|
||||
<state-badge state-obj="[[item]]" slot="item-icon"></state-badge>
|
||||
<paper-item-body two-line="">
|
||||
<div class='name'></div>
|
||||
<div secondary></div>
|
||||
<div class='name'>[[_computeStateName(item)]]</div>
|
||||
<div secondary>[[item.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
`;
|
||||
}
|
||||
|
||||
root.querySelector("state-badge")!.stateObj = model.item;
|
||||
root.querySelector(".name")!.textContent = computeStateName(model.item);
|
||||
root.querySelector("[secondary]")!.textContent = model.item.entity_id;
|
||||
@@ -147,10 +148,6 @@ class HaEntityPicker extends LitElement {
|
||||
}
|
||||
);
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues) {
|
||||
return !(!changedProps.has("_opened") && this._opened);
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (changedProps.has("_opened") && this._opened) {
|
||||
const states = this._getStates(
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { stateIcon } from "../../common/entity/state_icon";
|
||||
import "../ha-icon";
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import {
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { classMap } from "lit-html/directives/class-map.js";
|
||||
import secondsToDuration from "../../common/datetime/seconds_to_duration";
|
||||
import { computeStateDisplay } from "../../common/entity/compute_state_display";
|
||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -7,15 +6,17 @@ import {
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { ifDefined } from "lit-html/directives/if-defined.js";
|
||||
import { computeActiveState } from "../../common/entity/compute_active_state";
|
||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||
import { stateIcon } from "../../common/entity/state_icon";
|
||||
import { iconColorCSS } from "../../common/style/icon_color_css";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../ha-icon";
|
||||
import type { HaIcon } from "../ha-icon";
|
||||
|
||||
export class StateBadge extends LitElement {
|
||||
public hass?: HomeAssistant;
|
||||
@@ -28,15 +29,12 @@ export class StateBadge extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public stateColor?: boolean;
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "icon" })
|
||||
private _showIcon = true;
|
||||
|
||||
@property() private _iconStyle: { [name: string]: string } = {};
|
||||
@query("ha-icon") private _icon!: HaIcon;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const stateObj = this.stateObj;
|
||||
|
||||
if (!stateObj || !this._showIcon) {
|
||||
if (!stateObj) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
@@ -44,7 +42,7 @@ export class StateBadge extends LitElement {
|
||||
|
||||
return html`
|
||||
<ha-icon
|
||||
style=${styleMap(this._iconStyle)}
|
||||
id="icon"
|
||||
data-domain=${ifDefined(
|
||||
this.stateColor || (domain === "light" && this.stateColor !== false)
|
||||
? domain
|
||||
@@ -62,13 +60,14 @@ export class StateBadge extends LitElement {
|
||||
}
|
||||
const stateObj = this.stateObj;
|
||||
|
||||
const iconStyle: { [name: string]: string } = {};
|
||||
const iconStyle: Partial<CSSStyleDeclaration> = {
|
||||
color: "",
|
||||
filter: "",
|
||||
display: "",
|
||||
};
|
||||
const hostStyle: Partial<CSSStyleDeclaration> = {
|
||||
backgroundImage: "",
|
||||
};
|
||||
|
||||
this._showIcon = true;
|
||||
|
||||
if (stateObj) {
|
||||
// hide icon if we have entity picture
|
||||
if (
|
||||
@@ -80,7 +79,7 @@ export class StateBadge extends LitElement {
|
||||
imageUrl = this.hass.hassUrl(imageUrl);
|
||||
}
|
||||
hostStyle.backgroundImage = `url(${imageUrl})`;
|
||||
this._showIcon = false;
|
||||
iconStyle.display = "none";
|
||||
} else if (stateObj.state === "on") {
|
||||
if (stateObj.attributes.hs_color && this.stateColor !== false) {
|
||||
const hue = stateObj.attributes.hs_color[0];
|
||||
@@ -103,7 +102,7 @@ export class StateBadge extends LitElement {
|
||||
}
|
||||
}
|
||||
}
|
||||
this._iconStyle = iconStyle;
|
||||
Object.assign(this._icon.style, iconStyle);
|
||||
Object.assign(this.style, hostStyle);
|
||||
}
|
||||
|
||||
@@ -120,17 +119,8 @@ export class StateBadge extends LitElement {
|
||||
background-size: cover;
|
||||
line-height: 40px;
|
||||
vertical-align: middle;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host(:focus) {
|
||||
outline: none;
|
||||
}
|
||||
:host(:not([icon]):focus) {
|
||||
border: 2px solid var(--divider-color);
|
||||
}
|
||||
:host([icon]:focus) {
|
||||
background: var(--divider-color);
|
||||
}
|
||||
|
||||
ha-icon {
|
||||
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import "../ha-relative-time";
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import "./ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-item/paper-item-body.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light.js";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
css,
|
||||
|
@@ -8,7 +8,7 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { until } from "lit-html/directives/until.js";
|
||||
import hassAttributeUtil from "../util/hass-attributes-util";
|
||||
|
||||
let jsYamlPromise: Promise<typeof import("js-yaml")>;
|
||||
|
@@ -6,19 +6,18 @@ import {
|
||||
CSSResult,
|
||||
css,
|
||||
query,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-menu";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import type { Menu, Corner } from "@material/mwc-menu";
|
||||
import "@material/mwc-list/mwc-list-item.js";
|
||||
import type { Menu } from "@material/mwc-menu";
|
||||
|
||||
import { haStyle } from "../resources/styles";
|
||||
|
||||
import "./ha-icon-button";
|
||||
|
||||
@customElement("ha-button-menu")
|
||||
export class HaButtonMenu extends LitElement {
|
||||
@property() public corner: Corner = "TOP_START";
|
||||
|
||||
@query("mwc-menu") private _menu?: Menu;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@@ -26,7 +25,7 @@ export class HaButtonMenu extends LitElement {
|
||||
<div @click=${this._handleClick}>
|
||||
<slot name="trigger"></slot>
|
||||
</div>
|
||||
<mwc-menu .corner=${this.corner}>
|
||||
<mwc-menu>
|
||||
<slot></slot>
|
||||
</mwc-menu>
|
||||
`;
|
||||
@@ -37,13 +36,15 @@ export class HaButtonMenu extends LitElement {
|
||||
this._menu!.show();
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
`;
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import "@material/mwc-checkbox";
|
||||
import type { Checkbox } from "@material/mwc-checkbox";
|
||||
import { customElement } from "lit-element";
|
||||
import { style } from "@material/mwc-checkbox/mwc-checkbox-css.js";
|
||||
import { css, CSSResult, customElement } from "lit-element";
|
||||
import type { Constructor } from "../types";
|
||||
|
||||
const MwcCheckbox = customElements.get("mwc-checkbox") as Constructor<Checkbox>;
|
||||
@@ -11,6 +12,18 @@ export class HaCheckbox extends MwcCheckbox {
|
||||
super.firstUpdated();
|
||||
this.style.setProperty("--mdc-theme-secondary", "var(--primary-color)");
|
||||
}
|
||||
|
||||
protected static get styles(): CSSResult[] {
|
||||
return [
|
||||
style,
|
||||
css`
|
||||
.mdc-checkbox__native-control:enabled:not(:checked):not(:indeterminate)
|
||||
~ .mdc-checkbox__background {
|
||||
border-color: rgba(var(--rgb-primary-text-color), 0.54);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// @ts-ignore
|
||||
import chipStyles from "@material/chips/dist/mdc.chips.min.css";
|
||||
import { ripple } from "@material/mwc-ripple/ripple-directive";
|
||||
import { ripple } from "@material/mwc-ripple/ripple-directive.js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes.js";
|
||||
import "./ha-icon-button";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { EventsMixin } from "../mixins/events-mixin";
|
||||
|
||||
/*
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { CLIMATE_PRESET_NONE } from "../data/climate";
|
||||
import LocalizeMixin from "../mixins/localize-mixin";
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { EventsMixin } from "../mixins/events-mixin";
|
||||
|
||||
/**
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import "./ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light.js";
|
||||
import { EventsMixin } from "../mixins/events-mixin";
|
||||
|
||||
class HaComboBox extends EventsMixin(PolymerElement) {
|
||||
@@ -12,7 +12,8 @@ class HaComboBox extends EventsMixin(PolymerElement) {
|
||||
return html`
|
||||
<style>
|
||||
paper-input > ha-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import "./ha-icon-button";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { UNAVAILABLE } from "../data/entity";
|
||||
import CoverEntity from "../util/cover-model";
|
||||
|
||||
@@ -30,7 +30,7 @@ class HaCoverControls extends PolymerElement {
|
||||
icon="hass:stop"
|
||||
on-click="onStopTap"
|
||||
invisible$="[[!entityObj.supportsStop]]"
|
||||
disabled="[[computeStopDisabled(stateObj)]]"
|
||||
disabled="[[computStopDisabled(stateObj)]]"
|
||||
></ha-icon-button>
|
||||
<ha-icon-button
|
||||
aria-label="Close cover"
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes.js";
|
||||
import "./ha-icon-button";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import { UNAVAILABLE } from "../data/entity";
|
||||
import CoverEntity from "../util/cover-model";
|
||||
|
||||
@@ -31,7 +31,7 @@ class HaCoverTiltControls extends PolymerElement {
|
||||
icon="hass:stop"
|
||||
on-click="onStopTiltTap"
|
||||
invisible$="[[!entityObj.supportsStopTilt]]"
|
||||
disabled="[[computeStopDisabled(stateObj)]]"
|
||||
disabled="[[computStopDisabled(stateObj)]]"
|
||||
title="Stop tilt"
|
||||
></ha-icon-button>
|
||||
<ha-icon-button
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input.js";
|
||||
import {
|
||||
css,
|
||||
customElement,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import "./ha-label-badge";
|
||||
|
||||
class HaDemoBadge extends PolymerElement {
|
||||
|
@@ -1,22 +1,20 @@
|
||||
import "@material/mwc-dialog";
|
||||
import type { Dialog } from "@material/mwc-dialog";
|
||||
import { style } from "@material/mwc-dialog/mwc-dialog-css";
|
||||
import { style } from "@material/mwc-dialog/mwc-dialog-css.js";
|
||||
import "./ha-icon-button";
|
||||
import { css, CSSResult, customElement, html } from "lit-element";
|
||||
import type { Constructor, HomeAssistant } from "../types";
|
||||
import { mdiClose } from "@mdi/js";
|
||||
|
||||
const MwcDialog = customElements.get("mwc-dialog") as Constructor<Dialog>;
|
||||
|
||||
export const createCloseHeading = (hass: HomeAssistant, title: string) => html`
|
||||
${title}
|
||||
<mwc-icon-button
|
||||
<ha-icon-button
|
||||
aria-label=${hass.localize("ui.dialogs.generic.close")}
|
||||
icon="hass:close"
|
||||
dialogAction="close"
|
||||
class="close_button"
|
||||
>
|
||||
<ha-svg-icon path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
></ha-icon-button>
|
||||
`;
|
||||
|
||||
@customElement("ha-dialog")
|
||||
|
41
src/components/ha-fab.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import "@material/mwc-fab";
|
||||
import type { Fab } from "@material/mwc-fab";
|
||||
import { ripple } from "@material/mwc-ripple/ripple-directive.js";
|
||||
import { customElement, html, TemplateResult } from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map.js";
|
||||
import type { Constructor } from "../types";
|
||||
import "./ha-icon";
|
||||
|
||||
const MwcFab = customElements.get("mwc-fab") as Constructor<Fab>;
|
||||
|
||||
@customElement("ha-fab")
|
||||
export class HaFab extends MwcFab {
|
||||
// We override the render method because we don't have an icon font and mwc-fab doesn't support our svg-icon sets.
|
||||
// Based on version mwc-fab 0.8
|
||||
protected render(): TemplateResult {
|
||||
const classes = {
|
||||
"mdc-fab--mini": this.mini,
|
||||
"mdc-fab--exited": this.exited,
|
||||
"mdc-fab--extended": this.extended,
|
||||
};
|
||||
const showLabel = this.label !== "" && this.extended;
|
||||
return html`
|
||||
<button
|
||||
.ripple="${ripple()}"
|
||||
class="mdc-fab ${classMap(classes)}"
|
||||
?disabled="${this.disabled}"
|
||||
aria-label="${this.label || this.icon}"
|
||||
>
|
||||
${showLabel && this.showIconAtEnd ? this.label : ""}
|
||||
${this.icon ? html` <ha-icon .icon=${this.icon}></ha-icon> ` : ""}
|
||||
${showLabel && !this.showIconAtEnd ? this.label : ""}
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-fab": HaFab;
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
import "@polymer/paper-checkbox/paper-checkbox";
|
||||
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
|
||||
import "@polymer/paper-checkbox";
|
||||
import type { PaperCheckboxElement } from "@polymer/paper-checkbox";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input.js";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-slider/paper-slider";
|
||||
import type { PaperSliderElement } from "@polymer/paper-slider/paper-slider";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-slider";
|
||||
import type { PaperSliderElement } from "@polymer/paper-slider";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import "@polymer/paper-checkbox/paper-checkbox";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-icon-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-menu-button/paper-menu-button";
|
||||
import "@polymer/paper-ripple/paper-ripple";
|
||||
import "@polymer/paper-checkbox";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import "@polymer/paper-item/paper-icon-item.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import "@polymer/paper-menu-button";
|
||||
import "@polymer/paper-ripple";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu.js";
|
||||
import "@polymer/paper-item/paper-item.js";
|
||||
import "@polymer/paper-listbox";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import "../ha-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import type { PaperInputElement } from "@polymer/paper-input/paper-input.js";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
|
@@ -1,30 +1,17 @@
|
||||
import { LitElement, property, TemplateResult, html } from "lit-element";
|
||||
import { mdiArrowLeft, mdiArrowRight } from "@mdi/js";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import "./ha-svg-icon";
|
||||
|
||||
export class HaIconButtonArrowPrev extends LitElement {
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@property() private _icon = mdiArrowLeft;
|
||||
import { HaIconButton } from "./ha-icon-button";
|
||||
|
||||
export class HaIconButtonArrowPrev extends HaIconButton {
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
// wait to check for direction since otherwise direction is wrong even though top level is RTL
|
||||
setTimeout(() => {
|
||||
this._icon =
|
||||
this.icon =
|
||||
window.getComputedStyle(this).direction === "ltr"
|
||||
? mdiArrowLeft
|
||||
: mdiArrowRight;
|
||||
? "hass:arrow-left"
|
||||
: "hass:arrow-right";
|
||||
}, 100);
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`<mwc-icon-button .disabled=${this.disabled}>
|
||||
<ha-svg-icon .path=${this._icon}></ha-svg-icon>
|
||||
</mwc-icon-button> `;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -48,7 +48,6 @@ export class HaIconButton extends LitElement {
|
||||
}
|
||||
mwc-icon-button {
|
||||
--mdc-theme-on-primary: currentColor;
|
||||
--mdc-theme-text-disabled-on-light: var(--disabled-text-color);
|
||||
}
|
||||
ha-icon {
|
||||
--ha-icon-display: inline;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-input/paper-input.js";
|
||||
import {
|
||||
css,
|
||||
customElement,
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import "@polymer/iron-icon";
|
||||
import { get, set, clear, Store } from "idb-keyval";
|
||||
import {
|
||||
customElement,
|
||||
LitElement,
|
||||
@@ -10,23 +11,84 @@ import {
|
||||
CSSResult,
|
||||
} from "lit-element";
|
||||
import "./ha-svg-icon";
|
||||
import { customIconsets, CustomIcon } from "../data/custom_iconsets";
|
||||
import {
|
||||
Chunks,
|
||||
MDI_PREFIXES,
|
||||
getIcon,
|
||||
findIconChunk,
|
||||
Icons,
|
||||
checkCacheVersion,
|
||||
writeCache,
|
||||
} from "../data/iconsets";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
import { iconMetadata } from "../resources/icon-metadata";
|
||||
import { IconMeta } from "../types";
|
||||
|
||||
interface Icons {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface Chunks {
|
||||
[key: string]: Promise<Icons>;
|
||||
}
|
||||
|
||||
const iconStore = new Store("hass-icon-db", "mdi-icon-store");
|
||||
|
||||
get("_version", iconStore).then((version) => {
|
||||
if (!version) {
|
||||
set("_version", iconMetadata.version, iconStore);
|
||||
} else if (version !== iconMetadata.version) {
|
||||
clear(iconStore).then(() =>
|
||||
set("_version", iconMetadata.version, iconStore)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const chunks: Chunks = {};
|
||||
const MDI_PREFIXES = ["mdi", "hass", "hassio", "hademo"];
|
||||
|
||||
checkCacheVersion();
|
||||
let toRead: Array<[string, (string) => void]> = [];
|
||||
|
||||
const debouncedWriteCache = debounce(() => writeCache(chunks), 2000);
|
||||
// Queue up as many icon fetches in 1 transaction
|
||||
const getIcon = (iconName: string) =>
|
||||
new Promise<string>((resolve) => {
|
||||
toRead.push([iconName, resolve]);
|
||||
|
||||
if (toRead.length > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const results: Array<[(string) => void, IDBRequest]> = [];
|
||||
|
||||
iconStore
|
||||
._withIDBStore("readonly", (store) => {
|
||||
for (const [iconName_, resolve_] of toRead) {
|
||||
results.push([resolve_, store.get(iconName_)]);
|
||||
}
|
||||
toRead = [];
|
||||
})
|
||||
.then(() => {
|
||||
for (const [resolve_, request] of results) {
|
||||
resolve_(request.result);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const findIconChunk = (icon): string => {
|
||||
let lastChunk: IconMeta;
|
||||
for (const chunk of iconMetadata.parts) {
|
||||
if (chunk.start !== undefined && icon < chunk.start) {
|
||||
break;
|
||||
}
|
||||
lastChunk = chunk;
|
||||
}
|
||||
return lastChunk!.file;
|
||||
};
|
||||
|
||||
const debouncedWriteCache = debounce(async () => {
|
||||
const keys = Object.keys(chunks);
|
||||
const iconsSets: Icons[] = await Promise.all(Object.values(chunks));
|
||||
// We do a batch opening the store just once, for (considerable) performance
|
||||
iconStore._withIDBStore("readwrite", (store) => {
|
||||
iconsSets.forEach((icons, idx) => {
|
||||
Object.entries(icons).forEach(([name, path]) => {
|
||||
store.put(path, name);
|
||||
});
|
||||
delete chunks[keys[idx]];
|
||||
});
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
@customElement("ha-icon")
|
||||
export class HaIcon extends LitElement {
|
||||
@@ -34,14 +96,11 @@ export class HaIcon extends LitElement {
|
||||
|
||||
@property() private _path?: string;
|
||||
|
||||
@property() private _viewBox?;
|
||||
|
||||
@property() private _legacy = false;
|
||||
@property() private _noMdi = false;
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (changedProps.has("icon")) {
|
||||
this._path = undefined;
|
||||
this._viewBox = undefined;
|
||||
this._loadIcon();
|
||||
}
|
||||
}
|
||||
@@ -50,39 +109,25 @@ export class HaIcon extends LitElement {
|
||||
if (!this.icon) {
|
||||
return html``;
|
||||
}
|
||||
if (this._legacy) {
|
||||
if (this._noMdi) {
|
||||
return html`<iron-icon .icon=${this.icon}></iron-icon>`;
|
||||
}
|
||||
return html`<ha-svg-icon
|
||||
.path=${this._path}
|
||||
.viewBox=${this._viewBox}
|
||||
></ha-svg-icon>`;
|
||||
return html`<ha-svg-icon .path=${this._path}></ha-svg-icon>`;
|
||||
}
|
||||
|
||||
private async _loadIcon() {
|
||||
if (!this.icon) {
|
||||
return;
|
||||
}
|
||||
const [iconPrefix, iconName] = this.icon.split(":", 2);
|
||||
|
||||
if (!iconPrefix || !iconName) {
|
||||
const icon = this.icon.split(":", 2);
|
||||
if (!MDI_PREFIXES.includes(icon[0])) {
|
||||
this._noMdi = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MDI_PREFIXES.includes(iconPrefix)) {
|
||||
if (iconPrefix in customIconsets) {
|
||||
const customIconset = customIconsets[iconPrefix];
|
||||
if (customIconset) {
|
||||
this._setCustomPath(customIconset(iconName));
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._legacy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this._legacy = false;
|
||||
this._noMdi = false;
|
||||
|
||||
const iconName = icon[1];
|
||||
const cachedPath: string = await getIcon(iconName);
|
||||
if (cachedPath) {
|
||||
this._path = cachedPath;
|
||||
@@ -102,12 +147,6 @@ export class HaIcon extends LitElement {
|
||||
debouncedWriteCache();
|
||||
}
|
||||
|
||||
private async _setCustomPath(promise: Promise<CustomIcon>) {
|
||||
const icon = await promise;
|
||||
this._path = icon.path;
|
||||
this._viewBox = icon.viewBox;
|
||||
}
|
||||
|
||||
private async _setPath(promise: Promise<Icons>, iconName: string) {
|
||||
const iconPack = await promise;
|
||||
this._path = iconPack[iconName];
|
||||
|
@@ -7,7 +7,7 @@ import {
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { classMap } from "lit-html/directives/class-map.js";
|
||||
import "./ha-icon";
|
||||
|
||||
class HaLabelBadge extends LitElement {
|
||||
@@ -31,14 +31,12 @@ class HaLabelBadge extends LitElement {
|
||||
big: Boolean(this.value && this.value.length > 4),
|
||||
})}"
|
||||
>
|
||||
<slot>
|
||||
${this.icon && !this.value && !this.image
|
||||
? html` <ha-icon .icon=${this.icon}></ha-icon> `
|
||||
: ""}
|
||||
${this.value && !this.image
|
||||
? html` <span>${this.value}</span> `
|
||||
: ""}
|
||||
</slot>
|
||||
${this.icon && !this.value && !this.image
|
||||
? html` <ha-icon .icon="${this.icon}"></ha-icon> `
|
||||
: ""}
|
||||
${this.value && !this.image
|
||||
? html` <span>${this.value}</span> `
|
||||
: ""}
|
||||
</div>
|
||||
${this.label
|
||||
? html`
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag.js";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element.js";
|
||||
import "./ha-icon";
|
||||
import "./ha-paper-slider";
|
||||
|
||||
|