andoncloud-prometheus-widget 1.3.17 → 1.3.19

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/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
+ import { t as thumbnail_default } from "./thumbnail-B_DBfYD0.js";
1
2
  import { registerTranslations } from "andoncloud-sdk";
2
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
4
  import { generateTimeRange, getCurrentShift, getRecentShift, normalizeShifts, useGqlClients } from "andoncloud-dashboard-toolkit";
4
5
  import { BaseWidget } from "andoncloud-widget-base";
5
6
  import { useTranslation } from "react-i18next";
6
7
  import { Clear } from "@mui/icons-material";
7
8
  import { TabContext, TabList, TabPanel } from "@mui/lab";
8
- import { Box, Button, FormControl, FormHelperText, IconButton, InputLabel, MenuItem, Select, Stack, Tab, TextField } from "@mui/material";
9
+ import { Alert, Box, Button, Divider, FormControl, FormHelperText, IconButton, InputLabel, MenuItem, Select, Stack, Tab, TextField, Typography } from "@mui/material";
9
10
  import { getIn } from "formik";
10
- import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import "chartjs-adapter-dayjs-4";
11
13
  import { Line } from "react-chartjs-2";
12
14
  import { CategoryScale, Chart, Filler, Legend, LineElement, LinearScale, PointElement, TimeScale, Tooltip } from "chart.js";
13
- import "chartjs-adapter-dayjs-4";
14
- import { PrometheusDriver } from "prometheus-query";
15
15
  import dayjs from "dayjs";
16
- import pick from "lodash.pick";
16
+ import { PrometheusDriver } from "prometheus-query";
17
17
  import Color from "color";
18
18
  import { satisfies } from "compare-versions";
19
19
  import * as yup from "yup";
@@ -25,51 +25,73 @@ const resources = {
25
25
  "addAnotherDisplayedQueryParameter": "Add another displayed query parameter",
26
26
  "addAnotherQuery": "Add another query",
27
27
  "advanced": "Advanced",
28
+ "credentialsHelper": "Credentials are optional. Fill in only if the instance requires authentication.",
28
29
  "currentShift": "Current shift",
29
30
  "customTitle": "Custom title",
30
31
  "displayedQueryParameter": "Displayed query parameter",
32
+ "displayName": "PromQL chart",
31
33
  "endpointUrl": "Endpoint URL",
34
+ "errorAuth": "Could not authenticate to Prometheus. Check the username and password in widget settings.",
35
+ "errorForbidden": "Authenticated, but the Prometheus user has no permission to read these metrics.",
36
+ "errorUnreachable": "Could not reach Prometheus at the configured URL.",
37
+ "insecureWarning": "Credentials will be sent over an unencrypted connection (HTTP). Use HTTPS to protect them.",
32
38
  "name": "Name",
39
+ "password": "Password",
33
40
  "period": "Period",
34
41
  "previousShift": "Previous shift",
35
42
  "query": "Query",
43
+ "removeParam": "Remove parameter",
44
+ "removeQuery": "Remove query",
45
+ "sectionAuthorization": "Authorization",
46
+ "sectionData": "Data",
36
47
  "settings": "Settings",
37
48
  "thisFieldIsRequired": "This field is required",
38
- "xAxisUnit": "X axis unit",
39
- "displayName": "PromQL chart",
40
- "titleQueries_one": "{{count}} query",
41
- "titleQueries_other": "{{count}} queries",
42
49
  "titleCurrentShift": "current shift",
43
50
  "titlePreviousShift": "previous shift",
51
+ "titleQueries_one": "{{count}} query",
52
+ "titleQueries_other": "{{count}} queries",
53
+ "username": "Username",
54
+ "xAxisUnit": "X axis unit",
44
55
  "yAxisUnit": "Y axis unit"
45
56
  } } },
46
57
  pl: { translation: { prometheusWidget: {
47
58
  "addAnotherDisplayedQueryParameter": "Dodaj kolejny wyświetlany parametr zapytania",
48
59
  "addAnotherQuery": "Dodaj kolejne zapytanie",
49
60
  "advanced": "Zaawansowane",
61
+ "credentialsHelper": "Dane autoryzacyjne są opcjonalne. Wypełnij tylko jeśli instancja wymaga uwierzytelniania.",
50
62
  "currentShift": "Obecna zmiana",
51
63
  "customTitle": "Własny tytuł",
52
64
  "displayedQueryParameter": "Wyświetlany parametr zapytania",
65
+ "displayName": "Wykres PromQL",
53
66
  "endpointUrl": "Adres URL",
67
+ "errorAuth": "Nie można uwierzytelnić się w Prometheusie. Sprawdź nazwę użytkownika i hasło w ustawieniach widgetu.",
68
+ "errorForbidden": "Uwierzytelnienie powiodło się, ale użytkownik Prometheusa nie ma uprawnień do tych metryk.",
69
+ "errorUnreachable": "Nie można połączyć się z Prometheusem pod skonfigurowanym adresem.",
70
+ "insecureWarning": "Dane logowania zostaną wysłane nieszyfrowanym połączeniem (HTTP). Użyj HTTPS, aby je chronić.",
54
71
  "name": "Nazwa",
72
+ "password": "Hasło",
55
73
  "period": "Okres",
56
74
  "previousShift": "Poprzednia zmiana",
57
75
  "query": "Zapytanie",
76
+ "removeParam": "Usuń parametr",
77
+ "removeQuery": "Usuń zapytanie",
78
+ "sectionAuthorization": "Autoryzacja",
79
+ "sectionData": "Dane",
58
80
  "settings": "Ustawienia",
59
81
  "thisFieldIsRequired": "To pole jest wymagane",
60
- "xAxisUnit": "Jednostka osi X",
61
- "displayName": "Wykres PromQL",
62
- "titleQueries_one": "{{count}} zapytanie",
63
- "titleQueries_few": "{{count}} zapytania",
64
- "titleQueries_many": "{{count}} zapytań",
65
82
  "titleCurrentShift": "obecna zmiana",
66
83
  "titlePreviousShift": "poprzednia zmiana",
84
+ "titleQueries_few": "{{count}} zapytania",
85
+ "titleQueries_many": "{{count}} zapytań",
86
+ "titleQueries_one": "{{count}} zapytanie",
87
+ "username": "Nazwa użytkownika",
88
+ "xAxisUnit": "Jednostka osi X",
67
89
  "yAxisUnit": "Jednostka osi Y"
68
90
  } } }
69
91
  };
70
92
  //#endregion
71
93
  //#region src/version.ts
72
- const LIBRARY_VERSION = "1.3.17";
94
+ const LIBRARY_VERSION = "1.3.19";
73
95
  //#endregion
74
96
  //#region src/types.ts
75
97
  let QueriesPeriod = /* @__PURE__ */ function(QueriesPeriod) {
@@ -78,14 +100,87 @@ let QueriesPeriod = /* @__PURE__ */ function(QueriesPeriod) {
78
100
  return QueriesPeriod;
79
101
  }({});
80
102
  //#endregion
103
+ //#region src/components/SettingsFormContent/utils.ts
104
+ const isInsecureEndpoint = (url) => /^http:\/\//i.test(url);
105
+ //#endregion
106
+ //#region src/components/SettingsFormContent/styles.ts
107
+ const styles = {
108
+ sectionDivider: {
109
+ marginTop: 3,
110
+ marginBottom: 1,
111
+ color: (theme) => theme.palette.text.primary,
112
+ fontWeight: 600,
113
+ letterSpacing: "0.08em",
114
+ textTransform: "uppercase",
115
+ fontSize: "0.75rem",
116
+ "&::before, &::after": { borderColor: "rgba(255, 255, 255, 0.15)" }
117
+ },
118
+ formControl: { marginTop: 2 },
119
+ addButton: { marginTop: 2 },
120
+ credentialsHelper: {
121
+ marginTop: 1,
122
+ color: (theme) => theme.palette.text.primary
123
+ }
124
+ };
125
+ //#endregion
126
+ //#region src/components/SettingsFormContent/CredentialsFields/index.tsx
127
+ const CredentialsFields = ({ formProps }) => {
128
+ const [passwordInput, setPasswordInput] = useState("");
129
+ const { t } = useTranslation();
130
+ const handlePasswordChange = (event) => {
131
+ setPasswordInput(event.target.value);
132
+ formProps.setFieldValue("password", event.target.value);
133
+ };
134
+ const showInsecureWarning = isInsecureEndpoint(formProps.values.endpointUrl);
135
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
136
+ /* @__PURE__ */ jsx(FormHelperText, {
137
+ sx: styles.credentialsHelper,
138
+ "data-testid": "prometheus.settings.credentials-helper",
139
+ children: t("prometheusWidget.credentialsHelper")
140
+ }),
141
+ /* @__PURE__ */ jsx(FormControl, {
142
+ sx: styles.formControl,
143
+ fullWidth: true,
144
+ children: /* @__PURE__ */ jsx(TextField, {
145
+ name: "username",
146
+ label: t("prometheusWidget.username"),
147
+ value: formProps.values.username || "",
148
+ onChange: formProps.handleChange,
149
+ onBlur: formProps.handleBlur,
150
+ "data-testid": "prometheus.settings.username",
151
+ fullWidth: true
152
+ })
153
+ }),
154
+ /* @__PURE__ */ jsx(FormControl, {
155
+ sx: styles.formControl,
156
+ fullWidth: true,
157
+ children: /* @__PURE__ */ jsx(TextField, {
158
+ name: "password",
159
+ type: "password",
160
+ label: t("prometheusWidget.password"),
161
+ value: passwordInput,
162
+ onChange: handlePasswordChange,
163
+ onBlur: formProps.handleBlur,
164
+ "data-testid": "prometheus.settings.password",
165
+ fullWidth: true
166
+ })
167
+ }),
168
+ showInsecureWarning && /* @__PURE__ */ jsx(Alert, {
169
+ severity: "warning",
170
+ sx: styles.formControl,
171
+ "data-testid": "prometheus.settings.insecure-warning",
172
+ children: t("prometheusWidget.insecureWarning")
173
+ })
174
+ ] });
175
+ };
176
+ //#endregion
81
177
  //#region src/components/SettingsFormContent/index.tsx
178
+ const emptyQueryItem = {
179
+ query: "",
180
+ displayName: ""
181
+ };
82
182
  const SettingsFormContent = ({ formProps }) => {
83
183
  const [selectedTab, setSelectedTab] = useState("settings");
84
- const emptyQueryItem = {
85
- query: "",
86
- displayName: ""
87
- };
88
- const formControlStyles = { mt: 2 };
89
184
  const { t } = useTranslation();
90
185
  const setPrometheusQuery = (i, item) => {
91
186
  const queries = [...formProps.values.prometheusQueries || [emptyQueryItem]];
@@ -120,7 +215,7 @@ const SettingsFormContent = ({ formProps }) => {
120
215
  };
121
216
  const mapPeriodToLabel = (period) => {
122
217
  switch (period) {
123
- case QueriesPeriod.PREVIOUS_SHIFT: return t("prometheusWidget.previousShift");
218
+ case "PREVIOUS_SHIFT": return t("prometheusWidget.previousShift");
124
219
  default: return t("prometheusWidget.currentShift");
125
220
  }
126
221
  };
@@ -144,7 +239,7 @@ const SettingsFormContent = ({ formProps }) => {
144
239
  mb: 2,
145
240
  children: [
146
241
  /* @__PURE__ */ jsx(FormControl, {
147
- sx: formControlStyles,
242
+ sx: styles.formControl,
148
243
  fullWidth: true,
149
244
  children: /* @__PURE__ */ jsx(TextField, {
150
245
  name: "endpointUrl",
@@ -158,8 +253,17 @@ const SettingsFormContent = ({ formProps }) => {
158
253
  fullWidth: true
159
254
  })
160
255
  }),
256
+ /* @__PURE__ */ jsx(Divider, {
257
+ sx: styles.sectionDivider,
258
+ children: t("prometheusWidget.sectionAuthorization")
259
+ }),
260
+ /* @__PURE__ */ jsx(CredentialsFields, { formProps }),
261
+ /* @__PURE__ */ jsx(Divider, {
262
+ sx: styles.sectionDivider,
263
+ children: t("prometheusWidget.sectionData")
264
+ }),
161
265
  /* @__PURE__ */ jsxs(FormControl, {
162
- sx: formControlStyles,
266
+ sx: styles.formControl,
163
267
  fullWidth: true,
164
268
  children: [
165
269
  /* @__PURE__ */ jsx(InputLabel, {
@@ -170,16 +274,16 @@ const SettingsFormContent = ({ formProps }) => {
170
274
  variant: "outlined",
171
275
  name: "queriesPeriod",
172
276
  labelId: "queries-period-label",
173
- value: formProps.values.queriesPeriod || QueriesPeriod.CURRENT_SHIFT,
277
+ value: formProps.values.queriesPeriod || "CURRENT_SHIFT",
174
278
  onChange: formProps.handleChange,
175
279
  onBlur: formProps.handleBlur,
176
280
  error: formProps.touched.queriesPeriod && Boolean(formProps.errors.queriesPeriod),
177
281
  "data-testid": "prometheus.settings.period-select",
178
282
  fullWidth: true,
179
- children: Object.keys(QueriesPeriod).map((key) => /* @__PURE__ */ jsx(MenuItem, {
180
- value: QueriesPeriod[key],
181
- children: mapPeriodToLabel(QueriesPeriod[key])
182
- }, key))
283
+ children: Object.values(QueriesPeriod).map((value) => /* @__PURE__ */ jsx(MenuItem, {
284
+ value,
285
+ children: mapPeriodToLabel(value)
286
+ }, value))
183
287
  }),
184
288
  /* @__PURE__ */ jsx(FormHelperText, {
185
289
  error: true,
@@ -188,7 +292,7 @@ const SettingsFormContent = ({ formProps }) => {
188
292
  ]
189
293
  }),
190
294
  (formProps.values.prometheusQueries || [emptyQueryItem]).map(({ query, displayName }, i) => /* @__PURE__ */ jsx(FormControl, {
191
- sx: formControlStyles,
295
+ sx: styles.formControl,
192
296
  fullWidth: true,
193
297
  children: /* @__PURE__ */ jsxs(Stack, {
194
298
  direction: "row",
@@ -220,6 +324,7 @@ const SettingsFormContent = ({ formProps }) => {
220
324
  }),
221
325
  /* @__PURE__ */ jsx(IconButton, {
222
326
  color: "error",
327
+ "aria-label": t("prometheusWidget.removeQuery"),
223
328
  onClick: () => removeQueryField(i),
224
329
  "data-testid": `prometheus.settings.remove-query-${i}`,
225
330
  children: /* @__PURE__ */ jsx(Clear, {})
@@ -230,13 +335,13 @@ const SettingsFormContent = ({ formProps }) => {
230
335
  /* @__PURE__ */ jsx(Button, {
231
336
  color: "secondary",
232
337
  onClick: addQueryField,
233
- sx: { mt: (theme) => theme.spacing(2) },
338
+ sx: styles.addButton,
234
339
  "data-testid": "prometheus.settings.add-query",
235
340
  fullWidth: true,
236
341
  children: t("prometheusWidget.addAnotherQuery")
237
342
  }),
238
343
  (formProps.values.displayedQueryParams || [""]).map((param, i) => /* @__PURE__ */ jsx(FormControl, {
239
- sx: formControlStyles,
344
+ sx: styles.formControl,
240
345
  fullWidth: true,
241
346
  children: /* @__PURE__ */ jsxs(Stack, {
242
347
  direction: "row",
@@ -245,12 +350,13 @@ const SettingsFormContent = ({ formProps }) => {
245
350
  label: t("prometheusWidget.displayedQueryParameter"),
246
351
  value: param,
247
352
  onChange: (e) => setDisplayedQueryParam(i, e.target.value),
248
- error: formProps.touched.displayedQueryParams?.[i] && Boolean(getIn(formProps.errors, `displayedQueryParams.[${i}]`)),
249
- helperText: formProps.touched.displayedQueryParams?.[i] && getIn(formProps.errors, `displayedQueryParams.[${i}]`),
353
+ error: Boolean(Array.isArray(formProps.touched.displayedQueryParams) && formProps.touched.displayedQueryParams[i] && getIn(formProps.errors, `displayedQueryParams.[${i}]`)),
354
+ helperText: Array.isArray(formProps.touched.displayedQueryParams) && formProps.touched.displayedQueryParams[i] ? getIn(formProps.errors, `displayedQueryParams.[${i}]`) : void 0,
250
355
  "data-testid": `prometheus.settings.param-input-${i}`,
251
356
  fullWidth: true
252
357
  }), /* @__PURE__ */ jsx(IconButton, {
253
358
  color: "error",
359
+ "aria-label": t("prometheusWidget.removeParam"),
254
360
  onClick: () => removeDisplayedQueryParam(i),
255
361
  "data-testid": `prometheus.settings.remove-param-${i}`,
256
362
  children: /* @__PURE__ */ jsx(Clear, {})
@@ -260,13 +366,13 @@ const SettingsFormContent = ({ formProps }) => {
260
366
  /* @__PURE__ */ jsx(Button, {
261
367
  color: "secondary",
262
368
  onClick: addDisplayedQueryParam,
263
- sx: { mt: (theme) => theme.spacing(2) },
369
+ sx: styles.addButton,
264
370
  "data-testid": "prometheus.settings.add-param",
265
371
  fullWidth: true,
266
372
  children: t("prometheusWidget.addAnotherDisplayedQueryParameter")
267
373
  }),
268
374
  /* @__PURE__ */ jsx(FormControl, {
269
- sx: formControlStyles,
375
+ sx: styles.formControl,
270
376
  fullWidth: true,
271
377
  children: /* @__PURE__ */ jsx(TextField, {
272
378
  name: "xAxisUnit",
@@ -281,7 +387,7 @@ const SettingsFormContent = ({ formProps }) => {
281
387
  })
282
388
  }),
283
389
  /* @__PURE__ */ jsx(FormControl, {
284
- sx: formControlStyles,
390
+ sx: styles.formControl,
285
391
  fullWidth: true,
286
392
  children: /* @__PURE__ */ jsx(TextField, {
287
393
  name: "yAxisUnit",
@@ -314,13 +420,21 @@ const SettingsFormContent = ({ formProps }) => {
314
420
  };
315
421
  //#endregion
316
422
  //#region src/helpers.ts
423
+ const classifyFetchError = (err) => {
424
+ const e = err;
425
+ const status = e?.httpStatus ?? e?.response?.status;
426
+ if (status === 401) return "auth";
427
+ if (status === 403) return "forbidden";
428
+ return "unreachable";
429
+ };
430
+ const pickKeys = (obj, keys) => Object.fromEntries(keys.filter((k) => k in obj).map((k) => [k, obj[k]]));
317
431
  const getQueriesTimeRange = (period, data) => {
318
432
  const currentDate = dayjs();
319
433
  const normalizedShifts = normalizeShifts(data?.shifts, currentDate);
320
434
  const currentShift = getCurrentShift(currentDate, normalizedShifts);
321
435
  const recentShift = getRecentShift(currentDate, normalizedShifts);
322
436
  switch (period) {
323
- case QueriesPeriod.CURRENT_SHIFT:
437
+ case "CURRENT_SHIFT":
324
438
  if (currentShift) return {
325
439
  startedAt: currentShift.startedAt.toDate(),
326
440
  finishedAt: currentShift.finishedAt.toDate()
@@ -330,7 +444,7 @@ const getQueriesTimeRange = (period, data) => {
330
444
  finishedAt: recentShift.finishedAt.toDate()
331
445
  };
332
446
  return null;
333
- case QueriesPeriod.PREVIOUS_SHIFT:
447
+ case "PREVIOUS_SHIFT":
334
448
  if (recentShift) return {
335
449
  startedAt: recentShift.startedAt.toDate(),
336
450
  finishedAt: recentShift.finishedAt.toDate()
@@ -340,6 +454,21 @@ const getQueriesTimeRange = (period, data) => {
340
454
  }
341
455
  };
342
456
  //#endregion
457
+ //#region src/components/PrometheusChart/constants.ts
458
+ const COLORS = [
459
+ "#36A2EB",
460
+ "#FF6384",
461
+ "#4BC0C0",
462
+ "#FF9F40",
463
+ "#9966FF",
464
+ "#FFCD56",
465
+ "#C9CBCF",
466
+ "#7BC8A4",
467
+ "#E7E9ED",
468
+ "#FF6B6B"
469
+ ];
470
+ const DEFAULT_FONT_COLOR = "rgba(255, 255, 255, 0.75)";
471
+ //#endregion
343
472
  //#region src/components/PrometheusChart/GradientPlugin.ts
344
473
  const createGradient = (ctx, area) => {
345
474
  return ctx.createLinearGradient(0, area.bottom, 0, area.top);
@@ -367,31 +496,49 @@ const GradientPlugin = {
367
496
  //#region src/components/PrometheusChart/index.tsx
368
497
  Chart.register(CategoryScale, LinearScale, TimeScale, PointElement, LineElement, Filler, Legend, Tooltip);
369
498
  Chart.defaults.font.size = 12;
370
- Chart.defaults.color = "rgba(255, 255, 255, 0.75)";
371
- const COLORS = [
372
- "#36A2EB",
373
- "#FF6384",
374
- "#4BC0C0",
375
- "#FF9F40",
376
- "#9966FF",
377
- "#FFCD56",
378
- "#C9CBCF",
379
- "#7BC8A4",
380
- "#E7E9ED",
381
- "#FF6B6B"
382
- ];
499
+ Chart.defaults.color = DEFAULT_FONT_COLOR;
500
+ const errorTranslationKey = {
501
+ auth: "prometheusWidget.errorAuth",
502
+ forbidden: "prometheusWidget.errorForbidden",
503
+ unreachable: "prometheusWidget.errorUnreachable"
504
+ };
505
+ const errorMessageStyles = {
506
+ width: "100%",
507
+ height: "100%",
508
+ display: "flex",
509
+ alignItems: "center",
510
+ justifyContent: "center",
511
+ textAlign: "center",
512
+ padding: 2
513
+ };
383
514
  const PrometheusChart = ({ data, settings }) => {
384
515
  const chart = useRef(null);
516
+ const hiddenSeriesRef = useRef({});
517
+ const fetchGenRef = useRef(0);
385
518
  const [chartData, setChartData] = useState({
386
519
  labels: [],
387
520
  datasets: []
388
521
  });
389
522
  const [queriesTimeRange, setQueriesTimeRange] = useState(null);
390
523
  const [timeLabels, setTimeLabels] = useState([]);
391
- const hiddenSeriesRef = useRef({});
524
+ const [error, setError] = useState(null);
525
+ const driver = useMemo(() => {
526
+ const options = { endpoint: settings.endpointUrl };
527
+ if (settings.username && settings.password) options.auth = {
528
+ username: settings.username,
529
+ password: settings.password
530
+ };
531
+ return new PrometheusDriver(options);
532
+ }, [
533
+ settings.endpointUrl,
534
+ settings.username,
535
+ settings.password
536
+ ]);
537
+ const { t } = useTranslation();
392
538
  const fetchData = useCallback(async (timeRange) => {
393
539
  if (!settings.endpointUrl || !settings.prometheusQueries?.length) return;
394
- const driver = new PrometheusDriver({ endpoint: settings.endpointUrl });
540
+ fetchGenRef.current += 1;
541
+ const gen = fetchGenRef.current;
395
542
  const start = new Date(timeRange.startedAt);
396
543
  const end = timeRange.finishedAt ? new Date(timeRange.finishedAt) : /* @__PURE__ */ new Date();
397
544
  const step = 30;
@@ -399,39 +546,51 @@ const PrometheusChart = ({ data, settings }) => {
399
546
  const ds = chart.current.data.datasets[i];
400
547
  if (ds.label) hiddenSeriesRef.current[ds.label] = !chart.current.isDatasetVisible(i);
401
548
  }
402
- const queries = settings.prometheusQueries.map(({ query }) => query);
403
- const results = await Promise.all(queries.map((query) => driver.rangeQuery(query, start, end, step)));
404
- let seriesIndex = 0;
405
- setChartData({
406
- labels: [],
407
- datasets: results.flatMap((result, queryIndex) => result.result.map((serie) => {
408
- const idx = seriesIndex++;
409
- const queryConfig = settings.prometheusQueries[queryIndex];
410
- const metricLabels = serie.metric.labels || {};
411
- const filteredValues = Object.values(pick(metricLabels, settings.displayedQueryParams)).join(" - ");
412
- let label;
413
- if (queryConfig?.displayName) label = filteredValues ? `${queryConfig.displayName} - ${filteredValues}` : queryConfig.displayName;
414
- else {
415
- const metricName = serie.metric.name || queryConfig?.query || "";
416
- label = filteredValues ? `${metricName} ${JSON.stringify(pick(metricLabels, settings.displayedQueryParams))}` : metricName;
417
- }
418
- return {
419
- label,
420
- data: serie.values.map((v) => ({
421
- x: v.time,
422
- y: v.value
423
- })),
424
- fill: true,
425
- tension: .4,
426
- borderColor: COLORS[idx % COLORS.length],
427
- backgroundColor: COLORS[idx % COLORS.length],
428
- borderWidth: 3,
429
- pointRadius: 0,
430
- hidden: hiddenSeriesRef.current[label] || false
431
- };
432
- }))
433
- });
434
- }, [settings.endpointUrl, settings.prometheusQueries]);
549
+ try {
550
+ const queries = settings.prometheusQueries.map(({ query }) => query);
551
+ const results = await Promise.all(queries.map((query) => driver.rangeQuery(query, start, end, step)));
552
+ if (gen !== fetchGenRef.current) return;
553
+ let seriesIndex = 0;
554
+ setChartData({
555
+ labels: [],
556
+ datasets: results.flatMap((result, queryIndex) => result.result.map((serie) => {
557
+ const idx = seriesIndex++;
558
+ const queryConfig = settings.prometheusQueries[queryIndex];
559
+ const metricLabels = serie.metric.labels || {};
560
+ const filteredValues = Object.values(pickKeys(metricLabels, settings.displayedQueryParams)).join(" - ");
561
+ let label;
562
+ if (queryConfig?.displayName) label = filteredValues ? `${queryConfig.displayName} - ${filteredValues}` : queryConfig.displayName;
563
+ else {
564
+ const metricName = serie.metric.name || queryConfig?.query || "";
565
+ label = filteredValues ? `${metricName} ${JSON.stringify(pickKeys(metricLabels, settings.displayedQueryParams))}` : metricName;
566
+ }
567
+ return {
568
+ label,
569
+ data: serie.values.map((v) => ({
570
+ x: v.time,
571
+ y: v.value
572
+ })),
573
+ fill: true,
574
+ tension: .4,
575
+ borderColor: COLORS[idx % COLORS.length],
576
+ backgroundColor: COLORS[idx % COLORS.length],
577
+ borderWidth: 3,
578
+ pointRadius: 0,
579
+ hidden: hiddenSeriesRef.current[label] || false
580
+ };
581
+ }))
582
+ });
583
+ setError(null);
584
+ } catch (err) {
585
+ if (gen !== fetchGenRef.current) return;
586
+ setError(classifyFetchError(err));
587
+ }
588
+ }, [
589
+ settings.endpointUrl,
590
+ settings.prometheusQueries,
591
+ settings.displayedQueryParams,
592
+ driver
593
+ ]);
435
594
  useEffect(() => {
436
595
  if (queriesTimeRange) {
437
596
  setTimeLabels(generateTimeRange(dayjs(queriesTimeRange.startedAt), dayjs(queriesTimeRange.finishedAt), "minutes", 15).map((d) => d.toDate()));
@@ -440,7 +599,7 @@ const PrometheusChart = ({ data, settings }) => {
440
599
  }, [queriesTimeRange, fetchData]);
441
600
  useEffect(() => {
442
601
  setQueriesTimeRange(getQueriesTimeRange(settings.queriesPeriod, data));
443
- if (settings?.queriesPeriod === QueriesPeriod.CURRENT_SHIFT) {
602
+ if (settings?.queriesPeriod === "CURRENT_SHIFT") {
444
603
  const intervalId = setInterval(() => {
445
604
  setQueriesTimeRange(getQueriesTimeRange(settings.queriesPeriod, data));
446
605
  }, 3e4);
@@ -450,6 +609,15 @@ const PrometheusChart = ({ data, settings }) => {
450
609
  }
451
610
  return () => {};
452
611
  }, [data, settings]);
612
+ if (error) return /* @__PURE__ */ jsx(Box, {
613
+ sx: errorMessageStyles,
614
+ "data-testid": `prometheus-widget.error.${error}`,
615
+ children: /* @__PURE__ */ jsx(Typography, {
616
+ variant: "body2",
617
+ color: "text.primary",
618
+ children: t(errorTranslationKey[error])
619
+ })
620
+ });
453
621
  return queriesTimeRange && /* @__PURE__ */ jsx(Line, {
454
622
  ref: chart,
455
623
  data: chartData,
@@ -505,13 +673,16 @@ const WidgetView = ({ data, settings }) => {
505
673
  };
506
674
  //#endregion
507
675
  //#region src/components/Widget/utils.ts
676
+ const isLegacyQuery = (query) => typeof query === "string";
508
677
  const getSettingsFormProps = (t) => {
509
678
  yup.setLocale({ mixed: { required: t("prometheusWidget.thisFieldIsRequired") } });
510
679
  return {
511
680
  initialValues: {
512
681
  customTitle: "",
513
682
  endpointUrl: "",
514
- queriesPeriod: QueriesPeriod.CURRENT_SHIFT,
683
+ username: "",
684
+ password: "",
685
+ queriesPeriod: "CURRENT_SHIFT",
515
686
  prometheusQueries: [],
516
687
  displayedQueryParams: [],
517
688
  xAxisUnit: "",
@@ -519,6 +690,8 @@ const getSettingsFormProps = (t) => {
519
690
  },
520
691
  validationSchema: yup.object({
521
692
  endpointUrl: yup.string().required(),
693
+ username: yup.string(),
694
+ password: yup.string(),
522
695
  queriesPeriod: yup.string().required(),
523
696
  prometheusQueries: yup.array().of(yup.object().shape({
524
697
  query: yup.string().required(),
@@ -527,22 +700,26 @@ const getSettingsFormProps = (t) => {
527
700
  displayedQueryParams: yup.array().of(yup.string().required()),
528
701
  xAxisUnit: yup.string().required(),
529
702
  yAxisUnit: yup.string().required()
530
- })
703
+ }),
704
+ onSubmit: () => {}
531
705
  };
532
706
  };
533
707
  const migrateSettings = (settings) => {
534
- if (!satisfies(settings.version || "1.0.0", ">=1.2.5")) return {
535
- ...settings,
536
- prometheusQueries: settings.prometheusQueries.map((query) => ({
537
- query,
538
- displayName: ""
539
- }))
540
- };
708
+ if (!satisfies(settings.version || "1.0.0", ">=1.2.5")) {
709
+ const queries = settings.prometheusQueries;
710
+ return {
711
+ ...settings,
712
+ prometheusQueries: queries.map((query) => isLegacyQuery(query) ? {
713
+ query,
714
+ displayName: ""
715
+ } : query)
716
+ };
717
+ }
541
718
  return settings;
542
719
  };
543
720
  //#endregion
544
721
  //#region src/components/Widget/index.tsx
545
- const Widget = ({ url, wsUrl, lang, data, ...widgetProps }) => {
722
+ const Widget = ({ url, wsUrl, lang, data, sidePanelOpened = false, updateSidePanelProps = () => {}, ...widgetProps }) => {
546
723
  const { graphqlSdk, gqlWsClient } = useGqlClients({
547
724
  url,
548
725
  wsUrl,
@@ -557,10 +734,11 @@ const Widget = ({ url, wsUrl, lang, data, ...widgetProps }) => {
557
734
  }, [data, graphqlSdk]);
558
735
  return /* @__PURE__ */ jsx(BaseWidget, {
559
736
  ...widgetProps,
560
- url,
561
737
  lang,
562
738
  locales: resources,
563
739
  data: widgetData,
740
+ sidePanelOpened,
741
+ updateSidePanelProps,
564
742
  gqlClients: {
565
743
  graphqlSdk,
566
744
  gqlWsClient
@@ -591,10 +769,9 @@ const getTitle = (_data, settings, _filters, lang) => {
591
769
  //#endregion
592
770
  //#region src/index.tsx
593
771
  registerTranslations(resources);
594
- const thumbnail = void 0;
595
772
  const requiredFeatures = ["feature.prometheus-widget"];
596
773
  const extraPermissions = [];
597
774
  //#endregion
598
- export { Widget, extraPermissions, getDisplayName, getTitle, requiredFeatures, thumbnail, LIBRARY_VERSION as version };
775
+ export { Widget, extraPermissions, getDisplayName, getTitle, requiredFeatures, thumbnail_default as thumbnail, LIBRARY_VERSION as version };
599
776
 
600
777
  //# sourceMappingURL=index.js.map