Skip to content

Commit 4eafa3d

Browse files
authored
Merge pull request #38 from tinybirdco/fixes
Fixes
2 parents 294da5b + 9a6b584 commit 4eafa3d

File tree

11 files changed

+338
-163
lines changed

11 files changed

+338
-163
lines changed

dashboard/ai-analytics/src/app/api/extract-cost-parameters/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export async function POST(req: Request) {
7474
model: z.enum((availableDimensions?.data?.[0]?.model || ['gpt-4']) as [string, ...string[]]).optional(),
7575
provider: z.enum((availableDimensions?.data?.[0]?.provider || ['openai']) as [string, ...string[]]).optional(),
7676
environment: z.enum((availableDimensions?.data?.[0]?.environment || ['production']) as [string, ...string[]]).optional(),
77-
organization: z.enum((availableDimensions?.data?.[0]?.organization || ['']) as [string, ...string[]]).optional(),
77+
organization: z.enum((availableDimensions?.data?.[0]?.organizations || ['']) as [string, ...string[]]).optional(),
7878
project: z.enum((availableDimensions?.data?.[0]?.project || ['']) as [string, ...string[]]).optional(),
7979
user: z.string().optional()
8080
});

dashboard/ai-analytics/src/app/api/search/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export async function POST(req: Request) {
3333
model: z.enum((availableDimensions?.data?.[0]?.model || ['gpt-4']) as [string, ...string[]]).optional(),
3434
provider: z.enum((availableDimensions?.data?.[0]?.provider || ['openai']) as [string, ...string[]]).optional(),
3535
environment: z.enum((availableDimensions?.data?.[0]?.environment || ['production']) as [string, ...string[]]).optional(),
36-
organization: z.enum((availableDimensions?.data?.[0]?.organization || ['']) as [string, ...string[]]).optional(),
36+
organization: z.enum((availableDimensions?.data?.[0]?.organizations || ['']) as [string, ...string[]]).optional(),
3737
project: z.enum((availableDimensions?.data?.[0]?.project || ['']) as [string, ...string[]]).optional(),
3838
date_range: z.enum(['last month', 'last week'] as [string, ...string[]]).optional(),
3939
});
@@ -43,6 +43,7 @@ export async function POST(req: Request) {
4343
Common values: ${JSON.stringify(availableDimensions?.data?.[0] || {}, null, 2)}.
4444
Return only valid values from the provided dimensions, fix typos when necessary.`;
4545
console.log(systemPromptText);
46+
4647

4748
const result = await generateObject({
4849
model: wrappedOpenAI,

dashboard/ai-analytics/src/app/components/CostPredictionModal.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,20 @@ export default function CostPredictionModal({
323323
}
324324
};
325325

326+
const calculateButtonRef = useRef<HTMLButtonElement>(null);
327+
326328
const handleExampleClick = (example: string) => {
327329
setQuery(example);
328330
if (inputRef.current) {
329331
inputRef.current.focus();
330332
}
333+
334+
// Use setTimeout to ensure the query state is updated before clicking the button
335+
setTimeout(() => {
336+
if (calculateButtonRef.current) {
337+
calculateButtonRef.current.click();
338+
}
339+
}, 0);
331340
};
332341

333342
const calculateCosts = (usageData: UsageDataItem[], params: CostParameters) => {
@@ -1055,6 +1064,7 @@ export default function CostPredictionModal({
10551064

10561065
<div className="-mx-4 mt-4"> {/* Changed pt-4 to mt-4 */}
10571066
<button
1067+
ref={calculateButtonRef}
10581068
type="submit"
10591069
disabled={isLoading || !query.trim()}
10601070
className={`w-full py-4 transition-colors ${
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { useState, useRef, useEffect } from 'react';
2+
3+
interface ResizableSplitViewProps {
4+
topComponent: React.ReactNode;
5+
bottomComponent: React.ReactNode;
6+
initialTopHeight?: string;
7+
minTopHeight?: string;
8+
minBottomHeight?: string;
9+
}
10+
11+
export default function ResizableSplitView({
12+
topComponent,
13+
bottomComponent,
14+
initialTopHeight = '60vh',
15+
minTopHeight = '30vh',
16+
minBottomHeight = '20vh'
17+
}: ResizableSplitViewProps) {
18+
const [topHeight, setTopHeight] = useState(initialTopHeight);
19+
const [isDragging, setIsDragging] = useState(false);
20+
const containerRef = useRef<HTMLDivElement>(null);
21+
const dragHandleRef = useRef<HTMLDivElement>(null);
22+
23+
// Convert vh to pixels
24+
const vhToPixels = (vh: string) => {
25+
const vhValue = parseFloat(vh);
26+
return (window.innerHeight * vhValue) / 100;
27+
};
28+
29+
// Convert pixels to vh
30+
const pixelsToVh = (pixels: number) => {
31+
return `${(pixels / window.innerHeight) * 100}vh`;
32+
};
33+
34+
// Handle mouse down on the drag handle
35+
const handleMouseDown = (e: React.MouseEvent) => {
36+
setIsDragging(true);
37+
e.preventDefault();
38+
};
39+
40+
// Handle mouse move during dragging
41+
const handleMouseMove = (e: MouseEvent) => {
42+
if (!isDragging || !containerRef.current) return;
43+
44+
const containerRect = containerRef.current.getBoundingClientRect();
45+
const containerHeight = containerRect.height;
46+
const mouseY = e.clientY - containerRect.top;
47+
48+
// Calculate new height in pixels
49+
let newHeightPixels = mouseY;
50+
51+
// Apply min/max constraints
52+
const minTopPixels = vhToPixels(minTopHeight);
53+
const minBottomPixels = vhToPixels(minBottomHeight);
54+
55+
if (newHeightPixels < minTopPixels) {
56+
newHeightPixels = minTopPixels;
57+
} else if (containerHeight - newHeightPixels < minBottomPixels) {
58+
newHeightPixels = containerHeight - minBottomPixels;
59+
}
60+
61+
// Convert back to vh and update state
62+
setTopHeight(pixelsToVh(newHeightPixels));
63+
};
64+
65+
// Handle mouse up to stop dragging
66+
const handleMouseUp = () => {
67+
setIsDragging(false);
68+
};
69+
70+
// Add and remove event listeners
71+
useEffect(() => {
72+
if (isDragging) {
73+
window.addEventListener('mousemove', handleMouseMove);
74+
window.addEventListener('mouseup', handleMouseUp);
75+
}
76+
77+
return () => {
78+
window.removeEventListener('mousemove', handleMouseMove);
79+
window.removeEventListener('mouseup', handleMouseUp);
80+
};
81+
}, [isDragging]);
82+
83+
return (
84+
<div
85+
ref={containerRef}
86+
className="flex flex-col w-full h-full relative bg-[#262626] rounded-lg overflow-hidden"
87+
>
88+
{/* Top component */}
89+
<div style={{ height: topHeight }} className="w-full overflow-hidden">
90+
{topComponent}
91+
</div>
92+
93+
{/* Drag handle */}
94+
<div
95+
ref={dragHandleRef}
96+
className={`h-2 bg-[rgb(53, 53, 53)] hover:bg-[var(--accent)] cursor-row-resize flex items-center justify-center transition-colors ${
97+
isDragging ? 'bg-[var(--accent)]' : ''
98+
}`}
99+
onMouseDown={handleMouseDown}
100+
>
101+
<div className="w-8 h-1 bg-gray-500 rounded-full"></div>
102+
</div>
103+
104+
{/* Bottom component */}
105+
<div className="flex-1 w-full overflow-hidden">
106+
{bottomComponent}
107+
</div>
108+
</div>
109+
);
110+
}

dashboard/ai-analytics/src/app/components/TabbedPane.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ const getEnvironmentIcon = (env: string) => {
9797
};
9898

9999
interface TabbedPaneProps {
100-
filters: Record<string, string>;
101-
onFilterUpdate: (dimension: string, name: string, values: string[]) => void;
100+
filters: Record<string, string | undefined>;
101+
onFilterUpdate: (dimension: string, dimensionName: string, values: string[]) => void;
102102
}
103103

104104
export default function TabbedPane({ filters, onFilterUpdate }: TabbedPaneProps) {
@@ -112,7 +112,7 @@ export default function TabbedPane({ filters, onFilterUpdate }: TabbedPaneProps)
112112
const [selectedValues, setSelectedValues] = useState<string[]>([]);
113113

114114
// Pass all filters to the query
115-
const { data, isLoading, error } = useGenericCounter(selectedTab, filters);
115+
const { data, isLoading, error } = useGenericCounter(selectedTab, filters as Record<string, string>);
116116

117117
// Add effect to sync with URL params
118118
useEffect(() => {

0 commit comments

Comments
 (0)