feat(ai): add ai chat to dashboard
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import Chat from '@/components/chat/chat';
|
||||
import { db, getOrganizationBySlug } from '@openpanel/db';
|
||||
import type { UIMessage } from 'ai';
|
||||
|
||||
export default async function ChatPage({
|
||||
params,
|
||||
}: {
|
||||
params: { organizationSlug: string; projectId: string };
|
||||
}) {
|
||||
const { projectId } = await params;
|
||||
const [organization, chat] = await Promise.all([
|
||||
getOrganizationBySlug(params.organizationSlug),
|
||||
db.chat.findFirst({
|
||||
where: {
|
||||
projectId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const messages = ((chat?.messages as UIMessage[]) || []).slice(-10);
|
||||
return (
|
||||
<Chat
|
||||
projectId={projectId}
|
||||
initialMessages={messages}
|
||||
organization={organization}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { cn } from '@/utils/cn';
|
||||
import { useSelectedLayoutSegments } from 'next/navigation';
|
||||
|
||||
const NOT_MIGRATED_PAGES = ['reports'];
|
||||
@@ -16,6 +17,13 @@ export default function LayoutContent({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pb-20 transition-all max-lg:mt-12 lg:pl-72">{children}</div>
|
||||
<div
|
||||
className={cn(
|
||||
'pb-20 transition-all max-lg:mt-12 lg:pl-72',
|
||||
segments.includes('chat') && 'pb-0',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
PlusIcon,
|
||||
ScanEyeIcon,
|
||||
ServerIcon,
|
||||
SparklesIcon,
|
||||
UsersIcon,
|
||||
WallpaperIcon,
|
||||
} from 'lucide-react';
|
||||
@@ -23,6 +24,7 @@ import { usePathname } from 'next/navigation';
|
||||
|
||||
import { ProjectLink } from '@/components/links';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { CommandShortcut } from '@/components/ui/command';
|
||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||
import type { IServiceDashboards, IServiceOrganization } from '@openpanel/db';
|
||||
import { differenceInDays, format } from 'date-fns';
|
||||
@@ -174,15 +176,25 @@ export default function LayoutMenu({
|
||||
</div>
|
||||
</ProjectLink>
|
||||
)}
|
||||
<ProjectLink
|
||||
href={'/chat'}
|
||||
className={cn('rounded p-2 row gap-2 hover:bg-def-200 items-center')}
|
||||
>
|
||||
<SparklesIcon size={20} />
|
||||
<div className="flex-1 col gap-1">
|
||||
<div className="font-medium">Ask AI</div>
|
||||
</div>
|
||||
<CommandShortcut>⌘K</CommandShortcut>
|
||||
</ProjectLink>
|
||||
<ProjectLink
|
||||
href={'/reports'}
|
||||
className={cn('rounded p-2 row gap-2 hover:bg-def-200')}
|
||||
className={cn('rounded p-2 row gap-2 hover:bg-def-200 items-center')}
|
||||
>
|
||||
<ChartLineIcon size={20} />
|
||||
<div className="flex-1 col gap-1">
|
||||
<div className="font-medium">Create report</div>
|
||||
</div>
|
||||
<PlusIcon size={16} className="text-muted-foreground" />
|
||||
<CommandShortcut>⌘J</CommandShortcut>
|
||||
</ProjectLink>
|
||||
</div>
|
||||
<LinkWithIcon icon={WallpaperIcon} label="Overview" href={'/'} />
|
||||
|
||||
@@ -7,8 +7,10 @@ import { ReportInterval } from '@/components/report/ReportInterval';
|
||||
import { ReportLineType } from '@/components/report/ReportLineType';
|
||||
import { ReportSaveButton } from '@/components/report/ReportSaveButton';
|
||||
import {
|
||||
changeChartType,
|
||||
changeDateRanges,
|
||||
changeEndDate,
|
||||
changeInterval,
|
||||
changeStartDate,
|
||||
ready,
|
||||
reset,
|
||||
@@ -74,7 +76,13 @@ export default function ReportEditor({
|
||||
</div>
|
||||
</SheetTrigger>
|
||||
<div className="col-span-4 grid grid-cols-2 gap-2 md:grid-cols-4">
|
||||
<ReportChartType className="min-w-0 flex-1" />
|
||||
<ReportChartType
|
||||
className="min-w-0 flex-1"
|
||||
onChange={(type) => {
|
||||
dispatch(changeChartType(type));
|
||||
}}
|
||||
value={report.chartType}
|
||||
/>
|
||||
<TimeWindowPicker
|
||||
className="min-w-0 flex-1"
|
||||
onChange={(value) => {
|
||||
@@ -90,7 +98,13 @@ export default function ReportEditor({
|
||||
endDate={report.endDate}
|
||||
startDate={report.startDate}
|
||||
/>
|
||||
<ReportInterval className="min-w-0 flex-1" />
|
||||
<ReportInterval
|
||||
className="min-w-0 flex-1"
|
||||
interval={report.interval}
|
||||
onChange={(newInterval) => dispatch(changeInterval(newInterval))}
|
||||
range={report.range}
|
||||
chartType={report.chartType}
|
||||
/>
|
||||
<ReportLineType className="min-w-0 flex-1" />
|
||||
</div>
|
||||
<div className="col-start-2 row-start-1 text-right md:col-start-6">
|
||||
|
||||
@@ -5,6 +5,7 @@ import Providers from './providers';
|
||||
|
||||
import '@/styles/globals.css';
|
||||
import 'flag-icons/css/flag-icons.min.css';
|
||||
import 'katex/dist/katex.min.css';
|
||||
|
||||
import { GeistMono } from 'geist/font/mono';
|
||||
import { GeistSans } from 'geist/font/sans';
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { MetadataRoute } from 'next';
|
||||
|
||||
export const dynamic = 'static';
|
||||
|
||||
export default function manifest(): MetadataRoute.Manifest {
|
||||
return {
|
||||
id: process.env.NEXT_PUBLIC_DASHBOARD_URL,
|
||||
|
||||
@@ -54,34 +54,34 @@ function AllProviders({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
disableTransitionOnChange
|
||||
defaultTheme="system"
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_OP_CLIENT_ID && (
|
||||
<OpenPanelComponent
|
||||
clientId={process.env.NEXT_PUBLIC_OP_CLIENT_ID}
|
||||
trackScreenViews
|
||||
trackOutgoingLinks
|
||||
trackAttributes
|
||||
/>
|
||||
)}
|
||||
<ReduxProvider store={storeRef.current}>
|
||||
<api.Provider client={trpcClient} queryClient={queryClient}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<NuqsAdapter>
|
||||
<NuqsAdapter>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
disableTransitionOnChange
|
||||
defaultTheme="system"
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_OP_CLIENT_ID && (
|
||||
<OpenPanelComponent
|
||||
clientId={process.env.NEXT_PUBLIC_OP_CLIENT_ID}
|
||||
trackScreenViews
|
||||
trackOutgoingLinks
|
||||
trackAttributes
|
||||
/>
|
||||
)}
|
||||
<ReduxProvider store={storeRef.current}>
|
||||
<api.Provider client={trpcClient} queryClient={queryClient}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<TooltipProvider delayDuration={200}>
|
||||
{children}
|
||||
<NotificationProvider />
|
||||
<Toaster />
|
||||
<ModalProvider />
|
||||
</TooltipProvider>
|
||||
</NuqsAdapter>
|
||||
</QueryClientProvider>
|
||||
</api.Provider>
|
||||
</ReduxProvider>
|
||||
</ThemeProvider>
|
||||
</QueryClientProvider>
|
||||
</api.Provider>
|
||||
</ReduxProvider>
|
||||
</ThemeProvider>
|
||||
</NuqsAdapter>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user