Skip to content

Commit 91223ed

Browse files
committed
fix(cubejs-playground): update query builder * 4
1 parent 1adb0ab commit 91223ed

File tree

4 files changed

+82
-57
lines changed

4 files changed

+82
-57
lines changed

packages/cubejs-playground/src/QueryBuilderV2/QueryBuilderChartResults.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export function QueryBuilderChartResults({
5757
<ChartContainer
5858
ref={containerRef}
5959
style={{
60-
maxHeight: `${MAX_HEIGHT}px`,
61-
height: `${MAX_HEIGHT}px`,
60+
maxHeight: MAX_HEIGHT,
61+
height: MAX_HEIGHT,
6262
overflow,
6363
}}
6464
>

packages/cubejs-playground/src/QueryBuilderV2/QueryBuilderSidePanel.tsx

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export function QueryBuilderSidePanel({
7373
setQuery,
7474
usedCubes,
7575
usedMembers,
76+
queryStats,
7677
members,
7778
missingCubes,
7879
apiVersion,
@@ -109,19 +110,13 @@ export function QueryBuilderSidePanel({
109110
? cubesOrViews.filter((cube) => usedCubes[0] === cube.name)
110111
: cubesOrViews.filter((cube) => joinableCubes.includes(cube));
111112

112-
const [openCubes, setOpenCubes] = useState<Set<string>>(
113-
isQueryEmpty
114-
? cubesOrViews.length
115-
? new Set([cubesOrViews[0].name])
116-
: new Set()
117-
: new Set(usedCubes)
118-
);
113+
const [openCubes, setOpenCubes] = useState<Set<string>>(new Set());
119114

120115
useLayoutEffect(() => {
121116
if (isQueryEmpty) {
122117
setOpenCubes(cubesOrViews.length === 1 ? new Set([cubesOrViews[0].name]) : new Set());
123118
}
124-
}, [meta, cubesOrViews.length, selectedType]);
119+
}, [cubesOrViews.length, selectedType]);
125120

126121
const highlightedCubes = appliedFilterString ? usedCubes : [];
127122

@@ -341,21 +336,29 @@ export function QueryBuilderSidePanel({
341336
/>
342337
))}
343338
{cubesOrViews
344-
.filter((cube) => (appliedFilterString ? filteredCubes.includes(cube.name) : true))
345-
.map((item) => (
339+
.filter((cube) =>
340+
appliedFilterString
341+
? // If filter is applied, show only filtered cubes
342+
filteredCubes.includes(cube.name)
343+
: viewMode === 'query'
344+
? // In query mode, show only used cubes
345+
usedCubes.includes(cube.name)
346+
: true
347+
)
348+
.map((cube) => (
346349
<SidePanelCubeItem
347-
key={item.name}
348-
isNonJoinable={!allJoinableCubes.includes(item) && !usedCubes.includes(item.name)}
349-
isOpen={openCubes.has(item.name)}
350+
key={cube.name}
351+
isNonJoinable={!allJoinableCubes.includes(cube) && !usedCubes.includes(cube.name)}
352+
isOpen={openCubes.has(cube.name)}
350353
filterString={appliedFilterString}
351-
cubeName={item.name}
354+
cubeName={cube.name}
352355
mode={viewMode}
353356
rightIcon={isQueryEmpty ? 'arrow' : 'plus'}
354357
onToggle={(isOpen) => {
355-
onCubeToggle(item.name, isOpen);
358+
onCubeToggle(cube.name, isOpen);
356359
}}
357360
onMemberToggle={(name) => {
358-
onMemberToggle(item.name, name);
361+
onMemberToggle(cube.name, name);
359362
}}
360363
onHierarchyToggle={onHierarchyToggle}
361364
/>
@@ -364,15 +367,11 @@ export function QueryBuilderSidePanel({
364367
);
365368
}, [
366369
viewMode,
367-
meta,
370+
queryStats,
368371
[...openCubes.values()].join(),
369372
appliedFilterString,
370-
usedCubes.join(),
371-
cubesOrViews.length,
372373
memberViewType,
373374
selectedType,
374-
isQueryEmpty,
375-
missingCubes.join(),
376375
]);
377376

378377
const onApplyQuery = useCallback(async (query) => {

packages/cubejs-playground/src/QueryBuilderV2/icons/ChevronIcon.tsx

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
import { CubeIconProps, UpIcon } from '@cube-dev/ui-kit';
2-
import { memo, useEffect, useRef, useState } from 'react';
1+
import { CubeIconProps, tasty, UpIcon } from '@cube-dev/ui-kit';
2+
import { memo, useEffect, useState } from 'react';
3+
4+
const StyledUpIcon = tasty(UpIcon, {
5+
styles: {
6+
transformOrigin: 'center',
7+
transition: 'rotate linear 120ms, scale linear 120ms',
8+
},
9+
});
310

411
export type ChevronIconProps = {
512
/**
@@ -12,59 +19,52 @@ export type ChevronIconProps = {
1219
type Direction = 'left' | 'right' | 'top' | 'bottom';
1320

1421
const rotationByDirection: Record<Direction, number> = {
15-
bottom: -180,
16-
left: -90,
1722
top: 0,
1823
right: 90,
24+
bottom: 180,
25+
left: 270,
1926
};
2027

21-
const rotationByFlippedDirection: Record<Direction, number> = {
22-
bottom: 0,
23-
left: 90,
24-
top: -180,
25-
right: -90,
26-
};
28+
function flipRotation(rotation: number) {
29+
return (rotation + 180) % 360;
30+
}
2731

2832
export const ChevronIcon = memo(function ChevronIcon(props: ChevronIconProps) {
2933
const { direction = 'bottom', color, ...iconProps } = props;
3034
const [rotate, setRotate] = useState(rotationByDirection[direction]);
3135
const [flipScale, setFlipScale] = useState(1); // Tracks flipping: 1 (normal) or -1 (flipped)
3236

3337
useEffect(() => {
34-
let nextRotate =
35-
flipScale === 1 ? rotationByDirection[direction] : rotationByFlippedDirection[direction];
38+
let nextRotate = rotationByDirection[direction];
39+
40+
if (flipScale === -1) {
41+
nextRotate = flipRotation(nextRotate);
42+
}
3643

3744
// Check if the change is to the opposite direction
38-
const isOpposite = Math.abs(rotate - nextRotate) === 180;
45+
const isOpposite = Math.abs((rotate - nextRotate) % 360) === 180;
3946

4047
if (isOpposite) {
4148
// Toggle the flip state
4249
setFlipScale((prev) => -prev); // Alternates between 1 and -1
4350
} else {
44-
if (flipScale === -1) {
45-
nextRotate = rotationByFlippedDirection[direction];
46-
}
47-
48-
// Calculate the shortest rotation path
49-
let adjustedNextRotate = nextRotate;
50-
while (rotate - adjustedNextRotate > 180) {
51-
adjustedNextRotate += 360;
51+
while (rotate - nextRotate > 180) {
52+
nextRotate += 360;
5253
}
53-
while (rotate - adjustedNextRotate < -180) {
54-
adjustedNextRotate -= 360;
54+
while (rotate - nextRotate < -180) {
55+
nextRotate -= 360;
5556
}
5657

57-
setRotate(adjustedNextRotate);
58+
setRotate(nextRotate);
5859
}
5960
}, [direction]);
6061

6162
return (
62-
<UpIcon
63+
<StyledUpIcon
6364
{...iconProps}
6465
style={{
65-
transformOrigin: 'center',
66-
transform: `rotate(${rotate}deg) scaleY(${flipScale})`,
67-
transition: 'transform linear 120ms',
66+
rotate: `${rotate}deg`,
67+
scale: `1 ${flipScale}`,
6868
}}
6969
/>
7070
);

packages/cubejs-playground/src/components/QueryTabs/QueryTabs.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,44 @@ import { useChartRendererStateMethods } from './ChartRendererStateProvider';
1717

1818
const { TabPane } = Tabs;
1919

20-
const StyledTabs = styled(Tabs)`
20+
export const StyledTabs = styled(Tabs)`
21+
margin-top: 0;
22+
display: grid;
23+
max-width: 100%;
24+
grid-template-rows: min-content 1fr;
25+
overflow: hidden;
26+
2127
& .ant-tabs-nav {
22-
background: #fff;
23-
padding: 12px 16px 0;
28+
padding: 0;
2429
margin: 0;
30+
overflow: hidden;
31+
background-color: white;
32+
}
33+
34+
& .ant-tabs-nav-wrap {
35+
padding: 8px 8px 0;
2536
}
2637
2738
& .ant-tabs-extra-content {
28-
margin-left: 32px;
39+
padding: 8px;
40+
place-self: start;
41+
}
42+
43+
& .ant-tabs-tab {
44+
margin: 0 24px 0 0;
45+
}
46+
47+
& .ant-tabs-content-holder {
48+
position: relative;
49+
display: flex;
50+
}
51+
52+
& .ant-tabs-tab {
53+
border-radius: var(--radius) var(--radius) 0 0 !important;
2954
}
3055
`;
3156

57+
3258
type QueryTab = {
3359
id: string;
3460
query: Query;
@@ -246,7 +272,7 @@ export function QueryTabs({
246272
}),
247273
});
248274
}
249-
275+
250276
function setTabName(tabId: string, name: string) {
251277
saveTabs({
252278
...queryTabs,
@@ -327,7 +353,7 @@ export function QueryTabs({
327353
onKeyDown={(e) => {
328354
if (e.key === 'Enter') {
329355
setEditableTabId(undefined);
330-
356+
331357
if (editableTabValue.trim()) {
332358
setTabName(tab.id, editableTabValue.trim());
333359
setEditableTabValue('');

0 commit comments

Comments
 (0)