From 581e7ca9a3d45fee520440143ce3b9dd8fb0aed3 Mon Sep 17 00:00:00 2001 From: desiprisg Date: Fri, 8 Nov 2024 12:26:22 +0200 Subject: [PATCH] feat(dashboard): Autofill payload with example in step preview --- apps/dashboard/src/api/workflows.ts | 10 +++--- .../steps/in-app/in-app-editor-preview.tsx | 25 +++++++++----- .../steps/in-app/in-app-tabs.tsx | 34 +++++++++++++++++-- apps/dashboard/src/hooks/use-debounce.ts | 2 +- .../src/hooks/use-debounced-effect.ts | 34 +++++++++++++++++++ 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 apps/dashboard/src/hooks/use-debounced-effect.ts diff --git a/apps/dashboard/src/api/workflows.ts b/apps/dashboard/src/api/workflows.ts index f050e7dc3fe..c06d030b0cf 100644 --- a/apps/dashboard/src/api/workflows.ts +++ b/apps/dashboard/src/api/workflows.ts @@ -55,17 +55,17 @@ export const updateWorkflow = async ({ export const previewStep = async ({ workflowSlug, - payload, + data, stepSlug, }: { workflowSlug: string; stepSlug: string; - payload?: GeneratePreviewRequestDto; + data?: GeneratePreviewRequestDto; }): Promise => { - const { data } = await postV2<{ data: GeneratePreviewResponseDto }>( + const res = await postV2<{ data: GeneratePreviewResponseDto }>( `/workflows/${workflowSlug}/step/${stepSlug}/preview`, - payload + data ); - return data; + return res.data; }; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx index 4fff3697a7f..7534eb81a37 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx @@ -6,19 +6,25 @@ import { Code2 } from '@/components/icons/code-2'; import { Button } from '@/components/primitives/button'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/primitives/collapsible'; import { Editor } from '@/components/primitives/editor'; -import { usePreviewStep } from '@/hooks/use-preview-step'; -import { useParams } from 'react-router-dom'; import { InAppPreview } from '@/components/workflow-editor/in-app-preview'; +import { usePreviewStep } from '@/hooks/use-preview-step'; import { loadLanguage } from '@uiw/codemirror-extensions-langs'; +import { useFormContext } from 'react-hook-form'; +import { useParams } from 'react-router-dom'; -export const InAppEditorPreview = () => { - const [editorValue, setEditorValue] = useState('{}'); +type InAppEditorPreviewProps = { + value: string; + onChange: (value: string) => void; +}; +export const InAppEditorPreview = (props: InAppEditorPreviewProps) => { + const { value, onChange } = props; const [isEditorOpen, setIsEditorOpen] = useState(true); const { previewStep, data } = usePreviewStep(); const { workflowSlug = '', stepSlug = '' } = useParams<{ workflowSlug: string; stepSlug: string; }>(); + const form = useFormContext(); const [payloadError, setPayloadError] = useState(''); return ( @@ -48,10 +54,9 @@ export const InAppEditorPreview = () => { @@ -63,7 +68,11 @@ export const InAppEditorPreview = () => { className="self-end" onClick={() => { try { - previewStep({ workflowSlug, stepSlug, payload: JSON.parse(editorValue) }); + previewStep({ + workflowSlug, + stepSlug, + data: { controlValues: form.getValues(), previewPayload: JSON.parse(value) }, + }); } catch (e) { setPayloadError(String(e)); } diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx index d257a1acacf..ade24ef0d9b 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx @@ -1,7 +1,7 @@ import { RiEdit2Line, RiPencilRuler2Line } from 'react-icons/ri'; import { Cross2Icon } from '@radix-ui/react-icons'; import { useNavigate, useParams } from 'react-router-dom'; -import { useForm } from 'react-hook-form'; +import { useForm, useWatch } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { type WorkflowResponseDto, type StepDataDto, type StepUpdateDto } from '@novu/shared'; @@ -16,11 +16,14 @@ import { buildDynamicZodSchema, buildDefaultValues } from '@/utils/schema'; import { InAppEditor } from '@/components/workflow-editor/steps/in-app/in-app-editor'; import { showToast } from '@/components/primitives/sonner-helpers'; import { ToastIcon } from '@/components/primitives/sonner'; +import { useState } from 'react'; +import { usePreviewStep } from '@/hooks/use-preview-step'; +import useDebouncedEffect from '@/hooks/use-debounced-effect'; const tabsContentClassName = 'h-full w-full px-3 py-3.5'; export const InAppTabs = ({ workflow, step }: { workflow: WorkflowResponseDto; step: StepDataDto }) => { - const { stepSlug = '' } = useParams<{ stepSlug: string }>(); + const { stepSlug = '', workflowSlug = '' } = useParams<{ workflowSlug: string; stepSlug: string }>(); const { dataSchema, uiSchema } = step.controls; const navigate = useNavigate(); const schema = buildDynamicZodSchema(dataSchema ?? {}); @@ -31,8 +34,10 @@ export const InAppTabs = ({ workflow, step }: { workflow: WorkflowResponseDto; s defaultValues: buildDefaultValues(uiSchema ?? {}), values: step.controls.values, }); + const [editorValue, setEditorValue] = useState('{}'); const { reset, formState } = form; + const { previewStep } = usePreviewStep(); const { updateWorkflow } = useUpdateWorkflow({ onSuccess: () => { showToast({ @@ -81,6 +86,29 @@ export const InAppTabs = ({ workflow, step }: { workflow: WorkflowResponseDto; s reset({ ...data }); }; + const preview = async (props: { + controlValues: Record; + previewPayload: Record; + }) => { + const res = await previewStep({ + workflowSlug, + stepSlug, + data: { controlValues: props.controlValues, previewPayload: props.previewPayload }, + }); + setEditorValue(JSON.stringify(res.previewPayloadExample, null, 2)); + }; + const formValues = useWatch(form); + useDebouncedEffect( + () => { + preview({ + controlValues: form.getValues() as Record, + previewPayload: JSON.parse(editorValue), + }); + }, + 2000, + [formValues] + ); + return (
- +