@mwater/visualization 5.5.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.
Files changed (275) hide show
  1. package/lib/ColorComponent.js +2 -2
  2. package/lib/MWaterContextComponent.d.ts +1 -1
  3. package/lib/MWaterGlobalFiltersComponent.d.ts +2 -2
  4. package/lib/MWaterGlobalFiltersComponent.js +11 -20
  5. package/lib/MWaterLoaderComponent.d.ts +4 -13
  6. package/lib/MWaterLoaderComponent.js +2 -11
  7. package/lib/TranslationsTabComponent.d.ts +34 -0
  8. package/lib/TranslationsTabComponent.js +256 -0
  9. package/lib/UndoStack.d.ts +2 -1
  10. package/lib/UndoStack.js +12 -6
  11. package/lib/dashboards/DashboardComponent.js +6 -5
  12. package/lib/dashboards/DashboardDesign.d.ts +1 -1
  13. package/lib/dashboards/ServerDashboardDataSource.d.ts +0 -1
  14. package/lib/dashboards/ServerDashboardDataSource.js +0 -25
  15. package/lib/dashboards/SettingsModalComponent.js +9 -233
  16. package/lib/datagrids/DatagridComponent.js +27 -2
  17. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -3
  18. package/lib/datagrids/DatagridDesignerComponent.js +108 -120
  19. package/lib/datagrids/DatagridViewComponent.js +33 -6
  20. package/lib/datagrids/OrderBysDesignerComponent.d.ts +7 -7
  21. package/lib/datagrids/OrderBysDesignerComponent.js +19 -28
  22. package/lib/index.css +45 -2
  23. package/lib/index.d.ts +5 -5
  24. package/lib/index.js +2 -3
  25. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +8 -1
  26. package/lib/layouts/blocks/BlocksDisplayComponent.js +46 -4
  27. package/lib/maps/BufferLayer.d.ts +0 -13
  28. package/lib/maps/BufferLayer.js +24 -237
  29. package/lib/maps/BufferLayerDesign.d.ts +1 -1
  30. package/lib/maps/BufferLayerDesignerComponent.d.ts +1 -1
  31. package/lib/maps/BufferLayerDesignerComponent.js +2 -7
  32. package/lib/maps/ChoroplethLayer.d.ts +1 -16
  33. package/lib/maps/ChoroplethLayer.js +25 -358
  34. package/lib/maps/ChoroplethLayerDesign.d.ts +5 -2
  35. package/lib/maps/ChoroplethLayerDesigner.d.ts +10 -32
  36. package/lib/maps/ChoroplethLayerDesigner.js +58 -89
  37. package/lib/maps/ClusterLayer.d.ts +0 -9
  38. package/lib/maps/ClusterLayer.js +0 -250
  39. package/lib/maps/DirectMapDataSource.js +1 -48
  40. package/lib/maps/EditHoverOver.d.ts +4 -3
  41. package/lib/maps/EditHoverOver.js +3 -3
  42. package/lib/maps/GridLayer.d.ts +0 -15
  43. package/lib/maps/GridLayer.js +0 -212
  44. package/lib/maps/HoverContent.js +1 -1
  45. package/lib/maps/Layer.d.ts +1 -26
  46. package/lib/maps/Layer.js +0 -13
  47. package/lib/maps/LeafletMapComponent.js +10 -19
  48. package/lib/maps/MapComponent.d.ts +19 -35
  49. package/lib/maps/MapComponent.js +135 -77
  50. package/lib/maps/MapControlComponent.d.ts +4 -5
  51. package/lib/maps/MapControlComponent.js +5 -12
  52. package/lib/maps/MapDesign.d.ts +8 -0
  53. package/lib/maps/MapDesignerComponent.d.ts +2 -0
  54. package/lib/maps/MapDesignerComponent.js +7 -2
  55. package/lib/maps/MapLayerDataSource.d.ts +0 -4
  56. package/lib/maps/MapLayerViewDesignerComponent.d.ts +3 -1
  57. package/lib/maps/MapLayerViewDesignerComponent.js +5 -1
  58. package/lib/maps/MapLayersDesignerComponent.d.ts +2 -0
  59. package/lib/maps/MapLayersDesignerComponent.js +2 -1
  60. package/lib/maps/MapTranslationsTab.d.ts +15 -0
  61. package/lib/maps/MapTranslationsTab.js +47 -0
  62. package/lib/maps/MapUtils.d.ts +11 -0
  63. package/lib/maps/MapUtils.js +57 -1
  64. package/lib/maps/MapViewComponent.d.ts +1 -1
  65. package/lib/maps/MapViewComponent.js +1 -8
  66. package/lib/maps/MarkersLayer.d.ts +1 -14
  67. package/lib/maps/MarkersLayer.js +89 -254
  68. package/lib/maps/MarkersLayerDesign.d.ts +5 -1
  69. package/lib/maps/MarkersLayerDesignerComponent.d.ts +32 -57
  70. package/lib/maps/MarkersLayerDesignerComponent.js +158 -134
  71. package/lib/maps/ServerMapDataSource.d.ts +0 -1
  72. package/lib/maps/ServerMapDataSource.js +0 -25
  73. package/lib/maps/SwitchableTileUrlLayer.d.ts +0 -2
  74. package/lib/maps/SwitchableTileUrlLayer.js +0 -9
  75. package/lib/maps/TileUrlLayer.d.ts +0 -1
  76. package/lib/maps/TileUrlLayer.js +0 -5
  77. package/lib/maps/VectorMapViewComponent.js +13 -10
  78. package/lib/maps/symbols/font-awesome/asterisk.png +0 -0
  79. package/lib/maps/symbols/font-awesome/ban.png +0 -0
  80. package/lib/maps/symbols/font-awesome/beer.png +0 -0
  81. package/lib/maps/symbols/font-awesome/bell.png +0 -0
  82. package/lib/maps/symbols/font-awesome/bolt.png +0 -0
  83. package/lib/maps/symbols/font-awesome/building.png +0 -0
  84. package/lib/maps/symbols/font-awesome/bullseye.png +0 -0
  85. package/lib/maps/symbols/font-awesome/bus.png +0 -0
  86. package/lib/maps/symbols/font-awesome/caret-up.png +0 -0
  87. package/lib/maps/symbols/font-awesome/certificate.png +0 -0
  88. package/lib/maps/symbols/font-awesome/check-circle.png +0 -0
  89. package/lib/maps/symbols/font-awesome/check.png +0 -0
  90. package/lib/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  91. package/lib/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  92. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  93. package/lib/maps/symbols/font-awesome/cloud.png +0 -0
  94. package/lib/maps/symbols/font-awesome/comment.png +0 -0
  95. package/lib/maps/symbols/font-awesome/crosshairs.png +0 -0
  96. package/lib/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  97. package/lib/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  98. package/lib/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  99. package/lib/maps/symbols/font-awesome/female.png +0 -0
  100. package/lib/maps/symbols/font-awesome/file.png +0 -0
  101. package/lib/maps/symbols/font-awesome/flag.png +0 -0
  102. package/lib/maps/symbols/font-awesome/flask.png +0 -0
  103. package/lib/maps/symbols/font-awesome/h-square.png +0 -0
  104. package/lib/maps/symbols/font-awesome/home.png +0 -0
  105. package/lib/maps/symbols/font-awesome/info-circle.png +0 -0
  106. package/lib/maps/symbols/font-awesome/male.png +0 -0
  107. package/lib/maps/symbols/font-awesome/medkit.png +0 -0
  108. package/lib/maps/symbols/font-awesome/mobile.png +0 -0
  109. package/lib/maps/symbols/font-awesome/plus-circle.png +0 -0
  110. package/lib/maps/symbols/font-awesome/plus-square.png +0 -0
  111. package/lib/maps/symbols/font-awesome/plus.png +0 -0
  112. package/lib/maps/symbols/font-awesome/square.png +0 -0
  113. package/lib/maps/symbols/font-awesome/star.png +0 -0
  114. package/lib/maps/symbols/font-awesome/thumbs-down.png +0 -0
  115. package/lib/maps/symbols/font-awesome/thumbs-up.png +0 -0
  116. package/lib/maps/symbols/font-awesome/ticket.png +0 -0
  117. package/lib/maps/symbols/font-awesome/times-circle.png +0 -0
  118. package/lib/maps/symbols/font-awesome/times.png +0 -0
  119. package/lib/maps/symbols/font-awesome/tint.png +0 -0
  120. package/lib/maps/symbols/font-awesome/tree.png +0 -0
  121. package/lib/maps/symbols/font-awesome/university.png +0 -0
  122. package/lib/maps/symbols/font-awesome/usd.png +0 -0
  123. package/lib/maps/symbols/font-awesome/user.png +0 -0
  124. package/lib/maps/symbols/font-awesome/users.png +0 -0
  125. package/lib/maps/symbols/font-awesome/wheelchair.png +0 -0
  126. package/lib/maps/symbols/sdf-ize.sh +93 -0
  127. package/lib/maps/vectorMaps.d.ts +6 -6
  128. package/lib/maps/vectorMaps.js +33 -45
  129. package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +4 -2
  130. package/lib/mwater_table_selection/IndicatorsListComponent.js +103 -34
  131. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.d.ts +18 -0
  132. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.js +80 -0
  133. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +26 -0
  134. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +237 -51
  135. package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +2 -2
  136. package/lib/mwater_table_selection/MWaterTableSelectComponent.js +9 -4
  137. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.d.ts +19 -0
  138. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.js +111 -0
  139. package/lib/quickfilter/QuickfiltersComponent.d.ts +3 -102
  140. package/lib/quickfilter/QuickfiltersComponent.js +53 -110
  141. package/lib/quickfilter/TextLiteralComponent.d.ts +23 -47
  142. package/lib/quickfilter/TextLiteralComponent.js +85 -82
  143. package/lib/widgets/MapWidget.js +6 -3
  144. package/lib/widgets/text/ExprItemEditorComponent.d.ts +3 -8
  145. package/lib/widgets/text/ExprItemEditorComponent.js +36 -33
  146. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +1 -0
  147. package/package.json +3 -4
  148. package/src/ColorComponent.tsx +2 -2
  149. package/src/MWaterContextComponent.tsx +1 -1
  150. package/src/{MWaterGlobalFiltersComponent.ts → MWaterGlobalFiltersComponent.tsx} +32 -33
  151. package/src/{MWaterLoaderComponent.ts → MWaterLoaderComponent.tsx} +17 -18
  152. package/src/TranslationsTabComponent.tsx +429 -0
  153. package/src/UndoStack.ts +14 -6
  154. package/src/dashboards/DashboardComponent.tsx +6 -5
  155. package/src/dashboards/DashboardDesign.ts +1 -1
  156. package/src/dashboards/ServerDashboardDataSource.ts +0 -31
  157. package/src/dashboards/SettingsModalComponent.tsx +27 -383
  158. package/src/datagrids/DatagridComponent.tsx +36 -2
  159. package/src/datagrids/DatagridDesignerComponent.tsx +241 -229
  160. package/src/datagrids/DatagridViewComponent.tsx +44 -7
  161. package/src/datagrids/OrderBysDesignerComponent.tsx +61 -70
  162. package/src/index.css +45 -2
  163. package/src/index.ts +5 -11
  164. package/src/layouts/blocks/BlocksDisplayComponent.tsx +60 -5
  165. package/src/maps/BufferLayer.ts +30 -263
  166. package/src/maps/BufferLayerDesign.ts +1 -1
  167. package/src/maps/BufferLayerDesignerComponent.tsx +2 -7
  168. package/src/maps/ChoroplethLayer.ts +30 -394
  169. package/src/maps/ChoroplethLayerDesign.ts +5 -2
  170. package/src/maps/ChoroplethLayerDesigner.tsx +169 -165
  171. package/src/maps/ClusterLayer.ts +0 -274
  172. package/src/maps/DirectMapDataSource.ts +2 -61
  173. package/src/maps/EditHoverOver.tsx +9 -5
  174. package/src/maps/GridLayer.ts +0 -224
  175. package/src/maps/HoverContent.tsx +1 -1
  176. package/src/maps/Layer.ts +1 -35
  177. package/src/maps/LeafletMapComponent.tsx +10 -19
  178. package/src/maps/MapComponent.tsx +448 -0
  179. package/src/maps/MapControlComponent.tsx +41 -0
  180. package/src/maps/MapDesign.ts +6 -0
  181. package/src/maps/MapDesignerComponent.tsx +18 -1
  182. package/src/maps/MapLayerDataSource.ts +0 -5
  183. package/src/maps/MapLayerViewDesignerComponent.ts +9 -2
  184. package/src/maps/MapLayersDesignerComponent.ts +4 -1
  185. package/src/maps/MapTranslationsTab.tsx +53 -0
  186. package/src/maps/MapUtils.ts +61 -1
  187. package/src/maps/MapViewComponent.tsx +2 -8
  188. package/src/maps/MarkersLayer.ts +101 -275
  189. package/src/maps/MarkersLayerDesign.ts +7 -1
  190. package/src/maps/MarkersLayerDesignerComponent.tsx +436 -0
  191. package/src/maps/ServerMapDataSource.ts +0 -31
  192. package/src/maps/SwitchableTileUrlLayer.tsx +0 -11
  193. package/src/maps/TileUrlLayer.tsx +0 -6
  194. package/src/maps/VectorMapViewComponent.tsx +15 -15
  195. package/src/maps/symbols/font-awesome/asterisk.png +0 -0
  196. package/src/maps/symbols/font-awesome/ban.png +0 -0
  197. package/src/maps/symbols/font-awesome/beer.png +0 -0
  198. package/src/maps/symbols/font-awesome/bell.png +0 -0
  199. package/src/maps/symbols/font-awesome/bolt.png +0 -0
  200. package/src/maps/symbols/font-awesome/building.png +0 -0
  201. package/src/maps/symbols/font-awesome/bullseye.png +0 -0
  202. package/src/maps/symbols/font-awesome/bus.png +0 -0
  203. package/src/maps/symbols/font-awesome/caret-up.png +0 -0
  204. package/src/maps/symbols/font-awesome/certificate.png +0 -0
  205. package/src/maps/symbols/font-awesome/check-circle.png +0 -0
  206. package/src/maps/symbols/font-awesome/check.png +0 -0
  207. package/src/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  208. package/src/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  209. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  210. package/src/maps/symbols/font-awesome/cloud.png +0 -0
  211. package/src/maps/symbols/font-awesome/comment.png +0 -0
  212. package/src/maps/symbols/font-awesome/crosshairs.png +0 -0
  213. package/src/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  214. package/src/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  215. package/src/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  216. package/src/maps/symbols/font-awesome/female.png +0 -0
  217. package/src/maps/symbols/font-awesome/file.png +0 -0
  218. package/src/maps/symbols/font-awesome/flag.png +0 -0
  219. package/src/maps/symbols/font-awesome/flask.png +0 -0
  220. package/src/maps/symbols/font-awesome/h-square.png +0 -0
  221. package/src/maps/symbols/font-awesome/home.png +0 -0
  222. package/src/maps/symbols/font-awesome/info-circle.png +0 -0
  223. package/src/maps/symbols/font-awesome/male.png +0 -0
  224. package/src/maps/symbols/font-awesome/medkit.png +0 -0
  225. package/src/maps/symbols/font-awesome/mobile.png +0 -0
  226. package/src/maps/symbols/font-awesome/plus-circle.png +0 -0
  227. package/src/maps/symbols/font-awesome/plus-square.png +0 -0
  228. package/src/maps/symbols/font-awesome/plus.png +0 -0
  229. package/src/maps/symbols/font-awesome/square.png +0 -0
  230. package/src/maps/symbols/font-awesome/star.png +0 -0
  231. package/src/maps/symbols/font-awesome/thumbs-down.png +0 -0
  232. package/src/maps/symbols/font-awesome/thumbs-up.png +0 -0
  233. package/src/maps/symbols/font-awesome/ticket.png +0 -0
  234. package/src/maps/symbols/font-awesome/times-circle.png +0 -0
  235. package/src/maps/symbols/font-awesome/times.png +0 -0
  236. package/src/maps/symbols/font-awesome/tint.png +0 -0
  237. package/src/maps/symbols/font-awesome/tree.png +0 -0
  238. package/src/maps/symbols/font-awesome/university.png +0 -0
  239. package/src/maps/symbols/font-awesome/usd.png +0 -0
  240. package/src/maps/symbols/font-awesome/user.png +0 -0
  241. package/src/maps/symbols/font-awesome/users.png +0 -0
  242. package/src/maps/symbols/font-awesome/wheelchair.png +0 -0
  243. package/src/maps/symbols/sdf-ize.sh +93 -0
  244. package/src/maps/vectorMaps.tsx +32 -53
  245. package/src/mwater_table_selection/IndicatorsListComponent.tsx +165 -37
  246. package/src/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.tsx +111 -0
  247. package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +373 -37
  248. package/src/mwater_table_selection/MWaterTableSelectComponent.tsx +12 -8
  249. package/src/mwater_table_selection/MWaterWorkflowsSelectComponent.tsx +159 -0
  250. package/src/quickfilter/{QuickfiltersComponent.ts → QuickfiltersComponent.tsx} +165 -158
  251. package/src/quickfilter/TextLiteralComponent.tsx +197 -0
  252. package/src/widgets/MapWidget.tsx +11 -1
  253. package/src/widgets/text/ExprItemEditorComponent.tsx +83 -77
  254. package/src/widgets/text/ExprUpdateModalComponent.tsx +1 -0
  255. package/test/UndoStackTests.ts +52 -1
  256. package/.storybook/config.js +0 -7
  257. package/.storybook/head.html +0 -3
  258. package/.storybook/webpack.config.js +0 -15
  259. package/src/maps/BingLayer.ts +0 -146
  260. package/src/maps/MapComponent.ts +0 -312
  261. package/src/maps/MapControlComponent.ts +0 -46
  262. package/src/maps/MarkersLayerDesignerComponent.ts +0 -374
  263. package/src/maps/RasterMapViewComponent.ts +0 -345
  264. package/src/quickfilter/TextLiteralComponent.ts +0 -165
  265. package/stories/UpdateableComponent.js +0 -29
  266. package/stories/consoles.js +0 -202
  267. package/stories/dashboards.js +0 -217
  268. package/stories/datagridDesign.js +0 -114
  269. package/stories/datagrids.js +0 -69
  270. package/stories/dates.js +0 -80
  271. package/stories/exprcomponent.js +0 -43
  272. package/stories/index.js +0 -18
  273. package/stories/leaflet.js +0 -59
  274. package/stories/maps.js +0 -24
  275. package/stories/pivotChart.js +0 -235
@@ -29,7 +29,7 @@ import { getDefaultLayoutOptions } from "../dashboards/layoutOptions"
29
29
  import Widget from "../widgets/Widget"
30
30
  import BlocksLayoutManager from "../layouts/blocks/BlocksLayoutManager"
31
31
  import { getTranslatableStringsFromLayoutManager } from "../dashboards/DashboardUtils"
32
- import { getSimpleHoverOverData } from "./MapUtils"
32
+ import { getSimpleHoverOverData, getTranslatableStringsFromAxis, translateAxis } from "./MapUtils"
33
33
 
34
34
  export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
35
35
  /** Gets the type of layer definition */
@@ -837,389 +837,6 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
837
837
  }
838
838
  }
839
839
 
840
- /** Gets the layer definition as JsonQL + CSS in format:
841
- * {
842
- * layers: array of { id: layer id, jsonql: jsonql that includes "the_webmercator_geom" as a column }
843
- * css: carto css
844
- * interactivity: (optional) { layer: id of layer, fields: array of field names }
845
- * }
846
- * arguments:
847
- * design: design of layer
848
- * schema: schema to use
849
- * filters: array of filters to apply
850
- */
851
- getJsonQLCss(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): LayerDefinition {
852
- // Create design
853
- const layerDef = {
854
- layers: [{ id: "layer0", jsonql: this.createMapnikJsonQL(design, schema, filters) }],
855
- css: this.createCss(design, schema, filters),
856
- interactivity: {
857
- layer: "layer0",
858
- fields: ["id", "name"]
859
- }
860
- }
861
-
862
- return layerDef
863
- }
864
-
865
- createMapnikJsonQL(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): JsonQLQuery {
866
- const axisBuilder = new AxisBuilder({ schema })
867
- const exprCompiler = new ExprCompiler(schema)
868
-
869
- // Verify that scopeLevel is an integer to prevent injection
870
- if (design.scopeLevel != null && ![0, 1, 2, 3, 4, 5].includes(design.scopeLevel)) {
871
- throw new Error("Invalid scope level")
872
- }
873
-
874
- // Verify that detailLevel is an integer to prevent injection
875
- if (![0, 1, 2, 3, 4, 5].includes(design.detailLevel)) {
876
- throw new Error("Invalid detail level")
877
- }
878
-
879
- const regionsTable = design.regionsTable || "admin_regions"
880
-
881
- if (design.regionMode === "plain") {
882
- /*
883
- E.g:
884
- select name, shape_simplified from
885
- admin_regions as regions
886
- where regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
887
- and regions.level = 2
888
- */
889
- const query: JsonQLQuery = {
890
- type: "query",
891
- selects: [
892
- { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
893
- {
894
- type: "select",
895
- expr: { type: "field", tableAlias: "regions", column: "shape_simplified" },
896
- alias: "the_geom_webmercator"
897
- },
898
- { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
899
- ],
900
- from: { type: "table", table: regionsTable, alias: "regions" },
901
- where: {
902
- type: "op",
903
- op: "and",
904
- exprs: [
905
- // Level to display
906
- {
907
- type: "op",
908
- op: "=",
909
- exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
910
- }
911
- ]
912
- }
913
- }
914
-
915
- // Scope overall
916
- if (design.scope) {
917
- ;(query.where as JsonQLOp).exprs.push({
918
- type: "op",
919
- op: "=",
920
- exprs: [
921
- { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
922
- { type: "literal", value: design.scope }
923
- ]
924
- })
925
- }
926
-
927
- // Add filters on regions to outer query
928
- for (const filter of filters) {
929
- if (filter.table == regionsTable) {
930
- ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions"))
931
- }
932
- }
933
-
934
- return query
935
- }
936
-
937
- if (design.regionMode === "indirect" || !design.regionMode) {
938
- /*
939
- E.g:
940
- select name, shape_simplified, regions.color from
941
- admin_regions as regions2
942
- left outer join
943
- (
944
- select admin_regions.level2 as id,
945
- count(innerquery.*) as color
946
- from
947
- admin_regions inner join
948
- entities.water_point as innerquery
949
- on innerquery.admin_region = admin_regions._id
950
- where admin_regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
951
- group by 1
952
- ) as regions on regions.id = regions2._id
953
- where regions2.level = 2 and regions2.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
954
- */
955
- const compiledAdminRegionExpr = exprCompiler.compileExpr({
956
- expr: design.adminRegionExpr || null,
957
- tableAlias: "innerquery"
958
- })
959
-
960
- // Create inner query
961
- const innerQuery: JsonQLQuery = {
962
- type: "query",
963
- selects: [
964
- {
965
- type: "select",
966
- expr: { type: "field", tableAlias: "regions", column: `level${design.detailLevel}` },
967
- alias: "id"
968
- }
969
- ],
970
- from: {
971
- type: "join",
972
- kind: "inner",
973
- left: { type: "table", table: regionsTable, alias: "regions" },
974
- right: exprCompiler.compileTable(design.table!, "innerquery"),
975
- on: {
976
- type: "op",
977
- op: "=",
978
- exprs: [compiledAdminRegionExpr, { type: "field", tableAlias: "regions", column: "_id" }]
979
- }
980
- },
981
- groupBy: [1]
982
- }
983
-
984
- // Add color select if color axis
985
- if (design.axes.color) {
986
- const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "innerquery" })
987
- innerQuery.selects.push({ type: "select", expr: colorExpr, alias: "color" })
988
- }
989
-
990
- // Add label select if color axis
991
- if (design.axes.label) {
992
- const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "innerquery" })
993
- innerQuery.selects.push({ type: "select", expr: labelExpr, alias: "label" })
994
- }
995
-
996
- let whereClauses = []
997
-
998
- if (design.scope) {
999
- whereClauses.push({
1000
- type: "op",
1001
- op: "=",
1002
- exprs: [{ type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` }, design.scope]
1003
- })
1004
- }
1005
-
1006
- // Then add filters
1007
- if (design.filter) {
1008
- whereClauses.push(exprCompiler.compileExpr({ expr: design.filter, tableAlias: "innerquery" }))
1009
- }
1010
-
1011
- // Then add extra filters passed in, if relevant
1012
- const relevantFilters = _.where(filters, { table: design.table })
1013
- for (let filter of relevantFilters) {
1014
- whereClauses.push(injectTableAlias(filter.jsonql, "innerquery"))
1015
- }
1016
-
1017
- whereClauses = _.compact(whereClauses)
1018
-
1019
- if (whereClauses.length > 0) {
1020
- innerQuery.where = { type: "op", op: "and", exprs: whereClauses }
1021
- }
1022
-
1023
- // Now create outer query
1024
- const query: JsonQLQuery = {
1025
- type: "query",
1026
- selects: [
1027
- { type: "select", expr: { type: "field", tableAlias: "regions2", column: "_id" }, alias: "id" },
1028
- {
1029
- type: "select",
1030
- expr: { type: "field", tableAlias: "regions2", column: "shape_simplified" },
1031
- alias: "the_geom_webmercator"
1032
- },
1033
- { type: "select", expr: { type: "field", tableAlias: "regions2", column: "name" }, alias: "name" }
1034
- ],
1035
- from: {
1036
- type: "join",
1037
- kind: "left",
1038
- left: { type: "table", table: regionsTable, alias: "regions2" },
1039
- right: { type: "subquery", query: innerQuery, alias: "regions" },
1040
- on: {
1041
- type: "op",
1042
- op: "=",
1043
- exprs: [
1044
- { type: "field", tableAlias: "regions", column: "id" },
1045
- { type: "field", tableAlias: "regions2", column: "_id" }
1046
- ]
1047
- }
1048
- },
1049
- where: {
1050
- type: "op",
1051
- op: "and",
1052
- exprs: [
1053
- // Level to display
1054
- {
1055
- type: "op",
1056
- op: "=",
1057
- exprs: [{ type: "field", tableAlias: "regions2", column: "level" }, design.detailLevel]
1058
- }
1059
- ]
1060
- }
1061
- }
1062
-
1063
- // Scope overall
1064
- if (design.scope) {
1065
- ;(query.where as JsonQLOp).exprs.push({
1066
- type: "op",
1067
- op: "=",
1068
- exprs: [
1069
- { type: "field", tableAlias: "regions2", column: `level${design.scopeLevel || 0}` },
1070
- { type: "literal", value: design.scope }
1071
- ]
1072
- })
1073
- }
1074
-
1075
- // Add filters on regions to outer query
1076
- for (const filter of filters) {
1077
- if (filter.table == regionsTable) {
1078
- ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions2"))
1079
- }
1080
- }
1081
-
1082
- // Bubble up color and label
1083
- if (design.axes.color) {
1084
- query.selects.push({
1085
- type: "select",
1086
- expr: { type: "field", tableAlias: "regions", column: "color" },
1087
- alias: "color"
1088
- })
1089
- }
1090
-
1091
- // Add label select if color axis
1092
- if (design.axes.label) {
1093
- query.selects.push({
1094
- type: "select",
1095
- expr: { type: "field", tableAlias: "regions", column: "label" },
1096
- alias: "label"
1097
- })
1098
- }
1099
-
1100
- return query
1101
- }
1102
-
1103
- if (design.regionMode === "direct") {
1104
- /*
1105
- E.g:
1106
- select name, shape_simplified from
1107
- admin_regions as regions
1108
- where regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
1109
- and regions.level = 2
1110
- */
1111
- const query: JsonQLQuery = {
1112
- type: "query",
1113
- selects: [
1114
- { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
1115
- {
1116
- type: "select",
1117
- expr: { type: "field", tableAlias: "regions", column: "shape_simplified" },
1118
- alias: "the_geom_webmercator"
1119
- },
1120
- { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
1121
- ],
1122
- from: { type: "table", table: regionsTable, alias: "regions" },
1123
- where: {
1124
- type: "op",
1125
- op: "and",
1126
- exprs: [
1127
- // Level to display
1128
- {
1129
- type: "op",
1130
- op: "=",
1131
- exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
1132
- }
1133
- ]
1134
- }
1135
- }
1136
-
1137
- // Add color select
1138
- if (design.axes.color) {
1139
- const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "regions" })
1140
- query.selects.push({ type: "select", expr: colorExpr, alias: "color" })
1141
- }
1142
-
1143
- // Add label select if color axis
1144
- if (design.axes.label) {
1145
- const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "regions" })
1146
- query.selects.push({ type: "select", expr: labelExpr, alias: "label" })
1147
- }
1148
-
1149
- // Scope overall
1150
- if (design.scope) {
1151
- ;(query.where as JsonQLOp).exprs.push({
1152
- type: "op",
1153
- op: "=",
1154
- exprs: [
1155
- { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
1156
- { type: "literal", value: design.scope }
1157
- ]
1158
- })
1159
- }
1160
-
1161
- // Add filters on regions to outer query
1162
- for (const filter of filters) {
1163
- if (filter.table == regionsTable) {
1164
- ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions"))
1165
- }
1166
- }
1167
-
1168
- return query
1169
- }
1170
-
1171
- throw new Error(`Unsupported regionMode ${design.regionMode}`)
1172
- }
1173
-
1174
- createCss(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): string {
1175
- let css =
1176
- `\
1177
- #layer0 {
1178
- line-color: ${design.borderColor || "#000"};
1179
- line-width: 1.5;
1180
- line-opacity: 0.5;
1181
- polygon-opacity: ` +
1182
- design.fillOpacity * design.fillOpacity +
1183
- `;
1184
- polygon-fill: ` +
1185
- (design.color || "transparent") +
1186
- `;
1187
- }
1188
- \
1189
- `
1190
-
1191
- if (design.displayNames) {
1192
- css += `\
1193
- #layer0::labels {
1194
- text-name: [name];
1195
- text-face-name: 'Arial Regular';
1196
- text-halo-radius: 2;
1197
- text-halo-opacity: 0.5;
1198
- text-halo-fill: #FFF;
1199
- }\
1200
- `
1201
- }
1202
-
1203
- // If color axes, add color conditions
1204
- if (design.axes.color && design.axes.color.colorMap) {
1205
- for (let item of design.axes.color.colorMap) {
1206
- // If invisible
1207
- if (_.includes(design.axes.color.excludedValues || [], item.value)) {
1208
- css += `#layer0 [color=${JSON.stringify(
1209
- item.value
1210
- )}] { line-color: transparent; polygon-opacity: 0; polygon-fill: transparent; }\n`
1211
- if (design.displayNames) {
1212
- css += `#layer0::labels [color=${JSON.stringify(item.value)}] { text-opacity: 0; text-halo-opacity: 0; }\n`
1213
- }
1214
- } else {
1215
- css += `#layer0 [color=${JSON.stringify(item.value)}] { polygon-fill: ${item.color}; }\n`
1216
- }
1217
- }
1218
- }
1219
-
1220
- return css
1221
- }
1222
-
1223
840
  /**
1224
841
  * Called when the interactivity grid is clicked.
1225
842
  * arguments:
@@ -1474,7 +1091,7 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
1474
1091
  // Get the legend to be optionally displayed on the map. Returns
1475
1092
  // a React element
1476
1093
  getLegend(options: LegendOptions<ChoroplethLayerDesign>): ReactNode {
1477
- const { design, schema, name, dataSource, locale, filters } = options
1094
+ const { design, schema, name, dataSource, locale, filters, translate } = options
1478
1095
  const _filters = filters.slice()
1479
1096
  if (design.filter != null) {
1480
1097
  const exprCompiler = new ExprCompiler(schema)
@@ -1489,17 +1106,19 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
1489
1106
  const regionsTable = design.regionsTable || "admin_regions"
1490
1107
  const axisTable = design.regionMode === "direct" ? regionsTable : design.table
1491
1108
 
1109
+ // Clean and translate axis
1110
+ const axis = translateAxis(axisBuilder.cleanAxis({
1111
+ axis: design.axes.color || null,
1112
+ table: axisTable,
1113
+ types: ["enum", "text", "boolean", "date"],
1114
+ aggrNeed: design.regionMode == "indirect" ? "required" : "none"
1115
+ }), translate)
1116
+
1492
1117
  return React.createElement(LayerLegendComponent, {
1493
1118
  schema,
1494
- name,
1119
+ name: translate(name),
1495
1120
  filters: _.compact(_filters),
1496
- axis:
1497
- axisBuilder.cleanAxis({
1498
- axis: design.axes.color || null,
1499
- table: axisTable,
1500
- types: ["enum", "text", "boolean", "date"],
1501
- aggrNeed: design.regionMode == "indirect" ? "required" : "none"
1502
- }) || undefined,
1121
+ axis: axis || undefined,
1503
1122
  defaultColor: design.color || undefined,
1504
1123
  locale
1505
1124
  })
@@ -1600,6 +1219,19 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
1600
1219
  delete draft.filter
1601
1220
  }
1602
1221
 
1222
+ // Clean hover over expressions only for indirect mode with a valid table
1223
+ if (design.table && design.regionMode === "indirect" && design.hoverOver && design.hoverOver.items) {
1224
+ for (let i = 0; i < design.hoverOver.items.length; i++) {
1225
+ const item = design.hoverOver.items[i]
1226
+ if (item.value) {
1227
+ draft.hoverOver!.items[i].value = exprCleaner.cleanExpr(item.value || null, {
1228
+ table: design.table,
1229
+ aggrStatuses: ["individual", "literal", "aggregate"]
1230
+ })
1231
+ }
1232
+ }
1233
+ }
1234
+
1603
1235
  if (design.detailLevel == null) {
1604
1236
  draft.detailLevel = 0
1605
1237
  }
@@ -1690,6 +1322,10 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
1690
1322
  getTranslatableStrings(design: ChoroplethLayerDesign, schema: Schema): string[] {
1691
1323
  const strings: string[] = []
1692
1324
 
1325
+ // Add strings from axis category labels and null labels
1326
+ strings.push(...getTranslatableStringsFromAxis(design.axes.color))
1327
+ strings.push(...getTranslatableStringsFromAxis(design.axes.label))
1328
+
1693
1329
  // Add strings from hoverOver items
1694
1330
  if (design.hoverOver && design.hoverOver.items) {
1695
1331
  for (const item of design.hoverOver.items) {
@@ -1746,7 +1382,7 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
1746
1382
  filters: popupFilters,
1747
1383
  schema: options.schema,
1748
1384
  dataSource: options.dataSource,
1749
- hoverOverItems: options.design.hoverOver.items,
1385
+ hoverOverItems: options.design.hoverOver!.items,
1750
1386
  })
1751
1387
  }
1752
1388
  }
@@ -65,8 +65,11 @@ export default interface ChoroplethLayerDesign {
65
65
  /** customizable filtering for popup. See PopupFilterJoins.md. Only when region mode is "indirect" */
66
66
  popupFilterJoins: PopupFilterJoins
67
67
 
68
- /** Hover over items to display when hovering over a region. Only when region mode is "indirect" */
69
- hoverOver: { items: HoverOverItem[] }
68
+ /** Hover over items to display when hovering over a region. Only when region mode is "indirect".
69
+ * This is an aggregate hover over, but can contain individual items. If so, only the first row
70
+ * of the resulting query will be displayed.
71
+ */
72
+ hoverOver?: { items: HoverOverItem[] }
70
73
 
71
74
  /** minimum zoom level */
72
75
  minZoom?: number