-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(dashboard): page meta, gtm, and uptime #6974
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,13 @@ | |
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + React + TS</title> | ||
<title>Novu Cloud Dashboard</title> | ||
<meta name="description" content="Novu Cloud Dashboard" /> | ||
<meta name="theme-color" content="#fff" /> | ||
<link rel="icon" href="/favicon-gradient.svg" /> | ||
<link rel="apple-touch-icon" href="/favicon-gradient.svg" /> | ||
<link rel="manifest" href="/manifest.json" /> | ||
<link rel="preconnect" href="https://fonts.googleapis.com" /> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | ||
<link | ||
|
@@ -15,8 +19,40 @@ | |
href="https://fonts.googleapis.com/css2?family=Ubuntu+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<% if (env.VITE_GTM) { %> | ||
<script> | ||
(function (w, d, s, l, i) { | ||
w[l] = w[l] || []; | ||
w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); | ||
var f = d.getElementsByTagName(s)[0], | ||
j = d.createElement(s), | ||
dl = l != 'dataLayer' ? '&l=' + l : ''; | ||
j.async = true; | ||
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; | ||
f.parentNode.insertBefore(j, f); | ||
})(window, document, 'script', 'dataLayer', '<%= env.VITE_GTM %>'); | ||
</script> | ||
<% } %> | ||
Comment on lines
+22
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GTM |
||
</head> | ||
<body> | ||
<% if (env.VITE_GTM) { %> | ||
<noscript> | ||
<iframe | ||
src="https://www.googletagmanager.com/ns.html?id=<%= env.VITE_GTM %>" | ||
height="0" | ||
width="0" | ||
style="display: none; visibility: hidden" | ||
></iframe> | ||
</noscript> | ||
<% } %> <% if (env.VITE_SELF_HOSTED === 'false' ) { %> | ||
<script | ||
src="https://uptime.betterstack.com/widgets/announcement.js" | ||
data-id="144175" | ||
async="async" | ||
type="text/javascript" | ||
></script> | ||
<% } %> | ||
Comment on lines
+47
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uptime |
||
|
||
<div id="root" class="h-full"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,6 +106,7 @@ | |
"typescript": "5.6.2", | ||
"typescript-eslint": "^8.0.1", | ||
"vite": "^5.4.1", | ||
"vite-plugin-ejs": "^1.7.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the Vite EJS plugin that allows the use of conditionals in the HTML template; by default, it's not supported by Vite :/ |
||
"vite-plugin-static-copy": "^1.0.6" | ||
}, | ||
"peerDependencies": { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"short_name": "Novu Dashboard", | ||
"name": "Novu Dashboard application", | ||
"icons": [ | ||
{ | ||
"src": "favicon.ico", | ||
"sizes": "64x64 32x32 24x24 16x16", | ||
"type": "image/x-icon" | ||
} | ||
], | ||
"start_url": ".", | ||
"display": "standalone", | ||
"theme_color": "#000000", | ||
"background_color": "#ffffff" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,124 +16,130 @@ import { Switch } from '../primitives/switch'; | |
import { useWorkflowEditorContext } from '@/components/workflow-editor/hooks'; | ||
import { cn } from '@/utils/ui'; | ||
import { SidebarContent, SidebarHeader } from '@/components/side-navigation/Sidebar'; | ||
import { PageMeta } from '../page-meta'; | ||
|
||
export function ConfigureWorkflow() { | ||
const tagsQuery = useTagsQuery(); | ||
const { isReadOnly } = useWorkflowEditorContext(); | ||
|
||
const { control } = useFormContext<z.infer<typeof workflowSchema>>(); | ||
const { control, watch } = useFormContext<z.infer<typeof workflowSchema>>(); | ||
const workflowName = watch('name'); | ||
|
||
return ( | ||
<motion.div | ||
className={cn('relative flex h-full w-full flex-col')} | ||
initial={{ opacity: 0 }} | ||
animate={{ opacity: 1 }} | ||
exit={{ opacity: 0.1 }} | ||
transition={{ duration: 0.1 }} | ||
> | ||
<SidebarHeader className="items-center text-sm font-medium"> | ||
<div className="flex items-center gap-1"> | ||
<RouteFill /> | ||
<span>Configure workflow</span> | ||
</div> | ||
</SidebarHeader> | ||
<Separator /> | ||
<SidebarContent size="md"> | ||
<FormField | ||
control={control} | ||
name="active" | ||
render={({ field }) => ( | ||
<FormItem className="flex w-full items-center justify-between"> | ||
<div className="flex items-center gap-4"> | ||
<div | ||
className="bg-success/60 data-[active=false]:shadow-neutral-alpha-100 ml-2 h-1.5 w-1.5 rounded-full [--pulse-color:var(--success)] data-[active=true]:animate-[pulse-shadow_1s_ease-in-out_infinite] data-[active=false]:bg-neutral-300 data-[active=false]:shadow-[0_0px_0px_5px_var(--neutral-alpha-200),0_0px_0px_9px_var(--neutral-alpha-100)]" | ||
data-active={field.value} | ||
/> | ||
<FormLabel>Active Workflow</FormLabel> | ||
</div> | ||
<FormControl> | ||
<Switch checked={field.value} onCheckedChange={field.onChange} disabled={isReadOnly} /> | ||
</FormControl> | ||
</FormItem> | ||
)} | ||
/> | ||
</SidebarContent> | ||
<Separator /> | ||
<SidebarContent> | ||
<FormField | ||
control={control} | ||
name="name" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Workflow Name</FormLabel> | ||
<FormControl> | ||
<InputField> | ||
<Input placeholder="Untitled" {...field} disabled={isReadOnly} /> | ||
</InputField> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="workflowId" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Workflow Identifier</FormLabel> | ||
<FormControl> | ||
<InputField className="flex overflow-hidden pr-0"> | ||
<Input placeholder="Untitled" {...field} disabled={isReadOnly} /> | ||
<CopyButton | ||
content={field.value} | ||
className="rounded-md rounded-s-none border-b-0 border-r-0 border-t-0 text-neutral-400" | ||
<> | ||
<PageMeta title={workflowName} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. page meta component |
||
<motion.div | ||
className={cn('relative flex h-full w-full flex-col')} | ||
initial={{ opacity: 0 }} | ||
animate={{ opacity: 1 }} | ||
exit={{ opacity: 0.1 }} | ||
transition={{ duration: 0.1 }} | ||
> | ||
<SidebarHeader className="items-center text-sm font-medium"> | ||
<div className="flex items-center gap-1"> | ||
<RouteFill /> | ||
<span>Configure workflow</span> | ||
</div> | ||
</SidebarHeader> | ||
<Separator /> | ||
<SidebarContent size="md"> | ||
<FormField | ||
control={control} | ||
name="active" | ||
render={({ field }) => ( | ||
<FormItem className="flex w-full items-center justify-between"> | ||
<div className="flex items-center gap-4"> | ||
<div | ||
className="bg-success/60 data-[active=false]:shadow-neutral-alpha-100 ml-2 h-1.5 w-1.5 rounded-full [--pulse-color:var(--success)] data-[active=true]:animate-[pulse-shadow_1s_ease-in-out_infinite] data-[active=false]:bg-neutral-300 data-[active=false]:shadow-[0_0px_0px_5px_var(--neutral-alpha-200),0_0px_0px_9px_var(--neutral-alpha-100)]" | ||
data-active={field.value} | ||
/> | ||
</InputField> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="description" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Description</FormLabel> | ||
<FormControl> | ||
<Textarea placeholder="Description of what this workflow does" {...field} disabled={isReadOnly} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="tags" | ||
render={({ field }) => ( | ||
<FormItem className="group" tabIndex={-1}> | ||
<div className="flex items-center gap-1"> | ||
<FormLabel>Tags</FormLabel> | ||
</div> | ||
<FormControl className="text-xs text-neutral-600"> | ||
<TagInput | ||
{...field} | ||
disabled={isReadOnly} | ||
value={field.value ?? []} | ||
suggestions={tagsQuery.data?.data.map((tag) => tag.name) || []} | ||
/> | ||
</FormControl> | ||
</FormItem> | ||
)} | ||
/> | ||
</SidebarContent> | ||
<Separator /> | ||
{/* <SidebarContent size="lg"> | ||
<FormLabel>Active Workflow</FormLabel> | ||
</div> | ||
<FormControl> | ||
<Switch checked={field.value} onCheckedChange={field.onChange} disabled={isReadOnly} /> | ||
</FormControl> | ||
</FormItem> | ||
)} | ||
/> | ||
</SidebarContent> | ||
<Separator /> | ||
<SidebarContent> | ||
<FormField | ||
control={control} | ||
name="name" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Workflow Name</FormLabel> | ||
<FormControl> | ||
<InputField> | ||
<Input placeholder="Untitled" {...field} disabled={isReadOnly} /> | ||
</InputField> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="workflowId" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Workflow Identifier</FormLabel> | ||
<FormControl> | ||
<InputField className="flex overflow-hidden pr-0"> | ||
<Input placeholder="Untitled" {...field} disabled={isReadOnly} /> | ||
<CopyButton | ||
content={field.value} | ||
className="rounded-md rounded-s-none border-b-0 border-r-0 border-t-0 text-neutral-400" | ||
/> | ||
</InputField> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="description" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Description</FormLabel> | ||
<FormControl> | ||
<Textarea placeholder="Description of what this workflow does" {...field} disabled={isReadOnly} /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<FormField | ||
control={control} | ||
name="tags" | ||
render={({ field }) => ( | ||
<FormItem className="group" tabIndex={-1}> | ||
<div className="flex items-center gap-1"> | ||
<FormLabel>Tags</FormLabel> | ||
</div> | ||
<FormControl className="text-xs text-neutral-600"> | ||
<TagInput | ||
{...field} | ||
disabled={isReadOnly} | ||
value={field.value ?? []} | ||
suggestions={tagsQuery.data?.data.map((tag) => tag.name) || []} | ||
/> | ||
</FormControl> | ||
</FormItem> | ||
)} | ||
/> | ||
</SidebarContent> | ||
<Separator /> | ||
{/* <SidebarContent size="lg"> | ||
<Button variant="outline" className="flex w-full justify-start gap-1.5 text-xs font-medium" type="button"> | ||
<RiSettingsLine className="h-4 w-4 text-neutral-600" /> | ||
Configure channel preferences <RiArrowRightSLine className="ml-auto h-4 w-4 text-neutral-600" /> | ||
</Button> | ||
</SidebarContent> | ||
<Separator /> */} | ||
</motion.div> | ||
</motion.div> | ||
</> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
favicons and manifest