@mwater/visualization 5.4.1 → 5.4.2
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 +6 -0
- package/lib/dashboards/DashboardComponent.js +44 -12
- 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/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/QuickfiltersComponent.d.ts +2 -0
- package/lib/quickfilter/QuickfiltersComponent.js +9 -7
- package/lib/quickfilter/QuickfiltersDesignComponent.d.ts +1 -1
- package/lib/quickfilter/QuickfiltersDesignComponent.js +19 -35
- 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 +79 -14
- 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/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/QuickfiltersComponent.ts +13 -7
- package/src/quickfilter/QuickfiltersDesignComponent.tsx +56 -74
- 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
|
@@ -173,9 +173,12 @@ export default class MWaterResponsesFilterComponent extends React.Component<MWat
|
|
|
173
173
|
return R(
|
|
174
174
|
ui.Radio,
|
|
175
175
|
{ key: column.id, value: siteColumnId, radioValue: column.id, onChange: this.handleSiteChange },
|
|
176
|
-
T`Show only the latest response for each
|
|
176
|
+
T`Show only the latest response for each`,
|
|
177
|
+
" ",
|
|
177
178
|
R("i", null, `${ExprUtils.localizeString(this.props.schema.getTable(column.join.toTable)?.name)}`),
|
|
178
|
-
|
|
179
|
+
" ",
|
|
180
|
+
T`in the question`,
|
|
181
|
+
" ",
|
|
179
182
|
R("i", null, `'${ExprUtils.localizeString(column.name)}'`)
|
|
180
183
|
)
|
|
181
184
|
})
|
|
@@ -6,7 +6,7 @@ import { ExprUtils, Schema } from "@mwater/expressions"
|
|
|
6
6
|
import MWaterResponsesFilterComponent from "./MWaterResponsesFilterComponent"
|
|
7
7
|
import ModalPopupComponent from "@mwater/react-library/lib/ModalPopupComponent"
|
|
8
8
|
import MWaterCompleteTableSelectComponent from "./MWaterCompleteTableSelectComponent"
|
|
9
|
-
import { ActiveTablesContext
|
|
9
|
+
import { ActiveTablesContext } from "@mwater/expressions-ui"
|
|
10
10
|
|
|
11
11
|
export interface MWaterTableSelectComponentProps {
|
|
12
12
|
/** Url to hit api */
|
|
@@ -35,8 +35,6 @@ export default class MWaterTableSelectComponent extends React.Component<
|
|
|
35
35
|
MWaterTableSelectComponentProps,
|
|
36
36
|
MWaterTableSelectComponentState
|
|
37
37
|
> {
|
|
38
|
-
static contextType = LocaleContext
|
|
39
|
-
|
|
40
38
|
toggleEdit: any
|
|
41
39
|
|
|
42
40
|
constructor(props: MWaterTableSelectComponentProps) {
|
|
@@ -136,7 +134,7 @@ export default class MWaterTableSelectComponent extends React.Component<
|
|
|
136
134
|
},
|
|
137
135
|
forceOpen: !this.props.table, // Must have table
|
|
138
136
|
label: this.props.table
|
|
139
|
-
? ExprUtils.localizeString(this.props.schema.getTable(this.props.table)?.name,
|
|
137
|
+
? ExprUtils.localizeString(this.props.schema.getTable(this.props.table)?.name, T.locale)
|
|
140
138
|
: "",
|
|
141
139
|
editor,
|
|
142
140
|
onRemove: () => {
|
|
@@ -184,8 +182,6 @@ class EditModeTableSelectComponent extends React.Component<
|
|
|
184
182
|
EditModeTableSelectComponentProps,
|
|
185
183
|
EditModeTableSelectComponentState
|
|
186
184
|
> {
|
|
187
|
-
static contextType = LocaleContext
|
|
188
|
-
|
|
189
185
|
constructor(props: any) {
|
|
190
186
|
super(props)
|
|
191
187
|
|
|
@@ -235,7 +231,7 @@ class EditModeTableSelectComponent extends React.Component<
|
|
|
235
231
|
|
|
236
232
|
// Sort by name
|
|
237
233
|
tables = _.sortBy(tables, (tableId) =>
|
|
238
|
-
ExprUtils.localizeString(this.props.schema.getTable(tableId)!.name,
|
|
234
|
+
ExprUtils.localizeString(this.props.schema.getTable(tableId)!.name, T.locale)
|
|
239
235
|
)
|
|
240
236
|
|
|
241
237
|
return tables
|
|
@@ -277,8 +273,8 @@ class EditModeTableSelectComponent extends React.Component<
|
|
|
277
273
|
<OptionListComponent items={this.getTableShortlist(activeTables).map((tableId) => {
|
|
278
274
|
const table = this.props.schema.getTable(tableId)!
|
|
279
275
|
return {
|
|
280
|
-
name: ExprUtils.localizeString(table.name,
|
|
281
|
-
desc: ExprUtils.localizeString(table.desc,
|
|
276
|
+
name: ExprUtils.localizeString(table.name, T.locale),
|
|
277
|
+
desc: ExprUtils.localizeString(table.desc, T.locale),
|
|
282
278
|
onClick: () => this.props.onChange(table.id)
|
|
283
279
|
}
|
|
284
280
|
})} />
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { LocalizedString, Locale } from "ez-localize/lib/utils"
|
|
2
|
+
|
|
3
|
+
/** Translates an array of strings from a source language to a target language using the mWater translation API.
|
|
4
|
+
* @param strings Array of strings to translate
|
|
5
|
+
* @param sourceLanguage Source language code (e.g. "en")
|
|
6
|
+
* @param targetLanguage Target language code to translate to
|
|
7
|
+
* @returns Promise that resolves to array of translated strings in same order as input
|
|
8
|
+
* @throws Error if translation fails
|
|
9
|
+
*/
|
|
10
|
+
export async function translateStrings(
|
|
11
|
+
strings: string[],
|
|
12
|
+
sourceLanguage: string,
|
|
13
|
+
targetLanguage: string
|
|
14
|
+
): Promise<string[]> {
|
|
15
|
+
// Call translation API
|
|
16
|
+
const response = await fetch(
|
|
17
|
+
`https://api.mwater.co/v3/translate?source_language=${sourceLanguage}&target_language=${targetLanguage}`,
|
|
18
|
+
{
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json"
|
|
22
|
+
},
|
|
23
|
+
body: JSON.stringify({
|
|
24
|
+
phrases: strings
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error("Translation failed")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const result = await response.json()
|
|
34
|
+
return result.phrases
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Ensures that all LocalizedString objects have translations for all specified locales.
|
|
38
|
+
* Only translates missing translations, preserving existing ones and base strings.
|
|
39
|
+
* Each string's _base property is used as the source language for translations.
|
|
40
|
+
* @param strings Array of LocalizedString objects to ensure are fully translated
|
|
41
|
+
* @param locales Array of language codes specifying which languages to ensure exist
|
|
42
|
+
* @param baseLanguage Language code of the _base strings (e.g. "en", "fr", etc)
|
|
43
|
+
* @returns Promise that resolves to array of fully translated LocalizedString objects
|
|
44
|
+
*/
|
|
45
|
+
export async function translateLocalizedStrings(
|
|
46
|
+
strings: LocalizedString[],
|
|
47
|
+
locales: string[],
|
|
48
|
+
baseLanguage: string
|
|
49
|
+
): Promise<LocalizedString[]> {
|
|
50
|
+
// Create copy of strings to modify
|
|
51
|
+
const translatedStrings = strings.map(str => ({ ...str }))
|
|
52
|
+
|
|
53
|
+
// For each locale
|
|
54
|
+
for (const locale of locales) {
|
|
55
|
+
// Skip if it's the base language
|
|
56
|
+
if (locale === baseLanguage) {
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Group strings by their current source language
|
|
61
|
+
// Start with base language strings
|
|
62
|
+
const stringsBySourceLang = new Map<string, { str: LocalizedString; index: number }[]>()
|
|
63
|
+
|
|
64
|
+
translatedStrings.forEach((str, index) => {
|
|
65
|
+
// Skip if translation already exists
|
|
66
|
+
if (str[locale]) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Add to list to translate from base language
|
|
71
|
+
if (!stringsBySourceLang.has(baseLanguage)) {
|
|
72
|
+
stringsBySourceLang.set(baseLanguage, [])
|
|
73
|
+
}
|
|
74
|
+
stringsBySourceLang.get(baseLanguage)!.push({ str, index })
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// Translate each group
|
|
78
|
+
for (const [sourceLang, stringsToTranslate] of stringsBySourceLang.entries()) {
|
|
79
|
+
try {
|
|
80
|
+
// Get source strings
|
|
81
|
+
const sourceStrings = stringsToTranslate.map(item => item.str[item.str._base])
|
|
82
|
+
|
|
83
|
+
// Translate all strings at once
|
|
84
|
+
const translations = await translateStrings(sourceStrings, sourceLang, locale)
|
|
85
|
+
|
|
86
|
+
// Add translations back to strings
|
|
87
|
+
translations.forEach((translation, i) => {
|
|
88
|
+
translatedStrings[stringsToTranslate[i].index][locale] = translation
|
|
89
|
+
})
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(`Failed to translate from ${sourceLang} to ${locale}:`, error)
|
|
92
|
+
throw error
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return translatedStrings
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Returns true if the given language code can be automatically translated. */
|
|
101
|
+
export function canAutoTranslate(languageCode: string) {
|
|
102
|
+
const languageCodes = [
|
|
103
|
+
"en", // English
|
|
104
|
+
"fr", // French
|
|
105
|
+
"es", // Spanish
|
|
106
|
+
"pt", // Portuguese
|
|
107
|
+
"sw", // Swahili
|
|
108
|
+
"id", // Indonesian
|
|
109
|
+
"hi", // Hindi
|
|
110
|
+
"ne", // Nepali
|
|
111
|
+
"rw", // Kinyarwanda
|
|
112
|
+
"sd", // Sindhi
|
|
113
|
+
"tet", // Tetum
|
|
114
|
+
"ur", // Urdu
|
|
115
|
+
"ja", // Japanese
|
|
116
|
+
"de", // German
|
|
117
|
+
"it", // Italian
|
|
118
|
+
"su", // Sundanese
|
|
119
|
+
"ar", // Arabic
|
|
120
|
+
"vi", // Vietnamese
|
|
121
|
+
"mg", // Malagasy
|
|
122
|
+
"tl", // Tagalog/Filipino
|
|
123
|
+
"ht", // Haitian Creole
|
|
124
|
+
"fi", // Finnish
|
|
125
|
+
"bn", // Bangla
|
|
126
|
+
"my", // Burmese
|
|
127
|
+
"km", // Khmer
|
|
128
|
+
"so", // Somali
|
|
129
|
+
"jv", // Javanese
|
|
130
|
+
"ko", // Korean
|
|
131
|
+
"zh", // Chinese
|
|
132
|
+
"ru", // Russian
|
|
133
|
+
"tr", // Turkish
|
|
134
|
+
"nl", // Dutch
|
|
135
|
+
"pl", // Polish
|
|
136
|
+
"hu", // Hungarian
|
|
137
|
+
"cs", // Czech
|
|
138
|
+
"sk" // Slovak
|
|
139
|
+
]
|
|
140
|
+
return languageCodes.includes(languageCode)
|
|
141
|
+
}
|
package/src/axes/AxisBuilder.ts
CHANGED
|
@@ -532,7 +532,7 @@ export default class AxisBuilder {
|
|
|
532
532
|
|
|
533
533
|
if (range.maxValue != null) {
|
|
534
534
|
if (label) {
|
|
535
|
-
label += T`
|
|
535
|
+
label += ` ${T`and`} `
|
|
536
536
|
}
|
|
537
537
|
if (range.maxOpen) {
|
|
538
538
|
label += `< ${range.maxValue}`
|
|
@@ -1024,7 +1024,7 @@ export default class AxisBuilder {
|
|
|
1024
1024
|
if (category) {
|
|
1025
1025
|
return this.formatCategory(axis, category)
|
|
1026
1026
|
} else {
|
|
1027
|
-
return
|
|
1027
|
+
return `???`
|
|
1028
1028
|
}
|
|
1029
1029
|
}).join(", ")
|
|
1030
1030
|
} else {
|
|
@@ -1032,7 +1032,7 @@ export default class AxisBuilder {
|
|
|
1032
1032
|
if (category) {
|
|
1033
1033
|
return this.formatCategory(axis, category)
|
|
1034
1034
|
} else {
|
|
1035
|
-
return
|
|
1035
|
+
return `???`
|
|
1036
1036
|
}
|
|
1037
1037
|
}
|
|
1038
1038
|
}
|
|
@@ -86,6 +86,11 @@ export default class AxisColorEditorComponent extends React.Component<
|
|
|
86
86
|
axisBuilder.isCategorical(this.props.axis)
|
|
87
87
|
)
|
|
88
88
|
colorMap = (this.props.axis.colorMap || []).concat(missingColorMap)
|
|
89
|
+
|
|
90
|
+
// If there are categories present, remove any color map values that are not in the categories
|
|
91
|
+
if (this.props.categories.length > 0) {
|
|
92
|
+
colorMap = _.filter(colorMap, (cm) => this.props.categories!.find((c) => c.value === cm.value))
|
|
93
|
+
}
|
|
89
94
|
} else {
|
|
90
95
|
// Keep existing
|
|
91
96
|
const existing = _.indexBy(this.props.axis.colorMap || [], "value")
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import _ from "lodash"
|
|
2
2
|
import React from "react"
|
|
3
|
-
const R = React.createElement
|
|
4
3
|
import uuid from "uuid"
|
|
5
4
|
import AsyncLoadComponent from "@mwater/react-library/lib/AsyncLoadComponent"
|
|
6
5
|
import { ExprComponent, LocaleContext } from "@mwater/expressions-ui"
|
|
@@ -16,7 +15,7 @@ import { injectTableAlias } from "@mwater/expressions"
|
|
|
16
15
|
import { getFormatOptions } from "../valueFormatter"
|
|
17
16
|
import { getDefaultFormat } from "../valueFormatter"
|
|
18
17
|
import { JsonQLFilter } from "../JsonQLFilter"
|
|
19
|
-
import { Axis, AxisXform, AxisXformRange } from "./Axis"
|
|
18
|
+
import { Axis, AxisCategory, AxisXform, AxisXformRange } from "./Axis"
|
|
20
19
|
import produce from "immer"
|
|
21
20
|
import { JsonQLSelectQuery } from "@mwater/jsonql"
|
|
22
21
|
|
|
@@ -54,7 +53,7 @@ export interface AxisComponentProps {
|
|
|
54
53
|
// Axis component that allows designing of an axis
|
|
55
54
|
export default class AxisComponent extends AsyncLoadComponent<
|
|
56
55
|
AxisComponentProps,
|
|
57
|
-
{ categories:
|
|
56
|
+
{ categories: AxisCategory[] | null; loading: boolean }
|
|
58
57
|
> {
|
|
59
58
|
static defaultProps = {
|
|
60
59
|
reorderable: false,
|
|
@@ -146,14 +145,14 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
146
145
|
valuesQuery.where = whereClauses[0]
|
|
147
146
|
}
|
|
148
147
|
|
|
149
|
-
|
|
148
|
+
props.dataSource.performQuery(valuesQuery, (error: any, rows: any) => {
|
|
150
149
|
if (error) {
|
|
151
150
|
return // Ignore errors
|
|
152
151
|
}
|
|
153
152
|
|
|
154
153
|
// Get categories (value + label)
|
|
155
154
|
categories = axisBuilder.getCategories(axis, _.pluck(rows, "val"))
|
|
156
|
-
|
|
155
|
+
callback({ categories })
|
|
157
156
|
})
|
|
158
157
|
}
|
|
159
158
|
|
|
@@ -254,37 +253,37 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
254
253
|
if (axis.xform && ["bin", "ranges", "floor"].includes(axis.xform.type)) {
|
|
255
254
|
let comp
|
|
256
255
|
if (axis.xform.type === "ranges") {
|
|
257
|
-
comp =
|
|
258
|
-
schema
|
|
259
|
-
expr
|
|
260
|
-
xform
|
|
261
|
-
onChange
|
|
262
|
-
|
|
256
|
+
comp = <RangesComponent
|
|
257
|
+
schema={this.props.schema}
|
|
258
|
+
expr={axis.expr}
|
|
259
|
+
xform={axis.xform}
|
|
260
|
+
onChange={this.handleXformChange}
|
|
261
|
+
/>
|
|
263
262
|
} else if (axis.xform.type === "bin") {
|
|
264
|
-
comp =
|
|
265
|
-
schema
|
|
266
|
-
dataSource
|
|
267
|
-
expr
|
|
268
|
-
xform
|
|
269
|
-
onChange
|
|
270
|
-
|
|
263
|
+
comp = <BinsComponent
|
|
264
|
+
schema={this.props.schema}
|
|
265
|
+
dataSource={this.props.dataSource}
|
|
266
|
+
expr={axis.expr}
|
|
267
|
+
xform={axis.xform}
|
|
268
|
+
onChange={this.handleXformChange}
|
|
269
|
+
/>
|
|
271
270
|
} else {
|
|
272
271
|
comp = null
|
|
273
272
|
}
|
|
274
273
|
|
|
275
|
-
return
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
274
|
+
return (
|
|
275
|
+
<div>
|
|
276
|
+
<ui.RadioToggleComponent
|
|
277
|
+
value={axis.xform ? axis.xform.type : null}
|
|
278
|
+
options={[
|
|
279
|
+
{ value: "bin", label: T`Equal Bins` },
|
|
280
|
+
{ value: "ranges", label: T`Custom Ranges` },
|
|
281
|
+
{ value: "floor", label: T`Whole Numbers` }
|
|
282
|
+
]}
|
|
283
|
+
onChange={this.handleXformTypeChange}
|
|
284
|
+
/>
|
|
285
|
+
{comp}
|
|
286
|
+
</div>
|
|
288
287
|
)
|
|
289
288
|
}
|
|
290
289
|
|
|
@@ -293,9 +292,9 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
293
292
|
|
|
294
293
|
switch (exprType) {
|
|
295
294
|
case "date":
|
|
296
|
-
return
|
|
297
|
-
value
|
|
298
|
-
options
|
|
295
|
+
return <ui.RadioToggleComponent
|
|
296
|
+
value={axis.xform ? axis.xform.type : null}
|
|
297
|
+
options={[
|
|
299
298
|
{ value: null, label: T`Exact Date` },
|
|
300
299
|
{ value: "year", label: T`Year` },
|
|
301
300
|
{ value: "yearmonth", label: T`Year/Month` },
|
|
@@ -303,13 +302,13 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
303
302
|
{ value: "week", label: T`Week` },
|
|
304
303
|
{ value: "yearweek", label: T`Year/Week` },
|
|
305
304
|
{ value: "yearquarter", label: T`Year/Quarter` }
|
|
306
|
-
]
|
|
307
|
-
onChange
|
|
308
|
-
|
|
305
|
+
]}
|
|
306
|
+
onChange={this.handleXformTypeChange}
|
|
307
|
+
/>
|
|
309
308
|
case "datetime":
|
|
310
|
-
return
|
|
311
|
-
value
|
|
312
|
-
options
|
|
309
|
+
return <ui.RadioToggleComponent
|
|
310
|
+
value={axis.xform ? axis.xform.type : null}
|
|
311
|
+
options={[
|
|
313
312
|
{ value: "date", label: T`Date` },
|
|
314
313
|
{ value: "year", label: T`Year` },
|
|
315
314
|
{ value: "yearmonth", label: T`Year/Month` },
|
|
@@ -317,9 +316,9 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
317
316
|
{ value: "week", label: T`Week` },
|
|
318
317
|
{ value: "yearweek", label: T`Year/Week` },
|
|
319
318
|
{ value: "yearquarter", label: T`Year/Quarter` }
|
|
320
|
-
]
|
|
321
|
-
onChange
|
|
322
|
-
|
|
319
|
+
]}
|
|
320
|
+
onChange={this.handleXformTypeChange}
|
|
321
|
+
/>
|
|
323
322
|
}
|
|
324
323
|
return null
|
|
325
324
|
}
|
|
@@ -329,20 +328,22 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
329
328
|
return null
|
|
330
329
|
}
|
|
331
330
|
|
|
332
|
-
return
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
331
|
+
return (
|
|
332
|
+
<>
|
|
333
|
+
<br/>
|
|
334
|
+
<AxisColorEditorComponent
|
|
335
|
+
schema={this.props.schema}
|
|
336
|
+
axis={axis}
|
|
337
|
+
categories={this.state.categories ?? undefined}
|
|
338
|
+
onChange={this.props.onChange}
|
|
339
|
+
reorderable={this.props.reorderable}
|
|
340
|
+
defaultColor={this.props.defaultColor ?? undefined}
|
|
341
|
+
allowExcludedValues={this.props.allowExcludedValues}
|
|
342
|
+
autosetColors={this.props.autosetColors}
|
|
343
|
+
initiallyExpanded={this.props.collapseCategories !== true}
|
|
344
|
+
/>
|
|
345
|
+
</>
|
|
346
|
+
)
|
|
346
347
|
}
|
|
347
348
|
|
|
348
349
|
renderExcludedValues(axis: any) {
|
|
@@ -356,19 +357,21 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
356
357
|
return null
|
|
357
358
|
}
|
|
358
359
|
|
|
359
|
-
return
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
360
|
+
return (
|
|
361
|
+
<>
|
|
362
|
+
<br/>
|
|
363
|
+
<CategoryMapComponent
|
|
364
|
+
schema={this.props.schema}
|
|
365
|
+
axis={axis}
|
|
366
|
+
onChange={this.props.onChange}
|
|
367
|
+
categories={this.state.categories}
|
|
368
|
+
reorderable={false}
|
|
369
|
+
showColorMap={false}
|
|
370
|
+
allowExcludedValues={true}
|
|
371
|
+
initiallyExpanded={this.props.collapseCategories !== true}
|
|
372
|
+
/>
|
|
373
|
+
</>
|
|
374
|
+
)
|
|
372
375
|
}
|
|
373
376
|
|
|
374
377
|
renderFormat(axis: any) {
|
|
@@ -384,21 +387,21 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
384
387
|
return null
|
|
385
388
|
}
|
|
386
389
|
|
|
387
|
-
return
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
390
|
+
return (
|
|
391
|
+
<div className="mb-3">
|
|
392
|
+
<label className="text-muted">{T`Format`}</label>
|
|
393
|
+
{": "}
|
|
394
|
+
<select
|
|
395
|
+
value={axis.format != null ? axis.format : getDefaultFormat(valueType)}
|
|
396
|
+
className="form-select"
|
|
397
|
+
style={{ width: "auto", display: "inline-block" }}
|
|
398
|
+
onChange={this.handleFormatChange}
|
|
399
|
+
>
|
|
400
|
+
{_.map(formats, (format) => (
|
|
401
|
+
<option key={format.value} value={format.value}>{format.label}</option>
|
|
402
|
+
))}
|
|
403
|
+
</select>
|
|
404
|
+
</div>
|
|
402
405
|
)
|
|
403
406
|
}
|
|
404
407
|
|
|
@@ -422,27 +425,24 @@ export default class AxisComponent extends AsyncLoadComponent<
|
|
|
422
425
|
break
|
|
423
426
|
}
|
|
424
427
|
|
|
425
|
-
return
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
this.props.showFormat ? this.renderFormat(axis) : undefined,
|
|
444
|
-
this.renderColorMap(axis),
|
|
445
|
-
this.renderExcludedValues(axis)
|
|
428
|
+
return (
|
|
429
|
+
<div>
|
|
430
|
+
<div>
|
|
431
|
+
<ExprComponent
|
|
432
|
+
schema={this.props.schema}
|
|
433
|
+
dataSource={this.props.dataSource}
|
|
434
|
+
table={this.props.table}
|
|
435
|
+
types={axisBuilder.getExprTypes(this.props.types)}
|
|
436
|
+
onChange={this.handleExprChange}
|
|
437
|
+
value={this.props.value ? this.props.value.expr : null}
|
|
438
|
+
aggrStatuses={aggrStatuses}
|
|
439
|
+
/>
|
|
440
|
+
</div>
|
|
441
|
+
{this.renderXform(axis)}
|
|
442
|
+
{this.props.showFormat ? this.renderFormat(axis) : undefined}
|
|
443
|
+
{this.renderColorMap(axis)}
|
|
444
|
+
{this.renderExcludedValues(axis)}
|
|
445
|
+
</div>
|
|
446
446
|
)
|
|
447
447
|
}
|
|
448
448
|
}
|
|
@@ -44,7 +44,7 @@ export default class CategoryMapComponent extends React.Component<
|
|
|
44
44
|
|
|
45
45
|
handleReorder = (map: any) => {
|
|
46
46
|
const order = _.pluck(map, "value")
|
|
47
|
-
|
|
47
|
+
this.props.onChange(update(this.props.axis, { drawOrder: { $set: order } }))
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
handleColorChange = (value: any, color: any) => {
|
|
@@ -56,7 +56,7 @@ export default class CategoryMapComponent extends React.Component<
|
|
|
56
56
|
colorMap.push({ value, color })
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
this.props.onChange(update(this.props.axis, { colorMap: { $set: colorMap } }))
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
handleExcludeChange = (value: any, ev: any) => {
|
|
@@ -67,7 +67,7 @@ export default class CategoryMapComponent extends React.Component<
|
|
|
67
67
|
excludedValues = _.union(this.props.axis.excludedValues || [], [value])
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
this.props.onChange(update(this.props.axis, { excludedValues: { $set: excludedValues } }))
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Gets the current color value if known
|
|
@@ -82,7 +82,7 @@ export default class CategoryMapComponent extends React.Component<
|
|
|
82
82
|
handleNullLabelChange = (e: any) => {
|
|
83
83
|
const name = prompt(T`Enter label for none value`, this.props.axis.nullLabel || T`None`)
|
|
84
84
|
if (name) {
|
|
85
|
-
|
|
85
|
+
this.props.onChange(update(this.props.axis, { nullLabel: { $set: name } }))
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -95,7 +95,8 @@ export default class RangesComponent extends React.Component<RangesComponentProp
|
|
|
95
95
|
"button",
|
|
96
96
|
{ className: "btn btn-link btn-sm", type: "button", onClick: this.handleAddRange },
|
|
97
97
|
R("span", { className: "fas fa-plus" }),
|
|
98
|
-
|
|
98
|
+
" ",
|
|
99
|
+
T`Add Range`
|
|
99
100
|
)
|
|
100
101
|
)
|
|
101
102
|
}
|
|
@@ -145,7 +146,7 @@ class RangeComponent extends React.Component<RangeComponentProps> {
|
|
|
145
146
|
|
|
146
147
|
if (this.props.range.maxValue != null) {
|
|
147
148
|
if (placeholder) {
|
|
148
|
-
placeholder += T`
|
|
149
|
+
placeholder += ` ${T`and`} `
|
|
149
150
|
}
|
|
150
151
|
if (this.props.range.maxOpen) {
|
|
151
152
|
placeholder += `< ${this.props.range.maxValue}`
|