Skip to content

Commit

Permalink
feat(api): topology incidents (#2961)
Browse files Browse the repository at this point in the history
Signed-off-by: Tal <[email protected]>
Co-authored-by: Tal <[email protected]>
  • Loading branch information
shahargl and talboren authored Jan 13, 2025
1 parent 53a3fa0 commit 7b5af45
Show file tree
Hide file tree
Showing 75 changed files with 4,398 additions and 685 deletions.
9 changes: 6 additions & 3 deletions keep-ui/app/(keep)/alerts/alert-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { SilencedDoorbellNotification } from "@/components/icons";
import AlertAssociateIncidentModal from "./alert-associate-incident-modal";
import CreateIncidentWithAIModal from "./alert-create-incident-ai-modal";
import { useApi } from "@/shared/lib/hooks/useApi";
import { Table } from "@tanstack/react-table";

import { useRevalidateMultiple } from "@/shared/lib/state-utils";

interface Props {
selectedRowIds: string[];
alerts: AlertDto[];
table: Table<AlertDto>;
clearRowSelection: () => void;
setDismissModalAlert?: (alert: AlertDto[] | null) => void;
mutateAlerts?: () => void;
Expand All @@ -24,6 +26,7 @@ interface Props {
export default function AlertActions({
selectedRowIds,
alerts,
table,
clearRowSelection,
setDismissModalAlert,
mutateAlerts,
Expand All @@ -38,9 +41,9 @@ export default function AlertActions({
const [isCreateIncidentWithAIOpen, setIsCreateIncidentWithAIOpen] =
useState<boolean>(false);

const selectedAlerts = alerts.filter((_alert, index) =>
selectedRowIds.includes(index.toString())
);
const selectedAlerts = table
.getSelectedRowModel()
.rows.map((row) => row.original);

async function addOrUpdatePreset() {
const newPresetName = prompt("Enter new preset name");
Expand Down
20 changes: 1 addition & 19 deletions keep-ui/app/(keep)/alerts/alert-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { useRouter } from "next/navigation";
import { useApi } from "@/shared/lib/hooks/useApi";
import { DropdownMenu } from "@/shared/ui";
import { ElementType } from "react";
import { DynamicIcon } from "@/components/ui";

interface Props {
alert: AlertDto;
Expand All @@ -38,25 +39,6 @@ interface MenuItem {
show?: boolean;
}

function DynamicIcon({ providerType }: { providerType: string }) {
return (
<svg
width="24px"
height="24px"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
fill="none"
>
<image
id="image0"
width="24"
height="24"
href={`/icons/${providerType}-icon.png`}
/>
</svg>
);
}

export default function AlertMenu({
alert,
setRunWorkflowModalAlert,
Expand Down
1 change: 1 addition & 0 deletions keep-ui/app/(keep)/alerts/alert-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ export function AlertTable({
<AlertActions
selectedRowIds={selectedRowIds}
alerts={alerts}
table={table}
clearRowSelection={table.resetRowSelection}
setDismissModalAlert={setDismissedModalAlert}
mutateAlerts={mutateAlerts}
Expand Down
17 changes: 13 additions & 4 deletions keep-ui/app/(keep)/alerts/alerts-rules-builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -538,18 +538,27 @@ export const AlertsRulesBuilder = ({
};

const validateAndOpenSaveModal = (celExpression: string) => {
// Use existing validation logic
const celQuery = formatQuery(parseCEL(celExpression), "cel");

// Normalize both strings by:
// 1. Removing all whitespace
// 2. Creating versions with both single and double quotes
const normalizedCelQuery = celQuery.replace(/\s+/g, "");
const normalizedExpression = celExpression.replace(/\s+/g, "");

// Create variants with different quote styles
const celQuerySingleQuotes = normalizedCelQuery.replace(/"/g, "'");
const celQueryDoubleQuotes = normalizedCelQuery.replace(/'/g, '"');

const isValidCEL =
celQuery.replace(/\s+/g, "") === celExpression.replace(/\s+/g, "") ||
normalizedExpression === celQuerySingleQuotes ||
normalizedExpression === celQueryDoubleQuotes ||
celExpression === "";

if (isValidCEL && celExpression.length) {
// If CEL is valid and not empty, set the CEL rules for the preset and open the modal
setPresetCEL?.(celExpression);
setIsModalOpen?.(true);
} else {
// If CEL is invalid or empty, inform the user
alert("You can only save a valid CEL expression.");
setIsValidCEL(isValidCEL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function IncidentAlertsActions({

return (
<>
<div className="flex gap-2 justify-end">
<div className="flex gap-2 justify-end mb-2.5">
<Button
variant="primary"
onClick={() => setIsSplitModalOpen(true)}
Expand Down
30 changes: 18 additions & 12 deletions keep-ui/app/(keep)/incidents/[id]/alerts/incident-alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export default function IncidentAlerts({ incident }: Props) {
// TODO: Load data on server side
// Loading state is true if the data is not loaded and there is no error for smoother loading state on initial load
const isLoading = _alertsLoading || (!alerts && !alertsError);
const isTopologyIncident = incident.incident_type === "topology";

useEffect(() => {
if (alerts && alerts.limit != pagination.pageSize) {
Expand Down Expand Up @@ -169,17 +170,22 @@ export default function IncidentAlerts({ incident }: Props) {
}),
columnHelper.accessor("is_created_by_ai", {
id: "is_created_by_ai",
header: "🔗 Correlation type",
header: "Correlation",
minSize: 50,
cell: (context) => (
<>
{context.getValue() ? (
<div title="Correlated with AI">🤖 AI</div>
) : (
<div title="Correlated manually">👨‍💻 Manually</div>
)}
</>
),
cell: (context) => {
if (isTopologyIncident) {
return <div title="Correlated with topology">🌐 Topology</div>;
}
return (
<>
{context.getValue() ? (
<div title="Correlated with AI">🤖 AI</div>
) : (
<div title="Correlated manually">👨‍💻 Manually</div>
)}
</>
);
},
}),
columnHelper.accessor("lastReceived", {
id: "lastReceived",
Expand Down Expand Up @@ -266,7 +272,7 @@ export default function IncidentAlerts({ incident }: Props) {
selectedFingerprints={selectedFingerprints}
resetAlertsSelection={() => table.resetRowSelection()}
/>
<Card className="p-0 overflow-x-auto">
<Card className="p-0 overflow-x-auto h-[calc(100vh-28rem)]">
<Table className="[&>table]:table-fixed">
<TableHead>
{table.getHeaderGroups().map((headerGroup) => (
Expand Down Expand Up @@ -334,7 +340,7 @@ export default function IncidentAlerts({ incident }: Props) {
{isLoading && (
<IncidentAlertsTableBodySkeleton
table={table}
pageSize={pagination.pageSize}
pageSize={pagination.pageSize - 10}
/>
)}
</Table>
Expand Down
51 changes: 49 additions & 2 deletions keep-ui/app/(keep)/incidents/[id]/chat/incident-chat.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.copilotKitInput {
@apply sticky bottom-0 bg-white !important;
@apply sticky bottom-0 bg-white w-[98%] !important;
@apply flex items-center outline-none rounded-tremor-default px-3 py-2 mx-2 text-tremor-default focus:ring-2 transition duration-100 border shadow-tremor-input focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted dark:shadow-dark-tremor-input focus:dark:border-dark-tremor-brand-subtle focus:dark:ring-dark-tremor-brand-muted bg-tremor-background dark:bg-dark-tremor-background hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis border-tremor-border dark:border-dark-tremor-border placeholder:text-tremor-content dark:placeholder:text-dark-tremor-content !important;
}

Expand All @@ -10,12 +10,59 @@
.copilotKitInput textarea {
height: unset !important;
max-height: unset !important;
margin-bottom: 5px;
}

.copilotKitMessages {
@apply px-4 !important;
@apply h-full flex flex-col !important;
scroll-behavior: smooth;
overscroll-behavior: contain;
}

.copilotKitMessages > div {
@apply flex-1 overflow-y-auto !important;
overscroll-behavior: contain;
will-change: scroll-position;
}

.copilotKitUserMessage {
@apply bg-orange-300 !important;
}

.copilotKitMessages .suggestion {
@apply bg-white text-black scale-100 border-tremor-border border-2 hover:border-tremor-brand hover:text-tremor-brand hover:bg-tremor-brand-muted dark:border-dark-tremor-brand dark:hover:bg-dark-tremor-brand-muted transition !important;
}

.chat-container {
@apply h-[calc(100vh-28rem)] flex flex-col;
scroll-behavior: smooth;
}

.chat-messages {
@apply flex-1 overflow-y-scroll overflow-x-hidden;
scroll-behavior: smooth;
overscroll-behavior: contain;
will-change: scroll-position;
}

[data-message-role="assistant"] {
position: relative;
}

.message-feedback {
opacity: 0;
transition: opacity 0.2s;
}

[data-message-role="assistant"]:hover .message-feedback {
opacity: 1;
}

.message-feedback button {
color: var(--tremor-content);
opacity: 0.5;
transition: opacity 0.2xs;
}
.message-feedback button:hover {
opacity: 1;
}
Loading

0 comments on commit 7b5af45

Please sign in to comment.