Skip to content

Commit

Permalink
chore: Refactor show/hide in chart from #36
Browse files Browse the repository at this point in the history
  • Loading branch information
RomRider committed Feb 2, 2021
1 parent 9632047 commit 5221b57
Show file tree
Hide file tree
Showing 10 changed files with 9,529 additions and 7,099 deletions.
12 changes: 9 additions & 3 deletions .devcontainer/ui-lovelace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ views:
type: line
show:
as_duration: millisecond
in_header: true
in_chart: false
group_by:
duration: 10min
func: avg
Expand Down Expand Up @@ -121,16 +123,20 @@ views:
name: LAST
type: line
show:
as_duration: month
# as_duration: month
in_header: true
in_chart: false
# show:
# as_duration: month
group_by:
duration: 10min
func: last
- entity: sensor.random0_100
curve: smooth
name: FIRST
type: line
show:
as_duration: year
# show:
# as_duration: year
group_by:
duration: 10min
func: first
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ The card stricly validates all the options available (but not for the `apex_conf
| ---- | :--: | :-----: | :---: | ----------- |
| `legend_value` | boolean | `true` | v1.3.0 | Show/Hide the state in the legend. Will still display the name |
| `as_duration` | string | | v1.3.0 | Will pretty print the states as durations. Doesn't affect the graph, only the tooltip/legend/header display. You provide the source unit of your sensor. Valid values are `millisecond`, `second`, `minute`, `hour`, `day`, `week`, `month`, `year`.<br/>Eg: if the state is `345` and `as_duration` is set to `minute` then it would display `5h 45m` |
| `in_header` | boolean | `true` | NEXT_VERSION |If `show_states` is enabled, this would enable/disable this specific serie in the header |
| `in_chart` | boolean | `true` | NEXT_VERSION |If `false`, hides the series from the chart. Putting this to `false` in any serie will also hide all the series which are completely empty (ie no data at all) from the legend |
| `in_header` | boolean | `true` | NEXT_VERSION | If `show_states` is enabled, this would show/hide this specific serie in the header |
| `in_chart` | boolean | `true` | NEXT_VERSION | If `false`, hides the serie from the chart |


### Main `show` Options
Expand Down
16,412 changes: 9,396 additions & 7,016 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@ctrl/tinycolor": "^3.3.3",
"apexcharts": "^3.23.1",
"array-flat-polyfill": "^1.0.1",
"custom-card-helpers": "^1.6.6",
"home-assistant-js-websocket": "^5.7.0",
"lit-element": "^2.4.0",
Expand All @@ -47,6 +48,8 @@
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-typescript": "^7.12.7",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
Expand Down
12 changes: 10 additions & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ const plugins = [
babel({
exclude: 'node_modules/**',
babelHelpers: 'bundled',
babelrc: false,
presets: [
'@babel/preset-env',
{
useBuiltIns: 'entry',
targets: '> 0.25%, not dead',
},
],
}),
// cleanup({ comments: 'none' }),
dev && serve(serveopts),
!dev &&
terser({
format: {
terser({
format: {
comments: false,
},
mangle: {
Expand Down
65 changes: 35 additions & 30 deletions src/apex-layouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,28 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
strokeDashArray: 3,
},
fill: {
opacity: config.series.map((serie) => {
return serie.type === 'area' ? 0.7 : 1;
opacity: config.series.flatMap((serie) => {
if (!serie.show.in_chart) return [];
return [serie.type === 'area' ? 0.7 : 1];
}),
},
series: TIMESERIES_TYPES.includes(config.chart_type)
? config?.series.map((serie, index) => {
return {
name: computeName(index, config, undefined, hass?.states[serie.entity]),
type: serie.type,
data: [],
};
? config?.series.flatMap((serie, index) => {
if (!serie.show.in_chart) return [];
return [
{
name: computeName(index, config.series, undefined, hass?.states[serie.entity]),
type: serie.type,
data: [],
},
];
})
: [],
labels: TIMESERIES_TYPES.includes(config.chart_type)
? []
: config.series.map((serie, index) => {
return computeName(index, config, undefined, hass?.states[serie.entity]);
: config.series.flatMap((serie, index) => {
if (!serie.show.in_chart) return [];
return [computeName(index, config.series, undefined, hass?.states[serie.entity])];
}),
xaxis: TIMESERIES_TYPES.includes(config.chart_type)
? {
Expand Down Expand Up @@ -73,23 +78,23 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
value !== null &&
typeof value === 'number' &&
!Number.isInteger(value) &&
!conf.series[opts.seriesIndex]?.show.as_duration
!conf.series_in_graph[opts.seriesIndex]?.show.as_duration
) {
value = (value as number).toFixed(
conf.series[opts.seriesIndex].float_precision === undefined
conf.series_in_graph[opts.seriesIndex].float_precision === undefined
? DEFAULT_FLOAT_PRECISION
: conf.series[opts.seriesIndex].float_precision,
: conf.series_in_graph[opts.seriesIndex].float_precision,
);
}
const uom = computeUom(
opts.seriesIndex,
conf,
conf.series_in_graph,
undefined,
hass2?.states[conf.series[opts.seriesIndex].entity],
hass2?.states[conf.series_in_graph[opts.seriesIndex].entity],
);
return conf.series[opts.seriesIndex]?.show.as_duration
return conf.series_in_graph[opts.seriesIndex]?.show.as_duration
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
[`<strong>${prettyPrintTime(value, conf.series[opts.seriesIndex].show.as_duration!)}</strong>`]
[`<strong>${prettyPrintTime(value, conf.series_in_graph[opts.seriesIndex].show.as_duration!)}</strong>`]
: [`<strong>${value} ${uom}</strong>`];
},
},
Expand Down Expand Up @@ -119,17 +124,16 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
: {},
},
legend: {
showForNullSeries: !config.series.some((serie) => serie.show.in_chart === false),
position: 'bottom',
show: true,
formatter: function (_, opts, conf = config, hass2 = hass) {
const name = computeName(
opts.seriesIndex,
conf,
conf.series_in_graph,
undefined,
hass2?.states[conf.series[opts.seriesIndex].entity],
hass2?.states[conf.series_in_graph[opts.seriesIndex].entity],
);
if (!conf.series[opts.seriesIndex].show.legend_value) {
if (!conf.series_in_graph[opts.seriesIndex].show.legend_value) {
return [name];
} else {
let value = TIMESERIES_TYPES.includes(config.chart_type)
Expand All @@ -139,29 +143,29 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
value !== null &&
typeof value === 'number' &&
!Number.isInteger(value) &&
!conf.series[opts.seriesIndex]?.show.as_duration
!conf.series_in_graph[opts.seriesIndex]?.show.as_duration
) {
value = (value as number).toFixed(
conf.series[opts.seriesIndex].float_precision === undefined
conf.series_in_graph[opts.seriesIndex].float_precision === undefined
? DEFAULT_FLOAT_PRECISION
: conf.series[opts.seriesIndex].float_precision,
: conf.series_in_graph[opts.seriesIndex].float_precision,
);
}
const uom = computeUom(
opts.seriesIndex,
conf,
conf.series_in_graph,
undefined,
hass2?.states[conf.series[opts.seriesIndex].entity],
hass2?.states[conf.series_in_graph[opts.seriesIndex].entity],
);
let valueString = '';
if (value === undefined || value === null) {
valueString = `<strong>${NO_VALUE} ${uom}</strong>`;
} else {
if (conf.series[opts.seriesIndex]?.show.as_duration) {
if (conf.series_in_graph[opts.seriesIndex]?.show.as_duration) {
valueString = `<strong>${prettyPrintTime(
value,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
conf.series[opts.seriesIndex].show.as_duration!,
conf.series_in_graph[opts.seriesIndex].show.as_duration!,
)}</strong>`;
} else {
valueString = `<strong>${value} ${uom}</strong>`;
Expand All @@ -172,8 +176,9 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u
},
},
stroke: {
curve: config.series.map((serie) => {
return serie.curve || 'smooth';
curve: config.series.flatMap((serie) => {
if (!serie.show.in_chart) return [];
return [serie.curve || 'smooth'];
}),
lineCap: config.chart_type === 'radialBar' ? 'round' : 'butt',
colors:
Expand Down
82 changes: 59 additions & 23 deletions src/apexcharts-card.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'array-flat-polyfill';
import { LitElement, html, customElement, property, TemplateResult, CSSResult, PropertyValues } from 'lit-element';
import { ClassInfo, classMap } from 'lit-html/directives/class-map';
import { ChartCardConfig, EntityCachePoints, EntityEntryCache } from './types';
Expand Down Expand Up @@ -97,7 +98,9 @@ class ChartsCard extends LitElement {

private _intervalTimeout?: NodeJS.Timeout;

private _colors?: string[];
private _colors: string[] = [];

private _headerColors: string[] = [...DEFAULT_COLORS];

private _graphSpan: number = HOUR_24;

Expand Down Expand Up @@ -259,11 +262,13 @@ class ChartsCard extends LitElement {
);

if (this._config) {
this._colors = [...DEFAULT_COLORS];
// this._colors = [...DEFAULT_COLORS];
this._graphs = this._config.series.map((serie, index) => {
if (!this._headerColors[index]) {
this._headerColors[index] = this._headerColors[index % DEFAULT_COLORS.length];
}
if (serie.color) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this._colors![index] = serie.color;
this._headerColors[index] = serie.color;
}
serie.extend_to_end = serie.extend_to_end !== undefined ? serie.extend_to_end : true;
serie.type = this._config?.chart_type ? undefined : serie.type || DEFAULT_SERIE_TYPE;
Expand Down Expand Up @@ -307,7 +312,17 @@ class ChartsCard extends LitElement {
}
return undefined;
});
this._config.series_in_graph = [];
this._config.series.forEach((serie, index) => {
if (serie.show.in_chart) {
this._colors.push(this._headerColors[index]);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this._config!.series_in_graph.push(serie);
}
});
this._headerColors = this._headerColors.slice(0, this._config?.series.length);
}

// Full reset only happens in editor mode
this._reset();
}
Expand Down Expand Up @@ -387,8 +402,10 @@ class ChartsCard extends LitElement {
<div id="state__value">
<span
id="state"
style="${this._config?.header?.colorize_states && this._colors && this._colors.length > 0
? `color: ${this._colors[index % this._colors?.length]};`
style="${this._config?.header?.colorize_states &&
this._headerColors &&
this._headerColors.length > 0
? `color: ${this._headerColors[index]};`
: ''}"
>${this._lastState?.[index] === 0
? 0
Expand All @@ -397,10 +414,10 @@ class ChartsCard extends LitElement {
: this._lastState?.[index]) || NO_VALUE}</span
>
${!serie.show.as_duration
? html`<span id="uom">${computeUom(index, this._config, this._entities)}</span>`
? html`<span id="uom">${computeUom(index, this._config?.series, this._entities)}</span>`
: ''}
</div>
<div id="state__name">${computeName(index, this._config, this._entities)}</div>
<div id="state__name">${computeName(index, this._config?.series, this._entities)}</div>
</div>
`;
} else {
Expand Down Expand Up @@ -442,9 +459,18 @@ class ChartsCard extends LitElement {
let graphData: unknown = {};
if (TIMESERIES_TYPES.includes(this._config.chart_type)) {
graphData = {
series: this._graphs.map((graph, index) => {
if (!graph || graph.history.length === 0) return { data: [] };
this._lastState[index] = this._computeLastState(graph.history[graph.history.length - 1][1], index);
series: this._graphs.flatMap((graph, index) => {
if (!graph) return [];
if (graph.history.length === 0) {
this._lastState[index] = null;
} else {
const lastState = graph.history[graph.history.length - 1][1];
this._lastState[index] = this._computeLastState(lastState, index);
}
if (!this._config?.series[index].show.in_chart) {
return [];
}
if (graph.history.length === 0) return [{ data: [] }];
let data: EntityCachePoints = [];
if (this._config?.series[index].extend_to_end && this._config?.series[index].type !== 'column') {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Expand All @@ -453,9 +479,7 @@ class ChartsCard extends LitElement {
data = graph.history;
}
data = offsetData(data, this._seriesOffset[index]);
if (this._config?.series[index].show.in_chart)
return this._config?.series[index].invert ? { data: this._invertData(data) } : { data };
return { data: [] };
return [this._config?.series[index].invert ? { data: this._invertData(data) } : { data }];
}),
xaxis: {
min: start.getTime(),
Expand All @@ -466,19 +490,31 @@ class ChartsCard extends LitElement {
} else {
// No timeline charts
graphData = {
series: this._graphs.map((graph, index) => {
if (!graph || graph.history.length === 0) return;
const lastState = graph.history[graph.history.length - 1][1];
this._lastState[index] = this._computeLastState(lastState, index);
if (!this._config?.series[index].show.in_chart) return;
if (lastState === null) {
return;
series: this._graphs.flatMap((graph, index) => {
if (!graph) return [];
if (graph.history.length === 0) {
this._lastState[index] = null;
} else {
const lastState = graph.history[graph.history.length - 1][1];
this._lastState[index] = this._computeLastState(lastState, index);
}
if (!this._config?.series[index].show.in_chart) {
return [];
}
if (this._lastState[index] === null) {
return [0];
} else {
if (this._config?.chart_type === 'radialBar') {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return getPercentFromValue(lastState, this._config.series[index].min, this._config.series[index].max);
return [
getPercentFromValue(
this._lastState[index] as number,
this._config.series[index].min,
this._config.series[index].max,
),
];
} else {
return lastState;
return [this._lastState[index]];
}
}
}),
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {

export interface ChartCardConfig extends ChartCardExternalConfig {
series: ChartCardSeriesConfig[];
series_in_graph: ChartCardSeriesConfig[];
graph_span: string;
cache: boolean;
useCompress: boolean;
Expand Down

0 comments on commit 5221b57

Please sign in to comment.