@mwater/visualization 5.4.0 → 5.4.2

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 (271) hide show
  1. package/lib/ColorComponent.js +2 -1
  2. package/lib/IdSelection.d.ts +16 -0
  3. package/lib/IdSelection.js +59 -0
  4. package/lib/MWaterAddRelatedIndicatorComponent.js +2 -2
  5. package/lib/MWaterCompleteTableSelectComponent.d.ts +3 -8
  6. package/lib/MWaterCompleteTableSelectComponent.js +36 -42
  7. package/lib/MWaterLoaderComponent.d.ts +11 -10
  8. package/lib/MWaterLoaderComponent.js +1 -1
  9. package/lib/MWaterResponsesFilterComponent.js +1 -1
  10. package/lib/MWaterTableSelectComponent.d.ts +0 -1
  11. package/lib/MWaterTableSelectComponent.js +4 -6
  12. package/lib/autotranslate.d.ts +20 -0
  13. package/lib/autotranslate.js +122 -0
  14. package/lib/axes/AxisBuilder.js +3 -3
  15. package/lib/axes/AxisColorEditorComponent.js +4 -0
  16. package/lib/axes/AxisComponent.d.ts +8 -12
  17. package/lib/axes/AxisComponent.js +32 -80
  18. package/lib/axes/CategoryMapComponent.js +4 -4
  19. package/lib/axes/RangesComponent.js +2 -2
  20. package/lib/dashboards/DashboardComponent.d.ts +6 -0
  21. package/lib/dashboards/DashboardComponent.js +44 -12
  22. package/lib/dashboards/DashboardDesign.d.ts +11 -2
  23. package/lib/dashboards/DashboardUtils.d.ts +5 -0
  24. package/lib/dashboards/DashboardUtils.js +30 -0
  25. package/lib/dashboards/DashboardViewComponent.d.ts +2 -0
  26. package/lib/dashboards/DashboardViewComponent.js +16 -3
  27. package/lib/dashboards/ServerDashboardDataSource.js +2 -1
  28. package/lib/dashboards/SettingsModalComponent.d.ts +1 -1
  29. package/lib/dashboards/SettingsModalComponent.js +256 -19
  30. package/lib/dashboards/WidgetComponent.d.ts +6 -3
  31. package/lib/dashboards/WidgetComponent.js +3 -1
  32. package/lib/datagrids/CellEditor.d.ts +19 -0
  33. package/lib/datagrids/CellEditor.js +223 -0
  34. package/lib/datagrids/DatagridComponent.d.ts +18 -87
  35. package/lib/datagrids/DatagridComponent.js +304 -222
  36. package/lib/datagrids/DatagridViewComponent.d.ts +15 -53
  37. package/lib/datagrids/DatagridViewComponent.js +256 -257
  38. package/lib/datagrids/DirectDatagridDataSource.js +2 -3
  39. package/lib/datagrids/ExprCellComponent.d.ts +8 -15
  40. package/lib/datagrids/ExprCellComponent.js +11 -15
  41. package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -6
  42. package/lib/datagrids/FindReplaceModalComponent.js +38 -75
  43. package/lib/index.css +1 -1
  44. package/lib/index.d.ts +0 -1
  45. package/lib/index.js +0 -1
  46. package/lib/layouts/blocks/HorizontalBlockComponent.js +2 -2
  47. package/lib/mWaterLoader.d.ts +1 -1
  48. package/lib/maps/BufferLayer.d.ts +7 -5
  49. package/lib/maps/BufferLayer.js +69 -48
  50. package/lib/maps/BufferLayerDesign.d.ts +21 -14
  51. package/lib/maps/BufferLayerDesignerComponent.d.ts +16 -31
  52. package/lib/maps/BufferLayerDesignerComponent.js +68 -102
  53. package/lib/maps/ChoroplethLayer.d.ts +5 -4
  54. package/lib/maps/ChoroplethLayer.js +32 -9
  55. package/lib/maps/ChoroplethLayerDesign.d.ts +6 -2
  56. package/lib/maps/ChoroplethLayerDesigner.js +4 -2
  57. package/lib/maps/ClusterLayer.d.ts +3 -4
  58. package/lib/maps/ClusterLayer.js +2 -1
  59. package/lib/maps/DetailLevelSelectComponent.js +1 -1
  60. package/lib/maps/DirectMapDataSource.js +2 -1
  61. package/lib/maps/EditPopupComponent.js +5 -3
  62. package/lib/maps/GridLayer.d.ts +3 -4
  63. package/lib/maps/GridLayer.js +2 -1
  64. package/lib/maps/GridLayerDesigner.js +5 -3
  65. package/lib/maps/HoverContent.d.ts +11 -3
  66. package/lib/maps/HoverContent.js +25 -9
  67. package/lib/maps/Layer.d.ts +24 -3
  68. package/lib/maps/Layer.js +5 -1
  69. package/lib/maps/LayerFactory.js +0 -8
  70. package/lib/maps/LayerLegendComponent.js +0 -1
  71. package/lib/maps/LayerSwitcherComponent.d.ts +1 -0
  72. package/lib/maps/LayerSwitcherComponent.js +1 -1
  73. package/lib/maps/LeafletMapComponent.js +3 -1
  74. package/lib/maps/LegendComponent.d.ts +1 -0
  75. package/lib/maps/LegendComponent.js +9 -1
  76. package/lib/maps/MWaterServerLayer.d.ts +2 -2
  77. package/lib/maps/MWaterServerLayer.js +2 -2
  78. package/lib/maps/MapComponent.js +3 -3
  79. package/lib/maps/MapDesign.d.ts +2 -0
  80. package/lib/maps/MapDesignerComponent.d.ts +4 -3
  81. package/lib/maps/MapDesignerComponent.js +68 -74
  82. package/lib/maps/MapLayerViewDesignerComponent.js +2 -2
  83. package/lib/maps/MapUtils.d.ts +4 -0
  84. package/lib/maps/MapUtils.js +19 -0
  85. package/lib/maps/MapViewComponent.d.ts +8 -3
  86. package/lib/maps/MarkersLayer.d.ts +5 -4
  87. package/lib/maps/MarkersLayer.js +33 -7
  88. package/lib/maps/MarkersLayerDesign.d.ts +19 -16
  89. package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -3
  90. package/lib/maps/PopupFilterJoinsUtils.js +0 -6
  91. package/lib/maps/RasterMapViewComponent.d.ts +3 -31
  92. package/lib/maps/RasterMapViewComponent.js +7 -2
  93. package/lib/maps/ServerMapDataSource.js +2 -1
  94. package/lib/maps/SwitchableTileUrlLayer.d.ts +3 -3
  95. package/lib/maps/SwitchableTileUrlLayer.js +2 -1
  96. package/lib/maps/TileUrlLayer.d.ts +4 -5
  97. package/lib/maps/TileUrlLayer.js +2 -1
  98. package/lib/maps/VectorMapViewComponent.d.ts +5 -37
  99. package/lib/maps/VectorMapViewComponent.js +19 -8
  100. package/lib/maps/maps.d.ts +3 -0
  101. package/lib/quickfilter/QuickfiltersComponent.d.ts +2 -0
  102. package/lib/quickfilter/QuickfiltersComponent.js +9 -7
  103. package/lib/quickfilter/QuickfiltersDesignComponent.d.ts +1 -1
  104. package/lib/quickfilter/QuickfiltersDesignComponent.js +19 -35
  105. package/lib/richtext/ExprItemsHtmlConverter.d.ts +5 -2
  106. package/lib/richtext/ExprItemsHtmlConverter.js +4 -4
  107. package/lib/richtext/ExprItemsTranslator.d.ts +5 -0
  108. package/lib/richtext/ExprItemsTranslator.js +149 -0
  109. package/lib/richtext/ItemsHtmlConverter.d.ts +1 -1
  110. package/lib/richtext/ItemsHtmlConverter.js +31 -15
  111. package/lib/wellknown.js +12 -9
  112. package/lib/widgets/IFrameWidget.d.ts +4 -4
  113. package/lib/widgets/ImageWidget.d.ts +7 -4
  114. package/lib/widgets/ImageWidget.js +9 -1
  115. package/lib/widgets/ImageWidgetComponent.d.ts +1 -0
  116. package/lib/widgets/ImageWidgetComponent.js +1 -1
  117. package/lib/widgets/MapWidget.d.ts +5 -48
  118. package/lib/widgets/MapWidget.js +26 -63
  119. package/lib/widgets/MarkdownWidget.d.ts +3 -0
  120. package/lib/widgets/MarkdownWidget.js +3 -0
  121. package/lib/widgets/TOCWidget.d.ts +15 -27
  122. package/lib/widgets/TOCWidget.js +107 -183
  123. package/lib/widgets/Widget.d.ts +18 -7
  124. package/lib/widgets/Widget.js +4 -0
  125. package/lib/widgets/WidgetScopesViewComponent.js +1 -1
  126. package/lib/widgets/charts/Chart.d.ts +10 -1
  127. package/lib/widgets/charts/Chart.js +22 -11
  128. package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
  129. package/lib/widgets/charts/ChartViewComponent.js +6 -3
  130. package/lib/widgets/charts/ChartWidget.d.ts +2 -0
  131. package/lib/widgets/charts/ChartWidget.js +9 -1
  132. package/lib/widgets/charts/ChartWidgetComponent.d.ts +4 -0
  133. package/lib/widgets/charts/ChartWidgetComponent.js +2 -2
  134. package/lib/widgets/charts/calendar/CalendarChart.d.ts +1 -0
  135. package/lib/widgets/charts/calendar/CalendarChart.js +26 -0
  136. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +3 -1
  137. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -0
  138. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +8 -0
  139. package/lib/widgets/charts/layered/LayeredChart.d.ts +2 -0
  140. package/lib/widgets/charts/layered/LayeredChart.js +63 -3
  141. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +1 -1
  142. package/lib/widgets/charts/layered/LayeredChartCompiler.js +3 -3
  143. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +2 -2
  144. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +8 -3
  145. package/lib/widgets/charts/pivot/PivotChart.d.ts +1 -0
  146. package/lib/widgets/charts/pivot/PivotChart.js +63 -0
  147. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +1 -0
  148. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +1 -1
  149. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +6 -0
  150. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +7 -4
  151. package/lib/widgets/charts/table/OrderingsComponent.js +1 -1
  152. package/lib/widgets/charts/table/TableChart.d.ts +1 -0
  153. package/lib/widgets/charts/table/TableChart.js +15 -0
  154. package/lib/widgets/text/TextComponent.d.ts +11 -4
  155. package/lib/widgets/text/TextComponent.js +11 -8
  156. package/lib/widgets/text/TextWidget.d.ts +6 -3
  157. package/lib/widgets/text/TextWidget.js +7 -1
  158. package/lib/widgets/text/TextWidgetComponent.d.ts +4 -0
  159. package/lib/widgets/text/TextWidgetComponent.js +7 -1
  160. package/lib/widgets/text/TextWidgetDesign.d.ts +2 -4
  161. package/lib/widgets/text/TextWidgetDesign.js +1 -1
  162. package/package.json +7 -8
  163. package/src/ColorComponent.tsx +1 -2
  164. package/src/IdSelection.ts +62 -0
  165. package/src/MWaterAddRelatedIndicatorComponent.ts +3 -2
  166. package/src/MWaterCompleteTableSelectComponent.tsx +36 -46
  167. package/src/MWaterLoaderComponent.ts +28 -26
  168. package/src/MWaterResponsesFilterComponent.ts +5 -2
  169. package/src/MWaterTableSelectComponent.tsx +5 -9
  170. package/src/autotranslate.ts +141 -0
  171. package/src/axes/AxisBuilder.ts +3 -3
  172. package/src/axes/AxisColorEditorComponent.tsx +5 -0
  173. package/src/axes/{AxisComponent.ts → AxisComponent.tsx} +106 -106
  174. package/src/axes/CategoryMapComponent.ts +4 -4
  175. package/src/axes/RangesComponent.ts +3 -2
  176. package/src/dashboards/DashboardComponent.tsx +79 -14
  177. package/src/dashboards/DashboardDesign.ts +9 -2
  178. package/src/dashboards/DashboardUtils.ts +39 -0
  179. package/src/dashboards/DashboardViewComponent.tsx +22 -3
  180. package/src/dashboards/ServerDashboardDataSource.ts +2 -1
  181. package/src/dashboards/SettingsModalComponent.tsx +450 -35
  182. package/src/dashboards/WidgetComponent.tsx +12 -6
  183. package/src/datagrids/CellEditor.tsx +354 -0
  184. package/src/datagrids/DatagridComponent.tsx +646 -0
  185. package/src/datagrids/DatagridViewComponent.tsx +539 -0
  186. package/src/datagrids/DirectDatagridDataSource.ts +2 -3
  187. package/src/datagrids/{ExprCellComponent.ts → ExprCellComponent.tsx} +28 -23
  188. package/src/datagrids/{FindReplaceModalComponent.ts → FindReplaceModalComponent.tsx} +109 -122
  189. package/src/index.css +1 -1
  190. package/src/index.ts +0 -1
  191. package/src/layouts/blocks/HorizontalBlockComponent.ts +2 -2
  192. package/src/mWaterLoader.ts +1 -1
  193. package/src/maps/BufferLayer.ts +83 -60
  194. package/src/maps/BufferLayerDesign.ts +20 -14
  195. package/src/maps/BufferLayerDesignerComponent.tsx +309 -0
  196. package/src/maps/ChoroplethLayer.ts +40 -19
  197. package/src/maps/ChoroplethLayerDesign.ts +4 -2
  198. package/src/maps/ChoroplethLayerDesigner.tsx +4 -2
  199. package/src/maps/ClusterLayer.ts +4 -10
  200. package/src/maps/DetailLevelSelectComponent.ts +1 -1
  201. package/src/maps/DirectMapDataSource.ts +2 -1
  202. package/src/maps/EditPopupComponent.ts +7 -3
  203. package/src/maps/GridLayer.ts +4 -10
  204. package/src/maps/GridLayerDesigner.tsx +5 -3
  205. package/src/maps/HoverContent.tsx +40 -16
  206. package/src/maps/Layer.ts +28 -10
  207. package/src/maps/LayerFactory.ts +0 -8
  208. package/src/maps/LayerLegendComponent.ts +2 -4
  209. package/src/maps/LayerSwitcherComponent.tsx +6 -2
  210. package/src/maps/LeafletMapComponent.tsx +3 -1
  211. package/src/maps/LegendComponent.tsx +10 -1
  212. package/src/maps/MWaterServerLayer.ts +3 -3
  213. package/src/maps/MapComponent.ts +3 -3
  214. package/src/maps/MapDesign.ts +3 -0
  215. package/src/maps/MapDesignerComponent.tsx +165 -162
  216. package/src/maps/MapLayerViewDesignerComponent.ts +2 -2
  217. package/src/maps/MapUtils.ts +24 -0
  218. package/src/maps/MapViewComponent.tsx +11 -3
  219. package/src/maps/MarkersLayer.ts +44 -18
  220. package/src/maps/MarkersLayerDesign.ts +19 -16
  221. package/src/maps/PopupFilterJoinsUtils.ts +6 -2
  222. package/src/maps/RasterMapViewComponent.ts +9 -45
  223. package/src/maps/ServerMapDataSource.ts +2 -2
  224. package/src/maps/SwitchableTileUrlLayer.tsx +4 -10
  225. package/src/maps/TileUrlLayer.tsx +4 -10
  226. package/src/maps/VectorMapViewComponent.tsx +28 -55
  227. package/src/maps/maps.ts +3 -0
  228. package/src/quickfilter/QuickfiltersComponent.ts +13 -7
  229. package/src/quickfilter/QuickfiltersDesignComponent.tsx +56 -74
  230. package/src/richtext/ExprItemsHtmlConverter.ts +9 -5
  231. package/src/richtext/ExprItemsTranslator.ts +176 -0
  232. package/src/richtext/ItemsHtmlConverter.ts +33 -18
  233. package/src/wellknown.ts +33 -30
  234. package/src/widgets/ImageWidget.ts +10 -1
  235. package/src/widgets/ImageWidgetComponent.ts +3 -2
  236. package/src/widgets/{MapWidget.ts → MapWidget.tsx} +90 -101
  237. package/src/widgets/MarkdownWidget.ts +3 -0
  238. package/src/widgets/TOCWidget.tsx +281 -0
  239. package/src/widgets/Widget.ts +25 -5
  240. package/src/widgets/WidgetScopesViewComponent.ts +2 -1
  241. package/src/widgets/charts/Chart.ts +31 -12
  242. package/src/widgets/charts/ChartViewComponent.ts +13 -3
  243. package/src/widgets/charts/ChartWidget.ts +11 -1
  244. package/src/widgets/charts/ChartWidgetComponent.tsx +9 -1
  245. package/src/widgets/charts/calendar/CalendarChart.ts +29 -0
  246. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +3 -1
  247. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +9 -0
  248. package/src/widgets/charts/layered/LayeredChart.ts +71 -3
  249. package/src/widgets/charts/layered/LayeredChartCompiler.ts +4 -4
  250. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +4 -2
  251. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +10 -4
  252. package/src/widgets/charts/pivot/PivotChart.ts +73 -0
  253. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +1 -1
  254. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +6 -4
  255. package/src/widgets/charts/table/OrderingsComponent.tsx +2 -1
  256. package/src/widgets/charts/table/TableChart.ts +17 -0
  257. package/src/widgets/text/TextComponent.tsx +22 -12
  258. package/src/widgets/text/TextWidget.ts +9 -2
  259. package/src/widgets/text/TextWidgetComponent.tsx +16 -1
  260. package/src/widgets/text/TextWidgetDesign.ts +4 -7
  261. package/test/IdSelectionTests.ts +54 -0
  262. package/test/LayeredChartCompilerTests.ts +0 -2
  263. package/test/richtext/ExprItemsTranslatorTests.ts +144 -0
  264. package/test/wellknownTests.ts +144 -0
  265. package/src/datagrids/DatagridComponent.ts +0 -478
  266. package/src/datagrids/DatagridViewComponent.ts +0 -464
  267. package/src/datagrids/EditExprCellComponent.tsx +0 -305
  268. package/src/datagrids/README.md +0 -3
  269. package/src/maps/BufferLayerDesignerComponent.ts +0 -311
  270. package/src/widgets/TOCWidget.ts +0 -326
  271. package/test/LegoLayoutEngineTests.ts +0 -69
@@ -1,10 +1,11 @@
1
1
  import _ from "lodash"
2
- import ItemsHtmlConverter, { HtmlItemBase } from "./ItemsHtmlConverter"
2
+ import ItemsHtmlConverter, { HtmlItem, HtmlItemBase } from "./ItemsHtmlConverter"
3
3
  import { Expr, ExprUtils, Schema } from "@mwater/expressions"
4
4
  import uuid from "uuid"
5
5
  import { formatValue } from "../valueFormatter"
6
6
  import { canFormatType } from "../valueFormatter"
7
7
 
8
+ /** Html item that is an expression */
8
9
  export interface HtmlItemExpr extends HtmlItemBase {
9
10
  type: "expr"
10
11
 
@@ -24,6 +25,9 @@ export interface HtmlItemExpr extends HtmlItemBase {
24
25
  format?: string
25
26
  }
26
27
 
28
+ /** Html item that is an expression or a normal item */
29
+ export type HtmlItemOrExpr = HtmlItem | HtmlItemExpr
30
+
27
31
  /**
28
32
  * ItemsHtmlConverter that supports embedded mwater expressions
29
33
  * Converts items (JSON contents of rich text) to HTML and back to allow editing
@@ -66,7 +70,7 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
66
70
  if (this.summarizeExprs) {
67
71
  text = new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale)
68
72
  if (text.length > 30) {
69
- text = text.substr(0, 30) + T`...`
73
+ text = text.substr(0, 30) + `...`
70
74
  }
71
75
 
72
76
  exprHtml = _.escape(text)
@@ -88,7 +92,7 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
88
92
 
89
93
  exprHtml = _.escape(text)
90
94
  } else {
91
- exprHtml = `<span style="color: #DDD">${T`---`}</span>`
95
+ exprHtml = `<span style="color: #DDD">${`---`}</span>`
92
96
  }
93
97
  } else {
94
98
  // Placeholder
@@ -97,14 +101,14 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
97
101
 
98
102
  // Add label
99
103
  if (exprItem.includeLabel) {
100
- const label = exprItem.labelText || new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale) + T`:\u00A0`
104
+ const label = exprItem.labelText || new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale) + `:\u00A0`
101
105
  exprHtml = `<span class="text-muted">${_.escape(label)}</span>` + exprHtml
102
106
  }
103
107
 
104
108
  if (this.designMode) {
105
109
  html +=
106
110
  `\u2060<span data-embed="${_.escape(JSON.stringify(item))}" class="mwater-visualization-text-widget-expr">` +
107
- (exprHtml || T`\u00A0`) +
111
+ (exprHtml || `\u00A0`) +
108
112
  `</span>\u2060`
109
113
  } else {
110
114
  // View mode
@@ -0,0 +1,176 @@
1
+ import _ from "lodash"
2
+ import { HtmlItemExpr, HtmlItemOrExpr } from "./ExprItemsHtmlConverter"
3
+ import { produce } from "immer"
4
+ import ItemsHtmlConverter, { HtmlItem, HtmlItemBase, HtmlItemElement } from "./ItemsHtmlConverter"
5
+
6
+ /** Gets all unique strings from html items */
7
+ export function getHtmlItemsStrings(items: HtmlItemOrExpr[]): string[] {
8
+ const strings = new Set<string>()
9
+
10
+ // Create collector function that just saves strings and returns them unchanged
11
+ const collectStrings = (str: string) => {
12
+ // Only collect non-empty strings
13
+ if (str) {
14
+ strings.add(str)
15
+ }
16
+ return str
17
+ }
18
+
19
+ // Use existing translation function but with collector
20
+ translateHtmlItems(items, collectStrings)
21
+
22
+ return Array.from(strings)
23
+ }
24
+
25
+ /** Translates items in an html items list with expressions */
26
+ export function translateHtmlItems(items: HtmlItemOrExpr[], translate: (input: string) => string): HtmlItemOrExpr[] {
27
+ return produce(items, draft => {
28
+ function translateItems(itemList: HtmlItemOrExpr[]) {
29
+ // Accumulate simple items
30
+ let simpleItems: HtmlItemOrExpr[] = []
31
+ let simpleItemStartIndex: number | null = null
32
+
33
+ /** Process accumulated simple nodes which are simple inline elements */
34
+ function processSimpleNodes() {
35
+ if (simpleItems.length === 0) {
36
+ return
37
+ }
38
+
39
+ // Create html string with {0}, {1}, etc. for expressions and html for other items
40
+ const expressions: HtmlItemExpr[] = []
41
+
42
+ const converter = new TranslationItemsHtmlConverter(item => {
43
+ if (item.type === "expr") {
44
+ const expr = item as HtmlItemExpr
45
+ if (expr.labelText) {
46
+ expr.labelText = translate(expr.labelText)
47
+ }
48
+ expressions.push(expr)
49
+ return `{${expressions.length - 1}}`
50
+ }
51
+ return ""
52
+ })
53
+
54
+ // Convert items to html which has the side effect of translating expressions
55
+ let html = converter.convertItemsToHtml(simpleItems)
56
+
57
+ // If there was no text, do nothing except translate expressions
58
+ if (!simpleItems.some(doesItemContainText)) {
59
+ return
60
+ }
61
+
62
+ // Remove leading and trailing whitespace from the HTML
63
+ const leftWhitespace = html.slice(0, html.length - html.trimStart().length)
64
+ const rightWhitespace = html.slice(html.trimEnd().length)
65
+ html = html.trim()
66
+
67
+ if (!html) {
68
+ return
69
+ }
70
+
71
+ let translatedHtml = leftWhitespace + translate(html) + rightWhitespace
72
+
73
+ // Parse translatedHtml into items by first replacing {0}, {1}, etc. with html that can be converted to items
74
+ for (let i = 0; i < expressions.length; i++) {
75
+ const expr = expressions[i]
76
+ translatedHtml = translatedHtml.replace(new RegExp(`\\{${i}\\}`, "g"), `<span data-embed="${_.escape(JSON.stringify(expr))}"></span>`)
77
+ }
78
+
79
+ // Wrap in a div to prevent whitespace from being trimmed.
80
+ const translatedItems = (converter.convertElemToItems(new DOMParser().parseFromString("<div>" + translatedHtml + "</div>", "text/html").body.firstChild as HTMLElement))
81
+
82
+ // Replace the simple items with the translated items
83
+ itemList.splice(simpleItemStartIndex!, simpleItems.length, ...translatedItems)
84
+
85
+ simpleItems = []
86
+ simpleItemStartIndex = null
87
+ }
88
+
89
+ for (let i = 0; i < itemList.length; i++) {
90
+ const item = itemList[i]
91
+
92
+ // If the child is a simple node, add it to the list
93
+ if (isItemSimple(item)) {
94
+ simpleItems.push(item)
95
+ if (simpleItemStartIndex == null) {
96
+ simpleItemStartIndex = i
97
+ }
98
+ } else {
99
+ // If we have gathered simple nodes, we need to return/replace them
100
+ processSimpleNodes()
101
+ simpleItemStartIndex = null
102
+ simpleItems = []
103
+
104
+ // Handle the current node
105
+ if (typeof item !== "string" && item.type === "element" && item.items) {
106
+ translateItems(item.items)
107
+ }
108
+ }
109
+ }
110
+
111
+ if (simpleItems.length > 0) {
112
+ processSimpleNodes()
113
+ simpleItemStartIndex = null
114
+ simpleItems = []
115
+ }
116
+ }
117
+
118
+ translateItems(draft)
119
+ })
120
+ }
121
+
122
+ /** ItemsHtmlConverter that has a callback for handling special items */
123
+ class TranslationItemsHtmlConverter extends ItemsHtmlConverter {
124
+ handleSpecialItem: (item: HtmlItemBase) => string
125
+
126
+ constructor(handleSpecialItem: (item: HtmlItemBase) => string) {
127
+ super()
128
+ this.handleSpecialItem = handleSpecialItem
129
+ }
130
+
131
+ convertSpecialItemToHtml(item: HtmlItemBase) {
132
+ return this.handleSpecialItem(item)
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Check if an html item is simple.
138
+ * A node is simple if it is:
139
+ * - a string
140
+ * - a tag that is a "b", "i", "u", "a", "strong", "em" tag with no children or only simple children
141
+ * Only sequences of simple nodes are exported to translation entries as HTML.
142
+ */
143
+ function isItemSimple(node: HtmlItemOrExpr): boolean {
144
+ if (typeof node === "string") {
145
+ return true
146
+ }
147
+
148
+ if (node.type === "expr") {
149
+ return true
150
+ }
151
+
152
+ if (node.type === "element") {
153
+ const element = node as HtmlItemElement
154
+
155
+ if (["b", "i", "u", "a", "strong", "em"].indexOf(element.tag) === -1) {
156
+ return false
157
+ }
158
+
159
+ return (element.items || []).every(child => isItemSimple(child))
160
+ }
161
+
162
+ return false
163
+ }
164
+
165
+ /** Determines if an item contains any non-empty text strings */
166
+ function doesItemContainText(item: HtmlItemOrExpr): boolean {
167
+ if (typeof item === "string") {
168
+ return item.trim().length > 0
169
+ }
170
+
171
+ if (item.type === "element") {
172
+ return (item.items || []).some(child => doesItemContainText(child))
173
+ }
174
+
175
+ return false
176
+ }
@@ -47,7 +47,7 @@ export default class ItemsHtmlConverter {
47
47
  }
48
48
 
49
49
  // Converts list of items to html
50
- convertItemsToHtml(items: any) {
50
+ convertItemsToHtml(items: HtmlItem[]) {
51
51
  let html = ""
52
52
 
53
53
  for (let item of items || []) {
@@ -66,19 +66,20 @@ export default class ItemsHtmlConverter {
66
66
  // Escape HTML
67
67
  html += _.escape(itemStr)
68
68
  } else if (item.type === "element") {
69
- if (!allowedTags[item.tag]) {
69
+ const element = item as HtmlItemElement
70
+ if (!allowedTags[element.tag]) {
70
71
  // Ignore and do contents
71
- html += this.convertItemsToHtml(item.items)
72
+ html += this.convertItemsToHtml(element.items || [])
72
73
  continue
73
74
  }
74
75
 
75
76
  let attrs = ""
76
77
  // Add style
77
- if (item.style) {
78
+ if (element.style) {
78
79
  attrs += ' style="'
79
80
  let first = true
80
- for (let key in item.style) {
81
- const value = item.style[key]
81
+ for (let key in element.style) {
82
+ const value = element.style[key]
82
83
  if (!allowedStyles[key]) {
83
84
  continue
84
85
  }
@@ -97,20 +98,20 @@ export default class ItemsHtmlConverter {
97
98
  }
98
99
 
99
100
  // Add href
100
- if (item.href) {
101
- attrs += ' href="' + item.href + '"'
101
+ if (element.href) {
102
+ attrs += ' href="' + element.href + '"'
102
103
  }
103
104
 
104
105
  // Add target
105
- if (item.target) {
106
- attrs += ' target="' + _.escape(item.target) + '"'
106
+ if (element.target) {
107
+ attrs += ' target="' + _.escape(element.target) + '"'
107
108
  }
108
109
 
109
110
  // Special case for self-closing tags
110
- if (["br"].includes(item.tag)) {
111
- html += `<${item.tag}${attrs}>`
111
+ if (["br"].includes(element.tag)) {
112
+ html += `<${element.tag}${attrs}>`
112
113
  } else {
113
- html += `<${item.tag}${attrs}>` + this.convertItemsToHtml(item.items) + `</${item.tag}>`
114
+ html += `<${element.tag}${attrs}>` + this.convertItemsToHtml(element.items || []) + `</${element.tag}>`
114
115
  }
115
116
  } else {
116
117
  html += this.convertSpecialItemToHtml(item)
@@ -123,6 +124,8 @@ export default class ItemsHtmlConverter {
123
124
  }
124
125
 
125
126
  // console.log "createHtml: #{html}"
127
+ // console.log("convertItemsToHtml: " + JSON.stringify(items, null, 2))
128
+ // console.log("convertItemsToHtml: " + html)
126
129
  return html
127
130
  }
128
131
 
@@ -168,16 +171,22 @@ export default class ItemsHtmlConverter {
168
171
  const nodeElement = node as HTMLElement
169
172
  if (nodeElement.style != null) {
170
173
  const styleDeclaration = nodeElement.style
171
- for (const style of styleDeclaration) {
172
- if (!allowedStyles[style as string]) {
174
+ for (let i = 0; i < styleDeclaration.length; i++) {
175
+ const style = styleDeclaration[i]
176
+ if (!allowedStyles[style]) {
173
177
  continue
174
178
  }
175
179
 
176
- const value = styleDeclaration[style as any]
180
+ const value = styleDeclaration.getPropertyValue(style)
177
181
  if (value == null || value === "") {
178
182
  continue
179
183
  }
180
184
 
185
+ // Ignore bootstrap variables in style values
186
+ if (value.startsWith("var(--bs-")) {
187
+ continue
188
+ }
189
+
181
190
  item.style = item.style || {}
182
191
  item.style[style] = value
183
192
  }
@@ -203,7 +212,12 @@ export default class ItemsHtmlConverter {
203
212
  item.target = (node as HTMLLinkElement).target
204
213
  }
205
214
 
206
- items.push(item)
215
+ // Unwrap pointless span elements that have no style and one child
216
+ if (tag === "span" && item.style == null && item.items?.length === 1) {
217
+ items.push(item.items[0])
218
+ } else {
219
+ items.push(item)
220
+ }
207
221
 
208
222
  // Handle text
209
223
  } else if (node.nodeType === 3) {
@@ -218,7 +232,8 @@ export default class ItemsHtmlConverter {
218
232
  }
219
233
 
220
234
  // console.log JSON.stringify(items, null, 2)
221
-
235
+ // console.log("convertElemToItems: " + elem.outerHTML)
236
+ // console.log("convertElemToItems: " + JSON.stringify(items, null, 2))
222
237
  return items
223
238
  }
224
239
  }
package/src/wellknown.ts CHANGED
@@ -21,7 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
21
 
22
22
  const numberRegexp: RegExp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
23
23
  // Matches sequences like '100 100' or '100 100 100'.
24
- const tuples: RegExp = new RegExp('^' + numberRegexp.source + '(\\s' + numberRegexp.source + '){1,}');
24
+ const tuples: RegExp = new RegExp('^' + numberRegexp.source + '(\\s' + numberRegexp.source + '){1,3}');
25
25
 
26
26
  /*
27
27
  * Parse WKT and return GeoJSON.
@@ -61,12 +61,12 @@ export function parse(input: string): any {
61
61
  function white(): void { $(/^\s*/); }
62
62
 
63
63
  function multicoords(): any[] | null {
64
- white();
65
- let depth: number = 0;
66
- let rings: any[] = [];
67
- let stack: any[][] = [rings];
68
- let pointer: any[] = rings;
69
- let elem: string | null;
64
+ white()
65
+ let depth: number = 0
66
+ let rings: any[] = []
67
+ let stack: any[][] = [rings]
68
+ let pointer: any[] = rings
69
+ let elem: string | null
70
70
 
71
71
  while (elem =
72
72
  $(/^(\()/) ||
@@ -74,33 +74,35 @@ export function parse(input: string): any {
74
74
  $(/^(,)/) ||
75
75
  $(tuples)) {
76
76
  if (elem === '(') {
77
- stack.push(pointer);
78
- pointer = [];
79
- stack[stack.length - 1].push(pointer);
80
- depth++;
77
+ stack.push(pointer)
78
+ pointer = []
79
+ stack[stack.length - 1].push(pointer)
80
+ depth++
81
81
  } else if (elem === ')') {
82
82
  // For the case: Polygon(), ...
83
- if (pointer.length === 0) return null;
83
+ if (pointer.length === 0) return null
84
84
 
85
- pointer = stack.pop() || [];
85
+ pointer = stack.pop() || []
86
86
  // the stack was empty, input was malformed
87
- if (!pointer) return null;
88
- depth--;
89
- if (depth === 0) break;
87
+ if (!pointer) return null
88
+ depth--
89
+ if (depth === 0) break
90
90
  } else if (elem === ',') {
91
- pointer = [];
92
- stack[stack.length - 1].push(pointer);
91
+ pointer = []
92
+ stack[stack.length - 1].push(pointer)
93
93
  } else if (!elem.split(/\s/g).some(s => isNaN(s as any))) {
94
- Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat));
94
+ // Split into values and only take first 3 if there are 4 (ZM coordinates)
95
+ const values = elem.split(/\s/g).map(parseFloat)
96
+ Array.prototype.push.apply(pointer, values.length === 4 ? values.slice(0, 3) : values)
95
97
  } else {
96
- return null;
98
+ return null
97
99
  }
98
- white();
100
+ white()
99
101
  }
100
102
 
101
- if (depth !== 0) return null;
103
+ if (depth !== 0) return null
102
104
 
103
- return rings;
105
+ return rings
104
106
  }
105
107
 
106
108
  function coords(): any[] | null {
@@ -115,7 +117,8 @@ export function parse(input: string): any {
115
117
  item = [];
116
118
  } else if (!pt.split(/\s/g).some(s => isNaN(s as any))) {
117
119
  if (!item) item = [];
118
- Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat));
120
+ const values = pt.split(/\s/g).map(parseFloat)
121
+ Array.prototype.push.apply(item, values.length === 4 ? values.slice(0, 3) : values);
119
122
  }
120
123
  white();
121
124
  }
@@ -127,7 +130,7 @@ export function parse(input: string): any {
127
130
  }
128
131
 
129
132
  function point(): any | null {
130
- if (!$(/^(point(\sz)?)/i)) return null;
133
+ if (!$(/^(point(\s+zm|\s+z)?)/i)) return null;
131
134
  white();
132
135
  if (!$(/^(\()/)) return null;
133
136
  let c: any[] | null = coords();
@@ -141,7 +144,7 @@ export function parse(input: string): any {
141
144
  }
142
145
 
143
146
  function multipoint(): any | null {
144
- if (!$(/^(multipoint(\sz)?)/i)) return null;
147
+ if (!$(/^(multipoint(\s+zm|\s+z)?)/i)) return null;
145
148
  white();
146
149
  let newCoordsFormat: string = _!
147
150
  .substring(_!.indexOf('(') + 1, _!.length - 1)
@@ -158,7 +161,7 @@ export function parse(input: string): any {
158
161
  }
159
162
 
160
163
  function multilinestring(): any | null {
161
- if (!$(/^(multilinestring(\sz)?)/i)) return null;
164
+ if (!$(/^(multilinestring(\s+zm|\s+z)?)/i)) return null;
162
165
  white();
163
166
  let c: any[] | null = multicoords();
164
167
  if (!c) return null;
@@ -170,7 +173,7 @@ export function parse(input: string): any {
170
173
  }
171
174
 
172
175
  function linestring(): any | null {
173
- if (!$(/^(linestring(\sz)?)/i)) return null;
176
+ if (!$(/^(linestring(\s+zm|\s+z)?)/i)) return null;
174
177
  white();
175
178
  if (!$(/^(\()/)) return null;
176
179
  let c: any[] | null = coords();
@@ -183,7 +186,7 @@ export function parse(input: string): any {
183
186
  }
184
187
 
185
188
  function polygon(): any | null {
186
- if (!$(/^(polygon(\sz)?)/i)) return null;
189
+ if (!$(/^(polygon(\s+zm|\s+z)?)/i)) return null;
187
190
  white();
188
191
  let c: any[] | null = multicoords();
189
192
  if (!c) return null;
@@ -194,7 +197,7 @@ export function parse(input: string): any {
194
197
  }
195
198
 
196
199
  function multipolygon(): any | null {
197
- if (!$(/^(multipolygon(\sz)?)/i)) return null;
200
+ if (!$(/^(multipolygon(\s+zm|\s+z)?)/i)) return null;
198
201
  white();
199
202
  let c: any[] | null = multicoords();
200
203
  if (!c) return null;
@@ -62,7 +62,8 @@ export default class ImageWidget extends Widget {
62
62
  onDesignChange: options.onDesignChange,
63
63
  width: options.width,
64
64
  height: options.height,
65
- singleRowTable: options.singleRowTable
65
+ singleRowTable: options.singleRowTable,
66
+ translate: options.translate
66
67
  })
67
68
  }
68
69
 
@@ -144,4 +145,12 @@ export default class ImageWidget extends Widget {
144
145
 
145
146
  return []
146
147
  }
148
+
149
+ getTranslatableStrings(design: ImageWidgetDesign, schema: Schema): string[] {
150
+ const strings: string[] = []
151
+ if (design.caption) {
152
+ strings.push(design.caption)
153
+ }
154
+ return strings
155
+ }
147
156
  }
@@ -29,6 +29,7 @@ export interface ImageWidgetComponentProps {
29
29
  width: number
30
30
  height: number
31
31
  singleRowTable?: string
32
+ translate: (input: string) => string
32
33
  }
33
34
 
34
35
  export default class ImageWidgetComponent extends AsyncLoadComponent<ImageWidgetComponentProps, { data: any, loading: boolean }> {
@@ -154,9 +155,9 @@ export default class ImageWidgetComponent extends AsyncLoadComponent<ImageWidget
154
155
  className: "mwater-visualization-image-widget",
155
156
  style: { position: "relative", width: this.props.width, height: this.props.height }
156
157
  },
157
- captionPosition === "top" ? R("div", { className: "caption" }, this.props.design.caption) : undefined,
158
+ captionPosition === "top" && this.props.design.caption ? R("div", { className: "caption" }, this.props.translate(this.props.design.caption)) : undefined,
158
159
  R("div", { className: "image" }, this.renderContent()),
159
- captionPosition === "bottom" ? R("div", { className: "caption" }, this.props.design.caption) : undefined
160
+ captionPosition === "bottom" && this.props.design.caption ? R("div", { className: "caption" }, this.props.translate(this.props.design.caption)) : undefined
160
161
  )
161
162
  )
162
163
  }