feat: dashboard v2, esm, upgrades (#211)
* esm * wip * wip * wip * wip * wip * wip * subscription notice * wip * wip * wip * fix envs * fix: update docker build * fix * esm/types * delete dashboard :D * add patches to dockerfiles * update packages + catalogs + ts * wip * remove native libs * ts * improvements * fix redirects and fetching session * try fix favicon * fixes * fix * order and resize reportds within a dashboard * improvements * wip * added userjot to dashboard * fix * add op * wip * different cache key * improve date picker * fix table * event details loading * redo onboarding completely * fix login * fix * fix * extend session, billing and improve bars * fix * reduce price on 10M
This commit is contained in:
committed by
GitHub
parent
436e81ecc9
commit
81a7e5d62e
205
apps/start/src/components/time-window-picker.tsx
Normal file
205
apps/start/src/components/time-window-picker.tsx
Normal file
@@ -0,0 +1,205 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { pushModal, useOnPushModal } from '@/modals';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { bind } from 'bind-event-listener';
|
||||
import { CalendarIcon } from 'lucide-react';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
import { shouldIgnoreKeypress } from '@/utils/should-ignore-keypress';
|
||||
import { timeWindows } from '@openpanel/constants';
|
||||
import type { IChartRange } from '@openpanel/validation';
|
||||
import { endOfDay, format, startOfDay } from 'date-fns';
|
||||
|
||||
type Props = {
|
||||
value: IChartRange;
|
||||
onChange: (value: IChartRange) => void;
|
||||
onStartDateChange: (date: string) => void;
|
||||
onEndDateChange: (date: string) => void;
|
||||
endDate: string | null;
|
||||
startDate: string | null;
|
||||
className?: string;
|
||||
};
|
||||
export function TimeWindowPicker({
|
||||
value,
|
||||
onChange,
|
||||
startDate,
|
||||
onStartDateChange,
|
||||
endDate,
|
||||
onEndDateChange,
|
||||
className,
|
||||
}: Props) {
|
||||
const isDateRangerPickerOpen = useRef(false);
|
||||
useOnPushModal('DateRangerPicker', (open) => {
|
||||
isDateRangerPickerOpen.current = open;
|
||||
});
|
||||
const timeWindow = timeWindows[value ?? '30d'];
|
||||
|
||||
const handleCustom = useCallback(() => {
|
||||
pushModal('DateRangerPicker', {
|
||||
onChange: ({ startDate, endDate }) => {
|
||||
onStartDateChange(format(startOfDay(startDate), 'yyyy-MM-dd HH:mm:ss'));
|
||||
onEndDateChange(format(endOfDay(endDate), 'yyyy-MM-dd HH:mm:ss'));
|
||||
onChange('custom');
|
||||
},
|
||||
startDate: startDate ? new Date(startDate) : undefined,
|
||||
endDate: endDate ? new Date(endDate) : undefined,
|
||||
});
|
||||
}, [startDate, endDate]);
|
||||
|
||||
useEffect(() => {
|
||||
return bind(document, {
|
||||
type: 'keydown',
|
||||
listener(event) {
|
||||
if (shouldIgnoreKeypress(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDateRangerPickerOpen.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const match = Object.values(timeWindows).find(
|
||||
(tw) => event.key === tw.shortcut.toLowerCase(),
|
||||
);
|
||||
if (match?.key === 'custom') {
|
||||
handleCustom();
|
||||
} else if (match) {
|
||||
onChange(match.key);
|
||||
}
|
||||
},
|
||||
});
|
||||
}, [handleCustom]);
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
icon={CalendarIcon}
|
||||
className={cn('justify-start', className)}
|
||||
>
|
||||
{timeWindow?.label}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
<DropdownMenuLabel>Time window</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows['30min'].key)}>
|
||||
{timeWindows['30min'].label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows['30min'].shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows.lastHour.key)}>
|
||||
{timeWindows.lastHour.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.lastHour.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows.today.key)}>
|
||||
{timeWindows.today.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.today.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows.yesterday.key)}>
|
||||
{timeWindows.yesterday.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.yesterday.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows['7d'].key)}>
|
||||
{timeWindows['7d'].label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows['7d'].shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows['30d'].key)}>
|
||||
{timeWindows['30d'].label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows['30d'].shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows['6m'].key)}>
|
||||
{timeWindows['6m'].label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows['6m'].shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows['12m'].key)}>
|
||||
{timeWindows['12m'].label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows['12m'].shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
onClick={() => onChange(timeWindows.monthToDate.key)}
|
||||
>
|
||||
{timeWindows.monthToDate.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.monthToDate.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows.lastMonth.key)}>
|
||||
{timeWindows.lastMonth.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.lastMonth.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
onClick={() => onChange(timeWindows.yearToDate.key)}
|
||||
>
|
||||
{timeWindows.yearToDate.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.yearToDate.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => onChange(timeWindows.lastYear.key)}>
|
||||
{timeWindows.lastYear.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.lastYear.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onClick={() => handleCustom()}>
|
||||
{timeWindows.custom.label}
|
||||
<DropdownMenuShortcut>
|
||||
{timeWindows.custom.shortcut}
|
||||
</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user