@oneuptime/common 10.0.70 → 10.0.72
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/Models/DatabaseModels/Alert.ts +55 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +6 -4
- package/Models/DatabaseModels/Project.ts +5 -5
- package/Models/DatabaseModels/StatusPage.ts +80 -0
- package/Server/API/StatusPageAPI.ts +4 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.ts +6 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AIBillingService.ts +2 -2
- package/Server/Services/AnalyticsDatabaseService.ts +17 -7
- package/Server/Services/BillingService.ts +116 -48
- package/Server/Services/NotificationService.ts +2 -2
- package/Server/Types/Database/QueryUtil.ts +13 -7
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +175 -29
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +71 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +170 -7
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +171 -2
- package/Server/Utils/Monitor/MonitorIncident.ts +212 -8
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +423 -1
- package/Server/Utils/Monitor/MonitorResource.ts +2 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +99 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +268 -0
- package/Types/BaseDatabase/IncludesNone.ts +1 -4
- package/Types/Email.ts +50 -0
- package/Types/Infrastructure/BasicMetrics.ts +75 -0
- package/Types/Metrics/MetricQueryData.ts +11 -0
- package/Types/Monitor/CriteriaFilter.ts +10 -0
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +11 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +10 -0
- package/Types/Monitor/MetricMonitor/MetricSeriesResult.ts +20 -0
- package/Types/Monitor/MonitorMetricType.ts +34 -0
- package/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts +8 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +25 -0
- package/Types/StatusPage/StatusPageLanguage.ts +29 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +17 -12
- package/UI/Components/Charts/Bar/BarChart.tsx +16 -11
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +23 -0
- package/UI/Components/Charts/Line/LineChart.tsx +16 -11
- package/UI/Components/Filters/DateFilter.tsx +16 -8
- package/UI/Components/Filters/EntityFilter.tsx +33 -18
- package/UI/Components/Filters/FilterViewer.tsx +7 -5
- package/UI/Components/Filters/FiltersForm.tsx +27 -5
- package/UI/Components/Filters/NumberFilter.tsx +3 -2
- package/UI/Components/Filters/TextFilter.tsx +5 -4
- package/UI/Components/ModelTable/BaseModelTable.tsx +5 -3
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +453 -0
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +229 -0
- package/Utils/Metrics/MetricSeriesFingerprint.ts +97 -0
- package/Utils/Monitor/MonitorMetricType.ts +309 -19
- package/build/dist/Models/DatabaseModels/Alert.js +57 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +57 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +6 -4
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +5 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +82 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +4 -0
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.js +4 -2
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776881254913-DedupeKubernetesClustersAndAddUniqueIndex.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776940714709-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776971364783-AddStatusPageLanguageSettings.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/AIBillingService.js +2 -2
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +14 -4
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +99 -39
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/NotificationService.js +2 -2
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +13 -7
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +132 -30
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +58 -7
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +134 -12
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +112 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +159 -15
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +373 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +2 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +65 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js +199 -0
- package/build/dist/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.js.map +1 -1
- package/build/dist/Types/BaseDatabase/IncludesNone.js.map +1 -1
- package/build/dist/Types/Email.js +42 -0
- package/build/dist/Types/Email.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +10 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MetricMonitor/MetricSeriesResult.js +2 -0
- package/build/dist/Types/Monitor/MetricMonitor/MetricSeriesResult.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js +28 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/StatusPage/StatusPageLanguage.js +21 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -12
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +12 -11
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +11 -3
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +12 -11
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Filters/DateFilter.js +1 -4
- package/build/dist/UI/Components/Filters/DateFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +21 -14
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +1 -2
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/Filters/FiltersForm.js +7 -3
- package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
- package/build/dist/UI/Components/Filters/NumberFilter.js +0 -1
- package/build/dist/UI/Components/Filters/NumberFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/TextFilter.js +5 -4
- package/build/dist/UI/Components/Filters/TextFilter.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +5 -3
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +383 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +109 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js.map +1 -0
- package/build/dist/Utils/Metrics/MetricSeriesFingerprint.js +81 -0
- package/build/dist/Utils/Metrics/MetricSeriesFingerprint.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +287 -19
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AreaChart } from "../ChartLibrary/AreaChart/AreaChart";
|
|
2
|
+
import { AvailableChartColorsKeys } from "../ChartLibrary/Utils/ChartColors";
|
|
2
3
|
import React, {
|
|
3
4
|
FunctionComponent,
|
|
4
5
|
ReactElement,
|
|
@@ -17,6 +18,19 @@ import ExemplarPoint from "../Types/ExemplarPoint";
|
|
|
17
18
|
import XAxisUtil from "../Utils/XAxis";
|
|
18
19
|
import NoDataMessage from "../ChartGroup/NoDataMessage";
|
|
19
20
|
|
|
21
|
+
export const AreaChartPalette: Array<AvailableChartColorsKeys> = [
|
|
22
|
+
"blue",
|
|
23
|
+
"emerald",
|
|
24
|
+
"violet",
|
|
25
|
+
"amber",
|
|
26
|
+
"cyan",
|
|
27
|
+
"pink",
|
|
28
|
+
"lime",
|
|
29
|
+
"fuchsia",
|
|
30
|
+
"indigo",
|
|
31
|
+
"rose",
|
|
32
|
+
];
|
|
33
|
+
|
|
20
34
|
export interface ComponentProps {
|
|
21
35
|
data: Array<SeriesPoint>;
|
|
22
36
|
xAxis: XAxis;
|
|
@@ -27,6 +41,7 @@ export interface ComponentProps {
|
|
|
27
41
|
referenceLines?: Array<ChartReferenceLineProps> | undefined;
|
|
28
42
|
exemplarPoints?: Array<ExemplarPoint> | undefined;
|
|
29
43
|
onExemplarClick?: ((exemplar: ExemplarPoint) => void) | undefined;
|
|
44
|
+
showLegend?: boolean | undefined;
|
|
30
45
|
}
|
|
31
46
|
|
|
32
47
|
export interface AreaInternalProps extends ComponentProps {
|
|
@@ -93,20 +108,10 @@ const AreaChartElement: FunctionComponent<AreaInternalProps> = (
|
|
|
93
108
|
tickGap={1}
|
|
94
109
|
index={"Time"}
|
|
95
110
|
categories={categories}
|
|
96
|
-
colors={
|
|
97
|
-
"blue",
|
|
98
|
-
"emerald",
|
|
99
|
-
"violet",
|
|
100
|
-
"amber",
|
|
101
|
-
"cyan",
|
|
102
|
-
"pink",
|
|
103
|
-
"lime",
|
|
104
|
-
"fuchsia",
|
|
105
|
-
"indigo",
|
|
106
|
-
"rose",
|
|
107
|
-
]}
|
|
111
|
+
colors={AreaChartPalette}
|
|
108
112
|
valueFormatter={props.yAxis.options.formatter || undefined}
|
|
109
113
|
showTooltip={true}
|
|
114
|
+
showLegend={props.showLegend !== false}
|
|
110
115
|
connectNulls={true}
|
|
111
116
|
curve={props.curve || ChartCurve.MONOTONE}
|
|
112
117
|
syncid={props.sync ? props.syncid : undefined}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BarChart } from "../ChartLibrary/BarChart/BarChart";
|
|
2
|
+
import { AvailableChartColorsKeys } from "../ChartLibrary/Utils/ChartColors";
|
|
2
3
|
import React, { FunctionComponent, ReactElement, useEffect } from "react";
|
|
3
4
|
import SeriesPoint from "../Types/SeriesPoints";
|
|
4
5
|
import { XAxis } from "../Types/XAxis/XAxis";
|
|
@@ -8,6 +9,18 @@ import DataPointUtil from "../Utils/DataPoint";
|
|
|
8
9
|
import ChartReferenceLineProps from "../Types/ReferenceLineProps";
|
|
9
10
|
import NoDataMessage from "../ChartGroup/NoDataMessage";
|
|
10
11
|
|
|
12
|
+
export const BarChartPalette: Array<AvailableChartColorsKeys> = [
|
|
13
|
+
"indigo",
|
|
14
|
+
"rose",
|
|
15
|
+
"emerald",
|
|
16
|
+
"amber",
|
|
17
|
+
"cyan",
|
|
18
|
+
"gray",
|
|
19
|
+
"pink",
|
|
20
|
+
"lime",
|
|
21
|
+
"fuchsia",
|
|
22
|
+
];
|
|
23
|
+
|
|
11
24
|
export interface ComponentProps {
|
|
12
25
|
data: Array<SeriesPoint>;
|
|
13
26
|
xAxis: XAxis;
|
|
@@ -15,6 +28,7 @@ export interface ComponentProps {
|
|
|
15
28
|
sync: boolean;
|
|
16
29
|
heightInPx?: number | undefined;
|
|
17
30
|
referenceLines?: Array<ChartReferenceLineProps> | undefined;
|
|
31
|
+
showLegend?: boolean | undefined;
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
export interface BarInternalProps extends ComponentProps {
|
|
@@ -61,19 +75,10 @@ const BarChartElement: FunctionComponent<BarInternalProps> = (
|
|
|
61
75
|
tickGap={1}
|
|
62
76
|
index={"Time"}
|
|
63
77
|
categories={categories}
|
|
64
|
-
colors={
|
|
65
|
-
"indigo",
|
|
66
|
-
"rose",
|
|
67
|
-
"emerald",
|
|
68
|
-
"amber",
|
|
69
|
-
"cyan",
|
|
70
|
-
"gray",
|
|
71
|
-
"pink",
|
|
72
|
-
"lime",
|
|
73
|
-
"fuchsia",
|
|
74
|
-
]}
|
|
78
|
+
colors={BarChartPalette}
|
|
75
79
|
valueFormatter={props.yAxis.options.formatter || undefined}
|
|
76
80
|
showTooltip={true}
|
|
81
|
+
showLegend={props.showLegend !== false}
|
|
77
82
|
yAxisWidth={60}
|
|
78
83
|
syncid={props.sync ? props.syncid : undefined}
|
|
79
84
|
onValueChange={() => {}}
|
|
@@ -36,6 +36,13 @@ export interface Chart {
|
|
|
36
36
|
metricInfo?: ChartMetricInfo | undefined;
|
|
37
37
|
exemplarPoints?: Array<ExemplarPoint> | undefined;
|
|
38
38
|
onExemplarClick?: ((exemplar: ExemplarPoint) => void) | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Optional control panel rendered between the chart title and the
|
|
41
|
+
* chart body. Used by per-series-grouped metric charts to surface a
|
|
42
|
+
* search box, per-series toggles, and a "show all" escape hatch so
|
|
43
|
+
* the chart stays usable at thousands of unique label combinations.
|
|
44
|
+
*/
|
|
45
|
+
seriesControls?: ReactElement | undefined;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
export interface ComponentProps {
|
|
@@ -58,6 +65,13 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
58
65
|
chart: Chart,
|
|
59
66
|
index: number,
|
|
60
67
|
): ReactElement => {
|
|
68
|
+
/*
|
|
69
|
+
* When the chart has its own seriesControls panel, that panel doubles
|
|
70
|
+
* as a colored, interactive legend — so we suppress the built-in
|
|
71
|
+
* Recharts legend to avoid showing two legends for the same series.
|
|
72
|
+
*/
|
|
73
|
+
const showLegend: boolean = !chart.seriesControls;
|
|
74
|
+
|
|
61
75
|
switch (chart.type) {
|
|
62
76
|
case ChartType.LINE:
|
|
63
77
|
return (
|
|
@@ -68,6 +82,7 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
68
82
|
heightInPx={props.heightInPx}
|
|
69
83
|
exemplarPoints={chart.exemplarPoints}
|
|
70
84
|
onExemplarClick={chart.onExemplarClick}
|
|
85
|
+
showLegend={showLegend}
|
|
71
86
|
/>
|
|
72
87
|
);
|
|
73
88
|
case ChartType.BAR:
|
|
@@ -77,6 +92,7 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
77
92
|
{...(chart.props as BarChartProps)}
|
|
78
93
|
syncid={syncId}
|
|
79
94
|
heightInPx={props.heightInPx}
|
|
95
|
+
showLegend={showLegend}
|
|
80
96
|
/>
|
|
81
97
|
);
|
|
82
98
|
case ChartType.AREA:
|
|
@@ -88,6 +104,7 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
88
104
|
heightInPx={props.heightInPx}
|
|
89
105
|
exemplarPoints={chart.exemplarPoints}
|
|
90
106
|
onExemplarClick={chart.onExemplarClick}
|
|
107
|
+
showLegend={showLegend}
|
|
91
108
|
/>
|
|
92
109
|
);
|
|
93
110
|
default:
|
|
@@ -239,6 +256,9 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
239
256
|
</p>
|
|
240
257
|
)}
|
|
241
258
|
</div>
|
|
259
|
+
{chart.seriesControls ? (
|
|
260
|
+
<div className="mb-3">{chart.seriesControls}</div>
|
|
261
|
+
) : null}
|
|
242
262
|
{getChartContent(chart, index)}
|
|
243
263
|
</div>
|
|
244
264
|
</div>
|
|
@@ -283,6 +303,9 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
|
|
|
283
303
|
{chart.description}
|
|
284
304
|
</p>
|
|
285
305
|
)}
|
|
306
|
+
{chart.seriesControls ? (
|
|
307
|
+
<div className="mt-3">{chart.seriesControls}</div>
|
|
308
|
+
) : null}
|
|
286
309
|
{getChartContent(chart, index)}
|
|
287
310
|
</div>
|
|
288
311
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LineChart } from "../ChartLibrary/LineChart/LineChart";
|
|
2
|
+
import { AvailableChartColorsKeys } from "../ChartLibrary/Utils/ChartColors";
|
|
2
3
|
import React, {
|
|
3
4
|
FunctionComponent,
|
|
4
5
|
ReactElement,
|
|
@@ -17,6 +18,18 @@ import ExemplarPoint from "../Types/ExemplarPoint";
|
|
|
17
18
|
import XAxisUtil from "../Utils/XAxis";
|
|
18
19
|
import NoDataMessage from "../ChartGroup/NoDataMessage";
|
|
19
20
|
|
|
21
|
+
export const LineChartPalette: Array<AvailableChartColorsKeys> = [
|
|
22
|
+
"indigo",
|
|
23
|
+
"rose",
|
|
24
|
+
"emerald",
|
|
25
|
+
"amber",
|
|
26
|
+
"cyan",
|
|
27
|
+
"gray",
|
|
28
|
+
"pink",
|
|
29
|
+
"lime",
|
|
30
|
+
"fuchsia",
|
|
31
|
+
];
|
|
32
|
+
|
|
20
33
|
export interface ComponentProps {
|
|
21
34
|
data: Array<SeriesPoint>;
|
|
22
35
|
xAxis: XAxis;
|
|
@@ -27,6 +40,7 @@ export interface ComponentProps {
|
|
|
27
40
|
referenceLines?: Array<ChartReferenceLineProps> | undefined;
|
|
28
41
|
exemplarPoints?: Array<ExemplarPoint> | undefined;
|
|
29
42
|
onExemplarClick?: ((exemplar: ExemplarPoint) => void) | undefined;
|
|
43
|
+
showLegend?: boolean | undefined;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
export interface LineInternalProps extends ComponentProps {
|
|
@@ -93,19 +107,10 @@ const LineChartElement: FunctionComponent<LineInternalProps> = (
|
|
|
93
107
|
tickGap={1}
|
|
94
108
|
index={"Time"}
|
|
95
109
|
categories={categories}
|
|
96
|
-
colors={
|
|
97
|
-
"indigo",
|
|
98
|
-
"rose",
|
|
99
|
-
"emerald",
|
|
100
|
-
"amber",
|
|
101
|
-
"cyan",
|
|
102
|
-
"gray",
|
|
103
|
-
"pink",
|
|
104
|
-
"lime",
|
|
105
|
-
"fuchsia",
|
|
106
|
-
]}
|
|
110
|
+
colors={LineChartPalette}
|
|
107
111
|
valueFormatter={props.yAxis.options.formatter || undefined}
|
|
108
112
|
showTooltip={true}
|
|
113
|
+
showLegend={props.showLegend !== false}
|
|
109
114
|
connectNulls={true}
|
|
110
115
|
curve={props.curve}
|
|
111
116
|
syncid={props.sync ? props.syncid : undefined}
|
|
@@ -39,7 +39,9 @@ type DateState = {
|
|
|
39
39
|
end: Date | null;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
type ToDateFunction = (value: unknown) => Date | null;
|
|
43
|
+
|
|
44
|
+
const toDate: ToDateFunction = (value: unknown): Date | null => {
|
|
43
45
|
if (!value) {
|
|
44
46
|
return null;
|
|
45
47
|
}
|
|
@@ -53,7 +55,9 @@ const toDate = (value: unknown): Date | null => {
|
|
|
53
55
|
}
|
|
54
56
|
};
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
type DetectStateFunction = (rawValue: unknown) => DateState;
|
|
59
|
+
|
|
60
|
+
const detectState: DetectStateFunction = (rawValue: unknown): DateState => {
|
|
57
61
|
if (rawValue instanceof InBetween) {
|
|
58
62
|
const start: Date | null = toDate(rawValue.startValue as unknown);
|
|
59
63
|
const end: Date | null = toDate(rawValue.endValue as unknown);
|
|
@@ -102,7 +106,12 @@ const detectState = (rawValue: unknown): DateState => {
|
|
|
102
106
|
return { operator: FilterOperator.Is, start: null, end: null };
|
|
103
107
|
};
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
type BuildValueFunction = (state: DateState, isDateTime: boolean) => unknown;
|
|
110
|
+
|
|
111
|
+
const buildValue: BuildValueFunction = (
|
|
112
|
+
state: DateState,
|
|
113
|
+
isDateTime: boolean,
|
|
114
|
+
): unknown => {
|
|
106
115
|
switch (state.operator) {
|
|
107
116
|
case FilterOperator.Is: {
|
|
108
117
|
if (!state.start) {
|
|
@@ -128,9 +137,7 @@ const buildValue = (state: DateState, isDateTime: boolean): unknown => {
|
|
|
128
137
|
(isDateTime
|
|
129
138
|
? state.start
|
|
130
139
|
: OneUptimeDate.getStartOfDay(state.start)) as any,
|
|
131
|
-
(isDateTime
|
|
132
|
-
? state.end
|
|
133
|
-
: OneUptimeDate.getEndOfDay(state.end)) as any,
|
|
140
|
+
(isDateTime ? state.end : OneUptimeDate.getEndOfDay(state.end)) as any,
|
|
134
141
|
);
|
|
135
142
|
}
|
|
136
143
|
case FilterOperator.IsEmpty:
|
|
@@ -163,7 +170,6 @@ const DateFilter: DateFilterFunction = <T extends GenericObject>(
|
|
|
163
170
|
if (raw !== undefined && raw !== null) {
|
|
164
171
|
setLocalOperator(detected.operator);
|
|
165
172
|
}
|
|
166
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
167
173
|
}, [props.filterData[filter.key]]);
|
|
168
174
|
|
|
169
175
|
const state: DateState = { ...detected, operator: localOperator };
|
|
@@ -204,7 +210,9 @@ const DateFilter: DateFilterFunction = <T extends GenericObject>(
|
|
|
204
210
|
}}
|
|
205
211
|
/>
|
|
206
212
|
{!valuelessOperator && (
|
|
207
|
-
<div
|
|
213
|
+
<div
|
|
214
|
+
className={isBetween ? "flex-1 flex gap-2 min-w-0" : "flex-1 min-w-0"}
|
|
215
|
+
>
|
|
208
216
|
<div className="flex-1 min-w-0">
|
|
209
217
|
<Input
|
|
210
218
|
key={`${filter.key as string}-start-${state.operator}`}
|
|
@@ -42,7 +42,11 @@ type EntityState = {
|
|
|
42
42
|
values: Array<string>;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
type DetectStateFunction = (rawValue: unknown) => EntityState;
|
|
46
|
+
|
|
47
|
+
const detectArrayState: DetectStateFunction = (
|
|
48
|
+
rawValue: unknown,
|
|
49
|
+
): EntityState => {
|
|
46
50
|
if (rawValue instanceof IncludesAll) {
|
|
47
51
|
return {
|
|
48
52
|
operator: FilterOperator.HasAllOf,
|
|
@@ -84,7 +88,9 @@ const detectArrayState = (rawValue: unknown): EntityState => {
|
|
|
84
88
|
return { operator: FilterOperator.HasAnyOf, values: [] };
|
|
85
89
|
};
|
|
86
90
|
|
|
87
|
-
const detectSingleState = (
|
|
91
|
+
const detectSingleState: DetectStateFunction = (
|
|
92
|
+
rawValue: unknown,
|
|
93
|
+
): EntityState => {
|
|
88
94
|
if (rawValue instanceof IsNull) {
|
|
89
95
|
return { operator: FilterOperator.IsEmpty, values: [] };
|
|
90
96
|
}
|
|
@@ -97,12 +103,18 @@ const detectSingleState = (rawValue: unknown): EntityState => {
|
|
|
97
103
|
return { operator: FilterOperator.Is, values: [] };
|
|
98
104
|
};
|
|
99
105
|
|
|
100
|
-
|
|
106
|
+
type BuildValueFunction = (state: EntityState) => unknown;
|
|
107
|
+
|
|
108
|
+
const buildArrayValue: BuildValueFunction = (state: EntityState): unknown => {
|
|
101
109
|
switch (state.operator) {
|
|
102
110
|
case FilterOperator.HasAllOf:
|
|
103
|
-
return state.values.length > 0
|
|
111
|
+
return state.values.length > 0
|
|
112
|
+
? new IncludesAll(state.values)
|
|
113
|
+
: undefined;
|
|
104
114
|
case FilterOperator.HasNoneOf:
|
|
105
|
-
return state.values.length > 0
|
|
115
|
+
return state.values.length > 0
|
|
116
|
+
? new IncludesNone(state.values)
|
|
117
|
+
: undefined;
|
|
106
118
|
case FilterOperator.HasAnyOf:
|
|
107
119
|
return state.values.length > 0 ? state.values : undefined;
|
|
108
120
|
case FilterOperator.IsEmpty:
|
|
@@ -114,15 +126,13 @@ const buildArrayValue = (state: EntityState): unknown => {
|
|
|
114
126
|
}
|
|
115
127
|
};
|
|
116
128
|
|
|
117
|
-
const buildSingleValue = (state: EntityState): unknown => {
|
|
129
|
+
const buildSingleValue: BuildValueFunction = (state: EntityState): unknown => {
|
|
118
130
|
switch (state.operator) {
|
|
119
131
|
case FilterOperator.Is:
|
|
120
132
|
return state.values[0] || undefined;
|
|
121
133
|
case FilterOperator.IsNot:
|
|
122
134
|
// Use IncludesNone with single-item array to represent "is not".
|
|
123
|
-
return state.values[0]
|
|
124
|
-
? new IncludesNone([state.values[0]])
|
|
125
|
-
: undefined;
|
|
135
|
+
return state.values[0] ? new IncludesNone([state.values[0]]) : undefined;
|
|
126
136
|
case FilterOperator.IsEmpty:
|
|
127
137
|
return new IsNull();
|
|
128
138
|
case FilterOperator.IsNotEmpty:
|
|
@@ -153,24 +163,29 @@ const EntityFilter: EntityFilterFunction = <T extends GenericObject>(
|
|
|
153
163
|
? detectArrayState(props.filterData[filter.key])
|
|
154
164
|
: detectSingleState(props.filterData[filter.key]);
|
|
155
165
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
166
|
+
/*
|
|
167
|
+
* Hold the operator locally so the user's choice persists even when no
|
|
168
|
+
* values are selected yet (otherwise `buildArrayValue` would return
|
|
169
|
+
* undefined, filterData wouldn't carry the operator, and the next render
|
|
170
|
+
* would reset back to the default).
|
|
171
|
+
*/
|
|
160
172
|
const [localOperator, setLocalOperator] = useState<FilterOperator>(
|
|
161
173
|
detectedState.operator,
|
|
162
174
|
);
|
|
163
175
|
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
/*
|
|
177
|
+
* When the external filter data changes and can unambiguously tell us
|
|
178
|
+
* which operator it represents, sync local state.
|
|
179
|
+
*/
|
|
166
180
|
useEffect(() => {
|
|
167
181
|
const raw: unknown = props.filterData[filter.key];
|
|
168
182
|
if (raw !== undefined && raw !== null) {
|
|
169
183
|
setLocalOperator(detectedState.operator);
|
|
170
184
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
/*
|
|
186
|
+
* Intentionally only re-run when the underlying filter data reference
|
|
187
|
+
* changes — not on every detectedState re-computation.
|
|
188
|
+
*/
|
|
174
189
|
}, [props.filterData[filter.key]]);
|
|
175
190
|
|
|
176
191
|
const operator: FilterOperator = localOperator;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Icon from "../Icon/Icon";
|
|
1
|
+
import Icon, { SizeProp } from "../Icon/Icon";
|
|
2
2
|
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
3
3
|
import IncludesAll from "../../../Types/BaseDatabase/IncludesAll";
|
|
4
4
|
import IncludesNone from "../../../Types/BaseDatabase/IncludesNone";
|
|
@@ -16,7 +16,6 @@ import NotNull from "../../../Types/BaseDatabase/NotNull";
|
|
|
16
16
|
import Button, { ButtonStyleType } from "../Button/Button";
|
|
17
17
|
import { DropdownOption } from "../Dropdown/Dropdown";
|
|
18
18
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
19
|
-
import { SizeProp } from "../Icon/Icon";
|
|
20
19
|
import Modal, { ModalWidth } from "../Modal/Modal";
|
|
21
20
|
import FieldType from "../Types/FieldType";
|
|
22
21
|
import FilterViewerItem from "./FilterViewerItem";
|
|
@@ -213,7 +212,8 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
213
212
|
if (value instanceof NotNull) {
|
|
214
213
|
return (
|
|
215
214
|
<span>
|
|
216
|
-
<span className="font-medium">{data.filter.title}</span> is not
|
|
215
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
216
|
+
empty
|
|
217
217
|
</span>
|
|
218
218
|
);
|
|
219
219
|
}
|
|
@@ -302,7 +302,8 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
302
302
|
if (value instanceof NotNull) {
|
|
303
303
|
return (
|
|
304
304
|
<span>
|
|
305
|
-
<span className="font-medium">{data.filter.title}</span> is not
|
|
305
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
306
|
+
empty
|
|
306
307
|
</span>
|
|
307
308
|
);
|
|
308
309
|
}
|
|
@@ -369,7 +370,8 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
369
370
|
if (rawValue instanceof NotNull) {
|
|
370
371
|
return (
|
|
371
372
|
<span>
|
|
372
|
-
<span className="font-medium">{data.filter.title}</span> is not
|
|
373
|
+
<span className="font-medium">{data.filter.title}</span> is not
|
|
374
|
+
empty
|
|
373
375
|
</span>
|
|
374
376
|
);
|
|
375
377
|
}
|
|
@@ -28,6 +28,22 @@ export interface ComponentProps<T extends GenericObject> {
|
|
|
28
28
|
| undefined
|
|
29
29
|
| ((showAdvancedFilters: boolean) => void);
|
|
30
30
|
showAdvancedFiltersByDefault?: boolean | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Suppress the built-in "Show/Hide Advanced Filters" toggle
|
|
33
|
+
* button. Useful when the parent renders its own toggle further
|
|
34
|
+
* down the page (e.g. below other non-filter controls) and needs
|
|
35
|
+
* full layout control. Parent must drive visibility through
|
|
36
|
+
* `showAdvancedFilters` instead.
|
|
37
|
+
*/
|
|
38
|
+
hideAdvancedFilterToggle?: boolean | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Controlled replacement for the internal toggle state. When
|
|
41
|
+
* provided, the form renders advanced filters based on this flag
|
|
42
|
+
* and calls `onAdvancedFiltersToggle` for changes but does not
|
|
43
|
+
* manage its own state. Pair with `hideAdvancedFilterToggle` when
|
|
44
|
+
* the parent owns the UI toggle.
|
|
45
|
+
*/
|
|
46
|
+
showAdvancedFilters?: boolean | undefined;
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
type FiltersFormFunction = <T extends GenericObject>(
|
|
@@ -51,16 +67,24 @@ const FiltersForm: FiltersFormFunction = <T extends GenericObject>(
|
|
|
51
67
|
}
|
|
52
68
|
};
|
|
53
69
|
|
|
54
|
-
const
|
|
70
|
+
const hasAdvancedFilter: boolean = Boolean(
|
|
55
71
|
props.filters.find((filter: Filter<T>) => {
|
|
56
72
|
return filter.isAdvancedFilter;
|
|
57
73
|
}),
|
|
58
74
|
);
|
|
59
75
|
|
|
60
|
-
const
|
|
76
|
+
const showAdvancedFilterButton: boolean =
|
|
77
|
+
hasAdvancedFilter && !props.hideAdvancedFilterToggle;
|
|
78
|
+
|
|
79
|
+
const [internalShowMoreFilters, setShowMoreFilters] = React.useState<boolean>(
|
|
61
80
|
props.showAdvancedFiltersByDefault ?? false,
|
|
62
81
|
);
|
|
63
82
|
|
|
83
|
+
const showMoreFilters: boolean =
|
|
84
|
+
props.showAdvancedFilters !== undefined
|
|
85
|
+
? props.showAdvancedFilters
|
|
86
|
+
: internalShowMoreFilters;
|
|
87
|
+
|
|
64
88
|
type ClearFilterFunction = (key: keyof T) => void;
|
|
65
89
|
|
|
66
90
|
const clearFilter: ClearFilterFunction = (key: keyof T): void => {
|
|
@@ -72,9 +96,7 @@ const FiltersForm: FiltersFormFunction = <T extends GenericObject>(
|
|
|
72
96
|
const visibleFilters: Array<Filter<T>> = props.filters.filter(
|
|
73
97
|
(filter: Filter<T>) => {
|
|
74
98
|
if (filter.isAdvancedFilter) {
|
|
75
|
-
return
|
|
76
|
-
showMoreFilters && !props.isFilterLoading && !props.filterError
|
|
77
|
-
);
|
|
99
|
+
return showMoreFilters && !props.isFilterLoading && !props.filterError;
|
|
78
100
|
}
|
|
79
101
|
return true;
|
|
80
102
|
},
|
|
@@ -168,7 +168,6 @@ const NumberFilter: NumberFilterFunction = <T extends GenericObject>(
|
|
|
168
168
|
if (raw !== undefined && raw !== null) {
|
|
169
169
|
setLocalOperator(detected.operator);
|
|
170
170
|
}
|
|
171
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
172
171
|
}, [props.filterData[filter.key]]);
|
|
173
172
|
|
|
174
173
|
const state: NumberState = { ...detected, operator: localOperator };
|
|
@@ -209,7 +208,9 @@ const NumberFilter: NumberFilterFunction = <T extends GenericObject>(
|
|
|
209
208
|
}}
|
|
210
209
|
/>
|
|
211
210
|
{!valuelessOperator && (
|
|
212
|
-
<div
|
|
211
|
+
<div
|
|
212
|
+
className={isBetween ? "flex-1 flex gap-2 min-w-0" : "flex-1 min-w-0"}
|
|
213
|
+
>
|
|
213
214
|
<div className="flex-1 min-w-0">
|
|
214
215
|
<input
|
|
215
216
|
type="number"
|
|
@@ -133,9 +133,11 @@ const TextFilter: TextFilterFunction = <T extends GenericObject>(
|
|
|
133
133
|
const detected: { operator: FilterOperator; value: string } =
|
|
134
134
|
detectCurrentState(props.filterData[filter.key]);
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
/*
|
|
137
|
+
* Keep the operator locally so the user's choice persists even when no
|
|
138
|
+
* value has been typed yet (otherwise buildQueryValue returns undefined,
|
|
139
|
+
* the filter is deleted, and the operator resets on re-render).
|
|
140
|
+
*/
|
|
139
141
|
const [localOperator, setLocalOperator] = useState<FilterOperator>(
|
|
140
142
|
detected.operator,
|
|
141
143
|
);
|
|
@@ -145,7 +147,6 @@ const TextFilter: TextFilterFunction = <T extends GenericObject>(
|
|
|
145
147
|
if (raw !== undefined && raw !== null) {
|
|
146
148
|
setLocalOperator(detected.operator);
|
|
147
149
|
}
|
|
148
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
149
150
|
}, [props.filterData[filter.key]]);
|
|
150
151
|
|
|
151
152
|
const operator: FilterOperator = localOperator;
|
|
@@ -1525,9 +1525,11 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
|
|
|
1525
1525
|
);
|
|
1526
1526
|
}
|
|
1527
1527
|
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1528
|
+
/*
|
|
1529
|
+
* Pass any QueryOperator instance (IncludesAll, IncludesNone, StartsWith,
|
|
1530
|
+
* EndsWith, NotContains, EqualTo, NotEqual, GreaterThan, LessThan,
|
|
1531
|
+
* InBetween, IsNull, NotNull, ...) through to the query as-is.
|
|
1532
|
+
*/
|
|
1531
1533
|
if (filterData[key] instanceof QueryOperator) {
|
|
1532
1534
|
newQuery[key as keyof TBaseModel] = filterData[key];
|
|
1533
1535
|
}
|