@mwater/visualization 5.1.0 → 5.3.0

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 (305) 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/GlobalFilter.d.ts +13 -0
  10. package/lib/GlobalFilter.js +2 -0
  11. package/lib/LocaleContextInjector.d.ts +5 -11
  12. package/lib/LocaleContextInjector.js +4 -12
  13. package/lib/MWaterAddRelatedFormComponent.js +3 -3
  14. package/lib/MWaterAddRelatedIndicatorComponent.d.ts +1 -4
  15. package/lib/MWaterAddRelatedIndicatorComponent.js +6 -6
  16. package/lib/MWaterCompleteTableSelectComponent.d.ts +7 -25
  17. package/lib/MWaterCompleteTableSelectComponent.js +36 -36
  18. package/lib/MWaterContextComponent.d.ts +19 -9
  19. package/lib/MWaterContextComponent.js +38 -22
  20. package/lib/MWaterCustomTablesetListComponent.js +9 -3
  21. package/lib/MWaterGlobalFiltersComponent.d.ts +6 -5
  22. package/lib/MWaterGlobalFiltersComponent.js +4 -4
  23. package/lib/MWaterLoaderComponent.d.ts +15 -3
  24. package/lib/MWaterLoaderComponent.js +11 -2
  25. package/lib/MWaterTableSelectComponent.d.ts +1 -4
  26. package/lib/MWaterTableSelectComponent.js +10 -12
  27. package/lib/UIComponents.d.ts +2 -2
  28. package/lib/UIComponents.js +4 -12
  29. package/lib/axes/Axis.d.ts +20 -25
  30. package/lib/axes/AxisBuilder.d.ts +7 -4
  31. package/lib/axes/AxisBuilder.js +12 -8
  32. package/lib/axes/AxisComponent.d.ts +6 -9
  33. package/lib/axes/AxisComponent.js +1 -2
  34. package/lib/axes/ColorPaletteCollectionComponent.d.ts +5 -12
  35. package/lib/axes/ColorPaletteCollectionComponent.js +67 -36
  36. package/lib/dashboards/DashboardComponent.d.ts +4 -17
  37. package/lib/dashboards/DashboardComponent.js +20 -67
  38. package/lib/dashboards/DashboardDesign.d.ts +5 -20
  39. package/lib/dashboards/DashboardUpgrader.js +36 -1
  40. package/lib/dashboards/DashboardViewComponent.d.ts +5 -34
  41. package/lib/dashboards/DashboardViewComponent.js +112 -136
  42. package/lib/dashboards/FontStyleEditor.d.ts +8 -0
  43. package/lib/dashboards/FontStyleEditor.js +130 -0
  44. package/lib/dashboards/LayoutOptionsComponent.d.ts +0 -1
  45. package/lib/dashboards/LayoutOptionsComponent.js +209 -39
  46. package/lib/dashboards/ServerDashboardDataSource.d.ts +1 -2
  47. package/lib/dashboards/ServerDashboardDataSource.js +52 -33
  48. package/lib/dashboards/SettingsModalComponent.d.ts +4 -15
  49. package/lib/dashboards/SettingsModalComponent.js +24 -38
  50. package/lib/dashboards/WidgetComponent.d.ts +3 -3
  51. package/lib/dashboards/WidgetComponent.js +3 -6
  52. package/lib/dashboards/WidgetDataSourcePrioritizer.d.ts +20 -0
  53. package/lib/dashboards/WidgetDataSourcePrioritizer.js +72 -0
  54. package/lib/dashboards/layoutOptions.d.ts +83 -0
  55. package/lib/dashboards/layoutOptions.js +436 -10
  56. package/lib/datagrids/DatagridComponent.d.ts +2 -9
  57. package/lib/datagrids/DatagridDataSource.d.ts +3 -3
  58. package/lib/datagrids/DatagridDataSource.js +0 -14
  59. package/lib/datagrids/DatagridDesign.d.ts +7 -6
  60. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -93
  61. package/lib/datagrids/DatagridDesignerComponent.js +8 -6
  62. package/lib/datagrids/DatagridViewComponent.js +1 -1
  63. package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -20
  64. package/lib/datagrids/FindReplaceModalComponent.js +27 -13
  65. package/lib/datagrids/ServerDatagridDataSource.d.ts +8 -7
  66. package/lib/datagrids/ServerDatagridDataSource.js +88 -36
  67. package/lib/demo.js +4 -4
  68. package/lib/index.css +5 -0
  69. package/lib/index.d.ts +2 -1
  70. package/lib/index.js +0 -1
  71. package/lib/layouts/LayoutManager.d.ts +33 -29
  72. package/lib/layouts/LayoutManager.js +2 -8
  73. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +26 -56
  74. package/lib/layouts/blocks/BlocksDisplayComponent.js +122 -205
  75. package/lib/layouts/blocks/BlocksLayoutManager.d.ts +6 -22
  76. package/lib/layouts/blocks/BlocksLayoutManager.js +5 -14
  77. package/lib/layouts/blocks/HorizontalBlockComponent.d.ts +5 -4
  78. package/lib/layouts/blocks/HorizontalBlockComponent.js +5 -5
  79. package/lib/layouts/grid/GridLayoutManager.d.ts +2 -1
  80. package/lib/mWaterLoader.d.ts +2 -0
  81. package/lib/mWaterLoader.js +2 -1
  82. package/lib/maps/AddLayerComponent.d.ts +6 -8
  83. package/lib/maps/AddLayerComponent.js +6 -6
  84. package/lib/maps/BingLayer.js +10 -20
  85. package/lib/maps/BufferLayer.js +5 -2
  86. package/lib/maps/ChoroplethLayer.js +2 -1
  87. package/lib/maps/ClusterLayer.js +3 -1
  88. package/lib/maps/DirectMapDataSource.d.ts +5 -2
  89. package/lib/maps/DirectMapDataSource.js +2 -1
  90. package/lib/maps/EditPopupComponent.js +2 -1
  91. package/lib/maps/GridLayer.js +5 -3
  92. package/lib/maps/GridLayerDesigner.js +0 -1
  93. package/lib/maps/LayerSwitcherComponent.js +1 -1
  94. package/lib/maps/MapComponent.d.ts +3 -11
  95. package/lib/maps/MapComponent.js +3 -3
  96. package/lib/maps/MapDesign.d.ts +2 -13
  97. package/lib/maps/MapFiltersDesignerComponent.d.ts +0 -4
  98. package/lib/maps/MapFiltersDesignerComponent.js +4 -5
  99. package/lib/maps/MarkersLayer.js +30 -25
  100. package/lib/maps/RasterMapViewComponent.d.ts +3 -13
  101. package/lib/maps/RasterMapViewComponent.js +3 -3
  102. package/lib/maps/RegionSelectComponent.d.ts +2 -1
  103. package/lib/maps/ServerMapDataSource.d.ts +3 -4
  104. package/lib/maps/ServerMapDataSource.js +5 -5
  105. package/lib/maps/VectorMapViewComponent.js +2 -1
  106. package/lib/maps/mapSymbols.js +2 -0
  107. package/lib/maps/symbols/font-awesome/cloud-rain.png +0 -0
  108. package/lib/maps/vectorMaps.d.ts +1 -0
  109. package/lib/maps/vectorMaps.js +70 -56
  110. package/lib/quickfilter/QuickfilterCompiler.d.ts +1 -1
  111. package/lib/quickfilter/QuickfiltersComponent.d.ts +1 -4
  112. package/lib/quickfilter/QuickfiltersComponent.js +3 -3
  113. package/lib/richtext/DropdownPaletteItem.d.ts +32 -0
  114. package/lib/richtext/DropdownPaletteItem.js +82 -0
  115. package/lib/richtext/FontColorPaletteItem.d.ts +1 -5
  116. package/lib/richtext/FontColorPaletteItem.js +32 -27
  117. package/lib/richtext/ItemsHtmlConverter.js +12 -3
  118. package/lib/richtext/RichTextComponent.d.ts +26 -52
  119. package/lib/richtext/RichTextComponent.js +166 -128
  120. package/lib/valueFormatter.js +6 -1
  121. package/lib/wellknown.d.ts +5 -0
  122. package/lib/wellknown.js +288 -0
  123. package/lib/widgets/DropdownWidgetComponent.d.ts +8 -25
  124. package/lib/widgets/DropdownWidgetComponent.js +48 -25
  125. package/lib/widgets/IFrameWidgetComponent.d.ts +3 -11
  126. package/lib/widgets/ImageWidgetComponent.d.ts +8 -27
  127. package/lib/widgets/MapWidget.d.ts +4 -7
  128. package/lib/widgets/MapWidget.js +2 -1
  129. package/lib/widgets/MarkdownWidget.d.ts +2 -7
  130. package/lib/widgets/TOCWidget.d.ts +2 -9
  131. package/lib/widgets/TOCWidget.js +2 -1
  132. package/lib/widgets/Widget.d.ts +2 -0
  133. package/lib/widgets/WidgetDataSource.d.ts +3 -1
  134. package/lib/widgets/charts/Chart.d.ts +0 -1
  135. package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
  136. package/lib/widgets/charts/ChartViewComponent.js +11 -3
  137. package/lib/widgets/charts/ChartWidget.d.ts +1 -74
  138. package/lib/widgets/charts/ChartWidget.js +4 -183
  139. package/lib/widgets/charts/ChartWidgetComponent.d.ts +51 -0
  140. package/lib/widgets/charts/ChartWidgetComponent.js +167 -0
  141. package/lib/widgets/charts/calendar/CalendarChartViewComponent.d.ts +1 -4
  142. package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +4 -4
  143. package/lib/widgets/charts/imagemosaic/ImagePopupComponent.d.ts +2 -7
  144. package/lib/widgets/charts/layered/LayeredChart.d.ts +5 -10
  145. package/lib/widgets/charts/layered/LayeredChart.js +6 -7
  146. package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +4 -2
  147. package/lib/widgets/charts/layered/LayeredChartCompiler.js +46 -32
  148. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +4 -0
  149. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +5 -31
  150. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +21 -3
  151. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +1 -7
  152. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +2 -1
  153. package/lib/widgets/charts/layered/LayeredChartViewComponent.d.ts +1 -4
  154. package/lib/widgets/charts/layered/LayeredChartViewComponent.js +89 -38
  155. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +5 -105
  156. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.js +122 -166
  157. package/lib/widgets/charts/pivot/PivotChart.d.ts +6 -0
  158. package/lib/widgets/charts/pivot/PivotChart.js +47 -17
  159. package/lib/widgets/charts/pivot/PivotChartDesign.d.ts +11 -0
  160. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +11 -7
  161. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +1 -1
  162. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +2 -2
  163. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +20 -36
  164. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +0 -1
  165. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.d.ts +23 -2
  166. package/lib/widgets/charts/pivot/PivotChartQueryBuilder.js +215 -181
  167. package/lib/widgets/charts/pivot/PivotChartUtils.d.ts +2 -2
  168. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +9 -47
  169. package/lib/widgets/charts/pivot/PivotChartViewComponent.js +20 -60
  170. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +55 -58
  171. package/lib/widgets/charts/table/TableChart.js +8 -4
  172. package/lib/widgets/charts/table/TableChartDesignerComponent.js +3 -3
  173. package/lib/widgets/charts/table/TableChartViewComponent.js +30 -16
  174. package/lib/widgets/text/ExprInsertModalComponent.d.ts +2 -13
  175. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +2 -13
  176. package/lib/widgets/text/TextComponent.d.ts +5 -12
  177. package/lib/widgets/text/TextComponent.js +19 -39
  178. package/lib/widgets/text/TextWidget.d.ts +2 -1
  179. package/lib/widgets/text/TextWidget.js +5 -1
  180. package/lib/widgets/text/TextWidgetComponent.d.ts +15 -3
  181. package/lib/widgets/text/TextWidgetComponent.js +76 -19
  182. package/lib/widgets/text/TextWidgetDesign.d.ts +16 -2
  183. package/lib/widgets/text/TextWidgetDesign.js +6 -0
  184. package/package.json +4 -4
  185. package/src/ColorComponent.tsx +177 -0
  186. package/src/ColorSchemeFactory.ts +12 -6
  187. package/src/CustomColorsContext.tsx +8 -0
  188. package/src/FiltersDesignerComponent.ts +3 -4
  189. package/src/GlobalFilter.ts +17 -0
  190. package/src/LocaleContextInjector.tsx +14 -13
  191. package/src/MWaterAddRelatedFormComponent.ts +3 -3
  192. package/src/MWaterAddRelatedIndicatorComponent.ts +6 -6
  193. package/src/MWaterCompleteTableSelectComponent.tsx +36 -36
  194. package/src/MWaterContextComponent.tsx +42 -33
  195. package/src/MWaterCustomTablesetListComponent.tsx +21 -3
  196. package/src/MWaterGlobalFiltersComponent.ts +8 -8
  197. package/src/MWaterLoaderComponent.ts +14 -4
  198. package/src/MWaterTableSelectComponent.tsx +11 -12
  199. package/src/{UIComponents.ts → UIComponents.tsx} +7 -15
  200. package/src/axes/Axis.ts +24 -25
  201. package/src/axes/AxisBuilder.ts +16 -13
  202. package/src/axes/AxisComponent.ts +3 -4
  203. package/src/axes/{ColorPaletteCollectionComponent.ts → ColorPaletteCollectionComponent.tsx} +87 -61
  204. package/src/dashboards/DashboardComponent.tsx +73 -147
  205. package/src/dashboards/DashboardDesign.ts +5 -25
  206. package/src/dashboards/DashboardUpgrader.ts +41 -1
  207. package/src/dashboards/DashboardViewComponent.tsx +313 -0
  208. package/src/dashboards/FontStyleEditor.tsx +166 -0
  209. package/src/dashboards/LayoutOptionsComponent.tsx +377 -71
  210. package/src/dashboards/ServerDashboardDataSource.ts +52 -33
  211. package/src/dashboards/SettingsModalComponent.tsx +170 -0
  212. package/src/dashboards/WidgetComponent.tsx +6 -12
  213. package/src/dashboards/WidgetDataSourcePrioritizer.ts +82 -0
  214. package/src/dashboards/layoutOptions.tsx +581 -0
  215. package/src/datagrids/DatagridDataSource.ts +6 -12
  216. package/src/datagrids/DatagridDesign.ts +8 -3
  217. package/src/datagrids/DatagridDesignerComponent.tsx +22 -18
  218. package/src/datagrids/DatagridViewComponent.ts +3 -3
  219. package/src/datagrids/ExprCellComponent.ts +0 -1
  220. package/src/datagrids/FindReplaceModalComponent.ts +39 -22
  221. package/src/datagrids/ServerDatagridDataSource.ts +107 -45
  222. package/src/demo.ts +4 -4
  223. package/src/index.css +5 -0
  224. package/src/index.ts +2 -1
  225. package/src/layouts/LayoutManager.ts +44 -42
  226. package/src/layouts/blocks/BlocksDisplayComponent.tsx +498 -0
  227. package/src/layouts/blocks/BlocksLayoutManager.ts +6 -15
  228. package/src/layouts/blocks/HorizontalBlockComponent.ts +9 -8
  229. package/src/mWaterLoader.ts +4 -1
  230. package/src/maps/AddLayerComponent.ts +9 -9
  231. package/src/maps/BingLayer.ts +16 -26
  232. package/src/maps/BufferLayer.ts +5 -2
  233. package/src/maps/ChoroplethLayer.ts +2 -1
  234. package/src/maps/ClusterLayer.ts +3 -1
  235. package/src/maps/DirectMapDataSource.ts +12 -3
  236. package/src/maps/EditPopupComponent.ts +2 -1
  237. package/src/maps/GridLayer.ts +5 -3
  238. package/src/maps/GridLayerDesigner.tsx +0 -1
  239. package/src/maps/LayerSwitcherComponent.tsx +1 -1
  240. package/src/maps/MapComponent.ts +3 -3
  241. package/src/maps/MapDesign.ts +2 -17
  242. package/src/maps/{MapFiltersDesignerComponent.ts → MapFiltersDesignerComponent.tsx} +25 -25
  243. package/src/maps/MarkersLayer.ts +38 -41
  244. package/src/maps/RasterMapViewComponent.ts +3 -3
  245. package/src/maps/ServerMapDataSource.ts +8 -8
  246. package/src/maps/VectorMapViewComponent.tsx +2 -2
  247. package/src/maps/mapSymbols.ts +2 -0
  248. package/src/maps/symbols/font-awesome/cloud-rain.png +0 -0
  249. package/src/maps/vectorMaps.tsx +88 -74
  250. package/src/quickfilter/QuickfilterCompiler.ts +1 -1
  251. package/src/quickfilter/QuickfiltersComponent.ts +3 -3
  252. package/src/richtext/DropdownPaletteItem.tsx +144 -0
  253. package/src/richtext/FontColorPaletteItem.tsx +160 -0
  254. package/src/richtext/ItemsHtmlConverter.ts +15 -5
  255. package/src/richtext/RichTextComponent.tsx +274 -232
  256. package/src/valueFormatter.ts +5 -1
  257. package/src/wellknown.ts +286 -0
  258. package/src/widgets/DropdownWidgetComponent.tsx +75 -0
  259. package/src/widgets/MapWidget.ts +5 -2
  260. package/src/widgets/TOCWidget.ts +2 -1
  261. package/src/widgets/Widget.ts +3 -0
  262. package/src/widgets/WidgetDataSource.ts +3 -1
  263. package/src/widgets/charts/Chart.ts +1 -1
  264. package/src/widgets/charts/ChartViewComponent.ts +16 -3
  265. package/src/widgets/charts/ChartWidget.ts +3 -275
  266. package/src/widgets/charts/ChartWidgetComponent.tsx +281 -0
  267. package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +4 -4
  268. package/src/widgets/charts/layered/LayeredChart.ts +4 -6
  269. package/src/widgets/charts/layered/LayeredChartCompiler.ts +80 -63
  270. package/src/widgets/charts/layered/LayeredChartDesign.ts +7 -1
  271. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +43 -10
  272. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +6 -6
  273. package/src/widgets/charts/layered/LayeredChartViewComponent.ts +140 -88
  274. package/src/widgets/charts/pivot/IntersectionDesignerComponent.tsx +305 -221
  275. package/src/widgets/charts/pivot/PivotChart.ts +56 -18
  276. package/src/widgets/charts/pivot/PivotChartDesign.ts +12 -0
  277. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +4 -3
  278. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +39 -76
  279. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +0 -1
  280. package/src/widgets/charts/pivot/PivotChartQueryBuilder.ts +230 -189
  281. package/src/widgets/charts/pivot/PivotChartUtils.ts +4 -4
  282. package/src/widgets/charts/pivot/{PivotChartViewComponent.ts → PivotChartViewComponent.tsx} +86 -89
  283. package/src/widgets/charts/table/TableChart.ts +8 -4
  284. package/src/widgets/charts/table/TableChartDesignerComponent.ts +4 -4
  285. package/src/widgets/charts/table/TableChartViewComponent.ts +32 -19
  286. package/src/widgets/text/TextComponent.tsx +47 -49
  287. package/src/widgets/text/TextWidget.ts +8 -3
  288. package/src/widgets/text/TextWidgetComponent.tsx +249 -0
  289. package/src/widgets/text/TextWidgetDesign.ts +26 -2
  290. package/src/ColorComponent.ts +0 -117
  291. package/src/dashboards/DashboardViewComponent.ts +0 -304
  292. package/src/dashboards/SettingsModalComponent.ts +0 -169
  293. package/src/dashboards/layoutOptions.ts +0 -40
  294. package/src/layout-styles.css +0 -263
  295. package/src/layouts/blocks/BlocksDisplayComponent.ts +0 -461
  296. package/src/layouts/grid/GridLayoutComponent.ts +0 -67
  297. package/src/layouts/grid/GridLayoutManager.ts +0 -185
  298. package/src/layouts/grid/LegoLayoutEngine.ts +0 -142
  299. package/src/layouts/grid/PaletteItemComponent.ts +0 -28
  300. package/src/layouts/grid/README.md +0 -14
  301. package/src/layouts/grid/WidgetContainerComponent.ts +0 -420
  302. package/src/richtext/FontColorPaletteItem.ts +0 -172
  303. package/src/richtext/FontSizePaletteItem.ts +0 -110
  304. package/src/widgets/DropdownWidgetComponent.ts +0 -78
  305. package/src/widgets/text/TextWidgetComponent.ts +0 -120
@@ -1,14 +1,19 @@
1
+ import _ from "lodash"
1
2
  import React, { ReactNode } from "react"
2
3
  import { useState } from "react"
3
- import { FormGroup, Select, Toggle } from "@mwater/react-library/lib/bootstrap"
4
+ import { FormGroup, Toggle, Select, CollapsibleSection, Checkbox, CollapsiblePanel } from "@mwater/react-library/lib/bootstrap"
4
5
  import { DashboardDesign } from "./DashboardDesign"
5
6
  import {
6
7
  BlocksLayoutOptions,
7
8
  DashboardTheme,
8
9
  getDefaultLayoutOptions,
9
10
  getLayoutOptions,
10
- WidthBucket
11
+ Spacing,
11
12
  } from "./layoutOptions"
13
+ import ColorComponent from "../ColorComponent"
14
+ import { FontStyleEditor } from "./FontStyleEditor"
15
+ import produce from "immer"
16
+ import FileSaver from "file-saver"
12
17
 
13
18
  interface Size {
14
19
  width: number
@@ -25,7 +30,6 @@ const sizeOptions: { value: Size; label: string }[] = [
25
30
  export function LayoutOptionsComponent(props: {
26
31
  design: DashboardDesign
27
32
  onDesignChange: (design: DashboardDesign) => void
28
- onClose: () => void
29
33
 
30
34
  /** Dashboard view to preview*/
31
35
  dashboardView: ReactNode
@@ -40,78 +44,29 @@ export function LayoutOptionsComponent(props: {
40
44
  props.onDesignChange({ ...props.design, layoutOptions })
41
45
  }
42
46
 
43
- function handleResetDefaults() {
44
- props.onDesignChange({ ...props.design, layoutOptions: getDefaultLayoutOptions(props.design.style) })
45
- }
47
+ const isCustomized = !_.isEqual(layoutOptions, getDefaultLayoutOptions(props.design.style))
46
48
 
47
49
  return (
48
- <div style={{ display: "grid", gridTemplateRows: "auto 1fr", gridTemplateColumns: "auto 1fr", height: "100%" }}>
49
- <div style={{ padding: 5, gridRow: "1 / 3" }}>
50
- <div key="back">
51
- <button className="btn btn-sm btn-link" onClick={props.onClose}>
52
- <i className="fa fa-arrow-left" /> Close
53
- </button>
54
- </div>
55
- <br />
50
+ <div style={{ display: "grid", gridTemplateRows: "auto 1fr", gridTemplateColumns: "360px 1fr", height: "100%" }}>
51
+ <div style={{ padding: "5px 10px 5px 0px", gridRow: "1 / 3", overflowY: "auto" }}>
52
+ <h5>Theme</h5>
56
53
  <ThemeToggle
57
54
  theme={props.design.style}
58
55
  onChange={(theme) => {
56
+ if (isCustomized) {
57
+ if (!confirm("Are you sure you want to change the theme? Your customizations will be lost.")) return
58
+ }
59
59
  props.onDesignChange({ ...props.design, style: theme, layoutOptions: getDefaultLayoutOptions(theme) })
60
60
  }}
61
+ isCustomized={isCustomized}
61
62
  />
62
63
  <br />
63
- <h4>Advanced</h4>
64
- <a className="btn btn-sm btn-link" style={{ float: "right" }} onClick={handleResetDefaults}>
65
- Reset to Defaults
66
- </a>
67
- <FormGroup label="Collapse to Single Column">
68
- <WidthSelector
69
- value={layoutOptions.collapseColumnsWidth}
70
- onChange={(collapseColumnsWidth) => {
71
- setLayoutOptions({ ...layoutOptions, collapseColumnsWidth })
72
- }}
73
- sign="< "
74
- />
75
- </FormGroup>
76
- <FormGroup label="Hide Quickfilters">
77
- <WidthSelector
78
- value={layoutOptions.hideQuickfiltersWidth}
79
- onChange={(hideQuickfiltersWidth) => {
80
- setLayoutOptions({ ...layoutOptions, hideQuickfiltersWidth })
81
- }}
82
- sign="< "
83
- />
84
- </FormGroup>
85
- <FormGroup label="Minimum Width (before scrolling or scaling)">
86
- <WidthSelector
87
- value={layoutOptions.minimumWidth}
88
- onChange={(minimumWidth) => {
89
- setLayoutOptions({ ...layoutOptions, minimumWidth })
90
- }}
91
- sign="< "
92
- />
93
- <FormGroup label="When Below Minimum Width">
94
- <Toggle
95
- value={layoutOptions.belowMinimumWidth}
96
- onChange={(belowMinimumWidth) => {
97
- setLayoutOptions({ ...layoutOptions, belowMinimumWidth: belowMinimumWidth as "scale" | "scroll" })
98
- }}
99
- options={[
100
- { value: "scroll", label: "Scroll" },
101
- { value: "scale", label: "Scale" }
102
- ]}
103
- />
104
- </FormGroup>
105
- </FormGroup>
106
- <FormGroup label="Maximum Width (before padding)">
107
- <WidthSelector
108
- value={layoutOptions.maximumWidth}
109
- onChange={(maximumWidth) => {
110
- setLayoutOptions({ ...layoutOptions, maximumWidth })
111
- }}
112
- sign="> "
64
+ <CollapsibleSection label={<h5 style={{ display: "inline-block" }}>Customize Layout</h5>} initiallyOpen={isCustomized}>
65
+ <CustomizeLayout
66
+ layoutOptions={layoutOptions}
67
+ onLayoutOptionsChange={setLayoutOptions}
113
68
  />
114
- </FormGroup>
69
+ </CollapsibleSection>
115
70
  </div>
116
71
  <div style={{ textAlign: "center", padding: 3 }}>
117
72
  <span className="text-muted">Preview As:&nbsp;</span>
@@ -137,7 +92,7 @@ export function LayoutOptionsComponent(props: {
137
92
  <div style={{ height: "100%", display: "grid", gridTemplateRows: "auto 1fr" }}>
138
93
  <div key="quickfilters">
139
94
  {layoutOptions.hideQuickfiltersWidth == null ||
140
- sizeOptions[previewSize].value.width > layoutOptions.hideQuickfiltersWidth
95
+ sizeOptions[previewSize].value.width > layoutOptions.hideQuickfiltersWidth
141
96
  ? props.quickfiltersView
142
97
  : null}
143
98
  </div>
@@ -151,9 +106,13 @@ export function LayoutOptionsComponent(props: {
151
106
  )
152
107
  }
153
108
 
154
- function ThemeToggle(props: { theme?: DashboardTheme; onChange: (theme: DashboardTheme) => void }) {
109
+ function ThemeToggle(props: {
110
+ theme?: DashboardTheme;
111
+ onChange: (theme: DashboardTheme) => void
112
+ isCustomized: boolean
113
+ }) {
155
114
  function renderStyleItem(theme: string) {
156
- const isActive = (props.theme || "default") == theme
115
+ const isActive = props.isCustomized ? theme == "custom" : (props.theme || "default") == theme
157
116
 
158
117
  if (theme == "default") {
159
118
  return (
@@ -191,15 +150,362 @@ function ThemeToggle(props: { theme?: DashboardTheme; onChange: (theme: Dashboar
191
150
  </a>
192
151
  )
193
152
  }
153
+ if (theme == "custom") {
154
+ return (
155
+ <a
156
+ key={theme}
157
+ className={isActive ? "list-group-item active" : "list-group-item"}
158
+ >
159
+ <div>Custom</div>
160
+ <div style={{ opacity: 0.6 }}>Customized theme</div>
161
+ </a>
162
+ )
163
+ }
194
164
  return null
195
165
  }
196
166
 
197
167
  return (
198
- <FormGroup label="Theme">
168
+ <div className="list-group">
199
169
  {renderStyleItem("default")}
200
170
  {renderStyleItem("greybg")}
201
171
  {renderStyleItem("story")}
202
- </FormGroup>
172
+ {props.isCustomized && renderStyleItem("custom")}
173
+ </div>
174
+ )
175
+ }
176
+
177
+ function CustomizeLayout(props: { layoutOptions: BlocksLayoutOptions; onLayoutOptionsChange: (layoutOptions: BlocksLayoutOptions) => void }) {
178
+ const { layoutOptions, onLayoutOptionsChange } = props
179
+
180
+ const handleDownloadTheme = () => {
181
+ const blob = new Blob([JSON.stringify(layoutOptions, null, 2)], { type: "application/json" })
182
+ FileSaver.saveAs(blob, "custom_theme.theme")
183
+ }
184
+
185
+ const handleUploadTheme = (event: React.ChangeEvent<HTMLInputElement>) => {
186
+ const file = event.target.files?.[0]
187
+ if (file) {
188
+ const reader = new FileReader()
189
+ reader.onload = (e) => {
190
+ try {
191
+ const uploadedTheme = JSON.parse(e.target?.result as string)
192
+ onLayoutOptionsChange(uploadedTheme)
193
+ } catch (error) {
194
+ alert("Invalid theme file")
195
+ }
196
+ }
197
+ reader.readAsText(file)
198
+ }
199
+ }
200
+
201
+ return (
202
+ <div>
203
+ <CollapsiblePanel title="Text">
204
+ <FormGroup label="Title">
205
+ <FontStyleEditor value={layoutOptions.titleWidgetFont} onChange={(titleWidgetFont) => {
206
+ onLayoutOptionsChange({ ...layoutOptions, titleWidgetFont })
207
+ }} />
208
+ </FormGroup>
209
+ <FormGroup label="Heading H1">
210
+ <FontStyleEditor value={layoutOptions.textWidgetH1Font} onChange={(textWidgetH1Font) => {
211
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH1Font })
212
+ }} />
213
+ <div className="mt-1">
214
+ <FormGroup label="Top Margin:" horizontal labelMuted>
215
+ <PixelsInput
216
+ value={layoutOptions.textWidgetH1MarginTop}
217
+ onChange={(textWidgetH1MarginTop) => {
218
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH1MarginTop: textWidgetH1MarginTop! })
219
+ }}
220
+ />
221
+ </FormGroup>
222
+ </div>
223
+ </FormGroup>
224
+ <FormGroup label="Heading H2">
225
+ <FontStyleEditor value={layoutOptions.textWidgetH2Font} onChange={(textWidgetH2Font) => {
226
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH2Font })
227
+ }} />
228
+ <div className="mt-1">
229
+ <FormGroup label="Top Margin:" horizontal labelMuted>
230
+ <PixelsInput
231
+ value={layoutOptions.textWidgetH2MarginTop}
232
+ onChange={(textWidgetH2MarginTop) => {
233
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetH2MarginTop: textWidgetH2MarginTop! })
234
+ }}
235
+ />
236
+ </FormGroup>
237
+ </div>
238
+ </FormGroup>
239
+ <FormGroup label="Text">
240
+ <FontStyleEditor value={layoutOptions.textWidgetFont} onChange={(textWidgetFont) => {
241
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetFont })
242
+ }} />
243
+ <div className="mt-1">
244
+ <FormGroup label="Line Height:" horizontal labelMuted>
245
+ <PixelsInput
246
+ value={layoutOptions.textWidgetLineHeight}
247
+ onChange={(textWidgetLineHeight) => {
248
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetLineHeight: textWidgetLineHeight })
249
+ }}
250
+ allowDefault
251
+ defaultLabel="Default"
252
+ />
253
+ </FormGroup>
254
+ <FormGroup label="Paragraph Spacing:" horizontal labelMuted>
255
+ <PixelsInput
256
+ value={layoutOptions.textWidgetParagraphSpacing}
257
+ onChange={(textWidgetParagraphSpacing) => {
258
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetParagraphSpacing: textWidgetParagraphSpacing! })
259
+ }}
260
+ />
261
+ </FormGroup>
262
+ </div>
263
+ </FormGroup>
264
+ <FormGroup label="List Line Height:" horizontal>
265
+ <PixelsInput
266
+ value={layoutOptions.textWidgetListLineHeight}
267
+ onChange={(textWidgetListLineHeight) => {
268
+ onLayoutOptionsChange({ ...layoutOptions, textWidgetListLineHeight: textWidgetListLineHeight })
269
+ }}
270
+ allowDefault
271
+ defaultLabel="Default"
272
+ />
273
+ </FormGroup>
274
+ <FormGroup label="Chart Header Font">
275
+ <FontStyleEditor value={layoutOptions.widgetHeaderFont} onChange={(widgetHeaderFont) => {
276
+ onLayoutOptionsChange({ ...layoutOptions, widgetHeaderFont })
277
+ }} />
278
+ </FormGroup>
279
+ <FormGroup label="Chart Footer Font">
280
+ <FontStyleEditor value={layoutOptions.widgetFooterFont} onChange={(widgetFooterFont) => {
281
+ onLayoutOptionsChange({ ...layoutOptions, widgetFooterFont })
282
+ }} />
283
+ </FormGroup>
284
+ <FormGroup label="Chart Font">
285
+ <FontStyleEditor value={layoutOptions.chartFont} onChange={(chartFont) => {
286
+ onLayoutOptionsChange({ ...layoutOptions, chartFont })
287
+ }} />
288
+ </FormGroup>
289
+ <FormGroup label="Table Font">
290
+ <FontStyleEditor value={layoutOptions.tableFont} onChange={(tableFont) => {
291
+ onLayoutOptionsChange({ ...layoutOptions, tableFont })
292
+ }} />
293
+ </FormGroup>
294
+ <FormGroup label="Pivot Table Font">
295
+ <FontStyleEditor value={layoutOptions.pivotTableFont} onChange={(pivotTableFont) => {
296
+ onLayoutOptionsChange({ ...layoutOptions, pivotTableFont })
297
+ }} />
298
+ </FormGroup>
299
+ </CollapsiblePanel>
300
+ <CollapsiblePanel title="Spacing">
301
+ <FormGroup label="Outer Padding:" horizontal>
302
+ <PixelsInput
303
+ value={layoutOptions.outerPadding}
304
+ onChange={(outerPadding) => {
305
+ onLayoutOptionsChange({ ...layoutOptions, outerPadding: outerPadding! })
306
+ }}
307
+ />
308
+ </FormGroup>
309
+ <FormGroup label="Block Margins">
310
+ <SpacingInput value={layoutOptions.blockMargin} onChange={(blockMargin) => {
311
+ onLayoutOptionsChange({ ...layoutOptions, blockMargin })
312
+ }} />
313
+ </FormGroup>
314
+ <FormGroup label="Block Padding">
315
+ <SpacingInput value={layoutOptions.blockPadding} onChange={(blockPadding) => {
316
+ onLayoutOptionsChange({ ...layoutOptions, blockPadding })
317
+ }} />
318
+ </FormGroup>
319
+ <FormGroup label="Block Border Radius:" horizontal>
320
+ <PixelsInput
321
+ value={layoutOptions.blockBorderRadius}
322
+ onChange={(blockBorderRadius) => {
323
+ onLayoutOptionsChange({ ...layoutOptions, blockBorderRadius: blockBorderRadius! })
324
+ }}
325
+ />
326
+ </FormGroup>
327
+ </CollapsiblePanel>
328
+ <CollapsiblePanel title="Colors">
329
+ <FormGroup label="Background Color:" horizontal>
330
+ <ColorComponent
331
+ color={layoutOptions.backgroundColor}
332
+ onChange={(backgroundColor) => {
333
+ onLayoutOptionsChange({ ...layoutOptions, backgroundColor: backgroundColor ?? "white" })
334
+ }}
335
+ />
336
+ </FormGroup>
337
+ <FormGroup label="Block Background Color:" horizontal>
338
+ <ColorComponent
339
+ color={layoutOptions.blockBackgroundColor}
340
+ onChange={(blockBackgroundColor) => {
341
+ onLayoutOptionsChange({ ...layoutOptions, blockBackgroundColor: blockBackgroundColor ?? "white" })
342
+ }}
343
+ />
344
+ </FormGroup>
345
+ <FormGroup label="Custom Colors">
346
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: '5px' }}>
347
+ {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((colorIndex) => (
348
+ <ColorComponent
349
+ key={colorIndex}
350
+ color={layoutOptions.customColors[colorIndex]}
351
+ onChange={(color) => {
352
+ onLayoutOptionsChange(produce(layoutOptions, (draft) => {
353
+ draft.customColors[colorIndex] = color
354
+ }))
355
+ }}
356
+ />
357
+ ))}
358
+ </div>
359
+ </FormGroup>
360
+ </CollapsiblePanel>
361
+ <CollapsiblePanel title="Responsive Layout">
362
+ <FormGroup label="Collapse to Single Column">
363
+ <WidthSelector
364
+ value={layoutOptions.collapseColumnsWidth}
365
+ onChange={(collapseColumnsWidth) => {
366
+ onLayoutOptionsChange({ ...layoutOptions, collapseColumnsWidth })
367
+ }}
368
+ sign="< "
369
+ />
370
+ </FormGroup>
371
+ <FormGroup label="Hide Quickfilters">
372
+ <WidthSelector
373
+ value={layoutOptions.hideQuickfiltersWidth}
374
+ onChange={(hideQuickfiltersWidth) => {
375
+ onLayoutOptionsChange({ ...layoutOptions, hideQuickfiltersWidth })
376
+ }}
377
+ sign="< "
378
+ />
379
+ </FormGroup>
380
+ <FormGroup label="Minimum Width (before scrolling or scaling)">
381
+ <WidthSelector
382
+ value={layoutOptions.minimumWidth}
383
+ onChange={(minimumWidth) => {
384
+ onLayoutOptionsChange({ ...layoutOptions, minimumWidth })
385
+ }}
386
+ sign="< "
387
+ />
388
+ <FormGroup label="When Below Minimum Width">
389
+ <Toggle
390
+ value={layoutOptions.belowMinimumWidth}
391
+ onChange={(belowMinimumWidth) => {
392
+ onLayoutOptionsChange({ ...layoutOptions, belowMinimumWidth: belowMinimumWidth as "scale" | "scroll" })
393
+ }}
394
+ size="sm"
395
+ options={[
396
+ { value: "scroll", label: "Scroll" },
397
+ { value: "scale", label: "Scale" }
398
+ ]}
399
+ />
400
+ </FormGroup>
401
+ </FormGroup>
402
+ <FormGroup label="Maximum Width (before padding)">
403
+ <WidthSelector
404
+ value={layoutOptions.maximumWidth}
405
+ onChange={(maximumWidth) => {
406
+ onLayoutOptionsChange({ ...layoutOptions, maximumWidth })
407
+ }}
408
+ sign="> "
409
+ />
410
+ </FormGroup>
411
+ <Checkbox value={layoutOptions.collapseSpacers} onChange={(collapseSpacers) => {
412
+ onLayoutOptionsChange({ ...layoutOptions, collapseSpacers })
413
+ }}>
414
+ Collapse Spacers on Mobile
415
+ </Checkbox>
416
+ </CollapsiblePanel>
417
+
418
+ <CollapsiblePanel title="Download/Upload Theme" initiallyClosed>
419
+ <div className="mb-2 text-muted">
420
+ Download or upload a custom theme to use for this dashboard.
421
+ This saves the current theme as a theme file that you can then use on other dashboards by uploading it there.
422
+ </div>
423
+ <div style={{ display: "flex", flexDirection: "column", marginTop: "10px", gap: "10px" }}>
424
+ <button className="btn btn-sm btn-secondary" onClick={handleDownloadTheme}>
425
+ <i className="fas fa-download" /> Download Custom Theme
426
+ </button>
427
+ <label className="btn btn-sm btn-secondary">
428
+ <i className="fas fa-upload" /> Upload Custom Theme
429
+ <input
430
+ type="file"
431
+ accept=".theme"
432
+ style={{ display: "none" }}
433
+ onChange={handleUploadTheme}
434
+ />
435
+ </label>
436
+ </div>
437
+ </CollapsiblePanel>
438
+ </div>
439
+ )
440
+ }
441
+
442
+ function SpacingInput(props: { value: Spacing; onChange: (value: Spacing) => void }) {
443
+ return (
444
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', width: '100%' }}>
445
+ <div>Top</div>
446
+ <div>Bottom</div>
447
+ <div>Left</div>
448
+ <div>Right</div>
449
+ <PixelsInput value={props.value.top} onChange={(top) => props.onChange({ ...props.value, top: top! })} />
450
+ <PixelsInput value={props.value.bottom} onChange={(bottom) => props.onChange({ ...props.value, bottom: bottom! })} />
451
+ <PixelsInput value={props.value.left} onChange={(left) => props.onChange({ ...props.value, left: left! })} />
452
+ <PixelsInput value={props.value.right} onChange={(right) => props.onChange({ ...props.value, right: right! })} />
453
+ </div>
454
+ )
455
+ }
456
+
457
+ function PixelsInput(props: {
458
+ value: number | null
459
+ onChange: (value: number | null) => void
460
+ allowDefault?: boolean
461
+ defaultLabel?: string
462
+ }) {
463
+ const options = [
464
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40
465
+ ]
466
+
467
+ return (
468
+ <div className="dropdown">
469
+ <a
470
+ className="dropdown-toggle"
471
+ type="button"
472
+ id="pixelsInputDropdown"
473
+ data-bs-toggle="dropdown"
474
+ aria-expanded="false"
475
+ >
476
+ {props.value === null ? (props.defaultLabel || "Default") : `${props.value}px`}
477
+ </a>
478
+ <ul className="dropdown-menu" aria-labelledby="pixelsInputDropdown">
479
+ {props.allowDefault && (
480
+ <li key="default">
481
+ <a
482
+ className="dropdown-item"
483
+ href="#"
484
+ onClick={(e) => {
485
+ e.preventDefault()
486
+ props.onChange(null)
487
+ }}
488
+ >
489
+ {props.defaultLabel || "Default"}
490
+ </a>
491
+ </li>
492
+ )}
493
+ {options.map(option => (
494
+ <li key={option}>
495
+ <a
496
+ className="dropdown-item"
497
+ href="#"
498
+ onClick={(e) => {
499
+ e.preventDefault()
500
+ props.onChange(option)
501
+ }}
502
+ >
503
+ {option}px
504
+ </a>
505
+ </li>
506
+ ))}
507
+ </ul>
508
+ </div>
203
509
  )
204
510
  }
205
511
 
@@ -224,4 +530,4 @@ function WidthSelector(props: {
224
530
  ]}
225
531
  />
226
532
  )
227
- }
533
+ }
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash"
2
- import $ from "jquery"
3
2
  import { DataSource, Expr, injectTableAlias } from "@mwater/expressions"
4
3
  import { JsonQLFilter } from "../JsonQLFilter"
5
4
  import querystring from "querystring"
@@ -104,18 +103,23 @@ class ServerQuickfilterDataSource implements QuickfiltersDataSource {
104
103
  headers["Cache-Control"] = `max-age=${seconds}`
105
104
  }
106
105
 
107
- $.ajax({
108
- dataType: "json",
106
+ fetch(url, {
109
107
  method: "GET",
110
- url,
111
- headers
108
+ headers: headers
112
109
  })
113
- .done((data: any) => {
110
+ .then(async response => {
111
+ if (!response.ok) {
112
+ const text = await response.text()
113
+ throw new Error(text)
114
+ }
115
+ return response.json()
116
+ })
117
+ .then(data => {
114
118
  return callback(null, data)
115
119
  })
116
- .fail((xhr: any) => {
117
- console.log(xhr.responseText)
118
- return callback(new Error(xhr.responseText))
120
+ .catch(error => {
121
+ console.log(error.message)
122
+ return callback(error)
119
123
  })
120
124
  }
121
125
  }
@@ -158,18 +162,23 @@ class ServerWidgetDataSource {
158
162
  headers["Cache-Control"] = `max-age=${seconds}`
159
163
  }
160
164
 
161
- return $.ajax({
162
- dataType: "json",
165
+ fetch(url, {
163
166
  method: "GET",
164
- url,
165
- headers
167
+ headers: headers
166
168
  })
167
- .done((data: any) => {
169
+ .then(async response => {
170
+ if (!response.ok) {
171
+ const text = await response.text()
172
+ throw new Error(text)
173
+ }
174
+ return response.json()
175
+ })
176
+ .then(data => {
168
177
  return callback(null, data)
169
178
  })
170
- .fail((xhr: any) => {
171
- console.log(xhr.responseText)
172
- return callback(new Error(xhr.responseText))
179
+ .catch(error => {
180
+ console.log(error.message)
181
+ return callback(error)
173
182
  })
174
183
  }
175
184
 
@@ -242,18 +251,23 @@ class ServerWidgetMapDataSource implements MapDataSource {
242
251
  headers["Cache-Control"] = `max-age=${seconds}`
243
252
  }
244
253
 
245
- $.ajax({
246
- dataType: "json",
254
+ fetch(url, {
247
255
  method: "GET",
248
- url,
249
256
  headers
250
257
  })
251
- .done((data: any) => {
258
+ .then(async response => {
259
+ if (!response.ok) {
260
+ const text = await response.text()
261
+ throw new Error(text)
262
+ }
263
+ return response.json()
264
+ })
265
+ .then(data => {
252
266
  return callback(null, data)
253
267
  })
254
- .fail((xhr: any) => {
255
- console.log(xhr.responseText)
256
- return callback(new Error(xhr.responseText))
268
+ .catch(error => {
269
+ console.log(error.message)
270
+ return callback(error)
257
271
  })
258
272
  }
259
273
 
@@ -491,18 +505,23 @@ class ServerWidgetLayerPopupWidgetDataSource implements WidgetDataSource {
491
505
  headers["Cache-Control"] = `max-age=${seconds}`
492
506
  }
493
507
 
494
- $.ajax({
495
- dataType: "json",
508
+ fetch(url, {
496
509
  method: "GET",
497
- url,
498
- headers
510
+ headers: headers
499
511
  })
500
- .done((data: any) => {
501
- return callback(null, data)
512
+ .then(async response => {
513
+ if (!response.ok) {
514
+ const text = await response.text()
515
+ throw new Error(text)
516
+ }
517
+ return response.json()
518
+ })
519
+ .then(data => {
520
+ callback(null, data)
502
521
  })
503
- .fail((xhr: any) => {
504
- console.log(xhr.responseText)
505
- return callback(new Error(xhr.responseText))
522
+ .catch(error => {
523
+ console.log(error.message)
524
+ callback(error)
506
525
  })
507
526
  }
508
527