diff --git a/keep-ui/app/workflows/mockworkflows.tsx b/keep-ui/app/workflows/mockworkflows.tsx
index 5aec5cbb1..f39046a31 100644
--- a/keep-ui/app/workflows/mockworkflows.tsx
+++ b/keep-ui/app/workflows/mockworkflows.tsx
@@ -1,5 +1,5 @@
import React, { useState } from "react";
-import { Workflow } from './models';
+import { MockWorkflow, Workflow } from './models';
import { getApiURL } from "../../utils/apiUrl";
import Loading from "../loading";
import { Button } from "@tremor/react";
@@ -11,8 +11,7 @@ import { TiArrowRight } from "react-icons/ti";
-export function WorkflowSteps({ workflow }: { workflow: any }) {
- console.log("workflow===========>", workflow);
+export function WorkflowSteps({ workflow }: { workflow: MockWorkflow}) {
const isActionPresent = !!workflow?.actions?.length;
return (
@@ -54,7 +53,11 @@ export function WorkflowSteps({ workflow }: { workflow: any }) {
);
}
-export default function MockWorkflowCardSection({ mockWorkflows, mockError, mockLoading }) {
+export default function MockWorkflowCardSection({ mockWorkflows, mockError, mockLoading }:{
+ mockWorkflows: MockWorkflow[],
+ mockError: any,
+ mockLoading: boolean | null,
+}) {
const router = useRouter();
const getNameFromId = (id: string) => {
@@ -67,6 +70,11 @@ export default function MockWorkflowCardSection({ mockWorkflows, mockError, mock
console.log("mockWorkflows====>", mockWorkflows);
+ // if mockError is not null, handle the error case
+ if (mockError) {
+ return
Error: {mockError.message}
;
+ }
+
return (
Discover existing workflow templates
@@ -88,9 +96,12 @@ export default function MockWorkflowCardSection({ mockWorkflows, mockError, mock
+ {mockError && Error: {mockError.message || "Something went wrong!"}
}
+ {!mockLoading && !mockError && mockWorkflows.length === 0 && No workflows found
}
+
+ {mockError &&
Error: {mockError.message || "Something went wrong!"}
}
{mockLoading &&
}
- {!mockLoading && mockWorkflows.length === 0 &&
No workflows found
}
{!mockLoading && mockWorkflows.length > 0 && mockWorkflows.map((template: any, index: number) => {
const workflow = template.workflow;
console.log("insise th emao workflwo", workflow);
diff --git a/keep-ui/app/workflows/models.tsx b/keep-ui/app/workflows/models.tsx
index b2cb6502d..ca7795443 100644
--- a/keep-ui/app/workflows/models.tsx
+++ b/keep-ui/app/workflows/models.tsx
@@ -17,6 +17,14 @@ export type Trigger = {
};
+export type WorkflowExecution = {
+ id: string;
+ status: string;
+ started: string;
+ execution_time: number;
+ workflow: Workflow;
+};
+
export type Workflow = {
id: string;
name: string;
@@ -31,4 +39,50 @@ export type Workflow = {
last_updated: string;
workflow_raw: string;
workflow_raw_id: string;
+ last_execution_started?: string;
+ last_executions?: Pick
[]
}
+
+export type MockProvider = {
+ type: string;
+ config: string;
+ with?: {
+ command?: string;
+ timeout?: number;
+ _from?: string;
+ to?: string;
+ subject?: string;
+ html?: string;
+ };
+};
+
+export type MockCondition = {
+ assert: string;
+ name: string;
+ type: string;
+};
+
+export type WorkflowAction = {
+ condition: MockCondition[];
+ name: string;
+ provider: MockProvider;
+};
+
+export type MockStep = {
+ name: string;
+ provider: MockProvider;
+};
+
+export type MockTrigger = {
+ type: string;
+};
+
+export type MockWorkflow = {
+ id: string;
+ description: string;
+ triggers: MockTrigger[];
+ owners: any[]; // Adjust the type if you have more specific information about the owners
+ services: any[]; // Adjust the type if you have more specific information about the services
+ steps: MockStep[];
+ actions: WorkflowAction[];
+};
\ No newline at end of file
diff --git a/keep-ui/app/workflows/workflow-tile.tsx b/keep-ui/app/workflows/workflow-tile.tsx
index 0acb02aa8..0f3b39ec1 100644
--- a/keep-ui/app/workflows/workflow-tile.tsx
+++ b/keep-ui/app/workflows/workflow-tile.tsx
@@ -29,11 +29,13 @@ import { Provider as FullProvider } from "app/providers/providers";
import "./workflow-tile.css";
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/outline";
import AlertTriggerModal from "./workflow-run-with-alert-modal";
-import { parseISO, set } from "date-fns";
+import { parseISO, set, differenceInSeconds } from "date-fns";
import { Chart, CategoryScale, LinearScale, BarElement, Title as ChartTitle, Tooltip, Legend } from 'chart.js';
import { Bar } from 'react-chartjs-2';
import 'chart.js/auto';
import TimeAgo from 'react-timeago';
+import { WorkflowExecution } from "./builder/types";
+
Chart.register(CategoryScale, LinearScale, BarElement, ChartTitle, Tooltip, Legend);
@@ -390,41 +392,6 @@ function WorkflowTile({ workflow }: { workflow: Workflow }) {
)}
- {/*
-
- {WorkflowMenuSection({
- onDelete: handleDeleteClick,
- onRun: handleRunClick,
- onDownload: handleDownloadClick,
- onView: handleViewClick,
- onBuilder: handleBuilderClick,
- workflow,
- })}
-
-
-
-
-
{workflow?.name || 'Unknown'}{'testing the flow with large text'}
-
-
-
-
-
- {workflow?.last_execution_started ? (
-
- ) : null
- // (
- //
- // )
- }
-
-
-
-
*/}
{WorkflowMenuSection({
@@ -450,7 +417,7 @@ function WorkflowTile({ workflow }: { workflow: Workflow }) {
{workflow?.last_execution_started ? (
-
+
) : null
}
@@ -510,7 +477,7 @@ const demoColors = [
'rgba(75, 192, 192, 1)', // Green
'rgba(255, 99, 132, 1)', // Red
]
-const getLabels = (lastExecutions: { status: string, execution_time: number, started: string }[]) => {
+const getLabels = (lastExecutions: Pick[]) => {
if (!lastExecutions || (lastExecutions && lastExecutions.length === 0)) {
return show_real_data ? [] : demoLabels;
}
@@ -520,17 +487,17 @@ const getLabels = (lastExecutions: { status: string, execution_time: number, sta
}
-const getDataValues = (lastExecutions: { status: string, execution_time: number, started: string }[]) => {
+const getDataValues = (lastExecutions: Pick[]) => {
if (!lastExecutions || (lastExecutions && lastExecutions.length === 0)) {
return show_real_data ? [] : demoData;
}
return lastExecutions?.map((workflowExecution) => {
- return workflowExecution?.execution_time
+ return workflowExecution?.execution_time || differenceInSeconds(Date.now(), new Date(workflowExecution?.started));
})
}
-const getBackgroundColors = (lastExecutions: { status: string, execution_time: number, started: string }[]) => {
+const getBackgroundColors = (lastExecutions: Pick[]) => {
if (!lastExecutions || (lastExecutions && lastExecutions.length === 0)) {
return show_real_data ? [] : demoBgColors;
}
@@ -547,7 +514,7 @@ const getBackgroundColors = (lastExecutions: { status: string, execution_time: n
})
}
-const getBorderColors = (lastExecutions: { status: string, execution_time: number, started: string }[]) => {
+const getBorderColors = (lastExecutions: Pick[]) => {
if (!lastExecutions || (lastExecutions && lastExecutions.length === 0)) {
return show_real_data ? [] : demoColors;
}
@@ -565,7 +532,7 @@ const getBorderColors = (lastExecutions: { status: string, execution_time: numbe
})
}
-const WorkflowGraph = ({ workflow }) => {
+const WorkflowGraph = ({ workflow }:{workflow: Workflow}) => {
const lastExecutions = useMemo(() => {
const reversedExecutions = workflow?.last_executions?.slice(0, 15) || [];
return reversedExecutions.reverse();
@@ -587,8 +554,8 @@ const WorkflowGraph = ({ workflow }) => {
bottom: 0,
left: 0,
},
- barPercentage: 0.6, // Adjust this value to control bar width
- // categoryPercentage: 0.8, // Adjust this value to control space between bars
+ barPercentage: 1, // Adjust this value to control bar width
+ categoryPercentage: 0.5, // Adjust this value to control space between bars
},
],
};
@@ -627,8 +594,6 @@ const WorkflowGraph = ({ workflow }) => {
},
responsive: true,
maintainAspectRatio: false,
- barPercentage: 0.7, // Adjust this value to control bar width
- categoryPercentage: 0.8, // Adjust this value to control space between bars
};
const status = workflow?.last_execution_status?.toLowerCase() || null;
@@ -664,7 +629,7 @@ const WorkflowGraph = ({ workflow }) => {
No data available
) : (
-
+
)}
@@ -674,5 +639,4 @@ const WorkflowGraph = ({ workflow }) => {
};
-
export default WorkflowTile;
diff --git a/keep-ui/app/workflows/workflows.client.tsx b/keep-ui/app/workflows/workflows.client.tsx
index 6a1da53ab..112333e0a 100644
--- a/keep-ui/app/workflows/workflows.client.tsx
+++ b/keep-ui/app/workflows/workflows.client.tsx
@@ -10,7 +10,7 @@ import {
} from "@heroicons/react/24/outline";
import { useSession } from "next-auth/react";
import { fetcher } from "../../utils/fetcher";
-import { Workflow } from "./models";
+import { Workflow, MockWorkflow } from "./models";
import { getApiURL } from "../../utils/apiUrl";
import Loading from "../loading";
import React from "react";
@@ -36,7 +36,7 @@ export default function WorkflowsPage() {
(url: string) => fetcher(url, session?.accessToken!)
);
- const { data: mockWorkflows, error:mockError, isLoading: mockLoading } = useSWR
[]>(
+ const { data: mockWorkflows, error:mockError, isLoading: mockLoading } = useSWR(
status === "authenticated" ? `${apiUrl}/workflows/random-templates` : null,
(url: string) => fetcher(url, session?.accessToken!)
);
@@ -262,7 +262,7 @@ export default function WorkflowsPage() {
)}
diff --git a/keep-ui/package-lock.json b/keep-ui/package-lock.json
index fe1be4d47..b6940ee24 100644
--- a/keep-ui/package-lock.json
+++ b/keep-ui/package-lock.json
@@ -383,6 +383,7 @@
"@types/react-datepicker": "^6.0.2",
"@types/react-grid-layout": "^1.3.5",
"@types/react-modal": "^3.16.0",
+ "@types/react-timeago": "^4.1.7",
"@types/uuid": "^9.0.1"
}
},
@@ -4149,6 +4150,15 @@
"react-select": "*"
}
},
+ "node_modules/@types/react-timeago": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-timeago/-/react-timeago-4.1.7.tgz",
+ "integrity": "sha512-ogD4Ror/hDG+pQggCX+TgPgJ8W2jeeUxsgNU485Qpm0Ma+E2TND2EJuKwK5+sxlkDXDEgsHradO0zWBkTgLzNg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-transition-group": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
diff --git a/keep-ui/package.json b/keep-ui/package.json
index f0ac24375..beef7c69b 100644
--- a/keep-ui/package.json
+++ b/keep-ui/package.json
@@ -384,6 +384,7 @@
"@types/react-datepicker": "^6.0.2",
"@types/react-grid-layout": "^1.3.5",
"@types/react-modal": "^3.16.0",
+ "@types/react-timeago": "^4.1.7",
"@types/uuid": "^9.0.1"
},
"author": "",
diff --git a/keep/workflowmanager/workflowstore.py b/keep/workflowmanager/workflowstore.py
index 3709b3c88..4b8c3ae9c 100644
--- a/keep/workflowmanager/workflowstore.py
+++ b/keep/workflowmanager/workflowstore.py
@@ -255,7 +255,8 @@ def get_random_workflow_templates(self, tenant_id: str, workflows_dir: str, limi
if "workflow" in workflow_yaml:
workflow_yaml['name'] = workflow_yaml['workflow']['id']
workflow_yaml['workflow_raw'] = yaml.dump(workflow_yaml)
- workflows.append(workflow_yaml)
+ workflow_yaml['workflow_raw_id'] = yaml.dump(workflow_yaml)
+ workflows.append(workflow_yaml) = workflow_yaml['workflow']['id']
count += 1
self.logger.info(f"Workflow from {file} fetched successfully {workflow_yaml}")