Skip to content

Commit

Permalink
feat(dashboard): Add inbox (#6584)
Browse files Browse the repository at this point in the history
  • Loading branch information
desiprisg authored Sep 29, 2024
1 parent d02f669 commit 0d8b8e8
Show file tree
Hide file tree
Showing 10 changed files with 723 additions and 397 deletions.
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"tabWidth": 2,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"arrowParens": "always"
"arrowParens": "always",
"plugins": ["prettier-plugin-tailwindcss"]
}
4 changes: 3 additions & 1 deletion apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
"dependencies": {
"@clerk/clerk-react": "^5.2.5",
"@hookform/resolvers": "^2.9.1",
"@novu/react": "^2.3.0",
"@novu/shared": "^2.1.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@segment/analytics-next": "^1.73.0",
"@tanstack/react-query": "^4.20.4",
Expand Down Expand Up @@ -44,10 +46,10 @@
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"rimraf": "^3.0.2",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.5",
"rimraf": "^3.0.2",
"tailwindcss": "^3.4.13",
"typescript": "5.6.2",
"typescript-eslint": "^8.0.1",
Expand Down
28 changes: 28 additions & 0 deletions apps/dashboard/src/components/inbox-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Popover, PopoverContent, PopoverTrigger } from '@/components/primitives/popover';
import { APP_ID } from '@/config';
import { useUser } from '@clerk/clerk-react';
import { Bell, Inbox, InboxContent } from '@novu/react';
import { PopoverPortal } from '@radix-ui/react-popover';

export const InboxButton = () => {
const { user } = useUser();

if (!user) {
return null;
}

return (
<Inbox subscriberId={user.id} applicationIdentifier={APP_ID}>
<Popover>
<PopoverTrigger>
<Bell />
</PopoverTrigger>
<PopoverPortal>
<PopoverContent className="h-[500px] w-[350px] p-0">
<InboxContent />
</PopoverContent>
</PopoverPortal>
</Popover>
</Inbox>
);
};
31 changes: 31 additions & 0 deletions apps/dashboard/src/components/primitives/popover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react';
import * as PopoverPrimitive from '@radix-ui/react-popover';

import { cn } from '@/utils/ui';

const Popover = PopoverPrimitive.Root;

const PopoverTrigger = PopoverPrimitive.Trigger;

const PopoverAnchor = PopoverPrimitive.Anchor;

const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none',
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;

export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
36 changes: 16 additions & 20 deletions apps/dashboard/src/components/providers/clerk-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
import { CLERK_PUBLISHABLE_KEY, IS_EE_AUTH_ENABLED } from "@/config";
import { ClerkProvider as _ClerkProvider } from "@clerk/clerk-react";
import { PropsWithChildren } from "react";
import { useNavigate } from "react-router-dom";
import { CLERK_PUBLISHABLE_KEY } from '@/config';
import { ClerkProvider as _ClerkProvider } from '@clerk/clerk-react';
import { PropsWithChildren } from 'react';
import { useNavigate } from 'react-router-dom';

const CLERK_LOCALIZATION = {
userProfile: {
navbar: {
title: "Settings",
description: "",
account: "User profile",
security: "Access security",
title: 'Settings',
description: '',
account: 'User profile',
security: 'Access security',
},
},
organizationProfile: {
membersPage: {
requestsTab: { autoSuggestions: { headerTitle: "" } },
invitationsTab: { autoInvitations: { headerTitle: "" } },
requestsTab: { autoSuggestions: { headerTitle: '' } },
invitationsTab: { autoInvitations: { headerTitle: '' } },
},
},
userButton: {
action__signOut: "Log out",
action__signOutAll: "Log out from all accounts",
action__manageAccount: "Settings",
action__signOut: 'Log out',
action__signOutAll: 'Log out from all accounts',
action__manageAccount: 'Settings',
},
};

const ALLOWED_REDIRECT_ORIGINS = ["http://localhost:*", window.location.origin];
const ALLOWED_REDIRECT_ORIGINS = ['http://localhost:*', window.location.origin];

type ClerkProviderProps = PropsWithChildren;
export const ClerkProvider = (props: ClerkProviderProps) => {
const { children } = props;

const navigate = useNavigate();

if (!IS_EE_AUTH_ENABLED) {
return <>{children}</>;
}

return (
<_ClerkProvider
routerPush={(to) => navigate(to)}
Expand All @@ -46,10 +42,10 @@ export const ClerkProvider = (props: ClerkProviderProps) => {
createOrganization: {
elements: {
modalContent: {
width: "auto",
width: 'auto',
},
rootBox: {
width: "420px",
width: '420px',
},
},
},
Expand Down
17 changes: 8 additions & 9 deletions apps/dashboard/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
export const SENTRY_DSN = import.meta.env.REACT_APP_SENTRY_DSN;
export const SENTRY_DSN = import.meta.env.VITE_SENTRY_DSN;

export const LAUNCH_DARKLY_CLIENT_SIDE_ID = import.meta.env
.REACT_APP_LAUNCH_DARKLY_CLIENT_SIDE_ID;
export const LAUNCH_DARKLY_CLIENT_SIDE_ID = import.meta.env.VITE_LAUNCH_DARKLY_CLIENT_SIDE_ID;

export const HUBSPOT_PORTAL_ID = import.meta.env.REACT_APP_HUBSPOT_EMBED;
export const HUBSPOT_PORTAL_ID = import.meta.env.VITE_HUBSPOT_EMBED;

export const IS_EE_AUTH_ENABLED =
import.meta.env.REACT_APP_IS_EE_AUTH_ENABLED === "true";
export const IS_EE_AUTH_ENABLED = import.meta.env.VITE_IS_EE_AUTH_ENABLED === 'true';

export const CLERK_PUBLISHABLE_KEY =
import.meta.env.REACT_APP_CLERK_PUBLISHABLE_KEY || "";
export const CLERK_PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY || '';

export const APP_ID = import.meta.env.VITE_NOVU_APP_ID || '';

if (IS_EE_AUTH_ENABLED && !CLERK_PUBLISHABLE_KEY) {
throw new Error("Missing Clerk Publishable Key");
throw new Error('Missing Clerk Publishable Key');
}
6 changes: 4 additions & 2 deletions apps/dashboard/src/routes/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ClerkProvider } from '@/components/providers/clerk-provider';
import { SegmentProvider } from '@/components/providers/segment-provider';
import { Outlet } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { InboxButton } from '@/components/inbox-button';

const queryClient = new QueryClient();

Expand All @@ -11,14 +12,15 @@ export default function Root() {
<ClerkProvider>
<SegmentProvider>
<div className="relative min-h-dvh">
<div className="fixed left-0 top-0 h-12 w-full bg-green-200">
<div className="fixed left-0 top-0 flex h-12 w-full justify-between bg-green-200">
<a
href="/legacy/"
target="_self"
className="text-blue-600 visited:text-purple-600 hover:border-current hover:border-b"
className="text-blue-600 visited:text-purple-600 hover:border-b hover:border-current"
>
Go to the Web App
</a>
<InboxButton />
</div>

<div className="pt-12">
Expand Down
8 changes: 4 additions & 4 deletions apps/dashboard/src/utils/segment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ export class SegmentService {
public _mixpanelEnabled: boolean;

constructor() {
this._segmentEnabled = !!import.meta.env.REACT_APP_SEGMENT_KEY;
this._mixpanelEnabled = !!import.meta.env.REACT_APP_MIXPANEL_KEY;
this._segmentEnabled = !!import.meta.env.VITE_SEGMENT_KEY;
this._mixpanelEnabled = !!import.meta.env.VITE_MIXPANEL_KEY;

if (this._mixpanelEnabled) {
mixpanel.init(import.meta.env.REACT_APP_MIXPANEL_KEY as string, {
mixpanel.init(import.meta.env.VITE_MIXPANEL_KEY as string, {
//@ts-expect-error missing from types
record_sessions_percent: 100,
});
}

if (this._segmentEnabled) {
this._segment = AnalyticsBrowser.load({
writeKey: import.meta.env.REACT_APP_SEGMENT_KEY as string,
writeKey: import.meta.env.VITE_SEGMENT_KEY as string,
});
if (!this._mixpanelEnabled) {
return;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
"pkg-pr-new": "^0.0.24",
"pnpm": "9.1.4",
"prettier": "~3.3.3",
"prettier-plugin-tailwindcss": "^0.6.5",
"process": "^0.11.10",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
Expand Down
Loading

0 comments on commit 0d8b8e8

Please sign in to comment.