From 4ea19a6041f746beadb8ce89fb9e1b9f02a7c471 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 8 Dec 2022 15:41:51 +0100 Subject: [PATCH 01/25] Add daily gallery build action (#14640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joakim Sørensen --- .github/workflows/gallery.yaml | 41 ++++++++++++++++++++++++++++ .github/workflows/netflify.yml | 3 -- gallery/script/netlify_build_gallery | 3 +- 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/gallery.yaml diff --git a/.github/workflows/gallery.yaml b/.github/workflows/gallery.yaml new file mode 100644 index 0000000000..9d50bbec0f --- /dev/null +++ b/.github/workflows/gallery.yaml @@ -0,0 +1,41 @@ +name: Gallery + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +env: + NODE_VERSION: 16 + NODE_OPTIONS: --max_old_space_size=6144 + +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: Production + url: ${{ steps.deploy.outputs.NETLIFY_URL }} + steps: + - name: Check out files from GitHub + uses: actions/checkout@v3 + - name: Set up Node ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: yarn + - name: Install dependencies + run: yarn install + env: + CI: true + - name: Build Gallery + run: ./node_modules/.bin/gulp build-gallery + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Deploy to Netlify + id: deploy + uses: netlify/actions/cli@master + with: + args: deploy --dir=gallery/dist --prod + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_GALLERY_SITE_ID }} diff --git a/.github/workflows/netflify.yml b/.github/workflows/netflify.yml index 51989057ba..64b70d7b04 100644 --- a/.github/workflows/netflify.yml +++ b/.github/workflows/netflify.yml @@ -14,6 +14,3 @@ jobs: - name: Trigger Demo build run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }} - - - name: Trigger Design build - run: curl -X POST -d "NIGHTLY" https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_GALLERY_DEV_BUILD_HOOK }} diff --git a/gallery/script/netlify_build_gallery b/gallery/script/netlify_build_gallery index db8be615d1..97c95ebf2a 100755 --- a/gallery/script/netlify_build_gallery +++ b/gallery/script/netlify_build_gallery @@ -1,6 +1,7 @@ #!/bin/bash TARGET_LABEL="needs design preview" +export SKIP_FETCH_NIGHTLY_TRANSLATIONS="true" if [[ "$NETLIFY" != "true" ]]; then echo "This script can only be run on Netlify" @@ -30,6 +31,4 @@ if [[ "${PULL_REQUEST}" == "true" ]]; then else createStatus "success" "Build was not requested by PR label" fi -elif [[ "$INCOMING_HOOK_BODY" == "NIGHTLY" ]]; then - gulp build-gallery fi From 2d30994e5667ba54dcd0950da3b5244eaa577c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Thu, 8 Dec 2022 17:17:28 +0100 Subject: [PATCH 02/25] Adjust demo deployment (#14649) --- .../{demo.yaml => demo_deployment.yaml} | 17 +++++++++++++++-- .github/workflows/netflify.yml | 3 +-- 2 files changed, 16 insertions(+), 4 deletions(-) rename .github/workflows/{demo.yaml => demo_deployment.yaml} (73%) diff --git a/.github/workflows/demo.yaml b/.github/workflows/demo_deployment.yaml similarity index 73% rename from .github/workflows/demo.yaml rename to .github/workflows/demo_deployment.yaml index 9ff90402f6..aa489d0ba6 100644 --- a/.github/workflows/demo.yaml +++ b/.github/workflows/demo_deployment.yaml @@ -1,6 +1,9 @@ -name: Demo +name: Demo deployment on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" push: branches: - dev @@ -12,24 +15,34 @@ env: jobs: deploy: runs-on: ubuntu-latest + environment: + name: Demo + url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL }} steps: - name: Check out files from GitHub uses: actions/checkout@v3 + - name: Set up Node ${{ env.NODE_VERSION }} uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} cache: yarn + - name: Install dependencies run: yarn install env: CI: true + - name: Build Demo run: ./node_modules/.bin/gulp build-demo env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Deploy to Netlify - run: npx netlify-cli deploy --dir=demo/dist --prod + id: deploy + uses: netlify/actions/cli@master + with: + args: deploy --dir=demo/dist --prod env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_DEMO_DEV_SITE_ID }} diff --git a/.github/workflows/netflify.yml b/.github/workflows/netflify.yml index 64b70d7b04..fc554a813a 100644 --- a/.github/workflows/netflify.yml +++ b/.github/workflows/netflify.yml @@ -12,5 +12,4 @@ jobs: - name: Trigger Cast build run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_CAST_DEV_BUILD_HOOK }} - - name: Trigger Demo build - run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_DEMO_DEV_BUILD_HOOK }} + From b84de87688451a33aaad59174353eae116b50628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Thu, 8 Dec 2022 17:17:56 +0100 Subject: [PATCH 03/25] Adjust design deployment (#14650) --- .../{gallery.yaml => design_deployment.yaml} | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) rename .github/workflows/{gallery.yaml => design_deployment.yaml} (88%) diff --git a/.github/workflows/gallery.yaml b/.github/workflows/design_deployment.yaml similarity index 88% rename from .github/workflows/gallery.yaml rename to .github/workflows/design_deployment.yaml index 9d50bbec0f..e152f7b4c1 100644 --- a/.github/workflows/gallery.yaml +++ b/.github/workflows/design_deployment.yaml @@ -1,4 +1,4 @@ -name: Gallery +name: Design deployment on: workflow_dispatch: @@ -12,25 +12,29 @@ env: jobs: deploy: runs-on: ubuntu-latest - environment: - name: Production - url: ${{ steps.deploy.outputs.NETLIFY_URL }} + environment: + name: Design + url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL }} steps: - name: Check out files from GitHub uses: actions/checkout@v3 + - name: Set up Node ${{ env.NODE_VERSION }} uses: actions/setup-node@v3 with: node-version: ${{ env.NODE_VERSION }} cache: yarn + - name: Install dependencies run: yarn install env: CI: true + - name: Build Gallery run: ./node_modules/.bin/gulp build-gallery env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Deploy to Netlify id: deploy uses: netlify/actions/cli@master From 3c8c1260b172cb2ef01328070e1c900b2cd3d4dc Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 8 Dec 2022 19:23:43 +0100 Subject: [PATCH 04/25] Show start pause button on tile card if vacuum support pause (#14646) --- .../lovelace/tile-features/hui-vacuum-commands-tile-feature.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts index d3f9565881..6c19958a77 100644 --- a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts @@ -40,7 +40,7 @@ export const VACUUM_COMMANDS_FEATURES: Record< VacuumCommand, VacuumEntityFeature[] > = { - start_pause: [VacuumEntityFeature.PAUSE], + start_pause: [VacuumEntityFeature.PAUSE, VacuumEntityFeature.START], stop: [VacuumEntityFeature.STOP], clean_spot: [VacuumEntityFeature.CLEAN_SPOT], locate: [VacuumEntityFeature.LOCATE], From 23573d8c2605ea6cee8a80fea4b5ec5313166ff4 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Fri, 9 Dec 2022 16:04:14 +0100 Subject: [PATCH 05/25] Theme color fixes (#14672) * Split off and unavailable colors * off and unvailable in history panel * Refactor tile card color code * Use new color in state badge * Use new colors in button and entity card * Rename off to inactive * Add inactive color to color picker * Use amber instead of blue --- src/common/color/compute-color.ts | 1 + src/common/entity/color/sensor_color.ts | 4 +- src/common/entity/state_color.ts | 22 +++++++---- src/common/style/icon_color_css.ts | 2 +- .../chart/timeline-chart/timeline-color.ts | 12 +++++- src/components/entity/state-badge.ts | 37 ++++++++++--------- src/panels/lovelace/cards/hui-button-card.ts | 32 +++++++++------- src/panels/lovelace/cards/hui-entity-card.ts | 33 ++++++++--------- src/panels/lovelace/cards/hui-tile-card.ts | 26 +++++-------- src/resources/ha-style.ts | 19 ++++++---- src/resources/styles.ts | 3 +- src/translations/en.json | 1 + 12 files changed, 105 insertions(+), 87 deletions(-) diff --git a/src/common/color/compute-color.ts b/src/common/color/compute-color.ts index e7e3409a9d..40b43c44d4 100644 --- a/src/common/color/compute-color.ts +++ b/src/common/color/compute-color.ts @@ -4,6 +4,7 @@ export const THEME_COLORS = new Set([ "primary", "accent", "disabled", + "inactive", "red", "pink", "purple", diff --git a/src/common/entity/color/sensor_color.ts b/src/common/entity/color/sensor_color.ts index 5da0eeb0a2..298f996f26 100644 --- a/src/common/entity/color/sensor_color.ts +++ b/src/common/entity/color/sensor_color.ts @@ -3,12 +3,12 @@ import { batteryStateColor } from "./battery_color"; export const sensorColor = ( stateObj: HassEntity, - compareState: string + state: string ): string | undefined => { const deviceClass = stateObj?.attributes.device_class; if (deviceClass === "battery") { - return batteryStateColor(compareState); + return batteryStateColor(state); } return undefined; diff --git a/src/common/entity/state_color.ts b/src/common/entity/state_color.ts index 4cf278e231..6da45f1ee1 100644 --- a/src/common/entity/state_color.ts +++ b/src/common/entity/state_color.ts @@ -1,5 +1,6 @@ /** Return an color representing a state. */ import { HassEntity } from "home-assistant-js-websocket"; +import { UNAVAILABLE } from "../../data/entity"; import { UpdateEntity, updateIsInstalling } from "../../data/update"; import { alarmControlPanelColor } from "./color/alarm_control_panel_color"; import { binarySensorColor } from "./color/binary_sensor_color"; @@ -30,18 +31,23 @@ const STATIC_COLORED_DOMAIN = new Set([ "vacuum", ]); -export const stateColorCss = (stateObj?: HassEntity, state?: string) => { - if (!stateObj || !stateActive(stateObj, state)) { - return `var(--rgb-disabled-color)`; +export const stateColorCss = (stateObj: HassEntity, state?: string) => { + const compareState = state !== undefined ? state : stateObj?.state; + if (compareState === UNAVAILABLE) { + return `var(--rgb-state-unavailable-color)`; } - const color = stateColor(stateObj, state); - - if (color) { - return `var(--rgb-state-${color}-color)`; + if (!stateActive(stateObj, state)) { + return `var(--rgb-state-inactive-color)`; } - return `var(--rgb-state-default-color)`; + const domainColor = stateColor(stateObj, state); + + if (domainColor) { + return `var(--rgb-state-${domainColor}-color)`; + } + + return undefined; }; export const stateColor = (stateObj: HassEntity, state?: string) => { diff --git a/src/common/style/icon_color_css.ts b/src/common/style/icon_color_css.ts index 8e5f66d90c..fef56682b5 100644 --- a/src/common/style/icon_color_css.ts +++ b/src/common/style/icon_color_css.ts @@ -21,6 +21,6 @@ export const iconColorCSS = css` /* Color the icon if unavailable */ ha-state-icon[data-state="unavailable"] { - color: var(--state-unavailable-color); + color: rgb(var(--rgb-state-unavailable-color)); } `; diff --git a/src/components/chart/timeline-chart/timeline-color.ts b/src/components/chart/timeline-chart/timeline-color.ts index 012c9315f6..52e2283aa5 100644 --- a/src/components/chart/timeline-chart/timeline-color.ts +++ b/src/components/chart/timeline-chart/timeline-color.ts @@ -5,6 +5,7 @@ import { labBrighten } from "../../../common/color/lab"; import { computeDomain } from "../../../common/entity/compute_domain"; import { stateActive } from "../../../common/entity/state_active"; import { stateColor } from "../../../common/entity/state_color"; +import { UNAVAILABLE } from "../../../data/entity"; const DOMAIN_STATE_SHADES: Record> = { media_player: { @@ -49,11 +50,18 @@ function computeTimelineStateColor( computedStyles: CSSStyleDeclaration, stateObj?: HassEntity ): string | undefined { - if (!stateObj || !stateActive(stateObj, state)) { - const rgb = cssToRgb("--rgb-disabled-color", computedStyles); + if (!stateObj || state === UNAVAILABLE) { + const rgb = cssToRgb("--rgb-state-unavailable-color", computedStyles); if (!rgb) return undefined; return rgb2hex(rgb); } + + if (!stateActive(stateObj, state)) { + const rgb = cssToRgb("--rgb-state-inactive-color", computedStyles); + if (!rgb) return undefined; + return rgb2hex(rgb); + } + const color = stateColor(stateObj, state); if (!color) return undefined; diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts index 30022f677f..50458e1f88 100644 --- a/src/components/entity/state-badge.ts +++ b/src/components/entity/state-badge.ts @@ -14,7 +14,7 @@ import { styleMap } from "lit/directives/style-map"; import { computeDomain } from "../../common/entity/compute_domain"; import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { stateActive } from "../../common/entity/state_active"; -import { stateColor } from "../../common/entity/state_color"; +import { stateColorCss } from "../../common/entity/state_color"; import { iconColorCSS } from "../../common/style/icon_color_css"; import { cameraUrlWithWidthHeight } from "../../data/camera"; import type { HomeAssistant } from "../../types"; @@ -107,24 +107,27 @@ export class StateBadge extends LitElement { } hostStyle.backgroundImage = `url(${imageUrl})`; this._showIcon = false; - } else if (stateActive(stateObj) && this._stateColor) { - const iconColor = stateColor(stateObj); - if (stateObj.attributes.rgb_color) { - iconStyle.color = `rgb(${stateObj.attributes.rgb_color.join(",")})`; - } else if (iconColor) { - iconStyle.color = `rgb(var(--rgb-state-${iconColor}-color))`; + } else if (this._stateColor) { + const color = stateColorCss(stateObj); + if (color) { + iconStyle.color = `rgb(${color})`; } - if (stateObj.attributes.brightness) { - const brightness = stateObj.attributes.brightness; - if (typeof brightness !== "number") { - const errorMessage = `Type error: state-badge expected number, but type of ${ - stateObj.entity_id - }.attributes.brightness is ${typeof brightness} (${brightness})`; - // eslint-disable-next-line - console.warn(errorMessage); + if (stateActive(stateObj)) { + if (stateObj.attributes.rgb_color) { + iconStyle.color = `rgb(${stateObj.attributes.rgb_color.join(",")})`; + } + if (stateObj.attributes.brightness) { + const brightness = stateObj.attributes.brightness; + if (typeof brightness !== "number") { + const errorMessage = `Type error: state-badge expected number, but type of ${ + stateObj.entity_id + }.attributes.brightness is ${typeof brightness} (${brightness})`; + // eslint-disable-next-line + console.warn(errorMessage); + } + // lowest brightness will be around 50% (that's pretty dark) + iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; } - // lowest brightness will be around 50% (that's pretty dark) - iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; } } } else if (this.overrideImage) { diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts index 3e274f957a..480d86f542 100644 --- a/src/panels/lovelace/cards/hui-button-card.ts +++ b/src/panels/lovelace/cards/hui-button-card.ts @@ -26,7 +26,7 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { stateActive } from "../../../common/entity/state_active"; -import { stateColor } from "../../../common/entity/state_color"; +import { stateColorCss } from "../../../common/entity/state_color"; import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { iconColorCSS } from "../../../common/style/icon_color_css"; import "../../../components/ha-card"; @@ -79,6 +79,15 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { @state() private _shouldRenderRipple = false; + private getStateColor(stateObj: HassEntity, config: ButtonCardConfig) { + const domain = stateObj ? computeStateDomain(stateObj) : undefined; + return ( + config && + (config.state_color || + (domain === "light" && config.state_color !== false)) + ); + } + public getCardSize(): number { return ( (this._config?.show_icon ? 4 : 0) + (this._config?.show_name ? 1 : 0) @@ -146,13 +155,9 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { const name = this._config.show_name ? this._config.name || (stateObj ? computeStateName(stateObj) : "") : ""; - const domain = stateObj ? computeStateDomain(stateObj) : undefined; - const active = - (this._config.state_color || - (domain === "light" && this._config.state_color !== false)) && - stateObj && - stateActive(stateObj); + const colored = stateObj && this.getStateColor(stateObj, this._config); + const active = stateObj && colored && stateActive(stateObj); return html` @@ -141,7 +148,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { data-domain=${ifDefined(domain)} data-state=${stateObj.state} style=${styleMap({ - color: active ? this._computeColor(stateObj) : "", + color: colored ? this._computeColor(stateObj) : undefined, height: this._config.icon_height ? this._config.icon_height : "", @@ -187,19 +194,9 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { } private _computeColor(stateObj: HassEntity | LightEntity): string { - const domain = computeStateDomain(stateObj); - if ( - !( - this._config?.state_color || - (domain === "light" && this._config?.state_color !== false) - ) || - !stateActive(stateObj) - ) { - return ""; - } - const iconColor = stateColor(stateObj); + const iconColor = stateColorCss(stateObj); if (iconColor) { - return `rgb(var(--rgb-state-${iconColor}-color))`; + return `rgb(${iconColor})`; } return ""; } diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 52c8b9b96a..4ca720e34b 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -9,7 +9,6 @@ import { hsv2rgb, rgb2hsv } from "../../../common/color/convert-color"; import { DOMAINS_TOGGLE } from "../../../common/const"; import { computeDomain } from "../../../common/entity/compute_domain"; import { computeStateDisplay } from "../../../common/entity/compute_state_display"; -import { stateActive } from "../../../common/entity/state_active"; import { stateColorCss } from "../../../common/entity/state_color"; import { stateIconPath } from "../../../common/entity/state_icon_path"; import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; @@ -129,8 +128,9 @@ export class HuiTileCard extends LitElement implements LovelaceCard { } private _computeStateColor = memoize((entity: HassEntity, color?: string) => { - if (UNAVAILABLE_STATES.includes(entity.state)) { - return undefined; + // Use custom color + if (color) { + return computeRgbColor(color); } // Use default color for person/device_tracker because color is on the badge @@ -141,16 +141,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard { return "var(--rgb-state-default-color)"; } - if (!stateActive(entity)) { - return undefined; - } - - if (color) { - return computeRgbColor(color); - } - - let stateColor = stateColorCss(entity); - + // Use light color if the light support rgb if ( computeDomain(entity.entity_id) === "light" && entity.attributes.rgb_color @@ -166,10 +157,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard { hsvColor[1] = 0.4; } } - stateColor = hsv2rgb(hsvColor).join(","); + return hsv2rgb(hsvColor).join(","); } - return stateColor; + // Fallback to state color + return stateColorCss(entity) ?? "var(--rgb-state-default-color)"; }); private _computeStateDisplay(stateObj: HassEntity): TemplateResult | string { @@ -360,7 +352,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard { static get styles(): CSSResultGroup { return css` :host { - --tile-color: var(--rgb-disabled-color); + --tile-color: var(--rgb-state-default-color); --tile-tap-padding: 6px; -webkit-tap-highlight-color: transparent; } @@ -368,7 +360,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard { height: 100%; } ha-card.disabled { - background: rgba(var(--rgb-disabled-color), 0.1); + background: rgba(var(--rgb-state-unavailable-color), 0.1); } [role="button"] { cursor: pointer; diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 63ed84aa9a..b8adeee7d3 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -107,6 +107,7 @@ documentContainer.innerHTML = ` --rgb-primary-color: 3, 169, 244; --rgb-accent-color: 255, 152, 0; --rgb-disabled-color: 189, 189, 189; + --rgb-inactive-color: 114, 114, 114; --rgb-primary-text-color: 33, 33, 33; --rgb-secondary-text-color: 114, 114, 114; --rgb-text-primary-color: 255, 255, 255; @@ -134,7 +135,11 @@ documentContainer.innerHTML = ` --rgb-white-color: 255, 255, 255; /* rgb state color */ - --rgb-state-default-color: 68, 115, 158; + --rgb-state-default-color: var(--rgb-dark-primary-color, 68, 115, 158); + --rgb-state-unavailable-color: var(--rgb-disabled-color); + --rgb-state-inactive-color: var(--rgb-inactive-color); + + /* rgb state color */ --rgb-state-alarm-armed-color: var(--rgb-red-color); --rgb-state-alarm-arming-color: var(--rgb-orange-color); --rgb-state-alarm-pending-color: var(--rgb-orange-color); @@ -142,16 +147,16 @@ documentContainer.innerHTML = ` --rgb-state-alert-color: var(--rgb-red-color); --rgb-state-automation-color: var(--rgb-amber-color); --rgb-state-binary-sensor-alerting-color: var(--rgb-red-color); - --rgb-state-binary-sensor-color: var(--rgb-blue-color); - --rgb-state-calendar-color: var(--rgb-blue-color); - --rgb-state-camera-color: var(--rgb-blue-color); + --rgb-state-binary-sensor-color: var(--rgb-amber-color); + --rgb-state-calendar-color: var(--rgb-amber-color); + --rgb-state-camera-color: var(--rgb-amber-color); --rgb-state-climate-auto-color: var(--rgb-green-color); --rgb-state-climate-cool-color: var(--rgb-blue-color); --rgb-state-climate-dry-color: var(--rgb-orange-color); --rgb-state-climate-fan-only-color: var(--rgb-cyan-color); --rgb-state-climate-heat-color: var(--rgb-deep-orange-color); --rgb-state-climate-heat-cool-color: var(--rgb-amber-color); - --rgb-state-climate-idle-color: var(--rgb-disabled-color); + --rgb-state-climate-idle-color: var(--rgb-off-color); --rgb-state-cover-color: var(--rgb-purple-color); --rgb-state-fan-color: var(--rgb-cyan-color); --rgb-state-group-color: var(--rgb-amber-color); @@ -164,12 +169,12 @@ documentContainer.innerHTML = ` --rgb-state-media-player-color: var(--rgb-indigo-color); --rgb-state-person-home-color: var(--rgb-green-color); --rgb-state-person-zone-color: var(--rgb-blue-color); - --rgb-state-remote-color: var(--rgb-blue-color); + --rgb-state-remote-color: var(--rgb-amber-color); --rgb-state-script-color: var(--rgb-amber-color); --rgb-state-sensor-battery-high-color: var(--rgb-green-color); --rgb-state-sensor-battery-low-color: var(--rgb-red-color); --rgb-state-sensor-battery-medium-color: var(--rgb-orange-color); - --rgb-state-sensor-battery-unknown-color: var(--rgb-disabled-color); + --rgb-state-sensor-battery-unknown-color: var(--rgb-off-color); --rgb-state-siren-color: var(--rgb-red-color); --rgb-state-sun-day-color: var(--rgb-amber-color); --rgb-state-sun-night-color: var(--rgb-deep-purple-color); diff --git a/src/resources/styles.ts b/src/resources/styles.ts index 83ddd066dc..4b49cf06aa 100644 --- a/src/resources/styles.ts +++ b/src/resources/styles.ts @@ -48,7 +48,8 @@ export const darkStyles = { "energy-grid-return-color": "#a280db", "map-filter": "invert(.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) saturate(.3)", - "rgb-disabled-color": "111, 111, 111", + "rgb-disabled-color": "70, 70, 70", + "rgb-inactive-color": "141, 141, 141", }; export const derivedStyles = { diff --git a/src/translations/en.json b/src/translations/en.json index 008434e0c5..029113a66c 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4349,6 +4349,7 @@ "primary": "Primary", "accent": "Accent", "disabled": "Disabled", + "inactive": "Inactive", "red": "Red", "pink": "Pink", "purple": "Purple", From 9643e0268fd9102f161c8ababd9050120228eb9d Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Fri, 9 Dec 2022 21:56:57 +0100 Subject: [PATCH 06/25] Add new atmospheric pressure device class (#14596) --- src/common/const.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/const.ts b/src/common/const.ts index 8f9902c31e..8b920274a0 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -53,6 +53,7 @@ import { mdiSineWave, mdiSpeedometer, mdiThermometer, + mdiThermometerLines, mdiThermostat, mdiTimerOutline, mdiVideo, @@ -126,6 +127,7 @@ export const FIXED_DOMAIN_ICONS = { export const FIXED_DEVICE_CLASS_ICONS = { apparent_power: mdiFlash, aqi: mdiAirFilter, + atmospheric_pressure: mdiThermometerLines, // battery: mdiBattery, => not included by design since `sensorIcon()` will dynamically determine the icon carbon_dioxide: mdiMoleculeCo2, carbon_monoxide: mdiMoleculeCo, From 3f1903bd87ce2cad0cb7968c1e045ed78840279a Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Fri, 9 Dec 2022 21:57:28 +0100 Subject: [PATCH 07/25] Add new irradiance device class (#14593) --- src/common/const.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/const.ts b/src/common/const.ts index 8b920274a0..f9ed0e8ff6 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -52,6 +52,7 @@ import { mdiScriptText, mdiSineWave, mdiSpeedometer, + mdiSunWireless, mdiThermometer, mdiThermometerLines, mdiThermostat, @@ -140,6 +141,7 @@ export const FIXED_DEVICE_CLASS_ICONS = { gas: mdiMeterGas, humidity: mdiWaterPercent, illuminance: mdiBrightness5, + irradiance: mdiSunWireless, moisture: mdiWaterPercent, monetary: mdiCash, nitrogen_dioxide: mdiMolecule, From 6e4a6cb0db76d3909755bfbf89680db0e99471d1 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Sat, 10 Dec 2022 03:38:59 +0100 Subject: [PATCH 08/25] Improve person/alarm/lock state (#14633) * Opening device_class as alerting * Don't use blue color for default active color * Improve lock colors * Green color for disarmed alarm * Revert "Opening device_class as alerting" This reverts commit b78342678d430eb3967f82e759342955b44417ad. * Don't use active color * Revert amber color because fixed in another PR * Improve person, lock and alarm color state * Sort variables * Use alarm color in alarm card --- .../entity/color/alarm_control_panel_color.ts | 2 ++ src/common/entity/color/lock_color.ts | 2 ++ src/common/entity/color/person_color.ts | 2 ++ src/common/entity/state_active.ts | 6 +++--- src/common/entity/state_color.ts | 15 +++++++++------ .../chart/timeline-chart/timeline-color.ts | 11 ++++------- .../lovelace/cards/hui-alarm-panel-card.ts | 17 ++++++----------- .../cards/tile/badges/tile-badge-person.ts | 6 +++--- src/resources/ha-style.ts | 16 +++++++--------- 9 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/common/entity/color/alarm_control_panel_color.ts b/src/common/entity/color/alarm_control_panel_color.ts index ef72805c11..deb8846088 100644 --- a/src/common/entity/color/alarm_control_panel_color.ts +++ b/src/common/entity/color/alarm_control_panel_color.ts @@ -13,6 +13,8 @@ export const alarmControlPanelColor = (state?: string): string | undefined => { return "alarm-arming"; case "triggered": return "alarm-triggered"; + case "disarmed": + return "alarm-disarmed"; default: return undefined; } diff --git a/src/common/entity/color/lock_color.ts b/src/common/entity/color/lock_color.ts index faecef1288..6d0ec06665 100644 --- a/src/common/entity/color/lock_color.ts +++ b/src/common/entity/color/lock_color.ts @@ -1,5 +1,7 @@ export const lockColor = (state?: string): string | undefined => { switch (state) { + case "unlocked": + return "lock-unlocked"; case "locked": return "lock-locked"; case "jammed": diff --git a/src/common/entity/color/person_color.ts b/src/common/entity/color/person_color.ts index e1158ab8e1..efdabbd33d 100644 --- a/src/common/entity/color/person_color.ts +++ b/src/common/entity/color/person_color.ts @@ -2,6 +2,8 @@ export const personColor = (state: string): string | undefined => { switch (state) { case "home": return "person-home"; + case "not_home": + return "person-not-home"; default: return "person-zone"; } diff --git a/src/common/entity/state_active.ts b/src/common/entity/state_active.ts index 5bd58e9f2c..415be5f055 100644 --- a/src/common/entity/state_active.ts +++ b/src/common/entity/state_active.ts @@ -16,15 +16,15 @@ export function stateActive(stateObj: HassEntity, state?: string): boolean { // Custom cases switch (domain) { + case "alarm_control_panel": + return compareState !== "disarmed"; case "cover": return !["closed", "closing"].includes(compareState); case "device_tracker": case "person": return compareState !== "not_home"; - case "alarm_control_panel": - return compareState !== "disarmed"; case "lock": - return compareState !== "unlocked"; + return compareState !== "locked"; case "media_player": return compareState !== "standby"; case "vacuum": diff --git a/src/common/entity/state_color.ts b/src/common/entity/state_color.ts index 6da45f1ee1..aed20531e3 100644 --- a/src/common/entity/state_color.ts +++ b/src/common/entity/state_color.ts @@ -11,7 +11,7 @@ import { sensorColor } from "./color/sensor_color"; import { computeDomain } from "./compute_domain"; import { stateActive } from "./state_active"; -const STATIC_COLORED_DOMAIN = new Set([ +const STATIC_ACTIVE_COLORED_DOMAIN = new Set([ "alert", "automation", "calendar", @@ -37,16 +37,16 @@ export const stateColorCss = (stateObj: HassEntity, state?: string) => { return `var(--rgb-state-unavailable-color)`; } - if (!stateActive(stateObj, state)) { - return `var(--rgb-state-inactive-color)`; - } - const domainColor = stateColor(stateObj, state); if (domainColor) { return `var(--rgb-state-${domainColor}-color)`; } + if (!stateActive(stateObj, state)) { + return `var(--rgb-state-inactive-color)`; + } + return undefined; }; @@ -54,7 +54,10 @@ export const stateColor = (stateObj: HassEntity, state?: string) => { const compareState = state !== undefined ? state : stateObj?.state; const domain = computeDomain(stateObj.entity_id); - if (STATIC_COLORED_DOMAIN.has(domain)) { + if ( + STATIC_ACTIVE_COLORED_DOMAIN.has(domain) && + stateActive(stateObj, state) + ) { return domain.replace("_", "-"); } diff --git a/src/components/chart/timeline-chart/timeline-color.ts b/src/components/chart/timeline-chart/timeline-color.ts index 52e2283aa5..a61ad01e08 100644 --- a/src/components/chart/timeline-chart/timeline-color.ts +++ b/src/components/chart/timeline-chart/timeline-color.ts @@ -56,22 +56,19 @@ function computeTimelineStateColor( return rgb2hex(rgb); } - if (!stateActive(stateObj, state)) { + const color = stateColor(stateObj, state); + + if (!color && !stateActive(stateObj, state)) { const rgb = cssToRgb("--rgb-state-inactive-color", computedStyles); if (!rgb) return undefined; return rgb2hex(rgb); } - const color = stateColor(stateObj, state); - - if (!color) return undefined; - - const domain = computeDomain(stateObj.entity_id); - const rgb = cssToRgb(`--rgb-state-${color}-color`, computedStyles); if (!rgb) return undefined; + const domain = computeDomain(stateObj.entity_id); const shade = DOMAIN_STATE_SHADES[domain]?.[state] as number | number; if (!shade) { return rgb2hex(rgb); diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.ts b/src/panels/lovelace/cards/hui-alarm-panel-card.ts index 84f1d3b103..b9d01da1c0 100644 --- a/src/panels/lovelace/cards/hui-alarm-panel-card.ts +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.ts @@ -269,12 +269,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { flex-direction: column; align-items: center; box-sizing: border-box; - --alarm-color-disarmed: var(--label-badge-green); - --alarm-color-pending: var(--label-badge-yellow); - --alarm-color-triggered: var(--label-badge-red); - --alarm-color-armed: var(--label-badge-red); - --alarm-color-autoarm: rgba(0, 153, 255, 0.1); - --alarm-state-color: var(--alarm-color-armed); + --alarm-state-color: rgb(var(--rgb-state-alarm-armed-color)); } ha-chip { @@ -292,25 +287,25 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { } .unavailable { - --alarm-state-color: var(--state-unavailable-color); + --alarm-state-color: rgb(var(--rgb-state-unavailable-color)); } .disarmed { - --alarm-state-color: var(--alarm-color-disarmed); + --alarm-state-color: rgb(var(--rgb-state-alarm-disarmed-color)); } .triggered { - --alarm-state-color: var(--alarm-color-triggered); + --alarm-state-color: rgb(var(--rgb-state-alarm-trigger-color)); animation: pulse 1s infinite; } .arming { - --alarm-state-color: var(--alarm-color-pending); + --alarm-state-color: rgb(var(--rgb-state-alarm-arming-color)); animation: pulse 1s infinite; } .pending { - --alarm-state-color: var(--alarm-color-pending); + --alarm-state-color: rgb(var(--rgb-state-alarm-pending-color)); animation: pulse 1s infinite; } diff --git a/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts b/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts index 6770366acd..d4ad3d64c0 100644 --- a/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts +++ b/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts @@ -22,11 +22,11 @@ function personBadgeIcon(entity: HassEntity) { function personBadgeColor(entity: HassEntity) { switch (entity.state) { case "home": - return "var(--rgb-badge-person-home-color)"; + return "var(--rgb-state-person-home-color)"; case "not_home": - return "var(--rgb-badge-person-not-home-color)"; + return "var(--rgb-state-person-not-home-color)"; default: - return "var(--rgb-badge-person-zone-color)"; + return "var(--rgb-state-person-zone-color)"; } } diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index b8adeee7d3..b4720c1d82 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -136,12 +136,13 @@ documentContainer.innerHTML = ` /* rgb state color */ --rgb-state-default-color: var(--rgb-dark-primary-color, 68, 115, 158); - --rgb-state-unavailable-color: var(--rgb-disabled-color); --rgb-state-inactive-color: var(--rgb-inactive-color); + --rgb-state-unavailable-color: var(--rgb-disabled-color); - /* rgb state color */ - --rgb-state-alarm-armed-color: var(--rgb-red-color); + /* rgb state domain colors */ + --rgb-state-alarm-armed-color: var(--rgb-green-color); --rgb-state-alarm-arming-color: var(--rgb-orange-color); + --rgb-state-alarm-disarmed-color: var(--rgb-inactive-color); --rgb-state-alarm-pending-color: var(--rgb-orange-color); --rgb-state-alarm-triggered-color: var(--rgb-red-color); --rgb-state-alert-color: var(--rgb-red-color); @@ -164,10 +165,12 @@ documentContainer.innerHTML = ` --rgb-state-input-boolean-color: var(--rgb-amber-color); --rgb-state-light-color: var(--rgb-amber-color); --rgb-state-lock-jammed-color: var(--rgb-red-color); - --rgb-state-lock-locked-color: var(--rgb-red-color); + --rgb-state-lock-locked-color: var(--rgb-green-color); --rgb-state-lock-pending-color: var(--rgb-orange-color); + --rgb-state-lock-unlocked-color: var(--rgb-red-color); --rgb-state-media-player-color: var(--rgb-indigo-color); --rgb-state-person-home-color: var(--rgb-green-color); + --rgb-state-person-not-home-color: var(--rgb-inactive-color); --rgb-state-person-zone-color: var(--rgb-blue-color); --rgb-state-remote-color: var(--rgb-amber-color); --rgb-state-script-color: var(--rgb-amber-color); @@ -184,11 +187,6 @@ documentContainer.innerHTML = ` --rgb-state-update-installing-color: var(--rgb-orange-color); --rgb-state-vacuum-color: var(--rgb-teal-color); - /* rgb state badge color */ - --rgb-badge-person-home-color: var(--rgb-state-person-home-color); - --rgb-badge-person-zone-color: var(--rgb-state-person-zone-color); - --rgb-badge-person-not-home-color: var(--rgb-red-color); - /* input components */ --input-idle-line-color: rgba(0, 0, 0, 0.42); --input-hover-line-color: rgba(0, 0, 0, 0.87); From 1dbe8c9b64b3094745ffedc441f002acb4da1b8f Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sat, 10 Dec 2022 03:47:57 +0100 Subject: [PATCH 09/25] Ensure consistent "blank before percent" handling (#14638) --- .../core/ha-config-system-navigation.ts | 3 ++- .../config/devices/ha-config-device-page.ts | 13 ++++++++---- .../devices/ha-config-devices-dashboard.ts | 5 ++++- .../config/hardware/ha-config-hardware.ts | 7 +++++-- .../hui-energy-carbon-consumed-gauge-card.ts | 2 +- .../hui-energy-solar-consumed-gauge-card.ts | 2 +- .../hui-cover-open-close-tile-feature.ts | 20 ++++++++++--------- .../hui-cover-tilt-tile-feature.ts | 20 ++++++++++--------- 8 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/panels/config/core/ha-config-system-navigation.ts b/src/panels/config/core/ha-config-system-navigation.ts index 6f1dba83e0..6bab7dfb82 100644 --- a/src/panels/config/core/ha-config-system-navigation.ts +++ b/src/panels/config/core/ha-config-system-navigation.ts @@ -3,6 +3,7 @@ import { customElement, property, state } from "lit/decorators"; import { canShowPage } from "../../../common/config/can_show_page"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { relativeTime } from "../../../common/datetime/relative_time"; +import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import "../../../components/ha-card"; import "../../../components/ha-navigation-list"; import "../../../components/ha-tip"; @@ -84,7 +85,7 @@ class HaConfigSystemNavigation extends LitElement { "percent_used", `${Math.round( (this._storageInfo.used / this._storageInfo.total) * 100 - )}%`, + )}${blankBeforePercent(this.hass.locale)}%`, "free_space", `${this._storageInfo.free} GB` ) diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 025f048f9e..143f2a8f51 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -1,3 +1,4 @@ +import "@material/mwc-list/mwc-list-item"; import { mdiCog, mdiDelete, @@ -7,18 +8,19 @@ import { mdiPencil, mdiPlusCircle, } from "@mdi/js"; -import "@material/mwc-list/mwc-list-item"; import "@polymer/paper-tooltip/paper-tooltip"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; +import { SENSOR_ENTITIES } from "../../../common/const"; import { computeDomain } from "../../../common/entity/compute_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateName } from "../../../common/entity/compute_state_name"; import { stringCompare } from "../../../common/string/compare"; import { slugify } from "../../../common/string/slugify"; +import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import { groupBy } from "../../../common/util/group-by"; import "../../../components/entity/ha-battery-icon"; import "../../../components/ha-alert"; @@ -59,6 +61,7 @@ import { showConfirmationDialog, } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-error-screen"; +import "../../../layouts/hass-subpage"; import "../../../layouts/hass-tabs-subpage"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant } from "../../../types"; @@ -74,8 +77,6 @@ import { loadDeviceRegistryDetailDialog, showDeviceRegistryDetailDialog, } from "./device-registry-detail/show-dialog-device-registry-detail"; -import "../../../layouts/hass-subpage"; -import { SENSOR_ENTITIES } from "../../../common/const"; export interface EntityRegistryStateEntry extends EntityRegistryEntry { stateName?: string | null; @@ -639,7 +640,11 @@ export class HaConfigDevicePage extends LitElement { batteryState ? html`
- ${batteryIsBinary ? "" : batteryState.state + " %"} + ${batteryIsBinary + ? "" + : batteryState.state + + blankBeforePercent(this.hass.locale) + + "%"} value + "%", + callback: (value) => + value + blankBeforePercent(this.hass.locale) + "%", }, }, x: { @@ -386,7 +388,8 @@ class HaConfigHardware extends SubscribeMixin(LitElement) { )}
- ${this._systemStatusData.cpu_percent || "-"}% + ${this._systemStatusData.cpu_percent || + "-"}${blankBeforePercent(this.hass.locale)}%
diff --git a/src/panels/lovelace/cards/energy/hui-energy-carbon-consumed-gauge-card.ts b/src/panels/lovelace/cards/energy/hui-energy-carbon-consumed-gauge-card.ts index 33271eeca4..9c266c54ad 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-carbon-consumed-gauge-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-carbon-consumed-gauge-card.ts @@ -129,7 +129,7 @@ class HuiEnergyCarbonGaugeCard min="0" max="100" .value=${value} - .locale=${this.hass!.locale} + .locale=${this.hass.locale} label="%" style=${styleMap({ "--gauge-color": this._computeSeverity(value), diff --git a/src/panels/lovelace/cards/energy/hui-energy-solar-consumed-gauge-card.ts b/src/panels/lovelace/cards/energy/hui-energy-solar-consumed-gauge-card.ts index 5e5df30f85..fd5de64399 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-solar-consumed-gauge-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-solar-consumed-gauge-card.ts @@ -108,7 +108,7 @@ class HuiEnergySolarGaugeCard min="0" max="100" .value=${value} - .locale=${this.hass!.locale} + .locale=${this.hass.locale} label="%" style=${styleMap({ "--gauge-color": this._computeSeverity(value), diff --git a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts index 0c64f461b1..05d4e6dce7 100644 --- a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts @@ -86,15 +86,17 @@ class HuiCoverOpenCloseTileFeature ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.STOP) - ? html` - - ` + ? html` + + + + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.CLOSE) ? html` diff --git a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts index 314184c854..018a0fb307 100644 --- a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts @@ -80,15 +80,17 @@ class HuiCoverTiltTileFeature ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.STOP_TILT) - ? html` - - ` + ? html` + + + + ` : null} ${supportsFeature(this.stateObj, CoverEntityFeature.CLOSE_TILT) ? html` From 0f971e5868a26929c3332c0c4a8ca5edcb1d9131 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Mon, 12 Dec 2022 09:42:37 +0100 Subject: [PATCH 10/25] Add QoS parameter for MQTT Publish (#14559) * Add QoS parameter for MQTT Publish * Follow up comment --- .../mqtt/mqtt-config-panel.ts | 25 +++++++++++++++++++ src/translations/en.json | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts b/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts index f658f0b6fb..c5eab6b79e 100644 --- a/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts @@ -10,6 +10,8 @@ import { haStyle } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; import "./mqtt-subscribe-card"; +const qosLevel = ["0", "1", "2"]; + @customElement("mqtt-config-panel") class HaPanelDevMqtt extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -20,6 +22,8 @@ class HaPanelDevMqtt extends LitElement { @state() private payload = ""; + @state() private qos = "0"; + private inited = false; protected firstUpdated() { @@ -29,6 +33,9 @@ class HaPanelDevMqtt extends LitElement { if (localStorage && localStorage["panel-dev-mqtt-payload"]) { this.payload = localStorage["panel-dev-mqtt-payload"]; } + if (localStorage && localStorage["panel-dev-mqtt-qos"]) { + this.qos = localStorage["panel-dev-mqtt-qos"]; + } this.inited = true; } @@ -54,6 +61,15 @@ class HaPanelDevMqtt extends LitElement { .value=${this.topic} @change=${this._handleTopic} > + ${qosLevel.map( + (qos) => + html`${qos}` + )} +

${this.hass.localize("ui.panel.config.mqtt.payload")}

= 0 && newValue !== this.qos && localStorage && this.inited) { + this.qos = newValue; + localStorage["panel-dev-mqtt-qos"] = this.qos; + } + } + private _publish(): void { if (!this.hass) { return; @@ -102,6 +126,7 @@ class HaPanelDevMqtt extends LitElement { this.hass.callService("mqtt", "publish", { topic: this.topic, payload_template: this.payload, + qos: parseInt(this.qos), }); } diff --git a/src/translations/en.json b/src/translations/en.json index 029113a66c..aaa1798ded 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3233,7 +3233,8 @@ "subscribe_to": "Topic to subscribe to", "start_listening": "Start listening", "stop_listening": "Stop listening", - "message_received": "Message {id} received on {topic} at {time}:" + "message_received": "Message {id} received on {topic} at {time}:", + "qos": "QoS" }, "zha": { "common": { From 0b377c060c500d2db60c99e249ffe18561cfb7c0 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 12 Dec 2022 10:43:20 +0100 Subject: [PATCH 11/25] Only reset primary/accent color if theme actually changes (#14659) fixes undefined --- src/panels/profile/ha-pick-theme-row.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/panels/profile/ha-pick-theme-row.ts b/src/panels/profile/ha-pick-theme-row.ts index 59d9774712..0dcdaca9dd 100644 --- a/src/panels/profile/ha-pick-theme-row.ts +++ b/src/panels/profile/ha-pick-theme-row.ts @@ -194,6 +194,10 @@ export class HaPickThemeRow extends LitElement { private _handleThemeSelection(ev) { const theme = ev.target.value; + if (theme === this.hass.selectedTheme?.theme) { + return; + } + if (theme === "Backend-selected") { if (this.hass.selectedTheme?.theme) { fireEvent(this, "settheme", { From fe0492c2e0f7b480c2e2b29b741444e03465f1f9 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 12 Dec 2022 10:44:29 +0100 Subject: [PATCH 12/25] Enable all-day / multi-day rendering for calendar (#14660) --- src/panels/calendar/ha-full-calendar.ts | 4 +++- src/panels/lovelace/cards/hui-calendar-card.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/panels/calendar/ha-full-calendar.ts b/src/panels/calendar/ha-full-calendar.ts index 90f6e3d4c4..9ded52d223 100644 --- a/src/panels/calendar/ha-full-calendar.ts +++ b/src/panels/calendar/ha-full-calendar.ts @@ -69,7 +69,6 @@ const defaultFullCalendarConfig: CalendarOptions = { initialView: "dayGridMonth", dayMaxEventRows: true, height: "parent", - eventDisplay: "list-item", locales: allLocales, views: { listWeek: { @@ -97,6 +96,8 @@ export class HAFullCalendar extends LitElement { @property() public initialView: FullCalendarView = "dayGridMonth"; + @property() public eventDisplay = "auto"; + @property({ attribute: false }) public error?: string = undefined; private calendar?: Calendar; @@ -246,6 +247,7 @@ export class HAFullCalendar extends LitElement { locale: this.hass.language, firstDay: firstWeekdayIndex(this.hass.locale), initialView: this.initialView, + eventDisplay: this.eventDisplay, eventTimeFormat: { hour: useAmPm(this.hass.locale) ? "numeric" : "2-digit", minute: useAmPm(this.hass.locale) ? "numeric" : "2-digit", diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts index f389f9388e..2e5b3e6123 100644 --- a/src/panels/lovelace/cards/hui-calendar-card.ts +++ b/src/panels/lovelace/cards/hui-calendar-card.ts @@ -134,6 +134,7 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { .hass=${this.hass} .views=${views} .initialView=${this._config.initial_view!} + .eventDisplay=${"list-item"} .error=${this._error} @view-changed=${this._handleViewChanged} > From 348c3c9787e86df4a655a9e59498eaf1ba05ea2d Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 12 Dec 2022 04:51:25 -0500 Subject: [PATCH 13/25] Revise vscode extensions (#14679) --- .devcontainer/devcontainer.json | 49 +++++++++++++++++---------------- .vscode/extensions.json | 5 ++-- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 746fa30697..dec658cd8e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,33 +5,34 @@ "context": ".." }, "appPort": "8124:8123", - "context": "..", "postCreateCommand": "script/bootstrap", - "extensions": [ - "github.vscode-pull-request-github", - "dbaeumer.vscode-eslint", - "ms-vscode.vscode-typescript-tslint-plugin", - "esbenp.prettier-vscode", - "bierner.lit-html", - "runem.lit-plugin", - "ms-python.vscode-pylance" - ], "containerEnv": { "WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}" }, - "settings": { - "terminal.integrated.shell.linux": "/bin/bash", - "files.eol": "\n", - "editor.tabSize": 2, - "editor.formatOnPaste": false, - "editor.formatOnSave": true, - "editor.formatOnType": true, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "files.trimTrailingWhitespace": true + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "runem.lit-plugin", + "github.vscode-pull-request-github", + "eamodio.gitlens" + ], + "settings": { + "terminal.integrated.shell.linux": "/bin/bash", + "files.eol": "\n", + "editor.tabSize": 2, + "editor.formatOnPaste": false, + "editor.formatOnSave": true, + "editor.formatOnType": true, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "files.trimTrailingWhitespace": true + } + } } } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8bea127242..ea7763d5de 100755 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,7 +2,8 @@ "recommendations": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", - "bierner.lit-html", - "runem.lit-plugin" + "runem.lit-plugin", + "github.vscode-pull-request-github", + "eamodio.gitlens" ] } From 467957005d2e6885b628b00fb122571eb851be05 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 12 Dec 2022 11:58:30 +0100 Subject: [PATCH 14/25] Fix pick dashboard row (#14708) --- src/panels/profile/ha-pick-dashboard-row.ts | 55 ++++++++++++--------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/panels/profile/ha-pick-dashboard-row.ts b/src/panels/profile/ha-pick-dashboard-row.ts index 4b5d647002..39354f25bc 100644 --- a/src/panels/profile/ha-pick-dashboard-row.ts +++ b/src/panels/profile/ha-pick-dashboard-row.ts @@ -13,7 +13,7 @@ class HaPickDashboardRow extends LitElement { @property() public narrow!: boolean; - @state() private _dashboards: LovelaceDashboard[] = []; + @state() private _dashboards?: LovelaceDashboard[]; protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); @@ -29,30 +29,37 @@ class HaPickDashboardRow extends LitElement { ${this.hass.localize("ui.panel.profile.dashboard.description")} - - - ${this.hass.localize( - "ui.panel.profile.dashboard.default_dashboard_label" - )} - - ${this._dashboards.map((dashboard) => { - if (!this.hass.user!.is_admin && dashboard.require_admin) { - return ""; - } - return html` - - ${dashboard.title} + ${this._dashboards + ? html` + + ${this.hass.localize( + "ui.panel.profile.dashboard.default_dashboard_label" + )} - `; - })} - + ${this._dashboards.map((dashboard) => { + if (!this.hass.user!.is_admin && dashboard.require_admin) { + return ""; + } + return html` + + ${dashboard.title} + + `; + })} + ` + : html``} `; } From 545141da924dffb3099c0e8171c25d066f974ec6 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 12 Dec 2022 11:58:45 +0100 Subject: [PATCH 15/25] Align dev container settings with core (#14709) --- .devcontainer/devcontainer.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dec658cd8e..3c53eacb7e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -19,19 +19,24 @@ "eamodio.gitlens" ], "settings": { - "terminal.integrated.shell.linux": "/bin/bash", "files.eol": "\n", "editor.tabSize": 2, "editor.formatOnPaste": false, "editor.formatOnSave": true, "editor.formatOnType": true, + "editor.renderWhitespace": "boundary", + "editor.rulers": [80], "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "files.trimTrailingWhitespace": true + "files.trimTrailingWhitespace": true, + "terminal.integrated.shell.linux": "/usr/bin/zsh", + "gitlens.showWelcomeOnInstall": false, + "gitlens.showWhatsNewAfterUpgrades": false, + "workbench.startupEditor": "none" } } } From ef7d696f9d5dfabba04817d477a71c643ee3da86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Mon, 12 Dec 2022 13:46:03 +0100 Subject: [PATCH 16/25] Adjust cast deployment (#14651) * Adjust cast deployment * Handle dev/master builds * Consistant --- .github/workflows/cast_deployment.yaml | 90 ++++++++++++++++++++++++++ .github/workflows/netflify.yml | 15 ----- 2 files changed, 90 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/cast_deployment.yaml delete mode 100644 .github/workflows/netflify.yml diff --git a/.github/workflows/cast_deployment.yaml b/.github/workflows/cast_deployment.yaml new file mode 100644 index 0000000000..4634ae0136 --- /dev/null +++ b/.github/workflows/cast_deployment.yaml @@ -0,0 +1,90 @@ +name: Cast deployment + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + push: + branches: + - master + +env: + NODE_VERSION: 16 + NODE_OPTIONS: --max_old_space_size=6144 + +jobs: + deploy_dev: + runs-on: ubuntu-latest + name: Deploy Development + if: github.event_name != 'push' + environment: + name: Cast Development + url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} + steps: + - name: Check out files from GitHub + uses: actions/checkout@v3 + with: + ref: dev + + - name: Set up Node ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: yarn + + - name: Install dependencies + run: yarn install + env: + CI: true + + - name: Build Cast + run: ./node_modules/.bin/gulp build-cast + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Deploy to Netlify + id: deploy + uses: netlify/actions/cli@master + with: + args: deploy --dir=cast/dist --alias dev + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_CAST_SITE_ID }} + + deploy_master: + runs-on: ubuntu-latest + name: Deploy Production + if: github.event_name == 'push' + environment: + name: Cast Production + url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }} + steps: + - name: Check out files from GitHub + uses: actions/checkout@v3 + with: + ref: master + + - name: Set up Node ${{ env.NODE_VERSION }} + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: yarn + + - name: Install dependencies + run: yarn install + env: + CI: true + + - name: Build Cast + run: ./node_modules/.bin/gulp build-cast + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Deploy to Netlify + id: deploy + uses: netlify/actions/cli@master + with: + args: deploy --dir=cast/dist --prod + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_CAST_SITE_ID }} \ No newline at end of file diff --git a/.github/workflows/netflify.yml b/.github/workflows/netflify.yml deleted file mode 100644 index fc554a813a..0000000000 --- a/.github/workflows/netflify.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Netlify - -on: - schedule: - - cron: "0 0 * * *" - -jobs: - trigger_builds: - name: Trigger netlify build preview - runs-on: "ubuntu-latest" - steps: - - name: Trigger Cast build - run: curl -X POST -d {} https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_CAST_DEV_BUILD_HOOK }} - - From 03d33759b88bc733e7307a0d8770acccc9ac8248 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 12 Dec 2022 14:09:55 +0100 Subject: [PATCH 17/25] Use light blue for media player to improve contrast (#14713) --- src/resources/ha-style.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index b4720c1d82..5bcf388d54 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -168,7 +168,7 @@ documentContainer.innerHTML = ` --rgb-state-lock-locked-color: var(--rgb-green-color); --rgb-state-lock-pending-color: var(--rgb-orange-color); --rgb-state-lock-unlocked-color: var(--rgb-red-color); - --rgb-state-media-player-color: var(--rgb-indigo-color); + --rgb-state-media-player-color: var(--rgb-light-blue-color); --rgb-state-person-home-color: var(--rgb-green-color); --rgb-state-person-not-home-color: var(--rgb-inactive-color); --rgb-state-person-zone-color: var(--rgb-blue-color); From 1e654d96618dce561eaca8d2adb29ccd0027a1e6 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 12 Dec 2022 06:20:29 -0800 Subject: [PATCH 18/25] Fix gauge-editor loading of severity values. (#14700) fixes undefined --- src/components/ha-form/types.ts | 2 +- .../lovelace/editor/config-elements/hui-gauge-card-editor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ha-form/types.ts b/src/components/ha-form/types.ts index a41fad2d6e..287b904780 100644 --- a/src/components/ha-form/types.ts +++ b/src/components/ha-form/types.ts @@ -31,7 +31,7 @@ export interface HaFormBaseSchema { export interface HaFormGridSchema extends HaFormBaseSchema { type: "grid"; - name: ""; + name: string; column_min_width?: string; schema: readonly HaFormSchema[]; } diff --git a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts index 0c19e9872d..89c2656cf3 100644 --- a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts @@ -93,7 +93,7 @@ export class HuiGaugeCardEditor ...(showSeverity ? ([ { - name: "", + name: "severity", type: "grid", schema: [ { From bc9fb9a4728c350174b0b53a41f1fca39f084722 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 12 Dec 2022 15:21:01 +0100 Subject: [PATCH 19/25] Fix event alignment for current day (#14717) --- src/panels/calendar/ha-full-calendar.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/panels/calendar/ha-full-calendar.ts b/src/panels/calendar/ha-full-calendar.ts index 9ded52d223..b9027277c9 100644 --- a/src/panels/calendar/ha-full-calendar.ts +++ b/src/panels/calendar/ha-full-calendar.ts @@ -549,12 +549,8 @@ export class HAFullCalendar extends LitElement { background: inherit; } - td.fc-day-today .fc-daygrid-day-top { - padding-top: 4px; - } - td.fc-day-today .fc-daygrid-day-number { - height: 24px; + height: 26px; color: var(--text-primary-color) !important; background-color: var(--primary-color); border-radius: 50%; @@ -563,7 +559,6 @@ export class HAFullCalendar extends LitElement { white-space: nowrap; width: max-content; min-width: 24px; - line-height: 140%; } .fc-daygrid-day-events { From f204a163d489de8d850e9594027febcf71d369ed Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 12 Dec 2022 15:21:28 +0100 Subject: [PATCH 20/25] Show pointer cursor when hovering calender event or day number (#14712) --- src/panels/calendar/ha-full-calendar.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/calendar/ha-full-calendar.ts b/src/panels/calendar/ha-full-calendar.ts index b9027277c9..c0acd174c6 100644 --- a/src/panels/calendar/ha-full-calendar.ts +++ b/src/panels/calendar/ha-full-calendar.ts @@ -539,6 +539,7 @@ export class HAFullCalendar extends LitElement { a.fc-daygrid-day-number { float: none !important; font-size: 12px; + cursor: pointer; } .fc .fc-daygrid-day-number { @@ -568,6 +569,7 @@ export class HAFullCalendar extends LitElement { .fc-event { border-radius: 4px; line-height: 1.7; + cursor: pointer; } .fc-daygrid-block-event .fc-event-main { From d74fb8717c9e925471aa5ce3b88a6c91de8bd510 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 12 Dec 2022 15:47:05 +0100 Subject: [PATCH 21/25] Fix sorting auto generated dashboard (#14707) --- .../common/generate-lovelace-config.ts | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index 865de77944..ffbcd951da 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -491,9 +491,15 @@ export const generateDefaultViewConfig = ( const areaCards: LovelaceCardConfig[] = []; - for (const [areaId, areaEntities] of Object.entries( + const sortedAreas = Object.entries( splittedByAreaDevice.areasWithEntities - )) { + ).sort((a, b) => { + const areaA = areaEntries[a[0]]; + const areaB = areaEntries[b[0]]; + return stringCompare(areaA.name, areaB.name); + }); + + for (const [areaId, areaEntities] of sortedAreas) { const area = areaEntries[areaId]; areaCards.push( ...computeCards( @@ -506,13 +512,20 @@ export const generateDefaultViewConfig = ( ); } - areaCards.sort((a, b) => stringCompare(a.title || "", b.title || "")); - const deviceCards: LovelaceCardConfig[] = []; - for (const [deviceId, deviceEntities] of Object.entries( + const sortedDevices = Object.entries( splittedByAreaDevice.devicesWithEntities - )) { + ).sort((a, b) => { + const deviceA = deviceEntries[a[0]]; + const deviceB = deviceEntries[b[0]]; + return stringCompare( + deviceA.name_by_user || deviceA.name || "", + deviceB.name_by_user || deviceB.name || "" + ); + }); + + for (const [deviceId, deviceEntities] of sortedDevices) { const device = deviceEntries[deviceId]; deviceCards.push( ...computeCards( @@ -534,8 +547,6 @@ export const generateDefaultViewConfig = ( ); } - deviceCards.sort((a, b) => stringCompare(a.title || "", b.title || "")); - let energyCard: LovelaceCardConfig | undefined; if (energyPrefs) { From b939978de161f784f687dc114b2c38faac05923b Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 12 Dec 2022 15:48:26 +0100 Subject: [PATCH 22/25] Enable full day event mode in calendar card day grid (#14716) --- src/panels/calendar/ha-full-calendar.ts | 5 +++++ src/panels/lovelace/cards/hui-calendar-card.ts | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/panels/calendar/ha-full-calendar.ts b/src/panels/calendar/ha-full-calendar.ts index c0acd174c6..d3007ba5e6 100644 --- a/src/panels/calendar/ha-full-calendar.ts +++ b/src/panels/calendar/ha-full-calendar.ts @@ -234,6 +234,10 @@ export class HAFullCalendar extends LitElement { this._fireViewChanged(); } + if (changedProps.has("eventDisplay")) { + this.calendar!.setOption("eventDisplay", this.eventDisplay); + } + const oldHass = changedProps.get("hass") as HomeAssistant; if (oldHass && oldHass.language !== this.hass.language) { @@ -322,6 +326,7 @@ export class HAFullCalendar extends LitElement { this._activeView = "dayGridDay"; this.calendar!.changeView("dayGridDay"); this.calendar!.gotoDate(info.dateStr); + this._fireViewChanged(); } private _handleNext(): void { diff --git a/src/panels/lovelace/cards/hui-calendar-card.ts b/src/panels/lovelace/cards/hui-calendar-card.ts index 2e5b3e6123..abd69bf654 100644 --- a/src/panels/lovelace/cards/hui-calendar-card.ts +++ b/src/panels/lovelace/cards/hui-calendar-card.ts @@ -66,6 +66,8 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { @state() private _calendars: Calendar[] = []; + @state() private _eventDisplay = "list-item"; + @state() private _narrow = false; @state() private _veryNarrow = false; @@ -134,7 +136,7 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { .hass=${this.hass} .views=${views} .initialView=${this._config.initial_view!} - .eventDisplay=${"list-item"} + .eventDisplay=${this._eventDisplay} .error=${this._error} @view-changed=${this._handleViewChanged} > @@ -164,6 +166,8 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard { } private _handleViewChanged(ev: HASSDomEvent): void { + this._eventDisplay = + ev.detail.view === "dayGridMonth" ? "list-item" : "auto"; this._startDate = ev.detail.start; this._endDate = ev.detail.end; this._fetchCalendarEvents(); From 544272b4df85833beebdc73dfba47674ecc46a35 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 12 Dec 2022 15:49:31 +0100 Subject: [PATCH 23/25] Improve entity not found tile card (#14711) --- src/panels/lovelace/cards/hui-tile-card.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 4ca720e34b..17aea90e51 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -1,5 +1,5 @@ import { memoize } from "@fullcalendar/common"; -import { mdiHelp } from "@mdi/js"; +import { mdiExclamationThick, mdiHelp } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; @@ -225,10 +225,21 @@ export class HuiTileCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - +
- + +
Date: Mon, 12 Dec 2022 15:52:33 +0100 Subject: [PATCH 24/25] Transparent unavailable state in history (#14710) * Use transparent color for unavailable state for history * Remove inactive color * Only color active state for badge icon * Simplify condition * Update src/components/chart/timeline-chart/textbar-element.ts Co-authored-by: Bram Kragten Co-authored-by: Bram Kragten --- src/common/color/compute-color.ts | 1 - .../chart/timeline-chart/textbar-element.ts | 7 +++-- .../chart/timeline-chart/timeline-color.ts | 4 +-- src/components/entity/state-badge.ts | 30 +++++++++---------- src/panels/lovelace/cards/hui-button-card.ts | 10 ++++--- src/panels/lovelace/cards/hui-entity-card.ts | 10 ++++--- src/resources/ha-style.ts | 7 ++--- src/resources/styles.ts | 1 - 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/common/color/compute-color.ts b/src/common/color/compute-color.ts index 40b43c44d4..e7e3409a9d 100644 --- a/src/common/color/compute-color.ts +++ b/src/common/color/compute-color.ts @@ -4,7 +4,6 @@ export const THEME_COLORS = new Set([ "primary", "accent", "disabled", - "inactive", "red", "pink", "purple", diff --git a/src/components/chart/timeline-chart/textbar-element.ts b/src/components/chart/timeline-chart/textbar-element.ts index 93cc953ccd..1f11a8f433 100644 --- a/src/components/chart/timeline-chart/textbar-element.ts +++ b/src/components/chart/timeline-chart/textbar-element.ts @@ -37,8 +37,11 @@ export class TextBarElement extends BarElement { } const textColor = options.textColor || - (options.backgroundColor && - (luminosity(hex2rgb(options.backgroundColor)) > 0.5 ? "#000" : "#fff")); + (options?.backgroundColor === "transparent" + ? "transparent" + : luminosity(hex2rgb(options.backgroundColor)) > 0.5 + ? "#000" + : "#fff"); // ctx.font = "12px arial"; ctx.fillStyle = textColor; diff --git a/src/components/chart/timeline-chart/timeline-color.ts b/src/components/chart/timeline-chart/timeline-color.ts index a61ad01e08..ecbf9a78cc 100644 --- a/src/components/chart/timeline-chart/timeline-color.ts +++ b/src/components/chart/timeline-chart/timeline-color.ts @@ -51,9 +51,7 @@ function computeTimelineStateColor( stateObj?: HassEntity ): string | undefined { if (!stateObj || state === UNAVAILABLE) { - const rgb = cssToRgb("--rgb-state-unavailable-color", computedStyles); - if (!rgb) return undefined; - return rgb2hex(rgb); + return "transparent"; } const color = stateColor(stateObj, state); diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts index 50458e1f88..fdf507b0d0 100644 --- a/src/components/entity/state-badge.ts +++ b/src/components/entity/state-badge.ts @@ -107,27 +107,25 @@ export class StateBadge extends LitElement { } hostStyle.backgroundImage = `url(${imageUrl})`; this._showIcon = false; - } else if (this._stateColor) { + } else if (this._stateColor && stateActive(stateObj)) { const color = stateColorCss(stateObj); if (color) { iconStyle.color = `rgb(${color})`; } - if (stateActive(stateObj)) { - if (stateObj.attributes.rgb_color) { - iconStyle.color = `rgb(${stateObj.attributes.rgb_color.join(",")})`; - } - if (stateObj.attributes.brightness) { - const brightness = stateObj.attributes.brightness; - if (typeof brightness !== "number") { - const errorMessage = `Type error: state-badge expected number, but type of ${ - stateObj.entity_id - }.attributes.brightness is ${typeof brightness} (${brightness})`; - // eslint-disable-next-line - console.warn(errorMessage); - } - // lowest brightness will be around 50% (that's pretty dark) - iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; + if (stateObj.attributes.rgb_color) { + iconStyle.color = `rgb(${stateObj.attributes.rgb_color.join(",")})`; + } + if (stateObj.attributes.brightness) { + const brightness = stateObj.attributes.brightness; + if (typeof brightness !== "number") { + const errorMessage = `Type error: state-badge expected number, but type of ${ + stateObj.entity_id + }.attributes.brightness is ${typeof brightness} (${brightness})`; + // eslint-disable-next-line + console.warn(errorMessage); } + // lowest brightness will be around 50% (that's pretty dark) + iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`; } } } else if (this.overrideImage) { diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts index 480d86f542..4686c82f50 100644 --- a/src/panels/lovelace/cards/hui-button-card.ts +++ b/src/panels/lovelace/cards/hui-button-card.ts @@ -156,8 +156,8 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { ? this._config.name || (stateObj ? computeStateName(stateObj) : "") : ""; - const colored = stateObj && this.getStateColor(stateObj, this._config); - const active = stateObj && colored && stateActive(stateObj); + const active = stateObj && stateActive(stateObj); + const colored = active && this.getStateColor(stateObj, this._config); return html` @@ -193,12 +193,14 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { `; } - private _computeColor(stateObj: HassEntity | LightEntity): string { + private _computeColor( + stateObj: HassEntity | LightEntity + ): string | undefined { const iconColor = stateColorCss(stateObj); if (iconColor) { return `rgb(${iconColor})`; } - return ""; + return undefined; } protected shouldUpdate(changedProps: PropertyValues): boolean { diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 5bcf388d54..07b2fbde32 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -107,7 +107,6 @@ documentContainer.innerHTML = ` --rgb-primary-color: 3, 169, 244; --rgb-accent-color: 255, 152, 0; --rgb-disabled-color: 189, 189, 189; - --rgb-inactive-color: 114, 114, 114; --rgb-primary-text-color: 33, 33, 33; --rgb-secondary-text-color: 114, 114, 114; --rgb-text-primary-color: 255, 255, 255; @@ -136,13 +135,13 @@ documentContainer.innerHTML = ` /* rgb state color */ --rgb-state-default-color: var(--rgb-dark-primary-color, 68, 115, 158); - --rgb-state-inactive-color: var(--rgb-inactive-color); + --rgb-state-inactive-color: var(--rgb-grey-color); --rgb-state-unavailable-color: var(--rgb-disabled-color); /* rgb state domain colors */ --rgb-state-alarm-armed-color: var(--rgb-green-color); --rgb-state-alarm-arming-color: var(--rgb-orange-color); - --rgb-state-alarm-disarmed-color: var(--rgb-inactive-color); + --rgb-state-alarm-disarmed-color: var(--rgb-grey-color); --rgb-state-alarm-pending-color: var(--rgb-orange-color); --rgb-state-alarm-triggered-color: var(--rgb-red-color); --rgb-state-alert-color: var(--rgb-red-color); @@ -170,7 +169,7 @@ documentContainer.innerHTML = ` --rgb-state-lock-unlocked-color: var(--rgb-red-color); --rgb-state-media-player-color: var(--rgb-light-blue-color); --rgb-state-person-home-color: var(--rgb-green-color); - --rgb-state-person-not-home-color: var(--rgb-inactive-color); + --rgb-state-person-not-home-color: var(--rgb-grey-color); --rgb-state-person-zone-color: var(--rgb-blue-color); --rgb-state-remote-color: var(--rgb-amber-color); --rgb-state-script-color: var(--rgb-amber-color); diff --git a/src/resources/styles.ts b/src/resources/styles.ts index 4b49cf06aa..3f18eb7445 100644 --- a/src/resources/styles.ts +++ b/src/resources/styles.ts @@ -49,7 +49,6 @@ export const darkStyles = { "map-filter": "invert(.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) saturate(.3)", "rgb-disabled-color": "70, 70, 70", - "rgb-inactive-color": "141, 141, 141", }; export const derivedStyles = { From 149fa5fca6bd16b95165ecd8ecc4dcd39c8d1e99 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 12 Dec 2022 15:53:20 +0100 Subject: [PATCH 25/25] Bumped version to 20221212.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6d99314ec9..2c4a530952 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20221208.0" +version = "20221212.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md"