Skip to content

Commit

Permalink
feat: Add static preset for alerts without incidents (#2150)
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirFilonov authored Oct 13, 2024
1 parent 99cfd3b commit 5bbb98c
Show file tree
Hide file tree
Showing 20 changed files with 141 additions and 26 deletions.
5 changes: 5 additions & 0 deletions keep-ui/app/alerts/alert-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ interface Props {
alerts: AlertDto[];
clearRowSelection: () => void;
setDismissModalAlert?: (alert: AlertDto[] | null) => void;
mutateAlerts?: () => void;
}

export default function AlertActions({
selectedRowIds,
alerts,
clearRowSelection,
setDismissModalAlert,
mutateAlerts
}: Props) {
const router = useRouter();
const { useAllPresets } = usePresets();
Expand Down Expand Up @@ -88,6 +90,9 @@ export default function AlertActions({
const handleSuccessfulAlertsAssociation = () => {
hideIncidentSelector();
clearRowSelection();
if (mutateAlerts) {
mutateAlerts();
}
}

return (
Expand Down
10 changes: 9 additions & 1 deletion keep-ui/app/alerts/alert-table-tab-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
return alert.dismissed === true;
}

if (presetName === "without-incident") {
return alert.incident === null;
}


return true;
};

Expand All @@ -31,6 +36,7 @@
setRunWorkflowModalAlert: (alert: AlertDto | null) => void;
setDismissModalAlert: (alert: AlertDto[] | null) => void;
setChangeStatusAlert: (alert: AlertDto | null) => void;
mutateAlerts: () => void;
}

export default function AlertTableTabPanel({
Expand All @@ -42,6 +48,7 @@
setRunWorkflowModalAlert,
setDismissModalAlert,
setChangeStatusAlert,
mutateAlerts
}: Props) {
const sortedPresetAlerts = alerts
.filter((alert) => getPresetAlerts(alert, preset.name))
Expand Down Expand Up @@ -92,9 +99,10 @@
presetName={preset.name}
presetPrivate={preset.is_private}
presetNoisy={preset.is_noisy}
presetStatic={preset.name === "feed" || preset.name === "groups" || preset.name === "dismissed"}
presetStatic={preset.name === "feed" || preset.name === "groups" || preset.name === "dismissed" || preset.name === "without-incident"}
presetId={preset.id}
presetTabs={presetTabs}
mutateAlerts={mutateAlerts}
/>
);
}
3 changes: 3 additions & 0 deletions keep-ui/app/alerts/alert-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface Props {
isRefreshAllowed?: boolean;
isMenuColDisplayed?: boolean;
setDismissedModalAlert?: (alert: AlertDto[] | null) => void;
mutateAlerts?: () => void;
}

export function AlertTable({
Expand All @@ -65,6 +66,7 @@ export function AlertTable({
presetTabs = [],
isRefreshAllowed = true,
setDismissedModalAlert,
mutateAlerts
}: Props) {
const [theme, setTheme] = useLocalStorage(
"alert-table-theme",
Expand Down Expand Up @@ -186,6 +188,7 @@ export function AlertTable({
alerts={alerts}
clearRowSelection={table.resetRowSelection}
setDismissModalAlert={setDismissedModalAlert}
mutateAlerts={mutateAlerts}
/>
) : (
<AlertPresets
Expand Down
11 changes: 11 additions & 0 deletions keep-ui/app/alerts/alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ const defaultPresets: Preset[] = [
should_do_noise_now: false,
tags: []
},
{
id: "without-incident",
name: "without-incident",
options: [],
is_private: false,
is_noisy: false,
alerts_count: 0,
should_do_noise_now: false,
tags: []
},
];

type AlertsProps = {
Expand Down Expand Up @@ -125,6 +135,7 @@ export default function Alerts({ presetName }: AlertsProps) {
setRunWorkflowModalAlert={setRunWorkflowModalAlert}
setDismissModalAlert={setDismissModalAlert}
setChangeStatusAlert={setChangeStatusAlert}
mutateAlerts={mutateAlerts}
/>

{selectedPreset && (
Expand Down
1 change: 1 addition & 0 deletions keep-ui/app/alerts/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ group?: boolean;
note?: string;
isNoisy?: boolean;
enriched_fields: string[];
incident?: string;
}

interface Option {
Expand Down
4 changes: 4 additions & 0 deletions keep-ui/components/LinkWithIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type LinkWithIconProps = {
isDeletable?: boolean;
onDelete?: () => void;
className?: string;
testId?: string;
} & LinkProps & AnchorHTMLAttributes<HTMLAnchorElement>;

export const LinkWithIcon = ({
Expand All @@ -25,6 +26,7 @@ export const LinkWithIcon = ({
isDeletable = false,
onDelete,
className,
testId,
...restOfLinkProps
}: LinkWithIconProps) => {
const pathname = usePathname();
Expand Down Expand Up @@ -69,6 +71,7 @@ export const LinkWithIcon = ({
{...restOfLinkProps}
className="flex items-center space-x-2 flex-1"
onClick={onClick}
data-testid={`${testId}-link`}
>
<Icon className={iconClasses} icon={icon} />
<span className={textClasses}>{children}</span>
Expand All @@ -78,6 +81,7 @@ export const LinkWithIcon = ({
<Badge
size="xs"
color="orange"
data-testid={`${testId}-badge`}
>
{count}
</Badge>
Expand Down
18 changes: 17 additions & 1 deletion keep-ui/components/navbar/AlertsLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LinkWithIcon } from "components/LinkWithIcon";
import { CustomPresetAlertLinks } from "components/navbar/CustomPresetAlertLinks";
import { SilencedDoorbellNotification } from "components/icons";
import { IoChevronUp } from "react-icons/io5";
import { AiOutlineGroup, AiOutlineSwap } from "react-icons/ai";
import { AiOutlineSwap } from "react-icons/ai";
import { FiFilter } from "react-icons/fi";
import { Disclosure } from "@headlessui/react";
import classNames from "classnames";
Expand All @@ -17,6 +17,7 @@ import Modal from "@/components/ui/Modal";
import CreatableMultiSelect from "@/components/ui/CreatableMultiSelect";
import { useLocalStorage } from "utils/hooks/useLocalStorage";
import { ActionMeta, MultiValue } from "react-select";
import {MdFlashOff} from "react-icons/md";

type AlertsLinksProps = {
session: Session | null;
Expand Down Expand Up @@ -55,6 +56,9 @@ export const AlertsLinks = ({ session }: AlertsLinksProps) => {
const dismissedPreset = staticPresets.find(
(preset) => preset.name === "dismissed"
);
const withoutIncidentPreset = staticPresets.find(
(preset) => preset.name === "without-incident"
);

const handleTagSelect = (
newValue: MultiValue<{ value: string; label: string }>,
Expand Down Expand Up @@ -115,10 +119,21 @@ export const AlertsLinks = ({ session }: AlertsLinksProps) => {
href="/alerts/feed"
icon={AiOutlineSwap}
count={mainPreset?.alerts_count}
testId="menu-alerts-feed"
>
<Subtitle>Feed</Subtitle>
</LinkWithIcon>
</li>
<li>
<LinkWithIcon
href="/alerts/without-incident"
icon={MdFlashOff}
count={withoutIncidentPreset?.alerts_count}
testId="menu-alerts-without-incident"
>
<Subtitle>Without Incident</Subtitle>
</LinkWithIcon>
</li>
{session && (
<CustomPresetAlertLinks
session={session}
Expand All @@ -130,6 +145,7 @@ export const AlertsLinks = ({ session }: AlertsLinksProps) => {
href="/alerts/dismissed"
icon={SilencedDoorbellNotification}
count={dismissedPreset?.alerts_count}
testId="menu-alerts-dismissed"
>
<Subtitle>Dismissed</Subtitle>
</LinkWithIcon>
Expand Down
3 changes: 2 additions & 1 deletion keep-ui/components/navbar/CustomPresetAlertLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const CustomPresetAlertLinks = ({
revalidateIfStale: false,
revalidateOnFocus: false,
});

const pathname = usePathname();
const router = useRouter();
const [presetsOrder, setPresetsOrder] = useState<Preset[]>([]);
Expand All @@ -125,7 +126,7 @@ export const CustomPresetAlertLinks = ({

useEffect(() => {
const filteredLS = presetsOrderFromLS.filter(
(preset) => !["feed", "deleted", "dismissed", "groups"].includes(preset.name)
(preset) => !["feed", "deleted", "dismissed", "without-incident", "groups"].includes(preset.name)
);

// Combine live presets and local storage order
Expand Down
5 changes: 2 additions & 3 deletions keep-ui/components/navbar/IncidentLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
import { usePathname } from "next/navigation";
import { Subtitle } from "@tremor/react";
import { LinkWithIcon } from "components/LinkWithIcon";
import { DoorbellNotification } from "components/icons";
import { Session } from "next-auth";
import { Disclosure } from "@headlessui/react";
import { IoChevronUp } from "react-icons/io5";
import classNames from "classnames";
import { useIncidents, usePollIncidents } from "utils/hooks/useIncidents";
import { MdNearbyError } from "react-icons/md";
import {MdFlashOn} from "react-icons/md";

type IncidentsLinksProps = { session: Session | null };
const SHOW_N_INCIDENTS = 3;
Expand Down Expand Up @@ -46,7 +45,7 @@ export const IncidentsLinks = ({ session }: IncidentsLinksProps) => {
<li className="relative">
<LinkWithIcon
href="/incidents"
icon={DoorbellNotification}
icon={MdFlashOn}
count={incidents?.count}
>
<Subtitle>Incidents</Subtitle>
Expand Down
10 changes: 5 additions & 5 deletions keep-ui/utils/hooks/usePresets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ export const usePresets = (type?: string, useFilters?: boolean) => {
updatePresets(
presetsOrderRef.current,
newPresets.filter(
(p) => !["feed", "deleted", "dismissed", "groups"].includes(p.name)
(p) => !["feed", "deleted", "dismissed", "without-incident", "groups"].includes(p.name)
)
)
);
setStaticPresetsOrderFromLS((current) =>
updatePresets(
staticPresetsOrderRef.current,
newPresets.filter((p) =>
["feed", "deleted", "dismissed", "groups"].includes(p.name)
["feed", "deleted", "dismissed", "without-incident", "groups"].includes(p.name)
)
)
);
Expand Down Expand Up @@ -126,10 +126,10 @@ export const usePresets = (type?: string, useFilters?: boolean) => {
if (data) {
const dynamicPresets = data.filter(
(p) =>
!["feed", "deleted", "dismissed", "groups"].includes(p.name)
!["feed", "deleted", "dismissed", "without-incident", "groups"].includes(p.name)
);
const staticPresets = data.filter((p) =>
["feed", "deleted", "dismissed", "groups"].includes(p.name)
["feed", "deleted", "dismissed", "without-incident", "groups"].includes(p.name)
);

//if it is dashboard we don't need to merge with local storage.
Expand Down Expand Up @@ -193,7 +193,7 @@ export const usePresets = (type?: string, useFilters?: boolean) => {
} = useFetchAllPresets(options);
const filteredPresets = presets?.filter(
(preset) =>
!["feed", "deleted", "dismissed", "groups"].includes(preset.name)
!["feed", "deleted", "dismissed", "groups", "without-incident"].includes(preset.name)
);
return {
data: filteredPresets,
Expand Down
15 changes: 15 additions & 0 deletions keep/api/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@
static=True,
tags=[],
),
"without-incident": PresetDto(
id=StaticPresetsId.WITHOUT_INCIDENT_PRESET_ID.value,
name="without-incident",
options=[
{"label": "CEL", "value": "incident == null"},
{"label": "SQL", "value": {"sql": "incident is null", "params": {}}},
],
created_by=None,
is_private=False,
is_noisy=False,
should_do_noise_now=False,
static=True,
tags=[],
),

}

###
Expand Down
Loading

0 comments on commit 5bbb98c

Please sign in to comment.