diff --git a/package-lock.json b/package-lock.json index 7e1e4d3..f286e1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,9 @@ "@tanstack/react-query": "^5.51.1", "@tanstack/react-query-devtools": "^5.51.18", "@tanstack/react-table": "^8.20.5", + "@types/chroma-js": "^2.4.4", "axios": "^1.7.2", + "chroma-js": "^3.1.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "firebase": "^10.12.2", @@ -4687,6 +4689,11 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@types/chroma-js": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.4.tgz", + "integrity": "sha512-/DTccpHTaKomqussrn+ciEvfW4k6NAHzNzs/sts1TCqg333qNxOhy8TNIoQCmbGG3Tl8KdEhkGAssb1n3mTXiQ==" + }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", @@ -4984,6 +4991,11 @@ "node": ">= 6" } }, + "node_modules/chroma-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.1.2.tgz", + "integrity": "sha512-IJnETTalXbsLx1eKEgx19d5L6SRM7cH4vINw/99p/M11HCuXGRWL+6YmCm7FWFGIo6dtWuQoQi1dc5yQ7ESIHg==" + }, "node_modules/class-variance-authority": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", diff --git a/package.json b/package.json index ff21043..126645a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "@tanstack/react-query": "^5.51.1", "@tanstack/react-query-devtools": "^5.51.18", "@tanstack/react-table": "^8.20.5", + "@types/chroma-js": "^2.4.4", "axios": "^1.7.2", + "chroma-js": "^3.1.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "firebase": "^10.12.2", diff --git a/src/components/connections/queries/mongo/VectorSearchTabs.tsx b/src/components/connections/queries/mongo/VectorSearchTabs.tsx index 68bb598..c7483a4 100644 --- a/src/components/connections/queries/mongo/VectorSearchTabs.tsx +++ b/src/components/connections/queries/mongo/VectorSearchTabs.tsx @@ -221,6 +221,7 @@ const VectorSearchTabs = ({ handleSave({ index_created: true, num_candidates: 100, + limit: 5, }); }} isLoading={firstStepLoading} diff --git a/src/components/editor/fastboard-components/group-chart/FastboardGroupChart.tsx b/src/components/editor/fastboard-components/group-chart/FastboardGroupChart.tsx index ed42745..ef38db2 100644 --- a/src/components/editor/fastboard-components/group-chart/FastboardGroupChart.tsx +++ b/src/components/editor/fastboard-components/group-chart/FastboardGroupChart.tsx @@ -4,7 +4,15 @@ import { ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart"; -import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"; +import { + Bar, + BarChart, + CartesianGrid, + Label, + Pie, + PieChart, + XAxis, +} from "recharts"; import CustomSkeleton from "@/components/shared/CustomSkeleton"; import { FastboardGroupChartProperties } from "@/types/editor/group-chart-types"; import useData from "@/hooks/useData"; @@ -12,8 +20,9 @@ import { ComponentId, ComponentType } from "@/types/editor"; import { useEffect } from "react"; import { useSetRecoilState } from "recoil"; import { propertiesDrawerState } from "@/atoms/editor"; -import { QueryMethod } from "@/types/connections"; import { useTheme } from "next-themes"; +import { generatePalette } from "@/lib/colors"; +import { Card } from "@nextui-org/react"; const groupData = (data: any[], groupBy: string) => { return data.reduce((acc, item) => { @@ -26,6 +35,163 @@ const groupData = (data: any[], groupBy: string) => { }, {}); }; +const BarChartComponent = ({ + chartConfig, + groupBy, + countedData, + minimizedLabels, + theme, + barsColor, +}: { + chartConfig: ChartConfig; + groupBy: string; + countedData: any[]; + minimizedLabels: boolean; + theme: string | undefined; + barsColor: { light: string; dark: string }; +}) => { + return ( + + + + value.slice(0, 5) + "..." : undefined + } + /> + + } /> + + + + ); +}; + +const PieChartComponent = ({ + countedData, + groupBy, + minimizedLabels, + theme, + barsColor, +}: { + countedData: any[]; + groupBy: string; + minimizedLabels: boolean; + theme: string | undefined; + barsColor: { light: string; dark: string }; +}) => { + const pieChartConfig = Object.values(countedData).reduce((acc, item) => { + return { + ...acc, + [item.label]: { + label: item.label, + color: "hsl(var(--chart-1))", + }, + }; + }, {}) satisfies ChartConfig; + + const baseColor = theme === "light" ? barsColor.light : barsColor.dark; + + const paletteSize = Object.keys(countedData).length; + + const palette = generatePalette(baseColor, paletteSize); + + return ( +
+ + + { + return { + ...data, + fill: palette[index], + }; + }) + : [] + } + paddingAngle={1} + label={ + !minimizedLabels + ? ({ cx, cy, midAngle, outerRadius, index }) => { + const RADIAN = Math.PI / 180; + const radius = outerRadius * 1.15; + const x = cx + radius * Math.cos(-midAngle * RADIAN); + const y = cy + radius * Math.sin(-midAngle * RADIAN); + + return ( + cx ? "start" : "end"} + dominantBaseline="central" + > + {countedData[index].count} + + ); + } + : undefined + } + dataKey="count" + nameKey={"label"} + innerRadius={"50%"} + > + + } + /> + + +
+ ); +}; + const FastboardGroupChart = ({ id, properties, @@ -44,6 +210,7 @@ const FastboardGroupChart = ({ emptyMessage, minimizedLabels, barsColor, + layout, } = properties; const setProperties = useSetRecoilState(propertiesDrawerState); @@ -69,7 +236,7 @@ const FastboardGroupChart = ({ }, [keys]); const chartConfig = { - desktop: { + [groupBy]: { label: groupBy, color: "hsl(var(--chart-1))", }, @@ -98,33 +265,25 @@ const FastboardGroupChart = ({ className={"w-full h-[calc(100%-65px)] rounded-xl"} onlyRenderOnLoad > - - - - value.slice(0, 5) + "..." - : undefined - } - /> - - } /> - - - + {layout === "bar" && ( + + )} + {layout === "pie" && ( + + )} {!dataFetching && data.length === 0 && ( diff --git a/src/components/editor/fastboard-components/group-chart/properties/FastboardGroupChartProperties.tsx b/src/components/editor/fastboard-components/group-chart/properties/FastboardGroupChartProperties.tsx index c4fb1fc..2d14025 100644 --- a/src/components/editor/fastboard-components/group-chart/properties/FastboardGroupChartProperties.tsx +++ b/src/components/editor/fastboard-components/group-chart/properties/FastboardGroupChartProperties.tsx @@ -1,11 +1,19 @@ import { FastboardGroupChartProperties } from "@/types/editor/group-chart-types"; -import { Accordion, AccordionItem, Checkbox, Input } from "@nextui-org/react"; +import { + Accordion, + AccordionItem, + Button, + ButtonGroup, + Checkbox, + Input, +} from "@nextui-org/react"; import QuerySelection from "@/components/editor/QuerySelection"; import GroupKeySelect from "@/components/editor/fastboard-components/group-chart/properties/GroupKeySelect"; import { QueryType } from "@/types/connections"; import ColorPicker from "@/components/shared/ColorPicker"; import { useTheme } from "next-themes"; import { queryToQueryData } from "@/lib/rest-queries"; +import CheckBoxProperty from "@/components/shared/CheckBoxProperty"; const FastboardGroupChartPropertiesComponent = ({ properties, @@ -25,6 +33,7 @@ const FastboardGroupChartPropertiesComponent = ({ subtitle, minimizedLabels, barsColor, + layout, } = properties; return ( @@ -118,19 +127,49 @@ const FastboardGroupChartPropertiesComponent = ({ - { - onValueChange({ - ...properties, - minimizedLabels: e.target.checked, - }); - }} - > - Minimized labels - +
+

Layout

+ + + + +
+
+ { + onValueChange({ + ...properties, + minimizedLabels: value, + }); + }} + /> +
{ if (theme === "light") { diff --git a/src/lib/colors.ts b/src/lib/colors.ts new file mode 100644 index 0000000..4e59d0b --- /dev/null +++ b/src/lib/colors.ts @@ -0,0 +1,5 @@ +import chroma from "chroma-js"; + +export function generatePalette(baseColor: string, n: number): string[] { + return chroma.scale([chroma(baseColor).brighten(2), baseColor]).colors(n); +} diff --git a/src/types/editor/group-chart-types.ts b/src/types/editor/group-chart-types.ts index 310ba5d..be8bfa7 100644 --- a/src/types/editor/group-chart-types.ts +++ b/src/types/editor/group-chart-types.ts @@ -10,6 +10,7 @@ export class FastboardGroupChartProperties { emptyMessage: string = "No data to display."; minimizedLabels: boolean = false; barsColor: Color = Color.primary(); + layout: "bar" | "pie" = "bar"; static default(): FastboardGroupChartProperties { return new FastboardGroupChartProperties();