feat(ai): add ai chat to dashboard
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
|
||||
import { chartTypes } from '@openpanel/constants';
|
||||
import { objectToZodEnums } from '@openpanel/validation';
|
||||
import { type IChartType, objectToZodEnums } from '@openpanel/validation';
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
@@ -32,10 +32,14 @@ import { changeChartType } from './reportSlice';
|
||||
|
||||
interface ReportChartTypeProps {
|
||||
className?: string;
|
||||
value: IChartType;
|
||||
onChange: (type: IChartType) => void;
|
||||
}
|
||||
export function ReportChartType({ className }: ReportChartTypeProps) {
|
||||
const dispatch = useDispatch();
|
||||
const type = useSelector((state) => state.report.chartType);
|
||||
export function ReportChartType({
|
||||
className,
|
||||
value,
|
||||
onChange,
|
||||
}: ReportChartTypeProps) {
|
||||
const items = objectToZodEnums(chartTypes).map((key) => ({
|
||||
label: chartTypes[key],
|
||||
value: key,
|
||||
@@ -61,10 +65,10 @@ export function ReportChartType({ className }: ReportChartTypeProps) {
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
icon={Icons[type]}
|
||||
icon={Icons[value]}
|
||||
className={cn('justify-start', className)}
|
||||
>
|
||||
{items.find((item) => item.value === type)?.label}
|
||||
{items.find((item) => item.value === value)?.label}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
@@ -77,7 +81,7 @@ export function ReportChartType({ className }: ReportChartTypeProps) {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={item.value}
|
||||
onClick={() => dispatch(changeChartType(item.value))}
|
||||
onClick={() => onChange(item.value)}
|
||||
className="group"
|
||||
>
|
||||
{item.label}
|
||||
|
||||
@@ -6,17 +6,36 @@ import {
|
||||
isMinuteIntervalEnabledByRange,
|
||||
} from '@openpanel/constants';
|
||||
|
||||
import { Combobox } from '../ui/combobox';
|
||||
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 }: ReportIntervalProps) {
|
||||
const dispatch = useDispatch();
|
||||
const interval = useSelector((state) => state.report.interval);
|
||||
const range = useSelector((state) => state.report.range);
|
||||
const chartType = useSelector((state) => state.report.chartType);
|
||||
export function ReportInterval({
|
||||
className,
|
||||
interval,
|
||||
onChange,
|
||||
chartType,
|
||||
range,
|
||||
}: ReportIntervalProps) {
|
||||
if (
|
||||
chartType !== 'linear' &&
|
||||
chartType !== 'histogram' &&
|
||||
@@ -28,37 +47,66 @@ export function ReportInterval({ className }: ReportIntervalProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = [
|
||||
{
|
||||
value: 'minute',
|
||||
label: 'Minute',
|
||||
disabled: !isMinuteIntervalEnabledByRange(range),
|
||||
},
|
||||
{
|
||||
value: 'hour',
|
||||
label: 'Hour',
|
||||
disabled: !isHourIntervalEnabledByRange(range),
|
||||
},
|
||||
{
|
||||
value: 'day',
|
||||
label: 'Day',
|
||||
},
|
||||
{
|
||||
value: 'month',
|
||||
label: 'Month',
|
||||
disabled: range === 'today' || range === 'lastHour' || range === '30min',
|
||||
},
|
||||
];
|
||||
|
||||
const selectedItem = items.find((item) => item.value === interval);
|
||||
|
||||
return (
|
||||
<Combobox
|
||||
icon={ClockIcon}
|
||||
className={className}
|
||||
placeholder="Interval"
|
||||
onChange={(value) => {
|
||||
dispatch(changeInterval(value));
|
||||
}}
|
||||
value={interval}
|
||||
items={[
|
||||
{
|
||||
value: 'minute',
|
||||
label: 'Minute',
|
||||
disabled: !isMinuteIntervalEnabledByRange(range),
|
||||
},
|
||||
{
|
||||
value: 'hour',
|
||||
label: 'Hour',
|
||||
disabled: !isHourIntervalEnabledByRange(range),
|
||||
},
|
||||
{
|
||||
value: 'day',
|
||||
label: 'Day',
|
||||
},
|
||||
{
|
||||
value: 'month',
|
||||
label: 'Month',
|
||||
disabled:
|
||||
range === 'today' || range === 'lastHour' || range === '30min',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user