Skip to content

Commit 2e10294

Browse files
authored
feat(dashboard): Subscriber drawer on activity feed & improvements (#7686)
1 parent 7b61561 commit 2e10294

28 files changed

+1622
-1239
lines changed

apps/dashboard/package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@
2424
"@hookform/resolvers": "^3.9.0",
2525
"@lezer/highlight": "^1.2.1",
2626
"@maily-to/core": "^0.0.27",
27+
"@novu/api": "workspace:*",
2728
"@novu/framework": "workspace:*",
2829
"@novu/js": "workspace:*",
2930
"@novu/react": "workspace:*",
3031
"@novu/shared": "workspace:*",
31-
"@novu/api": "workspace:*",
3232
"@radix-ui/react-accordion": "^1.2.1",
33-
"@radix-ui/react-alert-dialog": "^1.1.2",
33+
"@radix-ui/react-alert-dialog": "^1.1.6",
3434
"@radix-ui/react-avatar": "^1.1.1",
3535
"@radix-ui/react-checkbox": "^1.1.2",
3636
"@radix-ui/react-collapsible": "^1.1.1",
37-
"@radix-ui/react-dialog": "^1.1.2",
37+
"@radix-ui/react-dialog": "^1.1.6",
3838
"@radix-ui/react-dropdown-menu": "^2.1.1",
3939
"@radix-ui/react-hover-card": "^1.1.2",
4040
"@radix-ui/react-icons": "^1.3.0",
@@ -118,6 +118,7 @@
118118
"@types/node": "^22.7.0",
119119
"@types/react": "^18.3.3",
120120
"@types/react-dom": "^18.3.0",
121+
"@types/react-window": "^1.8.8",
121122
"@vitejs/plugin-react": "^4.3.1",
122123
"autoprefixer": "^10.4.20",
123124
"eslint": "^9.9.0",

apps/dashboard/src/components/activity/components/activity-overview.tsx

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { format } from 'date-fns';
2-
import { Link } from 'react-router-dom';
3-
import { cn } from '@/utils/ui';
4-
import { buildRoute, ROUTES } from '@/utils/routes';
5-
import { useEnvironment } from '@/context/environment/hooks';
1+
import { SubscriberDrawerButton } from '@/components/subscribers/subscriber-drawer';
62
import { TimeDisplayHoverCard } from '@/components/time-display-hover-card';
7-
import { OverviewItem } from './overview-item';
3+
import { useEnvironment } from '@/context/environment/hooks';
4+
import { buildRoute, ROUTES } from '@/utils/routes';
5+
import { cn } from '@/utils/ui';
86
import { IActivity } from '@novu/shared';
7+
import { format } from 'date-fns';
8+
import { Link } from 'react-router-dom';
99
import { JOB_STATUS_CONFIG } from '../constants';
10+
import { OverviewItem } from './overview-item';
1011

1112
export interface ActivityOverviewProps {
1213
activity: IActivity;
@@ -37,12 +38,19 @@ export function ActivityOverview({ activity }: ActivityOverviewProps) {
3738

3839
<OverviewItem label="Transaction ID" value={activity.transactionId} isCopyable />
3940

40-
<OverviewItem
41-
label="Subscriber ID"
42-
isDeleted={!activity.subscriber}
43-
value={(activity.subscriber?.subscriberId || activity._subscriberId) ?? ''}
44-
isCopyable
45-
/>
41+
<SubscriberDrawerButton
42+
disabled={!activity.subscriber}
43+
className="text-start"
44+
subscriberId={activity.subscriber?.subscriberId || activity._subscriberId}
45+
readOnly={true}
46+
>
47+
<OverviewItem
48+
label="Subscriber ID"
49+
isDeleted={!activity.subscriber}
50+
value={(activity.subscriber?.subscriberId || activity._subscriberId) ?? ''}
51+
isCopyable
52+
/>
53+
</SubscriberDrawerButton>
4654

4755
<OverviewItem label="Triggered at" value={format(new Date(activity.createdAt), 'MMM d yyyy, HH:mm:ss')}>
4856
<TimeDisplayHoverCard

apps/dashboard/src/components/activity/components/overview-item.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ export function OverviewItem({
4646
valueToCopy={value}
4747
mode="ghost"
4848
size="2xs"
49+
onClick={(e) => {
50+
e.stopPropagation();
51+
}}
4952
className="text-foreground-600 mr-0 size-3 gap-0 p-0 opacity-0 transition-opacity group-hover:opacity-100"
50-
></CopyButton>
53+
/>
5154
)}
5255
{wrappedChildren}
5356
</div>

apps/dashboard/src/components/primitives/copy-button.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type CopyButtonProps = ButtonProps & {
1010
};
1111

1212
export const CopyButton = (props: CopyButtonProps) => {
13-
const { className, valueToCopy, children, size, ...rest } = props;
13+
const { className, valueToCopy, children, onClick, size, ...rest } = props;
1414

1515
const [copied, setCopied] = useState<boolean>(false);
1616

@@ -32,7 +32,10 @@ export const CopyButton = (props: CopyButtonProps) => {
3232
<Button
3333
mode="outline"
3434
variant="secondary"
35-
onClick={handleCopy}
35+
onClick={(e) => {
36+
handleCopy();
37+
onClick?.(e);
38+
}}
3639
className={cn(
3740
'rounded-none bg-transparent outline-none ring-1 ring-inset ring-transparent transition duration-200 ease-out',
3841
'hover:bg-bg-weak-50 hover:text-text-strong-950',

apps/dashboard/src/components/primitives/editor.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import React, { useCallback, useMemo } from 'react';
2-
import { flushSync } from 'react-dom';
3-
import { cva } from 'class-variance-authority';
41
import { autocompleteFooter, autocompleteHeader, functionIcon } from '@/components/primitives/constants';
52
import { useDataRef } from '@/hooks/use-data-ref';
63
import { tags as t } from '@lezer/highlight';
@@ -11,6 +8,9 @@ import {
118
ReactCodeMirrorProps,
129
type ReactCodeMirrorRef,
1310
} from '@uiw/react-codemirror';
11+
import { cva } from 'class-variance-authority';
12+
import React, { useCallback, useMemo } from 'react';
13+
import { flushSync } from 'react-dom';
1414

1515
const variants = cva('h-full w-full flex-1 [&_.cm-focused]:outline-none', {
1616
variants: {

apps/dashboard/src/components/primitives/phone-input.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import { cn } from '@/utils/ui';
12
import * as React from 'react';
3+
import { RiArrowDownSLine, RiCheckLine, RiEarthLine } from 'react-icons/ri';
24
import * as RPNInput from 'react-phone-number-input';
35
import flags from 'react-phone-number-input/flags';
4-
import { cn } from '@/utils/ui';
5-
import { InputPure, InputRoot, InputWrapper } from './input';
6-
import { Popover, PopoverContent, PopoverTrigger } from './popover';
76
import { Button } from './button';
87
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from './command';
8+
import { InputPure, InputRoot, InputWrapper } from './input';
9+
import { Popover, PopoverContent, PopoverTrigger } from './popover';
910
import { ScrollArea } from './scroll-area';
10-
import { RiArrowDownSLine, RiCheckLine, RiEarthLine } from 'react-icons/ri';
1111

1212
type PhoneInputProps = Omit<React.ComponentProps<'input'>, 'onChange' | 'value' | 'ref'> &
1313
Omit<RPNInput.Props<typeof RPNInput.default>, 'onChange'> & {
@@ -54,7 +54,7 @@ type CountrySelectProps = {
5454

5555
const CountrySelect = ({ disabled, value: selectedCountry, options: countryList, onChange }: CountrySelectProps) => {
5656
return (
57-
<Popover>
57+
<Popover modal={false}>
5858
<PopoverTrigger asChild>
5959
<Button
6060
type="button"
@@ -67,7 +67,7 @@ const CountrySelect = ({ disabled, value: selectedCountry, options: countryList,
6767
<RiArrowDownSLine className={cn('-mr-2 size-4 opacity-50', disabled ? 'hidden' : 'opacity-100')} />
6868
</Button>
6969
</PopoverTrigger>
70-
<PopoverContent className="w-[300px] rounded-lg border-t-0 p-0">
70+
<PopoverContent portal={false} className="w-[300px] rounded-lg border-t-0 p-0">
7171
<Command>
7272
<CommandInput placeholder="Search country..." />
7373
<CommandList>

apps/dashboard/src/components/primitives/select.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import * as React from 'react';
21
import { CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons';
32
import * as SelectPrimitive from '@radix-ui/react-select';
43
import { cva, VariantProps } from 'class-variance-authority';
4+
import * as React from 'react';
55

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

@@ -123,8 +123,8 @@ const SelectItem = React.forwardRef<
123123
{...props}
124124
>
125125
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
126-
<SelectPrimitive.ItemIndicator>
127-
<CheckIcon className="h-4 w-4" />
126+
<SelectPrimitive.ItemIndicator className="shrink-0">
127+
<CheckIcon className="size-4" />
128128
</SelectPrimitive.ItemIndicator>
129129
</span>
130130
<SelectPrimitive.ItemText className="text-sm">{children}</SelectPrimitive.ItemText>
@@ -142,14 +142,14 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
142142

143143
export {
144144
Select,
145+
SelectContent,
145146
SelectGroup,
146-
SelectValue,
147147
SelectIcon,
148-
SelectTrigger,
149-
SelectContent,
150-
SelectLabel,
151148
SelectItem,
152-
SelectSeparator,
153-
SelectScrollUpButton,
149+
SelectLabel,
154150
SelectScrollDownButton,
151+
SelectScrollUpButton,
152+
SelectSeparator,
153+
SelectTrigger,
154+
SelectValue,
155155
};

apps/dashboard/src/components/primitives/sheet.tsx

+3-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const SheetClose = SheetPrimitive.Close;
1414

1515
const SheetPortal = SheetPrimitive.Portal;
1616

17-
const SheetContentBase = SheetPrimitive.Content;
18-
1917
const SheetOverlay = React.forwardRef<
2018
React.ElementRef<typeof SheetPrimitive.Overlay>,
2119
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
@@ -39,9 +37,9 @@ const sheetVariants = cva(
3937
top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
4038
bottom:
4139
'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
42-
left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
40+
left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-xl',
4341
right:
44-
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
42+
'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-xl',
4543
},
4644
},
4745
defaultVariants: {
@@ -59,7 +57,7 @@ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Con
5957
<SheetPortal>
6058
<SheetOverlay />
6159
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
62-
<SheetPrimitive.Close className="absolute right-4 top-4" asChild>
60+
<SheetPrimitive.Close className="absolute right-3.5 top-3.5" asChild>
6361
<CompactButton size="md" variant="ghost" icon={RiCloseLine}>
6462
<span className="sr-only">Close</span>
6563
</CompactButton>
@@ -106,7 +104,6 @@ export {
106104
Sheet,
107105
SheetClose,
108106
SheetContent,
109-
SheetContentBase,
110107
SheetDescription,
111108
SheetFooter,
112109
SheetHeader,

0 commit comments

Comments
 (0)