@mwater/visualization 5.0.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/GlobalFilter.d.ts +13 -0
- package/lib/GlobalFilter.js +2 -0
- package/lib/MWaterAddRelatedFormComponent.d.ts +1 -1
- package/lib/MWaterAddRelatedFormComponent.js +10 -17
- package/lib/MWaterCompleteTableSelectComponent.d.ts +2 -9
- package/lib/MWaterContextComponent.d.ts +31 -9
- package/lib/MWaterContextComponent.js +85 -76
- package/lib/MWaterCustomTablesetListComponent.js +9 -3
- package/lib/MWaterGlobalFiltersComponent.d.ts +6 -5
- package/lib/MWaterGlobalFiltersComponent.js +4 -4
- package/lib/MWaterLoaderComponent.d.ts +14 -4
- package/lib/MWaterLoaderComponent.js +10 -2
- package/lib/MWaterTableSelectComponent.d.ts +0 -1
- package/lib/MWaterTableSelectComponent.js +20 -41
- 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/axes/RangesComponent.d.ts +12 -6
- package/lib/axes/RangesComponent.js +21 -10
- package/lib/dashboards/DashboardComponent.d.ts +1 -14
- package/lib/dashboards/DashboardComponent.js +18 -56
- 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/ServerDashboardDataSource.d.ts +1 -0
- package/lib/dashboards/ServerDashboardDataSource.js +3 -0
- package/lib/dashboards/SettingsModalComponent.d.ts +4 -15
- package/lib/dashboards/SettingsModalComponent.js +24 -38
- package/lib/datagrids/DatagridComponent.d.ts +10 -13
- package/lib/datagrids/DatagridComponent.js +27 -5
- package/lib/datagrids/DatagridDataSource.d.ts +3 -2
- package/lib/datagrids/DatagridDataSource.js +0 -11
- package/lib/datagrids/DatagridDesign.d.ts +2 -0
- package/lib/datagrids/DatagridDesignerComponent.d.ts +2 -93
- package/lib/datagrids/DatagridDesignerComponent.js +11 -8
- package/lib/datagrids/DatagridViewComponent.js +2 -2
- package/lib/datagrids/DirectDatagridDataSource.d.ts +1 -0
- package/lib/datagrids/DirectDatagridDataSource.js +26 -0
- package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -20
- package/lib/datagrids/FindReplaceModalComponent.js +27 -13
- package/lib/datagrids/ServerDatagridDataSource.d.ts +2 -1
- package/lib/datagrids/ServerDatagridDataSource.js +16 -3
- package/lib/demo.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -4
- package/lib/layouts/blocks/BlocksDisplayComponent.d.ts +2 -1
- package/lib/layouts/blocks/BlocksDisplayComponent.js +2 -2
- package/lib/layouts/grid/GridLayoutManager.d.ts +2 -1
- package/lib/layouts/grid/LegoLayoutEngine.d.ts +1 -1
- package/lib/maps/BufferLayer.js +3 -1
- package/lib/maps/BufferLayerDesignerComponent.js +2 -2
- package/lib/maps/ChoroplethLayerDesigner.js +2 -2
- package/lib/maps/ClusterLayer.js +3 -1
- package/lib/maps/ClusterLayerDesignerComponent.js +2 -2
- package/lib/maps/DirectMapDataSource.js +1 -2
- package/lib/maps/GridLayer.js +5 -3
- package/lib/maps/GridLayerDesigner.js +2 -3
- 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/MapDesignerComponent.d.ts +1 -12
- package/lib/maps/MapDesignerComponent.js +5 -12
- package/lib/maps/MapFiltersDesignerComponent.d.ts +0 -4
- package/lib/maps/MapFiltersDesignerComponent.js +4 -5
- package/lib/maps/MarkersLayerDesignerComponent.js +2 -2
- package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -1
- package/lib/maps/PopupFilterJoinsUtils.js +4 -3
- 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/UtfGridLayer.js +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/ImageWidgetComponent.js +2 -2
- 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/calendar/CalendarChartDesignerComponent.js +2 -2
- package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -1
- package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +1 -1
- package/lib/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.js +2 -2
- 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/layered/LayeredChartLayerDesignerComponent.js +2 -2
- 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/PivotChartDesignerComponent.js +2 -2
- 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/TableChartDesignerComponent.js +2 -2
- package/lib/widgets/charts/table/TableChartViewComponent.js +21 -7
- package/lib/widgets/text/ExprInsertModalComponent.d.ts +2 -13
- package/lib/widgets/text/ExprItemEditorComponent.js +2 -2
- 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/MWaterAddRelatedFormComponent.ts +15 -20
- package/src/MWaterContextComponent.tsx +158 -0
- package/src/MWaterCustomTablesetListComponent.tsx +21 -3
- package/src/MWaterGlobalFiltersComponent.ts +8 -8
- package/src/MWaterLoaderComponent.ts +10 -3
- package/src/{MWaterTableSelectComponent.ts → MWaterTableSelectComponent.tsx} +61 -66
- package/src/axes/Axis.ts +24 -25
- package/src/axes/AxisBuilder.ts +10 -9
- package/src/axes/RangesComponent.ts +27 -16
- package/src/dashboards/{DashboardComponent.ts → DashboardComponent.tsx} +39 -80
- package/src/dashboards/DashboardDesign.ts +2 -22
- package/src/dashboards/DashboardViewComponent.ts +4 -5
- package/src/dashboards/LayoutOptionsComponent.tsx +6 -4
- package/src/dashboards/ServerDashboardDataSource.ts +16 -12
- package/src/dashboards/SettingsModalComponent.tsx +170 -0
- package/src/datagrids/DatagridComponent.ts +45 -14
- package/src/datagrids/DatagridDataSource.ts +10 -8
- package/src/datagrids/DatagridDesign.ts +3 -0
- package/src/datagrids/DatagridDesignerComponent.tsx +31 -19
- package/src/datagrids/DatagridViewComponent.ts +4 -4
- package/src/datagrids/DirectDatagridDataSource.ts +35 -0
- package/src/datagrids/ExprCellComponent.ts +0 -1
- package/src/datagrids/FindReplaceModalComponent.ts +39 -22
- package/src/datagrids/ServerDatagridDataSource.ts +23 -6
- package/src/demo.ts +1 -1
- package/src/index.ts +1 -2
- package/src/layouts/blocks/BlocksDisplayComponent.ts +2 -2
- package/src/layouts/grid/LegoLayoutEngine.ts +2 -2
- package/src/layouts/grid/WidgetContainerComponent.ts +2 -2
- package/src/maps/BingLayer.ts +2 -2
- package/src/maps/BufferLayer.ts +3 -1
- package/src/maps/BufferLayerDesignerComponent.ts +1 -1
- package/src/maps/ChoroplethLayerDesigner.tsx +1 -1
- package/src/maps/ClusterLayer.ts +3 -1
- package/src/maps/ClusterLayerDesignerComponent.ts +1 -1
- package/src/maps/DirectMapDataSource.ts +1 -2
- package/src/maps/GridLayer.ts +5 -3
- package/src/maps/GridLayerDesigner.tsx +1 -2
- package/src/maps/LayerSwitcherComponent.tsx +1 -1
- package/src/maps/LegendGroup.ts +1 -1
- package/src/maps/MWaterServerLayer.ts +2 -2
- package/src/maps/MapDesign.ts +2 -17
- package/src/maps/{MapDesignerComponent.ts → MapDesignerComponent.tsx} +8 -16
- package/src/maps/{MapFiltersDesignerComponent.ts → MapFiltersDesignerComponent.tsx} +25 -25
- package/src/maps/MarkersLayerDesignerComponent.ts +1 -1
- package/src/maps/PopupFilterJoinsUtils.ts +4 -4
- package/src/maps/ServerMapDataSource.ts +7 -7
- package/src/maps/SwitchableTileUrlLayerDesigner.tsx +1 -13
- package/src/maps/UtfGridLayer.ts +4 -4
- package/src/maps/VectorMapViewComponent.tsx +0 -1
- package/src/maps/mapboxUtils.ts +2 -2
- package/src/maps/vectorMaps.tsx +10 -1
- package/src/quickfilter/QuickfilterCompiler.ts +1 -1
- package/src/richtext/ExprItemsHtmlConverter.ts +1 -1
- package/src/richtext/FontColorPaletteItem.ts +1 -1
- package/src/richtext/FontSizePaletteItem.ts +1 -1
- package/src/richtext/ItemsHtmlConverter.ts +2 -2
- package/src/widgets/ImageWidgetComponent.ts +1 -1
- package/src/widgets/charts/calendar/CalendarChartDesignerComponent.ts +1 -1
- package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +1 -1
- package/src/widgets/charts/imagemosaic/ImageMosaicChartDesignerComponent.ts +1 -1
- package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +1 -1
- package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +1 -1
- package/src/widgets/charts/table/TableChartDesignerComponent.ts +1 -1
- package/src/widgets/charts/table/TableChartViewComponent.ts +21 -7
- package/src/widgets/text/ExprItemEditorComponent.tsx +1 -1
- package/src/widgets/text/TextWidgetDesign.ts +4 -1
- package/src/MWaterContextComponent.ts +0 -141
- package/src/TableSelectComponent.ts +0 -60
- package/src/dashboards/SettingsModalComponent.ts +0 -169
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { JsonQLFilter } from "../JsonQLFilter"
|
|
2
1
|
import { Quickfilter } from "../quickfilter/Quickfilter"
|
|
3
|
-
import {
|
|
2
|
+
import { Expr } from "@mwater/expressions"
|
|
4
3
|
import { BlocksLayoutOptions, DashboardTheme } from "./layoutOptions"
|
|
4
|
+
import { GlobalFilter } from "../GlobalFilter"
|
|
5
5
|
|
|
6
6
|
/** Dashboard design
|
|
7
7
|
* Each understands enough of the dashboard design to create widgets.
|
|
@@ -35,23 +35,3 @@ export interface DashboardDesign {
|
|
|
35
35
|
/** array of global filters. See below. */
|
|
36
36
|
globalFilters?: GlobalFilter[]
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
/** Global Filters:
|
|
40
|
-
|
|
41
|
-
Global filters apply to multiple tables at once if a certain column is present. User-interface to set them is application-specific
|
|
42
|
-
and the default (non-mWater) dashboard applies them but does not allow editing.
|
|
43
|
-
|
|
44
|
-
*/
|
|
45
|
-
export interface GlobalFilter {
|
|
46
|
-
/** id of column to filter */
|
|
47
|
-
columnId: string
|
|
48
|
-
|
|
49
|
-
/** type of column to filter (to ensure that consistent) */
|
|
50
|
-
columnType: LiteralType
|
|
51
|
-
|
|
52
|
-
/** op of expression for filtering */
|
|
53
|
-
op: string
|
|
54
|
-
|
|
55
|
-
/** array of expressions to use for filtering. field expression for column will be injected as expression 0 in the resulting filter expression */
|
|
56
|
-
exprs: Expr[]
|
|
57
|
-
}
|
|
@@ -14,7 +14,7 @@ import WidgetScopesViewComponent from "../widgets/WidgetScopesViewComponent"
|
|
|
14
14
|
import { getLayoutOptions } from "./layoutOptions"
|
|
15
15
|
import { WidgetComponent } from "./WidgetComponent"
|
|
16
16
|
import { DashboardDataSource, DashboardDesign, JsonQLFilter } from ".."
|
|
17
|
-
import {
|
|
17
|
+
import { setPrintingModeEnabled } from "../maps/vectorMaps"
|
|
18
18
|
|
|
19
19
|
export interface DashboardViewComponentProps {
|
|
20
20
|
/** schema to use */
|
|
@@ -147,10 +147,9 @@ export default class DashboardViewComponent extends React.Component<
|
|
|
147
147
|
|
|
148
148
|
// Call to print the dashboard
|
|
149
149
|
print = async () => {
|
|
150
|
-
// Temporarily
|
|
151
|
-
const mapTilerAPIKey = getMapTilerApiKey()
|
|
150
|
+
// Temporarily enable print mode for vector maps
|
|
152
151
|
try {
|
|
153
|
-
|
|
152
|
+
setPrintingModeEnabled(true)
|
|
154
153
|
|
|
155
154
|
// Create element at 1080 wide (use as standard printing width)
|
|
156
155
|
const elem = R(
|
|
@@ -162,7 +161,7 @@ export default class DashboardViewComponent extends React.Component<
|
|
|
162
161
|
const printer = new ReactElementPrinter()
|
|
163
162
|
await printer.print(elem, { delay: 5000 })
|
|
164
163
|
} finally {
|
|
165
|
-
|
|
164
|
+
setPrintingModeEnabled(false)
|
|
166
165
|
}
|
|
167
166
|
}
|
|
168
167
|
|
|
@@ -137,7 +137,7 @@ export function LayoutOptionsComponent(props: {
|
|
|
137
137
|
<div style={{ height: "100%", display: "grid", gridTemplateRows: "auto 1fr" }}>
|
|
138
138
|
<div key="quickfilters">
|
|
139
139
|
{layoutOptions.hideQuickfiltersWidth == null ||
|
|
140
|
-
|
|
140
|
+
sizeOptions[previewSize].value.width > layoutOptions.hideQuickfiltersWidth
|
|
141
141
|
? props.quickfiltersView
|
|
142
142
|
: null}
|
|
143
143
|
</div>
|
|
@@ -196,9 +196,11 @@ function ThemeToggle(props: { theme?: DashboardTheme; onChange: (theme: Dashboar
|
|
|
196
196
|
|
|
197
197
|
return (
|
|
198
198
|
<FormGroup label="Theme">
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
<div className="list-group">
|
|
200
|
+
{renderStyleItem("default")}
|
|
201
|
+
{renderStyleItem("greybg")}
|
|
202
|
+
{renderStyleItem("story")}
|
|
203
|
+
</div>
|
|
202
204
|
</FormGroup>
|
|
203
205
|
)
|
|
204
206
|
}
|
|
@@ -97,7 +97,7 @@ class ServerQuickfilterDataSource implements QuickfiltersDataSource {
|
|
|
97
97
|
`dashboards/${this.options.dashboardId}/quickfilters/${index}/values?` +
|
|
98
98
|
querystring.stringify(query)
|
|
99
99
|
|
|
100
|
-
const headers = {}
|
|
100
|
+
const headers: any = {}
|
|
101
101
|
const cacheExpiry = this.options.dataSource.getCacheExpiry()
|
|
102
102
|
if (cacheExpiry) {
|
|
103
103
|
const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000)
|
|
@@ -110,10 +110,10 @@ class ServerQuickfilterDataSource implements QuickfiltersDataSource {
|
|
|
110
110
|
url,
|
|
111
111
|
headers
|
|
112
112
|
})
|
|
113
|
-
.done((data) => {
|
|
113
|
+
.done((data: any) => {
|
|
114
114
|
return callback(null, data)
|
|
115
115
|
})
|
|
116
|
-
.fail((xhr) => {
|
|
116
|
+
.fail((xhr: any) => {
|
|
117
117
|
console.log(xhr.responseText)
|
|
118
118
|
return callback(new Error(xhr.responseText))
|
|
119
119
|
})
|
|
@@ -151,7 +151,7 @@ class ServerWidgetDataSource {
|
|
|
151
151
|
`dashboards/${this.options.dashboardId}/widgets/${this.options.widgetId}/data?` +
|
|
152
152
|
querystring.stringify(query)
|
|
153
153
|
|
|
154
|
-
const headers = {}
|
|
154
|
+
const headers: any = {}
|
|
155
155
|
const cacheExpiry = this.options.dataSource.getCacheExpiry()
|
|
156
156
|
if (cacheExpiry) {
|
|
157
157
|
const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000)
|
|
@@ -164,10 +164,10 @@ class ServerWidgetDataSource {
|
|
|
164
164
|
url,
|
|
165
165
|
headers
|
|
166
166
|
})
|
|
167
|
-
.done((data) => {
|
|
167
|
+
.done((data: any) => {
|
|
168
168
|
return callback(null, data)
|
|
169
169
|
})
|
|
170
|
-
.fail((xhr) => {
|
|
170
|
+
.fail((xhr: any) => {
|
|
171
171
|
console.log(xhr.responseText)
|
|
172
172
|
return callback(new Error(xhr.responseText))
|
|
173
173
|
})
|
|
@@ -235,7 +235,7 @@ class ServerWidgetMapDataSource implements MapDataSource {
|
|
|
235
235
|
`dashboards/${this.options.dashboardId}/widgets/${this.options.widgetId}/bounds?` +
|
|
236
236
|
querystring.stringify(query)
|
|
237
237
|
|
|
238
|
-
const headers = {}
|
|
238
|
+
const headers: any = {}
|
|
239
239
|
const cacheExpiry = this.options.dataSource.getCacheExpiry()
|
|
240
240
|
if (cacheExpiry) {
|
|
241
241
|
const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000)
|
|
@@ -248,14 +248,18 @@ class ServerWidgetMapDataSource implements MapDataSource {
|
|
|
248
248
|
url,
|
|
249
249
|
headers
|
|
250
250
|
})
|
|
251
|
-
.done((data) => {
|
|
251
|
+
.done((data: any) => {
|
|
252
252
|
return callback(null, data)
|
|
253
253
|
})
|
|
254
|
-
.fail((xhr) => {
|
|
254
|
+
.fail((xhr: any) => {
|
|
255
255
|
console.log(xhr.responseText)
|
|
256
256
|
return callback(new Error(xhr.responseText))
|
|
257
257
|
})
|
|
258
258
|
}
|
|
259
|
+
|
|
260
|
+
getQuickfiltersDataSource(): QuickfiltersDataSource {
|
|
261
|
+
return new ServerQuickfilterDataSource(this.options)
|
|
262
|
+
}
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
interface ServerWidgetLayerDataSourceOptions extends ServerDashboardDataSourceOptions {
|
|
@@ -480,7 +484,7 @@ class ServerWidgetLayerPopupWidgetDataSource implements WidgetDataSource {
|
|
|
480
484
|
`dashboards/${this.options.dashboardId}/widgets/${this.options.widgetId}/layers/${this.options.layerView.id}/widgets/${this.options.popupWidgetId}/data?` +
|
|
481
485
|
querystring.stringify(query)
|
|
482
486
|
|
|
483
|
-
const headers = {}
|
|
487
|
+
const headers: any = {}
|
|
484
488
|
const cacheExpiry = this.options.dataSource.getCacheExpiry()
|
|
485
489
|
if (cacheExpiry) {
|
|
486
490
|
const seconds = Math.floor((new Date().getTime() - cacheExpiry) / 1000)
|
|
@@ -493,10 +497,10 @@ class ServerWidgetLayerPopupWidgetDataSource implements WidgetDataSource {
|
|
|
493
497
|
url,
|
|
494
498
|
headers
|
|
495
499
|
})
|
|
496
|
-
.done((data) => {
|
|
500
|
+
.done((data: any) => {
|
|
497
501
|
return callback(null, data)
|
|
498
502
|
})
|
|
499
|
-
.fail((xhr) => {
|
|
503
|
+
.fail((xhr: any) => {
|
|
500
504
|
console.log(xhr.responseText)
|
|
501
505
|
return callback(new Error(xhr.responseText))
|
|
502
506
|
})
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import _ from "lodash"
|
|
2
|
+
import React from "react"
|
|
3
|
+
const R = React.createElement
|
|
4
|
+
import update from "update-object"
|
|
5
|
+
import { languages } from "../languages"
|
|
6
|
+
import * as ui from "@mwater/react-library/lib/bootstrap"
|
|
7
|
+
import { default as ReactSelect } from "react-select"
|
|
8
|
+
import * as DashboardUtils from "./DashboardUtils"
|
|
9
|
+
import ActionCancelModalComponent from "@mwater/react-library/lib/ActionCancelModalComponent"
|
|
10
|
+
import QuickfiltersDesignComponent from "../quickfilter/QuickfiltersDesignComponent"
|
|
11
|
+
import FiltersDesignerComponent from "../FiltersDesignerComponent"
|
|
12
|
+
import { DataSource, Schema } from "@mwater/expressions"
|
|
13
|
+
import { DashboardDesign } from "./DashboardDesign"
|
|
14
|
+
import { GlobalFiltersElementFactoryContext } from "../MWaterContextComponent"
|
|
15
|
+
|
|
16
|
+
export interface SettingsModalComponentProps {
|
|
17
|
+
onDesignChange: any
|
|
18
|
+
schema: Schema
|
|
19
|
+
dataSource: DataSource
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SettingsModalComponentState {
|
|
23
|
+
design: DashboardDesign | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Popup with settings for dashboard
|
|
27
|
+
export default class SettingsModalComponent extends React.Component<
|
|
28
|
+
SettingsModalComponentProps,
|
|
29
|
+
SettingsModalComponentState
|
|
30
|
+
> {
|
|
31
|
+
constructor(props: SettingsModalComponentProps) {
|
|
32
|
+
super(props)
|
|
33
|
+
this.state = {
|
|
34
|
+
design: null // Set when being edited
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
show(design: any) {
|
|
39
|
+
return this.setState({ design })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
handleSave = () => {
|
|
43
|
+
this.props.onDesignChange(this.state.design)
|
|
44
|
+
return this.setState({ design: null })
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
handleCancel = () => {
|
|
48
|
+
return this.setState({ design: null })
|
|
49
|
+
}
|
|
50
|
+
handleDesignChange = (design: any) => {
|
|
51
|
+
return this.setState({ design })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
handleFiltersChange = (filters: any) => {
|
|
55
|
+
const design = _.extend({}, this.state.design, { filters })
|
|
56
|
+
return this.handleDesignChange(design)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
handleGlobalFiltersChange = (globalFilters: any) => {
|
|
60
|
+
const design = _.extend({}, this.state.design, { globalFilters })
|
|
61
|
+
return this.handleDesignChange(design)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
render() {
|
|
65
|
+
// Don't show if not editing
|
|
66
|
+
if (!this.state.design) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Get filterable tables
|
|
71
|
+
const filterableTables = DashboardUtils.getFilterableTables(this.state.design, this.props.schema)
|
|
72
|
+
|
|
73
|
+
const localeOptions = _.map(languages, (language) => {
|
|
74
|
+
return {
|
|
75
|
+
value: language.code,
|
|
76
|
+
label: language.en + " (" + language.name + ")"
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<ActionCancelModalComponent
|
|
82
|
+
size="large"
|
|
83
|
+
onCancel={this.handleCancel}
|
|
84
|
+
onAction={this.handleSave}
|
|
85
|
+
>
|
|
86
|
+
<div style={{ paddingBottom: 200 }}>
|
|
87
|
+
<h4>Quick Filters</h4>
|
|
88
|
+
<div className="text-muted">
|
|
89
|
+
Quick filters are shown to the user as a dropdown at the top of the dashboard and can be used to filter data of widgets.
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{filterableTables.length > 0 ? (
|
|
93
|
+
<QuickfiltersDesignComponent
|
|
94
|
+
design={this.state.design.quickfilters || []}
|
|
95
|
+
onDesignChange={(design: any) =>
|
|
96
|
+
this.handleDesignChange(update(this.state.design, { quickfilters: { $set: design } }))
|
|
97
|
+
}
|
|
98
|
+
schema={this.props.schema}
|
|
99
|
+
dataSource={this.props.dataSource}
|
|
100
|
+
tables={filterableTables}
|
|
101
|
+
/>
|
|
102
|
+
) : (
|
|
103
|
+
"Nothing to quickfilter. Add widgets to the dashboard"
|
|
104
|
+
)}
|
|
105
|
+
|
|
106
|
+
<h4 style={{ paddingTop: 10 }}>Filters</h4>
|
|
107
|
+
<div className="text-muted">
|
|
108
|
+
Filters are built in to the dashboard and cannot be changed by viewers of the dashboard.
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{filterableTables.length > 0 ? (
|
|
112
|
+
<FiltersDesignerComponent
|
|
113
|
+
schema={this.props.schema}
|
|
114
|
+
dataSource={this.props.dataSource}
|
|
115
|
+
filters={this.state.design.filters}
|
|
116
|
+
onFiltersChange={this.handleFiltersChange}
|
|
117
|
+
filterableTables={filterableTables}
|
|
118
|
+
/>
|
|
119
|
+
) : (
|
|
120
|
+
"Nothing to filter. Add widgets to the dashboard"
|
|
121
|
+
)}
|
|
122
|
+
|
|
123
|
+
<GlobalFiltersElementFactoryContext.Consumer>
|
|
124
|
+
{globalFiltersElementFactory =>
|
|
125
|
+
globalFiltersElementFactory ? (
|
|
126
|
+
<div>
|
|
127
|
+
<h4 style={{ paddingTop: 10 }}>Global Filters</h4>
|
|
128
|
+
{globalFiltersElementFactory({
|
|
129
|
+
schema: this.props.schema,
|
|
130
|
+
dataSource: this.props.dataSource,
|
|
131
|
+
filterableTables,
|
|
132
|
+
globalFilters: this.state.design!.globalFilters || [],
|
|
133
|
+
onChange: this.handleGlobalFiltersChange
|
|
134
|
+
})}
|
|
135
|
+
</div>
|
|
136
|
+
) : undefined
|
|
137
|
+
}
|
|
138
|
+
</GlobalFiltersElementFactoryContext.Consumer>
|
|
139
|
+
|
|
140
|
+
<h4 style={{ paddingTop: 10 }}>Language</h4>
|
|
141
|
+
<div className="text-muted">
|
|
142
|
+
Controls the preferred language of widgets and uses specified language when available
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<ReactSelect
|
|
146
|
+
value={_.findWhere(localeOptions, { value: this.state.design.locale || "en" }) || null}
|
|
147
|
+
options={localeOptions}
|
|
148
|
+
onChange={(locale: any) =>
|
|
149
|
+
this.handleDesignChange(update(this.state.design, { locale: { $set: locale.value } }))
|
|
150
|
+
}
|
|
151
|
+
/>
|
|
152
|
+
|
|
153
|
+
{this.state.design.implicitFiltersEnabled && (
|
|
154
|
+
<>
|
|
155
|
+
<h4 style={{ paddingTop: 10 }}>Advanced</h4>
|
|
156
|
+
<ui.Checkbox
|
|
157
|
+
value={this.state.design.implicitFiltersEnabled != null ? this.state.design.implicitFiltersEnabled : true}
|
|
158
|
+
onChange={(value: boolean) =>
|
|
159
|
+
this.handleDesignChange(update(this.state.design, { implicitFiltersEnabled: { $set: value } }))
|
|
160
|
+
}
|
|
161
|
+
>
|
|
162
|
+
Enable Implicit Filtering (leave unchecked for new dashboards)
|
|
163
|
+
</ui.Checkbox>
|
|
164
|
+
</>
|
|
165
|
+
)}
|
|
166
|
+
</div>
|
|
167
|
+
</ActionCancelModalComponent>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -16,6 +16,7 @@ import QuickfilterCompiler from "../quickfilter/QuickfilterCompiler"
|
|
|
16
16
|
import FindReplaceModalComponent from "./FindReplaceModalComponent"
|
|
17
17
|
import DatagridDataSource from "./DatagridDataSource"
|
|
18
18
|
import { DatagridDesign, JsonQLFilter } from ".."
|
|
19
|
+
import { format as d3Format } from "d3-format"
|
|
19
20
|
|
|
20
21
|
export interface DatagridComponentProps {
|
|
21
22
|
/** schema to use */
|
|
@@ -55,21 +56,25 @@ export interface DatagridComponentProps {
|
|
|
55
56
|
filters?: JsonQLFilter[]
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
interface DatagridComponentState {
|
|
60
|
+
/** is design being edited */
|
|
61
|
+
editingDesign: boolean
|
|
62
|
+
/** True if cells can be edited directly */
|
|
63
|
+
cellEditingEnabled: boolean
|
|
64
|
+
/** Height of quickfilters */
|
|
65
|
+
quickfiltersHeight: number | null
|
|
66
|
+
quickfiltersValues: null | any[]
|
|
67
|
+
refreshKey: number
|
|
68
|
+
/** Number of rows */
|
|
69
|
+
numRows?: number
|
|
70
|
+
}
|
|
71
|
+
|
|
58
72
|
// Datagrid with decorations
|
|
59
73
|
// See README.md for description of datagrid format
|
|
60
74
|
// Design should be cleaned already before being passed in (see DatagridUtils)
|
|
61
75
|
export default class DatagridComponent extends React.Component<
|
|
62
76
|
DatagridComponentProps,
|
|
63
|
-
|
|
64
|
-
/** is design being edited */
|
|
65
|
-
editingDesign: boolean
|
|
66
|
-
/** True if cells can be edited directly */
|
|
67
|
-
cellEditingEnabled: boolean
|
|
68
|
-
/** Height of quickfilters */
|
|
69
|
-
quickfiltersHeight: number | null
|
|
70
|
-
quickfiltersValues: null | any[]
|
|
71
|
-
refreshKey: number
|
|
72
|
-
}
|
|
77
|
+
DatagridComponentState
|
|
73
78
|
> {
|
|
74
79
|
datagridView?: DatagridViewComponent | null
|
|
75
80
|
quickfilters?: HTMLElement | null
|
|
@@ -88,15 +93,40 @@ export default class DatagridComponent extends React.Component<
|
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
reload() {
|
|
91
|
-
|
|
96
|
+
this.datagridView?.reload()
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
componentDidMount() {
|
|
95
|
-
|
|
100
|
+
this.loadRowCount()
|
|
101
|
+
this.updateHeight()
|
|
96
102
|
}
|
|
97
103
|
|
|
98
|
-
componentDidUpdate() {
|
|
99
|
-
|
|
104
|
+
componentDidUpdate(prevProps: DatagridComponentProps, prevState: DatagridComponentState) {
|
|
105
|
+
if (!_.isEqual(prevProps.design, this.props.design) || !_.isEqual(prevState.quickfiltersValues, this.state.quickfiltersValues) || prevState.refreshKey !== this.state.refreshKey) {
|
|
106
|
+
this.loadRowCount()
|
|
107
|
+
}
|
|
108
|
+
this.updateHeight()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
loadRowCount() {
|
|
112
|
+
if(!this.props.design.showNumRows) {
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
let filters = this.props.filters || []
|
|
116
|
+
|
|
117
|
+
// Compile quickfilters
|
|
118
|
+
filters = filters.concat(this.getQuickfilterFilters())
|
|
119
|
+
this.props.datagridDataSource.countRows(this.props.design,
|
|
120
|
+
filters,
|
|
121
|
+
(error: any, numRows: any) => {
|
|
122
|
+
if (error) {
|
|
123
|
+
console.error(error)
|
|
124
|
+
alert(T("Error loading data"))
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
console.log(numRows)
|
|
128
|
+
this.setState({numRows})
|
|
129
|
+
})
|
|
100
130
|
}
|
|
101
131
|
|
|
102
132
|
handleRefreshData = () => {
|
|
@@ -265,6 +295,7 @@ export default class DatagridComponent extends React.Component<
|
|
|
265
295
|
R(
|
|
266
296
|
"div",
|
|
267
297
|
{ style: { float: "right" } },
|
|
298
|
+
this.props.design.showNumRows && this.state.numRows ? R("small", {className: 'text-muted text-sm'}, `${d3Format(',')(this.state.numRows)} rows`): undefined,
|
|
268
299
|
this.renderFindReplace(),
|
|
269
300
|
this.renderCellEdit(),
|
|
270
301
|
this.renderEditButton(),
|
|
@@ -2,20 +2,22 @@ import { Row } from "@mwater/expressions"
|
|
|
2
2
|
import { DatagridDesign, JsonQLFilter } from ".."
|
|
3
3
|
import { QuickfiltersDataSource } from "../quickfilter/QuickfiltersDataSource"
|
|
4
4
|
|
|
5
|
-
export default
|
|
5
|
+
export default interface DatagridDataSource {
|
|
6
6
|
/** Gets the rows specified */
|
|
7
7
|
getRows(
|
|
8
8
|
design: DatagridDesign,
|
|
9
9
|
offset: number,
|
|
10
10
|
limit: number,
|
|
11
11
|
filters: JsonQLFilter[] | undefined,
|
|
12
|
-
callback: (error: any, rows
|
|
13
|
-
): void
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
callback: (error: any, rows?: Row[]) => void
|
|
13
|
+
): void
|
|
14
|
+
|
|
15
|
+
countRows(
|
|
16
|
+
design: DatagridDesign,
|
|
17
|
+
filters: JsonQLFilter[] | undefined,
|
|
18
|
+
callback: (error: any, numRows?: number) => void
|
|
19
|
+
): void
|
|
16
20
|
|
|
17
21
|
/** Gets the quickfilters data source */
|
|
18
|
-
getQuickfiltersDataSource(): QuickfiltersDataSource
|
|
19
|
-
throw new Error("Not implemented")
|
|
20
|
-
}
|
|
22
|
+
getQuickfiltersDataSource(): QuickfiltersDataSource
|
|
21
23
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import PropTypes from "prop-types"
|
|
2
1
|
import _ from "lodash"
|
|
3
2
|
import React, { useMemo } from "react"
|
|
4
3
|
const R = React.createElement
|
|
@@ -14,7 +13,7 @@ import OrderBysDesignerComponent from "./OrderBysDesignerComponent"
|
|
|
14
13
|
import ReorderableListComponent from "@mwater/react-library/lib/reorderable/ReorderableListComponent"
|
|
15
14
|
import QuickfiltersDesignComponent from "../quickfilter/QuickfiltersDesignComponent"
|
|
16
15
|
import LabeledExprGenerator from "./LabeledExprGenerator"
|
|
17
|
-
import TableSelectComponent from "
|
|
16
|
+
import { TableSelectComponent } from "@mwater/expressions-ui"
|
|
18
17
|
import uuid from "uuid"
|
|
19
18
|
import update from "update-object"
|
|
20
19
|
import * as ui from "@mwater/react-library/lib/bootstrap"
|
|
@@ -22,6 +21,7 @@ import { getFormatOptions } from "../valueFormatter"
|
|
|
22
21
|
import { getDefaultFormat } from "../valueFormatter"
|
|
23
22
|
import { DatagridDesignColumn } from "./DatagridDesign"
|
|
24
23
|
import { DatagridDesign } from ".."
|
|
24
|
+
import { GlobalFiltersElementFactoryContext } from "../MWaterContextComponent"
|
|
25
25
|
|
|
26
26
|
export interface DatagridDesignerComponentProps {
|
|
27
27
|
/** schema to use */
|
|
@@ -36,8 +36,6 @@ export interface DatagridDesignerComponentProps {
|
|
|
36
36
|
|
|
37
37
|
// Designer for the datagrid. Currenly allows only single-table designs (no subtable rows)
|
|
38
38
|
export default class DatagridDesignerComponent extends React.Component<DatagridDesignerComponentProps> {
|
|
39
|
-
static contextTypes = { globalFiltersElementFactory: PropTypes.func }
|
|
40
|
-
|
|
41
39
|
handleTableChange = (table: any) => {
|
|
42
40
|
const design = {
|
|
43
41
|
table,
|
|
@@ -93,20 +91,24 @@ export default class DatagridDesignerComponent extends React.Component<DatagridD
|
|
|
93
91
|
value: this.props.design.filter,
|
|
94
92
|
onChange: this.handleFilterChange
|
|
95
93
|
}),
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
<GlobalFiltersElementFactoryContext.Consumer>
|
|
95
|
+
{(globalFiltersElementFactory) =>
|
|
96
|
+
globalFiltersElementFactory
|
|
97
|
+
? R(
|
|
98
|
+
"div",
|
|
99
|
+
{ style: { marginTop: 20 } },
|
|
100
|
+
globalFiltersElementFactory({
|
|
101
|
+
schema: this.props.schema,
|
|
102
|
+
dataSource: this.props.dataSource,
|
|
103
|
+
filterableTables: [this.props.design.table!],
|
|
104
|
+
globalFilters: this.props.design.globalFilters,
|
|
105
|
+
onChange: this.handleGlobalFiltersChange,
|
|
106
|
+
nullIfIrrelevant: true
|
|
107
|
+
})
|
|
108
|
+
)
|
|
109
|
+
: undefined
|
|
110
|
+
}
|
|
111
|
+
</GlobalFiltersElementFactoryContext.Consumer>
|
|
110
112
|
)
|
|
111
113
|
},
|
|
112
114
|
{
|
|
@@ -196,6 +198,14 @@ function DatagridOptionsComponent(props: DatagridOptionsComponentProps) {
|
|
|
196
198
|
>
|
|
197
199
|
{T("Show row numbers")}
|
|
198
200
|
</ui.Checkbox>
|
|
201
|
+
<ui.Checkbox
|
|
202
|
+
value={props.design.showNumRows}
|
|
203
|
+
onChange={(showNumRows) =>
|
|
204
|
+
props.onDesignChange({ ...props.design, showNumRows })
|
|
205
|
+
}
|
|
206
|
+
>
|
|
207
|
+
{T("Show number of rows")}
|
|
208
|
+
</ui.Checkbox>
|
|
199
209
|
<ui.FormGroup label={T("Language")} hint={T("Preferred language of the datagrid")}>
|
|
200
210
|
<ReactSelect
|
|
201
211
|
value={localeOptions.find(opt => opt.value == (props.design.locale || "en")) || null}
|
|
@@ -554,7 +564,9 @@ class ColumnDesignerComponent extends React.Component<ColumnDesignerComponentPro
|
|
|
554
564
|
}),
|
|
555
565
|
this.renderSplit(),
|
|
556
566
|
this.renderFormat(),
|
|
557
|
-
error ?
|
|
567
|
+
error ? <span className="text-danger">
|
|
568
|
+
<i className="fa fa-exclamation-circle" /> {error}
|
|
569
|
+
</span> : undefined
|
|
558
570
|
),
|
|
559
571
|
|
|
560
572
|
R(
|
|
@@ -95,7 +95,7 @@ export default class DatagridViewComponent extends React.Component<
|
|
|
95
95
|
// If design or filters changed, delete all rows
|
|
96
96
|
// TODO won't this reload on column resize?
|
|
97
97
|
if (!_.isEqual(nextProps.design, this.props.design) || !_.isEqual(nextProps.filters, this.props.filters) || nextProps.refreshKey !== this.props.refreshKey) {
|
|
98
|
-
|
|
98
|
+
this.setState({ rows: [], entirelyLoaded: false })
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -191,8 +191,8 @@ export default class DatagridViewComponent extends React.Component<
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
const newRows = produce(this.state.rows, draft => {
|
|
194
|
-
if (rows[0]) {
|
|
195
|
-
draft[rowIndex] = rows[0]
|
|
194
|
+
if (rows![0]) {
|
|
195
|
+
draft[rowIndex] = rows![0]
|
|
196
196
|
}
|
|
197
197
|
else {
|
|
198
198
|
// If row missing, remove it from list
|
|
@@ -308,7 +308,7 @@ export default class DatagridViewComponent extends React.Component<
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
handleRowDoubleClick = (ev: any, rowIndex: any) => {
|
|
311
|
-
if (this.props.onRowDoubleClick != null && this.state.rows[rowIndex]
|
|
311
|
+
if (this.props.onRowDoubleClick != null && this.state.rows[rowIndex]?.id) {
|
|
312
312
|
this.props.onRowDoubleClick(this.props.design.table!, this.state.rows[rowIndex].id, rowIndex)
|
|
313
313
|
}
|
|
314
314
|
}
|
|
@@ -4,6 +4,8 @@ import * as QuickfilterUtils from "../quickfilter/QuickfilterUtils"
|
|
|
4
4
|
import { DataSource, Row, Schema } from "@mwater/expressions"
|
|
5
5
|
import { DatagridDesign } from "./DatagridDesign"
|
|
6
6
|
import { JsonQLFilter } from "../JsonQLFilter"
|
|
7
|
+
import _ from "lodash"
|
|
8
|
+
import { JsonQLSelectQuery } from "@mwater/jsonql"
|
|
7
9
|
|
|
8
10
|
/** Uses direct DataSource queries */
|
|
9
11
|
export default class DirectDatagridDataSource implements DatagridDataSource {
|
|
@@ -37,6 +39,39 @@ export default class DirectDatagridDataSource implements DatagridDataSource {
|
|
|
37
39
|
return this.options.dataSource.performQuery(query, callback)
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
countRows(
|
|
43
|
+
design: DatagridDesign,
|
|
44
|
+
filters: JsonQLFilter[] | undefined,
|
|
45
|
+
callback: (error: any, numRows: number) => void
|
|
46
|
+
): void {
|
|
47
|
+
const queryBuilder = new DatagridQueryBuilder(this.options.schema)
|
|
48
|
+
|
|
49
|
+
// Create query to get the page of rows at the specific offset
|
|
50
|
+
const query = queryBuilder.createQuery(design, {
|
|
51
|
+
extraFilters: filters
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const countQuery: JsonQLSelectQuery = {
|
|
55
|
+
..._.omit(query, 'orderBy'),
|
|
56
|
+
selects: [
|
|
57
|
+
{
|
|
58
|
+
type: 'select',
|
|
59
|
+
expr: {
|
|
60
|
+
type: 'op',
|
|
61
|
+
op: 'count',
|
|
62
|
+
exprs: []
|
|
63
|
+
},
|
|
64
|
+
alias: 'cnt'
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
console.log(countQuery)
|
|
70
|
+
return this.options.dataSource.performQuery(countQuery, (error, rows) => {
|
|
71
|
+
callback(error, rows?.[0]?.cnt)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
40
75
|
// Gets the quickfilters data source
|
|
41
76
|
getQuickfiltersDataSource() {
|
|
42
77
|
return {
|