Skip to content

Commit

Permalink
feat(bi): Added the ability to customise table columns (#24236)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Gilbert09 and github-actions[bot] authored Aug 12, 2024
1 parent ce575be commit 26ae860
Show file tree
Hide file tree
Showing 14 changed files with 528 additions and 172 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/insights-navigation-open-directly.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Insights', () => {
insight.newInsight('SQL')
insight.updateQueryEditorText(hogQLQuery, 'hogql-query-editor')
cy.get('[data-attr="hogql-query-editor"]').should('exist')
cy.get('tr.DataTable__row').should('have.length.gte', 2)
cy.get('tr.DataVizRow').should('have.length.gte', 2)
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/insights-navigation-open-sql-insight-first.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Insights', () => {
insight.newInsight('SQL')
insight.updateQueryEditorText(hogQLQuery, 'hogql-query-editor')
cy.get('[data-attr="hogql-query-editor"]').should('exist')
cy.get('tr.DataTable__row').should('have.length.gte', 2)
cy.get('tr.DataVizRow').should('have.length.gte', 2)
})

it('can open a new trends insight', () => {
Expand Down Expand Up @@ -68,7 +68,7 @@ describe('Insights', () => {
insight.clickTab('SQL')
insight.updateQueryEditorText(hogQLQuery, 'hogql-query-editor')
cy.get('[data-attr="hogql-query-editor"]').should('exist')
cy.get('tr.DataTable__row').should('have.length.gte', 2)
cy.get('tr.DataVizRow').should('have.length.gte', 2)
})
})
})
Expand Down
6 changes: 3 additions & 3 deletions cypress/e2e/insights-navigation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Insights', () => {
cy.contains('.Link', insightName).click()

cy.get('[data-attr="hogql-query-editor"]').should('not.exist')
cy.get('tr.DataTable__row').should('have.length.gte', 2)
cy.get('tr.DataVizRow').should('have.length.gte', 2)

cy.get('[data-attr="insight-edit-button"]').click()
insight.clickTab('RETENTION')
Expand All @@ -50,7 +50,7 @@ describe('Insights', () => {
cy.get('[data-attr="hogql-query-editor"]').should('exist')
insight.updateQueryEditorText(hogQLQuery, 'hogql-query-editor')

cy.get('.DataTable tr').should('have.length.gte', 2)
cy.get('.DataVizRow').should('have.length.gte', 2)

insight.clickTab('TRENDS')
cy.get('.TrendsInsight canvas').should('exist')
Expand All @@ -61,7 +61,7 @@ describe('Insights', () => {
cy.get('[data-attr="hogql-query-editor"]').should('exist')
insight.updateQueryEditorText(hogQLQuery, 'hogql-query-editor')

cy.get('.DataTable tr').should('have.length.gte', 2)
cy.get('.DataVizRow').should('have.length.gte', 2)

insight.clickTab('TRENDS')
cy.get('.TrendsInsight canvas').should('exist')
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 0 additions & 29 deletions frontend/src/queries/nodes/DataVisualization/Components/Chart.tsx

This file was deleted.

194 changes: 112 additions & 82 deletions frontend/src/queries/nodes/DataVisualization/Components/SeriesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,23 @@ import { AxisSeries, dataVisualizationLogic } from '../dataVisualizationLogic'
import { ySeriesLogic, YSeriesLogicProps, YSeriesSettingsTab } from './ySeriesLogic'

export const SeriesTab = (): JSX.Element => {
const { columns, numericalColumns, xData, yData, responseLoading } = useValues(dataVisualizationLogic)
const { columns, numericalColumns, xData, yData, responseLoading, isTableVisualization, tabularColumns } =
useValues(dataVisualizationLogic)
const { updateXSeries, addYSeries } = useActions(dataVisualizationLogic)

const hideAddYSeries = yData.length >= numericalColumns.length

if (isTableVisualization) {
return (
<div className="flex flex-col w-full">
<LemonLabel>Columns</LemonLabel>
{tabularColumns.map((series, index) => (
<YSeries series={series} index={index} key={`${series.column.name}-${index}`} />
))}
</div>
)
}

const options = columns.map(({ name, type }) => ({
value: name,
label: (
Expand Down Expand Up @@ -75,8 +87,9 @@ export const SeriesTab = (): JSX.Element => {
}

const YSeries = ({ series, index }: { series: AxisSeries<number>; index: number }): JSX.Element => {
const { columns, numericalColumns, responseLoading, dataVisualizationProps } = useValues(dataVisualizationLogic)
const { updateYSeries, deleteYSeries } = useActions(dataVisualizationLogic)
const { columns, numericalColumns, responseLoading, dataVisualizationProps, isTableVisualization } =
useValues(dataVisualizationLogic)
const { updateSeriesIndex, deleteYSeries } = useActions(dataVisualizationLogic)

const seriesLogicProps: YSeriesLogicProps = { series, seriesIndex: index, dataVisualizationProps }
const seriesLogic = ySeriesLogic(seriesLogicProps)
Expand All @@ -87,22 +100,25 @@ const YSeries = ({ series, index }: { series: AxisSeries<number>; index: number
const { isDarkModeOn } = useValues(themeLogic)
const seriesColor = getSeriesColor(index)

const options = numericalColumns.map(({ name, type }) => ({
const columnsInOptions = isTableVisualization ? columns : numericalColumns
const options = columnsInOptions.map(({ name, type }) => ({
value: name,
label: (
<div className="items-center flex flex-1">
<SeriesGlyph
style={{
borderColor: seriesColor,
color: seriesColor,
backgroundColor: isDarkModeOn
? RGBToRGBA(lightenDarkenColor(seriesColor, -20), 0.3)
: hexToRGBA(seriesColor, 0.2),
}}
className="mr-2"
>
<></>
</SeriesGlyph>
{!isTableVisualization && (
<SeriesGlyph
style={{
borderColor: seriesColor,
color: seriesColor,
backgroundColor: isDarkModeOn
? RGBToRGBA(lightenDarkenColor(seriesColor, -20), 0.3)
: hexToRGBA(seriesColor, 0.2),
}}
className="mr-2"
>
<></>
</SeriesGlyph>
)}
{series.settings?.display?.label && series.column.name === name ? series.settings.display.label : name}
<LemonTag className="ml-2" type="default">
{type.name}
Expand All @@ -121,7 +137,7 @@ const YSeries = ({ series, index }: { series: AxisSeries<number>; index: number
onChange={(value) => {
const column = columns.find((n) => n.name === value)
if (column) {
updateYSeries(index, column.name)
updateSeriesIndex(index, column.name)
}
}}
/>
Expand Down Expand Up @@ -156,94 +172,108 @@ const YSeries = ({ series, index }: { series: AxisSeries<number>; index: number
disabledReasonWrapperClass="flex"
/>
</Popover>
<LemonButton
key="delete"
icon={<IconTrash />}
status="danger"
title="Delete Y-series"
noPadding
onClick={() => deleteYSeries(index)}
/>
{!isTableVisualization && (
<LemonButton
key="delete"
icon={<IconTrash />}
status="danger"
title="Delete Y-series"
noPadding
onClick={() => deleteYSeries(index)}
/>
)}
</div>
)
}

const YSeriesFormattingTab = ({ ySeriesLogicProps }: { ySeriesLogicProps: YSeriesLogicProps }): JSX.Element => {
return (
<Form logic={ySeriesLogic} props={ySeriesLogicProps} formKey="formatting" className="space-y-4">
<LemonField name="style" label="Style" className="gap-1">
<LemonSelect
options={[
{ value: 'none', label: 'None' },
{ value: 'number', label: 'Number' },
{ value: 'percent', label: 'Percentage' },
]}
/>
</LemonField>
{ySeriesLogicProps.series.column.type.isNumerical && (
<LemonField name="style" label="Style" className="gap-1">
<LemonSelect
options={[
{ value: 'none', label: 'None' },
{ value: 'number', label: 'Number' },
{ value: 'percent', label: 'Percentage' },
]}
/>
</LemonField>
)}
<LemonField name="prefix" label="Prefix">
<LemonInput placeholder="$" />
</LemonField>
<LemonField name="suffix" label="Suffix">
<LemonInput placeholder="USD" />
</LemonField>
<LemonField name="decimalPlaces" label="Decimal places">
<LemonInput type="number" min={0} />
</LemonField>
{ySeriesLogicProps.series.column.type.isNumerical && (
<LemonField name="decimalPlaces" label="Decimal places">
<LemonInput type="number" min={0} />
</LemonField>
)}
</Form>
)
}

const YSeriesDisplayTab = ({ ySeriesLogicProps }: { ySeriesLogicProps: YSeriesLogicProps }): JSX.Element => {
const { isTableVisualization } = useValues(dataVisualizationLogic)

return (
<Form logic={ySeriesLogic} props={ySeriesLogicProps} formKey="display" className="space-y-4">
<LemonField name="label" label="Label">
<LemonInput />
</LemonField>
<LemonField name="trendLine" label="Trend line">
{({ value, onChange }) => <LemonSwitch checked={value} onChange={(newValue) => onChange(newValue)} />}
</LemonField>
<LemonField name="yAxisPosition" label="Y-axis position">
{({ value, onChange }) => (
<LemonSegmentedButton
value={value}
className="w-full"
options={[
{
label: 'Left',
value: 'left',
},
{
label: 'Right',
value: 'right',
},
]}
onChange={(newValue) => onChange(newValue)}
/>
)}
</LemonField>
<LemonField name="displayType" label="Display type">
{({ value, onChange }) => (
<LemonSegmentedButton
value={value}
className="w-full"
options={[
{
label: 'Auto',
value: 'auto',
},
{
label: 'Line',
value: 'line',
},
{
label: 'Bar',
value: 'bar',
},
]}
onChange={(newValue) => onChange(newValue)}
/>
)}
</LemonField>
{!isTableVisualization && (
<>
<LemonField name="trendLine" label="Trend line">
{({ value, onChange }) => (
<LemonSwitch checked={value} onChange={(newValue) => onChange(newValue)} />
)}
</LemonField>
<LemonField name="yAxisPosition" label="Y-axis position">
{({ value, onChange }) => (
<LemonSegmentedButton
value={value}
className="w-full"
options={[
{
label: 'Left',
value: 'left',
},
{
label: 'Right',
value: 'right',
},
]}
onChange={(newValue) => onChange(newValue)}
/>
)}
</LemonField>
<LemonField name="displayType" label="Display type">
{({ value, onChange }) => (
<LemonSegmentedButton
value={value}
className="w-full"
options={[
{
label: 'Auto',
value: 'auto',
},
{
label: 'Line',
value: 'line',
},
{
label: 'Bar',
value: 'bar',
},
]}
onChange={(newValue) => onChange(newValue)}
/>
)}
</LemonField>
</>
)}
</Form>
)
}
Expand Down
Loading

0 comments on commit 26ae860

Please sign in to comment.