Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,16 @@ import { selectPopularByIdStrict } from './featured';
*/
function mapTemplateStepsToSteps(templateSteps: StepCreateDto[]): Step[] {
return templateSteps.map((step, index) => {
// Create a proper Step object with all required properties
const mappedStep: Step = {
name: step.name || `Step ${index + 1}`,
type: step.type,
_id: `temp-${index}`, // Temporary ID for template preview
_id: `temp-${index}`,
stepId: step.name || `step-${index}`,
slug: `template-step-${index}_st_temp` as const, // Temporary slug for template preview
slug: `template-step-${index}_st_temp` as const,
controls: {
values: step.controlValues ?? {},
},
issues: undefined, // No issues for template steps
issues: undefined,
};

return mappedStep;
Expand All @@ -72,6 +71,10 @@ export function WorkflowTemplateModal(props: WorkflowTemplateModalProps) {

const selectedTemplate = props.selectedTemplate ?? internalSelectedTemplate;
const { suggestions } = useTemplateStore();
const previewSteps = useMemo(() => {
if (!selectedTemplate) return [] as Step[];
return mapTemplateStepsToSteps(selectedTemplate.workflowDefinition.steps);
}, [selectedTemplate]);
const filteredSuggestions = useMemo(() => {
if (selectedCategory === 'popular') {
const popular = selectPopularByIdStrict(suggestions, (s) => s.workflowDefinition.workflowId, 12);
Expand Down Expand Up @@ -239,10 +242,7 @@ export function WorkflowTemplateModal(props: WorkflowTemplateModalProps) {
) : (
<div className="flex h-full w-full gap-4">
<div className="flex-1">
<WorkflowCanvas
isTemplateStorePreview
steps={mapTemplateStepsToSteps(selectedTemplate.workflowDefinition.steps)}
/>
<WorkflowCanvas isTemplateStorePreview steps={previewSteps} />
</div>
<div className="border-stroke-soft w-full max-w-[300px] border-l p-3">
<CreateWorkflowForm onSubmit={handleCreateWorkflow} template={selectedTemplate.workflowDefinition} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const LayoutSelect = () => {
}));
}, [data]);

// Intentionally not auto-selecting default layout here

return (
<FormField
control={control}
Expand Down
36 changes: 34 additions & 2 deletions apps/dashboard/src/hooks/use-create-workflow.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { type CreateWorkflowDto, WorkflowCreationSourceEnum } from '@novu/shared';
import { type CreateWorkflowDto, StepTypeEnum, WorkflowCreationSourceEnum } from '@novu/shared';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { z } from 'zod';
import { getLayouts } from '@/api/layouts';
import { createWorkflow } from '@/api/workflows';
import { useEnvironment } from '@/context/environment/hooks';
import { QueryKeys } from '@/utils/query-keys';
Expand Down Expand Up @@ -51,9 +52,40 @@ export function useCreateWorkflow({ onSuccess }: UseCreateWorkflowOptions = {})
});

const submit = async (values: z.infer<typeof workflowSchema>, template?: CreateWorkflowDto) => {
let steps = template?.steps ?? [];

const isFromTemplateStore = template?.__source === WorkflowCreationSourceEnum.TEMPLATE_STORE;
const hasEmailWithoutLayout = steps.some(
(s) =>
s.type === StepTypeEnum.EMAIL &&
(!s.controlValues || (s.controlValues as Record<string, unknown>).layoutId == null)
);

if (isFromTemplateStore && hasEmailWithoutLayout && currentEnvironment) {
try {
const layouts = await getLayouts({
environment: currentEnvironment,
limit: 100,
offset: 0,
query: '',
});
const defaultLayoutId = layouts.layouts.find((l) => l.isDefault)?.layoutId;
if (defaultLayoutId) {
steps = steps.map((s) => {
if (s.type !== StepTypeEnum.EMAIL) return s;
const controlValues = { ...(s.controlValues || {}) } as Record<string, unknown>;
if (controlValues.layoutId == null) controlValues.layoutId = defaultLayoutId;
return { ...s, controlValues };
});
}
} catch {
// proceed without modifying steps if layouts fetch fails
}
}

return mutation.mutateAsync({
name: values.name,
steps: template?.steps ?? [],
steps,
__source: template?.__source ?? WorkflowCreationSourceEnum.DASHBOARD,
workflowId: values.workflowId,
description: values.description || undefined,
Expand Down
Loading