Skip to content

Commit

Permalink
Use entity components translations for update entity
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Nov 10, 2023
1 parent d3f6ebd commit d740364
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/common/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export const DOMAINS_WITH_CARD = [
"select",
"timer",
"text",
"update",
"vacuum",
"water_heater",
];
Expand Down
28 changes: 1 addition & 27 deletions src/common/entity/compute_state_display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { HassConfig, HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import { FrontendLocaleData, TimeZone } from "../../data/translation";
import {
UPDATE_SUPPORT_PROGRESS,
updateIsInstallingFromAttributes,
} from "../../data/update";
import { HomeAssistant } from "../../types";
import {
UNIT_TO_MILLISECOND_CONVERT,
Expand All @@ -19,10 +15,9 @@ import {
getNumberFormatOptions,
isNumericFromAttributes,
} from "../number/format_number";
import { blankBeforeUnit } from "../translations/blank_before_unit";
import { LocalizeFunc } from "../translations/localize";
import { computeDomain } from "./compute_domain";
import { supportsFeatureFromAttributes } from "./supports-feature";
import { blankBeforeUnit } from "../translations/blank_before_unit";

export const computeStateDisplaySingleEntity = (
localize: LocalizeFunc,
Expand Down Expand Up @@ -208,27 +203,6 @@ export const computeStateDisplayFromEntityAttributes = (
}
}

if (domain === "update") {
// When updating, and entity does not support % show "Installing"
// When updating, and entity does support % show "Installing (xx%)"
// When update available, show the version
// When the latest version is skipped, show the latest version
// When update is not available, show "Up-to-date"
// When update is not available and there is no latest_version show "Unavailable"
return state === "on"
? updateIsInstallingFromAttributes(attributes)
? supportsFeatureFromAttributes(attributes, UPDATE_SUPPORT_PROGRESS) &&
typeof attributes.in_progress === "number"
? localize("ui.card.update.installing_with_progress", {
progress: attributes.in_progress,
})
: localize("ui.card.update.installing")
: attributes.latest_version
: attributes.skipped_version === attributes.latest_version
? attributes.latest_version ?? localize("state.default.unavailable")
: localize("ui.card.update.up_to_date");
}

return (
(entity?.translation_key &&
localize(
Expand Down
63 changes: 47 additions & 16 deletions src/data/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import type {
import { BINARY_STATE_ON } from "../common/const";
import { computeDomain } from "../common/entity/compute_domain";
import { computeStateDomain } from "../common/entity/compute_state_domain";
import {
supportsFeature,
supportsFeatureFromAttributes,
} from "../common/entity/supports-feature";
import { supportsFeature } from "../common/entity/supports-feature";
import { caseInsensitiveStringCompare } from "../common/string/compare";
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
import { HomeAssistant } from "../types";
Expand Down Expand Up @@ -38,13 +35,8 @@ export interface UpdateEntity extends HassEntityBase {
}

export const updateUsesProgress = (entity: UpdateEntity): boolean =>
updateUsesProgressFromAttributes(entity.attributes);

export const updateUsesProgressFromAttributes = (attributes: {
[key: string]: any;
}): boolean =>
supportsFeatureFromAttributes(attributes, UPDATE_SUPPORT_PROGRESS) &&
typeof attributes.in_progress === "number";
supportsFeature(entity, UPDATE_SUPPORT_PROGRESS) &&
typeof entity.attributes.in_progress === "number";

export const updateCanInstall = (
entity: UpdateEntity,
Expand All @@ -57,11 +49,6 @@ export const updateCanInstall = (
export const updateIsInstalling = (entity: UpdateEntity): boolean =>
updateUsesProgress(entity) || !!entity.attributes.in_progress;

export const updateIsInstallingFromAttributes = (attributes: {
[key: string]: any;
}): boolean =>
updateUsesProgressFromAttributes(attributes) || !!attributes.in_progress;

export const updateReleaseNotes = (hass: HomeAssistant, entityId: string) =>
hass.callWS<string | null>({
type: "update/release_notes",
Expand Down Expand Up @@ -162,3 +149,47 @@ export const checkForEntityUpdates = async (
});
}
};

// When updating, and entity does not support % show "Installing"
// When updating, and entity does support % show "Installing (xx%)"
// When update available, show the version
// When the latest version is skipped, show the latest version
// When update is not available, show "Up-to-date"
// When update is not available and there is no latest_version show "Unavailable"
export const computeUpdateStateDisplay = (
stateObj: UpdateEntity,
hass: HomeAssistant
): string => {
const state = stateObj.state;
const attributes = stateObj.attributes;

if (state === "off") {
const isSkipped =
attributes.latest_version &&
attributes.skipped_version === attributes.latest_version;
if (isSkipped) {
return attributes.latest_version!;
}
return hass.formatEntityState(stateObj);
}

if (state === "on") {
if (updateIsInstalling(stateObj)) {
const supportsProgress =
supportsFeature(stateObj, UPDATE_SUPPORT_PROGRESS) &&
typeof typeof attributes.in_progress === "number";
if (supportsProgress) {
return hass.localize("ui.card.update.installing_with_progress", {
progress: attributes.in_progress,
});
}
return hass.localize("ui.card.update.installing");
}

if (attributes.latest_version) {
return attributes.latest_version;
}
}

return hass.formatEntityState(stateObj);
};
10 changes: 6 additions & 4 deletions src/dialogs/more-info/controls/more-info-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ class MoreInfoUpdate extends LitElement {
: ""}
<div class="row">
<div class="key">
${this.hass.localize(
"ui.dialogs.more_info_control.update.installed_version"
${this.hass.formatEntityAttributeName(
this.stateObj,
"installed_version"
)}
</div>
<div class="value">
Expand All @@ -74,8 +75,9 @@ class MoreInfoUpdate extends LitElement {
</div>
<div class="row">
<div class="key">
${this.hass.localize(
"ui.dialogs.more_info_control.update.latest_version"
${this.hass.formatEntityAttributeName(
this.stateObj,
"latest_version"
)}
</div>
<div class="value">
Expand Down
8 changes: 8 additions & 0 deletions src/panels/lovelace/cards/hui-tile-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import "../tile-features/hui-tile-features";
import type { LovelaceCard, LovelaceCardEditor } from "../types";
import { computeTileBadge } from "./tile/badges/tile-badge";
import type { ThermostatCardConfig, TileCardConfig } from "./types";
import { UpdateEntity, computeUpdateStateDisplay } from "../../../data/update";

const TIMESTAMP_STATE_DOMAINS = ["button", "input_button", "scene"];

Expand Down Expand Up @@ -260,6 +261,13 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
]);
}

if (domain === "update") {
return html`${computeUpdateStateDisplay(
stateObj as UpdateEntity,
this.hass!
)}`;
}

return this._renderStateContent(stateObj, "state");
}

Expand Down
4 changes: 3 additions & 1 deletion src/panels/lovelace/create-element/create-row-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const LAZY_LOAD_TYPES = {
"text-entity": () => import("../entity-rows/hui-text-entity-row"),
"time-entity": () => import("../entity-rows/hui-time-entity-row"),
"timer-entity": () => import("../entity-rows/hui-timer-entity-row"),
"update-entity": () => import("../entity-rows/hui-update-entity-row"),
conditional: () => import("../special-rows/hui-conditional-row"),
"weather-entity": () => import("../entity-rows/hui-weather-entity-row"),
divider: () => import("../special-rows/hui-divider-row"),
Expand All @@ -73,6 +74,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
humidifier: "humidifier",
input_boolean: "toggle",
input_button: "input-button",
input_datetime: "input-datetime",
input_number: "input-number",
input_select: "input-select",
input_text: "input-text",
Expand All @@ -90,11 +92,11 @@ const DOMAIN_TO_ELEMENT_TYPE = {
text: "text",
time: "time",
timer: "timer",
update: "update",
vacuum: "toggle",
// Temporary. Once climate is rewritten,
// water heater should get its own row.
water_heater: "climate",
input_datetime: "input-datetime",
weather: "weather",
};

Expand Down
75 changes: 75 additions & 0 deletions src/panels/lovelace/entity-rows/hui-update-entity-row.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
CSSResultGroup,
LitElement,
PropertyValues,
css,
html,
nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { UpdateEntity, computeUpdateStateDisplay } from "../../../data/update";
import { HomeAssistant } from "../../../types";
import { EntitiesCardEntityConfig } from "../cards/types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceRow } from "./types";

@customElement("hui-update-entity-row")
class HuiUpdateEntityRow extends LitElement implements LovelaceRow {
@property({ attribute: false }) public hass?: HomeAssistant;

@state() private _config?: EntitiesCardEntityConfig;

public setConfig(config: EntitiesCardEntityConfig): void {
if (!config) {
throw new Error("Invalid configuration");
}
this._config = config;
}

protected shouldUpdate(changedProps: PropertyValues): boolean {
return hasConfigOrEntityChanged(this, changedProps);
}

protected render() {
if (!this._config || !this.hass) {
return nothing;
}

const stateObj = this.hass.states[this._config.entity] as
| UpdateEntity
| undefined;

if (!stateObj) {
return html`
<hui-warning>
${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning>
`;
}

return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
${computeUpdateStateDisplay(stateObj, this.hass)}
</hui-generic-entity-row>
`;
}

static get styles(): CSSResultGroup {
return css`
div {
text-align: right;
}
.pointer {
cursor: pointer;
}
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"hui-update-entity-row": HuiUpdateEntityRow;
}
}
1 change: 1 addition & 0 deletions src/state-summary/state-card-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import "./state-card-select";
import "./state-card-text";
import "./state-card-timer";
import "./state-card-toggle";
import "./state-card-update";
import "./state-card-vacuum";
import "./state-card-water_heater";

Expand Down
56 changes: 56 additions & 0 deletions src/state-summary/state-card-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import "../components/entity/state-info";
import { computeUpdateStateDisplay, UpdateEntity } from "../data/update";
import { haStyle } from "../resources/styles";
import type { HomeAssistant } from "../types";

@customElement("state-card-update")
export class StateCardUpdate extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ attribute: false }) public stateObj!: UpdateEntity;

@property({ type: Boolean }) public inDialog = false;

protected render(): TemplateResult {
return html`
<div class="horizontal justified layout">
<state-info
.hass=${this.hass}
.stateObj=${this.stateObj}
.inDialog=${this.inDialog}
>
</state-info>
<div class="state">
${computeUpdateStateDisplay(this.stateObj, this.hass)}
</div>
</div>
`;
}

static get styles(): CSSResultGroup {
return [
haStyle,
css`
state-info {
flex: 0 1 fit-content;
min-width: 120px;
}
.state {
color: var(--primary-text-color);
margin-inline-start: 16px;
margin-inline-end: initial;
text-align: var(--float-end, right);
min-width: 50px;
flex: 0 1 fit-content;
word-break: break-word;
display: flex;
align-items: center;
direction: ltr;
justify-content: flex-end;
}
`,
];
}
}
2 changes: 0 additions & 2 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,6 @@
"setting": "Setting"
},
"update": {
"installed_version": "Installed version",
"latest_version": "Latest version",
"release_announcement": "Read release announcement",
"skip": "Skip",
"clear_skipped": "Clear skipped",
Expand Down

0 comments on commit d740364

Please sign in to comment.