@carto/api-client 0.5.0-alpha.3 → 0.5.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/build/api/carto-api-error.d.ts +1 -1
- package/build/api/query.d.ts +1 -1
- package/build/api/request-with-parameters.d.ts +2 -2
- package/build/api-client.cjs +2324 -2188
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.modern.js +2196 -2055
- package/build/api-client.modern.js.map +1 -1
- package/build/client.d.ts +2 -2
- package/build/constants-internal.d.ts +5 -5
- package/build/constants.d.ts +6 -6
- package/build/deck/get-data-filter-extension-props.d.ts +18 -0
- package/build/deck/index.d.ts +1 -0
- package/build/filters/Filter.d.ts +15 -3
- package/build/filters/FilterTypes.d.ts +1 -1
- package/build/filters/geosjonFeatures.d.ts +2 -2
- package/build/filters/tileFeatures.d.ts +8 -8
- package/build/filters/tileFeaturesRaster.d.ts +3 -3
- package/build/filters.d.ts +2 -2
- package/build/geo.d.ts +1 -1
- package/build/index.d.ts +1 -0
- package/build/models/common.d.ts +4 -3
- package/build/models/model.d.ts +2 -2
- package/build/operations/aggregation.d.ts +5 -5
- package/build/operations/applySorting.d.ts +3 -3
- package/build/operations/groupBy.d.ts +4 -4
- package/build/operations/groupByDate.d.ts +1 -1
- package/build/operations/histogram.d.ts +3 -3
- package/build/operations/scatterPlot.d.ts +3 -3
- package/build/sources/base-source.d.ts +2 -2
- package/build/sources/boundary-query-source.d.ts +1 -1
- package/build/sources/boundary-table-source.d.ts +1 -1
- package/build/sources/h3-query-source.d.ts +2 -2
- package/build/sources/h3-table-source.d.ts +2 -2
- package/build/sources/h3-tileset-source.d.ts +2 -2
- package/build/sources/index.d.ts +26 -26
- package/build/sources/quadbin-query-source.d.ts +2 -2
- package/build/sources/quadbin-table-source.d.ts +2 -2
- package/build/sources/quadbin-tileset-source.d.ts +2 -2
- package/build/sources/raster-source.d.ts +2 -2
- package/build/sources/types.d.ts +3 -3
- package/build/sources/vector-query-source.d.ts +1 -1
- package/build/sources/vector-table-source.d.ts +1 -1
- package/build/sources/vector-tileset-source.d.ts +2 -2
- package/build/spatial-index.d.ts +3 -3
- package/build/types-internal.d.ts +5 -5
- package/build/types.d.ts +15 -15
- package/build/utils/makeIntervalComplete.d.ts +1 -1
- package/build/utils.d.ts +3 -3
- package/build/widget-sources/types.d.ts +4 -2
- package/build/widget-sources/widget-query-source.d.ts +2 -1
- package/build/widget-sources/widget-remote-source.d.ts +3 -0
- package/build/widget-sources/widget-source.d.ts +3 -3
- package/build/widget-sources/widget-table-source.d.ts +2 -1
- package/build/widget-sources/widget-tileset-source.d.ts +22 -24
- package/package.json +36 -30
- package/src/api/carto-api-error.ts +1 -1
- package/src/api/query.ts +5 -5
- package/src/api/request-with-parameters.ts +6 -6
- package/src/client.ts +3 -3
- package/src/constants-internal.ts +5 -5
- package/src/constants.ts +6 -6
- package/src/deck/get-data-filter-extension-props.ts +146 -0
- package/src/deck/index.ts +1 -0
- package/src/filters/Filter.ts +18 -8
- package/src/filters/FilterTypes.ts +2 -2
- package/src/filters/geosjonFeatures.ts +2 -2
- package/src/filters/tileFeatures.ts +13 -19
- package/src/filters/tileFeaturesRaster.ts +7 -7
- package/src/filters.ts +4 -4
- package/src/geo.ts +12 -14
- package/src/index.ts +1 -0
- package/src/models/common.ts +9 -7
- package/src/models/model.ts +3 -4
- package/src/operations/aggregation.ts +5 -5
- package/src/operations/applySorting.ts +4 -4
- package/src/operations/groupBy.ts +4 -4
- package/src/operations/groupByDate.ts +1 -1
- package/src/operations/histogram.ts +4 -4
- package/src/operations/scatterPlot.ts +4 -4
- package/src/sources/base-source.ts +8 -8
- package/src/sources/boundary-query-source.ts +2 -2
- package/src/sources/boundary-table-source.ts +2 -2
- package/src/sources/h3-query-source.ts +7 -5
- package/src/sources/h3-table-source.ts +7 -5
- package/src/sources/h3-tileset-source.ts +4 -4
- package/src/sources/index.ts +26 -26
- package/src/sources/quadbin-query-source.ts +7 -5
- package/src/sources/quadbin-table-source.ts +7 -5
- package/src/sources/quadbin-tileset-source.ts +4 -4
- package/src/sources/raster-source.ts +8 -4
- package/src/sources/types.ts +3 -3
- package/src/sources/vector-query-source.ts +2 -3
- package/src/sources/vector-table-source.ts +2 -3
- package/src/sources/vector-tileset-source.ts +5 -5
- package/src/spatial-index.ts +4 -4
- package/src/types-internal.ts +5 -5
- package/src/types.ts +15 -15
- package/src/utils/makeIntervalComplete.ts +1 -1
- package/src/utils.ts +3 -3
- package/src/widget-sources/types.ts +5 -3
- package/src/widget-sources/widget-query-source.ts +6 -2
- package/src/widget-sources/widget-remote-source.ts +31 -16
- package/src/widget-sources/widget-source.ts +13 -4
- package/src/widget-sources/widget-table-source.ts +6 -2
- package/src/widget-sources/widget-tileset-source.ts +132 -81
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
WidgetRemoteSourceProps,
|
|
9
9
|
} from './widget-remote-source.js';
|
|
10
10
|
import {ModelSource} from '../models/model.js';
|
|
11
|
+
import {Filters} from '../types.js';
|
|
11
12
|
|
|
12
13
|
type LayerQuerySourceOptions =
|
|
13
14
|
| Omit<VectorQuerySourceOptions, 'filters'>
|
|
@@ -41,9 +42,12 @@ export type WidgetQuerySourceResult = {widgetSource: WidgetQuerySource};
|
|
|
41
42
|
export class WidgetQuerySource extends WidgetRemoteSource<
|
|
42
43
|
LayerQuerySourceOptions & WidgetRemoteSourceProps
|
|
43
44
|
> {
|
|
44
|
-
protected override getModelSource(
|
|
45
|
+
protected override getModelSource(
|
|
46
|
+
filters: Filters | undefined,
|
|
47
|
+
filterOwner?: string
|
|
48
|
+
): ModelSource {
|
|
45
49
|
return {
|
|
46
|
-
...super._getModelSource(
|
|
50
|
+
...super._getModelSource(filters, filterOwner),
|
|
47
51
|
type: 'query',
|
|
48
52
|
data: this.props.sqlQuery,
|
|
49
53
|
queryParameters: this.props.queryParameters,
|
|
@@ -31,10 +31,18 @@ export type WidgetRemoteSourceProps = WidgetSourceProps;
|
|
|
31
31
|
export abstract class WidgetRemoteSource<
|
|
32
32
|
Props extends WidgetRemoteSourceProps,
|
|
33
33
|
> extends WidgetSource<Props> {
|
|
34
|
+
protected _headers: Record<string, string> = {};
|
|
35
|
+
|
|
36
|
+
/** Assigns HTTP headers to be included on API requests from this source. */
|
|
37
|
+
setRequestHeaders(headers: Record<string, string>): void {
|
|
38
|
+
this._headers = headers;
|
|
39
|
+
}
|
|
40
|
+
|
|
34
41
|
async getCategories(
|
|
35
42
|
options: CategoryRequestOptions
|
|
36
43
|
): Promise<CategoryResponse> {
|
|
37
44
|
const {
|
|
45
|
+
filters = this.props.filters,
|
|
38
46
|
filterOwner,
|
|
39
47
|
spatialFilter,
|
|
40
48
|
spatialFiltersMode,
|
|
@@ -43,7 +51,7 @@ export abstract class WidgetRemoteSource<
|
|
|
43
51
|
...params
|
|
44
52
|
} = options;
|
|
45
53
|
const {column, operation, operationColumn} = params;
|
|
46
|
-
const source = this.getModelSource(filterOwner);
|
|
54
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
47
55
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
48
56
|
source,
|
|
49
57
|
spatialFilter,
|
|
@@ -65,7 +73,7 @@ export abstract class WidgetRemoteSource<
|
|
|
65
73
|
operation,
|
|
66
74
|
operationColumn: operationColumn || column,
|
|
67
75
|
},
|
|
68
|
-
opts: {abortController},
|
|
76
|
+
opts: {abortController, headers: this._headers},
|
|
69
77
|
}).then((res: CategoriesModelResponse) => normalizeObjectKeys(res.rows));
|
|
70
78
|
}
|
|
71
79
|
|
|
@@ -73,6 +81,7 @@ export abstract class WidgetRemoteSource<
|
|
|
73
81
|
options: FeaturesRequestOptions
|
|
74
82
|
): Promise<FeaturesResponse> {
|
|
75
83
|
const {
|
|
84
|
+
filters = this.props.filters,
|
|
76
85
|
filterOwner,
|
|
77
86
|
spatialFilter,
|
|
78
87
|
spatialFiltersMode,
|
|
@@ -81,7 +90,7 @@ export abstract class WidgetRemoteSource<
|
|
|
81
90
|
...params
|
|
82
91
|
} = options;
|
|
83
92
|
const {columns, dataType, featureIds, z, limit, tileResolution} = params;
|
|
84
|
-
const source = this.getModelSource(filterOwner);
|
|
93
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
85
94
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
86
95
|
source,
|
|
87
96
|
spatialFilter,
|
|
@@ -106,13 +115,14 @@ export abstract class WidgetRemoteSource<
|
|
|
106
115
|
limit: limit || 1000,
|
|
107
116
|
tileResolution: tileResolution || DEFAULT_TILE_RESOLUTION,
|
|
108
117
|
},
|
|
109
|
-
opts: {abortController},
|
|
118
|
+
opts: {abortController, headers: this._headers},
|
|
110
119
|
// Avoid `normalizeObjectKeys()`, which changes column names.
|
|
111
120
|
}).then(({rows}: FeaturesModelResponse) => ({rows}));
|
|
112
121
|
}
|
|
113
122
|
|
|
114
123
|
async getFormula(options: FormulaRequestOptions): Promise<FormulaResponse> {
|
|
115
124
|
const {
|
|
125
|
+
filters = this.props.filters,
|
|
116
126
|
filterOwner,
|
|
117
127
|
spatialFilter,
|
|
118
128
|
spatialFiltersMode,
|
|
@@ -122,7 +132,7 @@ export abstract class WidgetRemoteSource<
|
|
|
122
132
|
...params
|
|
123
133
|
} = options;
|
|
124
134
|
const {column, operation} = params;
|
|
125
|
-
const source = this.getModelSource(filterOwner);
|
|
135
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
126
136
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
127
137
|
source,
|
|
128
138
|
spatialFilter,
|
|
@@ -144,7 +154,7 @@ export abstract class WidgetRemoteSource<
|
|
|
144
154
|
operation: operation ?? 'count',
|
|
145
155
|
operationExp,
|
|
146
156
|
},
|
|
147
|
-
opts: {abortController},
|
|
157
|
+
opts: {abortController, headers: this._headers},
|
|
148
158
|
}).then((res: FormulaModelResponse) => normalizeObjectKeys(res.rows[0]));
|
|
149
159
|
}
|
|
150
160
|
|
|
@@ -152,6 +162,7 @@ export abstract class WidgetRemoteSource<
|
|
|
152
162
|
options: HistogramRequestOptions
|
|
153
163
|
): Promise<HistogramResponse> {
|
|
154
164
|
const {
|
|
165
|
+
filters = this.props.filters,
|
|
155
166
|
filterOwner,
|
|
156
167
|
spatialFilter,
|
|
157
168
|
spatialFiltersMode,
|
|
@@ -160,7 +171,7 @@ export abstract class WidgetRemoteSource<
|
|
|
160
171
|
...params
|
|
161
172
|
} = options;
|
|
162
173
|
const {column, operation, ticks} = params;
|
|
163
|
-
const source = this.getModelSource(filterOwner);
|
|
174
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
164
175
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
165
176
|
source,
|
|
166
177
|
spatialFilter,
|
|
@@ -178,7 +189,7 @@ export abstract class WidgetRemoteSource<
|
|
|
178
189
|
spatialFilter,
|
|
179
190
|
},
|
|
180
191
|
params: {column, operation, ticks},
|
|
181
|
-
opts: {abortController},
|
|
192
|
+
opts: {abortController, headers: this._headers},
|
|
182
193
|
}).then((res: HistogramModelResponse) => normalizeObjectKeys(res.rows));
|
|
183
194
|
|
|
184
195
|
if (data.length) {
|
|
@@ -196,6 +207,7 @@ export abstract class WidgetRemoteSource<
|
|
|
196
207
|
|
|
197
208
|
async getRange(options: RangeRequestOptions): Promise<RangeResponse> {
|
|
198
209
|
const {
|
|
210
|
+
filters = this.props.filters,
|
|
199
211
|
filterOwner,
|
|
200
212
|
spatialFilter,
|
|
201
213
|
spatialFiltersMode,
|
|
@@ -204,7 +216,7 @@ export abstract class WidgetRemoteSource<
|
|
|
204
216
|
...params
|
|
205
217
|
} = options;
|
|
206
218
|
const {column} = params;
|
|
207
|
-
const source = this.getModelSource(filterOwner);
|
|
219
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
208
220
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
209
221
|
source,
|
|
210
222
|
spatialFilter,
|
|
@@ -222,12 +234,13 @@ export abstract class WidgetRemoteSource<
|
|
|
222
234
|
spatialFilter,
|
|
223
235
|
},
|
|
224
236
|
params: {column},
|
|
225
|
-
opts: {abortController},
|
|
237
|
+
opts: {abortController, headers: this._headers},
|
|
226
238
|
}).then((res: RangeModelResponse) => normalizeObjectKeys(res.rows[0]));
|
|
227
239
|
}
|
|
228
240
|
|
|
229
241
|
async getScatter(options: ScatterRequestOptions): Promise<ScatterResponse> {
|
|
230
242
|
const {
|
|
243
|
+
filters = this.props.filters,
|
|
231
244
|
filterOwner,
|
|
232
245
|
spatialFilter,
|
|
233
246
|
spatialFiltersMode,
|
|
@@ -238,7 +251,7 @@ export abstract class WidgetRemoteSource<
|
|
|
238
251
|
const {xAxisColumn, xAxisJoinOperation, yAxisColumn, yAxisJoinOperation} =
|
|
239
252
|
params;
|
|
240
253
|
|
|
241
|
-
const source = this.getModelSource(filterOwner);
|
|
254
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
242
255
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
243
256
|
source,
|
|
244
257
|
spatialFilter,
|
|
@@ -265,7 +278,7 @@ export abstract class WidgetRemoteSource<
|
|
|
265
278
|
yAxisJoinOperation,
|
|
266
279
|
limit: HARD_LIMIT,
|
|
267
280
|
},
|
|
268
|
-
opts: {abortController},
|
|
281
|
+
opts: {abortController, headers: this._headers},
|
|
269
282
|
})
|
|
270
283
|
.then((res: ScatterModelResponse) => normalizeObjectKeys(res.rows))
|
|
271
284
|
.then((res) => res.map(({x, y}: {x: number; y: number}) => [x, y]));
|
|
@@ -273,6 +286,7 @@ export abstract class WidgetRemoteSource<
|
|
|
273
286
|
|
|
274
287
|
async getTable(options: TableRequestOptions): Promise<TableResponse> {
|
|
275
288
|
const {
|
|
289
|
+
filters = this.props.filters,
|
|
276
290
|
filterOwner,
|
|
277
291
|
spatialFilter,
|
|
278
292
|
spatialFiltersMode,
|
|
@@ -281,7 +295,7 @@ export abstract class WidgetRemoteSource<
|
|
|
281
295
|
...params
|
|
282
296
|
} = options;
|
|
283
297
|
const {columns, sortBy, sortDirection, offset = 0, limit = 10} = params;
|
|
284
|
-
const source = this.getModelSource(filterOwner);
|
|
298
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
285
299
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
286
300
|
source,
|
|
287
301
|
spatialFilter,
|
|
@@ -308,7 +322,7 @@ export abstract class WidgetRemoteSource<
|
|
|
308
322
|
limit,
|
|
309
323
|
offset,
|
|
310
324
|
},
|
|
311
|
-
opts: {abortController},
|
|
325
|
+
opts: {abortController, headers: this._headers},
|
|
312
326
|
}).then((res: TableModelResponse) => ({
|
|
313
327
|
// Avoid `normalizeObjectKeys()`, which changes column names.
|
|
314
328
|
rows: res.rows ?? (res as any).ROWS,
|
|
@@ -320,6 +334,7 @@ export abstract class WidgetRemoteSource<
|
|
|
320
334
|
options: TimeSeriesRequestOptions
|
|
321
335
|
): Promise<TimeSeriesResponse> {
|
|
322
336
|
const {
|
|
337
|
+
filters = this.props.filters,
|
|
323
338
|
filterOwner,
|
|
324
339
|
abortController,
|
|
325
340
|
spatialFilter,
|
|
@@ -339,7 +354,7 @@ export abstract class WidgetRemoteSource<
|
|
|
339
354
|
splitByCategoryValues,
|
|
340
355
|
} = params;
|
|
341
356
|
|
|
342
|
-
const source = this.getModelSource(filterOwner);
|
|
357
|
+
const source = this.getModelSource(filters, filterOwner);
|
|
343
358
|
const spatialFiltersResolution = this._getSpatialFiltersResolution(
|
|
344
359
|
source,
|
|
345
360
|
spatialFilter,
|
|
@@ -370,7 +385,7 @@ export abstract class WidgetRemoteSource<
|
|
|
370
385
|
splitByCategoryLimit,
|
|
371
386
|
splitByCategoryValues,
|
|
372
387
|
},
|
|
373
|
-
opts: {abortController},
|
|
388
|
+
opts: {abortController, headers: this._headers},
|
|
374
389
|
}).then((res: TimeSeriesModelResponse) => ({
|
|
375
390
|
rows: normalizeObjectKeys(res.rows),
|
|
376
391
|
categories: res.metadata?.categories,
|
|
@@ -17,7 +17,12 @@ import {
|
|
|
17
17
|
TimeSeriesResponse,
|
|
18
18
|
ViewState,
|
|
19
19
|
} from './types.js';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
FilterLogicalOperator,
|
|
22
|
+
Filter,
|
|
23
|
+
SpatialFilter,
|
|
24
|
+
Filters,
|
|
25
|
+
} from '../types.js';
|
|
21
26
|
import {getApplicableFilters} from '../utils.js';
|
|
22
27
|
import {getClient} from '../client.js';
|
|
23
28
|
import {ModelSource} from '../models/model.js';
|
|
@@ -58,10 +63,14 @@ export abstract class WidgetSource<Props extends WidgetSourceProps> {
|
|
|
58
63
|
* properties, and adding additional required properties including 'type' and
|
|
59
64
|
* 'data'.
|
|
60
65
|
*/
|
|
61
|
-
protected abstract getModelSource(
|
|
66
|
+
protected abstract getModelSource(
|
|
67
|
+
filters: Filters | undefined,
|
|
68
|
+
filterOwner?: string
|
|
69
|
+
): ModelSource;
|
|
62
70
|
|
|
63
71
|
protected _getModelSource(
|
|
64
|
-
|
|
72
|
+
filters: Filters | undefined,
|
|
73
|
+
filterOwner?: string
|
|
65
74
|
): Omit<ModelSource, 'type' | 'data'> {
|
|
66
75
|
const props = this.props;
|
|
67
76
|
return {
|
|
@@ -70,7 +79,7 @@ export abstract class WidgetSource<Props extends WidgetSourceProps> {
|
|
|
70
79
|
clientId: props.clientId as string,
|
|
71
80
|
accessToken: props.accessToken,
|
|
72
81
|
connectionName: props.connectionName,
|
|
73
|
-
filters: getApplicableFilters(
|
|
82
|
+
filters: getApplicableFilters(filterOwner, filters || props.filters),
|
|
74
83
|
filtersLogicalOperator: props.filtersLogicalOperator,
|
|
75
84
|
spatialDataType: props.spatialDataType,
|
|
76
85
|
spatialDataColumn: props.spatialDataColumn,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
WidgetRemoteSourceProps,
|
|
9
9
|
} from './widget-remote-source.js';
|
|
10
10
|
import {ModelSource} from '../models/model.js';
|
|
11
|
+
import {Filters} from '../types.js';
|
|
11
12
|
|
|
12
13
|
type LayerTableSourceOptions =
|
|
13
14
|
| Omit<VectorTableSourceOptions, 'filters'>
|
|
@@ -41,9 +42,12 @@ export type WidgetTableSourceResult = {widgetSource: WidgetTableSource};
|
|
|
41
42
|
export class WidgetTableSource extends WidgetRemoteSource<
|
|
42
43
|
LayerTableSourceOptions & WidgetRemoteSourceProps
|
|
43
44
|
> {
|
|
44
|
-
protected override getModelSource(
|
|
45
|
+
protected override getModelSource(
|
|
46
|
+
filters: Filters | undefined,
|
|
47
|
+
filterOwner?: string
|
|
48
|
+
): ModelSource {
|
|
45
49
|
return {
|
|
46
|
-
...super._getModelSource(
|
|
50
|
+
...super._getModelSource(filters, filterOwner),
|
|
47
51
|
type: 'table',
|
|
48
52
|
data: this.props.tableName,
|
|
49
53
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
1
2
|
import {TilesetSourceOptions} from '../sources/index.js';
|
|
2
3
|
import type {ModelSource} from '../models/index.js';
|
|
3
4
|
import {
|
|
4
5
|
CategoryRequestOptions,
|
|
5
6
|
CategoryResponse,
|
|
6
|
-
FeaturesRequestOptions,
|
|
7
7
|
FeaturesResponse,
|
|
8
8
|
FormulaRequestOptions,
|
|
9
9
|
FormulaResponse,
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
TimeSeriesRequestOptions,
|
|
19
19
|
TimeSeriesResponse,
|
|
20
20
|
} from './types.js';
|
|
21
|
-
import {InvalidColumnError, getApplicableFilters} from '../utils.js';
|
|
21
|
+
import {InvalidColumnError, assert, getApplicableFilters} from '../utils.js';
|
|
22
22
|
import {TileFormat} from '../constants.js';
|
|
23
|
-
import {SpatialFilter, Tile} from '../types.js';
|
|
23
|
+
import {Filter, Filters, SpatialFilter, Tile} from '../types.js';
|
|
24
24
|
import {
|
|
25
25
|
TileFeatureExtractOptions,
|
|
26
26
|
applyFilters,
|
|
@@ -39,6 +39,7 @@ import {FeatureData} from '../types-internal.js';
|
|
|
39
39
|
import {FeatureCollection} from 'geojson';
|
|
40
40
|
import {SpatialDataType} from '../sources/types.js';
|
|
41
41
|
import {WidgetSource, WidgetSourceProps} from './widget-source.js';
|
|
42
|
+
import {booleanEqual} from '@turf/boolean-equal';
|
|
42
43
|
|
|
43
44
|
// TODO(cleanup): Parameter defaults in source functions and widget API calls are
|
|
44
45
|
// currently duplicated and possibly inconsistent. Consider consolidating and
|
|
@@ -78,12 +79,18 @@ export type WidgetTilesetSourceResult = {widgetSource: WidgetTilesetSource};
|
|
|
78
79
|
export class WidgetTilesetSource<
|
|
79
80
|
Props extends WidgetTilesetSourceProps = WidgetTilesetSourceProps,
|
|
80
81
|
> extends WidgetSource<Props> {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
private _tiles: Tile[] = [];
|
|
83
|
+
private _features: FeatureData[] = [];
|
|
84
|
+
private _tileFeatureExtractOptions: TileFeatureExtractOptions = {};
|
|
85
|
+
private _tileFeatureExtractPreviousInputs: {spatialFilter?: SpatialFilter} =
|
|
86
|
+
{};
|
|
87
|
+
|
|
88
|
+
protected override getModelSource(
|
|
89
|
+
filters: Filters | undefined,
|
|
90
|
+
filterOwner: string
|
|
91
|
+
): ModelSource {
|
|
85
92
|
return {
|
|
86
|
-
...super._getModelSource(
|
|
93
|
+
...super._getModelSource(filters, filterOwner),
|
|
87
94
|
type: 'tileset',
|
|
88
95
|
data: this.props.tableName,
|
|
89
96
|
};
|
|
@@ -96,50 +103,58 @@ export class WidgetTilesetSource<
|
|
|
96
103
|
*/
|
|
97
104
|
loadTiles(tiles: unknown[]) {
|
|
98
105
|
this._tiles = tiles as Tile[];
|
|
106
|
+
this._features.length = 0;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
/** Configures options used to extract features from tiles. */
|
|
110
|
+
setTileFeatureExtractOptions(options: TileFeatureExtractOptions) {
|
|
111
|
+
this._tileFeatureExtractOptions = options;
|
|
112
|
+
this._features.length = 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected _extractTileFeatures(spatialFilter: SpatialFilter) {
|
|
116
|
+
// When spatial filter has not changed, don't redo extraction. If tiles or
|
|
117
|
+
// tile extract options change, features will have been cleared already.
|
|
118
|
+
const prevInputs = this._tileFeatureExtractPreviousInputs;
|
|
119
|
+
if (
|
|
120
|
+
this._features.length &&
|
|
121
|
+
prevInputs.spatialFilter &&
|
|
122
|
+
booleanEqual(prevInputs.spatialFilter, spatialFilter)
|
|
123
|
+
) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
114
127
|
this._features = tileFeatures({
|
|
128
|
+
...this.props,
|
|
129
|
+
...this._tileFeatureExtractOptions,
|
|
115
130
|
tiles: this._tiles,
|
|
116
|
-
options,
|
|
117
131
|
spatialFilter,
|
|
118
|
-
uniqueIdProperty,
|
|
119
|
-
...this.props,
|
|
120
132
|
});
|
|
133
|
+
|
|
134
|
+
prevInputs.spatialFilter = spatialFilter;
|
|
121
135
|
}
|
|
122
136
|
|
|
123
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Loads features as GeoJSON (used for testing).
|
|
139
|
+
* @experimental
|
|
140
|
+
* @internal Not for public use. Spatial filters in other method calls will be ignored.
|
|
141
|
+
*/
|
|
124
142
|
loadGeoJSON({
|
|
125
143
|
geojson,
|
|
126
144
|
spatialFilter,
|
|
127
|
-
uniqueIdProperty,
|
|
128
145
|
}: {
|
|
129
146
|
geojson: FeatureCollection;
|
|
130
147
|
spatialFilter: SpatialFilter;
|
|
131
|
-
uniqueIdProperty?: string;
|
|
132
148
|
}) {
|
|
133
149
|
this._features = geojsonFeatures({
|
|
134
150
|
geojson,
|
|
135
151
|
spatialFilter,
|
|
136
|
-
|
|
152
|
+
...this._tileFeatureExtractOptions,
|
|
137
153
|
});
|
|
154
|
+
this._tileFeatureExtractPreviousInputs.spatialFilter = spatialFilter;
|
|
138
155
|
}
|
|
139
156
|
|
|
140
|
-
override async getFeatures(
|
|
141
|
-
options: FeaturesRequestOptions
|
|
142
|
-
): Promise<FeaturesResponse> {
|
|
157
|
+
override async getFeatures(): Promise<FeaturesResponse> {
|
|
143
158
|
throw new Error('getFeatures not supported for tilesets');
|
|
144
159
|
}
|
|
145
160
|
|
|
@@ -147,22 +162,24 @@ export class WidgetTilesetSource<
|
|
|
147
162
|
column = '*',
|
|
148
163
|
operation = 'count',
|
|
149
164
|
joinOperation,
|
|
165
|
+
filters,
|
|
150
166
|
filterOwner,
|
|
167
|
+
spatialFilter,
|
|
151
168
|
}: FormulaRequestOptions): Promise<FormulaResponse> {
|
|
152
169
|
if (operation === 'custom') {
|
|
153
170
|
throw new Error('Custom aggregation not supported for tilesets');
|
|
154
171
|
}
|
|
155
172
|
|
|
156
|
-
if (!this._features.length) {
|
|
157
|
-
return {value: null};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
173
|
// Column is required except when operation is 'count'.
|
|
161
174
|
if ((column && column !== '*') || operation !== 'count') {
|
|
162
175
|
assertColumn(this._features, column);
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
const filteredFeatures = this._getFilteredFeatures(
|
|
178
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
179
|
+
spatialFilter,
|
|
180
|
+
filters,
|
|
181
|
+
filterOwner
|
|
182
|
+
);
|
|
166
183
|
|
|
167
184
|
if (filteredFeatures.length === 0 && operation !== 'count') {
|
|
168
185
|
return {value: null};
|
|
@@ -170,11 +187,7 @@ export class WidgetTilesetSource<
|
|
|
170
187
|
|
|
171
188
|
const targetOperation = aggregationFunctions[operation];
|
|
172
189
|
return {
|
|
173
|
-
value: targetOperation(
|
|
174
|
-
filteredFeatures as FeatureData[],
|
|
175
|
-
column,
|
|
176
|
-
joinOperation
|
|
177
|
-
),
|
|
190
|
+
value: targetOperation(filteredFeatures, column, joinOperation),
|
|
178
191
|
};
|
|
179
192
|
}
|
|
180
193
|
|
|
@@ -183,16 +196,22 @@ export class WidgetTilesetSource<
|
|
|
183
196
|
ticks,
|
|
184
197
|
column,
|
|
185
198
|
joinOperation,
|
|
199
|
+
filters,
|
|
186
200
|
filterOwner,
|
|
201
|
+
spatialFilter,
|
|
187
202
|
}: HistogramRequestOptions): Promise<HistogramResponse> {
|
|
203
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
204
|
+
spatialFilter,
|
|
205
|
+
filters,
|
|
206
|
+
filterOwner
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
assertColumn(this._features, column);
|
|
210
|
+
|
|
188
211
|
if (!this._features.length) {
|
|
189
212
|
return [];
|
|
190
213
|
}
|
|
191
214
|
|
|
192
|
-
const filteredFeatures = this._getFilteredFeatures(filterOwner);
|
|
193
|
-
|
|
194
|
-
assertColumn(this._features, column);
|
|
195
|
-
|
|
196
215
|
return histogram({
|
|
197
216
|
data: filteredFeatures,
|
|
198
217
|
valuesColumns: normalizeColumns(column),
|
|
@@ -207,15 +226,21 @@ export class WidgetTilesetSource<
|
|
|
207
226
|
operation = 'count',
|
|
208
227
|
operationColumn,
|
|
209
228
|
joinOperation,
|
|
229
|
+
filters,
|
|
210
230
|
filterOwner,
|
|
231
|
+
spatialFilter,
|
|
211
232
|
}: CategoryRequestOptions): Promise<CategoryResponse> {
|
|
212
|
-
|
|
233
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
234
|
+
spatialFilter,
|
|
235
|
+
filters,
|
|
236
|
+
filterOwner
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
if (!filteredFeatures.length) {
|
|
213
240
|
return [];
|
|
214
241
|
}
|
|
215
242
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
assertColumn(this._features, column as string, operationColumn as string);
|
|
243
|
+
assertColumn(this._features, column, operationColumn as string);
|
|
219
244
|
|
|
220
245
|
const groups = groupValuesByColumn({
|
|
221
246
|
data: filteredFeatures,
|
|
@@ -233,14 +258,20 @@ export class WidgetTilesetSource<
|
|
|
233
258
|
yAxisColumn,
|
|
234
259
|
xAxisJoinOperation,
|
|
235
260
|
yAxisJoinOperation,
|
|
261
|
+
filters,
|
|
236
262
|
filterOwner,
|
|
263
|
+
spatialFilter,
|
|
237
264
|
}: ScatterRequestOptions): Promise<ScatterResponse> {
|
|
238
|
-
|
|
265
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
266
|
+
spatialFilter,
|
|
267
|
+
filters,
|
|
268
|
+
filterOwner
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
if (!filteredFeatures.length) {
|
|
239
272
|
return [];
|
|
240
273
|
}
|
|
241
274
|
|
|
242
|
-
const filteredFeatures = this._getFilteredFeatures(filterOwner);
|
|
243
|
-
|
|
244
275
|
assertColumn(this._features, xAxisColumn, yAxisColumn);
|
|
245
276
|
|
|
246
277
|
return scatterPlot({
|
|
@@ -252,35 +283,36 @@ export class WidgetTilesetSource<
|
|
|
252
283
|
});
|
|
253
284
|
}
|
|
254
285
|
|
|
255
|
-
override async getTable(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
286
|
+
override async getTable({
|
|
287
|
+
columns,
|
|
288
|
+
searchFilterColumn,
|
|
289
|
+
searchFilterText,
|
|
290
|
+
sortBy,
|
|
291
|
+
sortDirection,
|
|
292
|
+
sortByColumnType,
|
|
293
|
+
offset = 0,
|
|
294
|
+
limit = 10,
|
|
295
|
+
filters,
|
|
296
|
+
filterOwner,
|
|
297
|
+
spatialFilter,
|
|
298
|
+
}: TableRequestOptions): Promise<TableResponse> {
|
|
299
|
+
// Filter.
|
|
300
|
+
let filteredFeatures = this._getFilteredFeatures(
|
|
301
|
+
spatialFilter,
|
|
302
|
+
filters,
|
|
303
|
+
filterOwner
|
|
304
|
+
);
|
|
269
305
|
|
|
270
|
-
if (!
|
|
306
|
+
if (!filteredFeatures.length) {
|
|
271
307
|
return {rows: [], totalCount: 0};
|
|
272
308
|
}
|
|
273
309
|
|
|
274
|
-
// Filter.
|
|
275
|
-
let filteredFeatures = this._getFilteredFeatures(filterOwner);
|
|
276
|
-
|
|
277
310
|
// Search.
|
|
278
|
-
// TODO: Could we get the same behavior by applying filters in loadTiles()?
|
|
279
311
|
if (searchFilterColumn && searchFilterText) {
|
|
280
312
|
filteredFeatures = filteredFeatures.filter(
|
|
281
313
|
(row) =>
|
|
282
314
|
row[searchFilterColumn] &&
|
|
283
|
-
String(row[searchFilterColumn])
|
|
315
|
+
String(row[searchFilterColumn] as unknown)
|
|
284
316
|
.toLowerCase()
|
|
285
317
|
.includes(String(searchFilterText).toLowerCase())
|
|
286
318
|
);
|
|
@@ -318,15 +350,21 @@ export class WidgetTilesetSource<
|
|
|
318
350
|
operation,
|
|
319
351
|
operationColumn,
|
|
320
352
|
joinOperation,
|
|
353
|
+
filters,
|
|
321
354
|
filterOwner,
|
|
355
|
+
spatialFilter,
|
|
322
356
|
}: TimeSeriesRequestOptions): Promise<TimeSeriesResponse> {
|
|
323
|
-
|
|
357
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
358
|
+
spatialFilter,
|
|
359
|
+
filters,
|
|
360
|
+
filterOwner
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
if (!filteredFeatures.length) {
|
|
324
364
|
return {rows: []};
|
|
325
365
|
}
|
|
326
366
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
assertColumn(this._features, column as string, operationColumn as string);
|
|
367
|
+
assertColumn(this._features, column, operationColumn as string);
|
|
330
368
|
|
|
331
369
|
const rows =
|
|
332
370
|
groupValuesByDateColumn({
|
|
@@ -343,17 +381,24 @@ export class WidgetTilesetSource<
|
|
|
343
381
|
|
|
344
382
|
override async getRange({
|
|
345
383
|
column,
|
|
384
|
+
filters,
|
|
346
385
|
filterOwner,
|
|
386
|
+
spatialFilter,
|
|
347
387
|
}: RangeRequestOptions): Promise<RangeResponse> {
|
|
388
|
+
assertColumn(this._features, column);
|
|
389
|
+
|
|
390
|
+
const filteredFeatures = this._getFilteredFeatures(
|
|
391
|
+
spatialFilter,
|
|
392
|
+
filters,
|
|
393
|
+
filterOwner
|
|
394
|
+
);
|
|
395
|
+
|
|
348
396
|
if (!this._features.length) {
|
|
349
397
|
// TODO: Is this the only nullable response in the Widgets API? If so,
|
|
350
398
|
// can we do something more consistent?
|
|
351
399
|
return null;
|
|
352
400
|
}
|
|
353
401
|
|
|
354
|
-
assertColumn(this._features, column);
|
|
355
|
-
|
|
356
|
-
const filteredFeatures = this._getFilteredFeatures(filterOwner);
|
|
357
402
|
return {
|
|
358
403
|
min: aggregationFunctions.min(filteredFeatures, column),
|
|
359
404
|
max: aggregationFunctions.max(filteredFeatures, column),
|
|
@@ -364,10 +409,16 @@ export class WidgetTilesetSource<
|
|
|
364
409
|
* INTERNAL
|
|
365
410
|
*/
|
|
366
411
|
|
|
367
|
-
private _getFilteredFeatures(
|
|
412
|
+
private _getFilteredFeatures(
|
|
413
|
+
spatialFilter?: SpatialFilter,
|
|
414
|
+
filters?: Record<string, Filter>,
|
|
415
|
+
filterOwner?: string
|
|
416
|
+
): FeatureData[] {
|
|
417
|
+
assert(spatialFilter, 'spatialFilter required for tilesets');
|
|
418
|
+
this._extractTileFeatures(spatialFilter);
|
|
368
419
|
return applyFilters(
|
|
369
420
|
this._features,
|
|
370
|
-
getApplicableFilters(filterOwner, this.props.filters),
|
|
421
|
+
getApplicableFilters(filterOwner, filters || this.props.filters),
|
|
371
422
|
this.props.filtersLogicalOperator || 'and'
|
|
372
423
|
);
|
|
373
424
|
}
|