@mwater/visualization 5.0.0 → 5.1.0

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.
Files changed (138) hide show
  1. package/lib/MWaterAddRelatedFormComponent.d.ts +1 -1
  2. package/lib/MWaterAddRelatedFormComponent.js +10 -17
  3. package/lib/MWaterContextComponent.d.ts +17 -7
  4. package/lib/MWaterContextComponent.js +51 -70
  5. package/lib/MWaterLoaderComponent.d.ts +2 -2
  6. package/lib/MWaterLoaderComponent.js +1 -1
  7. package/lib/MWaterTableSelectComponent.d.ts +0 -1
  8. package/lib/MWaterTableSelectComponent.js +20 -41
  9. package/lib/axes/RangesComponent.d.ts +12 -6
  10. package/lib/axes/RangesComponent.js +21 -10
  11. package/lib/dashboards/DashboardComponent.d.ts +1 -9
  12. package/lib/dashboards/DashboardComponent.js +16 -27
  13. package/lib/dashboards/ServerDashboardDataSource.d.ts +1 -0
  14. package/lib/dashboards/ServerDashboardDataSource.js +3 -0
  15. package/lib/datagrids/DatagridComponent.d.ts +10 -4
  16. package/lib/datagrids/DatagridComponent.js +34 -6
  17. package/lib/datagrids/DatagridDataSource.d.ts +1 -0
  18. package/lib/datagrids/DatagridDataSource.js +3 -0
  19. package/lib/datagrids/DatagridDesign.d.ts +2 -0
  20. package/lib/datagrids/DatagridDesignerComponent.js +3 -2
  21. package/lib/datagrids/DatagridViewComponent.d.ts +2 -0
  22. package/lib/datagrids/DatagridViewComponent.js +4 -3
  23. package/lib/datagrids/DirectDatagridDataSource.d.ts +1 -0
  24. package/lib/datagrids/DirectDatagridDataSource.js +26 -0
  25. package/lib/datagrids/LabeledExprGenerator.js +15 -0
  26. package/lib/datagrids/ServerDatagridDataSource.d.ts +1 -0
  27. package/lib/datagrids/ServerDatagridDataSource.js +15 -0
  28. package/lib/dayjs.d.ts +2 -0
  29. package/lib/dayjs.js +9 -0
  30. package/lib/index.d.ts +0 -1
  31. package/lib/index.js +2 -4
  32. package/lib/languages.js +5 -0
  33. package/lib/layouts/blocks/BlocksDisplayComponent.js +2 -2
  34. package/lib/layouts/grid/LegoLayoutEngine.d.ts +1 -1
  35. package/lib/maps/BufferLayerDesignerComponent.js +2 -2
  36. package/lib/maps/ChoroplethLayerDesigner.js +2 -2
  37. package/lib/maps/ClusterLayerDesignerComponent.js +2 -2
  38. package/lib/maps/DetailLevelSelectComponent.d.ts +1 -93
  39. package/lib/maps/DirectMapDataSource.js +1 -2
  40. package/lib/maps/GridLayerDesigner.js +2 -2
  41. package/lib/maps/Layer.js +7 -18
  42. package/lib/maps/MapComponent.js +1 -1
  43. package/lib/maps/MapDesignerComponent.d.ts +1 -12
  44. package/lib/maps/MapDesignerComponent.js +5 -12
  45. package/lib/maps/MarkersLayerDesignerComponent.js +2 -2
  46. package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -1
  47. package/lib/maps/PopupFilterJoinsUtils.js +4 -3
  48. package/lib/maps/RegionSelectComponent.d.ts +1 -33
  49. package/lib/maps/UtfGridLayer.js +1 -1
  50. package/lib/maps/VectorMapViewComponent.js +21 -29
  51. package/lib/quickfilter/QuickfiltersComponent.d.ts +2 -186
  52. package/lib/quickfilter/QuickfiltersDesignComponent.js +1 -1
  53. package/lib/quickfilter/TextLiteralComponent.d.ts +2 -186
  54. package/lib/quickfilter/TextLiteralComponent.js +3 -0
  55. package/lib/valueFormatter.js +52 -1
  56. package/lib/widgets/ImageWidgetComponent.js +2 -2
  57. package/lib/widgets/charts/calendar/CalendarChartDesignerComponent.js +2 -2
  58. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -1
  59. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +1 -1
  60. package/lib/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.js +2 -2
  61. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +1 -1
  62. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +2 -2
  63. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +2 -2
  64. package/lib/widgets/charts/pivot/PivotChartLayout.d.ts +3 -2
  65. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +4 -1
  66. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.js +1 -1
  67. package/lib/widgets/charts/table/TableChart.js +15 -4
  68. package/lib/widgets/charts/table/TableChartDesignerComponent.js +2 -2
  69. package/lib/widgets/charts/table/TableChartViewComponent.d.ts +2 -1
  70. package/lib/widgets/charts/table/TableChartViewComponent.js +9 -4
  71. package/lib/widgets/text/ExprItemEditorComponent.js +2 -2
  72. package/package.json +8 -8
  73. package/src/MWaterAddRelatedFormComponent.ts +15 -20
  74. package/src/MWaterAddRelatedIndicatorComponent.ts +1 -1
  75. package/src/MWaterContextComponent.tsx +140 -0
  76. package/src/MWaterLoaderComponent.ts +2 -2
  77. package/src/{MWaterTableSelectComponent.ts → MWaterTableSelectComponent.tsx} +61 -66
  78. package/src/axes/AxisBuilder.ts +1 -1
  79. package/src/axes/RangesComponent.ts +27 -16
  80. package/src/dashboards/{DashboardComponent.ts → DashboardComponent.tsx} +37 -40
  81. package/src/dashboards/ServerDashboardDataSource.ts +16 -12
  82. package/src/datagrids/DatagridComponent.ts +59 -14
  83. package/src/datagrids/DatagridDataSource.ts +8 -0
  84. package/src/datagrids/DatagridDesign.ts +3 -0
  85. package/src/datagrids/DatagridDesignerComponent.tsx +9 -1
  86. package/src/datagrids/DatagridViewComponent.ts +7 -3
  87. package/src/datagrids/DirectDatagridDataSource.ts +35 -0
  88. package/src/datagrids/LabeledExprGenerator.ts +15 -0
  89. package/src/datagrids/ServerDatagridDataSource.ts +22 -4
  90. package/src/dayjs.ts +5 -0
  91. package/src/index.ts +0 -2
  92. package/src/languages.ts +5 -0
  93. package/src/layouts/blocks/BlocksDisplayComponent.ts +2 -2
  94. package/src/layouts/grid/LegoLayoutEngine.ts +2 -2
  95. package/src/layouts/grid/WidgetContainerComponent.ts +2 -2
  96. package/src/maps/BingLayer.ts +2 -2
  97. package/src/maps/BufferLayerDesignerComponent.ts +1 -1
  98. package/src/maps/ChoroplethLayerDesigner.tsx +1 -1
  99. package/src/maps/ClusterLayerDesignerComponent.ts +1 -1
  100. package/src/maps/DirectMapDataSource.ts +1 -2
  101. package/src/maps/GridLayerDesigner.tsx +1 -1
  102. package/src/maps/Layer.ts +6 -16
  103. package/src/maps/LegendGroup.ts +1 -1
  104. package/src/maps/MWaterServerLayer.ts +2 -2
  105. package/src/maps/MapComponent.ts +1 -1
  106. package/src/maps/{MapDesignerComponent.ts → MapDesignerComponent.tsx} +8 -16
  107. package/src/maps/MarkersLayerDesignerComponent.ts +1 -1
  108. package/src/maps/PopupFilterJoinsUtils.ts +4 -4
  109. package/src/maps/RasterMapViewComponent.ts +0 -1
  110. package/src/maps/ServerMapDataSource.ts +6 -6
  111. package/src/maps/SwitchableTileUrlLayerDesigner.tsx +1 -13
  112. package/src/maps/UtfGridLayer.ts +4 -4
  113. package/src/maps/VectorMapViewComponent.tsx +23 -36
  114. package/src/maps/mapboxUtils.ts +2 -2
  115. package/src/quickfilter/QuickfiltersDesignComponent.tsx +1 -1
  116. package/src/quickfilter/TextLiteralComponent.ts +4 -0
  117. package/src/richtext/ExprItemsHtmlConverter.ts +1 -1
  118. package/src/richtext/FontColorPaletteItem.ts +1 -1
  119. package/src/richtext/FontSizePaletteItem.ts +1 -1
  120. package/src/richtext/ItemsHtmlConverter.ts +2 -2
  121. package/src/valueFormatter.ts +54 -1
  122. package/src/widgets/ImageWidgetComponent.ts +1 -1
  123. package/src/widgets/charts/calendar/CalendarChartDesignerComponent.ts +1 -1
  124. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +1 -1
  125. package/src/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.ts +1 -1
  126. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +1 -1
  127. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +1 -1
  128. package/src/widgets/charts/pivot/PivotChartLayout.ts +3 -2
  129. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +2 -2
  130. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +7 -3
  131. package/src/widgets/charts/pivot/PivotChartQueryBuilder.ts +1 -1
  132. package/src/widgets/charts/table/TableChart.ts +24 -14
  133. package/src/widgets/charts/table/TableChartDesignerComponent.ts +1 -1
  134. package/src/widgets/charts/table/TableChartViewComponent.ts +10 -5
  135. package/src/widgets/text/ExprItemEditorComponent.tsx +1 -1
  136. package/stories/dashboards.js +3 -3
  137. package/src/MWaterContextComponent.ts +0 -144
  138. package/src/TableSelectComponent.ts +0 -60
package/src/maps/Layer.ts CHANGED
@@ -312,22 +312,12 @@ export default class Layer<LayerDesign> {
312
312
 
313
313
  if (results[0].bounds) {
314
314
  const [w, s, e, n] = bbox(results[0].bounds)
315
- // Pad to 10km if point
316
- if (w === e && n === s) {
317
- bounds = {
318
- w: w - 0.1,
319
- s: s - 0.1,
320
- e: e + 0.1,
321
- n: n + 0.1
322
- }
323
- // Pad bounds to prevent too small box (10m)
324
- } else {
325
- bounds = {
326
- w: w - 0.001,
327
- s: s - 0.001,
328
- e: e + 0.001,
329
- n: n + 0.001
330
- }
315
+ // Pad bounds to prevent too small box (100m)
316
+ bounds = {
317
+ w: w - 0.001,
318
+ s: s - 0.001,
319
+ e: e + 0.001,
320
+ n: n + 0.001
331
321
  }
332
322
  }
333
323
 
@@ -76,7 +76,7 @@ class LegendItem extends React.Component<LegendItemProps> {
76
76
  }
77
77
 
78
78
  renderColorIndicator() {
79
- const indicatorStyle = {
79
+ const indicatorStyle: React.CSSProperties = {
80
80
  height: 10,
81
81
  width: 10,
82
82
  backgroundColor: this.props.color,
@@ -94,14 +94,14 @@ class LoadingLegend extends React.Component<LoadingLegendProps, LoadingLegendSta
94
94
  }
95
95
 
96
96
  componentDidMount() {
97
- return $.get(this.props.url).done((data) => {
97
+ return $.get(this.props.url).done((data: any) => {
98
98
  return this.setState({ html: data })
99
99
  })
100
100
  }
101
101
 
102
102
  componentWillReceiveProps(nextProps: any) {
103
103
  if (nextProps.url !== this.props.url) {
104
- return $.get(nextProps.url).done((data) => {
104
+ return $.get(nextProps.url).done((data: any) => {
105
105
  return this.setState({ html: data })
106
106
  })
107
107
  }
@@ -303,7 +303,7 @@ export default class MapComponent extends React.Component<MapComponentProps, Map
303
303
  gridTemplateAreas: `"header designer" "quickfilters designer" "view designer"`
304
304
  }
305
305
  },
306
- this.renderHeader(),
306
+ this.props.hideTitleBar != true ? this.renderHeader() : null,
307
307
  this.state.hideQuickfilters ? null : this.renderQuickfilter(),
308
308
  R("div", { style: { width: "100%", height: "100%", gridArea: "view", overflow: "hidden" } }, this.renderView()),
309
309
  designerVisible ? this.renderDesigner() : null
@@ -18,6 +18,7 @@ import { MapDesign } from "./MapDesign"
18
18
  import { JsonQLFilter } from "../JsonQLFilter"
19
19
  import QuickfiltersDesignComponent from "../quickfilter/QuickfiltersDesignComponent"
20
20
  import produce from "immer"
21
+ import { ActiveTablesContext } from "@mwater/expressions-ui"
21
22
 
22
23
  export interface MapDesignerComponentProps {
23
24
  /** Schema to use */
@@ -36,15 +37,6 @@ export interface MapDesignerComponentProps {
36
37
  }
37
38
 
38
39
  export default class MapDesignerComponent extends React.Component<MapDesignerComponentProps> {
39
- static childContextTypes = { activeTables: PropTypes.arrayOf(PropTypes.string.isRequired) }
40
-
41
- getChildContext() {
42
- return {
43
- // Pass active tables down to table select components so they can present a shorter list
44
- activeTables: MapUtils.getFilterableTables(this.props.design, this.props.schema)
45
- }
46
- }
47
-
48
40
  handleAttributionChange = (text: any) => {
49
41
  const design = { ...this.props.design, attribution: text }
50
42
  return this.props.onDesignChange(design)
@@ -229,14 +221,14 @@ export default class MapDesignerComponent extends React.Component<MapDesignerCom
229
221
  })
230
222
  }
231
223
 
224
+ const activeTables = MapUtils.getFilterableTables(this.props.design, this.props.schema)
232
225
 
233
- return R(
234
- "div",
235
- { style: { padding: 5 } },
236
- R(TabbedComponent, {
237
- initialTabId: "layers",
238
- tabs
239
- })
226
+ return (
227
+ <ActiveTablesContext.Provider value={activeTables}>
228
+ <div style={{ padding: 5 }}>
229
+ <TabbedComponent initialTabId="layers" tabs={tabs} />
230
+ </div>
231
+ </ActiveTablesContext.Provider>
240
232
  )
241
233
  }
242
234
  }
@@ -6,7 +6,7 @@ import { DataSource, ExprUtils, OpExpr, Schema } from "@mwater/expressions"
6
6
  import { ExprCompiler } from "@mwater/expressions"
7
7
  import AxisComponent from "./../axes/AxisComponent"
8
8
  import ColorComponent from "../ColorComponent"
9
- import TableSelectComponent from "../TableSelectComponent"
9
+ import { TableSelectComponent } from "@mwater/expressions-ui"
10
10
  import EditPopupComponent from "./EditPopupComponent"
11
11
  import ZoomLevelsComponent from "./ZoomLevelsComponent"
12
12
  import MarkerSymbolSelectComponent from "./MarkerSymbolSelectComponent"
@@ -38,7 +38,7 @@ export function createPopupFilters(
38
38
  type: "op",
39
39
  op: "within",
40
40
  table,
41
- exprs: [expr, { type: "literal", idTable: exprUtils.getExprIdTable(expr), valueType: "id", value: rowId }]
41
+ exprs: [expr, { type: "literal", idTable: exprUtils.getExprIdTable(expr) ?? undefined, valueType: "id", value: rowId }]
42
42
  }
43
43
  filters.push({ table, jsonql: exprCompiler.compileExpr({ expr: filterExpr, tableAlias: "{alias}" }) })
44
44
  }
@@ -90,10 +90,10 @@ export function createPopupFilters(
90
90
 
91
91
  // Create default popup filter joins where the join is just the id (not used for choropleth since that needs to join to admin_regions)
92
92
  export function createDefaultPopupFilterJoins(table: any) {
93
- const popupFilterJoins = {}
94
-
95
93
  // Return id of row for a simple match
96
- popupFilterJoins[table] = { table, type: "id" }
94
+ const popupFilterJoins = {
95
+ [table]: { table, type: "id" }
96
+ }
97
97
 
98
98
  return popupFilterJoins
99
99
  }
@@ -13,7 +13,6 @@ import { JsonQLFilter } from "../JsonQLFilter"
13
13
  import { MapDesign } from "./MapDesign"
14
14
  import { MapDataSource } from "./MapDataSource"
15
15
  import { MapScope } from "./MapUtils"
16
- import { defaultProps } from "react-select/src/Select"
17
16
 
18
17
  export interface RasterMapViewComponentProps {
19
18
  schema: Schema
@@ -79,7 +79,7 @@ export default class ServerMapDataSource implements MapDataSource {
79
79
 
80
80
  $.getJSON(url, (data: any) => {
81
81
  return callback(null, data)
82
- }).fail((xhr) => {
82
+ }).fail((xhr: any) => {
83
83
  console.log(xhr.responseText)
84
84
  return callback(new Error(xhr.responseText))
85
85
  })
@@ -317,9 +317,9 @@ class ServerMapLayerPopupWidgetDataSource implements WidgetDataSource {
317
317
  `maps/${this.options.mapId}/layers/${this.options.layerId}/widgets/${this.options.popupWidgetId}/data?` +
318
318
  querystring.stringify(query)
319
319
 
320
- return $.getJSON(url, (data) => {
320
+ return $.getJSON(url, (data: any) => {
321
321
  return callback(null, data)
322
- }).fail((xhr) => {
322
+ }).fail((xhr: any) => {
323
323
  console.log(xhr.responseText)
324
324
  return callback(new Error(xhr.responseText))
325
325
  })
@@ -374,7 +374,7 @@ class ServerQuickfilterDataSource implements QuickfiltersDataSource {
374
374
  `maps/${this.options.mapId}/quickfilters/${index}/values?` +
375
375
  querystring.stringify(query)
376
376
 
377
- const headers = {}
377
+ const headers: any = {}
378
378
  const cacheExpiry = this.options.dataSource.getCacheExpiry()
379
379
  if (cacheExpiry) {
380
380
  const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000)
@@ -387,10 +387,10 @@ class ServerQuickfilterDataSource implements QuickfiltersDataSource {
387
387
  url,
388
388
  headers
389
389
  })
390
- .done((data) => {
390
+ .done((data: any) => {
391
391
  return callback(null, data)
392
392
  })
393
- .fail((xhr) => {
393
+ .fail((xhr: any) => {
394
394
  console.log(xhr.responseText)
395
395
  return callback(new Error(xhr.responseText))
396
396
  })
@@ -3,22 +3,10 @@ import React from "react"
3
3
  const R = React.createElement
4
4
  import { produce } from "immer"
5
5
 
6
- import { ExprComponent, FilterExprComponent } from "@mwater/expressions-ui"
7
- import { ExprCompiler, Schema, DataSource, Expr, OpExpr } from "@mwater/expressions"
8
- import AxisComponent from "./../axes/AxisComponent"
9
- import TableSelectComponent from "../TableSelectComponent"
10
- import ColorComponent from "../ColorComponent"
11
- import Rcslider from "rc-slider"
12
- import ChoroplethLayerDesign from "./ChoroplethLayerDesign"
13
6
  import { JsonQLFilter } from "../index"
14
- import EditPopupComponent from "./EditPopupComponent"
15
- import ZoomLevelsComponent from "./ZoomLevelsComponent"
16
- import ui, { Radio } from "@mwater/react-library/lib/bootstrap"
17
- import { Axis } from "../axes/Axis"
7
+ import { Radio } from "@mwater/react-library/lib/bootstrap"
18
8
  import { SwitchableTileUrlLayerDesign } from "./SwitchableTileUrlLayer"
19
9
 
20
- import AdminScopeAndDetailLevelComponent from "./AdminScopeAndDetailLevelComponent"
21
- import ScopeAndDetailLevelComponent from "./ScopeAndDetailLevelComponent"
22
10
 
23
11
  /** Designer for a switchable tile url layer */
24
12
  export default class SwitchableTileUrlLayerDesigner extends React.Component<{
@@ -65,8 +65,8 @@ module.exports = L.Layer.extend({
65
65
 
66
66
  //Find a unique id in window we can use for our callbacks
67
67
  //Required for jsonP
68
- var i = 0
69
- while (window["lu" + i]) {
68
+ let i = 0
69
+ while ((window as any)["lu" + i]) {
70
70
  i++
71
71
  }
72
72
  this._windowKey = "lu" + i
@@ -244,9 +244,9 @@ module.exports = L.Layer.extend({
244
244
  script.setAttribute("type", "text/javascript")
245
245
  script.setAttribute("src", url)
246
246
 
247
- window[wk][functionName] = function (data: any) {
247
+ ;(window as any)[wk][functionName] = function (data: any) {
248
248
  self._cache[key] = data
249
- delete window[wk][functionName]
249
+ delete (window as any)[wk][functionName]
250
250
  head.removeChild(script)
251
251
  }
252
252
 
@@ -1,4 +1,4 @@
1
- import _ from "lodash"
1
+ import _, { find } from "lodash"
2
2
  import { LayerSpecification, MapLayerMouseEvent } from "maplibre-gl"
3
3
  import { DataSource, Schema } from "@mwater/expressions"
4
4
  import React, { CSSProperties, ReactNode, useEffect, useMemo, useState } from "react"
@@ -14,7 +14,7 @@ import {
14
14
  getFilterableTables as utilsGetFilterableTables,
15
15
  MapScope
16
16
  } from "./MapUtils"
17
- import { memoizedDebounce } from "../memoizedDebounce"
17
+ import {Color} from '@maplibre/maplibre-gl-style-spec';
18
18
 
19
19
  import "maplibre-gl/dist/maplibre-gl.css"
20
20
  import "./VectorMapViewComponent.css"
@@ -115,7 +115,7 @@ export function VectorMapViewComponent(props: {
115
115
  )
116
116
 
117
117
  // Last feature that mouse entered
118
- const lastFeature = useRef()
118
+ const lastFeature = useRef<string>()
119
119
 
120
120
  // Load map
121
121
  const map = useVectorMap({
@@ -162,6 +162,7 @@ export function VectorMapViewComponent(props: {
162
162
  })
163
163
 
164
164
  if (!results) {
165
+ setHoverContents(null)
165
166
  return
166
167
  }
167
168
 
@@ -171,15 +172,6 @@ export function VectorMapViewComponent(props: {
171
172
  }
172
173
  })
173
174
 
174
- const handleLayerHoverDebounced = memoizedDebounce(
175
- (layerViewId: string, ev: { data: any; event: any }) => {
176
- handleLayerHover(layerViewId, ev)
177
- },
178
- 250,
179
- { leading: true, trailing: false },
180
- (layerViewId, ev) => ev.data.id
181
- )
182
-
183
175
  /** Handle a click on a layer */
184
176
  const handleLayerClick = useStableCallback((layerViewId: string, ev: { data: any; event: any }) => {
185
177
  const layerView = props.design.layerViews.find(lv => lv.id == layerViewId)!
@@ -514,7 +506,7 @@ export function VectorMapViewComponent(props: {
514
506
  setBusy(b => b - 1)
515
507
 
516
508
  if (bounds) {
517
- map!.fitBounds([bounds.w, bounds.s, bounds.e, bounds.n], { padding: 20, duration: 3000 })
509
+ map!.fitBounds([bounds.w, bounds.s, bounds.e, bounds.n], { padding: 20, duration: 2500 })
518
510
 
519
511
  // Also record if editable as part of bounds
520
512
  setBounds(bounds)
@@ -598,42 +590,37 @@ export function VectorMapViewComponent(props: {
598
590
  return
599
591
  }
600
592
 
601
- const removes: { (): void }[] = []
602
593
 
603
- for (const clickHandler of layerClickHandlers) {
604
- const onEnter = (ev: MapLayerMouseEvent) => {
605
- if (!ev.features || !ev.features[0].properties) {
594
+ const layers = layerClickHandlers.map(clickHandler => clickHandler.mapLayerId)
595
+
596
+ const onEnter = (ev: MapLayerMouseEvent) => {
597
+ let f = map.queryRenderedFeatures(ev.point, { layers });
598
+ if (f.length) {
599
+ if(f[0].layer.type === 'fill' && f[0].layer.paint?.['fill-color']?.toString() == 'rgba(0,0,0,0)') {
606
600
  lastFeature.current = undefined
607
601
  setHoverContents(null)
608
602
  return
609
603
  }
610
-
611
- if (ev.features![0].properties.id !== lastFeature.current) {
604
+ if(lastFeature.current !== f[0].properties.id) {
605
+ lastFeature.current = f[0].properties.id
612
606
  setHoverContents(null)
613
- lastFeature.current = ev.features![0].properties.id
607
+ const handler = find(layerClickHandlers, {mapLayerId: f[0].layer.id})
608
+ handleLayerHover(handler!.layerViewId, {
609
+ data: f[0].properties,
610
+ event: ev
611
+ })
614
612
  }
615
-
616
- handleLayerHoverDebounced(clickHandler.layerViewId, {
617
- data: ev.features![0].properties,
618
- event: ev
619
- })
620
- }
621
- const onLeave = (ev: MapLayerMouseEvent) => {
613
+ } else {
622
614
  lastFeature.current = undefined
623
615
  setHoverContents(null)
624
616
  }
625
- map.on("mousemove", clickHandler.mapLayerId, onEnter)
626
- map.on("mouseleave", clickHandler.mapLayerId, onLeave)
627
- removes.push(() => {
628
- map.off("mousemove", clickHandler.mapLayerId, onEnter)
629
- map.off("mouseleave", clickHandler.mapLayerId, onLeave)
630
- })
631
617
  }
618
+ map.on("mousemove", onEnter)
619
+
632
620
  return () => {
633
- for (const remove of removes) {
634
- remove()
635
- }
621
+ map.off("mousemove", onEnter)
636
622
  }
623
+
637
624
  }, [map, layerClickHandlers])
638
625
 
639
626
  function renderLegend() {
@@ -3,7 +3,7 @@ import { Axis } from "../axes/Axis"
3
3
 
4
4
  /** Compile a color mapped axis to mapbox format case statement */
5
5
  export function compileColorMapToMapbox(axis: Axis | null | undefined, defaultColor: string): DataDrivenPropertyValueSpecification<string> | string {
6
- let compiled: DataDrivenPropertyValueSpecification<string> | string
6
+ let compiled: any
7
7
 
8
8
  if (axis && axis.colorMap && axis.colorMap.length > 0) {
9
9
  const excludedValues = axis.excludedValues || []
@@ -31,7 +31,7 @@ export function compileColorMapToMapbox(axis: Axis | null | undefined, defaultCo
31
31
 
32
32
  /** Compile a color that is transparent if excluded to mapbox format case statement */
33
33
  export function compileColorToMapbox(color: string, excludedValues?: any[]): DataDrivenPropertyValueSpecification<string> | string {
34
- let compiled: DataDrivenPropertyValueSpecification<string> | string
34
+ let compiled: any
35
35
 
36
36
  if (excludedValues) {
37
37
  // Create match operator
@@ -210,7 +210,7 @@ class QuickfilterDesignComponent extends React.Component<
210
210
  table: this.state.table,
211
211
  value: this.props.design.expr,
212
212
  onChange: this.handleExprChange,
213
- types: ["enum", "text", "enumset", "date", "datetime", "id[]", "text[]"]
213
+ types: ["enum", "text", "enumset", "date", "datetime", "id[]", "text[]"],
214
214
  })
215
215
  )
216
216
  ),
@@ -51,6 +51,10 @@ export default class TextLiteralComponent extends React.Component<TextLiteralCom
51
51
  // Create query to get matches
52
52
  const exprCompiler = new ExprCompiler(this.props.schema)
53
53
 
54
+ if(!this.props.expr.table) {
55
+ return
56
+ }
57
+
54
58
  // Add filter for input (simple if just text)
55
59
  if (exprType === "text") {
56
60
  if (input) {
@@ -121,7 +121,7 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
121
121
  const items = super.convertElemToItems(elem)
122
122
 
123
123
  // Ensure exprs have unique ids
124
- const takenIds = {}
124
+ const takenIds: { [id: string]: boolean } = {}
125
125
  var uniqueify = (items: any) => {
126
126
  for (let item of items) {
127
127
  if (item.type === "expr") {
@@ -36,7 +36,7 @@ export default class FontColorPaletteItem extends React.Component<
36
36
  }
37
37
 
38
38
  render() {
39
- const popupPosition = {
39
+ const popupPosition: React.CSSProperties = {
40
40
  position: "absolute",
41
41
  left: 0,
42
42
  zIndex: 1000,
@@ -60,7 +60,7 @@ export default class FontSizePaletteItem extends React.Component<FontSizePalette
60
60
  }
61
61
 
62
62
  render() {
63
- const popupPosition = {
63
+ const popupPosition: React.CSSProperties = {
64
64
  position: "absolute",
65
65
  left: 0,
66
66
  zIndex: 1000,
@@ -215,7 +215,7 @@ export default class ItemsHtmlConverter {
215
215
  }
216
216
 
217
217
  // Whitelist allowed tags and styles
218
- var allowedTags = {
218
+ var allowedTags: { [tag: string]: number } = {
219
219
  div: 1,
220
220
  p: 1,
221
221
  ul: 1,
@@ -236,7 +236,7 @@ var allowedTags = {
236
236
  strong: 1,
237
237
  font: 1
238
238
  }
239
- var allowedStyles = {
239
+ var allowedStyles: { [style: string]: number } = {
240
240
  "text-align": 1,
241
241
  "font-weight": 1,
242
242
  "font-style": 1,
@@ -1,6 +1,7 @@
1
1
  import { LiteralType } from "@mwater/expressions"
2
2
  import { format as d3Format } from "d3-format"
3
3
  import { fromLatLon } from "utm"
4
+ import dayjs from './dayjs'
4
5
 
5
6
  /** Option for list of format options */
6
7
  export interface FormatOption {
@@ -10,7 +11,7 @@ export interface FormatOption {
10
11
 
11
12
  /** Determine if can format type */
12
13
  export function canFormatType(type: LiteralType): boolean {
13
- return type == "number" || type == "geometry"
14
+ return type == "number" || type == "geometry" || type === "date" || type === "datetime"
14
15
  }
15
16
 
16
17
  /** Get available options for formatting a type. Null if not available */
@@ -35,6 +36,43 @@ export function getFormatOptions(type: LiteralType): FormatOption[] | null {
35
36
  ]
36
37
  }
37
38
 
39
+ if (type == "date") {
40
+ return [
41
+ { value: "ll", label: dayjs().format("ll") },
42
+ { value: "YYYY-MM-DD", label: dayjs().format("YYYY-MM-DD") },
43
+ { value: "YYYY-MMM-DD", label: dayjs().format("YYYY-MMM-DD") },
44
+ { value: "YYYY-MM", label: dayjs().format("YYYY-MM") },
45
+ { value: "YYYY", label: dayjs().format("YYYY") },
46
+ { value: "MMM YYYY", label: dayjs().format("MMM YYYY") },
47
+ { value: "MMM DD, YYYY", label: dayjs().format("MMM DD, YYYY") },
48
+ { value: "MMMM D, YYYY", label: dayjs().format("MMMM D, YYYY") },
49
+ { value: "MM/DD/YYYY", label: dayjs().format("MM/DD/YYYY") },
50
+ { value: "DD/MM/YYYY", label: dayjs().format("DD/MM/YYYY") },
51
+ { value: "DD-MM-YYYY", label: dayjs().format("DD-MM-YYYY") },
52
+ ]
53
+ }
54
+
55
+ if (type == "datetime") {
56
+ return [
57
+ { value: "lll", label: dayjs().format("lll") },
58
+ { value: "llll", label: dayjs().format("llll") },
59
+ { value: "YYYY-MM-DD", label: dayjs().format("YYYY-MM-DD") },
60
+ { value: "YYYY-MMM-DD", label: dayjs().format("YYYY-MMM-DD") },
61
+ { value: "YYYY-MM", label: dayjs().format("YYYY-MM") },
62
+ { value: "YYYY", label: dayjs().format("YYYY") },
63
+ { value: "MMM YYYY", label: dayjs().format("MMM YYYY") },
64
+ { value: "MMM DD, YYYY h:mm A", label: dayjs().format("MMM DD, YYYY h:mm A") },
65
+ { value: "MMMM D, YYYY h:mm A", label: dayjs().format("MMMM D, YYYY h:mm A") },
66
+ { value: "MMM DD, YYYY", label: dayjs().format("MMM DD, YYYY") },
67
+ { value: "MMMM D, YYYY", label: dayjs().format("MMMM D, YYYY") },
68
+ { value: "MM/DD/YYYY", label: dayjs().format("MM/DD/YYYY") },
69
+ { value: "DD/MM/YYYY", label: dayjs().format("DD/MM/YYYY") },
70
+ { value: "DD-MM-YYYY", label: dayjs().format("DD-MM-YYYY") },
71
+ { value: "YYYY-MM-DD HH:mm:ss", label: dayjs().format("YYYY-MM-DD HH:mm:ss") },
72
+ { value: "ISO 8601", label: dayjs().toISOString() },
73
+ ]
74
+ }
75
+
38
76
  return null
39
77
  }
40
78
 
@@ -48,6 +86,14 @@ export function getDefaultFormat(type: LiteralType): string {
48
86
  return "lat, lng"
49
87
  }
50
88
 
89
+ if (type == "date") {
90
+ return "ll"
91
+ }
92
+
93
+ if (type == "datetime") {
94
+ return "lll"
95
+ }
96
+
51
97
  throw new Error("Not supported")
52
98
  }
53
99
 
@@ -78,6 +124,13 @@ export function formatValue(
78
124
  return d3Format(format)(value)
79
125
  }
80
126
 
127
+ if (["date", "datetime"].includes(type)) {
128
+ if (format == "ISO 8601") {
129
+ return dayjs(value).toISOString()
130
+ }
131
+ return dayjs(value).format(format)
132
+ }
133
+
81
134
  if (type == "geometry") {
82
135
  if (format == "UTM") {
83
136
  if (value.type == "Point") {
@@ -10,7 +10,7 @@ import DropdownWidgetComponent from "./DropdownWidgetComponent"
10
10
  import ModalPopupComponent from "@mwater/react-library/lib/ModalPopupComponent"
11
11
  import TabbedComponent from "@mwater/react-library/lib/TabbedComponent"
12
12
  import { ExprComponent } from "@mwater/expressions-ui"
13
- import TableSelectComponent from "../TableSelectComponent"
13
+ import { TableSelectComponent } from "@mwater/expressions-ui"
14
14
  import ImageUploaderComponent from "./ImageUploaderComponent"
15
15
  import ImagelistCarouselComponent from "./ImagelistCarouselComponent"
16
16
  import { DataSource, Schema } from "@mwater/expressions"
@@ -7,7 +7,7 @@ import { DataSource, ExprUtils, Schema } from "@mwater/expressions"
7
7
  import AxisBuilder from "../../../axes/AxisBuilder"
8
8
  import AxisComponent from "../../../axes/AxisComponent"
9
9
  import { FilterExprComponent } from "@mwater/expressions-ui"
10
- import TableSelectComponent from "../../../TableSelectComponent"
10
+ import { TableSelectComponent } from "@mwater/expressions-ui"
11
11
  import ColorComponent from "../../../ColorComponent"
12
12
  import { CalendarChartDesign } from "./CalendarChart"
13
13
 
@@ -183,7 +183,7 @@ export default class ImageMosaicChart extends Chart {
183
183
 
184
184
  createDataTable(design: any, schema: Schema, dataSource: DataSource, data: any) {
185
185
  alert("Not available for Image Mosaics")
186
- return null
186
+ return []
187
187
  }
188
188
  // TODO
189
189
  // renderHeaderCell = (column) =>
@@ -8,7 +8,7 @@ import { DataSource, ExprUtils, Schema } from "@mwater/expressions"
8
8
  import AxisBuilder from "../../../axes/AxisBuilder"
9
9
  import AxisComponent from "../../../axes/AxisComponent"
10
10
  import { FilterExprComponent } from "@mwater/expressions-ui"
11
- import TableSelectComponent from "../../../TableSelectComponent"
11
+ import { TableSelectComponent } from "@mwater/expressions-ui"
12
12
 
13
13
  export interface ImageMosaicChartDesignerComponentProps {
14
14
  design: any
@@ -11,7 +11,7 @@ import ColorComponent from "../../../ColorComponent"
11
11
  import * as LayeredChartUtils from "./LayeredChartUtils"
12
12
  import LayeredChartCompiler from "./LayeredChartCompiler"
13
13
  import * as uiComponents from "../../../UIComponents"
14
- import TableSelectComponent from "../../../TableSelectComponent"
14
+ import { TableSelectComponent } from "@mwater/expressions-ui"
15
15
  import * as ui from "@mwater/react-library/lib/bootstrap"
16
16
  import { Checkbox } from "@mwater/react-library/lib/bootstrap"
17
17
  import PopoverHelpComponent from "@mwater/react-library/lib/PopoverHelpComponent"
@@ -5,7 +5,7 @@ const R = React.createElement
5
5
  import uuid from "uuid"
6
6
  import * as ui from "@mwater/react-library/lib/bootstrap"
7
7
  import { FilterExprComponent } from "@mwater/expressions-ui"
8
- import TableSelectComponent from "../../../TableSelectComponent"
8
+ import { TableSelectComponent } from "@mwater/expressions-ui"
9
9
  import AxisComponent from "../../../axes/AxisComponent"
10
10
  import { DataSource, Schema } from "@mwater/expressions"
11
11
 
@@ -40,8 +40,9 @@ export interface PivotChartLayoutCell {
40
40
  align: "left" | "center" | "right"
41
41
 
42
42
  /** section id of either a segment or intersection or blank area. Always a rectangle.
43
- * Id is like intersection id if intersection, id of segment if segment */
44
- section: string
43
+ * Id is like intersection id if intersection, id of segment if segment. Undefined if doesn't
44
+ * exist yet. */
45
+ section?: string
45
46
 
46
47
  /** true if cell is on top edge of section */
47
48
  sectionTop?: boolean
@@ -373,7 +373,7 @@ export default class PivotChartLayoutBuilder {
373
373
  const intersectionData = dataIndexed[intersectionId]
374
374
 
375
375
  // Create key to lookup value
376
- const key = {}
376
+ const key: { [rNcN: string]: any } = {}
377
377
  for (i = 0; i < row.length; i++) {
378
378
  part = row[i]
379
379
  key[`r${i}`] = part.value
@@ -727,7 +727,7 @@ export default class PivotChartLayoutBuilder {
727
727
  // Sort categories if segment is sorted
728
728
  if (segment.orderExpr) {
729
729
  // Index the ordering by the JSON.stringify to make it O(n)
730
- const orderIndex = {}
730
+ const orderIndex: { [key: string]: number } = {}
731
731
  const iterable = _.pluck(data[segment.id], "value")
732
732
  for (let index = 0; index < iterable.length; index++) {
733
733
  value = iterable[index]