diff --git a/.devcontainer/ui-lovelace.yaml b/.devcontainer/ui-lovelace.yaml index c0dc3f4..096d926 100644 --- a/.devcontainer/ui-lovelace.yaml +++ b/.devcontainer/ui-lovelace.yaml @@ -1184,7 +1184,29 @@ views: graph_span: 1h header: show: true + show_states: true title: Test Extremas + all_series_config: + header_actions: + tap_action: + action: fire-dom-event + browser_mod: + command: popup + card: + type: button + entity: sensor.random0_100 + style: | + ha-dialog { + --mdc-dialog-max-width: 100vw !important; + } + :host .content { + width: 98vw !important; + } + ha-card { + border-radius: 0.8vw; + opacity: 0.9; + } + title: Synology NAS series: - entity: sensor.random_0_1000 name: Min diff --git a/src/apex-layouts.ts b/src/apex-layouts.ts index b224bc2..72ef637 100644 --- a/src/apex-layouts.ts +++ b/src/apex-layouts.ts @@ -10,7 +10,7 @@ import { TIMESERIES_TYPES, } from './const'; import { ChartCardConfig } from './types'; -import { computeName, computeUom, is12Hour, mergeDeep, prettyPrintTime, truncateFloat } from './utils'; +import { computeName, computeUom, is12Hour, mergeDeep, myFormatNumber, prettyPrintTime } from './utils'; import { layoutMinimal } from './layouts/minimal'; import { getLocales, getDefaultLocale } from './locales'; import GraphEntry from './graphEntry'; @@ -63,10 +63,10 @@ export function getLayoutConfig( dataLabels: { enabled: getDataLabelsEnabled(config), enabledOnSeries: getDataLabels_enabledOnSeries(config), - formatter: getDataLabelsFormatter(config, graphs), + formatter: getDataLabelsFormatter(config, graphs, hass), }, plotOptions: { - radialBar: getPlotOptions_radialBar(config), + radialBar: getPlotOptions_radialBar(config, hass), }, legend: { position: 'bottom', @@ -293,7 +293,7 @@ function getYTooltipFormatter(config: ChartCardConfig, hass: HomeAssistant | und lValue = -lValue; } if (!conf.series_in_graph[opts.seriesIndex]?.show.as_duration) { - lValue = truncateFloat(lValue, conf.series_in_graph[opts.seriesIndex].float_precision); + lValue = myFormatNumber(lValue, hass?.locale, conf.series_in_graph[opts.seriesIndex].float_precision); } const uom = computeUom( opts.seriesIndex, @@ -317,25 +317,31 @@ function getDataLabelsEnabled(config: ChartCardConfig): boolean { ); } -function getDataLabelsFormatter(config: ChartCardConfig, graphs: (GraphEntry | undefined)[] | undefined) { +function getDataLabelsFormatter( + config: ChartCardConfig, + graphs: (GraphEntry | undefined)[] | undefined, + hass: HomeAssistant | undefined, +) { if (config.chart_type === 'pie' || config.chart_type === 'donut') { - return function (value, opts, lgraphs = graphs, conf = config) { + return function (value, opts, lgraphs = graphs, conf = config, lHass = hass) { if (conf.series_in_graph[opts.seriesIndex].show.datalabels !== false) { if (conf.series_in_graph[opts.seriesIndex].show.datalabels === 'percent') { - return truncateFloat(value, conf.series_in_graph[opts.seriesIndex].float_precision); + return myFormatNumber(value, lHass?.locale, conf.series_in_graph[opts.seriesIndex].float_precision); } - return truncateFloat( + return myFormatNumber( lgraphs?.[conf.series_in_graph[opts.seriesIndex].index]?.lastState, + lHass?.locale, conf.series_in_graph[opts.seriesIndex].float_precision, ); } return ''; }; } - return function (value, opts, conf = config) { + return function (value, opts, conf = config, lHass = hass) { if (conf.series_in_graph[opts.seriesIndex].show.datalabels === 'total') { - return truncateFloat( + return myFormatNumber( opts.w.globals.stackedSeriesTotals[opts.dataPointIndex], + lHass?.locale, conf.series_in_graph[opts.seriesIndex].float_precision, ); } @@ -344,11 +350,11 @@ function getDataLabelsFormatter(config: ChartCardConfig, graphs: (GraphEntry | u if (conf.series_in_graph[opts.seriesIndex]?.invert && lValue) { lValue = -lValue; } - return truncateFloat(lValue, conf.series_in_graph[opts.seriesIndex].float_precision); + return myFormatNumber(lValue, lHass?.locale, conf.series_in_graph[opts.seriesIndex].float_precision); }; } -function getPlotOptions_radialBar(config: ChartCardConfig) { +function getPlotOptions_radialBar(config: ChartCardConfig, hass: HomeAssistant | undefined) { if (config.chart_type === 'radialBar') { return { track: { @@ -356,12 +362,12 @@ function getPlotOptions_radialBar(config: ChartCardConfig) { }, dataLabels: { value: { - formatter: function (value, opts, conf = config) { + formatter: function (value, opts, conf = config, lHass = hass) { const index = opts?.config?.series?.findIndex((x) => { return parseFloat(value) === x; }); if (index != -1) { - return truncateFloat(value, conf.series_in_graph[index].float_precision) + '%'; + return myFormatNumber(value, lHass?.locale, conf.series_in_graph[index].float_precision) + '%'; } return value; }, @@ -391,7 +397,7 @@ function getLegendFormatter(config: ChartCardConfig, hass: HomeAssistant | undef value = -value; } if (!conf.series_in_graph[opts.seriesIndex]?.show.as_duration) { - value = truncateFloat(value, conf.series_in_graph[opts.seriesIndex].float_precision); + value = myFormatNumber(value, hass2?.locale, conf.series_in_graph[opts.seriesIndex].float_precision); } const uom = config.chart_type === 'radialBar' diff --git a/src/apexcharts-card.ts b/src/apexcharts-card.ts index 9ac4b88..ea01fe8 100644 --- a/src/apexcharts-card.ts +++ b/src/apexcharts-card.ts @@ -28,6 +28,7 @@ import { mergeConfigTemplates, mergeDeep, mergeDeepConfig, + myFormatNumber, offsetData, prettyPrintTime, truncateFloat, @@ -1030,7 +1031,7 @@ class ChartsCard extends LitElement { fillColor: 'var(--card-background-color)', }, label: { - text: truncateFloat(value[1], serie.float_precision)?.toString(), + text: myFormatNumber(value[1], this._hass?.locale, serie.float_precision), borderColor: 'var(--card-background-color)', borderWidth: 2, style: { @@ -1353,7 +1354,8 @@ class ChartsCard extends LitElement { } private _computeLastState(value: number | null, index: number): string | number | null { - return truncateFloat(value, this._config?.series[index].float_precision); + if (value === null) return value; + return myFormatNumber(value, this._hass?.locale, this._config?.series[index].float_precision); } /* diff --git a/src/utils.ts b/src/utils.ts index 4c87df3..a3e63cd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,7 +5,7 @@ import { TinyColor } from '@ctrl/tinycolor'; import parse from 'parse-duration'; import { ChartCardExternalConfig, ChartCardPrettyTime, ChartCardSeriesExternalConfig } from './types-config'; import { DEFAULT_FLOAT_PRECISION, DEFAULT_MAX, DEFAULT_MIN, moment, NO_VALUE } from './const'; -import { HomeAssistant, LovelaceConfig } from 'custom-card-helpers'; +import { formatNumber, FrontendLocaleData, HomeAssistant, LovelaceConfig } from 'custom-card-helpers'; export function compress(data: unknown): string { return lzStringCompress(JSON.stringify(data)); @@ -272,3 +272,21 @@ export function truncateFloat( } return lValue; } + +export function myFormatNumber( + num: string | number | null | undefined, + localeOptions?: FrontendLocaleData, + precision?: number | undefined, +): string | null { + let lValue: string | number | null | undefined = num; + if (lValue === undefined || lValue === null) return null; + if (typeof lValue === 'string') { + lValue = parseFloat(lValue); + if (Number.isNaN(lValue)) { + return num as string; + } + } + return formatNumber(lValue, localeOptions, { + maximumFractionDigits: precision === undefined ? DEFAULT_FLOAT_PRECISION : precision, + }); +}