@oneuptime/common 10.0.36 → 10.0.38

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.
Files changed (93) hide show
  1. package/Models/DatabaseModels/Index.ts +2 -0
  2. package/Models/DatabaseModels/WorkspaceNotificationSummary.ts +819 -0
  3. package/Server/API/StatusPageAPI.ts +7 -0
  4. package/Server/API/TelemetryAPI.ts +10 -0
  5. package/Server/API/WorkspaceNotificationSummaryAPI.ts +67 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/1774355321449-MigrationName.ts +51 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1774357353502-MigrationName.ts +29 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  9. package/Server/Middleware/MasterAdminAuthorization.ts +55 -0
  10. package/Server/Services/Index.ts +2 -0
  11. package/Server/Services/LogAggregationService.ts +24 -1
  12. package/Server/Services/WorkspaceNotificationSummaryService.ts +1450 -0
  13. package/Server/Utils/Greenlock/Greenlock.ts +1 -0
  14. package/Server/Utils/Telemetry/Telemetry.ts +38 -19
  15. package/Types/Permission.ts +42 -0
  16. package/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryItem.ts +13 -0
  17. package/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryType.ts +8 -0
  18. package/UI/Components/Charts/Area/AreaChart.tsx +81 -0
  19. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +106 -63
  20. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +986 -0
  21. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +1 -1
  22. package/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts +18 -1
  23. package/UI/Components/Charts/Utils/XAxis.ts +26 -21
  24. package/UI/Components/ConditionsTable/ConditionsTable.tsx +86 -67
  25. package/UI/Components/Dictionary/DictionaryOfStingsViewer.tsx +48 -28
  26. package/UI/Components/Filters/FiltersForm.tsx +19 -13
  27. package/UI/Components/GanttChart/Bar/Index.tsx +23 -5
  28. package/UI/Components/InfoCard/InfoCard.tsx +3 -1
  29. package/UI/Components/LogsViewer/LogsViewer.tsx +9 -4
  30. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +29 -2
  31. package/UI/Components/LogsViewer/types.ts +1 -0
  32. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  33. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  34. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js +857 -0
  35. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js.map +1 -0
  36. package/build/dist/Server/API/StatusPageAPI.js +2 -0
  37. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  38. package/build/dist/Server/API/TelemetryAPI.js +8 -0
  39. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  40. package/build/dist/Server/API/WorkspaceNotificationSummaryAPI.js +40 -0
  41. package/build/dist/Server/API/WorkspaceNotificationSummaryAPI.js.map +1 -0
  42. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774355321449-MigrationName.js +24 -0
  43. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774355321449-MigrationName.js.map +1 -0
  44. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774357353502-MigrationName.js +16 -0
  45. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1774357353502-MigrationName.js.map +1 -0
  46. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  47. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  48. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +25 -0
  49. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -0
  50. package/build/dist/Server/Services/Index.js +2 -0
  51. package/build/dist/Server/Services/Index.js.map +1 -1
  52. package/build/dist/Server/Services/LogAggregationService.js +12 -0
  53. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  54. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +1122 -0
  55. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -0
  56. package/build/dist/Server/Utils/Greenlock/Greenlock.js +1 -0
  57. package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
  58. package/build/dist/Server/Utils/Telemetry/Telemetry.js +29 -15
  59. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  60. package/build/dist/Types/Permission.js +36 -0
  61. package/build/dist/Types/Permission.js.map +1 -1
  62. package/build/dist/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryItem.js +14 -0
  63. package/build/dist/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryItem.js.map +1 -0
  64. package/build/dist/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryType.js +9 -0
  65. package/build/dist/Types/Workspace/NotificationSummary/WorkspaceNotificationSummaryType.js.map +1 -0
  66. package/build/dist/UI/Components/Charts/Area/AreaChart.js +39 -0
  67. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -0
  68. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +28 -9
  69. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  70. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +376 -0
  71. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -0
  72. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +1 -1
  73. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  74. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/ChartColors.js +15 -0
  75. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/ChartColors.js.map +1 -1
  76. package/build/dist/UI/Components/Charts/Utils/XAxis.js +25 -21
  77. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  78. package/build/dist/UI/Components/ConditionsTable/ConditionsTable.js +51 -30
  79. package/build/dist/UI/Components/ConditionsTable/ConditionsTable.js.map +1 -1
  80. package/build/dist/UI/Components/Dictionary/DictionaryOfStingsViewer.js +23 -11
  81. package/build/dist/UI/Components/Dictionary/DictionaryOfStingsViewer.js.map +1 -1
  82. package/build/dist/UI/Components/Filters/FiltersForm.js +10 -6
  83. package/build/dist/UI/Components/Filters/FiltersForm.js.map +1 -1
  84. package/build/dist/UI/Components/GanttChart/Bar/Index.js +15 -3
  85. package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +1 -1
  86. package/build/dist/UI/Components/InfoCard/InfoCard.js +1 -1
  87. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  88. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +5 -1
  89. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  90. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +17 -2
  91. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  92. package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
  93. package/package.json +1 -1
@@ -321,6 +321,7 @@ export default class GreenlockUtil {
321
321
  }
322
322
  } catch (e) {
323
323
  logger.error(`Error ordering certificate for domain: ${data.domain}`);
324
+ logger.error(e);
324
325
 
325
326
  if (e instanceof Exception) {
326
327
  throw e;
@@ -211,33 +211,50 @@ export default class TelemetryUtil {
211
211
  const jsonValue: JSONObject = value as JSONObject;
212
212
 
213
213
  if (jsonValue && typeof jsonValue === "object") {
214
- if (Object.prototype.hasOwnProperty.call(jsonValue, "stringValue")) {
215
- const stringValue: JSONValue = jsonValue["stringValue"];
214
+ // Handle both camelCase (JSON encoding) and snake_case (protobuf via protobufjs)
215
+ if (
216
+ Object.prototype.hasOwnProperty.call(jsonValue, "stringValue") ||
217
+ Object.prototype.hasOwnProperty.call(jsonValue, "string_value")
218
+ ) {
219
+ const stringValue: JSONValue =
220
+ jsonValue["stringValue"] ?? jsonValue["string_value"];
216
221
  finalObj =
217
222
  stringValue !== undefined && stringValue !== null
218
223
  ? (stringValue as string)
219
224
  : "";
220
- } else if (Object.prototype.hasOwnProperty.call(jsonValue, "intValue")) {
221
- const intValue: JSONValue = jsonValue["intValue"];
225
+ } else if (
226
+ Object.prototype.hasOwnProperty.call(jsonValue, "intValue") ||
227
+ Object.prototype.hasOwnProperty.call(jsonValue, "int_value")
228
+ ) {
229
+ const intValue: JSONValue =
230
+ jsonValue["intValue"] ?? jsonValue["int_value"];
222
231
  if (intValue !== undefined && intValue !== null) {
223
232
  finalObj = intValue as number;
224
233
  }
225
234
  } else if (
226
- Object.prototype.hasOwnProperty.call(jsonValue, "doubleValue")
235
+ Object.prototype.hasOwnProperty.call(jsonValue, "doubleValue") ||
236
+ Object.prototype.hasOwnProperty.call(jsonValue, "double_value")
227
237
  ) {
228
- const doubleValue: JSONValue = jsonValue["doubleValue"];
238
+ const doubleValue: JSONValue =
239
+ jsonValue["doubleValue"] ?? jsonValue["double_value"];
229
240
  if (doubleValue !== undefined && doubleValue !== null) {
230
241
  finalObj = doubleValue as number;
231
242
  }
232
- } else if (Object.prototype.hasOwnProperty.call(jsonValue, "boolValue")) {
233
- finalObj = jsonValue["boolValue"] as boolean;
234
243
  } else if (
235
- jsonValue["arrayValue"] &&
236
- (jsonValue["arrayValue"] as JSONObject)["values"]
244
+ Object.prototype.hasOwnProperty.call(jsonValue, "boolValue") ||
245
+ Object.prototype.hasOwnProperty.call(jsonValue, "bool_value")
246
+ ) {
247
+ finalObj = (jsonValue["boolValue"] ??
248
+ jsonValue["bool_value"]) as boolean;
249
+ } else if (
250
+ (jsonValue["arrayValue"] &&
251
+ (jsonValue["arrayValue"] as JSONObject)["values"]) ||
252
+ (jsonValue["array_value"] &&
253
+ (jsonValue["array_value"] as JSONObject)["values"])
237
254
  ) {
238
- const values: JSONArray = (jsonValue["arrayValue"] as JSONObject)[
239
- "values"
240
- ] as JSONArray;
255
+ const arrayVal: JSONObject = (jsonValue["arrayValue"] ||
256
+ jsonValue["array_value"]) as JSONObject;
257
+ const values: JSONArray = arrayVal["values"] as JSONArray;
241
258
  finalObj = values.map((v: JSONObject) => {
242
259
  return this.getAttributeValues(
243
260
  prefixKeysWithString,
@@ -290,17 +307,19 @@ export default class TelemetryUtil {
290
307
 
291
308
  finalObj = flattenedFields;
292
309
  } else if (
293
- jsonValue["kvlistValue"] &&
294
- (jsonValue["kvlistValue"] as JSONObject)["values"]
310
+ (jsonValue["kvlistValue"] &&
311
+ (jsonValue["kvlistValue"] as JSONObject)["values"]) ||
312
+ (jsonValue["kvlist_value"] &&
313
+ (jsonValue["kvlist_value"] as JSONObject)["values"])
295
314
  ) {
296
- const values: JSONArray = (jsonValue["kvlistValue"] as JSONObject)[
297
- "values"
298
- ] as JSONArray;
315
+ const kvlistVal: JSONObject = (jsonValue["kvlistValue"] ||
316
+ jsonValue["kvlist_value"]) as JSONObject;
317
+ const values: JSONArray = kvlistVal["values"] as JSONArray;
299
318
  finalObj = this.getAttributes({
300
319
  prefixKeysWithString,
301
320
  items: values,
302
321
  });
303
- } else if ("nullValue" in jsonValue) {
322
+ } else if ("nullValue" in jsonValue || "null_value" in jsonValue) {
304
323
  finalObj = null;
305
324
  }
306
325
  }
@@ -771,6 +771,11 @@ enum Permission {
771
771
  EditWorkspaceNotificationRule = "EditWorkspaceNotificationRule",
772
772
  ReadWorkspaceNotificationRule = "ReadWorkspaceNotificationRule",
773
773
 
774
+ CreateWorkspaceNotificationSummary = "CreateWorkspaceNotificationSummary",
775
+ DeleteWorkspaceNotificationSummary = "DeleteWorkspaceNotificationSummary",
776
+ EditWorkspaceNotificationSummary = "EditWorkspaceNotificationSummary",
777
+ ReadWorkspaceNotificationSummary = "ReadWorkspaceNotificationSummary",
778
+
774
779
  // Alert Episode Permissions
775
780
  CreateAlertEpisode = "CreateAlertEpisode",
776
781
  DeleteAlertEpisode = "DeleteAlertEpisode",
@@ -1389,6 +1394,43 @@ export class PermissionHelper {
1389
1394
  group: PermissionGroup.Settings,
1390
1395
  },
1391
1396
 
1397
+ {
1398
+ permission: Permission.CreateWorkspaceNotificationSummary,
1399
+ title: "Create Workspace Notification Summary",
1400
+ description:
1401
+ "This permission can create workspace notification summaries for this project.",
1402
+ isAssignableToTenant: true,
1403
+ isAccessControlPermission: false,
1404
+ group: PermissionGroup.Settings,
1405
+ },
1406
+ {
1407
+ permission: Permission.DeleteWorkspaceNotificationSummary,
1408
+ title: "Delete Workspace Notification Summary",
1409
+ description:
1410
+ "This permission can delete workspace notification summaries of this project.",
1411
+ isAssignableToTenant: true,
1412
+ isAccessControlPermission: false,
1413
+ group: PermissionGroup.Settings,
1414
+ },
1415
+ {
1416
+ permission: Permission.EditWorkspaceNotificationSummary,
1417
+ title: "Edit Workspace Notification Summary",
1418
+ description:
1419
+ "This permission can edit workspace notification summaries of this project.",
1420
+ isAssignableToTenant: true,
1421
+ isAccessControlPermission: false,
1422
+ group: PermissionGroup.Settings,
1423
+ },
1424
+ {
1425
+ permission: Permission.ReadWorkspaceNotificationSummary,
1426
+ title: "Read Workspace Notification Summary",
1427
+ description:
1428
+ "This permission can read workspace notification summaries of this project.",
1429
+ isAssignableToTenant: true,
1430
+ isAccessControlPermission: false,
1431
+ group: PermissionGroup.Settings,
1432
+ },
1433
+
1392
1434
  {
1393
1435
  permission: Permission.CreateIncidentStateTimeline,
1394
1436
  title: "Create Incident State Timeline",
@@ -0,0 +1,13 @@
1
+ enum WorkspaceNotificationSummaryItem {
2
+ TotalCount = "Total Count",
3
+ ListWithLinks = "List with Links",
4
+ WhoAcknowledged = "Who Acknowledged",
5
+ WhoResolved = "Who Resolved",
6
+ TimeToAcknowledge = "Time to Acknowledge",
7
+ TimeToResolve = "Time to Resolve",
8
+ ResourcesAffected = "Resources Affected",
9
+ SeverityBreakdown = "Severity Breakdown",
10
+ StateBreakdown = "State Breakdown",
11
+ }
12
+
13
+ export default WorkspaceNotificationSummaryItem;
@@ -0,0 +1,8 @@
1
+ enum WorkspaceNotificationSummaryType {
2
+ Incident = "Incident",
3
+ Alert = "Alert",
4
+ IncidentEpisode = "Incident Episode",
5
+ AlertEpisode = "Alert Episode",
6
+ }
7
+
8
+ export default WorkspaceNotificationSummaryType;
@@ -0,0 +1,81 @@
1
+ import { AreaChart } from "../ChartLibrary/AreaChart/AreaChart";
2
+ import React, { FunctionComponent, ReactElement, useEffect } from "react";
3
+ import SeriesPoint from "../Types/SeriesPoints";
4
+ import { XAxis } from "../Types/XAxis/XAxis";
5
+ import YAxis from "../Types/YAxis/YAxis";
6
+ import ChartCurve from "../Types/ChartCurve";
7
+ import ChartDataPoint from "../ChartLibrary/Types/ChartDataPoint";
8
+ import DataPointUtil from "../Utils/DataPoint";
9
+
10
+ export interface ComponentProps {
11
+ data: Array<SeriesPoint>;
12
+ xAxis: XAxis;
13
+ yAxis: YAxis;
14
+ curve: ChartCurve;
15
+ sync: boolean;
16
+ heightInPx?: number | undefined;
17
+ }
18
+
19
+ export interface AreaInternalProps extends ComponentProps {
20
+ syncid: string;
21
+ }
22
+
23
+ const AreaChartElement: FunctionComponent<AreaInternalProps> = (
24
+ props: AreaInternalProps,
25
+ ): ReactElement => {
26
+ const [records, setRecords] = React.useState<Array<ChartDataPoint>>([]);
27
+
28
+ const categories: Array<string> = props.data.map((item: SeriesPoint) => {
29
+ return item.seriesName;
30
+ });
31
+
32
+ useEffect(() => {
33
+ if (!props.data || props.data.length === 0) {
34
+ setRecords([]);
35
+ }
36
+
37
+ const records: Array<ChartDataPoint> = DataPointUtil.getChartDataPoints({
38
+ seriesPoints: props.data,
39
+ xAxis: props.xAxis,
40
+ yAxis: props.yAxis,
41
+ });
42
+
43
+ setRecords(records);
44
+ }, [props.data]);
45
+
46
+ const className: string = props.heightInPx ? `` : "h-80";
47
+ const style: React.CSSProperties = props.heightInPx
48
+ ? { height: `${props.heightInPx}px` }
49
+ : {};
50
+
51
+ return (
52
+ <AreaChart
53
+ className={className}
54
+ style={style}
55
+ data={records}
56
+ tickGap={1}
57
+ index={"Time"}
58
+ categories={categories}
59
+ colors={[
60
+ "blue",
61
+ "emerald",
62
+ "violet",
63
+ "amber",
64
+ "cyan",
65
+ "pink",
66
+ "lime",
67
+ "fuchsia",
68
+ "indigo",
69
+ "rose",
70
+ ]}
71
+ valueFormatter={props.yAxis.options.formatter || undefined}
72
+ showTooltip={true}
73
+ connectNulls={true}
74
+ curve={props.curve || ChartCurve.MONOTONE}
75
+ syncid={props.sync ? props.syncid : undefined}
76
+ yAxisWidth={60}
77
+ />
78
+ );
79
+ };
80
+
81
+ export default AreaChartElement;
@@ -3,6 +3,9 @@ import LineChart, { ComponentProps as LineChartProps } from "../Line/LineChart";
3
3
  import BarChartElement, {
4
4
  ComponentProps as BarChartProps,
5
5
  } from "../Bar/BarChart";
6
+ import AreaChartElement, {
7
+ ComponentProps as AreaChartProps,
8
+ } from "../Area/AreaChart";
6
9
  import React, { FunctionComponent, ReactElement } from "react";
7
10
 
8
11
  export enum ChartType {
@@ -16,7 +19,7 @@ export interface Chart {
16
19
  title: string;
17
20
  description?: string | undefined;
18
21
  type: ChartType;
19
- props: LineChartProps | BarChartProps;
22
+ props: LineChartProps | BarChartProps | AreaChartProps;
20
23
  }
21
24
 
22
25
  export interface ComponentProps {
@@ -31,71 +34,111 @@ const ChartGroup: FunctionComponent<ComponentProps> = (
31
34
  ): ReactElement => {
32
35
  const syncId: string = Text.generateRandomText(10);
33
36
 
37
+ const isLastChart: (index: number) => boolean = (index: number): boolean => {
38
+ return index === props.charts.length - 1;
39
+ };
40
+
41
+ type GetChartContentFunction = (chart: Chart, index: number) => ReactElement;
42
+
43
+ const getChartContent: GetChartContentFunction = (
44
+ chart: Chart,
45
+ index: number,
46
+ ): ReactElement => {
47
+ switch (chart.type) {
48
+ case ChartType.LINE:
49
+ return (
50
+ <LineChart
51
+ key={index}
52
+ {...(chart.props as LineChartProps)}
53
+ syncid={syncId}
54
+ heightInPx={props.heightInPx}
55
+ />
56
+ );
57
+ case ChartType.BAR:
58
+ return (
59
+ <BarChartElement
60
+ key={index}
61
+ {...(chart.props as BarChartProps)}
62
+ syncid={syncId}
63
+ heightInPx={props.heightInPx}
64
+ />
65
+ );
66
+ case ChartType.AREA:
67
+ return (
68
+ <AreaChartElement
69
+ key={index}
70
+ {...(chart.props as AreaChartProps)}
71
+ syncid={syncId}
72
+ heightInPx={props.heightInPx}
73
+ />
74
+ );
75
+ default:
76
+ return <></>;
77
+ }
78
+ };
79
+
80
+ // When hideCard is true, render charts in a clean vertical stack with dividers
81
+ if (props.hideCard) {
82
+ return (
83
+ <div className="space-y-0">
84
+ {props.charts.map((chart: Chart, index: number) => {
85
+ return (
86
+ <div
87
+ key={index}
88
+ className={`${!isLastChart(index) ? "border-b border-gray-100" : ""} ${props.chartCssClass || ""}`}
89
+ >
90
+ <div className="px-1 pt-5 pb-4">
91
+ <div className="mb-1">
92
+ <h3 className="text-sm font-semibold text-gray-700 tracking-tight">
93
+ {chart.title}
94
+ </h3>
95
+ {chart.description && (
96
+ <p className="mt-0.5 text-xs text-gray-400 hidden md:block">
97
+ {chart.description}
98
+ </p>
99
+ )}
100
+ </div>
101
+ {getChartContent(chart, index)}
102
+ </div>
103
+ </div>
104
+ );
105
+ })}
106
+ </div>
107
+ );
108
+ }
109
+
110
+ // When showing cards, use the grid layout
111
+ const gridCols: string =
112
+ props.charts.length > 1 ? "lg:grid-cols-2" : "lg:grid-cols-1";
113
+
34
114
  return (
35
- <div className="lg:grid grid-cols-1 gap-5 space-y-5 lg:space-y-0">
115
+ <div
116
+ className={`grid grid-cols-1 ${gridCols} gap-4 space-y-4 lg:space-y-0`}
117
+ >
36
118
  {props.charts.map((chart: Chart, index: number) => {
37
- switch (chart.type) {
38
- case ChartType.LINE:
39
- return (
40
- <div
41
- key={index}
42
- className={`p-6 ${props.hideCard ? "" : "rounded-md bg-white shadow"} ${props.chartCssClass || ""}`}
43
- >
44
- <h2
45
- data-testid="card-details-heading"
46
- id="card-details-heading"
47
- className="text-lg font-medium leading-6 text-gray-900"
48
- >
49
- {chart.title}
50
- </h2>
51
- {chart.description && (
52
- <p
53
- data-testid="card-description"
54
- className="mt-1 text-sm text-gray-500 w-full hidden md:block"
55
- >
56
- {chart.description}
57
- </p>
58
- )}
59
- <LineChart
60
- key={index}
61
- {...(chart.props as LineChartProps)}
62
- syncid={syncId}
63
- heightInPx={props.heightInPx}
64
- />
65
- </div>
66
- );
67
- case ChartType.BAR:
68
- return (
69
- <div
70
- key={index}
71
- className={`p-6 ${props.hideCard ? "" : "rounded-md bg-white shadow"} ${props.chartCssClass || ""}`}
119
+ return (
120
+ <div
121
+ key={index}
122
+ className={`p-5 rounded-lg border border-gray-200 bg-white shadow-sm ${props.chartCssClass || ""}`}
123
+ >
124
+ <h2
125
+ data-testid="card-details-heading"
126
+ id="card-details-heading"
127
+ className="text-base font-semibold leading-6 text-gray-900"
128
+ >
129
+ {chart.title}
130
+ </h2>
131
+ {chart.description && (
132
+ <p
133
+ data-testid="card-description"
134
+ className="mt-0.5 text-sm text-gray-500 w-full hidden md:block"
72
135
  >
73
- <h2
74
- data-testid="card-details-heading"
75
- id="card-details-heading"
76
- className="text-lg font-medium leading-6 text-gray-900"
77
- >
78
- {chart.title}
79
- </h2>
80
- {chart.description && (
81
- <p
82
- data-testid="card-description"
83
- className="mt-1 text-sm text-gray-500 w-full hidden md:block"
84
- >
85
- {chart.description}
86
- </p>
87
- )}
88
- <BarChartElement
89
- key={index}
90
- {...(chart.props as BarChartProps)}
91
- syncid={syncId}
92
- heightInPx={props.heightInPx}
93
- />
94
- </div>
95
- );
96
- default:
97
- return <></>;
98
- }
136
+ {chart.description}
137
+ </p>
138
+ )}
139
+ {getChartContent(chart, index)}
140
+ </div>
141
+ );
99
142
  })}
100
143
  </div>
101
144
  );