Skip to content

Commit

Permalink
refactor: remove heavy frontend deps (#2785)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kiryous authored Dec 9, 2024
1 parent 35fb897 commit 4612b40
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 139 deletions.
5 changes: 2 additions & 3 deletions keep-ui/app/(keep)/alerts/alert-table-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { AlertDto } from "./models";
import { Accordion, AccordionBody, AccordionHeader, Icon } from "@tremor/react";
import AlertTableCheckbox from "./alert-table-checkbox";
import AlertName from "./alert-name";
import { getAlertLastReceieved } from "utils/helpers";
import Image from "next/image";
import AlertAssignee from "./alert-assignee";
import AlertExtraPayload from "./alert-extra-payload";
Expand All @@ -23,7 +22,7 @@ import {
} from "react-icons/md";
import { AlertSeverityBorder } from "./alert-severity-border";
import { getStatusIcon, getStatusColor } from "@/shared/lib/status-utils";

import TimeAgo from "react-timeago";
import { useConfig } from "utils/hooks/useConfig";

export const DEFAULT_COLS = [
Expand Down Expand Up @@ -338,7 +337,7 @@ export const useAlertTableCols = (
minSize: 100,
cell: (context) => (
<span title={context.getValue().toISOString()}>
{getAlertLastReceieved(context.getValue())}
<TimeAgo date={context.getValue().toISOString()} />
</span>
),
}),
Expand Down
8 changes: 2 additions & 6 deletions keep-ui/app/(keep)/incidents/[id]/alerts/incident-alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ import {
TableRow,
} from "@tremor/react";
import Image from "next/image";
import AlertSeverity from "@/app/(keep)/alerts/alert-severity";
import { AlertDto } from "@/app/(keep)/alerts/models";
import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";
import { getAlertLastReceieved } from "utils/helpers";
import {
useIncidentAlerts,
usePollIncidentAlerts,
Expand All @@ -37,7 +35,7 @@ import { TablePagination } from "@/shared/ui";
import { AlertSeverityBorder } from "@/app/(keep)/alerts/alert-severity-border";
import { getStatusIcon } from "@/shared/lib/status-utils";
import { getStatusColor } from "@/shared/lib/status-utils";

import TimeAgo from "react-timeago";
interface Props {
incident: IncidentDto;
}
Expand Down Expand Up @@ -180,9 +178,7 @@ export default function IncidentAlerts({ incident }: Props) {
id: "lastReceived",
header: "Last Event Time",
minSize: 100,
cell: (context) => (
<span>{getAlertLastReceieved(context.getValue())}</span>
),
cell: (context) => <TimeAgo date={context.getValue().toISOString()} />,
}),
columnHelper.accessor("source", {
id: "source",
Expand Down
7 changes: 4 additions & 3 deletions keep-ui/app/(keep)/providers/provider-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import {
MapIcon,
Cog6ToothIcon,
} from "@heroicons/react/20/solid";
import "./provider-tile.css";
import moment from "moment";
import ImageWithFallback from "@/components/ImageWithFallback";
import { FaCode } from "react-icons/fa";
import TimeAgo from "react-timeago";
import "./provider-tile.css";

interface Props {
provider: Provider;
Expand Down Expand Up @@ -231,7 +231,8 @@ export default function ProviderTile({ provider, onClick }: Props) {
)}
{provider.last_alert_received ? (
<Text>
Last alert: {moment(provider.last_alert_received).fromNow()}
Last alert:{" "}
<TimeAgo date={provider.last_alert_received + "Z"} />
</Text>
) : (
<p></p>
Expand Down
18 changes: 1 addition & 17 deletions keep-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions keep-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"eslint-import-resolver-node": "^0.3.7",
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-module-utils": "^2.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
Expand All @@ -54,7 +53,6 @@
"js-yaml": "^4.1.0",
"lodash.debounce": "^4.0.8",
"lucide-react": "^0.460.0",
"moment": "^2.29.4",
"next": "^14.2.13",
"next-auth": "^5.0.0-beta.25",
"openai": "^4.73.0",
Expand Down Expand Up @@ -124,9 +122,9 @@
"@types/uuid": "^9.0.1",
"@typescript-eslint/parser": "^5.62.0",
"clsx": "^2.1.1",
"elkjs": "^0.9.3",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.31.0",
"prettier": "^3.3.3",
"prettier-eslint": "^16.3.0",
"typescript": "^5.6.2"
Expand Down
7 changes: 0 additions & 7 deletions keep-ui/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { toast } from "react-toastify";
import { Provider } from "@/app/(keep)/providers/providers";
import moment from "moment";
import { twMerge } from "tailwind-merge";
import { clsx, type ClassValue } from "clsx";

Expand Down Expand Up @@ -38,10 +35,6 @@ export function toDateObjectWithFallback(date: string | Date) {
return new Date();
}

export function getAlertLastReceieved(lastRecievedFromAlert: Date) {
return moment(lastRecievedFromAlert).fromNow();
}

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Expand Down
179 changes: 79 additions & 100 deletions keep-ui/utils/hooks/useWorkflowInitialization.ts
Original file line number Diff line number Diff line change
@@ -1,99 +1,77 @@
import { useEffect, useState, useCallback } from "react";
import { Edge, useReactFlow } from "@xyflow/react";
import useStore, {
Definition,
ReactFlowDefinition,
V2Step,
} from "@/app/(keep)/workflows/builder/builder-store";
import { FlowNode } from "@/app/(keep)/workflows/builder/builder-store";
import { Provider } from "@/app/(keep)/providers/providers";
import ELK from "elkjs/lib/elk.bundled.js";
import dagre, { graphlib } from "@dagrejs/dagre";
import { processWorkflowV2, getTriggerStep } from "utils/reactFlow";

const layoutOptions = {
"elk.nodeLabels.placement": "INSIDE V_CENTER H_BOTTOM",
"elk.algorithm": "layered",
"elk.direction": "BOTTOM",
"org.eclipse.elk.layered.layering.strategy": "INTERACTIVE",
"elk.edgeRouting": "ORTHOGONAL",
"elk.layered.unnecessaryBendpoints": false,
"elk.layered.spacing.edgeNodeBetweenLayers": "70",
"org.eclipse.elk.layered.nodePlacement.bk.fixedAlignment": "BALANCED",
"org.eclipse.elk.layered.cycleBreaking.strategy": "DEPTH_FIRST",
"elk.insideSelfLoops.activate": true,
separateConnectedComponents: "false",
"spacing.componentComponent": "80",
spacing: "80",
"elk.spacing.nodeNodeBetweenLayers": "80",
"elk.spacing.nodeNode": "120",
"elk.layered.spacing.nodeNodeBetweenLayers": "80",
portConstraints: "FIXED_ORDER",
"nodeSize.constraints": "[MINIMUM_SIZE]",
"elk.alignment": "CENTER",
"elk.spacing.edgeNodeBetweenLayers": "70.0",
"org.eclipse.elk.layoutAncestors": "true",
"elk.layered.nodePlacement.strategy": "BRANDES_KOEPF",
"elk.layered.nodePlacement.outerSpacing": "30",
"elk.layered.nodePlacement.outerPadding": "30",
"elk.layered.edgeRouting.orthogonal": true,

// Avoid bending towards nodes
"elk.layered.allowEdgeLabelOverlap": false,
"elk.layered.edgeRouting.avoidNodes": true,
"elk.layered.edgeRouting.avoidEdges": true,
"elk.layered.nodePlacement.nodeNodeOverlapAllowed": false,
"elk.layered.consistentLevelSpacing": true,
};

const getLayoutedElements = (
nodes: FlowNode[],
edges: Edge[],
options = {}
) => {
// @ts-ignore
const isHorizontal = options?.["elk.direction"] === "RIGHT";
const elk = new ELK();

const graph = {
id: "root",
layoutOptions: options,
children: nodes.map((node) => {
const type = node?.data?.type
?.replace("step-", "")
?.replace("action-", "")
?.replace("condition-", "")
?.replace("__end", "");
return {
...node,
// Adjust the target and source handle positions based on the layout
// direction.
targetPosition: isHorizontal ? "left" : "top",
sourcePosition: isHorizontal ? "right" : "bottom",

// Hardcode a width and height for elk to use when layouting.
width: ["start", "end"].includes(type) ? 80 : 280,
height: 80,
};
}),
edges: edges,
};
const dagreGraph = new graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));

// Set graph direction and spacing
dagreGraph.setGraph({
rankdir: isHorizontal ? "LR" : "TB",
nodesep: 80,
ranksep: 80,
edgesep: 80,
});

// Add nodes to dagre graph
nodes.forEach((node) => {
const type = node?.data?.type
?.replace("step-", "")
?.replace("action-", "")
?.replace("condition-", "")
?.replace("__end", "");

const width = ["start", "end"].includes(type) ? 80 : 280;
const height = 80;

dagreGraph.setNode(node.id, { width, height });
});

// Add edges to dagre graph
edges.forEach((edge) => {
dagreGraph.setEdge(edge.source, edge.target);
});

// Run the layout
dagre.layout(dagreGraph);

// Get the positioned nodes and edges
const layoutedNodes = nodes.map((node) => {
const dagreNode = dagreGraph.node(node.id);
return {
...node,
targetPosition: isHorizontal ? "left" : "top",
sourcePosition: isHorizontal ? "right" : "bottom",
style: {
...node.style,
width: dagreNode.width as number,
height: dagreNode.height as number,
},
// Dagre provides positions with the center of the node as origin
position: {
x: dagreNode.x - dagreNode.width / 2,
y: dagreNode.y - dagreNode.height / 2,
},
};
});

return (
elk
// @ts-ignore
.layout(graph)
.then((layoutedGraph) => ({
nodes: layoutedGraph?.children?.map((node) => ({
...node,
// React Flow expects a position property on the node instead of `x`
// and `y` fields.
position: { x: node.x, y: node.y },
})),

edges: layoutedGraph.edges,
}))
.catch(console.error)
);
return {
nodes: layoutedNodes,
edges,
};
};

const useWorkflowInitialization = (
Expand Down Expand Up @@ -145,31 +123,32 @@ const useWorkflowInitialization = (
initialNodes?: FlowNode[];
initialEdges?: Edge[];
}) => {
const opts = { ...layoutOptions, "elk.direction": direction };
const opts = { "elk.direction": direction };
const ns = useInitialNodes ? initialNodes : nodes;
const es = useInitialNodes ? initialEdges : edges;

// @ts-ignore
getLayoutedElements(ns, es, opts).then(
const { nodes: _layoutedNodes, edges: _layoutedEdges } =
// @ts-ignore
({ nodes: layoutedNodes, edges: layoutedEdges }) => {
layoutedEdges = layoutedEdges.map((edge: Edge) => {
return {
...edge,
animated: !!edge?.target?.includes("empty"),
data: { ...edge.data, isLayouted: true },
};
});
layoutedNodes.forEach((node: FlowNode) => {
node.data = { ...node.data, isLayouted: true };
});
setNodes(layoutedNodes);
setEdges(layoutedEdges);
setIsLayouted(true);
setFinalEdges(layoutedEdges);
setFinalNodes(layoutedNodes);
}
);
getLayoutedElements(ns, es, opts);
const layoutedEdges = _layoutedEdges.map((edge: Edge) => {
return {
...edge,
animated: !!edge?.target?.includes("empty"),
data: { ...edge.data, isLayouted: true },
};
});
// @ts-ignore
const layoutedNodes = _layoutedNodes.map((node: FlowNode) => {
return {
...node,
data: { ...node.data, isLayouted: true },
};
});
setNodes(layoutedNodes);
setEdges(layoutedEdges);
setIsLayouted(true);
setFinalEdges(layoutedEdges);
setFinalNodes(layoutedNodes);
},
[nodes, edges]
);
Expand Down

0 comments on commit 4612b40

Please sign in to comment.