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:
Carl-Gerhard Lindesvärd
2025-10-16 12:27:44 +02:00
committed by GitHub
parent 436e81ecc9
commit 81a7e5d62e
741 changed files with 32695 additions and 16996 deletions

View File

@@ -0,0 +1,121 @@
import { useDispatch, useSelector } from '@/redux';
import { ClockIcon } from 'lucide-react';
import {
isHourIntervalEnabledByRange,
isMinuteIntervalEnabledByRange,
} from '@openpanel/constants';
import { cn } from '@/utils/cn';
import type { IChartRange, IChartType, IInterval } from '@openpanel/validation';
import { Button } from '../ui/button';
import { CommandShortcut } from '../ui/command';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuTrigger,
} from '../ui/dropdown-menu';
import { changeInterval } from './reportSlice';
interface ReportIntervalProps {
className?: string;
interval: IInterval;
onChange: (range: IInterval) => void;
chartType: IChartType;
range: IChartRange;
}
export function ReportInterval({
className,
interval,
onChange,
chartType,
range,
}: ReportIntervalProps) {
if (
chartType !== 'linear' &&
chartType !== 'histogram' &&
chartType !== 'area' &&
chartType !== 'metric' &&
chartType !== 'retention' &&
chartType !== 'conversion'
) {
return null;
}
const items = [
{
value: 'minute',
label: 'Minute',
disabled: !isMinuteIntervalEnabledByRange(range),
},
{
value: 'hour',
label: 'Hour',
disabled: !isHourIntervalEnabledByRange(range),
},
{
value: 'day',
label: 'Day',
},
{
value: 'week',
label: 'Week',
disabled:
range === 'today' ||
range === 'lastHour' ||
range === '30min' ||
range === '7d',
},
{
value: 'month',
label: 'Month',
disabled: range === 'today' || range === 'lastHour' || range === '30min',
},
];
const selectedItem = items.find((item) => item.value === interval);
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
icon={ClockIcon}
className={cn('justify-start', className)}
>
{items.find((item) => item.value === interval)?.label || 'Interval'}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel className="row items-center justify-between">
Select interval
{!!selectedItem && (
<CommandShortcut>{selectedItem?.label}</CommandShortcut>
)}
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
{items.map((item) => (
<DropdownMenuItem
key={item.value}
onClick={() => onChange(item.value as IInterval)}
disabled={item.disabled}
>
{item.label}
{item.value === interval && (
<DropdownMenuShortcut>
<ClockIcon className="size-4" />
</DropdownMenuShortcut>
)}
</DropdownMenuItem>
))}
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
);
}