From 3ca2cbb3f921f2b727de37e463c3f0b67152443c Mon Sep 17 00:00:00 2001
From: emufan
Date: Thu, 30 Jun 2022 15:03:34 +0200
Subject: [PATCH 01/24] Update ha-config-integrations.ts
---
src/panels/config/integrations/ha-config-integrations.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts
index 6ae2d3d81f..beb0bb0cb0 100644
--- a/src/panels/config/integrations/ha-config-integrations.ts
+++ b/src/panels/config/integrations/ha-config-integrations.ts
@@ -766,7 +766,6 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
display: flex;
justify-content: flex-end;
width: 100%;
- margin-right: 8px;
align-items: center;
height: 56px;
position: sticky;
From 0f3886e053987157b23c7653bd9cbb5a6a395852 Mon Sep 17 00:00:00 2001
From: Bram Kragten
Date: Thu, 30 Jun 2022 21:41:58 +0200
Subject: [PATCH 02/24] improve autocompletion
---
src/components/ha-code-editor.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/components/ha-code-editor.ts b/src/components/ha-code-editor.ts
index 152e7a9a6f..a8f9938332 100644
--- a/src/components/ha-code-editor.ts
+++ b/src/components/ha-code-editor.ts
@@ -209,7 +209,7 @@ export class HaCodeEditor extends ReactiveElement {
private _entityCompletions(
context: CompletionContext
): CompletionResult | null | Promise {
- const entityWord = context.matchBefore(/[a-z_]{3,}\./);
+ const entityWord = context.matchBefore(/[a-z_]{3,}\.\w*/);
if (
!entityWord ||
@@ -227,7 +227,7 @@ export class HaCodeEditor extends ReactiveElement {
return {
from: Number(entityWord.from),
options: states,
- span: /^\w*.\w*$/,
+ span: /^[a-z_]{3,}\.\w*$/,
};
}
@@ -257,7 +257,7 @@ export class HaCodeEditor extends ReactiveElement {
private async _mdiCompletions(
context: CompletionContext
): Promise {
- const match = context.matchBefore(/mdi:/);
+ const match = context.matchBefore(/mdi:\S*/);
if (!match || (match.from === match.to && !context.explicit)) {
return null;
@@ -268,7 +268,7 @@ export class HaCodeEditor extends ReactiveElement {
return {
from: Number(match.from),
options: iconItems,
- span: /^\w*.\w*$/,
+ span: /^mdi:\S*$/,
};
}
From d9d29db5608ff0ece6ac424a5cccc7e16cade6df Mon Sep 17 00:00:00 2001
From: Sven Serlier <85389871+wrt54g@users.noreply.github.com>
Date: Thu, 30 Jun 2022 21:51:23 +0200
Subject: [PATCH 03/24] Fix demo labels (#13033)
---
demo/src/configs/kernehed/entities.ts | 12 ++++++------
demo/src/configs/kernehed/lovelace.ts | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/demo/src/configs/kernehed/entities.ts b/demo/src/configs/kernehed/entities.ts
index f7020ee719..193a05179d 100644
--- a/demo/src/configs/kernehed/entities.ts
+++ b/demo/src/configs/kernehed/entities.ts
@@ -797,7 +797,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 34,
on: true,
- friendly_name: "altan_motion_sensor",
+ friendly_name: "Porch motion sensor",
device_class: "motion",
},
},
@@ -818,7 +818,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 74,
on: true,
- friendly_name: "badrumssensor",
+ friendly_name: "Bathroom motion sensor",
device_class: "motion",
},
},
@@ -829,7 +829,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 47,
on: true,
dark: true,
- friendly_name: "R\u00f6relsesensor k\u00e4llaren 1",
+ friendly_name: "Basement motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -863,7 +863,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
attributes: {
battery_level: 60,
on: true,
- friendly_name: "R\u00f6relsesensor skafferiet",
+ friendly_name: "Pantry motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -875,7 +875,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 60,
on: true,
dark: true,
- friendly_name: "R\u00f6relsesensor k\u00e4llaren 2",
+ friendly_name: "Stair motion sensor",
device_class: "motion",
icon: "mdi:walk",
},
@@ -887,7 +887,7 @@ export const demoEntitiesKernehed: DemoConfig["entities"] = () =>
battery_level: 47,
on: true,
dark: true,
- friendly_name: "B\u00e4nksensor",
+ friendly_name: "Bench sensor",
device_class: "motion",
},
},
diff --git a/demo/src/configs/kernehed/lovelace.ts b/demo/src/configs/kernehed/lovelace.ts
index b8550d2b62..5d8cc442e4 100644
--- a/demo/src/configs/kernehed/lovelace.ts
+++ b/demo/src/configs/kernehed/lovelace.ts
@@ -277,7 +277,7 @@ export const demoLovelaceKernehed: DemoConfig["lovelace"] = () => ({
],
show_header_toggle: false,
type: "entities",
- title: "Bandbredd",
+ title: "Bandwidth",
},
// {
// title: "Updater",
From 198e2b7bdf051387819a873fdbcb0909ea1557df Mon Sep 17 00:00:00 2001
From: Paulus Schoutsen
Date: Fri, 1 Jul 2022 10:23:23 -0700
Subject: [PATCH 04/24] Do not show the sun during onboarding
---
src/onboarding/onboarding-integrations.ts | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/onboarding/onboarding-integrations.ts b/src/onboarding/onboarding-integrations.ts
index 1c21b94008..0bcf2ce86b 100644
--- a/src/onboarding/onboarding-integrations.ts
+++ b/src/onboarding/onboarding-integrations.ts
@@ -30,7 +30,13 @@ import { HomeAssistant } from "../types";
import "./action-badge";
import "./integration-badge";
-const HIDDEN_DOMAINS = new Set(["hassio", "met", "radio_browser", "rpi_power"]);
+const HIDDEN_DOMAINS = new Set([
+ "hassio",
+ "met",
+ "radio_browser",
+ "rpi_power",
+ "sun",
+]);
@customElement("onboarding-integrations")
class OnboardingIntegrations extends LitElement {
From 1cc02415d3d02091b086952dbc6c99929179d437 Mon Sep 17 00:00:00 2001
From: Paulus Schoutsen
Date: Fri, 1 Jul 2022 11:52:56 -0700
Subject: [PATCH 05/24] Fix rendering config entry titles (#13060)
* Fix rendering config entry titles
* Fix location height
* Only fetch installation type when user not created yet
---
src/onboarding/ha-onboarding.ts | 4 +++-
src/onboarding/onboarding-core-config.ts | 4 ++++
src/onboarding/onboarding-integrations.ts | 5 ++++-
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts
index 3c05e5b680..28de65a955 100644
--- a/src/onboarding/ha-onboarding.ts
+++ b/src/onboarding/ha-onboarding.ts
@@ -124,7 +124,6 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this._fetchOnboardingSteps();
- this._fetchInstallationType();
import("./onboarding-integrations");
import("./onboarding-core-config");
registerServiceWorker(this, false);
@@ -215,6 +214,9 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
});
history.replaceState(null, "", location.pathname);
await this._connectHass(auth);
+ } else {
+ // User creating screen needs to know the installation type.
+ this._fetchInstallationType();
}
this._steps = steps;
diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts
index b18f14653f..2abb8cc8c6 100644
--- a/src/onboarding/onboarding-core-config.ts
+++ b/src/onboarding/onboarding-core-config.ts
@@ -378,6 +378,10 @@ class OnboardingCoreConfig extends LitElement {
color: var(--secondary-text-color);
}
+ ha-locations-editor {
+ height: 200px;
+ }
+
.flex {
flex: 1;
}
diff --git a/src/onboarding/onboarding-integrations.ts b/src/onboarding/onboarding-integrations.ts
index 0bcf2ce86b..ff89d020c0 100644
--- a/src/onboarding/onboarding-integrations.ts
+++ b/src/onboarding/onboarding-integrations.ts
@@ -81,7 +81,10 @@ class OnboardingIntegrations extends LitElement {
// Render discovered and existing entries together sorted by localized title.
const entries: Array<[string, TemplateResult]> = this._entries.map(
(entry) => {
- const title = domainToName(this.hass.localize, entry.domain);
+ const title =
+ entry.title ||
+ domainToName(this.hass.localize, entry.domain) ||
+ entry.domain;
return [
title,
html`
From f3c7583bf7ec4b54cb55ec294d42294ea5041343 Mon Sep 17 00:00:00 2001
From: Franck Nijhof
Date: Fri, 1 Jul 2022 23:30:40 +0200
Subject: [PATCH 06/24] Add nightly frontend builds (#13061)
---
.github/workflows/nightly.yaml | 63 ++++++++++++++++++++++++++++++++++
script/version_bump.js | 11 +++++-
2 files changed, 73 insertions(+), 1 deletion(-)
create mode 100644 .github/workflows/nightly.yaml
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
new file mode 100644
index 0000000000..b9cace1ad1
--- /dev/null
+++ b/.github/workflows/nightly.yaml
@@ -0,0 +1,63 @@
+name: Nightly
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "0 1 * * *"
+
+env:
+ PYTHON_VERSION: 3.8
+ NODE_VERSION: 14
+ NODE_OPTIONS: --max_old_space_size=6144
+
+permissions:
+ actions: none
+
+jobs:
+ nightly:
+ name: Nightly
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v2
+
+ - name: Set up Python ${{ env.PYTHON_VERSION }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+
+ - name: Set up Node ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@v2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: yarn
+
+ - name: Install dependencies
+ run: yarn install
+
+ - name: Download translations
+ run: ./script/translations_download
+ env:
+ LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
+
+ - name: Bump version
+ run: script/version_bump.js nightly
+
+ - name: Build nightly Python wheels
+ run: |
+ pip install build
+ yarn install
+
+ script/build_frontend
+
+ rm -rf dist home_assistant_frontend.egg-info
+ python3 -m build
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v3
+ with:
+ name: wheels
+ path: dist/
+ if-no-files-found: error
diff --git a/script/version_bump.js b/script/version_bump.js
index 7796f1451a..a1c8f9c9be 100755
--- a/script/version_bump.js
+++ b/script/version_bump.js
@@ -24,10 +24,15 @@ function auto(version) {
return patch(version);
}
+function nightly() {
+ return `${today()}.dev`;
+}
+
const methods = {
patch,
today,
auto,
+ nightly,
};
async function main(args) {
@@ -57,7 +62,11 @@ async function main(args) {
console.log("Current version:", version);
console.log("New version:", newVersion);
- fs.writeFileSync("pyproject.toml", setup.replace(version, newVersion), "utf-8");
+ fs.writeFileSync(
+ "pyproject.toml",
+ setup.replace(version, newVersion),
+ "utf-8"
+ );
if (!commit) {
return;
From 07332bf155997fae782a45ffc5ef8e95d6872295 Mon Sep 17 00:00:00 2001
From: Franck Nijhof
Date: Sat, 2 Jul 2022 00:22:54 +0200
Subject: [PATCH 07/24] Fix version detection in build env to allow for nightly
builds (#13062)
---
build-scripts/env.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build-scripts/env.js b/build-scripts/env.js
index b12f20582f..e2eff4a4fa 100644
--- a/build-scripts/env.js
+++ b/build-scripts/env.js
@@ -27,7 +27,7 @@ module.exports = {
version() {
const version = fs
.readFileSync(path.resolve(paths.polymer_dir, "pyproject.toml"), "utf8")
- .match(/version\W+=\W"(\d{8}\.\d)"/);
+ .match(/version\W+=\W"(\d{8}\.\d(?:\.dev)?)"/);
if (!version) {
throw Error("Version not found");
}
From e8da573ba26b4fcf6bd461634d2a67ca86839abf Mon Sep 17 00:00:00 2001
From: Franck Nijhof
Date: Sat, 2 Jul 2022 15:49:27 +0200
Subject: [PATCH 08/24] Only upload nighlty wheel build artifact (#13064)
---
.github/workflows/nightly.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index b9cace1ad1..fa3b977b2b 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -59,5 +59,5 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: wheels
- path: dist/
+ path: dist/home_assistant_frontend*.whl
if-no-files-found: error
From 77977f64a3d3283a4eebfbd98b4821f33af3e49d Mon Sep 17 00:00:00 2001
From: Raman Gupta <7243222+raman325@users.noreply.github.com>
Date: Sun, 3 Jul 2022 16:45:19 -0400
Subject: [PATCH 09/24] Don't check zwave_js node firmware update capabilities
(#13066)
---
.../zwave_js/device-actions.ts | 21 ++-----
.../dialog-zwave_js-update-firmware-node.ts | 55 ++++++-------------
...ow-dialog-zwave_js-update-firmware-node.ts | 2 -
3 files changed, 23 insertions(+), 55 deletions(-)
diff --git a/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts b/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts
index d0843bc2ac..180d33adb0 100644
--- a/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts
+++ b/src/panels/config/devices/device-detail/integration-elements/zwave_js/device-actions.ts
@@ -2,7 +2,6 @@ import { getConfigEntries } from "../../../../../../data/config_entries";
import { DeviceRegistryEntry } from "../../../../../../data/device_registry";
import {
fetchZwaveIsAnyFirmwareUpdateInProgress,
- fetchZwaveNodeFirmwareUpdateCapabilities,
fetchZwaveNodeIsFirmwareUpdateInProgress,
fetchZwaveNodeStatus,
} from "../../../../../../data/zwave_js";
@@ -87,20 +86,13 @@ export const getZwaveDeviceActions = async (
return actions;
}
- const [
- firmwareUpdateCapabilities,
- isAnyFirmwareUpdateInProgress,
- isNodeFirmwareUpdateInProgress,
- ] = await Promise.all([
- fetchZwaveNodeFirmwareUpdateCapabilities(hass, device.id),
- fetchZwaveIsAnyFirmwareUpdateInProgress(hass, entryId),
- fetchZwaveNodeIsFirmwareUpdateInProgress(hass, device.id),
- ]);
+ const [isAnyFirmwareUpdateInProgress, isNodeFirmwareUpdateInProgress] =
+ await Promise.all([
+ fetchZwaveIsAnyFirmwareUpdateInProgress(hass, entryId),
+ fetchZwaveNodeIsFirmwareUpdateInProgress(hass, device.id),
+ ]);
- if (
- firmwareUpdateCapabilities.firmware_upgradable &&
- (!isAnyFirmwareUpdateInProgress || isNodeFirmwareUpdateInProgress)
- ) {
+ if (!isAnyFirmwareUpdateInProgress || isNodeFirmwareUpdateInProgress) {
actions.push({
label: hass.localize(
"ui.panel.config.zwave_js.device_info.update_firmware"
@@ -117,7 +109,6 @@ export const getZwaveDeviceActions = async (
) {
showZWaveJUpdateFirmwareNodeDialog(el, {
device,
- firmwareUpdateCapabilities,
});
}
},
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
index b0f76d331d..21596f649e 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
@@ -6,7 +6,6 @@ import "@material/mwc-linear-progress/mwc-linear-progress";
import { mdiCheckCircle, mdiCloseCircle, mdiFileUpload } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
-import memoizeOne from "memoize-one";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { createCloseHeading } from "../../../../../components/ha-dialog";
@@ -26,7 +25,6 @@ import {
ZWaveJSNodeFirmwareUpdateFinishedMessage,
ZWaveJSNodeFirmwareUpdateProgressMessage,
ZWaveJSNodeStatusUpdatedMessage,
- ZWaveJSNodeFirmwareUpdateCapabilities,
ZWaveJSNodeStatus,
} from "../../../../../data/zwave_js";
import { haStyleDialog } from "../../../../../resources/styles";
@@ -66,12 +64,9 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {
private _deviceName?: string;
- private _firmwareUpdateCapabilities?: ZWaveJSNodeFirmwareUpdateCapabilities;
-
public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void {
this._deviceName = computeDeviceName(params.device, this.hass!);
this.device = params.device;
- this._firmwareUpdateCapabilities = params.firmwareUpdateCapabilities;
this._fetchData();
this._subscribeNodeStatus();
}
@@ -84,7 +79,6 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {
this._updateFinishedMessage =
this._firmwareFile =
this._nodeStatus =
- this._firmwareUpdateCapabilities =
undefined;
this._firmwareTarget = 0;
this._uploading = this._updateInProgress = false;
@@ -92,34 +86,21 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
- private _schema = memoizeOne(
- (
- firmwareUpdateCapabilities: ZWaveJSNodeFirmwareUpdateCapabilities
- ): HaFormIntegerSchema => {
- if (!firmwareUpdateCapabilities.firmware_upgradable) {
- // We should never get here, this is to pass type checks
- throw new Error();
- }
- return {
- name: "firmware_target",
- type: "integer",
- valueMin: Math.min(...firmwareUpdateCapabilities.firmware_targets),
- valueMax: Math.max(...firmwareUpdateCapabilities.firmware_targets),
- };
- }
- );
-
protected render(): TemplateResult {
if (
!this.device ||
!this._nodeStatus ||
- !this._firmwareUpdateCapabilities ||
- !this._firmwareUpdateCapabilities.firmware_upgradable ||
this._updateInProgress === undefined
) {
return html``;
}
+ const schema: HaFormIntegerSchema = {
+ name: "firmware_target",
+ type: "integer",
+ valueMin: 0,
+ };
+
const beginFirmwareUpdateHTML = html`
- ${this._firmwareUpdateCapabilities.firmware_targets.length > 1
- ? html`
- ${this.hass.localize(
- "ui.panel.config.zwave_js.update_firmware.firmware_target_intro"
- )}
-
- `
- : ""}
+
+ ${this.hass.localize(
+ "ui.panel.config.zwave_js.update_firmware.firmware_target_intro"
+ )}
+
+
From f7fb731dc80a7df71569067ded90ba9492904eb0 Mon Sep 17 00:00:00 2001
From: Sven Serlier <85389871+wrt54g@users.noreply.github.com>
Date: Tue, 5 Jul 2022 09:40:57 +0200
Subject: [PATCH 10/24] Add dependabot (#13073)
Co-authored-by: Franck Nijhof
---
.github/dependabot.yml | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..b7b4ca2ddc
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: weekly
+ time: "06:00"
+ open-pull-requests-limit: 10
From 184bdc0c85cd5f640b51921e6d1e4fa630218306 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Jul 2022 10:04:02 +0200
Subject: [PATCH 11/24] Bump github/codeql-action from 1 to 2 (#13081)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/codeql-analysis.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f03f0dcbd0..7693243c0e 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -36,14 +36,14 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@v2
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -57,4 +57,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v2
From b6cc3e3ef0cf10aabefd1b4fcf6b308f0235b220 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Jul 2022 10:04:22 +0200
Subject: [PATCH 12/24] Bump actions/setup-node from 2 to 3 (#13080)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yaml | 8 ++++----
.github/workflows/demo.yaml | 2 +-
.github/workflows/nightly.yaml | 2 +-
.github/workflows/release.yaml | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 4a67ddd5a0..39ea454de1 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -21,7 +21,7 @@ jobs:
- name: Check out files from GitHub
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -45,7 +45,7 @@ jobs:
- name: Check out files from GitHub
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -64,7 +64,7 @@ jobs:
- name: Check out files from GitHub
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
@@ -83,7 +83,7 @@ jobs:
- name: Check out files from GitHub
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
diff --git a/.github/workflows/demo.yaml b/.github/workflows/demo.yaml
index 3896f292c0..1fff5c7980 100644
--- a/.github/workflows/demo.yaml
+++ b/.github/workflows/demo.yaml
@@ -16,7 +16,7 @@ jobs:
- name: Check out files from GitHub
uses: actions/checkout@v2
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index fa3b977b2b..d3fde17f62 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -29,7 +29,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index a556ef94a7..37f104d0ea 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -35,7 +35,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
cache: yarn
From 5e29c7efa9a1e5106ae89d706bca411cdc8018c0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Jul 2022 10:26:46 +0200
Subject: [PATCH 13/24] Bump dessant/lock-threads from 2.0.1 to 3.0.0 (#13077)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/lock.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml
index 4f7a0efb2d..e49906d686 100644
--- a/.github/workflows/lock.yml
+++ b/.github/workflows/lock.yml
@@ -9,7 +9,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- - uses: dessant/lock-threads@v2.0.1
+ - uses: dessant/lock-threads@v3.0.0
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: "30"
From 8fcb3a017b4de161ec9ac6558f9fc3f6a4431ef4 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Jul 2022 10:28:53 +0200
Subject: [PATCH 14/24] Bump actions/setup-python from 2 to 4 (#13078)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/nightly.yaml | 2 +-
.github/workflows/release.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index d3fde17f62..f0430c1caa 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 37f104d0ea..dd9c5e61d0 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -30,7 +30,7 @@ jobs:
uses: home-assistant/actions/helpers/verify-version@master
- name: Set up Python ${{ env.PYTHON_VERSION }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
From 30a254f98fd336ae4d7c67e1adda9726fde68fab Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Jul 2022 10:45:41 +0200
Subject: [PATCH 15/24] Bump actions/checkout from 2 to 3 (#13075)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/ci.yaml | 8 ++++----
.github/workflows/codeql-analysis.yml | 2 +-
.github/workflows/demo.yaml | 2 +-
.github/workflows/nightly.yaml | 2 +-
.github/workflows/release.yaml | 2 +-
.github/workflows/translations.yaml | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 39ea454de1..c0f6369fb2 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
@@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
@@ -62,7 +62,7 @@ jobs:
needs: [lint, test]
steps:
- name: Check out files from GitHub
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
@@ -81,7 +81,7 @@ jobs:
needs: [lint, test]
steps:
- name: Check out files from GitHub
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 7693243c0e..a15a50c233 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
diff --git a/.github/workflows/demo.yaml b/.github/workflows/demo.yaml
index 1fff5c7980..05fd6a28e0 100644
--- a/.github/workflows/demo.yaml
+++ b/.github/workflows/demo.yaml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index f0430c1caa..e272963950 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -21,7 +21,7 @@ jobs:
contents: write
steps:
- name: Checkout the repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v4
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index dd9c5e61d0..b3e7cf3d94 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -24,7 +24,7 @@ jobs:
contents: write # Required to upload release assets
steps:
- name: Checkout the repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Verify version
uses: home-assistant/actions/helpers/verify-version@master
diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml
index 3224317199..0a798b1dc4 100644
--- a/.github/workflows/translations.yaml
+++ b/.github/workflows/translations.yaml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Upload Translations
run: |
From e22dd0c49d3683412a5ac41db787a40a18de0dec Mon Sep 17 00:00:00 2001
From: Zack Barett
Date: Tue, 5 Jul 2022 04:23:46 -0500
Subject: [PATCH 16/24] Fix Energy Compare Translations (#13055)
* Fix Energy Compare Translations
* Fix alert
---
src/translations/en.json | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/translations/en.json b/src/translations/en.json
index 5d22072f24..9f10b0d264 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -4012,7 +4012,8 @@
"month": "Month",
"year": "Year",
"previous": "Previous",
- "next": "Next"
+ "next": "Next",
+ "compare": "Compare Data"
}
},
"reload_lovelace": "Reload UI"
@@ -4537,6 +4538,9 @@
}
},
"energy": {
+ "compare": {
+ "info": "You are comparing the period {start} with the period {end}"
+ },
"setup": {
"next": "Next",
"back": "Back",
From 4148b8c7aa2ff6aa0d963adc687985a6f589412a Mon Sep 17 00:00:00 2001
From: Raman Gupta <7243222+raman325@users.noreply.github.com>
Date: Tue, 5 Jul 2022 05:26:38 -0400
Subject: [PATCH 17/24] Get rid of dupe HTML in zwave_js firmware upload dialog
(#13067)
---
.../zwave_js/dialog-zwave_js-update-firmware-node.ts | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
index 21596f649e..00e4bfb437 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-update-firmware-node.ts
@@ -264,12 +264,6 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {
)}
${beginFirmwareUpdateHTML}`}
-
- ${this.hass.localize(
- "ui.panel.config.zwave_js.update_firmware.finished_status.try_again"
- )}
-
- ${beginFirmwareUpdateHTML}
`}
`;
From b70eee77ef58b010fba91520b07c27c1c84bc74d Mon Sep 17 00:00:00 2001
From: Zack Barett
Date: Tue, 5 Jul 2022 04:41:40 -0500
Subject: [PATCH 18/24] Remove config Path from about (#13049)
Co-authored-by: Bram Kragten
---
src/panels/config/info/ha-config-info.ts | 15 +--------------
src/translations/en.json | 1 -
2 files changed, 1 insertion(+), 15 deletions(-)
diff --git a/src/panels/config/info/ha-config-info.ts b/src/panels/config/info/ha-config-info.ts
index 459531f6f1..3c87a70dd7 100644
--- a/src/panels/config/info/ha-config-info.ts
+++ b/src/panels/config/info/ha-config-info.ts
@@ -165,13 +165,6 @@ class HaConfigInfo extends LitElement {
`
)}
-
- ${this.hass.localize(
- "ui.panel.config.info.path_configuration",
- "path",
- hass.config.config_dir
- )}
-
${!customUiList.length
? ""
: html`
@@ -202,7 +195,7 @@ class HaConfigInfo extends LitElement {
if (((window as any).CUSTOM_UI_LIST || []).length !== customUI.length) {
this.requestUpdate();
}
- }, 1000);
+ }, 2000);
if (isComponentLoaded(this.hass, "hassio")) {
this._loadSupervisorInfo();
@@ -291,12 +284,6 @@ class HaConfigInfo extends LitElement {
}
}
- .config-path {
- color: var(--secondary-text-color);
- text-align: center;
- font-style: italic;
- }
-
.custom-ui {
color: var(--secondary-text-color);
text-align: center;
diff --git a/src/translations/en.json b/src/translations/en.json
index 9f10b0d264..bfe9582b37 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -1593,7 +1593,6 @@
"copy_github": "For GitHub",
"description": "Version, loaded integrations and links to documentation",
"home_assistant_logo": "Home Assistant logo",
- "path_configuration": "Path to configuration.yaml: {path}",
"developed_by": "Developed by a bunch of awesome people.",
"license": "Published under the Apache 2.0 license",
"source": "Source:",
From 8fd5f53f9657cb9f35ca87d532b38b5babe078a3 Mon Sep 17 00:00:00 2001
From: Erik Montnemery
Date: Tue, 5 Jul 2022 15:49:05 +0200
Subject: [PATCH 19/24] Exclude config and diagnostic entities from scenes
(#13072)
Co-authored-by: Bram Kragten
---
src/panels/config/scene/ha-scene-editor.ts | 41 ++++++++++++++--------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts
index 7832d9116c..22bcf8e876 100644
--- a/src/panels/config/scene/ha-scene-editor.ts
+++ b/src/panels/config/scene/ha-scene-editor.ts
@@ -107,6 +107,8 @@ export class HaSceneEditor extends SubscribeMixin(
@state() private _entities: string[] = [];
+ private _single_entities: string[] = [];
+
@state() private _devices: string[] = [];
@state()
@@ -121,7 +123,7 @@ export class HaSceneEditor extends SubscribeMixin(
private _unsubscribeEvents?: () => void;
- @state() private _deviceEntityLookup: DeviceEntitiesLookup = {};
+ private _deviceEntityLookup: DeviceEntitiesLookup = {};
private _activateContextId?: string;
@@ -520,9 +522,11 @@ export class HaSceneEditor extends SubscribeMixin(
}
if (changedProps.has("_entityRegistryEntries")) {
+ this._deviceEntityLookup = {};
for (const entity of this._entityRegistryEntries) {
if (
!entity.device_id ||
+ entity.entity_category ||
SCENE_IGNORED_DOMAINS.includes(computeDomain(entity.entity_id))
) {
continue;
@@ -530,13 +534,10 @@ export class HaSceneEditor extends SubscribeMixin(
if (!(entity.device_id in this._deviceEntityLookup)) {
this._deviceEntityLookup[entity.device_id] = [];
}
- if (
- !this._deviceEntityLookup[entity.device_id].includes(entity.entity_id)
- ) {
- this._deviceEntityLookup[entity.device_id].push(entity.entity_id);
- }
+ this._deviceEntityLookup[entity.device_id].push(entity.entity_id);
if (
this._entities.includes(entity.entity_id) &&
+ !this._single_entities.includes(entity.device_id) &&
!this._devices.includes(entity.device_id)
) {
this._devices = [...this._devices, entity.device_id];
@@ -625,12 +626,24 @@ export class HaSceneEditor extends SubscribeMixin(
private _initEntities(config: SceneConfig) {
this._entities = Object.keys(config.entities);
this._entities.forEach((entity) => this._storeState(entity));
+ this._single_entities = [];
const filteredEntityReg = this._entityRegistryEntries.filter((entityReg) =>
this._entities.includes(entityReg.entity_id)
);
const newDevices: string[] = [];
+ if (config.metadata) {
+ Object.keys(config.entities).forEach((entity) => {
+ if (
+ !this._single_entities.includes(entity) &&
+ config.metadata![entity].entity_only
+ ) {
+ this._single_entities.push(entity);
+ }
+ });
+ }
+
for (const entityReg of filteredEntityReg) {
if (!entityReg.device_id) {
continue;
@@ -654,6 +667,7 @@ export class HaSceneEditor extends SubscribeMixin(
return;
}
this._entities = [...this._entities, entityId];
+ this._single_entities.push(entityId);
this._storeState(entityId);
this._dirty = true;
}
@@ -664,6 +678,9 @@ export class HaSceneEditor extends SubscribeMixin(
this._entities = this._entities.filter(
(entityId) => entityId !== deleteEntityId
);
+ this._single_entities = this._single_entities.filter(
+ (entityId) => entityId !== deleteEntityId
+ );
this._dirty = true;
}
@@ -815,19 +832,15 @@ export class HaSceneEditor extends SubscribeMixin(
private _calculateMetaData(): SceneMetaData {
const output: SceneMetaData = {};
- for (const entityReg of this._entityRegistryEntries) {
- if (!this._entities.includes(entityReg.entity_id)) {
- continue;
- }
-
- const entityState = this._getCurrentState(entityReg.entity_id);
+ for (const entityId of this._single_entities) {
+ const entityState = this._getCurrentState(entityId);
if (!entityState) {
continue;
}
- output[entityReg.entity_id] = {
- entity_only: !this._devices.includes(entityReg.device_id!),
+ output[entityId] = {
+ entity_only: true,
};
}
From 6cd38472cd2e1a6ab6a15aed8605f417e595dad9 Mon Sep 17 00:00:00 2001
From: D3v01dZA
Date: Tue, 5 Jul 2022 10:23:38 -0400
Subject: [PATCH 20/24] Multiple entities on history panel bugfix and
additional improvements (#13045)
Co-authored-by: Zack Barett
---
src/components/chart/state-history-charts.ts | 1 +
src/components/ha-target-picker.ts | 199 ++++++++--------
src/panels/history/ha-panel-history.ts | 233 +++++++++++++------
src/translations/en.json | 5 +
4 files changed, 276 insertions(+), 162 deletions(-)
diff --git a/src/components/chart/state-history-charts.ts b/src/components/chart/state-history-charts.ts
index b00fb19cdf..415ecbb4e7 100644
--- a/src/components/chart/state-history-charts.ts
+++ b/src/components/chart/state-history-charts.ts
@@ -186,6 +186,7 @@ class StateHistoryCharts extends LitElement {
line-height: 60px;
color: var(--secondary-text-color);
}
+
.container {
max-height: var(--history-max-height);
}
diff --git a/src/components/ha-target-picker.ts b/src/components/ha-target-picker.ts
index 7545a19a36..b98d969d05 100644
--- a/src/components/ha-target-picker.ts
+++ b/src/components/ha-target-picker.ts
@@ -42,8 +42,8 @@ import "./entity/ha-entity-picker";
import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker";
import "./ha-area-picker";
import "./ha-icon-button";
-import "./ha-svg-icon";
import "./ha-input-helper-text";
+import "./ha-svg-icon";
@customElement("ha-target-picker")
export class HaTargetPicker extends SubscribeMixin(LitElement) {
@@ -119,55 +119,68 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
if (!this._areas || !this._devices || !this._entities) {
return html``;
}
- return html`
- ${this.horizontal ? this._renderChips() : this._renderItems()}
- ${this._renderPicker()}
- ${this.horizontal ? this._renderItems() : this._renderChips()}
-
`;
+ return html`
+ ${this.horizontal
+ ? html`
+
+ ${this._renderChips()} ${this._renderPicker()}
+
+ ${this._renderItems()}
+ `
+ : html`
+
+ ${this._renderItems()} ${this._renderPicker()}
+ ${this._renderChips()}
+
+ `}
+ `;
}
private _renderItems() {
- return html`
- ${this.value?.area_id
- ? ensureArray(this.value.area_id).map((area_id) => {
- const area = this._areas![area_id];
- return this._renderChip(
- "area_id",
- area_id,
- area?.name || area_id,
- undefined,
- mdiSofa
- );
- })
- : ""}
- ${this.value?.device_id
- ? ensureArray(this.value.device_id).map((device_id) => {
- const device = this._devices![device_id];
- return this._renderChip(
- "device_id",
- device_id,
- device ? computeDeviceName(device, this.hass) : device_id,
- undefined,
- mdiDevices
- );
- })
- : ""}
- ${this.value?.entity_id
- ? ensureArray(this.value.entity_id).map((entity_id) => {
- const entity = this.hass.states[entity_id];
- return this._renderChip(
- "entity_id",
- entity_id,
- entity ? computeStateName(entity) : entity_id,
- entity
- );
- })
- : ""}
-
`;
+ return html`
+
+ ${this.value?.area_id
+ ? ensureArray(this.value.area_id).map((area_id) => {
+ const area = this._areas![area_id];
+ return this._renderChip(
+ "area_id",
+ area_id,
+ area?.name || area_id,
+ undefined,
+ mdiSofa
+ );
+ })
+ : ""}
+ ${this.value?.device_id
+ ? ensureArray(this.value.device_id).map((device_id) => {
+ const device = this._devices![device_id];
+ return this._renderChip(
+ "device_id",
+ device_id,
+ device ? computeDeviceName(device, this.hass) : device_id,
+ undefined,
+ mdiDevices
+ );
+ })
+ : ""}
+ ${this.value?.entity_id
+ ? ensureArray(this.value.entity_id).map((entity_id) => {
+ const entity = this.hass.states[entity_id];
+ return this._renderChip(
+ "entity_id",
+ entity_id,
+ entity ? computeStateName(entity) : entity_id,
+ entity
+ );
+ })
+ : ""}
+
+ `;
}
private _renderChips() {
- return html`
+ return html`
+
${this.helper
? html`
${this.helper}`
- : ""} `;
+ : ""}
+ `;
}
private async _showPicker(ev) {
@@ -320,51 +334,54 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
private _renderPicker() {
switch (this._addMode) {
case "area_id":
- return html`
`;
+ return html`
+
+ `;
case "device_id":
- return html`
`;
+ return html`
+
+ `;
case "entity_id":
- return html`
`;
+ return html`
+
+ `;
}
return html``;
}
@@ -553,12 +570,6 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
static get styles(): CSSResultGroup {
return css`
${unsafeCSS(chipStyles)}
- .hidden-picker {
- height: 0px;
- display: inline-block;
- overflow: hidden;
- position: absolute;
- }
.horizontal-container {
display: flex;
flex-wrap: wrap;
diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts
index 9deb2cf1b1..83a5dba36b 100644
--- a/src/panels/history/ha-panel-history.ts
+++ b/src/panels/history/ha-panel-history.ts
@@ -1,4 +1,4 @@
-import { mdiRefresh } from "@mdi/js";
+import { mdiCollapseAll, mdiRefresh } from "@mdi/js";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import {
@@ -34,6 +34,10 @@ import {
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../../data/entity_registry";
+import {
+ DeviceRegistryEntry,
+ subscribeDeviceRegistry,
+} from "../../data/device_registry";
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
import { computeStateName } from "../../common/entity/compute_state_name";
import { computeDomain } from "../../common/entity/compute_domain";
@@ -57,9 +61,23 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
@state() private _ranges?: DateRangePickerRanges;
- @state() private _entities?: EntityRegistryEntry[];
+ @state() private _devices?: { [deviceId: string]: DeviceRegistryEntry };
- @state() private _stateEntities?: EntityRegistryEntry[];
+ @state() private _entities?: { [entityId: string]: EntityRegistryEntry };
+
+ @state() private _stateEntities?: { [entityId: string]: EntityRegistryEntry };
+
+ @state() private _deviceIdToEntities?: {
+ [deviceId: string]: EntityRegistryEntry[];
+ };
+
+ @state() private _areaIdToEntities?: {
+ [areaId: string]: EntityRegistryEntry[];
+ };
+
+ @state() private _areaIdToDevices?: {
+ [areaId: string]: DeviceRegistryEntry[];
+ };
public constructor() {
super();
@@ -76,7 +94,52 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
public hassSubscribe(): UnsubscribeFunc[] {
return [
subscribeEntityRegistry(this.hass.connection!, (entities) => {
- this._entities = entities;
+ this._entities = entities.reduce((accumulator, current) => {
+ accumulator[current.entity_id] = current;
+ return accumulator;
+ }, {});
+ this._deviceIdToEntities = entities.reduce((accumulator, current) => {
+ if (!current.device_id) {
+ return accumulator;
+ }
+ let found = accumulator[current.device_id];
+ if (found === undefined) {
+ found = [];
+ accumulator[current.device_id] = found;
+ }
+ found.push(current);
+ return accumulator;
+ }, {});
+ this._areaIdToEntities = entities.reduce((accumulator, current) => {
+ if (!current.area_id) {
+ return accumulator;
+ }
+ let found = accumulator[current.area_id];
+ if (found === undefined) {
+ found = [];
+ accumulator[current.area_id] = found;
+ }
+ found.push(current);
+ return accumulator;
+ }, {});
+ }),
+ subscribeDeviceRegistry(this.hass.connection!, (devices) => {
+ this._devices = devices.reduce((accumulator, current) => {
+ accumulator[current.id] = current;
+ return accumulator;
+ }, {});
+ this._areaIdToDevices = devices.reduce((accumulator, current) => {
+ if (!current.area_id) {
+ return accumulator;
+ }
+ let found = accumulator[current.area_id];
+ if (found === undefined) {
+ found = [];
+ accumulator[current.area_id] = found;
+ }
+ found.push(current);
+ return accumulator;
+ }, {});
}),
];
}
@@ -91,6 +154,12 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
.narrow=${this.narrow}
>
${this.hass.localize("panel.history")}
+
`
+ : !this._targetPickerValue
+ ? html`
+ ${this.hass.localize("ui.panel.history.start_search")}
+
`
: html`
`}
- ${this._isLoading
- ? html`
-
-
`
- : html`
-
-
- `}
`;
}
@@ -199,8 +254,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
if (
changedProps.has("_startDate") ||
changedProps.has("_endDate") ||
- changedProps.has("_targetPickerValue") ||
- changedProps.has("_entities")
+ changedProps.has("_targetPickerValue")
) {
this._getHistory();
}
@@ -211,15 +265,13 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this.rtl = computeRTL(this.hass);
}
if (this._entities) {
- const stateEntities: EntityRegistryEntry[] = [];
- const regEntityIds = new Set(
- this._entities.map((entity) => entity.entity_id)
- );
+ const stateEntities: { [entityId: string]: EntityRegistryEntry } = {};
+ const regEntityIds = new Set(Object.keys(this._entities));
for (const entityId of Object.keys(this.hass.states)) {
if (regEntityIds.has(entityId)) {
continue;
}
- stateEntities.push({
+ stateEntities[entityId] = {
name: computeStateName(this.hass.states[entityId]),
entity_id: entityId,
platform: computeDomain(entityId),
@@ -230,17 +282,27 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
device_id: null,
icon: null,
entity_category: null,
- });
+ };
}
this._stateEntities = stateEntities;
}
}
}
+ private _removeAll() {
+ this._targetPickerValue = undefined;
+ }
+
private _refreshHistory() {
this._getHistory();
}
+ private _shouldShowEntityByLargerSelection(
+ entity: EntityRegistryEntry
+ ): boolean {
+ return entity.entity_category === null;
+ }
+
private async _getHistory() {
this._isLoading = true;
const entityIds = this._getEntityIds();
@@ -261,50 +323,79 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._isLoading = false;
}
- private _filterEntity(entity: EntityRegistryEntry): boolean {
- const { area_id, device_id, entity_id } = this._targetPickerValue;
- if (area_id !== undefined) {
- if (typeof area_id === "string" && area_id === entity.area_id) {
- return true;
- }
- if (Array.isArray(area_id) && area_id.includes(entity.area_id)) {
- return true;
- }
- }
- if (device_id !== undefined) {
- if (typeof device_id === "string" && device_id === entity.device_id) {
- return true;
- }
- if (Array.isArray(device_id) && device_id.includes(entity.device_id)) {
- return true;
- }
- }
- if (entity_id !== undefined) {
- if (typeof entity_id === "string" && entity_id === entity.entity_id) {
- return true;
- }
- if (Array.isArray(entity_id) && entity_id.includes(entity.entity_id)) {
- return true;
- }
- }
- return false;
- }
-
private _getEntityIds(): string[] {
if (
this._targetPickerValue === undefined ||
this._entities === undefined ||
- this._stateEntities === undefined
+ this._stateEntities === undefined ||
+ this._devices === undefined ||
+ this._deviceIdToEntities === undefined ||
+ this._areaIdToEntities === undefined ||
+ this._areaIdToDevices === undefined
) {
return [];
}
- const entityIds = this._entities
- .filter((entity) => this._filterEntity(entity))
- .map((entity) => entity.entity_id);
- const stateEntityIds = this._stateEntities
- .filter((entity) => this._filterEntity(entity))
- .map((entity) => entity.entity_id);
- return [...entityIds, ...stateEntityIds];
+ const entityIds = new Set
();
+ let {
+ area_id: searchingAreaId,
+ device_id: searchingDeviceId,
+ entity_id: searchingEntityId,
+ } = this._targetPickerValue;
+ if (searchingAreaId !== undefined) {
+ if (typeof searchingAreaId === "string") {
+ searchingAreaId = [searchingAreaId];
+ }
+ for (const singleSearchingAreaId of searchingAreaId) {
+ const foundEntities = this._areaIdToEntities[singleSearchingAreaId];
+ if (foundEntities !== undefined) {
+ for (const foundEntity of foundEntities) {
+ if (this._shouldShowEntityByLargerSelection(foundEntity)) {
+ entityIds.add(foundEntity.entity_id);
+ }
+ }
+ }
+ const foundDevices = this._areaIdToDevices[singleSearchingAreaId];
+ if (foundDevices !== undefined) {
+ for (const foundDevice of foundDevices) {
+ const foundDeviceEntities =
+ this._deviceIdToEntities[foundDevice.id];
+ for (const foundDeviceEntity of foundDeviceEntities) {
+ if (
+ (!foundDeviceEntity.area_id ||
+ foundDeviceEntity.area_id === singleSearchingAreaId) &&
+ this._shouldShowEntityByLargerSelection(foundDeviceEntity)
+ ) {
+ entityIds.add(foundDeviceEntity.entity_id);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (searchingDeviceId !== undefined) {
+ if (typeof searchingDeviceId === "string") {
+ searchingDeviceId = [searchingDeviceId];
+ }
+ for (const singleSearchingDeviceId of searchingDeviceId) {
+ const foundEntities = this._deviceIdToEntities[singleSearchingDeviceId];
+ if (foundEntities !== undefined) {
+ for (const foundEntity of foundEntities) {
+ if (this._shouldShowEntityByLargerSelection(foundEntity)) {
+ entityIds.add(foundEntity.entity_id);
+ }
+ }
+ }
+ }
+ }
+ if (searchingEntityId !== undefined) {
+ if (typeof searchingEntityId === "string") {
+ searchingEntityId = [searchingEntityId];
+ }
+ for (const singleSearchingEntityId of searchingEntityId) {
+ entityIds.add(singleSearchingEntityId);
+ }
+ }
+ return [...entityIds];
}
private _dateRangeChanged(ev) {
@@ -389,7 +480,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
.filters {
display: flex;
- align-items: flex-end;
+ align-items: flex-start;
padding: 8px 16px 0;
}
@@ -429,6 +520,12 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
max-width: none;
width: 100%;
}
+
+ .start-search {
+ padding-top: 16px;
+ text-align: center;
+ color: var(--secondary-text-color);
+ }
`,
];
}
diff --git a/src/translations/en.json b/src/translations/en.json
index bfe9582b37..cc53fac488 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -4559,6 +4559,11 @@
"energy_sources_table_title": "Sources",
"energy_devices_graph_title": "Monitor individual devices"
}
+ },
+ "history": {
+ "start_search": "Start by selecting an area, device or entity above",
+ "add_all": "Add all entities",
+ "remove_all": "Remove all selections"
}
},
"tips": {
From b285fda61bcfc833d8d457c447c7b96806e1d9fa Mon Sep 17 00:00:00 2001
From: Zack Barett
Date: Tue, 5 Jul 2022 10:15:09 -0500
Subject: [PATCH 21/24] Move Sign out back to Account Card for Cloud (#13094)
---
.../config/cloud/account/cloud-account.ts | 116 ++++++++----------
.../config/cloud/account/cloud-tts-pref.ts | 4 +
2 files changed, 52 insertions(+), 68 deletions(-)
diff --git a/src/panels/config/cloud/account/cloud-account.ts b/src/panels/config/cloud/account/cloud-account.ts
index 46293adf67..e3a8fbd494 100644
--- a/src/panels/config/cloud/account/cloud-account.ts
+++ b/src/panels/config/cloud/account/cloud-account.ts
@@ -1,7 +1,5 @@
import "@material/mwc-button";
-import type { ActionDetail } from "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
-import { mdiDotsVertical } from "@mdi/js";
import "@polymer/paper-item/paper-item-body";
import { css, html, LitElement, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
@@ -11,9 +9,7 @@ import { computeRTLDirection } from "../../../../common/util/compute_rtl";
import { debounce } from "../../../../common/util/debounce";
import "../../../../components/buttons/ha-call-api-button";
import "../../../../components/ha-alert";
-import "../../../../components/ha-button-menu";
import "../../../../components/ha-card";
-import "../../../../components/ha-icon-button";
import {
cloudLogout,
CloudStatusLoggedIn,
@@ -23,6 +19,7 @@ import {
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
import "../../../../layouts/hass-subpage";
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
+import { haStyle } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types";
import "../../ha-config-section";
import "./cloud-alexa-pref";
@@ -52,23 +49,6 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
.narrow=${this.narrow}
header="Home Assistant Cloud"
>
-
-
-
-
- ${this.hass.localize("ui.panel.config.cloud.account.sign_out")}
-
-
-
Home Assistant Cloud
@@ -156,6 +136,11 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
)}
+
+ ${this.hass.localize(
+ "ui.panel.config.cloud.account.sign_out"
+ )}
+
@@ -279,18 +264,15 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
}
}
- private async _handleMenuAction(ev: CustomEvent) {
- switch (ev.detail.index) {
- case 0:
- showConfirmationDialog(this, {
- text: this.hass.localize(
- "ui.panel.config.cloud.account.sign_out_confirm"
- ),
- confirmText: this.hass!.localize("ui.common.yes"),
- dismissText: this.hass!.localize("ui.common.no"),
- confirm: () => this._logoutFromCloud(),
- });
- }
+ private async _signOut() {
+ showConfirmationDialog(this, {
+ text: this.hass.localize(
+ "ui.panel.config.cloud.account.sign_out_confirm"
+ ),
+ confirmText: this.hass!.localize("ui.common.yes"),
+ dismissText: this.hass!.localize("ui.common.no"),
+ confirm: () => this._logoutFromCloud(),
+ });
}
private async _logoutFromCloud() {
@@ -303,41 +285,39 @@ export class CloudAccount extends SubscribeMixin(LitElement) {
}
static get styles() {
- return css`
- [slot="introduction"] {
- margin: -1em 0;
- }
- [slot="introduction"] a {
- color: var(--primary-color);
- }
- .content {
- padding-bottom: 24px;
- }
- .account-row {
- display: flex;
- padding: 0 16px;
- }
- .card-actions {
- display: flex;
- flex-direction: row-reverse;
- }
- .card-actions a {
- text-decoration: none;
- }
- mwc-button {
- align-self: center;
- }
- .wrap {
- white-space: normal;
- }
- .status {
- text-transform: capitalize;
- padding: 16px;
- }
- a {
- color: var(--primary-color);
- }
- `;
+ return [
+ haStyle,
+ css`
+ [slot="introduction"] {
+ margin: -1em 0;
+ }
+ [slot="introduction"] a {
+ color: var(--primary-color);
+ }
+ .content {
+ padding-bottom: 24px;
+ }
+ .account-row {
+ display: flex;
+ padding: 0 16px;
+ }
+ .card-actions {
+ display: flex;
+ flex-direction: row-reverse;
+ justify-content: space-between;
+ }
+ mwc-button {
+ align-self: center;
+ }
+ .wrap {
+ white-space: normal;
+ }
+ .status {
+ text-transform: capitalize;
+ padding: 16px;
+ }
+ `,
+ ];
}
}
diff --git a/src/panels/config/cloud/account/cloud-tts-pref.ts b/src/panels/config/cloud/account/cloud-tts-pref.ts
index c5eaea962f..6856595d96 100644
--- a/src/panels/config/cloud/account/cloud-tts-pref.ts
+++ b/src/panels/config/cloud/account/cloud-tts-pref.ts
@@ -185,6 +185,10 @@ export class CloudTTSPref extends LitElement {
right: auto;
left: 24px;
}
+ .card-actions {
+ display: flex;
+ flex-direction: row-reverse;
+ }
`;
}
}
From 5038f9c3c61d1e27ca4bbd6e591342b8037f39e2 Mon Sep 17 00:00:00 2001
From: Zack Barett
Date: Tue, 5 Jul 2022 10:31:17 -0500
Subject: [PATCH 22/24] Some Updates to the History Panel (#13095)
---
src/components/ha-target-picker.ts | 2 +
src/panels/history/ha-panel-history.ts | 223 ++++++++++++++-----------
2 files changed, 127 insertions(+), 98 deletions(-)
diff --git a/src/components/ha-target-picker.ts b/src/components/ha-target-picker.ts
index b98d969d05..8df2bea571 100644
--- a/src/components/ha-target-picker.ts
+++ b/src/components/ha-target-picker.ts
@@ -573,6 +573,8 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
.horizontal-container {
display: flex;
flex-wrap: wrap;
+ min-height: 56px;
+ align-items: center;
}
.mdc-chip {
color: var(--primary-text-color);
diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts
index 83a5dba36b..06d8be2834 100644
--- a/src/panels/history/ha-panel-history.ts
+++ b/src/panels/history/ha-panel-history.ts
@@ -10,9 +10,12 @@ import {
startOfWeek,
startOfYesterday,
} from "date-fns/esm";
+import { UnsubscribeFunc } from "home-assistant-js-websocket/dist/types";
import { css, html, LitElement, PropertyValues } from "lit";
import { property, state } from "lit/decorators";
-import { UnsubscribeFunc } from "home-assistant-js-websocket/dist/types";
+import { LocalStorage } from "../../common/decorators/local-storage";
+import { computeDomain } from "../../common/entity/compute_domain";
+import { computeStateName } from "../../common/entity/compute_state_name";
import { navigate } from "../../common/navigate";
import {
createSearchParam,
@@ -20,45 +23,43 @@ import {
} from "../../common/url/search-params";
import { computeRTL } from "../../common/util/compute_rtl";
import "../../components/chart/state-history-charts";
-import "../../components/ha-target-picker";
import "../../components/ha-circular-progress";
import "../../components/ha-date-range-picker";
import type { DateRangePickerRanges } from "../../components/ha-date-range-picker";
import "../../components/ha-icon-button";
import "../../components/ha-menu-button";
-import { computeHistory, fetchDateWS } from "../../data/history";
-import "../../layouts/ha-app-layout";
-import { haStyle } from "../../resources/styles";
-import { HomeAssistant } from "../../types";
-import {
- EntityRegistryEntry,
- subscribeEntityRegistry,
-} from "../../data/entity_registry";
+import "../../components/ha-target-picker";
import {
DeviceRegistryEntry,
subscribeDeviceRegistry,
} from "../../data/device_registry";
+import {
+ EntityRegistryEntry,
+ subscribeEntityRegistry,
+} from "../../data/entity_registry";
+import { computeHistory, fetchDateWS } from "../../data/history";
+import "../../layouts/ha-app-layout";
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
-import { computeStateName } from "../../common/entity/compute_state_name";
-import { computeDomain } from "../../common/entity/compute_domain";
+import { haStyle } from "../../resources/styles";
+import { HomeAssistant } from "../../types";
class HaPanelHistory extends SubscribeMixin(LitElement) {
- @property() hass!: HomeAssistant;
+ @property({ attribute: false }) hass!: HomeAssistant;
@property({ reflect: true, type: Boolean }) narrow!: boolean;
- @property() _startDate: Date;
-
- @property() _endDate: Date;
-
- @property() _targetPickerValue?;
-
- @property() _isLoading = false;
-
- @property() _stateHistory?;
-
@property({ reflect: true, type: Boolean }) rtl = false;
+ @state() private _startDate: Date;
+
+ @state() private _endDate: Date;
+
+ @LocalStorage("historyPickedValue", true, false) private _targetPickerValue?;
+
+ @state() private _isLoading = false;
+
+ @state() private _stateHistory?;
+
@state() private _ranges?: DateRangePickerRanges;
@state() private _devices?: { [deviceId: string]: DeviceRegistryEntry };
@@ -154,14 +155,18 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
.narrow=${this.narrow}
>
${this.hass.localize("panel.history")}
+ ${this._targetPickerValue
+ ? html`
+
+ `
+ : ""}
-
Date: Tue, 5 Jul 2022 11:38:24 -0500
Subject: [PATCH 23/24] Update MDI to v6.9.96 (#13096)
---
package.json | 4 ++--
yarn.lock | 20 ++++++++++----------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/package.json b/package.json
index 76028454a6..b0f426ea1c 100644
--- a/package.json
+++ b/package.json
@@ -72,8 +72,8 @@
"@material/mwc-textfield": "0.25.3",
"@material/mwc-top-app-bar-fixed": "^0.25.3",
"@material/top-app-bar": "14.0.0-canary.261f2db59.0",
- "@mdi/js": "6.7.96",
- "@mdi/svg": "6.7.96",
+ "@mdi/js": "6.9.96",
+ "@mdi/svg": "6.9.96",
"@polymer/app-layout": "^3.1.0",
"@polymer/iron-flex-layout": "^3.0.1",
"@polymer/iron-icon": "^3.0.1",
diff --git a/yarn.lock b/yarn.lock
index 492b213e6e..d21c1833a5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2975,17 +2975,17 @@ __metadata:
languageName: node
linkType: hard
-"@mdi/js@npm:6.7.96":
- version: 6.7.96
- resolution: "@mdi/js@npm:6.7.96"
- checksum: 8c8f6acb8fd3f856a92ffe2405e258ee5aa84cf541fda1c0a564c9c8bbf935cf2b6a6100cf97d41e9ada1ccb59e4b138d4c712e075f759d7595e21ef1cff84b5
+"@mdi/js@npm:6.9.96":
+ version: 6.9.96
+ resolution: "@mdi/js@npm:6.9.96"
+ checksum: 94c43271585981e7ebf8cc5e3ead11915eea1339b79e849b351fbaae58e9626aaca0a8b031f0e80754d880ea6b08fd715906588f3cf980603bb5f6871bff12cc
languageName: node
linkType: hard
-"@mdi/svg@npm:6.7.96":
- version: 6.7.96
- resolution: "@mdi/svg@npm:6.7.96"
- checksum: 959332009b8833d0347e2dfac86028362a6d11996db850025b7da8c493d7fd341a14d8716ef775dd2ed0492158c77236bcf09adfc4ae77b31044a0a8a26fc74b
+"@mdi/svg@npm:6.9.96":
+ version: 6.9.96
+ resolution: "@mdi/svg@npm:6.9.96"
+ checksum: 3e45f9a6632b0aa22f02ab0023d44131e3aea308bae85160445fe1f8f0b6d61df5c01e2756d18bd1461f7314fbf7c00a397bf99670f55803d90de5fa8e3fe33e
languageName: node
linkType: hard
@@ -9047,8 +9047,8 @@ fsevents@^1.2.7:
"@material/mwc-textfield": 0.25.3
"@material/mwc-top-app-bar-fixed": ^0.25.3
"@material/top-app-bar": 14.0.0-canary.261f2db59.0
- "@mdi/js": 6.7.96
- "@mdi/svg": 6.7.96
+ "@mdi/js": 6.9.96
+ "@mdi/svg": 6.9.96
"@open-wc/dev-server-hmr": ^0.0.2
"@polymer/app-layout": ^3.1.0
"@polymer/iron-flex-layout": ^3.0.1
From 153ebb2a2073dc8d13155e99f8f88f432658cbe9 Mon Sep 17 00:00:00 2001
From: Zack Barett
Date: Tue, 5 Jul 2022 11:40:26 -0500
Subject: [PATCH 24/24] Bumped version to 20220705.0 (#13098)
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 9d88995977..08a642995e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
-version = "20220630.0"
+version = "20220705.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"