-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(bi): First iteration of BI tooling (#18995)
* First pass of BI and DataVisualizationNode * First pass of a BI interface * PR comments * Fix types * Added data viz node to metadata
- Loading branch information
Showing
24 changed files
with
683 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
frontend/src/queries/nodes/DataVisualization/Components/Chart.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DataVisualization { | ||
--viz-min-height: calc(80vh - 6rem); | ||
} |
24 changes: 24 additions & 0 deletions
24
frontend/src/queries/nodes/DataVisualization/Components/Chart.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import './Chart.scss' | ||
|
||
import { useValues } from 'kea' | ||
|
||
import { dataVisualizationLogic } from '../dataVisualizationLogic' | ||
import { LineGraph } from './Charts/LineGraph' | ||
import { ChartSelection } from './ChartSelection' | ||
|
||
export const Chart = (): JSX.Element => { | ||
const { showEditingUI } = useValues(dataVisualizationLogic) | ||
|
||
return ( | ||
<div className="flex flex-row gap-4"> | ||
{showEditingUI && ( | ||
<div className="h-full"> | ||
<ChartSelection /> | ||
</div> | ||
)} | ||
<div className="w-full"> | ||
<LineGraph /> | ||
</div> | ||
</div> | ||
) | ||
} |
9 changes: 9 additions & 0 deletions
9
frontend/src/queries/nodes/DataVisualization/Components/ChartSelection.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@import '../../../../styles/mixins'; | ||
|
||
.DataVisualization { | ||
.ChartSelectionWrapper { | ||
width: 20vw; | ||
height: var(--viz-min-height); | ||
border-radius: var(--radius); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
frontend/src/queries/nodes/DataVisualization/Components/ChartSelection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import './ChartSelection.scss' | ||
|
||
import { LemonLabel, LemonSelect } from '@posthog/lemon-ui' | ||
import { useActions, useValues } from 'kea' | ||
|
||
import { dataNodeLogic } from '../../DataNode/dataNodeLogic' | ||
import { dataVisualizationLogic } from '../dataVisualizationLogic' | ||
|
||
export const ChartSelection = (): JSX.Element => { | ||
const { columns, selectedXIndex, selectedYIndex } = useValues(dataVisualizationLogic) | ||
const { responseLoading } = useValues(dataNodeLogic) | ||
const { setXAxis, setYAxis } = useActions(dataVisualizationLogic) | ||
|
||
const options = columns.map(({ name, type }) => ({ | ||
value: name, | ||
label: `${name} - ${type}`, | ||
})) | ||
|
||
return ( | ||
<div className="ChartSelectionWrapper bg-bg-light border p-4"> | ||
<div className="flex flex-col"> | ||
<LemonLabel>X-axis</LemonLabel> | ||
<LemonSelect | ||
value={selectedXIndex !== null ? options[selectedXIndex]?.label : 'None'} | ||
options={options} | ||
disabledReason={responseLoading ? 'Query loading...' : undefined} | ||
onChange={(value) => { | ||
const index = options.findIndex((n) => n.value === value) | ||
setXAxis(index) | ||
}} | ||
/> | ||
<LemonLabel className="mt-4">Y-axis</LemonLabel> | ||
<LemonSelect | ||
value={selectedYIndex !== null ? options[selectedYIndex]?.label : 'None'} | ||
options={options} | ||
disabledReason={responseLoading ? 'Query loading...' : undefined} | ||
onChange={(value) => { | ||
const index = options.findIndex((n) => n.value === value) | ||
setYAxis(index) | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
) | ||
} |
3 changes: 3 additions & 0 deletions
3
frontend/src/queries/nodes/DataVisualization/Components/Charts/LineGraph.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DataVisualization__LineGraph { | ||
min-height: var(--viz-min-height); | ||
} |
147 changes: 147 additions & 0 deletions
147
frontend/src/queries/nodes/DataVisualization/Components/Charts/LineGraph.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import 'chartjs-adapter-dayjs-3' | ||
import './LineGraph.scss' | ||
|
||
import { ChartData, Color, GridLineOptions, TickOptions } from 'chart.js' | ||
import ChartDataLabels from 'chartjs-plugin-datalabels' | ||
import { useMountedLogic, useValues } from 'kea' | ||
import { Chart, ChartItem, ChartOptions } from 'lib/Chart' | ||
import { getGraphColors } from 'lib/colors' | ||
import { useEffect, useRef } from 'react' | ||
|
||
import { themeLogic } from '~/layout/navigation-3000/themeLogic' | ||
import { GraphType } from '~/types' | ||
|
||
import { dataVisualizationLogic } from '../../dataVisualizationLogic' | ||
|
||
export const LineGraph = (): JSX.Element => { | ||
const canvasRef = useRef<HTMLCanvasElement | null>(null) | ||
const { isDarkModeOn } = useValues(themeLogic) | ||
const colors = getGraphColors(isDarkModeOn) | ||
|
||
const vizLogic = useMountedLogic(dataVisualizationLogic) | ||
const { xData, yData } = useValues(vizLogic) | ||
|
||
useEffect(() => { | ||
if (!xData || !yData) { | ||
return | ||
} | ||
|
||
const data: ChartData = { | ||
labels: xData, | ||
datasets: [ | ||
{ | ||
label: 'Dataset 1', | ||
data: yData, | ||
borderColor: 'red', | ||
}, | ||
], | ||
} | ||
|
||
const tickOptions: Partial<TickOptions> = { | ||
color: colors.axisLabel as Color, | ||
font: { | ||
family: '-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", "Roboto", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', | ||
size: 12, | ||
weight: '500', | ||
}, | ||
} | ||
|
||
const gridOptions: Partial<GridLineOptions> = { | ||
color: colors.axisLine as Color, | ||
borderColor: colors.axisLine as Color, | ||
tickColor: colors.axisLine as Color, | ||
borderDash: [4, 2], | ||
} | ||
|
||
const options: ChartOptions = { | ||
responsive: true, | ||
maintainAspectRatio: false, | ||
elements: { | ||
line: { | ||
tension: 0, | ||
}, | ||
}, | ||
plugins: { | ||
datalabels: { | ||
color: 'white', | ||
anchor: (context) => { | ||
const datum = context.dataset.data[context.dataIndex] | ||
return typeof datum !== 'number' ? 'end' : datum > 0 ? 'end' : 'start' | ||
}, | ||
backgroundColor: (context) => { | ||
return (context.dataset.borderColor as string) || 'black' | ||
}, | ||
display: () => { | ||
return true | ||
}, | ||
borderWidth: 2, | ||
borderRadius: 4, | ||
borderColor: 'white', | ||
}, | ||
legend: { | ||
display: false, | ||
}, | ||
// @ts-expect-error Types of library are out of date | ||
crosshair: { | ||
snap: { | ||
enabled: true, // Snap crosshair to data points | ||
}, | ||
sync: { | ||
enabled: false, // Sync crosshairs across multiple Chartjs instances | ||
}, | ||
zoom: { | ||
enabled: false, // Allow drag to zoom | ||
}, | ||
line: { | ||
color: colors.crosshair ?? undefined, | ||
width: 1, | ||
}, | ||
}, | ||
}, | ||
hover: { | ||
mode: 'nearest', | ||
axis: 'x', | ||
intersect: false, | ||
}, | ||
scales: { | ||
x: { | ||
display: true, | ||
beginAtZero: true, | ||
ticks: tickOptions, | ||
grid: { | ||
...gridOptions, | ||
drawOnChartArea: false, | ||
tickLength: 12, | ||
}, | ||
}, | ||
y: { | ||
display: true, | ||
beginAtZero: true, | ||
stacked: false, | ||
ticks: { | ||
display: true, | ||
...tickOptions, | ||
precision: 1, | ||
}, | ||
grid: gridOptions, | ||
}, | ||
}, | ||
} | ||
|
||
const newChart = new Chart(canvasRef.current?.getContext('2d') as ChartItem, { | ||
type: GraphType.Line, | ||
data, | ||
options, | ||
plugins: [ChartDataLabels], | ||
}) | ||
return () => newChart.destroy() | ||
}, [xData, yData]) | ||
|
||
return ( | ||
<div className="DataVisualization__LineGraph rounded bg-bg-light relative flex flex-col p-2"> | ||
<div className="flex w-full h-full overflow-hidden"> | ||
<canvas ref={canvasRef} /> | ||
</div> | ||
</div> | ||
) | ||
} |
44 changes: 44 additions & 0 deletions
44
frontend/src/queries/nodes/DataVisualization/Components/TableDisplay.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { LemonSelect, LemonSelectOptions } from '@posthog/lemon-ui' | ||
import { useActions, useValues } from 'kea' | ||
import { IconShowChart, IconTableChart } from 'lib/lemon-ui/icons' | ||
|
||
import { ChartDisplayType } from '~/types' | ||
|
||
import { dataVisualizationLogic } from '../dataVisualizationLogic' | ||
|
||
export const TableDisplay = (): JSX.Element => { | ||
const { setVisualizationType } = useActions(dataVisualizationLogic) | ||
const { visualizationType } = useValues(dataVisualizationLogic) | ||
|
||
const options: LemonSelectOptions<ChartDisplayType> = [ | ||
{ | ||
options: [ | ||
{ | ||
value: ChartDisplayType.ActionsTable, | ||
icon: <IconTableChart />, | ||
label: 'Table', | ||
}, | ||
{ | ||
value: ChartDisplayType.ActionsLineGraph, | ||
icon: <IconShowChart />, | ||
label: 'Line chart', | ||
}, | ||
], | ||
}, | ||
] | ||
|
||
return ( | ||
<LemonSelect | ||
value={visualizationType} | ||
onChange={(value) => { | ||
setVisualizationType(value) | ||
}} | ||
dropdownPlacement="bottom-end" | ||
optionTooltipPlacement="left" | ||
dropdownMatchSelectWidth={false} | ||
data-attr="chart-filter" | ||
options={options} | ||
size="small" | ||
/> | ||
) | ||
} |
Oops, something went wrong.