@mwater/visualization 5.0.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 (860) hide show
  1. package/.prettierrc +11 -0
  2. package/.storybook/config.js +7 -0
  3. package/.storybook/head.html +4 -0
  4. package/.storybook/webpack.config.js +15 -0
  5. package/.vscode/launch.json +40 -0
  6. package/LICENSE +21 -0
  7. package/README.md +19 -0
  8. package/build-demo.ts +54 -0
  9. package/lib/CheckboxComponent.d.ts +15 -0
  10. package/lib/CheckboxComponent.js +25 -0
  11. package/lib/ColorComponent.d.ts +24 -0
  12. package/lib/ColorComponent.js +77 -0
  13. package/lib/ColorSchemeFactory.d.ts +8 -0
  14. package/lib/ColorSchemeFactory.js +164 -0
  15. package/lib/CsvBuilder.d.ts +5 -0
  16. package/lib/CsvBuilder.js +63 -0
  17. package/lib/DateRangeComponent.d.ts +81 -0
  18. package/lib/DateRangeComponent.js +190 -0
  19. package/lib/FiltersDesignerComponent.d.ts +25 -0
  20. package/lib/FiltersDesignerComponent.js +38 -0
  21. package/lib/ImplicitFilterBuilder.d.ts +8 -0
  22. package/lib/ImplicitFilterBuilder.js +114 -0
  23. package/lib/JsonQLFilter.d.ts +7 -0
  24. package/lib/JsonQLFilter.js +2 -0
  25. package/lib/LocaleContextInjector.d.ts +14 -0
  26. package/lib/LocaleContextInjector.js +20 -0
  27. package/lib/MWaterAddRelatedFormComponent.d.ts +25 -0
  28. package/lib/MWaterAddRelatedFormComponent.js +155 -0
  29. package/lib/MWaterAddRelatedIndicatorComponent.d.ts +31 -0
  30. package/lib/MWaterAddRelatedIndicatorComponent.js +129 -0
  31. package/lib/MWaterAssetSystemsListComponent.d.ts +17 -0
  32. package/lib/MWaterAssetSystemsListComponent.js +78 -0
  33. package/lib/MWaterCompleteTableSelectComponent.d.ts +224 -0
  34. package/lib/MWaterCompleteTableSelectComponent.js +680 -0
  35. package/lib/MWaterContextComponent.d.ts +31 -0
  36. package/lib/MWaterContextComponent.js +111 -0
  37. package/lib/MWaterCustomTablesetListComponent.d.ts +17 -0
  38. package/lib/MWaterCustomTablesetListComponent.js +87 -0
  39. package/lib/MWaterGlobalFiltersComponent.d.ts +16 -0
  40. package/lib/MWaterGlobalFiltersComponent.js +103 -0
  41. package/lib/MWaterLoaderComponent.d.ts +42 -0
  42. package/lib/MWaterLoaderComponent.js +77 -0
  43. package/lib/MWaterMetricsTableListComponent.d.ts +17 -0
  44. package/lib/MWaterMetricsTableListComponent.js +79 -0
  45. package/lib/MWaterResponsesFilterComponent.d.ts +42 -0
  46. package/lib/MWaterResponsesFilterComponent.js +145 -0
  47. package/lib/MWaterTableSelectComponent.d.ts +36 -0
  48. package/lib/MWaterTableSelectComponent.js +206 -0
  49. package/lib/MenuItemComponent.d.ts +0 -0
  50. package/lib/MenuItemComponent.js +3 -0
  51. package/lib/PopoverComponent.d.ts +15 -0
  52. package/lib/PopoverComponent.js +49 -0
  53. package/lib/RadioButtonComponent.d.ts +16 -0
  54. package/lib/RadioButtonComponent.js +25 -0
  55. package/lib/TableSelectComponent.d.ts +21 -0
  56. package/lib/TableSelectComponent.js +68 -0
  57. package/lib/UIComponents.d.ts +85 -0
  58. package/lib/UIComponents.js +195 -0
  59. package/lib/UndoStack.d.ts +11 -0
  60. package/lib/UndoStack.js +51 -0
  61. package/lib/VerticalLayoutComponent.d.ts +21 -0
  62. package/lib/VerticalLayoutComponent.js +76 -0
  63. package/lib/WidgetScope.d.ts +13 -0
  64. package/lib/WidgetScope.js +2 -0
  65. package/lib/axes/Axis.d.ts +81 -0
  66. package/lib/axes/Axis.js +2 -0
  67. package/lib/axes/AxisBuilder.d.ts +66 -0
  68. package/lib/axes/AxisBuilder.js +1202 -0
  69. package/lib/axes/AxisColorEditorComponent.d.ts +39 -0
  70. package/lib/axes/AxisColorEditorComponent.js +133 -0
  71. package/lib/axes/AxisComponent.d.ts +65 -0
  72. package/lib/axes/AxisComponent.js +359 -0
  73. package/lib/axes/BinsComponent.d.ts +21 -0
  74. package/lib/axes/BinsComponent.js +96 -0
  75. package/lib/axes/CategoryMapComponent.d.ts +41 -0
  76. package/lib/axes/CategoryMapComponent.js +175 -0
  77. package/lib/axes/ColorPaletteCollectionComponent.d.ts +17 -0
  78. package/lib/axes/ColorPaletteCollectionComponent.js +130 -0
  79. package/lib/axes/RangesComponent.d.ts +35 -0
  80. package/lib/axes/RangesComponent.js +119 -0
  81. package/lib/componenttest.d.ts +1 -0
  82. package/lib/componenttest.js +47 -0
  83. package/lib/compressJson.d.ts +4 -0
  84. package/lib/compressJson.js +19 -0
  85. package/lib/dashboards/DashboardComponent.d.ts +115 -0
  86. package/lib/dashboards/DashboardComponent.js +297 -0
  87. package/lib/dashboards/DashboardDataSource.d.ts +9 -0
  88. package/lib/dashboards/DashboardDataSource.js +14 -0
  89. package/lib/dashboards/DashboardDesign.d.ts +45 -0
  90. package/lib/dashboards/DashboardDesign.js +2 -0
  91. package/lib/dashboards/DashboardUpgrader.d.ts +4 -0
  92. package/lib/dashboards/DashboardUpgrader.js +95 -0
  93. package/lib/dashboards/DashboardUtils.d.ts +7 -0
  94. package/lib/dashboards/DashboardUtils.js +69 -0
  95. package/lib/dashboards/DashboardViewComponent.d.ts +71 -0
  96. package/lib/dashboards/DashboardViewComponent.js +235 -0
  97. package/lib/dashboards/DirectDashboardDataSource.d.ts +31 -0
  98. package/lib/dashboards/DirectDashboardDataSource.js +62 -0
  99. package/lib/dashboards/LayoutOptionsComponent.d.ts +11 -0
  100. package/lib/dashboards/LayoutOptionsComponent.js +119 -0
  101. package/lib/dashboards/README.md +13 -0
  102. package/lib/dashboards/ServerDashboardDataSource.d.ts +96 -0
  103. package/lib/dashboards/ServerDashboardDataSource.js +383 -0
  104. package/lib/dashboards/SettingsModalComponent.d.ts +33 -0
  105. package/lib/dashboards/SettingsModalComponent.js +122 -0
  106. package/lib/dashboards/WidgetComponent.d.ts +53 -0
  107. package/lib/dashboards/WidgetComponent.js +66 -0
  108. package/lib/dashboards/layoutOptions.d.ts +19 -0
  109. package/lib/dashboards/layoutOptions.js +19 -0
  110. package/lib/datagrids/DatagridComponent.d.ts +122 -0
  111. package/lib/datagrids/DatagridComponent.js +285 -0
  112. package/lib/datagrids/DatagridDataSource.d.ts +9 -0
  113. package/lib/datagrids/DatagridDataSource.js +13 -0
  114. package/lib/datagrids/DatagridDesign.d.ts +75 -0
  115. package/lib/datagrids/DatagridDesign.js +2 -0
  116. package/lib/datagrids/DatagridDesignerComponent.d.ts +114 -0
  117. package/lib/datagrids/DatagridDesignerComponent.js +389 -0
  118. package/lib/datagrids/DatagridQueryBuilder.d.ts +68 -0
  119. package/lib/datagrids/DatagridQueryBuilder.js +540 -0
  120. package/lib/datagrids/DatagridUtils.d.ts +8 -0
  121. package/lib/datagrids/DatagridUtils.js +91 -0
  122. package/lib/datagrids/DatagridViewComponent.d.ts +86 -0
  123. package/lib/datagrids/DatagridViewComponent.js +321 -0
  124. package/lib/datagrids/DirectDatagridDataSource.d.ts +20 -0
  125. package/lib/datagrids/DirectDatagridDataSource.js +62 -0
  126. package/lib/datagrids/EditExprCellComponent.d.ts +77 -0
  127. package/lib/datagrids/EditExprCellComponent.js +212 -0
  128. package/lib/datagrids/ExprCellComponent.d.ts +34 -0
  129. package/lib/datagrids/ExprCellComponent.js +81 -0
  130. package/lib/datagrids/FindReplaceModalComponent.d.ts +52 -0
  131. package/lib/datagrids/FindReplaceModalComponent.js +248 -0
  132. package/lib/datagrids/LabeledExprGenerator.d.ts +40 -0
  133. package/lib/datagrids/LabeledExprGenerator.js +252 -0
  134. package/lib/datagrids/OrderBysDesignerComponent.d.ts +22 -0
  135. package/lib/datagrids/OrderBysDesignerComponent.js +67 -0
  136. package/lib/datagrids/README.md +3 -0
  137. package/lib/datagrids/ServerDatagridDataSource.d.ts +40 -0
  138. package/lib/datagrids/ServerDatagridDataSource.js +79 -0
  139. package/lib/demo.d.ts +1 -0
  140. package/lib/demo.js +4006 -0
  141. package/lib/demoBlocks.d.ts +1 -0
  142. package/lib/demoBlocks.js +112 -0
  143. package/lib/index.css +550 -0
  144. package/lib/index.d.ts +69 -0
  145. package/lib/index.js +156 -0
  146. package/lib/injectTableAlias.d.ts +2 -0
  147. package/lib/injectTableAlias.js +30 -0
  148. package/lib/languages.d.ts +9 -0
  149. package/lib/languages.js +926 -0
  150. package/lib/layout-styles.css +263 -0
  151. package/lib/layouts/DecoratedBlockComponent.d.ts +44 -0
  152. package/lib/layouts/DecoratedBlockComponent.js +96 -0
  153. package/lib/layouts/DragSourceComponent.d.ts +2 -0
  154. package/lib/layouts/DragSourceComponent.js +26 -0
  155. package/lib/layouts/LayoutManager.d.ts +50 -0
  156. package/lib/layouts/LayoutManager.js +41 -0
  157. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +75 -0
  158. package/lib/layouts/blocks/BlocksDisplayComponent.js +336 -0
  159. package/lib/layouts/blocks/BlocksLayoutManager.d.ts +36 -0
  160. package/lib/layouts/blocks/BlocksLayoutManager.js +74 -0
  161. package/lib/layouts/blocks/ClipboardPaletteItemComponent.d.ts +9 -0
  162. package/lib/layouts/blocks/ClipboardPaletteItemComponent.js +59 -0
  163. package/lib/layouts/blocks/DraggableBlockComponent.d.ts +2 -0
  164. package/lib/layouts/blocks/DraggableBlockComponent.js +163 -0
  165. package/lib/layouts/blocks/HorizontalBlockComponent.d.ts +31 -0
  166. package/lib/layouts/blocks/HorizontalBlockComponent.js +191 -0
  167. package/lib/layouts/blocks/PaletteItemComponent.d.ts +14 -0
  168. package/lib/layouts/blocks/PaletteItemComponent.js +15 -0
  169. package/lib/layouts/blocks/README.md +11 -0
  170. package/lib/layouts/blocks/blockUtils.d.ts +22 -0
  171. package/lib/layouts/blocks/blockUtils.js +155 -0
  172. package/lib/layouts/decorated-block.css +100 -0
  173. package/lib/layouts/grid/GridLayoutComponent.d.ts +23 -0
  174. package/lib/layouts/grid/GridLayoutComponent.js +49 -0
  175. package/lib/layouts/grid/GridLayoutManager.d.ts +29 -0
  176. package/lib/layouts/grid/GridLayoutManager.js +141 -0
  177. package/lib/layouts/grid/LegoLayoutEngine.d.ts +33 -0
  178. package/lib/layouts/grid/LegoLayoutEngine.js +129 -0
  179. package/lib/layouts/grid/PaletteItemComponent.d.ts +14 -0
  180. package/lib/layouts/grid/PaletteItemComponent.js +15 -0
  181. package/lib/layouts/grid/README.md +14 -0
  182. package/lib/layouts/grid/WidgetContainerComponent.d.ts +9 -0
  183. package/lib/layouts/grid/WidgetContainerComponent.js +333 -0
  184. package/lib/mWaterLoader.d.ts +26 -0
  185. package/lib/mWaterLoader.js +55 -0
  186. package/lib/mapdemo.d.ts +0 -0
  187. package/lib/mapdemo.js +115 -0
  188. package/lib/maps/AddLayerComponent.d.ts +22 -0
  189. package/lib/maps/AddLayerComponent.js +85 -0
  190. package/lib/maps/AdminScopeAndDetailLevelComponent.d.ts +19 -0
  191. package/lib/maps/AdminScopeAndDetailLevelComponent.js +59 -0
  192. package/lib/maps/BaseLayerDesignerComponent.d.ts +28 -0
  193. package/lib/maps/BaseLayerDesignerComponent.js +57 -0
  194. package/lib/maps/BingLayer.d.ts +1 -0
  195. package/lib/maps/BingLayer.js +151 -0
  196. package/lib/maps/BufferLayer.d.ts +51 -0
  197. package/lib/maps/BufferLayer.js +816 -0
  198. package/lib/maps/BufferLayerDesign.d.ts +37 -0
  199. package/lib/maps/BufferLayerDesign.js +2 -0
  200. package/lib/maps/BufferLayerDesignerComponent.d.ts +49 -0
  201. package/lib/maps/BufferLayerDesignerComponent.js +217 -0
  202. package/lib/maps/ChoroplethLayer.d.ts +74 -0
  203. package/lib/maps/ChoroplethLayer.js +1515 -0
  204. package/lib/maps/ChoroplethLayerDesign.d.ts +56 -0
  205. package/lib/maps/ChoroplethLayerDesign.js +2 -0
  206. package/lib/maps/ChoroplethLayerDesigner.d.ts +53 -0
  207. package/lib/maps/ChoroplethLayerDesigner.js +382 -0
  208. package/lib/maps/ClusterLayer.d.ts +38 -0
  209. package/lib/maps/ClusterLayer.js +746 -0
  210. package/lib/maps/ClusterLayerDesign.d.ts +22 -0
  211. package/lib/maps/ClusterLayerDesign.js +2 -0
  212. package/lib/maps/ClusterLayerDesignerComponent.d.ts +37 -0
  213. package/lib/maps/ClusterLayerDesignerComponent.js +110 -0
  214. package/lib/maps/DetailLevelSelectComponent.d.ts +122 -0
  215. package/lib/maps/DetailLevelSelectComponent.js +91 -0
  216. package/lib/maps/DirectMapDataSource.d.ts +68 -0
  217. package/lib/maps/DirectMapDataSource.js +265 -0
  218. package/lib/maps/EditHoverOver.d.ts +18 -0
  219. package/lib/maps/EditHoverOver.js +88 -0
  220. package/lib/maps/EditPopupComponent.d.ts +26 -0
  221. package/lib/maps/EditPopupComponent.js +75 -0
  222. package/lib/maps/Grid Functions.sql +167 -0
  223. package/lib/maps/GridLayer.d.ts +48 -0
  224. package/lib/maps/GridLayer.js +684 -0
  225. package/lib/maps/GridLayerDesign.d.ts +35 -0
  226. package/lib/maps/GridLayerDesign.js +2 -0
  227. package/lib/maps/GridLayerDesigner.d.ts +38 -0
  228. package/lib/maps/GridLayerDesigner.js +229 -0
  229. package/lib/maps/HoverContent.d.ts +13 -0
  230. package/lib/maps/HoverContent.js +92 -0
  231. package/lib/maps/HtmlUrlLegend.d.ts +16 -0
  232. package/lib/maps/HtmlUrlLegend.js +38 -0
  233. package/lib/maps/Layer.d.ts +164 -0
  234. package/lib/maps/Layer.js +193 -0
  235. package/lib/maps/LayerFactory.d.ts +5 -0
  236. package/lib/maps/LayerFactory.js +47 -0
  237. package/lib/maps/LayerLegendComponent.d.ts +23 -0
  238. package/lib/maps/LayerLegendComponent.js +68 -0
  239. package/lib/maps/LayerSwitcherComponent.d.ts +7 -0
  240. package/lib/maps/LayerSwitcherComponent.js +97 -0
  241. package/lib/maps/LeafletLoading.css +24 -0
  242. package/lib/maps/LeafletLoading.d.ts +42 -0
  243. package/lib/maps/LeafletLoading.js +318 -0
  244. package/lib/maps/LeafletMapComponent.d.ts +141 -0
  245. package/lib/maps/LeafletMapComponent.js +438 -0
  246. package/lib/maps/LegendComponent.d.ts +14 -0
  247. package/lib/maps/LegendComponent.js +74 -0
  248. package/lib/maps/LegendGroup.d.ts +24 -0
  249. package/lib/maps/LegendGroup.js +86 -0
  250. package/lib/maps/MWaterServerLayer.d.ts +40 -0
  251. package/lib/maps/MWaterServerLayer.js +101 -0
  252. package/lib/maps/MapBoundsCalculator.d.ts +16 -0
  253. package/lib/maps/MapBoundsCalculator.js +85 -0
  254. package/lib/maps/MapComponent.d.ts +98 -0
  255. package/lib/maps/MapComponent.js +186 -0
  256. package/lib/maps/MapControlComponent.d.ts +17 -0
  257. package/lib/maps/MapControlComponent.js +25 -0
  258. package/lib/maps/MapDataSource.d.ts +18 -0
  259. package/lib/maps/MapDataSource.js +2 -0
  260. package/lib/maps/MapDesign.d.ts +77 -0
  261. package/lib/maps/MapDesign.js +2 -0
  262. package/lib/maps/MapDesignerComponent.d.ts +39 -0
  263. package/lib/maps/MapDesignerComponent.js +215 -0
  264. package/lib/maps/MapFiltersDesignerComponent.d.ts +21 -0
  265. package/lib/maps/MapFiltersDesignerComponent.js +70 -0
  266. package/lib/maps/MapLayerDataSource.d.ts +22 -0
  267. package/lib/maps/MapLayerDataSource.js +2 -0
  268. package/lib/maps/MapLayerViewDesignerComponent.d.ts +87 -0
  269. package/lib/maps/MapLayerViewDesignerComponent.js +151 -0
  270. package/lib/maps/MapLayersDesignerComponent.d.ts +32 -0
  271. package/lib/maps/MapLayersDesignerComponent.js +98 -0
  272. package/lib/maps/MapUtils.d.ts +21 -0
  273. package/lib/maps/MapUtils.js +119 -0
  274. package/lib/maps/MapViewComponent.d.ts +38 -0
  275. package/lib/maps/MapViewComponent.js +20 -0
  276. package/lib/maps/Maptiler-logo.png +0 -0
  277. package/lib/maps/MarkerSymbolSelectComponent.d.ts +10 -0
  278. package/lib/maps/MarkerSymbolSelectComponent.js +28 -0
  279. package/lib/maps/MarkersLayer.d.ts +66 -0
  280. package/lib/maps/MarkersLayer.js +838 -0
  281. package/lib/maps/MarkersLayerDesign.d.ts +44 -0
  282. package/lib/maps/MarkersLayerDesign.js +2 -0
  283. package/lib/maps/MarkersLayerDesignerComponent.d.ts +56 -0
  284. package/lib/maps/MarkersLayerDesignerComponent.js +269 -0
  285. package/lib/maps/PopupFilterJoinsEditComponent.d.ts +30 -0
  286. package/lib/maps/PopupFilterJoinsEditComponent.js +75 -0
  287. package/lib/maps/PopupFilterJoinsUtils.d.ts +15 -0
  288. package/lib/maps/PopupFilterJoinsUtils.js +91 -0
  289. package/lib/maps/RasterMapViewComponent.d.ts +108 -0
  290. package/lib/maps/RasterMapViewComponent.js +283 -0
  291. package/lib/maps/RegionSelectComponent.d.ts +55 -0
  292. package/lib/maps/RegionSelectComponent.js +61 -0
  293. package/lib/maps/ScopeAndDetailLevelComponent.d.ts +21 -0
  294. package/lib/maps/ScopeAndDetailLevelComponent.js +76 -0
  295. package/lib/maps/ServerMapDataSource.d.ts +86 -0
  296. package/lib/maps/ServerMapDataSource.js +273 -0
  297. package/lib/maps/SwitchableTileUrlLayer.d.ts +53 -0
  298. package/lib/maps/SwitchableTileUrlLayer.js +69 -0
  299. package/lib/maps/SwitchableTileUrlLayerDesigner.d.ts +14 -0
  300. package/lib/maps/SwitchableTileUrlLayerDesigner.js +26 -0
  301. package/lib/maps/TileUrlLayer.d.ts +40 -0
  302. package/lib/maps/TileUrlLayer.js +96 -0
  303. package/lib/maps/UtfGridLayer.d.ts +1 -0
  304. package/lib/maps/UtfGridLayer.js +216 -0
  305. package/lib/maps/VectorMapViewComponent.css +21 -0
  306. package/lib/maps/VectorMapViewComponent.d.ts +44 -0
  307. package/lib/maps/VectorMapViewComponent.js +565 -0
  308. package/lib/maps/ZoomLevelsComponent.d.ts +15 -0
  309. package/lib/maps/ZoomLevelsComponent.js +37 -0
  310. package/lib/maps/mapSymbols.d.ts +6 -0
  311. package/lib/maps/mapSymbols.js +167 -0
  312. package/lib/maps/mapboxUtils.d.ts +6 -0
  313. package/lib/maps/mapboxUtils.js +60 -0
  314. package/lib/maps/maps.d.ts +36 -0
  315. package/lib/maps/maps.js +2 -0
  316. package/lib/maps/marker-icon-2x.png +0 -0
  317. package/lib/maps/marker-icon.png +0 -0
  318. package/lib/maps/marker-shadow.png +0 -0
  319. package/lib/maps/symbols/font-awesome/asterisk.png +0 -0
  320. package/lib/maps/symbols/font-awesome/ban.png +0 -0
  321. package/lib/maps/symbols/font-awesome/beer.png +0 -0
  322. package/lib/maps/symbols/font-awesome/bell.png +0 -0
  323. package/lib/maps/symbols/font-awesome/bolt.png +0 -0
  324. package/lib/maps/symbols/font-awesome/building.png +0 -0
  325. package/lib/maps/symbols/font-awesome/bullseye.png +0 -0
  326. package/lib/maps/symbols/font-awesome/bus.png +0 -0
  327. package/lib/maps/symbols/font-awesome/caret-up.png +0 -0
  328. package/lib/maps/symbols/font-awesome/certificate.png +0 -0
  329. package/lib/maps/symbols/font-awesome/check-circle.png +0 -0
  330. package/lib/maps/symbols/font-awesome/check.png +0 -0
  331. package/lib/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  332. package/lib/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  333. package/lib/maps/symbols/font-awesome/cloud.png +0 -0
  334. package/lib/maps/symbols/font-awesome/comment.png +0 -0
  335. package/lib/maps/symbols/font-awesome/crosshairs.png +0 -0
  336. package/lib/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  337. package/lib/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  338. package/lib/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  339. package/lib/maps/symbols/font-awesome/female.png +0 -0
  340. package/lib/maps/symbols/font-awesome/file.png +0 -0
  341. package/lib/maps/symbols/font-awesome/flag.png +0 -0
  342. package/lib/maps/symbols/font-awesome/flask.png +0 -0
  343. package/lib/maps/symbols/font-awesome/h-square.png +0 -0
  344. package/lib/maps/symbols/font-awesome/home.png +0 -0
  345. package/lib/maps/symbols/font-awesome/info-circle.png +0 -0
  346. package/lib/maps/symbols/font-awesome/male.png +0 -0
  347. package/lib/maps/symbols/font-awesome/medkit.png +0 -0
  348. package/lib/maps/symbols/font-awesome/mobile.png +0 -0
  349. package/lib/maps/symbols/font-awesome/plus-circle.png +0 -0
  350. package/lib/maps/symbols/font-awesome/plus-square.png +0 -0
  351. package/lib/maps/symbols/font-awesome/plus.png +0 -0
  352. package/lib/maps/symbols/font-awesome/square.png +0 -0
  353. package/lib/maps/symbols/font-awesome/star.png +0 -0
  354. package/lib/maps/symbols/font-awesome/thumbs-down.png +0 -0
  355. package/lib/maps/symbols/font-awesome/thumbs-up.png +0 -0
  356. package/lib/maps/symbols/font-awesome/ticket.png +0 -0
  357. package/lib/maps/symbols/font-awesome/times-circle.png +0 -0
  358. package/lib/maps/symbols/font-awesome/times.png +0 -0
  359. package/lib/maps/symbols/font-awesome/tint.png +0 -0
  360. package/lib/maps/symbols/font-awesome/tree.png +0 -0
  361. package/lib/maps/symbols/font-awesome/university.png +0 -0
  362. package/lib/maps/symbols/font-awesome/usd.png +0 -0
  363. package/lib/maps/symbols/font-awesome/user.png +0 -0
  364. package/lib/maps/symbols/font-awesome/users.png +0 -0
  365. package/lib/maps/symbols/font-awesome/wheelchair.png +0 -0
  366. package/lib/maps/vectorMaps.d.ts +42 -0
  367. package/lib/maps/vectorMaps.js +331 -0
  368. package/lib/memoizedDebounce.d.ts +6 -0
  369. package/lib/memoizedDebounce.js +21 -0
  370. package/lib/quickfilter/DateExprComponent.d.ts +81 -0
  371. package/lib/quickfilter/DateExprComponent.js +197 -0
  372. package/lib/quickfilter/IdArrayQuickfilterComponent.d.ts +24 -0
  373. package/lib/quickfilter/IdArrayQuickfilterComponent.js +30 -0
  374. package/lib/quickfilter/Quickfilter.d.ts +21 -0
  375. package/lib/quickfilter/Quickfilter.js +2 -0
  376. package/lib/quickfilter/QuickfilterCompiler.d.ts +16 -0
  377. package/lib/quickfilter/QuickfilterCompiler.js +167 -0
  378. package/lib/quickfilter/QuickfilterUtils.d.ts +7 -0
  379. package/lib/quickfilter/QuickfilterUtils.js +106 -0
  380. package/lib/quickfilter/QuickfiltersComponent.d.ts +293 -0
  381. package/lib/quickfilter/QuickfiltersComponent.js +257 -0
  382. package/lib/quickfilter/QuickfiltersDataSource.d.ts +7 -0
  383. package/lib/quickfilter/QuickfiltersDataSource.js +2 -0
  384. package/lib/quickfilter/QuickfiltersDesignComponent.d.ts +46 -0
  385. package/lib/quickfilter/QuickfiltersDesignComponent.js +176 -0
  386. package/lib/quickfilter/README.md +8 -0
  387. package/lib/quickfilter/TextLiteralComponent.d.ts +216 -0
  388. package/lib/quickfilter/TextLiteralComponent.js +128 -0
  389. package/lib/richtext/ExprItemsHtmlConverter.d.ts +39 -0
  390. package/lib/richtext/ExprItemsHtmlConverter.js +118 -0
  391. package/lib/richtext/FontColorPaletteItem.d.ts +23 -0
  392. package/lib/richtext/FontColorPaletteItem.js +84 -0
  393. package/lib/richtext/FontSizePaletteItem.d.ts +29 -0
  394. package/lib/richtext/FontSizePaletteItem.js +70 -0
  395. package/lib/richtext/ItemsHtmlConverter.d.ts +31 -0
  396. package/lib/richtext/ItemsHtmlConverter.js +209 -0
  397. package/lib/richtext/README.md +3 -0
  398. package/lib/richtext/RichTextComponent.d.ts +84 -0
  399. package/lib/richtext/RichTextComponent.js +255 -0
  400. package/lib/valueFormatter.d.ts +16 -0
  401. package/lib/valueFormatter.js +93 -0
  402. package/lib/widgets/DirectWidgetDataSource.d.ts +43 -0
  403. package/lib/widgets/DirectWidgetDataSource.js +39 -0
  404. package/lib/widgets/DropdownWidgetComponent.d.ts +31 -0
  405. package/lib/widgets/DropdownWidgetComponent.js +41 -0
  406. package/lib/widgets/IFrameWidget.d.ts +16 -0
  407. package/lib/widgets/IFrameWidget.js +38 -0
  408. package/lib/widgets/IFrameWidgetComponent.d.ts +33 -0
  409. package/lib/widgets/IFrameWidgetComponent.js +101 -0
  410. package/lib/widgets/ImageUploaderComponent.d.ts +29 -0
  411. package/lib/widgets/ImageUploaderComponent.js +91 -0
  412. package/lib/widgets/ImageWidget.d.ts +49 -0
  413. package/lib/widgets/ImageWidget.js +112 -0
  414. package/lib/widgets/ImageWidgetComponent.d.ts +125 -0
  415. package/lib/widgets/ImageWidgetComponent.js +368 -0
  416. package/lib/widgets/ImagelistCarouselComponent.d.ts +29 -0
  417. package/lib/widgets/ImagelistCarouselComponent.js +64 -0
  418. package/lib/widgets/MapWidget.d.ts +55 -0
  419. package/lib/widgets/MapWidget.js +167 -0
  420. package/lib/widgets/MarkdownWidget.d.ts +53 -0
  421. package/lib/widgets/MarkdownWidget.js +134 -0
  422. package/lib/widgets/TOCWidget.d.ts +39 -0
  423. package/lib/widgets/TOCWidget.js +254 -0
  424. package/lib/widgets/Widget.d.ts +61 -0
  425. package/lib/widgets/Widget.js +33 -0
  426. package/lib/widgets/WidgetDataSource.d.ts +20 -0
  427. package/lib/widgets/WidgetDataSource.js +2 -0
  428. package/lib/widgets/WidgetFactory.d.ts +4 -0
  429. package/lib/widgets/WidgetFactory.js +40 -0
  430. package/lib/widgets/WidgetScoper.d.ts +9 -0
  431. package/lib/widgets/WidgetScoper.js +49 -0
  432. package/lib/widgets/WidgetScopesViewComponent.d.ts +26 -0
  433. package/lib/widgets/WidgetScopesViewComponent.js +36 -0
  434. package/lib/widgets/charts/Chart.d.ts +57 -0
  435. package/lib/widgets/charts/Chart.js +83 -0
  436. package/lib/widgets/charts/ChartViewComponent.d.ts +72 -0
  437. package/lib/widgets/charts/ChartViewComponent.js +120 -0
  438. package/lib/widgets/charts/ChartWidget.d.ts +87 -0
  439. package/lib/widgets/charts/ChartWidget.js +248 -0
  440. package/lib/widgets/charts/calendar/CalendarChart.d.ts +39 -0
  441. package/lib/widgets/charts/calendar/CalendarChart.js +175 -0
  442. package/lib/widgets/charts/calendar/CalendarChartDesignerComponent.d.ts +35 -0
  443. package/lib/widgets/charts/calendar/CalendarChartDesignerComponent.js +142 -0
  444. package/lib/widgets/charts/calendar/CalendarChartViewComponent.d.ts +56 -0
  445. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +263 -0
  446. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +21 -0
  447. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +183 -0
  448. package/lib/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.d.ts +28 -0
  449. package/lib/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.js +105 -0
  450. package/lib/widgets/charts/imagemosaic/ImageMosaicChartViewComponent.d.ts +31 -0
  451. package/lib/widgets/charts/imagemosaic/ImageMosaicChartViewComponent.js +87 -0
  452. package/lib/widgets/charts/imagemosaic/ImagePopupComponent.d.ts +20 -0
  453. package/lib/widgets/charts/imagemosaic/ImagePopupComponent.js +38 -0
  454. package/lib/widgets/charts/layered/LayeredChart.d.ts +28 -0
  455. package/lib/widgets/charts/layered/LayeredChart.js +324 -0
  456. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +113 -0
  457. package/lib/widgets/charts/layered/LayeredChartCompiler.js +1092 -0
  458. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +76 -0
  459. package/lib/widgets/charts/layered/LayeredChartDesign.js +2 -0
  460. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +80 -0
  461. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +317 -0
  462. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +72 -0
  463. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +329 -0
  464. package/lib/widgets/charts/layered/LayeredChartSvgFileSaver.d.ts +5 -0
  465. package/lib/widgets/charts/layered/LayeredChartSvgFileSaver.js +138 -0
  466. package/lib/widgets/charts/layered/LayeredChartUtils.d.ts +1 -0
  467. package/lib/widgets/charts/layered/LayeredChartUtils.js +25 -0
  468. package/lib/widgets/charts/layered/LayeredChartViewComponent.d.ts +44 -0
  469. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +406 -0
  470. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +115 -0
  471. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.js +235 -0
  472. package/lib/widgets/charts/pivot/PivotChart.d.ts +36 -0
  473. package/lib/widgets/charts/pivot/PivotChart.js +343 -0
  474. package/lib/widgets/charts/pivot/PivotChartDesign.d.ts +88 -0
  475. package/lib/widgets/charts/pivot/PivotChartDesign.js +2 -0
  476. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +37 -0
  477. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +159 -0
  478. package/lib/widgets/charts/pivot/PivotChartLayout.d.ts +73 -0
  479. package/lib/widgets/charts/pivot/PivotChartLayout.js +2 -0
  480. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +37 -0
  481. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +676 -0
  482. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.d.ts +74 -0
  483. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +333 -0
  484. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.d.ts +31 -0
  485. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.js +263 -0
  486. package/lib/widgets/charts/pivot/PivotChartUtils.d.ts +12 -0
  487. package/lib/widgets/charts/pivot/PivotChartUtils.js +195 -0
  488. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +84 -0
  489. package/lib/widgets/charts/pivot/PivotChartViewComponent.js +205 -0
  490. package/lib/widgets/charts/pivot/README.md +30 -0
  491. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +96 -0
  492. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +216 -0
  493. package/lib/widgets/charts/table/OrderingsComponent.d.ts +15 -0
  494. package/lib/widgets/charts/table/OrderingsComponent.js +66 -0
  495. package/lib/widgets/charts/table/TableChart.d.ts +57 -0
  496. package/lib/widgets/charts/table/TableChart.js +310 -0
  497. package/lib/widgets/charts/table/TableChartDesignerComponent.d.ts +48 -0
  498. package/lib/widgets/charts/table/TableChartDesignerComponent.js +291 -0
  499. package/lib/widgets/charts/table/TableChartViewComponent.d.ts +28 -0
  500. package/lib/widgets/charts/table/TableChartViewComponent.js +206 -0
  501. package/lib/widgets/text/ExprInsertModalComponent.d.ts +35 -0
  502. package/lib/widgets/text/ExprInsertModalComponent.js +51 -0
  503. package/lib/widgets/text/ExprItemEditorComponent.d.ts +34 -0
  504. package/lib/widgets/text/ExprItemEditorComponent.js +92 -0
  505. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +33 -0
  506. package/lib/widgets/text/ExprUpdateModalComponent.js +47 -0
  507. package/lib/widgets/text/README.md +2 -0
  508. package/lib/widgets/text/TextComponent.d.ts +48 -0
  509. package/lib/widgets/text/TextComponent.js +109 -0
  510. package/lib/widgets/text/TextWidget.d.ts +29 -0
  511. package/lib/widgets/text/TextWidget.js +243 -0
  512. package/lib/widgets/text/TextWidgetComponent.d.ts +33 -0
  513. package/lib/widgets/text/TextWidgetComponent.js +88 -0
  514. package/lib/widgets/text/TextWidgetDesign.d.ts +6 -0
  515. package/lib/widgets/text/TextWidgetDesign.js +2 -0
  516. package/mocha.html +10 -0
  517. package/package.json +113 -0
  518. package/server.js +10 -0
  519. package/src/CheckboxComponent.ts +33 -0
  520. package/src/ColorComponent.ts +117 -0
  521. package/src/ColorSchemeFactory.ts +144 -0
  522. package/src/CsvBuilder.ts +65 -0
  523. package/src/DateRangeComponent.ts +279 -0
  524. package/src/FiltersDesignerComponent.ts +55 -0
  525. package/src/ImplicitFilterBuilder.ts +135 -0
  526. package/src/JsonQLFilter.ts +8 -0
  527. package/src/LocaleContextInjector.tsx +17 -0
  528. package/src/MWaterAddRelatedFormComponent.ts +213 -0
  529. package/src/MWaterAddRelatedIndicatorComponent.ts +205 -0
  530. package/src/MWaterAssetSystemsListComponent.tsx +114 -0
  531. package/src/MWaterCompleteTableSelectComponent.tsx +984 -0
  532. package/src/MWaterContextComponent.ts +144 -0
  533. package/src/MWaterCustomTablesetListComponent.tsx +141 -0
  534. package/src/MWaterGlobalFiltersComponent.ts +117 -0
  535. package/src/MWaterLoaderComponent.ts +118 -0
  536. package/src/MWaterMetricsTableListComponent.tsx +120 -0
  537. package/src/MWaterResponsesFilterComponent.ts +194 -0
  538. package/src/MWaterTableSelectComponent.ts +316 -0
  539. package/src/MenuItemComponent.ts +2 -0
  540. package/src/PopoverComponent.ts +59 -0
  541. package/src/RadioButtonComponent.ts +34 -0
  542. package/src/TableSelectComponent.ts +60 -0
  543. package/src/UIComponents.ts +289 -0
  544. package/src/UndoStack.ts +59 -0
  545. package/src/VerticalLayoutComponent.ts +108 -0
  546. package/src/WidgetScope.ts +17 -0
  547. package/src/axes/Axis.ts +89 -0
  548. package/src/axes/AxisBuilder.ts +1325 -0
  549. package/src/axes/AxisColorEditorComponent.ts +210 -0
  550. package/src/axes/AxisComponent.ts +449 -0
  551. package/src/axes/BinsComponent.tsx +169 -0
  552. package/src/axes/CategoryMapComponent.ts +278 -0
  553. package/src/axes/ColorPaletteCollectionComponent.ts +163 -0
  554. package/src/axes/RangesComponent.ts +234 -0
  555. package/src/color-mixer.d.ts +1 -0
  556. package/src/componenttest.ts +64 -0
  557. package/src/compressJson.ts +13 -0
  558. package/src/dashboards/DashboardComponent.ts +468 -0
  559. package/src/dashboards/DashboardDataSource.ts +15 -0
  560. package/src/dashboards/DashboardDesign.ts +57 -0
  561. package/src/dashboards/DashboardUpgrader.ts +103 -0
  562. package/src/dashboards/DashboardUtils.ts +82 -0
  563. package/src/dashboards/DashboardViewComponent.ts +304 -0
  564. package/src/dashboards/DirectDashboardDataSource.ts +69 -0
  565. package/src/dashboards/LayoutOptionsComponent.tsx +227 -0
  566. package/src/dashboards/README.md +13 -0
  567. package/src/dashboards/ServerDashboardDataSource.ts +520 -0
  568. package/src/dashboards/SettingsModalComponent.ts +169 -0
  569. package/src/dashboards/WidgetComponent.tsx +131 -0
  570. package/src/dashboards/layoutOptions.ts +40 -0
  571. package/src/datagrids/DatagridComponent.ts +430 -0
  572. package/src/datagrids/DatagridDataSource.ts +21 -0
  573. package/src/datagrids/DatagridDesign.ts +94 -0
  574. package/src/datagrids/DatagridDesignerComponent.tsx +585 -0
  575. package/src/datagrids/DatagridQueryBuilder.ts +722 -0
  576. package/src/datagrids/DatagridUtils.ts +74 -0
  577. package/src/datagrids/DatagridViewComponent.ts +460 -0
  578. package/src/datagrids/DirectDatagridDataSource.ts +57 -0
  579. package/src/datagrids/EditExprCellComponent.tsx +305 -0
  580. package/src/datagrids/ExprCellComponent.ts +104 -0
  581. package/src/datagrids/FindReplaceModalComponent.ts +354 -0
  582. package/src/datagrids/LabeledExprGenerator.ts +302 -0
  583. package/src/datagrids/OrderBysDesignerComponent.tsx +128 -0
  584. package/src/datagrids/README.md +3 -0
  585. package/src/datagrids/ServerDatagridDataSource.ts +119 -0
  586. package/src/datagrids/react-linkify.d.ts +1 -0
  587. package/src/demo.ts +4148 -0
  588. package/src/demoBlocks.ts +130 -0
  589. package/src/globals.d.ts +2 -0
  590. package/src/index.css +550 -0
  591. package/src/index.ts +112 -0
  592. package/src/injectTableAlias.ts +31 -0
  593. package/src/languages.ts +931 -0
  594. package/src/layout-styles.css +263 -0
  595. package/src/layouts/DecoratedBlockComponent.ts +167 -0
  596. package/src/layouts/DragSourceComponent.ts +35 -0
  597. package/src/layouts/LayoutManager.ts +86 -0
  598. package/src/layouts/blocks/BlocksDisplayComponent.ts +461 -0
  599. package/src/layouts/blocks/BlocksLayoutManager.ts +78 -0
  600. package/src/layouts/blocks/ClipboardPaletteItemComponent.ts +89 -0
  601. package/src/layouts/blocks/DraggableBlockComponent.ts +219 -0
  602. package/src/layouts/blocks/HorizontalBlockComponent.ts +288 -0
  603. package/src/layouts/blocks/PaletteItemComponent.ts +27 -0
  604. package/src/layouts/blocks/README.md +11 -0
  605. package/src/layouts/blocks/blockUtils.ts +207 -0
  606. package/src/layouts/decorated-block.css +100 -0
  607. package/src/layouts/grid/GridLayoutComponent.ts +67 -0
  608. package/src/layouts/grid/GridLayoutManager.ts +185 -0
  609. package/src/layouts/grid/LegoLayoutEngine.ts +142 -0
  610. package/src/layouts/grid/PaletteItemComponent.ts +28 -0
  611. package/src/layouts/grid/README.md +14 -0
  612. package/src/layouts/grid/WidgetContainerComponent.ts +420 -0
  613. package/src/mWaterLoader.ts +82 -0
  614. package/src/mapdemo.ts +127 -0
  615. package/src/maps/AddLayerComponent.ts +125 -0
  616. package/src/maps/AdminScopeAndDetailLevelComponent.ts +90 -0
  617. package/src/maps/BaseLayerDesignerComponent.ts +104 -0
  618. package/src/maps/BingLayer.ts +156 -0
  619. package/src/maps/BufferLayer.ts +927 -0
  620. package/src/maps/BufferLayerDesign.ts +48 -0
  621. package/src/maps/BufferLayerDesignerComponent.ts +311 -0
  622. package/src/maps/ChoroplethLayer.ts +1712 -0
  623. package/src/maps/ChoroplethLayerDesign.ts +73 -0
  624. package/src/maps/ChoroplethLayerDesigner.tsx +558 -0
  625. package/src/maps/ClusterLayer.ts +836 -0
  626. package/src/maps/ClusterLayerDesign.ts +29 -0
  627. package/src/maps/ClusterLayerDesignerComponent.ts +190 -0
  628. package/src/maps/DetailLevelSelectComponent.ts +119 -0
  629. package/src/maps/DirectMapDataSource.ts +386 -0
  630. package/src/maps/EditHoverOver.tsx +151 -0
  631. package/src/maps/EditPopupComponent.ts +121 -0
  632. package/src/maps/Grid Functions.sql +167 -0
  633. package/src/maps/GridLayer.ts +776 -0
  634. package/src/maps/GridLayerDesign.ts +53 -0
  635. package/src/maps/GridLayerDesigner.tsx +332 -0
  636. package/src/maps/HoverContent.tsx +96 -0
  637. package/src/maps/HtmlUrlLegend.tsx +44 -0
  638. package/src/maps/Layer.ts +338 -0
  639. package/src/maps/LayerFactory.ts +51 -0
  640. package/src/maps/LayerLegendComponent.ts +88 -0
  641. package/src/maps/LayerSwitcherComponent.tsx +91 -0
  642. package/src/maps/LeafletLoading.css +24 -0
  643. package/src/maps/LeafletLoading.ts +355 -0
  644. package/src/maps/LeafletMapComponent.tsx +587 -0
  645. package/src/maps/LegendComponent.tsx +101 -0
  646. package/src/maps/LegendGroup.ts +120 -0
  647. package/src/maps/MWaterServerLayer.ts +116 -0
  648. package/src/maps/MapBoundsCalculator.ts +88 -0
  649. package/src/maps/MapComponent.ts +312 -0
  650. package/src/maps/MapControlComponent.ts +46 -0
  651. package/src/maps/MapDataSource.ts +20 -0
  652. package/src/maps/MapDesign.ts +103 -0
  653. package/src/maps/MapDesignerComponent.ts +356 -0
  654. package/src/maps/MapFiltersDesignerComponent.ts +95 -0
  655. package/src/maps/MapLayerDataSource.ts +27 -0
  656. package/src/maps/MapLayerViewDesignerComponent.ts +243 -0
  657. package/src/maps/MapLayersDesignerComponent.ts +144 -0
  658. package/src/maps/MapUtils.ts +148 -0
  659. package/src/maps/MapViewComponent.tsx +62 -0
  660. package/src/maps/Maptiler-logo.png +0 -0
  661. package/src/maps/MarkerSymbolSelectComponent.ts +41 -0
  662. package/src/maps/MarkersLayer.ts +941 -0
  663. package/src/maps/MarkersLayerDesign.ts +56 -0
  664. package/src/maps/MarkersLayerDesignerComponent.ts +374 -0
  665. package/src/maps/PopupFilterJoinsEditComponent.ts +114 -0
  666. package/src/maps/PopupFilterJoinsUtils.ts +99 -0
  667. package/src/maps/RasterMapViewComponent.ts +382 -0
  668. package/src/maps/RegionSelectComponent.ts +80 -0
  669. package/src/maps/ScopeAndDetailLevelComponent.ts +82 -0
  670. package/src/maps/ServerMapDataSource.ts +399 -0
  671. package/src/maps/SwitchableTileUrlLayer.tsx +130 -0
  672. package/src/maps/SwitchableTileUrlLayerDesigner.tsx +60 -0
  673. package/src/maps/TileUrlLayer.tsx +142 -0
  674. package/src/maps/UtfGridLayer.ts +286 -0
  675. package/src/maps/VectorMapViewComponent.css +21 -0
  676. package/src/maps/VectorMapViewComponent.tsx +743 -0
  677. package/src/maps/ZoomLevelsComponent.ts +72 -0
  678. package/src/maps/mapSymbols.ts +162 -0
  679. package/src/maps/mapboxUtils.ts +61 -0
  680. package/src/maps/maps.ts +38 -0
  681. package/src/maps/marker-icon-2x.png +0 -0
  682. package/src/maps/marker-icon.png +0 -0
  683. package/src/maps/marker-shadow.png +0 -0
  684. package/src/maps/png.d.ts +1 -0
  685. package/src/maps/symbols/font-awesome/asterisk.png +0 -0
  686. package/src/maps/symbols/font-awesome/ban.png +0 -0
  687. package/src/maps/symbols/font-awesome/beer.png +0 -0
  688. package/src/maps/symbols/font-awesome/bell.png +0 -0
  689. package/src/maps/symbols/font-awesome/bolt.png +0 -0
  690. package/src/maps/symbols/font-awesome/building.png +0 -0
  691. package/src/maps/symbols/font-awesome/bullseye.png +0 -0
  692. package/src/maps/symbols/font-awesome/bus.png +0 -0
  693. package/src/maps/symbols/font-awesome/caret-up.png +0 -0
  694. package/src/maps/symbols/font-awesome/certificate.png +0 -0
  695. package/src/maps/symbols/font-awesome/check-circle.png +0 -0
  696. package/src/maps/symbols/font-awesome/check.png +0 -0
  697. package/src/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  698. package/src/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  699. package/src/maps/symbols/font-awesome/cloud.png +0 -0
  700. package/src/maps/symbols/font-awesome/comment.png +0 -0
  701. package/src/maps/symbols/font-awesome/crosshairs.png +0 -0
  702. package/src/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  703. package/src/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  704. package/src/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  705. package/src/maps/symbols/font-awesome/female.png +0 -0
  706. package/src/maps/symbols/font-awesome/file.png +0 -0
  707. package/src/maps/symbols/font-awesome/flag.png +0 -0
  708. package/src/maps/symbols/font-awesome/flask.png +0 -0
  709. package/src/maps/symbols/font-awesome/h-square.png +0 -0
  710. package/src/maps/symbols/font-awesome/home.png +0 -0
  711. package/src/maps/symbols/font-awesome/info-circle.png +0 -0
  712. package/src/maps/symbols/font-awesome/male.png +0 -0
  713. package/src/maps/symbols/font-awesome/medkit.png +0 -0
  714. package/src/maps/symbols/font-awesome/mobile.png +0 -0
  715. package/src/maps/symbols/font-awesome/plus-circle.png +0 -0
  716. package/src/maps/symbols/font-awesome/plus-square.png +0 -0
  717. package/src/maps/symbols/font-awesome/plus.png +0 -0
  718. package/src/maps/symbols/font-awesome/square.png +0 -0
  719. package/src/maps/symbols/font-awesome/star.png +0 -0
  720. package/src/maps/symbols/font-awesome/thumbs-down.png +0 -0
  721. package/src/maps/symbols/font-awesome/thumbs-up.png +0 -0
  722. package/src/maps/symbols/font-awesome/ticket.png +0 -0
  723. package/src/maps/symbols/font-awesome/times-circle.png +0 -0
  724. package/src/maps/symbols/font-awesome/times.png +0 -0
  725. package/src/maps/symbols/font-awesome/tint.png +0 -0
  726. package/src/maps/symbols/font-awesome/tree.png +0 -0
  727. package/src/maps/symbols/font-awesome/university.png +0 -0
  728. package/src/maps/symbols/font-awesome/usd.png +0 -0
  729. package/src/maps/symbols/font-awesome/user.png +0 -0
  730. package/src/maps/symbols/font-awesome/users.png +0 -0
  731. package/src/maps/symbols/font-awesome/wheelchair.png +0 -0
  732. package/src/maps/vectorMaps.tsx +410 -0
  733. package/src/memoizedDebounce.tsx +32 -0
  734. package/src/quickfilter/DateExprComponent.ts +284 -0
  735. package/src/quickfilter/IdArrayQuickfilterComponent.ts +58 -0
  736. package/src/quickfilter/Quickfilter.ts +29 -0
  737. package/src/quickfilter/QuickfilterCompiler.ts +167 -0
  738. package/src/quickfilter/QuickfilterUtils.ts +123 -0
  739. package/src/quickfilter/QuickfiltersComponent.ts +416 -0
  740. package/src/quickfilter/QuickfiltersDataSource.ts +15 -0
  741. package/src/quickfilter/QuickfiltersDesignComponent.tsx +257 -0
  742. package/src/quickfilter/README.md +8 -0
  743. package/src/quickfilter/TextLiteralComponent.ts +161 -0
  744. package/src/quickfilter/react-onclickout.d.ts +1 -0
  745. package/src/richtext/ExprItemsHtmlConverter.ts +144 -0
  746. package/src/richtext/FontColorPaletteItem.ts +172 -0
  747. package/src/richtext/FontSizePaletteItem.ts +110 -0
  748. package/src/richtext/ItemsHtmlConverter.ts +246 -0
  749. package/src/richtext/README.md +3 -0
  750. package/src/richtext/RichTextComponent.tsx +390 -0
  751. package/src/richtext/react-float-affixed.d.ts +1 -0
  752. package/src/update-object.d.ts +1 -0
  753. package/src/valueFormatter.ts +110 -0
  754. package/src/widgets/DirectWidgetDataSource.ts +67 -0
  755. package/src/widgets/DropdownWidgetComponent.ts +78 -0
  756. package/src/widgets/IFrameWidget.ts +36 -0
  757. package/src/widgets/IFrameWidgetComponent.ts +116 -0
  758. package/src/widgets/ImageUploaderComponent.tsx +143 -0
  759. package/src/widgets/ImageWidget.ts +147 -0
  760. package/src/widgets/ImageWidgetComponent.ts +546 -0
  761. package/src/widgets/ImagelistCarouselComponent.ts +109 -0
  762. package/src/widgets/MapWidget.ts +219 -0
  763. package/src/widgets/MarkdownWidget.ts +201 -0
  764. package/src/widgets/TOCWidget.ts +326 -0
  765. package/src/widgets/Widget.ts +83 -0
  766. package/src/widgets/WidgetDataSource.ts +23 -0
  767. package/src/widgets/WidgetFactory.ts +37 -0
  768. package/src/widgets/WidgetScoper.ts +51 -0
  769. package/src/widgets/WidgetScopesViewComponent.ts +54 -0
  770. package/src/widgets/charts/Chart.ts +140 -0
  771. package/src/widgets/charts/ChartViewComponent.ts +209 -0
  772. package/src/widgets/charts/ChartWidget.ts +345 -0
  773. package/src/widgets/charts/calendar/CalendarChart.ts +227 -0
  774. package/src/widgets/charts/calendar/CalendarChartDesignerComponent.ts +187 -0
  775. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +320 -0
  776. package/src/widgets/charts/calendar/d3-tip.d.ts +1 -0
  777. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +213 -0
  778. package/src/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.ts +121 -0
  779. package/src/widgets/charts/imagemosaic/ImageMosaicChartViewComponent.ts +117 -0
  780. package/src/widgets/charts/imagemosaic/ImagePopupComponent.ts +51 -0
  781. package/src/widgets/charts/imagemosaic/react-lazy-load-image-component.d.ts +1 -0
  782. package/src/widgets/charts/layered/LayeredChart.ts +361 -0
  783. package/src/widgets/charts/layered/LayeredChartCompiler.ts +1299 -0
  784. package/src/widgets/charts/layered/LayeredChartDesign.ts +106 -0
  785. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +523 -0
  786. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +448 -0
  787. package/src/widgets/charts/layered/LayeredChartSvgFileSaver.ts +146 -0
  788. package/src/widgets/charts/layered/LayeredChartUtils.ts +24 -0
  789. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +486 -0
  790. package/src/widgets/charts/layered/save-svg-as-png.d.ts +1 -0
  791. package/src/widgets/charts/pivot/IntersectionDesignerComponent.tsx +338 -0
  792. package/src/widgets/charts/pivot/PivotChart.ts +377 -0
  793. package/src/widgets/charts/pivot/PivotChartDesign.ts +115 -0
  794. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +240 -0
  795. package/src/widgets/charts/pivot/PivotChartLayout.ts +99 -0
  796. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +779 -0
  797. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +504 -0
  798. package/src/widgets/charts/pivot/PivotChartQueryBuilder.ts +273 -0
  799. package/src/widgets/charts/pivot/PivotChartUtils.ts +219 -0
  800. package/src/widgets/charts/pivot/PivotChartViewComponent.ts +276 -0
  801. package/src/widgets/charts/pivot/README.md +30 -0
  802. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +353 -0
  803. package/src/widgets/charts/table/OrderingsComponent.tsx +119 -0
  804. package/src/widgets/charts/table/TableChart.ts +420 -0
  805. package/src/widgets/charts/table/TableChartDesignerComponent.ts +441 -0
  806. package/src/widgets/charts/table/TableChartViewComponent.ts +327 -0
  807. package/src/widgets/text/ExprInsertModalComponent.ts +77 -0
  808. package/src/widgets/text/ExprItemEditorComponent.tsx +164 -0
  809. package/src/widgets/text/ExprUpdateModalComponent.ts +70 -0
  810. package/src/widgets/text/README.md +2 -0
  811. package/src/widgets/text/TextComponent.tsx +151 -0
  812. package/src/widgets/text/TextWidget.ts +265 -0
  813. package/src/widgets/text/TextWidgetComponent.ts +120 -0
  814. package/src/widgets/text/TextWidgetDesign.ts +7 -0
  815. package/stories/UpdateableComponent.js +29 -0
  816. package/stories/consoles.js +202 -0
  817. package/stories/dashboards.js +217 -0
  818. package/stories/datagridDesign.js +114 -0
  819. package/stories/datagrids.js +69 -0
  820. package/stories/dates.js +80 -0
  821. package/stories/exprcomponent.js +43 -0
  822. package/stories/index.js +18 -0
  823. package/stories/leaflet.js +59 -0
  824. package/stories/maps.js +24 -0
  825. package/stories/pivotChart.js +235 -0
  826. package/test/AxisBuilderTests.ts +931 -0
  827. package/test/ChartWidgetTests.ts +85 -0
  828. package/test/ColorSchemeFactoryTests.ts +29 -0
  829. package/test/CsvBuilderTests.ts +22 -0
  830. package/test/DashboardUpgraderTests.ts +170 -0
  831. package/test/ImplicitFilterBuilderTests.ts +161 -0
  832. package/test/LayeredChartCompilerTests.ts +1067 -0
  833. package/test/LayeredChartTests.ts +88 -0
  834. package/test/LegoLayoutEngineTests.ts +69 -0
  835. package/test/MWaterGlobalFiltersComponentTests.ts +130 -0
  836. package/test/MWaterResponsesFilterComponentTests.ts +164 -0
  837. package/test/QuickfilterCompilerTests.ts +167 -0
  838. package/test/TestComponent.ts +49 -0
  839. package/test/UndoStackTests.ts +73 -0
  840. package/test/WidgetScoperTests.ts +35 -0
  841. package/test/blockUtilsTests.ts +290 -0
  842. package/test/canonical-json.d.ts +1 -0
  843. package/test/dashboards/DashboardUtilsTests.ts +131 -0
  844. package/test/datagrids/DatagridQueryBuilderTests.ts +445 -0
  845. package/test/datagrids/DatagridUtilsTests.ts +54 -0
  846. package/test/datagrids/LabeledExprGeneratorTests.ts +121 -0
  847. package/test/fixtures.ts +263 -0
  848. package/test/index.ts +2 -0
  849. package/test/maps/MapUtilsTests.ts +168 -0
  850. package/test/maps/PopupFilterJoinsUtilsTests.ts +105 -0
  851. package/test/richtext/ItemsHtmlConverterTests.ts +41 -0
  852. package/test/test_index.ts +4 -0
  853. package/test/widgets/TextWidgetTests.ts +42 -0
  854. package/test/widgets/charts/pivot/PivotChartLayoutBuilderTests.ts +817 -0
  855. package/test/widgets/charts/pivot/PivotChartQueryBuilderTests.ts +359 -0
  856. package/test/widgets/charts/pivot/PivotChartTests.ts +64 -0
  857. package/test/widgets/charts/pivot/PivotChartUtilsTests.ts +184 -0
  858. package/test/widgets/charts/table/TableChartTests.ts +253 -0
  859. package/tsconfig.build.json +26 -0
  860. package/types/utm.d.ts +10 -0
@@ -0,0 +1,1712 @@
1
+ import _ from "lodash"
2
+ import React from "react"
3
+
4
+ import { original, produce } from "immer"
5
+
6
+ import Layer, { OnGridClickOptions, OnGridHoverOptions, VectorTileDef } from "./Layer"
7
+ import {
8
+ ExprUtils,
9
+ ExprCompiler,
10
+ ExprCleaner,
11
+ injectTableAlias,
12
+ Schema,
13
+ Expr,
14
+ DataSource,
15
+ OpExpr,
16
+ ExprValidator
17
+ } from "@mwater/expressions"
18
+ import AxisBuilder from "../axes/AxisBuilder"
19
+ import { LayerDefinition, OnGridClickResults, OnGridHoverResults } from "./maps"
20
+ import { JsonQLFilter } from "../index"
21
+ import ChoroplethLayerDesign from "./ChoroplethLayerDesign"
22
+ import { JsonQLExpr, JsonQLOp, JsonQLQuery, JsonQLScalar } from "@mwater/jsonql"
23
+ import { compileColorMapToMapbox, compileColorToMapbox } from "./mapboxUtils"
24
+ import LayerLegendComponent from "./LayerLegendComponent"
25
+ import * as PopupFilterJoinsUtils from "./PopupFilterJoinsUtils"
26
+ import { LayerSpecification } from "maplibre-gl"
27
+ import HoverContent from "./HoverContent"
28
+
29
+ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
30
+ /** Gets the type of layer definition */
31
+ getLayerDefinitionType(): "VectorTile" {
32
+ return "VectorTile"
33
+ }
34
+
35
+ getVectorTile(
36
+ design: ChoroplethLayerDesign,
37
+ sourceId: string,
38
+ schema: Schema,
39
+ filters: JsonQLFilter[],
40
+ opacity: number
41
+ ): VectorTileDef {
42
+ // Verify that scopeLevel is an integer to prevent injection
43
+ if (design.scopeLevel != null && ![0, 1, 2, 3, 4, 5].includes(design.scopeLevel)) {
44
+ throw new Error("Invalid scope level")
45
+ }
46
+
47
+ // Verify that detailLevel is an integer to prevent injection
48
+ if (![0, 1, 2, 3, 4, 5].includes(design.detailLevel)) {
49
+ throw new Error("Invalid detail level")
50
+ }
51
+
52
+ if (design.regionMode === "plain") {
53
+ return this.createPlainVectorTile(design, sourceId, schema, filters, opacity)
54
+ } else if (design.regionMode === "indirect" || !design.regionMode) {
55
+ return this.createIndirectVectorTile(design, sourceId, schema, filters, opacity)
56
+ } else if (design.regionMode == "direct") {
57
+ return this.createDirectVectorTile(design, sourceId, schema, filters, opacity)
58
+ } else {
59
+ throw new Error("NOT IMPLEMENTED")
60
+ }
61
+ }
62
+
63
+ createPlainVectorTile(
64
+ design: ChoroplethLayerDesign,
65
+ sourceId: string,
66
+ schema: Schema,
67
+ filters: JsonQLFilter[],
68
+ opacity: number
69
+ ): VectorTileDef {
70
+ const regionsTable = design.regionsTable || "admin_regions"
71
+
72
+ // Expression of envelope from tile table
73
+ const envelopeExpr: JsonQLScalar = {
74
+ type: "scalar",
75
+ expr: { type: "field", tableAlias: "tile", column: "envelope" },
76
+ from: { type: "table", table: "tile", alias: "tile" }
77
+ }
78
+ const envelopeWithMarginExpr: JsonQLScalar = {
79
+ type: "scalar",
80
+ expr: { type: "field", tableAlias: "tile", column: "envelope_with_margin" },
81
+ from: { type: "table", table: "tile", alias: "tile" }
82
+ }
83
+
84
+ /*
85
+ Returns two source layers, "polygons" and "points". Points are used for labels.
86
+
87
+ polygons:
88
+ select name, ST_AsMVTGeom(shape_simplified, tile.envelope) as the_geom_webmercator from
89
+ admin_regions as regions, tile as tile
90
+ where regions.level0 = 242
91
+ and regions.level = 1
92
+ and shape && tile.envelope_with_margin
93
+
94
+ points:
95
+ select name, ST_AsMVTGeom(
96
+ (select ST_Centroid(polys.geom) from ST_Dump(shape_simplified) as polys order by ST_Area(polys.geom) desc limit 1)
97
+ , tile.envelope) as the_geom_webmercator from
98
+ admin_regions as regions, tile as tile
99
+ where regions.level0 = 242
100
+ and regions.level = 1
101
+ and shape && tile.envelope_with_margin
102
+
103
+ */
104
+
105
+ // Create where
106
+ const where: JsonQLExpr = {
107
+ type: "op",
108
+ op: "and",
109
+ exprs: [
110
+ // Level to display
111
+ {
112
+ type: "op",
113
+ op: "=",
114
+ exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
115
+ },
116
+ // Filter to tile
117
+ {
118
+ type: "op",
119
+ op: "&&",
120
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape" }, envelopeWithMarginExpr]
121
+ }
122
+ ]
123
+ }
124
+
125
+ // Scope overall
126
+ if (design.scope) {
127
+ where.exprs.push({
128
+ type: "op",
129
+ op: "=",
130
+ exprs: [
131
+ { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
132
+ { type: "literal", value: design.scope }
133
+ ]
134
+ })
135
+ }
136
+
137
+ // Add filters on regions to outer query
138
+ for (const filter of filters) {
139
+ if (filter.table == regionsTable) {
140
+ where.exprs.push(injectTableAlias(filter.jsonql, "regions"))
141
+ }
142
+ }
143
+
144
+ const polygonsQuery: JsonQLQuery = {
145
+ type: "query",
146
+ selects: [
147
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
148
+ {
149
+ type: "select",
150
+ expr: {
151
+ type: "op",
152
+ op: "ST_AsMVTGeom",
153
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape_simplified" }, envelopeExpr]
154
+ },
155
+ alias: "the_geom_webmercator"
156
+ },
157
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
158
+ ],
159
+ from: { type: "table", table: regionsTable, alias: "regions" },
160
+ where: where
161
+ }
162
+
163
+ const pointsQuery: JsonQLQuery = {
164
+ type: "query",
165
+ selects: [
166
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
167
+ {
168
+ type: "select",
169
+ expr: {
170
+ type: "op",
171
+ op: "ST_AsMVTGeom",
172
+ exprs: [
173
+ {
174
+ type: "scalar",
175
+ expr: {
176
+ type: "op",
177
+ op: "ST_Centroid",
178
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
179
+ },
180
+ from: {
181
+ type: "subexpr",
182
+ expr: {
183
+ type: "op",
184
+ op: "ST_Dump",
185
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape_simplified" }]
186
+ },
187
+ alias: "polys"
188
+ },
189
+ orderBy: [
190
+ {
191
+ expr: {
192
+ type: "op",
193
+ op: "ST_Area",
194
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
195
+ },
196
+ direction: "desc"
197
+ }
198
+ ],
199
+ limit: 1
200
+ },
201
+ envelopeExpr
202
+ ]
203
+ },
204
+ alias: "the_geom_webmercator"
205
+ },
206
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
207
+ ],
208
+ from: { type: "table", table: regionsTable, alias: "regions" },
209
+ where: where
210
+ }
211
+
212
+ // Create layers
213
+ const mapLayers: LayerSpecification[] = []
214
+
215
+ mapLayers.push({
216
+ id: `${sourceId}:polygon-fill`,
217
+ type: "fill",
218
+ source: sourceId,
219
+ "source-layer": "polygons",
220
+ paint: {
221
+ "fill-opacity": design.fillOpacity * design.fillOpacity * opacity,
222
+ "fill-color": design.color || "transparent",
223
+ "fill-outline-color": "transparent"
224
+ }
225
+ })
226
+
227
+ mapLayers.push({
228
+ id: `${sourceId}:polygon-line`,
229
+ type: "line",
230
+ source: sourceId,
231
+ "source-layer": "polygons",
232
+ paint: {
233
+ // Because of https://github.com/mapbox/mapbox-gl-js/issues/4090, line opacities < 1 create artifacts.
234
+ "line-color": design.borderColor || "#000",
235
+ "line-opacity": opacity, // 0.5 * opacity,
236
+ "line-width": 1,
237
+ "line-blur": 1.5
238
+ }
239
+ })
240
+
241
+ if (design.displayNames) {
242
+ mapLayers.push({
243
+ id: `${sourceId}:labels`,
244
+ type: "symbol",
245
+ source: sourceId,
246
+ "source-layer": "points",
247
+ layout: {
248
+ "text-field": ["get", "name"],
249
+ "text-size": 10
250
+ },
251
+ paint: {
252
+ "text-color": "black",
253
+ "text-halo-color": "rgba(255, 255, 255, 0.5)",
254
+ "text-halo-width": 2,
255
+ "text-opacity": opacity
256
+ }
257
+ })
258
+ }
259
+
260
+ return {
261
+ ctes: [],
262
+ sourceLayers: [
263
+ { id: "polygons", jsonql: polygonsQuery },
264
+ { id: "points", jsonql: pointsQuery }
265
+ ],
266
+ mapLayers: mapLayers,
267
+ mapLayersHandleClicks: [`${sourceId}:polygon-fill`],
268
+ minZoom: design.minZoom,
269
+ maxZoom: design.maxZoom
270
+ }
271
+ }
272
+
273
+ createIndirectVectorTile(
274
+ design: ChoroplethLayerDesign,
275
+ sourceId: string,
276
+ schema: Schema,
277
+ filters: JsonQLFilter[],
278
+ opacity: number
279
+ ): VectorTileDef {
280
+ const axisBuilder = new AxisBuilder({ schema })
281
+ const exprCompiler = new ExprCompiler(schema)
282
+ const regionsTable = design.regionsTable || "admin_regions"
283
+
284
+ // Expression of scale and envelope from tile table
285
+ const envelopeExpr: JsonQLScalar = {
286
+ type: "scalar",
287
+ expr: { type: "field", tableAlias: "tile", column: "envelope" },
288
+ from: { type: "table", table: "tile", alias: "tile" }
289
+ }
290
+
291
+ /*
292
+ Returns two source layers, "polygons" and "points". Points are used for labels.
293
+
294
+ Has a CTE (regions) that is the core data that doesn't change by tile. e.g.:
295
+
296
+ select admin_regions.level1 as id,
297
+ count(innerquery.*) as color
298
+ from
299
+ admin_regions inner join
300
+ entities.water_point as innerquery
301
+ on innerquery.admin_region = admin_regions._id
302
+ where admin_regions.level0 = 242
303
+ group by 1
304
+
305
+ polygons:
306
+ select name, ST_AsMVTGeom(shape_simplified, tile.envelope) as the_geom_webmercator, regions.color from
307
+ admin_regions as regions2
308
+ left outer join regions as regions on regions.id = regions2._id
309
+ where regions2.level = 1 and regions2.level0 = 242
310
+
311
+ points:
312
+ select name, ST_AsMVTGeom(
313
+ (select ST_Centroid(polys.geom) from ST_Dump(shape_simplified) as polys order by ST_Area(polys.geom) desc limit 1), tile.envelope) as the_geom_webmercator, regions.color from
314
+ admin_regions as regions2
315
+ left outer join regions as regions on regions.id = regions2._id, tile as tile
316
+ where regions2.level = 1 and regions2.level0 = 242 and shape && tile.envelope_with_margin
317
+
318
+ */
319
+ const compiledAdminRegionExpr = exprCompiler.compileExpr({
320
+ expr: design.adminRegionExpr || null,
321
+ tableAlias: "innerquery"
322
+ })
323
+
324
+ // Create CTE query
325
+ const cteQuery: JsonQLQuery = {
326
+ type: "query",
327
+ selects: [
328
+ {
329
+ type: "select",
330
+ expr: { type: "field", tableAlias: "regions", column: `level${design.detailLevel}` },
331
+ alias: "id"
332
+ }
333
+ ],
334
+ from: {
335
+ type: "join",
336
+ kind: "inner",
337
+ left: { type: "table", table: regionsTable, alias: "regions" },
338
+ right: exprCompiler.compileTable(design.table!, "innerquery"),
339
+ on: {
340
+ type: "op",
341
+ op: "=",
342
+ exprs: [compiledAdminRegionExpr, { type: "field", tableAlias: "regions", column: "_id" }]
343
+ }
344
+ },
345
+ groupBy: [1]
346
+ }
347
+
348
+ // Add color select if color axis
349
+ if (design.axes.color) {
350
+ const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "innerquery" })
351
+ cteQuery.selects.push({ type: "select", expr: colorExpr, alias: "color" })
352
+ }
353
+
354
+ // Add label select if color axis
355
+ if (design.axes.label) {
356
+ const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "innerquery" })
357
+ cteQuery.selects.push({ type: "select", expr: labelExpr, alias: "label" })
358
+ }
359
+
360
+ let whereClauses = []
361
+
362
+ if (design.scope) {
363
+ whereClauses.push({
364
+ type: "op",
365
+ op: "=",
366
+ exprs: [{ type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` }, design.scope]
367
+ })
368
+ }
369
+
370
+ // Then add filters
371
+ if (design.filter) {
372
+ whereClauses.push(exprCompiler.compileExpr({ expr: design.filter, tableAlias: "innerquery" }))
373
+ }
374
+
375
+ // Then add extra filters passed in, if relevant
376
+ const relevantFilters = _.where(filters, { table: design.table })
377
+ for (let filter of relevantFilters) {
378
+ whereClauses.push(injectTableAlias(filter.jsonql, "innerquery"))
379
+ }
380
+
381
+ whereClauses = _.compact(whereClauses)
382
+
383
+ if (whereClauses.length > 0) {
384
+ cteQuery.where = { type: "op", op: "and", exprs: whereClauses }
385
+ }
386
+
387
+ // Create outer where clause
388
+ const outerWhere: JsonQLExpr = {
389
+ type: "op",
390
+ op: "and",
391
+ exprs: [
392
+ // Level to display
393
+ {
394
+ type: "op",
395
+ op: "=",
396
+ exprs: [{ type: "field", tableAlias: "regions2", column: "level" }, design.detailLevel]
397
+ }
398
+ ]
399
+ }
400
+
401
+ // Scope overall
402
+ if (design.scope) {
403
+ outerWhere.exprs.push({
404
+ type: "op",
405
+ op: "=",
406
+ exprs: [
407
+ { type: "field", tableAlias: "regions2", column: `level${design.scopeLevel || 0}` },
408
+ { type: "literal", value: design.scope }
409
+ ]
410
+ })
411
+ }
412
+
413
+ // Add filters on regions to outer query
414
+ for (const filter of filters) {
415
+ if (filter.table == regionsTable) {
416
+ outerWhere.exprs.push(injectTableAlias(filter.jsonql, "regions2"))
417
+ }
418
+ }
419
+
420
+ // Now create outer query
421
+ const polygonsQuery: JsonQLQuery = {
422
+ type: "query",
423
+ selects: [
424
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "_id" }, alias: "id" },
425
+ {
426
+ type: "select",
427
+ expr: {
428
+ type: "op",
429
+ op: "ST_AsMVTGeom",
430
+ exprs: [{ type: "field", tableAlias: "regions2", column: "shape_simplified" }, envelopeExpr]
431
+ },
432
+ alias: "the_geom_webmercator"
433
+ },
434
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "name" }, alias: "name" }
435
+ ],
436
+ from: {
437
+ type: "join",
438
+ kind: "left",
439
+ left: { type: "table", table: regionsTable, alias: "regions2" },
440
+ right: { type: "table", table: "regions", alias: "regions" },
441
+ on: {
442
+ type: "op",
443
+ op: "=",
444
+ exprs: [
445
+ { type: "field", tableAlias: "regions", column: "id" },
446
+ { type: "field", tableAlias: "regions2", column: "_id" }
447
+ ]
448
+ }
449
+ },
450
+ where: outerWhere
451
+ }
452
+
453
+ const pointsQuery: JsonQLQuery = {
454
+ type: "query",
455
+ selects: [
456
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "_id" }, alias: "id" },
457
+ {
458
+ type: "select",
459
+ expr: {
460
+ type: "op",
461
+ op: "ST_AsMVTGeom",
462
+ exprs: [
463
+ {
464
+ type: "scalar",
465
+ expr: {
466
+ type: "op",
467
+ op: "ST_Centroid",
468
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
469
+ },
470
+ from: {
471
+ type: "subexpr",
472
+ expr: {
473
+ type: "op",
474
+ op: "ST_Dump",
475
+ exprs: [{ type: "field", tableAlias: "regions2", column: "shape_simplified" }]
476
+ },
477
+ alias: "polys"
478
+ },
479
+ orderBy: [
480
+ {
481
+ expr: {
482
+ type: "op",
483
+ op: "ST_Area",
484
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
485
+ },
486
+ direction: "desc"
487
+ }
488
+ ],
489
+ limit: 1
490
+ },
491
+ envelopeExpr
492
+ ]
493
+ },
494
+ alias: "the_geom_webmercator"
495
+ },
496
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "name" }, alias: "name" }
497
+ ],
498
+ from: {
499
+ type: "join",
500
+ kind: "left",
501
+ left: { type: "table", table: regionsTable, alias: "regions2" },
502
+ right: { type: "table", table: "regions", alias: "regions" },
503
+ on: {
504
+ type: "op",
505
+ op: "=",
506
+ exprs: [
507
+ { type: "field", tableAlias: "regions", column: "id" },
508
+ { type: "field", tableAlias: "regions2", column: "_id" }
509
+ ]
510
+ }
511
+ },
512
+ where: outerWhere
513
+ }
514
+
515
+ // Bubble up color and label
516
+ if (design.axes.color) {
517
+ polygonsQuery.selects.push({
518
+ type: "select",
519
+ expr: { type: "field", tableAlias: "regions", column: "color" },
520
+ alias: "color"
521
+ })
522
+ pointsQuery.selects.push({
523
+ type: "select",
524
+ expr: { type: "field", tableAlias: "regions", column: "color" },
525
+ alias: "color"
526
+ })
527
+ }
528
+
529
+ // Add label select if color axis
530
+ if (design.axes.label) {
531
+ polygonsQuery.selects.push({
532
+ type: "select",
533
+ expr: { type: "field", tableAlias: "regions", column: "label" },
534
+ alias: "label"
535
+ })
536
+ pointsQuery.selects.push({
537
+ type: "select",
538
+ expr: { type: "field", tableAlias: "regions", column: "label" },
539
+ alias: "label"
540
+ })
541
+ }
542
+
543
+ // If color axes, add color conditions
544
+ const color = compileColorMapToMapbox(design.axes.color, design.color || "transparent")
545
+
546
+ // Create layers
547
+ const mapLayers: LayerSpecification[] = []
548
+
549
+ mapLayers.push({
550
+ id: `${sourceId}:polygon-fill`,
551
+ type: "fill",
552
+ source: sourceId,
553
+ "source-layer": "polygons",
554
+ paint: {
555
+ "fill-opacity": design.fillOpacity * design.fillOpacity * opacity,
556
+ "fill-color": color,
557
+ "fill-outline-color": "transparent"
558
+ }
559
+ })
560
+
561
+ mapLayers.push({
562
+ id: `${sourceId}:polygon-line`,
563
+ type: "line",
564
+ source: sourceId,
565
+ "source-layer": "polygons",
566
+ paint: {
567
+ // Because of https://github.com/mapbox/mapbox-gl-js/issues/4090, line opacities < 1 create artifacts
568
+ "line-color": compileColorToMapbox(design.borderColor || "#000", design.axes.color?.excludedValues),
569
+ "line-opacity": opacity, // 0.5 * opacity,
570
+ "line-width": 1,
571
+ "line-blur": 1.5
572
+ }
573
+ })
574
+
575
+ if (design.displayNames) {
576
+ mapLayers.push({
577
+ id: `${sourceId}:labels`,
578
+ type: "symbol",
579
+ source: sourceId,
580
+ "source-layer": "points",
581
+ layout: {
582
+ "text-field": design.axes.label ? ["get", "label"] : ["get", "name"],
583
+ "text-size": 10
584
+ },
585
+ paint: {
586
+ "text-color": compileColorToMapbox("black", design.axes.color?.excludedValues),
587
+ "text-halo-color": compileColorToMapbox("rgba(255, 255, 255, 0.5)", design.axes.color?.excludedValues),
588
+ "text-halo-width": 2,
589
+ "text-opacity": opacity
590
+ }
591
+ })
592
+ }
593
+
594
+ return {
595
+ ctes: [{ tableName: "regions", jsonql: cteQuery }],
596
+ sourceLayers: [
597
+ { id: "polygons", jsonql: polygonsQuery },
598
+ { id: "points", jsonql: pointsQuery }
599
+ ],
600
+ mapLayers: mapLayers,
601
+ mapLayersHandleClicks: [`${sourceId}:polygon-fill`],
602
+ minZoom: design.minZoom,
603
+ maxZoom: design.maxZoom
604
+ }
605
+ }
606
+
607
+ createDirectVectorTile(
608
+ design: ChoroplethLayerDesign,
609
+ sourceId: string,
610
+ schema: Schema,
611
+ filters: JsonQLFilter[],
612
+ opacity: number
613
+ ): VectorTileDef {
614
+ const axisBuilder = new AxisBuilder({ schema })
615
+ const regionsTable = design.regionsTable || "admin_regions"
616
+
617
+ // Expression of scale and envelope from tile table
618
+ const envelopeExpr: JsonQLScalar = {
619
+ type: "scalar",
620
+ expr: { type: "field", tableAlias: "tile", column: "envelope" },
621
+ from: { type: "table", table: "tile", alias: "tile" }
622
+ }
623
+ const envelopeWithMarginExpr: JsonQLScalar = {
624
+ type: "scalar",
625
+ expr: { type: "field", tableAlias: "tile", column: "envelope_with_margin" },
626
+ from: { type: "table", table: "tile", alias: "tile" }
627
+ }
628
+
629
+ /*
630
+ Returns two source layers, "polygons" and "points". Points are used for labels.
631
+
632
+ polygons:
633
+ select name, ST_AsMVTGeom(shape_simplified, tile.envelope) as the_geom_webmercator from
634
+ admin_regions as regions, tile as tile
635
+ where regions.level0 = 242
636
+ and regions.level = 1
637
+ and shape && tile.envelope_with_margin
638
+
639
+ points:
640
+ select name, ST_AsMVTGeom(
641
+ (select ST_Centroid(polys.geom) from ST_Dump(shape_simplified) as polys order by ST_Area(polys.geom) desc limit 1)
642
+ , tile.envelope) as the_geom_webmercator from
643
+ admin_regions as regions, tile as tile
644
+ where regions.level0 = 242
645
+ and regions.level = 1
646
+ and shape && tile.envelope_with_margin
647
+
648
+ */
649
+
650
+ // Create where
651
+ const where: JsonQLExpr = {
652
+ type: "op",
653
+ op: "and",
654
+ exprs: [
655
+ // Level to display
656
+ {
657
+ type: "op",
658
+ op: "=",
659
+ exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
660
+ },
661
+ // Filter to tile
662
+ {
663
+ type: "op",
664
+ op: "&&",
665
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape" }, envelopeWithMarginExpr]
666
+ }
667
+ ]
668
+ }
669
+
670
+ // Scope overall
671
+ if (design.scope) {
672
+ where.exprs.push({
673
+ type: "op",
674
+ op: "=",
675
+ exprs: [
676
+ { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
677
+ { type: "literal", value: design.scope }
678
+ ]
679
+ })
680
+ }
681
+
682
+ // Add filters on regions to outer query
683
+ for (const filter of filters) {
684
+ if (filter.table == regionsTable) {
685
+ where.exprs.push(injectTableAlias(filter.jsonql, "regions"))
686
+ }
687
+ }
688
+
689
+ const polygonsQuery: JsonQLQuery = {
690
+ type: "query",
691
+ selects: [
692
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
693
+ {
694
+ type: "select",
695
+ expr: {
696
+ type: "op",
697
+ op: "ST_AsMVTGeom",
698
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape_simplified" }, envelopeExpr]
699
+ },
700
+ alias: "the_geom_webmercator"
701
+ },
702
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
703
+ ],
704
+ from: { type: "table", table: regionsTable, alias: "regions" },
705
+ where: where
706
+ }
707
+
708
+ const pointsQuery: JsonQLQuery = {
709
+ type: "query",
710
+ selects: [
711
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
712
+ {
713
+ type: "select",
714
+ expr: {
715
+ type: "op",
716
+ op: "ST_AsMVTGeom",
717
+ exprs: [
718
+ {
719
+ type: "scalar",
720
+ expr: {
721
+ type: "op",
722
+ op: "ST_Centroid",
723
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
724
+ },
725
+ from: {
726
+ type: "subexpr",
727
+ expr: {
728
+ type: "op",
729
+ op: "ST_Dump",
730
+ exprs: [{ type: "field", tableAlias: "regions", column: "shape_simplified" }]
731
+ },
732
+ alias: "polys"
733
+ },
734
+ orderBy: [
735
+ {
736
+ expr: {
737
+ type: "op",
738
+ op: "ST_Area",
739
+ exprs: [{ type: "field", tableAlias: "polys", column: "geom" }]
740
+ },
741
+ direction: "desc"
742
+ }
743
+ ],
744
+ limit: 1
745
+ },
746
+ envelopeExpr
747
+ ]
748
+ },
749
+ alias: "the_geom_webmercator"
750
+ },
751
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
752
+ ],
753
+ from: { type: "table", table: regionsTable, alias: "regions" },
754
+ where: where
755
+ }
756
+
757
+ // Add color select
758
+ if (design.axes.color) {
759
+ const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "regions" })
760
+ pointsQuery.selects.push({ type: "select", expr: colorExpr, alias: "color" })
761
+ polygonsQuery.selects.push({ type: "select", expr: colorExpr, alias: "color" })
762
+ }
763
+
764
+ // Add label select if color axis
765
+ if (design.axes.label) {
766
+ const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "regions" })
767
+ pointsQuery.selects.push({ type: "select", expr: labelExpr, alias: "label" })
768
+ polygonsQuery.selects.push({ type: "select", expr: labelExpr, alias: "label" })
769
+ }
770
+
771
+ // If color axes, add color conditions
772
+ const color = compileColorMapToMapbox(design.axes.color, design.color || "transparent")
773
+
774
+ // Create layers
775
+ const mapLayers: LayerSpecification[] = []
776
+
777
+ mapLayers.push({
778
+ id: `${sourceId}:polygon-fill`,
779
+ type: "fill",
780
+ source: sourceId,
781
+ "source-layer": "polygons",
782
+ paint: {
783
+ "fill-opacity": design.fillOpacity * design.fillOpacity * opacity,
784
+ "fill-color": color,
785
+ "fill-outline-color": "transparent"
786
+ }
787
+ })
788
+
789
+ mapLayers.push({
790
+ id: `${sourceId}:polygon-line`,
791
+ type: "line",
792
+ source: sourceId,
793
+ "source-layer": "polygons",
794
+ paint: {
795
+ // Because of https://github.com/mapbox/mapbox-gl-js/issues/4090, line opacities < 1 create artifacts.
796
+ "line-color": design.borderColor || "#000",
797
+ "line-opacity": opacity, // 0.5 * opacity,
798
+ "line-width": 1,
799
+ "line-blur": 1.5
800
+ }
801
+ })
802
+
803
+ if (design.displayNames) {
804
+ mapLayers.push({
805
+ id: `${sourceId}:labels`,
806
+ type: "symbol",
807
+ source: sourceId,
808
+ "source-layer": "points",
809
+ layout: {
810
+ "text-field": ["get", "name"],
811
+ "text-size": 10
812
+ },
813
+ paint: {
814
+ "text-color": "black",
815
+ "text-halo-color": "rgba(255, 255, 255, 0.5)",
816
+ "text-halo-width": 2,
817
+ "text-opacity": opacity
818
+ }
819
+ })
820
+ }
821
+
822
+ return {
823
+ ctes: [],
824
+ sourceLayers: [
825
+ { id: "polygons", jsonql: polygonsQuery },
826
+ { id: "points", jsonql: pointsQuery }
827
+ ],
828
+ mapLayers: mapLayers,
829
+ mapLayersHandleClicks: [`${sourceId}:polygon-fill`],
830
+ minZoom: design.minZoom,
831
+ maxZoom: design.maxZoom
832
+ }
833
+ }
834
+
835
+ /** Gets the layer definition as JsonQL + CSS in format:
836
+ * {
837
+ * layers: array of { id: layer id, jsonql: jsonql that includes "the_webmercator_geom" as a column }
838
+ * css: carto css
839
+ * interactivity: (optional) { layer: id of layer, fields: array of field names }
840
+ * }
841
+ * arguments:
842
+ * design: design of layer
843
+ * schema: schema to use
844
+ * filters: array of filters to apply
845
+ */
846
+ getJsonQLCss(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): LayerDefinition {
847
+ // Create design
848
+ const layerDef = {
849
+ layers: [{ id: "layer0", jsonql: this.createMapnikJsonQL(design, schema, filters) }],
850
+ css: this.createCss(design, schema, filters),
851
+ interactivity: {
852
+ layer: "layer0",
853
+ fields: ["id", "name"]
854
+ }
855
+ }
856
+
857
+ return layerDef
858
+ }
859
+
860
+ createMapnikJsonQL(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): JsonQLQuery {
861
+ const axisBuilder = new AxisBuilder({ schema })
862
+ const exprCompiler = new ExprCompiler(schema)
863
+
864
+ // Verify that scopeLevel is an integer to prevent injection
865
+ if (design.scopeLevel != null && ![0, 1, 2, 3, 4, 5].includes(design.scopeLevel)) {
866
+ throw new Error("Invalid scope level")
867
+ }
868
+
869
+ // Verify that detailLevel is an integer to prevent injection
870
+ if (![0, 1, 2, 3, 4, 5].includes(design.detailLevel)) {
871
+ throw new Error("Invalid detail level")
872
+ }
873
+
874
+ const regionsTable = design.regionsTable || "admin_regions"
875
+
876
+ if (design.regionMode === "plain") {
877
+ /*
878
+ E.g:
879
+ select name, shape_simplified from
880
+ admin_regions as regions
881
+ where regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
882
+ and regions.level = 2
883
+ */
884
+ const query: JsonQLQuery = {
885
+ type: "query",
886
+ selects: [
887
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
888
+ {
889
+ type: "select",
890
+ expr: { type: "field", tableAlias: "regions", column: "shape_simplified" },
891
+ alias: "the_geom_webmercator"
892
+ },
893
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
894
+ ],
895
+ from: { type: "table", table: regionsTable, alias: "regions" },
896
+ where: {
897
+ type: "op",
898
+ op: "and",
899
+ exprs: [
900
+ // Level to display
901
+ {
902
+ type: "op",
903
+ op: "=",
904
+ exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
905
+ }
906
+ ]
907
+ }
908
+ }
909
+
910
+ // Scope overall
911
+ if (design.scope) {
912
+ ;(query.where as JsonQLOp).exprs.push({
913
+ type: "op",
914
+ op: "=",
915
+ exprs: [
916
+ { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
917
+ { type: "literal", value: design.scope }
918
+ ]
919
+ })
920
+ }
921
+
922
+ // Add filters on regions to outer query
923
+ for (const filter of filters) {
924
+ if (filter.table == regionsTable) {
925
+ ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions"))
926
+ }
927
+ }
928
+
929
+ return query
930
+ }
931
+
932
+ if (design.regionMode === "indirect" || !design.regionMode) {
933
+ /*
934
+ E.g:
935
+ select name, shape_simplified, regions.color from
936
+ admin_regions as regions2
937
+ left outer join
938
+ (
939
+ select admin_regions.level2 as id,
940
+ count(innerquery.*) as color
941
+ from
942
+ admin_regions inner join
943
+ entities.water_point as innerquery
944
+ on innerquery.admin_region = admin_regions._id
945
+ where admin_regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
946
+ group by 1
947
+ ) as regions on regions.id = regions2._id
948
+ where regions2.level = 2 and regions2.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
949
+ */
950
+ const compiledAdminRegionExpr = exprCompiler.compileExpr({
951
+ expr: design.adminRegionExpr || null,
952
+ tableAlias: "innerquery"
953
+ })
954
+
955
+ // Create inner query
956
+ const innerQuery: JsonQLQuery = {
957
+ type: "query",
958
+ selects: [
959
+ {
960
+ type: "select",
961
+ expr: { type: "field", tableAlias: "regions", column: `level${design.detailLevel}` },
962
+ alias: "id"
963
+ }
964
+ ],
965
+ from: {
966
+ type: "join",
967
+ kind: "inner",
968
+ left: { type: "table", table: regionsTable, alias: "regions" },
969
+ right: exprCompiler.compileTable(design.table!, "innerquery"),
970
+ on: {
971
+ type: "op",
972
+ op: "=",
973
+ exprs: [compiledAdminRegionExpr, { type: "field", tableAlias: "regions", column: "_id" }]
974
+ }
975
+ },
976
+ groupBy: [1]
977
+ }
978
+
979
+ // Add color select if color axis
980
+ if (design.axes.color) {
981
+ const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "innerquery" })
982
+ innerQuery.selects.push({ type: "select", expr: colorExpr, alias: "color" })
983
+ }
984
+
985
+ // Add label select if color axis
986
+ if (design.axes.label) {
987
+ const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "innerquery" })
988
+ innerQuery.selects.push({ type: "select", expr: labelExpr, alias: "label" })
989
+ }
990
+
991
+ let whereClauses = []
992
+
993
+ if (design.scope) {
994
+ whereClauses.push({
995
+ type: "op",
996
+ op: "=",
997
+ exprs: [{ type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` }, design.scope]
998
+ })
999
+ }
1000
+
1001
+ // Then add filters
1002
+ if (design.filter) {
1003
+ whereClauses.push(exprCompiler.compileExpr({ expr: design.filter, tableAlias: "innerquery" }))
1004
+ }
1005
+
1006
+ // Then add extra filters passed in, if relevant
1007
+ const relevantFilters = _.where(filters, { table: design.table })
1008
+ for (let filter of relevantFilters) {
1009
+ whereClauses.push(injectTableAlias(filter.jsonql, "innerquery"))
1010
+ }
1011
+
1012
+ whereClauses = _.compact(whereClauses)
1013
+
1014
+ if (whereClauses.length > 0) {
1015
+ innerQuery.where = { type: "op", op: "and", exprs: whereClauses }
1016
+ }
1017
+
1018
+ // Now create outer query
1019
+ const query: JsonQLQuery = {
1020
+ type: "query",
1021
+ selects: [
1022
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "_id" }, alias: "id" },
1023
+ {
1024
+ type: "select",
1025
+ expr: { type: "field", tableAlias: "regions2", column: "shape_simplified" },
1026
+ alias: "the_geom_webmercator"
1027
+ },
1028
+ { type: "select", expr: { type: "field", tableAlias: "regions2", column: "name" }, alias: "name" }
1029
+ ],
1030
+ from: {
1031
+ type: "join",
1032
+ kind: "left",
1033
+ left: { type: "table", table: regionsTable, alias: "regions2" },
1034
+ right: { type: "subquery", query: innerQuery, alias: "regions" },
1035
+ on: {
1036
+ type: "op",
1037
+ op: "=",
1038
+ exprs: [
1039
+ { type: "field", tableAlias: "regions", column: "id" },
1040
+ { type: "field", tableAlias: "regions2", column: "_id" }
1041
+ ]
1042
+ }
1043
+ },
1044
+ where: {
1045
+ type: "op",
1046
+ op: "and",
1047
+ exprs: [
1048
+ // Level to display
1049
+ {
1050
+ type: "op",
1051
+ op: "=",
1052
+ exprs: [{ type: "field", tableAlias: "regions2", column: "level" }, design.detailLevel]
1053
+ }
1054
+ ]
1055
+ }
1056
+ }
1057
+
1058
+ // Scope overall
1059
+ if (design.scope) {
1060
+ ;(query.where as JsonQLOp).exprs.push({
1061
+ type: "op",
1062
+ op: "=",
1063
+ exprs: [
1064
+ { type: "field", tableAlias: "regions2", column: `level${design.scopeLevel || 0}` },
1065
+ { type: "literal", value: design.scope }
1066
+ ]
1067
+ })
1068
+ }
1069
+
1070
+ // Add filters on regions to outer query
1071
+ for (const filter of filters) {
1072
+ if (filter.table == regionsTable) {
1073
+ ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions2"))
1074
+ }
1075
+ }
1076
+
1077
+ // Bubble up color and label
1078
+ if (design.axes.color) {
1079
+ query.selects.push({
1080
+ type: "select",
1081
+ expr: { type: "field", tableAlias: "regions", column: "color" },
1082
+ alias: "color"
1083
+ })
1084
+ }
1085
+
1086
+ // Add label select if color axis
1087
+ if (design.axes.label) {
1088
+ query.selects.push({
1089
+ type: "select",
1090
+ expr: { type: "field", tableAlias: "regions", column: "label" },
1091
+ alias: "label"
1092
+ })
1093
+ }
1094
+
1095
+ return query
1096
+ }
1097
+
1098
+ if (design.regionMode === "direct") {
1099
+ /*
1100
+ E.g:
1101
+ select name, shape_simplified from
1102
+ admin_regions as regions
1103
+ where regions.level0 = 'eb3e12a2-de1e-49a9-8afd-966eb55d47eb'
1104
+ and regions.level = 2
1105
+ */
1106
+ const query: JsonQLQuery = {
1107
+ type: "query",
1108
+ selects: [
1109
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "_id" }, alias: "id" },
1110
+ {
1111
+ type: "select",
1112
+ expr: { type: "field", tableAlias: "regions", column: "shape_simplified" },
1113
+ alias: "the_geom_webmercator"
1114
+ },
1115
+ { type: "select", expr: { type: "field", tableAlias: "regions", column: "name" }, alias: "name" }
1116
+ ],
1117
+ from: { type: "table", table: regionsTable, alias: "regions" },
1118
+ where: {
1119
+ type: "op",
1120
+ op: "and",
1121
+ exprs: [
1122
+ // Level to display
1123
+ {
1124
+ type: "op",
1125
+ op: "=",
1126
+ exprs: [{ type: "field", tableAlias: "regions", column: "level" }, design.detailLevel]
1127
+ }
1128
+ ]
1129
+ }
1130
+ }
1131
+
1132
+ // Add color select
1133
+ if (design.axes.color) {
1134
+ const colorExpr = axisBuilder.compileAxis({ axis: design.axes.color, tableAlias: "regions" })
1135
+ query.selects.push({ type: "select", expr: colorExpr, alias: "color" })
1136
+ }
1137
+
1138
+ // Add label select if color axis
1139
+ if (design.axes.label) {
1140
+ const labelExpr = axisBuilder.compileAxis({ axis: design.axes.label, tableAlias: "regions" })
1141
+ query.selects.push({ type: "select", expr: labelExpr, alias: "label" })
1142
+ }
1143
+
1144
+ // Scope overall
1145
+ if (design.scope) {
1146
+ ;(query.where as JsonQLOp).exprs.push({
1147
+ type: "op",
1148
+ op: "=",
1149
+ exprs: [
1150
+ { type: "field", tableAlias: "regions", column: `level${design.scopeLevel || 0}` },
1151
+ { type: "literal", value: design.scope }
1152
+ ]
1153
+ })
1154
+ }
1155
+
1156
+ // Add filters on regions to outer query
1157
+ for (const filter of filters) {
1158
+ if (filter.table == regionsTable) {
1159
+ ;(query.where as JsonQLOp).exprs.push(injectTableAlias(filter.jsonql, "regions"))
1160
+ }
1161
+ }
1162
+
1163
+ return query
1164
+ }
1165
+
1166
+ throw new Error(`Unsupported regionMode ${design.regionMode}`)
1167
+ }
1168
+
1169
+ createCss(design: ChoroplethLayerDesign, schema: Schema, filters: JsonQLFilter[]): string {
1170
+ let css =
1171
+ `\
1172
+ #layer0 {
1173
+ line-color: ${design.borderColor || "#000"};
1174
+ line-width: 1.5;
1175
+ line-opacity: 0.5;
1176
+ polygon-opacity: ` +
1177
+ design.fillOpacity * design.fillOpacity +
1178
+ `;
1179
+ polygon-fill: ` +
1180
+ (design.color || "transparent") +
1181
+ `;
1182
+ }
1183
+ \
1184
+ `
1185
+
1186
+ if (design.displayNames) {
1187
+ css += `\
1188
+ #layer0::labels {
1189
+ text-name: [name];
1190
+ text-face-name: 'Arial Regular';
1191
+ text-halo-radius: 2;
1192
+ text-halo-opacity: 0.5;
1193
+ text-halo-fill: #FFF;
1194
+ }\
1195
+ `
1196
+ }
1197
+
1198
+ // If color axes, add color conditions
1199
+ if (design.axes.color && design.axes.color.colorMap) {
1200
+ for (let item of design.axes.color.colorMap) {
1201
+ // If invisible
1202
+ if (_.includes(design.axes.color.excludedValues || [], item.value)) {
1203
+ css += `#layer0 [color=${JSON.stringify(
1204
+ item.value
1205
+ )}] { line-color: transparent; polygon-opacity: 0; polygon-fill: transparent; }\n`
1206
+ if (design.displayNames) {
1207
+ css += `#layer0::labels [color=${JSON.stringify(item.value)}] { text-opacity: 0; text-halo-opacity: 0; }\n`
1208
+ }
1209
+ } else {
1210
+ css += `#layer0 [color=${JSON.stringify(item.value)}] { polygon-fill: ${item.color}; }\n`
1211
+ }
1212
+ }
1213
+ }
1214
+
1215
+ return css
1216
+ }
1217
+
1218
+ /**
1219
+ * Called when the interactivity grid is clicked.
1220
+ * arguments:
1221
+ * ev: { data: interactivty data e.g. `{ id: 123 }` }
1222
+ * clickOptions:
1223
+ * design: design of layer
1224
+ * schema: schema to use
1225
+ * dataSource: data source to use
1226
+ * layerDataSource: layer data source
1227
+ * scopeData: current scope data if layer is scoping
1228
+ * filters: compiled filters to apply to the popup
1229
+ *
1230
+ * Returns:
1231
+ * null/undefined
1232
+ * or
1233
+ * {
1234
+ * scope: scope to apply ({ name, filter, data })
1235
+ * row: { tableId:, primaryKey: } # row that was selected
1236
+ * popup: React element to put into a popup
1237
+ */
1238
+ onGridClick(
1239
+ ev: { data: any; event: any },
1240
+ clickOptions: OnGridClickOptions<ChoroplethLayerDesign>
1241
+ ): OnGridClickResults {
1242
+ const regionsTable = clickOptions.design.regionsTable || "admin_regions"
1243
+
1244
+ // Row only if mode is "plain" or "direct"
1245
+ if (clickOptions.design.regionMode == "plain" || clickOptions.design.regionMode == "direct") {
1246
+ if (ev.data && ev.data.id) {
1247
+ return {
1248
+ row: { tableId: regionsTable, primaryKey: ev.data.id }
1249
+ }
1250
+ } else {
1251
+ return null
1252
+ }
1253
+ }
1254
+
1255
+ // Ignore if indirect with no table
1256
+ if (!clickOptions.design.table) {
1257
+ return null
1258
+ }
1259
+
1260
+ // TODO abstract most to base class
1261
+ if (ev.data && ev.data.id) {
1262
+ const results: OnGridClickResults = {
1263
+ row: { tableId: regionsTable, primaryKey: ev.data.id }
1264
+ }
1265
+
1266
+ // Create filter for single row
1267
+ const { table } = clickOptions.design
1268
+
1269
+ // Compile adminRegionExpr
1270
+ const exprCompiler = new ExprCompiler(clickOptions.schema)
1271
+ const filterExpr: Expr = {
1272
+ type: "op",
1273
+ op: "within",
1274
+ table,
1275
+ exprs: [
1276
+ clickOptions.design.adminRegionExpr!,
1277
+ { type: "literal", idTable: regionsTable, valueType: "id", value: ev.data.id }
1278
+ ]
1279
+ }
1280
+
1281
+ const compiledFilterExpr = exprCompiler.compileExpr({ expr: filterExpr, tableAlias: "{alias}" })
1282
+
1283
+ // Filter within
1284
+ const filter = {
1285
+ table,
1286
+ jsonql: compiledFilterExpr
1287
+ }
1288
+
1289
+ if (ev.event.originalEvent.shiftKey) {
1290
+ // Scope to region, unless already scoped
1291
+ if (clickOptions.scopeData === ev.data.id) {
1292
+ results.scope = null
1293
+ } else {
1294
+ results.scope = {
1295
+ name: ev.data.name,
1296
+ filter,
1297
+ filterExpr,
1298
+ data: ev.data.id
1299
+ }
1300
+ }
1301
+ } else if (clickOptions.design.popup) {
1302
+ // Create default popup filter joins
1303
+ const defaultPopupFilterJoins: { [tableId: string]: Expr } = {}
1304
+ if (clickOptions.design.adminRegionExpr) {
1305
+ defaultPopupFilterJoins[clickOptions.design.table] = clickOptions.design.adminRegionExpr
1306
+ }
1307
+
1308
+ // Create filter using popupFilterJoins
1309
+ const popupFilterJoins = clickOptions.design.popupFilterJoins || defaultPopupFilterJoins
1310
+ const popupFilters = PopupFilterJoinsUtils.createPopupFilters(
1311
+ popupFilterJoins,
1312
+ clickOptions.schema,
1313
+ table,
1314
+ ev.data.id,
1315
+ true
1316
+ )
1317
+
1318
+ // Add filter for admin region
1319
+ popupFilters.push({
1320
+ table: regionsTable,
1321
+ jsonql: {
1322
+ type: "op",
1323
+ op: "=",
1324
+ exprs: [
1325
+ { type: "field", tableAlias: "{alias}", column: "_id" },
1326
+ { type: "literal", value: ev.data.id }
1327
+ ]
1328
+ }
1329
+ })
1330
+
1331
+ const BlocksLayoutManager = require("../layouts/blocks/BlocksLayoutManager").default
1332
+ const WidgetFactory = require("../widgets/WidgetFactory").default
1333
+
1334
+ results.popup = new BlocksLayoutManager().renderLayout({
1335
+ items: clickOptions.design.popup.items,
1336
+ style: "popup",
1337
+ renderWidget: (options: any) => {
1338
+ const widget = WidgetFactory.createWidget(options.type)
1339
+
1340
+ // Create filters for single row
1341
+ const filters = clickOptions.filters.concat(popupFilters)
1342
+
1343
+ // Get data source for widget
1344
+ const widgetDataSource = clickOptions.layerDataSource.getPopupWidgetDataSource(
1345
+ clickOptions.design,
1346
+ options.id
1347
+ )
1348
+
1349
+ return widget.createViewElement({
1350
+ schema: clickOptions.schema,
1351
+ dataSource: clickOptions.dataSource,
1352
+ widgetDataSource,
1353
+ design: options.design,
1354
+ scope: null,
1355
+ filters,
1356
+ onScopeChange: null,
1357
+ onDesignChange: null,
1358
+ width: options.width,
1359
+ height: options.height
1360
+ })
1361
+ }
1362
+ })
1363
+ }
1364
+
1365
+ return results
1366
+ } else {
1367
+ return null
1368
+ }
1369
+ }
1370
+
1371
+ // same as onGridClick but handles hover over
1372
+ onGridHoverOver(
1373
+ ev: { data: any; event: any },
1374
+ hoverOptions: OnGridHoverOptions<ChoroplethLayerDesign>
1375
+ ): OnGridHoverResults {
1376
+ const regionsTable = hoverOptions.design.regionsTable || "admin_regions"
1377
+
1378
+ // Row only if mode is "plain" or "direct"
1379
+ if (hoverOptions.design.regionMode == "plain" || hoverOptions.design.regionMode == "direct") {
1380
+ if (!ev.data || !ev.data.id) {
1381
+ return null
1382
+ }
1383
+ }
1384
+
1385
+ // Ignore if indirect with no table
1386
+ if (!hoverOptions.design.table) {
1387
+ return null
1388
+ }
1389
+
1390
+ if (ev.data && ev.data.id) {
1391
+ const { table } = hoverOptions.design
1392
+ const results: OnGridHoverResults = {}
1393
+
1394
+ // Popup
1395
+ if (hoverOptions.design.hoverOver) {
1396
+ // Create default popup filter joins
1397
+ const defaultPopupFilterJoins: { [tableId: string]: Expr } = {}
1398
+ if (hoverOptions.design.adminRegionExpr) {
1399
+ defaultPopupFilterJoins[hoverOptions.design.table] = hoverOptions.design.adminRegionExpr
1400
+ }
1401
+
1402
+ // Create filter using popupFilterJoins
1403
+ const popupFilterJoins = hoverOptions.design.popupFilterJoins || defaultPopupFilterJoins
1404
+ const popupFilters = PopupFilterJoinsUtils.createPopupFilters(
1405
+ popupFilterJoins,
1406
+ hoverOptions.schema,
1407
+ table,
1408
+ ev.data.id,
1409
+ true
1410
+ )
1411
+
1412
+ results.hoverOver = React.createElement(HoverContent, {
1413
+ key: ev.data.id,
1414
+ schema: hoverOptions.schema,
1415
+ dataSource: hoverOptions.dataSource,
1416
+ design: hoverOptions.design,
1417
+ filters: popupFilters
1418
+ })
1419
+ }
1420
+
1421
+ return results
1422
+ } else {
1423
+ return null
1424
+ }
1425
+ }
1426
+
1427
+ // Gets the bounds of the layer as GeoJSON
1428
+ getBounds(
1429
+ design: ChoroplethLayerDesign,
1430
+ schema: Schema,
1431
+ dataSource: DataSource,
1432
+ filters: JsonQLFilter[],
1433
+ callback: any
1434
+ ) {
1435
+ const regionsTable = design.regionsTable || "admin_regions"
1436
+
1437
+ const appliedFilters: JsonQLFilter[] = []
1438
+
1439
+ // If scoped, use that as filter
1440
+ if (design.scope) {
1441
+ appliedFilters.push({
1442
+ table: regionsTable,
1443
+ jsonql: {
1444
+ type: "op",
1445
+ op: "and",
1446
+ exprs: [
1447
+ {
1448
+ type: "op",
1449
+ op: "=",
1450
+ exprs: [{ type: "field", tableAlias: "{alias}", column: `level${design.scopeLevel}` }, design.scope]
1451
+ },
1452
+ {
1453
+ type: "op",
1454
+ op: "=",
1455
+ exprs: [{ type: "field", tableAlias: "{alias}", column: `level` }, design.detailLevel]
1456
+ }
1457
+ ]
1458
+ }
1459
+ })
1460
+ }
1461
+
1462
+ // If regions table is filtered, use that as filter
1463
+ for (const filter of filters) {
1464
+ if (filter.table == regionsTable) {
1465
+ appliedFilters.push(filter)
1466
+ }
1467
+ }
1468
+
1469
+ // Use shape_simplified for speed, as bounds are always approximate
1470
+ return this.getBoundsFromExpr(
1471
+ schema,
1472
+ dataSource,
1473
+ regionsTable,
1474
+ { type: "field", table: regionsTable, column: "shape_simplified" },
1475
+ null,
1476
+ appliedFilters,
1477
+ callback
1478
+ )
1479
+ }
1480
+
1481
+ // Get min and max zoom levels
1482
+ getMinZoom(design: ChoroplethLayerDesign) {
1483
+ return design.minZoom
1484
+ }
1485
+ getMaxZoom(design: ChoroplethLayerDesign) {
1486
+ return design.maxZoom || 21
1487
+ }
1488
+
1489
+ // Get the legend to be optionally displayed on the map. Returns
1490
+ // a React element
1491
+ getLegend(
1492
+ design: ChoroplethLayerDesign,
1493
+ schema: Schema,
1494
+ name: string,
1495
+ dataSource: DataSource,
1496
+ locale: string,
1497
+ filters: JsonQLFilter[]
1498
+ ) {
1499
+ if (filters == null) {
1500
+ filters = []
1501
+ }
1502
+ const _filters = filters.slice()
1503
+ if (design.filter != null) {
1504
+ const exprCompiler = new ExprCompiler(schema)
1505
+ const jsonql = exprCompiler.compileExpr({ expr: design.filter, tableAlias: "{alias}" })
1506
+ const table = (design.filter as OpExpr).table
1507
+ if (jsonql && table) {
1508
+ _filters.push({ table: table, jsonql })
1509
+ }
1510
+ }
1511
+ const axisBuilder = new AxisBuilder({ schema })
1512
+
1513
+ const regionsTable = design.regionsTable || "admin_regions"
1514
+ const axisTable = design.regionMode === "direct" ? regionsTable : design.table
1515
+
1516
+ return React.createElement(LayerLegendComponent, {
1517
+ schema,
1518
+ name,
1519
+ filters: _.compact(_filters),
1520
+ axis:
1521
+ axisBuilder.cleanAxis({
1522
+ axis: design.axes.color || null,
1523
+ table: axisTable,
1524
+ types: ["enum", "text", "boolean", "date"],
1525
+ aggrNeed: design.regionMode == "indirect" ? "required" : "none"
1526
+ }) || undefined,
1527
+ defaultColor: design.color || undefined,
1528
+ locale
1529
+ })
1530
+ }
1531
+
1532
+ // Get a list of table ids that can be filtered on
1533
+ getFilterableTables(design: ChoroplethLayerDesign, schema: Schema): string[] {
1534
+ const filterableTables: string[] = []
1535
+
1536
+ if (design.table) {
1537
+ filterableTables.push(design.table)
1538
+ }
1539
+
1540
+ if (design.regionMode === "direct") {
1541
+ const regionsTable = design.regionsTable || "admin_regions"
1542
+ filterableTables.push(regionsTable)
1543
+ }
1544
+
1545
+ return filterableTables
1546
+ }
1547
+
1548
+ /** True if layer can be edited */
1549
+ isEditable() {
1550
+ return true
1551
+ }
1552
+
1553
+ // Returns a cleaned design
1554
+ cleanDesign(design: ChoroplethLayerDesign, schema: Schema): ChoroplethLayerDesign {
1555
+ const regionsTable = design.regionsTable || "admin_regions"
1556
+ const exprCleaner = new ExprCleaner(schema)
1557
+ const axisBuilder = new AxisBuilder({ schema })
1558
+
1559
+ design = produce(design, draft => {
1560
+ draft.axes = design.axes || {}
1561
+
1562
+ // Default region mode
1563
+ if (!design.regionMode) {
1564
+ draft.regionMode = draft.axes.color ? "indirect" : "plain"
1565
+ }
1566
+
1567
+ // Default color
1568
+ if (draft.regionMode === "plain") {
1569
+ draft.color = design.color || "#FFFFFF"
1570
+ } else {
1571
+ draft.color = "#FFFFFF"
1572
+ }
1573
+
1574
+ if (draft.regionMode === "indirect" && design.table) {
1575
+ draft.adminRegionExpr = exprCleaner.cleanExpr(design.adminRegionExpr || null, {
1576
+ table: design.table,
1577
+ types: ["id"],
1578
+ idTable: regionsTable
1579
+ })
1580
+ } else {
1581
+ delete draft.adminRegionExpr
1582
+ delete draft.table
1583
+ }
1584
+
1585
+ draft.fillOpacity = design.fillOpacity != null ? design.fillOpacity : 0.75
1586
+ draft.displayNames = design.displayNames != null ? design.displayNames : true
1587
+
1588
+ // Clean the axes
1589
+ if (draft.regionMode === "indirect" && design.table) {
1590
+ draft.axes.color = axisBuilder.cleanAxis({
1591
+ axis: draft.axes.color ? original(draft.axes.color) || null : null,
1592
+ table: design.table,
1593
+ types: ["enum", "text", "boolean", "date"],
1594
+ aggrNeed: "required"
1595
+ })
1596
+ draft.axes.label = axisBuilder.cleanAxis({
1597
+ axis: draft.axes.label ? original(draft.axes.label) || null : null,
1598
+ table: design.table,
1599
+ types: ["text", "number"],
1600
+ aggrNeed: "required"
1601
+ })
1602
+ } else if (draft.regionMode === "plain" || (draft.regionMode === "indirect" && !design.table)) {
1603
+ delete draft.axes.color
1604
+ delete draft.axes.label
1605
+ } else if (draft.regionMode === "direct") {
1606
+ draft.axes.color = axisBuilder.cleanAxis({
1607
+ axis: draft.axes.color ? original(draft.axes.color) || null : null,
1608
+ table: regionsTable,
1609
+ types: ["enum", "text", "boolean", "date"],
1610
+ aggrNeed: "none"
1611
+ })
1612
+ draft.axes.label = axisBuilder.cleanAxis({
1613
+ axis: draft.axes.label ? original(draft.axes.label) || null : null,
1614
+ table: regionsTable,
1615
+ types: ["text", "number"],
1616
+ aggrNeed: "none"
1617
+ })
1618
+ }
1619
+
1620
+ // Filter is only for indirect
1621
+ if (draft.regionMode === "indirect" && design.table) {
1622
+ draft.filter = exprCleaner.cleanExpr(design.filter || null, { table: design.table })
1623
+ } else {
1624
+ delete draft.filter
1625
+ }
1626
+
1627
+ if (design.detailLevel == null) {
1628
+ draft.detailLevel = 0
1629
+ }
1630
+ })
1631
+
1632
+ return design
1633
+ }
1634
+
1635
+ // Validates design. Null if ok, message otherwise
1636
+ validateDesign(design: ChoroplethLayerDesign, schema: Schema) {
1637
+ let error
1638
+ const exprUtils = new ExprUtils(schema)
1639
+ const axisBuilder = new AxisBuilder({ schema })
1640
+ const exprValidator = new ExprValidator(schema)
1641
+
1642
+ if (design.regionMode === "indirect") {
1643
+ if (!design.table) {
1644
+ return "Missing table"
1645
+ }
1646
+ if (!design.adminRegionExpr || exprUtils.getExprType(design.adminRegionExpr) !== "id") {
1647
+ return "Missing admin region expr"
1648
+ }
1649
+
1650
+ error = axisBuilder.validateAxis({ axis: design.axes.color || null })
1651
+ if (error) {
1652
+ return error
1653
+ }
1654
+
1655
+ error = axisBuilder.validateAxis({ axis: design.axes.label || null })
1656
+ if (error) {
1657
+ return error
1658
+ }
1659
+
1660
+ // Validate filter
1661
+ error = exprValidator.validateExpr(design.filter || null)
1662
+ if (error) {
1663
+ return error
1664
+ }
1665
+ } else if (design.regionMode === "direct") {
1666
+ error = axisBuilder.validateAxis({ axis: design.axes.color || null })
1667
+ if (error) {
1668
+ return error
1669
+ }
1670
+
1671
+ error = axisBuilder.validateAxis({ axis: design.axes.label || null })
1672
+ if (error) {
1673
+ return error
1674
+ }
1675
+ }
1676
+
1677
+ if (design.detailLevel == null) {
1678
+ return "Missing detail level"
1679
+ }
1680
+
1681
+ return null
1682
+ }
1683
+
1684
+ // Creates a design element with specified options
1685
+ // options:
1686
+ // design: design of layer
1687
+ // schema: schema to use
1688
+ // dataSource: data source to use
1689
+ // onDesignChange: function called when design changes
1690
+ // filters: array of filters
1691
+ createDesignerElement(options: {
1692
+ design: ChoroplethLayerDesign
1693
+ schema: Schema
1694
+ dataSource: DataSource
1695
+ onDesignChange: (design: ChoroplethLayerDesign) => void
1696
+ filters: JsonQLFilter[]
1697
+ }): React.ReactElement<{}> {
1698
+ // Require here to prevent server require problems
1699
+ const ChoroplethLayerDesigner = require("./ChoroplethLayerDesigner").default
1700
+
1701
+ // Clean on way in and out
1702
+ return React.createElement(ChoroplethLayerDesigner, {
1703
+ schema: options.schema,
1704
+ dataSource: options.dataSource,
1705
+ design: this.cleanDesign(options.design, options.schema),
1706
+ filters: options.filters,
1707
+ onDesignChange: (design: ChoroplethLayerDesign) => {
1708
+ return options.onDesignChange(this.cleanDesign(design, options.schema))
1709
+ }
1710
+ })
1711
+ }
1712
+ }