@mwater/visualization 5.4.4 → 5.5.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 (136) hide show
  1. package/.storybook/head.html +0 -1
  2. package/lib/MWaterContextComponent.js +1 -1
  3. package/lib/MWaterLoaderComponent.d.ts +2 -2
  4. package/lib/dashboards/DashboardComponent.js +2 -1
  5. package/lib/dashboards/LayoutOptionsComponent.js +18 -11
  6. package/lib/dashboards/ServerDashboardDataSource.d.ts +10 -1
  7. package/lib/dashboards/ServerDashboardDataSource.js +29 -0
  8. package/lib/dashboards/layoutOptions.d.ts +5 -1
  9. package/lib/datagrids/DatagridComponent.js +1 -1
  10. package/lib/datagrids/ExprCellComponent.d.ts +1 -0
  11. package/lib/datagrids/ExprCellComponent.js +22 -20
  12. package/lib/maps/BufferLayer.d.ts +18 -0
  13. package/lib/maps/BufferLayer.js +24 -14
  14. package/lib/maps/ChoroplethLayer.d.ts +18 -0
  15. package/lib/maps/ChoroplethLayer.js +34 -25
  16. package/lib/maps/ChoroplethLayerDesign.d.ts +3 -2
  17. package/lib/maps/ChoroplethLayerDesigner.d.ts +11 -1
  18. package/lib/maps/DirectMapDataSource.js +17 -0
  19. package/lib/maps/EditHoverOver.d.ts +1 -1
  20. package/lib/maps/EditHoverOver.js +62 -33
  21. package/lib/maps/HoverContent.d.ts +10 -5
  22. package/lib/maps/HoverContent.js +6 -35
  23. package/lib/maps/Layer.d.ts +37 -0
  24. package/lib/maps/Layer.js +30 -4
  25. package/lib/maps/MWaterServerLayer.d.ts +2 -2
  26. package/lib/maps/MWaterServerLayer.js +6 -6
  27. package/lib/maps/MapLayerDataSource.d.ts +9 -0
  28. package/lib/maps/MapUtils.d.ts +19 -1
  29. package/lib/maps/MapUtils.js +71 -1
  30. package/lib/maps/MarkersLayer.d.ts +18 -0
  31. package/lib/maps/MarkersLayer.js +24 -24
  32. package/lib/maps/MarkersLayerDesignerComponent.d.ts +14 -1
  33. package/lib/maps/RasterMapViewComponent.js +1 -1
  34. package/lib/maps/ServerMapDataSource.d.ts +9 -0
  35. package/lib/maps/ServerMapDataSource.js +29 -0
  36. package/lib/maps/VectorMapViewComponent.js +6 -6
  37. package/lib/maps/maps.d.ts +4 -2
  38. package/lib/mwater_table_selection/FormsListComponent.d.ts +33 -0
  39. package/lib/mwater_table_selection/FormsListComponent.js +141 -0
  40. package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +47 -0
  41. package/lib/mwater_table_selection/IndicatorsListComponent.js +182 -0
  42. package/lib/mwater_table_selection/IssuesListComponent.d.ts +29 -0
  43. package/lib/mwater_table_selection/IssuesListComponent.js +123 -0
  44. package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.d.ts +20 -0
  45. package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.js +157 -0
  46. package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.d.ts +17 -0
  47. package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.js +79 -0
  48. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +37 -0
  49. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +275 -0
  50. package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.d.ts +17 -0
  51. package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.js +94 -0
  52. package/lib/mwater_table_selection/MWaterMetricsTableListComponent.d.ts +17 -0
  53. package/lib/mwater_table_selection/MWaterMetricsTableListComponent.js +80 -0
  54. package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +32 -0
  55. package/lib/mwater_table_selection/MWaterTableSelectComponent.js +158 -0
  56. package/lib/quickfilter/Quickfilter.d.ts +2 -0
  57. package/lib/quickfilter/QuickfiltersDesignComponent.js +18 -10
  58. package/lib/widgets/charts/Chart.d.ts +11 -0
  59. package/lib/widgets/charts/Chart.js +15 -0
  60. package/lib/widgets/charts/ChartWidgetComponent.d.ts +1 -0
  61. package/lib/widgets/charts/ChartWidgetComponent.js +27 -1
  62. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +1 -1
  63. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +1 -1
  64. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +5 -12
  65. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +43 -57
  66. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +113 -110
  67. package/lib/widgets/charts/layered/LayeredChartUtils.d.ts +2 -1
  68. package/lib/widgets/charts/layered/LayeredChartUtils.js +0 -2
  69. package/lib/widgets/charts/pivot/PivotChart.d.ts +2 -0
  70. package/lib/widgets/charts/pivot/PivotChart.js +156 -0
  71. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +5 -20
  72. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +31 -61
  73. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +4 -0
  74. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +4 -2
  75. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.d.ts +5 -44
  76. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +38 -63
  77. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +7 -68
  78. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +58 -106
  79. package/lib/widgets/charts/table/TableChart.d.ts +2 -0
  80. package/lib/widgets/charts/table/TableChart.js +172 -1
  81. package/lib/widgets/charts/table/TableChartDesignerComponent.d.ts +7 -17
  82. package/lib/widgets/charts/table/TableChartDesignerComponent.js +79 -95
  83. package/lib/widgets/charts/table/TableChartViewComponent.d.ts +1 -7
  84. package/lib/widgets/charts/table/TableChartViewComponent.js +19 -27
  85. package/package.json +3 -8
  86. package/src/MWaterContextComponent.tsx +1 -1
  87. package/src/MWaterLoaderComponent.ts +1 -1
  88. package/src/dashboards/DashboardComponent.tsx +2 -1
  89. package/src/dashboards/LayoutOptionsComponent.tsx +22 -10
  90. package/src/dashboards/ServerDashboardDataSource.ts +36 -1
  91. package/src/dashboards/layoutOptions.tsx +5 -1
  92. package/src/datagrids/DatagridComponent.tsx +1 -1
  93. package/src/datagrids/ExprCellComponent.tsx +23 -20
  94. package/src/maps/BufferLayer.ts +35 -20
  95. package/src/maps/ChoroplethLayer.ts +51 -33
  96. package/src/maps/ChoroplethLayerDesign.ts +3 -2
  97. package/src/maps/ChoroplethLayerDesigner.tsx +2 -2
  98. package/src/maps/DirectMapDataSource.ts +21 -1
  99. package/src/maps/EditHoverOver.tsx +91 -51
  100. package/src/maps/HoverContent.tsx +16 -47
  101. package/src/maps/Layer.ts +42 -4
  102. package/src/maps/MWaterServerLayer.ts +6 -6
  103. package/src/maps/MapLayerDataSource.ts +8 -0
  104. package/src/maps/MapUtils.ts +70 -3
  105. package/src/maps/MarkersLayer.ts +34 -24
  106. package/src/maps/RasterMapViewComponent.ts +1 -1
  107. package/src/maps/ServerMapDataSource.ts +35 -0
  108. package/src/maps/VectorMapViewComponent.tsx +6 -6
  109. package/src/maps/maps.ts +4 -2
  110. package/src/mwater_table_selection/FormsListComponent.tsx +188 -0
  111. package/src/mwater_table_selection/IndicatorsListComponent.tsx +283 -0
  112. package/src/mwater_table_selection/IssuesListComponent.tsx +167 -0
  113. package/src/mwater_table_selection/MWaterAccountingSystemListComponent.tsx +225 -0
  114. package/src/{MWaterAssetSystemsListComponent.tsx → mwater_table_selection/MWaterAssetSystemsListComponent.tsx} +2 -2
  115. package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +377 -0
  116. package/src/{MWaterCustomTablesetListComponent.tsx → mwater_table_selection/MWaterCustomTablesetListComponent.tsx} +1 -1
  117. package/src/{MWaterMetricsTableListComponent.tsx → mwater_table_selection/MWaterMetricsTableListComponent.tsx} +1 -1
  118. package/src/{MWaterTableSelectComponent.tsx → mwater_table_selection/MWaterTableSelectComponent.tsx} +83 -86
  119. package/src/quickfilter/Quickfilter.ts +3 -0
  120. package/src/quickfilter/QuickfiltersDesignComponent.tsx +19 -14
  121. package/src/widgets/charts/Chart.ts +17 -0
  122. package/src/widgets/charts/ChartWidgetComponent.tsx +36 -1
  123. package/src/widgets/charts/layered/LayeredChartDesign.ts +1 -1
  124. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +23 -24
  125. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +260 -211
  126. package/src/widgets/charts/layered/LayeredChartUtils.ts +7 -7
  127. package/src/widgets/charts/pivot/PivotChart.ts +191 -0
  128. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +124 -129
  129. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +4 -2
  130. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +120 -149
  131. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +178 -198
  132. package/src/widgets/charts/table/TableChart.ts +177 -1
  133. package/src/widgets/charts/table/TableChartDesignerComponent.tsx +422 -0
  134. package/src/widgets/charts/table/{TableChartViewComponent.ts → TableChartViewComponent.tsx} +65 -60
  135. package/src/MWaterCompleteTableSelectComponent.tsx +0 -975
  136. package/src/widgets/charts/table/TableChartDesignerComponent.ts +0 -441
@@ -1,4 +1,3 @@
1
1
  <link rel="stylesheet" type="text/css" href="dist/css/libs.css">
2
2
  <link rel="stylesheet" type="text/css" href="dist/css/index.css">
3
3
  <link rel="stylesheet" type="text/css" href="assets/font-awesome/css/font-awesome.min.css">
4
- <script src="dist/js/libs.js"></script>
@@ -30,7 +30,7 @@ exports.AddLayerElementFactoryContext = exports.GlobalFiltersElementFactoryConte
30
30
  const lodash_1 = __importDefault(require("lodash"));
31
31
  const react_1 = __importStar(require("react"));
32
32
  const R = react_1.default.createElement;
33
- const MWaterTableSelectComponent_1 = __importDefault(require("./MWaterTableSelectComponent"));
33
+ const MWaterTableSelectComponent_1 = __importDefault(require("./mwater_table_selection/MWaterTableSelectComponent"));
34
34
  const MWaterAddRelatedFormComponent_1 = __importDefault(require("./MWaterAddRelatedFormComponent"));
35
35
  const MWaterAddRelatedIndicatorComponent_1 = __importDefault(require("./MWaterAddRelatedIndicatorComponent"));
36
36
  const MWaterGlobalFiltersComponent_1 = __importDefault(require("./MWaterGlobalFiltersComponent"));
@@ -22,7 +22,7 @@ export interface MWaterLoaderComponentProps {
22
22
  children: (error: any, config?: {
23
23
  schema: Schema;
24
24
  dataSource: DataSource;
25
- }) => ReactElement<any>;
25
+ }) => ReactElement<any> | null;
26
26
  /** Custom error formatter that returns React node or string, gets passed the error response from server */
27
27
  errorFormatter?: (data: any, defaultError: string) => string;
28
28
  /** Origin of usage. e.g. "dashboards:43445364..." */
@@ -51,5 +51,5 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<MWaterLoad
51
51
  extraTables?: string[];
52
52
  onExtraTablesChange?: (extraTables: string[]) => void;
53
53
  addLayerElementFactory?: AddLayerElementFactory;
54
- }, MWaterContextComponent>;
54
+ }, MWaterContextComponent> | null;
55
55
  }
@@ -65,7 +65,8 @@ class DashboardComponent extends react_1.default.Component {
65
65
  editing: LayoutManager_1.default.createLayoutManager(props.design.layout).isEmpty(props.design.items) &&
66
66
  props.onDesignChange != null,
67
67
  layoutOptionsOpen: false,
68
- hideQuickfilters: layoutOptions.hideQuickfiltersWidth != null && layoutOptions.hideQuickfiltersWidth > document.body.clientWidth,
68
+ hideQuickfilters: layoutOptions.hideQuickfiltersWidth === 0 ||
69
+ (layoutOptions.hideQuickfiltersWidth != null && layoutOptions.hideQuickfiltersWidth > document.body.clientWidth),
69
70
  refreshKey: 1,
70
71
  locale: initialLocale
71
72
  };
@@ -78,8 +78,9 @@ function LayoutOptionsComponent(props) {
78
78
  react_1.default.createElement("div", { style: { backgroundColor: "#888", gridColumn: "1 / 4" } }),
79
79
  react_1.default.createElement("div", { style: { backgroundColor: "#888" } }),
80
80
  react_1.default.createElement("div", { style: { height: "100%", display: "grid", gridTemplateRows: "auto 1fr" } },
81
- react_1.default.createElement("div", { key: "quickfilters" }, layoutOptions.hideQuickfiltersWidth == null ||
82
- sizeOptions[previewSize].value.width > layoutOptions.hideQuickfiltersWidth
81
+ react_1.default.createElement("div", { key: "quickfilters" }, (layoutOptions.hideQuickfiltersWidth !== 0) &&
82
+ (layoutOptions.hideQuickfiltersWidth == null ||
83
+ sizeOptions[previewSize].value.width > layoutOptions.hideQuickfiltersWidth)
83
84
  ? props.quickfiltersView
84
85
  : null),
85
86
  props.dashboardView),
@@ -240,7 +241,7 @@ function CustomizeLayout(props) {
240
241
  react_1.default.createElement(bootstrap_1.FormGroup, { label: T `Hide Quickfilters` },
241
242
  react_1.default.createElement(WidthSelector, { value: layoutOptions.hideQuickfiltersWidth, onChange: (hideQuickfiltersWidth) => {
242
243
  onLayoutOptionsChange({ ...layoutOptions, hideQuickfiltersWidth });
243
- }, sign: "< " })),
244
+ }, sign: "< ", includeAlways: true })),
244
245
  react_1.default.createElement(bootstrap_1.FormGroup, { label: T `Minimum Width (before scrolling or scaling)` },
245
246
  react_1.default.createElement(WidthSelector, { value: layoutOptions.minimumWidth, onChange: (minimumWidth) => {
246
247
  onLayoutOptionsChange({ ...layoutOptions, minimumWidth });
@@ -305,12 +306,18 @@ function PixelsInput(props) {
305
306
  "px")))))));
306
307
  }
307
308
  function WidthSelector(props) {
308
- return (react_1.default.createElement(bootstrap_1.Select, { value: props.value, onChange: props.onChange, nullLabel: T `N/A`, options: [
309
- { value: 400, label: `${props.sign}400px (${T `Phone`})` },
310
- { value: 600, label: `${props.sign}600px (${T `Small tablet`})` },
311
- { value: 800, label: `${props.sign}800px (${T `Tablet`})` },
312
- { value: 1000, label: `${props.sign}1000px (${T `Laptop`})` },
313
- { value: 1200, label: `${props.sign}1200px (${T `Desktop`})` },
314
- { value: 1600, label: `${props.sign}1600px (${T `Wide Desktop`})` }
315
- ] }));
309
+ // Create options array with conditional "Always" option
310
+ const options = [
311
+ { value: 400, label: `${props.sign}400px (${T `Phone`})` },
312
+ { value: 600, label: `${props.sign}600px (${T `Small tablet`})` },
313
+ { value: 800, label: `${props.sign}800px (${T `Tablet`})` },
314
+ { value: 1000, label: `${props.sign}1000px (${T `Laptop`})` },
315
+ { value: 1200, label: `${props.sign}1200px (${T `Desktop`})` },
316
+ { value: 1600, label: `${props.sign}1600px (${T `Wide Desktop`})` }
317
+ ];
318
+ // Add "Always" option if requested
319
+ if (props.includeAlways) {
320
+ options.push({ value: 0, label: T `Always` });
321
+ }
322
+ return (react_1.default.createElement(bootstrap_1.Select, { value: props.value, onChange: props.onChange, nullLabel: T `N/A`, options: options }));
316
323
  }
@@ -17,7 +17,7 @@ interface ServerDashboardDataSourceOptions {
17
17
  /** data source that is used for determining cache expiry */
18
18
  dataSource: DataSource;
19
19
  /** revision to use to allow caching */
20
- rev: string;
20
+ rev?: number;
21
21
  }
22
22
  interface ServerWidgetDataSourceOptions extends ServerDashboardDataSourceOptions {
23
23
  widgetId: string;
@@ -77,6 +77,15 @@ declare class ServerWidgetLayerDataSource implements MapLayerDataSource {
77
77
  getPopupWidgetDataSource(design: any, widgetId: string): ServerWidgetLayerPopupWidgetDataSource;
78
78
  createUrl(filters: JsonQLFilter[], extension: string): string;
79
79
  createLegacyUrl(design: any, extension: string, filters: JsonQLFilter[]): string;
80
+ /** Gets hover over data for hover over items
81
+ * @param design The design of the layer
82
+ * @param data The data of the current item being hovered over. e.g. { id: 123 }
83
+ * @param filters The filters to apply to the layer does not include filters that narrow down to a specific item
84
+ * @returns A promise that resolves to the hover over data, indexed by the id of the hover over item
85
+ */
86
+ getHoverOverData(design: any, data: any, filters: JsonQLFilter[]): Promise<{
87
+ [key: string]: any;
88
+ }>;
80
89
  }
81
90
  interface ServerWidgetLayerPopupDataSourceOptions extends ServerDashboardDataSourceOptions {
82
91
  widgetId: string;
@@ -336,6 +336,35 @@ class ServerWidgetLayerDataSource {
336
336
  }
337
337
  return url;
338
338
  }
339
+ /** Gets hover over data for hover over items
340
+ * @param design The design of the layer
341
+ * @param data The data of the current item being hovered over. e.g. { id: 123 }
342
+ * @param filters The filters to apply to the layer does not include filters that narrow down to a specific item
343
+ * @returns A promise that resolves to the hover over data, indexed by the id of the hover over item
344
+ */
345
+ async getHoverOverData(design, data, filters) {
346
+ const query = {
347
+ client: this.options.client,
348
+ share: this.options.share,
349
+ filters: (0, compressJson_1.default)(filters || []),
350
+ data: (0, compressJson_1.default)(data),
351
+ rev: this.options.rev
352
+ };
353
+ const url = `${this.options.apiUrl}dashboards/${this.options.dashboardId}/widgets/${this.options.widgetId}/layers/${this.options.layerView.id}/hoverdata?` +
354
+ querystring_1.default.stringify(query);
355
+ const response = await fetch(url, {
356
+ method: "GET",
357
+ headers: {
358
+ Accept: "application/json"
359
+ }
360
+ });
361
+ if (!response.ok) {
362
+ const errorText = await response.text();
363
+ console.error(errorText);
364
+ throw new Error(`Error fetching hover data: ${response.statusText}`);
365
+ }
366
+ return await response.json();
367
+ }
339
368
  }
340
369
  class ServerWidgetLayerPopupWidgetDataSource {
341
370
  options;
@@ -12,7 +12,11 @@ export interface BlocksLayoutOptions {
12
12
  belowMinimumWidth: "scale" | "scroll";
13
13
  /** Width above which pads */
14
14
  maximumWidth: number | null;
15
- /** Width at which to hide quickfilters. Null for never */
15
+ /** Width at which to hide quickfilters.
16
+ * Null for never hide
17
+ * 0 for always hide
18
+ * Positive number for responsive hiding based on width
19
+ */
16
20
  hideQuickfiltersWidth: number | null;
17
21
  /** The padding around the entire dashboard */
18
22
  outerPadding: number;
@@ -276,7 +276,7 @@ exports.default = (0, react_1.forwardRef)(function DatagridComponent(props, ref)
276
276
  const renderTitleBar = () => {
277
277
  return (react_1.default.createElement("div", { style: { position: "absolute", top: 0, left: 0, right: 0, height: 40, padding: 4 } },
278
278
  react_1.default.createElement("div", { style: { float: "right" } },
279
- design.showNumRows && numRows ? react_1.default.createElement("small", { className: 'text-muted text-sm' }, `${(0, d3_format_1.format)(',')(numRows)} rows`) : undefined,
279
+ design.showNumRows && numRows ? react_1.default.createElement("small", { className: 'text-muted text-sm me-2' }, `${(0, d3_format_1.format)(',')(numRows)} rows`) : undefined,
280
280
  renderDeleteRows(),
281
281
  renderFindReplace(),
282
282
  renderCellEdit(),
@@ -23,5 +23,6 @@ export interface ExprCellComponentProps {
23
23
  }
24
24
  export default class ExprCellComponent extends React.Component<ExprCellComponentProps> {
25
25
  renderImage(id: string): React.JSX.Element;
26
+ renderCellContent(): string | React.JSX.Element | React.JSX.Element[] | null;
26
27
  render(): React.JSX.Element;
27
28
  }
@@ -16,51 +16,53 @@ class ExprCellComponent extends react_1.default.Component {
16
16
  const url = this.props.dataSource.getImageUrl(id);
17
17
  return react_1.default.createElement("a", { href: url, key: id, target: "_blank", style: { paddingLeft: 5, paddingRight: 5 } }, T `Image`);
18
18
  }
19
- render() {
20
- let node;
21
- const exprUtils = new expressions_1.ExprUtils(this.props.schema);
19
+ renderCellContent() {
22
20
  let { value } = this.props;
21
+ const exprUtils = new expressions_1.ExprUtils(this.props.schema);
23
22
  if (value == null || !this.props.expr) {
24
- node = null;
23
+ return null;
25
24
  }
26
25
  else {
27
26
  // Parse if should be JSON
28
27
  if (["image", "imagelist", "geometry", "text[]"].includes(this.props.exprType) && lodash_1.default.isString(value)) {
29
- value = JSON.parse(value);
28
+ try {
29
+ value = JSON.parse(value);
30
+ }
31
+ catch (e) {
32
+ console.error("Error parsing JSON", e);
33
+ return "???";
34
+ }
30
35
  }
31
36
  // Format if possible
32
37
  if ((0, valueFormatter_1.canFormatType)(this.props.exprType)) {
33
- node = (0, valueFormatter_2.formatValue)(this.props.exprType, value, this.props.format);
38
+ return (0, valueFormatter_2.formatValue)(this.props.exprType, value, this.props.format);
34
39
  }
35
40
  else {
36
41
  // Convert to node based on type
37
42
  switch (this.props.exprType) {
38
43
  case "text":
39
- node = react_1.default.createElement(react_linkify_1.default, { properties: { target: "_blank" } }, value);
40
- break;
44
+ return react_1.default.createElement(react_linkify_1.default, { properties: { target: "_blank" } }, value);
41
45
  case "boolean":
42
46
  case "enum":
43
47
  case "enumset":
44
48
  case "text[]":
45
- node = exprUtils.stringifyExprLiteral(this.props.expr, value, this.props.locale);
46
- break;
49
+ return exprUtils.stringifyExprLiteral(this.props.expr, value, this.props.locale);
47
50
  case "date":
48
- node = (0, moment_1.default)(value, "YYYY-MM-DD").format("ll");
49
- break;
51
+ return (0, moment_1.default)(value, "YYYY-MM-DD").format("ll");
50
52
  case "datetime":
51
- node = (0, moment_1.default)(value, moment_1.default.ISO_8601).format("lll");
52
- break;
53
+ return (0, moment_1.default)(value, moment_1.default.ISO_8601).format("lll");
53
54
  case "image":
54
- node = this.renderImage(value.id);
55
- break;
55
+ return this.renderImage(value.id);
56
56
  case "imagelist":
57
- node = lodash_1.default.map(value, (v) => this.renderImage(v.id));
58
- break;
57
+ return lodash_1.default.map(value, (v) => this.renderImage(v.id));
59
58
  default:
60
- node = "" + value;
59
+ return "" + value;
61
60
  }
62
61
  }
63
62
  }
63
+ }
64
+ render() {
65
+ const content = this.renderCellContent();
64
66
  return (react_1.default.createElement("div", { style: {
65
67
  width: this.props.width,
66
68
  height: this.props.height,
@@ -71,7 +73,7 @@ class ExprCellComponent extends react_1.default.Component {
71
73
  cursor: this.props.onClick ? "pointer" : undefined,
72
74
  overflow: "hidden",
73
75
  textOverflow: "ellipsis"
74
- }, onClick: this.props.onClick, onDoubleClick: this.props.onDoubleClick }, node));
76
+ }, onClick: this.props.onClick, onDoubleClick: this.props.onDoubleClick }, content));
75
77
  }
76
78
  }
77
79
  exports.default = ExprCellComponent;
@@ -50,4 +50,22 @@ export default class BufferLayer extends Layer<BufferLayerDesign> {
50
50
  validateDesign(design: BufferLayerDesign, schema: Schema): string | null;
51
51
  /** Get strings to be translated */
52
52
  getTranslatableStrings(design: BufferLayerDesign, schema: Schema): string[];
53
+ /** Gets hover over data for hover over items. This should be implemented by layers that have hover over items.
54
+ * It will be called on the server side if using a server map data source, or on the client side if using a direct
55
+ * map data source.
56
+ */
57
+ getHoverOverData(options: {
58
+ /** Design of the layer */
59
+ design: BufferLayerDesign;
60
+ /** Data of the current item being hovered over. e.g. { id: 123 } */
61
+ data: any;
62
+ /** Filters to apply to the hover over data, not including filtering down to the current item */
63
+ filters: JsonQLFilter[];
64
+ /** Schema to use */
65
+ schema: Schema;
66
+ /** Data source to use */
67
+ dataSource: DataSource;
68
+ }): Promise<{
69
+ [key: string]: any;
70
+ }>;
53
71
  }
@@ -39,6 +39,7 @@ const HoverContent_1 = __importDefault(require("./HoverContent"));
39
39
  const layoutOptions_1 = require("../dashboards/layoutOptions");
40
40
  const BlocksLayoutManager_1 = __importDefault(require("../layouts/blocks/BlocksLayoutManager"));
41
41
  const DashboardUtils_1 = require("../dashboards/DashboardUtils");
42
+ const MapUtils_1 = require("./MapUtils");
42
43
  /** Layer which draws a buffer around geometries (i.e. a radius circle around points) */
43
44
  class BufferLayer extends Layer_1.default {
44
45
  /** Gets the type of layer definition */
@@ -635,25 +636,20 @@ marker-fill: ` +
635
636
  }
636
637
  // same as onGridClick but handles hover over
637
638
  onGridHoverOver(ev, hoverOptions) {
638
- if (ev.data && ev.data.id) {
639
- const { table } = hoverOptions.design;
640
- const results = {};
641
- // Popup
642
- if (hoverOptions.design.hoverOver) {
643
- // Create filter using popupFilterJoins
644
- const popupFilterJoins = hoverOptions.design.popupFilterJoins || PopupFilterJoinsUtils.createDefaultPopupFilterJoins(table);
645
- const popupFilters = PopupFilterJoinsUtils.createPopupFilters(popupFilterJoins, hoverOptions.schema, table, ev.data.id);
646
- results.hoverOver = react_1.default.createElement(HoverContent_1.default, {
639
+ if (ev.data && ev.data.id && hoverOptions.design.hoverOver && hoverOptions.design.hoverOver.items.length > 0) {
640
+ const results = {
641
+ hoverOver: react_1.default.createElement(HoverContent_1.default, {
647
642
  key: ev.data.id,
648
643
  schema: hoverOptions.schema,
649
- dataSource: hoverOptions.dataSource,
650
- table,
644
+ data: ev.data,
645
+ mapLayerDataSource: hoverOptions.layerDataSource,
646
+ design: hoverOptions.design,
651
647
  items: hoverOptions.design.hoverOver.items,
652
- filters: popupFilters,
648
+ filters: hoverOptions.filters,
653
649
  locale: hoverOptions.locale,
654
650
  translate: hoverOptions.translate
655
- });
656
- }
651
+ })
652
+ };
657
653
  return results;
658
654
  }
659
655
  else {
@@ -836,5 +832,19 @@ marker-fill: ` +
836
832
  // Remove duplicates
837
833
  return lodash_1.default.uniq(strings);
838
834
  }
835
+ /** Gets hover over data for hover over items. This should be implemented by layers that have hover over items.
836
+ * It will be called on the server side if using a server map data source, or on the client side if using a direct
837
+ * map data source.
838
+ */
839
+ getHoverOverData(options) {
840
+ return (0, MapUtils_1.getSimpleHoverOverData)({
841
+ id: options.data.id,
842
+ table: options.design.table,
843
+ filters: options.filters,
844
+ schema: options.schema,
845
+ dataSource: options.dataSource,
846
+ hoverOverItems: options.design.hoverOver.items,
847
+ });
848
+ }
839
849
  }
840
850
  exports.default = BufferLayer;
@@ -72,4 +72,22 @@ export default class ChoroplethLayer extends Layer<ChoroplethLayerDesign> {
72
72
  }): React.ReactElement<{}>;
73
73
  /** Get strings to be translated */
74
74
  getTranslatableStrings(design: ChoroplethLayerDesign, schema: Schema): string[];
75
+ /** Gets hover over data for hover over items. This should be implemented by layers that have hover over items.
76
+ * It will be called on the server side if using a server map data source, or on the client side if using a direct
77
+ * map data source.
78
+ */
79
+ getHoverOverData(options: {
80
+ /** Design of the layer */
81
+ design: ChoroplethLayerDesign;
82
+ /** Data of the current item being hovered over. e.g. { id: 123 } */
83
+ data: any;
84
+ /** Filters to apply to the hover over data, not including filtering down to the current item */
85
+ filters: JsonQLFilter[];
86
+ /** Schema to use */
87
+ schema: Schema;
88
+ /** Data source to use */
89
+ dataSource: DataSource;
90
+ }): Promise<{
91
+ [key: string]: any;
92
+ }>;
75
93
  }
@@ -39,6 +39,7 @@ const HoverContent_1 = __importDefault(require("./HoverContent"));
39
39
  const layoutOptions_1 = require("../dashboards/layoutOptions");
40
40
  const BlocksLayoutManager_1 = __importDefault(require("../layouts/blocks/BlocksLayoutManager"));
41
41
  const DashboardUtils_1 = require("../dashboards/DashboardUtils");
42
+ const MapUtils_1 = require("./MapUtils");
42
43
  class ChoroplethLayer extends Layer_1.default {
43
44
  /** Gets the type of layer definition */
44
45
  getLayerDefinitionType() {
@@ -1246,41 +1247,28 @@ class ChoroplethLayer extends Layer_1.default {
1246
1247
  }
1247
1248
  // same as onGridClick but handles hover over
1248
1249
  onGridHoverOver(ev, hoverOptions) {
1249
- const regionsTable = hoverOptions.design.regionsTable || "admin_regions";
1250
- // Row only if mode is "plain" or "direct"
1251
- if (hoverOptions.design.regionMode == "plain" || hoverOptions.design.regionMode == "direct") {
1252
- if (!ev.data || !ev.data.id) {
1253
- return null;
1254
- }
1250
+ // Only applicable to indirect mode
1251
+ if (hoverOptions.design.regionMode !== "indirect") {
1252
+ return null;
1255
1253
  }
1256
1254
  // Ignore if indirect with no table
1257
1255
  if (!hoverOptions.design.table) {
1258
1256
  return null;
1259
1257
  }
1260
- if (ev.data && ev.data.id) {
1261
- const { table } = hoverOptions.design;
1262
- const results = {};
1263
- // Popup
1264
- if (hoverOptions.design.hoverOver) {
1265
- // Create default popup filter joins
1266
- const defaultPopupFilterJoins = {};
1267
- if (hoverOptions.design.adminRegionExpr) {
1268
- defaultPopupFilterJoins[hoverOptions.design.table] = hoverOptions.design.adminRegionExpr;
1269
- }
1270
- // Create filter using popupFilterJoins
1271
- const popupFilterJoins = hoverOptions.design.popupFilterJoins || defaultPopupFilterJoins;
1272
- const popupFilters = PopupFilterJoinsUtils.createPopupFilters(popupFilterJoins, hoverOptions.schema, table, ev.data.id, true);
1273
- results.hoverOver = react_1.default.createElement(HoverContent_1.default, {
1258
+ if (ev.data && ev.data.id && hoverOptions.design.hoverOver && hoverOptions.design.hoverOver.items.length > 0) {
1259
+ const results = {
1260
+ hoverOver: react_1.default.createElement(HoverContent_1.default, {
1274
1261
  key: ev.data.id,
1275
1262
  schema: hoverOptions.schema,
1276
- dataSource: hoverOptions.dataSource,
1277
- table,
1263
+ mapLayerDataSource: hoverOptions.layerDataSource,
1264
+ design: hoverOptions.design,
1278
1265
  items: hoverOptions.design.hoverOver.items,
1279
- filters: popupFilters,
1266
+ data: ev.data,
1267
+ filters: hoverOptions.filters,
1280
1268
  locale: hoverOptions.locale,
1281
1269
  translate: hoverOptions.translate
1282
- });
1283
- }
1270
+ })
1271
+ };
1284
1272
  return results;
1285
1273
  }
1286
1274
  else {
@@ -1535,5 +1523,26 @@ class ChoroplethLayer extends Layer_1.default {
1535
1523
  // Remove duplicates
1536
1524
  return lodash_1.default.uniq(strings);
1537
1525
  }
1526
+ /** Gets hover over data for hover over items. This should be implemented by layers that have hover over items.
1527
+ * It will be called on the server side if using a server map data source, or on the client side if using a direct
1528
+ * map data source.
1529
+ */
1530
+ getHoverOverData(options) {
1531
+ // Use popup filter joins utilities to create filters
1532
+ const popupFilterJoins = {};
1533
+ if (options.design.adminRegionExpr) {
1534
+ popupFilterJoins[options.design.table] = options.design.adminRegionExpr;
1535
+ }
1536
+ const popupFilters = PopupFilterJoinsUtils.createPopupFilters(popupFilterJoins, options.schema, options.design.table, options.data.id, true);
1537
+ return (0, MapUtils_1.getSimpleHoverOverData)({
1538
+ // Filter using popup filters instead of id since will return multiple rows
1539
+ id: null,
1540
+ table: options.design.table,
1541
+ filters: popupFilters,
1542
+ schema: options.schema,
1543
+ dataSource: options.dataSource,
1544
+ hoverOverItems: options.design.hoverOver.items,
1545
+ });
1546
+ }
1538
1547
  }
1539
1548
  exports.default = ChoroplethLayer;
@@ -48,11 +48,12 @@ export default interface ChoroplethLayerDesign {
48
48
  popup: {
49
49
  items: LayoutBlock;
50
50
  };
51
+ /** customizable filtering for popup. See PopupFilterJoins.md. Only when region mode is "indirect" */
52
+ popupFilterJoins: PopupFilterJoins;
53
+ /** Hover over items to display when hovering over a region. Only when region mode is "indirect" */
51
54
  hoverOver: {
52
55
  items: HoverOverItem[];
53
56
  };
54
- /** customizable filtering for popup. See PopupFilterJoins.md. Only when region mode is "indirect" */
55
- popupFilterJoins: PopupFilterJoins;
56
57
  /** minimum zoom level */
57
58
  minZoom?: number;
58
59
  /** maximum zoom level */
@@ -48,6 +48,16 @@ export default class ChoroplethLayerDesigner extends React.Component<{
48
48
  className: string;
49
49
  }, HTMLElement> | null;
50
50
  renderPopup(): React.CElement<any, EditPopupComponent> | null;
51
- renderHoverOver(): React.FunctionComponentElement<import("./EditHoverOver").EditHoverOverProps> | null;
51
+ renderHoverOver(): React.FunctionComponentElement<{
52
+ design: ChoroplethLayerDesign;
53
+ onDesignChange: (design: ChoroplethLayerDesign) => void;
54
+ schema: Schema;
55
+ dataSource: DataSource;
56
+ table: string;
57
+ idTable: string;
58
+ defaultPopupFilterJoins: {
59
+ [tableId: string]: Expr;
60
+ };
61
+ }> | null;
52
62
  render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
53
63
  }
@@ -262,4 +262,21 @@ class DirectLayerDataSource {
262
262
  }
263
263
  return url;
264
264
  }
265
+ /** Gets hover over data for hover over items
266
+ * @param design The design of the layer
267
+ * @param data The data of the current item being hovered over. e.g. { id: 123 }
268
+ * @param filters The filters to apply to the hover over data, not including filtering down to the current item
269
+ * @returns A promise that resolves to the hover over data, indexed by the id of the hover over item
270
+ */
271
+ getHoverOverData(design, data, filters) {
272
+ // Create layer
273
+ const layer = LayerFactory_1.default.createLayer(this.options.layerView.type);
274
+ return layer.getHoverOverData({
275
+ design,
276
+ data,
277
+ filters,
278
+ schema: this.options.schema,
279
+ dataSource: this.options.dataSource,
280
+ });
281
+ }
265
282
  }
@@ -14,5 +14,5 @@ export interface EditHoverOverProps {
14
14
  idTable: string;
15
15
  defaultPopupFilterJoins: any;
16
16
  }
17
- declare const EditHoverOver: React.FC<EditHoverOverProps>;
17
+ declare function EditHoverOver(props: EditHoverOverProps): React.JSX.Element;
18
18
  export default EditHoverOver;