Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cubejs-playground): new query builder #8654

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4475d76
feat(cubejs-client/playground): new query builder
tenphi Aug 29, 2024
a2f8969
fix react ts errors
vasilev-alex Aug 30, 2024
82cd144
fix(cubejs-client/playground): typings
tenphi Aug 30, 2024
3c1748c
fix(cubejs-client/playground): e2e tests
tenphi Aug 30, 2024
2241372
fix(cubejs-client/playground): e2e tests * 2
tenphi Aug 30, 2024
e61415e
fix(cubejs-client/playground): e2e tests * 3
tenphi Aug 30, 2024
0c28c69
fix(cubejs-client/playground): e2e tests * 4
tenphi Sep 3, 2024
9e4fee6
fix(cubejs-client/playground): e2e tests * 5
tenphi Sep 3, 2024
ed7384a
fix(cubejs-client/playground): e2e tests * 6
tenphi Sep 3, 2024
446b7c6
fix(cubejs-client/playground): e2e tests * 7
tenphi Sep 3, 2024
83ce76a
fix(cubejs-client/playground): e2e tests * 8
tenphi Sep 3, 2024
5a17f37
fix(cubejs-client/playground): e2e tests * 9
tenphi Sep 3, 2024
ea2bc1c
fix(cubejs-client/playground): e2e tests * 10
tenphi Sep 4, 2024
1d7c18d
fix(cubejs-client/playground): e2e tests * 11
tenphi Sep 4, 2024
5418980
fix(cubejs-client/playground): e2e tests * 12
tenphi Sep 4, 2024
98902bd
fix(cubejs-client/playground): e2e tests * 13
tenphi Sep 5, 2024
58b88a2
fix(cubejs-client/playground): e2e tests * 14
tenphi Sep 5, 2024
9de7d1c
fix(cubejs-client/playground): e2e tests * 15
tenphi Sep 6, 2024
c50b25f
fix(cubejs-client/playground): graphql raw response
tenphi Sep 6, 2024
7df70d2
fix(cubejs-client/playground): graphql raw response * 2
tenphi Sep 6, 2024
3167117
Merge remote-tracking branch 'origin' into new-query-builder
tenphi Sep 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions packages/cubejs-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@
"homepage": ".",
"license": "MIT",
"dependencies": {
"@apollo/client": "^3.11.4",
"@graphiql/toolkit": "^0.4.3",
"anser": "^2.1.1",
"camel-case": "^4.1.2",
"codesandbox-import-utils": "^2.1.1",
"cron-validator": "^1.2.1",
"customize-cra": "^1.0.0",
"date-fns": "^2.16.1",
"fast-deep-equal": "^3.1.3",
"flexsearch": "^0.7.21",
"graphiql": "^1.8.6",
Expand All @@ -53,24 +55,25 @@
"react-is": "^16.8.4",
"react-responsive": "^8.0.1",
"react-router-dom": "^5.1.2",
"recharts": "^2.12.7",
"sql-formatter": "^3.1.0",
"throttle-debounce": "^3.0.1",
"uuid": "^8.3.2"
"uuid": "^8.3.2",
"vite-plugin-environment": "^1.1.3"
},
"devDependencies": {
"@ant-design/compatible": "^1.0.2",
"@ant-design/icons": "^4.7.0",
"@cube-dev/ui-kit": "0.31.2",
"@ant-design/compatible": "^1.0.1",
"@ant-design/icons": "^5.3.5",
"@cube-dev/ui-kit": "0.37.3",
"@cubejs-client/core": "^0.35.23",
"@cubejs-client/react": "^0.35.48",
"@types/flexsearch": "^0.7.3",
"@types/node": "^16",
"@types/react": "^17.0.3",
"@types/react": "^18.3.4",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "^17.0.2",
"@types/react-router": "^5.1.12",
"@types/react-router-dom": "^5.1.7",
"@types/styled-components": "^5.1.9",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.34",
"@types/uuid": "^8.3.1",
"@vitejs/plugin-react": "^2.1.0",
"antd": "4.16.13",
Expand All @@ -81,25 +84,25 @@
"graphql": "^15.8.0",
"jsdom": "^16.7.0",
"prismjs": "^1.25.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"recursive-readdir": "^2.2.2",
"styled-components": "5.2.0",
"styled-components": "6.1.12",
"tslib": "^2.3.0",
"typescript": "~5.2.2",
"vite": "^4.5.0",
"vite": "^5.4.2",
"vitest": "^0.34.6"
},
"peerDependencies": {
"@ant-design/icons": ">=4.7.0",
"@cube-dev/ui-kit": ">=0.30.0",
"@cube-dev/ui-kit": ">=0.37.2",
"@cubejs-client/core": ">=0.30.0",
"@cubejs-client/react": ">=0.30.0",
"antd": ">=4.16.13",
"graphql": ">=15.8.0",
"prismjs": ">=1.25.0",
"react": ">=17.0.1",
"react-dom": ">=17.0.1",
"styled-components": ">=5.2.0"
"react": ">=18.0.0",
"react-dom": ">=18.0.0",
"styled-components": ">=6.0.0"
}
}
49 changes: 28 additions & 21 deletions packages/cubejs-playground/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable no-undef,react/jsx-no-target-blank */
import '@ant-design/compatible/assets/index.css';
import { Alert, Layout } from 'antd';
import { Component, useEffect } from 'react';
import { Component, PropsWithChildren, useEffect } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import styled from 'styled-components';
import { Root, tasty } from '@cube-dev/ui-kit';
import { Root } from '@cube-dev/ui-kit';

import { CubeLoader } from './atoms';
import { AppContextConsumer, PlaygroundContext } from './components/AppContext';
Expand All @@ -19,6 +19,8 @@ import {
trackImpl,
} from './events';
import { useAppContext } from './hooks';
import { QUERY_BUILDER_COLOR_TOKENS } from './QueryBuilderV2';

const StyledLayoutContent = styled(Layout.Content)`
height: 100%;
`;
Expand All @@ -30,7 +32,14 @@ type AppState = {
isAppContextSet: boolean;
};

class App extends Component<RouteComponentProps, AppState> {
const ROOT_STYLES = {
height: 'min 100vh',
display: 'grid',
gridTemplateRows: 'min-content 1fr',
...QUERY_BUILDER_COLOR_TOKENS,
};

class App extends Component<PropsWithChildren<RouteComponentProps>, AppState> {
static getDerivedStateFromError(error) {
return { fatalError: error };
}
Expand Down Expand Up @@ -103,24 +112,22 @@ class App extends Component<RouteComponentProps, AppState> {
<LivePreviewContextProvider
disabled={context!.livePreview == null || !context!.livePreview}
>
<Root>
<Layout>
<GlobalStyles />

<Header selectedKeys={[location.pathname]} />

<StyledLayoutContent>
{fatalError ? (
<Alert
message="Error occured while rendering"
description={fatalError.stack || ''}
type="error"
/>
) : (
children
)}
</StyledLayoutContent>
</Layout>
<Root styles={ROOT_STYLES}>
<GlobalStyles />

<Header selectedKeys={[location.pathname]} />

<StyledLayoutContent>
{fatalError ? (
<Alert
message="Error occured while rendering"
description={fatalError.stack || ''}
type="error"
/>
) : (
children
)}
</StyledLayoutContent>
</Root>
</LivePreviewContextProvider>
);
Expand Down
39 changes: 39 additions & 0 deletions packages/cubejs-playground/src/QueryBuilderV2/Pivot/Axes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { DragDropContext } from 'react-beautiful-dnd';
import { Grid } from '@cube-dev/ui-kit';

import { QueryBuilderContextProps } from '../types';

import { PivotDroppableArea } from './DroppableArea';

export function PivotAxes({
pivotConfig,
onMove,
}: {
pivotConfig: QueryBuilderContextProps['pivotConfig'];
onMove: QueryBuilderContextProps['updatePivotConfig']['moveItem'];
}) {
return (
<DragDropContext
onDragEnd={({ source, destination }) => {
if (!destination) {
return;
}
onMove({
sourceIndex: source.index,
destinationIndex: destination.index,
sourceAxis: source.droppableId as 'x' | 'y',
destinationAxis: destination.droppableId as 'x' | 'y',
});
}}
>
<Grid columns="minmax(160px, 1fr) minmax(160px, 1fr)">
<div>
<PivotDroppableArea pivotConfig={pivotConfig} axis="x" />
</div>
<div>
<PivotDroppableArea pivotConfig={pivotConfig} axis="y" />
</div>
</Grid>
</DragDropContext>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { memo } from 'react';
import { Flow, tasty } from '@cube-dev/ui-kit';
import { Droppable } from 'react-beautiful-dnd';

import { QueryBuilderContextProps } from '../types';

import { PivotItem } from './Item';

const HeaderElement = tasty({
styles: {
display: 'grid',
preset: 'h6',
color: '#dark',
placeContent: 'center',
fill: '#light',
padding: '8px 16px',
border: 'bottom',
},
});

const Header = memo(({ axis }: { axis: string }) => {
return <HeaderElement>{axis.toUpperCase()} axis</HeaderElement>;
});

export function PivotDroppableArea({
pivotConfig,
axis,
}: {
pivotConfig: QueryBuilderContextProps['pivotConfig'];
axis: string;
}) {
return (
<>
<Header axis={axis} />

<div
data-testid={`pivot-popover-${axis}`}
style={{
padding: '8px',
}}
>
<Droppable droppableId={axis}>
{(provided) => (
<Flow ref={provided.innerRef} {...provided.droppableProps} gap="1ow">
{/* @ts-ignore */}
{pivotConfig[axis].map((id, index) => {
let type: 'timeDimension' | 'dimension' | 'measure' = id.includes('.')
? id.split('.').length === 3
? 'timeDimension'
: 'dimension'
: 'measure';

return <PivotItem key={id} type={type} id={id} index={index} />;
})}

{provided.placeholder}
</Flow>
)}
</Droppable>
</div>
</>
);
}
85 changes: 85 additions & 0 deletions packages/cubejs-playground/src/QueryBuilderV2/Pivot/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Draggable } from 'react-beautiful-dnd';
import { DragOutlined } from '@ant-design/icons';
import { tasty } from '@cube-dev/ui-kit';

import { MemberLabelText } from '../components/MemberLabelText';
import { MemberBadge } from '../components/Badge';

const PivotItemElement = tasty({
styles: {
display: 'grid',
flow: 'row',
gridColumns: 'min-content 1fr',
gap: '1x',
placeContent: 'center start',
placeItems: 'center stretch',
radius: true,
padding: '.5x 1x',
preset: 't3m',

color: {
'': '#dark',
'[data-type="dimension"]': '#dimension-text',
'[data-type="measure"]': '#measure-text',
'[data-type="time-dimension"]': '#time-dimension-text',
},
fill: {
'': '#dark.15',
'[data-type="dimension"]': '#dimension-hover',
'[data-type="measure"]': '#measure-hover',
'[data-type="timeDimension"]': '#time-dimension-hover',
},
},
});

export function PivotItem({
id,
index,
type,
}: {
id: string;
index: number;
type: 'timeDimension' | 'dimension' | 'measure';
}) {
return (
<Draggable draggableId={id} index={index}>
{({ draggableProps, dragHandleProps, innerRef }) => {
const arr = id.split('.');

return (
// <TooltipProvider activeWrap title={id} tooltipStyles={{ width: 'auto' }}>
<PivotItemElement
ref={innerRef}
data-type={type}
{...draggableProps}
{...dragHandleProps}
style={draggableProps.style}
>
<DragOutlined />
<MemberLabelText data-member={type}>
{arr.length > 1 ? (
<>
<span data-element="Name">
<span data-element="CubeName">{arr[0]}</span>
<span data-element="Divider">.</span>
<span data-element="MemberName">{arr[1]}</span>
</span>
{arr[2] ? (
<span data-element="Grouping">
<MemberBadge isSpecial type={type}>
{arr[2]}
</MemberBadge>
</span>
) : null}
</>
) : (
<span data-element="MemberName">{id}</span>
)}
</MemberLabelText>
</PivotItemElement>
// </TooltipProvider>
);
}}
</Draggable>
);
}
24 changes: 24 additions & 0 deletions packages/cubejs-playground/src/QueryBuilderV2/Pivot/Options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Checkbox } from '@cube-dev/ui-kit';

import { QueryBuilderContextProps } from '../types';

export function PivotOptions({
pivotConfig,
onUpdate,
}: {
pivotConfig: QueryBuilderContextProps['pivotConfig'];
onUpdate: QueryBuilderContextProps['updatePivotConfig']['update'];
}) {
return pivotConfig ? (
<Checkbox
isSelected={pivotConfig.fillMissingDates as boolean}
onChange={() =>
onUpdate({
fillMissingDates: !pivotConfig.fillMissingDates,
})
}
>
Fill Missing Dates
</Checkbox>
) : null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './Axes';
export * from './DroppableArea';
export * from './Item';
export * from './Options';
Loading
Loading