diff --git a/app/package-lock.json b/app/package-lock.json index 41228f7..063d147 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -13,11 +13,14 @@ "@heroicons/react": "^2.1.1", "@uiw/codemirror-themes": "^4.21.21", "@uiw/react-codemirror": "^4.21.21", + "@visx/axis": "^3.5.0", "@visx/gradient": "^3.3.0", + "@visx/grid": "^3.5.0", "@visx/group": "^3.3.0", "@visx/mock-data": "^3.3.0", "@visx/scale": "^3.5.0", "@visx/shape": "^3.5.0", + "@visx/vendor": "^3.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "uniqid": "^5.4.0" @@ -1602,6 +1605,24 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@visx/axis": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@visx/axis/-/axis-3.5.0.tgz", + "integrity": "sha512-vaY/CGk9+iQL1BFlHd5muIAuAjpPKLwtt6HwpITErW+cImjQJlNgYdgbwDCyuJMmJqXOlC9byWlmF+iI1dOPYg==", + "dependencies": { + "@types/react": "*", + "@visx/group": "3.3.0", + "@visx/point": "3.3.0", + "@visx/scale": "3.5.0", + "@visx/shape": "3.5.0", + "@visx/text": "3.3.0", + "classnames": "^2.3.1", + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0" + } + }, "node_modules/@visx/curve": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@visx/curve/-/curve-3.3.0.tgz", @@ -1623,6 +1644,24 @@ "react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0" } }, + "node_modules/@visx/grid": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@visx/grid/-/grid-3.5.0.tgz", + "integrity": "sha512-i1pdobTE223ItMiER3q4ojIaZWja3vg46TkS6FotnBZ4c0VRDHSrALQPdi0na+YEgppASWCQ2WrI/vD6mIkhSg==", + "dependencies": { + "@types/react": "*", + "@visx/curve": "3.3.0", + "@visx/group": "3.3.0", + "@visx/point": "3.3.0", + "@visx/scale": "3.5.0", + "@visx/shape": "3.5.0", + "classnames": "^2.3.1", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0" + } + }, "node_modules/@visx/group": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@visx/group/-/group-3.3.0.tgz", @@ -1645,6 +1684,11 @@ "d3-random": "^2.2.2" } }, + "node_modules/@visx/point": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@visx/point/-/point-3.3.0.tgz", + "integrity": "sha512-03eBBIJarkmX79WbeEGTUZwmS5/MUuabbiM9KfkGS9pETBTWkp1DZtEHZdp5z34x5TDQVLSi0rk1Plg3/8RtDg==" + }, "node_modules/@visx/scale": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@visx/scale/-/scale-3.5.0.tgz", @@ -1675,6 +1719,22 @@ "react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0" } }, + "node_modules/@visx/text": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@visx/text/-/text-3.3.0.tgz", + "integrity": "sha512-fOimcsf0GtQE9whM5MdA/xIkHMaV29z7qNqNXysUDE8znSMKsN+ott7kSg2ljAEE89CQo3WKHkPNettoVsa84w==", + "dependencies": { + "@types/lodash": "^4.14.172", + "@types/react": "*", + "classnames": "^2.3.1", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "reduce-css-calc": "^1.3.0" + }, + "peerDependencies": { + "react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0" + } + }, "node_modules/@visx/vendor": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@visx/vendor/-/vendor-3.5.0.tgz", @@ -1972,8 +2032,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -3951,6 +4010,11 @@ "yallist": "^3.0.2" } }, + "node_modules/math-expression-evaluator": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz", + "integrity": "sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4613,6 +4677,29 @@ "node": ">=8.10.0" } }, + "node_modules/reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==", + "dependencies": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + } + }, + "node_modules/reduce-css-calc/node_modules/balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==" + }, + "node_modules/reduce-function-call": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz", + "integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", diff --git a/app/package.json b/app/package.json index ac29e53..b5c2763 100644 --- a/app/package.json +++ b/app/package.json @@ -15,11 +15,14 @@ "@heroicons/react": "^2.1.1", "@uiw/codemirror-themes": "^4.21.21", "@uiw/react-codemirror": "^4.21.21", + "@visx/axis": "^3.5.0", "@visx/gradient": "^3.3.0", + "@visx/grid": "^3.5.0", "@visx/group": "^3.3.0", "@visx/mock-data": "^3.3.0", "@visx/scale": "^3.5.0", "@visx/shape": "^3.5.0", + "@visx/vendor": "^3.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "uniqid": "^5.4.0" diff --git a/app/src/components/Chart.jsx b/app/src/components/Chart.jsx index 07bc893..724f407 100644 --- a/app/src/components/Chart.jsx +++ b/app/src/components/Chart.jsx @@ -3,34 +3,44 @@ import { Bar } from '@visx/shape' import { Group } from '@visx/group' import { GradientTealBlue } from '@visx/gradient' import { scaleBand, scaleLinear } from '@visx/scale' +import { Grid } from '@visx/grid' +import { AxisBottom } from '@visx/axis' +import { timeParse, timeFormat } from '@visx/vendor/d3-time-format' -const verticalMargin = 120 +const verticalMargin = 64 function useSvgDimensions() { const ref = useRef(null); - const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); + const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) useEffect(() => { if (ref.current) { - const { width, height } = ref.current.getBoundingClientRect(); - setDimensions({ width, height }); + const { width, height } = ref.current.getBoundingClientRect() + setDimensions({ width, height }) } - }, []); + }, []) - return [ref, dimensions]; + return [ref, dimensions] } -export default function Chart({ data }) { +const parseDate = timeParse('%Y-%m-%d'); +const format = timeFormat('%h %m'); +const formatDate = (date) => format(parseDate(date)) + +export default function Chart({ data, axes }) { const data_ = data || [] const [svgRef, dimensions] = useSvgDimensions() - const xMax = dimensions.width; - const yMax = dimensions.height - verticalMargin; + const width = dimensions.width + const height = dimensions.height - verticalMargin + const xMax = width + const yMax = height + console.log(data_, axes) // scales, memoize for performance const xScale = useMemo( () => scaleBand({ range: [0, xMax], round: true, - domain: data_?.map(x => x.x), + domain: data_?.map(it => (axes?.x in it) && it[axes?.x]), padding: 0.4, }), [xMax, JSON.stringify(data)] @@ -39,16 +49,28 @@ export default function Chart({ data }) { () => scaleLinear({ range: [yMax, 0], round: true, - domain: [0, Math.max(...data_?.map(x => x.y))], + domain: [0, Math.max(...data_?.map(it => (axes?.y in it) && it[axes?.y]))], }), [yMax, JSON.stringify(data)], ) - console.log("drawing", data_, dimensions) - if(!data) return null + console.log("dim", dimensions) + console.log("drawing", data_) + console.log("xaxis", data_?.map(it => (axes?.x in it) && it[axes?.x])) + console.log("yaxis", [0, Math.max(...data_?.map(it => (axes?.y in it) && it[axes?.y]))]) + if(!data || !axes) return null return ( - - + + {false && } {data_?.map(({x, y}) => { const barWidth = xScale.bandwidth(); @@ -62,14 +84,28 @@ export default function Chart({ data }) { y={barY} width={barWidth} height={barHeight} - fill="rgba(23, 233, 217, .5)" + fill='dodgerblue' onClick={() => { console.log("clicked graph") }} /> - ); + + ) })} + {false && } ); -} \ No newline at end of file +} +// \ No newline at end of file diff --git a/app/src/pages/Notebook.jsx b/app/src/pages/Notebook.jsx index 89af337..b3720cc 100644 --- a/app/src/pages/Notebook.jsx +++ b/app/src/pages/Notebook.jsx @@ -178,14 +178,15 @@ export function NotebookHeader({datasource, datasources, addCell, onPublish}) { } -function NotebookCellStatusBar({isComputing, columns, setVisualizationStyle}) { - const cols = columns || [] +function NotebookCellStatusBar({isComputing, cell, setVisualizationStyle}) { + const cols = cell?.result?.columns || [] const progressVisibility = isComputing ? '' : ' invisible ' return (
- + + 0.3s @@ -194,7 +195,7 @@ function NotebookCellStatusBar({isComputing, columns, setVisualizationStyle}) {
setVisualizationStyle({type: s.id})} items={[{id: 'table', name: 'Table'}, {id: 'bar', name: 'Bar'}]} /> @@ -202,10 +203,20 @@ function NotebookCellStatusBar({isComputing, columns, setVisualizationStyle}) {
- ({id: c, name: c}))} /> + ({id: c, name: c}))} + setSelected={(s) => setVisualizationStyle({options: {x: s.id, y: cell?.style?.options?.y}})} + />
- ({id: c, name: c}))} /> + ({id: c, name: c}))} + setSelected={(s) => setVisualizationStyle({options: {x: cell?.style?.options?.x, y: s.id}})} + />
@@ -253,17 +264,21 @@ function NotebookCell({api, datasource, setQuery, setResult, setStyle, cell, onR /> {}} + setVisualizationStyle={(newStyle) => setStyle(Object.assign({}, cell?.style, newStyle))} + cell={cell} /> - {cell.result.columns && ((cell.style && cell.style.type === 'table' )) && } - {cell.result.columns && ((cell.style && cell.style.type === 'bar' )) && } + {cell.result.columns && ((cell.style && cell.style.type === 'table' )) && ( +
+ )} + {cell.result.columns && ((cell.style && cell.style.type === 'bar' )) && ( + + )} {cell.result.error && {JSON.stringify(cell?.result?.error)}} ) @@ -316,17 +331,19 @@ export function Notebook({api, datasource, show, data}) { datasource={state.datasource_id} />
- {cells.map((cell, idx) => {}} - setQuery={updateCell(cell, 'query')} - setResult={updateCell(cell, 'result')} - setStyle={updateCell(cell, 'style')} - onRun={idx >= cells.length - 1 ? addCell : () => {}} - publishNotebook={publishNotebook} - />)} + {cells.map((cell, idx) => ( + {}} + setQuery={updateCell(cell, 'query')} + setResult={updateCell(cell, 'result')} + setStyle={updateCell(cell, 'style')} + onRun={idx >= cells.length - 1 ? addCell : () => {}} + publishNotebook={publishNotebook} + /> + ))}
)