@mwater/visualization 5.6.0 → 5.6.1
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/lib/ColorComponent.js +2 -2
- package/lib/TranslationsTabComponent.d.ts +34 -0
- package/lib/TranslationsTabComponent.js +256 -0
- package/lib/dashboards/DashboardComponent.js +1 -1
- package/lib/dashboards/ServerDashboardDataSource.d.ts +0 -1
- package/lib/dashboards/ServerDashboardDataSource.js +0 -15
- package/lib/dashboards/SettingsModalComponent.js +9 -233
- package/lib/datagrids/DatagridComponent.js +5 -0
- package/lib/datagrids/DatagridViewComponent.js +30 -4
- package/lib/maps/BufferLayer.d.ts +0 -13
- package/lib/maps/BufferLayer.js +12 -237
- package/lib/maps/BufferLayerDesignerComponent.d.ts +1 -1
- package/lib/maps/BufferLayerDesignerComponent.js +0 -5
- package/lib/maps/ChoroplethLayer.d.ts +1 -16
- package/lib/maps/ChoroplethLayer.js +13 -358
- package/lib/maps/ClusterLayer.d.ts +0 -9
- package/lib/maps/ClusterLayer.js +0 -250
- package/lib/maps/DirectMapDataSource.js +1 -38
- package/lib/maps/GridLayer.d.ts +0 -15
- package/lib/maps/GridLayer.js +0 -212
- package/lib/maps/Layer.d.ts +1 -26
- package/lib/maps/Layer.js +0 -13
- package/lib/maps/MapComponent.d.ts +19 -35
- package/lib/maps/MapComponent.js +135 -76
- package/lib/maps/MapControlComponent.d.ts +4 -5
- package/lib/maps/MapControlComponent.js +5 -12
- package/lib/maps/MapDesign.d.ts +8 -0
- package/lib/maps/MapDesignerComponent.d.ts +2 -0
- package/lib/maps/MapDesignerComponent.js +7 -2
- package/lib/maps/MapLayerDataSource.d.ts +0 -4
- package/lib/maps/MapLayerViewDesignerComponent.d.ts +3 -1
- package/lib/maps/MapLayerViewDesignerComponent.js +5 -1
- package/lib/maps/MapLayersDesignerComponent.d.ts +2 -0
- package/lib/maps/MapLayersDesignerComponent.js +2 -1
- package/lib/maps/MapTranslationsTab.d.ts +15 -0
- package/lib/maps/MapTranslationsTab.js +47 -0
- package/lib/maps/MapUtils.d.ts +11 -0
- package/lib/maps/MapUtils.js +47 -0
- package/lib/maps/MapViewComponent.d.ts +1 -1
- package/lib/maps/MapViewComponent.js +1 -8
- package/lib/maps/MarkersLayer.d.ts +1 -14
- package/lib/maps/MarkersLayer.js +71 -252
- package/lib/maps/MarkersLayerDesign.d.ts +4 -0
- package/lib/maps/MarkersLayerDesignerComponent.d.ts +20 -16
- package/lib/maps/MarkersLayerDesignerComponent.js +77 -23
- package/lib/maps/ServerMapDataSource.d.ts +0 -1
- package/lib/maps/ServerMapDataSource.js +0 -15
- package/lib/maps/SwitchableTileUrlLayer.d.ts +0 -2
- package/lib/maps/SwitchableTileUrlLayer.js +0 -9
- package/lib/maps/TileUrlLayer.d.ts +0 -1
- package/lib/maps/TileUrlLayer.js +0 -5
- package/lib/maps/VectorMapViewComponent.js +12 -1
- package/lib/maps/vectorMaps.d.ts +5 -6
- package/lib/maps/vectorMaps.js +13 -9
- package/lib/widgets/MapWidget.js +2 -1
- package/package.json +2 -2
- package/src/ColorComponent.tsx +2 -2
- package/src/TranslationsTabComponent.tsx +429 -0
- package/src/dashboards/DashboardComponent.tsx +1 -1
- package/src/dashboards/ServerDashboardDataSource.ts +0 -19
- package/src/dashboards/SettingsModalComponent.tsx +27 -383
- package/src/datagrids/DatagridComponent.tsx +6 -0
- package/src/datagrids/DatagridViewComponent.tsx +41 -5
- package/src/maps/BufferLayer.ts +16 -262
- package/src/maps/BufferLayerDesignerComponent.tsx +0 -6
- package/src/maps/ChoroplethLayer.ts +16 -393
- package/src/maps/ClusterLayer.ts +0 -274
- package/src/maps/DirectMapDataSource.ts +2 -49
- package/src/maps/GridLayer.ts +0 -224
- package/src/maps/Layer.ts +1 -35
- package/src/maps/MapComponent.tsx +448 -0
- package/src/maps/MapControlComponent.tsx +41 -0
- package/src/maps/MapDesign.ts +6 -0
- package/src/maps/MapDesignerComponent.tsx +18 -1
- package/src/maps/MapLayerDataSource.ts +0 -5
- package/src/maps/MapLayerViewDesignerComponent.ts +9 -2
- package/src/maps/MapLayersDesignerComponent.ts +4 -1
- package/src/maps/MapTranslationsTab.tsx +53 -0
- package/src/maps/MapUtils.ts +48 -0
- package/src/maps/MapViewComponent.tsx +2 -8
- package/src/maps/MarkersLayer.ts +79 -270
- package/src/maps/MarkersLayerDesign.ts +6 -0
- package/src/maps/MarkersLayerDesignerComponent.tsx +114 -38
- package/src/maps/ServerMapDataSource.ts +0 -19
- package/src/maps/SwitchableTileUrlLayer.tsx +0 -11
- package/src/maps/TileUrlLayer.tsx +0 -6
- package/src/maps/VectorMapViewComponent.tsx +13 -2
- package/src/maps/vectorMaps.tsx +12 -9
- package/src/widgets/MapWidget.tsx +2 -0
- package/src/maps/MapComponent.ts +0 -311
- package/src/maps/MapControlComponent.ts +0 -46
- package/src/maps/RasterMapViewComponent.ts +0 -345
package/src/maps/BufferLayer.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { getDefaultLayoutOptions } from "../dashboards/layoutOptions"
|
|
|
18
18
|
import Widget from "../widgets/Widget"
|
|
19
19
|
import BlocksLayoutManager from "../layouts/blocks/BlocksLayoutManager"
|
|
20
20
|
import { getTranslatableStringsFromLayoutManager } from "../dashboards/DashboardUtils"
|
|
21
|
-
import { getSimpleHoverOverData } from "./MapUtils"
|
|
21
|
+
import { getSimpleHoverOverData, getTranslatableStringsFromAxis, translateAxis } from "./MapUtils"
|
|
22
22
|
|
|
23
23
|
/** Layer which draws a buffer around geometries (i.e. a radius circle around points) */
|
|
24
24
|
export default class BufferLayer extends Layer<BufferLayerDesign> {
|
|
@@ -313,259 +313,6 @@ export default class BufferLayer extends Layer<BufferLayerDesign> {
|
|
|
313
313
|
return query
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
// Gets the layer definition as JsonQL + CSS in format:
|
|
317
|
-
// {
|
|
318
|
-
// layers: array of { id: layer id, jsonql: jsonql that includes "the_webmercator_geom" as a column }
|
|
319
|
-
// css: carto css
|
|
320
|
-
// interactivity: (optional) { layer: id of layer, fields: array of field names }
|
|
321
|
-
// }
|
|
322
|
-
// arguments:
|
|
323
|
-
// design: design of layer
|
|
324
|
-
// schema: schema to use
|
|
325
|
-
// filters: array of filters to apply. Each is { table: table id, jsonql: jsonql condition with {alias} for tableAlias. Use injectAlias to put in table alias
|
|
326
|
-
getJsonQLCss(design: BufferLayerDesign, schema: Schema, filters: JsonQLFilter[]) {
|
|
327
|
-
// Create design
|
|
328
|
-
const layerDef = {
|
|
329
|
-
layers: [{ id: "layer0", jsonql: this.createMapnikJsonQL(design, schema, filters) }],
|
|
330
|
-
css: this.createCss(design, schema),
|
|
331
|
-
interactivity: {
|
|
332
|
-
layer: "layer0",
|
|
333
|
-
fields: ["id"]
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return layerDef
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
createMapnikJsonQL(design: BufferLayerDesign, schema: Schema, filters: JsonQLFilter[]) {
|
|
341
|
-
let colorExpr: JsonQLExpr
|
|
342
|
-
const axisBuilder = new AxisBuilder({ schema })
|
|
343
|
-
const exprCompiler = new ExprCompiler(schema)
|
|
344
|
-
|
|
345
|
-
// Get radius expression
|
|
346
|
-
const radiusCompiledExpr: JsonQLExpr = exprCompiler.compileExpr({
|
|
347
|
-
expr: design.radiusExpr ?? { type: "literal", valueType: "number", value: design.radius },
|
|
348
|
-
tableAlias: "main"
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
// Convert radius in meters to a maximum number of degrees latitude
|
|
352
|
-
const radiusDegCompiledExpr: JsonQLExpr = { type: "op", op: "/", exprs: [radiusCompiledExpr, 100000] }
|
|
353
|
-
|
|
354
|
-
/*
|
|
355
|
-
Query:
|
|
356
|
-
select
|
|
357
|
-
<primary key> as id,
|
|
358
|
-
[<color axis> as color,
|
|
359
|
-
st_transform(<geometry axis>, 3857) as the_geom_webmercator,
|
|
360
|
-
radius * 2 / (!pixel_width! * cos(st_ymin(st_transform(geometryExpr, 4326)) * 0.017453293) as width
|
|
361
|
-
from <table> as main
|
|
362
|
-
where
|
|
363
|
-
<geometry axis> is not null
|
|
364
|
-
* Bounding box filter for speed
|
|
365
|
-
and <geometry axis> &&
|
|
366
|
-
ST_Transform(ST_Expand(
|
|
367
|
-
* Prevent 3857 overflow (i.e. > 85 degrees lat)
|
|
368
|
-
ST_Intersection(
|
|
369
|
-
ST_Transform(!bbox!, 4326),
|
|
370
|
-
ST_Expand(ST_MakeEnvelope(-180, -85, 180, 85, 4326), -<radius in degrees>))
|
|
371
|
-
, <radius in degrees>})
|
|
372
|
-
, 3857)
|
|
373
|
-
and <other filters>
|
|
374
|
-
*/
|
|
375
|
-
|
|
376
|
-
// Compile geometry axis
|
|
377
|
-
let geometryExpr = axisBuilder.compileAxis({ axis: design.axes.geometry!, tableAlias: "main" })
|
|
378
|
-
|
|
379
|
-
// radius * 2 / (!pixel_width! * cos(st_ymin(st_transform(geometryExpr, 4326)) * 0.017453293) + 1 # add one to make always visible
|
|
380
|
-
const widthExpr: JsonQLExpr = {
|
|
381
|
-
type: "op",
|
|
382
|
-
op: "+",
|
|
383
|
-
exprs: [
|
|
384
|
-
{
|
|
385
|
-
type: "op",
|
|
386
|
-
op: "/",
|
|
387
|
-
exprs: [
|
|
388
|
-
{ type: "op", op: "*", exprs: [radiusCompiledExpr, 2] },
|
|
389
|
-
{
|
|
390
|
-
type: "op",
|
|
391
|
-
op: "*",
|
|
392
|
-
exprs: [
|
|
393
|
-
{ type: "op", op: "nullif", exprs: [{ type: "token", token: "!pixel_height!" }, 0] },
|
|
394
|
-
{
|
|
395
|
-
type: "op",
|
|
396
|
-
op: "cos",
|
|
397
|
-
exprs: [
|
|
398
|
-
{
|
|
399
|
-
type: "op",
|
|
400
|
-
op: "*",
|
|
401
|
-
exprs: [
|
|
402
|
-
{
|
|
403
|
-
type: "op",
|
|
404
|
-
op: "ST_YMIN",
|
|
405
|
-
exprs: [{ type: "op", op: "ST_Transform", exprs: [geometryExpr, 4326] }]
|
|
406
|
-
},
|
|
407
|
-
0.017453293
|
|
408
|
-
]
|
|
409
|
-
}
|
|
410
|
-
]
|
|
411
|
-
}
|
|
412
|
-
]
|
|
413
|
-
}
|
|
414
|
-
]
|
|
415
|
-
},
|
|
416
|
-
2
|
|
417
|
-
]
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const selects: JsonQLSelect[] = [
|
|
421
|
-
{
|
|
422
|
-
type: "select",
|
|
423
|
-
expr: { type: "field", tableAlias: "main", column: schema.getTable(design.table)!.primaryKey },
|
|
424
|
-
alias: "id"
|
|
425
|
-
}, // main primary key as id
|
|
426
|
-
{ type: "select", expr: geometryExpr, alias: "the_geom_webmercator" },
|
|
427
|
-
{ type: "select", expr: widthExpr, alias: "width" } // Width of circles
|
|
428
|
-
]
|
|
429
|
-
|
|
430
|
-
// Add color select if color axis
|
|
431
|
-
if (design.axes.color) {
|
|
432
|
-
colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "main" })
|
|
433
|
-
selects.push({ type: "select", expr: colorExpr, alias: "color" })
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// Select _id, location and clustered row number
|
|
437
|
-
const query: JsonQLQuery = {
|
|
438
|
-
type: "query",
|
|
439
|
-
selects,
|
|
440
|
-
from: exprCompiler.compileTable(design.table, "main")
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const boundingBox: JsonQLExpr = {
|
|
444
|
-
type: "op",
|
|
445
|
-
op: "ST_Transform",
|
|
446
|
-
exprs: [
|
|
447
|
-
{
|
|
448
|
-
type: "op",
|
|
449
|
-
op: "ST_Expand",
|
|
450
|
-
exprs: [
|
|
451
|
-
{
|
|
452
|
-
type: "op",
|
|
453
|
-
op: "ST_Intersection",
|
|
454
|
-
exprs: [
|
|
455
|
-
{ type: "op", op: "ST_Transform", exprs: [{ type: "token", token: "!bbox!" }, 4326] },
|
|
456
|
-
{
|
|
457
|
-
type: "op",
|
|
458
|
-
op: "ST_Expand",
|
|
459
|
-
exprs: [
|
|
460
|
-
{ type: "op", op: "ST_MakeEnvelope", exprs: [-180, -85, 180, 85, 4326] },
|
|
461
|
-
{ type: "op", op: "*", exprs: [radiusDegCompiledExpr, -1] }
|
|
462
|
-
]
|
|
463
|
-
}
|
|
464
|
-
]
|
|
465
|
-
},
|
|
466
|
-
radiusDegCompiledExpr
|
|
467
|
-
]
|
|
468
|
-
},
|
|
469
|
-
3857
|
|
470
|
-
]
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Create filters. First ensure geometry and limit to bounding box
|
|
474
|
-
let whereClauses: JsonQLExpr[] = [
|
|
475
|
-
{ type: "op", op: "is not null", exprs: [geometryExpr] },
|
|
476
|
-
{
|
|
477
|
-
type: "op",
|
|
478
|
-
op: "&&",
|
|
479
|
-
exprs: [geometryExpr, boundingBox]
|
|
480
|
-
}
|
|
481
|
-
]
|
|
482
|
-
|
|
483
|
-
// Then add filters baked into layer
|
|
484
|
-
if (design.filter) {
|
|
485
|
-
whereClauses.push(exprCompiler.compileExpr({ expr: design.filter, tableAlias: "main" }))
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Then add extra filters passed in, if relevant
|
|
489
|
-
// Get relevant filters
|
|
490
|
-
const relevantFilters = _.where(filters, { table: design.table })
|
|
491
|
-
for (let filter of relevantFilters) {
|
|
492
|
-
whereClauses.push(injectTableAlias(filter.jsonql, "main"))
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
whereClauses = _.compact(whereClauses)
|
|
496
|
-
|
|
497
|
-
// Wrap if multiple
|
|
498
|
-
if (whereClauses.length > 1) {
|
|
499
|
-
query.where = { type: "op", op: "and", exprs: whereClauses }
|
|
500
|
-
} else {
|
|
501
|
-
query.where = whereClauses[0]
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// Sort order
|
|
505
|
-
if (design.axes.color && design.axes.color.colorMap) {
|
|
506
|
-
// TODO should use categories, not colormap order
|
|
507
|
-
const order = design.axes.color.drawOrder || _.pluck(design.axes.color.colorMap, "value")
|
|
508
|
-
const categories = axisBuilder.getCategories(design.axes.color, order)
|
|
509
|
-
|
|
510
|
-
const cases = _.map(categories, (category, i) => {
|
|
511
|
-
return {
|
|
512
|
-
when:
|
|
513
|
-
category.value != null
|
|
514
|
-
? ({ type: "op", op: "=", exprs: [colorExpr, category.value] } as JsonQLExpr)
|
|
515
|
-
: ({ type: "op", op: "is null", exprs: [colorExpr] } as JsonQLExpr),
|
|
516
|
-
then: order.indexOf(category.value) || -1
|
|
517
|
-
}
|
|
518
|
-
})
|
|
519
|
-
|
|
520
|
-
if (cases.length > 0) {
|
|
521
|
-
query.orderBy = [
|
|
522
|
-
{
|
|
523
|
-
expr: {
|
|
524
|
-
type: "case",
|
|
525
|
-
cases
|
|
526
|
-
},
|
|
527
|
-
direction: "desc" // Reverse color map order
|
|
528
|
-
}
|
|
529
|
-
]
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
return query
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
createCss(design: BufferLayerDesign, schema: Schema) {
|
|
537
|
-
let css =
|
|
538
|
-
`\
|
|
539
|
-
#layer0 {
|
|
540
|
-
marker-fill-opacity: ` +
|
|
541
|
-
design.fillOpacity +
|
|
542
|
-
`;
|
|
543
|
-
marker-type: ellipse;
|
|
544
|
-
marker-width: [width];
|
|
545
|
-
marker-line-width: 0;
|
|
546
|
-
marker-allow-overlap: true;
|
|
547
|
-
marker-ignore-placement: true;
|
|
548
|
-
marker-fill: ` +
|
|
549
|
-
(design.color || "transparent") +
|
|
550
|
-
`;
|
|
551
|
-
}\
|
|
552
|
-
`
|
|
553
|
-
|
|
554
|
-
// If color axes, add color conditions
|
|
555
|
-
if (design.axes.color != null && design.axes.color.colorMap != null) {
|
|
556
|
-
for (let item of design.axes.color.colorMap) {
|
|
557
|
-
// If invisible
|
|
558
|
-
if ((design.axes.color.excludedValues || []).includes(item.value)) {
|
|
559
|
-
css += `#layer0 [color=${JSON.stringify(item.value)}] { marker-fill-opacity: 0; }\n`
|
|
560
|
-
} else {
|
|
561
|
-
css += `#layer0 [color=${JSON.stringify(item.value)}] { marker-fill: ${item.color}; }\n`
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
return css
|
|
567
|
-
}
|
|
568
|
-
|
|
569
316
|
// Called when the interactivity grid is clicked.
|
|
570
317
|
// arguments:
|
|
571
318
|
// ev: { data: interactivty data e.g. `{ id: 123 }` }
|
|
@@ -760,7 +507,7 @@ marker-fill: ` +
|
|
|
760
507
|
// Get the legend to be optionally displayed on the map. Returns
|
|
761
508
|
// a React element
|
|
762
509
|
getLegend(options: LegendOptions<BufferLayerDesign>): ReactNode {
|
|
763
|
-
const { design, schema, name, dataSource, locale, filters } = options
|
|
510
|
+
const { design, schema, name, dataSource, locale, filters, translate } = options
|
|
764
511
|
const _filters = filters.slice()
|
|
765
512
|
if (design.filter != null) {
|
|
766
513
|
const exprCompiler = new ExprCompiler(schema)
|
|
@@ -771,16 +518,20 @@ marker-fill: ` +
|
|
|
771
518
|
}
|
|
772
519
|
|
|
773
520
|
const axisBuilder = new AxisBuilder({ schema })
|
|
521
|
+
|
|
522
|
+
// Clean and translate axis
|
|
523
|
+
const axis = translateAxis(axisBuilder.cleanAxis({
|
|
524
|
+
axis: design.axes.color,
|
|
525
|
+
table: design.table,
|
|
526
|
+
types: ["enum", "text", "boolean", "date"],
|
|
527
|
+
aggrNeed: "none"
|
|
528
|
+
}), translate)
|
|
529
|
+
|
|
774
530
|
return React.createElement(LayerLegendComponent, {
|
|
775
531
|
schema,
|
|
776
|
-
name,
|
|
532
|
+
name: translate(name),
|
|
777
533
|
filters: _.compact(_filters),
|
|
778
|
-
axis:
|
|
779
|
-
axis: design.axes.color,
|
|
780
|
-
table: design.table,
|
|
781
|
-
types: ["enum", "text", "boolean", "date"],
|
|
782
|
-
aggrNeed: "none"
|
|
783
|
-
})!,
|
|
534
|
+
axis: axis!,
|
|
784
535
|
radiusLayer: true,
|
|
785
536
|
defaultColor: design.color,
|
|
786
537
|
locale
|
|
@@ -932,6 +683,9 @@ marker-fill: ` +
|
|
|
932
683
|
getTranslatableStrings(design: BufferLayerDesign, schema: Schema): string[] {
|
|
933
684
|
const strings: string[] = []
|
|
934
685
|
|
|
686
|
+
// Add strings from axis category labels and null labels
|
|
687
|
+
strings.push(...getTranslatableStringsFromAxis(design.axes.color))
|
|
688
|
+
|
|
935
689
|
// Add strings from hoverOver items
|
|
936
690
|
if (design.hoverOver && design.hoverOver.items) {
|
|
937
691
|
for (const item of design.hoverOver.items) {
|
|
@@ -14,7 +14,6 @@ import * as PopupFilterJoinsUtils from "./PopupFilterJoinsUtils"
|
|
|
14
14
|
import { Checkbox } from "@mwater/react-library/lib/bootstrap"
|
|
15
15
|
import { BufferLayerDesign } from "./BufferLayerDesign"
|
|
16
16
|
import { JsonQLFilter } from "../JsonQLFilter"
|
|
17
|
-
import { areVectorMapsEnabled } from "./vectorMaps"
|
|
18
17
|
import { EditHoverOver } from "./EditHoverOver"
|
|
19
18
|
|
|
20
19
|
export interface BufferLayerDesignerComponentProps {
|
|
@@ -138,11 +137,6 @@ export default class BufferLayerDesignerComponent extends React.Component<Buffer
|
|
|
138
137
|
}
|
|
139
138
|
|
|
140
139
|
renderUnionShapes() {
|
|
141
|
-
// Only implemented for vector maps
|
|
142
|
-
if (!areVectorMapsEnabled()) {
|
|
143
|
-
return null
|
|
144
|
-
}
|
|
145
|
-
|
|
146
140
|
return (
|
|
147
141
|
<div className="mb-3">
|
|
148
142
|
<Checkbox
|