@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,28 +5,37 @@ 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 MapViewComponent_1 = require("./MapViewComponent");
10
9
  const MapDesignerComponent_1 = __importDefault(require("./MapDesignerComponent"));
11
10
  const MapControlComponent_1 = __importDefault(require("./MapControlComponent"));
12
11
  const AutoSizeComponent_1 = __importDefault(require("@mwater/react-library/lib/AutoSizeComponent"));
13
12
  const UndoStack_1 = __importDefault(require("../UndoStack"));
14
13
  const PopoverHelpComponent_1 = __importDefault(require("@mwater/react-library/lib/PopoverHelpComponent"));
14
+ const __1 = require("..");
15
15
  const QuickfilterCompiler_1 = __importDefault(require("../quickfilter/QuickfilterCompiler"));
16
16
  const QuickfiltersComponent_1 = __importDefault(require("../quickfilter/QuickfiltersComponent"));
17
17
  const MapUtils_1 = require("./MapUtils");
18
- const expressions_ui_1 = require("@mwater/expressions-ui");
19
18
  /** Map with designer on right */
20
19
  class MapComponent extends react_1.default.Component {
21
- static contextType = expressions_ui_1.LocaleContext;
22
20
  constructor(props) {
23
21
  super(props);
22
+ // Prefer the T.locale if available when loading the map
23
+ let initialLocale = props.design.locale || "en";
24
+ const otherLocales = props.design.otherLocales || [];
25
+ if (props.preferredLocale && otherLocales.includes(props.preferredLocale)) {
26
+ initialLocale = props.preferredLocale;
27
+ }
28
+ else if (otherLocales.includes(T.locale)) {
29
+ initialLocale = T.locale;
30
+ }
24
31
  this.state = {
25
32
  undoStack: new UndoStack_1.default().push(props.design),
26
33
  transientDesign: props.design, // Temporary design for read-only maps
27
34
  zoomLocked: true,
28
35
  quickfiltersValues: props.quickfiltersValues ?? null,
29
- hideQuickfilters: false
36
+ hideQuickfilters: false,
37
+ locale: initialLocale,
38
+ previewLocale: null
30
39
  };
31
40
  }
32
41
  componentDidUpdate(prevProps) {
@@ -54,39 +63,93 @@ class MapComponent extends react_1.default.Component {
54
63
  handleZoomLockClick = () => {
55
64
  return this.setState({ zoomLocked: !this.state.zoomLocked });
56
65
  };
66
+ /** Handle locale selection from dropdown */
67
+ handleLocaleSelect = (locale) => {
68
+ const baseLocale = this.props.design.locale || "en";
69
+ const isEditing = this.props.onDesignChange != null;
70
+ if (isEditing) {
71
+ // In edit mode, selecting base language exits preview mode
72
+ // Selecting other language enters preview mode
73
+ if (locale === baseLocale) {
74
+ this.setState({ previewLocale: null });
75
+ }
76
+ else {
77
+ this.setState({ previewLocale: locale });
78
+ }
79
+ }
80
+ else {
81
+ // In readonly mode, just change the locale
82
+ this.setState({ locale: locale });
83
+ }
84
+ };
85
+ /** Render the language selector dropdown */
86
+ renderLanguageDropdown() {
87
+ const baseLocale = this.props.design.locale || "en";
88
+ const otherLocales = this.props.design.otherLocales || [];
89
+ const isEditing = this.props.onDesignChange != null;
90
+ const isPreviewMode = isEditing && this.state.previewLocale != null;
91
+ // Determine which locale to display in the dropdown button
92
+ let displayedLocale;
93
+ if (isEditing) {
94
+ displayedLocale = this.state.previewLocale || baseLocale;
95
+ }
96
+ else {
97
+ displayedLocale = this.state.locale;
98
+ }
99
+ return (react_1.default.createElement("div", { key: "translations", className: "dropdown d-inline-block" },
100
+ react_1.default.createElement("a", { className: `btn btn-link btn-sm dropdown-toggle ${isPreviewMode ? "text-info" : ""}`, "data-bs-toggle": "dropdown" },
101
+ react_1.default.createElement("span", { className: "fal fa-globe" }),
102
+ " ",
103
+ __1.languages.find(l => l.code === displayedLocale)?.name || displayedLocale,
104
+ isPreviewMode && react_1.default.createElement("span", { className: "badge bg-info ms-1" }, T `Preview`)),
105
+ react_1.default.createElement("ul", { className: "dropdown-menu dropdown-menu-end" },
106
+ react_1.default.createElement("li", { key: baseLocale },
107
+ react_1.default.createElement("a", { className: `dropdown-item ${displayedLocale === baseLocale ? "active" : ""}`, onClick: () => this.handleLocaleSelect(baseLocale) }, __1.languages.find(l => l.code === baseLocale)?.name || baseLocale)),
108
+ isEditing && otherLocales.length > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
109
+ react_1.default.createElement("li", null,
110
+ react_1.default.createElement("hr", { className: "dropdown-divider" })),
111
+ react_1.default.createElement("li", null,
112
+ react_1.default.createElement("span", { className: "dropdown-header" }, T `Preview translations:`)))),
113
+ otherLocales.filter(loc => loc !== baseLocale).map(locale => react_1.default.createElement("li", { key: locale },
114
+ react_1.default.createElement("a", { className: `dropdown-item ${displayedLocale === locale ? "active" : ""}`, onClick: () => this.handleLocaleSelect(locale) }, __1.languages.find(l => l.code === locale)?.name || locale))))));
115
+ }
57
116
  renderActionLinks() {
58
- return R("div", null, this.props.onDesignChange != null
59
- ? [
60
- R("a", { key: "lock", className: "btn btn-link btn-sm", onClick: this.handleZoomLockClick }, R("span", {
61
- className: `fa ${this.state.zoomLocked ? "fa-lock red" : "fa-unlock green"}`,
62
- style: { marginRight: 5 }
63
- }), R(PopoverHelpComponent_1.default, { placement: "bottom" }, T `Changes to zoom level wont be saved in locked mode`)),
64
- R("a", {
65
- key: "undo",
66
- className: `btn btn-link btn-sm ${!this.state.undoStack.canUndo() ? "disabled" : ""}`,
67
- onClick: this.handleUndo
68
- }, R("span", { className: "fas fa-caret-left" }), R("span", { className: "hide-600px" }, " ", T `Undo`)),
117
+ return (react_1.default.createElement("div", null,
118
+ this.props.onDesignChange != null && [
119
+ react_1.default.createElement("a", { key: "lock", className: "btn btn-link btn-sm", onClick: this.handleZoomLockClick },
120
+ react_1.default.createElement("span", { className: `fa ${this.state.zoomLocked ? "fa-lock red" : "fa-unlock green"}`, style: { marginRight: 5 } }),
121
+ react_1.default.createElement(PopoverHelpComponent_1.default, { placement: "bottom" }, T `Changes to zoom level wont be saved in locked mode`)),
122
+ react_1.default.createElement("a", { key: "undo", className: `btn btn-link btn-sm ${!this.state.undoStack.canUndo() ? "disabled" : ""}`, onClick: this.handleUndo },
123
+ react_1.default.createElement("span", { className: "fas fa-caret-left" }),
124
+ react_1.default.createElement("span", { className: "hide-600px" },
125
+ " ",
126
+ T `Undo`)),
69
127
  " ",
70
- R("a", {
71
- key: "redo",
72
- className: `btn btn-link btn-sm ${!this.state.undoStack.canRedo() ? "disabled" : ""}`,
73
- onClick: this.handleRedo
74
- }, R("span", { className: "fas fa-caret-right" }), R("span", { className: "hide-600px" }, " ", T `Redo`))
75
- ]
76
- : undefined, this.state.hideQuickfilters && this.props.design.quickfilters && this.props.design.quickfilters.length > 0
77
- ? R("a", { key: "showQuickfilters", className: "btn btn-link btn-sm", onClick: this.handleShowQuickfilters }, R("span", { className: "fa fa-filter" }), R("span", { className: "hide-600px" }, " ", T `Show Quickfilters`))
78
- : undefined, this.props.extraTitleButtonsElem, R("a", { key: "toggleDesign", className: "btn btn-link btn-sm", onClick: this.handleToggleDesignPanel, alt: T `Toggle design panel` }, this.getDesign().hideDesignPanel ?
79
- R("span", { className: "fas fa-angle-double-left" })
80
- : R("span", { className: "fas fa-angle-double-right" })));
128
+ react_1.default.createElement("a", { key: "redo", className: `btn btn-link btn-sm ${!this.state.undoStack.canRedo() ? "disabled" : ""}`, onClick: this.handleRedo },
129
+ react_1.default.createElement("span", { className: "fas fa-caret-right" }),
130
+ react_1.default.createElement("span", { className: "hide-600px" },
131
+ " ",
132
+ T `Redo`))
133
+ ],
134
+ this.props.design.otherLocales && this.props.design.otherLocales.length > 0
135
+ ? this.renderLanguageDropdown()
136
+ : undefined,
137
+ this.state.hideQuickfilters && this.props.design.quickfilters && this.props.design.quickfilters.length > 0 && (react_1.default.createElement("a", { key: "showQuickfilters", className: "btn btn-link btn-sm", onClick: this.handleShowQuickfilters },
138
+ react_1.default.createElement("span", { className: "fa fa-filter" }),
139
+ react_1.default.createElement("span", { className: "hide-600px" },
140
+ " ",
141
+ T `Show Quickfilters`))),
142
+ this.props.extraTitleButtonsElem,
143
+ react_1.default.createElement("a", { key: "toggleDesign", className: "btn btn-link btn-sm", onClick: this.handleToggleDesignPanel, title: T `Toggle design panel` }, this.getDesign().hideDesignPanel ? (react_1.default.createElement("span", { className: "fas fa-angle-double-left" })) : (react_1.default.createElement("span", { className: "fas fa-angle-double-right" })))));
81
144
  }
82
145
  renderHeader() {
83
- return R("div", {
84
- style: {
146
+ return (react_1.default.createElement("div", { style: {
85
147
  padding: 4,
86
148
  borderBottom: "solid 1px #e8e8e8",
87
149
  gridArea: "header"
88
- }
89
- }, R("div", { style: { float: "right" } }, this.renderActionLinks()), this.props.titleElem);
150
+ } },
151
+ react_1.default.createElement("div", { style: { float: "right" } }, this.renderActionLinks()),
152
+ this.props.titleElem));
90
153
  }
91
154
  handleDesignChange = (design) => {
92
155
  if (this.props.onDesignChange) {
@@ -115,21 +178,19 @@ class MapComponent extends react_1.default.Component {
115
178
  let filters = this.props.extraFilters || [];
116
179
  // Compile quickfilters
117
180
  filters = filters.concat(new QuickfilterCompiler_1.default(this.props.schema).compile(this.props.design.quickfilters || [], this.state.quickfiltersValues, this.props.quickfilterLocks));
118
- return react_1.default.createElement(AutoSizeComponent_1.default, { injectWidth: true, injectHeight: true }, (size) => {
119
- return react_1.default.createElement(MapViewComponent_1.MapViewComponent, {
120
- mapDataSource: this.props.mapDataSource,
121
- schema: this.props.schema,
122
- dataSource: this.props.dataSource,
123
- design: this.getDesign(),
124
- onDesignChange: this.handleDesignChange,
125
- zoomLocked: this.state.zoomLocked,
126
- onRowClick: this.props.onRowClick,
127
- extraFilters: filters,
128
- locale: this.context,
129
- width: size.width,
130
- height: size.height
131
- });
132
- });
181
+ const isPreviewMode = this.props.onDesignChange != null && this.state.previewLocale != null;
182
+ // Determine display locale:
183
+ // - In preview mode: use previewLocale
184
+ // - In edit mode (no preview): use design locale
185
+ // - In readonly mode: use state locale
186
+ const displayLocale = isPreviewMode
187
+ ? this.state.previewLocale
188
+ : (this.props.onDesignChange != null
189
+ ? this.props.design.locale || "en"
190
+ : this.state.locale);
191
+ return (react_1.default.createElement(AutoSizeComponent_1.default, { injectWidth: true, injectHeight: true }, (size) => {
192
+ return (react_1.default.createElement(MapViewComponent_1.MapViewComponent, { mapDataSource: this.props.mapDataSource, schema: this.props.schema, dataSource: this.props.dataSource, design: this.getDesign(), onDesignChange: isPreviewMode ? undefined : this.handleDesignChange, zoomLocked: this.state.zoomLocked, onRowClick: this.props.onRowClick, extraFilters: filters, locale: displayLocale, width: size.width, height: size.height }));
193
+ }));
133
194
  }
134
195
  // Get filters from props filters combined with maps filters
135
196
  getCompiledFilters() {
@@ -138,49 +199,46 @@ class MapComponent extends react_1.default.Component {
138
199
  return compiledFilters;
139
200
  }
140
201
  renderQuickfilter() {
141
- return R("div", { style: { gridArea: "quickfilters", borderBottom: "solid 1px #e8e8e8" } }, R(QuickfiltersComponent_1.default, {
142
- design: this.props.design.quickfilters || [],
143
- schema: this.props.schema,
144
- dataSource: this.props.dataSource,
145
- quickfiltersDataSource: this.props.mapDataSource.getQuickfiltersDataSource(),
146
- values: this.state.quickfiltersValues || undefined,
147
- onValuesChange: (values) => this.setState({ quickfiltersValues: values }),
148
- locks: this.props.quickfilterLocks,
149
- filters: this.getCompiledFilters(),
150
- hideTopBorder: this.props.hideTitleBar,
151
- onHide: () => this.setState({ hideQuickfilters: true })
152
- }));
202
+ return (react_1.default.createElement("div", { style: { gridArea: "quickfilters", borderBottom: "solid 1px #e8e8e8" } },
203
+ react_1.default.createElement(QuickfiltersComponent_1.default, { design: this.props.design.quickfilters || [], schema: this.props.schema, dataSource: this.props.dataSource, quickfiltersDataSource: this.props.mapDataSource.getQuickfiltersDataSource(), values: this.state.quickfiltersValues || undefined, onValuesChange: (values) => this.setState({ quickfiltersValues: values }), locks: this.props.quickfilterLocks, filters: this.getCompiledFilters(), hideTopBorder: this.props.hideTitleBar, onHide: () => this.setState({ hideQuickfilters: true }) })));
153
204
  }
205
+ /** Translate function to use for display based on current locale */
206
+ translate = (input) => {
207
+ const design = this.getDesign();
208
+ const designLocale = design.locale || "en";
209
+ const isPreviewMode = this.props.onDesignChange != null && this.state.previewLocale != null;
210
+ // Determine display locale:
211
+ // - In preview mode: use previewLocale
212
+ // - In edit mode (no preview): use design locale
213
+ // - In readonly mode: use state locale
214
+ const displayLocale = isPreviewMode
215
+ ? this.state.previewLocale
216
+ : (this.props.onDesignChange != null
217
+ ? designLocale
218
+ : this.state.locale);
219
+ if (designLocale === displayLocale) {
220
+ return input;
221
+ }
222
+ return design.translations?.[displayLocale]?.[input] ?? input;
223
+ };
154
224
  renderDesigner() {
155
- return R("div", { style: { gridArea: "designer", borderLeft: "solid 2px #e8e8e8", overflowY: 'scroll' } }, this.props.onDesignChange ?
156
- react_1.default.createElement(MapDesignerComponent_1.default, {
157
- schema: this.props.schema,
158
- dataSource: this.props.dataSource,
159
- design: this.getDesign(),
160
- onDesignChange: this.handleDesignChange,
161
- enableQuickfilters: this.props.enableQuickfilters
162
- })
163
- :
164
- react_1.default.createElement(MapControlComponent_1.default, {
165
- schema: this.props.schema,
166
- dataSource: this.props.dataSource,
167
- design: this.getDesign(),
168
- onDesignChange: this.handleDesignChange
169
- }));
225
+ const isPreviewMode = this.props.onDesignChange != null && this.state.previewLocale != null;
226
+ return (react_1.default.createElement("div", { style: { gridArea: "designer", borderLeft: "solid 2px #e8e8e8", overflowY: 'scroll' } }, this.props.onDesignChange && !isPreviewMode ? (react_1.default.createElement(MapDesignerComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, design: this.getDesign(), onDesignChange: this.handleDesignChange, enableQuickfilters: this.props.enableQuickfilters })) : (react_1.default.createElement(MapControlComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, design: this.getDesign(), onDesignChange: this.handleDesignChange, translate: this.translate }))));
170
227
  }
171
228
  render() {
172
229
  const designerVisible = !this.getDesign().hideDesignPanel;
173
- console.log("designerVisible", designerVisible);
174
- return R("div", {
175
- style: {
230
+ return (react_1.default.createElement("div", { style: {
176
231
  width: "100%",
177
232
  height: "100%",
178
233
  display: "grid",
179
234
  gridTemplateColumns: designerVisible ? "70% 30%" : "100%",
180
235
  gridTemplateRows: "auto auto 1fr",
181
236
  gridTemplateAreas: `"header designer" "quickfilters designer" "view designer"`
182
- }
183
- }, this.props.hideTitleBar != true ? this.renderHeader() : null, this.state.hideQuickfilters ? null : this.renderQuickfilter(), R("div", { style: { width: "100%", height: "100%", gridArea: "view", overflow: "hidden" } }, this.renderView()), designerVisible ? this.renderDesigner() : null);
237
+ } },
238
+ this.props.hideTitleBar != true ? this.renderHeader() : null,
239
+ this.state.hideQuickfilters ? null : this.renderQuickfilter(),
240
+ react_1.default.createElement("div", { style: { width: "100%", height: "100%", gridArea: "view", overflow: "hidden" } }, this.renderView()),
241
+ designerVisible ? this.renderDesigner() : null));
184
242
  }
185
243
  }
186
244
  exports.default = MapComponent;
@@ -7,11 +7,10 @@ export interface MapControlComponentProps {
7
7
  /** See Map Design.md */
8
8
  design: any;
9
9
  onDesignChange: any;
10
+ /** Translate function to use for display */
11
+ translate?: (input: string) => string;
10
12
  }
13
+ /** Allows controlling readonly map */
11
14
  export default class MapControlComponent extends React.Component<MapControlComponentProps> {
12
- render(): React.DetailedReactHTMLElement<{
13
- style: {
14
- padding: number;
15
- };
16
- }, HTMLElement>;
15
+ render(): React.JSX.Element;
17
16
  }
@@ -4,22 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
- const R = react_1.default.createElement;
8
7
  const MapLayersDesignerComponent_1 = __importDefault(require("./MapLayersDesignerComponent"));
9
8
  const BaseLayerDesignerComponent_1 = __importDefault(require("./BaseLayerDesignerComponent"));
10
- // Allows controlling readonly map
9
+ /** Allows controlling readonly map */
11
10
  class MapControlComponent extends react_1.default.Component {
12
11
  render() {
13
- return R("div", { style: { padding: 5 } }, R(MapLayersDesignerComponent_1.default, {
14
- schema: this.props.schema,
15
- dataSource: this.props.dataSource,
16
- design: this.props.design,
17
- onDesignChange: this.props.onDesignChange,
18
- allowEditingLayers: false
19
- }), R("br"), R("div", { className: "mb-3" }, R("label", { className: "text-muted" }, T `Map Style`), R(BaseLayerDesignerComponent_1.default, {
20
- design: this.props.design,
21
- onDesignChange: this.props.onDesignChange
22
- })));
12
+ return (react_1.default.createElement("div", { style: { padding: 5 } },
13
+ react_1.default.createElement(MapLayersDesignerComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, design: this.props.design, onDesignChange: this.props.onDesignChange, allowEditingLayers: false, translate: this.props.translate }),
14
+ react_1.default.createElement("br", null),
15
+ react_1.default.createElement(BaseLayerDesignerComponent_1.default, { design: this.props.design, onDesignChange: this.props.onDesignChange })));
23
16
  }
24
17
  }
25
18
  exports.default = MapControlComponent;
@@ -35,6 +35,14 @@ export interface MapDesign {
35
35
  initialLegendDisplay?: "open" | "closed" | "closedIfSmall";
36
36
  /** optional locale (e.g. "fr") to use for display */
37
37
  locale?: string;
38
+ /** Other locales that the map is available in. */
39
+ otherLocales?: string[];
40
+ /** Translation map for map. Maps locale to translation map. Does not include default locale. */
41
+ translations?: {
42
+ [locale: string]: {
43
+ [key: string]: string;
44
+ };
45
+ };
38
46
  /** True if design panel is hidden */
39
47
  hideDesignPanel?: boolean;
40
48
  }
@@ -15,6 +15,8 @@ export interface MapDesignerComponentProps {
15
15
  filters?: JsonQLFilter[];
16
16
  /** True to enable quickfilters */
17
17
  enableQuickfilters?: boolean;
18
+ /** True to enable translations tab. Defaults to true. Set to false when map is embedded in a dashboard. */
19
+ enableTranslations?: boolean;
18
20
  }
19
21
  export default class MapDesignerComponent extends React.Component<MapDesignerComponentProps> {
20
22
  handleAttributionChange: (text: string | undefined) => void;
@@ -41,6 +41,7 @@ const ui = __importStar(require("@mwater/react-library/lib/bootstrap"));
41
41
  const QuickfiltersDesignComponent_1 = __importDefault(require("../quickfilter/QuickfiltersDesignComponent"));
42
42
  const immer_1 = __importDefault(require("immer"));
43
43
  const expressions_ui_1 = require("@mwater/expressions-ui");
44
+ const MapTranslationsTab_1 = require("./MapTranslationsTab");
44
45
  class MapDesignerComponent extends react_1.default.Component {
45
46
  handleAttributionChange = (text) => {
46
47
  const design = { ...this.props.design, attribution: text };
@@ -69,7 +70,7 @@ class MapDesignerComponent extends react_1.default.Component {
69
70
  return this.props.onDesignChange(design);
70
71
  };
71
72
  renderOptionsTab() {
72
- return (react_1.default.createElement("div", null,
73
+ return (react_1.default.createElement("div", { style: { marginBottom: 200 } },
73
74
  react_1.default.createElement(BaseLayerDesignerComponent_1.default, { design: this.props.design, onDesignChange: this.props.onDesignChange }),
74
75
  react_1.default.createElement(CheckboxComponent_1.default, { checked: this.props.design.autoBounds, onChange: this.handleAutoBoundsChange },
75
76
  react_1.default.createElement("span", { className: "text-muted" },
@@ -94,7 +95,11 @@ class MapDesignerComponent extends react_1.default.Component {
94
95
  react_1.default.createElement("a", { onClick: this.handleConvertToMarkersMap, className: "btn btn-link btn-sm" }, T `Convert to markers map`))) : undefined,
95
96
  react_1.default.createElement(AttributionComponent, { text: this.props.design.attribution, onTextChange: this.handleAttributionChange }),
96
97
  react_1.default.createElement("br", null),
97
- react_1.default.createElement(AdvancedOptionsComponent, { design: this.props.design, onDesignChange: this.props.onDesignChange })));
98
+ react_1.default.createElement(AdvancedOptionsComponent, { design: this.props.design, onDesignChange: this.props.onDesignChange }),
99
+ this.props.enableTranslations !== false && (react_1.default.createElement(react_1.default.Fragment, null,
100
+ react_1.default.createElement("hr", null),
101
+ react_1.default.createElement("h5", null, T `Translations`),
102
+ react_1.default.createElement(MapTranslationsTab_1.MapTranslationsTab, { schema: this.props.schema, design: this.props.design, onDesignChange: this.props.onDesignChange })))));
98
103
  }
99
104
  render() {
100
105
  const filterableTables = MapUtils.getFilterableTables(this.props.design, this.props.schema);
@@ -6,10 +6,6 @@ export interface MapLayerDataSource {
6
6
  * Called with (design, filters) where design is the design of the layer and filters are filters to apply. Returns URL
7
7
  * Only called on layers that are valid */
8
8
  getTileUrl(design: any, filters: JsonQLFilter[]): string | null;
9
- /** Get the url for the interactivity tiles with the specified filters applied
10
- * Called with (design, filters) where design is the design of the layer and filters are filters to apply. Returns URL
11
- * Only called on layers that are valid */
12
- getUtfGridUrl(design: any, filters: JsonQLFilter[]): string | null;
13
9
  /** Get the url for vector tile source with an expiry time. Only for layers of type "VectorTile"
14
10
  * @param createdAfter ISO 8601 timestamp requiring that tile source on server is created after specified datetime
15
11
  */
@@ -18,12 +18,14 @@ export interface MapLayerViewDesignerComponentProps {
18
18
  connectDropTarget?: any;
19
19
  allowEditingLayer: boolean;
20
20
  filters?: any;
21
+ /** Translate function to use for display */
22
+ translate?: (input: string) => string;
21
23
  }
22
24
  interface MapLayerViewDesignerComponentState {
23
25
  editing: any;
24
26
  }
25
27
  export default class MapLayerViewDesignerComponent extends React.Component<MapLayerViewDesignerComponentProps, MapLayerViewDesignerComponentState> {
26
- constructor(props: any);
28
+ constructor(props: MapLayerViewDesignerComponentProps);
27
29
  update(updates: any): any;
28
30
  handleVisibleClick: () => any;
29
31
  handleHideLegend: (hideLegend: any) => any;
@@ -97,7 +97,11 @@ class MapLayerViewDesignerComponent extends react_1.default.Component {
97
97
  }), R("div", null, R(PopoverHelpComponent_1.default, { placement: "top", key: "help" }, T `Layers in the same group can only be selected one at a time`)));
98
98
  }
99
99
  renderName() {
100
- return R("span", { className: "hover-display-parent", onClick: this.handleRename, style: { cursor: "pointer" } }, this.props.layerView.name, " ", R("span", { className: "hover-display-child fas fa-pencil-alt text-muted" }));
100
+ // Translate the name if a translate function is provided
101
+ const displayName = this.props.translate
102
+ ? this.props.translate(this.props.layerView.name)
103
+ : this.props.layerView.name;
104
+ return R("span", { className: "hover-display-parent", onClick: this.handleRename, style: { cursor: "pointer" } }, displayName, " ", R("span", { className: "hover-display-child fas fa-pencil-alt text-muted" }));
101
105
  }
102
106
  renderEditor() {
103
107
  const layer = LayerFactory_1.default.createLayer(this.props.layerView.type);
@@ -12,6 +12,8 @@ export interface MapLayersDesignerComponentProps {
12
12
  /** True to allow editing layers */
13
13
  allowEditingLayers: boolean;
14
14
  filters?: any;
15
+ /** Translate function to use for display */
16
+ translate?: (input: string) => string;
15
17
  }
16
18
  export default class MapLayersDesignerComponent extends React.Component<MapLayersDesignerComponentProps> {
17
19
  updateDesign(changes: any): void;
@@ -70,7 +70,8 @@ class MapLayersDesignerComponent extends react_1.default.Component {
70
70
  connectDragPreview,
71
71
  connectDropTarget,
72
72
  allowEditingLayer: this.props.allowEditingLayers,
73
- filters: lodash_1.default.compact(filters)
73
+ filters: lodash_1.default.compact(filters),
74
+ translate: this.props.translate
74
75
  }));
75
76
  };
76
77
  render() {
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { Schema } from "@mwater/expressions";
3
+ import { MapDesign } from "./MapDesign";
4
+ export interface MapTranslationsTabProps {
5
+ /** Schema to use */
6
+ schema: Schema;
7
+ /** Map design */
8
+ design: MapDesign;
9
+ /** Called with new design */
10
+ onDesignChange: (design: MapDesign) => void;
11
+ }
12
+ /**
13
+ * Translations tab for map designer that wraps the reusable TranslationsTabComponent
14
+ */
15
+ export declare function MapTranslationsTab(props: MapTranslationsTabProps): React.JSX.Element;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.MapTranslationsTab = MapTranslationsTab;
30
+ const react_1 = __importStar(require("react"));
31
+ const TranslationsTabComponent_1 = require("../TranslationsTabComponent");
32
+ const MapUtils = __importStar(require("./MapUtils"));
33
+ const immer_1 = __importDefault(require("immer"));
34
+ /**
35
+ * Translations tab for map designer that wraps the reusable TranslationsTabComponent
36
+ */
37
+ function MapTranslationsTab(props) {
38
+ const { design, onDesignChange, schema } = props;
39
+ const translatableStrings = (0, react_1.useMemo)(() => MapUtils.getTranslatableStrings(design, schema), [design, schema]);
40
+ return (react_1.default.createElement(TranslationsTabComponent_1.TranslationsTabComponent, { locale: design.locale || "en", otherLocales: design.otherLocales || [], translations: design.translations || {}, translatableStrings: translatableStrings, onLocaleChange: (locale) => onDesignChange((0, immer_1.default)(design, draft => {
41
+ draft.locale = locale;
42
+ })), onOtherLocalesChange: (otherLocales) => onDesignChange((0, immer_1.default)(design, draft => {
43
+ draft.otherLocales = otherLocales;
44
+ })), onTranslationsChange: (translations) => onDesignChange((0, immer_1.default)(design, draft => {
45
+ draft.translations = translations;
46
+ })), downloadFilename: "Map Translations.xlsx", baseLanguageDescription: T `This is the language that the map is written in.` }));
47
+ }
@@ -3,6 +3,7 @@ import { DataSource, Schema } from "@mwater/expressions";
3
3
  import { JsonQLFilter } from "../JsonQLFilter";
4
4
  import { MapDesign } from "./MapDesign";
5
5
  import { HoverOverItem } from "./maps";
6
+ import { Axis } from "../axes/Axis";
6
7
  export interface MapScope {
7
8
  name: string;
8
9
  filter: JsonQLFilter;
@@ -24,6 +25,16 @@ export declare function getCompiledFilters(design: MapDesign, schema: Schema, fi
24
25
  * Get a list of translatable strings in the map design
25
26
  */
26
27
  export declare function getTranslatableStrings(design: MapDesign, schema: Schema): string[];
28
+ /**
29
+ * Get translatable strings from an axis's categoryLabels and nullLabel.
30
+ * Always includes "None" since it's the default label for null values in AxisBuilder.
31
+ */
32
+ export declare function getTranslatableStringsFromAxis(axis: Axis | null | undefined): string[];
33
+ /**
34
+ * Translate an axis's category labels and null label.
35
+ * If no nullLabel is set, translates the default "None" and sets it so AxisBuilder uses it.
36
+ */
37
+ export declare function translateAxis(axis: Axis | null | undefined, translate: (input: string) => string): Axis | null | undefined;
27
38
  /**
28
39
  * Convenience function to get hover over data for a map given an id and a list of hover over items
29
40
  */
@@ -34,10 +34,13 @@ exports.convertToMarkersMap = convertToMarkersMap;
34
34
  exports.getFilterableTables = getFilterableTables;
35
35
  exports.getCompiledFilters = getCompiledFilters;
36
36
  exports.getTranslatableStrings = getTranslatableStrings;
37
+ exports.getTranslatableStringsFromAxis = getTranslatableStringsFromAxis;
38
+ exports.translateAxis = translateAxis;
37
39
  exports.getSimpleHoverOverData = getSimpleHoverOverData;
38
40
  const lodash_1 = __importStar(require("lodash"));
39
41
  const expressions_1 = require("@mwater/expressions");
40
42
  const LayerFactory_1 = __importDefault(require("./LayerFactory"));
43
+ const immer_1 = require("immer");
41
44
  // Check if can convert to a cluster map. Only maps containing marker views can be
42
45
  function canConvertToClusterMap(design) {
43
46
  return lodash_1.default.any(design.layerViews, (lv) => lv.type === "Markers");
@@ -159,25 +162,78 @@ function getTranslatableStrings(design, schema) {
159
162
  // Remove duplicates
160
163
  return lodash_1.default.uniq(strings);
161
164
  }
165
+ /**
166
+ * Get translatable strings from an axis's categoryLabels and nullLabel.
167
+ * Always includes "None" since it's the default label for null values in AxisBuilder.
168
+ */
169
+ function getTranslatableStringsFromAxis(axis) {
170
+ const strings = [];
171
+ if (axis?.categoryLabels) {
172
+ strings.push(...Object.values(axis.categoryLabels));
173
+ }
174
+ if (axis?.nullLabel) {
175
+ strings.push(axis.nullLabel);
176
+ }
177
+ else {
178
+ // Always include "None" as it's the default nullLabel in AxisBuilder
179
+ strings.push("None");
180
+ }
181
+ return strings;
182
+ }
183
+ /**
184
+ * Translate an axis's category labels and null label.
185
+ * If no nullLabel is set, translates the default "None" and sets it so AxisBuilder uses it.
186
+ */
187
+ function translateAxis(axis, translate) {
188
+ if (!axis)
189
+ return axis;
190
+ return (0, immer_1.produce)(axis, draft => {
191
+ if (draft.categoryLabels) {
192
+ for (const key in draft.categoryLabels) {
193
+ draft.categoryLabels[key] = translate(draft.categoryLabels[key]);
194
+ }
195
+ }
196
+ if (draft.nullLabel) {
197
+ draft.nullLabel = translate(draft.nullLabel);
198
+ }
199
+ else {
200
+ // Translate the default "None" and set it so AxisBuilder uses it
201
+ // instead of falling back to T`None` which uses the global locale
202
+ const translatedNone = translate("None");
203
+ if (translatedNone !== "None") {
204
+ draft.nullLabel = translatedNone;
205
+ }
206
+ }
207
+ });
208
+ }
162
209
  /**
163
210
  * Convenience function to get hover over data for a map given an id and a list of hover over items
164
211
  */
165
212
  async function getSimpleHoverOverData(options) {
166
213
  const { id, table, filters, schema, dataSource, hoverOverItems } = options;
214
+ const exprUtils = new expressions_1.ExprUtils(schema);
167
215
  const exprCompiler = new expressions_1.ExprCompiler(schema);
168
216
  const query = {
169
217
  type: "query",
170
218
  selects: [],
171
219
  from: exprCompiler.compileTable(table, "main"),
220
+ groupBy: [],
172
221
  limit: 1
173
222
  };
174
- for (const item of hoverOverItems) {
223
+ // Check if any items are aggregate
224
+ const isAggregate = hoverOverItems.some(item => exprUtils.getExprAggrStatus(item.value ?? null) === "aggregate");
225
+ for (let i = 0; i < hoverOverItems.length; i++) {
226
+ const item = hoverOverItems[i];
175
227
  if (item.value) {
176
228
  query.selects.push({
177
229
  type: "select",
178
230
  expr: exprCompiler.compileExpr({ expr: item.value, tableAlias: "main" }),
179
231
  alias: item.id
180
232
  });
233
+ // Group by if there are aggregate items and this is not aggregate
234
+ if (isAggregate && exprUtils.getExprAggrStatus(item.value) !== "aggregate") {
235
+ query.groupBy.push(i + 1);
236
+ }
181
237
  }
182
238
  }
183
239
  if (filters) {