Skip to content

Commit

Permalink
feat(dashboard): Open step template drawer on Add Step
Browse files Browse the repository at this point in the history
  • Loading branch information
desiprisg committed Jan 9, 2025
1 parent 01b973c commit 08ea66e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { ChannelTypeEnum, UpdateWorkflowDto, WorkflowPreferences, WorkflowResponseDto } from '@novu/shared';
import { ChannelTypeEnum, WorkflowPreferences, WorkflowResponseDto } from '@novu/shared';
import { motion } from 'motion/react';
import { useMemo } from 'react';
import { useForm, useWatch } from 'react-hook-form';
Expand All @@ -9,6 +9,7 @@ import { z } from 'zod';

import { SidebarContent, SidebarHeader } from '@/components/side-navigation/sidebar';
import { UserPreferencesFormSchema } from '@/components/workflow-editor/schema';
import { UpdateWorkflowFn } from '@/components/workflow-editor/workflow-provider';
import { useTelemetry } from '@/hooks/use-telemetry';
import { STEP_TYPE_TO_COLOR } from '@/utils/color';
import { StepTypeEnum, WorkflowOriginEnum } from '@/utils/enums';
Expand All @@ -28,7 +29,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '../primitives/tooltip';

type ConfigureWorkflowFormProps = {
workflow: WorkflowResponseDto;
update: (data: UpdateWorkflowDto) => void;
update: UpdateWorkflowFn;
};

const CHANNEL_LABELS_LOOKUP: Record<`${ChannelTypeEnum}` | 'all', string> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ToastIcon } from '@/components/primitives/sonner';
import { showToast } from '@/components/primitives/sonner-helpers';
import { SidebarContent, SidebarHeader } from '@/components/side-navigation/sidebar';
import { MAX_DESCRIPTION_LENGTH, workflowSchema } from '@/components/workflow-editor/schema';
import { UpdateWorkflowFn } from '@/components/workflow-editor/workflow-provider';
import { useEnvironment } from '@/context/environment/hooks';
import { useDeleteWorkflow } from '@/hooks/use-delete-workflow';
import { useFormAutosave } from '@/hooks/use-form-autosave';
Expand All @@ -26,7 +27,7 @@ import { useTags } from '@/hooks/use-tags';
import { ROUTES } from '@/utils/routes';
import { cn } from '@/utils/ui';
import { zodResolver } from '@hookform/resolvers/zod';
import { UpdateWorkflowDto, WorkflowOriginEnum, WorkflowResponseDto } from '@novu/shared';
import { WorkflowOriginEnum, WorkflowResponseDto } from '@novu/shared';
import {
RiArrowRightSLine,
RiCodeSSlashLine,
Expand Down Expand Up @@ -55,7 +56,7 @@ import { usePromotionalBanner } from '../promotional/coming-soon-banner';

type ConfigureWorkflowFormProps = {
workflow: WorkflowResponseDto;
update: (data: UpdateWorkflowDto) => void;
update: UpdateWorkflowFn;
};

const toastOptions: ExternalToast = {
Expand Down
34 changes: 26 additions & 8 deletions apps/dashboard/src/components/workflow-editor/edges.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { BaseEdge, Edge, EdgeLabelRenderer, EdgeProps, getBezierPath } from '@xyflow/react';
import { AddStepMenu } from './add-step-menu';
import { createStep } from '@/components/workflow-editor/step-utils';
import { useWorkflow } from '@/components/workflow-editor/workflow-provider';
import { TEMPLATE_CONFIGURABLE_STEP_TYPES } from '@/utils/constants';
import { buildRoute, ROUTES } from '@/utils/routes';
import { WorkflowOriginEnum } from '@novu/shared';
import { createStep } from '@/components/workflow-editor/step-utils';
import { BaseEdge, Edge, EdgeLabelRenderer, EdgeProps, getBezierPath } from '@xyflow/react';
import { useNavigate } from 'react-router-dom';
import { AddStepMenu } from './add-step-menu';

export type AddNodeEdgeType = Edge<{ isLast: boolean; addStepIndex: number }>;

Expand All @@ -18,6 +21,7 @@ export function AddNodeEdge({
markerEnd,
}: EdgeProps<AddNodeEdgeType>) {
const { workflow, update } = useWorkflow();
const navigate = useNavigate();
const isReadOnly = workflow?.origin === WorkflowOriginEnum.EXTERNAL;

const [edgePath, labelX, labelY] = getBezierPath({
Expand Down Expand Up @@ -47,7 +51,7 @@ export function AddNodeEdge({
>
{!isReadOnly && (
<AddStepMenu
onMenuItemClick={(stepType) => {
onMenuItemClick={async (stepType) => {
if (workflow) {
const indexToAdd = data.addStepIndex;

Expand All @@ -59,10 +63,24 @@ export function AddNodeEdge({
...workflow.steps.slice(indexToAdd),
];

update({
...workflow,
steps: updatedSteps,
});
update(
{
...workflow,
steps: updatedSteps,
},
{
onSuccess: (data) => {
if (TEMPLATE_CONFIGURABLE_STEP_TYPES.includes(stepType)) {
navigate(
buildRoute(ROUTES.EDIT_STEP_TEMPLATE, {
workflowSlug: workflow.slug,
stepSlug: data.steps[indexToAdd].slug,
})
);
}
},
}
);
}
}}
/>
Expand Down
24 changes: 22 additions & 2 deletions apps/dashboard/src/components/workflow-editor/nodes.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { createStep } from '@/components/workflow-editor/step-utils';
import { useWorkflow } from '@/components/workflow-editor/workflow-provider';
import { STEP_TYPE_TO_COLOR } from '@/utils/color';
import { TEMPLATE_CONFIGURABLE_STEP_TYPES } from '@/utils/constants';
import { StepTypeEnum } from '@/utils/enums';
import { buildRoute, ROUTES } from '@/utils/routes';
import { getWorkflowIdFromSlug, STEP_DIVIDER } from '@/utils/step';
import { cn } from '@/utils/ui';
import { WorkflowOriginEnum } from '@novu/shared';
import { Node as FlowNode, Handle, NodeProps, Position } from '@xyflow/react';
import { steps } from 'motion/react';
import { ComponentProps } from 'react';
import { RiPlayCircleLine } from 'react-icons/ri';
import { Link, useParams } from 'react-router-dom';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { STEP_TYPE_TO_ICON } from '../icons/utils';
import { AddStepMenu } from './add-step-menu';
import { Node, NodeBody, NodeError, NodeHeader, NodeIcon, NodeName } from './base-node';
Expand Down Expand Up @@ -242,6 +244,7 @@ export const CustomNode = (props: NodeProps<NodeType>) => {

export const AddNode = (_props: NodeProps<NodeType>) => {
const { workflow, update } = useWorkflow();
const navigate = useNavigate();
if (!workflow) {
return null;
}
Expand All @@ -257,7 +260,24 @@ export const AddNode = (_props: NodeProps<NodeType>) => {
<AddStepMenu
visible
onMenuItemClick={(stepType) => {
update({ ...workflow, steps: [...workflow.steps, createStep(stepType)] });
update(
{
...workflow,
steps: [...workflow.steps, createStep(stepType)],
},
{
onSuccess: (data) => {
if (TEMPLATE_CONFIGURABLE_STEP_TYPES.includes(stepType)) {
navigate(
buildRoute(ROUTES.EDIT_STEP_TEMPLATE, {
workflowSlug: workflow.slug,
stepSlug: data.steps[steps.length - 1].slug,
})
);
}
},
}
);
}}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
StepResponseDto,
StepTypeEnum,
StepUpdateDto,
UpdateWorkflowDto,
WorkflowOriginEnum,
WorkflowResponseDto,
} from '@novu/shared';
Expand Down Expand Up @@ -47,11 +46,12 @@ import { ConfigurePushStepPreview } from '@/components/workflow-editor/steps/pus
import { SaveFormContext } from '@/components/workflow-editor/steps/save-form-context';
import { SdkBanner } from '@/components/workflow-editor/steps/sdk-banner';
import { ConfigureSmsStepPreview } from '@/components/workflow-editor/steps/sms/configure-sms-step-preview';
import { UpdateWorkflowFn } from '@/components/workflow-editor/workflow-provider';
import { useFeatureFlag } from '@/hooks/use-feature-flag';
import { useFormAutosave } from '@/hooks/use-form-autosave';
import { INLINE_CONFIGURABLE_STEP_TYPES, STEP_TYPE_LABELS, TEMPLATE_CONFIGURABLE_STEP_TYPES } from '@/utils/constants';
import { buildRoute, ROUTES } from '@/utils/routes';
import { CompactButton } from '../../primitives/button-compact';
import { useFeatureFlag } from '@/hooks/use-feature-flag';

const STEP_TYPE_TO_INLINE_CONTROL_VALUES: Record<StepTypeEnum, () => React.JSX.Element | null> = {
[StepTypeEnum.DELAY]: DelayControlValues,
Expand Down Expand Up @@ -81,7 +81,7 @@ type ConfigureStepFormProps = {
workflow: WorkflowResponseDto;
environment: IEnvironment;
step: StepResponseDto;
update: (data: UpdateWorkflowDto) => void;
update: UpdateWorkflowFn;
};

export const ConfigureStepForm = (props: ConfigureStepFormProps) => {
Expand All @@ -108,8 +108,19 @@ export const ConfigureStepForm = (props: ConfigureStepFormProps) => {
const isInlineConfigurableStepWithCustomControls = isInlineConfigurableStep && hasCustomControls;

const onDeleteStep = () => {
update({ ...workflow, steps: workflow.steps.filter((s) => s._id !== step._id) });
navigate(buildRoute(ROUTES.EDIT_WORKFLOW, { environmentSlug: environment.slug!, workflowSlug: workflow.slug }));
update(
{
...workflow,
steps: workflow.steps.filter((s) => s._id !== step._id),
},
{
onSuccess: () => {
navigate(
buildRoute(ROUTES.EDIT_WORKFLOW, { environmentSlug: environment.slug!, workflowSlug: workflow.slug })
);
},
}
);
};

const registerInlineControlValues = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
type StepResponseDto,
StepTypeEnum,
StepUpdateDto,
UpdateWorkflowDto,
type WorkflowResponseDto,
} from '@novu/shared';
import { type StepResponseDto, StepTypeEnum, StepUpdateDto, type WorkflowResponseDto } from '@novu/shared';
import { useCallback, useEffect, useMemo } from 'react';
import { useForm } from 'react-hook-form';

Expand All @@ -18,6 +12,7 @@ import { InAppTabs } from '@/components/workflow-editor/steps/in-app/in-app-tabs
import { PushTabs } from '@/components/workflow-editor/steps/push/push-tabs';
import { SaveFormContext } from '@/components/workflow-editor/steps/save-form-context';
import { SmsTabs } from '@/components/workflow-editor/steps/sms/sms-tabs';
import { UpdateWorkflowFn } from '@/components/workflow-editor/workflow-provider';
import { useDataRef } from '@/hooks/use-data-ref';
import { useFormAutosave } from '@/hooks/use-form-autosave';

Expand All @@ -39,7 +34,7 @@ export type StepEditorProps = {
};

type ConfigureStepTemplateFormProps = StepEditorProps & {
update: (data: UpdateWorkflowDto) => void;
update: UpdateWorkflowFn;
};

export const ConfigureStepTemplateForm = (props: ConfigureStepTemplateFormProps) => {
Expand Down
45 changes: 27 additions & 18 deletions apps/dashboard/src/components/workflow-editor/workflow-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,39 @@ import { PatchWorkflowDto, StepResponseDto, UpdateWorkflowDto, WorkflowResponseD
import { createContext, ReactNode, useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
import { useBlocker, useNavigate, useParams } from 'react-router-dom';

import { useEnvironment } from '@/context/environment/hooks';
import { useFetchWorkflow } from '@/hooks/use-fetch-workflow';
import { useUpdateWorkflow } from '@/hooks/use-update-workflow';
import { usePatchWorkflow } from '@/hooks/use-patch-workflow';
import { createContextHook } from '@/utils/context';
import { buildRoute, ROUTES } from '@/utils/routes';
import { toast } from 'sonner';
import { RiCloseFill } from 'react-icons/ri';
import {
AlertDialog,
AlertDialogHeader,
AlertDialogContent,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/primitives/alert-dialog';
import { RiAlertFill } from 'react-icons/ri';
import { CheckCircleIcon } from 'lucide-react';
import { useEnvironment } from '@/context/environment/hooks';
import { useBeforeUnload } from '@/hooks/use-before-unload';
import { useFetchWorkflow } from '@/hooks/use-fetch-workflow';
import { useInvocationQueue } from '@/hooks/use-invocation-queue';
import { usePatchWorkflow } from '@/hooks/use-patch-workflow';
import { useUpdateWorkflow } from '@/hooks/use-update-workflow';
import { createContextHook } from '@/utils/context';
import { buildRoute, ROUTES } from '@/utils/routes';
import { getWorkflowIdFromSlug, STEP_DIVIDER } from '@/utils/step';
import { CheckCircleIcon } from 'lucide-react';
import { RiAlertFill, RiCloseFill } from 'react-icons/ri';
import { toast } from 'sonner';
import { showErrorToast, showSavingToast, showSuccessToast } from './toasts';
import { STEP_DIVIDER } from '@/utils/step';
import { getWorkflowIdFromSlug } from '@/utils/step';
import { useBeforeUnload } from '@/hooks/use-before-unload';

export type UpdateWorkflowFn = (
data: UpdateWorkflowDto,
options?: {
onSuccess?: (workflow: WorkflowResponseDto) => void;
}
) => void;

export type WorkflowContextType = {
isPending: boolean;
workflow?: WorkflowResponseDto;
step?: StepResponseDto;
update: (data: UpdateWorkflowDto) => void;
update: UpdateWorkflowFn;
patch: (data: PatchWorkflowDto) => void;
};

Expand Down Expand Up @@ -111,9 +116,13 @@ export const WorkflowProvider = ({ children }: { children: ReactNode }) => {
useBeforeUnload(isUpdatePatchPending);

const update = useCallback(
(data: UpdateWorkflowDto) => {
(data: UpdateWorkflowDto, options?: { onSuccess?: (workflow: WorkflowResponseDto) => void }) => {
if (workflow) {
enqueue(() => updateWorkflow({ workflowSlug: workflow.slug, workflow: { ...data } }));
enqueue(async () => {
const res = await updateWorkflow({ workflowSlug: workflow.slug, workflow: { ...data } });
options?.onSuccess?.(res);
return res;
});
}
},
[enqueue, updateWorkflow, workflow]
Expand Down

0 comments on commit 08ea66e

Please sign in to comment.