@@ -16,6 +16,7 @@ export class DataService {
16
16
db ?: AsyncDuckDB
17
17
baseURL : string = window . location . origin
18
18
conn ?: AsyncDuckDBConnection
19
+ tooltipResults : any = { }
19
20
20
21
constructor ( completeCallback ?: ( s : string ) => void , config : DataConfig [ ] = defaultConfig ) {
21
22
this . config = config
@@ -79,27 +80,37 @@ export class DataService {
79
80
}
80
81
}
81
82
82
- async runQuery ( query : string ) {
83
+ async runQuery ( query : string , freshConn ?: boolean ) {
83
84
await this . initDb ( )
84
85
try {
85
- return await runQuery ( {
86
- conn : this . conn ! ,
86
+ const conn = freshConn ? await this . db ! . connect ( ) : this . conn !
87
+ const r = await runQuery ( {
88
+ conn,
87
89
query,
88
90
} )
91
+ if ( freshConn ) {
92
+ await conn . close ( )
93
+ }
94
+ return r
89
95
} catch ( e ) {
90
96
console . error ( e )
91
97
return [ ]
92
98
}
93
99
}
94
- async getQuantiles ( column : string | number , table : string , n : number ) : Promise < Array < number > > {
100
+ async getQuantiles ( column : string | number , table : string , n : number , idCol : string , filter ?: string ) : Promise < Array < number > > {
95
101
// breakpoints to use for quantile breaks
96
102
// eg. n=5 - 0.2, 0.4, 0.6, 0.8 - 4 breaks
97
103
// eg. n=4 - 0.25, 0.5, 0.75 - 3 breaks
98
104
const quantileFractions = Array . from ( { length : n - 1 } , ( _ , i ) => ( i + 1 ) / n )
99
- const query = `SELECT
105
+ let query = `SELECT
100
106
${ quantileFractions . map ( ( f , i ) => `approx_quantile("${ column } ", ${ f } ) as break${ i } ` ) }
101
- FROM ${ this . getFromQueryString ( table ) } ;
107
+ FROM ${ this . getFromQueryString ( table ) }
102
108
`
109
+ if ( filter ) {
110
+ query += ` WHERE "${ idCol } " LIKE '${ filter } %';`
111
+ } else {
112
+ query += ";"
113
+ }
103
114
const result = await this . runQuery ( query )
104
115
if ( ! result || result . length === 0 ) {
105
116
console . error ( `No results for quantile query: ${ query } ` )
@@ -114,7 +125,8 @@ export class DataService {
114
125
reversed : boolean ,
115
126
column : string | number ,
116
127
table : string ,
117
- n : number
128
+ n : number ,
129
+ filter ?: string
118
130
) {
119
131
// @ts -ignore
120
132
const d3Colors = d3 [ colorScheme ] ?. [ n ]
@@ -133,15 +145,21 @@ export class DataService {
133
145
if ( reversed ) {
134
146
rgbColors . reverse ( )
135
147
}
136
- const quantiles = await this . getQuantiles ( column , table , n )
137
- const query = `
148
+ const quantiles = await this . getQuantiles ( column , table , n , idColumn , filter )
149
+ let query = `
138
150
SELECT "${ column } ", "${ idColumn } ",
139
151
CASE
140
152
${ quantiles . map ( ( q , i ) => `WHEN "${ column } " < ${ q } THEN [${ rgbColors [ i ] } ]` ) . join ( "\n" ) }
153
+ WHEN "${ column } " IS NULL THEN [120,120,120,0]
141
154
ELSE [${ rgbColors [ rgbColors . length - 1 ] } ]
142
155
END as color
143
- FROM ${ this . getFromQueryString ( table ) } ;
156
+ FROM ${ this . getFromQueryString ( table ) }
144
157
`
158
+ if ( filter ) {
159
+ query += ` WHERE "${ idColumn } " LIKE '${ filter } %';`
160
+ } else {
161
+ query += ";"
162
+ }
145
163
// @ts -ignore
146
164
const colorValues = await this . runQuery ( query )
147
165
const colorMap = { }
@@ -156,41 +174,40 @@ export class DataService {
156
174
}
157
175
}
158
176
159
- ingestData ( data : Array < any > , config : DataConfig , dataStore : any ) {
160
- console . log ( config , data [ 0 ] )
161
- for ( let i = 0 ; i < data . length ; i ++ ) {
162
- const row = data [ i ]
163
- if ( ! row ?. [ config . id ] ) {
164
- console . error ( `Row ${ i } in ${ config . filename } is missing a valid id` )
177
+ async getTooltipValues (
178
+ id : string
179
+ ) {
180
+ if ( this . tooltipResults [ id ] ) {
181
+ return this . tooltipResults [ id ]
182
+ }
183
+ let data : any [ ] = [ ]
184
+ for ( let i = 0 ; i < this . config . length ; i ++ ) {
185
+ const c = this . config [ i ]
186
+ if ( ! c ) {
165
187
continue
166
188
}
167
- let id = `${ row [ config . id ] } `
168
- // if (id.length === 10) {
169
- // id = `0${id}`
170
- // }
171
- dataStore [ id ] = {
172
- ...row ,
173
- id,
174
- }
175
- // @ts -ignore
176
- }
177
- console . log ( "All done!" )
178
- if ( this . completeCallback ) {
179
- this . completeCallback ( config . filename )
180
- }
181
- this . complete . push ( config . filename )
182
- }
183
- async fetchData ( config : DataConfig ) {
184
- if ( this . complete . includes ( config . filename ) ) {
185
- return
186
- }
187
- await this . initDb ( )
188
- const dataStore = this . data [ config . filename ]
189
- if ( this . data [ config . filename ] ) {
190
- // console.error(`Data store already exists for ${config.filename}`);
191
- return
189
+
190
+ const query = `SELECT "${ c . columns . map ( spec => spec . column ) . join ( '","' ) } " FROM ${ this . getFromQueryString ( c . filename ) } WHERE "${ c . id } " = '${ id } '`
191
+ const result = await this . runQuery ( query , true )
192
+ data . push ( result [ 0 ] )
192
193
}
193
- this . data [ config . filename ] = { }
194
+ const mappedTooltipContent = this . config . map ( ( c , i ) => {
195
+ const dataOutput = {
196
+ header : c . name ,
197
+ }
198
+ if ( ! data [ i ] ) {
199
+ return dataOutput
200
+ }
201
+ const columns = JSON . parse ( JSON . stringify ( data ! [ i ] ) )
202
+ if ( columns ) {
203
+ c . columns . forEach ( ( col ) => {
204
+ // @ts -ignore
205
+ dataOutput [ col . name ] = columns [ col . column ]
206
+ } )
207
+ }
208
+ return dataOutput
209
+ } )
210
+ this . tooltipResults [ id ] = mappedTooltipContent
194
211
}
195
212
196
213
setCompleteCallback ( cb : ( s : string ) => void ) {
0 commit comments