diff --git a/web/package-lock.json b/web/package-lock.json
index 74259301b..96decab33 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -65,7 +65,7 @@
"react": "^18",
"react-color": "^2.19.3",
"react-data-grid": "7.0.0-beta.47",
- "react-day-picker": "^9.6.2",
+ "react-day-picker": "8.10.1",
"react-dom": "^18",
"react-hotkeys-hook": "^4.6.1",
"react-markdown": "^10.1.0",
@@ -2150,12 +2150,6 @@
"storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0"
}
},
- "node_modules/@date-fns/tz": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz",
- "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==",
- "license": "MIT"
- },
"node_modules/@dnd-kit/accessibility": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
@@ -10056,21 +10050,16 @@
}
},
"node_modules/date-fns": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
- "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"license": "MIT",
+ "peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
- "node_modules/date-fns-jalali": {
- "version": "4.1.0-0",
- "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz",
- "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==",
- "license": "MIT"
- },
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -18051,24 +18040,17 @@
}
},
"node_modules/react-day-picker": {
- "version": "9.6.2",
- "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.6.2.tgz",
- "integrity": "sha512-HVrTpDUYGKbi9scU9v2N3BPGMnL5jwekGFXcyyrvpamZdgYGfzVcovsBD4/yNGxhpCIX5X/5IoLDEAayNv1EqA==",
+ "version": "8.10.1",
+ "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
+ "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
"license": "MIT",
- "dependencies": {
- "@date-fns/tz": "^1.2.0",
- "date-fns": "^4.1.0",
- "date-fns-jalali": "^4.1.0-0"
- },
- "engines": {
- "node": ">=18"
- },
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/gpbl"
},
"peerDependencies": {
- "react": ">=16.8.0"
+ "date-fns": "^2.28.0 || ^3.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-docgen": {
diff --git a/web/package.json b/web/package.json
index 7b875bed2..718ab853a 100644
--- a/web/package.json
+++ b/web/package.json
@@ -73,7 +73,7 @@
"react": "^18",
"react-color": "^2.19.3",
"react-data-grid": "7.0.0-beta.47",
- "react-day-picker": "^9.6.2",
+ "react-day-picker": "8.10.1",
"react-dom": "^18",
"react-hotkeys-hook": "^4.6.1",
"react-markdown": "^10.1.0",
diff --git a/web/src/components/features/ShareMenu/AccessDropdown.tsx b/web/src/components/features/ShareMenu/AccessDropdown.tsx
index 1e3f1032b..31651b62a 100644
--- a/web/src/components/features/ShareMenu/AccessDropdown.tsx
+++ b/web/src/components/features/ShareMenu/AccessDropdown.tsx
@@ -69,6 +69,7 @@ export const AccessDropdown: React.FC<{
footerContent={}
footerClassName="p-0!"
onSelect={onSelectMenuItem}
+ sideOffset={9}
selectType="single"
align="end"
side="bottom">
diff --git a/web/src/components/features/ShareMenu/ShareMenuContent.stories.tsx b/web/src/components/features/ShareMenu/ShareMenuContent.stories.tsx
index a77b5fcd3..46423334e 100644
--- a/web/src/components/features/ShareMenu/ShareMenuContent.stories.tsx
+++ b/web/src/components/features/ShareMenu/ShareMenuContent.stories.tsx
@@ -85,3 +85,16 @@ export const ViewerPermission: Story = {
}
}
};
+
+export const PublishedMetric: Story = {
+ args: {
+ assetId: 'metric-123',
+ assetType: ShareAssetType.METRIC,
+ shareAssetConfig: {
+ ...mockShareConfig,
+ publicly_accessible: true,
+ public_expiry_date: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), // 7 days from now
+ public_enabled_by: 'test@example.com'
+ }
+ }
+};
diff --git a/web/src/components/features/ShareMenu/ShareMenuContentBody.tsx b/web/src/components/features/ShareMenu/ShareMenuContentBody.tsx
index 9b149509f..c8c7dcff9 100644
--- a/web/src/components/features/ShareMenu/ShareMenuContentBody.tsx
+++ b/web/src/components/features/ShareMenu/ShareMenuContentBody.tsx
@@ -175,7 +175,7 @@ const ShareMenuContentShare: React.FC<{
diff --git a/web/src/components/features/ShareMenu/ShareMenuContentPublish.tsx b/web/src/components/features/ShareMenu/ShareMenuContentPublish.tsx
index b87eb42b1..48a384247 100644
--- a/web/src/components/features/ShareMenu/ShareMenuContentPublish.tsx
+++ b/web/src/components/features/ShareMenu/ShareMenuContentPublish.tsx
@@ -17,6 +17,7 @@ import { DatePicker } from '@/components/ui/date';
import { useUpdateCollection } from '@/api/buster_rest/collections';
import { useUpdateMetric } from '@/api/buster_rest/metrics';
import { useUpdateDashboard } from '@/api/buster_rest/dashboards';
+import { SelectSingleEventHandler } from 'react-day-picker';
export const ShareMenuContentPublish: React.FC<{
onCopyLink: () => void;
@@ -127,8 +128,8 @@ export const ShareMenuContentPublish: React.FC<{
<>
-
-
+
+
} onClick={onCopyLink} />
@@ -160,15 +161,18 @@ export const ShareMenuContentPublish: React.FC<{
<>
-
+
-
+
>
)}
@@ -201,16 +205,21 @@ const LinkExpiration: React.FC<{
}, []);
const maxDate = useMemo(() => {
- return createDayjsDate(new Date()).add(3, 'year');
+ return createDayjsDate(new Date()).add(2, 'year');
}, []);
+ const onSelect: SelectSingleEventHandler = useMemoizedFn((date) => {
+ onChangeLinkExpiry(date || null);
+ });
+
return (
-
Link expiration
+
Link expiration
{
@@ -276,7 +285,7 @@ const SetAPassword: React.FC<{
{isPasswordProtected && (
-
+
: }
onClick={onClickVisibilityToggle}>
diff --git a/web/src/components/ui/calendar/calendar.tsx b/web/src/components/ui/calendar/calendar.tsx
index 6a5322629..06d5724af 100644
--- a/web/src/components/ui/calendar/calendar.tsx
+++ b/web/src/components/ui/calendar/calendar.tsx
@@ -1,27 +1,18 @@
'use client';
import * as React from 'react';
-import { ChevronLeft } from '@/components/ui/icons';
-import { DayPicker, DayPickerProps } from 'react-day-picker';
+import { DayPicker } from 'react-day-picker';
+import { ChevronRight, ChevronLeft } from '../icons';
+
import { cn } from '@/lib/utils';
-import { buttonVariants } from '@/components/ui/buttons';
-export type CalendarProps = DayPickerProps;
+export type CalendarProps = React.ComponentProps
;
-function Calendar({
- className,
- classNames,
- showOutsideDays = true,
- required = false,
- ...props
-}: CalendarProps) {
+function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
return (
(
-
+ IconLeft: ({ className, ...props }) => (
+
+ ),
+ IconRight: ({ className, ...props }) => (
+
+
+
)
}}
{...props}
diff --git a/web/src/components/ui/date/DatePicker.tsx b/web/src/components/ui/date/DatePicker.tsx
index 24c784ed9..eb9b72d7b 100644
--- a/web/src/components/ui/date/DatePicker.tsx
+++ b/web/src/components/ui/date/DatePicker.tsx
@@ -5,43 +5,40 @@ import { Calendar as CalendarIcon } from '@/components/ui/icons';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/buttons';
-import { Calendar } from '@/components/ui/calendar';
+import { Calendar, CalendarProps } from '@/components/ui/calendar';
import {
PopoverRoot as Popover,
PopoverContent,
PopoverTrigger
} from '@/components/ui/tooltip/PopoverBase';
import { formatDate } from '@/lib';
-import { type DayPickerProps } from 'react-day-picker';
+import { DayPickerProps } from 'react-day-picker';
-export interface DatePickerProps extends Omit
{
- date: Date;
- onSelect: (date: Date) => void;
+export type DatePickerProps = CalendarProps & {
dateFormat?: string;
placeholder?: string;
-}
+};
export function DatePicker({
- date,
- onSelect,
dateFormat = 'lll',
- placeholder = 'Pick a date'
+ placeholder = 'Pick a date',
+ selected,
+
+ ...props
}: DatePickerProps) {
return (
}
className={cn(
- 'w-[280px] justify-start text-left font-normal',
- !date && 'text-muted-foreground'
+ 'justify-start text-left font-normal',
+ !selected && 'text-muted-foreground'
)}>
-
-
-
- {date ? (
+ {selected ? (
formatDate({
- date,
+ date: selected as Date,
format: dateFormat
})
) : (
@@ -50,7 +47,7 @@ export function DatePicker({
-
+
);
diff --git a/web/src/components/ui/dropdown/Dropdown.tsx b/web/src/components/ui/dropdown/Dropdown.tsx
index 12972b38d..c08bcb3d0 100644
--- a/web/src/components/ui/dropdown/Dropdown.tsx
+++ b/web/src/components/ui/dropdown/Dropdown.tsx
@@ -64,6 +64,7 @@ export interface DropdownProps extends DropdownMenuProps {
showIndex?: boolean;
contentClassName?: string;
footerClassName?: string;
+ sideOffset?: number;
}
export interface DropdownContentProps
@@ -92,6 +93,7 @@ export const DropdownBase = ({
footerContent,
dir,
modal,
+ sideOffset,
footerClassName = '',
showIndex = false
}: DropdownProps) => {
@@ -105,7 +107,11 @@ export const DropdownBase = ({
{children}
-
+