diff --git a/packages/components/src/components/PlotlyBarChart.tsx b/packages/components/src/components/PlotlyBarChart.tsx index bcb7f1da..6f2e02e8 100644 --- a/packages/components/src/components/PlotlyBarChart.tsx +++ b/packages/components/src/components/PlotlyBarChart.tsx @@ -1,7 +1,8 @@ -import { QueryClient, QueryClientProvider, useQuery } from "react-query"; -import { Plotly } from "./Plotly"; -import Papa, { ParseConfig } from "papaparse"; -import LoadingSpinner from "./LoadingSpinner"; +import { QueryClient, QueryClientProvider, useQuery } from 'react-query'; +import { Plotly } from './Plotly'; +import Papa, { ParseConfig } from 'papaparse'; +import LoadingSpinner from './LoadingSpinner'; +import { Data } from '../types/properties'; const queryClient = new QueryClient(); @@ -17,7 +18,7 @@ async function getCsv(url: string, bytes: number) { async function parseCsv( file: string, - parsingConfig: ParseConfig, + parsingConfig: ParseConfig ): Promise { return new Promise((resolve, reject) => { Papa.parse(file, { @@ -39,43 +40,40 @@ async function parseCsv( } export interface PlotlyBarChartProps { - url?: string; - data?: { [key: string]: number | string }[]; - rawCsv?: string; - randomId?: number; + data: Data; + uniqueId?: number; bytes?: number; parsingConfig?: ParseConfig; xAxis: string; yAxis: string; - lineLabel?: string; + // TODO: commented out because this doesn't work. I believe + // this would only make any difference on charts with multiple + // traces. + // lineLabel?: string; title?: string; } export const PlotlyBarChart: React.FC = ({ - url, data, - rawCsv, bytes = 5132288, parsingConfig = {}, xAxis, yAxis, - lineLabel, - title = "", + // lineLabel, + title = '', }) => { - const randomId = Math.random(); + const uniqueId = Math.random(); return ( // Provide the client to your App @@ -83,30 +81,28 @@ export const PlotlyBarChart: React.FC = ({ }; const PlotlyBarChartInner: React.FC = ({ - url, data, - rawCsv, - randomId, + uniqueId, bytes, parsingConfig, xAxis, yAxis, - lineLabel, + // lineLabel, title, }) => { - if (data) { + if (data.values) { return ( -
+
d[xAxis]), - y: data.map((d) => d[yAxis]), - type: "bar", - name: lineLabel, + x: data.values.map((d) => d[xAxis]), + y: data.values.map((d) => d[yAxis]), + type: 'bar', + // name: lineLabel, }, ]} /> @@ -114,18 +110,18 @@ const PlotlyBarChartInner: React.FC = ({ ); } const { data: csvString, isLoading: isDownloadingCSV } = useQuery( - ["dataCsv", url, randomId], - () => getCsv(url as string, bytes ?? 5132288), - { enabled: !!url }, + ['dataCsv', data.url, uniqueId], + () => getCsv(data.url as string, bytes ?? 5132288), + { enabled: !!data.url } ); const { data: parsedData, isLoading: isParsing } = useQuery( - ["dataPreview", csvString, randomId], + ['dataPreview', csvString, uniqueId], () => parseCsv( - rawCsv ? (rawCsv as string) : (csvString as string), - parsingConfig ?? {}, + data.csv ? (data.csv as string) : (csvString as string), + parsingConfig ?? {} ), - { enabled: rawCsv ? true : !!csvString }, + { enabled: data.csv ? true : !!csvString } ); if (isParsing || isDownloadingCSV)
@@ -133,7 +129,7 @@ const PlotlyBarChartInner: React.FC = ({
; if (parsedData) return ( -
+
= ({ { x: parsedData.data.map((d: any) => d[xAxis]), y: parsedData.data.map((d: any) => d[yAxis]), - type: "bar", - name: lineLabel, + type: 'bar', + // name: lineLabel, TODO: commented out because this doesn't work }, ]} /> diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 154290f2..a5c5a5c7 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -8,7 +8,8 @@ export * from './components/OpenLayers/OpenLayers'; export * from './components/Map'; export * from './components/PdfViewer'; export * from "./components/Excel"; -export * from "./components/BucketViewer"; +// NOTE: hidden for now +// export * from "./components/BucketViewer"; export * from "./components/Iframe"; export * from "./components/Plotly"; export * from "./components/PlotlyLineChart"; diff --git a/packages/components/src/types/properties.ts b/packages/components/src/types/properties.ts new file mode 100644 index 00000000..35dc93e0 --- /dev/null +++ b/packages/components/src/types/properties.ts @@ -0,0 +1,11 @@ +/* + * All components should use this interface for + * its data property. + * Based on vega. + * + */ +export interface Data { + url?: string; + values?: { [key: string]: number | string }[]; + csv?: string; +} diff --git a/packages/components/stories/BarChartPlotly.stories.ts b/packages/components/stories/BarChartPlotly.stories.ts index 879312e6..a7b3d4a9 100644 --- a/packages/components/stories/BarChartPlotly.stories.ts +++ b/packages/components/stories/BarChartPlotly.stories.ts @@ -1,6 +1,9 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { PlotlyBarChart, PlotlyBarChartProps } from '../src/components/PlotlyBarChart'; +import { + PlotlyBarChart, + PlotlyBarChartProps, +} from '../src/components/PlotlyBarChart'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { @@ -8,39 +11,44 @@ const meta: Meta = { component: PlotlyBarChart, tags: ['autodocs'], argTypes: { - url: { - description: - 'CSV Url to be parsed and used as data source', - }, data: { description: - 'Data to be displayed. as an array of key value pairs \n\n E.g.: [{ year: 1850, temperature: -0.41765878 }, { year: 1851, temperature: -0.2333498 }, ...]', - }, - rawCsv: { - description: - 'Raw csv data to be parsed and used as data source', + 'Data to be displayed. \n\n \ +Must be an object with one of the following properties: `url`, `values` or `csv` \n\n \ +`url`: URL pointing to a CSV file. \n\n \ +`values`: array of objects (check out [this example](/?path=/story/components-plotlybarchart--from-data-points)) \n\n \ +`csv`: string with valid CSV (check out [this example](/?path=/story/components-plotlybarchart--from-inline-csv)) \n\n \ +', }, bytes: { + // TODO: likely this should be an extra option on the data parameter, + // specific to URLs description: - 'How many bytes to read from the url', + "How many bytes to read from the url so that the entire file doesn's have to be fetched.", }, parsingConfig: { - description: 'If using url or rawCsv, this parsing config will be used to parse the data. Optional, check https://www.papaparse.com/ for more info', + description: + 'If using URL or CSV, this parsing config will be used to parse the data. Optional, check https://www.papaparse.com/ for more info.', }, title: { description: 'Title to display on the chart. Optional.', }, - lineLabel: { - description: 'Label to display on the line, Optional, will use yAxis if not provided', - }, + // TODO: commented out because this doesn't work + // lineLabel: { + // description: + // 'Label to display on the line, Optional, will use yAxis if not provided', + // }, xAxis: { description: - 'Name of the X axis on the data. Required when the "data" parameter is an URL.', + 'Name of the column header or object property that represents the X-axis on the data.', }, yAxis: { description: - 'Name of the Y axis on the data. Required when the "data" parameter is an URL.', + 'Name of the column header or object property that represents the Y-axis on the data.', }, + uniqueId: { + description: 'Provide a unique ID to help with cache revalidation of the fetched data.' + } }, }; @@ -49,25 +57,45 @@ export default meta; type Story = StoryObj; export const FromDataPoints: Story = { - name: 'Line chart from array of data points', + name: 'Bar chart from array of data points', args: { - data: [ - {year: '1850', temperature: -0.41765878}, - {year: '1851', temperature: -0.2333498}, - {year: '1852', temperature: -0.22939907}, - {year: '1853', temperature: -0.27035445}, - {year: '1854', temperature: -0.29163003}, - ], + data: { + values: [ + { year: '1850', temperature: -0.41765878 }, + { year: '1851', temperature: -0.2333498 }, + { year: '1852', temperature: -0.22939907 }, + { year: '1853', temperature: -0.27035445 }, + { year: '1854', temperature: -0.29163003 }, + ], + }, xAxis: 'year', yAxis: 'temperature', }, }; export const FromURL: Story = { - name: 'Line chart from URL', + name: 'Bar chart from URL', args: { title: 'Apple Stock Prices', - url: 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv', + data: { + url: 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv', + }, + xAxis: 'Date', + yAxis: 'AAPL.Open', + }, +}; + +export const FromInlineCSV: Story = { + name: 'Bar chart from inline CSV', + args: { + title: 'Apple Stock Prices', + data: { + csv: `Date,AAPL.Open,AAPL.High,AAPL.Low,AAPL.Close,AAPL.Volume,AAPL.Adjusted,dn,mavg,up,direction +2015-02-17,127.489998,128.880005,126.919998,127.830002,63152400,122.905254,106.7410523,117.9276669,129.1142814,Increasing +2015-02-18,127.629997,128.779999,127.449997,128.720001,44891700,123.760965,107.842423,118.9403335,130.0382439,Increasing +2015-02-19,128.479996,129.029999,128.330002,128.449997,37362400,123.501363,108.8942449,119.8891668,130.8840887,Decreasing +2015-02-20,128.619995,129.5,128.050003,129.5,48948400,124.510914,109.7854494,120.7635001,131.7415509,Increasing`, + }, xAxis: 'Date', yAxis: 'AAPL.Open', }, diff --git a/packages/components/stories/BucketViewer.stories.ts b/packages/components/stories/BucketViewer.bkp.stories.ts similarity index 96% rename from packages/components/stories/BucketViewer.stories.ts rename to packages/components/stories/BucketViewer.bkp.stories.ts index 893fbb2e..669acab4 100644 --- a/packages/components/stories/BucketViewer.stories.ts +++ b/packages/components/stories/BucketViewer.bkp.stories.ts @@ -1,3 +1,6 @@ +// NOTE: this component was renamed with .bkp so that it's hidden +// from the Storybook app + import { type Meta, type StoryObj } from '@storybook/react'; import { diff --git a/packages/components/stories/OpenLayers.stories.tsx b/packages/components/stories/OpenLayers.bkp.stories.tsx similarity index 96% rename from packages/components/stories/OpenLayers.stories.tsx rename to packages/components/stories/OpenLayers.bkp.stories.tsx index 101d4740..d9eabbd0 100644 --- a/packages/components/stories/OpenLayers.stories.tsx +++ b/packages/components/stories/OpenLayers.bkp.stories.tsx @@ -1,3 +1,6 @@ +// NOTE: this component was renamed with .bkp so that it's hidden +// from the Storybook app + import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import OpenLayers from '../src/components/OpenLayers/OpenLayers';