@oneuptime/common 11.5.0 → 11.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.ts +2 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1783937343400-MigrationName.ts +386 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AnalyticsDatabaseService.ts +59 -7
- package/Server/Services/MetricService.ts +124 -28
- package/Server/Services/SpanService.ts +11 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +39 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +8 -5
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +84 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +167 -0
- package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +40 -0
- package/Types/BaseDatabase/AggregateBy.ts +11 -1
- package/Types/BaseDatabase/AggregationInterval.ts +10 -0
- package/Types/BaseDatabase/AggregationIntervalUtil.ts +23 -0
- package/Types/Metrics/MetricFormulaConfigData.ts +5 -0
- package/Types/Metrics/MetricQueryConfigData.ts +19 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +15 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +16 -2
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +31 -32
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +41 -17
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +38 -34
- package/UI/Components/Charts/ChartLibrary/SparkChart/SparkChart.tsx +4 -3
- package/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts +48 -10
- package/UI/Components/Charts/Line/LineChart.tsx +15 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +61 -2
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.js +2 -2
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783650000000-AddAdditionalParamsToLlmProvider.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783937343400-MigrationName.js +384 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783937343400-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +43 -5
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +110 -23
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/SpanService.js +10 -0
- package/build/dist/Server/Services/SpanService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +32 -0
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +2 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Types/BaseDatabase/AggregationInterval.js +10 -0
- package/build/dist/Types/BaseDatabase/AggregationInterval.js.map +1 -1
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +13 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +3 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +3 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +13 -9
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +19 -7
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +21 -9
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/SparkChart/SparkChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/ChartColors.js +26 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/ChartColors.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +3 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +44 -4
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import GroupBy from "../../Server/Types/Database/GroupBy";
|
|
2
2
|
import GenericObject from "../GenericObject";
|
|
3
|
+
import AggregationInterval from "./AggregationInterval";
|
|
3
4
|
import AggregationType from "./AggregationType";
|
|
4
5
|
import Query from "./Query";
|
|
5
6
|
import Sort from "./Sort";
|
|
@@ -7,7 +8,16 @@ import Sort from "./Sort";
|
|
|
7
8
|
export default interface AggregateBy<TBaseModel extends GenericObject> {
|
|
8
9
|
aggregateColumnName: keyof TBaseModel;
|
|
9
10
|
aggregationType: AggregationType;
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Optional explicit time-bucket size. When omitted (the default), the
|
|
13
|
+
* bucket size is derived from the query window (≤3h → minute, ≤7d →
|
|
14
|
+
* hour, ≤6w → day, …) — see AggregationIntervalUtil. Set this to pin a
|
|
15
|
+
* granularity independent of the window (e.g. `Day` buckets over a
|
|
16
|
+
* one-week window), or to `Total` to aggregate the whole window into a
|
|
17
|
+
* single value per group (no time bucketing). Invalid values are
|
|
18
|
+
* rejected with a 400 in AnalyticsDatabaseService.aggregateBy.
|
|
19
|
+
*/
|
|
20
|
+
aggregationInterval?: AggregationInterval | undefined;
|
|
11
21
|
aggregationTimestampColumnName: keyof TBaseModel;
|
|
12
22
|
startTimestamp: Date;
|
|
13
23
|
endTimestamp: Date;
|
|
@@ -5,6 +5,16 @@ export enum AggregationInterval {
|
|
|
5
5
|
Week = "Week",
|
|
6
6
|
Month = "Month",
|
|
7
7
|
Year = "Year",
|
|
8
|
+
/**
|
|
9
|
+
* No time bucketing: collapse the entire [startTimestamp, endTimestamp]
|
|
10
|
+
* window into a single aggregate per group (one total value over the
|
|
11
|
+
* whole range). Only meaningful as an explicit
|
|
12
|
+
* `AggregateBy.aggregationInterval` override — the window-derived
|
|
13
|
+
* interval picker never returns it. Builders emit one row per group with
|
|
14
|
+
* the earliest sample timestamp in the window as the bucket label (see
|
|
15
|
+
* AggregateUtil.buildBucketTimestampSelect).
|
|
16
|
+
*/
|
|
17
|
+
Total = "Total",
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
export default AggregationInterval;
|
|
@@ -16,7 +16,21 @@ export class AggregationIntervalUtil {
|
|
|
16
16
|
public static getAggregationIntervalForWindow(data: {
|
|
17
17
|
startDate: Date;
|
|
18
18
|
endDate: Date;
|
|
19
|
+
/**
|
|
20
|
+
* Explicit override. When set to a valid AggregationInterval it is
|
|
21
|
+
* returned verbatim (including `Total`), so callers can pin a bucket
|
|
22
|
+
* size independent of the window. Unknown/undefined falls through to
|
|
23
|
+
* the window-derived interval below.
|
|
24
|
+
*/
|
|
25
|
+
aggregationInterval?: AggregationInterval | undefined;
|
|
19
26
|
}): AggregationInterval {
|
|
27
|
+
if (
|
|
28
|
+
data.aggregationInterval &&
|
|
29
|
+
Object.values(AggregationInterval).includes(data.aggregationInterval)
|
|
30
|
+
) {
|
|
31
|
+
return data.aggregationInterval;
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
const startDate: Date = OneUptimeDate.fromString(data.startDate);
|
|
21
35
|
const endDate: Date = OneUptimeDate.fromString(data.endDate);
|
|
22
36
|
|
|
@@ -65,6 +79,15 @@ export class AggregationIntervalUtil {
|
|
|
65
79
|
return 1000 * 60 * 60 * 24 * 30;
|
|
66
80
|
case AggregationInterval.Year:
|
|
67
81
|
return 1000 * 60 * 60 * 24 * 365;
|
|
82
|
+
case AggregationInterval.Total:
|
|
83
|
+
/*
|
|
84
|
+
* `Total` is a single whole-window bucket with no fixed width. The
|
|
85
|
+
* window-derived picker never returns it, so grid-reconstruction
|
|
86
|
+
* callers (heartbeat charts, XAxis) never see it. Return a very
|
|
87
|
+
* large finite width (~1000 years) so any defensive fixed-step
|
|
88
|
+
* grid walk emits a single slot instead of looping forever.
|
|
89
|
+
*/
|
|
90
|
+
return 1000 * 60 * 60 * 24 * 365 * 1000;
|
|
68
91
|
default:
|
|
69
92
|
return 1000 * 60;
|
|
70
93
|
}
|
|
@@ -8,4 +8,9 @@ export default interface MetricFormulaConfigData {
|
|
|
8
8
|
chartType?: MetricChartType | undefined;
|
|
9
9
|
warningThreshold?: number | undefined;
|
|
10
10
|
criticalThreshold?: number | undefined;
|
|
11
|
+
/*
|
|
12
|
+
* Optional user-chosen color for the formula's series, stored as a hex
|
|
13
|
+
* string (e.g. "#6366f1"). Unset = auto-assigned from the chart palette.
|
|
14
|
+
*/
|
|
15
|
+
color?: string | undefined;
|
|
11
16
|
}
|
|
@@ -31,6 +31,25 @@ export default interface MetricQueryConfigData {
|
|
|
31
31
|
| undefined;
|
|
32
32
|
warningThreshold?: number | undefined;
|
|
33
33
|
criticalThreshold?: number | undefined;
|
|
34
|
+
/*
|
|
35
|
+
* Optional user-chosen color for this query's series. Stored as a hex
|
|
36
|
+
* string (e.g. "#6366f1") — the preset swatches write their palette hex
|
|
37
|
+
* and the custom picker writes an arbitrary hex. When set, it becomes the
|
|
38
|
+
* lead color for this query's chart (single-series → the series color;
|
|
39
|
+
* grouped multi-series → the first series, with the default palette filling
|
|
40
|
+
* the rest). Unset = auto-assigned from the chart-type palette.
|
|
41
|
+
*/
|
|
42
|
+
color?: string | undefined;
|
|
43
|
+
/*
|
|
44
|
+
* Per-group color pins for GROUP-BY queries. Keyed by the individual
|
|
45
|
+
* "key=value" segment that MetricCharts' series renderer emits for a
|
|
46
|
+
* grouped series — e.g. { "service.name=api": "#f59e0b" }. Use "(unset)"
|
|
47
|
+
* as the value for null/empty groups to match the series name. A series
|
|
48
|
+
* whose composed name contains a pinned segment renders in that color
|
|
49
|
+
* (first matching segment wins for multi-key group-bys); unpinned series
|
|
50
|
+
* fall back to `color` (lead) then the chart-type palette. Stored as hex.
|
|
51
|
+
*/
|
|
52
|
+
colorsByGroup?: Record<string, string> | undefined;
|
|
34
53
|
/*
|
|
35
54
|
* When true, the post-aggregation series points are transformed into
|
|
36
55
|
* a per-second rate of change: `(value - previousValue) / Δt`. This is
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { AreaChart } from "../ChartLibrary/AreaChart/AreaChart";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AvailableChartColorsKeys,
|
|
4
|
+
ChartColorValue,
|
|
5
|
+
} from "../ChartLibrary/Utils/ChartColors";
|
|
3
6
|
import React, {
|
|
4
7
|
FunctionComponent,
|
|
5
8
|
ReactElement,
|
|
@@ -51,6 +54,12 @@ export interface ComponentProps {
|
|
|
51
54
|
*/
|
|
52
55
|
anomalyBandLowerSeriesName?: string | undefined;
|
|
53
56
|
anomalyBandUpperSeriesName?: string | undefined;
|
|
57
|
+
/*
|
|
58
|
+
* Optional per-series color override (named palette keys or hex strings).
|
|
59
|
+
* When provided, replaces the default AreaChartPalette. Indexed by series
|
|
60
|
+
* position (index % length).
|
|
61
|
+
*/
|
|
62
|
+
colors?: Array<ChartColorValue> | undefined;
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
export interface AreaInternalProps extends ComponentProps {
|
|
@@ -138,7 +147,11 @@ const AreaChartElement: FunctionComponent<AreaInternalProps> = (
|
|
|
138
147
|
tickGap={30}
|
|
139
148
|
index={"Time"}
|
|
140
149
|
categories={categories}
|
|
141
|
-
colors={
|
|
150
|
+
colors={
|
|
151
|
+
props.colors && props.colors.length > 0
|
|
152
|
+
? props.colors
|
|
153
|
+
: AreaChartPalette
|
|
154
|
+
}
|
|
142
155
|
valueFormatter={props.yAxis.options.formatter || undefined}
|
|
143
156
|
showTooltip={true}
|
|
144
157
|
showLegend={props.showLegend !== false}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { BarChart } from "../ChartLibrary/BarChart/BarChart";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AvailableChartColorsKeys,
|
|
4
|
+
ChartColorValue,
|
|
5
|
+
} from "../ChartLibrary/Utils/ChartColors";
|
|
3
6
|
import React, { FunctionComponent, ReactElement, useEffect } from "react";
|
|
4
7
|
import SeriesPoint from "../Types/SeriesPoints";
|
|
5
8
|
import { XAxis } from "../Types/XAxis/XAxis";
|
|
@@ -29,6 +32,13 @@ export interface ComponentProps {
|
|
|
29
32
|
heightInPx?: number | undefined;
|
|
30
33
|
referenceLines?: Array<ChartReferenceLineProps> | undefined;
|
|
31
34
|
showLegend?: boolean | undefined;
|
|
35
|
+
/*
|
|
36
|
+
* Optional per-series color override. Each entry may be a named palette key
|
|
37
|
+
* or a raw hex string. When provided (and non-empty), it replaces the
|
|
38
|
+
* default BarChartPalette so callers can assign custom colors; the array is
|
|
39
|
+
* indexed by series position (index % length), matching the default palette.
|
|
40
|
+
*/
|
|
41
|
+
colors?: Array<ChartColorValue> | undefined;
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
export interface BarInternalProps extends ComponentProps {
|
|
@@ -71,7 +81,11 @@ const BarChartElement: FunctionComponent<BarInternalProps> = (
|
|
|
71
81
|
tickGap={30}
|
|
72
82
|
index={"Time"}
|
|
73
83
|
categories={categories}
|
|
74
|
-
colors={
|
|
84
|
+
colors={
|
|
85
|
+
props.colors && props.colors.length > 0
|
|
86
|
+
? props.colors
|
|
87
|
+
: BarChartPalette
|
|
88
|
+
}
|
|
75
89
|
valueFormatter={props.yAxis.options.formatter || undefined}
|
|
76
90
|
showTooltip={true}
|
|
77
91
|
showLegend={props.showLegend !== false}
|
|
@@ -26,10 +26,11 @@ import { AxisDomain } from "recharts/types/util/types";
|
|
|
26
26
|
import { useOnWindowResize } from "../Utils/UseWindowOnResize";
|
|
27
27
|
import {
|
|
28
28
|
AvailableChartColors,
|
|
29
|
-
|
|
29
|
+
ChartColorValue,
|
|
30
30
|
constructCategoryColors,
|
|
31
31
|
getColorClassName,
|
|
32
32
|
getColorHex,
|
|
33
|
+
isHexColorValue,
|
|
33
34
|
} from "../Utils/ChartColors";
|
|
34
35
|
import { cx } from "../Utils/Cx";
|
|
35
36
|
import { getYAxisDomain } from "../Utils/GetYAxisDomain";
|
|
@@ -40,8 +41,8 @@ import ChartCurve from "../../Types/ChartCurve";
|
|
|
40
41
|
|
|
41
42
|
interface LegendItemProps {
|
|
42
43
|
name: string;
|
|
43
|
-
color:
|
|
44
|
-
onClick?: (name: string, color:
|
|
44
|
+
color: ChartColorValue;
|
|
45
|
+
onClick?: (name: string, color: ChartColorValue) => void;
|
|
45
46
|
activeLegend?: string;
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -76,6 +77,11 @@ const LegendItem: ({
|
|
|
76
77
|
getColorClassName(color, "bg"),
|
|
77
78
|
activeLegend && activeLegend !== name ? "opacity-40" : "opacity-100",
|
|
78
79
|
)}
|
|
80
|
+
style={
|
|
81
|
+
isHexColorValue(color)
|
|
82
|
+
? { backgroundColor: getColorHex(color) }
|
|
83
|
+
: undefined
|
|
84
|
+
}
|
|
79
85
|
aria-hidden={true}
|
|
80
86
|
/>
|
|
81
87
|
<p
|
|
@@ -163,7 +169,7 @@ const ScrollButton: ({
|
|
|
163
169
|
|
|
164
170
|
interface LegendProps extends React.OlHTMLAttributes<HTMLOListElement> {
|
|
165
171
|
categories: string[];
|
|
166
|
-
colors?:
|
|
172
|
+
colors?: ChartColorValue[];
|
|
167
173
|
onClickLegendItem?: (category: string, color: string) => void;
|
|
168
174
|
activeLegend?: string;
|
|
169
175
|
enableLegendSlider?: boolean;
|
|
@@ -307,7 +313,7 @@ const Legend: React.ForwardRefExoticComponent<
|
|
|
307
313
|
<LegendItem
|
|
308
314
|
key={`item-${index}`}
|
|
309
315
|
name={category}
|
|
310
|
-
color={colors[index] as
|
|
316
|
+
color={colors[index] as ChartColorValue}
|
|
311
317
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
312
318
|
onClick={onClickLegendItem as any}
|
|
313
319
|
activeLegend={activeLegend!}
|
|
@@ -356,7 +362,7 @@ type PayloadItem = {
|
|
|
356
362
|
category: string;
|
|
357
363
|
value: number;
|
|
358
364
|
index: string;
|
|
359
|
-
color:
|
|
365
|
+
color: ChartColorValue;
|
|
360
366
|
type?: string;
|
|
361
367
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
362
368
|
payload: any;
|
|
@@ -366,7 +372,7 @@ type PayloadItem = {
|
|
|
366
372
|
const ChartLegend: (
|
|
367
373
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
368
374
|
{ payload }: any,
|
|
369
|
-
categoryColors: Map<string,
|
|
375
|
+
categoryColors: Map<string, ChartColorValue>,
|
|
370
376
|
setLegendHeight: React.Dispatch<React.SetStateAction<number>>,
|
|
371
377
|
activeLegend: string | undefined,
|
|
372
378
|
onClick?: (category: string, color: string) => void,
|
|
@@ -376,7 +382,7 @@ const ChartLegend: (
|
|
|
376
382
|
) => React.JSX.Element = (
|
|
377
383
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
378
384
|
{ payload }: any,
|
|
379
|
-
categoryColors: Map<string,
|
|
385
|
+
categoryColors: Map<string, ChartColorValue>,
|
|
380
386
|
setLegendHeight: React.Dispatch<React.SetStateAction<number>>,
|
|
381
387
|
activeLegend: string | undefined,
|
|
382
388
|
onClick?: (category: string, color: string) => void,
|
|
@@ -485,6 +491,11 @@ const ChartTooltip: ({
|
|
|
485
491
|
"h-[3px] w-3.5 shrink-0 rounded-full",
|
|
486
492
|
getColorClassName(color, "bg"),
|
|
487
493
|
)}
|
|
494
|
+
style={
|
|
495
|
+
isHexColorValue(color)
|
|
496
|
+
? { backgroundColor: getColorHex(color) }
|
|
497
|
+
: undefined
|
|
498
|
+
}
|
|
488
499
|
/>
|
|
489
500
|
<p
|
|
490
501
|
className={cx(
|
|
@@ -534,7 +545,7 @@ interface AreaChartProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
534
545
|
data: Record<string, any>[];
|
|
535
546
|
index: string;
|
|
536
547
|
categories: string[];
|
|
537
|
-
colors?:
|
|
548
|
+
colors?: ChartColorValue[];
|
|
538
549
|
valueFormatter?: (value: number) => string;
|
|
539
550
|
startEndOnly?: boolean;
|
|
540
551
|
showXAxis?: boolean;
|
|
@@ -620,7 +631,7 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
620
631
|
const [activeLegend, setActiveLegend] = React.useState<string | undefined>(
|
|
621
632
|
undefined,
|
|
622
633
|
);
|
|
623
|
-
const categoryColors: Map<string,
|
|
634
|
+
const categoryColors: Map<string, ChartColorValue> =
|
|
624
635
|
constructCategoryColors(categories, colors);
|
|
625
636
|
|
|
626
637
|
const yAxisDomain: (number | "auto")[] = getYAxisDomain(
|
|
@@ -716,9 +727,8 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
716
727
|
>
|
|
717
728
|
<defs>
|
|
718
729
|
{categories.map((category: string, i: number) => {
|
|
719
|
-
const colorKey:
|
|
720
|
-
(colors[i % colors.length] as
|
|
721
|
-
"blue";
|
|
730
|
+
const colorKey: ChartColorValue =
|
|
731
|
+
(colors[i % colors.length] as ChartColorValue) || "blue";
|
|
722
732
|
const hex: string = getColorHex(colorKey);
|
|
723
733
|
return (
|
|
724
734
|
<linearGradient
|
|
@@ -833,7 +843,7 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
833
843
|
index: item.payload[index],
|
|
834
844
|
color: categoryColors.get(
|
|
835
845
|
item.dataKey,
|
|
836
|
-
) as
|
|
846
|
+
) as ChartColorValue,
|
|
837
847
|
type: item.type,
|
|
838
848
|
payload: item.payload,
|
|
839
849
|
};
|
|
@@ -921,10 +931,11 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
921
931
|
) : null}
|
|
922
932
|
{categories.map((category: string) => {
|
|
923
933
|
const gradientId: string = `gradient-${category.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
924
|
-
const colorKey:
|
|
934
|
+
const colorKey: ChartColorValue = categoryColors.get(
|
|
925
935
|
category,
|
|
926
|
-
) as
|
|
936
|
+
) as ChartColorValue;
|
|
927
937
|
const hex: string = getColorHex(colorKey);
|
|
938
|
+
const isCustomColor: boolean = isHexColorValue(colorKey);
|
|
928
939
|
|
|
929
940
|
return (
|
|
930
941
|
<Area
|
|
@@ -954,24 +965,18 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
954
965
|
strokeLinecap: slc,
|
|
955
966
|
strokeLinejoin: slj,
|
|
956
967
|
strokeWidth,
|
|
957
|
-
dataKey,
|
|
958
968
|
} = dotProps;
|
|
959
969
|
return (
|
|
960
970
|
<Dot
|
|
961
971
|
className={cx(
|
|
962
972
|
"stroke-white",
|
|
963
973
|
onValueChange ? "cursor-pointer" : "",
|
|
964
|
-
getColorClassName(
|
|
965
|
-
categoryColors.get(
|
|
966
|
-
dataKey,
|
|
967
|
-
) as AvailableChartColorsKeys,
|
|
968
|
-
"fill",
|
|
969
|
-
),
|
|
974
|
+
getColorClassName(colorKey, "fill"),
|
|
970
975
|
)}
|
|
971
976
|
cx={cxCoord}
|
|
972
977
|
cy={cyCoord}
|
|
973
978
|
r={5}
|
|
974
|
-
fill=""
|
|
979
|
+
fill={isCustomColor ? hex : ""}
|
|
975
980
|
stroke={stroke}
|
|
976
981
|
strokeLinecap={slc}
|
|
977
982
|
strokeLinejoin={slj}
|
|
@@ -992,7 +997,6 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
992
997
|
strokeWidth,
|
|
993
998
|
cx: cxCoord,
|
|
994
999
|
cy: cyCoord,
|
|
995
|
-
dataKey,
|
|
996
1000
|
index: dotIndex,
|
|
997
1001
|
} = dotProps;
|
|
998
1002
|
|
|
@@ -1012,19 +1016,14 @@ const AreaChart: React.ForwardRefExoticComponent<
|
|
|
1012
1016
|
cy={cyCoord}
|
|
1013
1017
|
r={5}
|
|
1014
1018
|
stroke={stroke}
|
|
1015
|
-
fill=""
|
|
1019
|
+
fill={isCustomColor ? hex : ""}
|
|
1016
1020
|
strokeLinecap={slc}
|
|
1017
1021
|
strokeLinejoin={slj}
|
|
1018
1022
|
strokeWidth={strokeWidth}
|
|
1019
1023
|
className={cx(
|
|
1020
1024
|
"stroke-white",
|
|
1021
1025
|
onValueChange ? "cursor-pointer" : "",
|
|
1022
|
-
getColorClassName(
|
|
1023
|
-
categoryColors.get(
|
|
1024
|
-
dataKey,
|
|
1025
|
-
) as AvailableChartColorsKeys,
|
|
1026
|
-
"fill",
|
|
1027
|
-
),
|
|
1026
|
+
getColorClassName(colorKey, "fill"),
|
|
1028
1027
|
)}
|
|
1029
1028
|
/>
|
|
1030
1029
|
);
|
|
@@ -22,9 +22,11 @@ import type { AxisDomain } from "recharts/types/util/types";
|
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
24
|
AvailableChartColors,
|
|
25
|
-
type
|
|
25
|
+
type ChartColorValue,
|
|
26
26
|
constructCategoryColors,
|
|
27
27
|
getColorClassName,
|
|
28
|
+
getColorHex,
|
|
29
|
+
isHexColorValue,
|
|
28
30
|
} from "../Utils/ChartColors";
|
|
29
31
|
import { cx } from "../Utils/Cx";
|
|
30
32
|
import { getYAxisDomain } from "../Utils/GetYAxisDomain";
|
|
@@ -73,7 +75,7 @@ const renderShape: (
|
|
|
73
75
|
activeLegend: string | undefined,
|
|
74
76
|
layout: string,
|
|
75
77
|
): React.ReactElement => {
|
|
76
|
-
const { fillOpacity, name, payload, value } = props;
|
|
78
|
+
const { fillOpacity, name, payload, value, fill } = props;
|
|
77
79
|
let { x, width, y, height } = props;
|
|
78
80
|
|
|
79
81
|
if (layout === "horizontal" && height < 0) {
|
|
@@ -120,6 +122,12 @@ const renderShape: (
|
|
|
120
122
|
return (
|
|
121
123
|
<path
|
|
122
124
|
d={path}
|
|
125
|
+
/*
|
|
126
|
+
* A custom hex color is passed through as the Bar's `fill` prop; apply
|
|
127
|
+
* it directly on the path. For named palette colors `fill` is "" and the
|
|
128
|
+
* path inherits the Tailwind `fill-*` class set on the parent Bar.
|
|
129
|
+
*/
|
|
130
|
+
{...(fill ? { fill } : {})}
|
|
123
131
|
opacity={
|
|
124
132
|
activeBar || (activeLegend && activeLegend !== name)
|
|
125
133
|
? deepEqual(activeBar, { ...payload, value })
|
|
@@ -135,7 +143,7 @@ const renderShape: (
|
|
|
135
143
|
|
|
136
144
|
interface LegendItemProps {
|
|
137
145
|
name: string;
|
|
138
|
-
color:
|
|
146
|
+
color: ChartColorValue;
|
|
139
147
|
onClick?: (name: string, color: string) => void;
|
|
140
148
|
activeLegend?: string;
|
|
141
149
|
}
|
|
@@ -167,6 +175,11 @@ const LegendItem: React.FunctionComponent<LegendItemProps> = ({
|
|
|
167
175
|
getColorClassName(color, "bg"),
|
|
168
176
|
activeLegend && activeLegend !== name ? "opacity-40" : "opacity-100",
|
|
169
177
|
)}
|
|
178
|
+
style={
|
|
179
|
+
isHexColorValue(color)
|
|
180
|
+
? { backgroundColor: getColorHex(color) }
|
|
181
|
+
: undefined
|
|
182
|
+
}
|
|
170
183
|
aria-hidden={true}
|
|
171
184
|
/>
|
|
172
185
|
<p
|
|
@@ -252,7 +265,7 @@ const ScrollButton: React.FunctionComponent<ScrollButtonProps> = ({
|
|
|
252
265
|
|
|
253
266
|
interface LegendProps extends React.OlHTMLAttributes<HTMLOListElement> {
|
|
254
267
|
categories: string[];
|
|
255
|
-
colors?:
|
|
268
|
+
colors?: ChartColorValue[];
|
|
256
269
|
onClickLegendItem?: (category: string, color: string) => void;
|
|
257
270
|
activeLegend?: string;
|
|
258
271
|
enableLegendSlider?: boolean;
|
|
@@ -398,7 +411,7 @@ const Legend: React.ForwardRefExoticComponent<
|
|
|
398
411
|
<LegendItem
|
|
399
412
|
key={`item-${index}`}
|
|
400
413
|
name={category}
|
|
401
|
-
color={colors[index] as
|
|
414
|
+
color={colors[index] as ChartColorValue}
|
|
402
415
|
{...(onClickLegendItem ? { onClick: onClickLegendItem } : {})}
|
|
403
416
|
{...(activeLegend ? { activeLegend: activeLegend } : {})}
|
|
404
417
|
/>
|
|
@@ -443,7 +456,7 @@ Legend.displayName = "Legend";
|
|
|
443
456
|
|
|
444
457
|
const ChartLegend: (
|
|
445
458
|
payload: any,
|
|
446
|
-
categoryColors: Map<string,
|
|
459
|
+
categoryColors: Map<string, ChartColorValue>,
|
|
447
460
|
setLegendHeight: React.Dispatch<React.SetStateAction<number>>,
|
|
448
461
|
activeLegend: string | undefined,
|
|
449
462
|
onClick?: (category: string, color: string) => void,
|
|
@@ -452,7 +465,7 @@ const ChartLegend: (
|
|
|
452
465
|
yAxisWidth?: number,
|
|
453
466
|
) => React.ReactElement = (
|
|
454
467
|
{ payload }: any,
|
|
455
|
-
categoryColors: Map<string,
|
|
468
|
+
categoryColors: Map<string, ChartColorValue>,
|
|
456
469
|
setLegendHeight: React.Dispatch<React.SetStateAction<number>>,
|
|
457
470
|
activeLegend: string | undefined,
|
|
458
471
|
onClick?: (category: string, color: string) => void,
|
|
@@ -497,7 +510,7 @@ const ChartLegend: (
|
|
|
497
510
|
return entry.value;
|
|
498
511
|
})}
|
|
499
512
|
colors={filteredPayload.map((entry: any) => {
|
|
500
|
-
return categoryColors.get(entry.value) as
|
|
513
|
+
return categoryColors.get(entry.value) as ChartColorValue;
|
|
501
514
|
})}
|
|
502
515
|
{...(onClick ? { onClickLegendItem: onClick } : {})}
|
|
503
516
|
{...(activeLegend ? { activeLegend: activeLegend } : {})}
|
|
@@ -518,7 +531,7 @@ type PayloadItem = {
|
|
|
518
531
|
category: string; // eslint-disable-line react/no-unused-prop-types
|
|
519
532
|
value: number; // eslint-disable-line react/no-unused-prop-types
|
|
520
533
|
index: string; // eslint-disable-line react/no-unused-prop-types
|
|
521
|
-
color:
|
|
534
|
+
color: ChartColorValue; // eslint-disable-line react/no-unused-prop-types
|
|
522
535
|
type?: string; // eslint-disable-line react/no-unused-prop-types
|
|
523
536
|
payload: any;
|
|
524
537
|
};
|
|
@@ -575,6 +588,11 @@ const ChartTooltip: React.FunctionComponent<ChartTooltipProps> = ({
|
|
|
575
588
|
"size-2 shrink-0 rounded-xs",
|
|
576
589
|
getColorClassName(color, "bg"),
|
|
577
590
|
)}
|
|
591
|
+
style={
|
|
592
|
+
isHexColorValue(color)
|
|
593
|
+
? { backgroundColor: getColorHex(color) }
|
|
594
|
+
: undefined
|
|
595
|
+
}
|
|
578
596
|
/>
|
|
579
597
|
<p
|
|
580
598
|
className={cx(
|
|
@@ -622,7 +640,7 @@ interface BarChartProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
622
640
|
data: Record<string, any>[];
|
|
623
641
|
index: string;
|
|
624
642
|
categories: string[];
|
|
625
|
-
colors?:
|
|
643
|
+
colors?: ChartColorValue[];
|
|
626
644
|
valueFormatter?: (value: number) => string;
|
|
627
645
|
startEndOnly?: boolean;
|
|
628
646
|
showXAxis?: boolean;
|
|
@@ -699,7 +717,7 @@ const BarChart: React.ForwardRefExoticComponent<
|
|
|
699
717
|
const [activeLegend, setActiveLegend] = React.useState<string | undefined>(
|
|
700
718
|
undefined,
|
|
701
719
|
);
|
|
702
|
-
const categoryColors: Map<string,
|
|
720
|
+
const categoryColors: Map<string, ChartColorValue> =
|
|
703
721
|
constructCategoryColors(categories, colors);
|
|
704
722
|
const [activeBar, setActiveBar] = React.useState<any | undefined>(
|
|
705
723
|
undefined,
|
|
@@ -942,7 +960,7 @@ const BarChart: React.ForwardRefExoticComponent<
|
|
|
942
960
|
index: item.payload[index],
|
|
943
961
|
color: categoryColors.get(
|
|
944
962
|
item.dataKey,
|
|
945
|
-
) as
|
|
963
|
+
) as ChartColorValue,
|
|
946
964
|
type: item.type,
|
|
947
965
|
payload: item.payload,
|
|
948
966
|
};
|
|
@@ -1000,13 +1018,14 @@ const BarChart: React.ForwardRefExoticComponent<
|
|
|
1000
1018
|
/>
|
|
1001
1019
|
) : null}
|
|
1002
1020
|
{categories.map((category: string) => {
|
|
1021
|
+
const barColor: ChartColorValue = categoryColors.get(
|
|
1022
|
+
category,
|
|
1023
|
+
) as ChartColorValue;
|
|
1024
|
+
const isCustomColor: boolean = isHexColorValue(barColor);
|
|
1003
1025
|
return (
|
|
1004
1026
|
<Bar
|
|
1005
1027
|
className={cx(
|
|
1006
|
-
getColorClassName(
|
|
1007
|
-
categoryColors.get(category) as AvailableChartColorsKeys,
|
|
1008
|
-
"fill",
|
|
1009
|
-
),
|
|
1028
|
+
getColorClassName(barColor, "fill"),
|
|
1010
1029
|
onValueChange ? "cursor-pointer" : "",
|
|
1011
1030
|
)}
|
|
1012
1031
|
key={category}
|
|
@@ -1015,7 +1034,12 @@ const BarChart: React.ForwardRefExoticComponent<
|
|
|
1015
1034
|
dataKey={category}
|
|
1016
1035
|
{...(stacked ? { stackId: "stack" } : {})}
|
|
1017
1036
|
isAnimationActive={false}
|
|
1018
|
-
|
|
1037
|
+
/*
|
|
1038
|
+
* Custom hex → apply the color inline (Tailwind has no class
|
|
1039
|
+
* for arbitrary user hex); named palette → keep "" so the
|
|
1040
|
+
* `fill-*` class on the Bar cascades to the shape path.
|
|
1041
|
+
*/
|
|
1042
|
+
fill={isCustomColor ? getColorHex(barColor) : ""}
|
|
1019
1043
|
shape={shapeRenderer}
|
|
1020
1044
|
onClick={onBarClick}
|
|
1021
1045
|
/>
|