Skip to content

Commit

Permalink
feat(header): More header options and title support (#8)
Browse files Browse the repository at this point in the history
* feat(header): More header options and title support

* fix(header): Header should be off by default

* doc(header): New header options

Fixes #5
  • Loading branch information
RomRider committed Jan 26, 2021
1 parent 3a15db2 commit 2cbd769
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 46 deletions.
10 changes: 9 additions & 1 deletion .devcontainer/ui-lovelace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ views:
- type: custom:apexcharts-card
hours_to_show: 1
header:
show: false
title: Test Aggregate
show: true
show_states: true
colorize_states: true
series:
- entity: sensor.random0_100
name: AVG
Expand Down Expand Up @@ -96,6 +99,8 @@ views:

- type: custom:apexcharts-card
hours_to_show: 4
header:
title: Test
series:
- entity: sensor.humidity
type: area
Expand All @@ -109,6 +114,9 @@ views:
group_by:
func: avg
duration: 1h
- type: sensor
entity: sensor.humidity
graph: line

- type: custom:apexcharts-card
hours_to_show: 6
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ The card stricly validates all the options available (but not for the `apex_conf

| Name | Type | Default | Since | Description |
| ---- | :--: | :-----: | :---: | ----------- |
| `show` | boolean | `true` | v1.0.0 | Show or hide the header |
| `show` | boolean | `false` | v1.0.0 | Show or hide the header |
| `floating` | boolean | `false` | v1.0.0 | Makes the header float above the graph. Positionning will be supported later |
| `show_states` | boolean | `false` | NEXT_VERSION | Show or hide the states in the header |
| `colorize_states` | boolean | `false` | NEXT_VERSION | Colorize the states based on the color of the serie |

### `group_by` Options

Expand Down
40 changes: 24 additions & 16 deletions src/apex-layouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
},
series: config?.series.map((serie, index) => {
return {
name: computeName(index, config, hass?.states),
name: computeName(index, config, undefined, hass?.states[serie.entity]),
type: serie.type,
data: [],
};
Expand All @@ -53,28 +53,36 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
return moment(new Date(val)).format('MMM Do, HH:mm:ss');
},
},
y: {
formatter: function (_, opts, conf = config, hass2 = hass) {
let value = opts.w.globals.series[opts.seriesIndex].slice(-1)[0];
if (value !== null && typeof value === 'number' && !Number.isInteger(value)) {
value = (value as number).toFixed(1);
}
const uom = computeUom(
opts.seriesIndex,
conf,
undefined,
hass2?.states[conf.series[opts.seriesIndex].entity],
);
return [`<strong>${value} ${uom}</strong>`];
},
},
fixed: {
enabled: true,
postion: 'topRight',
},
},
legend: {
formatter: function (_, opts, conf = config, hass2 = hass) {
return [
`${computeName(opts.seriesIndex, conf, undefined, hass2?.states[conf.series[opts.seriesIndex].entity])}:`,
`<strong>${
opts.w.globals.series[opts.seriesIndex].slice(-1).length !== 0
? opts.w.globals.series[opts.seriesIndex].slice(-1)[0].toFixed(1)
: opts.w.globals.series[opts.seriesIndex].slice(-1)
}
${computeUom(
opts.seriesIndex,
conf,
undefined,
hass2?.states[conf.series[opts.seriesIndex].entity],
)}</strong>
`,
];
const name =
computeName(opts.seriesIndex, conf, undefined, hass2?.states[conf.series[opts.seriesIndex].entity]) + ':';
let value = opts.w.globals.series[opts.seriesIndex].slice(-1)[0];
if (value !== null && typeof value === 'number' && !Number.isInteger(value)) {
value = (value as number).toFixed(1);
}
const uom = computeUom(opts.seriesIndex, conf, undefined, hass2?.states[conf.series[opts.seriesIndex].entity]);
return [name, `<strong>${value} ${uom}</strong>`];
},
},
stroke: {
Expand Down
51 changes: 42 additions & 9 deletions src/apexcharts-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,22 @@ class ChartsCard extends LitElement {

private _loaded = false;

@property() private _updating = false;
@property({ type: Boolean }) private _updating = false;

private _graphs: (GraphEntry | undefined)[] | undefined;

@property() private _config?: ChartCardConfig;
@property({ attribute: false }) private _config?: ChartCardConfig;

@property() private _entities: HassEntity[] = [];
private _entities: HassEntity[] = [];

private _interval?: number | null;

private _intervalTimeout?: NodeJS.Timeout;

private _colors?: string[];

@property({ attribute: false }) private _lastState: (number | string | null)[] = [];

public connectedCallback() {
super.connectedCallback();
if (this._config && this._hass && !this._loaded) {
Expand Down Expand Up @@ -153,7 +155,6 @@ class ChartsCard extends LitElement {
cache: true,
useCompress: false,
show: { loading: true },
header: { show: true },
},
JSON.parse(JSON.stringify(config)),
);
Expand Down Expand Up @@ -252,11 +253,32 @@ class ChartsCard extends LitElement {
};
return html`
<div id="header" class=${classMap(classes)}>
<div id="header__title">
<span id="state">${this._entities[0].state}</span>
<span id="uom">${computeUom(0, this._config, this._entities)}</span>
</div>
<div id="header__subtitle">${computeName(0, this._config, this._entities)}</div>
${this._config?.header?.title ? html`<div id="header__title">${this._config.header.title}</div>` : html``}
${this._config?.header?.show_states ? this._renderStates() : html``}
</div>
`;
}

private _renderStates(): TemplateResult {
return html`
<div id="header__states">
${this._config?.series.map((_, index) => {
return html`
<div id="states__state">
<div id="state__value">
<span
id="state"
style="${this._colors && this._colors.length > 0
? `color: ${this._colors[index % this._colors?.length]};`
: ''}"
>${this._lastState?.[index] === 0 ? 0 : this._lastState?.[index] || 'N/A'}</span
>
<span id="uom">${computeUom(index, this._config, this._entities)}</span>
</div>
<div id="state__name">${computeName(index, this._config, this._entities)}</div>
</div>
`;
})}
</div>
`;
}
Expand Down Expand Up @@ -288,6 +310,16 @@ class ChartsCard extends LitElement {
series: this._graphs.map((graph) => {
if (!graph || graph.history.length === 0) return { data: [] };
const index = graph.index;
if (graph.history.length > 0) {
this._lastState[index] = graph.history[graph.history.length - 1][1];
if (
this._lastState[index] !== null &&
typeof this._lastState[index] === 'number' &&
!Number.isInteger(this._lastState[index])
) {
this._lastState[index] = (this._lastState[index] as number).toFixed(1);
}
}
return {
data:
this._config?.series[index].extend_to_end && this._config?.series[index].type !== 'column'
Expand All @@ -302,6 +334,7 @@ class ChartsCard extends LitElement {
},
colors: computeColors(this._colors),
};
this._lastState = [...this._lastState];
this._apexChart?.updateOptions(graphData, false, false);
} catch (err) {
log(err);
Expand Down
44 changes: 37 additions & 7 deletions src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const styles: CSSResult = css`
.wrapper {
display: grid;
grid-template-areas: "header" "graph";
grid-template-areas: 'header' 'graph';
grid-template-columns: 1fr;
grid-template-rows: min-content 1fr;
}
Expand All @@ -28,28 +28,58 @@ export const styles: CSSResult = css`
}
#header {
padding-top: 10px;
padding-left: 10px;
padding: 8px 16px 0px;
grid-area: header;
}
#header.floating {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
}
#header__title > #state {
#header__title {
color: var(--secondary-text-color);
font-size: 16px;
font-weight: 500;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding-bottom: 5px;
}
#header__states {
display: flex;
justify-content: space-between;
flex-flow: row wrap;
margin: -5px;
}
#header__states > * {
margin: 5px;
}
#states__state {
flex: 0 0 10%;
}
#state__value > #state {
font-size: 1.8em;
font-weight: 500;
}
#header__title > #uom {
#state__value > #uom {
font-size: 1em;
font-weight: 400;
opacity: 0.8;
}
#header__subtitle {
#state__name {
font-size: 0.8em;
font-weight: 300;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/* Apex Charts Default CSS */
Expand Down Expand Up @@ -318,7 +348,7 @@ export const styles: CSSResult = css`
opacity: 0;
padding: 4px 10px;
pointer-events: none;
color: var(--primary-text-color)
color: var(--primary-text-color);
font-size: 13px;
text-align: center;
border-radius: 2px;
Expand Down
3 changes: 3 additions & 0 deletions src/types-config-ti.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export const GroupByFunc = t.union(t.lit('raw'), t.lit('avg'), t.lit('min'), t.l
export const ChartCardHeaderExternalConfig = t.iface([], {
"show": t.opt("boolean"),
"floating": t.opt("boolean"),
"title": t.opt("string"),
"show_states": t.opt("boolean"),
"colorize_states": t.opt("boolean"),
});

const exportedTypeSuite: t.ITypeSuite = {
Expand Down
3 changes: 3 additions & 0 deletions src/types-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ export type GroupByFunc = 'raw' | 'avg' | 'min' | 'max' | 'last' | 'first' | 'su
export interface ChartCardHeaderExternalConfig {
show?: boolean;
floating?: boolean;
title?: string;
show_states?: boolean;
colorize_states?: boolean;
}
28 changes: 16 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export function computeName(
} else if (entities) {
return (
config.series[index].name ||
entities[config.series[index].entity]?.attributes?.friendly_name ||
entities[entities[config.series[index].entity]]?.entity_id ||
entities[index]?.attributes?.friendly_name ||
entities[entities[index]]?.entity_id ||
''
);
}
Expand All @@ -85,22 +85,26 @@ export function computeUom(
if (entity) {
return config.series[index].unit || entity.attributes?.unit_of_measurement || '';
} else if (entities) {
return config.series[index].unit || entities[config.series[index].entity]?.attributes?.unit_of_measurement || '';
return config.series[index].unit || entities[index]?.attributes?.unit_of_measurement || '';
}
return '';
}

export function computeColors(colors: string[] | undefined): string[] {
if (!colors) return [];
return colors.map((color) => {
if (color[0] === '#') {
return color;
} else if (color.substring(0, 3) === 'var') {
return new TinyColor(
window.getComputedStyle(document.documentElement).getPropertyValue(color.substring(4).slice(0, -1)).trim(),
).toHexString();
} else {
return new TinyColor(color).toHexString();
}
return computeColor(color);
});
}

export function computeColor(color: string): string {
if (color[0] === '#') {
return color;
} else if (color.substring(0, 3) === 'var') {
return new TinyColor(
window.getComputedStyle(document.documentElement).getPropertyValue(color.substring(4).slice(0, -1)).trim(),
).toHexString();
} else {
return new TinyColor(color).toHexString();
}
}

0 comments on commit 2cbd769

Please sign in to comment.