@mwater/visualization 5.5.0 → 5.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/lib/ColorComponent.js +2 -2
  2. package/lib/MWaterContextComponent.d.ts +1 -1
  3. package/lib/MWaterGlobalFiltersComponent.d.ts +2 -2
  4. package/lib/MWaterGlobalFiltersComponent.js +11 -20
  5. package/lib/MWaterLoaderComponent.d.ts +4 -13
  6. package/lib/MWaterLoaderComponent.js +2 -11
  7. package/lib/TranslationsTabComponent.d.ts +34 -0
  8. package/lib/TranslationsTabComponent.js +256 -0
  9. package/lib/UndoStack.d.ts +2 -1
  10. package/lib/UndoStack.js +12 -6
  11. package/lib/dashboards/DashboardComponent.js +6 -5
  12. package/lib/dashboards/DashboardDesign.d.ts +1 -1
  13. package/lib/dashboards/ServerDashboardDataSource.d.ts +0 -1
  14. package/lib/dashboards/ServerDashboardDataSource.js +0 -25
  15. package/lib/dashboards/SettingsModalComponent.js +9 -233
  16. package/lib/datagrids/DatagridComponent.js +27 -2
  17. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -3
  18. package/lib/datagrids/DatagridDesignerComponent.js +108 -120
  19. package/lib/datagrids/DatagridViewComponent.js +33 -6
  20. package/lib/datagrids/OrderBysDesignerComponent.d.ts +7 -7
  21. package/lib/datagrids/OrderBysDesignerComponent.js +19 -28
  22. package/lib/index.css +45 -2
  23. package/lib/index.d.ts +5 -5
  24. package/lib/index.js +2 -3
  25. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +8 -1
  26. package/lib/layouts/blocks/BlocksDisplayComponent.js +46 -4
  27. package/lib/maps/BufferLayer.d.ts +0 -13
  28. package/lib/maps/BufferLayer.js +24 -237
  29. package/lib/maps/BufferLayerDesign.d.ts +1 -1
  30. package/lib/maps/BufferLayerDesignerComponent.d.ts +1 -1
  31. package/lib/maps/BufferLayerDesignerComponent.js +2 -7
  32. package/lib/maps/ChoroplethLayer.d.ts +1 -16
  33. package/lib/maps/ChoroplethLayer.js +25 -358
  34. package/lib/maps/ChoroplethLayerDesign.d.ts +5 -2
  35. package/lib/maps/ChoroplethLayerDesigner.d.ts +10 -32
  36. package/lib/maps/ChoroplethLayerDesigner.js +58 -89
  37. package/lib/maps/ClusterLayer.d.ts +0 -9
  38. package/lib/maps/ClusterLayer.js +0 -250
  39. package/lib/maps/DirectMapDataSource.js +1 -48
  40. package/lib/maps/EditHoverOver.d.ts +4 -3
  41. package/lib/maps/EditHoverOver.js +3 -3
  42. package/lib/maps/GridLayer.d.ts +0 -15
  43. package/lib/maps/GridLayer.js +0 -212
  44. package/lib/maps/HoverContent.js +1 -1
  45. package/lib/maps/Layer.d.ts +1 -26
  46. package/lib/maps/Layer.js +0 -13
  47. package/lib/maps/LeafletMapComponent.js +10 -19
  48. package/lib/maps/MapComponent.d.ts +19 -35
  49. package/lib/maps/MapComponent.js +135 -77
  50. package/lib/maps/MapControlComponent.d.ts +4 -5
  51. package/lib/maps/MapControlComponent.js +5 -12
  52. package/lib/maps/MapDesign.d.ts +8 -0
  53. package/lib/maps/MapDesignerComponent.d.ts +2 -0
  54. package/lib/maps/MapDesignerComponent.js +7 -2
  55. package/lib/maps/MapLayerDataSource.d.ts +0 -4
  56. package/lib/maps/MapLayerViewDesignerComponent.d.ts +3 -1
  57. package/lib/maps/MapLayerViewDesignerComponent.js +5 -1
  58. package/lib/maps/MapLayersDesignerComponent.d.ts +2 -0
  59. package/lib/maps/MapLayersDesignerComponent.js +2 -1
  60. package/lib/maps/MapTranslationsTab.d.ts +15 -0
  61. package/lib/maps/MapTranslationsTab.js +47 -0
  62. package/lib/maps/MapUtils.d.ts +11 -0
  63. package/lib/maps/MapUtils.js +57 -1
  64. package/lib/maps/MapViewComponent.d.ts +1 -1
  65. package/lib/maps/MapViewComponent.js +1 -8
  66. package/lib/maps/MarkersLayer.d.ts +1 -14
  67. package/lib/maps/MarkersLayer.js +89 -254
  68. package/lib/maps/MarkersLayerDesign.d.ts +5 -1
  69. package/lib/maps/MarkersLayerDesignerComponent.d.ts +32 -57
  70. package/lib/maps/MarkersLayerDesignerComponent.js +158 -134
  71. package/lib/maps/ServerMapDataSource.d.ts +0 -1
  72. package/lib/maps/ServerMapDataSource.js +0 -25
  73. package/lib/maps/SwitchableTileUrlLayer.d.ts +0 -2
  74. package/lib/maps/SwitchableTileUrlLayer.js +0 -9
  75. package/lib/maps/TileUrlLayer.d.ts +0 -1
  76. package/lib/maps/TileUrlLayer.js +0 -5
  77. package/lib/maps/VectorMapViewComponent.js +13 -10
  78. package/lib/maps/symbols/font-awesome/asterisk.png +0 -0
  79. package/lib/maps/symbols/font-awesome/ban.png +0 -0
  80. package/lib/maps/symbols/font-awesome/beer.png +0 -0
  81. package/lib/maps/symbols/font-awesome/bell.png +0 -0
  82. package/lib/maps/symbols/font-awesome/bolt.png +0 -0
  83. package/lib/maps/symbols/font-awesome/building.png +0 -0
  84. package/lib/maps/symbols/font-awesome/bullseye.png +0 -0
  85. package/lib/maps/symbols/font-awesome/bus.png +0 -0
  86. package/lib/maps/symbols/font-awesome/caret-up.png +0 -0
  87. package/lib/maps/symbols/font-awesome/certificate.png +0 -0
  88. package/lib/maps/symbols/font-awesome/check-circle.png +0 -0
  89. package/lib/maps/symbols/font-awesome/check.png +0 -0
  90. package/lib/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  91. package/lib/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  92. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  93. package/lib/maps/symbols/font-awesome/cloud.png +0 -0
  94. package/lib/maps/symbols/font-awesome/comment.png +0 -0
  95. package/lib/maps/symbols/font-awesome/crosshairs.png +0 -0
  96. package/lib/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  97. package/lib/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  98. package/lib/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  99. package/lib/maps/symbols/font-awesome/female.png +0 -0
  100. package/lib/maps/symbols/font-awesome/file.png +0 -0
  101. package/lib/maps/symbols/font-awesome/flag.png +0 -0
  102. package/lib/maps/symbols/font-awesome/flask.png +0 -0
  103. package/lib/maps/symbols/font-awesome/h-square.png +0 -0
  104. package/lib/maps/symbols/font-awesome/home.png +0 -0
  105. package/lib/maps/symbols/font-awesome/info-circle.png +0 -0
  106. package/lib/maps/symbols/font-awesome/male.png +0 -0
  107. package/lib/maps/symbols/font-awesome/medkit.png +0 -0
  108. package/lib/maps/symbols/font-awesome/mobile.png +0 -0
  109. package/lib/maps/symbols/font-awesome/plus-circle.png +0 -0
  110. package/lib/maps/symbols/font-awesome/plus-square.png +0 -0
  111. package/lib/maps/symbols/font-awesome/plus.png +0 -0
  112. package/lib/maps/symbols/font-awesome/square.png +0 -0
  113. package/lib/maps/symbols/font-awesome/star.png +0 -0
  114. package/lib/maps/symbols/font-awesome/thumbs-down.png +0 -0
  115. package/lib/maps/symbols/font-awesome/thumbs-up.png +0 -0
  116. package/lib/maps/symbols/font-awesome/ticket.png +0 -0
  117. package/lib/maps/symbols/font-awesome/times-circle.png +0 -0
  118. package/lib/maps/symbols/font-awesome/times.png +0 -0
  119. package/lib/maps/symbols/font-awesome/tint.png +0 -0
  120. package/lib/maps/symbols/font-awesome/tree.png +0 -0
  121. package/lib/maps/symbols/font-awesome/university.png +0 -0
  122. package/lib/maps/symbols/font-awesome/usd.png +0 -0
  123. package/lib/maps/symbols/font-awesome/user.png +0 -0
  124. package/lib/maps/symbols/font-awesome/users.png +0 -0
  125. package/lib/maps/symbols/font-awesome/wheelchair.png +0 -0
  126. package/lib/maps/symbols/sdf-ize.sh +93 -0
  127. package/lib/maps/vectorMaps.d.ts +6 -6
  128. package/lib/maps/vectorMaps.js +33 -45
  129. package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +4 -2
  130. package/lib/mwater_table_selection/IndicatorsListComponent.js +103 -34
  131. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.d.ts +18 -0
  132. package/lib/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.js +80 -0
  133. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +26 -0
  134. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +237 -51
  135. package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +2 -2
  136. package/lib/mwater_table_selection/MWaterTableSelectComponent.js +9 -4
  137. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.d.ts +19 -0
  138. package/lib/mwater_table_selection/MWaterWorkflowsSelectComponent.js +111 -0
  139. package/lib/quickfilter/QuickfiltersComponent.d.ts +3 -102
  140. package/lib/quickfilter/QuickfiltersComponent.js +53 -110
  141. package/lib/quickfilter/TextLiteralComponent.d.ts +23 -47
  142. package/lib/quickfilter/TextLiteralComponent.js +85 -82
  143. package/lib/widgets/MapWidget.js +6 -3
  144. package/lib/widgets/text/ExprItemEditorComponent.d.ts +3 -8
  145. package/lib/widgets/text/ExprItemEditorComponent.js +36 -33
  146. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +1 -0
  147. package/package.json +3 -4
  148. package/src/ColorComponent.tsx +2 -2
  149. package/src/MWaterContextComponent.tsx +1 -1
  150. package/src/{MWaterGlobalFiltersComponent.ts → MWaterGlobalFiltersComponent.tsx} +32 -33
  151. package/src/{MWaterLoaderComponent.ts → MWaterLoaderComponent.tsx} +17 -18
  152. package/src/TranslationsTabComponent.tsx +429 -0
  153. package/src/UndoStack.ts +14 -6
  154. package/src/dashboards/DashboardComponent.tsx +6 -5
  155. package/src/dashboards/DashboardDesign.ts +1 -1
  156. package/src/dashboards/ServerDashboardDataSource.ts +0 -31
  157. package/src/dashboards/SettingsModalComponent.tsx +27 -383
  158. package/src/datagrids/DatagridComponent.tsx +36 -2
  159. package/src/datagrids/DatagridDesignerComponent.tsx +241 -229
  160. package/src/datagrids/DatagridViewComponent.tsx +44 -7
  161. package/src/datagrids/OrderBysDesignerComponent.tsx +61 -70
  162. package/src/index.css +45 -2
  163. package/src/index.ts +5 -11
  164. package/src/layouts/blocks/BlocksDisplayComponent.tsx +60 -5
  165. package/src/maps/BufferLayer.ts +30 -263
  166. package/src/maps/BufferLayerDesign.ts +1 -1
  167. package/src/maps/BufferLayerDesignerComponent.tsx +2 -7
  168. package/src/maps/ChoroplethLayer.ts +30 -394
  169. package/src/maps/ChoroplethLayerDesign.ts +5 -2
  170. package/src/maps/ChoroplethLayerDesigner.tsx +169 -165
  171. package/src/maps/ClusterLayer.ts +0 -274
  172. package/src/maps/DirectMapDataSource.ts +2 -61
  173. package/src/maps/EditHoverOver.tsx +9 -5
  174. package/src/maps/GridLayer.ts +0 -224
  175. package/src/maps/HoverContent.tsx +1 -1
  176. package/src/maps/Layer.ts +1 -35
  177. package/src/maps/LeafletMapComponent.tsx +10 -19
  178. package/src/maps/MapComponent.tsx +448 -0
  179. package/src/maps/MapControlComponent.tsx +41 -0
  180. package/src/maps/MapDesign.ts +6 -0
  181. package/src/maps/MapDesignerComponent.tsx +18 -1
  182. package/src/maps/MapLayerDataSource.ts +0 -5
  183. package/src/maps/MapLayerViewDesignerComponent.ts +9 -2
  184. package/src/maps/MapLayersDesignerComponent.ts +4 -1
  185. package/src/maps/MapTranslationsTab.tsx +53 -0
  186. package/src/maps/MapUtils.ts +61 -1
  187. package/src/maps/MapViewComponent.tsx +2 -8
  188. package/src/maps/MarkersLayer.ts +101 -275
  189. package/src/maps/MarkersLayerDesign.ts +7 -1
  190. package/src/maps/MarkersLayerDesignerComponent.tsx +436 -0
  191. package/src/maps/ServerMapDataSource.ts +0 -31
  192. package/src/maps/SwitchableTileUrlLayer.tsx +0 -11
  193. package/src/maps/TileUrlLayer.tsx +0 -6
  194. package/src/maps/VectorMapViewComponent.tsx +15 -15
  195. package/src/maps/symbols/font-awesome/asterisk.png +0 -0
  196. package/src/maps/symbols/font-awesome/ban.png +0 -0
  197. package/src/maps/symbols/font-awesome/beer.png +0 -0
  198. package/src/maps/symbols/font-awesome/bell.png +0 -0
  199. package/src/maps/symbols/font-awesome/bolt.png +0 -0
  200. package/src/maps/symbols/font-awesome/building.png +0 -0
  201. package/src/maps/symbols/font-awesome/bullseye.png +0 -0
  202. package/src/maps/symbols/font-awesome/bus.png +0 -0
  203. package/src/maps/symbols/font-awesome/caret-up.png +0 -0
  204. package/src/maps/symbols/font-awesome/certificate.png +0 -0
  205. package/src/maps/symbols/font-awesome/check-circle.png +0 -0
  206. package/src/maps/symbols/font-awesome/check.png +0 -0
  207. package/src/maps/symbols/font-awesome/chevron-circle-down.png +0 -0
  208. package/src/maps/symbols/font-awesome/chevron-circle-up.png +0 -0
  209. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  210. package/src/maps/symbols/font-awesome/cloud.png +0 -0
  211. package/src/maps/symbols/font-awesome/comment.png +0 -0
  212. package/src/maps/symbols/font-awesome/crosshairs.png +0 -0
  213. package/src/maps/symbols/font-awesome/dot-circle-o.png +0 -0
  214. package/src/maps/symbols/font-awesome/exclamation-circle.png +0 -0
  215. package/src/maps/symbols/font-awesome/exclamation-triangle.png +0 -0
  216. package/src/maps/symbols/font-awesome/female.png +0 -0
  217. package/src/maps/symbols/font-awesome/file.png +0 -0
  218. package/src/maps/symbols/font-awesome/flag.png +0 -0
  219. package/src/maps/symbols/font-awesome/flask.png +0 -0
  220. package/src/maps/symbols/font-awesome/h-square.png +0 -0
  221. package/src/maps/symbols/font-awesome/home.png +0 -0
  222. package/src/maps/symbols/font-awesome/info-circle.png +0 -0
  223. package/src/maps/symbols/font-awesome/male.png +0 -0
  224. package/src/maps/symbols/font-awesome/medkit.png +0 -0
  225. package/src/maps/symbols/font-awesome/mobile.png +0 -0
  226. package/src/maps/symbols/font-awesome/plus-circle.png +0 -0
  227. package/src/maps/symbols/font-awesome/plus-square.png +0 -0
  228. package/src/maps/symbols/font-awesome/plus.png +0 -0
  229. package/src/maps/symbols/font-awesome/square.png +0 -0
  230. package/src/maps/symbols/font-awesome/star.png +0 -0
  231. package/src/maps/symbols/font-awesome/thumbs-down.png +0 -0
  232. package/src/maps/symbols/font-awesome/thumbs-up.png +0 -0
  233. package/src/maps/symbols/font-awesome/ticket.png +0 -0
  234. package/src/maps/symbols/font-awesome/times-circle.png +0 -0
  235. package/src/maps/symbols/font-awesome/times.png +0 -0
  236. package/src/maps/symbols/font-awesome/tint.png +0 -0
  237. package/src/maps/symbols/font-awesome/tree.png +0 -0
  238. package/src/maps/symbols/font-awesome/university.png +0 -0
  239. package/src/maps/symbols/font-awesome/usd.png +0 -0
  240. package/src/maps/symbols/font-awesome/user.png +0 -0
  241. package/src/maps/symbols/font-awesome/users.png +0 -0
  242. package/src/maps/symbols/font-awesome/wheelchair.png +0 -0
  243. package/src/maps/symbols/sdf-ize.sh +93 -0
  244. package/src/maps/vectorMaps.tsx +32 -53
  245. package/src/mwater_table_selection/IndicatorsListComponent.tsx +165 -37
  246. package/src/mwater_table_selection/MWaterCalculatedDataSourcesListComponent.tsx +111 -0
  247. package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +373 -37
  248. package/src/mwater_table_selection/MWaterTableSelectComponent.tsx +12 -8
  249. package/src/mwater_table_selection/MWaterWorkflowsSelectComponent.tsx +159 -0
  250. package/src/quickfilter/{QuickfiltersComponent.ts → QuickfiltersComponent.tsx} +165 -158
  251. package/src/quickfilter/TextLiteralComponent.tsx +197 -0
  252. package/src/widgets/MapWidget.tsx +11 -1
  253. package/src/widgets/text/ExprItemEditorComponent.tsx +83 -77
  254. package/src/widgets/text/ExprUpdateModalComponent.tsx +1 -0
  255. package/test/UndoStackTests.ts +52 -1
  256. package/.storybook/config.js +0 -7
  257. package/.storybook/head.html +0 -3
  258. package/.storybook/webpack.config.js +0 -15
  259. package/src/maps/BingLayer.ts +0 -146
  260. package/src/maps/MapComponent.ts +0 -312
  261. package/src/maps/MapControlComponent.ts +0 -46
  262. package/src/maps/MarkersLayerDesignerComponent.ts +0 -374
  263. package/src/maps/RasterMapViewComponent.ts +0 -345
  264. package/src/quickfilter/TextLiteralComponent.ts +0 -165
  265. package/stories/UpdateableComponent.js +0 -29
  266. package/stories/consoles.js +0 -202
  267. package/stories/dashboards.js +0 -217
  268. package/stories/datagridDesign.js +0 -114
  269. package/stories/datagrids.js +0 -69
  270. package/stories/dates.js +0 -80
  271. package/stories/exprcomponent.js +0 -43
  272. package/stories/index.js +0 -18
  273. package/stories/leaflet.js +0 -59
  274. package/stories/maps.js +0 -24
  275. package/stories/pivotChart.js +0 -235
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
7
  const react_1 = __importDefault(require("react"));
8
- const R = react_1.default.createElement;
9
8
  const async_1 = __importDefault(require("react-select/async"));
10
9
  const expressions_1 = require("@mwater/expressions");
11
10
  const expressions_2 = require("@mwater/expressions");
@@ -15,114 +14,118 @@ const expressions_2 = require("@mwater/expressions");
15
14
  class TextLiteralComponent extends react_1.default.Component {
16
15
  handleSingleChange = (val) => {
17
16
  const value = val ? val.value || null : null; // Blank is null
18
- return this.props.onChange(value);
17
+ return this.props.onChange?.(value);
19
18
  };
20
19
  handleMultipleChange = (val) => {
21
20
  const value = val ? lodash_1.default.pluck(val, "value") : [];
22
21
  if (value.length > 0) {
23
- return this.props.onChange(value);
22
+ return this.props.onChange?.(value);
24
23
  }
25
24
  else {
26
- return this.props.onChange(null);
25
+ return this.props.onChange?.(null);
27
26
  }
28
27
  };
28
+ /**
29
+ * Load the options for the select. If multiple expressions are supplied, each
30
+ * is queried independently and the union of the results (unique values) is
31
+ * returned.
32
+ */
29
33
  getOptions = (input, cb) => {
30
- // Determine type of expression
31
- const filters = (this.props.filters || []).slice();
32
- const exprUtils = new expressions_2.ExprUtils(this.props.schema);
33
- const exprType = exprUtils.getExprType(this.props.expr);
34
- // Create query to get matches
35
- const exprCompiler = new expressions_1.ExprCompiler(this.props.schema);
36
- if (!this.props.expr.table) {
34
+ // Normalise to array so we can treat single and multiple uniformly
35
+ const exprs = this.props.expr;
36
+ // Keep the unique set of text values that come back from each expression
37
+ const uniqueValues = new Set();
38
+ // Early exit if no expressions
39
+ if (exprs.length === 0) {
40
+ cb([]);
37
41
  return;
38
42
  }
39
- // Add filter for input (simple if just text)
40
- if (exprType === "text") {
41
- if (input) {
42
- filters.push({
43
- table: this.props.expr.table,
44
- jsonql: {
45
- type: "op",
46
- op: "~*",
47
- exprs: [
48
- exprCompiler.compileExpr({ expr: this.props.expr, tableAlias: "{alias}" }),
49
- escapeRegex(input) // Don't use _.escapeRegExp as adds weird backslashes that postgres doesn't like
50
- ]
51
- }
52
- });
43
+ let remaining = exprs.length;
44
+ // Helper that is called after each async query completes
45
+ const maybeFinish = () => {
46
+ remaining -= 1;
47
+ if (remaining === 0) {
48
+ const result = Array.from(uniqueValues).map((value) => ({ value, label: value }));
49
+ cb(result);
53
50
  }
54
- }
55
- else if (exprType === "text[]") {
56
- // Special filter for text[]
57
- if (input) {
58
- filters.push({
59
- table: "values",
60
- jsonql: {
61
- type: "op",
62
- op: "~*",
63
- exprs: [
64
- { type: "field", tableAlias: "{alias}", column: "value" },
65
- "^" + escapeRegex(input) // Don't use _.escapeRegExp as adds weird backslashes that postgres doesn't like
66
- ]
67
- }
68
- });
51
+ };
52
+ // Execute a query for each expression
53
+ for (let i = 0; i < exprs.length; i++) {
54
+ const expr = exprs[i];
55
+ // Clone base filters for this expression so that each expression gets its own copy
56
+ const filters = (this.props.filters || []).slice();
57
+ const exprUtils = new expressions_2.ExprUtils(this.props.schema);
58
+ const exprType = exprUtils.getExprType(expr);
59
+ // Create query to get matches
60
+ const exprCompiler = new expressions_1.ExprCompiler(this.props.schema);
61
+ const exprTable = exprUtils.getExprTable(expr);
62
+ if (!exprTable) {
63
+ maybeFinish();
64
+ return;
69
65
  }
70
- }
71
- else {
72
- return;
73
- }
74
- // Execute query
75
- this.props.quickfiltersDataSource.getValues(this.props.index, this.props.expr, filters, null, 250, (err, values) => {
76
- if (err) {
66
+ // Add filter for the input text depending on expression type
67
+ if (exprType === "text") {
68
+ if (input) {
69
+ filters.push({
70
+ table: exprTable,
71
+ jsonql: {
72
+ type: "op",
73
+ op: "~*",
74
+ exprs: [
75
+ exprCompiler.compileExpr({ expr, tableAlias: "{alias}" }),
76
+ escapeRegex(input) // Avoid _.escapeRegExp to prevent extra backslashes that Postgres dislikes
77
+ ]
78
+ }
79
+ });
80
+ }
81
+ }
82
+ else if (exprType === "text[]") {
83
+ if (input) {
84
+ filters.push({
85
+ table: "values",
86
+ jsonql: {
87
+ type: "op",
88
+ op: "~*",
89
+ exprs: [
90
+ { type: "field", tableAlias: "{alias}", column: "value" },
91
+ "^" + escapeRegex(input) // Avoid _.escapeRegExp to prevent extra backslashes that Postgres dislikes
92
+ ]
93
+ }
94
+ });
95
+ }
96
+ }
97
+ else {
98
+ // Unsupported type – skip this expression
99
+ maybeFinish();
77
100
  return;
78
101
  }
79
- // Filter null and blank
80
- values = lodash_1.default.filter(values, (value) => value);
81
- return cb(lodash_1.default.map(values, (value) => ({
82
- value,
83
- label: value
84
- })));
85
- });
102
+ // Execute the data source query for this expression
103
+ this.props.quickfiltersDataSource.getValues(this.props.index + i, // Index of this quickfilter in the design
104
+ expr, filters, null, 250, (err, values = []) => {
105
+ if (!err && values) {
106
+ // Filter out null / blank and add to unique set
107
+ lodash_1.default.filter(values, (v) => v).forEach((v) => uniqueValues.add(v));
108
+ }
109
+ maybeFinish();
110
+ });
111
+ }
86
112
  };
87
113
  renderSingle() {
88
114
  const currentValue = this.props.value ? { value: this.props.value, label: this.props.value } : null;
89
- return R(async_1.default, {
90
- key: JSON.stringify(this.props.filters), // Include to force a change when filters change
91
- placeholder: T `All`,
92
- value: currentValue,
93
- loadOptions: this.getOptions,
94
- onChange: this.props.onChange ? this.handleSingleChange : undefined,
95
- isClearable: true,
96
- defaultOptions: true,
97
- isDisabled: this.props.onChange == null,
98
- noOptionsMessage: () => T `Type to search`,
99
- styles: {
115
+ return react_1.default.createElement(async_1.default, { key: JSON.stringify(this.props.filters), placeholder: T `All`, value: currentValue, loadOptions: this.getOptions, onChange: this.props.onChange ? this.handleSingleChange : undefined, isClearable: true, defaultOptions: true, isDisabled: this.props.onChange == null, noOptionsMessage: () => T `Type to search`, styles: {
100
116
  // Keep menu above fixed data table headers
101
117
  menu: (style) => lodash_1.default.extend({}, style, { zIndex: 2000 })
102
- }
103
- });
118
+ } });
104
119
  }
105
120
  renderMultiple() {
106
121
  const currentValue = this.props.value ? lodash_1.default.map(this.props.value, (v) => ({ value: v, label: v })) : null;
107
- return R(async_1.default, {
108
- placeholder: T `All`,
109
- value: currentValue,
110
- key: JSON.stringify(this.props.filters), // Include to force a change when filters change
111
- isMulti: true,
112
- loadOptions: this.getOptions,
113
- defaultOptions: true,
114
- onChange: this.props.onChange ? this.handleMultipleChange : undefined,
115
- isClearable: true,
116
- isDisabled: this.props.onChange == null,
117
- noOptionsMessage: () => T `Type to search`,
118
- styles: {
122
+ return react_1.default.createElement(async_1.default, { placeholder: T `All`, value: currentValue, key: JSON.stringify(this.props.filters), isMulti: true, loadOptions: this.getOptions, defaultOptions: true, onChange: this.props.onChange ? this.handleMultipleChange : undefined, isClearable: true, isDisabled: this.props.onChange == null, noOptionsMessage: () => T `Type to search`, styles: {
119
123
  // Keep menu above fixed data table headers
120
124
  menu: (style) => lodash_1.default.extend({}, style, { zIndex: 2000 })
121
- }
122
- });
125
+ } });
123
126
  }
124
127
  render() {
125
- return R("div", { style: { width: "100%" } }, this.props.multi ? this.renderMultiple() : this.renderSingle());
128
+ return react_1.default.createElement("div", { style: { width: "100%" } }, this.props.multi ? this.renderMultiple() : this.renderSingle());
126
129
  }
127
130
  }
128
131
  exports.default = TextLiteralComponent;
@@ -91,7 +91,8 @@ class MapWidgetComponent extends react_1.default.Component {
91
91
  // Require here to prevent server require problems
92
92
  const MapDesignerComponent = require("../maps/MapDesignerComponent").default;
93
93
  // Create editor
94
- const editor = react_1.default.createElement(MapDesignerComponent, { schema: this.props.schema, dataSource: this.props.dataSource, design: this.state.editDesign, onDesignChange: this.handleEditDesignChange, filters: this.props.filters });
94
+ // Note: enableTranslations is false because translations are managed at the dashboard level
95
+ const editor = react_1.default.createElement(MapDesignerComponent, { schema: this.props.schema, dataSource: this.props.dataSource, design: this.state.editDesign, onDesignChange: this.handleEditDesignChange, filters: this.props.filters, enableTranslations: false });
95
96
  // Create map (maxing out at half of width of screen)
96
97
  const width = Math.min(document.body.clientWidth / 2, this.props.width || 0);
97
98
  const height = ((this.props.height || 0) * width) / (this.props.width || 1);
@@ -123,9 +124,11 @@ class MapWidgetComponent extends react_1.default.Component {
123
124
  dropdownItems.push({ label: T `Edit`, icon: "pencil", onClick: this.handleStartEditing });
124
125
  }
125
126
  const handleDesignChange = (d) => this.setState({ transientDesign: d });
127
+ // Only allow single click to edit if there are no layers
128
+ const handleClick = this.props.onDesignChange != null && this.state.editDesign === null && this.props.design.layerViews.length == 0 ? this.handleStartEditing : undefined;
126
129
  // Wrap in a simple widget
127
- return react_1.default.createElement("div", null,
130
+ return (react_1.default.createElement("div", { onClick: handleClick, style: { position: "relative", width: this.props.width } },
128
131
  this.props.onDesignChange != null ? this.renderEditor() : undefined,
129
- react_1.default.createElement(DropdownWidgetComponent_1.default, { width: this.props.width, height: this.props.height, dropdownItems: dropdownItems }, this.renderContent(this.state.transientDesign, handleDesignChange, this.props.width, this.props.height)));
132
+ react_1.default.createElement(DropdownWidgetComponent_1.default, { width: this.props.width, height: this.props.height, dropdownItems: dropdownItems }, this.renderContent(this.state.transientDesign, handleDesignChange, this.props.width, this.props.height))));
130
133
  }
131
134
  }
@@ -10,6 +10,7 @@ export interface ExprItemEditorComponentProps {
10
10
  exprItem: HtmlItemExpr;
11
11
  /** Called with expr item */
12
12
  onChange: (exprItem: HtmlItemExpr) => void;
13
+ /** Optional table that will be filtered to have a single row present. Widget designer should optionally account for this */
13
14
  singleRowTable?: string;
14
15
  }
15
16
  interface ExprItemEditorComponentState {
@@ -22,13 +23,7 @@ export default class ExprItemEditorComponent extends React.Component<ExprItemEdi
22
23
  handleIncludeLabelChange: (value: any) => void;
23
24
  handleLabelTextChange: (ev: any) => void;
24
25
  handleFormatChange: (ev: any) => void;
25
- renderFormat(): React.DetailedReactHTMLElement<{
26
- className: string;
27
- }, HTMLElement> | null;
28
- render(): React.DetailedReactHTMLElement<{
29
- style: {
30
- paddingBottom: number;
31
- };
32
- }, HTMLElement>;
26
+ renderFormat(): React.JSX.Element | null;
27
+ render(): React.JSX.Element;
33
28
  }
34
29
  export {};
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
7
  const react_1 = __importDefault(require("react"));
8
- const R = react_1.default.createElement;
9
8
  const expressions_1 = require("@mwater/expressions");
10
9
  const expressions_ui_1 = require("@mwater/expressions-ui");
11
10
  const expressions_ui_2 = require("@mwater/expressions-ui");
@@ -53,40 +52,44 @@ class ExprItemEditorComponent extends react_1.default.Component {
53
52
  if (!formats) {
54
53
  return null;
55
54
  }
56
- return R("div", { className: "mb-3" }, R("label", { className: "text-muted" }, T `Format`), ": ", R("select", {
57
- value: this.props.exprItem.format != null ? this.props.exprItem.format : (0, valueFormatter_2.getDefaultFormat)(exprType),
58
- className: "form-select",
59
- style: { width: "auto", display: "inline-block" },
60
- onChange: this.handleFormatChange
61
- }, lodash_1.default.map(formats, (format) => R("option", { key: format.value, value: format.value }, format.label))));
55
+ return (react_1.default.createElement("div", { className: "mb-3" },
56
+ react_1.default.createElement("label", { className: "text-muted" }, T `Format`),
57
+ ": ",
58
+ react_1.default.createElement("select", { value: this.props.exprItem.format != null ? this.props.exprItem.format : (0, valueFormatter_2.getDefaultFormat)(exprType), className: "form-select", style: { width: "auto", display: "inline-block" }, onChange: this.handleFormatChange }, lodash_1.default.map(formats, (format) => react_1.default.createElement("option", { key: format.value, value: format.value }, format.label)))));
62
59
  }
63
60
  render() {
64
- return R("div", { style: { paddingBottom: 200 } }, R("div", { className: "mb-3" }, R("label", { className: "text-muted" }, R("i", { className: "fa fa-database" }), " ", T `Data Source`), ": ", R(expressions_ui_2.TableSelectComponent, {
65
- schema: this.props.schema,
66
- value: this.state.table,
67
- onChange: this.handleTableChange
68
- }), R("br")), this.state.table
69
- ? R("div", { className: "mb-3" }, R("label", { className: "text-muted" }, T `Field`), ": ", R(expressions_ui_1.ExprComponent, {
70
- schema: this.props.schema,
71
- dataSource: this.props.dataSource,
72
- table: this.state.table,
73
- types: ["text", "number", "enum", "date", "datetime", "boolean", "enumset", "geometry"],
74
- value: this.props.exprItem.expr,
75
- aggrStatuses: ["individual", "literal", "aggregate"],
76
- onChange: this.handleExprChange
77
- }))
78
- : undefined, this.state.table && this.props.exprItem.expr
79
- ? R("div", { className: "mb-3" }, react_1.default.createElement(bootstrap_1.Checkbox, { key: "includeLabel", value: this.props.exprItem.includeLabel, onChange: this.handleIncludeLabelChange }, T `Include Label`), this.props.exprItem.includeLabel
80
- ? R("input", {
81
- key: "labelText",
82
- className: "form-control",
83
- type: "text",
84
- value: this.props.exprItem.labelText || "",
85
- onChange: this.handleLabelTextChange,
86
- placeholder: new expressions_1.ExprUtils(this.props.schema).summarizeExpr(this.props.exprItem.expr) + ": "
87
- })
88
- : undefined)
89
- : undefined, this.renderFormat());
61
+ const exprValidator = new expressions_1.ExprValidator(this.props.schema);
62
+ const error = exprValidator.validateExpr(this.props.exprItem.expr, {
63
+ table: this.state.table,
64
+ aggrStatuses: ["individual", "literal", "aggregate"]
65
+ });
66
+ return (react_1.default.createElement("div", { style: { paddingBottom: 200 } },
67
+ react_1.default.createElement("div", { className: "mb-3" },
68
+ react_1.default.createElement("label", { className: "text-muted" },
69
+ react_1.default.createElement("i", { className: "fa fa-database" }),
70
+ " ",
71
+ T `Data Source`),
72
+ ": ",
73
+ react_1.default.createElement(expressions_ui_2.TableSelectComponent, { schema: this.props.schema, value: this.state.table, onChange: this.handleTableChange }),
74
+ react_1.default.createElement("br", null)),
75
+ this.state.table
76
+ ? (react_1.default.createElement("div", { className: "mb-3" },
77
+ react_1.default.createElement("label", { className: "text-muted" }, T `Field`),
78
+ ": ",
79
+ react_1.default.createElement(expressions_ui_1.ExprComponent, { schema: this.props.schema, dataSource: this.props.dataSource, table: this.state.table, types: ["text", "number", "enum", "date", "datetime", "boolean", "enumset", "geometry"], value: this.props.exprItem.expr, aggrStatuses: ["individual", "literal", "aggregate"], onChange: this.handleExprChange })))
80
+ : undefined,
81
+ error ? react_1.default.createElement("div", { className: "alert alert-danger" },
82
+ react_1.default.createElement("i", { className: "fa fa-exclamation-circle" }),
83
+ " ",
84
+ error) : undefined,
85
+ this.state.table && this.props.exprItem.expr
86
+ ? (react_1.default.createElement("div", { className: "mb-3" },
87
+ react_1.default.createElement(bootstrap_1.Checkbox, { key: "includeLabel", value: this.props.exprItem.includeLabel, onChange: this.handleIncludeLabelChange }, T `Include Label`),
88
+ this.props.exprItem.includeLabel
89
+ ? react_1.default.createElement("input", { key: "labelText", className: "form-control", type: "text", value: this.props.exprItem.labelText || "", onChange: this.handleLabelTextChange, placeholder: new expressions_1.ExprUtils(this.props.schema).summarizeExpr(this.props.exprItem.expr) + ": " })
90
+ : undefined))
91
+ : undefined,
92
+ this.renderFormat()));
90
93
  }
91
94
  }
92
95
  exports.default = ExprItemEditorComponent;
@@ -6,6 +6,7 @@ export interface ExprUpdateModalComponentProps {
6
6
  schema: Schema;
7
7
  /** Data source to use to get values */
8
8
  dataSource: DataSource;
9
+ /** Optional table that will be filtered to have a single row present. Widget designer should optionally account for this */
9
10
  singleRowTable?: string;
10
11
  }
11
12
  interface ExprUpdateModalComponentState {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mwater/visualization",
3
- "version": "5.5.0",
3
+ "version": "5.6.1",
4
4
  "description": "Visualization library",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -36,7 +36,7 @@
36
36
  "d3-tip": "^0.9.0",
37
37
  "dayjs": "^1.11.10",
38
38
  "dompurify": "^1.0.11",
39
- "ez-localize": "^2.13.0",
39
+ "ez-localize": "^2.15.0",
40
40
  "file-saver": "^2.0.5",
41
41
  "immer": "^8.0.0",
42
42
  "immutable-setter": "^1.1.1",
@@ -45,7 +45,7 @@
45
45
  "leaflet": "^1.8.0",
46
46
  "lodash": "^3.1.0",
47
47
  "lru-cache": "^6.0.0",
48
- "maplibre-gl": "^3.3.1",
48
+ "maplibre-gl": "^5.16.0",
49
49
  "markdown-it": "^12.0.4",
50
50
  "moment": "^2.29.1",
51
51
  "p-queue": "^8.0.1",
@@ -74,7 +74,6 @@
74
74
  "xlsx-js-style": "^1.2.0"
75
75
  },
76
76
  "devDependencies": {
77
- "@kadira/storybook": "^2.21.0",
78
77
  "@types/chai": "^4.3.0",
79
78
  "@types/color": "^3.0.2",
80
79
  "@types/d3": "^5.16.4",
@@ -51,8 +51,8 @@ export default class ColorComponent extends React.Component<ColorComponentProps,
51
51
 
52
52
  const popupPosition: CSSProperties = {
53
53
  position: "fixed",
54
- top: `${rect.bottom + window.scrollY}px`,
55
- left: `${rect.left + window.scrollX}px`,
54
+ top: `${rect.bottom}px`,
55
+ left: `${rect.left}px`,
56
56
  zIndex: 1070,
57
57
  backgroundColor: "white",
58
58
  border: "solid 1px #DDD",
@@ -18,7 +18,7 @@ export interface GlobalFiltersElementFactoryProps {
18
18
  dataSource: DataSource
19
19
  filterableTables: string[]
20
20
  globalFilters?: GlobalFilter[]
21
- onChange: (globalFilters: GlobalFilter[]) => void
21
+ onChange?: (globalFilters: GlobalFilter[]) => void
22
22
 
23
23
  /** If true, return null element if not applicable to filterableTables */
24
24
  nullIfIrrelevant?: boolean
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash"
2
2
  import React from "react"
3
- const R = React.createElement
4
3
 
5
4
  import * as ui from "@mwater/react-library/lib/bootstrap"
6
5
  import { IdLiteralComponent } from "@mwater/expressions-ui"
@@ -14,12 +13,14 @@ export interface MWaterGlobalFiltersComponentProps {
14
13
  dataSource: DataSource
15
14
  filterableTables: string[]
16
15
  globalFilters?: GlobalFilter[]
17
- onChange: (globalFilters: GlobalFilter[]) => void
16
+ onChange?: (globalFilters: GlobalFilter[]) => void
18
17
  }
19
18
 
20
19
  // Control to edit the global filters (_managed_by and admin_region)
21
20
  export default class MWaterGlobalFiltersComponent extends React.Component<MWaterGlobalFiltersComponentProps> {
22
21
  handleRegionsChange = (regions: any) => {
22
+ if (!this.props.onChange) { return }
23
+
23
24
  // Remove existing filter
24
25
  const globalFilters = _.filter(
25
26
  this.props.globalFilters || [],
@@ -40,6 +41,8 @@ export default class MWaterGlobalFiltersComponent extends React.Component<MWater
40
41
  }
41
42
 
42
43
  handleManagedByChange = (managedBy: any) => {
44
+ if (!this.props.onChange) { return }
45
+
43
46
  // Remove existing filter
44
47
  const globalFilters = _.filter(
45
48
  this.props.globalFilters || [],
@@ -80,38 +83,34 @@ export default class MWaterGlobalFiltersComponent extends React.Component<MWater
80
83
  adminRegions = null
81
84
  }
82
85
 
83
- return R(
84
- "div",
85
- null,
86
- R(
87
- ui.FormGroup,
88
- { label: T`Only sites managed by`, labelMuted: true },
89
- R(IdLiteralComponent, {
90
- value: managedBy,
91
- onChange: this.handleManagedByChange,
92
- idTable: "groups",
93
- schema: this.props.schema,
94
- dataSource: this.props.dataSource,
95
- placeholder: T`All Organizations`,
96
- multi: false,
97
- filter: { type: "field", tableAlias: "main", column: "canManageEntities" }
98
- })
99
- ),
86
+ return (
87
+ <div>
88
+ <ui.FormGroup label={T`Only sites managed by`} labelMuted={true}>
89
+ <IdLiteralComponent
90
+ value={managedBy}
91
+ onChange={ this.props.onChange ? this.handleManagedByChange : undefined}
92
+ idTable="groups"
93
+ schema={this.props.schema}
94
+ dataSource={this.props.dataSource}
95
+ placeholder={T`All Organizations`}
96
+ multi={false}
97
+ filter={{ type: "field", tableAlias: "main", column: "canManageEntities" }}
98
+ />
99
+ </ui.FormGroup>
100
100
 
101
- R(
102
- ui.FormGroup,
103
- { label: T`Only sites located in`, labelMuted: true },
104
- R(IdLiteralComponent, {
105
- value: adminRegions,
106
- onChange: this.handleRegionsChange,
107
- idTable: "admin_regions",
108
- schema: this.props.schema,
109
- dataSource: this.props.dataSource,
110
- placeholder: T`All Regions`,
111
- multi: true,
112
- orderBy: [{ expr: { type: "field", tableAlias: "main", column: "level" }, direction: "asc" }]
113
- })
114
- )
101
+ <ui.FormGroup label={T`Only sites located in`} labelMuted={true}>
102
+ <IdLiteralComponent
103
+ value={adminRegions}
104
+ onChange={this.props.onChange ? this.handleRegionsChange : undefined}
105
+ idTable="admin_regions"
106
+ schema={this.props.schema}
107
+ dataSource={this.props.dataSource}
108
+ placeholder={T`All Regions`}
109
+ multi={true}
110
+ orderBy={[{ expr: { type: "field", tableAlias: "main", column: "level" }, direction: "asc" }]}
111
+ />
112
+ </ui.FormGroup>
113
+ </div>
115
114
  )
116
115
  }
117
116
  }
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash"
2
- import React, { ReactElement } from "react"
3
- const R = React.createElement
2
+ import React, { ReactElement, ReactNode } from "react"
4
3
 
5
4
  import { DataSource, Schema } from "@mwater/expressions"
6
5
  import AsyncLoadComponent from "@mwater/react-library/lib/AsyncLoadComponent"
@@ -26,7 +25,7 @@ export interface MWaterLoaderComponentProps {
26
25
  addLayerElementFactory?: AddLayerElementFactory
27
26
  children: (error: any, config?: { schema: Schema; dataSource: DataSource }) => ReactElement<any> | null
28
27
  /** Custom error formatter that returns React node or string, gets passed the error response from server */
29
- errorFormatter?: (data: any, defaultError: string) => string
28
+ errorFormatter?: (data: any, defaultError: ReactNode) => ReactNode
30
29
  /** Origin of usage. e.g. "dashboards:43445364..." */
31
30
  origin?: string
32
31
  }
@@ -110,21 +109,21 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<
110
109
  }
111
110
 
112
111
  // Inject context
113
- return R(
114
- MWaterContextComponent,
115
- {
116
- apiUrl: this.props.apiUrl,
117
- client: this.props.client,
118
- user: this.props.user,
119
- schema: this.state.schema!,
120
- extraTables: this.props.extraTables,
121
- onExtraTablesChange: this.props.onExtraTablesChange,
122
- addLayerElementFactory: this.props.addLayerElementFactory
123
- },
124
- this.props.children(this.state.error, {
125
- schema: this.state.schema!,
126
- dataSource: this.state.dataSource!
127
- })
112
+ return (
113
+ <MWaterContextComponent
114
+ apiUrl={this.props.apiUrl}
115
+ client={this.props.client}
116
+ user={this.props.user}
117
+ schema={this.state.schema!}
118
+ extraTables={this.props.extraTables}
119
+ onExtraTablesChange={this.props.onExtraTablesChange}
120
+ addLayerElementFactory={this.props.addLayerElementFactory}
121
+ >
122
+ {this.props.children(this.state.error, {
123
+ schema: this.state.schema!,
124
+ dataSource: this.state.dataSource!
125
+ })}
126
+ </MWaterContextComponent>
128
127
  )
129
128
  }
130
129
  }