Skip to content

Commit

Permalink
chore(root): Release 2024-10-21 09:38 (#6730)
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] authored Oct 21, 2024
2 parents 71dcd8a + fc5b3cb commit 142d15c
Show file tree
Hide file tree
Showing 82 changed files with 1,959 additions and 713 deletions.
4 changes: 3 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,9 @@
"zulip",
"zwnj",
"motionone",
"xyflow"
"xyflow",
"Sonner",
"sonner",
],
"flagWords": [],
"patterns": [
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package.json
apps/api/src/metadata.ts

/.nx/cache
/.nx/workspace-data
/.nx/workspace-data
6 changes: 1 addition & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"cSpell.userWords": [],
"cSpell.enabled": true,
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"eslint.format.enable": true,
"editor.tabSize": 2,
Expand All @@ -15,8 +13,6 @@
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"cSpell.words": ["mantine"],
"vsicons.presets.nestjs": true,
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
Expand Down
8 changes: 7 additions & 1 deletion apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"dependencies": {
"@clerk/clerk-react": "^5.2.5",
"@hookform/resolvers": "^2.9.11",
"@hookform/resolvers": "^3.9.0",
"@novu/react": "^2.3.0",
"@novu/shared": "workspace:*",
"@radix-ui/react-dialog": "^1.1.2",
Expand All @@ -32,6 +32,7 @@
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-scroll-area": "^1.2.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.3",
Expand All @@ -41,23 +42,28 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"lodash.debounce": "^4.0.8",
"lucide-react": "^0.439.0",
"mixpanel-browser": "^2.52.0",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^1.3.0",
"react-hook-form": "7.43.9",
"react-icons": "^5.3.0",
"react-router-dom": "6.26.2",
"react-use-intercom": "^2.0.0",
"sonner": "^1.5.0",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"use-deep-compare-effect": "^1.8.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@clerk/types": "^4.6.1",
"@eslint/js": "^9.9.0",
"@playwright/test": "^1.44.0",
"@types/lodash.debounce": "^4.0.9",
"@types/mixpanel-browser": "^2.49.0",
"@types/node": "^22.7.0",
"@types/react": "^18.3.3",
Expand Down
20 changes: 18 additions & 2 deletions apps/dashboard/src/api/workflows.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import type { WorkflowResponseDto } from '@novu/shared';
import { getV2 } from './api.client';
import type { CreateWorkflowDto, UpdateWorkflowDto, WorkflowResponseDto } from '@novu/shared';
import { getV2, postV2, putV2 } from './api.client';

export const fetchWorkflow = async ({ workflowId }: { workflowId?: string }): Promise<WorkflowResponseDto> => {
const { data } = await getV2<{ data: WorkflowResponseDto }>(`/workflows/${workflowId}`);

return data;
};

export async function createWorkflow(payload: CreateWorkflowDto) {
return postV2<{ data: WorkflowResponseDto }>(`/workflows`, payload);
}

export const updateWorkflow = async ({
id,
workflow,
}: {
id: string;
workflow: UpdateWorkflowDto;
}): Promise<WorkflowResponseDto> => {
const { data } = await putV2<{ data: WorkflowResponseDto }>(`/workflows/${id}`, workflow);

return data;
};
184 changes: 184 additions & 0 deletions apps/dashboard/src/components/create-workflow-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { createWorkflow } from '@/api/workflows';
import { Button } from '@/components/primitives/button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/primitives/form';
import { Input, InputField } from '@/components/primitives/input';
import { Separator } from '@/components/primitives/separator';
import {
Sheet,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetMain,
SheetTitle,
SheetTrigger,
} from '@/components/primitives/sheet';
import { TagInput } from '@/components/primitives/tag-input';
import { Textarea } from '@/components/primitives/textarea';
import { useEnvironment } from '@/context/environment/hooks';
import { QueryKeys } from '@/utils/query-keys';
import { zodResolver } from '@hookform/resolvers/zod';
import { type CreateWorkflowDto, WorkflowCreationSourceEnum } from '@novu/shared';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { ComponentProps, useState } from 'react';
import { useForm } from 'react-hook-form';
import { RiExternalLinkLine } from 'react-icons/ri';

import { Link } from 'react-router-dom';
import { z } from 'zod';

const formSchema = z.object({
name: z.string(),
identifier: z.string().regex(/^[a-z0-9-]+$/, 'Invalid identifier format. Must follow ^[a-z0-9-]+$'),
tags: z
.array(z.string().min(1))
.max(8)
.refine((tags) => new Set(tags).size === tags.length, {
message: 'Duplicate tags are not allowed.',
}),
description: z.string().max(200).optional(),
});

type CreateWorkflowButtonProps = ComponentProps<typeof SheetTrigger>;
export const CreateWorkflowButton = (props: CreateWorkflowButtonProps) => {
const queryClient = useQueryClient();
const { currentEnvironment } = useEnvironment();
const [isOpen, setIsOpen] = useState(false);
const { mutateAsync, isPending } = useMutation({
mutationFn: async (data: CreateWorkflowDto) => createWorkflow(data),
onSuccess: (result) => {
queryClient.invalidateQueries({ queryKey: [QueryKeys.fetchWorkflows, currentEnvironment?._id] });
queryClient.invalidateQueries({
queryKey: [QueryKeys.fetchWorkflow, currentEnvironment?._id, result.data.workflowId],
});
setIsOpen(false);
},
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { description: '', identifier: '', name: '', tags: [] },
});

return (
<Sheet
open={isOpen}
onOpenChange={(open) => {
setIsOpen(open);
if (open) {
form.reset();
}
}}
>
<SheetTrigger {...props} />
<SheetContent>
<SheetHeader>
<SheetTitle>Create workflow</SheetTitle>
<div>
<SheetDescription>
Workflows manage event-driven notifications across multiple channels in a version-controlled flow, with
the ability to manage preference for each subscriber.
</SheetDescription>
<Link
target="_blank"
to="https://docs.novu.co/api-reference/workflows/create-workflow"
className="text-foreground-400 flex items-center text-sm underline"
>
Learn more <RiExternalLinkLine className="inline size-4" />
</Link>
</div>
</SheetHeader>
<Separator />
<SheetMain>
<Form {...form}>
<form
id="create-workflow"
onSubmit={form.handleSubmit((values) => {
mutateAsync({
name: values.name,
steps: [],
__source: WorkflowCreationSourceEnum.DASHBOARD,
workflowId: values.identifier,
description: values.description || undefined,
tags: values.tags,
});
})}
className="flex flex-col gap-6"
>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<InputField>
<Input placeholder="Untitled" {...field} />
</InputField>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="identifier"
render={({ field }) => (
<FormItem>
<FormLabel>Identifier</FormLabel>
<FormControl>
<InputField>
<Input placeholder="untitled" {...field} />
</InputField>
</FormControl>
<FormMessage>Must be unique and all lowercase ^[a-z0-9\-]+$</FormMessage>
</FormItem>
)}
/>

<Separator className="bg-neutral-alpha-100" />

<FormField
control={form.control}
name="tags"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-1">
<FormLabel hint="(max. 8)">Add tags</FormLabel>
</div>
<FormControl>
<TagInput {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-1">
<FormLabel optional>Description</FormLabel>
</div>
<FormControl>
<Textarea placeholder="Description of what this workflow does" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</SheetMain>
<Separator />
<SheetFooter>
<Button disabled={isPending} variant="default" type="submit" form="create-workflow">
Create workflow
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useLayoutEffect, useState } from 'react';
import { RiLinkM, RiPencilFill } from 'react-icons/ri';
import { useForm } from 'react-hook-form';
// eslint-disable-next-line
// @ts-ignore
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';

Expand Down Expand Up @@ -86,7 +84,7 @@ export const EditBridgeUrlButton = () => {
<FormItem>
<FormLabel>Bridge Endpoint URL</FormLabel>
<FormControl>
<InputField variant="xs" state={errors.bridgeUrl?.message ? 'error' : 'default'}>
<InputField state={errors.bridgeUrl?.message ? 'error' : 'default'}>
<RiLinkM className="size-5 min-w-5" />
<Input id="bridgeUrl" {...field} />
</InputField>
Expand Down
29 changes: 23 additions & 6 deletions apps/dashboard/src/components/primitives/form/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider } fro
import { cn } from '@/utils/ui';
import { Label } from '@/components/primitives/label';
import { cva } from 'class-variance-authority';
import { RiInformationFill } from 'react-icons/ri';
import { FormFieldContext, FormItemContext, useFormField } from './form-context';
import { RiErrorWarningFill, RiInformationFill } from 'react-icons/ri';
import { BsFillInfoCircleFill } from 'react-icons/bs';

const Form = FormProvider;

Expand Down Expand Up @@ -39,11 +40,27 @@ FormItem.displayName = 'FormItem';

const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => {
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & { optional?: boolean; hint?: string }
>(({ className, optional, hint, children, ...props }, ref) => {
const { formItemId } = useFormField();

return <Label ref={ref} className={className} htmlFor={formItemId} {...props} />;
return (
<Label ref={ref} className={cn('text-foreground-950', className)} htmlFor={formItemId} {...props}>
{children}
{hint && (
<span className="text-foreground-400 ml-0.5 inline-flex items-center gap-1">
{hint}
<BsFillInfoCircleFill className="text-foreground-300 inline size-3" />
</span>
)}

{optional && (
<span className="text-foreground-400 ml-0.5 inline-flex items-center gap-1">
(optional) <BsFillInfoCircleFill className="text-foreground-300 inline size-3" />
</span>
)}
</Label>
);
});
FormLabel.displayName = 'FormLabel';

Expand Down Expand Up @@ -78,7 +95,7 @@ FormDescription.displayName = 'FormDescription';
const formMessageVariants = cva('flex items-center gap-1', {
variants: {
variant: {
default: '[&>svg]:text-neutral-400 [&>span]:text-foreground-600',
default: '[&>svg]:text-foreground-300 text-foreground-400',
error: '[&>svg]:text-destructive [&>span]:text-destructive',
},
},
Expand All @@ -100,7 +117,7 @@ const FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<
className={formMessageVariants({ variant: error ? 'error' : 'default', className })}
{...props}
>
<RiInformationFill className="size-4" />
{error ? <RiErrorWarningFill className="size-4" /> : <RiInformationFill className="size-4" />}
<span className="mt-[1px] text-xs leading-3">{body}</span>
</p>
);
Expand Down
Loading

0 comments on commit 142d15c

Please sign in to comment.