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,147 @@
import { Badge } from '@/components/ui/badge';
import { Command, CommandInput, CommandItem } from '@/components/ui/command';
import { cn } from '@/utils/cn';
import { ChevronsUpDownIcon } from 'lucide-react';
import VirtualList from 'rc-virtual-list';
import * as React from 'react';
import { useOnClickOutside } from 'usehooks-ts';
import { Button, type ButtonProps } from './button';
import { Checkbox, DumpCheckbox } from './checkbox';
import {
Popover,
PopoverContent,
PopoverPortal,
PopoverTrigger,
} from './popover';
type IValue = any;
type IItem = Record<'value' | 'label', IValue>;
interface ComboboxAdvancedProps {
value: IValue[];
onChange: (value: IValue[]) => void;
items: IItem[];
placeholder: string;
className?: string;
size?: ButtonProps['size'];
}
export function ComboboxAdvanced({
items,
value,
onChange,
placeholder,
className,
size,
}: ComboboxAdvancedProps) {
const [open, setOpen] = React.useState(false);
const [inputValue, setInputValue] = React.useState('');
const ref = React.useRef<HTMLDivElement>(null);
useOnClickOutside(ref as React.RefObject<HTMLElement>, () => setOpen(false));
const selectables = items
.filter((item) => !value.find((s) => s === item.value))
.filter(
(item) =>
(typeof item.label === 'string' &&
item.label.toLowerCase().includes(inputValue.toLowerCase())) ||
(typeof item.value === 'string' &&
item.value.toLowerCase().includes(inputValue.toLowerCase())),
);
const renderItem = (item: IItem) => {
const checked = !!value.find((s) => s === item.value);
return (
<CommandItem
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onSelect={() => {
setInputValue('');
onChange(
value.includes(item.value)
? value.filter((s) => s !== item.value)
: [...value, item.value],
);
}}
className={'flex cursor-pointer items-center gap-2'}
>
<DumpCheckbox checked={checked} />
{item?.label ?? item?.value}
</CommandItem>
);
};
const data = React.useMemo(() => {
return [
...(inputValue === ''
? []
: [
{
value: inputValue,
label: `Pick '${inputValue}'`,
},
]),
...value.map((val) => {
const item = items.find((item) => item.value === val);
return item
? {
value: val,
label: item.label,
}
: {
value: val,
label: val,
};
}),
...selectables,
].filter((item) => item.value);
}, [inputValue, selectables, items]);
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant={'outline'}
onClick={() => setOpen((prev) => !prev)}
className={className}
size={size}
autoHeight
>
<div className="flex w-full flex-wrap gap-1">
{value.length === 0 && placeholder}
{value.map((value) => {
const item = items.find((item) => item.value === value) ?? {
value,
label: value,
};
return <Badge key={String(item.value)}>{item.label}</Badge>;
})}
</div>
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverPortal>
<PopoverContent className="w-full max-w-md p-0" align="start">
<Command shouldFilter={false}>
<CommandInput
placeholder="Search"
value={inputValue}
onValueChange={setInputValue}
/>
<VirtualList
height={Math.min(items.length * 32, 300)}
data={data}
itemHeight={32}
itemKey="value"
>
{renderItem}
</VirtualList>
</Command>
</PopoverContent>
</PopoverPortal>
</Popover>
);
}