mirror of
https://github.com/home-assistant/frontend.git
synced 2026-06-24 09:11:36 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e37b48fd6 |
@@ -105,6 +105,8 @@ jobs:
|
||||
name: frontend-bundle-stats
|
||||
path: build/stats/*.json
|
||||
if-no-files-found: error
|
||||
- name: Check entrypoint bundle size budget
|
||||
run: yarn run check-bundlesize
|
||||
- name: Upload frontend build
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"_comment": "Initial JS budget (raw/uncompressed bytes) for the cold-load critical entrypoints. Enforced by build-scripts/check-bundle-size.cjs in CI. Re-seed after an intentional change with `--update --headroom=<percent>`.",
|
||||
"frontend-modern": {
|
||||
"app": 561513,
|
||||
"core": 54473,
|
||||
"authorize": 544272,
|
||||
"onboarding": 647136
|
||||
},
|
||||
"frontend-legacy": {
|
||||
"app": 790323,
|
||||
"core": 237208,
|
||||
"authorize": 765464,
|
||||
"onboarding": 918679
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/* global require, process, __dirname */
|
||||
// Enforce a strict size budget on the initial JS of the most critical
|
||||
// entrypoints (`app` and `core`). These two are downloaded on every cold load
|
||||
// before anything interactive can happen, so unintended growth here hurts
|
||||
// first-load performance directly.
|
||||
//
|
||||
// In production rspack does not split initial chunks (splitChunks only operates
|
||||
// on `!chunk.canBeInitial()`), so each entrypoint resolves to a single initial
|
||||
// JS asset. We read the per-build stats written by StatsWriterPlugin and compare
|
||||
// the entrypoint's initial JS size against a committed budget.
|
||||
//
|
||||
// Usage:
|
||||
// node build-scripts/check-bundle-size.cjs # enforce, exit 1 on regression
|
||||
// node build-scripts/check-bundle-size.cjs --update # rewrite budgets from current sizes
|
||||
// node build-scripts/check-bundle-size.cjs --update --headroom=3 # current + 3% headroom
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const paths = require("./paths.cjs");
|
||||
|
||||
// Entrypoints whose initial JS we hold to a strict budget. These are all
|
||||
// downloaded on a user-facing cold load before anything interactive can happen:
|
||||
// `app`/`core` for the main app, plus the standalone `authorize` and
|
||||
// `onboarding` pages. `custom-panel` is intentionally excluded (only loaded
|
||||
// when a custom panel is opened).
|
||||
const TRACKED_ENTRYPOINTS = ["app", "core", "authorize", "onboarding"];
|
||||
|
||||
// App build stats files, as written by StatsWriterPlugin (`${name}.json`).
|
||||
const BUILDS = ["frontend-modern", "frontend-legacy"];
|
||||
|
||||
const BUDGET_FILE = path.join(__dirname, "bundle-budget.json");
|
||||
const STATS_DIR = path.join(paths.build_dir, "stats");
|
||||
|
||||
const readStats = (build) => {
|
||||
const file = path.join(STATS_DIR, `${build}.json`);
|
||||
if (!fs.existsSync(file)) {
|
||||
throw new Error(
|
||||
`Missing stats file: ${path.relative(process.cwd(), file)}.\n` +
|
||||
`Run a production build first (e.g. \`gulp build-app\`), then re-run this check.`
|
||||
);
|
||||
}
|
||||
return JSON.parse(fs.readFileSync(file, "utf8"));
|
||||
};
|
||||
|
||||
// Initial JS bytes for an entrypoint = sum of the .js asset sizes of its initial
|
||||
// entry chunk(s). Sizes are raw (uncompressed) bytes, matching the stats output.
|
||||
const entrypointInitialJS = (stats, entrypoint) => {
|
||||
const assetSize = new Map(stats.assets.map((a) => [a.name, a.size]));
|
||||
let total = 0;
|
||||
let found = false;
|
||||
for (const chunk of stats.chunks) {
|
||||
if (!chunk.entry || !chunk.initial) {
|
||||
continue;
|
||||
}
|
||||
if (!(chunk.names || []).includes(entrypoint)) {
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
for (const file of chunk.files || []) {
|
||||
if (file.endsWith(".js") && assetSize.has(file)) {
|
||||
total += assetSize.get(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new Error(`Entrypoint "${entrypoint}" not found in bundle stats.`);
|
||||
}
|
||||
return total;
|
||||
};
|
||||
|
||||
const kib = (bytes) => `${(bytes / 1024).toFixed(1)} KiB`;
|
||||
|
||||
const main = () => {
|
||||
const update = process.argv.includes("--update");
|
||||
const headroomArg = process.argv.find((a) => a.startsWith("--headroom="));
|
||||
const headroom = headroomArg ? Number(headroomArg.split("=")[1]) : 0;
|
||||
|
||||
const current = {};
|
||||
for (const build of BUILDS) {
|
||||
const stats = readStats(build);
|
||||
current[build] = {};
|
||||
for (const entrypoint of TRACKED_ENTRYPOINTS) {
|
||||
current[build][entrypoint] = entrypointInitialJS(stats, entrypoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
const budget = { _comment: BUDGET_COMMENT };
|
||||
for (const build of BUILDS) {
|
||||
budget[build] = {};
|
||||
for (const entrypoint of TRACKED_ENTRYPOINTS) {
|
||||
budget[build][entrypoint] = Math.ceil(
|
||||
current[build][entrypoint] * (1 + headroom / 100)
|
||||
);
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(BUDGET_FILE, `${JSON.stringify(budget, null, 2)}\n`);
|
||||
console.log(
|
||||
`Updated ${path.relative(process.cwd(), BUDGET_FILE)} from current sizes` +
|
||||
(headroom ? ` (+${headroom}% headroom).` : ".")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(BUDGET_FILE)) {
|
||||
throw new Error(
|
||||
`Missing budget file ${path.relative(process.cwd(), BUDGET_FILE)}.\n` +
|
||||
`Seed it from a production build with: node build-scripts/check-bundle-size.cjs --update --headroom=3`
|
||||
);
|
||||
}
|
||||
const budget = JSON.parse(fs.readFileSync(BUDGET_FILE, "utf8"));
|
||||
|
||||
let failed = false;
|
||||
console.log("Initial JS budget (entry chunks, raw bytes):\n");
|
||||
for (const build of BUILDS) {
|
||||
for (const entrypoint of TRACKED_ENTRYPOINTS) {
|
||||
const actual = current[build][entrypoint];
|
||||
const limit = budget[build] && budget[build][entrypoint];
|
||||
if (typeof limit !== "number") {
|
||||
failed = true;
|
||||
console.log(
|
||||
` ✗ ${build} / ${entrypoint}: no budget set (current ${kib(actual)})`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const ok = actual <= limit;
|
||||
const delta = (((actual - limit) / limit) * 100).toFixed(1);
|
||||
console.log(
|
||||
` ${ok ? "✓" : "✗"} ${build} / ${entrypoint}: ` +
|
||||
`${kib(actual)} / ${kib(limit)}${ok ? "" : ` (+${delta}% over budget)`}`
|
||||
);
|
||||
if (!ok) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
console.error(
|
||||
"\nInitial JS budget exceeded for a critical entrypoint.\n" +
|
||||
"Investigate what was pulled into the entry chunk (a static import that should be lazy?).\n" +
|
||||
"If the growth is intentional, re-seed the budget:\n" +
|
||||
" node build-scripts/check-bundle-size.cjs --update --headroom=3"
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log("\nAll tracked entrypoints within budget.");
|
||||
};
|
||||
|
||||
const BUDGET_COMMENT =
|
||||
"Initial JS budget (raw/uncompressed bytes) for the cold-load critical entrypoints. " +
|
||||
"Enforced by build-scripts/check-bundle-size.cjs in CI. " +
|
||||
"Re-seed after an intentional change with `--update --headroom=<percent>`.";
|
||||
|
||||
main();
|
||||
+2
-1
@@ -22,7 +22,8 @@
|
||||
"postpack": "pinst --enable",
|
||||
"test": "vitest run --config test/vitest.config.ts",
|
||||
"test:bench": "vitest bench --run --config test/vitest.bench.config.ts",
|
||||
"test:coverage": "vitest run --config test/vitest.config.ts --coverage"
|
||||
"test:coverage": "vitest run --config test/vitest.config.ts --coverage",
|
||||
"check-bundlesize": "node build-scripts/check-bundle-size.cjs"
|
||||
},
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
||||
import type { PageNavigation } from "../layouts/hass-tabs-subpage";
|
||||
import { configSections } from "../panels/config/ha-panel-config";
|
||||
import { configSections } from "../panels/config/config-sections";
|
||||
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import type { HassioAddonInfo } from "./hassio/addon";
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { HaTabsSubpageDataTable } from "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showAddApplicationCredentialDialog } from "./show-dialog-add-application-credential";
|
||||
|
||||
@customElement("ha-config-application-credentials")
|
||||
|
||||
@@ -54,7 +54,7 @@ import {
|
||||
import "../../../layouts/hass-tabs-subpage";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { showToast } from "../../../util/toast";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import {
|
||||
loadAreaRegistryDetailDialog,
|
||||
showAreaRegistryDetailDialog,
|
||||
|
||||
@@ -120,7 +120,7 @@ import {
|
||||
getLabelsTableColumn,
|
||||
getTriggeredAtTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
getAssistantsSortableKey,
|
||||
|
||||
@@ -52,7 +52,7 @@ import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import { showToast } from "../../../util/toast";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showAddBlueprintDialog } from "./show-dialog-import-blueprint";
|
||||
|
||||
type BlueprintMetaDataPath = BlueprintMetaData & {
|
||||
|
||||
@@ -0,0 +1,555 @@
|
||||
import {
|
||||
mdiAccount,
|
||||
mdiBackupRestore,
|
||||
mdiBadgeAccountHorizontal,
|
||||
mdiBluetooth,
|
||||
mdiCellphoneCog,
|
||||
mdiCog,
|
||||
mdiDatabase,
|
||||
mdiDevices,
|
||||
mdiFlask,
|
||||
mdiHammer,
|
||||
mdiInformationOutline,
|
||||
mdiLabel,
|
||||
mdiLightningBolt,
|
||||
mdiMapMarkerRadius,
|
||||
mdiMemory,
|
||||
mdiMicrophone,
|
||||
mdiNetwork,
|
||||
mdiNfcVariant,
|
||||
mdiPalette,
|
||||
mdiPaletteSwatch,
|
||||
mdiPuzzle,
|
||||
mdiRadioTower,
|
||||
mdiRemote,
|
||||
mdiRobot,
|
||||
mdiScrewdriver,
|
||||
mdiScriptText,
|
||||
mdiShape,
|
||||
mdiSofa,
|
||||
mdiStarFourPoints,
|
||||
mdiTextBoxOutline,
|
||||
mdiTools,
|
||||
mdiUpdate,
|
||||
mdiViewDashboard,
|
||||
mdiZigbee,
|
||||
mdiZWave,
|
||||
} from "@mdi/js";
|
||||
import memoizeOne from "memoize-one";
|
||||
import type { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
|
||||
const getHasDomainCheck = (domain: string) => {
|
||||
const prefix = `${domain}.`;
|
||||
const checkRegistry = memoizeOne((entries: HomeAssistant["entities"]) =>
|
||||
Object.values(entries).some((entry) => entry.entity_id.startsWith(prefix))
|
||||
);
|
||||
return (hass: HomeAssistant) => checkRegistry(hass.entities);
|
||||
};
|
||||
|
||||
export const configSections: Record<string, PageNavigation[]> = {
|
||||
dashboard: [
|
||||
{
|
||||
path: "/config/integrations",
|
||||
translationKey: "devices",
|
||||
iconPath: mdiDevices,
|
||||
iconColor: "#0D47A1",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/automation",
|
||||
translationKey: "automations",
|
||||
iconPath: mdiRobot,
|
||||
iconColor: "#518C43",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/areas",
|
||||
translationKey: "areas",
|
||||
iconPath: mdiSofa,
|
||||
iconColor: "#E48629",
|
||||
component: "zone",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/apps",
|
||||
translationKey: "apps",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#F1C447",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/lovelace/dashboards",
|
||||
translationKey: "dashboards",
|
||||
iconPath: mdiViewDashboard,
|
||||
iconColor: "#B1345C",
|
||||
component: "lovelace",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/voice-assistants",
|
||||
translationKey: "voice_assistants",
|
||||
iconPath: mdiMicrophone,
|
||||
iconColor: "#3263C3",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
dashboard_external_settings: [
|
||||
{
|
||||
path: "#external-app-configuration",
|
||||
translationKey: "companion",
|
||||
iconPath: mdiCellphoneCog,
|
||||
iconColor: "#8E24AA",
|
||||
},
|
||||
],
|
||||
dashboard_2: [
|
||||
{
|
||||
path: "/config/matter",
|
||||
iconPath:
|
||||
"M7.228375 6.41685c0.98855 0.80195 2.16365 1.3412 3.416275 1.56765V1.30093l1.3612 -0.7854275 1.360125 0.7854275V7.9845c1.252875 -0.226675 2.4283 -0.765875 3.41735 -1.56765l2.471225 1.4293c-4.019075 3.976275 -10.490025 3.976275 -14.5091 0l2.482925 -1.4293Zm3.00335 17.067575c1.43325 -5.47035 -1.8052 -11.074775 -7.2604 -12.564675v2.859675c1.189125 0.455 2.244125 1.202875 3.0672 2.174275L0.25 19.2955v1.5719l1.3611925 0.781175L7.39865 18.3068c0.430175 1.19825 0.550625 2.48575 0.35015 3.743l2.482925 1.434625ZM21.034 10.91975c-5.452225 1.4932 -8.6871 7.09635 -7.254025 12.564675l2.47655 -1.43035c-0.200025 -1.257275 -0.079575 -2.544675 0.35015 -3.743025l5.7832 3.337525L23.75 20.86315V19.2955L17.961475 15.9537c0.8233 -0.97115 1.878225 -1.718975 3.0672 -2.174275l0.005325 -2.859675Z",
|
||||
iconViewBox: "0 1 24 24",
|
||||
iconColor: "#2458B3",
|
||||
component: "matter",
|
||||
translationKey: "matter",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/zha",
|
||||
iconPath: mdiZigbee,
|
||||
iconColor: "#E74011",
|
||||
component: "zha",
|
||||
translationKey: "zha",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/zwave_js",
|
||||
iconPath: mdiZWave,
|
||||
iconColor: "#153163",
|
||||
component: "zwave_js",
|
||||
translationKey: "zwave_js",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/knx",
|
||||
iconPath:
|
||||
"M 3.9861338,14.261456 3.7267552,13.934877 6.3179131,11.306266 H 4.466374 l -2.6385205,2.68258 V 11.312882 H 0.00440574 L 0,17.679803 l 1.8278535,5.43e-4 v -1.818482 l 0.7225444,-0.732459 2.1373588,2.543782 2.1869324,-5.44e-4 M 24,17.680369 21.809238,17.669359 19.885559,15.375598 17.640262,17.68037 h -1.828407 l 3.236048,-3.302138 -2.574075,-3.067547 2.135161,0.0016 1.610309,1.87687 1.866403,-1.87687 h 1.828429 l -2.857742,2.87478 m -10.589867,-2.924898 2.829625,3.990552 -0.01489,-3.977887 1.811889,-0.0044 0.0011,6.357564 -2.093314,-5.44e-4 -2.922133,-3.947594 -0.0314,3.947594 H 8.2581097 V 11.261677 M 11.971203,6.3517488 c 0,0 2.800714,-0.093203 6.172001,1.0812045 3.462393,1.0898845 5.770926,3.4695627 5.770926,3.4695627 l -1.823898,-5.43e-4 C 22.088532,10.900273 20.577938,9.4271528 17.660223,8.5024618 15.139256,7.703366 12.723057,7.645835 12.111178,7.6449876 l -9.71e-4,0.0011 c 0,0 -0.0259,-6.4e-4 -0.07527,-9.714e-4 -0.04726,3.33e-4 -0.07201,9.714e-4 -0.07201,9.714e-4 v -0.00113 C 11.337007,7.6453728 8.8132091,7.7001736 6.2821829,8.5024618 3.3627914,9.4276738 1.8521646,10.901973 1.8521646,10.901973 l -1.82398708,5.43e-4 C 0.03128403,10.899322 2.339143,8.5221038 5.799224,7.4329533 9.170444,6.2585642 11.971203,6.3517488 11.971203,6.3517488 Z",
|
||||
iconColor: "#4EAA66",
|
||||
component: "knx",
|
||||
translationKey: "knx",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/thread",
|
||||
iconPath:
|
||||
"m 17.126982,8.0730792 c 0,-0.7297242 -0.593746,-1.32357 -1.323637,-1.32357 -0.729454,0 -1.323199,0.5938458 -1.323199,1.32357 v 1.3234242 l 1.323199,1.458e-4 c 0.729891,0 1.323637,-0.5937006 1.323637,-1.32357 z M 11.999709,0 C 5.3829818,0 0,5.3838955 0,12.001455 0,18.574352 5.3105455,23.927406 11.865164,24 V 12.012075 l -3.9275642,-2.91e-4 c -1.1669814,0 -2.1169453,0.949979 -2.1169453,2.118323 0,1.16718 0.9499639,2.116868 2.1169453,2.116868 v 2.615717 c -2.6093089,0 -4.732218,-2.12327 -4.732218,-4.732585 0,-2.61048 2.1229091,-4.7343308 4.732218,-4.7343308 l 3.9275642,5.82e-4 v -1.323279 c 0,-2.172296 1.766691,-3.9395777 3.938181,-3.9395777 2.171928,0 3.9392,1.7672817 3.9392,3.9395777 0,2.1721498 -1.767272,3.9395768 -3.9392,3.9395768 l -1.323199,-1.45e-4 V 23.744102 C 19.911127,22.597726 24,17.768833 24,12.001455 24,5.3838955 18.616727,0 11.999709,0 Z",
|
||||
iconColor: "#ED7744",
|
||||
component: "thread",
|
||||
translationKey: "thread",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/bluetooth",
|
||||
iconPath: mdiBluetooth,
|
||||
iconColor: "#0082FC",
|
||||
component: "bluetooth",
|
||||
translationKey: "bluetooth",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/infrared",
|
||||
iconPath: mdiRemote,
|
||||
iconColor: "#9C27B0",
|
||||
translationKey: "infrared",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("infrared"),
|
||||
},
|
||||
{
|
||||
path: "/config/radio-frequency",
|
||||
iconPath: mdiRadioTower,
|
||||
iconColor: "#E74011",
|
||||
component: "radio_frequency",
|
||||
translationKey: "radio_frequency",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("radio_frequency"),
|
||||
},
|
||||
{
|
||||
path: "/insteon",
|
||||
iconPath:
|
||||
"m 12.001571,6.3842473 h 0.02973 c 3.652189,0 6.767389,-2.29456 7.987462,-5.5177193 L 15.389382,0 Z m 0,0 h -0.02972 c -3.6522186,0 -6.7673314,-2.2918546 -7.9874477,-5.5177193 h -0.00271 L 8.6111273,0 Z M 6.3840436,11.999287 v -0.02972 c 0,-3.6524074 -2.2944727,-6.7675928 -5.51754469,-7.9877383 L 0,8.6114473 Z m 0,0 v 0.02964 c 0,3.652378 -2.2917818,6.767578 -5.51754469,7.987796 v 0.0026 L 0,15.389818 Z M 24,8.6114473 23.133527,3.9818327 v 0.00269 C 19.907636,5.2046836 17.616,8.3198691 17.616,11.972276 v 0.02966 0.02972 0.0027 c 0,3.65232 2.2944,6.76752 5.517527,7.987738 L 24,15.392436 17.616,12.001935 Z M 20.018618,23.133527 15.389091,24 11.99872,17.615709 h 0.02964 c 3.652218,0 6.767418,2.291927 7.987491,5.517818 z M 11.99872,17.615709 8.6082618,24 3.9788364,23.133527 C 5.1989527,19.9104 8.3140655,17.615709 11.966284,17.615709 h 0.0027 z",
|
||||
iconColor: "#E4002C",
|
||||
component: "insteon",
|
||||
translationKey: "insteon",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/tags",
|
||||
translationKey: "tags",
|
||||
iconPath: mdiNfcVariant,
|
||||
iconColor: "#616161",
|
||||
component: "tag",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
dashboard_3: [
|
||||
{
|
||||
path: "/config/person",
|
||||
translationKey: "people",
|
||||
iconPath: mdiAccount,
|
||||
iconColor: "#5A87FA",
|
||||
component: ["person", "users"],
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/system",
|
||||
translationKey: "system",
|
||||
iconPath: mdiCog,
|
||||
iconColor: "#301ABE",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/developer-tools",
|
||||
translationKey: "developer_tools",
|
||||
iconPath: mdiHammer,
|
||||
iconColor: "#7A5AA6",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/info",
|
||||
translationKey: "about",
|
||||
iconPath: mdiInformationOutline,
|
||||
iconColor: "#4A5963",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
backup: [
|
||||
{
|
||||
path: "/config/backup",
|
||||
translationKey: "ui.panel.config.backup.caption",
|
||||
iconPath: mdiBackupRestore,
|
||||
iconColor: "#4084CD",
|
||||
component: "backup",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
devices: [
|
||||
{
|
||||
component: "integrations",
|
||||
path: "/config/integrations",
|
||||
translationKey: "ui.panel.config.integrations.caption",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "devices",
|
||||
path: "/config/devices",
|
||||
translationKey: "ui.panel.config.devices.caption",
|
||||
iconPath: mdiDevices,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "entities",
|
||||
path: "/config/entities",
|
||||
translationKey: "ui.panel.config.entities.caption",
|
||||
iconPath: mdiShape,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "helpers",
|
||||
path: "/config/helpers",
|
||||
translationKey: "ui.panel.config.helpers.caption",
|
||||
iconPath: mdiTools,
|
||||
iconColor: "#4D2EA4",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
automations: [
|
||||
{
|
||||
component: "automation",
|
||||
path: "/config/automation",
|
||||
translationKey: "ui.panel.config.automation.caption",
|
||||
iconPath: mdiRobot,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "scene",
|
||||
path: "/config/scene",
|
||||
translationKey: "ui.panel.config.scene.caption",
|
||||
iconPath: mdiPalette,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "script",
|
||||
path: "/config/script",
|
||||
translationKey: "ui.panel.config.script.caption",
|
||||
iconPath: mdiScriptText,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "blueprint",
|
||||
path: "/config/blueprint",
|
||||
translationKey: "ui.panel.config.blueprint.caption",
|
||||
iconPath: mdiPaletteSwatch,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
tags: [
|
||||
{
|
||||
component: "tag",
|
||||
path: "/config/tags",
|
||||
translationKey: "ui.panel.config.tag.caption",
|
||||
iconPath: mdiNfcVariant,
|
||||
iconColor: "#616161",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
voice_assistants: [
|
||||
{
|
||||
path: "/config/voice-assistants",
|
||||
translationKey: "ui.panel.config.dashboard.voice_assistants.main",
|
||||
iconPath: mdiMicrophone,
|
||||
iconColor: "#3263C3",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
developer_tools: [
|
||||
{
|
||||
path: "/config/developer-tools",
|
||||
translationKey: "ui.panel.config.dashboard.developer_tools.main",
|
||||
iconPath: mdiHammer,
|
||||
iconColor: "#7A5AA6",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
energy: [
|
||||
{
|
||||
component: "energy",
|
||||
path: "/config/energy",
|
||||
translationKey: "ui.panel.config.energy.caption",
|
||||
iconPath: mdiLightningBolt,
|
||||
iconColor: "#F1C447",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
network_discovery: [
|
||||
{
|
||||
component: "dhcp",
|
||||
path: "/config/dhcp",
|
||||
translationKey: "ui.panel.config.network.discovery.dhcp",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "ssdp",
|
||||
path: "/config/ssdp",
|
||||
translationKey: "ui.panel.config.network.discovery.ssdp",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "zeroconf",
|
||||
path: "/config/zeroconf",
|
||||
translationKey: "ui.panel.config.network.discovery.zeroconf",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
integration_credentials: [
|
||||
{
|
||||
path: "/config/application_credentials",
|
||||
translationKey: "ui.panel.config.application_credentials.caption",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
integration_mqtt: [
|
||||
{
|
||||
component: "mqtt",
|
||||
path: "/config/mqtt",
|
||||
translationKey: "ui.panel.config.mqtt.title",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
lovelace: [
|
||||
{
|
||||
component: "lovelace",
|
||||
path: "/config/lovelace/dashboards",
|
||||
translationKey: "ui.panel.config.lovelace.caption",
|
||||
iconPath: mdiViewDashboard,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
persons: [
|
||||
{
|
||||
component: "person",
|
||||
path: "/config/person",
|
||||
translationKey: "ui.panel.config.person.caption",
|
||||
iconPath: mdiAccount,
|
||||
iconColor: "#5A87FA",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "users",
|
||||
path: "/config/users",
|
||||
translationKey: "ui.panel.config.users.caption",
|
||||
iconPath: mdiBadgeAccountHorizontal,
|
||||
iconColor: "#5A87FA",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
areas: [
|
||||
{
|
||||
component: "areas",
|
||||
path: "/config/areas",
|
||||
translationKey: "ui.panel.config.areas.caption",
|
||||
iconPath: mdiSofa,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "labels",
|
||||
path: "/config/labels",
|
||||
translationKey: "ui.panel.config.labels.caption",
|
||||
iconPath: mdiLabel,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "zone",
|
||||
path: "/config/zone",
|
||||
translationKey: "ui.panel.config.zone.caption",
|
||||
iconPath: mdiMapMarkerRadius,
|
||||
iconColor: "#E48629",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
general: [
|
||||
{
|
||||
path: "/config/general",
|
||||
translationKey: "core",
|
||||
iconPath: mdiCog,
|
||||
iconColor: "#653249",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/updates",
|
||||
translationKey: "updates",
|
||||
iconPath: mdiUpdate,
|
||||
iconColor: "#3B808E",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/repairs",
|
||||
translationKey: "repairs",
|
||||
iconPath: mdiScrewdriver,
|
||||
iconColor: "#5c995c",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "logs",
|
||||
path: "/config/logs",
|
||||
translationKey: "logs",
|
||||
iconPath: mdiTextBoxOutline,
|
||||
iconColor: "#C65326",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/backup",
|
||||
translationKey: "backup",
|
||||
iconPath: mdiBackupRestore,
|
||||
iconColor: "#0D47A1",
|
||||
component: "backup",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/analytics",
|
||||
translationKey: "analytics",
|
||||
iconPath: mdiShape,
|
||||
iconColor: "#f1c447",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/ai-tasks",
|
||||
translationKey: "ai_tasks",
|
||||
iconPath: mdiStarFourPoints,
|
||||
iconColor: "#8B69E3",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/labs",
|
||||
translationKey: "labs",
|
||||
iconPath: mdiFlask,
|
||||
iconColor: "#b1b134",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/network",
|
||||
translationKey: "network",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/storage",
|
||||
translationKey: "storage",
|
||||
iconPath: mdiDatabase,
|
||||
iconColor: "#518C43",
|
||||
component: "hassio",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/hardware",
|
||||
translationKey: "hardware",
|
||||
iconPath: mdiMemory,
|
||||
iconColor: "#301A8E",
|
||||
component: ["hassio", "hardware"],
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
about: [
|
||||
{
|
||||
component: "info",
|
||||
path: "/config/info",
|
||||
translationKey: "ui.panel.config.info.caption",
|
||||
iconPath: mdiInformationOutline,
|
||||
iconColor: "#4A5963",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -30,7 +30,7 @@ import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import "../components/ha-config-navigation-list";
|
||||
import "../ha-config-section";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
|
||||
@customElement("ha-config-system-navigation")
|
||||
class HaConfigSystemNavigation extends LitElement {
|
||||
|
||||
@@ -43,7 +43,7 @@ import { documentationUrl } from "../../../util/documentation-url";
|
||||
import { isMac } from "../../../util/is_mac";
|
||||
import { isMobileClient } from "../../../util/is_mobile";
|
||||
import "../ha-config-section";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import "../repairs/ha-config-repairs";
|
||||
import "./ha-config-navigation";
|
||||
import "./ha-config-updates";
|
||||
|
||||
@@ -93,7 +93,7 @@ import {
|
||||
getLabelsTableColumn,
|
||||
getModifiedAtTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
|
||||
@@ -118,7 +118,7 @@ import {
|
||||
getLabelsTableColumn,
|
||||
getModifiedAtTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import type { Helper } from "../helpers/const";
|
||||
import { isHelperDomain } from "../helpers/const";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
|
||||
@@ -1,43 +1,5 @@
|
||||
import {
|
||||
mdiAccount,
|
||||
mdiBackupRestore,
|
||||
mdiBadgeAccountHorizontal,
|
||||
mdiBluetooth,
|
||||
mdiCellphoneCog,
|
||||
mdiCog,
|
||||
mdiDatabase,
|
||||
mdiDevices,
|
||||
mdiFlask,
|
||||
mdiHammer,
|
||||
mdiInformationOutline,
|
||||
mdiLabel,
|
||||
mdiLightningBolt,
|
||||
mdiMapMarkerRadius,
|
||||
mdiMemory,
|
||||
mdiMicrophone,
|
||||
mdiNetwork,
|
||||
mdiNfcVariant,
|
||||
mdiPalette,
|
||||
mdiPaletteSwatch,
|
||||
mdiPuzzle,
|
||||
mdiRadioTower,
|
||||
mdiRemote,
|
||||
mdiRobot,
|
||||
mdiScrewdriver,
|
||||
mdiScriptText,
|
||||
mdiShape,
|
||||
mdiSofa,
|
||||
mdiStarFourPoints,
|
||||
mdiTextBoxOutline,
|
||||
mdiTools,
|
||||
mdiUpdate,
|
||||
mdiViewDashboard,
|
||||
mdiZigbee,
|
||||
mdiZWave,
|
||||
} from "@mdi/js";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { listenMediaQuery } from "../../common/dom/media_query";
|
||||
import type { CloudStatus } from "../../data/cloud";
|
||||
@@ -48,7 +10,6 @@ import {
|
||||
} from "../../data/entity/entity_registry";
|
||||
import type { RouterOptions } from "../../layouts/hass-router-page";
|
||||
import { HassRouterPage } from "../../layouts/hass-router-page";
|
||||
import type { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||
import type { HomeAssistant, Route } from "../../types";
|
||||
|
||||
declare global {
|
||||
@@ -58,521 +19,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
const getHasDomainCheck = (domain: string) => {
|
||||
const prefix = `${domain}.`;
|
||||
const checkRegistry = memoizeOne((entries: HomeAssistant["entities"]) =>
|
||||
Object.values(entries).some((entry) => entry.entity_id.startsWith(prefix))
|
||||
);
|
||||
return (hass: HomeAssistant) => checkRegistry(hass.entities);
|
||||
};
|
||||
|
||||
export const configSections: Record<string, PageNavigation[]> = {
|
||||
dashboard: [
|
||||
{
|
||||
path: "/config/integrations",
|
||||
translationKey: "devices",
|
||||
iconPath: mdiDevices,
|
||||
iconColor: "#0D47A1",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/automation",
|
||||
translationKey: "automations",
|
||||
iconPath: mdiRobot,
|
||||
iconColor: "#518C43",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/areas",
|
||||
translationKey: "areas",
|
||||
iconPath: mdiSofa,
|
||||
iconColor: "#E48629",
|
||||
component: "zone",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/apps",
|
||||
translationKey: "apps",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#F1C447",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/lovelace/dashboards",
|
||||
translationKey: "dashboards",
|
||||
iconPath: mdiViewDashboard,
|
||||
iconColor: "#B1345C",
|
||||
component: "lovelace",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/voice-assistants",
|
||||
translationKey: "voice_assistants",
|
||||
iconPath: mdiMicrophone,
|
||||
iconColor: "#3263C3",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
dashboard_external_settings: [
|
||||
{
|
||||
path: "#external-app-configuration",
|
||||
translationKey: "companion",
|
||||
iconPath: mdiCellphoneCog,
|
||||
iconColor: "#8E24AA",
|
||||
},
|
||||
],
|
||||
dashboard_2: [
|
||||
{
|
||||
path: "/config/matter",
|
||||
iconPath:
|
||||
"M7.228375 6.41685c0.98855 0.80195 2.16365 1.3412 3.416275 1.56765V1.30093l1.3612 -0.7854275 1.360125 0.7854275V7.9845c1.252875 -0.226675 2.4283 -0.765875 3.41735 -1.56765l2.471225 1.4293c-4.019075 3.976275 -10.490025 3.976275 -14.5091 0l2.482925 -1.4293Zm3.00335 17.067575c1.43325 -5.47035 -1.8052 -11.074775 -7.2604 -12.564675v2.859675c1.189125 0.455 2.244125 1.202875 3.0672 2.174275L0.25 19.2955v1.5719l1.3611925 0.781175L7.39865 18.3068c0.430175 1.19825 0.550625 2.48575 0.35015 3.743l2.482925 1.434625ZM21.034 10.91975c-5.452225 1.4932 -8.6871 7.09635 -7.254025 12.564675l2.47655 -1.43035c-0.200025 -1.257275 -0.079575 -2.544675 0.35015 -3.743025l5.7832 3.337525L23.75 20.86315V19.2955L17.961475 15.9537c0.8233 -0.97115 1.878225 -1.718975 3.0672 -2.174275l0.005325 -2.859675Z",
|
||||
iconViewBox: "0 1 24 24",
|
||||
iconColor: "#2458B3",
|
||||
component: "matter",
|
||||
translationKey: "matter",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/zha",
|
||||
iconPath: mdiZigbee,
|
||||
iconColor: "#E74011",
|
||||
component: "zha",
|
||||
translationKey: "zha",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/zwave_js",
|
||||
iconPath: mdiZWave,
|
||||
iconColor: "#153163",
|
||||
component: "zwave_js",
|
||||
translationKey: "zwave_js",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/knx",
|
||||
iconPath:
|
||||
"M 3.9861338,14.261456 3.7267552,13.934877 6.3179131,11.306266 H 4.466374 l -2.6385205,2.68258 V 11.312882 H 0.00440574 L 0,17.679803 l 1.8278535,5.43e-4 v -1.818482 l 0.7225444,-0.732459 2.1373588,2.543782 2.1869324,-5.44e-4 M 24,17.680369 21.809238,17.669359 19.885559,15.375598 17.640262,17.68037 h -1.828407 l 3.236048,-3.302138 -2.574075,-3.067547 2.135161,0.0016 1.610309,1.87687 1.866403,-1.87687 h 1.828429 l -2.857742,2.87478 m -10.589867,-2.924898 2.829625,3.990552 -0.01489,-3.977887 1.811889,-0.0044 0.0011,6.357564 -2.093314,-5.44e-4 -2.922133,-3.947594 -0.0314,3.947594 H 8.2581097 V 11.261677 M 11.971203,6.3517488 c 0,0 2.800714,-0.093203 6.172001,1.0812045 3.462393,1.0898845 5.770926,3.4695627 5.770926,3.4695627 l -1.823898,-5.43e-4 C 22.088532,10.900273 20.577938,9.4271528 17.660223,8.5024618 15.139256,7.703366 12.723057,7.645835 12.111178,7.6449876 l -9.71e-4,0.0011 c 0,0 -0.0259,-6.4e-4 -0.07527,-9.714e-4 -0.04726,3.33e-4 -0.07201,9.714e-4 -0.07201,9.714e-4 v -0.00113 C 11.337007,7.6453728 8.8132091,7.7001736 6.2821829,8.5024618 3.3627914,9.4276738 1.8521646,10.901973 1.8521646,10.901973 l -1.82398708,5.43e-4 C 0.03128403,10.899322 2.339143,8.5221038 5.799224,7.4329533 9.170444,6.2585642 11.971203,6.3517488 11.971203,6.3517488 Z",
|
||||
iconColor: "#4EAA66",
|
||||
component: "knx",
|
||||
translationKey: "knx",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/thread",
|
||||
iconPath:
|
||||
"m 17.126982,8.0730792 c 0,-0.7297242 -0.593746,-1.32357 -1.323637,-1.32357 -0.729454,0 -1.323199,0.5938458 -1.323199,1.32357 v 1.3234242 l 1.323199,1.458e-4 c 0.729891,0 1.323637,-0.5937006 1.323637,-1.32357 z M 11.999709,0 C 5.3829818,0 0,5.3838955 0,12.001455 0,18.574352 5.3105455,23.927406 11.865164,24 V 12.012075 l -3.9275642,-2.91e-4 c -1.1669814,0 -2.1169453,0.949979 -2.1169453,2.118323 0,1.16718 0.9499639,2.116868 2.1169453,2.116868 v 2.615717 c -2.6093089,0 -4.732218,-2.12327 -4.732218,-4.732585 0,-2.61048 2.1229091,-4.7343308 4.732218,-4.7343308 l 3.9275642,5.82e-4 v -1.323279 c 0,-2.172296 1.766691,-3.9395777 3.938181,-3.9395777 2.171928,0 3.9392,1.7672817 3.9392,3.9395777 0,2.1721498 -1.767272,3.9395768 -3.9392,3.9395768 l -1.323199,-1.45e-4 V 23.744102 C 19.911127,22.597726 24,17.768833 24,12.001455 24,5.3838955 18.616727,0 11.999709,0 Z",
|
||||
iconColor: "#ED7744",
|
||||
component: "thread",
|
||||
translationKey: "thread",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/bluetooth",
|
||||
iconPath: mdiBluetooth,
|
||||
iconColor: "#0082FC",
|
||||
component: "bluetooth",
|
||||
translationKey: "bluetooth",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/infrared",
|
||||
iconPath: mdiRemote,
|
||||
iconColor: "#9C27B0",
|
||||
translationKey: "infrared",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("infrared"),
|
||||
},
|
||||
{
|
||||
path: "/config/radio-frequency",
|
||||
iconPath: mdiRadioTower,
|
||||
iconColor: "#E74011",
|
||||
component: "radio_frequency",
|
||||
translationKey: "radio_frequency",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("radio_frequency"),
|
||||
},
|
||||
{
|
||||
path: "/insteon",
|
||||
iconPath:
|
||||
"m 12.001571,6.3842473 h 0.02973 c 3.652189,0 6.767389,-2.29456 7.987462,-5.5177193 L 15.389382,0 Z m 0,0 h -0.02972 c -3.6522186,0 -6.7673314,-2.2918546 -7.9874477,-5.5177193 h -0.00271 L 8.6111273,0 Z M 6.3840436,11.999287 v -0.02972 c 0,-3.6524074 -2.2944727,-6.7675928 -5.51754469,-7.9877383 L 0,8.6114473 Z m 0,0 v 0.02964 c 0,3.652378 -2.2917818,6.767578 -5.51754469,7.987796 v 0.0026 L 0,15.389818 Z M 24,8.6114473 23.133527,3.9818327 v 0.00269 C 19.907636,5.2046836 17.616,8.3198691 17.616,11.972276 v 0.02966 0.02972 0.0027 c 0,3.65232 2.2944,6.76752 5.517527,7.987738 L 24,15.392436 17.616,12.001935 Z M 20.018618,23.133527 15.389091,24 11.99872,17.615709 h 0.02964 c 3.652218,0 6.767418,2.291927 7.987491,5.517818 z M 11.99872,17.615709 8.6082618,24 3.9788364,23.133527 C 5.1989527,19.9104 8.3140655,17.615709 11.966284,17.615709 h 0.0027 z",
|
||||
iconColor: "#E4002C",
|
||||
component: "insteon",
|
||||
translationKey: "insteon",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/tags",
|
||||
translationKey: "tags",
|
||||
iconPath: mdiNfcVariant,
|
||||
iconColor: "#616161",
|
||||
component: "tag",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
dashboard_3: [
|
||||
{
|
||||
path: "/config/person",
|
||||
translationKey: "people",
|
||||
iconPath: mdiAccount,
|
||||
iconColor: "#5A87FA",
|
||||
component: ["person", "users"],
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/system",
|
||||
translationKey: "system",
|
||||
iconPath: mdiCog,
|
||||
iconColor: "#301ABE",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/developer-tools",
|
||||
translationKey: "developer_tools",
|
||||
iconPath: mdiHammer,
|
||||
iconColor: "#7A5AA6",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/info",
|
||||
translationKey: "about",
|
||||
iconPath: mdiInformationOutline,
|
||||
iconColor: "#4A5963",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
backup: [
|
||||
{
|
||||
path: "/config/backup",
|
||||
translationKey: "ui.panel.config.backup.caption",
|
||||
iconPath: mdiBackupRestore,
|
||||
iconColor: "#4084CD",
|
||||
component: "backup",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
devices: [
|
||||
{
|
||||
component: "integrations",
|
||||
path: "/config/integrations",
|
||||
translationKey: "ui.panel.config.integrations.caption",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "devices",
|
||||
path: "/config/devices",
|
||||
translationKey: "ui.panel.config.devices.caption",
|
||||
iconPath: mdiDevices,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "entities",
|
||||
path: "/config/entities",
|
||||
translationKey: "ui.panel.config.entities.caption",
|
||||
iconPath: mdiShape,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "helpers",
|
||||
path: "/config/helpers",
|
||||
translationKey: "ui.panel.config.helpers.caption",
|
||||
iconPath: mdiTools,
|
||||
iconColor: "#4D2EA4",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
automations: [
|
||||
{
|
||||
component: "automation",
|
||||
path: "/config/automation",
|
||||
translationKey: "ui.panel.config.automation.caption",
|
||||
iconPath: mdiRobot,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "scene",
|
||||
path: "/config/scene",
|
||||
translationKey: "ui.panel.config.scene.caption",
|
||||
iconPath: mdiPalette,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "script",
|
||||
path: "/config/script",
|
||||
translationKey: "ui.panel.config.script.caption",
|
||||
iconPath: mdiScriptText,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "blueprint",
|
||||
path: "/config/blueprint",
|
||||
translationKey: "ui.panel.config.blueprint.caption",
|
||||
iconPath: mdiPaletteSwatch,
|
||||
iconColor: "#518C43",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
tags: [
|
||||
{
|
||||
component: "tag",
|
||||
path: "/config/tags",
|
||||
translationKey: "ui.panel.config.tag.caption",
|
||||
iconPath: mdiNfcVariant,
|
||||
iconColor: "#616161",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
voice_assistants: [
|
||||
{
|
||||
path: "/config/voice-assistants",
|
||||
translationKey: "ui.panel.config.dashboard.voice_assistants.main",
|
||||
iconPath: mdiMicrophone,
|
||||
iconColor: "#3263C3",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
developer_tools: [
|
||||
{
|
||||
path: "/config/developer-tools",
|
||||
translationKey: "ui.panel.config.dashboard.developer_tools.main",
|
||||
iconPath: mdiHammer,
|
||||
iconColor: "#7A5AA6",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
energy: [
|
||||
{
|
||||
component: "energy",
|
||||
path: "/config/energy",
|
||||
translationKey: "ui.panel.config.energy.caption",
|
||||
iconPath: mdiLightningBolt,
|
||||
iconColor: "#F1C447",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
network_discovery: [
|
||||
{
|
||||
component: "dhcp",
|
||||
path: "/config/dhcp",
|
||||
translationKey: "ui.panel.config.network.discovery.dhcp",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "ssdp",
|
||||
path: "/config/ssdp",
|
||||
translationKey: "ui.panel.config.network.discovery.ssdp",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "zeroconf",
|
||||
path: "/config/zeroconf",
|
||||
translationKey: "ui.panel.config.network.discovery.zeroconf",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
integration_credentials: [
|
||||
{
|
||||
path: "/config/application_credentials",
|
||||
translationKey: "ui.panel.config.application_credentials.caption",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
// Not used as a tab, but this way it will stay in the quick bar
|
||||
integration_mqtt: [
|
||||
{
|
||||
component: "mqtt",
|
||||
path: "/config/mqtt",
|
||||
translationKey: "ui.panel.config.mqtt.title",
|
||||
iconPath: mdiPuzzle,
|
||||
iconColor: "#2D338F",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
lovelace: [
|
||||
{
|
||||
component: "lovelace",
|
||||
path: "/config/lovelace/dashboards",
|
||||
translationKey: "ui.panel.config.lovelace.caption",
|
||||
iconPath: mdiViewDashboard,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
persons: [
|
||||
{
|
||||
component: "person",
|
||||
path: "/config/person",
|
||||
translationKey: "ui.panel.config.person.caption",
|
||||
iconPath: mdiAccount,
|
||||
iconColor: "#5A87FA",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "users",
|
||||
path: "/config/users",
|
||||
translationKey: "ui.panel.config.users.caption",
|
||||
iconPath: mdiBadgeAccountHorizontal,
|
||||
iconColor: "#5A87FA",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
areas: [
|
||||
{
|
||||
component: "areas",
|
||||
path: "/config/areas",
|
||||
translationKey: "ui.panel.config.areas.caption",
|
||||
iconPath: mdiSofa,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "labels",
|
||||
path: "/config/labels",
|
||||
translationKey: "ui.panel.config.labels.caption",
|
||||
iconPath: mdiLabel,
|
||||
iconColor: "#2D338F",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "zone",
|
||||
path: "/config/zone",
|
||||
translationKey: "ui.panel.config.zone.caption",
|
||||
iconPath: mdiMapMarkerRadius,
|
||||
iconColor: "#E48629",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
general: [
|
||||
{
|
||||
path: "/config/general",
|
||||
translationKey: "core",
|
||||
iconPath: mdiCog,
|
||||
iconColor: "#653249",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/updates",
|
||||
translationKey: "updates",
|
||||
iconPath: mdiUpdate,
|
||||
iconColor: "#3B808E",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/repairs",
|
||||
translationKey: "repairs",
|
||||
iconPath: mdiScrewdriver,
|
||||
iconColor: "#5c995c",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
component: "logs",
|
||||
path: "/config/logs",
|
||||
translationKey: "logs",
|
||||
iconPath: mdiTextBoxOutline,
|
||||
iconColor: "#C65326",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/backup",
|
||||
translationKey: "backup",
|
||||
iconPath: mdiBackupRestore,
|
||||
iconColor: "#0D47A1",
|
||||
component: "backup",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/analytics",
|
||||
translationKey: "analytics",
|
||||
iconPath: mdiShape,
|
||||
iconColor: "#f1c447",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/ai-tasks",
|
||||
translationKey: "ai_tasks",
|
||||
iconPath: mdiStarFourPoints,
|
||||
iconColor: "#8B69E3",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/labs",
|
||||
translationKey: "labs",
|
||||
iconPath: mdiFlask,
|
||||
iconColor: "#b1b134",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/network",
|
||||
translationKey: "network",
|
||||
iconPath: mdiNetwork,
|
||||
iconColor: "#B1345C",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/storage",
|
||||
translationKey: "storage",
|
||||
iconPath: mdiDatabase,
|
||||
iconColor: "#518C43",
|
||||
component: "hassio",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/hardware",
|
||||
translationKey: "hardware",
|
||||
iconPath: mdiMemory,
|
||||
iconColor: "#301A8E",
|
||||
component: ["hassio", "hardware"],
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
about: [
|
||||
{
|
||||
component: "info",
|
||||
path: "/config/info",
|
||||
translationKey: "ui.panel.config.info.caption",
|
||||
iconPath: mdiInformationOutline,
|
||||
iconColor: "#4A5963",
|
||||
core: true,
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@customElement("ha-panel-config")
|
||||
class HaPanelConfig extends HassRouterPage {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@@ -122,7 +122,7 @@ import {
|
||||
getEntityIdTableColumn,
|
||||
getLabelsTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { renderConfigEntryError } from "../integrations/ha-config-integration-page";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
|
||||
@@ -58,7 +58,7 @@ import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
|
||||
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { isHelperDomain } from "../helpers/const";
|
||||
import "./ha-config-flow-card";
|
||||
import type { DataEntryFlowProgressExtended } from "./ha-config-integrations";
|
||||
|
||||
@@ -57,7 +57,7 @@ import {
|
||||
getCreatedAtTableColumn,
|
||||
getModifiedAtTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showLabelDetailDialog } from "./show-dialog-label-detail";
|
||||
|
||||
type ConfigTranslationKey = FlattenObjectKeys<
|
||||
|
||||
@@ -27,7 +27,7 @@ import "../../../layouts/hass-tabs-subpage";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import "../ha-config-section";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import {
|
||||
loadPersonDetailDialog,
|
||||
showPersonDetailDialog,
|
||||
|
||||
@@ -108,7 +108,7 @@ import {
|
||||
getLabelsTableColumn,
|
||||
renderRelativeTimeColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
getAssistantsSortableKey,
|
||||
|
||||
@@ -113,7 +113,7 @@ import {
|
||||
getLabelsTableColumn,
|
||||
getTriggeredAtTableColumn,
|
||||
} from "../common/data-table-columns";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
|
||||
import {
|
||||
getAssistantsSortableKey,
|
||||
|
||||
@@ -37,7 +37,7 @@ import "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showTagDetailDialog } from "./show-dialog-tag-detail";
|
||||
import "./tag-image";
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showAddUserDialog } from "./show-dialog-add-user";
|
||||
import { showUserDetailDialog } from "./show-dialog-user-detail";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
|
||||
@@ -43,7 +43,7 @@ import "../../../layouts/hass-tabs-subpage";
|
||||
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import "../ha-config-section";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { configSections } from "../config-sections";
|
||||
import { showHomeZoneDetailDialog } from "./show-dialog-home-zone-detail";
|
||||
import { showZoneDetailDialog } from "./show-dialog-zone-detail";
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { css, unsafeCSS } from "lit";
|
||||
export const fontStyles = css`
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Thin"),
|
||||
local("Roboto-Thin"),
|
||||
@@ -13,6 +14,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Thin Italic"),
|
||||
local("Roboto-ThinItalic"),
|
||||
@@ -23,6 +25,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Light"),
|
||||
local("Roboto-Light"),
|
||||
@@ -33,6 +36,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Light Italic"),
|
||||
local("Roboto-LightItalic"),
|
||||
@@ -43,6 +47,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Regular"),
|
||||
local("Roboto-Regular"),
|
||||
@@ -53,6 +58,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Italic"),
|
||||
local("Roboto-Italic"),
|
||||
@@ -63,6 +69,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Medium"),
|
||||
local("Roboto-Medium"),
|
||||
@@ -73,6 +80,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Medium Italic"),
|
||||
local("Roboto-MediumItalic"),
|
||||
@@ -83,6 +91,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Bold"),
|
||||
local("Roboto-Bold"),
|
||||
@@ -93,6 +102,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Bold Italic"),
|
||||
local("Roboto-BoldItalic"),
|
||||
@@ -103,6 +113,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Black"),
|
||||
local("Roboto-Black"),
|
||||
@@ -113,6 +124,7 @@ export const fontStyles = css`
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-display: swap;
|
||||
src:
|
||||
local("Roboto Black Italic"),
|
||||
local("Roboto-BlackItalic"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { PropertyValues } from "lit";
|
||||
import { getConfigSubpageTitle, getPanelTitleFromUrlPath } from "../data/panel";
|
||||
import { configSections } from "../panels/config/ha-panel-config";
|
||||
import { configSections } from "../panels/config/config-sections";
|
||||
import type { Constructor, HomeAssistant } from "../types";
|
||||
import type { HassBaseEl } from "./hass-base-mixin";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user