Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 57 additions & 22 deletions ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export type Packed<T> = T | S
export interface Data {
list(): (Rec | null)[]
dict(): Dict<Rec>
getTupByIdx(i: U): Rec | null
}

interface OpsD {
Expand Down Expand Up @@ -399,6 +400,14 @@ export function unpack<T>(data: any): T {
: data
}

export function unpackByIdx<T>(data: any, idx: U): T {
return (typeof data === 'string')
? decodeString(data, idx)
: (isData(data))
? (data as Data).getTupByIdx(idx)
: data
}

const
errorCodes: Dict<WaveErrorCode> = {
not_found: WaveErrorCode.PageNotFound,
Expand All @@ -407,13 +416,31 @@ const
const i = d.indexOf(':')
return (i > 0) ? [d.substring(0, i), d.substring(i + 1)] : ['', d]
},
decodeString = (data: S): any => {
rowToRowObj = (item: any, fields: any) => {
const rec: Rec = {}
for (let j = 0; j < fields.length; j++) {
const f = fields[j], v = item[j]
rec[f] = v
}
return rec
},
colToRowObj = (columns: any, fields: any, idx: U) => {
const rec: Rec = {}
for (let j = 0; j < fields.length; j++) {
const f = fields[j], v = columns[j][idx]
rec[f] = v
}
return rec
},
decodeString = (data: S, idx?: U): any => {
if (data === '') return data
const [t, d] = decodeType(data)
switch (t) {
case 'data':
try {
return JSON.parse(d)
const parsedData = JSON.parse(d)
if (idx !== undefined && parsedData?.[idx]) return parsedData[idx]
return parsedData
} catch (e) {
console.error(e)
}
Expand All @@ -423,17 +450,12 @@ const
const [fields, rows] = JSON.parse(d)
if (!Array.isArray(fields)) return data
if (!Array.isArray(rows)) return data
const w = fields.length // width
if (idx !== undefined) return rowToRowObj(rows[idx], fields)
const recs: Rec[] = []
for (const r of rows) {
if (!Array.isArray(r)) continue
if (r.length !== w) continue
const rec: Rec = {}
for (let j = 0; j < w; j++) {
const f = fields[j], v = r[j]
rec[f] = v
}
recs.push(rec)
if (r.length !== fields.length) continue
recs.push(rowToRowObj(r, fields))
}
return recs
} catch (e) {
Expand All @@ -445,18 +467,13 @@ const
const [fields, columns] = JSON.parse(d)
if (!Array.isArray(fields)) return data
if (!Array.isArray(columns)) return data
const w = fields.length // width
if (columns.length !== w) return data
if (columns.length !== fields.length) return data
if (columns.length === 0) return data
if (idx !== undefined) return colToRowObj(columns, fields, idx)
const n = columns[0].length
const recs = new Array<Rec>(n)
const recs: Rec[] = []
for (let i = 0; i < n; i++) {
const rec: Rec = {}
for (let j = 0; j < w; j++) {
const f = fields[j], v = columns[j][i]
rec[f] = v
}
recs[i] = rec
recs.push(colToRowObj(columns, fields, i))
}
return recs
} catch (e) {
Expand Down Expand Up @@ -566,13 +583,20 @@ const
}
return null
},
getTupByIdx = (i: U): Rec | null => {
if (i >= 0 && i < n) {
const tup = tups[i]
if (tup) return t.make(tup)
}
return null
},
list = (): (Rec | null)[] => {
const xs: (Rec | null)[] = []
for (const tup of tups) xs.push(tup ? t.make(tup) : null)
return xs
},
dict = (): Dict<Rec> => ({})
return { __buf__: true, n, put, set, seti, get, geti, list, dict }
return { __buf__: true, n, put, set, seti, get, geti, getTupByIdx, list, dict }
},
newCycBuf = (t: Typ, tups: (Tup | null)[], i: U): CycBuf => {
const
Expand All @@ -590,6 +614,13 @@ const
get = (_k: S): Cur | null => {
return b.geti(i)
},
getTupByIdx = (i: U): Rec | null => {
if (i >= 0 && i < n) {
const tup = tups[i]
if (tup) return t.make(tup)
}
return null
},
list = (): Rec[] => {
const xs: Rec[] = []
for (let j = i, k = 0; k < n; j++, k++) {
Expand All @@ -600,7 +631,7 @@ const
return xs
},
dict = (): Dict<Rec> => ({})
return { __buf__: true, put, set, get, list, dict }
return { __buf__: true, put, set, get, getTupByIdx, list, dict }
},
newMapBuf = (t: Typ, tups: Dict<Tup>): MapBuf => {
const
Expand All @@ -624,6 +655,10 @@ const
const tup = tups[k]
return tup ? newCur(t, tup) : null
},
getTupByIdx = (i: U): Rec | null => {
const k = keysOf(tups)[i]
return t.make(tups[k])
},
list = (): Rec[] => {
const keys = keysOf(tups)
keys.sort()
Expand All @@ -636,7 +671,7 @@ const
for (const k in tups) d[k] = t.make(tups[k])
return d
}
return { __buf__: true, put, set, get, list, dict }
return { __buf__: true, put, set, get, getTupByIdx, list, dict }
},
newTups = (n: U) => {
const xs = new Array<Tup | null>(n)
Expand Down
1 change: 1 addition & 0 deletions ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"build": "tsc",
"build-dev": "tsc --project dev.tsconfig.json",
"build-dev-watch": "tsc --project dev.tsconfig.json --watch",
"minify": "terser dist/index.js -c -m -o dist/index.min.js",
"prepublishOnly": "npm run build && npm run minify",
"test": "echo \"Error: no test specified\" && exit 1"
Expand Down
17 changes: 8 additions & 9 deletions ui/src/plot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import { Chart } from '@antv/g2'
import { AdjustOption, AnnotationPosition, ArcOption, AxisOption, ChartCfg, CoordinateActions, CoordinateOption, DataMarkerOption, DataRegionOption, GeometryOption, LineOption, RegionOption, ScaleOption, TextOption, TooltipItem } from '@antv/g2/lib/interface'
import { B, Dict, Disposable, F, Model, on, parseI, parseU, Rec, S, unpack, V } from 'h2o-wave'
import { B, Dict, Disposable, F, Model, on, parseI, parseU, Rec, S, unpack, unpackByIdx, V } from 'h2o-wave'
import React from 'react'
import ReactDOM from 'react-dom'
import { stylesheet } from 'typestyle'
Expand Down Expand Up @@ -1040,11 +1040,12 @@ export interface Visualization {
const tooltipContainer = document.createElement('div')
tooltipContainer.className = 'g2-tooltip'

const PlotTooltip = ({ items, originalItems }: { items: TooltipItem[], originalItems: any[] }) =>
const PlotTooltip = ({ items, originalData }: { items: TooltipItem[], originalData: Rec }) =>
<>
{items.map(({ data, mappingData, color }: TooltipItem) =>
Object.keys(originalItems[data.idx]).map((itemKey, idx) => {
const item = originalItems[data.idx][itemKey]
{items.map(({ data, mappingData, color }: TooltipItem) => {
const originalItems = unpackByIdx<any>(originalData, data.idx)
return Object.keys(originalItems).map((itemKey, idx) => {
const item = originalItems[itemKey]
return <li key={idx} className="g2-tooltip-list-item" data-index={idx} style={{ display: 'flex', alignItems: 'center', marginBottom: 4 }}>
<span style={{ backgroundColor: mappingData?.color || color }} className="g2-tooltip-marker" />
<span style={{ display: 'inline-flex', flex: 1, justifyContent: 'space-between' }}>
Expand All @@ -1054,6 +1055,7 @@ const PlotTooltip = ({ items, originalItems }: { items: TooltipItem[], originalI
</li>
}
)
}
)}
</>

Expand All @@ -1066,7 +1068,6 @@ export const
currentChart = React.useRef<Chart | null>(null),
currentPlot = React.useRef<Plot | null>(null),
themeWatchRef = React.useRef<Disposable | null>(null),
originalDataRef = React.useRef<any[]>([]),
checkDimensionsPostInit = (w: F, h: F) => { // Safari fix
const el = container.current
if (!el) return
Expand All @@ -1091,7 +1092,6 @@ export const
data = refactorData(raw_data, plot.marks),
{ Chart } = await import('@antv/g2'),
chart = plot.marks ? new Chart(makeChart(el, space, plot.marks, model.interactions || [])) : null
originalDataRef.current = unpack<any[]>(model.data)
currentPlot.current = plot
if (chart) {
chart.tooltip({
Expand All @@ -1105,7 +1105,7 @@ export const
},
},
customContent: (_title, items) => {
ReactDOM.render(<PlotTooltip items={items} originalItems={originalDataRef.current} />, tooltipContainer)
ReactDOM.render(<PlotTooltip items={items} originalData={model.data} />, tooltipContainer)
return tooltipContainer
}
})
Expand Down Expand Up @@ -1155,7 +1155,6 @@ export const
const
raw_data = unpack<any[]>(model.data),
data = refactorData(raw_data, currentPlot.current.marks)
originalDataRef.current = unpack<any[]>(model.data)
currentChart.current.changeData(data)
}, [currentChart, currentPlot, model])

Expand Down
4 changes: 4 additions & 0 deletions ui/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { defineConfig } from 'vite'
import legacy from '@vitejs/plugin-legacy'
import eslintPlugin from 'vite-plugin-eslint'
import react from '@vitejs/plugin-react'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
Expand All @@ -31,6 +32,9 @@ export default defineConfig({
assetsDir: 'wave-static',
chunkSizeWarningLimit: 900
},
optimizeDeps: {
link: ['h2o-wave']
},
server: {
port: 3000,
proxy: {
Expand Down