@mwater/visualization 5.5.0 → 5.6.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 (222) hide show
  1. package/lib/MWaterContextComponent.d.ts +1 -1
  2. package/lib/MWaterGlobalFiltersComponent.d.ts +2 -2
  3. package/lib/MWaterGlobalFiltersComponent.js +11 -20
  4. package/lib/MWaterLoaderComponent.d.ts +4 -13
  5. package/lib/MWaterLoaderComponent.js +2 -11
  6. package/lib/UndoStack.d.ts +2 -1
  7. package/lib/UndoStack.js +12 -6
  8. package/lib/dashboards/DashboardComponent.js +5 -4
  9. package/lib/dashboards/DashboardDesign.d.ts +1 -1
  10. package/lib/dashboards/ServerDashboardDataSource.js +0 -10
  11. package/lib/dashboards/SettingsModalComponent.js +1 -1
  12. package/lib/datagrids/DatagridComponent.js +22 -2
  13. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -3
  14. package/lib/datagrids/DatagridDesignerComponent.js +108 -120
  15. package/lib/datagrids/DatagridViewComponent.js +3 -2
  16. package/lib/datagrids/OrderBysDesignerComponent.d.ts +7 -7
  17. package/lib/datagrids/OrderBysDesignerComponent.js +19 -28
  18. package/lib/index.css +45 -2
  19. package/lib/index.d.ts +5 -5
  20. package/lib/index.js +2 -3
  21. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +8 -1
  22. package/lib/layouts/blocks/BlocksDisplayComponent.js +46 -4
  23. package/lib/maps/BufferLayer.js +12 -0
  24. package/lib/maps/BufferLayerDesign.d.ts +1 -1
  25. package/lib/maps/BufferLayerDesignerComponent.js +2 -2
  26. package/lib/maps/ChoroplethLayer.js +12 -0
  27. package/lib/maps/ChoroplethLayerDesign.d.ts +5 -2
  28. package/lib/maps/ChoroplethLayerDesigner.d.ts +10 -32
  29. package/lib/maps/ChoroplethLayerDesigner.js +58 -89
  30. package/lib/maps/DirectMapDataSource.js +0 -10
  31. package/lib/maps/EditHoverOver.d.ts +4 -3
  32. package/lib/maps/EditHoverOver.js +3 -3
  33. package/lib/maps/HoverContent.js +1 -1
  34. package/lib/maps/LeafletMapComponent.js +10 -19
  35. package/lib/maps/MapComponent.js +0 -1
  36. package/lib/maps/MapUtils.js +10 -1
  37. package/lib/maps/MarkersLayer.js +18 -2
  38. package/lib/maps/MarkersLayerDesign.d.ts +1 -1
  39. package/lib/maps/MarkersLayerDesignerComponent.d.ts +12 -41
  40. package/lib/maps/MarkersLayerDesignerComponent.js +81 -111
  41. package/lib/maps/ServerMapDataSource.js +0 -10
  42. package/lib/maps/VectorMapViewComponent.js +1 -9
  43. package/lib/maps/symbols/font-awesome/asterisk.png +0 -0
  44. package/lib/maps/symbols/font-awesome/ban.png +0 -0
  45. package/lib/maps/symbols/font-awesome/beer.png +0 -0
  46. package/lib/maps/symbols/font-awesome/bell.png +0 -0
  47. package/lib/maps/symbols/font-awesome/bolt.png +0 -0
  48. package/lib/maps/symbols/font-awesome/building.png +0 -0
  49. package/lib/maps/symbols/font-awesome/bullseye.png +0 -0
  50. package/lib/maps/symbols/font-awesome/bus.png +0 -0
  51. package/lib/maps/symbols/font-awesome/caret-up.png +0 -0
  52. package/lib/maps/symbols/font-awesome/certificate.png +0 -0
  53. package/lib/maps/symbols/font-awesome/check-circle.png +0 -0
  54. package/lib/maps/symbols/font-awesome/check.png +0 -0
  55. package/lib/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  56. package/lib/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  57. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  58. package/lib/maps/symbols/font-awesome/cloud.png +0 -0
  59. package/lib/maps/symbols/font-awesome/comment.png +0 -0
  60. package/lib/maps/symbols/font-awesome/crosshairs.png +0 -0
  61. package/lib/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  62. package/lib/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  63. package/lib/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  64. package/lib/maps/symbols/font-awesome/female.png +0 -0
  65. package/lib/maps/symbols/font-awesome/file.png +0 -0
  66. package/lib/maps/symbols/font-awesome/flag.png +0 -0
  67. package/lib/maps/symbols/font-awesome/flask.png +0 -0
  68. package/lib/maps/symbols/font-awesome/h-square.png +0 -0
  69. package/lib/maps/symbols/font-awesome/home.png +0 -0
  70. package/lib/maps/symbols/font-awesome/info-circle.png +0 -0
  71. package/lib/maps/symbols/font-awesome/male.png +0 -0
  72. package/lib/maps/symbols/font-awesome/medkit.png +0 -0
  73. package/lib/maps/symbols/font-awesome/mobile.png +0 -0
  74. package/lib/maps/symbols/font-awesome/plus-circle.png +0 -0
  75. package/lib/maps/symbols/font-awesome/plus-square.png +0 -0
  76. package/lib/maps/symbols/font-awesome/plus.png +0 -0
  77. package/lib/maps/symbols/font-awesome/square.png +0 -0
  78. package/lib/maps/symbols/font-awesome/star.png +0 -0
  79. package/lib/maps/symbols/font-awesome/thumbs-down.png +0 -0
  80. package/lib/maps/symbols/font-awesome/thumbs-up.png +0 -0
  81. package/lib/maps/symbols/font-awesome/ticket.png +0 -0
  82. package/lib/maps/symbols/font-awesome/times-circle.png +0 -0
  83. package/lib/maps/symbols/font-awesome/times.png +0 -0
  84. package/lib/maps/symbols/font-awesome/tint.png +0 -0
  85. package/lib/maps/symbols/font-awesome/tree.png +0 -0
  86. package/lib/maps/symbols/font-awesome/university.png +0 -0
  87. package/lib/maps/symbols/font-awesome/usd.png +0 -0
  88. package/lib/maps/symbols/font-awesome/user.png +0 -0
  89. package/lib/maps/symbols/font-awesome/users.png +0 -0
  90. package/lib/maps/symbols/font-awesome/wheelchair.png +0 -0
  91. package/lib/maps/symbols/sdf-ize.sh +93 -0
  92. package/lib/maps/vectorMaps.d.ts +1 -0
  93. package/lib/maps/vectorMaps.js +20 -36
  94. package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +4 -2
  95. package/lib/mwater_table_selection/IndicatorsListComponent.js +103 -34
  96. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.d.ts +18 -0
  97. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.js +80 -0
  98. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +26 -0
  99. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +237 -51
  100. package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +2 -2
  101. package/lib/mwater_table_selection/MWaterTableSelectComponent.js +9 -4
  102. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.d.ts +19 -0
  103. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.js +111 -0
  104. package/lib/quickfilter/QuickfiltersComponent.d.ts +3 -102
  105. package/lib/quickfilter/QuickfiltersComponent.js +53 -110
  106. package/lib/quickfilter/TextLiteralComponent.d.ts +23 -47
  107. package/lib/quickfilter/TextLiteralComponent.js +85 -82
  108. package/lib/widgets/MapWidget.js +4 -2
  109. package/lib/widgets/text/ExprItemEditorComponent.d.ts +3 -8
  110. package/lib/widgets/text/ExprItemEditorComponent.js +36 -33
  111. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +1 -0
  112. package/package.json +2 -3
  113. package/src/MWaterContextComponent.tsx +1 -1
  114. package/src/{MWaterGlobalFiltersComponent.ts → MWaterGlobalFiltersComponent.tsx} +32 -33
  115. package/src/{MWaterLoaderComponent.ts → MWaterLoaderComponent.tsx} +17 -18
  116. package/src/UndoStack.ts +14 -6
  117. package/src/dashboards/DashboardComponent.tsx +5 -4
  118. package/src/dashboards/DashboardDesign.ts +1 -1
  119. package/src/dashboards/ServerDashboardDataSource.ts +0 -12
  120. package/src/dashboards/SettingsModalComponent.tsx +1 -1
  121. package/src/datagrids/DatagridComponent.tsx +30 -2
  122. package/src/datagrids/DatagridDesignerComponent.tsx +241 -229
  123. package/src/datagrids/DatagridViewComponent.tsx +3 -2
  124. package/src/datagrids/OrderBysDesignerComponent.tsx +61 -70
  125. package/src/index.css +45 -2
  126. package/src/index.ts +5 -11
  127. package/src/layouts/blocks/BlocksDisplayComponent.tsx +60 -5
  128. package/src/maps/BufferLayer.ts +14 -1
  129. package/src/maps/BufferLayerDesign.ts +1 -1
  130. package/src/maps/BufferLayerDesignerComponent.tsx +2 -1
  131. package/src/maps/ChoroplethLayer.ts +20 -7
  132. package/src/maps/ChoroplethLayerDesign.ts +5 -2
  133. package/src/maps/ChoroplethLayerDesigner.tsx +169 -165
  134. package/src/maps/DirectMapDataSource.ts +0 -12
  135. package/src/maps/EditHoverOver.tsx +9 -5
  136. package/src/maps/HoverContent.tsx +1 -1
  137. package/src/maps/LeafletMapComponent.tsx +10 -19
  138. package/src/maps/MapComponent.ts +0 -1
  139. package/src/maps/MapUtils.ts +13 -1
  140. package/src/maps/MarkersLayer.ts +22 -5
  141. package/src/maps/MarkersLayerDesign.ts +1 -1
  142. package/src/maps/MarkersLayerDesignerComponent.tsx +360 -0
  143. package/src/maps/ServerMapDataSource.ts +0 -12
  144. package/src/maps/VectorMapViewComponent.tsx +2 -13
  145. package/src/maps/symbols/font-awesome/asterisk.png +0 -0
  146. package/src/maps/symbols/font-awesome/ban.png +0 -0
  147. package/src/maps/symbols/font-awesome/beer.png +0 -0
  148. package/src/maps/symbols/font-awesome/bell.png +0 -0
  149. package/src/maps/symbols/font-awesome/bolt.png +0 -0
  150. package/src/maps/symbols/font-awesome/building.png +0 -0
  151. package/src/maps/symbols/font-awesome/bullseye.png +0 -0
  152. package/src/maps/symbols/font-awesome/bus.png +0 -0
  153. package/src/maps/symbols/font-awesome/caret-up.png +0 -0
  154. package/src/maps/symbols/font-awesome/certificate.png +0 -0
  155. package/src/maps/symbols/font-awesome/check-circle.png +0 -0
  156. package/src/maps/symbols/font-awesome/check.png +0 -0
  157. package/src/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  158. package/src/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  159. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  160. package/src/maps/symbols/font-awesome/cloud.png +0 -0
  161. package/src/maps/symbols/font-awesome/comment.png +0 -0
  162. package/src/maps/symbols/font-awesome/crosshairs.png +0 -0
  163. package/src/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  164. package/src/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  165. package/src/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  166. package/src/maps/symbols/font-awesome/female.png +0 -0
  167. package/src/maps/symbols/font-awesome/file.png +0 -0
  168. package/src/maps/symbols/font-awesome/flag.png +0 -0
  169. package/src/maps/symbols/font-awesome/flask.png +0 -0
  170. package/src/maps/symbols/font-awesome/h-square.png +0 -0
  171. package/src/maps/symbols/font-awesome/home.png +0 -0
  172. package/src/maps/symbols/font-awesome/info-circle.png +0 -0
  173. package/src/maps/symbols/font-awesome/male.png +0 -0
  174. package/src/maps/symbols/font-awesome/medkit.png +0 -0
  175. package/src/maps/symbols/font-awesome/mobile.png +0 -0
  176. package/src/maps/symbols/font-awesome/plus-circle.png +0 -0
  177. package/src/maps/symbols/font-awesome/plus-square.png +0 -0
  178. package/src/maps/symbols/font-awesome/plus.png +0 -0
  179. package/src/maps/symbols/font-awesome/square.png +0 -0
  180. package/src/maps/symbols/font-awesome/star.png +0 -0
  181. package/src/maps/symbols/font-awesome/thumbs-down.png +0 -0
  182. package/src/maps/symbols/font-awesome/thumbs-up.png +0 -0
  183. package/src/maps/symbols/font-awesome/ticket.png +0 -0
  184. package/src/maps/symbols/font-awesome/times-circle.png +0 -0
  185. package/src/maps/symbols/font-awesome/times.png +0 -0
  186. package/src/maps/symbols/font-awesome/tint.png +0 -0
  187. package/src/maps/symbols/font-awesome/tree.png +0 -0
  188. package/src/maps/symbols/font-awesome/university.png +0 -0
  189. package/src/maps/symbols/font-awesome/usd.png +0 -0
  190. package/src/maps/symbols/font-awesome/user.png +0 -0
  191. package/src/maps/symbols/font-awesome/users.png +0 -0
  192. package/src/maps/symbols/font-awesome/wheelchair.png +0 -0
  193. package/src/maps/symbols/sdf-ize.sh +93 -0
  194. package/src/maps/vectorMaps.tsx +20 -44
  195. package/src/mwater_table_selection/IndicatorsListComponent.tsx +165 -37
  196. package/src/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.tsx +111 -0
  197. package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +373 -37
  198. package/src/mwater_table_selection/MWaterTableSelectComponent.tsx +12 -8
  199. package/src/mwater_table_selection/MWaterWorkflowsSelectComponent.tsx +159 -0
  200. package/src/quickfilter/{QuickfiltersComponent.ts → QuickfiltersComponent.tsx} +165 -158
  201. package/src/quickfilter/TextLiteralComponent.tsx +197 -0
  202. package/src/widgets/MapWidget.tsx +9 -1
  203. package/src/widgets/text/ExprItemEditorComponent.tsx +83 -77
  204. package/src/widgets/text/ExprUpdateModalComponent.tsx +1 -0
  205. package/test/UndoStackTests.ts +52 -1
  206. package/.storybook/config.js +0 -7
  207. package/.storybook/head.html +0 -3
  208. package/.storybook/webpack.config.js +0 -15
  209. package/src/maps/BingLayer.ts +0 -146
  210. package/src/maps/MarkersLayerDesignerComponent.ts +0 -374
  211. package/src/quickfilter/TextLiteralComponent.ts +0 -165
  212. package/stories/UpdateableComponent.js +0 -29
  213. package/stories/consoles.js +0 -202
  214. package/stories/dashboards.js +0 -217
  215. package/stories/datagridDesign.js +0 -114
  216. package/stories/datagrids.js +0 -69
  217. package/stories/dates.js +0 -80
  218. package/stories/exprcomponent.js +0 -43
  219. package/stories/index.js +0 -18
  220. package/stories/leaflet.js +0 -59
  221. package/stories/maps.js +0 -24
  222. package/stories/pivotChart.js +0 -235
@@ -1,10 +1,9 @@
1
1
  import _ from "lodash"
2
2
  import React from "react"
3
- const R = React.createElement
4
3
  import { produce } from "immer"
5
4
 
6
5
  import { ExprComponent, FilterExprComponent } from "@mwater/expressions-ui"
7
- import { ExprCompiler, Schema, DataSource, Expr, OpExpr } from "@mwater/expressions"
6
+ import { ExprCompiler, Schema, DataSource, Expr, OpExpr, ExprUtils } from "@mwater/expressions"
8
7
  import AxisComponent from "./../axes/AxisComponent"
9
8
  import { TableSelectComponent } from "@mwater/expressions-ui"
10
9
  import ColorComponent from "../ColorComponent"
@@ -18,7 +17,7 @@ import { Axis } from "../axes/Axis"
18
17
 
19
18
  import AdminScopeAndDetailLevelComponent from "./AdminScopeAndDetailLevelComponent"
20
19
  import ScopeAndDetailLevelComponent from "./ScopeAndDetailLevelComponent"
21
- import EditHoverOver from "./EditHoverOver"
20
+ import { EditHoverOver } from "./EditHoverOver"
22
21
 
23
22
  // Designer for a choropleth layer
24
23
  export default class ChoroplethLayerDesigner extends React.Component<{
@@ -188,9 +187,10 @@ export default class ChoroplethLayerDesigner extends React.Component<{
188
187
  }
189
188
 
190
189
  renderRegionsTable() {
190
+ // Regions tables are either "regions." or "regions_<name>" with a shape column
191
191
  let options = _.map(
192
- _.filter(this.props.schema.getTables(), table => table.id.startsWith("regions.")),
193
- table => ({ value: table.id, label: table.name.en })
192
+ _.filter(this.props.schema.getTables(), table => table.id.startsWith("regions.") || (table.id.startsWith("regions_") && this.props.schema.getColumn(table.id, "shape") != null)),
193
+ table => ({ value: table.id, label: ExprUtils.localizeString(table.name) })
194
194
  )
195
195
 
196
196
  const regionsTable = this.props.design.regionsTable || "admin_regions"
@@ -253,34 +253,34 @@ export default class ChoroplethLayerDesigner extends React.Component<{
253
253
  const regionsTable = this.props.design.regionsTable || "admin_regions"
254
254
 
255
255
  if (regionsTable === "admin_regions") {
256
- return R(AdminScopeAndDetailLevelComponent, {
257
- schema: this.props.schema,
258
- dataSource: this.props.dataSource,
259
- scope: this.props.design.scope as number | undefined,
260
- scopeLevel: this.props.design.scopeLevel || 0,
261
- detailLevel: this.props.design.detailLevel,
262
- onScopeAndDetailLevelChange: this.handleScopeAndDetailLevelChange
263
- })
256
+ return <AdminScopeAndDetailLevelComponent
257
+ schema={this.props.schema}
258
+ dataSource={this.props.dataSource}
259
+ scope={this.props.design.scope as number | undefined}
260
+ scopeLevel={this.props.design.scopeLevel || 0}
261
+ detailLevel={this.props.design.detailLevel}
262
+ onScopeAndDetailLevelChange={this.handleScopeAndDetailLevelChange}
263
+ />
264
264
  } else {
265
- return R(ScopeAndDetailLevelComponent, {
266
- schema: this.props.schema,
267
- dataSource: this.props.dataSource,
268
- scope: this.props.design.scope as string | undefined,
269
- scopeLevel: this.props.design.scopeLevel,
270
- detailLevel: this.props.design.detailLevel,
271
- onScopeAndDetailLevelChange: this.handleScopeAndDetailLevelChange,
272
- regionsTable
273
- })
265
+ return <ScopeAndDetailLevelComponent
266
+ schema={this.props.schema}
267
+ dataSource={this.props.dataSource}
268
+ scope={this.props.design.scope as string | undefined}
269
+ scopeLevel={this.props.design.scopeLevel}
270
+ detailLevel={this.props.design.detailLevel}
271
+ onScopeAndDetailLevelChange={this.handleScopeAndDetailLevelChange}
272
+ regionsTable={regionsTable}
273
+ />
274
274
  }
275
275
  }
276
276
 
277
277
  renderDisplayNames() {
278
- return R(
279
- "div",
280
- { className: "mb-3" },
281
- <ui.Checkbox value={this.props.design.displayNames} onChange={value => this.handleDisplayNamesChange(value)}>
282
- {T`Display Region Names`}
283
- </ui.Checkbox>
278
+ return (
279
+ <div className="mb-3">
280
+ <ui.Checkbox value={this.props.design.displayNames} onChange={value => this.handleDisplayNamesChange(value)}>
281
+ {T`Display Region Names`}
282
+ </ui.Checkbox>
283
+ </div>
284
284
  )
285
285
  }
286
286
 
@@ -290,19 +290,20 @@ export default class ChoroplethLayerDesigner extends React.Component<{
290
290
  return null
291
291
  }
292
292
 
293
- return R(
294
- "div",
295
- { className: "mb-3" },
296
- R("label", { className: "text-muted" }, R("span", { className: "fas fa-tint" }), T`Fill Color`),
297
-
298
- R(
299
- "div",
300
- null,
301
- R(ColorComponent, {
302
- color: this.props.design.color,
303
- onChange: this.handleColorChange
304
- })
305
- )
293
+ return (
294
+ <div className="mb-3">
295
+ <label className="text-muted">
296
+ <span className="fas fa-tint" />
297
+ {T`Fill Color`}
298
+ </label>
299
+
300
+ <div>
301
+ <ColorComponent
302
+ color={this.props.design.color}
303
+ onChange={this.handleColorChange}
304
+ />
305
+ </div>
306
+ </div>
306
307
  )
307
308
  }
308
309
 
@@ -328,28 +329,29 @@ export default class ChoroplethLayerDesigner extends React.Component<{
328
329
 
329
330
  const table = this.props.design.table
330
331
 
331
- return R(
332
- "div",
333
- null,
334
- R(
335
- "div",
336
- { className: "mb-3" },
337
- R("label", { className: "text-muted" }, R("span", { className: "fas fa-tint" }), T`Color By Data`),
338
-
339
- R(AxisComponent, {
340
- schema: this.props.schema,
341
- dataSource: this.props.dataSource,
342
- table: this.props.design.table,
343
- types: ["text", "enum", "boolean", "date"],
344
- aggrNeed: "required",
345
- value: this.props.design.axes.color,
346
- defaultColor: this.props.design.color,
347
- showColorMap: true,
348
- onChange: this.handleColorAxisChange,
349
- allowExcludedValues: true,
350
- filters: filters
351
- })
352
- )
332
+ return (
333
+ <div>
334
+ <div className="mb-3">
335
+ <label className="text-muted">
336
+ <span className="fas fa-tint" />
337
+ {T`Color By Data`}
338
+ </label>
339
+
340
+ <AxisComponent
341
+ schema={this.props.schema}
342
+ dataSource={this.props.dataSource}
343
+ table={this.props.design.table}
344
+ types={["text", "enum", "boolean", "date"]}
345
+ aggrNeed="required"
346
+ value={this.props.design.axes.color}
347
+ defaultColor={this.props.design.color}
348
+ showColorMap={true}
349
+ onChange={this.handleColorAxisChange}
350
+ allowExcludedValues={true}
351
+ filters={filters}
352
+ />
353
+ </div>
354
+ </div>
353
355
  )
354
356
  } else {
355
357
  // direct mode
@@ -380,28 +382,29 @@ export default class ChoroplethLayerDesigner extends React.Component<{
380
382
  })
381
383
  }
382
384
 
383
- return R(
384
- "div",
385
- null,
386
- R(
387
- "div",
388
- { className: "mb-3" },
389
- R("label", { className: "text-muted" }, R("span", { className: "fas fa-tint" }), T`Color By Data`),
390
-
391
- R(AxisComponent, {
392
- schema: this.props.schema,
393
- dataSource: this.props.dataSource,
394
- table: regionsTable,
395
- types: ["text", "enum", "boolean", "date"],
396
- aggrNeed: "none",
397
- value: this.props.design.axes.color,
398
- defaultColor: this.props.design.color,
399
- showColorMap: true,
400
- onChange: this.handleColorAxisChange,
401
- allowExcludedValues: true,
402
- filters: filters
403
- })
404
- )
385
+ return (
386
+ <div>
387
+ <div className="mb-3">
388
+ <label className="text-muted">
389
+ <span className="fas fa-tint" />
390
+ {T`Color By Data`}
391
+ </label>
392
+
393
+ <AxisComponent
394
+ schema={this.props.schema}
395
+ dataSource={this.props.dataSource}
396
+ table={regionsTable}
397
+ types={["text", "enum", "boolean", "date"]}
398
+ aggrNeed="none"
399
+ value={this.props.design.axes.color}
400
+ defaultColor={this.props.design.color}
401
+ showColorMap={true}
402
+ onChange={this.handleColorAxisChange}
403
+ allowExcludedValues={true}
404
+ filters={filters}
405
+ />
406
+ </div>
407
+ </div>
405
408
  )
406
409
  }
407
410
  }
@@ -428,40 +431,39 @@ export default class ChoroplethLayerDesigner extends React.Component<{
428
431
  // onChange: @handleColorAxisChange)
429
432
 
430
433
  renderFillOpacity() {
431
- return R(
432
- "div",
433
- { className: "mb-3" },
434
- R(
435
- "label",
436
- { className: "text-muted" },
437
- T`Fill Opacity: ${(this.props.design.fillOpacity * this.props.design.fillOpacity * 100).toFixed(0)}%`
438
- ),
439
- ": ",
440
- R(Rcslider, {
441
- min: 0,
442
- max: 100,
443
- step: 1,
444
- tipTransitionName: "rc-slider-tooltip-zoom-down",
445
- value: Math.round(this.props.design.fillOpacity * this.props.design.fillOpacity * 100),
446
- onChange: (val: number) => this.handleFillOpacityChange(Math.sqrt(val / 100))
447
- })
434
+ return (
435
+ <div className="mb-3">
436
+ <label className="text-muted">
437
+ {T`Fill Opacity: ${(this.props.design.fillOpacity * this.props.design.fillOpacity * 100).toFixed(0)}%`}
438
+ </label>
439
+ {": "}
440
+ <Rcslider
441
+ min={0}
442
+ max={100}
443
+ step={1}
444
+ tipTransitionName="rc-slider-tooltip-zoom-down"
445
+ value={Math.round(this.props.design.fillOpacity * this.props.design.fillOpacity * 100)}
446
+ onChange={(val: number) => this.handleFillOpacityChange(Math.sqrt(val / 100))}
447
+ />
448
+ </div>
448
449
  )
449
450
  }
450
451
 
451
452
  renderBorderColor() {
452
- return R(
453
- "div",
454
- { className: "mb-3" },
455
- R("label", { className: "text-muted" }, R("span", { className: "fas fa-tint" }), T`Border Color`),
456
-
457
- R(
458
- "div",
459
- null,
460
- R(ColorComponent, {
461
- color: this.props.design.borderColor || "#000",
462
- onChange: this.handleBorderColorChange
463
- })
464
- )
453
+ return (
454
+ <div className="mb-3">
455
+ <label className="text-muted">
456
+ <span className="fas fa-tint" />
457
+ {T`Border Color`}
458
+ </label>
459
+
460
+ <div>
461
+ <ColorComponent
462
+ color={this.props.design.borderColor || "#000"}
463
+ onChange={this.handleBorderColorChange}
464
+ />
465
+ </div>
466
+ </div>
465
467
  )
466
468
  }
467
469
 
@@ -471,21 +473,22 @@ export default class ChoroplethLayerDesigner extends React.Component<{
471
473
  return null
472
474
  }
473
475
 
474
- return R(
475
- "div",
476
- { className: "mb-3" },
477
- R("label", { className: "text-muted" }, R("span", { className: "fas fa-filter" }), T`Filters`),
478
- R(
479
- "div",
480
- { style: { marginLeft: 8 } },
481
- R(FilterExprComponent, {
482
- schema: this.props.schema,
483
- dataSource: this.props.dataSource,
484
- onChange: this.handleFilterChange,
485
- table: this.props.design.table,
486
- value: this.props.design.filter
487
- })
488
- )
476
+ return (
477
+ <div className="mb-3">
478
+ <label className="text-muted">
479
+ <span className="fas fa-filter" />
480
+ {T`Filters`}
481
+ </label>
482
+ <div style={{ marginLeft: 8 }}>
483
+ <FilterExprComponent
484
+ schema={this.props.schema}
485
+ dataSource={this.props.dataSource}
486
+ onChange={this.handleFilterChange}
487
+ table={this.props.design.table}
488
+ value={this.props.design.filter}
489
+ />
490
+ </div>
491
+ </div>
489
492
  )
490
493
  }
491
494
 
@@ -502,15 +505,15 @@ export default class ChoroplethLayerDesigner extends React.Component<{
502
505
  defaultPopupFilterJoins[this.props.design.table] = this.props.design.adminRegionExpr
503
506
  }
504
507
 
505
- return R(EditPopupComponent, {
506
- design: this.props.design,
507
- onDesignChange: this.props.onDesignChange,
508
- schema: this.props.schema,
509
- dataSource: this.props.dataSource,
510
- table: this.props.design.table,
511
- idTable: regionsTable,
512
- defaultPopupFilterJoins
513
- })
508
+ return <EditPopupComponent
509
+ design={this.props.design}
510
+ onDesignChange={this.props.onDesignChange}
511
+ schema={this.props.schema}
512
+ dataSource={this.props.dataSource}
513
+ table={this.props.design.table}
514
+ idTable={regionsTable}
515
+ defaultPopupFilterJoins={defaultPopupFilterJoins}
516
+ />
514
517
  }
515
518
 
516
519
  renderHoverOver() {
@@ -526,35 +529,36 @@ export default class ChoroplethLayerDesigner extends React.Component<{
526
529
  defaultPopupFilterJoins[this.props.design.table] = this.props.design.adminRegionExpr
527
530
  }
528
531
 
529
- return R(EditHoverOver, {
530
- design: this.props.design,
531
- onDesignChange: this.props.onDesignChange,
532
- schema: this.props.schema,
533
- dataSource: this.props.dataSource,
534
- table: this.props.design.table,
535
- idTable: regionsTable,
536
- defaultPopupFilterJoins
537
- })
532
+ return <EditHoverOver
533
+ design={this.props.design}
534
+ onDesignChange={this.props.onDesignChange}
535
+ schema={this.props.schema}
536
+ dataSource={this.props.dataSource}
537
+ table={this.props.design.table}
538
+ idTable={regionsTable}
539
+ defaultPopupFilterJoins={defaultPopupFilterJoins}
540
+ aggrStatuses={["individual", "aggregate", "literal"]}
541
+ />
538
542
  }
539
543
 
540
544
  render() {
541
- return R(
542
- "div",
543
- null,
544
- this.renderRegionMode(),
545
- this.renderRegionsTable(),
546
- this.renderTable(),
547
- this.renderAdminRegionExpr(),
548
- this.renderScopeAndDetailLevel(),
549
- this.renderDisplayNames(),
550
- this.renderColor(),
551
- this.renderColorAxis(),
552
- this.renderFillOpacity(),
553
- this.renderBorderColor(),
554
- this.renderFilter(),
555
- this.renderPopup(),
556
- this.renderHoverOver(),
557
- R(ZoomLevelsComponent, { design: this.props.design, onDesignChange: this.props.onDesignChange })
545
+ return (
546
+ <div>
547
+ {this.renderRegionMode()}
548
+ {this.renderRegionsTable()}
549
+ {this.renderTable()}
550
+ {this.renderAdminRegionExpr()}
551
+ {this.renderScopeAndDetailLevel()}
552
+ {this.renderDisplayNames()}
553
+ {this.renderColor()}
554
+ {this.renderColorAxis()}
555
+ {this.renderFillOpacity()}
556
+ {this.renderBorderColor()}
557
+ {this.renderFilter()}
558
+ {this.renderPopup()}
559
+ {this.renderHoverOver()}
560
+ <ZoomLevelsComponent design={this.props.design} onDesignChange={this.props.onDesignChange} />
561
+ </div>
558
562
  )
559
563
  }
560
564
  }
@@ -350,12 +350,6 @@ class DirectLayerDataSource implements MapLayerDataSource {
350
350
 
351
351
  let url = `${this.options.apiUrl}maps/tiles/{z}/{x}/{y}.${extension}?` + querystring.stringify(query)
352
352
 
353
- // Add subdomains: {s} will be substituted with "a", "b" or "c" in leaflet for api.mwater.co only.
354
- // Used to speed queries
355
- if (url.match(/^https:\/\/api\.mwater\.co\//)) {
356
- url = url.replace(/^https:\/\/api\.mwater\.co\//, "https://{s}-api.mwater.co/")
357
- }
358
-
359
353
  return url
360
354
  }
361
355
 
@@ -364,12 +358,6 @@ class DirectLayerDataSource implements MapLayerDataSource {
364
358
  let where
365
359
  let url = `${this.options.apiUrl}maps/tiles/{z}/{x}/{y}.${extension}?type=${design.type}&radius=1000`
366
360
 
367
- // Add subdomains: {s} will be substituted with "a", "b" or "c" in leaflet for api.mwater.co only.
368
- // Used to speed queries
369
- if (url.match(/^https:\/\/api\.mwater\.co\//)) {
370
- url = url.replace(/^https:\/\/api\.mwater\.co\//, "https://{s}-api.mwater.co/")
371
- }
372
-
373
361
  if (this.options.client) {
374
362
  url += `&client=${this.options.client}`
375
363
  }
@@ -1,5 +1,5 @@
1
1
  import { omit } from "lodash"
2
- import { DataSource, Expr, ExprUtils, Schema } from "@mwater/expressions"
2
+ import { AggrStatus, DataSource, Expr, ExprUtils, Schema } from "@mwater/expressions"
3
3
  import { ExprComponent } from "@mwater/expressions-ui"
4
4
  import React, { useState } from "react"
5
5
  import ActionCancelModalComponent from "@mwater/react-library/lib/ActionCancelModalComponent"
@@ -22,9 +22,12 @@ export interface EditHoverOverProps {
22
22
  /** Table of the row that join is to. Usually same as table except for choropleth maps */
23
23
  idTable: string
24
24
  defaultPopupFilterJoins: any
25
+
26
+ /** Aggr statuses to allow in hover over expressions */
27
+ aggrStatuses: AggrStatus[]
25
28
  }
26
29
 
27
- function EditHoverOver(props: EditHoverOverProps) {
30
+ export function EditHoverOver(props: EditHoverOverProps) {
28
31
  const { schema, dataSource, design, onDesignChange, table } = props
29
32
  const [editing, setEditing] = useState(false)
30
33
  const [draftItems, setDraftItems] = useState<HoverOverItem[] | undefined>(undefined)
@@ -103,6 +106,7 @@ function EditHoverOver(props: EditHoverOverProps) {
103
106
  onItemChange={handleItemChange}
104
107
  onItemDelete={handleItemDelete}
105
108
  item={item}
109
+ aggrStatuses={props.aggrStatuses}
106
110
  />
107
111
  ))}
108
112
  </tbody>
@@ -129,6 +133,8 @@ interface HoverOverItemEditorProps {
129
133
  onItemChange: (item: HoverOverItem) => void
130
134
  onItemDelete: (item: HoverOverItem) => void
131
135
  table: string
136
+ /** Aggr statuses to allow in hover over expressions */
137
+ aggrStatuses: AggrStatus[]
132
138
  }
133
139
 
134
140
  function HoverOverItemEditor(props: HoverOverItemEditorProps) {
@@ -173,7 +179,7 @@ function HoverOverItemEditor(props: HoverOverItemEditorProps) {
173
179
  types={["text", "number", "enum", "boolean", "date", "datetime", "id"]}
174
180
  onChange={expr => onItemChange({ ...item, value: expr })}
175
181
  value={item.value ?? null}
176
- aggrStatuses={["individual", "literal", "aggregate"]}
182
+ aggrStatuses={props.aggrStatuses}
177
183
  />
178
184
  </td>
179
185
  <td className="align-middle" style={{ width: "1%", whiteSpace: "nowrap" }}>
@@ -187,5 +193,3 @@ function HoverOverItemEditor(props: HoverOverItemEditorProps) {
187
193
  </tr>
188
194
  )
189
195
  }
190
-
191
- export default EditHoverOver
@@ -57,7 +57,7 @@ const HoverContent = (props: HoverContentProps) => {
57
57
  }
58
58
 
59
59
  return (
60
- <div className="_mviz-map-hover-content">
60
+ <div className="mwater-visualization-map-hover-content">
61
61
  {props.items.map((item: HoverOverItem) => {
62
62
  let value = values[item.id]
63
63
 
@@ -3,7 +3,6 @@ import React, { ReactElement, Component } from "react"
3
3
  import ReactDOM from "react-dom"
4
4
  import LeafletLoading from "./LeafletLoading"
5
5
  import L, { PathOptions, CircleMarkerOptions } from "leaflet"
6
- let BingLayer = require("./BingLayer")
7
6
  let UtfGridLayer = require("./UtfGridLayer")
8
7
 
9
8
  const R = React.createElement
@@ -387,36 +386,28 @@ export default class LeafletMapComponent extends Component<Props> {
387
386
 
388
387
  switch (this.props.baseLayerId) {
389
388
  case "bing_road":
390
- this.baseLayer = new BingLayer("Ao26dWY2IC8PjorsJKFaoR85EPXCnCohrJdisCWXIULAXFo0JAXquGauppTMQbyU", {
391
- type: "Road"
389
+ this.baseLayer = L.tileLayer('https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png?api_key=835a418e-91f9-4eb8-9856-0883c3656c9d', {
390
+ maxZoom: 20,
391
+ attribution: '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a> &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
392
392
  })
393
393
  break
394
- // @baseLayer = L.tileLayer('https://{s}.api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
395
- // attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
396
- // tileSize: 512,
397
- // maxZoom: 21,
398
- // maxNativeZoom: 19,
399
- // subdomains: ["a", "b"],
400
- // zoomOffset: -1,
401
- // id: 'mapbox/streets-v11',
402
- // accessToken: 'pk.eyJ1IjoiZ3Jhc3NpY2siLCJhIjoiY2ozMzU1N3ZoMDA3ZDJxbzh0aTRtOTRoeSJ9.fFWBZ88vbdezyhfw-I-fag'
403
- // })
404
394
  case "bing_aerial":
405
- this.baseLayer = new BingLayer("Ao26dWY2IC8PjorsJKFaoR85EPXCnCohrJdisCWXIULAXFo0JAXquGauppTMQbyU", {
406
- type: "AerialWithLabels"
395
+ this.baseLayer = L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_satellite/{z}/{x}/{y}.jpg?api_key=835a418e-91f9-4eb8-9856-0883c3656c9d', {
396
+ maxZoom: 20,
397
+ attribution: '&copy; CNES, Distribution Airbus DS, &copy; Airbus DS, &copy; PlanetObserver (Contains Copernicus Data) | &copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a> &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
407
398
  })
408
399
  break
409
400
  case "cartodb_positron":
410
- this.baseLayer = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png", {
401
+ this.baseLayer = L.tileLayer("https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png?api_key=835a418e-91f9-4eb8-9856-0883c3656c9d", {
411
402
  attribution:
412
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://cartodb.com/attributions">CartoDB</a>',
403
+ '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
413
404
  maxZoom: 21
414
405
  })
415
406
  break
416
407
  case "cartodb_dark_matter":
417
- this.baseLayer = L.tileLayer("https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png", {
408
+ this.baseLayer = L.tileLayer("https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png?api_key=835a418e-91f9-4eb8-9856-0883c3656c9d", {
418
409
  attribution:
419
- '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://cartodb.com/attributions">CartoDB</a>',
410
+ '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
420
411
  maxZoom: 21
421
412
  })
422
413
  break
@@ -290,7 +290,6 @@ export default class MapComponent extends React.Component<MapComponentProps, Map
290
290
 
291
291
  render() {
292
292
  const designerVisible = !this.getDesign().hideDesignPanel
293
- console.log("designerVisible", designerVisible)
294
293
  return R(
295
294
  "div",
296
295
  {
@@ -191,21 +191,33 @@ export async function getSimpleHoverOverData(options: {
191
191
  }) {
192
192
  const { id, table, filters, schema, dataSource, hoverOverItems } = options
193
193
 
194
+ const exprUtils = new ExprUtils(schema)
194
195
  const exprCompiler = new ExprCompiler(schema)
195
196
  const query: JsonQLSelectQuery = {
196
197
  type: "query",
197
198
  selects: [],
198
199
  from: exprCompiler.compileTable(table, "main"),
200
+ groupBy: [],
199
201
  limit: 1
200
202
  }
201
203
 
202
- for (const item of hoverOverItems) {
204
+ // Check if any items are aggregate
205
+ const isAggregate = hoverOverItems.some(item => exprUtils.getExprAggrStatus(item.value ?? null) === "aggregate")
206
+
207
+ for (let i = 0; i < hoverOverItems.length; i++) {
208
+ const item = hoverOverItems[i]
209
+
203
210
  if (item.value) {
204
211
  query.selects.push({
205
212
  type: "select",
206
213
  expr: exprCompiler.compileExpr({ expr: item.value, tableAlias: "main" }),
207
214
  alias: item.id
208
215
  })
216
+
217
+ // Group by if there are aggregate items and this is not aggregate
218
+ if (isAggregate && exprUtils.getExprAggrStatus(item.value) !== "aggregate") {
219
+ query.groupBy!.push(i + 1)
220
+ }
209
221
  }
210
222
  }
211
223