@mwater/visualization 5.1.0 → 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 (101) hide show
  1. package/lib/GlobalFilter.d.ts +13 -0
  2. package/lib/GlobalFilter.js +2 -0
  3. package/lib/MWaterCompleteTableSelectComponent.d.ts +2 -9
  4. package/lib/MWaterContextComponent.d.ts +15 -3
  5. package/lib/MWaterContextComponent.js +38 -13
  6. package/lib/MWaterCustomTablesetListComponent.js +9 -3
  7. package/lib/MWaterGlobalFiltersComponent.d.ts +6 -5
  8. package/lib/MWaterGlobalFiltersComponent.js +4 -4
  9. package/lib/MWaterLoaderComponent.d.ts +12 -2
  10. package/lib/MWaterLoaderComponent.js +9 -1
  11. package/lib/axes/Axis.d.ts +20 -25
  12. package/lib/axes/AxisBuilder.js +9 -7
  13. package/lib/axes/AxisComponent.d.ts +4 -4
  14. package/lib/dashboards/DashboardComponent.d.ts +0 -5
  15. package/lib/dashboards/DashboardComponent.js +2 -29
  16. package/lib/dashboards/DashboardDesign.d.ts +2 -17
  17. package/lib/dashboards/DashboardViewComponent.js +3 -4
  18. package/lib/dashboards/LayoutOptionsComponent.js +4 -3
  19. package/lib/dashboards/SettingsModalComponent.d.ts +4 -15
  20. package/lib/dashboards/SettingsModalComponent.js +24 -38
  21. package/lib/datagrids/DatagridComponent.d.ts +2 -9
  22. package/lib/datagrids/DatagridDataSource.d.ts +3 -3
  23. package/lib/datagrids/DatagridDataSource.js +0 -14
  24. package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -93
  25. package/lib/datagrids/DatagridDesignerComponent.js +8 -6
  26. package/lib/datagrids/DatagridViewComponent.js +1 -1
  27. package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -20
  28. package/lib/datagrids/FindReplaceModalComponent.js +27 -13
  29. package/lib/datagrids/ServerDatagridDataSource.d.ts +1 -1
  30. package/lib/datagrids/ServerDatagridDataSource.js +1 -3
  31. package/lib/demo.js +1 -1
  32. package/lib/index.d.ts +1 -0
  33. package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +2 -1
  34. package/lib/layouts/grid/GridLayoutManager.d.ts +2 -1
  35. package/lib/maps/BufferLayer.js +3 -1
  36. package/lib/maps/ClusterLayer.js +3 -1
  37. package/lib/maps/GridLayer.js +5 -3
  38. package/lib/maps/GridLayerDesigner.js +0 -1
  39. package/lib/maps/LayerSwitcherComponent.js +1 -1
  40. package/lib/maps/MapComponent.d.ts +2 -7
  41. package/lib/maps/MapDesign.d.ts +2 -13
  42. package/lib/maps/MapFiltersDesignerComponent.d.ts +0 -4
  43. package/lib/maps/MapFiltersDesignerComponent.js +4 -5
  44. package/lib/maps/RasterMapViewComponent.d.ts +2 -9
  45. package/lib/maps/RegionSelectComponent.d.ts +2 -1
  46. package/lib/maps/ServerMapDataSource.d.ts +1 -1
  47. package/lib/maps/vectorMaps.d.ts +1 -0
  48. package/lib/maps/vectorMaps.js +10 -2
  49. package/lib/quickfilter/QuickfilterCompiler.d.ts +1 -1
  50. package/lib/widgets/IFrameWidgetComponent.d.ts +2 -9
  51. package/lib/widgets/ImageWidgetComponent.d.ts +6 -24
  52. package/lib/widgets/MapWidget.d.ts +2 -7
  53. package/lib/widgets/MarkdownWidget.d.ts +2 -7
  54. package/lib/widgets/TOCWidget.d.ts +2 -9
  55. package/lib/widgets/charts/ChartWidget.d.ts +3 -15
  56. package/lib/widgets/charts/imagemosaic/ImagePopupComponent.d.ts +2 -7
  57. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +2 -31
  58. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +2 -7
  59. package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +73 -66
  60. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +10 -6
  61. package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +3 -22
  62. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +55 -58
  63. package/lib/widgets/charts/table/TableChartViewComponent.js +21 -7
  64. package/lib/widgets/text/ExprInsertModalComponent.d.ts +2 -13
  65. package/lib/widgets/text/ExprUpdateModalComponent.d.ts +2 -13
  66. package/lib/widgets/text/TextWidgetDesign.d.ts +3 -1
  67. package/package.json +1 -1
  68. package/src/GlobalFilter.ts +17 -0
  69. package/src/MWaterContextComponent.tsx +37 -19
  70. package/src/MWaterCustomTablesetListComponent.tsx +21 -3
  71. package/src/MWaterGlobalFiltersComponent.ts +8 -8
  72. package/src/MWaterLoaderComponent.ts +8 -1
  73. package/src/axes/Axis.ts +24 -25
  74. package/src/axes/AxisBuilder.ts +9 -8
  75. package/src/dashboards/DashboardComponent.tsx +2 -40
  76. package/src/dashboards/DashboardDesign.ts +2 -22
  77. package/src/dashboards/DashboardViewComponent.ts +4 -5
  78. package/src/dashboards/LayoutOptionsComponent.tsx +6 -4
  79. package/src/dashboards/SettingsModalComponent.tsx +170 -0
  80. package/src/datagrids/DatagridDataSource.ts +6 -12
  81. package/src/datagrids/DatagridDesignerComponent.tsx +22 -18
  82. package/src/datagrids/DatagridViewComponent.ts +3 -3
  83. package/src/datagrids/ExprCellComponent.ts +0 -1
  84. package/src/datagrids/FindReplaceModalComponent.ts +39 -22
  85. package/src/datagrids/ServerDatagridDataSource.ts +1 -2
  86. package/src/demo.ts +1 -1
  87. package/src/index.ts +1 -0
  88. package/src/maps/BufferLayer.ts +3 -1
  89. package/src/maps/ClusterLayer.ts +3 -1
  90. package/src/maps/GridLayer.ts +5 -3
  91. package/src/maps/GridLayerDesigner.tsx +0 -1
  92. package/src/maps/LayerSwitcherComponent.tsx +1 -1
  93. package/src/maps/MapDesign.ts +2 -17
  94. package/src/maps/{MapFiltersDesignerComponent.ts → MapFiltersDesignerComponent.tsx} +25 -25
  95. package/src/maps/ServerMapDataSource.ts +1 -1
  96. package/src/maps/VectorMapViewComponent.tsx +0 -1
  97. package/src/maps/vectorMaps.tsx +10 -1
  98. package/src/quickfilter/QuickfilterCompiler.ts +1 -1
  99. package/src/widgets/charts/table/TableChartViewComponent.ts +21 -7
  100. package/src/widgets/text/TextWidgetDesign.ts +4 -1
  101. package/src/dashboards/SettingsModalComponent.ts +0 -169
@@ -0,0 +1,13 @@
1
+ import { Expr, LiteralType } from "@mwater/expressions";
2
+ /** Global filters apply to multiple tables at once if a certain column is present. User-interface to set them
3
+ * is application-specific and the default (non-mWater) dashboard applies them but does not allow editing. */
4
+ export interface GlobalFilter {
5
+ /** id of column to filter */
6
+ columnId: string;
7
+ /** type of column to filter (to ensure that consistent) */
8
+ columnType: LiteralType;
9
+ /** op of expression for filtering */
10
+ op: string;
11
+ /** array of expressions to use for filtering. field expression for column will be injected as expression 0 in the resulting filter expression */
12
+ exprs: Expr[];
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
3
3
  import React from "react";
4
4
  import * as uiComponents from "./UIComponents";
5
5
  import { Schema } from "@mwater/expressions";
6
+ import ModalPopupComponent from "@mwater/react-library/lib/ModalPopupComponent";
6
7
  interface MWaterCompleteTableSelectComponentProps {
7
8
  /** Url to hit api */
8
9
  apiUrl: string;
@@ -180,15 +181,7 @@ declare class AddIndicatorConfirmPopupComponent extends React.Component<AddIndic
180
181
  renderContents(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | React.DetailedReactHTMLElement<{
181
182
  className: string;
182
183
  }, HTMLElement>;
183
- render(): React.CElement<{
184
- showCloseX: boolean;
185
- onClose: () => void;
186
- header: string;
187
- }, React.Component<{
188
- showCloseX: boolean;
189
- onClose: () => void;
190
- header: string;
191
- }, any, any>> | null;
184
+ render(): React.CElement<import("@mwater/react-library/lib/ModalPopupComponent").ModalPopupComponentProps, ModalPopupComponent> | null;
192
185
  }
193
186
  interface IssuesListComponentProps {
194
187
  /** Url to hit api */
@@ -1,7 +1,19 @@
1
1
  import PropTypes from "prop-types";
2
2
  import React from "react";
3
- import { Schema, Section } from "@mwater/expressions";
3
+ import { DataSource, Schema, Section } from "@mwater/expressions";
4
4
  import { CustomTableSelectComponentFactoryOptions, DecorateScalarExprTreeSectionChildrenOptions } from "@mwater/expressions-ui";
5
+ import { GlobalFilter } from "./GlobalFilter";
6
+ export interface GlobalFiltersElementFactoryProps {
7
+ schema: Schema;
8
+ dataSource: DataSource;
9
+ filterableTables: string[];
10
+ globalFilters?: GlobalFilter[];
11
+ onChange: (globalFilters: GlobalFilter[]) => void;
12
+ /** If true, return null element if not applicable to filterableTables */
13
+ nullIfIrrelevant?: boolean;
14
+ }
15
+ export type GlobalFiltersElementFactory = (props: GlobalFiltersElementFactoryProps) => React.ReactElement | null;
16
+ export declare const GlobalFiltersElementFactoryContext: React.Context<GlobalFiltersElementFactory | null>;
5
17
  /**
6
18
  * Creates several contexts to allow selecting of a table in an mWater-friendly way
7
19
  * and several other context items
@@ -9,7 +21,7 @@ import { CustomTableSelectComponentFactoryOptions, DecorateScalarExprTreeSection
9
21
  export default class MWaterContextComponent extends React.Component<{
10
22
  apiUrl: string;
11
23
  client?: string;
12
- /** user id of logged in user */
24
+ /** user id of logged in user */
13
25
  user?: string;
14
26
  schema: Schema;
15
27
  /** Extra tables to load in schema. Forms are not loaded by default as they are too many */
@@ -21,10 +33,10 @@ export default class MWaterContextComponent extends React.Component<{
21
33
  }> {
22
34
  static childContextTypes: {
23
35
  addLayerElementFactory: PropTypes.Requireable<(...args: any[]) => any>;
24
- globalFiltersElementFactory: PropTypes.Requireable<(...args: any[]) => any>;
25
36
  };
26
37
  createTableSelectElementFactory: (options: CustomTableSelectComponentFactoryOptions) => React.JSX.Element;
27
38
  getChildContext(): any;
39
+ createGlobalFiltersElementFactory: (props: GlobalFiltersElementFactoryProps) => React.JSX.Element | null;
28
40
  isScalarExprTreeSectionMatch: (options: {
29
41
  tableId: string;
30
42
  section: Section;
@@ -1,11 +1,35 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.GlobalFiltersElementFactoryContext = void 0;
6
30
  const prop_types_1 = __importDefault(require("prop-types"));
7
31
  const lodash_1 = __importDefault(require("lodash"));
8
- const react_1 = __importDefault(require("react"));
32
+ const react_1 = __importStar(require("react"));
9
33
  const R = react_1.default.createElement;
10
34
  const MWaterTableSelectComponent_1 = __importDefault(require("./MWaterTableSelectComponent"));
11
35
  const MWaterAddRelatedFormComponent_1 = __importDefault(require("./MWaterAddRelatedFormComponent"));
@@ -13,15 +37,14 @@ const MWaterAddRelatedIndicatorComponent_1 = __importDefault(require("./MWaterAd
13
37
  const MWaterGlobalFiltersComponent_1 = __importDefault(require("./MWaterGlobalFiltersComponent"));
14
38
  const expressions_ui_1 = require("@mwater/expressions-ui");
15
39
  const expressions_ui_2 = require("@mwater/expressions-ui");
40
+ exports.GlobalFiltersElementFactoryContext = (0, react_1.createContext)(null);
16
41
  /**
17
42
  * Creates several contexts to allow selecting of a table in an mWater-friendly way
18
43
  * and several other context items
19
44
  */
20
45
  class MWaterContextComponent extends react_1.default.Component {
21
46
  static childContextTypes = {
22
- addLayerElementFactory: prop_types_1.default.func,
23
- globalFiltersElementFactory: prop_types_1.default.func, // Call with props { schema, dataSource, filterableTables, globalFilters, onChange, nullIfIrrelevant }.
24
- // Displays a component to edit global filters. nullIfIrrelevant causes null element if not applicable to filterableTables
47
+ addLayerElementFactory: prop_types_1.default.func, // Call with props of AddLayerComponent
25
48
  };
26
49
  createTableSelectElementFactory = (options) => {
27
50
  return (react_1.default.createElement(MWaterTableSelectComponent_1.default, { apiUrl: this.props.apiUrl, client: this.props.client, schema: options.schema, user: this.props.user, table: options.value ?? undefined, onChange: options.onChange, extraTables: this.props.extraTables, onExtraTablesChange: this.props.onExtraTablesChange, filter: options.filter, onFilterChange: options.onFilterChange }));
@@ -31,14 +54,14 @@ class MWaterContextComponent extends react_1.default.Component {
31
54
  if (this.props.addLayerElementFactory) {
32
55
  context.addLayerElementFactory = this.props.addLayerElementFactory;
33
56
  }
34
- context.globalFiltersElementFactory = (props) => {
35
- if (props.nullIfIrrelevant && !lodash_1.default.any(props.filterableTables, (t) => t.match(/^entities./))) {
36
- return null;
37
- }
38
- return react_1.default.createElement(MWaterGlobalFiltersComponent_1.default, props);
39
- };
40
57
  return context;
41
58
  }
59
+ createGlobalFiltersElementFactory = (props) => {
60
+ if (props.nullIfIrrelevant && !lodash_1.default.any(props.filterableTables, (t) => t.match(/^entities./))) {
61
+ return null;
62
+ }
63
+ return react_1.default.createElement(MWaterGlobalFiltersComponent_1.default, { ...props });
64
+ };
42
65
  isScalarExprTreeSectionMatch = (options) => {
43
66
  if (options.tableId.match(/^entities\./) && options.section.id === "!indicators") {
44
67
  return true;
@@ -84,9 +107,11 @@ class MWaterContextComponent extends react_1.default.Component {
84
107
  };
85
108
  render() {
86
109
  return react_1.default.createElement(expressions_ui_1.CustomTableSelectComponentFactoryContext.Provider, { value: this.createTableSelectElementFactory },
87
- react_1.default.createElement(expressions_ui_2.IsScalarExprTreeSectionMatchContext.Provider, { value: this.isScalarExprTreeSectionMatch },
88
- react_1.default.createElement(expressions_ui_2.IsScalarExprTreeSectionInitiallyOpenContext.Provider, { value: this.isScalarExprTreeSectionInitiallyOpen },
89
- react_1.default.createElement(expressions_ui_1.DecorateScalarExprTreeSectionChildrenContext.Provider, { value: this.decorateScalarExprTreeSectionChildren }, this.props.children))));
110
+ react_1.default.createElement(exports.GlobalFiltersElementFactoryContext.Provider, { value: this.createGlobalFiltersElementFactory },
111
+ react_1.default.createElement(expressions_ui_2.IsScalarExprTreeSectionMatchContext.Provider, { value: this.isScalarExprTreeSectionMatch },
112
+ react_1.default.createElement(expressions_ui_2.IsScalarExprTreeSectionInitiallyOpenContext.Provider, { value: this.isScalarExprTreeSectionInitiallyOpen },
113
+ react_1.default.createElement(expressions_ui_1.DecorateScalarExprTreeSectionChildrenContext.Provider, { value: this.decorateScalarExprTreeSectionChildren }, this.props.children)))),
114
+ " ");
90
115
  }
91
116
  }
92
117
  exports.default = MWaterContextComponent;
@@ -15,13 +15,16 @@ const MWaterCustomTablesetListComponent = (props) => {
15
15
  const [tablesets, setTablesets] = (0, react_1.useState)();
16
16
  const [search, setSearch] = (0, react_1.useState)("");
17
17
  const [extraTableNeeded, setExtraTableNeeded] = (0, react_1.useState)();
18
+ const [showSystem, setShowSystem] = (0, react_1.useState)(false);
18
19
  // Get list of all tablesets
19
20
  (0, react_1.useEffect)(() => {
20
21
  fetch(`${props.apiUrl}custom_tablesets?client=${props.client || ""}`)
21
22
  .then((response) => response.json())
22
- .then((body) => {
23
+ .then((tablesets) => {
24
+ // Filter out non-normal
25
+ tablesets = tablesets.filter((ts) => ts.type === "normal");
23
26
  // Put included ones first
24
- setTablesets(lodash_1.default.sortByAll(body, [
27
+ setTablesets(lodash_1.default.sortByAll(tablesets, [
25
28
  (ts) => (props.extraTables.some((t) => (t || "").startsWith(`custom.${ts.code}.`)) ? 0 : 1),
26
29
  (ts) => expressions_1.ExprUtils.localizeString(ts.design.name, props.locale)
27
30
  ]));
@@ -80,8 +83,11 @@ const MWaterCustomTablesetListComponent = (props) => {
80
83
  react_2.default.createElement("h4", { className: "text-muted" }, name),
81
84
  react_2.default.createElement(UIComponents_1.OptionListComponent, { items: items })));
82
85
  };
86
+ const visibleTablesets = tablesets.filter((ts) => (showSystem || !ts.design.system) && !ts.design.deprecated);
83
87
  return (react_2.default.createElement("div", null,
84
88
  react_2.default.createElement(bootstrap_1.TextInput, { value: search, onChange: setSearch, placeholder: "Search..." }),
85
- tablesets.map((ts) => renderTableset(ts))));
89
+ visibleTablesets.map((ts) => renderTableset(ts)),
90
+ react_2.default.createElement("div", null,
91
+ react_2.default.createElement("button", { className: "btn btn-link btn-sm", onClick: () => setShowSystem(!showSystem) }, showSystem ? "Hide system tables" : "Show system tables"))));
86
92
  };
87
93
  exports.MWaterCustomTablesetListComponent = MWaterCustomTablesetListComponent;
@@ -1,16 +1,17 @@
1
1
  import React from "react";
2
2
  import { DataSource, Schema } from "@mwater/expressions";
3
+ import { GlobalFilter } from "./GlobalFilter";
3
4
  export interface MWaterGlobalFiltersComponentProps {
4
5
  /** Schema of the database */
5
6
  schema: Schema;
6
7
  /** Data source to use to get values */
7
8
  dataSource: DataSource;
8
- filterableTables: any;
9
- globalFilters?: any;
10
- onChange: any;
9
+ filterableTables: string[];
10
+ globalFilters?: GlobalFilter[];
11
+ onChange: (globalFilters: GlobalFilter[]) => void;
11
12
  }
12
13
  export default class MWaterGlobalFiltersComponent extends React.Component<MWaterGlobalFiltersComponentProps> {
13
- handleRegionsChange: (regions: any) => any;
14
- handleManagedByChange: (managedBy: any) => any;
14
+ handleRegionsChange: (regions: any) => void;
15
+ handleManagedByChange: (managedBy: any) => void;
15
16
  render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
16
17
  }
@@ -45,7 +45,7 @@ class MWaterGlobalFiltersComponent extends react_1.default.Component {
45
45
  exprs: [{ type: "literal", valueType: "id[]", idTable: "admin_regions", value: regions }]
46
46
  });
47
47
  }
48
- return this.props.onChange(globalFilters);
48
+ this.props.onChange(globalFilters);
49
49
  };
50
50
  handleManagedByChange = (managedBy) => {
51
51
  // Remove existing filter
@@ -59,12 +59,12 @@ class MWaterGlobalFiltersComponent extends react_1.default.Component {
59
59
  exprs: [{ type: "literal", valueType: "id", idTable: "subjects", value: "group:" + managedBy }]
60
60
  });
61
61
  }
62
- return this.props.onChange(globalFilters);
62
+ this.props.onChange(globalFilters);
63
63
  };
64
64
  render() {
65
65
  // Find managed by
66
66
  let adminRegions, managedBy;
67
- const managedByEntry = lodash_1.default.find(this.props.globalFilters, (gf) => gf.op === "within" && gf.columnId === "_managed_by");
67
+ const managedByEntry = lodash_1.default.find(this.props.globalFilters || [], (gf) => gf.op === "within" && gf.columnId === "_managed_by");
68
68
  if (managedByEntry) {
69
69
  managedBy = managedByEntry.exprs[0].value.split(":")[1];
70
70
  }
@@ -72,7 +72,7 @@ class MWaterGlobalFiltersComponent extends react_1.default.Component {
72
72
  managedBy = null;
73
73
  }
74
74
  // Find admin region
75
- const adminRegionEntry = lodash_1.default.find(this.props.globalFilters, (gf) => gf.op === "within any" && gf.columnId === "admin_region");
75
+ const adminRegionEntry = lodash_1.default.find(this.props.globalFilters || [], (gf) => gf.op === "within any" && gf.columnId === "admin_region");
76
76
  if (adminRegionEntry) {
77
77
  adminRegions = adminRegionEntry.exprs[0].value;
78
78
  }
@@ -1,6 +1,8 @@
1
- import { ReactElement } from "react";
1
+ import React, { ReactElement } from "react";
2
2
  import { DataSource, Schema } from "@mwater/expressions";
3
3
  import AsyncLoadComponent from "@mwater/react-library/lib/AsyncLoadComponent";
4
+ import LoadingComponent from "@mwater/react-library/lib/LoadingComponent";
5
+ import MWaterContextComponent from "./MWaterContextComponent";
4
6
  /**
5
7
  * Loads an mWater schema from the server and creates child with schema and dataSource
6
8
  * Also creates context to allow selecting of a table in an mWater-friendly way
@@ -38,5 +40,13 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<{
38
40
  constructor(props: any);
39
41
  isLoadNeeded(newProps: any, oldProps: any): boolean;
40
42
  load(props: any, prevProps: any, callback: any): void;
41
- render(): any;
43
+ render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | React.CElement<import("@mwater/react-library/lib/LoadingComponent").LoadingComponentProps, LoadingComponent> | React.CElement<{
44
+ apiUrl: string;
45
+ client?: string | undefined;
46
+ user?: string | undefined;
47
+ schema: Schema;
48
+ extraTables?: string[] | undefined;
49
+ onExtraTablesChange?: ((extraTables: string[]) => void) | undefined;
50
+ addLayerElementFactory?: any;
51
+ }, MWaterContextComponent>;
42
52
  }
@@ -45,7 +45,15 @@ class MWaterLoaderComponent extends AsyncLoadComponent_1.default {
45
45
  if (error) {
46
46
  const defaultError = `Cannot load one of the forms that this depends on. Perhaps the administrator has not shared the form with you? Details: ${error.message}`;
47
47
  if (this.props.errorFormatter) {
48
- return callback({ error: this.props.errorFormatter(JSON.parse(error.message), defaultError) });
48
+ try {
49
+ const parsedError = JSON.parse(error.message);
50
+ if (parsedError) {
51
+ return callback({ error: this.props.errorFormatter(parsedError, defaultError) });
52
+ }
53
+ }
54
+ catch (e) {
55
+ // Ignore
56
+ }
49
57
  }
50
58
  return callback({ error: defaultError });
51
59
  }
@@ -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;
@@ -83,11 +83,6 @@ export default class DashboardComponent extends React.Component<DashboardCompone
83
83
  className: string;
84
84
  onClick: () => void;
85
85
  }, HTMLElement>;
86
- renderStyleItem(style: any): React.DetailedReactHTMLElement<{
87
- key: any;
88
- className: string;
89
- onClick: () => void;
90
- }, HTMLElement>;
91
86
  renderStyle(): React.DetailedReactHTMLElement<{
92
87
  type: string;
93
88
  key: string;
@@ -160,34 +160,6 @@ class DashboardComponent extends react_1.default.Component {
160
160
  onClick: this.handleToggleEditing
161
161
  }, R("span", { className: "fas fa-pencil-alt" }), this.state.editing ? " Editing" : " Edit");
162
162
  }
163
- renderStyleItem(style) {
164
- const isActive = (this.props.design.style || "default") === style;
165
- const content = (() => {
166
- switch (style) {
167
- case "default":
168
- return [
169
- R("h4", { key: "name", className: "list-group-item-heading" }, "Classic Dashboard"),
170
- R("p", { key: "description", className: "" }, "Ideal for data display with minimal text")
171
- ];
172
- case "greybg":
173
- return [
174
- R("h4", { key: "name", className: "list-group-item-heading" }, "Framed Dashboard"),
175
- R("p", { key: "description", className: "" }, "Each widget is white on a grey background")
176
- ];
177
- case "story":
178
- return [
179
- R("h4", { key: "name", className: "list-group-item-heading" }, "Story"),
180
- R("p", { key: "description", className: "" }, "Ideal for data-driven storytelling with lots of text. Responsive and mobile-friendly")
181
- ];
182
- }
183
- return null;
184
- })();
185
- return R("a", {
186
- key: style,
187
- className: `list-group-item ${isActive ? "active" : ""}`,
188
- onClick: this.handleStyleChange.bind(null, style)
189
- }, content);
190
- }
191
163
  renderStyle() {
192
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 "));
193
165
  }
@@ -232,7 +204,8 @@ class DashboardComponent extends react_1.default.Component {
232
204
  locks: this.props.quickfilterLocks,
233
205
  filters: this.getCompiledFilters(),
234
206
  hideTopBorder: this.props.hideTitleBar,
235
- 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
236
209
  });
237
210
  }
238
211
  refDashboardView = (el) => {
@@ -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: [
@@ -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 {};