Skip to content

Commit 507b16e

Browse files
DolevNedolevneshahargl
authored
feat: Bringing back the OG Alerts Count Widget + Adding optional additional link functionality (#5209)
Signed-off-by: DolevNe <[email protected]> Signed-off-by: Shahar Glazner <[email protected]> Co-authored-by: dolevne <[email protected]> Co-authored-by: Shahar Glazner <[email protected]>
1 parent 7bdc98d commit 507b16e

File tree

6 files changed

+336
-12
lines changed

6 files changed

+336
-12
lines changed

keep-ui/app/(keep)/dashboard/GridLayout.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const GridLayout: React.FC<GridLayoutProps> = ({
4444
onLayoutChange(updatedLayout as LayoutItem[]);
4545
}}
4646
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
47-
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
47+
cols={{ lg: 24, md: 20, sm: 12, xs: 8, xxs: 4 }}
4848
rowHeight={30}
4949
containerPadding={[0, 0]}
5050
margin={[10, 10]}
@@ -53,6 +53,7 @@ const GridLayout: React.FC<GridLayoutProps> = ({
5353
isResizable={true}
5454
compactType={null}
5555
draggableHandle=".grid-item__widget"
56+
transformScale={1}
5657
>
5758
{data.map((item) => {
5859
//Updating the static hardcode db value.

keep-ui/app/(keep)/dashboard/types.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,21 @@ export enum WidgetType {
2929
GENERICS_METRICS = "GENERICS_METRICS",
3030
}
3131

32+
export enum PresetPanelType {
33+
ALERT_TABLE = "ALERT_TABLE",
34+
ALERT_COUNT_PANEL = "ALERT_COUNT_PANEL",
35+
}
36+
3237
export interface WidgetData extends LayoutItem {
3338
thresholds?: Threshold[];
3439
preset?: Preset;
3540
name: string;
3641
widgetType: WidgetType;
3742
genericMetrics?: GenericsMetrics;
3843
metric?: MetricsWidget;
44+
presetPanelType?: PresetPanelType;
45+
showFiringOnly?: boolean;
46+
customLink?: string;
3947
}
4048

4149
export interface Threshold {

keep-ui/app/(keep)/dashboard/widget-types/preset/preset-grid-item.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useMemo } from "react";
2-
import { WidgetData, WidgetType } from "../../types";
2+
import { WidgetData, WidgetType, PresetPanelType } from "../../types";
33
import { usePresetAlertsCount } from "@/features/presets/custom-preset-links";
44
import { useDashboardPreset } from "@/utils/hooks/useDashboardPresets";
55
import { Button, Icon } from "@tremor/react";
@@ -11,6 +11,7 @@ import { useRouter } from "next/navigation";
1111
import TimeAgo from "react-timeago";
1212
import { useSearchParams } from "next/navigation";
1313
import WidgetAlertsTable from "./widget-alerts-table";
14+
import WidgetAlertCountPanel from "./widget-alert-count-panel";
1415
import CelInput from "@/features/cel-input/cel-input";
1516

1617
interface GridItemProps {
@@ -177,8 +178,13 @@ const PresetGridItem: React.FC<GridItemProps> = ({ item }) => {
177178
);
178179
}
179180

181+
const isAlertTable = item.presetPanelType === PresetPanelType.ALERT_TABLE || !item.presetPanelType;
182+
const isAlertCountPanel = item.presetPanelType === PresetPanelType.ALERT_COUNT_PANEL;
183+
180184
return (
181185
<div className="flex flex-col overflow-y-auto gap-2">
186+
{isAlertTable && (
187+
<>
182188
<div className="flex gap-2">
183189
<div className="flex-1 min-w-0 overflow-hidden whitespace-nowrap">
184190
<div className="flex gap-1 items-center">
@@ -205,6 +211,17 @@ const PresetGridItem: React.FC<GridItemProps> = ({ item }) => {
205211
alerts={isLoading ? undefined : alerts}
206212
columns={(item as any)?.presetColumns}
207213
background={isLoading ? undefined : hexToRgb(getColor(), 0.1)}
214+
/>
215+
)}
216+
</>
217+
)}
218+
{isAlertCountPanel && (
219+
<WidgetAlertCountPanel
220+
presetName={preset?.name as string}
221+
showFiringOnly={item.showFiringOnly}
222+
background={isLoading ? undefined : hexToRgb(getColor(), 0.1)}
223+
thresholds={item.thresholds}
224+
customLink={item.customLink}
208225
/>
209226
)}
210227
</div>

keep-ui/app/(keep)/dashboard/widget-types/preset/preset-widget-form.tsx

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
SelectItem,
88
Subtitle,
99
TextInput,
10+
Switch,
1011
} from "@tremor/react";
1112
import { useEffect, useMemo, useState } from "react";
1213
import {
@@ -16,13 +17,16 @@ import {
1617
useWatch,
1718
useFieldArray,
1819
} from "react-hook-form";
19-
import { LayoutItem, Threshold } from "../../types";
20+
import { LayoutItem, Threshold, PresetPanelType } from "../../types";
2021
import ColumnsSelection from "./columns-selection";
2122

2223
interface PresetForm {
2324
selectedPreset: string;
2425
countOfLastAlerts: string;
2526
thresholds: Threshold[];
27+
presetPanelType: PresetPanelType;
28+
showFiringOnly: boolean;
29+
customLink?: string;
2630
}
2731

2832
export interface PresetWidgetFormProps {
@@ -47,9 +51,12 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
4751
? editingItem.preset.countOfLastAlerts || 0
4852
: 5,
4953
thresholds: editingItem?.thresholds || [
50-
{ value: 0, color: "#22c55e" }, // Green
51-
{ value: 20, color: "#ef4444" }, // Red
54+
{ value: 0, color: "#10b981" }, // Bold emerald green
55+
{ value: 20, color: "#dc2626" }, // Bold red
5256
],
57+
presetPanelType: editingItem?.presetPanelType || PresetPanelType.ALERT_TABLE,
58+
showFiringOnly: editingItem?.showFiringOnly ?? false,
59+
customLink: editingItem?.customLink || "",
5360
},
5461
});
5562
const [presetColumns, setPresetColumns] = useState<string[] | undefined>(
@@ -72,6 +79,9 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
7279
...t,
7380
value: parseInt(t.value?.toString() as string, 10) || 0,
7481
})),
82+
presetPanelType: formValues.presetPanelType || PresetPanelType.ALERT_TABLE,
83+
showFiringOnly: formValues.showFiringOnly ?? false,
84+
customLink: formValues.customLink || "",
7585
};
7686
}, [formValues, presetColumns]);
7787

@@ -80,8 +90,23 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
8090
return {} as LayoutItem;
8191
}
8292

83-
const itemHeight = normalizedFormValues.countOfLastAlerts > 0 ? 6 : 4;
84-
const itemWidth = normalizedFormValues.countOfLastAlerts > 0 ? 4 : 3;
93+
const isAlertTable = normalizedFormValues.presetPanelType === PresetPanelType.ALERT_TABLE;
94+
const isAlertCountPanel = normalizedFormValues.presetPanelType === PresetPanelType.ALERT_COUNT_PANEL;
95+
96+
if (isAlertCountPanel) {
97+
// Narrower, more compact layout for count panels with no minimum width
98+
return {
99+
w: 4,
100+
h: 3,
101+
minW: 0,
102+
minH: 2,
103+
static: false,
104+
} as LayoutItem;
105+
}
106+
107+
// Original layout for alert tables
108+
const itemHeight = isAlertTable && normalizedFormValues.countOfLastAlerts > 0 ? 6 : 4;
109+
const itemWidth = isAlertTable && normalizedFormValues.countOfLastAlerts > 0 ? 8 : 6;
85110

86111
return {
87112
w: itemWidth,
@@ -102,6 +127,9 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
102127
},
103128
presetColumns: normalizedFormValues.presetColumns,
104129
thresholds: normalizedFormValues.thresholds,
130+
presetPanelType: normalizedFormValues.presetPanelType,
131+
showFiringOnly: normalizedFormValues.showFiringOnly,
132+
customLink: normalizedFormValues.customLink,
105133
},
106134
isValid
107135
);
@@ -158,18 +186,81 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
158186
/>
159187
</div>
160188
<div className="mb-4 mt-2">
161-
<Subtitle>Last alerts count to display</Subtitle>
189+
<Subtitle>Panel Type</Subtitle>
162190
<Controller
163-
name="countOfLastAlerts"
191+
name="presetPanelType"
164192
control={control}
165193
rules={{
166194
required: {
167195
value: true,
168-
message: "Preset selection is required",
196+
message: "Panel type selection is required",
169197
},
170198
}}
171199
render={({ field }) => (
172-
<TextInput
200+
<Select
201+
{...field}
202+
placeholder="Select a panel type"
203+
error={!!get(errors, "presetPanelType.message")}
204+
errorMessage={get(errors, "presetPanelType.message")}
205+
>
206+
<SelectItem value={PresetPanelType.ALERT_TABLE}>
207+
Alert Table
208+
</SelectItem>
209+
<SelectItem value={PresetPanelType.ALERT_COUNT_PANEL}>
210+
Alert Count Panel
211+
</SelectItem>
212+
</Select>
213+
)}
214+
/>
215+
</div>
216+
{formValues.presetPanelType === PresetPanelType.ALERT_COUNT_PANEL && (
217+
<>
218+
<div className="mb-4 mt-2">
219+
<div className="flex items-center justify-between">
220+
<Subtitle>Show Firing Alerts Only</Subtitle>
221+
<Controller
222+
name="showFiringOnly"
223+
control={control}
224+
render={({ field }) => (
225+
<Switch
226+
checked={field.value}
227+
onChange={field.onChange}
228+
/>
229+
)}
230+
/>
231+
</div>
232+
</div>
233+
<div className="mb-4 mt-2">
234+
<Subtitle>Custom Link (optional)</Subtitle>
235+
<Controller
236+
name="customLink"
237+
control={control}
238+
render={({ field }) => (
239+
<TextInput
240+
{...field}
241+
placeholder="https://example.com or leave empty for preset link"
242+
type="url"
243+
/>
244+
)}
245+
/>
246+
</div>
247+
</>
248+
)}
249+
{formValues.presetPanelType === PresetPanelType.ALERT_TABLE && (
250+
<>
251+
<div className="mb-4 mt-2">
252+
<Subtitle>Last alerts count to display</Subtitle>
253+
<Controller
254+
name="countOfLastAlerts"
255+
control={control}
256+
rules={{
257+
required: {
258+
value: true,
259+
message: "Preset selection is required",
260+
},
261+
}}
262+
render={({ field }) => (
263+
<TextInput
173264
{...field}
174265
error={!!get(errors, "countOfLastAlerts.message")}
175266
errorMessage={get(errors, "countOfLastAlerts.message")}
@@ -185,6 +276,8 @@ export const PresetWidgetForm: React.FC<PresetWidgetFormProps> = ({
185276
selectedColumns={presetColumns}
186277
onChange={(selectedColumns) => setPresetColumns(selectedColumns)}
187278
></ColumnsSelection>
279+
</>
280+
)}
188281
<div className="mb-4">
189282
<div className="flex items-center justify-between">
190283
<Subtitle>Thresholds</Subtitle>

0 commit comments

Comments
 (0)