@mwater/visualization 5.4.1 → 5.4.3
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/ColorComponent.js +2 -1
- package/lib/IdSelection.d.ts +16 -0
- package/lib/IdSelection.js +59 -0
- package/lib/MWaterAddRelatedIndicatorComponent.js +2 -2
- package/lib/MWaterCompleteTableSelectComponent.d.ts +3 -8
- package/lib/MWaterCompleteTableSelectComponent.js +36 -42
- package/lib/MWaterLoaderComponent.d.ts +11 -10
- package/lib/MWaterLoaderComponent.js +1 -1
- package/lib/MWaterResponsesFilterComponent.js +1 -1
- package/lib/MWaterTableSelectComponent.d.ts +0 -1
- package/lib/MWaterTableSelectComponent.js +4 -6
- package/lib/autotranslate.d.ts +20 -0
- package/lib/autotranslate.js +122 -0
- package/lib/axes/AxisBuilder.js +3 -3
- package/lib/axes/AxisColorEditorComponent.js +4 -0
- package/lib/axes/AxisComponent.d.ts +8 -12
- package/lib/axes/AxisComponent.js +32 -80
- package/lib/axes/CategoryMapComponent.js +4 -4
- package/lib/axes/RangesComponent.js +2 -2
- package/lib/dashboards/DashboardComponent.d.ts +12 -20
- package/lib/dashboards/DashboardComponent.js +109 -69
- package/lib/dashboards/DashboardDesign.d.ts +11 -2
- package/lib/dashboards/DashboardUtils.d.ts +5 -0
- package/lib/dashboards/DashboardUtils.js +30 -0
- package/lib/dashboards/DashboardViewComponent.d.ts +2 -0
- package/lib/dashboards/DashboardViewComponent.js +16 -3
- package/lib/dashboards/ServerDashboardDataSource.js +2 -1
- package/lib/dashboards/SettingsModalComponent.d.ts +1 -1
- package/lib/dashboards/SettingsModalComponent.js +256 -19
- package/lib/dashboards/WidgetComponent.d.ts +6 -3
- package/lib/dashboards/WidgetComponent.js +3 -1
- package/lib/datagrids/CellEditor.d.ts +19 -0
- package/lib/datagrids/CellEditor.js +223 -0
- package/lib/datagrids/DatagridComponent.d.ts +18 -87
- package/lib/datagrids/DatagridComponent.js +304 -222
- package/lib/datagrids/DatagridViewComponent.d.ts +15 -53
- package/lib/datagrids/DatagridViewComponent.js +256 -257
- package/lib/datagrids/DirectDatagridDataSource.js +2 -3
- package/lib/datagrids/ExprCellComponent.d.ts +8 -15
- package/lib/datagrids/ExprCellComponent.js +11 -15
- package/lib/datagrids/FindReplaceModalComponent.d.ts +4 -6
- package/lib/datagrids/FindReplaceModalComponent.js +38 -75
- package/lib/index.css +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/languages.js +6 -1
- package/lib/layouts/blocks/HorizontalBlockComponent.js +2 -2
- package/lib/mWaterLoader.d.ts +1 -1
- package/lib/maps/BufferLayer.d.ts +7 -5
- package/lib/maps/BufferLayer.js +69 -48
- package/lib/maps/BufferLayerDesign.d.ts +21 -14
- package/lib/maps/BufferLayerDesignerComponent.d.ts +16 -31
- package/lib/maps/BufferLayerDesignerComponent.js +68 -102
- package/lib/maps/ChoroplethLayer.d.ts +5 -4
- package/lib/maps/ChoroplethLayer.js +32 -9
- package/lib/maps/ChoroplethLayerDesign.d.ts +6 -2
- package/lib/maps/ChoroplethLayerDesigner.js +4 -2
- package/lib/maps/ClusterLayer.d.ts +3 -4
- package/lib/maps/ClusterLayer.js +2 -1
- package/lib/maps/DetailLevelSelectComponent.js +1 -1
- package/lib/maps/DirectMapDataSource.js +2 -1
- package/lib/maps/EditPopupComponent.js +5 -3
- package/lib/maps/GridLayer.d.ts +3 -4
- package/lib/maps/GridLayer.js +2 -1
- package/lib/maps/GridLayerDesigner.js +5 -3
- package/lib/maps/HoverContent.d.ts +11 -3
- package/lib/maps/HoverContent.js +25 -9
- package/lib/maps/Layer.d.ts +24 -3
- package/lib/maps/Layer.js +5 -1
- package/lib/maps/LayerFactory.js +0 -8
- package/lib/maps/LayerLegendComponent.js +0 -1
- package/lib/maps/LayerSwitcherComponent.d.ts +1 -0
- package/lib/maps/LayerSwitcherComponent.js +1 -1
- package/lib/maps/LeafletMapComponent.js +3 -1
- package/lib/maps/LegendComponent.d.ts +1 -0
- package/lib/maps/LegendComponent.js +9 -1
- package/lib/maps/MWaterServerLayer.d.ts +2 -2
- package/lib/maps/MWaterServerLayer.js +2 -2
- package/lib/maps/MapComponent.js +3 -3
- package/lib/maps/MapDesign.d.ts +2 -0
- package/lib/maps/MapDesignerComponent.d.ts +4 -3
- package/lib/maps/MapDesignerComponent.js +68 -74
- package/lib/maps/MapLayerViewDesignerComponent.js +2 -2
- package/lib/maps/MapUtils.d.ts +4 -0
- package/lib/maps/MapUtils.js +19 -0
- package/lib/maps/MapViewComponent.d.ts +8 -3
- package/lib/maps/MarkersLayer.d.ts +5 -4
- package/lib/maps/MarkersLayer.js +33 -7
- package/lib/maps/MarkersLayerDesign.d.ts +19 -16
- package/lib/maps/PopupFilterJoinsUtils.d.ts +6 -3
- package/lib/maps/PopupFilterJoinsUtils.js +0 -6
- package/lib/maps/RasterMapViewComponent.d.ts +3 -31
- package/lib/maps/RasterMapViewComponent.js +7 -2
- package/lib/maps/ServerMapDataSource.js +2 -1
- package/lib/maps/SwitchableTileUrlLayer.d.ts +3 -3
- package/lib/maps/SwitchableTileUrlLayer.js +2 -1
- package/lib/maps/TileUrlLayer.d.ts +4 -5
- package/lib/maps/TileUrlLayer.js +2 -1
- package/lib/maps/VectorMapViewComponent.d.ts +5 -37
- package/lib/maps/VectorMapViewComponent.js +19 -8
- package/lib/maps/maps.d.ts +3 -0
- package/lib/quickfilter/Quickfilter.d.ts +2 -0
- package/lib/quickfilter/QuickfiltersComponent.d.ts +2 -0
- package/lib/quickfilter/QuickfiltersComponent.js +9 -7
- package/lib/quickfilter/QuickfiltersDesignComponent.d.ts +5 -30
- package/lib/quickfilter/QuickfiltersDesignComponent.js +56 -63
- package/lib/richtext/ExprItemsHtmlConverter.d.ts +5 -2
- package/lib/richtext/ExprItemsHtmlConverter.js +4 -4
- package/lib/richtext/ExprItemsTranslator.d.ts +5 -0
- package/lib/richtext/ExprItemsTranslator.js +149 -0
- package/lib/richtext/ItemsHtmlConverter.d.ts +1 -1
- package/lib/richtext/ItemsHtmlConverter.js +31 -15
- package/lib/wellknown.js +12 -9
- package/lib/widgets/IFrameWidget.d.ts +4 -4
- package/lib/widgets/ImageWidget.d.ts +7 -4
- package/lib/widgets/ImageWidget.js +9 -1
- package/lib/widgets/ImageWidgetComponent.d.ts +1 -0
- package/lib/widgets/ImageWidgetComponent.js +1 -1
- package/lib/widgets/MapWidget.d.ts +5 -48
- package/lib/widgets/MapWidget.js +26 -63
- package/lib/widgets/MarkdownWidget.d.ts +3 -0
- package/lib/widgets/MarkdownWidget.js +3 -0
- package/lib/widgets/TOCWidget.d.ts +15 -27
- package/lib/widgets/TOCWidget.js +107 -183
- package/lib/widgets/Widget.d.ts +18 -7
- package/lib/widgets/Widget.js +4 -0
- package/lib/widgets/WidgetScopesViewComponent.js +1 -1
- package/lib/widgets/charts/Chart.d.ts +10 -1
- package/lib/widgets/charts/Chart.js +22 -11
- package/lib/widgets/charts/ChartViewComponent.d.ts +4 -0
- package/lib/widgets/charts/ChartViewComponent.js +6 -3
- package/lib/widgets/charts/ChartWidget.d.ts +2 -0
- package/lib/widgets/charts/ChartWidget.js +9 -1
- package/lib/widgets/charts/ChartWidgetComponent.d.ts +4 -0
- package/lib/widgets/charts/ChartWidgetComponent.js +2 -2
- package/lib/widgets/charts/calendar/CalendarChart.d.ts +1 -0
- package/lib/widgets/charts/calendar/CalendarChart.js +26 -0
- package/lib/widgets/charts/calendar/CalendarChartViewComponent.js +3 -1
- package/lib/widgets/charts/imagemosaic/ImageMosaicChart.d.ts +1 -0
- package/lib/widgets/charts/imagemosaic/ImageMosaicChart.js +8 -0
- package/lib/widgets/charts/layered/LayeredChart.d.ts +2 -0
- package/lib/widgets/charts/layered/LayeredChart.js +63 -3
- package/lib/widgets/charts/layered/LayeredChartCompiler.d.ts +1 -1
- package/lib/widgets/charts/layered/LayeredChartCompiler.js +1 -1
- package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +2 -2
- package/lib/widgets/charts/layered/LayeredChartViewComponent.js +8 -3
- package/lib/widgets/charts/pivot/PivotChart.d.ts +1 -0
- package/lib/widgets/charts/pivot/PivotChart.js +63 -0
- package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +1 -1
- package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +7 -4
- package/lib/widgets/charts/table/OrderingsComponent.js +1 -1
- package/lib/widgets/charts/table/TableChart.d.ts +1 -0
- package/lib/widgets/charts/table/TableChart.js +15 -0
- package/lib/widgets/text/TextComponent.d.ts +11 -4
- package/lib/widgets/text/TextComponent.js +11 -8
- package/lib/widgets/text/TextWidget.d.ts +6 -3
- package/lib/widgets/text/TextWidget.js +7 -1
- package/lib/widgets/text/TextWidgetComponent.d.ts +4 -0
- package/lib/widgets/text/TextWidgetComponent.js +7 -1
- package/lib/widgets/text/TextWidgetDesign.d.ts +2 -4
- package/lib/widgets/text/TextWidgetDesign.js +1 -1
- package/package.json +7 -8
- package/src/ColorComponent.tsx +1 -2
- package/src/IdSelection.ts +62 -0
- package/src/MWaterAddRelatedIndicatorComponent.ts +3 -2
- package/src/MWaterCompleteTableSelectComponent.tsx +36 -46
- package/src/MWaterLoaderComponent.ts +28 -26
- package/src/MWaterResponsesFilterComponent.ts +5 -2
- package/src/MWaterTableSelectComponent.tsx +5 -9
- package/src/autotranslate.ts +141 -0
- package/src/axes/AxisBuilder.ts +3 -3
- package/src/axes/AxisColorEditorComponent.tsx +5 -0
- package/src/axes/{AxisComponent.ts → AxisComponent.tsx} +106 -106
- package/src/axes/CategoryMapComponent.ts +4 -4
- package/src/axes/RangesComponent.ts +3 -2
- package/src/dashboards/DashboardComponent.tsx +189 -125
- package/src/dashboards/DashboardDesign.ts +9 -2
- package/src/dashboards/DashboardUtils.ts +39 -0
- package/src/dashboards/DashboardViewComponent.tsx +22 -3
- package/src/dashboards/ServerDashboardDataSource.ts +2 -1
- package/src/dashboards/SettingsModalComponent.tsx +450 -35
- package/src/dashboards/WidgetComponent.tsx +12 -6
- package/src/datagrids/CellEditor.tsx +354 -0
- package/src/datagrids/DatagridComponent.tsx +646 -0
- package/src/datagrids/DatagridViewComponent.tsx +539 -0
- package/src/datagrids/DirectDatagridDataSource.ts +2 -3
- package/src/datagrids/{ExprCellComponent.ts → ExprCellComponent.tsx} +28 -23
- package/src/datagrids/{FindReplaceModalComponent.ts → FindReplaceModalComponent.tsx} +109 -122
- package/src/index.css +1 -1
- package/src/index.ts +0 -1
- package/src/languages.ts +6 -1
- package/src/layouts/blocks/HorizontalBlockComponent.ts +2 -2
- package/src/mWaterLoader.ts +1 -1
- package/src/maps/BufferLayer.ts +83 -60
- package/src/maps/BufferLayerDesign.ts +20 -14
- package/src/maps/BufferLayerDesignerComponent.tsx +309 -0
- package/src/maps/ChoroplethLayer.ts +40 -19
- package/src/maps/ChoroplethLayerDesign.ts +4 -2
- package/src/maps/ChoroplethLayerDesigner.tsx +4 -2
- package/src/maps/ClusterLayer.ts +4 -10
- package/src/maps/DetailLevelSelectComponent.ts +1 -1
- package/src/maps/DirectMapDataSource.ts +2 -1
- package/src/maps/EditPopupComponent.ts +7 -3
- package/src/maps/GridLayer.ts +4 -10
- package/src/maps/GridLayerDesigner.tsx +5 -3
- package/src/maps/HoverContent.tsx +40 -16
- package/src/maps/Layer.ts +28 -10
- package/src/maps/LayerFactory.ts +0 -8
- package/src/maps/LayerLegendComponent.ts +2 -4
- package/src/maps/LayerSwitcherComponent.tsx +6 -2
- package/src/maps/LeafletMapComponent.tsx +3 -1
- package/src/maps/LegendComponent.tsx +10 -1
- package/src/maps/MWaterServerLayer.ts +3 -3
- package/src/maps/MapComponent.ts +3 -3
- package/src/maps/MapDesign.ts +3 -0
- package/src/maps/MapDesignerComponent.tsx +165 -162
- package/src/maps/MapLayerViewDesignerComponent.ts +2 -2
- package/src/maps/MapUtils.ts +24 -0
- package/src/maps/MapViewComponent.tsx +11 -3
- package/src/maps/MarkersLayer.ts +44 -18
- package/src/maps/MarkersLayerDesign.ts +19 -16
- package/src/maps/PopupFilterJoinsUtils.ts +6 -2
- package/src/maps/RasterMapViewComponent.ts +9 -45
- package/src/maps/ServerMapDataSource.ts +2 -2
- package/src/maps/SwitchableTileUrlLayer.tsx +4 -10
- package/src/maps/TileUrlLayer.tsx +4 -10
- package/src/maps/VectorMapViewComponent.tsx +28 -55
- package/src/maps/maps.ts +3 -0
- package/src/quickfilter/Quickfilter.ts +3 -0
- package/src/quickfilter/QuickfiltersComponent.ts +13 -7
- package/src/quickfilter/QuickfiltersDesignComponent.tsx +127 -128
- package/src/richtext/ExprItemsHtmlConverter.ts +9 -5
- package/src/richtext/ExprItemsTranslator.ts +176 -0
- package/src/richtext/ItemsHtmlConverter.ts +33 -18
- package/src/wellknown.ts +33 -30
- package/src/widgets/ImageWidget.ts +10 -1
- package/src/widgets/ImageWidgetComponent.ts +3 -2
- package/src/widgets/{MapWidget.ts → MapWidget.tsx} +90 -101
- package/src/widgets/MarkdownWidget.ts +3 -0
- package/src/widgets/TOCWidget.tsx +281 -0
- package/src/widgets/Widget.ts +25 -5
- package/src/widgets/WidgetScopesViewComponent.ts +2 -1
- package/src/widgets/charts/Chart.ts +31 -12
- package/src/widgets/charts/ChartViewComponent.ts +13 -3
- package/src/widgets/charts/ChartWidget.ts +11 -1
- package/src/widgets/charts/ChartWidgetComponent.tsx +9 -1
- package/src/widgets/charts/calendar/CalendarChart.ts +29 -0
- package/src/widgets/charts/calendar/CalendarChartViewComponent.tsx +3 -1
- package/src/widgets/charts/imagemosaic/ImageMosaicChart.ts +9 -0
- package/src/widgets/charts/layered/LayeredChart.ts +71 -3
- package/src/widgets/charts/layered/LayeredChartCompiler.ts +2 -2
- package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +4 -2
- package/src/widgets/charts/layered/LayeredChartViewComponent.ts +10 -4
- package/src/widgets/charts/pivot/PivotChart.ts +73 -0
- package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +1 -1
- package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +6 -4
- package/src/widgets/charts/table/OrderingsComponent.tsx +2 -1
- package/src/widgets/charts/table/TableChart.ts +17 -0
- package/src/widgets/text/TextComponent.tsx +22 -12
- package/src/widgets/text/TextWidget.ts +9 -2
- package/src/widgets/text/TextWidgetComponent.tsx +16 -1
- package/src/widgets/text/TextWidgetDesign.ts +4 -7
- package/test/IdSelectionTests.ts +54 -0
- package/test/LayeredChartCompilerTests.ts +0 -2
- package/test/richtext/ExprItemsTranslatorTests.ts +144 -0
- package/test/wellknownTests.ts +144 -0
- package/src/datagrids/DatagridComponent.ts +0 -478
- package/src/datagrids/DatagridViewComponent.ts +0 -464
- package/src/datagrids/EditExprCellComponent.tsx +0 -305
- package/src/datagrids/README.md +0 -3
- package/src/maps/BufferLayerDesignerComponent.ts +0 -311
- package/src/widgets/TOCWidget.ts +0 -326
- package/test/LegoLayoutEngineTests.ts +0 -69
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import _ from "lodash"
|
|
2
2
|
import React from "react"
|
|
3
|
-
|
|
4
|
-
import
|
|
3
|
+
import uuid from "uuid"
|
|
4
|
+
import { produce } from "immer"
|
|
5
5
|
import { ExprComponent } from "@mwater/expressions-ui"
|
|
6
|
-
import { DataSource, ExprUtils, Schema } from "@mwater/expressions"
|
|
6
|
+
import { DataSource, Expr, ExprUtils, FieldExpr, Schema } from "@mwater/expressions"
|
|
7
7
|
import * as ui from "@mwater/react-library/lib/bootstrap"
|
|
8
8
|
import { ListEditorComponent } from "@mwater/react-library/lib/ListEditorComponent"
|
|
9
9
|
import { Quickfilter } from "./Quickfilter"
|
|
@@ -21,21 +21,29 @@ export interface QuickfiltersDesignComponentProps {
|
|
|
21
21
|
|
|
22
22
|
// Displays quick filters and allows their value to be modified
|
|
23
23
|
export default class QuickfiltersDesignComponent extends React.Component<QuickfiltersDesignComponentProps> {
|
|
24
|
-
handleDesignChange = (design:
|
|
25
|
-
|
|
24
|
+
handleDesignChange = (design: Quickfilter[]) => {
|
|
25
|
+
// Use immer produce to create immutable update
|
|
26
|
+
const newDesign = produce(design, draft => {
|
|
27
|
+
// Add UUID if missing
|
|
28
|
+
for (let i = 0; i < draft.length; i++) {
|
|
29
|
+
if (!draft[i].id) {
|
|
30
|
+
draft[i].id = uuid.v4()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
// Update merged flag, clearing if not mergeable
|
|
35
|
+
for (let i = 0; i < draft.length; i++) {
|
|
36
|
+
if (draft[i].merged && !this.isMergeable(draft, i)) {
|
|
37
|
+
draft[i].merged = false
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
|
-
}
|
|
40
|
+
})
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
this.props.onDesignChange(newDesign)
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
// Determine if quickfilter at index is mergeable with previous (same type, id table and enum values)
|
|
38
|
-
isMergeable(design:
|
|
46
|
+
isMergeable(design: Quickfilter[], index: number) {
|
|
39
47
|
if (index === 0) {
|
|
40
48
|
return false
|
|
41
49
|
}
|
|
@@ -73,54 +81,51 @@ export default class QuickfiltersDesignComponent extends React.Component<Quickfi
|
|
|
73
81
|
return true
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
renderQuickfilter = (item:
|
|
77
|
-
return
|
|
78
|
-
key
|
|
79
|
-
design
|
|
80
|
-
schema
|
|
81
|
-
dataSource
|
|
82
|
-
tables
|
|
83
|
-
mergeable
|
|
84
|
-
onChange
|
|
84
|
+
renderQuickfilter = (item: Quickfilter, index: number) => {
|
|
85
|
+
return <QuickfilterDesignComponent
|
|
86
|
+
key={index}
|
|
87
|
+
design={item}
|
|
88
|
+
schema={this.props.schema}
|
|
89
|
+
dataSource={this.props.dataSource}
|
|
90
|
+
tables={this.props.tables}
|
|
91
|
+
mergeable={this.isMergeable(this.props.design, index)}
|
|
92
|
+
onChange={(newItem: Quickfilter) => {
|
|
85
93
|
const design = this.props.design.slice()
|
|
86
94
|
design[index] = newItem
|
|
87
95
|
return this.handleDesignChange(design)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
})
|
|
96
|
+
}}
|
|
97
|
+
onRemove={this.handleRemove.bind(null, index)}
|
|
98
|
+
/>
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
handleAdd = () => {
|
|
95
102
|
// Add blank to end
|
|
96
103
|
const design = this.props.design.concat([{ expr: null }])
|
|
97
|
-
|
|
104
|
+
this.props.onDesignChange(design)
|
|
98
105
|
}
|
|
99
106
|
|
|
100
|
-
handleRemove = (index:
|
|
107
|
+
handleRemove = (index: number) => {
|
|
101
108
|
const design = this.props.design.slice()
|
|
102
109
|
design.splice(index, 1)
|
|
103
|
-
|
|
110
|
+
this.props.onDesignChange(design)
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
render() {
|
|
107
|
-
return
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
123
|
-
: undefined
|
|
114
|
+
return (
|
|
115
|
+
<div>
|
|
116
|
+
<ListEditorComponent
|
|
117
|
+
items={this.props.design}
|
|
118
|
+
onItemsChange={this.handleDesignChange}
|
|
119
|
+
renderItem={this.renderQuickfilter}
|
|
120
|
+
getReorderableKey={(item, index) => item.id || index}
|
|
121
|
+
/>
|
|
122
|
+
{this.props.tables.length > 0 ? (
|
|
123
|
+
<button type="button" className="btn btn-sm btn-link" onClick={this.handleAdd}>
|
|
124
|
+
<span className="fas fa-plus me-1" />
|
|
125
|
+
{T`Add Quick Filter`}
|
|
126
|
+
</button>
|
|
127
|
+
) : undefined}
|
|
128
|
+
</div>
|
|
124
129
|
)
|
|
125
130
|
}
|
|
126
131
|
}
|
|
@@ -138,7 +143,7 @@ interface QuickfilterDesignComponentProps {
|
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
interface QuickfilterDesignComponentState {
|
|
141
|
-
table:
|
|
146
|
+
table: string
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
/** Single quickfilter design component */
|
|
@@ -146,16 +151,16 @@ class QuickfilterDesignComponent extends React.Component<
|
|
|
146
151
|
QuickfilterDesignComponentProps,
|
|
147
152
|
QuickfilterDesignComponentState
|
|
148
153
|
> {
|
|
149
|
-
constructor(props:
|
|
154
|
+
constructor(props: QuickfilterDesignComponentProps) {
|
|
150
155
|
super(props)
|
|
151
156
|
|
|
152
157
|
// Store table to allow selecting table first, then expression
|
|
153
158
|
this.state = {
|
|
154
|
-
table: props.design.expr?.table || props.tables[0]
|
|
159
|
+
table: (props.design.expr as FieldExpr)?.table || props.tables[0]
|
|
155
160
|
}
|
|
156
161
|
}
|
|
157
162
|
|
|
158
|
-
handleTableChange = (table:
|
|
163
|
+
handleTableChange = (table: string) => {
|
|
159
164
|
this.setState({ table })
|
|
160
165
|
const design = {
|
|
161
166
|
expr: null
|
|
@@ -163,95 +168,89 @@ class QuickfilterDesignComponent extends React.Component<
|
|
|
163
168
|
return this.props.onChange(design)
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
handleExprChange = (expr:
|
|
167
|
-
|
|
171
|
+
handleExprChange = (expr: Expr) => {
|
|
172
|
+
this.props.onChange(produce(this.props.design, draft => {
|
|
173
|
+
draft.expr = expr
|
|
174
|
+
}))
|
|
168
175
|
}
|
|
176
|
+
|
|
169
177
|
handleLabelChange = (ev: any) => {
|
|
170
|
-
|
|
178
|
+
this.props.onChange(produce(this.props.design, draft => {
|
|
179
|
+
draft.label = ev.target.value
|
|
180
|
+
}))
|
|
171
181
|
}
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
|
|
183
|
+
handleMergedChange = (merged: boolean) => {
|
|
184
|
+
this.props.onChange(produce(this.props.design, draft => {
|
|
185
|
+
draft.merged = merged
|
|
186
|
+
}))
|
|
174
187
|
}
|
|
175
|
-
|
|
176
|
-
|
|
188
|
+
|
|
189
|
+
handleMultiChange = (multi: boolean) => {
|
|
190
|
+
this.props.onChange(produce(this.props.design, draft => {
|
|
191
|
+
draft.multi = multi
|
|
192
|
+
}))
|
|
177
193
|
}
|
|
178
194
|
|
|
179
195
|
render() {
|
|
180
196
|
// Determine type of expression
|
|
181
197
|
const exprType = new ExprUtils(this.props.schema).getExprType(this.props.design.expr)
|
|
182
198
|
|
|
183
|
-
return
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
onChange: this.handleMergedChange
|
|
239
|
-
},
|
|
240
|
-
T`Merge with previous quickfilter `,
|
|
241
|
-
R("span", { className: "text-muted" }, T`- displays as one single control that filters both`)
|
|
242
|
-
)
|
|
243
|
-
: undefined,
|
|
244
|
-
|
|
245
|
-
["enum", "text", "enumset", "id[]", "text[]"].includes(exprType!)
|
|
246
|
-
? R(
|
|
247
|
-
ui.Checkbox,
|
|
248
|
-
{
|
|
249
|
-
value: this.props.design.multi,
|
|
250
|
-
onChange: this.handleMultiChange
|
|
251
|
-
},
|
|
252
|
-
T`Allow multiple selections`
|
|
253
|
-
)
|
|
254
|
-
: undefined
|
|
199
|
+
return (
|
|
200
|
+
<div>
|
|
201
|
+
<div className="mb-3 mt-1" key="table">
|
|
202
|
+
<label className="text-muted">{T`Data Source`}</label>
|
|
203
|
+
<ui.Select
|
|
204
|
+
value={this.state.table}
|
|
205
|
+
options={_.map(this.props.tables, (table) => ({
|
|
206
|
+
value: table,
|
|
207
|
+
label: ExprUtils.localizeString(this.props.schema.getTable(table)!.name)
|
|
208
|
+
}))}
|
|
209
|
+
onChange={this.handleTableChange}
|
|
210
|
+
nullLabel={T`Select...`}
|
|
211
|
+
/>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div className="mb-3" key="expr">
|
|
215
|
+
<label className="text-muted">{T`Filter By`}</label>
|
|
216
|
+
<div>
|
|
217
|
+
<ExprComponent
|
|
218
|
+
schema={this.props.schema}
|
|
219
|
+
dataSource={this.props.dataSource}
|
|
220
|
+
table={this.state.table}
|
|
221
|
+
value={this.props.design.expr}
|
|
222
|
+
onChange={this.handleExprChange}
|
|
223
|
+
types={["enum", "text", "enumset", "date", "datetime", "id[]", "text[]"]}
|
|
224
|
+
/>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
{this.props.design.expr ? (
|
|
229
|
+
<div className="mb-3" key="label">
|
|
230
|
+
<label className="text-muted">{T`Label`}</label>
|
|
231
|
+
<input
|
|
232
|
+
type="text"
|
|
233
|
+
className="form-control form-control-sm"
|
|
234
|
+
value={this.props.design.label || ""}
|
|
235
|
+
onChange={this.handleLabelChange}
|
|
236
|
+
placeholder={T`Optional Label`}
|
|
237
|
+
/>
|
|
238
|
+
</div>
|
|
239
|
+
) : undefined}
|
|
240
|
+
|
|
241
|
+
{this.props.mergeable ? (
|
|
242
|
+
<ui.Checkbox value={this.props.design.merged} onChange={this.handleMergedChange}>
|
|
243
|
+
{T`Merge with previous quickfilter `}
|
|
244
|
+
<span className="text-muted">{`- ${T`displays as one single control that filters both`}`}</span>
|
|
245
|
+
</ui.Checkbox>
|
|
246
|
+
) : undefined}
|
|
247
|
+
|
|
248
|
+
{["enum", "text", "enumset", "id[]", "text[]"].includes(exprType!) ? (
|
|
249
|
+
<ui.Checkbox value={this.props.design.multi} onChange={this.handleMultiChange}>
|
|
250
|
+
{T`Allow multiple selections`}
|
|
251
|
+
</ui.Checkbox>
|
|
252
|
+
) : undefined}
|
|
253
|
+
</div>
|
|
255
254
|
)
|
|
256
255
|
}
|
|
257
256
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import _ from "lodash"
|
|
2
|
-
import ItemsHtmlConverter, { HtmlItemBase } from "./ItemsHtmlConverter"
|
|
2
|
+
import ItemsHtmlConverter, { HtmlItem, HtmlItemBase } from "./ItemsHtmlConverter"
|
|
3
3
|
import { Expr, ExprUtils, Schema } from "@mwater/expressions"
|
|
4
4
|
import uuid from "uuid"
|
|
5
5
|
import { formatValue } from "../valueFormatter"
|
|
6
6
|
import { canFormatType } from "../valueFormatter"
|
|
7
7
|
|
|
8
|
+
/** Html item that is an expression */
|
|
8
9
|
export interface HtmlItemExpr extends HtmlItemBase {
|
|
9
10
|
type: "expr"
|
|
10
11
|
|
|
@@ -24,6 +25,9 @@ export interface HtmlItemExpr extends HtmlItemBase {
|
|
|
24
25
|
format?: string
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
/** Html item that is an expression or a normal item */
|
|
29
|
+
export type HtmlItemOrExpr = HtmlItem | HtmlItemExpr
|
|
30
|
+
|
|
27
31
|
/**
|
|
28
32
|
* ItemsHtmlConverter that supports embedded mwater expressions
|
|
29
33
|
* Converts items (JSON contents of rich text) to HTML and back to allow editing
|
|
@@ -66,7 +70,7 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
|
|
|
66
70
|
if (this.summarizeExprs) {
|
|
67
71
|
text = new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale)
|
|
68
72
|
if (text.length > 30) {
|
|
69
|
-
text = text.substr(0, 30) +
|
|
73
|
+
text = text.substr(0, 30) + `...`
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
exprHtml = _.escape(text)
|
|
@@ -88,7 +92,7 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
|
|
|
88
92
|
|
|
89
93
|
exprHtml = _.escape(text)
|
|
90
94
|
} else {
|
|
91
|
-
exprHtml = `<span style="color: #DDD">${
|
|
95
|
+
exprHtml = `<span style="color: #DDD">${`---`}</span>`
|
|
92
96
|
}
|
|
93
97
|
} else {
|
|
94
98
|
// Placeholder
|
|
@@ -97,14 +101,14 @@ export default class ExprItemsHtmlConverter extends ItemsHtmlConverter {
|
|
|
97
101
|
|
|
98
102
|
// Add label
|
|
99
103
|
if (exprItem.includeLabel) {
|
|
100
|
-
const label = exprItem.labelText || new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale) +
|
|
104
|
+
const label = exprItem.labelText || new ExprUtils(this.schema).summarizeExpr(exprItem.expr, this.locale) + `:\u00A0`
|
|
101
105
|
exprHtml = `<span class="text-muted">${_.escape(label)}</span>` + exprHtml
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
if (this.designMode) {
|
|
105
109
|
html +=
|
|
106
110
|
`\u2060<span data-embed="${_.escape(JSON.stringify(item))}" class="mwater-visualization-text-widget-expr">` +
|
|
107
|
-
(exprHtml ||
|
|
111
|
+
(exprHtml || `\u00A0`) +
|
|
108
112
|
`</span>\u2060`
|
|
109
113
|
} else {
|
|
110
114
|
// View mode
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import _ from "lodash"
|
|
2
|
+
import { HtmlItemExpr, HtmlItemOrExpr } from "./ExprItemsHtmlConverter"
|
|
3
|
+
import { produce } from "immer"
|
|
4
|
+
import ItemsHtmlConverter, { HtmlItem, HtmlItemBase, HtmlItemElement } from "./ItemsHtmlConverter"
|
|
5
|
+
|
|
6
|
+
/** Gets all unique strings from html items */
|
|
7
|
+
export function getHtmlItemsStrings(items: HtmlItemOrExpr[]): string[] {
|
|
8
|
+
const strings = new Set<string>()
|
|
9
|
+
|
|
10
|
+
// Create collector function that just saves strings and returns them unchanged
|
|
11
|
+
const collectStrings = (str: string) => {
|
|
12
|
+
// Only collect non-empty strings
|
|
13
|
+
if (str) {
|
|
14
|
+
strings.add(str)
|
|
15
|
+
}
|
|
16
|
+
return str
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Use existing translation function but with collector
|
|
20
|
+
translateHtmlItems(items, collectStrings)
|
|
21
|
+
|
|
22
|
+
return Array.from(strings)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Translates items in an html items list with expressions */
|
|
26
|
+
export function translateHtmlItems(items: HtmlItemOrExpr[], translate: (input: string) => string): HtmlItemOrExpr[] {
|
|
27
|
+
return produce(items, draft => {
|
|
28
|
+
function translateItems(itemList: HtmlItemOrExpr[]) {
|
|
29
|
+
// Accumulate simple items
|
|
30
|
+
let simpleItems: HtmlItemOrExpr[] = []
|
|
31
|
+
let simpleItemStartIndex: number | null = null
|
|
32
|
+
|
|
33
|
+
/** Process accumulated simple nodes which are simple inline elements */
|
|
34
|
+
function processSimpleNodes() {
|
|
35
|
+
if (simpleItems.length === 0) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Create html string with {0}, {1}, etc. for expressions and html for other items
|
|
40
|
+
const expressions: HtmlItemExpr[] = []
|
|
41
|
+
|
|
42
|
+
const converter = new TranslationItemsHtmlConverter(item => {
|
|
43
|
+
if (item.type === "expr") {
|
|
44
|
+
const expr = item as HtmlItemExpr
|
|
45
|
+
if (expr.labelText) {
|
|
46
|
+
expr.labelText = translate(expr.labelText)
|
|
47
|
+
}
|
|
48
|
+
expressions.push(expr)
|
|
49
|
+
return `{${expressions.length - 1}}`
|
|
50
|
+
}
|
|
51
|
+
return ""
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Convert items to html which has the side effect of translating expressions
|
|
55
|
+
let html = converter.convertItemsToHtml(simpleItems)
|
|
56
|
+
|
|
57
|
+
// If there was no text, do nothing except translate expressions
|
|
58
|
+
if (!simpleItems.some(doesItemContainText)) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Remove leading and trailing whitespace from the HTML
|
|
63
|
+
const leftWhitespace = html.slice(0, html.length - html.trimStart().length)
|
|
64
|
+
const rightWhitespace = html.slice(html.trimEnd().length)
|
|
65
|
+
html = html.trim()
|
|
66
|
+
|
|
67
|
+
if (!html) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let translatedHtml = leftWhitespace + translate(html) + rightWhitespace
|
|
72
|
+
|
|
73
|
+
// Parse translatedHtml into items by first replacing {0}, {1}, etc. with html that can be converted to items
|
|
74
|
+
for (let i = 0; i < expressions.length; i++) {
|
|
75
|
+
const expr = expressions[i]
|
|
76
|
+
translatedHtml = translatedHtml.replace(new RegExp(`\\{${i}\\}`, "g"), `<span data-embed="${_.escape(JSON.stringify(expr))}"></span>`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Wrap in a div to prevent whitespace from being trimmed.
|
|
80
|
+
const translatedItems = (converter.convertElemToItems(new DOMParser().parseFromString("<div>" + translatedHtml + "</div>", "text/html").body.firstChild as HTMLElement))
|
|
81
|
+
|
|
82
|
+
// Replace the simple items with the translated items
|
|
83
|
+
itemList.splice(simpleItemStartIndex!, simpleItems.length, ...translatedItems)
|
|
84
|
+
|
|
85
|
+
simpleItems = []
|
|
86
|
+
simpleItemStartIndex = null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < itemList.length; i++) {
|
|
90
|
+
const item = itemList[i]
|
|
91
|
+
|
|
92
|
+
// If the child is a simple node, add it to the list
|
|
93
|
+
if (isItemSimple(item)) {
|
|
94
|
+
simpleItems.push(item)
|
|
95
|
+
if (simpleItemStartIndex == null) {
|
|
96
|
+
simpleItemStartIndex = i
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// If we have gathered simple nodes, we need to return/replace them
|
|
100
|
+
processSimpleNodes()
|
|
101
|
+
simpleItemStartIndex = null
|
|
102
|
+
simpleItems = []
|
|
103
|
+
|
|
104
|
+
// Handle the current node
|
|
105
|
+
if (typeof item !== "string" && item.type === "element" && item.items) {
|
|
106
|
+
translateItems(item.items)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (simpleItems.length > 0) {
|
|
112
|
+
processSimpleNodes()
|
|
113
|
+
simpleItemStartIndex = null
|
|
114
|
+
simpleItems = []
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
translateItems(draft)
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** ItemsHtmlConverter that has a callback for handling special items */
|
|
123
|
+
class TranslationItemsHtmlConverter extends ItemsHtmlConverter {
|
|
124
|
+
handleSpecialItem: (item: HtmlItemBase) => string
|
|
125
|
+
|
|
126
|
+
constructor(handleSpecialItem: (item: HtmlItemBase) => string) {
|
|
127
|
+
super()
|
|
128
|
+
this.handleSpecialItem = handleSpecialItem
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
convertSpecialItemToHtml(item: HtmlItemBase) {
|
|
132
|
+
return this.handleSpecialItem(item)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check if an html item is simple.
|
|
138
|
+
* A node is simple if it is:
|
|
139
|
+
* - a string
|
|
140
|
+
* - a tag that is a "b", "i", "u", "a", "strong", "em" tag with no children or only simple children
|
|
141
|
+
* Only sequences of simple nodes are exported to translation entries as HTML.
|
|
142
|
+
*/
|
|
143
|
+
function isItemSimple(node: HtmlItemOrExpr): boolean {
|
|
144
|
+
if (typeof node === "string") {
|
|
145
|
+
return true
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (node.type === "expr") {
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (node.type === "element") {
|
|
153
|
+
const element = node as HtmlItemElement
|
|
154
|
+
|
|
155
|
+
if (["b", "i", "u", "a", "strong", "em"].indexOf(element.tag) === -1) {
|
|
156
|
+
return false
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (element.items || []).every(child => isItemSimple(child))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Determines if an item contains any non-empty text strings */
|
|
166
|
+
function doesItemContainText(item: HtmlItemOrExpr): boolean {
|
|
167
|
+
if (typeof item === "string") {
|
|
168
|
+
return item.trim().length > 0
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (item.type === "element") {
|
|
172
|
+
return (item.items || []).some(child => doesItemContainText(child))
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return false
|
|
176
|
+
}
|