Skip to content

Commit

Permalink
feat: add the option to run workflow manually but with alert payload (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
shahargl authored Sep 15, 2024
1 parent c9dc74a commit 5ac65ca
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 28 deletions.
11 changes: 7 additions & 4 deletions keep-ui/app/workflows/builder/ReactFlowBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ const nodeTypes = { custom: CustomNode as any };
const edgeTypes: EdgeTypesType = { "custom-edge": CustomEdge as React.ComponentType<any> };

const ReactFlowBuilder = ({
providers,
installedProviders,
toolboxConfiguration,
definition,
onDefinitionChange,
validatorConfiguration
}: {
providers: Provider[] | undefined | null;
installedProviders: Provider[] | undefined | null;
toolboxConfiguration: Record<string, any>;
definition: any;
Expand All @@ -29,7 +31,7 @@ const ReactFlowBuilder = ({
};
onDefinitionChange:(def: Definition) => void;
}) => {

const {
nodes,
edges,
Expand Down Expand Up @@ -60,13 +62,14 @@ const ReactFlowBuilder = ({
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
fitView
>
>
<Controls orientation="horizontal"/>
<Background/>
</ReactFlow>
)}
<ReactFlowEditor
providers={installedProviders}
<ReactFlowEditor
providers={providers}
installedProviders={installedProviders}
onDefinitionChange= {onDefinitionChange}
validatorConfiguration= {validatorConfiguration}
/>
Expand Down
5 changes: 3 additions & 2 deletions keep-ui/app/workflows/builder/ReactFlowEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import debounce from "lodash.debounce";

const ReactFlowEditor = ({
providers,
installedProviders,
validatorConfiguration,
onDefinitionChange
}: {
providers: Provider[] | undefined | null;
installedProviders: Provider[] | undefined | null;
validatorConfiguration: {
step: (step: V2Step, parent?: V2Step, defnition?: ReactFlowDefinition) => boolean;
root: (def: Definition) => boolean;
Expand Down Expand Up @@ -114,7 +116,7 @@ const ReactFlowEditor = ({
<div style={{ width: "300px" }}>
<GlobalEditorV2 synced={synced} />
{!selectedNode?.includes('empty') && !isTrigger && <Divider ref={stepEditorRef} />}
{!selectedNode?.includes('empty') && !isTrigger && <StepEditorV2 installedProviders={providers} setSynced={setSynced} />}
{!selectedNode?.includes('empty') && !isTrigger && <StepEditorV2 providers={providers} installedProviders={installedProviders} setSynced={setSynced} />}
</div>
</div>
</div>
Expand All @@ -124,4 +126,3 @@ const ReactFlowEditor = ({
};

export default ReactFlowEditor;

1 change: 1 addition & 0 deletions keep-ui/app/workflows/builder/builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ function Builder({
<div className="h-[94%]">
<ReactFlowProvider>
<ReactFlowBuilder
providers={providers}
installedProviders={installedProviders}
definition={definition}
validatorConfiguration={ValidatorConfigurationV2}
Expand Down
15 changes: 12 additions & 3 deletions keep-ui/app/workflows/builder/editors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export function GlobalEditorV2({synced}: {synced: boolean}) {
interface keepEditorProps {
properties: V2Properties;
updateProperty: ((key: string, value: any) => void);
providers?: Provider[] | null | undefined;
installedProviders?: Provider[] | null | undefined;
providerType?: string;
type?: string;
Expand All @@ -64,6 +65,7 @@ function KeepStepEditor({
properties,
updateProperty,
installedProviders,
providers,
providerType,
type,
}: keepEditorProps) {
Expand All @@ -86,6 +88,9 @@ function KeepStepEditor({
const installedProviderByType = installedProviders?.filter(
(p) => p.type === providerType
);
const isThisProviderNeedsInstallation = providers?.some(
(p) => p.type === providerType && p.config && Object.keys(p.config).length > 0
) ?? false;

const DynamicIcon = (props: any) => (
<svg
Expand Down Expand Up @@ -141,12 +146,13 @@ function KeepStepEditor({
error={
providerConfig !== "" &&
providerConfig !== undefined &&
isThisProviderNeedsInstallation &&
installedProviderByType?.find(
(p) => p.details?.name === providerConfig
) === undefined
}
errorMessage={`${
providerConfig &&
providerConfig && isThisProviderNeedsInstallation &&
installedProviderByType?.find(
(p) => p.details?.name === providerConfig
) === undefined
Expand Down Expand Up @@ -412,14 +418,16 @@ function WorkflowEditorV2({


export function StepEditorV2({
providers,
installedProviders,
setSynced
}: {
providers: Provider[] | undefined | null;
installedProviders?: Provider[] | undefined | null;
setSynced: (sync:boolean) => void;
}) {
const [formData, setFormData] = useState<{ name?: string; properties?: V2Properties, type?:string }>({});
const {
const {
selectedNode,
updateSelectedNodeData,
setOpneGlobalEditor,
Expand Down Expand Up @@ -475,6 +483,7 @@ export function StepEditorV2({
<KeepStepEditor
properties={formData.properties}
updateProperty={handlePropertyChange}
providers={providers}
installedProviders={installedProviders}
providerType={providerType}
type={formData.type}
Expand Down Expand Up @@ -503,4 +512,4 @@ export function StepEditorV2({
</button>
</EditorLayout>
);
}
}
11 changes: 6 additions & 5 deletions keep-ui/app/workflows/workflow-run-with-alert-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,17 @@ export default function AlertTriggerModal({
return (
<Modal isOpen={isOpen} onClose={onClose} title="Build Alert Payload">
<form onSubmit={handleSubmit}>
<Card className="mb-4">
<Text className="mb-2">Fields Defined As Workflow Filters</Text>
{Array.isArray(staticFields) &&
staticFields.map((field, index) => (
{Array.isArray(staticFields) && staticFields.length > 0 && (
<Card className="mb-4">
<Text className="mb-2">Fields Defined As Workflow Filters</Text>
{staticFields.map((field, index) => (
<div key={field.key} className="flex gap-2 mb-2">
<TextInput placeholder="Key" value={field.key} disabled />
<TextInput placeholder="Value" value={field.value} disabled />
</div>
))}
</Card>
</Card>
)}

<Card className="mb-4">
<Text className="mb-2">
Expand Down
41 changes: 27 additions & 14 deletions keep-ui/utils/hooks/useWorkflowRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { useState } from "react";
import { useSession } from "next-auth/react";
import { getApiURL } from "utils/apiUrl";
import { useRouter } from "next/navigation";
import { useProviders } from "./useProviders";
import { Filter, Workflow } from "app/workflows/models";
import { Provider } from "app/providers/providers";

interface ProvidersData {
providers: { [key: string]: { providers: Provider[] } };
}


export const useWorkflowRun = (workflow: Workflow) => {

Expand All @@ -15,14 +22,23 @@ export const useWorkflowRun = (workflow: Workflow) => {
const [alertFilters, setAlertFilters] = useState<Filter[]>([]);
const [alertDependencies, setAlertDependencies] = useState<string[]>([]);

const { data: providersData = { providers: {} } as ProvidersData } = useProviders();
const providers = providersData.providers;


const apiUrl = getApiURL();

if (!workflow) {
return {};
}
const allProvidersInstalled = workflow?.providers?.every(
(provider) => provider.installed
);

const notInstalledProviders = workflow?.providers?.filter((workflowProvider) =>
!workflowProvider.installed && Object.values(providers || {}).some(provider =>
provider.type === workflowProvider.type && (provider.config && Object.keys(provider.config).length > 0)
)
).map(provider => provider.type);

const allProvidersInstalled = notInstalledProviders.length === 0;

// Check if there is a manual trigger
const hasManualTrigger = workflow?.triggers?.some(
Expand All @@ -36,7 +52,7 @@ export const useWorkflowRun = (workflow: Workflow) => {
const isWorkflowDisabled = !!workflow?.disabled

const getDisabledTooltip = () => {
if (!allProvidersInstalled) return "Not all providers are installed.";
if (!allProvidersInstalled) return `Not all providers are installed: ${notInstalledProviders.join(", ")}`;
if (!hasManualTrigger) return "No manual trigger available.";
if(isWorkflowDisabled) {
return "Workflow is Disabled";
Expand Down Expand Up @@ -107,28 +123,25 @@ export const useWorkflowRun = (workflow: Workflow) => {
if (!workflow) {
return;
}
const hasAlertTrigger = workflow?.triggers?.some(
(trigger) => trigger.type === "alert"
);
const dependencies = extractAlertDependencies(workflow?.workflow_raw);
const hasDependencies = dependencies.length > 0;

// if it needs alert payload, than open the modal
if (hasAlertTrigger) {
// if it has dependencies, open the modal
if (hasDependencies) {
setAlertDependencies(dependencies);
// extract the filters
// TODO: support more than one trigger
for (const trigger of workflow?.triggers) {
// at least one trigger is alert, o/w hasAlertTrigger was false
for (const trigger of workflow?.triggers || []) {
if (trigger.type === "alert") {
const staticAlertFilters = trigger.filters || [];
setAlertFilters(staticAlertFilters);
break;
}
}
const dependencies = extractAlertDependencies(workflow?.workflow_raw);
setAlertDependencies(dependencies);
setIsAlertTriggerModalOpen(true);
return;
}
// else, manual trigger, just run it
// else, no dependencies, just run it
else {
runWorkflow({});
}
Expand Down

0 comments on commit 5ac65ca

Please sign in to comment.