Skip to content

Commit

Permalink
Merge pull request #586 from openchatai/ui/analytics-2
Browse files Browse the repository at this point in the history
Real Analytics
  • Loading branch information
faltawy authored Jan 27, 2024
2 parents 4f67ca5 + df56977 commit 7f361c3
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use client';

import { SimpleCard } from "@/components/domain/simple-card";
import { getMostCalledActions } from "@/data/analytics";
import { EChart } from "@kbox-labs/react-echarts";
import useSWR from "swr";

type Props = {
copilot_id: string
}

export function AnalyticsActions({ copilot_id }: Props) {
const {
data: mostCalledActions,
} = useSWR([copilot_id, 'copilot-mostCalledActions'], () => getMostCalledActions(copilot_id));
const noMostCalledActions = mostCalledActions?.length === 0 || !mostCalledActions;
return (
<SimpleCard title="Most Called Actions" className="relative overflow-hidden">
{noMostCalledActions ? <div className="h-full flex-center">
<p className="text-center text-xl">No actions called yet</p>
</div> : <EChart
renderer='svg'
className='size-full'
xAxis={{
type: 'category',
data: mostCalledActions?.map((action) => action.operation_id) ?? [],
}}
yAxis={{
type: 'value',
}}
series={{
data: mostCalledActions?.map((action) => (action.count)) ?? [],
type: 'bar',
}}
/>}
</SimpleCard>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";
import { SimpleCard } from "@/components/domain/simple-card";
import useSWR from "swr";
import { getAnalyticsData } from "@/data/analytics";
import { Skeleton } from "@/components/ui/skeleton";
import { Counter } from "@/components/ui/Counter";

export function SimpleAnalyticsCards({ copilot_id }: {
copilot_id: string
}) {
const {
data: analyticsData,
isLoading
} = useSWR([copilot_id, 'copilot-analytics'], () => getAnalyticsData(copilot_id))
return (
<div className="grid grid-cols-3 gap-4">
<SimpleCard title="Number of api calls">
<Skeleton isLoading={isLoading}>
<h2 className="text-lg font-bold">
<Counter value={analyticsData?.api_called_count} />
</h2>
</Skeleton>
</SimpleCard>

<SimpleCard title="Knowledge Base Queries">
<Skeleton isLoading={isLoading}>
<h2 className="text-lg font-bold">
<Counter value={analyticsData?.knowledgebase_called_count} />
</h2>
</Skeleton>
</SimpleCard>

<SimpleCard title="Misc Queries">
<Skeleton isLoading={isLoading}>
<h2 className="text-lg font-bold">
<Counter value={analyticsData?.other_count} />
</h2>
</Skeleton>
</SimpleCard>

</div>
);
}
65 changes: 7 additions & 58 deletions dashboard/app/(copilot)/copilot/[copilot_id]/analytics/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { HeaderShell } from '@/components/domain/HeaderShell'
import { SimpleCard } from '@/components/domain/simple-card'
import { Stack } from '@/components/ui/Stack'
import React from 'react'
import { EChart } from '@kbox-labs/react-echarts'
import { SimpleAnalyticsCards } from './AnalyticsCards';
import { AnalyticsActions } from './AnalyticsActions'

type Props = {
params: {
copilot_id: string
}
}
export default async function AnalyticsPage(props: Props) {

export default function AnalyticsPage(props: Props) {

return (
<Stack direction='column' fluid className='h-full'>
<HeaderShell>
Expand All @@ -18,63 +21,9 @@ export default async function AnalyticsPage(props: Props) {
</h1>
</HeaderShell>
<main className='flex-1 overflow-auto p-4 w-full flex flex-col gap-4'>
<div className='grid grid-cols-3 gap-4'>
<SimpleCard title="Knowledgebase Calls" description="number of knowledgebase calls">
20
</SimpleCard>
<SimpleCard title="Api Calls" description="number of api calls">
20
</SimpleCard>
</div>
<SimpleAnalyticsCards copilot_id={props.params.copilot_id} />
<div className='flex-1 w-full rounded-md grid grid-cols-2 overflow-hidden gap-5'>
<SimpleCard title="Messages Per session">
<EChart
renderer='svg'
className='size-full'
xAxis={{
type: "value",
}}
yAxis={{
type: "value",
}}
series={[{
type: "scatter",
symbolSize: 20,
data: [
[10.0, 8.04],
[8.0, 6.95],
[13.0, 7.58],
[9.0, 8.81],
[11.0, 8.33],
[14.0, 9.96],
[6.0, 7.24],
[4.0, 4.26],
[12.0, 10.84],
[7.0, 4.82],
[5.0, 5.68],
],
}]}
/>
</SimpleCard>
<SimpleCard title="Action Calls">
<EChart
renderer='svg'
className='size-full'
xAxis={{
type: 'category'
}}
yAxis={{
type: 'value',
boundaryGap: [0, '30%']
}}
series={[
{
type: "line",
data: [120, 200, 150, 80, 70, 110, 130],
}
]}
/>
</SimpleCard>
<AnalyticsActions copilot_id={props.params.copilot_id} />
</div>
</main>
</Stack>
Expand Down
59 changes: 59 additions & 0 deletions dashboard/app/(main)/_parts/CopilotCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Stack } from "@/components/ui/Stack";
import { CopilotType } from "@/data/copilot";
import { Link } from "@/lib/router-events";
import { motion } from "framer-motion";
import { GalleryHorizontalEnd } from "lucide-react";
import { format } from "timeago.js";

const IsoMorphicAnimatedLink = (animated:boolean) => animated ? motion(Link) : Link;

export function CopilotCard(
{
copilot,
index,
animated = true
}:{
copilot: CopilotType,
index: number
animated?: boolean
}
) {
const copilotUrl = `/copilot/${copilot.id}`;
const AnimatedLink = IsoMorphicAnimatedLink(animated);
return (
<AnimatedLink
key={copilot.id}
href={copilotUrl}
animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
initial={{
opacity: 0, y: 50,
filter: "blur(10px)"
}}
exit={{
opacity: 0, y: 50,
filter: "blur(10px)"
}}
transition={{ duration: 0.2, delay: 0.1 * index }}
className="group col-span-full lg:col-span-6 xl:col-span-3 copilot"
>
<div
style={{
transitionDelay: `max(0.1s, ${0.1 * index}ms)`,
}}
className="group relative flex h-56 items-center justify-center rounded-lg border-2 transition-colors box">
<div className="flex-center size-20 shadow-lg group-hover:scale-95 transition-transform rounded-lg bg-primary text-gray-100">
<GalleryHorizontalEnd className="size-12" />
</div>
</div>
<Stack className="mt-1.5 ps-1 justify-between" gap={10} fluid>
<h2 className="flex-1 text-sm font-semibold line-clamp-1" title={copilot.name}>
{copilot.name}
</h2>
<p className="text-xs text-black">
Created{" "}
<span className="font-semibold">{format(copilot.created_at)}</span>
</p>
</Stack>
</AnimatedLink>
)
}
47 changes: 7 additions & 40 deletions dashboard/app/(main)/_parts/CopilotsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";
import React from "react";
import { GalleryHorizontalEnd } from "lucide-react";
import { Link } from "@/lib/router-events";
import useSwr from "swr";
import { CopilotType, listCopilots } from "@/data/copilot";
Expand All @@ -10,15 +9,14 @@ import { EmptyBlock } from "@/components/domain/EmptyBlock";
import { filterAtom } from "./Search";
import { useAtomValue } from "jotai";
import { Button } from "@/components/ui/button";
import { format } from "timeago.js";
import { motion, AnimatePresence } from 'framer-motion';
import { Stack } from "@/components/ui/Stack";
import { AnimatePresence } from "framer-motion";
import { CopilotCard } from "./CopilotCard";

function orderByCreatedAt(copilots: CopilotType[]) {
return copilots.sort((a, b) => {
return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
});
}
const AnimatedLink = motion(Link);

export function CopilotsContainer() {
const { data: copilots, isLoading } = useSwr("copilotsList", listCopilots);
Expand Down Expand Up @@ -67,44 +65,13 @@ export function CopilotsContainer() {
) : (
<div className="grid gap-4 py-4 grid-cols-12 copilot__container">
{orderByCreatedAt($copilots).map((copilot, index) => {
const copilotUrl = "/copilot/" + copilot.id;
return (
<AnimatePresence
key={copilot.id}>
<AnimatedLink
key={copilot.id}
href={copilotUrl}
animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
initial={{
opacity: 0, y: 50,
filter: "blur(10px)"
}}
exit={{
opacity: 0, y: 50,
filter: "blur(10px)"
}}
transition={{ duration: 0.2, delay: 0.1 * index }}
className="group col-span-full lg:col-span-6 xl:col-span-3 copilot"
>
<div
style={{
transitionDelay: `max(0.1s, ${0.1 * index}ms)`,
}}
className="group relative flex h-56 items-center justify-center rounded-lg border-2 transition-colors box">
<div className="flex-center size-20 shadow-lg group-hover:scale-95 transition-transform rounded-lg bg-primary text-gray-100">
<GalleryHorizontalEnd className="size-12" />
</div>
</div>
<Stack className="mt-1.5 ps-1 justify-between" gap={10} fluid>
<h2 className="flex-1 text-sm font-semibold line-clamp-1" title={copilot.name}>
{copilot.name}
</h2>
<p className="text-xs text-black">
Created{" "}
<span className="font-semibold">{format(copilot.created_at)}</span>
</p>
</Stack>
</AnimatedLink>
<CopilotCard
copilot={copilot}
index={index}
/>
</AnimatePresence>
);
})}
Expand Down
Loading

0 comments on commit 7f361c3

Please sign in to comment.