@mwater/visualization 5.4.1 → 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 (269) 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 +1 -1
  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/PivotChartLayoutComponent.js +1 -1
  148. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +7 -4
  149. package/lib/widgets/charts/table/OrderingsComponent.js +1 -1
  150. package/lib/widgets/charts/table/TableChart.d.ts +1 -0
  151. package/lib/widgets/charts/table/TableChart.js +15 -0
  152. package/lib/widgets/text/TextComponent.d.ts +11 -4
  153. package/lib/widgets/text/TextComponent.js +11 -8
  154. package/lib/widgets/text/TextWidget.d.ts +6 -3
  155. package/lib/widgets/text/TextWidget.js +7 -1
  156. package/lib/widgets/text/TextWidgetComponent.d.ts +4 -0
  157. package/lib/widgets/text/TextWidgetComponent.js +7 -1
  158. package/lib/widgets/text/TextWidgetDesign.d.ts +2 -4
  159. package/lib/widgets/text/TextWidgetDesign.js +1 -1
  160. package/package.json +7 -8
  161. package/src/ColorComponent.tsx +1 -2
  162. package/src/IdSelection.ts +62 -0
  163. package/src/MWaterAddRelatedIndicatorComponent.ts +3 -2
  164. package/src/MWaterCompleteTableSelectComponent.tsx +36 -46
  165. package/src/MWaterLoaderComponent.ts +28 -26
  166. package/src/MWaterResponsesFilterComponent.ts +5 -2
  167. package/src/MWaterTableSelectComponent.tsx +5 -9
  168. package/src/autotranslate.ts +141 -0
  169. package/src/axes/AxisBuilder.ts +3 -3
  170. package/src/axes/AxisColorEditorComponent.tsx +5 -0
  171. package/src/axes/{AxisComponent.ts → AxisComponent.tsx} +106 -106
  172. package/src/axes/CategoryMapComponent.ts +4 -4
  173. package/src/axes/RangesComponent.ts +3 -2
  174. package/src/dashboards/DashboardComponent.tsx +79 -14
  175. package/src/dashboards/DashboardDesign.ts +9 -2
  176. package/src/dashboards/DashboardUtils.ts +39 -0
  177. package/src/dashboards/DashboardViewComponent.tsx +22 -3
  178. package/src/dashboards/ServerDashboardDataSource.ts +2 -1
  179. package/src/dashboards/SettingsModalComponent.tsx +450 -35
  180. package/src/dashboards/WidgetComponent.tsx +12 -6
  181. package/src/datagrids/CellEditor.tsx +354 -0
  182. package/src/datagrids/DatagridComponent.tsx +646 -0
  183. package/src/datagrids/DatagridViewComponent.tsx +539 -0
  184. package/src/datagrids/DirectDatagridDataSource.ts +2 -3
  185. package/src/datagrids/{ExprCellComponent.ts → ExprCellComponent.tsx} +28 -23
  186. package/src/datagrids/{FindReplaceModalComponent.ts → FindReplaceModalComponent.tsx} +109 -122
  187. package/src/index.css +1 -1
  188. package/src/index.ts +0 -1
  189. package/src/layouts/blocks/HorizontalBlockComponent.ts +2 -2
  190. package/src/mWaterLoader.ts +1 -1
  191. package/src/maps/BufferLayer.ts +83 -60
  192. package/src/maps/BufferLayerDesign.ts +20 -14
  193. package/src/maps/BufferLayerDesignerComponent.tsx +309 -0
  194. package/src/maps/ChoroplethLayer.ts +40 -19
  195. package/src/maps/ChoroplethLayerDesign.ts +4 -2
  196. package/src/maps/ChoroplethLayerDesigner.tsx +4 -2
  197. package/src/maps/ClusterLayer.ts +4 -10
  198. package/src/maps/DetailLevelSelectComponent.ts +1 -1
  199. package/src/maps/DirectMapDataSource.ts +2 -1
  200. package/src/maps/EditPopupComponent.ts +7 -3
  201. package/src/maps/GridLayer.ts +4 -10
  202. package/src/maps/GridLayerDesigner.tsx +5 -3
  203. package/src/maps/HoverContent.tsx +40 -16
  204. package/src/maps/Layer.ts +28 -10
  205. package/src/maps/LayerFactory.ts +0 -8
  206. package/src/maps/LayerLegendComponent.ts +2 -4
  207. package/src/maps/LayerSwitcherComponent.tsx +6 -2
  208. package/src/maps/LeafletMapComponent.tsx +3 -1
  209. package/src/maps/LegendComponent.tsx +10 -1
  210. package/src/maps/MWaterServerLayer.ts +3 -3
  211. package/src/maps/MapComponent.ts +3 -3
  212. package/src/maps/MapDesign.ts +3 -0
  213. package/src/maps/MapDesignerComponent.tsx +165 -162
  214. package/src/maps/MapLayerViewDesignerComponent.ts +2 -2
  215. package/src/maps/MapUtils.ts +24 -0
  216. package/src/maps/MapViewComponent.tsx +11 -3
  217. package/src/maps/MarkersLayer.ts +44 -18
  218. package/src/maps/MarkersLayerDesign.ts +19 -16
  219. package/src/maps/PopupFilterJoinsUtils.ts +6 -2
  220. package/src/maps/RasterMapViewComponent.ts +9 -45
  221. package/src/maps/ServerMapDataSource.ts +2 -2
  222. package/src/maps/SwitchableTileUrlLayer.tsx +4 -10
  223. package/src/maps/TileUrlLayer.tsx +4 -10
  224. package/src/maps/VectorMapViewComponent.tsx +28 -55
  225. package/src/maps/maps.ts +3 -0
  226. package/src/quickfilter/QuickfiltersComponent.ts +13 -7
  227. package/src/quickfilter/QuickfiltersDesignComponent.tsx +56 -74
  228. package/src/richtext/ExprItemsHtmlConverter.ts +9 -5
  229. package/src/richtext/ExprItemsTranslator.ts +176 -0
  230. package/src/richtext/ItemsHtmlConverter.ts +33 -18
  231. package/src/wellknown.ts +33 -30
  232. package/src/widgets/ImageWidget.ts +10 -1
  233. package/src/widgets/ImageWidgetComponent.ts +3 -2
  234. package/src/widgets/{MapWidget.ts → MapWidget.tsx} +90 -101
  235. package/src/widgets/MarkdownWidget.ts +3 -0
  236. package/src/widgets/TOCWidget.tsx +281 -0
  237. package/src/widgets/Widget.ts +25 -5
  238. package/src/widgets/WidgetScopesViewComponent.ts +2 -1
  239. package/src/widgets/charts/Chart.ts +31 -12
  240. package/src/widgets/charts/ChartViewComponent.ts +13 -3
  241. package/src/widgets/charts/ChartWidget.ts +11 -1
  242. package/src/widgets/charts/ChartWidgetComponent.tsx +9 -1
  243. package/src/widgets/charts/calendar/CalendarChart.ts +29 -0
  244. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +3 -1
  245. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +9 -0
  246. package/src/widgets/charts/layered/LayeredChart.ts +71 -3
  247. package/src/widgets/charts/layered/LayeredChartCompiler.ts +2 -2
  248. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +4 -2
  249. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +10 -4
  250. package/src/widgets/charts/pivot/PivotChart.ts +73 -0
  251. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +1 -1
  252. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +6 -4
  253. package/src/widgets/charts/table/OrderingsComponent.tsx +2 -1
  254. package/src/widgets/charts/table/TableChart.ts +17 -0
  255. package/src/widgets/text/TextComponent.tsx +22 -12
  256. package/src/widgets/text/TextWidget.ts +9 -2
  257. package/src/widgets/text/TextWidgetComponent.tsx +16 -1
  258. package/src/widgets/text/TextWidgetDesign.ts +4 -7
  259. package/test/IdSelectionTests.ts +54 -0
  260. package/test/LayeredChartCompilerTests.ts +0 -2
  261. package/test/richtext/ExprItemsTranslatorTests.ts +144 -0
  262. package/test/wellknownTests.ts +144 -0
  263. package/src/datagrids/DatagridComponent.ts +0 -478
  264. package/src/datagrids/DatagridViewComponent.ts +0 -464
  265. package/src/datagrids/EditExprCellComponent.tsx +0 -305
  266. package/src/datagrids/README.md +0 -3
  267. package/src/maps/BufferLayerDesignerComponent.ts +0 -311
  268. package/src/widgets/TOCWidget.ts +0 -326
  269. package/test/LegoLayoutEngineTests.ts +0 -69
@@ -1,5 +1,4 @@
1
1
  import React from "react"
2
- const R = React.createElement
3
2
  import _ from "lodash"
4
3
  import Widget, { CreateViewElementOptions } from "./Widget"
5
4
  import DropdownWidgetComponent from "./DropdownWidgetComponent"
@@ -7,6 +6,7 @@ import ModalWindowComponent from "@mwater/react-library/lib/ModalWindowComponent
7
6
  import * as MapUtils from "../maps/MapUtils"
8
7
  import { DataSource, Schema } from "@mwater/expressions"
9
8
  import { WidgetDataSource } from "./WidgetDataSource"
9
+ import { MapDesign } from "../maps/MapDesign"
10
10
 
11
11
  // Design is the map design specified in maps/Map Design.md
12
12
  export default class MapWidget extends Widget {
@@ -24,28 +24,33 @@ export default class MapWidget extends Widget {
24
24
  // height: height in pixels on screen
25
25
  // onRowClick: Called with (tableId, rowId) when item is clicked
26
26
  createViewElement(options: CreateViewElementOptions) {
27
- return React.createElement(MapWidgetComponent, {
28
- schema: options.schema,
29
- dataSource: options.dataSource,
30
- widgetDataSource: options.widgetDataSource,
31
-
32
- design: options.design,
33
- onDesignChange: options.onDesignChange,
34
- scope: options.scope,
35
- filters: options.filters,
36
- onScopeChange: options.onScopeChange,
37
- width: options.width,
38
- height: options.height,
39
- onRowClick: options.onRowClick,
40
- refreshKey: options.refreshKey
41
- })
27
+ return <MapWidgetComponent
28
+ schema={options.schema}
29
+ dataSource={options.dataSource}
30
+ widgetDataSource={options.widgetDataSource}
31
+ design={options.design}
32
+ onDesignChange={options.onDesignChange}
33
+ scope={options.scope}
34
+ filters={options.filters}
35
+ onScopeChange={options.onScopeChange}
36
+ width={options.width}
37
+ height={options.height}
38
+ onRowClick={options.onRowClick}
39
+ refreshKey={options.refreshKey}
40
+ locale={options.locale}
41
+ translate={options.translate}
42
+ />
42
43
  }
43
44
 
44
45
  // Get a list of table ids that can be filtered on
45
- getFilterableTables(design: any, schema: Schema) {
46
+ getFilterableTables(design: MapDesign, schema: Schema) {
46
47
  // Get filterable tables
47
48
  return MapUtils.getFilterableTables(design, schema)
48
49
  }
50
+
51
+ getTranslatableStrings(design: MapDesign, schema: Schema): string[] {
52
+ return MapUtils.getTranslatableStrings(design, schema)
53
+ }
49
54
  }
50
55
 
51
56
  interface MapWidgetComponentProps {
@@ -54,8 +59,7 @@ interface MapWidgetComponentProps {
54
59
  /** Data source to use */
55
60
  dataSource: DataSource
56
61
  widgetDataSource: WidgetDataSource
57
- /** See Map Design.md */
58
- design: any
62
+ design: MapDesign
59
63
  /** Called with new design. null/undefined for readonly */
60
64
  onDesignChange?: any
61
65
  width?: number
@@ -69,6 +73,10 @@ interface MapWidgetComponentProps {
69
73
  onRowClick?: any
70
74
  /** TODO: implement refreshing */
71
75
  refreshKey?: any
76
+ /** Locale to use. Overrides map design locale */
77
+ locale: string
78
+ /** Translate function to use for display */
79
+ translate: (input: string) => string
72
80
  }
73
81
 
74
82
  interface MapWidgetComponentState {
@@ -115,83 +123,69 @@ class MapWidgetComponent extends React.Component<MapWidgetComponentProps, MapWid
115
123
  const MapDesignerComponent = require("../maps/MapDesignerComponent").default
116
124
 
117
125
  // Create editor
118
- const editor = React.createElement(MapDesignerComponent, {
119
- schema: this.props.schema,
120
- dataSource: this.props.dataSource,
121
- design: this.state.editDesign,
122
- onDesignChange: this.handleEditDesignChange,
123
- filters: this.props.filters
124
- })
126
+ const editor = <MapDesignerComponent
127
+ schema={this.props.schema}
128
+ dataSource={this.props.dataSource}
129
+ design={this.state.editDesign}
130
+ onDesignChange={this.handleEditDesignChange}
131
+ filters={this.props.filters}
132
+ />
125
133
 
126
134
  // Create map (maxing out at half of width of screen)
127
- const width = Math.min(document.body.clientWidth / 2, this.props.width)
128
- const height = (this.props.height * width) / this.props.width
135
+ const width = Math.min(document.body.clientWidth / 2, this.props.width || 0)
136
+ const height = ((this.props.height || 0) * width) / (this.props.width || 1)
129
137
  const chart = this.renderContent(this.state.editDesign, this.handleEditDesignChange, width, height)
130
138
 
131
- const content = R(
132
- "div",
133
- { style: { height: "100%", width: "100%" } },
134
- R(
135
- "div",
136
- {
137
- style: {
138
- position: "absolute",
139
- left: 0,
140
- top: 0,
141
- border: "solid 2px #EEE",
142
- borderRadius: 8,
143
- padding: 10,
144
- width: width + 20,
145
- height: height + 20
146
- }
147
- },
148
- chart
149
- ),
150
- R(
151
- "div",
152
- { style: { width: "100%", height: "100%", paddingLeft: width + 40 } },
153
- R(
154
- "div",
155
- {
156
- style: { width: "100%", height: "100%", overflowY: "auto", paddingLeft: 20, borderLeft: "solid 3px #AAA" }
157
- },
158
- editor
159
- )
160
- )
161
- )
162
-
163
- return React.createElement(
164
- ModalWindowComponent,
165
- {
166
- isOpen: true,
167
- onRequestClose: this.handleEndEditing
168
- },
169
- content
170
- )
139
+ const content = <div style={{ height: "100%", width: "100%" }}>
140
+ <div style={{
141
+ position: "absolute",
142
+ left: 0,
143
+ top: 0,
144
+ border: "solid 2px #EEE",
145
+ borderRadius: 8,
146
+ padding: 10,
147
+ width: width + 20,
148
+ height: height + 20
149
+ }}>
150
+ {chart}
151
+ </div>
152
+ <div style={{ width: "100%", height: "100%", paddingLeft: width + 40 }}>
153
+ <div style={{ width: "100%", height: "100%", overflowY: "auto", paddingLeft: 20, borderLeft: "solid 3px #AAA" }}>
154
+ {editor}
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ return <ModalWindowComponent
160
+ isOpen={true}
161
+ onRequestClose={this.handleEndEditing}
162
+ >
163
+ {content}
164
+ </ModalWindowComponent>
171
165
  }
172
166
 
173
167
  renderContent(design: any, onDesignChange: any, width: any, height: any) {
174
168
  // Require here to prevent server require problems
175
169
  const { MapViewComponent } = require("../maps/MapViewComponent")
176
170
 
177
- return R(
178
- "div",
179
- { style: { width, height, padding: 10 } },
180
- React.createElement(MapViewComponent, {
181
- schema: this.props.schema,
182
- design,
183
- dataSource: this.props.dataSource,
184
- mapDataSource: this.props.widgetDataSource.getMapDataSource!(design),
185
- onDesignChange,
186
- scope: this.props.scope,
187
- onScopeChange: this.props.onScopeChange,
188
- extraFilters: this.props.filters,
189
- width: width - 20,
190
- height: height - 20,
191
- scrollWheelZoom: false, // Prevent accidental zooming
192
- onRowClick: this.props.onRowClick
193
- })
194
- )
171
+ return <div style={{ width, height, padding: 10 }}>
172
+ <MapViewComponent
173
+ schema={this.props.schema}
174
+ design={design}
175
+ dataSource={this.props.dataSource}
176
+ mapDataSource={this.props.widgetDataSource.getMapDataSource!(design)}
177
+ onDesignChange={onDesignChange}
178
+ scope={this.props.scope}
179
+ onScopeChange={this.props.onScopeChange}
180
+ extraFilters={this.props.filters}
181
+ width={width - 20}
182
+ height={height - 20}
183
+ scrollWheelZoom={false} // Prevent accidental zooming
184
+ onRowClick={this.props.onRowClick}
185
+ locale={this.props.locale}
186
+ translate={this.props.translate}
187
+ />
188
+ </div>
195
189
  }
196
190
 
197
191
  render() {
@@ -203,20 +197,15 @@ class MapWidgetComponent extends React.Component<MapWidgetComponentProps, MapWid
203
197
  const handleDesignChange = (d: any) => this.setState({ transientDesign: d })
204
198
 
205
199
  // Wrap in a simple widget
206
- return R(
207
- "div",
208
- null,
209
- this.props.onDesignChange != null ? this.renderEditor() : undefined,
210
- // Use transient design (as it may be affected by toggling layers)
211
- React.createElement(
212
- DropdownWidgetComponent,
213
- {
214
- width: this.props.width,
215
- height: this.props.height,
216
- dropdownItems
217
- },
218
- this.renderContent(this.state.transientDesign, handleDesignChange, this.props.width, this.props.height)
219
- )
220
- )
200
+ return <div>
201
+ {this.props.onDesignChange != null ? this.renderEditor() : undefined}
202
+ <DropdownWidgetComponent
203
+ width={this.props.width}
204
+ height={this.props.height}
205
+ dropdownItems={dropdownItems}
206
+ >
207
+ {this.renderContent(this.state.transientDesign, handleDesignChange, this.props.width, this.props.height)}
208
+ </DropdownWidgetComponent>
209
+ </div>
221
210
  }
222
211
  }
@@ -7,6 +7,9 @@ import DropdownWidgetComponent from "./DropdownWidgetComponent"
7
7
  import Markdown from "markdown-it"
8
8
  import ModalWindowComponent from "@mwater/react-library/lib/ModalWindowComponent"
9
9
 
10
+ /** Widget for displaying markdown. Deprecated. Use TextWidget instead.
11
+ * @deprecated
12
+ */
10
13
  export default class MarkdownWidget extends Widget {
11
14
  // Creates a React element that is a view of the widget
12
15
  // options:
@@ -0,0 +1,281 @@
1
+ import React, { useState } from "react"
2
+ import _ from "lodash"
3
+ import * as ui from "@mwater/react-library/lib/bootstrap"
4
+ import Widget, { CreateViewElementOptions, TOCEntry } from "./Widget"
5
+ import DropdownWidgetComponent from "./DropdownWidgetComponent"
6
+ import ModalPopupComponent from "@mwater/react-library/lib/ModalPopupComponent"
7
+ import produce from "immer"
8
+ import { Schema } from "@mwater/expressions"
9
+
10
+ export interface TOCWidgetDesign {
11
+ /** Header text. Defaults to blank */
12
+ header?: string
13
+ /** Border weight. Defaults to 0=None. 1=light, 2=medium, 3=heavy */
14
+ borderWeight?: number
15
+ /** True/false for prepending numbering to entries (e.g. 3.4.1) */
16
+ numbering?: boolean
17
+ }
18
+
19
+ /**
20
+ * Table of contents widget that displays the h1, h2, etc entries from all text fields in one widget
21
+ */
22
+ export default class TOCWidget extends Widget {
23
+ /** Creates a React element that is a view of the widget */
24
+ createViewElement(options: CreateViewElementOptions) {
25
+ return <TOCWidgetComponent
26
+ design={options.design}
27
+ onDesignChange={options.onDesignChange ?? undefined}
28
+ width={options.width}
29
+ height={options.height}
30
+ tocEntries={options.tocEntries}
31
+ onScrollToTOCEntry={options.onScrollToTOCEntry}
32
+ translate={options.translate}
33
+ />
34
+ }
35
+
36
+ // Determine if widget is auto-height, which means that a vertical height is not required.
37
+ isAutoHeight() {
38
+ return true
39
+ }
40
+
41
+ getTranslatableStrings(design: TOCWidgetDesign, schema: Schema): string[] {
42
+ const strings: string[] = []
43
+ if (design.header) {
44
+ strings.push(design.header)
45
+ }
46
+ return strings
47
+ }
48
+ }
49
+
50
+ interface TOCWidgetComponentProps {
51
+ design: TOCWidgetDesign
52
+ /** Called with new design. null/undefined for readonly */
53
+ onDesignChange?: (design: TOCWidgetDesign) => void
54
+ width?: number
55
+ height?: number
56
+ tocEntries?: TOCEntry[]
57
+ onScrollToTOCEntry?: (widgetId: string, id: any) => void
58
+ translate: (input: string) => string
59
+ }
60
+
61
+ function TOCWidgetComponent(props: TOCWidgetComponentProps) {
62
+ const { design, onDesignChange, width, height, tocEntries, onScrollToTOCEntry, translate } = props
63
+ const [editing, setEditing] = useState(false)
64
+
65
+ const handleStartEditing = () => {
66
+ setEditing(true)
67
+ }
68
+
69
+ const handleEndEditing = () => {
70
+ setEditing(false)
71
+ }
72
+
73
+ const renderEditor = () => {
74
+ if (!editing) {
75
+ return null
76
+ }
77
+
78
+ // Create editor
79
+ const editor = <TOCWidgetDesignerComponent
80
+ design={design}
81
+ onDesignChange={onDesignChange!}
82
+ />
83
+
84
+ return <ModalPopupComponent
85
+ showCloseX={true}
86
+ header={T`Table of Contents Options`}
87
+ onClose={handleEndEditing}
88
+ >
89
+ {editor}
90
+ </ModalPopupComponent>
91
+ }
92
+
93
+ const renderContent = () => {
94
+ return <TOCWidgetViewComponent
95
+ design={design}
96
+ onDesignChange={onDesignChange}
97
+ width={width}
98
+ height={height}
99
+ tocEntries={tocEntries}
100
+ onScrollToTOCEntry={onScrollToTOCEntry}
101
+ translate={translate}
102
+ />
103
+ }
104
+
105
+ const dropdownItems = []
106
+ if (onDesignChange != null) {
107
+ dropdownItems.push({ label: T`Edit`, icon: "pencil", onClick: handleStartEditing })
108
+ }
109
+
110
+ // Wrap in a simple widget
111
+ return <div onDoubleClick={handleStartEditing}>
112
+ {onDesignChange != null ? renderEditor() : undefined}
113
+ <DropdownWidgetComponent
114
+ width={width}
115
+ height={height}
116
+ dropdownItems={dropdownItems}
117
+ >
118
+ {renderContent()}
119
+ </DropdownWidgetComponent>
120
+ </div>
121
+ }
122
+
123
+ interface TOCWidgetViewComponentProps {
124
+ design: TOCWidgetDesign
125
+ onDesignChange?: (design: TOCWidgetDesign) => void
126
+ width?: number
127
+ height?: number
128
+ tocEntries?: TOCEntry[]
129
+ onScrollToTOCEntry?: (widgetId: string, id: any) => void
130
+ translate: (input: string) => string
131
+ }
132
+
133
+ // Displays the contents of the widget
134
+ function TOCWidgetViewComponent(props: TOCWidgetViewComponentProps) {
135
+ const { design, onDesignChange, width, height, tocEntries, onScrollToTOCEntry, translate } = props
136
+
137
+ const handleEntryClick = (tocEntry: TOCEntry) => {
138
+ return onScrollToTOCEntry?.(tocEntry.widgetId, tocEntry.id)
139
+ }
140
+
141
+ const renderTOCEntry = (tocEntry: TOCEntry, index: number) => {
142
+ // Find indentation number (e.g "1.3.2") by counting # backwards that are same level with no level lower
143
+ let level
144
+ let indentation = ""
145
+ if (design.numbering) {
146
+ // For each level up to the current entry's level
147
+ for (let level = 1; level <= tocEntry.level; level++) {
148
+ let value = 0
149
+ // Count entries at this level up to current index
150
+ for (let i = 0; i <= index; i++) {
151
+ const entry = tocEntries?.[i]
152
+ if (!entry) {
153
+ continue
154
+ }
155
+ if (entry.level === level) {
156
+ value++
157
+ } else if (entry.level < level) {
158
+ // Reset counter when we hit a higher level
159
+ value = 0
160
+ }
161
+ }
162
+ indentation += `${value}.`
163
+ }
164
+ indentation += " "
165
+ }
166
+
167
+ return <div key={index} style={{ paddingLeft: tocEntry.level * 8 - 8 }}>
168
+ <a className="link-plain" onClick={() => handleEntryClick(tocEntry)}>
169
+ {indentation}
170
+ <span>{translate(tocEntry.text)}</span>
171
+ </a>
172
+ </div>
173
+ }
174
+
175
+ // Get border
176
+ const border = (() => {
177
+ switch (design.borderWeight) {
178
+ case 0:
179
+ return "none"
180
+ case 1:
181
+ return "solid 1px #f4f4f4"
182
+ case 2:
183
+ return "solid 1px #ccc"
184
+ case 3:
185
+ return "solid 1px #888"
186
+ }
187
+ })()
188
+
189
+ return <div
190
+ style={{
191
+ width,
192
+ height,
193
+ border,
194
+ padding: 5,
195
+ margin: 1
196
+ }}
197
+ >
198
+ {/* Render header */}
199
+ <div style={{ fontWeight: "bold" }}>{design.header ? props.translate(design.header) : ""}</div>
200
+ {_.map(tocEntries || [], (tocEntry, i) => {
201
+ return renderTOCEntry(tocEntry, i)
202
+ })}
203
+
204
+ {/* Add placeholder if none and editable */}
205
+ {onDesignChange && (tocEntries || []).length === 0
206
+ ? <div className="text-muted">
207
+ {T`Table of Contents will appear here as text blocks with headings are added to the dashboard`}
208
+ </div>
209
+ : undefined}
210
+ </div>
211
+ }
212
+
213
+ interface TOCWidgetDesignerProps {
214
+ design: TOCWidgetDesign
215
+ onDesignChange: (design: TOCWidgetDesign) => void
216
+ }
217
+
218
+ // Designer for TOC widget options
219
+ function TOCWidgetDesignerComponent(props: TOCWidgetDesignerProps) {
220
+ const { design, onDesignChange } = props
221
+
222
+ // Updates design with the specified changes
223
+ const handleUpdate = (field: keyof TOCWidgetDesign) => (value: any) => {
224
+ onDesignChange(produce(design, draft => {
225
+ draft[field] = value
226
+ }))
227
+ }
228
+
229
+ return <div>
230
+ <ui.FormGroup label={T`Header`}>
231
+ <ui.TextInput
232
+ value={design.header || ""}
233
+ onChange={handleUpdate("header")}
234
+ placeholder={T`None`}
235
+ />
236
+ </ui.FormGroup>
237
+ <ui.FormGroup label={T`Border`}>
238
+ <BorderComponent
239
+ value={design.borderWeight || 0}
240
+ onChange={handleUpdate("borderWeight")}
241
+ />
242
+ </ui.FormGroup>
243
+ <ui.FormGroup label={T`Numbering`}>
244
+ <ui.Radio
245
+ inline={true}
246
+ value={design.numbering || false}
247
+ radioValue={true}
248
+ onChange={handleUpdate("numbering")}
249
+ >
250
+ {T`On`}
251
+ </ui.Radio>
252
+ <ui.Radio
253
+ inline={true}
254
+ value={design.numbering || false}
255
+ radioValue={false}
256
+ onChange={handleUpdate("numbering")}
257
+ >
258
+ {T`Off`}
259
+ </ui.Radio>
260
+ </ui.FormGroup>
261
+ </div>
262
+ }
263
+
264
+ interface BorderComponentProps {
265
+ value?: number
266
+ defaultValue?: number
267
+ onChange: (value: number) => void
268
+ }
269
+
270
+ // Allows setting border heaviness
271
+ function BorderComponent(props: BorderComponentProps) {
272
+ const { value, defaultValue, onChange } = props
273
+ const currentValue = value != null ? value : defaultValue
274
+
275
+ return <div>
276
+ <ui.Radio inline={true} value={currentValue} radioValue={0} onChange={onChange}>{T`None`}</ui.Radio>
277
+ <ui.Radio inline={true} value={currentValue} radioValue={1} onChange={onChange}>{T`Light`}</ui.Radio>
278
+ <ui.Radio inline={true} value={currentValue} radioValue={2} onChange={onChange}>{T`Medium`}</ui.Radio>
279
+ <ui.Radio inline={true} value={currentValue} radioValue={3} onChange={onChange}>{T`Heavy`}</ui.Radio>
280
+ </div>
281
+ }
@@ -10,16 +10,16 @@ export interface CreateViewElementOptions {
10
10
  dataSource: DataSource
11
11
  /** Gives data to the widget in a way that allows client-server separation and secure sharing. See definition in WidgetDataSource. **/
12
12
  widgetDataSource: WidgetDataSource
13
- /** widget design **/
14
- design: object
13
+ /** widget design */
14
+ design: any
15
15
  /** scope of the widget (when the widget self-selects a particular scope) **/
16
16
  scope?: WidgetScope | null
17
17
  /** array of filters to apply.**/
18
18
  filters: JsonQLFilter[]
19
19
  /** called with scope of widget **/
20
- onScopeChange: (scope: WidgetScope | null) => void
20
+ onScopeChange?: (scope: WidgetScope | null) => void
21
21
  /** called with new design. null/undefined for readonly **/
22
- onDesignChange?: { (design: object): void } | null
22
+ onDesignChange?: ((design: any) => void) | null
23
23
  /** width in pixels on screen **/
24
24
  width?: number
25
25
  /** height in pixels on screen **/
@@ -32,7 +32,7 @@ export interface CreateViewElementOptions {
32
32
  namedStrings?: { [key: string]: string }
33
33
 
34
34
  /** Entries in the table of content */
35
- tocEntries?: string[]
35
+ tocEntries?: TOCEntry[]
36
36
 
37
37
  /** the widget callback ref */
38
38
  widgetRef?: (widget: any) => void
@@ -42,8 +42,23 @@ export interface CreateViewElementOptions {
42
42
 
43
43
  /** A key that changes when the widget should be refreshed */
44
44
  refreshKey?: any
45
+
46
+ /** Locale to use for display */
47
+ locale: string
48
+
49
+ /** Translate function to use for display. Returns same string when editing. */
50
+ translate: (input: string) => string
51
+ }
52
+
53
+ /** An entry in the table of contents */
54
+ export interface TOCEntry {
55
+ id: any
56
+ widgetId: string
57
+ level: number
58
+ text: string
45
59
  }
46
60
 
61
+
47
62
  export default class Widget {
48
63
  /** Creates a React element that is a view of the widget */
49
64
  createViewElement(options: CreateViewElementOptions): ReactElement<any> {
@@ -83,4 +98,9 @@ export default class Widget {
83
98
  getTOCEntries(design: any, namedStrings?: { [key: string]: string }): { id: string; text: string; level: number }[] {
84
99
  return []
85
100
  }
101
+
102
+ /** Gets any strings that should be translated */
103
+ getTranslatableStrings(design: any, schema: Schema): string[] {
104
+ return []
105
+ }
86
106
  }
@@ -47,7 +47,8 @@ export default class WidgetScopesViewComponent extends React.Component<WidgetSco
47
47
  "div",
48
48
  { className: "alert alert-info" },
49
49
  R("span", { className: "fas fa-filter" }),
50
- T` Filters: `,
50
+ " ",
51
+ T`Filters: `,
51
52
  _.map(_.keys(scopes), (id) => this.renderScope(id, scopes[id]))
52
53
  )
53
54
  }
@@ -11,7 +11,7 @@ export interface ChartCreateViewElementOptions {
11
11
  /** data source to use. Only used when designing, for display uses data **/
12
12
  dataSource: DataSource
13
13
 
14
- /** Chart design **/
14
+ /** Chart design. Should already be translated. */
15
15
  design: any
16
16
 
17
17
  /** called with new design. null/undefined for readonly **/
@@ -37,6 +37,9 @@ export interface ChartCreateViewElementOptions {
37
37
 
38
38
  /** Called with (tableId, rowId) when item is clicked **/
39
39
  onRowClick?: (tableId: string, rowId: any) => void
40
+
41
+ /** Locale to use for display */
42
+ locale: string
40
43
  }
41
44
 
42
45
  export default class Chart {
@@ -98,17 +101,9 @@ export default class Chart {
98
101
  throw new Error("Not implemented")
99
102
  }
100
103
 
101
- // Create a view element for the chart
102
- // Options include:
103
- // schema: schema to use
104
- // dataSource: dataSource to use
105
- // design: design of the chart
106
- // onDesignChange: when design changes
107
- // data: results from queries
108
- // width, height: size of the chart view
109
- // scope: current scope of the view element
110
- // onScopeChange: called when scope changes with new scope
111
- // onRowClick: Called with (tableId, rowId) when item is clicked
104
+ /** Create a view element for the chart.
105
+ * Chart design should already be translated. This is handled by ChartViewComponent.
106
+ */
112
107
  createViewElement(options: ChartCreateViewElementOptions): ReactNode {
113
108
  throw new Error("Not implemented")
114
109
  }
@@ -137,4 +132,28 @@ export default class Chart {
137
132
  getPlaceholderIcon() {
138
133
  return ""
139
134
  }
135
+
136
+ /** Get a list of translatable strings in the design. No need to override in subclasses. Design should already be cleaned. */
137
+ getTranslatableStrings(design: any, schema: Schema): string[] {
138
+ const strings = new Set<string>()
139
+
140
+ // Create collector function that just saves strings and returns them unchanged
141
+ const collectStrings = (str: string) => {
142
+ // Only collect non-empty strings
143
+ if (str) {
144
+ strings.add(str)
145
+ }
146
+ return str
147
+ }
148
+
149
+ // Use existing translation function but with collector
150
+ this.translateDesign(design, collectStrings)
151
+
152
+ return Array.from(strings)
153
+ }
154
+
155
+ /** Translates the design. Override in subclasses. Design is already cleaned. */
156
+ translateDesign(design: any, translate: (input: string) => string): any {
157
+ return design
158
+ }
140
159
  }