diff --git a/README.md b/README.md index e18d6fc..25dfc4e 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Else, if you prefer the graphical editor, use the menu to add the resource: | clickable_entities | `boolean` | false | If true, clicking on the entity will open the entity's more info dialog. | | min_expected_power | `number` | 0.01 | Represents the minimum amount of power (in Watts) expected to flow through the system at a given moment. Only used in the [New Flow Formula](#new-flow-formula). | | max_expected_power | `number` | 2000 | Represents the maximum amount of power (in Watts) expected to flow through the system at a given moment. Only used in the [New Flow Formula](#new-flow-formula). | -| display_zero_lines | `boolean` | true | If false, lines where no power is flowing will be hidden. | +| display_zero_lines | `object` | `{mode: "show"}` | Check [Display Zero Lines](#display-zero) | | use_new_flow_rate_model | `boolean` | false | If set to true, the card will use the [New Flow Formula](#new-flow-formula). #### Entities object @@ -262,6 +262,16 @@ This feature allows you to configure how the card handles a Grid Power Outage sc | label_alert | `string` | A text that will be displayed below the icon when there is a power outage. | | calculate_flow_rate | `boolean` or `number` | `false` | If set to `true`, the flow rate will be calculated by using the flow rate formula (either the new or the old one, depending on your configuration). If set to a number, the flow rate will be set to that number. For example, defining the value `10` will ensure one dot will flow every 10 seconds. | +#### Display Zero Lines + +This object allows you to control the behavior of the flow lines that are inactive. + +| Name | Type | Description | +| ----------- | -------- | ------------------------------------------------------------------------------------------------- | +| mode | string | Valid Options are: `show`, `hide`, `transparency`, `grey_out`, `custom` | +| transparency | number | A number between 0 and 100. 100 means the line doesn't show at all. 0 means the line shows in full opacity. Default is 50. Will be used when the mode is either `transparency` or `custom`. | +| grey_color | `string` or `list of numbers` | Either a HEX Code or a List of three numbers between 0 and 255 in RGB order. Will be used when the mode is either `grey_out` or `custom`. | + ### Minimal Configuration > Don't forget to change the entity ids diff --git a/src/localize/languages/de.json b/src/localize/languages/de.json index 0aa1537..879d74d 100644 --- a/src/localize/languages/de.json +++ b/src/localize/languages/de.json @@ -60,6 +60,13 @@ "display_zero_lines": "Nulllinien anzeigen", "clickable_entities": "Klickbare Entitäten", "use_new_flow_rate_model": "Neues Fluss-Modell verwenden", - "use_metadata": "Metadaten verwenden" + "use_metadata": "Metadaten verwenden", + "mode": "Modus", + "show": "Anzeigen", + "hide": "Verstecken", + "custom": "Benutzerdefiniert", + "grey_out": "Ausgrauen", + "transparency": "Transparenz", + "grey_color": "Graue Farbe" } } \ No newline at end of file diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index 7e7c2cb..1d91618 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -60,6 +60,13 @@ "display_zero_lines": "Display Zero Lines", "clickable_entities": "Clickable Entities", "use_new_flow_rate_model": "New Flow Rate Model", - "use_metadata": "Use Metadata" + "use_metadata": "Use Metadata", + "mode": "Mode", + "show": "Show", + "hide": "Hide", + "custom": "Custom", + "grey_out": "Grey Out", + "transparency": "Transparency", + "grey_color": "Grey Color" } } \ No newline at end of file diff --git a/src/localize/languages/es.json b/src/localize/languages/es.json index 43bbd8b..5aecc61 100644 --- a/src/localize/languages/es.json +++ b/src/localize/languages/es.json @@ -60,6 +60,13 @@ "display_zero_lines": "Mostrar Líneas de Cero", "clickable_entities": "Entidades Clicables", "use_new_flow_rate_model": "Utilizar Nuevo Modelo de Tasa de Flujo", - "use_metadata": "Utilizar Metadatos" + "use_metadata": "Utilizar Metadatos", + "mode": "Modo", + "show": "Mostrar", + "hide": "Ocultar", + "custom": "Personalizado", + "grey_out": "Gris", + "transparency": "Transparencia", + "grey_color": "Color Gris" } } \ No newline at end of file diff --git a/src/localize/languages/fi.json b/src/localize/languages/fi.json index a9d6d0f..cba1b92 100644 --- a/src/localize/languages/fi.json +++ b/src/localize/languages/fi.json @@ -60,6 +60,13 @@ "display_zero_lines": "Näytä nolla-viivat", "clickable_entities": "Napautettavat kohteet", "use_new_flow_rate_model": "Uusi virtausnopeusmalli", - "use_metadata": "Käytä metatietoja" + "use_metadata": "Käytä metatietoja", + "mode": "Tila", + "show": "Näytä", + "hide": "Piilota", + "custom": "Mukautettu", + "grey_out": "Harmaa", + "transparency": "Läpinäkyvyys", + "grey_color": "Harmaa väri" } } \ No newline at end of file diff --git a/src/localize/languages/fr.json b/src/localize/languages/fr.json index c27d5e6..96a5d34 100644 --- a/src/localize/languages/fr.json +++ b/src/localize/languages/fr.json @@ -60,6 +60,13 @@ "display_zero_lines": "Afficher les lignes zéro", "clickable_entities": "Entités cliquables", "use_new_flow_rate_model": "Nouveau modèle de débit", - "use_metadata": "Utiliser les métadonnées" + "use_metadata": "Utiliser les métadonnées", + "mode": "Mode", + "show": "Afficher", + "hide": "Masquer", + "custom": "Personnalisé", + "grey_out": "Griser", + "transparency": "Transparence", + "grey_color": "Couleur grise" } } \ No newline at end of file diff --git a/src/localize/languages/it.json b/src/localize/languages/it.json index cf4dc29..0031c83 100644 --- a/src/localize/languages/it.json +++ b/src/localize/languages/it.json @@ -60,6 +60,13 @@ "display_zero_lines": "Mostra Linee Zero", "clickable_entities": "Entità Cliccabili", "use_new_flow_rate_model": "Utilizza Nuovo Modello di Tasso di Flusso", - "use_metadata": "Utilizza Metadati" + "use_metadata": "Utilizza Metadati", + "mode": "Modalità", + "show": "Mostra", + "hide": "Nascondi", + "custom": "Personalizzato", + "grey_out": "Sfuma", + "transparency": "Trasparenza", + "grey_color": "Colore Sfumato" } } \ No newline at end of file diff --git a/src/localize/languages/nl.json b/src/localize/languages/nl.json index 3129f15..3675cfe 100644 --- a/src/localize/languages/nl.json +++ b/src/localize/languages/nl.json @@ -60,6 +60,13 @@ "display_zero_lines": "Nullijnen Weergeven", "clickable_entities": "Klikbare Entiteiten", "use_new_flow_rate_model": "Nieuw Stroomsnelheid Model Gebruiken", - "use_metadata": "Metadata Gebruiken" + "use_metadata": "Metadata Gebruiken", + "mode": "Modus", + "show": "Weergeven", + "hide": "Verbergen", + "custom": "Aangepast", + "grey_out": "Grijstint", + "transparency": "Transparantie", + "grey_color": "Grijstint" } } \ No newline at end of file diff --git a/src/localize/languages/pl.json b/src/localize/languages/pl.json index b7c3148..a865c59 100644 --- a/src/localize/languages/pl.json +++ b/src/localize/languages/pl.json @@ -60,6 +60,13 @@ "display_zero_lines": "Wyświetl linie zera", "clickable_entities": "Klikalne jednostki", "use_new_flow_rate_model": "Nowy model wskaźnika przepływu", - "use_metadata": "Użyj metadanych" + "use_metadata": "Użyj metadanych", + "mode": "Tryb", + "show": "Pokaż", + "hide": "Ukryj", + "custom": "Niestandardowy", + "grey_out": "Szary", + "transparency": "Przezroczystość", + "grey_color": "Kolor szary" } } \ No newline at end of file diff --git a/src/localize/languages/pt-BR.json b/src/localize/languages/pt-BR.json index 499f9eb..e556bce 100644 --- a/src/localize/languages/pt-BR.json +++ b/src/localize/languages/pt-BR.json @@ -60,6 +60,13 @@ "display_zero_lines": "Exibir Linhas Zero", "clickable_entities": "Entidades Clicáveis", "use_new_flow_rate_model": "Utilizar Novo Modelo de Velocidade", - "use_metadata": "Utilizar Metadados" + "use_metadata": "Utilizar Metadados", + "mode": "Modo", + "show": "Mostrar", + "hide": "Esconder", + "custom": "Personalizado", + "grey_out": "Cinza", + "transparency": "Transparência", + "grey_color": "Cor do Cinza" } } \ No newline at end of file diff --git a/src/localize/languages/pt-PT.json b/src/localize/languages/pt-PT.json index 0399c3d..661bd68 100644 --- a/src/localize/languages/pt-PT.json +++ b/src/localize/languages/pt-PT.json @@ -60,6 +60,13 @@ "display_zero_lines": "Mostrar Linhas Zero", "clickable_entities": "Entidades Clicáveis", "use_new_flow_rate_model": "Utilizar Novo Modelo de Velocidade", - "use_metadata": "Utilizar Metadados" + "use_metadata": "Utilizar Metadados", + "mode": "Modo", + "show": "Mostrar", + "hide": "Esconder", + "custom": "Personalizado", + "grey_out": "Cinzento", + "transparency": "Transparência", + "grey_color": "Cor Cinzenta" } } \ No newline at end of file diff --git a/src/localize/languages/ru.json b/src/localize/languages/ru.json index 4c7e0fe..dd23a8f 100644 --- a/src/localize/languages/ru.json +++ b/src/localize/languages/ru.json @@ -60,6 +60,13 @@ "display_zero_lines": "Отображать нулевые линии", "clickable_entities": "Кликабельные сущности", "use_new_flow_rate_model": "Использовать новую модель скорости потока", - "use_metadata": "Использовать метаданные" + "use_metadata": "Использовать метаданные", + "mode": "Режим", + "show": "Показать", + "hide": "Скрыть", + "custom": "Пользовательский", + "grey_out": "Серый", + "transparency": "Прозрачность", + "grey_color": "Серый цвет" } } \ No newline at end of file diff --git a/src/power-flow-card-plus-config.ts b/src/power-flow-card-plus-config.ts index 863cbef..0cd6bf0 100644 --- a/src/power-flow-card-plus-config.ts +++ b/src/power-flow-card-plus-config.ts @@ -12,8 +12,12 @@ interface mainConfigOptions { clickable_entities: boolean; max_expected_power: number; min_expected_power: number; - display_zero_lines?: boolean; use_new_flow_rate_model?: boolean; + display_zero_lines?: { + mode?: string; + transparency?: number; + grey_color?: string | number[]; + }; } export interface PowerFlowCardPlusConfig extends LovelaceCardConfig, mainConfigOptions { entities: { diff --git a/src/power-flow-card-plus.ts b/src/power-flow-card-plus.ts index b60d99d..8c6b24d 100644 --- a/src/power-flow-card-plus.ts +++ b/src/power-flow-card-plus.ts @@ -56,6 +56,11 @@ export class PowerFlowCardPlus extends LitElement { watt_threshold: coerceNumber(config.watt_threshold, defaultValues.wattThreshold), max_expected_power: coerceNumber(config.max_expected_power, defaultValues.maxExpectedPower), min_expected_power: coerceNumber(config.min_expected_power, defaultValues.minExpectedPower), + display_zero_lines: { + mode: config.display_zero_lines?.mode ?? defaultValues.displayZeroLines.mode, + transparency: coerceNumber(config.display_zero_lines?.transparency, defaultValues.displayZeroLines.transparency), + grey_color: config.display_zero_lines?.grey_color ?? defaultValues.displayZeroLines.grey_color, + }, }; } @@ -232,9 +237,34 @@ export class PowerFlowCardPlus extends LitElement { ) as boolean; } + /** + * Determine wether to show the line or not based on if the power is flowing or not and if not, based on display_zero_lines mode + * @param power - power flowing through the line + * @returns boolean - `true` if line should be shown, `false` if not + */ private showLine(power: number): boolean { - if (this._config?.display_zero_lines !== false) return true; - return power > 0; + if (power > 0) return true; + return this._config?.display_zero_lines?.mode !== "hide"; + } + + /** + * Depending on display_zero_lines mode, return the style class to apply to the line + * @param power - power flowing through the line + * @returns string - style class to apply to the line + */ + private styleLine(power: number): string { + if (power > 0) return ""; + const displayZeroMode = this._config?.display_zero_lines?.mode; + if (displayZeroMode === "show" || displayZeroMode === undefined) return ""; + let styleclass = ""; + if (displayZeroMode === "transparency" || displayZeroMode === "custom") { + const transparency = this._config?.display_zero_lines?.transparency; + if (transparency ?? 50 > 0) styleclass += "transparency "; + } + if (displayZeroMode === "grey_out" || displayZeroMode === "custom") { + styleclass += "grey"; + } + return styleclass; } private computeFieldIcon(field: any, fallback: string): string { @@ -879,6 +909,17 @@ export class PowerFlowCardPlus extends LitElement { entities.home?.secondary_info?.color_value ? "var(--text-home-color)" : "var(--primary-text-color)" ); + this.style.setProperty( + "--transparency-unused-lines", + this._config?.display_zero_lines?.transparency ? this._config.display_zero_lines.transparency.toString() : "0" + ); + + if (this._config.display_zero_lines?.grey_color !== undefined) { + let greyColor = this._config.display_zero_lines.grey_color; + if (typeof greyColor === "object") greyColor = this.convertColorListToHex(greyColor); + this.style.setProperty("--greyed-out--line-color", greyColor); + } + const templatesObj = { gridSecondary: this._templateResults.gridSecondary?.result, solarSecondary: this._templateResults.solarSecondary?.result, @@ -1072,7 +1113,7 @@ export class PowerFlowCardPlus extends LitElement { ${this.showLine(nonFossil.state.power || 0) ? html` - + ${nonFossil.has ? svg` - + ${individual2.state ? svg` - + ${individual1.state ? svg` - + ${individual1.state ? svg` @@ -1591,7 +1632,7 @@ export class PowerFlowCardPlus extends LitElement { @@ -1627,9 +1668,12 @@ export class PowerFlowCardPlus extends LitElement { id="solar-battery-flow" class="flat-line" > - - ${solar.state.toBattery - ? svg` + ${ + solar.state.toBattery + ? svg` ` - : ""} + : "" + } ` : ""} @@ -1660,8 +1705,13 @@ export class PowerFlowCardPlus extends LitElement { id="grid-home-flow" class="flat-line" > - - ${grid.state.fromGrid + + ${grid.state.toHome ? svg` @@ -1721,10 +1771,7 @@ export class PowerFlowCardPlus extends LitElement { diff --git a/src/style.ts b/src/style.ts index 30e932c..7f9ddb8 100644 --- a/src/style.ts +++ b/src/style.ts @@ -32,6 +32,8 @@ export const styles = css` --lines-svg-not-flat-line-top: -3%; --lines-svg-flat-width: calc(100% - 160px); --lines-svg-not-flat-width: calc(103% - 165px); + --transparency: var(--transparency-unused-lines); + --greyed-out--line-color: #bdbdbd; } :root { } @@ -156,6 +158,12 @@ export const styles = css` stroke-width: 1; fill: none; } + path.transparency { + opacity: calc(calc(100 - var(--transparency)) / 100); + } + path.grey { + stroke: var(--greyed-out--line-color) !important; + } .circle svg { position: absolute; fill: none; diff --git a/src/ui-editor/schema/_schema-all.ts b/src/ui-editor/schema/_schema-all.ts index 4276afa..6e333c0 100644 --- a/src/ui-editor/schema/_schema-all.ts +++ b/src/ui-editor/schema/_schema-all.ts @@ -8,6 +8,8 @@ import { solarSchema } from "./solar"; import { individualSchema } from "./individual"; import { nonFossilSchema } from "./fossil_fuel_percentage"; import { homeSchema } from "./home"; +import { displayZeroLinesSchema } from "./display_zero_lines"; +import { html } from "lit-html"; const baseLovelaceCardConfig = object({ type: string(), @@ -30,7 +32,9 @@ export const cardConfigStruct = assign( max_expected_power: optional(number()), watt_threshold: optional(number()), clickable_entities: optional(boolean()), - display_zero_lines: optional(boolean()), + transparency_zero_lines: optional(number()), + greyout_zero_lines: optional(boolean()), + display_zero_lines: optional(any()), use_new_flow_rate_model: optional(boolean()), entities: object({ battery: optional(any()), @@ -104,7 +108,7 @@ export const entitiesSchema = memoizeOne((localize) => [ }, ]); -export const advancedOptionsSchema = memoizeOne((localize) => [ +export const advancedOptionsSchema = memoizeOne((localize, displayZeroLinesMode) => [ { title: localize("editor.advanced"), type: "expandable", @@ -158,11 +162,7 @@ export const advancedOptionsSchema = memoizeOne((localize) => [ label: "Watt to Kilowatt Threshold", selector: { number: { mode: "box", min: 0, max: 1000000, step: 1 } }, }, - { - name: "display_zero_lines", - label: "Display Zero Lines", - selector: { boolean: {} }, - }, + { name: "clickable_entities", label: "Clickable Entities", @@ -175,6 +175,11 @@ export const advancedOptionsSchema = memoizeOne((localize) => [ }, ], }, + { + type: "expandable", + title: localize("editor.display_zero_lines"), + schema: [...displayZeroLinesSchema(localize, displayZeroLinesMode)], + }, ], }, ]); diff --git a/src/ui-editor/schema/display_zero_lines.ts b/src/ui-editor/schema/display_zero_lines.ts new file mode 100644 index 0000000..66da72f --- /dev/null +++ b/src/ui-editor/schema/display_zero_lines.ts @@ -0,0 +1,79 @@ +import memoizeOne from "memoize-one"; + +const greyColorSchema = { + name: "grey_color", + selector: { color_rgb: {} }, +}; + +const transparencySchema = { + name: "transparency", + selector: { + number: { + min: 0, + max: 100, + step: 1, + mode: "box", + }, + }, +}; + +const gridCustomSchema = { + name: "", + type: "grid", + column_min_width: "200px", + schema: [transparencySchema, greyColorSchema], +}; + +const displayZeroLinesOptionsSchema = (mode: string) => { + switch (mode) { + case "grey_out": + return greyColorSchema; + case "transparency": + return transparencySchema; + case "custom": + return gridCustomSchema; + default: + return []; + } +}; + +export const displayZeroLinesSchema = memoizeOne((localize, mode) => [ + { + name: "display_zero_lines", + type: "grid", + column_min_width: "400px", + schema: [ + { + name: "mode", + selector: { + select: { + mode: "dropdown", + options: [ + { + value: "show", + label: localize("editor.show"), + }, + { + value: "hide", + label: localize("editor.hide"), + }, + { + value: "transparency", + label: localize("editor.transparency"), + }, + { + value: "grey_out", + label: localize("editor.grey_out"), + }, + { + value: "custom", + label: localize("editor.custom"), + }, + ], + }, + }, + }, + displayZeroLinesOptionsSchema(mode), + ], + }, +]); diff --git a/src/ui-editor/ui-editor.ts b/src/ui-editor/ui-editor.ts index 51262b2..0f0c400 100644 --- a/src/ui-editor/ui-editor.ts +++ b/src/ui-editor/ui-editor.ts @@ -8,6 +8,8 @@ import { assert } from "superstruct"; import { PowerFlowCardPlusConfig } from "../power-flow-card-plus-config"; import { cardConfigStruct, generalConfigSchema, entitiesSchema, advancedOptionsSchema } from "./schema/_schema-all"; import localize from "../localize/localize"; +import { defaultValues } from "../utils/get-default-config"; +import { coerceNumber } from "../utils/utils"; export const loadHaForm = async () => { if (customElements.get("ha-form")) return; @@ -42,6 +44,11 @@ export class PowerFlowCardPlusEditor extends LitElement implements LovelaceCardE } const data = { ...this._config, + display_zero_lines: { + mode: this._config.display_zero_lines?.mode ?? defaultValues.displayZeroLines.mode, + transparency: this._config.display_zero_lines?.transparency ?? defaultValues.displayZeroLines.transparency, + grey_color: this._config.display_zero_lines?.grey_color ?? defaultValues.displayZeroLines.grey_color, + }, }; return html` @@ -66,7 +73,7 @@ export class PowerFlowCardPlusEditor extends LitElement implements LovelaceCardE diff --git a/src/utils/get-default-config.ts b/src/utils/get-default-config.ts index 4f2a489..d912c25 100644 --- a/src/utils/get-default-config.ts +++ b/src/utils/get-default-config.ts @@ -9,6 +9,12 @@ export const defaultValues = { minExpectedPower: 0.01, maxExpectedPower: 2000, wattThreshold: 1000, + transparencyZeroLines: 0, + displayZeroLines: { + mode: "show", + transparency: 50, + grey_color: [189, 189, 189], + }, }; export function getDefaultConfig(hass: HomeAssistant): object { @@ -57,5 +63,6 @@ export function getDefaultConfig(hass: HomeAssistant): object { max_expected_power: defaultValues.maxExpectedPower, min_expected_power: defaultValues.minExpectedPower, watt_threshold: defaultValues.wattThreshold, + transparency_zero_lines: defaultValues.transparencyZeroLines, }; }