diff --git a/.eslintrc.js b/.eslintrc.js index 02f97dbd46c..2441c77348e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -55,7 +55,7 @@ module.exports = { // let's save the humans time and let the machines do the work // "never" means if the prop does not need the curly braces, they will be removed/errored // see https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-curly-brace-presence.md - "react/jsx-curly-brace-presence": ['error', { "props": "never", "children": "never", "propElementValues": "always" }], + 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never', propElementValues: 'always' }], 'no-console': ['error', { allow: ['warn', 'error'] }], 'no-debugger': 'error', 'no-only-tests/no-only-tests': 'error', diff --git a/.storybook/main.ts b/.storybook/main.ts index 6168c174840..097de03c004 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -38,7 +38,7 @@ const config: StorybookConfig = { framework: { name: '@storybook/react-webpack5', - options: { builder: { useSWC: true } } + options: { builder: { useSWC: true } }, }, docs: { diff --git a/.stylelintrc.js b/.stylelintrc.js index 3b41343e308..986a9ec24ba 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -43,8 +43,8 @@ module.exports = { 'scss/at-rule-no-unknown': [ true, { - 'ignoreAtRules': ['tailwind'] - } + ignoreAtRules: ['tailwind'], + }, ], 'scss/operator-no-newline-after': null, // Doesn't always play well with prettier 'scss/at-extend-no-missing-placeholder': null, diff --git a/bin/build-schema.mjs b/bin/build-schema.mjs index de14126b9eb..a599ff528b7 100644 --- a/bin/build-schema.mjs +++ b/bin/build-schema.mjs @@ -2,27 +2,27 @@ // replaces ts-json-schema-generator -f tsconfig.json --path 'frontend/src/queries/schema.ts' --no-type-check > frontend/src/queries/schema.json -import fs from "fs"; -import stableStringify from "safe-stable-stringify"; -import tsj from "ts-json-schema-generator"; +import fs from 'fs' +import stableStringify from 'safe-stable-stringify' +import tsj from 'ts-json-schema-generator' /** @type {import('ts-json-schema-generator/dist/src/Config').Config} */ const config = { ...tsj.DEFAULT_CONFIG, - path: "frontend/src/queries/schema.ts", - tsconfig: "tsconfig.json", - discriminatorType: "open-api", + path: 'frontend/src/queries/schema.ts', + tsconfig: 'tsconfig.json', + discriminatorType: 'open-api', skipTypeCheck: true, -}; +} -const output_path = "frontend/src/queries/schema.json"; +const output_path = 'frontend/src/queries/schema.json' -const schema = tsj.createGenerator(config).createSchema(config.type); -const stringify = config.sortProps ? stableStringify : JSON.stringify; -const schemaString = (config.minify ? stringify(schema) : stringify(schema, null, 2)); +const schema = tsj.createGenerator(config).createSchema(config.type) +const stringify = config.sortProps ? stableStringify : JSON.stringify +const schemaString = config.minify ? stringify(schema) : stringify(schema, null, 2) fs.writeFile(output_path, schemaString, (err) => { if (err) { - throw err; + throw err } -}); +}) diff --git a/frontend/src/queries/nodes/DataTable/renderColumn.tsx b/frontend/src/queries/nodes/DataTable/renderColumn.tsx index ffd9e94521d..578d2becfa8 100644 --- a/frontend/src/queries/nodes/DataTable/renderColumn.tsx +++ b/frontend/src/queries/nodes/DataTable/renderColumn.tsx @@ -83,7 +83,17 @@ export function renderColumn( object[value[i]] = value[i + 1] } if ('results' in object && Array.isArray(object.results)) { - return + // TODO: If results aren't an array of numbers, show a helpful message on using sparkline() + return ( + Number(v)), + }, + ]} + /> + ) } } diff --git a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx index 83a60db5419..98d1be89d54 100644 --- a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx +++ b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx @@ -31,8 +31,8 @@ import { insightLogic } from 'scenes/insights/insightLogic' import { InsightTooltip } from 'scenes/insights/InsightTooltip/InsightTooltip' import { TooltipConfig } from 'scenes/insights/InsightTooltip/insightTooltipUtils' import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic' -import { lineGraphLogic } from 'scenes/insights/views/LineGraph/lineGraphLogic' import { PieChart } from 'scenes/insights/views/LineGraph/PieChart' +import { createTooltipData } from 'scenes/insights/views/LineGraph/tooltip-data' import { ErrorBoundary } from '~/layout/ErrorBoundary' import { themeLogic } from '~/layout/navigation-3000/themeLogic' @@ -278,8 +278,6 @@ export function LineGraph_({ const { insightProps, insight } = useValues(insightLogic) const { timezone, isTrends } = useValues(insightVizDataLogic(insightProps)) - const { createTooltipData } = useValues(lineGraphLogic) - const canvasRef = useRef(null) const [myLineChart, setMyLineChart] = useState>() diff --git a/frontend/src/scenes/insights/views/LineGraph/PieChart.tsx b/frontend/src/scenes/insights/views/LineGraph/PieChart.tsx index 552daf3ff78..25f09bddf3e 100644 --- a/frontend/src/scenes/insights/views/LineGraph/PieChart.tsx +++ b/frontend/src/scenes/insights/views/LineGraph/PieChart.tsx @@ -26,7 +26,7 @@ import { onChartClick, onChartHover, } from 'scenes/insights/views/LineGraph/LineGraph' -import { lineGraphLogic } from 'scenes/insights/views/LineGraph/lineGraphLogic' +import { createTooltipData } from 'scenes/insights/views/LineGraph/tooltip-data' import { areObjectValuesEmpty } from '~/lib/utils' import { groupsModel } from '~/models/groupsModel' @@ -84,7 +84,6 @@ export function PieChart({ let datasets = _datasets - const { createTooltipData } = useValues(lineGraphLogic) const { aggregationLabel } = useValues(groupsModel) const { highlightSeries } = useActions(insightLogic) const canvasRef = useRef(null) diff --git a/frontend/src/scenes/insights/views/LineGraph/lineGraphLogic.ts b/frontend/src/scenes/insights/views/LineGraph/lineGraphLogic.ts deleted file mode 100644 index a5df4b88f6c..00000000000 --- a/frontend/src/scenes/insights/views/LineGraph/lineGraphLogic.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { TooltipItem } from 'chart.js' -import { kea, path, selectors } from 'kea' -import { SeriesDatum } from 'scenes/insights/InsightTooltip/insightTooltipUtils' - -import { GraphDataset } from '~/types' - -import type { lineGraphLogicType } from './lineGraphLogicType' - -// TODO: Eventually we should move all state from LineGraph into this logic -export const lineGraphLogic = kea([ - path(['scenes', 'insights', 'LineGraph', 'lineGraphLogic']), - selectors({ - createTooltipData: [ - () => [], - () => - (tooltipDataPoints: TooltipItem[], filterFn: (s: SeriesDatum) => boolean): SeriesDatum[] => { - return tooltipDataPoints - ?.map((dp, idx) => { - const pointDataset = (dp?.dataset ?? {}) as GraphDataset - return { - id: idx, - dataIndex: dp.dataIndex, - datasetIndex: dp.datasetIndex, - dotted: !!pointDataset?.dotted, - breakdown_value: - pointDataset?.breakdown_value ?? - pointDataset?.breakdownValues?.[dp.dataIndex] ?? - undefined, - compare_label: - pointDataset?.compare_label ?? - pointDataset?.compareLabels?.[dp.dataIndex] ?? - undefined, - action: pointDataset?.action ?? pointDataset?.actions?.[dp.dataIndex] ?? undefined, - label: pointDataset?.label ?? pointDataset.labels?.[dp.dataIndex] ?? undefined, - color: Array.isArray(pointDataset.borderColor) - ? pointDataset.borderColor?.[dp.dataIndex] - : pointDataset.borderColor, - count: pointDataset?.data?.[dp.dataIndex] || 0, - filter: pointDataset?.filter ?? {}, - } - }) - ?.sort((a, b) => { - // Sort by descending order and fallback on alphabetic sort - return ( - b.count - a.count || - (a.label === undefined || b.label === undefined ? -1 : a.label.localeCompare(b.label)) - ) - }) - ?.filter(filterFn) - ?.map((s, id) => ({ - ...s, - id, - })) - }, - ], - }), -]) diff --git a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts new file mode 100644 index 00000000000..d17d447372e --- /dev/null +++ b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts @@ -0,0 +1,47 @@ +import { TooltipItem } from 'chart.js' +import { SeriesDatum } from 'scenes/insights/InsightTooltip/insightTooltipUtils' + +import { GraphDataset } from '~/types' + +export function createTooltipData( + tooltipDataPoints: TooltipItem[], + filterFn?: (s: SeriesDatum) => boolean +): SeriesDatum[] { + if (!tooltipDataPoints) { + return [] + } + let data = tooltipDataPoints + .map((dp, idx) => { + const pointDataset = (dp?.dataset ?? {}) as GraphDataset + return { + id: idx, + dataIndex: dp.dataIndex, + datasetIndex: dp.datasetIndex, + dotted: !!pointDataset?.dotted, + breakdown_value: + pointDataset?.breakdown_value ?? pointDataset?.breakdownValues?.[dp.dataIndex] ?? undefined, + compare_label: pointDataset?.compare_label ?? pointDataset?.compareLabels?.[dp.dataIndex] ?? undefined, + action: pointDataset?.action ?? pointDataset?.actions?.[dp.dataIndex] ?? undefined, + label: pointDataset?.label ?? pointDataset.labels?.[dp.dataIndex] ?? undefined, + color: Array.isArray(pointDataset.borderColor) + ? pointDataset.borderColor?.[dp.dataIndex] + : pointDataset.borderColor, + count: pointDataset?.data?.[dp.dataIndex] || 0, + filter: pointDataset?.filter ?? {}, + } + }) + .sort((a, b) => { + // Sort by descending order and fallback on alphabetic sort + return ( + b.count - a.count || + (a.label === undefined || b.label === undefined ? -1 : a.label.localeCompare(b.label)) + ) + }) + if (filterFn) { + data = data.filter(filterFn) + } + return data.map((s, id) => ({ + ...s, + id, + })) +}