Skip to content

Commit

Permalink
Merge pull request #21 from davet2001/add-gui-card-editors
Browse files Browse the repository at this point in the history
Add UI card editors
  • Loading branch information
davet2001 authored Jan 5, 2025
2 parents bbd0ae4 + 550d87a commit d113cbb
Show file tree
Hide file tree
Showing 36 changed files with 5,594 additions and 281 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Energy Sankey is a collection of dashboard cards for homeassistant, dynamically

![alt text](image.png)

The cards are ideal if you want to track your energy consumption and identify where your energy is going.
The cards are ideal if you want to track your electricity consumption and identify where your energy is going.

The aim is for as easy setup as possible. No configuring groups of child entities, complicated choices or hunting for info to populate a yaml configuration. In most cases, the default configuration should just work.

Expand All @@ -34,7 +34,7 @@ The diagram dynamically scales to fit the size of the window it is in (mostly).
- Reload when prompted
- Select a dashboard and enter editing mode
- Type 'Sankey' in the search box
- Select 'Custom: Sankey Energy Flow Card' or 'Custom: Sakney Power Flow Card'
- Select 'Custom: Sankey Energy Flow Card' or 'Custom: Sankey Power Flow Card'
- The energy card does not require configuration
- The power card auto configures. If there are any problems with autoconfiguration, edit the displayed yaml to select the correct power entities for grid input / generation / consumers.

Expand Down
1,336 changes: 1,146 additions & 190 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 19 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@
"url": "https://github.com/davet2001/homeassistant-energy-sankey-card"
},
"dependencies": {
"@davethompson/elec-sankey": "^1.0.0",
"@material/mwc-icon-button": "^0.27.0",
"@material/mwc-list": "^0.27.0",
"@material/mwc-textfield": "^0.27.0",
"@mdi/js": "^7.4.47",
"@vaadin/combo-box": "24.5.3",
"@vaadin/vaadin-themable-mixin": "24.5.3",
"color-name": "^2.0.0",
"date-fns": "^4.1.0",
"date-fns-tz": "^3.2.0",
"home-assistant-js-websocket": "^9.4.0",
"lit": "^2.8.0",
"memoize-one": "^6.0.0"
"memoize-one": "^6.0.0",
"sortablejs": "^1.15.6"
},
"devDependencies": {
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-typescript": "^11.1.6",
Expand All @@ -34,5 +38,17 @@
"rollup-plugin-serve": "^2.0.3",
"tslib": "^2.8.0",
"typescript": "^5.5.3"
},
"overrides": {
"@lit/reactive-element": "1.6.3"
},
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
"resolutions": {
"@polymer/polymer": "patch:@polymer/[email protected]#./.yarn/patches/@polymer/polymer/pr-5569.patch",
"@material/mwc-button@^0.25.3": "^0.27.0",
"lit": "2.8.0",
"lit-html": "2.8.0",
"@fullcalendar/daygrid": "6.1.15",
"globals": "15.12.0"
}
}
24 changes: 24 additions & 0 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,37 @@
import json from "@rollup/plugin-json";
import nodeResolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import alias from "@rollup/plugin-alias";

const plugins = [
typescript({
declaration: false,
}),
nodeResolve(),
json(),
alias({
entries: {
// "lit/static-html$": "lit/static-html.js",
"lit/decorators": "lit/decorators.js",
// "lit/directive$": "lit/directive.js",
// "lit/directives/until$": "lit/directives/until.js",
// "lit/directives/class-map$": "lit/directives/class-map.js",
// "lit/directives/style-map$": "lit/directives/style-map.js",
"lit/directives/if-defined": "lit/directives/if-defined.js",
// "lit/directives/guard$": "lit/directives/guard.js",
// "lit/directives/cache$": "lit/directives/cache.js",
"lit/directives/repeat": "lit/directives/repeat.js",
// "lit/directives/live$": "lit/directives/live.js",
// "lit/directives/keyed$": "lit/directives/keyed.js",
// "lit/polyfill-support$": "lit/polyfill-support.js",
// "@lit-labs/virtualizer/layouts/grid":
// "@lit-labs/virtualizer/layouts/grid.js",
// "@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver":
// "@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver.js",
// "@lit-labs/observers/resize-controller":
// "@lit-labs/observers/resize-controller.js",
},
}),
];

export default {
Expand Down
2 changes: 2 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash
# Script to setup node.js ready for card development.
# So far this has been used inside a homeassistant core vscode devcontainer.
#
# After completing setup, use
#
# npm run start
Expand Down
6 changes: 6 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const PREFIX_NAME = 'energy-sankey';

export const POWER_CARD_NAME = `${PREFIX_NAME}-power-flow-card`;
export const POWER_CARD_EDITOR_NAME = `${POWER_CARD_NAME}-editor`;
export const ENERGY_CARD_NAME = `${PREFIX_NAME}-energy-elec-flow-card`;
export const ENERGY_CARD_EDITOR_NAME = `${ENERGY_CARD_NAME}-editor`;
65 changes: 65 additions & 0 deletions src/energy-flow-card-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { customElement, property, state } from "lit/decorators";

import { LovelaceCardEditor } from "./ha/panels/lovelace/types";
import { EnergyElecFlowCardConfig, PowerFlowCardConfig } from "./types";
import { html, LitElement, nothing } from "lit";
import { HomeAssistant, LocalizeFunc } from "./ha/types";
import { HaFormSchema } from "./utils/form/ha-form";
import "./ha/panels/lovelace/editor/hui-entities-card-row-editor";
import { fireEvent } from "./ha/common/dom/fire_event";

import { ENERGY_CARD_EDITOR_NAME } from "./const";

const schema = [
{ name: "title", selector: { text: {} } },
];

@customElement(ENERGY_CARD_EDITOR_NAME)
export class EnergyFlowCardEditor extends LitElement implements LovelaceCardEditor {

@property({ attribute: false }) public hass!: HomeAssistant;

@state() private _config?: EnergyElecFlowCardConfig;

public setConfig(config: EnergyElecFlowCardConfig): void {
this._config = config;
}

private _computeLabel = (schema: HaFormSchema) => {
switch (schema.name) {
case "title": return "Title";
}
console.error("Error name key missing for '" + schema.name + "'")
return ""
};

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

const data = { ...this._config } as any;
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${schema}
.computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged}
></ha-form>
<ha-alert
alert-type="info"
.title="Note"
>
Energy flow entities are configured in the
<a href="/config/energy">Energy Dashboard Config</a>.
They cannot be modified via the card configuration.
</ha-alert>
`;
}

private _valueChanged(ev: CustomEvent): void {
const config = ev.detail.value;
fireEvent(this, "config-changed", { config });
}
}
13 changes: 13 additions & 0 deletions src/ha/common/dom/get_main_window.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { MAIN_WINDOW_NAME } from "../../data/main_window";

export const mainWindow = (() => {
try {
return window.name === MAIN_WINDOW_NAME
? window
: parent.name === MAIN_WINDOW_NAME
? parent
: top!;
} catch {
return window;
}
})();
47 changes: 47 additions & 0 deletions src/ha/common/string/compare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import memoizeOne from "memoize-one";

const collator = memoizeOne(
(language: string | undefined) => new Intl.Collator(language)
);

const caseInsensitiveCollator = memoizeOne(
(language: string | undefined) =>
new Intl.Collator(language, { sensitivity: "accent" })
);

const fallbackStringCompare = (a: string, b: string) => {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}

return 0;
};

export const stringCompare = (
a: string,
b: string,
language: string | undefined = undefined
) => {
// @ts-ignore
if (Intl?.Collator) {
return collator(language).compare(a, b);
}

return fallbackStringCompare(a, b);
};

export const caseInsensitiveStringCompare = (
a: string,
b: string,
language: string | undefined = undefined
) => {
// @ts-ignore
if (Intl?.Collator) {
return caseInsensitiveCollator(language).compare(a, b);
}

return fallbackStringCompare(a.toLowerCase(), b.toLowerCase());
};
Loading

0 comments on commit d113cbb

Please sign in to comment.