Skip to content

Commit

Permalink
Merge pull request #16 from amaximus/master
Browse files Browse the repository at this point in the history
Box coloring based on entity state
  • Loading branch information
MindFreeze authored May 28, 2022
2 parents 69b3e91 + c938be6 commit de28cab
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This card is intended to display connections between entities with numeric state
| wide | boolean | **Optional** | false | Set this to true if you see extra empty space in the right side of the card. This will expand it horizontally to cover all the available space. Enable if you see empty space on the right size.
| show_icons | boolean | **Optional** | false | Display entity icons
| show_names | boolean | **Optional** | false | Display entity names
| show_states | boolean | **Optional** | true | Display entity states
| min_box_height | number | **Optional** | 3 | Minimum size of an entity box
| min_box_distance | number | **Optional** | 5 | Minimum space between entity boxes

Expand All @@ -43,6 +44,10 @@ This card is intended to display connections between entities with numeric state
| children | list | **Required** | | List of entity ids describing child entities (branches). Only entities from the next section will be connected.
| name | string | **Optional** | entity name from HA | Custom label for this entity
| color | string | **Optional** | var(--primary-color)| Color of the box
| color_on_state | boolean | **Optional** | false | Color the box based on state value
| color_limit | string | **Optional** | 1 | State value for coloring the box based on state value
| color_above | string | **Optional** | var(--paper-item-icon-color)| Color for state value above color_limit
| color_below | string | **Optional** | var(--primary-color)| Color for state value below color_limit
| remaining | [object](#remaining-object) | **Optional** | | This configures wheter to display a box for the remaining state if the sum of entity states from children is less than this entity's state.

### Remaining object
Expand Down
37 changes: 23 additions & 14 deletions src/ha-sankey-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class SankeyChart extends LitElement {
// https://lit.dev/docs/components/properties/
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) private entities: string[] = [];

@state() private config!: Config;
@state() public height = 200;
@state() private sections: SectionState[] = [];
Expand All @@ -81,6 +81,7 @@ export class SankeyChart extends LitElement {
round: 0,
min_box_height: 3,
min_box_distance: 5,
show_states: true,
...config,
};

Expand Down Expand Up @@ -152,11 +153,11 @@ export class SankeyChart extends LitElement {
}

protected renderSection(index: number): TemplateResult {
const {show_names, show_icons} = this.config;
const {show_names, show_icons, show_states} = this.config;
const section = this.sections[index];
const {boxes, spacerH} = section;
const hasChildren = index < this.sections.length - 1 && boxes.some(b => b.children.length > 0);

return html`
<div class="section">
${hasChildren ?
Expand All @@ -177,14 +178,14 @@ export class SankeyChart extends LitElement {
return html`
${i > 0 ? html`<div class="spacerv" style=${styleMap({height: spacerH+'px'})}></div>` : null}
<div class="box" style=${styleMap({height: box.size+'px'})}>
<div style=${styleMap({backgroundColor: box.color})}
@click=${() => this._handleBoxClick(box)}
<div style=${styleMap({backgroundColor: box.color})}
@click=${() => this._handleBoxClick(box)}
title=${name}
>
${show_icons ? html`<ha-icon .icon=${stateIcon(box.entity)}></ha-icon>` : null}
</div>
<div class="label" style=${styleMap(labelStyle)}>
<span class="state">${formattedState}</span><span class="unit">${box.unit_of_measurement}</span>
${show_states ? html`<span class="state">${formattedState}</span><span class="unit">${box.unit_of_measurement}</span>` : null}
${show_names ? html`<span class="name">&nbsp;${name}</span>` : null}
</div>
</div>
Expand Down Expand Up @@ -214,10 +215,10 @@ export class SankeyChart extends LitElement {
}

const connection = {
startY,
startSize,
startY,
startSize,
startColor: b.color,
endY,
endY,
endSize,
endColor: c.color,
};
Expand Down Expand Up @@ -262,7 +263,7 @@ export class SankeyChart extends LitElement {
const entity = this._getEntityState(entityConf);
// eslint-disable-next-line prefer-const
let {state, unit_of_measurement} = this._normalizeStateValue(
Number(entity.state),
Number(entity.state),
entity.attributes.unit_of_measurement
);
if (entityConf.accountedState) {
Expand All @@ -280,7 +281,7 @@ export class SankeyChart extends LitElement {
let children = entityConf.children || [];
if (entityConf.remaining && extraEntities[sectionIndex + 1]) {
children = [...children, entityConf.entity_id];
const remainingConf = typeof entityConf.remaining === 'string'
const remainingConf = typeof entityConf.remaining === 'string'
? {name: entityConf.remaining} : entityConf.remaining;
extraEntities[sectionIndex + 1].push({
...entityConf,
Expand All @@ -290,13 +291,21 @@ export class SankeyChart extends LitElement {
});
}

let finalColor = entityConf.color || 'var(--primary-color)';
if (typeof entityConf.color_on_state != 'undefined' && entityConf.color_on_state) {
const colorLimit = typeof entityConf.color_limit === 'undefined' ? 1 : entityConf.color_limit;
const colorBelow = typeof entityConf.color_below === 'undefined' ? 'var(--primary-color)' : entityConf.color_below;
const colorAbove = typeof entityConf.color_above === 'undefined' ? 'var(--paper-item-icon-color)' : entityConf.color_above;
finalColor = state > colorLimit ? colorAbove : colorBelow;
}

return {
config: entityConf,
entity,
entity_id: this._getEntityId(entityConf),
state,
unit_of_measurement,
color: entityConf.color || 'var(--primary-color)',
color: finalColor,
children,
connections: {parents: []},
top: 0,
Expand All @@ -313,7 +322,7 @@ export class SankeyChart extends LitElement {
}
// leave room for margin
const availableHeight = this.height - ((boxes.length - 1) * this.config.min_box_distance);
// calc sizes to determine statePerPixelY ratio and find the best one
// calc sizes to determine statePerPixelY ratio and find the best one
const calcResults = this._calcBoxHeights(boxes, availableHeight, total);
boxes = calcResults.boxes;
const totalSize = boxes.reduce((sum, b) => sum + b.size, 0);
Expand Down Expand Up @@ -413,7 +422,7 @@ export class SankeyChart extends LitElement {
}
return {
state: state * currentFactor / targetFactor,
unit_of_measurement: prefix
unit_of_measurement: prefix
? unit_of_measurement.replace(prefix, unit_prefix) : unit_prefix + unit_of_measurement,
};
}
Expand Down
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export type EntityConfig = {
children?: string[];
color?: string;
name?: string;
color_on_state?: boolean;
color_above?: string;
color_below?: string;
color_limit?: number;
remaining?: string | {
name: string;
color?: string;
Expand Down Expand Up @@ -43,6 +47,7 @@ export interface SankeyChartConfig extends LovelaceCardConfig {
show_names?: boolean;
min_box_height?: number,
min_box_distance?: number,
show_states?: boolean;
}

export interface Config extends SankeyChartConfig {
Expand Down Expand Up @@ -80,4 +85,4 @@ export interface SectionState {
total: number,
spacerH: number,
statePerPixelY: number,
}
}

0 comments on commit de28cab

Please sign in to comment.