@mwater/visualization 5.2.0 → 5.3.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 (254) hide show
  1. package/lib/ColorComponent.d.ts +10 -11
  2. package/lib/ColorComponent.js +78 -29
  3. package/lib/ColorSchemeFactory.d.ts +13 -2
  4. package/lib/ColorSchemeFactory.js +7 -5
  5. package/lib/CustomColorsContext.d.ts +6 -0
  6. package/lib/CustomColorsContext.js +6 -0
  7. package/lib/FiltersDesignerComponent.d.ts +1 -4
  8. package/lib/FiltersDesignerComponent.js +2 -3
  9. package/lib/LocaleContextInjector.d.ts +5 -11
  10. package/lib/LocaleContextInjector.js +4 -12
  11. package/lib/MWaterAddRelatedFormComponent.js +3 -3
  12. package/lib/MWaterAddRelatedIndicatorComponent.d.ts +1 -4
  13. package/lib/MWaterAddRelatedIndicatorComponent.js +6 -6
  14. package/lib/MWaterCompleteTableSelectComponent.d.ts +5 -16
  15. package/lib/MWaterCompleteTableSelectComponent.js +36 -36
  16. package/lib/MWaterContextComponent.d.ts +4 -6
  17. package/lib/MWaterContextComponent.js +4 -13
  18. package/lib/MWaterLoaderComponent.d.ts +5 -3
  19. package/lib/MWaterLoaderComponent.js +2 -1
  20. package/lib/MWaterTableSelectComponent.d.ts +1 -4
  21. package/lib/MWaterTableSelectComponent.js +10 -12
  22. package/lib/UIComponents.d.ts +2 -2
  23. package/lib/UIComponents.js +4 -12
  24. package/lib/axes/AxisBuilder.d.ts +7 -4
  25. package/lib/axes/AxisBuilder.js +3 -1
  26. package/lib/axes/AxisComponent.d.ts +2 -5
  27. package/lib/axes/AxisComponent.js +1 -2
  28. package/lib/axes/ColorPaletteCollectionComponent.d.ts +5 -12
  29. package/lib/axes/ColorPaletteCollectionComponent.js +67 -36
  30. package/lib/dashboards/DashboardComponent.d.ts +4 -12
  31. package/lib/dashboards/DashboardComponent.js +18 -38
  32. package/lib/dashboards/DashboardDesign.d.ts +3 -3
  33. package/lib/dashboards/DashboardUpgrader.js +36 -1
  34. package/lib/dashboards/DashboardViewComponent.d.ts +5 -34
  35. package/lib/dashboards/DashboardViewComponent.js +109 -132
  36. package/lib/dashboards/FontStyleEditor.d.ts +8 -0
  37. package/lib/dashboards/FontStyleEditor.js +130 -0
  38. package/lib/dashboards/LayoutOptionsComponent.d.ts +0 -1
  39. package/lib/dashboards/LayoutOptionsComponent.js +211 -42
  40. package/lib/dashboards/ServerDashboardDataSource.d.ts +1 -2
  41. package/lib/dashboards/ServerDashboardDataSource.js +52 -33
  42. package/lib/dashboards/WidgetComponent.d.ts +3 -3
  43. package/lib/dashboards/WidgetComponent.js +3 -6
  44. package/lib/dashboards/WidgetDataSourcePrioritizer.d.ts +20 -0
  45. package/lib/dashboards/WidgetDataSourcePrioritizer.js +72 -0
  46. package/lib/dashboards/layoutOptions.d.ts +83 -0
  47. package/lib/dashboards/layoutOptions.js +436 -10
  48. package/lib/datagrids/DatagridDesign.d.ts +7 -6
  49. package/lib/datagrids/ServerDatagridDataSource.d.ts +7 -6
  50. package/lib/datagrids/ServerDatagridDataSource.js +87 -33
  51. package/lib/demo.js +3 -3
  52. package/lib/index.css +5 -0
  53. package/lib/index.d.ts +1 -1
  54. package/lib/index.js +0 -1
  55. package/lib/layouts/LayoutManager.d.ts +33 -29
  56. package/lib/layouts/LayoutManager.js +2 -8
  57. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +26 -57
  58. package/lib/layouts/blocks/BlocksDisplayComponent.js +122 -205
  59. package/lib/layouts/blocks/BlocksLayoutManager.d.ts +6 -22
  60. package/lib/layouts/blocks/BlocksLayoutManager.js +5 -14
  61. package/lib/layouts/blocks/HorizontalBlockComponent.d.ts +5 -4
  62. package/lib/layouts/blocks/HorizontalBlockComponent.js +5 -5
  63. package/lib/mWaterLoader.d.ts +2 -0
  64. package/lib/mWaterLoader.js +2 -1
  65. package/lib/maps/AddLayerComponent.d.ts +6 -8
  66. package/lib/maps/AddLayerComponent.js +6 -6
  67. package/lib/maps/BingLayer.js +10 -20
  68. package/lib/maps/BufferLayer.js +2 -1
  69. package/lib/maps/ChoroplethLayer.js +2 -1
  70. package/lib/maps/DirectMapDataSource.d.ts +5 -2
  71. package/lib/maps/DirectMapDataSource.js +2 -1
  72. package/lib/maps/EditPopupComponent.js +2 -1
  73. package/lib/maps/MapComponent.d.ts +1 -4
  74. package/lib/maps/MapComponent.js +3 -3
  75. package/lib/maps/MarkersLayer.js +30 -25
  76. package/lib/maps/RasterMapViewComponent.d.ts +1 -4
  77. package/lib/maps/RasterMapViewComponent.js +3 -3
  78. package/lib/maps/ServerMapDataSource.d.ts +2 -3
  79. package/lib/maps/ServerMapDataSource.js +5 -5
  80. package/lib/maps/VectorMapViewComponent.js +2 -1
  81. package/lib/maps/mapSymbols.js +2 -0
  82. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  83. package/lib/maps/vectorMaps.js +61 -55
  84. package/lib/quickfilter/QuickfiltersComponent.d.ts +1 -4
  85. package/lib/quickfilter/QuickfiltersComponent.js +3 -3
  86. package/lib/richtext/DropdownPaletteItem.d.ts +32 -0
  87. package/lib/richtext/DropdownPaletteItem.js +82 -0
  88. package/lib/richtext/FontColorPaletteItem.d.ts +1 -5
  89. package/lib/richtext/FontColorPaletteItem.js +32 -27
  90. package/lib/richtext/ItemsHtmlConverter.js +12 -3
  91. package/lib/richtext/RichTextComponent.d.ts +26 -52
  92. package/lib/richtext/RichTextComponent.js +166 -128
  93. package/lib/valueFormatter.js +6 -1
  94. package/lib/wellknown.d.ts +5 -0
  95. package/lib/wellknown.js +288 -0
  96. package/lib/widgets/DropdownWidgetComponent.d.ts +8 -25
  97. package/lib/widgets/DropdownWidgetComponent.js +48 -25
  98. package/lib/widgets/IFrameWidgetComponent.d.ts +1 -2
  99. package/lib/widgets/ImageWidgetComponent.d.ts +2 -3
  100. package/lib/widgets/MapWidget.d.ts +2 -0
  101. package/lib/widgets/MapWidget.js +2 -1
  102. package/lib/widgets/TOCWidget.js +2 -1
  103. package/lib/widgets/Widget.d.ts +2 -0
  104. package/lib/widgets/WidgetDataSource.d.ts +3 -1
  105. package/lib/widgets/charts/Chart.d.ts +0 -1
  106. package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
  107. package/lib/widgets/charts/ChartViewComponent.js +11 -3
  108. package/lib/widgets/charts/ChartWidget.d.ts +1 -62
  109. package/lib/widgets/charts/ChartWidget.js +4 -183
  110. package/lib/widgets/charts/ChartWidgetComponent.d.ts +51 -0
  111. package/lib/widgets/charts/ChartWidgetComponent.js +167 -0
  112. package/lib/widgets/charts/calendar/CalendarChartViewComponent.d.ts +1 -4
  113. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +4 -4
  114. package/lib/widgets/charts/layered/LayeredChart.d.ts +5 -10
  115. package/lib/widgets/charts/layered/LayeredChart.js +6 -7
  116. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +4 -2
  117. package/lib/widgets/charts/layered/LayeredChartCompiler.js +46 -32
  118. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +4 -0
  119. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +3 -0
  120. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +21 -3
  121. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +1 -2
  122. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +2 -1
  123. package/lib/widgets/charts/layered/LayeredChartViewComponent.d.ts +1 -4
  124. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +89 -38
  125. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +5 -112
  126. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.js +122 -166
  127. package/lib/widgets/charts/pivot/PivotChart.d.ts +6 -0
  128. package/lib/widgets/charts/pivot/PivotChart.js +47 -17
  129. package/lib/widgets/charts/pivot/PivotChartDesign.d.ts +11 -0
  130. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +1 -1
  131. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +1 -1
  132. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +2 -2
  133. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +20 -36
  134. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +0 -1
  135. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.d.ts +23 -2
  136. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.js +215 -181
  137. package/lib/widgets/charts/pivot/PivotChartUtils.d.ts +2 -2
  138. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +9 -28
  139. package/lib/widgets/charts/pivot/PivotChartViewComponent.js +20 -60
  140. package/lib/widgets/charts/table/TableChart.js +8 -4
  141. package/lib/widgets/charts/table/TableChartDesignerComponent.js +3 -3
  142. package/lib/widgets/charts/table/TableChartViewComponent.js +11 -11
  143. package/lib/widgets/text/TextComponent.d.ts +5 -12
  144. package/lib/widgets/text/TextComponent.js +19 -39
  145. package/lib/widgets/text/TextWidget.d.ts +2 -1
  146. package/lib/widgets/text/TextWidget.js +5 -1
  147. package/lib/widgets/text/TextWidgetComponent.d.ts +15 -3
  148. package/lib/widgets/text/TextWidgetComponent.js +76 -19
  149. package/lib/widgets/text/TextWidgetDesign.d.ts +13 -1
  150. package/lib/widgets/text/TextWidgetDesign.js +6 -0
  151. package/package.json +4 -4
  152. package/src/ColorComponent.tsx +177 -0
  153. package/src/ColorSchemeFactory.ts +12 -6
  154. package/src/CustomColorsContext.tsx +9 -0
  155. package/src/FiltersDesignerComponent.ts +3 -4
  156. package/src/LocaleContextInjector.tsx +14 -13
  157. package/src/MWaterAddRelatedFormComponent.ts +3 -3
  158. package/src/MWaterAddRelatedIndicatorComponent.ts +6 -6
  159. package/src/MWaterCompleteTableSelectComponent.tsx +36 -36
  160. package/src/MWaterContextComponent.tsx +8 -17
  161. package/src/MWaterLoaderComponent.ts +6 -3
  162. package/src/MWaterTableSelectComponent.tsx +11 -12
  163. package/src/{UIComponents.ts → UIComponents.tsx} +7 -15
  164. package/src/axes/AxisBuilder.ts +7 -5
  165. package/src/axes/AxisComponent.ts +3 -4
  166. package/src/axes/{ColorPaletteCollectionComponent.ts → ColorPaletteCollectionComponent.tsx} +87 -61
  167. package/src/dashboards/DashboardComponent.tsx +71 -107
  168. package/src/dashboards/DashboardDesign.ts +3 -3
  169. package/src/dashboards/DashboardUpgrader.ts +41 -1
  170. package/src/dashboards/DashboardViewComponent.tsx +313 -0
  171. package/src/dashboards/FontStyleEditor.tsx +166 -0
  172. package/src/dashboards/LayoutOptionsComponent.tsx +380 -75
  173. package/src/dashboards/ServerDashboardDataSource.ts +52 -33
  174. package/src/dashboards/WidgetComponent.tsx +6 -12
  175. package/src/dashboards/WidgetDataSourcePrioritizer.ts +82 -0
  176. package/src/dashboards/layoutOptions.tsx +581 -0
  177. package/src/datagrids/DatagridDesign.ts +8 -3
  178. package/src/datagrids/ServerDatagridDataSource.ts +106 -43
  179. package/src/demo.ts +3 -3
  180. package/src/index.css +5 -0
  181. package/src/index.ts +1 -1
  182. package/src/layouts/LayoutManager.ts +44 -42
  183. package/src/layouts/blocks/BlocksDisplayComponent.tsx +498 -0
  184. package/src/layouts/blocks/BlocksLayoutManager.ts +6 -15
  185. package/src/layouts/blocks/HorizontalBlockComponent.ts +9 -8
  186. package/src/mWaterLoader.ts +4 -1
  187. package/src/maps/AddLayerComponent.ts +9 -9
  188. package/src/maps/BingLayer.ts +16 -26
  189. package/src/maps/BufferLayer.ts +2 -1
  190. package/src/maps/ChoroplethLayer.ts +2 -1
  191. package/src/maps/DirectMapDataSource.ts +12 -3
  192. package/src/maps/EditPopupComponent.ts +2 -1
  193. package/src/maps/MapComponent.ts +3 -3
  194. package/src/maps/MarkersLayer.ts +38 -41
  195. package/src/maps/RasterMapViewComponent.ts +3 -3
  196. package/src/maps/ServerMapDataSource.ts +7 -7
  197. package/src/maps/VectorMapViewComponent.tsx +2 -1
  198. package/src/maps/mapSymbols.ts +2 -0
  199. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  200. package/src/maps/vectorMaps.tsx +79 -74
  201. package/src/quickfilter/QuickfiltersComponent.ts +3 -3
  202. package/src/richtext/DropdownPaletteItem.tsx +144 -0
  203. package/src/richtext/FontColorPaletteItem.tsx +160 -0
  204. package/src/richtext/ItemsHtmlConverter.ts +15 -5
  205. package/src/richtext/RichTextComponent.tsx +274 -232
  206. package/src/valueFormatter.ts +5 -1
  207. package/src/wellknown.ts +286 -0
  208. package/src/widgets/DropdownWidgetComponent.tsx +75 -0
  209. package/src/widgets/MapWidget.ts +5 -2
  210. package/src/widgets/TOCWidget.ts +2 -1
  211. package/src/widgets/Widget.ts +3 -0
  212. package/src/widgets/WidgetDataSource.ts +3 -1
  213. package/src/widgets/charts/Chart.ts +1 -1
  214. package/src/widgets/charts/ChartViewComponent.ts +16 -3
  215. package/src/widgets/charts/ChartWidget.ts +3 -275
  216. package/src/widgets/charts/ChartWidgetComponent.tsx +281 -0
  217. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +4 -4
  218. package/src/widgets/charts/layered/LayeredChart.ts +4 -6
  219. package/src/widgets/charts/layered/LayeredChartCompiler.ts +80 -63
  220. package/src/widgets/charts/layered/LayeredChartDesign.ts +7 -1
  221. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +43 -10
  222. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +6 -6
  223. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +140 -88
  224. package/src/widgets/charts/pivot/IntersectionDesignerComponent.tsx +305 -221
  225. package/src/widgets/charts/pivot/PivotChart.ts +56 -18
  226. package/src/widgets/charts/pivot/PivotChartDesign.ts +12 -0
  227. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +4 -3
  228. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +39 -76
  229. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +0 -1
  230. package/src/widgets/charts/pivot/PivotChartQueryBuilder.ts +230 -189
  231. package/src/widgets/charts/pivot/PivotChartUtils.ts +4 -4
  232. package/src/widgets/charts/pivot/{PivotChartViewComponent.ts → PivotChartViewComponent.tsx} +86 -89
  233. package/src/widgets/charts/table/TableChart.ts +8 -4
  234. package/src/widgets/charts/table/TableChartDesignerComponent.ts +4 -4
  235. package/src/widgets/charts/table/TableChartViewComponent.ts +13 -14
  236. package/src/widgets/text/TextComponent.tsx +47 -49
  237. package/src/widgets/text/TextWidget.ts +8 -3
  238. package/src/widgets/text/TextWidgetComponent.tsx +249 -0
  239. package/src/widgets/text/TextWidgetDesign.ts +22 -1
  240. package/src/ColorComponent.ts +0 -117
  241. package/src/dashboards/DashboardViewComponent.ts +0 -303
  242. package/src/dashboards/layoutOptions.ts +0 -40
  243. package/src/layout-styles.css +0 -263
  244. package/src/layouts/blocks/BlocksDisplayComponent.ts +0 -461
  245. package/src/layouts/grid/GridLayoutComponent.ts +0 -67
  246. package/src/layouts/grid/GridLayoutManager.ts +0 -185
  247. package/src/layouts/grid/LegoLayoutEngine.ts +0 -142
  248. package/src/layouts/grid/PaletteItemComponent.ts +0 -28
  249. package/src/layouts/grid/README.md +0 -14
  250. package/src/layouts/grid/WidgetContainerComponent.ts +0 -420
  251. package/src/richtext/FontColorPaletteItem.ts +0 -172
  252. package/src/richtext/FontSizePaletteItem.ts +0 -110
  253. package/src/widgets/DropdownWidgetComponent.ts +0 -78
  254. package/src/widgets/text/TextWidgetComponent.ts +0 -120
@@ -4,10 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LayoutOptionsComponent = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
7
8
  const react_1 = __importDefault(require("react"));
8
9
  const react_2 = require("react");
9
10
  const bootstrap_1 = require("@mwater/react-library/lib/bootstrap");
10
11
  const layoutOptions_1 = require("./layoutOptions");
12
+ const ColorComponent_1 = __importDefault(require("../ColorComponent"));
13
+ const FontStyleEditor_1 = require("./FontStyleEditor");
14
+ const immer_1 = __importDefault(require("immer"));
15
+ const file_saver_1 = __importDefault(require("file-saver"));
11
16
  const sizeOptions = [
12
17
  { value: { width: 360, height: 640 }, label: "Phone (360x640)" },
13
18
  { value: { width: 768, height: 1024 }, label: "Tablet (768x1024)" },
@@ -20,45 +25,20 @@ function LayoutOptionsComponent(props) {
20
25
  function setLayoutOptions(layoutOptions) {
21
26
  props.onDesignChange({ ...props.design, layoutOptions });
22
27
  }
23
- function handleResetDefaults() {
24
- props.onDesignChange({ ...props.design, layoutOptions: (0, layoutOptions_1.getDefaultLayoutOptions)(props.design.style) });
25
- }
26
- return (react_1.default.createElement("div", { style: { display: "grid", gridTemplateRows: "auto 1fr", gridTemplateColumns: "auto 1fr", height: "100%" } },
27
- react_1.default.createElement("div", { style: { padding: 5, gridRow: "1 / 3" } },
28
- react_1.default.createElement("div", { key: "back" },
29
- react_1.default.createElement("button", { className: "btn btn-sm btn-link", onClick: props.onClose },
30
- react_1.default.createElement("i", { className: "fa fa-arrow-left" }),
31
- " Close")),
32
- react_1.default.createElement("br", null),
28
+ const isCustomized = !lodash_1.default.isEqual(layoutOptions, (0, layoutOptions_1.getDefaultLayoutOptions)(props.design.style));
29
+ return (react_1.default.createElement("div", { style: { display: "grid", gridTemplateRows: "auto 1fr", gridTemplateColumns: "360px 1fr", height: "100%" } },
30
+ react_1.default.createElement("div", { style: { padding: "5px 10px 5px 0px", gridRow: "1 / 3", overflowY: "auto" } },
31
+ react_1.default.createElement("h5", null, "Theme"),
33
32
  react_1.default.createElement(ThemeToggle, { theme: props.design.style, onChange: (theme) => {
33
+ if (isCustomized) {
34
+ if (!confirm("Are you sure you want to change the theme? Your customizations will be lost."))
35
+ return;
36
+ }
34
37
  props.onDesignChange({ ...props.design, style: theme, layoutOptions: (0, layoutOptions_1.getDefaultLayoutOptions)(theme) });
35
- } }),
38
+ }, isCustomized: isCustomized }),
36
39
  react_1.default.createElement("br", null),
37
- react_1.default.createElement("h4", null, "Advanced"),
38
- react_1.default.createElement("a", { className: "btn btn-sm btn-link", style: { float: "right" }, onClick: handleResetDefaults }, "Reset to Defaults"),
39
- react_1.default.createElement(bootstrap_1.FormGroup, { label: "Collapse to Single Column" },
40
- react_1.default.createElement(WidthSelector, { value: layoutOptions.collapseColumnsWidth, onChange: (collapseColumnsWidth) => {
41
- setLayoutOptions({ ...layoutOptions, collapseColumnsWidth });
42
- }, sign: "< " })),
43
- react_1.default.createElement(bootstrap_1.FormGroup, { label: "Hide Quickfilters" },
44
- react_1.default.createElement(WidthSelector, { value: layoutOptions.hideQuickfiltersWidth, onChange: (hideQuickfiltersWidth) => {
45
- setLayoutOptions({ ...layoutOptions, hideQuickfiltersWidth });
46
- }, sign: "< " })),
47
- react_1.default.createElement(bootstrap_1.FormGroup, { label: "Minimum Width (before scrolling or scaling)" },
48
- react_1.default.createElement(WidthSelector, { value: layoutOptions.minimumWidth, onChange: (minimumWidth) => {
49
- setLayoutOptions({ ...layoutOptions, minimumWidth });
50
- }, sign: "< " }),
51
- react_1.default.createElement(bootstrap_1.FormGroup, { label: "When Below Minimum Width" },
52
- react_1.default.createElement(bootstrap_1.Toggle, { value: layoutOptions.belowMinimumWidth, onChange: (belowMinimumWidth) => {
53
- setLayoutOptions({ ...layoutOptions, belowMinimumWidth: belowMinimumWidth });
54
- }, options: [
55
- { value: "scroll", label: "Scroll" },
56
- { value: "scale", label: "Scale" }
57
- ] }))),
58
- react_1.default.createElement(bootstrap_1.FormGroup, { label: "Maximum Width (before padding)" },
59
- react_1.default.createElement(WidthSelector, { value: layoutOptions.maximumWidth, onChange: (maximumWidth) => {
60
- setLayoutOptions({ ...layoutOptions, maximumWidth });
61
- }, sign: "> " }))),
40
+ react_1.default.createElement(bootstrap_1.CollapsibleSection, { label: react_1.default.createElement("h5", { style: { display: "inline-block" } }, "Customize Layout"), initiallyOpen: isCustomized },
41
+ react_1.default.createElement(CustomizeLayout, { layoutOptions: layoutOptions, onLayoutOptionsChange: setLayoutOptions }))),
62
42
  react_1.default.createElement("div", { style: { textAlign: "center", padding: 3 } },
63
43
  react_1.default.createElement("span", { className: "text-muted" }, "Preview As:\u00A0"),
64
44
  react_1.default.createElement(bootstrap_1.Toggle, { value: previewSize, onChange: setPreviewSize, size: "xs", options: sizeOptions.map((so, index) => ({ value: index, label: so.label })) })),
@@ -84,7 +64,7 @@ function LayoutOptionsComponent(props) {
84
64
  exports.LayoutOptionsComponent = LayoutOptionsComponent;
85
65
  function ThemeToggle(props) {
86
66
  function renderStyleItem(theme) {
87
- const isActive = (props.theme || "default") == theme;
67
+ const isActive = props.isCustomized ? theme == "custom" : (props.theme || "default") == theme;
88
68
  if (theme == "default") {
89
69
  return (react_1.default.createElement("a", { key: theme, className: isActive ? "list-group-item active" : "list-group-item", onClick: props.onChange.bind(null, "default") },
90
70
  react_1.default.createElement("div", null, "Classic Dashboard"),
@@ -100,13 +80,202 @@ function ThemeToggle(props) {
100
80
  react_1.default.createElement("div", null, "Story"),
101
81
  react_1.default.createElement("div", { style: { opacity: 0.6 } }, "Ideal for data-driven storytelling with lots of text")));
102
82
  }
83
+ if (theme == "custom") {
84
+ return (react_1.default.createElement("a", { key: theme, className: isActive ? "list-group-item active" : "list-group-item" },
85
+ react_1.default.createElement("div", null, "Custom"),
86
+ react_1.default.createElement("div", { style: { opacity: 0.6 } }, "Customized theme")));
87
+ }
103
88
  return null;
104
89
  }
105
- return (react_1.default.createElement(bootstrap_1.FormGroup, { label: "Theme" },
106
- react_1.default.createElement("div", { className: "list-group" },
107
- renderStyleItem("default"),
108
- renderStyleItem("greybg"),
109
- renderStyleItem("story"))));
90
+ return (react_1.default.createElement("div", { className: "list-group" },
91
+ renderStyleItem("default"),
92
+ renderStyleItem("greybg"),
93
+ renderStyleItem("story"),
94
+ props.isCustomized && renderStyleItem("custom")));
95
+ }
96
+ function CustomizeLayout(props) {
97
+ const { layoutOptions, onLayoutOptionsChange } = props;
98
+ const handleDownloadTheme = () => {
99
+ const blob = new Blob([JSON.stringify(layoutOptions, null, 2)], { type: "application/json" });
100
+ file_saver_1.default.saveAs(blob, "custom_theme.theme");
101
+ };
102
+ const handleUploadTheme = (event) => {
103
+ const file = event.target.files?.[0];
104
+ if (file) {
105
+ const reader = new FileReader();
106
+ reader.onload = (e) => {
107
+ try {
108
+ const uploadedTheme = JSON.parse(e.target?.result);
109
+ onLayoutOptionsChange(uploadedTheme);
110
+ }
111
+ catch (error) {
112
+ alert("Invalid theme file");
113
+ }
114
+ };
115
+ reader.readAsText(file);
116
+ }
117
+ };
118
+ return (react_1.default.createElement("div", null,
119
+ react_1.default.createElement(bootstrap_1.CollapsiblePanel, { title: "Text" },
120
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Title" },
121
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.titleWidgetFont, onChange: (titleWidgetFont) => {
122
+ onLayoutOptionsChange({ ...layoutOptions, titleWidgetFont });
123
+ } })),
124
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Heading H1" },
125
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.textWidgetH1Font, onChange: (textWidgetH1Font) => {
126
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH1Font });
127
+ } }),
128
+ react_1.default.createElement("div", { className: "mt-1" },
129
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Top Margin:", horizontal: true, labelMuted: true },
130
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.textWidgetH1MarginTop, onChange: (textWidgetH1MarginTop) => {
131
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH1MarginTop: textWidgetH1MarginTop });
132
+ } })))),
133
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Heading H2" },
134
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.textWidgetH2Font, onChange: (textWidgetH2Font) => {
135
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH2Font });
136
+ } }),
137
+ react_1.default.createElement("div", { className: "mt-1" },
138
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Top Margin:", horizontal: true, labelMuted: true },
139
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.textWidgetH2MarginTop, onChange: (textWidgetH2MarginTop) => {
140
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH2MarginTop: textWidgetH2MarginTop });
141
+ } })))),
142
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Text" },
143
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.textWidgetFont, onChange: (textWidgetFont) => {
144
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetFont });
145
+ } }),
146
+ react_1.default.createElement("div", { className: "mt-1" },
147
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Line Height:", horizontal: true, labelMuted: true },
148
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.textWidgetLineHeight, onChange: (textWidgetLineHeight) => {
149
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetLineHeight: textWidgetLineHeight });
150
+ }, allowDefault: true, defaultLabel: "Default" })),
151
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Paragraph Spacing:", horizontal: true, labelMuted: true },
152
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.textWidgetParagraphSpacing, onChange: (textWidgetParagraphSpacing) => {
153
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetParagraphSpacing: textWidgetParagraphSpacing });
154
+ } })))),
155
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "List Line Height:", horizontal: true },
156
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.textWidgetListLineHeight, onChange: (textWidgetListLineHeight) => {
157
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetListLineHeight: textWidgetListLineHeight });
158
+ }, allowDefault: true, defaultLabel: "Default" })),
159
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Chart Header Font" },
160
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.widgetHeaderFont, onChange: (widgetHeaderFont) => {
161
+ onLayoutOptionsChange({ ...layoutOptions, widgetHeaderFont });
162
+ } })),
163
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Chart Footer Font" },
164
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.widgetFooterFont, onChange: (widgetFooterFont) => {
165
+ onLayoutOptionsChange({ ...layoutOptions, widgetFooterFont });
166
+ } })),
167
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Chart Font" },
168
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.chartFont, onChange: (chartFont) => {
169
+ onLayoutOptionsChange({ ...layoutOptions, chartFont });
170
+ } })),
171
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Table Font" },
172
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.tableFont, onChange: (tableFont) => {
173
+ onLayoutOptionsChange({ ...layoutOptions, tableFont });
174
+ } })),
175
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Pivot Table Font" },
176
+ react_1.default.createElement(FontStyleEditor_1.FontStyleEditor, { value: layoutOptions.pivotTableFont, onChange: (pivotTableFont) => {
177
+ onLayoutOptionsChange({ ...layoutOptions, pivotTableFont });
178
+ } }))),
179
+ react_1.default.createElement(bootstrap_1.CollapsiblePanel, { title: "Spacing" },
180
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Outer Padding:", horizontal: true },
181
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.outerPadding, onChange: (outerPadding) => {
182
+ onLayoutOptionsChange({ ...layoutOptions, outerPadding: outerPadding });
183
+ } })),
184
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Block Margins" },
185
+ react_1.default.createElement(SpacingInput, { value: layoutOptions.blockMargin, onChange: (blockMargin) => {
186
+ onLayoutOptionsChange({ ...layoutOptions, blockMargin });
187
+ } })),
188
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Block Padding" },
189
+ react_1.default.createElement(SpacingInput, { value: layoutOptions.blockPadding, onChange: (blockPadding) => {
190
+ onLayoutOptionsChange({ ...layoutOptions, blockPadding });
191
+ } })),
192
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Block Border Radius:", horizontal: true },
193
+ react_1.default.createElement(PixelsInput, { value: layoutOptions.blockBorderRadius, onChange: (blockBorderRadius) => {
194
+ onLayoutOptionsChange({ ...layoutOptions, blockBorderRadius: blockBorderRadius });
195
+ } }))),
196
+ react_1.default.createElement(bootstrap_1.CollapsiblePanel, { title: "Colors" },
197
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Background Color:", horizontal: true },
198
+ react_1.default.createElement(ColorComponent_1.default, { color: layoutOptions.backgroundColor, onChange: (backgroundColor) => {
199
+ onLayoutOptionsChange({ ...layoutOptions, backgroundColor: backgroundColor ?? "white" });
200
+ } })),
201
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Block Background Color:", horizontal: true },
202
+ react_1.default.createElement(ColorComponent_1.default, { color: layoutOptions.blockBackgroundColor, onChange: (blockBackgroundColor) => {
203
+ onLayoutOptionsChange({ ...layoutOptions, blockBackgroundColor: blockBackgroundColor ?? "white" });
204
+ } })),
205
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Custom Colors" },
206
+ react_1.default.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: '5px' } }, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((colorIndex) => (react_1.default.createElement(ColorComponent_1.default, { key: colorIndex, color: layoutOptions.customColors[colorIndex], onChange: (color) => {
207
+ onLayoutOptionsChange((0, immer_1.default)(layoutOptions, (draft) => {
208
+ draft.customColors[colorIndex] = color;
209
+ }));
210
+ } })))))),
211
+ react_1.default.createElement(bootstrap_1.CollapsiblePanel, { title: "Responsive Layout" },
212
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Collapse to Single Column" },
213
+ react_1.default.createElement(WidthSelector, { value: layoutOptions.collapseColumnsWidth, onChange: (collapseColumnsWidth) => {
214
+ onLayoutOptionsChange({ ...layoutOptions, collapseColumnsWidth });
215
+ }, sign: "< " })),
216
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Hide Quickfilters" },
217
+ react_1.default.createElement(WidthSelector, { value: layoutOptions.hideQuickfiltersWidth, onChange: (hideQuickfiltersWidth) => {
218
+ onLayoutOptionsChange({ ...layoutOptions, hideQuickfiltersWidth });
219
+ }, sign: "< " })),
220
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Minimum Width (before scrolling or scaling)" },
221
+ react_1.default.createElement(WidthSelector, { value: layoutOptions.minimumWidth, onChange: (minimumWidth) => {
222
+ onLayoutOptionsChange({ ...layoutOptions, minimumWidth });
223
+ }, sign: "< " }),
224
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "When Below Minimum Width" },
225
+ react_1.default.createElement(bootstrap_1.Toggle, { value: layoutOptions.belowMinimumWidth, onChange: (belowMinimumWidth) => {
226
+ onLayoutOptionsChange({ ...layoutOptions, belowMinimumWidth: belowMinimumWidth });
227
+ }, size: "sm", options: [
228
+ { value: "scroll", label: "Scroll" },
229
+ { value: "scale", label: "Scale" }
230
+ ] }))),
231
+ react_1.default.createElement(bootstrap_1.FormGroup, { label: "Maximum Width (before padding)" },
232
+ react_1.default.createElement(WidthSelector, { value: layoutOptions.maximumWidth, onChange: (maximumWidth) => {
233
+ onLayoutOptionsChange({ ...layoutOptions, maximumWidth });
234
+ }, sign: "> " })),
235
+ react_1.default.createElement(bootstrap_1.Checkbox, { value: layoutOptions.collapseSpacers, onChange: (collapseSpacers) => {
236
+ onLayoutOptionsChange({ ...layoutOptions, collapseSpacers });
237
+ } }, "Collapse Spacers on Mobile")),
238
+ react_1.default.createElement(bootstrap_1.CollapsiblePanel, { title: "Download/Upload Theme", initiallyClosed: true },
239
+ react_1.default.createElement("div", { className: "mb-2 text-muted" }, "Download or upload a custom theme to use for this dashboard. This saves the current theme as a theme file that you can then use on other dashboards by uploading it there."),
240
+ react_1.default.createElement("div", { style: { display: "flex", flexDirection: "column", marginTop: "10px", gap: "10px" } },
241
+ react_1.default.createElement("button", { className: "btn btn-sm btn-secondary", onClick: handleDownloadTheme },
242
+ react_1.default.createElement("i", { className: "fas fa-download" }),
243
+ " Download Custom Theme"),
244
+ react_1.default.createElement("label", { className: "btn btn-sm btn-secondary" },
245
+ react_1.default.createElement("i", { className: "fas fa-upload" }),
246
+ " Upload Custom Theme",
247
+ react_1.default.createElement("input", { type: "file", accept: ".theme", style: { display: "none" }, onChange: handleUploadTheme }))))));
248
+ }
249
+ function SpacingInput(props) {
250
+ return (react_1.default.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', width: '100%' } },
251
+ react_1.default.createElement("div", null, "Top"),
252
+ react_1.default.createElement("div", null, "Bottom"),
253
+ react_1.default.createElement("div", null, "Left"),
254
+ react_1.default.createElement("div", null, "Right"),
255
+ react_1.default.createElement(PixelsInput, { value: props.value.top, onChange: (top) => props.onChange({ ...props.value, top: top }) }),
256
+ react_1.default.createElement(PixelsInput, { value: props.value.bottom, onChange: (bottom) => props.onChange({ ...props.value, bottom: bottom }) }),
257
+ react_1.default.createElement(PixelsInput, { value: props.value.left, onChange: (left) => props.onChange({ ...props.value, left: left }) }),
258
+ react_1.default.createElement(PixelsInput, { value: props.value.right, onChange: (right) => props.onChange({ ...props.value, right: right }) })));
259
+ }
260
+ function PixelsInput(props) {
261
+ const options = [
262
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40
263
+ ];
264
+ return (react_1.default.createElement("div", { className: "dropdown" },
265
+ react_1.default.createElement("a", { className: "dropdown-toggle", type: "button", id: "pixelsInputDropdown", "data-bs-toggle": "dropdown", "aria-expanded": "false" }, props.value === null ? (props.defaultLabel || "Default") : `${props.value}px`),
266
+ react_1.default.createElement("ul", { className: "dropdown-menu", "aria-labelledby": "pixelsInputDropdown" },
267
+ props.allowDefault && (react_1.default.createElement("li", { key: "default" },
268
+ react_1.default.createElement("a", { className: "dropdown-item", href: "#", onClick: (e) => {
269
+ e.preventDefault();
270
+ props.onChange(null);
271
+ } }, props.defaultLabel || "Default"))),
272
+ options.map(option => (react_1.default.createElement("li", { key: option },
273
+ react_1.default.createElement("a", { className: "dropdown-item", href: "#", onClick: (e) => {
274
+ e.preventDefault();
275
+ props.onChange(option);
276
+ } },
277
+ option,
278
+ "px")))))));
110
279
  }
111
280
  function WidthSelector(props) {
112
281
  return (react_1.default.createElement(bootstrap_1.Select, { value: props.value, onChange: props.onChange, nullLabel: "N/A", options: [
@@ -1,4 +1,3 @@
1
- /// <reference types="jquery" />
2
1
  import { DataSource, Expr } from "@mwater/expressions";
3
2
  import { JsonQLFilter } from "../JsonQLFilter";
4
3
  import { QuickfiltersDataSource } from "../quickfilter/QuickfiltersDataSource";
@@ -42,7 +41,7 @@ declare class ServerQuickfilterDataSource implements QuickfiltersDataSource {
42
41
  declare class ServerWidgetDataSource {
43
42
  options: ServerWidgetDataSourceOptions;
44
43
  constructor(options: ServerWidgetDataSourceOptions);
45
- getData(design: any, filters: JsonQLFilter[], callback: (error: any, data?: any) => void): JQuery.jqXHR<any>;
44
+ getData(design: any, filters: JsonQLFilter[], callback: (error: any, data?: any) => void): void;
46
45
  getMapDataSource(design: any): ServerWidgetMapDataSource;
47
46
  getImageUrl(imageId: string, height?: number): string;
48
47
  }
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
- const jquery_1 = __importDefault(require("jquery"));
8
7
  const expressions_1 = require("@mwater/expressions");
9
8
  const querystring_1 = __importDefault(require("querystring"));
10
9
  const LayerFactory_1 = __importDefault(require("../maps/LayerFactory"));
@@ -55,18 +54,23 @@ class ServerQuickfilterDataSource {
55
54
  const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000);
56
55
  headers["Cache-Control"] = `max-age=${seconds}`;
57
56
  }
58
- jquery_1.default.ajax({
59
- dataType: "json",
57
+ fetch(url, {
60
58
  method: "GET",
61
- url,
62
- headers
59
+ headers: headers
60
+ })
61
+ .then(async (response) => {
62
+ if (!response.ok) {
63
+ const text = await response.text();
64
+ throw new Error(text);
65
+ }
66
+ return response.json();
63
67
  })
64
- .done((data) => {
68
+ .then(data => {
65
69
  return callback(null, data);
66
70
  })
67
- .fail((xhr) => {
68
- console.log(xhr.responseText);
69
- return callback(new Error(xhr.responseText));
71
+ .catch(error => {
72
+ console.log(error.message);
73
+ return callback(error);
70
74
  });
71
75
  }
72
76
  }
@@ -102,18 +106,23 @@ class ServerWidgetDataSource {
102
106
  const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000);
103
107
  headers["Cache-Control"] = `max-age=${seconds}`;
104
108
  }
105
- return jquery_1.default.ajax({
106
- dataType: "json",
109
+ fetch(url, {
107
110
  method: "GET",
108
- url,
109
- headers
111
+ headers: headers
112
+ })
113
+ .then(async (response) => {
114
+ if (!response.ok) {
115
+ const text = await response.text();
116
+ throw new Error(text);
117
+ }
118
+ return response.json();
110
119
  })
111
- .done((data) => {
120
+ .then(data => {
112
121
  return callback(null, data);
113
122
  })
114
- .fail((xhr) => {
115
- console.log(xhr.responseText);
116
- return callback(new Error(xhr.responseText));
123
+ .catch(error => {
124
+ console.log(error.message);
125
+ return callback(error);
117
126
  });
118
127
  }
119
128
  // For map widgets, the following is required
@@ -170,18 +179,23 @@ class ServerWidgetMapDataSource {
170
179
  const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000);
171
180
  headers["Cache-Control"] = `max-age=${seconds}`;
172
181
  }
173
- jquery_1.default.ajax({
174
- dataType: "json",
182
+ fetch(url, {
175
183
  method: "GET",
176
- url,
177
184
  headers
178
185
  })
179
- .done((data) => {
186
+ .then(async (response) => {
187
+ if (!response.ok) {
188
+ const text = await response.text();
189
+ throw new Error(text);
190
+ }
191
+ return response.json();
192
+ })
193
+ .then(data => {
180
194
  return callback(null, data);
181
195
  })
182
- .fail((xhr) => {
183
- console.log(xhr.responseText);
184
- return callback(new Error(xhr.responseText));
196
+ .catch(error => {
197
+ console.log(error.message);
198
+ return callback(error);
185
199
  });
186
200
  }
187
201
  getQuickfiltersDataSource() {
@@ -356,18 +370,23 @@ class ServerWidgetLayerPopupWidgetDataSource {
356
370
  const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000);
357
371
  headers["Cache-Control"] = `max-age=${seconds}`;
358
372
  }
359
- jquery_1.default.ajax({
360
- dataType: "json",
373
+ fetch(url, {
361
374
  method: "GET",
362
- url,
363
- headers
375
+ headers: headers
364
376
  })
365
- .done((data) => {
366
- return callback(null, data);
377
+ .then(async (response) => {
378
+ if (!response.ok) {
379
+ const text = await response.text();
380
+ throw new Error(text);
381
+ }
382
+ return response.json();
383
+ })
384
+ .then(data => {
385
+ callback(null, data);
367
386
  })
368
- .fail((xhr) => {
369
- console.log(xhr.responseText);
370
- return callback(new Error(xhr.responseText));
387
+ .catch(error => {
388
+ console.log(error.message);
389
+ callback(error);
371
390
  });
372
391
  }
373
392
  /** For map widgets, the following is required */
@@ -2,7 +2,7 @@
2
2
  import { Schema, DataSource } from "@mwater/expressions";
3
3
  import { JsonQLFilter } from "../JsonQLFilter";
4
4
  import { WidgetScope } from "../WidgetScope";
5
- import DashboardDataSource from "./DashboardDataSource";
5
+ import { WidgetDataSource } from "../widgets/WidgetDataSource";
6
6
  /**
7
7
  * Component which renders a widget and ensures that props do not change
8
8
  * unnecessarily.
@@ -18,8 +18,8 @@ export declare function WidgetComponent(props: {
18
18
  onDesignChange?: {
19
19
  (design: object): void;
20
20
  } | null;
21
- /** Data source for dashboard */
22
- dashboardDataSource: DashboardDataSource;
21
+ /** Data source for widget */
22
+ widgetDataSource: WidgetDataSource;
23
23
  /** schema to use **/
24
24
  schema: Schema;
25
25
  /** data source to use. Only used when designing, for display uses widgetDataSource **/
@@ -11,10 +11,6 @@ const WidgetFactory_1 = __importDefault(require("../widgets/WidgetFactory"));
11
11
  * unnecessarily.
12
12
  */
13
13
  function WidgetComponent(props) {
14
- // Get and stabilize widget data source
15
- // TODO!!! There is a global problem with DashboardDataSources being re-created on each render.
16
- // TODO!!! This now only uses the type of the dashboard data source. They should be more stable in the future.
17
- const widgetDataSource = (0, react_1.useMemo)(() => props.dashboardDataSource.getWidgetDataSource(props.type, props.id), [props.dashboardDataSource.constructor, props.type, props.id, props.schema, props.dataSource, props.refreshKey]);
18
14
  const widget = WidgetFactory_1.default.createWidget(props.type);
19
15
  // Stabilize functions
20
16
  const onDesignChange = useStabilizeFunction(props.onDesignChange);
@@ -27,7 +23,7 @@ function WidgetComponent(props) {
27
23
  return widget.createViewElement({
28
24
  schema: props.schema,
29
25
  dataSource: props.dataSource,
30
- widgetDataSource,
26
+ widgetDataSource: props.widgetDataSource,
31
27
  design: props.design,
32
28
  scope,
33
29
  filters,
@@ -40,7 +36,8 @@ function WidgetComponent(props) {
40
36
  namedStrings: props.namedStrings,
41
37
  tocEntries: props.tocEntries,
42
38
  onScrollToTOCEntry: props.onScrollToTOCEntry,
43
- widgetRef
39
+ widgetRef,
40
+ refreshKey: props.refreshKey
44
41
  });
45
42
  }
46
43
  exports.WidgetComponent = WidgetComponent;
@@ -0,0 +1,20 @@
1
+ import DashboardDataSource from './DashboardDataSource';
2
+ import { WidgetDataSource } from '../widgets/WidgetDataSource';
3
+ /**
4
+ * A class that prioritizes widget data sources based on the priority of the data source
5
+ * and ensures that only N requests is made at a time for a given widget data source.
6
+ */
7
+ export declare class WidgetDataSourcePrioritizer {
8
+ private queue;
9
+ private dashboardDataSource;
10
+ /**
11
+ * Key is widget type + ":" + widget id + ":" + priority
12
+ */
13
+ widgetDataSources: {
14
+ [key: string]: WidgetDataSource;
15
+ };
16
+ constructor(dashboardDataSource: DashboardDataSource, concurrency: number);
17
+ /** Get a widget data source with the given priority */
18
+ getWidgetDataSource(widgetType: string, widgetId: string, priority: number): WidgetDataSource;
19
+ cancel(): void;
20
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WidgetDataSourcePrioritizer = void 0;
7
+ const p_queue_1 = __importDefault(require("p-queue"));
8
+ /**
9
+ * A class that prioritizes widget data sources based on the priority of the data source
10
+ * and ensures that only N requests is made at a time for a given widget data source.
11
+ */
12
+ class WidgetDataSourcePrioritizer {
13
+ queue;
14
+ dashboardDataSource;
15
+ /**
16
+ * Key is widget type + ":" + widget id + ":" + priority
17
+ */
18
+ widgetDataSources;
19
+ constructor(dashboardDataSource, concurrency) {
20
+ this.dashboardDataSource = dashboardDataSource;
21
+ this.queue = new p_queue_1.default({ concurrency: concurrency });
22
+ this.widgetDataSources = {};
23
+ }
24
+ /** Get a widget data source with the given priority */
25
+ getWidgetDataSource(widgetType, widgetId, priority) {
26
+ let widgetDataSource = this.widgetDataSources[widgetType + ":" + widgetId + ":" + priority];
27
+ if (!widgetDataSource) {
28
+ const innerWidgetDataSource = this.dashboardDataSource.getWidgetDataSource(widgetType, widgetId);
29
+ widgetDataSource = {
30
+ getData: (design, filters, callback) => {
31
+ const task = () => new Promise((resolve, reject) => {
32
+ innerWidgetDataSource.getData(design, filters, (error, data) => {
33
+ if (error) {
34
+ callback(error);
35
+ reject(error);
36
+ }
37
+ else {
38
+ callback(null, data);
39
+ resolve(data);
40
+ }
41
+ });
42
+ });
43
+ // Create an abort controller for this task
44
+ const taskAbortController = new AbortController();
45
+ // Queue the task and handle errors
46
+ this.queue.add(task, { priority: priority, signal: taskAbortController.signal }).catch((e) => {
47
+ console.log("Task failed", e);
48
+ callback(e);
49
+ });
50
+ return taskAbortController;
51
+ },
52
+ /** Get the url to download an image (by id from an image or imagelist column)
53
+ * Height, if specified, is minimum height needed. May return larger image */
54
+ getImageUrl: (imageId, height) => {
55
+ return innerWidgetDataSource.getImageUrl(imageId, height);
56
+ }
57
+ };
58
+ if (innerWidgetDataSource.getMapDataSource) {
59
+ widgetDataSource.getMapDataSource = (design) => {
60
+ return innerWidgetDataSource.getMapDataSource(design);
61
+ };
62
+ }
63
+ this.widgetDataSources[widgetType + ":" + widgetId + ":" + priority] = widgetDataSource;
64
+ }
65
+ return widgetDataSource;
66
+ }
67
+ cancel() {
68
+ // Clear the queue
69
+ this.queue.clear();
70
+ }
71
+ }
72
+ exports.WidgetDataSourcePrioritizer = WidgetDataSourcePrioritizer;