@mwater/visualization 5.0.1 → 5.2.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 (172) hide show
  1. package/lib/GlobalFilter.d.ts +13 -0
  2. package/lib/GlobalFilter.js +2 -0
  3. package/lib/MWaterAddRelatedFormComponent.d.ts +1 -1
  4. package/lib/MWaterAddRelatedFormComponent.js +10 -17
  5. package/lib/MWaterCompleteTableSelectComponent.d.ts +2 -9
  6. package/lib/MWaterContextComponent.d.ts +31 -9
  7. package/lib/MWaterContextComponent.js +85 -76
  8. package/lib/MWaterCustomTablesetListComponent.js +9 -3
  9. package/lib/MWaterGlobalFiltersComponent.d.ts +6 -5
  10. package/lib/MWaterGlobalFiltersComponent.js +4 -4
  11. package/lib/MWaterLoaderComponent.d.ts +14 -4
  12. package/lib/MWaterLoaderComponent.js +10 -2
  13. package/lib/MWaterTableSelectComponent.d.ts +0 -1
  14. package/lib/MWaterTableSelectComponent.js +20 -41
  15. package/lib/axes/Axis.d.ts +20 -25
  16. package/lib/axes/AxisBuilder.js +9 -7
  17. package/lib/axes/AxisComponent.d.ts +4 -4
  18. package/lib/axes/RangesComponent.d.ts +12 -6
  19. package/lib/axes/RangesComponent.js +21 -10
  20. package/lib/dashboards/DashboardComponent.d.ts +1 -14
  21. package/lib/dashboards/DashboardComponent.js +18 -56
  22. package/lib/dashboards/DashboardDesign.d.ts +2 -17
  23. package/lib/dashboards/DashboardViewComponent.js +3 -4
  24. package/lib/dashboards/LayoutOptionsComponent.js +4 -3
  25. package/lib/dashboards/ServerDashboardDataSource.d.ts +1 -0
  26. package/lib/dashboards/ServerDashboardDataSource.js +3 -0
  27. package/lib/dashboards/SettingsModalComponent.d.ts +4 -15
  28. package/lib/dashboards/SettingsModalComponent.js +24 -38
  29. package/lib/datagrids/DatagridComponent.d.ts +10 -13
  30. package/lib/datagrids/DatagridComponent.js +27 -5
  31. package/lib/datagrids/DatagridDataSource.d.ts +3 -2
  32. package/lib/datagrids/DatagridDataSource.js +0 -11
  33. package/lib/datagrids/DatagridDesign.d.ts +2 -0
  34. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -93
  35. package/lib/datagrids/DatagridDesignerComponent.js +11 -8
  36. package/lib/datagrids/DatagridViewComponent.js +2 -2
  37. package/lib/datagrids/DirectDatagridDataSource.d.ts +1 -0
  38. package/lib/datagrids/DirectDatagridDataSource.js +26 -0
  39. package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -20
  40. package/lib/datagrids/FindReplaceModalComponent.js +27 -13
  41. package/lib/datagrids/ServerDatagridDataSource.d.ts +2 -1
  42. package/lib/datagrids/ServerDatagridDataSource.js +16 -3
  43. package/lib/demo.js +1 -1
  44. package/lib/index.d.ts +1 -1
  45. package/lib/index.js +2 -4
  46. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +2 -1
  47. package/lib/layouts/blocks/BlocksDisplayComponent.js +2 -2
  48. package/lib/layouts/grid/GridLayoutManager.d.ts +2 -1
  49. package/lib/layouts/grid/LegoLayoutEngine.d.ts +1 -1
  50. package/lib/maps/BufferLayer.js +3 -1
  51. package/lib/maps/BufferLayerDesignerComponent.js +2 -2
  52. package/lib/maps/ChoroplethLayerDesigner.js +2 -2
  53. package/lib/maps/ClusterLayer.js +3 -1
  54. package/lib/maps/ClusterLayerDesignerComponent.js +2 -2
  55. package/lib/maps/DirectMapDataSource.js +1 -2
  56. package/lib/maps/GridLayer.js +5 -3
  57. package/lib/maps/GridLayerDesigner.js +2 -3
  58. package/lib/maps/LayerSwitcherComponent.js +1 -1
  59. package/lib/maps/MapComponent.d.ts +2 -7
  60. package/lib/maps/MapDesign.d.ts +2 -13
  61. package/lib/maps/MapDesignerComponent.d.ts +1 -12
  62. package/lib/maps/MapDesignerComponent.js +5 -12
  63. package/lib/maps/MapFiltersDesignerComponent.d.ts +0 -4
  64. package/lib/maps/MapFiltersDesignerComponent.js +4 -5
  65. package/lib/maps/MarkersLayerDesignerComponent.js +2 -2
  66. package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -1
  67. package/lib/maps/PopupFilterJoinsUtils.js +4 -3
  68. package/lib/maps/RasterMapViewComponent.d.ts +2 -9
  69. package/lib/maps/RegionSelectComponent.d.ts +2 -1
  70. package/lib/maps/ServerMapDataSource.d.ts +1 -1
  71. package/lib/maps/UtfGridLayer.js +1 -1
  72. package/lib/maps/vectorMaps.d.ts +1 -0
  73. package/lib/maps/vectorMaps.js +10 -2
  74. package/lib/quickfilter/QuickfilterCompiler.d.ts +1 -1
  75. package/lib/widgets/IFrameWidgetComponent.d.ts +2 -9
  76. package/lib/widgets/ImageWidgetComponent.d.ts +6 -24
  77. package/lib/widgets/ImageWidgetComponent.js +2 -2
  78. package/lib/widgets/MapWidget.d.ts +2 -7
  79. package/lib/widgets/MarkdownWidget.d.ts +2 -7
  80. package/lib/widgets/TOCWidget.d.ts +2 -9
  81. package/lib/widgets/charts/ChartWidget.d.ts +3 -15
  82. package/lib/widgets/charts/calendar/CalendarChartDesignerComponent.js +2 -2
  83. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -1
  84. package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +1 -1
  85. package/lib/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.js +2 -2
  86. package/lib/widgets/charts/imagemosaic/ImagePopupComponent.d.ts +2 -7
  87. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +2 -31
  88. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +2 -7
  89. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +2 -2
  90. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +73 -66
  91. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +10 -6
  92. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +2 -2
  93. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +3 -22
  94. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +55 -58
  95. package/lib/widgets/charts/table/TableChartDesignerComponent.js +2 -2
  96. package/lib/widgets/charts/table/TableChartViewComponent.js +21 -7
  97. package/lib/widgets/text/ExprInsertModalComponent.d.ts +2 -13
  98. package/lib/widgets/text/ExprItemEditorComponent.js +2 -2
  99. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +2 -13
  100. package/lib/widgets/text/TextWidgetDesign.d.ts +3 -1
  101. package/package.json +1 -1
  102. package/src/GlobalFilter.ts +17 -0
  103. package/src/MWaterAddRelatedFormComponent.ts +15 -20
  104. package/src/MWaterContextComponent.tsx +158 -0
  105. package/src/MWaterCustomTablesetListComponent.tsx +21 -3
  106. package/src/MWaterGlobalFiltersComponent.ts +8 -8
  107. package/src/MWaterLoaderComponent.ts +10 -3
  108. package/src/{MWaterTableSelectComponent.ts → MWaterTableSelectComponent.tsx} +61 -66
  109. package/src/axes/Axis.ts +24 -25
  110. package/src/axes/AxisBuilder.ts +10 -9
  111. package/src/axes/RangesComponent.ts +27 -16
  112. package/src/dashboards/{DashboardComponent.ts → DashboardComponent.tsx} +39 -80
  113. package/src/dashboards/DashboardDesign.ts +2 -22
  114. package/src/dashboards/DashboardViewComponent.ts +4 -5
  115. package/src/dashboards/LayoutOptionsComponent.tsx +6 -4
  116. package/src/dashboards/ServerDashboardDataSource.ts +16 -12
  117. package/src/dashboards/SettingsModalComponent.tsx +170 -0
  118. package/src/datagrids/DatagridComponent.ts +45 -14
  119. package/src/datagrids/DatagridDataSource.ts +10 -8
  120. package/src/datagrids/DatagridDesign.ts +3 -0
  121. package/src/datagrids/DatagridDesignerComponent.tsx +31 -19
  122. package/src/datagrids/DatagridViewComponent.ts +4 -4
  123. package/src/datagrids/DirectDatagridDataSource.ts +35 -0
  124. package/src/datagrids/ExprCellComponent.ts +0 -1
  125. package/src/datagrids/FindReplaceModalComponent.ts +39 -22
  126. package/src/datagrids/ServerDatagridDataSource.ts +23 -6
  127. package/src/demo.ts +1 -1
  128. package/src/index.ts +1 -2
  129. package/src/layouts/blocks/BlocksDisplayComponent.ts +2 -2
  130. package/src/layouts/grid/LegoLayoutEngine.ts +2 -2
  131. package/src/layouts/grid/WidgetContainerComponent.ts +2 -2
  132. package/src/maps/BingLayer.ts +2 -2
  133. package/src/maps/BufferLayer.ts +3 -1
  134. package/src/maps/BufferLayerDesignerComponent.ts +1 -1
  135. package/src/maps/ChoroplethLayerDesigner.tsx +1 -1
  136. package/src/maps/ClusterLayer.ts +3 -1
  137. package/src/maps/ClusterLayerDesignerComponent.ts +1 -1
  138. package/src/maps/DirectMapDataSource.ts +1 -2
  139. package/src/maps/GridLayer.ts +5 -3
  140. package/src/maps/GridLayerDesigner.tsx +1 -2
  141. package/src/maps/LayerSwitcherComponent.tsx +1 -1
  142. package/src/maps/LegendGroup.ts +1 -1
  143. package/src/maps/MWaterServerLayer.ts +2 -2
  144. package/src/maps/MapDesign.ts +2 -17
  145. package/src/maps/{MapDesignerComponent.ts → MapDesignerComponent.tsx} +8 -16
  146. package/src/maps/{MapFiltersDesignerComponent.ts → MapFiltersDesignerComponent.tsx} +25 -25
  147. package/src/maps/MarkersLayerDesignerComponent.ts +1 -1
  148. package/src/maps/PopupFilterJoinsUtils.ts +4 -4
  149. package/src/maps/ServerMapDataSource.ts +7 -7
  150. package/src/maps/SwitchableTileUrlLayerDesigner.tsx +1 -13
  151. package/src/maps/UtfGridLayer.ts +4 -4
  152. package/src/maps/VectorMapViewComponent.tsx +0 -1
  153. package/src/maps/mapboxUtils.ts +2 -2
  154. package/src/maps/vectorMaps.tsx +10 -1
  155. package/src/quickfilter/QuickfilterCompiler.ts +1 -1
  156. package/src/richtext/ExprItemsHtmlConverter.ts +1 -1
  157. package/src/richtext/FontColorPaletteItem.ts +1 -1
  158. package/src/richtext/FontSizePaletteItem.ts +1 -1
  159. package/src/richtext/ItemsHtmlConverter.ts +2 -2
  160. package/src/widgets/ImageWidgetComponent.ts +1 -1
  161. package/src/widgets/charts/calendar/CalendarChartDesignerComponent.ts +1 -1
  162. package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +1 -1
  163. package/src/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.ts +1 -1
  164. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +1 -1
  165. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +1 -1
  166. package/src/widgets/charts/table/TableChartDesignerComponent.ts +1 -1
  167. package/src/widgets/charts/table/TableChartViewComponent.ts +21 -7
  168. package/src/widgets/text/ExprItemEditorComponent.tsx +1 -1
  169. package/src/widgets/text/TextWidgetDesign.ts +4 -1
  170. package/src/MWaterContextComponent.ts +0 -141
  171. package/src/TableSelectComponent.ts +0 -60
  172. package/src/dashboards/SettingsModalComponent.ts +0 -169
@@ -4,35 +4,15 @@ import { Expr } from "@mwater/expressions";
4
4
  An axis is an expression with optional aggregation, transform and color mapping
5
5
  In ggplot2 parlance, an "aesthetic"
6
6
 
7
- It contains:
8
- expr: expression
9
- aggr: DEPRECATED: optional aggregation (e.g. sum)
10
- xform: optional transformation to be applied. object with `type` field. See below
11
- colorMap: optional array of color mappings. See below
12
- excludedValues: Array of post-xform values to exclude when displaying.
13
- format: optional d3-format format for numeric values. Default if null is ","
14
-
15
- ## Xforms
16
-
17
- types:
18
-
19
-
20
7
  */
21
8
  export interface Axis {
9
+ /** Expression to be displayed on axis */
22
10
  expr: Expr;
23
- /**
24
- * `bin`: convert into bins. always has `numBins` integer and `min` and `max`. Can have `excludeUpper` and/or `excludeLower` to remove open bin on top or bottem. type enum
25
- * `date`: convert to complete date e.g. `2015-02-08`. type date
26
- * `year`: year only e.g. `2015-01-01`. type date
27
- * `yearmonth`: year and month only e.g. `2015-02-01`. type date
28
- * `yearquarter`: year and quarter only e.g. `2015-01`. type enum
29
- * `yearweek`: year and week (ISO) only e.g. `2015-31`. type enum
30
- * `month`: month only e.g. `02`. type enum
31
- * `week`: ISO week of year e.g. `01` for the first week that contains January 4th
32
- * `ranges`: convert to ranges. type enum. `ranges` is array of { id (unique id), label (optional label), minValue (null for none), maxValue (null for none), minOpen (true for >, false for >=), maxOpen (true for <, false for <=) }
33
- * `floor`: convert to floor. type enum
11
+ /** Optional transformation to be applied. If a date is used, for example, it's generally
12
+ * better to use a transform to convert to a year or month rather than creating an expression.
34
13
  */
35
14
  xform?: AxisXform;
15
+ /** optional array of color mappings */
36
16
  colorMap?: ColorMap;
37
17
  /** optional array of category values which define the order in which categories should be rendered */
38
18
  drawOrder?: any[];
@@ -42,9 +22,11 @@ export interface Axis {
42
22
  };
43
23
  /** optional string for null category */
44
24
  nullLabel?: string;
25
+ /** Array of post-xform values to exclude when displaying. */
45
26
  excludedValues?: any[];
27
+ /** optional d3-format format for numeric values. Default if null is "," */
46
28
  format?: string;
47
- /** @deprecated */
29
+ /** @deprecated optional aggregation (e.g. sum) */
48
30
  aggr?: string;
49
31
  }
50
32
  /**
@@ -63,6 +45,19 @@ export interface AxisCategory {
63
45
  value: any;
64
46
  }
65
47
  export interface AxisXform {
48
+ /**
49
+ * Type of transformation
50
+ * `bin`: convert into bins. always has `numBins` integer and `min` and `max`. Can have `excludeUpper` and/or `excludeLower` to remove open bin on top or bottem. type enum
51
+ * `date`: convert to complete date e.g. `2015-02-08`. type date
52
+ * `year`: year only e.g. `2015-01-01`. type date
53
+ * `yearmonth`: year and month only e.g. `2015-02-01`. type date
54
+ * `yearquarter`: year and quarter only e.g. `2015-01`. type enum
55
+ * `yearweek`: year and week (ISO) only e.g. `2015-31`. type enum
56
+ * `month`: month only e.g. `02`. type enum
57
+ * `week`: ISO week of year e.g. `01` for the first week that contains January 4th
58
+ * `ranges`: convert to ranges. type enum. `ranges` is array of { id (unique id), label (optional label), minValue (null for none), maxValue (null for none), minOpen (true for >, false for >=), maxOpen (true for <, false for <=) }
59
+ * `floor`: convert to floor. type enum
60
+ */
66
61
  type: "bin" | "date" | "year" | "yearmonth" | "month" | "week" | "ranges" | "yearweek" | "yearquarter" | "floor";
67
62
  numBins?: number;
68
63
  min?: number;
@@ -38,6 +38,7 @@ const react_1 = __importDefault(require("react"));
38
38
  const R = react_1.default.createElement;
39
39
  const immer_1 = __importDefault(require("immer"));
40
40
  const valueFormatter_1 = require("../valueFormatter");
41
+ const dayjs_1 = __importDefault(require("../dayjs"));
41
42
  const xforms = [
42
43
  { type: "bin", input: "number", output: "enum" },
43
44
  { type: "ranges", input: "number", output: "enum" },
@@ -827,7 +828,7 @@ class AxisBuilder {
827
828
  }
828
829
  if (options.onlyValuesPresent) {
829
830
  // Sort and take only present
830
- categories = lodash_1.default.sortBy(lodash_1.default.uniq(values), item => item).map(value => ({ value, label: (0, moment_1.default)(value, "YYYY-MM-DD").format("ll") }));
831
+ categories = lodash_1.default.sortBy(lodash_1.default.uniq(values), item => item).map(value => ({ value, label: (0, valueFormatter_1.formatValue)("date", value, axis.format) }));
831
832
  if (hasNone) {
832
833
  categories.push(noneCategory);
833
834
  }
@@ -837,12 +838,12 @@ class AxisBuilder {
837
838
  min = values.sort()[0];
838
839
  max = values.sort().slice(-1)[0];
839
840
  // Use moment to get range
840
- current = (0, moment_1.default)(min, "YYYY-MM-DD");
841
- end = (0, moment_1.default)(max, "YYYY-MM-DD");
841
+ current = (0, dayjs_1.default)(min);
842
+ end = (0, dayjs_1.default)(max);
842
843
  categories = [];
843
844
  while (!current.isAfter(end)) {
844
- categories.push({ value: current.format("YYYY-MM-DD"), label: current.format("ll") });
845
- current.add(1, "days");
845
+ categories.push({ value: current.format("YYYY-MM-DD"), label: current.format(axis.format ?? "ll") });
846
+ current = current.add(1, "days");
846
847
  if (categories.length >= 1000) {
847
848
  break;
848
849
  }
@@ -947,9 +948,10 @@ class AxisBuilder {
947
948
  }
948
949
  return R("div", null, lodash_1.default.map(value, (v, i) => R("div", { key: i }, v)));
949
950
  case "date":
950
- return (0, moment_1.default)(value, moment_1.default.ISO_8601).format("ll");
951
+ console.log(axis);
952
+ return (0, valueFormatter_1.formatValue)(type, value, axis.format);
951
953
  case "datetime":
952
- return (0, moment_1.default)(value, moment_1.default.ISO_8601).format("lll");
954
+ return (0, valueFormatter_1.formatValue)(type, value, axis.format);
953
955
  }
954
956
  return "" + value;
955
957
  }
@@ -50,10 +50,10 @@ export default class AxisComponent extends AsyncLoadComponent<AxisComponentProps
50
50
  constructor(props: any);
51
51
  isLoadNeeded(newProps: any, oldProps: any): boolean;
52
52
  load(props: any, prevProps: any, callback: any): any;
53
- handleExprChange: (expr: any) => any;
54
- handleFormatChange: (ev: any) => any;
55
- handleXformTypeChange: (type: any) => any;
56
- handleXformChange: (xform: any) => any;
53
+ handleExprChange: (expr: any) => void;
54
+ handleFormatChange: (ev: any) => void;
55
+ handleXformTypeChange: (type: any) => void;
56
+ handleXformChange: (xform: any) => void;
57
57
  cleanAxis(axis: any): Axis | null;
58
58
  renderXform(axis: any): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | React.CElement<ui.RadioToggleComponentProps, ui.RadioToggleComponent> | null;
59
59
  renderColorMap(axis: any): (React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | React.CElement<any, AxisColorEditorComponent>)[] | null;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { AxisXform } from "./Axis";
2
+ import { AxisXform, AxisXformRange } from "./Axis";
3
3
  import { Expr, Schema } from "@mwater/expressions";
4
4
  export interface RangesComponentProps {
5
5
  schema: Schema;
@@ -18,9 +18,9 @@ export default class RangesComponent extends React.Component<RangesComponentProp
18
18
  }
19
19
  interface RangeComponentProps {
20
20
  /** Range to edit */
21
- range: any;
22
- onChange: any;
23
- onRemove: any;
21
+ range: AxisXformRange;
22
+ onChange: (range: AxisXformRange) => void;
23
+ onRemove: () => void;
24
24
  /** reorderable connector */
25
25
  connectDragSource: any;
26
26
  /** reorderable connector */
@@ -28,8 +28,14 @@ interface RangeComponentProps {
28
28
  connectDropTarget: any;
29
29
  }
30
30
  declare class RangeComponent extends React.Component<RangeComponentProps> {
31
- handleMinOpenChange: (minOpen: any) => any;
32
- handleMaxOpenChange: (maxOpen: any) => any;
31
+ /**
32
+ * Handles change in minimum open value
33
+ */
34
+ handleMinOpenChange: (minOpen: boolean) => void;
35
+ /**
36
+ * Handles change in maximum open value
37
+ */
38
+ handleMaxOpenChange: (maxOpen: boolean) => void;
33
39
  render(): any;
34
40
  }
35
41
  export {};
@@ -10,6 +10,7 @@ const update_object_1 = __importDefault(require("update-object"));
10
10
  const expressions_ui_1 = require("@mwater/expressions-ui");
11
11
  const NumberInputComponent_1 = __importDefault(require("@mwater/react-library/lib/NumberInputComponent"));
12
12
  const ReorderableListComponent_1 = __importDefault(require("@mwater/react-library/lib/reorderable/ReorderableListComponent"));
13
+ const immer_1 = __importDefault(require("immer"));
13
14
  // Allows setting of ranges
14
15
  class RangesComponent extends react_1.default.Component {
15
16
  handleRangeChange = (index, range) => {
@@ -59,11 +60,21 @@ class RangesComponent extends react_1.default.Component {
59
60
  exports.default = RangesComponent;
60
61
  // Single range (row)
61
62
  class RangeComponent extends react_1.default.Component {
63
+ /**
64
+ * Handles change in minimum open value
65
+ */
62
66
  handleMinOpenChange = (minOpen) => {
63
- return this.props.onChange((0, update_object_1.default)(this.props.range, { minOpen: { $set: minOpen } }));
67
+ return this.props.onChange((0, immer_1.default)(this.props.range, draft => {
68
+ draft.minOpen = minOpen;
69
+ }));
64
70
  };
71
+ /**
72
+ * Handles change in maximum open value
73
+ */
65
74
  handleMaxOpenChange = (maxOpen) => {
66
- return this.props.onChange((0, update_object_1.default)(this.props.range, { maxOpen: { $set: maxOpen } }));
75
+ return this.props.onChange((0, immer_1.default)(this.props.range, draft => {
76
+ draft.maxOpen = maxOpen;
77
+ }));
67
78
  };
68
79
  render() {
69
80
  let placeholder = "";
@@ -88,23 +99,23 @@ class RangeComponent extends react_1.default.Component {
88
99
  }
89
100
  return this.props.connectDragPreview(this.props.connectDropTarget(R("tr", null, R("td", null, this.props.connectDragSource(R("span", { className: "fa fa-bars" }))), R("td", { key: "minOpen" }, R(expressions_ui_1.LinkComponent, {
90
101
  dropdownItems: [
91
- { id: true, name: "greater than" },
92
- { id: false, name: "greater than or equal to" }
102
+ { id: "true", name: "greater than" },
103
+ { id: "false", name: "greater than or equal to" }
93
104
  ],
94
- onDropdownItemClicked: this.handleMinOpenChange
105
+ onDropdownItemClicked: (id) => this.handleMinOpenChange(id === "true")
95
106
  }, this.props.range.minOpen ? "greater than" : "greater than or equal to")), R("td", { key: "minValue" }, R(NumberInputComponent_1.default, {
96
- value: this.props.range.minValue,
107
+ value: this.props.range.minValue ?? undefined,
97
108
  placeholder: "None",
98
109
  small: true,
99
110
  onChange: (v) => this.props.onChange((0, update_object_1.default)(this.props.range, { minValue: { $set: v } }))
100
111
  })), R("td", { key: "and" }, "\u00A0and\u00A0"), R("td", { key: "maxOpen" }, R(expressions_ui_1.LinkComponent, {
101
112
  dropdownItems: [
102
- { id: true, name: "less than" },
103
- { id: false, name: "less than or equal to" }
113
+ { id: "true", name: "less than" },
114
+ { id: "false", name: "less than or equal to" }
104
115
  ],
105
- onDropdownItemClicked: this.handleMaxOpenChange
116
+ onDropdownItemClicked: (id) => this.handleMaxOpenChange(id === "true")
106
117
  }, this.props.range.maxOpen ? "less than" : "less than or equal to")), R("td", { key: "maxValue" }, R(NumberInputComponent_1.default, {
107
- value: this.props.range.maxValue,
118
+ value: this.props.range.maxValue ?? undefined,
108
119
  placeholder: "None",
109
120
  small: true,
110
121
  onChange: (v) => this.props.onChange((0, update_object_1.default)(this.props.range, { maxValue: { $set: v } }))
@@ -57,12 +57,10 @@ export default class DashboardComponent extends React.Component<DashboardCompone
57
57
  };
58
58
  static childContextTypes: {
59
59
  locale: PropTypes.Requireable<string>;
60
- activeTables: PropTypes.Requireable<string[]>;
61
60
  };
62
61
  settings: SettingsModalComponent | null;
63
62
  getChildContext(): {
64
63
  locale: string | undefined;
65
- activeTables: string[];
66
64
  };
67
65
  constructor(props: any);
68
66
  getQuickfilterValues: () => any[];
@@ -85,11 +83,6 @@ export default class DashboardComponent extends React.Component<DashboardCompone
85
83
  className: string;
86
84
  onClick: () => void;
87
85
  }, HTMLElement>;
88
- renderStyleItem(style: any): React.DetailedReactHTMLElement<{
89
- key: any;
90
- className: string;
91
- onClick: () => void;
92
- }, HTMLElement>;
93
86
  renderStyle(): React.DetailedReactHTMLElement<{
94
87
  type: string;
95
88
  key: string;
@@ -105,11 +98,5 @@ export default class DashboardComponent extends React.Component<DashboardCompone
105
98
  }, HTMLElement>;
106
99
  renderQuickfilter(): React.CElement<import("../quickfilter/QuickfiltersComponent").QuickfiltersComponentProps, QuickfiltersComponent>;
107
100
  refDashboardView: (el: any) => any;
108
- render(): React.DetailedReactHTMLElement<{
109
- style: {
110
- display: "grid";
111
- gridTemplateRows: string;
112
- height: string;
113
- };
114
- }, HTMLElement>;
101
+ render(): React.JSX.Element;
115
102
  }
@@ -41,6 +41,7 @@ const DashboardUpgrader_1 = __importDefault(require("./DashboardUpgrader"));
41
41
  const LayoutOptionsComponent_1 = require("./LayoutOptionsComponent");
42
42
  const ModalWindowComponent_1 = __importDefault(require("@mwater/react-library/lib/ModalWindowComponent"));
43
43
  const layoutOptions_1 = require("./layoutOptions");
44
+ const expressions_ui_1 = require("@mwater/expressions-ui");
44
45
  /** Dashboard component that includes an action bar at the top
45
46
  * Manages undo stack and quickfilter value
46
47
  */
@@ -49,15 +50,12 @@ class DashboardComponent extends react_1.default.Component {
49
50
  static defaultProps = { printScaling: true };
50
51
  static childContextTypes = {
51
52
  locale: prop_types_1.default.string,
52
- activeTables: prop_types_1.default.arrayOf(prop_types_1.default.string.isRequired)
53
53
  };
54
54
  settings;
55
55
  getChildContext() {
56
56
  return {
57
57
  // Pass locale down. Both here and DashboardViewComponent to ensure that quickfilters also get context
58
58
  locale: this.props.design.locale,
59
- // Pass active tables down to table select components so they can present a shorter list
60
- activeTables: DashboardUtils.getFilterableTables(this.props.design, this.props.schema)
61
59
  };
62
60
  }
63
61
  constructor(props) {
@@ -162,34 +160,6 @@ class DashboardComponent extends react_1.default.Component {
162
160
  onClick: this.handleToggleEditing
163
161
  }, R("span", { className: "fas fa-pencil-alt" }), this.state.editing ? " Editing" : " Edit");
164
162
  }
165
- renderStyleItem(style) {
166
- const isActive = (this.props.design.style || "default") === style;
167
- const content = (() => {
168
- switch (style) {
169
- case "default":
170
- return [
171
- R("h4", { key: "name", className: "list-group-item-heading" }, "Classic Dashboard"),
172
- R("p", { key: "description", className: "" }, "Ideal for data display with minimal text")
173
- ];
174
- case "greybg":
175
- return [
176
- R("h4", { key: "name", className: "list-group-item-heading" }, "Framed Dashboard"),
177
- R("p", { key: "description", className: "" }, "Each widget is white on a grey background")
178
- ];
179
- case "story":
180
- return [
181
- R("h4", { key: "name", className: "list-group-item-heading" }, "Story"),
182
- R("p", { key: "description", className: "" }, "Ideal for data-driven storytelling with lots of text. Responsive and mobile-friendly")
183
- ];
184
- }
185
- return null;
186
- })();
187
- return R("a", {
188
- key: style,
189
- className: `list-group-item ${isActive ? "active" : ""}`,
190
- onClick: this.handleStyleChange.bind(null, style)
191
- }, content);
192
- }
193
163
  renderStyle() {
194
164
  return R("button", { type: "button", key: "style", className: "btn btn-link btn-sm", onClick: this.handleOpenLayoutOptions }, R("span", { className: "fa fa-mobile" }), R("span", { className: "hide-600px" }, " Layout "));
195
165
  }
@@ -234,7 +204,8 @@ class DashboardComponent extends react_1.default.Component {
234
204
  locks: this.props.quickfilterLocks,
235
205
  filters: this.getCompiledFilters(),
236
206
  hideTopBorder: this.props.hideTitleBar,
237
- onHide: () => this.setState({ hideQuickfilters: true })
207
+ // Don't hide if title bar is hidden as it can't be shown again
208
+ onHide: () => !this.props.hideTitleBar ? this.setState({ hideQuickfilters: true }) : undefined
238
209
  });
239
210
  }
240
211
  refDashboardView = (el) => {
@@ -268,30 +239,21 @@ class DashboardComponent extends react_1.default.Component {
268
239
  namedStrings: this.props.namedStrings,
269
240
  hideScopes: this.state.hideQuickfilters
270
241
  });
271
- return R("div", {
272
- style: {
273
- display: "grid",
274
- gridTemplateRows: this.props.hideTitleBar ? "auto 1fr" : "auto auto 1fr",
275
- height: "100%"
276
- }
277
- }, !this.props.hideTitleBar ? this.renderTitleBar() : undefined, R("div", null, !this.state.hideQuickfilters ? this.renderQuickfilter() : undefined), dashboardView, this.props.onDesignChange != null
278
- ? R(SettingsModalComponent_1.default, {
279
- onDesignChange: this.handleDesignChange,
280
- schema: this.props.schema,
281
- dataSource: this.props.dataSource,
282
- ref: (c) => {
283
- this.settings = c;
284
- }
285
- })
286
- : undefined, this.state.layoutOptionsOpen
287
- ? R(ModalWindowComponent_1.default, { isOpen: true, outerPadding: 10, innerPadding: 10 }, R(LayoutOptionsComponent_1.LayoutOptionsComponent, {
288
- design: this.props.design,
289
- onDesignChange: this.props.onDesignChange,
290
- onClose: () => this.setState({ layoutOptionsOpen: false }),
291
- dashboardView: readonlyDashboardView,
292
- quickfiltersView: this.renderQuickfilter()
293
- }))
294
- : undefined);
242
+ // Pass active tables down to table select components so they can present a shorter list
243
+ return react_1.default.createElement(expressions_ui_1.ActiveTablesContext.Provider, { value: DashboardUtils.getFilterableTables(this.props.design, this.props.schema) },
244
+ react_1.default.createElement("div", { style: {
245
+ display: "grid",
246
+ gridTemplateRows: this.props.hideTitleBar ? "auto 1fr" : "auto auto 1fr",
247
+ height: "100%"
248
+ } },
249
+ !this.props.hideTitleBar ? this.renderTitleBar() : undefined,
250
+ react_1.default.createElement("div", null, !this.state.hideQuickfilters ? this.renderQuickfilter() : undefined),
251
+ dashboardView,
252
+ this.props.onDesignChange != null && (react_1.default.createElement(SettingsModalComponent_1.default, { onDesignChange: this.handleDesignChange, schema: this.props.schema, dataSource: this.props.dataSource, ref: (c) => {
253
+ this.settings = c;
254
+ } })),
255
+ this.state.layoutOptionsOpen && (react_1.default.createElement(ModalWindowComponent_1.default, { isOpen: true, outerPadding: 10, innerPadding: 10 },
256
+ react_1.default.createElement(LayoutOptionsComponent_1.LayoutOptionsComponent, { design: this.props.design, onDesignChange: this.props.onDesignChange, onClose: () => this.setState({ layoutOptionsOpen: false }), dashboardView: readonlyDashboardView, quickfiltersView: this.renderQuickfilter() })))));
295
257
  }
296
258
  }
297
259
  exports.default = DashboardComponent;
@@ -1,6 +1,7 @@
1
1
  import { Quickfilter } from "../quickfilter/Quickfilter";
2
- import { LiteralType, Expr } from "@mwater/expressions";
2
+ import { Expr } from "@mwater/expressions";
3
3
  import { BlocksLayoutOptions, DashboardTheme } from "./layoutOptions";
4
+ import { GlobalFilter } from "../GlobalFilter";
4
5
  /** Dashboard design
5
6
  * Each understands enough of the dashboard design to create widgets.
6
7
  * Widget refers to the widget itself, where *item* refers also to the layout and id that it has in the dashboard.
@@ -27,19 +28,3 @@ export interface DashboardDesign {
27
28
  /** array of global filters. See below. */
28
29
  globalFilters?: GlobalFilter[];
29
30
  }
30
- /** Global Filters:
31
-
32
- Global filters apply to multiple tables at once if a certain column is present. User-interface to set them is application-specific
33
- and the default (non-mWater) dashboard applies them but does not allow editing.
34
-
35
- */
36
- export interface GlobalFilter {
37
- /** id of column to filter */
38
- columnId: string;
39
- /** type of column to filter (to ensure that consistent) */
40
- columnType: LiteralType;
41
- /** op of expression for filtering */
42
- op: string;
43
- /** array of expressions to use for filtering. field expression for column will be injected as expression 0 in the resulting filter expression */
44
- exprs: Expr[];
45
- }
@@ -114,17 +114,16 @@ class DashboardViewComponent extends react_1.default.Component {
114
114
  }
115
115
  // Call to print the dashboard
116
116
  print = async () => {
117
- // Temporarily disable vector maps as WebGL is not supported in print mode
118
- const mapTilerAPIKey = (0, vectorMaps_1.getMapTilerApiKey)();
117
+ // Temporarily enable print mode for vector maps
119
118
  try {
120
- (0, vectorMaps_1.setMapTilerApiKey)("");
119
+ (0, vectorMaps_1.setPrintingModeEnabled)(true);
121
120
  // Create element at 1080 wide (use as standard printing width)
122
121
  const elem = R("div", { style: { width: 1080 } }, R(DashboardViewComponent, lodash_1.default.extend({}, this.props, { onDesignChange: null, printMode: true })));
123
122
  const printer = new ReactElementPrinter_1.default();
124
123
  await printer.print(elem, { delay: 5000 });
125
124
  }
126
125
  finally {
127
- (0, vectorMaps_1.setMapTilerApiKey)(mapTilerAPIKey);
126
+ (0, vectorMaps_1.setPrintingModeEnabled)(false);
128
127
  }
129
128
  };
130
129
  // Get filters from props filters combined with dashboard filters
@@ -103,9 +103,10 @@ function ThemeToggle(props) {
103
103
  return null;
104
104
  }
105
105
  return (react_1.default.createElement(bootstrap_1.FormGroup, { label: "Theme" },
106
- renderStyleItem("default"),
107
- renderStyleItem("greybg"),
108
- renderStyleItem("story")));
106
+ react_1.default.createElement("div", { className: "list-group" },
107
+ renderStyleItem("default"),
108
+ renderStyleItem("greybg"),
109
+ renderStyleItem("story"))));
109
110
  }
110
111
  function WidthSelector(props) {
111
112
  return (react_1.default.createElement(bootstrap_1.Select, { value: props.value, onChange: props.onChange, nullLabel: "N/A", options: [
@@ -56,6 +56,7 @@ declare class ServerWidgetMapDataSource implements MapDataSource {
56
56
  e: number;
57
57
  s: number;
58
58
  } | null) => void): void;
59
+ getQuickfiltersDataSource(): QuickfiltersDataSource;
59
60
  }
60
61
  interface ServerWidgetLayerDataSourceOptions extends ServerDashboardDataSourceOptions {
61
62
  widgetId: string;
@@ -184,6 +184,9 @@ class ServerWidgetMapDataSource {
184
184
  return callback(new Error(xhr.responseText));
185
185
  });
186
186
  }
187
+ getQuickfiltersDataSource() {
188
+ return new ServerQuickfilterDataSource(this.options);
189
+ }
187
190
  }
188
191
  class ServerWidgetLayerDataSource {
189
192
  options;
@@ -1,33 +1,22 @@
1
- import PropTypes from "prop-types";
2
1
  import React from "react";
3
2
  import { DataSource, Schema } from "@mwater/expressions";
3
+ import { DashboardDesign } from "./DashboardDesign";
4
4
  export interface SettingsModalComponentProps {
5
5
  onDesignChange: any;
6
6
  schema: Schema;
7
7
  dataSource: DataSource;
8
8
  }
9
9
  interface SettingsModalComponentState {
10
- design: any;
10
+ design: DashboardDesign | null;
11
11
  }
12
12
  export default class SettingsModalComponent extends React.Component<SettingsModalComponentProps, SettingsModalComponentState> {
13
- static contextTypes: {
14
- globalFiltersElementFactory: PropTypes.Requireable<(...args: any[]) => any>;
15
- };
16
- constructor(props: any);
13
+ constructor(props: SettingsModalComponentProps);
17
14
  show(design: any): void;
18
15
  handleSave: () => void;
19
16
  handleCancel: () => void;
20
17
  handleDesignChange: (design: any) => void;
21
18
  handleFiltersChange: (filters: any) => void;
22
19
  handleGlobalFiltersChange: (globalFilters: any) => void;
23
- render(): React.CElement<{
24
- size: string;
25
- onCancel: () => void;
26
- onAction: () => void;
27
- }, React.Component<{
28
- size: string;
29
- onCancel: () => void;
30
- onAction: () => void;
31
- }, any, any>> | null;
20
+ render(): React.JSX.Element | null;
32
21
  }
33
22
  export {};
@@ -26,7 +26,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const prop_types_1 = __importDefault(require("prop-types"));
30
29
  const lodash_1 = __importDefault(require("lodash"));
31
30
  const react_1 = __importDefault(require("react"));
32
31
  const R = react_1.default.createElement;
@@ -38,9 +37,9 @@ const DashboardUtils = __importStar(require("./DashboardUtils"));
38
37
  const ActionCancelModalComponent_1 = __importDefault(require("@mwater/react-library/lib/ActionCancelModalComponent"));
39
38
  const QuickfiltersDesignComponent_1 = __importDefault(require("../quickfilter/QuickfiltersDesignComponent"));
40
39
  const FiltersDesignerComponent_1 = __importDefault(require("../FiltersDesignerComponent"));
40
+ const MWaterContextComponent_1 = require("../MWaterContextComponent");
41
41
  // Popup with settings for dashboard
42
42
  class SettingsModalComponent extends react_1.default.Component {
43
- static contextTypes = { globalFiltersElementFactory: prop_types_1.default.func };
44
43
  constructor(props) {
45
44
  super(props);
46
45
  this.state = {
@@ -81,42 +80,29 @@ class SettingsModalComponent extends react_1.default.Component {
81
80
  label: language.en + " (" + language.name + ")"
82
81
  };
83
82
  });
84
- return R(ActionCancelModalComponent_1.default, {
85
- size: "large",
86
- onCancel: this.handleCancel,
87
- onAction: this.handleSave
88
- }, R("div", { style: { paddingBottom: 200 } }, R("h4", null, "Quick Filters"), R("div", { className: "text-muted" }, "Quick filters are shown to the user as a dropdown at the top of the dashboard and can be used to filter data of widgets."), filterableTables.length > 0
89
- ? R(QuickfiltersDesignComponent_1.default, {
90
- design: this.state.design.quickfilters || [],
91
- onDesignChange: (design) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { quickfilters: { $set: design } })),
92
- schema: this.props.schema,
93
- dataSource: this.props.dataSource,
94
- tables: filterableTables
95
- })
96
- : "Nothing to quickfilter. Add widgets to the dashboard", R("h4", { style: { paddingTop: 10 } }, "Filters"), R("div", { className: "text-muted" }, "Filters are built in to the dashboard and cannot be changed by viewers of the dashboard."), filterableTables.length > 0
97
- ? R(FiltersDesignerComponent_1.default, {
98
- schema: this.props.schema,
99
- dataSource: this.props.dataSource,
100
- filters: this.state.design.filters,
101
- onFiltersChange: this.handleFiltersChange,
102
- filterableTables
103
- })
104
- : "Nothing to filter. Add widgets to the dashboard", this.context.globalFiltersElementFactory
105
- ? R("div", null, R("h4", { style: { paddingTop: 10 } }, "Global Filters"), this.context.globalFiltersElementFactory({
106
- schema: this.props.schema,
107
- dataSource: this.props.dataSource,
108
- filterableTables,
109
- globalFilters: this.state.design.globalFilters || [],
110
- onChange: this.handleGlobalFiltersChange
111
- }))
112
- : undefined, R("h4", { style: { paddingTop: 10 } }, "Language"), R("div", { className: "text-muted" }, "Controls the preferred language of widgets and uses specified language when available"), R(react_select_1.default, {
113
- value: lodash_1.default.findWhere(localeOptions, { value: this.state.design.locale || "en" }) || null,
114
- options: localeOptions,
115
- onChange: (locale) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { locale: { $set: locale.value } }))
116
- }), R("h4", { style: { paddingTop: 10 } }, "Advanced"), R(ui.Checkbox, {
117
- value: this.state.design.implicitFiltersEnabled != null ? this.state.design.implicitFiltersEnabled : true,
118
- onChange: (value) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { implicitFiltersEnabled: { $set: value } }))
119
- }, "Enable Implicit Filtering (leave unchecked for new dashboards)")));
83
+ return (react_1.default.createElement(ActionCancelModalComponent_1.default, { size: "large", onCancel: this.handleCancel, onAction: this.handleSave },
84
+ react_1.default.createElement("div", { style: { paddingBottom: 200 } },
85
+ react_1.default.createElement("h4", null, "Quick Filters"),
86
+ react_1.default.createElement("div", { className: "text-muted" }, "Quick filters are shown to the user as a dropdown at the top of the dashboard and can be used to filter data of widgets."),
87
+ filterableTables.length > 0 ? (react_1.default.createElement(QuickfiltersDesignComponent_1.default, { design: this.state.design.quickfilters || [], onDesignChange: (design) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { quickfilters: { $set: design } })), schema: this.props.schema, dataSource: this.props.dataSource, tables: filterableTables })) : ("Nothing to quickfilter. Add widgets to the dashboard"),
88
+ react_1.default.createElement("h4", { style: { paddingTop: 10 } }, "Filters"),
89
+ react_1.default.createElement("div", { className: "text-muted" }, "Filters are built in to the dashboard and cannot be changed by viewers of the dashboard."),
90
+ filterableTables.length > 0 ? (react_1.default.createElement(FiltersDesignerComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, filters: this.state.design.filters, onFiltersChange: this.handleFiltersChange, filterableTables: filterableTables })) : ("Nothing to filter. Add widgets to the dashboard"),
91
+ react_1.default.createElement(MWaterContextComponent_1.GlobalFiltersElementFactoryContext.Consumer, null, globalFiltersElementFactory => globalFiltersElementFactory ? (react_1.default.createElement("div", null,
92
+ react_1.default.createElement("h4", { style: { paddingTop: 10 } }, "Global Filters"),
93
+ globalFiltersElementFactory({
94
+ schema: this.props.schema,
95
+ dataSource: this.props.dataSource,
96
+ filterableTables,
97
+ globalFilters: this.state.design.globalFilters || [],
98
+ onChange: this.handleGlobalFiltersChange
99
+ }))) : undefined),
100
+ react_1.default.createElement("h4", { style: { paddingTop: 10 } }, "Language"),
101
+ react_1.default.createElement("div", { className: "text-muted" }, "Controls the preferred language of widgets and uses specified language when available"),
102
+ react_1.default.createElement(react_select_1.default, { value: lodash_1.default.findWhere(localeOptions, { value: this.state.design.locale || "en" }) || null, options: localeOptions, onChange: (locale) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { locale: { $set: locale.value } })) }),
103
+ this.state.design.implicitFiltersEnabled && (react_1.default.createElement(react_1.default.Fragment, null,
104
+ react_1.default.createElement("h4", { style: { paddingTop: 10 } }, "Advanced"),
105
+ react_1.default.createElement(ui.Checkbox, { value: this.state.design.implicitFiltersEnabled != null ? this.state.design.implicitFiltersEnabled : true, onChange: (value) => this.handleDesignChange((0, update_object_1.default)(this.state.design, { implicitFiltersEnabled: { $set: value } })) }, "Enable Implicit Filtering (leave unchecked for new dashboards)"))))));
120
106
  }
121
107
  }
122
108
  exports.default = SettingsModalComponent;