@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.
- package/lib/GlobalFilter.d.ts +13 -0
- package/lib/GlobalFilter.js +2 -0
- package/lib/MWaterCompleteTableSelectComponent.d.ts +2 -9
- package/lib/MWaterContextComponent.d.ts +15 -3
- package/lib/MWaterContextComponent.js +38 -13
- package/lib/MWaterCustomTablesetListComponent.js +9 -3
- package/lib/MWaterGlobalFiltersComponent.d.ts +6 -5
- package/lib/MWaterGlobalFiltersComponent.js +4 -4
- package/lib/MWaterLoaderComponent.d.ts +12 -2
- package/lib/MWaterLoaderComponent.js +9 -1
- package/lib/axes/Axis.d.ts +20 -25
- package/lib/axes/AxisBuilder.js +9 -7
- package/lib/axes/AxisComponent.d.ts +4 -4
- package/lib/dashboards/DashboardComponent.d.ts +0 -5
- package/lib/dashboards/DashboardComponent.js +2 -29
- package/lib/dashboards/DashboardDesign.d.ts +2 -17
- package/lib/dashboards/DashboardViewComponent.js +3 -4
- package/lib/dashboards/LayoutOptionsComponent.js +4 -3
- package/lib/dashboards/SettingsModalComponent.d.ts +4 -15
- package/lib/dashboards/SettingsModalComponent.js +24 -38
- package/lib/datagrids/DatagridComponent.d.ts +2 -9
- package/lib/datagrids/DatagridDataSource.d.ts +3 -3
- package/lib/datagrids/DatagridDataSource.js +0 -14
- package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -93
- package/lib/datagrids/DatagridDesignerComponent.js +8 -6
- package/lib/datagrids/DatagridViewComponent.js +1 -1
- package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -20
- package/lib/datagrids/FindReplaceModalComponent.js +27 -13
- package/lib/datagrids/ServerDatagridDataSource.d.ts +1 -1
- package/lib/datagrids/ServerDatagridDataSource.js +1 -3
- package/lib/demo.js +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +2 -1
- package/lib/layouts/grid/GridLayoutManager.d.ts +2 -1
- package/lib/maps/BufferLayer.js +3 -1
- package/lib/maps/ClusterLayer.js +3 -1
- package/lib/maps/GridLayer.js +5 -3
- package/lib/maps/GridLayerDesigner.js +0 -1
- package/lib/maps/LayerSwitcherComponent.js +1 -1
- package/lib/maps/MapComponent.d.ts +2 -7
- package/lib/maps/MapDesign.d.ts +2 -13
- package/lib/maps/MapFiltersDesignerComponent.d.ts +0 -4
- package/lib/maps/MapFiltersDesignerComponent.js +4 -5
- package/lib/maps/RasterMapViewComponent.d.ts +2 -9
- package/lib/maps/RegionSelectComponent.d.ts +2 -1
- package/lib/maps/ServerMapDataSource.d.ts +1 -1
- package/lib/maps/vectorMaps.d.ts +1 -0
- package/lib/maps/vectorMaps.js +10 -2
- package/lib/quickfilter/QuickfilterCompiler.d.ts +1 -1
- package/lib/widgets/IFrameWidgetComponent.d.ts +2 -9
- package/lib/widgets/ImageWidgetComponent.d.ts +6 -24
- package/lib/widgets/MapWidget.d.ts +2 -7
- package/lib/widgets/MarkdownWidget.d.ts +2 -7
- package/lib/widgets/TOCWidget.d.ts +2 -9
- package/lib/widgets/charts/ChartWidget.d.ts +3 -15
- package/lib/widgets/charts/imagemosaic/ImagePopupComponent.d.ts +2 -7
- package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +2 -31
- package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +2 -7
- package/lib/widgets/charts/pivot/IntersectionDesignerComponent.d.ts +73 -66
- package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +10 -6
- package/lib/widgets/charts/pivot/PivotChartViewComponent.d.ts +3 -22
- package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +55 -58
- package/lib/widgets/charts/table/TableChartViewComponent.js +21 -7
- package/lib/widgets/text/ExprInsertModalComponent.d.ts +2 -13
- package/lib/widgets/text/ExprUpdateModalComponent.d.ts +2 -13
- package/lib/widgets/text/TextWidgetDesign.d.ts +3 -1
- package/package.json +1 -1
- package/src/GlobalFilter.ts +17 -0
- package/src/MWaterContextComponent.tsx +37 -19
- package/src/MWaterCustomTablesetListComponent.tsx +21 -3
- package/src/MWaterGlobalFiltersComponent.ts +8 -8
- package/src/MWaterLoaderComponent.ts +8 -1
- package/src/axes/Axis.ts +24 -25
- package/src/axes/AxisBuilder.ts +9 -8
- package/src/dashboards/DashboardComponent.tsx +2 -40
- package/src/dashboards/DashboardDesign.ts +2 -22
- package/src/dashboards/DashboardViewComponent.ts +4 -5
- package/src/dashboards/LayoutOptionsComponent.tsx +6 -4
- package/src/dashboards/SettingsModalComponent.tsx +170 -0
- package/src/datagrids/DatagridDataSource.ts +6 -12
- package/src/datagrids/DatagridDesignerComponent.tsx +22 -18
- package/src/datagrids/DatagridViewComponent.ts +3 -3
- package/src/datagrids/ExprCellComponent.ts +0 -1
- package/src/datagrids/FindReplaceModalComponent.ts +39 -22
- package/src/datagrids/ServerDatagridDataSource.ts +1 -2
- package/src/demo.ts +1 -1
- package/src/index.ts +1 -0
- package/src/maps/BufferLayer.ts +3 -1
- package/src/maps/ClusterLayer.ts +3 -1
- package/src/maps/GridLayer.ts +5 -3
- package/src/maps/GridLayerDesigner.tsx +0 -1
- package/src/maps/LayerSwitcherComponent.tsx +1 -1
- package/src/maps/MapDesign.ts +2 -17
- package/src/maps/{MapFiltersDesignerComponent.ts → MapFiltersDesignerComponent.tsx} +25 -25
- package/src/maps/ServerMapDataSource.ts +1 -1
- package/src/maps/VectorMapViewComponent.tsx +0 -1
- package/src/maps/vectorMaps.tsx +10 -1
- package/src/quickfilter/QuickfilterCompiler.ts +1 -1
- package/src/widgets/charts/table/TableChartViewComponent.ts +21 -7
- package/src/widgets/text/TextWidgetDesign.ts +4 -1
- package/src/dashboards/SettingsModalComponent.ts +0 -169
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import * as ui from "@mwater/react-library/lib/bootstrap";
|
|
2
3
|
import { DataSource, Schema } from "@mwater/expressions";
|
|
3
4
|
export interface PivotChartDesignerComponentProps {
|
|
4
5
|
design: any;
|
|
@@ -25,12 +26,15 @@ export default class PivotChartDesignerComponent extends React.Component<PivotCh
|
|
|
25
26
|
className: string;
|
|
26
27
|
}, HTMLElement> | null;
|
|
27
28
|
renderStriping(): React.CElement<{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
label: React.ReactNode;
|
|
30
|
+
labelMuted?: boolean | undefined;
|
|
31
|
+
hint?: React.ReactNode;
|
|
32
|
+
help?: React.ReactNode;
|
|
33
|
+
required?: boolean | undefined;
|
|
34
|
+
hasSuccess?: boolean | undefined;
|
|
35
|
+
hasWarnings?: boolean | undefined;
|
|
36
|
+
hasErrors?: boolean | undefined;
|
|
37
|
+
}, ui.FormGroup> | null;
|
|
34
38
|
renderSetup(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
35
39
|
render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
36
40
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PropTypes from "prop-types";
|
|
2
2
|
import React from "react";
|
|
3
|
+
import ActionCancelModalComponent from "@mwater/react-library/lib/ActionCancelModalComponent";
|
|
3
4
|
import { DataSource, Schema } from "@mwater/expressions";
|
|
4
5
|
import { JsonQLFilter, WidgetScope } from "../../..";
|
|
5
6
|
import { PivotChartDesign } from "./PivotChartDesign";
|
|
@@ -52,28 +53,8 @@ export default class PivotChartViewComponent extends React.Component<PivotChartV
|
|
|
52
53
|
paddingRight: number;
|
|
53
54
|
};
|
|
54
55
|
}, HTMLElement>;
|
|
55
|
-
renderEditSegmentModal(): React.CElement<
|
|
56
|
-
|
|
57
|
-
onAction: () => void;
|
|
58
|
-
onCancel: () => void;
|
|
59
|
-
size: string;
|
|
60
|
-
}, React.Component<{
|
|
61
|
-
title: string;
|
|
62
|
-
onAction: () => void;
|
|
63
|
-
onCancel: () => void;
|
|
64
|
-
size: string;
|
|
65
|
-
}, any, any>> | undefined;
|
|
66
|
-
renderEditIntersectionModal(): React.CElement<{
|
|
67
|
-
title: string;
|
|
68
|
-
onAction: () => void;
|
|
69
|
-
onCancel: () => void;
|
|
70
|
-
size: string;
|
|
71
|
-
}, React.Component<{
|
|
72
|
-
title: string;
|
|
73
|
-
onAction: () => void;
|
|
74
|
-
onCancel: () => void;
|
|
75
|
-
size: string;
|
|
76
|
-
}, any, any>> | undefined;
|
|
56
|
+
renderEditSegmentModal(): React.CElement<import("@mwater/react-library/lib/ActionCancelModalComponent").ActionCancelModalComponentProps, ActionCancelModalComponent> | undefined;
|
|
57
|
+
renderEditIntersectionModal(): React.CElement<import("@mwater/react-library/lib/ActionCancelModalComponent").ActionCancelModalComponentProps, ActionCancelModalComponent> | undefined;
|
|
77
58
|
render(): React.DetailedReactHTMLElement<{
|
|
78
59
|
style: {
|
|
79
60
|
width: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import * as ui from "@mwater/react-library/lib/bootstrap";
|
|
2
3
|
import { DataSource, Schema } from "@mwater/expressions";
|
|
3
4
|
import { PivotChartSegment } from "./PivotChartDesign";
|
|
4
5
|
export interface SegmentDesignerComponentProps {
|
|
@@ -27,70 +28,66 @@ export default class SegmentDesignerComponent extends React.Component<SegmentDes
|
|
|
27
28
|
handleOrderExprChange: (orderExpr: any) => any;
|
|
28
29
|
handleOrderDirChange: (orderDir: any) => any;
|
|
29
30
|
renderMode(): React.CElement<{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
label: React.ReactNode;
|
|
32
|
+
labelMuted?: boolean | undefined;
|
|
33
|
+
hint?: React.ReactNode;
|
|
34
|
+
help?: React.ReactNode;
|
|
35
|
+
required?: boolean | undefined;
|
|
36
|
+
hasSuccess?: boolean | undefined;
|
|
37
|
+
hasWarnings?: boolean | undefined;
|
|
38
|
+
hasErrors?: boolean | undefined;
|
|
39
|
+
}, ui.FormGroup>;
|
|
36
40
|
renderLabel(): React.CElement<{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
label: React.ReactNode;
|
|
42
|
+
labelMuted?: boolean | undefined;
|
|
43
|
+
hint?: React.ReactNode;
|
|
44
|
+
help?: React.ReactNode;
|
|
45
|
+
required?: boolean | undefined;
|
|
46
|
+
hasSuccess?: boolean | undefined;
|
|
47
|
+
hasWarnings?: boolean | undefined;
|
|
48
|
+
hasErrors?: boolean | undefined;
|
|
49
|
+
}, ui.FormGroup>;
|
|
45
50
|
renderValueAxis(): React.JSX.Element;
|
|
46
51
|
renderFilter(): React.CElement<{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
label: (string | React.CElement<{
|
|
57
|
-
id: string;
|
|
58
|
-
}, React.Component<{
|
|
59
|
-
id: string;
|
|
60
|
-
}, any, any>>)[];
|
|
61
|
-
hint: string;
|
|
62
|
-
}, any, any>>;
|
|
52
|
+
label: React.ReactNode;
|
|
53
|
+
labelMuted?: boolean | undefined;
|
|
54
|
+
hint?: React.ReactNode;
|
|
55
|
+
help?: React.ReactNode;
|
|
56
|
+
required?: boolean | undefined;
|
|
57
|
+
hasSuccess?: boolean | undefined;
|
|
58
|
+
hasWarnings?: boolean | undefined;
|
|
59
|
+
hasErrors?: boolean | undefined;
|
|
60
|
+
}, ui.FormGroup>;
|
|
63
61
|
renderStyling(): React.CElement<{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
label: React.ReactNode;
|
|
63
|
+
labelMuted?: boolean | undefined;
|
|
64
|
+
hint?: React.ReactNode;
|
|
65
|
+
help?: React.ReactNode;
|
|
66
|
+
required?: boolean | undefined;
|
|
67
|
+
hasSuccess?: boolean | undefined;
|
|
68
|
+
hasWarnings?: boolean | undefined;
|
|
69
|
+
hasErrors?: boolean | undefined;
|
|
70
|
+
}, ui.FormGroup>;
|
|
70
71
|
renderBorders(): React.CElement<{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
label: React.ReactNode;
|
|
73
|
+
labelMuted?: boolean | undefined;
|
|
74
|
+
hint?: React.ReactNode;
|
|
75
|
+
help?: React.ReactNode;
|
|
76
|
+
required?: boolean | undefined;
|
|
77
|
+
hasSuccess?: boolean | undefined;
|
|
78
|
+
hasWarnings?: boolean | undefined;
|
|
79
|
+
hasErrors?: boolean | undefined;
|
|
80
|
+
}, ui.FormGroup>;
|
|
77
81
|
renderOrderExpr(): React.CElement<{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
label: (string | React.CElement<{
|
|
88
|
-
id: string;
|
|
89
|
-
}, React.Component<{
|
|
90
|
-
id: string;
|
|
91
|
-
}, any, any>>)[];
|
|
92
|
-
hint: string;
|
|
93
|
-
}, any, any>>;
|
|
82
|
+
label: React.ReactNode;
|
|
83
|
+
labelMuted?: boolean | undefined;
|
|
84
|
+
hint?: React.ReactNode;
|
|
85
|
+
help?: React.ReactNode;
|
|
86
|
+
required?: boolean | undefined;
|
|
87
|
+
hasSuccess?: boolean | undefined;
|
|
88
|
+
hasWarnings?: boolean | undefined;
|
|
89
|
+
hasErrors?: boolean | undefined;
|
|
90
|
+
}, ui.FormGroup>;
|
|
94
91
|
render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
95
92
|
}
|
|
96
93
|
export {};
|
|
@@ -124,7 +124,7 @@ class TableContentsComponent extends react_1.default.Component {
|
|
|
124
124
|
}
|
|
125
125
|
renderImage(id) {
|
|
126
126
|
const url = this.props.dataSource.getImageUrl(id);
|
|
127
|
-
return R("a", { href: url, key: id, target: "_blank", style: { paddingLeft: 5, paddingRight: 5 } }, "Image");
|
|
127
|
+
return R("a", { href: url, onClick: (e) => { e.stopPropagation(); }, key: id, target: "_blank", style: { paddingLeft: 5, paddingRight: 5 } }, "Image");
|
|
128
128
|
}
|
|
129
129
|
renderCell(rowIndex, columnIndex) {
|
|
130
130
|
const axisBuilder = new AxisBuilder_1.default({ schema: this.props.schema });
|
|
@@ -162,7 +162,9 @@ class TableContentsComponent extends react_1.default.Component {
|
|
|
162
162
|
// Convert to node based on type
|
|
163
163
|
switch (exprType) {
|
|
164
164
|
case "text":
|
|
165
|
-
|
|
165
|
+
if (lodash_1.default.isString(value)) {
|
|
166
|
+
node = R(react_linkify_1.default, { properties: { target: "_blank" } }, value);
|
|
167
|
+
}
|
|
166
168
|
break;
|
|
167
169
|
case "number":
|
|
168
170
|
case "geometry":
|
|
@@ -170,21 +172,33 @@ class TableContentsComponent extends react_1.default.Component {
|
|
|
170
172
|
break;
|
|
171
173
|
case "boolean":
|
|
172
174
|
case "enum":
|
|
175
|
+
node = exprUtils.stringifyExprLiteral(column.textAxis?.expr, value, this.context.locale);
|
|
176
|
+
break;
|
|
173
177
|
case "enumset":
|
|
174
178
|
case "text[]":
|
|
175
|
-
|
|
179
|
+
if (lodash_1.default.isArray(value)) {
|
|
180
|
+
node = exprUtils.stringifyExprLiteral(column.textAxis?.expr, value, this.context.locale);
|
|
181
|
+
}
|
|
176
182
|
break;
|
|
177
183
|
case "date":
|
|
178
|
-
|
|
184
|
+
if (lodash_1.default.isString(value)) {
|
|
185
|
+
node = (0, valueFormatter_1.formatValue)(exprType, value, column.format);
|
|
186
|
+
}
|
|
179
187
|
break;
|
|
180
188
|
case "datetime":
|
|
181
|
-
|
|
189
|
+
if (lodash_1.default.isString(value)) {
|
|
190
|
+
node = (0, valueFormatter_1.formatValue)(exprType, value, column.format);
|
|
191
|
+
}
|
|
182
192
|
break;
|
|
183
193
|
case "image":
|
|
184
|
-
|
|
194
|
+
if (lodash_1.default.isObject(value) && value.id != null) {
|
|
195
|
+
node = this.renderImage(value.id);
|
|
196
|
+
}
|
|
185
197
|
break;
|
|
186
198
|
case "imagelist":
|
|
187
|
-
|
|
199
|
+
if (lodash_1.default.isArray(value)) {
|
|
200
|
+
node = lodash_1.default.map(value, (v) => this.renderImage(v.id));
|
|
201
|
+
}
|
|
188
202
|
break;
|
|
189
203
|
default:
|
|
190
204
|
node = "" + value;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { DataSource, Schema } from "@mwater/expressions";
|
|
3
|
+
import ActionCancelModalComponent from "@mwater/react-library/lib/ActionCancelModalComponent";
|
|
3
4
|
import { HtmlItemExpr } from "../../richtext/ExprItemsHtmlConverter";
|
|
4
5
|
export interface ExprInsertModalComponentProps {
|
|
5
6
|
/** Schema to use */
|
|
@@ -18,18 +19,6 @@ export default class ExprInsertModalComponent extends React.Component<ExprInsert
|
|
|
18
19
|
constructor(props: ExprInsertModalComponentProps);
|
|
19
20
|
open(): void;
|
|
20
21
|
handleInsert: () => void;
|
|
21
|
-
render(): React.CElement<
|
|
22
|
-
actionLabel: string;
|
|
23
|
-
onAction: () => void;
|
|
24
|
-
onCancel: () => void;
|
|
25
|
-
title: string;
|
|
26
|
-
size: string;
|
|
27
|
-
}, React.Component<{
|
|
28
|
-
actionLabel: string;
|
|
29
|
-
onAction: () => void;
|
|
30
|
-
onCancel: () => void;
|
|
31
|
-
title: string;
|
|
32
|
-
size: string;
|
|
33
|
-
}, any, any>> | null;
|
|
22
|
+
render(): React.CElement<import("@mwater/react-library/lib/ActionCancelModalComponent").ActionCancelModalComponentProps, ActionCancelModalComponent> | null;
|
|
34
23
|
}
|
|
35
24
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { DataSource, Schema } from "@mwater/expressions";
|
|
3
|
+
import ActionCancelModalComponent from "@mwater/react-library/lib/ActionCancelModalComponent";
|
|
3
4
|
import { HtmlItemExpr } from "../../richtext/ExprItemsHtmlConverter";
|
|
4
5
|
export interface ExprUpdateModalComponentProps {
|
|
5
6
|
/** Schema to use */
|
|
@@ -16,18 +17,6 @@ interface ExprUpdateModalComponentState {
|
|
|
16
17
|
export default class ExprUpdateModalComponent extends React.Component<ExprUpdateModalComponentProps, ExprUpdateModalComponentState> {
|
|
17
18
|
constructor(props: any);
|
|
18
19
|
open(item: any, onUpdate: any): void;
|
|
19
|
-
render(): React.CElement<
|
|
20
|
-
actionLabel: string;
|
|
21
|
-
onAction: () => void;
|
|
22
|
-
onCancel: () => void;
|
|
23
|
-
title: string;
|
|
24
|
-
size: string;
|
|
25
|
-
}, React.Component<{
|
|
26
|
-
actionLabel: string;
|
|
27
|
-
onAction: () => void;
|
|
28
|
-
onCancel: () => void;
|
|
29
|
-
title: string;
|
|
30
|
-
size: string;
|
|
31
|
-
}, any, any>> | null;
|
|
20
|
+
render(): React.CElement<import("@mwater/react-library/lib/ActionCancelModalComponent").ActionCancelModalComponentProps, ActionCancelModalComponent> | null;
|
|
32
21
|
}
|
|
33
22
|
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { HtmlItemExpr } from "../../richtext/ExprItemsHtmlConverter";
|
|
2
|
+
import { HtmlItem } from "../../richtext/ItemsHtmlConverter";
|
|
1
3
|
export interface TextWidgetDesign {
|
|
2
4
|
/** Text widget stores its content as array of items. See ItemsHtmlConverter TODO */
|
|
3
|
-
items:
|
|
5
|
+
items: (HtmlItem | HtmlItemExpr)[];
|
|
4
6
|
/** "title" for title block. default is "default" */
|
|
5
7
|
style?: "title" | "default";
|
|
6
8
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Expr, LiteralType } from "@mwater/expressions"
|
|
2
|
+
|
|
3
|
+
/** Global filters apply to multiple tables at once if a certain column is present. User-interface to set them
|
|
4
|
+
* is application-specific and the default (non-mWater) dashboard applies them but does not allow editing. */
|
|
5
|
+
export interface GlobalFilter {
|
|
6
|
+
/** id of column to filter */
|
|
7
|
+
columnId: string
|
|
8
|
+
|
|
9
|
+
/** type of column to filter (to ensure that consistent) */
|
|
10
|
+
columnType: LiteralType
|
|
11
|
+
|
|
12
|
+
/** op of expression for filtering */
|
|
13
|
+
op: string
|
|
14
|
+
|
|
15
|
+
/** array of expressions to use for filtering. field expression for column will be injected as expression 0 in the resulting filter expression */
|
|
16
|
+
exprs: Expr[]
|
|
17
|
+
}
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import PropTypes from "prop-types"
|
|
2
2
|
import _ from "lodash"
|
|
3
|
-
import React from "react"
|
|
3
|
+
import React, { createContext } from "react"
|
|
4
4
|
const R = React.createElement
|
|
5
5
|
|
|
6
6
|
import MWaterTableSelectComponent from "./MWaterTableSelectComponent"
|
|
7
7
|
import MWaterAddRelatedFormComponent from "./MWaterAddRelatedFormComponent"
|
|
8
8
|
import MWaterAddRelatedIndicatorComponent from "./MWaterAddRelatedIndicatorComponent"
|
|
9
9
|
import MWaterGlobalFiltersComponent from "./MWaterGlobalFiltersComponent"
|
|
10
|
-
import { Schema, Section } from "@mwater/expressions"
|
|
10
|
+
import { DataSource, Schema, Section } from "@mwater/expressions"
|
|
11
11
|
import { CustomTableSelectComponentFactoryContext, CustomTableSelectComponentFactoryOptions, DecorateScalarExprTreeSectionChildrenContext, DecorateScalarExprTreeSectionChildrenOptions } from "@mwater/expressions-ui"
|
|
12
12
|
import { IsScalarExprTreeSectionInitiallyOpenContext, IsScalarExprTreeSectionMatchContext } from "@mwater/expressions-ui"
|
|
13
|
+
import { GlobalFilter } from "./GlobalFilter"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export interface GlobalFiltersElementFactoryProps {
|
|
17
|
+
schema: Schema
|
|
18
|
+
dataSource: DataSource
|
|
19
|
+
filterableTables: string[]
|
|
20
|
+
globalFilters?: GlobalFilter[]
|
|
21
|
+
onChange: (globalFilters: GlobalFilter[]) => void
|
|
22
|
+
|
|
23
|
+
/** If true, return null element if not applicable to filterableTables */
|
|
24
|
+
nullIfIrrelevant?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type GlobalFiltersElementFactory = (props: GlobalFiltersElementFactoryProps) => React.ReactElement | null
|
|
28
|
+
|
|
29
|
+
export const GlobalFiltersElementFactoryContext = createContext<GlobalFiltersElementFactory | null>(null)
|
|
30
|
+
|
|
13
31
|
|
|
14
32
|
/**
|
|
15
33
|
* Creates several contexts to allow selecting of a table in an mWater-friendly way
|
|
@@ -18,7 +36,7 @@ import { IsScalarExprTreeSectionInitiallyOpenContext, IsScalarExprTreeSectionMat
|
|
|
18
36
|
export default class MWaterContextComponent extends React.Component<{
|
|
19
37
|
apiUrl: string
|
|
20
38
|
client?: string
|
|
21
|
-
/**
|
|
39
|
+
/** user id of logged in user */
|
|
22
40
|
user?: string
|
|
23
41
|
schema: Schema
|
|
24
42
|
/** Extra tables to load in schema. Forms are not loaded by default as they are too many */
|
|
@@ -30,8 +48,6 @@ export default class MWaterContextComponent extends React.Component<{
|
|
|
30
48
|
}> {
|
|
31
49
|
static childContextTypes = {
|
|
32
50
|
addLayerElementFactory: PropTypes.func, // Call with props of AddLayerComponent
|
|
33
|
-
globalFiltersElementFactory: PropTypes.func, // Call with props { schema, dataSource, filterableTables, globalFilters, onChange, nullIfIrrelevant }.
|
|
34
|
-
// Displays a component to edit global filters. nullIfIrrelevant causes null element if not applicable to filterableTables
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
createTableSelectElementFactory = (options: CustomTableSelectComponentFactoryOptions) => {
|
|
@@ -58,15 +74,15 @@ export default class MWaterContextComponent extends React.Component<{
|
|
|
58
74
|
context.addLayerElementFactory = this.props.addLayerElementFactory
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
context
|
|
62
|
-
|
|
63
|
-
return null
|
|
64
|
-
}
|
|
77
|
+
return context
|
|
78
|
+
}
|
|
65
79
|
|
|
66
|
-
|
|
80
|
+
createGlobalFiltersElementFactory = (props: GlobalFiltersElementFactoryProps) => {
|
|
81
|
+
if (props.nullIfIrrelevant && !_.any(props.filterableTables, (t: string) => t.match(/^entities./))) {
|
|
82
|
+
return null
|
|
67
83
|
}
|
|
68
84
|
|
|
69
|
-
return
|
|
85
|
+
return <MWaterGlobalFiltersComponent {...props} />
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
isScalarExprTreeSectionMatch = (options: { tableId: string; section: Section; filter?: string }) => {
|
|
@@ -128,13 +144,15 @@ export default class MWaterContextComponent extends React.Component<{
|
|
|
128
144
|
|
|
129
145
|
render() {
|
|
130
146
|
return <CustomTableSelectComponentFactoryContext.Provider value={this.createTableSelectElementFactory}>
|
|
131
|
-
<
|
|
132
|
-
<
|
|
133
|
-
<
|
|
134
|
-
{this.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
147
|
+
<GlobalFiltersElementFactoryContext.Provider value={this.createGlobalFiltersElementFactory}>
|
|
148
|
+
<IsScalarExprTreeSectionMatchContext.Provider value={this.isScalarExprTreeSectionMatch}>
|
|
149
|
+
<IsScalarExprTreeSectionInitiallyOpenContext.Provider value={this.isScalarExprTreeSectionInitiallyOpen}>
|
|
150
|
+
<DecorateScalarExprTreeSectionChildrenContext.Provider value={this.decorateScalarExprTreeSectionChildren}>
|
|
151
|
+
{this.props.children}
|
|
152
|
+
</DecorateScalarExprTreeSectionChildrenContext.Provider>
|
|
153
|
+
</IsScalarExprTreeSectionInitiallyOpenContext.Provider>
|
|
154
|
+
|
|
155
|
+
</IsScalarExprTreeSectionMatchContext.Provider>
|
|
156
|
+
</GlobalFiltersElementFactoryContext.Provider> </CustomTableSelectComponentFactoryContext.Provider>
|
|
139
157
|
}
|
|
140
158
|
}
|
|
@@ -27,14 +27,19 @@ export const MWaterCustomTablesetListComponent = (props: {
|
|
|
27
27
|
const [search, setSearch] = useState<string | null>("")
|
|
28
28
|
const [extraTableNeeded, setExtraTableNeeded] = useState<string>()
|
|
29
29
|
|
|
30
|
+
const [showSystem, setShowSystem] = useState(false)
|
|
31
|
+
|
|
30
32
|
// Get list of all tablesets
|
|
31
33
|
useEffect(() => {
|
|
32
34
|
fetch(`${props.apiUrl}custom_tablesets?client=${props.client || ""}`)
|
|
33
35
|
.then((response) => response.json())
|
|
34
|
-
.then((
|
|
36
|
+
.then((tablesets) => {
|
|
37
|
+
// Filter out non-normal
|
|
38
|
+
tablesets = tablesets.filter((ts: CustomTableset) => ts.type === "normal")
|
|
39
|
+
|
|
35
40
|
// Put included ones first
|
|
36
41
|
setTablesets(
|
|
37
|
-
_.sortByAll(
|
|
42
|
+
_.sortByAll(tablesets, [
|
|
38
43
|
(ts) => (props.extraTables.some((t) => (t || "").startsWith(`custom.${ts.code}.`)) ? 0 : 1),
|
|
39
44
|
(ts) => ExprUtils.localizeString(ts.design.name, props.locale)
|
|
40
45
|
])
|
|
@@ -117,10 +122,17 @@ export const MWaterCustomTablesetListComponent = (props: {
|
|
|
117
122
|
)
|
|
118
123
|
}
|
|
119
124
|
|
|
125
|
+
const visibleTablesets = tablesets.filter((ts) => (showSystem || !ts.design.system) && !ts.design.deprecated)
|
|
126
|
+
|
|
120
127
|
return (
|
|
121
128
|
<div>
|
|
122
129
|
<TextInput value={search} onChange={setSearch} placeholder="Search..." />
|
|
123
|
-
{
|
|
130
|
+
{visibleTablesets.map((ts) => renderTableset(ts))}
|
|
131
|
+
<div>
|
|
132
|
+
<button className="btn btn-link btn-sm" onClick={() => setShowSystem(!showSystem)}>
|
|
133
|
+
{showSystem ? "Hide system tables" : "Show system tables"}
|
|
134
|
+
</button>
|
|
135
|
+
</div>
|
|
124
136
|
</div>
|
|
125
137
|
)
|
|
126
138
|
}
|
|
@@ -137,5 +149,11 @@ interface CustomTableset {
|
|
|
137
149
|
desc?: LocalizedString
|
|
138
150
|
|
|
139
151
|
tables: Table[]
|
|
152
|
+
|
|
153
|
+
/** True if tableset is deprecated */
|
|
154
|
+
deprecated?: boolean
|
|
155
|
+
|
|
156
|
+
/** True if tableset is for system use and should only be visible to admins in the UI */
|
|
157
|
+
system?: boolean
|
|
140
158
|
}
|
|
141
159
|
}
|
|
@@ -2,19 +2,19 @@ import _ from "lodash"
|
|
|
2
2
|
import React from "react"
|
|
3
3
|
const R = React.createElement
|
|
4
4
|
|
|
5
|
-
import querystring from "querystring"
|
|
6
5
|
import * as ui from "@mwater/react-library/lib/bootstrap"
|
|
7
6
|
import { IdLiteralComponent } from "@mwater/expressions-ui"
|
|
8
7
|
import { DataSource, Schema } from "@mwater/expressions"
|
|
8
|
+
import { GlobalFilter } from "./GlobalFilter"
|
|
9
9
|
|
|
10
10
|
export interface MWaterGlobalFiltersComponentProps {
|
|
11
11
|
/** Schema of the database */
|
|
12
12
|
schema: Schema
|
|
13
13
|
/** Data source to use to get values */
|
|
14
14
|
dataSource: DataSource
|
|
15
|
-
filterableTables:
|
|
16
|
-
globalFilters?:
|
|
17
|
-
onChange:
|
|
15
|
+
filterableTables: string[]
|
|
16
|
+
globalFilters?: GlobalFilter[]
|
|
17
|
+
onChange: (globalFilters: GlobalFilter[]) => void
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// Control to edit the global filters (_managed_by and admin_region)
|
|
@@ -36,7 +36,7 @@ export default class MWaterGlobalFiltersComponent extends React.Component<MWater
|
|
|
36
36
|
})
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
this.props.onChange(globalFilters)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
handleManagedByChange = (managedBy: any) => {
|
|
@@ -56,13 +56,13 @@ export default class MWaterGlobalFiltersComponent extends React.Component<MWater
|
|
|
56
56
|
})
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
this.props.onChange(globalFilters)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
render() {
|
|
63
63
|
// Find managed by
|
|
64
64
|
let adminRegions, managedBy
|
|
65
|
-
const managedByEntry = _.find(this.props.globalFilters, (gf) => gf.op === "within" && gf.columnId === "_managed_by")
|
|
65
|
+
const managedByEntry = _.find(this.props.globalFilters || [], (gf) => gf.op === "within" && gf.columnId === "_managed_by")
|
|
66
66
|
if (managedByEntry) {
|
|
67
67
|
managedBy = managedByEntry.exprs[0].value.split(":")[1]
|
|
68
68
|
} else {
|
|
@@ -71,7 +71,7 @@ export default class MWaterGlobalFiltersComponent extends React.Component<MWater
|
|
|
71
71
|
|
|
72
72
|
// Find admin region
|
|
73
73
|
const adminRegionEntry = _.find(
|
|
74
|
-
this.props.globalFilters,
|
|
74
|
+
this.props.globalFilters || [],
|
|
75
75
|
(gf) => gf.op === "within any" && gf.columnId === "admin_region"
|
|
76
76
|
)
|
|
77
77
|
if (adminRegionEntry) {
|
|
@@ -79,7 +79,14 @@ export default class MWaterLoaderComponent extends AsyncLoadComponent<
|
|
|
79
79
|
if (error) {
|
|
80
80
|
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}`
|
|
81
81
|
if (this.props.errorFormatter) {
|
|
82
|
-
|
|
82
|
+
try {
|
|
83
|
+
const parsedError = JSON.parse(error.message)
|
|
84
|
+
if (parsedError) {
|
|
85
|
+
return callback({ error: this.props.errorFormatter(parsedError, defaultError) })
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {
|
|
88
|
+
// Ignore
|
|
89
|
+
}
|
|
83
90
|
}
|
|
84
91
|
return callback({ error: defaultError })
|
|
85
92
|
}
|