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}")