@mwater/visualization 5.4.4 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.storybook/head.html +0 -1
  2. package/lib/MWaterContextComponent.js +1 -1
  3. package/lib/MWaterLoaderComponent.d.ts +2 -2
  4. package/lib/dashboards/DashboardComponent.js +2 -1
  5. package/lib/dashboards/LayoutOptionsComponent.js +18 -11
  6. package/lib/dashboards/ServerDashboardDataSource.d.ts +10 -1
  7. package/lib/dashboards/ServerDashboardDataSource.js +29 -0
  8. package/lib/dashboards/layoutOptions.d.ts +5 -1
  9. package/lib/datagrids/DatagridComponent.js +1 -1
  10. package/lib/datagrids/ExprCellComponent.d.ts +1 -0
  11. package/lib/datagrids/ExprCellComponent.js +22 -20
  12. package/lib/maps/BufferLayer.d.ts +18 -0
  13. package/lib/maps/BufferLayer.js +24 -14
  14. package/lib/maps/ChoroplethLayer.d.ts +18 -0
  15. package/lib/maps/ChoroplethLayer.js +34 -25
  16. package/lib/maps/ChoroplethLayerDesign.d.ts +3 -2
  17. package/lib/maps/ChoroplethLayerDesigner.d.ts +11 -1
  18. package/lib/maps/DirectMapDataSource.js +17 -0
  19. package/lib/maps/EditHoverOver.d.ts +1 -1
  20. package/lib/maps/EditHoverOver.js +62 -33
  21. package/lib/maps/HoverContent.d.ts +10 -5
  22. package/lib/maps/HoverContent.js +6 -35
  23. package/lib/maps/Layer.d.ts +37 -0
  24. package/lib/maps/Layer.js +30 -4
  25. package/lib/maps/MWaterServerLayer.d.ts +2 -2
  26. package/lib/maps/MWaterServerLayer.js +6 -6
  27. package/lib/maps/MapLayerDataSource.d.ts +9 -0
  28. package/lib/maps/MapUtils.d.ts +19 -1
  29. package/lib/maps/MapUtils.js +71 -1
  30. package/lib/maps/MarkersLayer.d.ts +18 -0
  31. package/lib/maps/MarkersLayer.js +24 -24
  32. package/lib/maps/MarkersLayerDesignerComponent.d.ts +14 -1
  33. package/lib/maps/RasterMapViewComponent.js +1 -1
  34. package/lib/maps/ServerMapDataSource.d.ts +9 -0
  35. package/lib/maps/ServerMapDataSource.js +29 -0
  36. package/lib/maps/VectorMapViewComponent.js +6 -6
  37. package/lib/maps/maps.d.ts +4 -2
  38. package/lib/mwater_table_selection/FormsListComponent.d.ts +33 -0
  39. package/lib/mwater_table_selection/FormsListComponent.js +141 -0
  40. package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +47 -0
  41. package/lib/mwater_table_selection/IndicatorsListComponent.js +182 -0
  42. package/lib/mwater_table_selection/IssuesListComponent.d.ts +29 -0
  43. package/lib/mwater_table_selection/IssuesListComponent.js +123 -0
  44. package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.d.ts +20 -0
  45. package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.js +157 -0
  46. package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.d.ts +17 -0
  47. package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.js +79 -0
  48. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +37 -0
  49. package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +275 -0
  50. package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.d.ts +17 -0
  51. package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.js +94 -0
  52. package/lib/mwater_table_selection/MWaterMetricsTableListComponent.d.ts +17 -0
  53. package/lib/mwater_table_selection/MWaterMetricsTableListComponent.js +80 -0
  54. package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +32 -0
  55. package/lib/mwater_table_selection/MWaterTableSelectComponent.js +158 -0
  56. package/lib/quickfilter/Quickfilter.d.ts +2 -0
  57. package/lib/quickfilter/QuickfiltersDesignComponent.js +18 -10
  58. package/lib/widgets/charts/Chart.d.ts +11 -0
  59. package/lib/widgets/charts/Chart.js +15 -0
  60. package/lib/widgets/charts/ChartWidgetComponent.d.ts +1 -0
  61. package/lib/widgets/charts/ChartWidgetComponent.js +27 -1
  62. package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +1 -1
  63. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +1 -1
  64. package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +5 -12
  65. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +43 -57
  66. package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +113 -110
  67. package/lib/widgets/charts/layered/LayeredChartUtils.d.ts +2 -1
  68. package/lib/widgets/charts/layered/LayeredChartUtils.js +0 -2
  69. package/lib/widgets/charts/pivot/PivotChart.d.ts +2 -0
  70. package/lib/widgets/charts/pivot/PivotChart.js +156 -0
  71. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +5 -20
  72. package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +31 -61
  73. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +4 -0
  74. package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +4 -2
  75. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.d.ts +5 -44
  76. package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +38 -63
  77. package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +7 -68
  78. package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +58 -106
  79. package/lib/widgets/charts/table/TableChart.d.ts +2 -0
  80. package/lib/widgets/charts/table/TableChart.js +172 -1
  81. package/lib/widgets/charts/table/TableChartDesignerComponent.d.ts +7 -17
  82. package/lib/widgets/charts/table/TableChartDesignerComponent.js +79 -95
  83. package/lib/widgets/charts/table/TableChartViewComponent.d.ts +1 -7
  84. package/lib/widgets/charts/table/TableChartViewComponent.js +19 -27
  85. package/package.json +3 -8
  86. package/src/MWaterContextComponent.tsx +1 -1
  87. package/src/MWaterLoaderComponent.ts +1 -1
  88. package/src/dashboards/DashboardComponent.tsx +2 -1
  89. package/src/dashboards/LayoutOptionsComponent.tsx +22 -10
  90. package/src/dashboards/ServerDashboardDataSource.ts +36 -1
  91. package/src/dashboards/layoutOptions.tsx +5 -1
  92. package/src/datagrids/DatagridComponent.tsx +1 -1
  93. package/src/datagrids/ExprCellComponent.tsx +23 -20
  94. package/src/maps/BufferLayer.ts +35 -20
  95. package/src/maps/ChoroplethLayer.ts +51 -33
  96. package/src/maps/ChoroplethLayerDesign.ts +3 -2
  97. package/src/maps/ChoroplethLayerDesigner.tsx +2 -2
  98. package/src/maps/DirectMapDataSource.ts +21 -1
  99. package/src/maps/EditHoverOver.tsx +91 -51
  100. package/src/maps/HoverContent.tsx +16 -47
  101. package/src/maps/Layer.ts +42 -4
  102. package/src/maps/MWaterServerLayer.ts +6 -6
  103. package/src/maps/MapLayerDataSource.ts +8 -0
  104. package/src/maps/MapUtils.ts +70 -3
  105. package/src/maps/MarkersLayer.ts +34 -24
  106. package/src/maps/RasterMapViewComponent.ts +1 -1
  107. package/src/maps/ServerMapDataSource.ts +35 -0
  108. package/src/maps/VectorMapViewComponent.tsx +6 -6
  109. package/src/maps/maps.ts +4 -2
  110. package/src/mwater_table_selection/FormsListComponent.tsx +188 -0
  111. package/src/mwater_table_selection/IndicatorsListComponent.tsx +283 -0
  112. package/src/mwater_table_selection/IssuesListComponent.tsx +167 -0
  113. package/src/mwater_table_selection/MWaterAccountingSystemListComponent.tsx +225 -0
  114. package/src/{MWaterAssetSystemsListComponent.tsx → mwater_table_selection/MWaterAssetSystemsListComponent.tsx} +2 -2
  115. package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +377 -0
  116. package/src/{MWaterCustomTablesetListComponent.tsx → mwater_table_selection/MWaterCustomTablesetListComponent.tsx} +1 -1
  117. package/src/{MWaterMetricsTableListComponent.tsx → mwater_table_selection/MWaterMetricsTableListComponent.tsx} +1 -1
  118. package/src/{MWaterTableSelectComponent.tsx → mwater_table_selection/MWaterTableSelectComponent.tsx} +83 -86
  119. package/src/quickfilter/Quickfilter.ts +3 -0
  120. package/src/quickfilter/QuickfiltersDesignComponent.tsx +19 -14
  121. package/src/widgets/charts/Chart.ts +17 -0
  122. package/src/widgets/charts/ChartWidgetComponent.tsx +36 -1
  123. package/src/widgets/charts/layered/LayeredChartDesign.ts +1 -1
  124. package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +23 -24
  125. package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +260 -211
  126. package/src/widgets/charts/layered/LayeredChartUtils.ts +7 -7
  127. package/src/widgets/charts/pivot/PivotChart.ts +191 -0
  128. package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +124 -129
  129. package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +4 -2
  130. package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +120 -149
  131. package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +178 -198
  132. package/src/widgets/charts/table/TableChart.ts +177 -1
  133. package/src/widgets/charts/table/TableChartDesignerComponent.tsx +422 -0
  134. package/src/widgets/charts/table/{TableChartViewComponent.ts → TableChartViewComponent.tsx} +65 -60
  135. package/src/MWaterCompleteTableSelectComponent.tsx +0 -975
  136. package/src/widgets/charts/table/TableChartDesignerComponent.ts +0 -441
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import * as ui from "@mwater/react-library/lib/bootstrap";
3
2
  import { DataSource, Schema } from "@mwater/expressions";
4
3
  import { PivotChartSegment } from "./PivotChartDesign";
5
4
  export interface SegmentDesignerComponentProps {
@@ -27,73 +26,13 @@ export default class SegmentDesignerComponent extends React.Component<SegmentDes
27
26
  handleFilterChange: (filter: any) => any;
28
27
  handleOrderExprChange: (orderExpr: any) => any;
29
28
  handleOrderDirChange: (orderDir: any) => any;
30
- renderMode(): React.CElement<{
31
- label: React.ReactNode;
32
- labelMuted?: boolean;
33
- hint?: React.ReactNode;
34
- help?: React.ReactNode;
35
- required?: boolean;
36
- hasSuccess?: boolean;
37
- hasWarnings?: boolean;
38
- hasErrors?: boolean;
39
- horizontal?: boolean;
40
- }, ui.FormGroup>;
41
- renderLabel(): React.CElement<{
42
- label: React.ReactNode;
43
- labelMuted?: boolean;
44
- hint?: React.ReactNode;
45
- help?: React.ReactNode;
46
- required?: boolean;
47
- hasSuccess?: boolean;
48
- hasWarnings?: boolean;
49
- hasErrors?: boolean;
50
- horizontal?: boolean;
51
- }, ui.FormGroup>;
29
+ renderMode(): React.JSX.Element;
30
+ renderLabel(): React.JSX.Element;
52
31
  renderValueAxis(): React.JSX.Element;
53
- renderFilter(): React.CElement<{
54
- label: React.ReactNode;
55
- labelMuted?: boolean;
56
- hint?: React.ReactNode;
57
- help?: React.ReactNode;
58
- required?: boolean;
59
- hasSuccess?: boolean;
60
- hasWarnings?: boolean;
61
- hasErrors?: boolean;
62
- horizontal?: boolean;
63
- }, ui.FormGroup>;
64
- renderStyling(): React.CElement<{
65
- label: React.ReactNode;
66
- labelMuted?: boolean;
67
- hint?: React.ReactNode;
68
- help?: React.ReactNode;
69
- required?: boolean;
70
- hasSuccess?: boolean;
71
- hasWarnings?: boolean;
72
- hasErrors?: boolean;
73
- horizontal?: boolean;
74
- }, ui.FormGroup>;
75
- renderBorders(): React.CElement<{
76
- label: React.ReactNode;
77
- labelMuted?: boolean;
78
- hint?: React.ReactNode;
79
- help?: React.ReactNode;
80
- required?: boolean;
81
- hasSuccess?: boolean;
82
- hasWarnings?: boolean;
83
- hasErrors?: boolean;
84
- horizontal?: boolean;
85
- }, ui.FormGroup>;
86
- renderOrderExpr(): React.CElement<{
87
- label: React.ReactNode;
88
- labelMuted?: boolean;
89
- hint?: React.ReactNode;
90
- help?: React.ReactNode;
91
- required?: boolean;
92
- hasSuccess?: boolean;
93
- hasWarnings?: boolean;
94
- hasErrors?: boolean;
95
- horizontal?: boolean;
96
- }, ui.FormGroup>;
97
- render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
32
+ renderFilter(): React.JSX.Element;
33
+ renderStyling(): React.JSX.Element;
34
+ renderBorders(): React.JSX.Element;
35
+ renderOrderExpr(): React.JSX.Element;
36
+ render(): React.JSX.Element;
98
37
  }
99
38
  export {};
@@ -28,7 +28,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const lodash_1 = __importDefault(require("lodash"));
30
30
  const react_1 = __importDefault(require("react"));
31
- const R = react_1.default.createElement;
32
31
  const ui = __importStar(require("@mwater/react-library/lib/bootstrap"));
33
32
  const AxisComponent_1 = __importDefault(require("../../../axes/AxisComponent"));
34
33
  const ColorComponent_1 = __importDefault(require("../../../ColorComponent"));
@@ -78,32 +77,22 @@ class SegmentDesignerComponent extends react_1.default.Component {
78
77
  return this.update({ orderDir });
79
78
  };
80
79
  renderMode() {
81
- return R(ui.FormGroup, {
82
- labelMuted: true,
83
- label: T `Type`
84
- }, react_1.default.createElement(ui.Radio, { key: "single", value: this.state.mode, radioValue: "single", onChange: this.handleMode },
85
- T `Single ${this.props.segmentType}`,
86
- react_1.default.createElement("span", { className: "text-muted" },
87
- ` - `,
88
- T `used for summary ${this.props.segmentType}s and empty ${this.props.segmentType}s`)), react_1.default.createElement(ui.Radio, { key: "multiple", value: this.state.mode, radioValue: "multiple", onChange: this.handleMode },
89
- T `Multiple ${this.props.segmentType}s`,
90
- " - ",
91
- react_1.default.createElement("span", { className: "text-muted" }, T `disaggregate data by a field`)));
80
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Type` },
81
+ react_1.default.createElement(ui.Radio, { key: "single", value: this.state.mode, radioValue: "single", onChange: this.handleMode },
82
+ T `Single ${this.props.segmentType}`,
83
+ react_1.default.createElement("span", { className: "text-muted" },
84
+ ` - `,
85
+ T `used for summary ${this.props.segmentType}s and empty ${this.props.segmentType}s`)),
86
+ react_1.default.createElement(ui.Radio, { key: "multiple", value: this.state.mode, radioValue: "multiple", onChange: this.handleMode },
87
+ T `Multiple ${this.props.segmentType}s`,
88
+ " - ",
89
+ react_1.default.createElement("span", { className: "text-muted" }, T `disaggregate data by a field`))));
92
90
  }
93
91
  renderLabel() {
94
- return R(ui.FormGroup, {
95
- labelMuted: true,
96
- label: T `Label`,
97
- help: this.state.mode === "multiple" ? T `Optional label for the ${this.props.segmentType}s` : undefined
98
- }, R("input", {
99
- ref: (elem) => {
100
- this.labelElem = elem;
101
- },
102
- type: "text",
103
- className: "form-control",
104
- value: this.props.segment.label || "",
105
- onChange: this.handleLabelChange
106
- }));
92
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Label`, help: this.state.mode === "multiple" ? T `Optional label for the ${this.props.segmentType}s` : undefined },
93
+ react_1.default.createElement("input", { ref: (elem) => {
94
+ this.labelElem = elem;
95
+ }, type: "text", className: "form-control", value: this.props.segment.label || "", onChange: this.handleLabelChange })));
107
96
  }
108
97
  renderValueAxis() {
109
98
  // Get type of axis
@@ -112,18 +101,7 @@ class SegmentDesignerComponent extends react_1.default.Component {
112
101
  const allowValueAxisOnlyValuesPresent = axisType == "enum" || axisType == "enumset" || axisType == "date";
113
102
  return react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Field`, help: T `Field to disaggregate data by` },
114
103
  react_1.default.createElement("div", { style: { marginLeft: 8 } },
115
- R(AxisComponent_1.default, {
116
- schema: this.props.schema,
117
- dataSource: this.props.dataSource,
118
- table: this.props.table,
119
- types: ["enum", "enumset", "text", "boolean", "date"],
120
- aggrNeed: "none",
121
- value: this.props.segment.valueAxis,
122
- onChange: this.handleValueAxisChange,
123
- allowExcludedValues: true,
124
- filters: this.props.filters,
125
- collapseCategories: true
126
- }),
104
+ react_1.default.createElement(AxisComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, table: this.props.table, types: ["enum", "enumset", "text", "boolean", "date"], aggrNeed: "none", value: this.props.segment.valueAxis, onChange: this.handleValueAxisChange, allowExcludedValues: true, filters: this.props.filters, collapseCategories: true }),
127
105
  allowValueAxisOnlyValuesPresent ?
128
106
  react_1.default.createElement(ui.Checkbox, { value: this.props.segment.valueAxisOnlyValuesPresent, onChange: this.handleValueAxisOnlyValuesPresentChange },
129
107
  T `Only show values actually present`,
@@ -133,82 +111,52 @@ class SegmentDesignerComponent extends react_1.default.Component {
133
111
  : null));
134
112
  }
135
113
  renderFilter() {
136
- return R(ui.FormGroup, {
137
- labelMuted: true,
138
- label: [R(ui.Icon, { id: "glyphicon-filter" }), " ", T `Filters`],
139
- hint: T `Filters all data associated with this ${this.props.segmentType}`
140
- }, R(expressions_ui_2.FilterExprComponent, {
141
- schema: this.props.schema,
142
- dataSource: this.props.dataSource,
143
- onChange: this.handleFilterChange,
144
- table: this.props.table,
145
- value: this.props.segment.filter
146
- }));
114
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: react_1.default.createElement(react_1.default.Fragment, null,
115
+ react_1.default.createElement(ui.Icon, { id: "glyphicon-filter" }),
116
+ " ",
117
+ T `Filters`), hint: T `Filters all data associated with this ${this.props.segmentType}` },
118
+ react_1.default.createElement(expressions_ui_2.FilterExprComponent, { schema: this.props.schema, dataSource: this.props.dataSource, onChange: this.handleFilterChange, table: this.props.table, value: this.props.segment.filter })));
147
119
  }
148
120
  renderStyling() {
149
- return R(ui.FormGroup, {
150
- labelMuted: true,
151
- label: T `Styling`
152
- }, react_1.default.createElement("div", null,
153
- react_1.default.createElement(ui.Checkbox, { key: "bold", inline: true, value: this.props.segment.bold === true, onChange: (value) => this.update({ bold: value }) }, T `Bold`),
154
- react_1.default.createElement(ui.Checkbox, { key: "italic", inline: true, value: this.props.segment.italic === true, onChange: (value) => this.update({ italic: value }) }, T `Italic`),
155
- this.props.segment.valueAxis && this.props.segment.label ?
156
- react_1.default.createElement(ui.Checkbox, { key: "valueLabelBold", inline: true, value: this.props.segment.valueLabelBold === true, onChange: (value) => this.update({ valueLabelBold: value }) }, T `Header Bold`)
157
- : undefined,
158
- this.props.segment.valueAxis && this.props.segment.label
159
- ? R("div", { style: { paddingTop: 5 } }, T `Shade filler cells: `, R(ColorComponent_1.default, {
160
- color: this.props.segment.fillerColor,
161
- onChange: (color) => this.update({ fillerColor: color })
162
- }))
163
- : undefined));
121
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Styling` },
122
+ react_1.default.createElement("div", null,
123
+ react_1.default.createElement(ui.Checkbox, { key: "bold", inline: true, value: this.props.segment.bold === true, onChange: (value) => this.update({ bold: value }) }, T `Bold`),
124
+ react_1.default.createElement(ui.Checkbox, { key: "italic", inline: true, value: this.props.segment.italic === true, onChange: (value) => this.update({ italic: value }) }, T `Italic`),
125
+ this.props.segment.valueAxis && this.props.segment.label ?
126
+ react_1.default.createElement(ui.Checkbox, { key: "valueLabelBold", inline: true, value: this.props.segment.valueLabelBold === true, onChange: (value) => this.update({ valueLabelBold: value }) }, T `Header Bold`)
127
+ : undefined,
128
+ this.props.segment.valueAxis && this.props.segment.label ? (react_1.default.createElement("div", { style: { paddingTop: 5 } },
129
+ T `Shade filler cells: `,
130
+ react_1.default.createElement(ColorComponent_1.default, { color: this.props.segment.fillerColor, onChange: (color) => this.update({ fillerColor: color }) }))) : undefined)));
164
131
  }
165
132
  renderBorders() {
166
- return R(ui.FormGroup, {
167
- labelMuted: true,
168
- label: T `Borders`
169
- }, R("div", { key: "before" }, this.props.segmentType === "row" ? T `Top: ` : T `Left: `), R(BorderComponent, {
170
- value: this.props.segment.borderBefore,
171
- defaultValue: 2,
172
- onChange: (value) => this.update({ borderBefore: value })
173
- }), R("div", { key: "within" }, T `Within: `), R(BorderComponent, {
174
- value: this.props.segment.borderWithin,
175
- defaultValue: 1,
176
- onChange: (value) => this.update({ borderWithin: value })
177
- }), R("div", { key: "after" }, this.props.segmentType === "row" ? T `Bottom: ` : T `Right: `), R(BorderComponent, {
178
- value: this.props.segment.borderAfter,
179
- defaultValue: 2,
180
- onChange: (value) => this.update({ borderAfter: value })
181
- }));
133
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Borders` },
134
+ react_1.default.createElement("div", { key: "before" }, this.props.segmentType === "row" ? T `Top: ` : T `Left: `),
135
+ react_1.default.createElement(BorderComponent, { value: this.props.segment.borderBefore, defaultValue: 2, onChange: (value) => this.update({ borderBefore: value }) }),
136
+ react_1.default.createElement("div", { key: "within" }, T `Within: `),
137
+ react_1.default.createElement(BorderComponent, { value: this.props.segment.borderWithin, defaultValue: 1, onChange: (value) => this.update({ borderWithin: value }) }),
138
+ react_1.default.createElement("div", { key: "after" }, this.props.segmentType === "row" ? T `Bottom: ` : T `Right: `),
139
+ react_1.default.createElement(BorderComponent, { value: this.props.segment.borderAfter, defaultValue: 2, onChange: (value) => this.update({ borderAfter: value }) })));
182
140
  }
183
141
  renderOrderExpr() {
184
- return R(ui.FormGroup, {
185
- labelMuted: true,
186
- label: [R(ui.Icon, { id: "fa-sort-amount-asc" }), " ", T `Sort`],
187
- hint: T `Sorts the display of this ${this.props.segmentType}`
188
- }, R(expressions_ui_1.ExprComponent, {
189
- schema: this.props.schema,
190
- dataSource: this.props.dataSource,
191
- onChange: this.handleOrderExprChange,
192
- table: this.props.table,
193
- types: ["enum", "text", "boolean", "date", "datetime", "number"],
194
- aggrStatuses: ["aggregate"],
195
- value: this.props.segment.orderExpr ?? null
196
- }), this.props.segment.orderExpr
197
- ? R("div", null, R(ui.Radio, {
198
- value: this.props.segment.orderDir || "asc",
199
- radioValue: "asc",
200
- onChange: this.handleOrderDirChange,
201
- inline: true
202
- }, T `Ascending`), R(ui.Radio, {
203
- value: this.props.segment.orderDir || "asc",
204
- radioValue: "desc",
205
- onChange: this.handleOrderDirChange,
206
- inline: true
207
- }, T `Descending`))
208
- : undefined);
142
+ return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: react_1.default.createElement(react_1.default.Fragment, null,
143
+ react_1.default.createElement(ui.Icon, { id: "fa-sort-amount-asc" }),
144
+ " ",
145
+ T `Sort`), hint: T `Sorts the display of this ${this.props.segmentType}` },
146
+ react_1.default.createElement(expressions_ui_1.ExprComponent, { schema: this.props.schema, dataSource: this.props.dataSource, onChange: this.handleOrderExprChange, table: this.props.table, types: ["enum", "text", "boolean", "date", "datetime", "number"], aggrStatuses: ["aggregate"], value: this.props.segment.orderExpr ?? null }),
147
+ this.props.segment.orderExpr ? (react_1.default.createElement("div", null,
148
+ react_1.default.createElement(ui.Radio, { value: this.props.segment.orderDir || "asc", radioValue: "asc", onChange: this.handleOrderDirChange, inline: true }, T `Ascending`),
149
+ react_1.default.createElement(ui.Radio, { value: this.props.segment.orderDir || "asc", radioValue: "desc", onChange: this.handleOrderDirChange, inline: true }, T `Descending`))) : undefined));
209
150
  }
210
151
  render() {
211
- return R("div", null, this.renderMode(), this.state.mode ? this.renderLabel() : undefined, this.state.mode === "multiple" ? this.renderValueAxis() : undefined, this.state.mode ? this.renderFilter() : undefined, this.state.mode === "multiple" ? this.renderOrderExpr() : undefined, this.state.mode ? this.renderStyling() : undefined, this.state.mode ? this.renderBorders() : undefined);
152
+ return (react_1.default.createElement("div", null,
153
+ this.renderMode(),
154
+ this.state.mode ? this.renderLabel() : undefined,
155
+ this.state.mode === "multiple" ? this.renderValueAxis() : undefined,
156
+ this.state.mode ? this.renderFilter() : undefined,
157
+ this.state.mode === "multiple" ? this.renderOrderExpr() : undefined,
158
+ this.state.mode ? this.renderStyling() : undefined,
159
+ this.state.mode ? this.renderBorders() : undefined));
212
160
  }
213
161
  }
214
162
  exports.default = SegmentDesignerComponent;
@@ -216,6 +164,10 @@ exports.default = SegmentDesignerComponent;
216
164
  class BorderComponent extends react_1.default.Component {
217
165
  render() {
218
166
  const value = this.props.value != null ? this.props.value : this.props.defaultValue;
219
- return R("span", null, react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 0, onChange: () => this.props.onChange(0) }, T `None`), react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 1, onChange: () => this.props.onChange(1) }, T `Light`), react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 2, onChange: () => this.props.onChange(2) }, T `Medium`), react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 3, onChange: () => this.props.onChange(3) }, T `Heavy`));
167
+ return (react_1.default.createElement("span", null,
168
+ react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 0, onChange: () => this.props.onChange(0) }, T `None`),
169
+ react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 1, onChange: () => this.props.onChange(1) }, T `Light`),
170
+ react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 2, onChange: () => this.props.onChange(2) }, T `Medium`),
171
+ react_1.default.createElement(bootstrap_1.Radio, { inline: true, value: value, radioValue: 3, onChange: () => this.props.onChange(3) }, T `Heavy`)));
220
172
  }
221
173
  }
@@ -55,4 +55,6 @@ export default class TableChart extends Chart {
55
55
  getFilterableTables(design: any, schema: Schema): any[];
56
56
  getPlaceholderIcon(): string;
57
57
  translateDesign(design: TableChartDesign, translate: (input: string) => string): TableChartDesign;
58
+ supportsXlsxExport(): boolean;
59
+ createXlsxWorkbook(design: TableChartDesign, schema: Schema, dataSource: DataSource, data: any, locale: string): any;
58
60
  }
@@ -1,11 +1,33 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
29
  const lodash_1 = __importDefault(require("lodash"));
7
30
  const react_1 = __importDefault(require("react"));
8
- const R = react_1.default.createElement;
9
31
  const uuid_1 = __importDefault(require("uuid"));
10
32
  const immer_1 = __importDefault(require("immer"));
11
33
  const immer_2 = require("immer");
@@ -16,6 +38,8 @@ const expressions_3 = require("@mwater/expressions");
16
38
  const AxisBuilder_1 = __importDefault(require("../../../axes/AxisBuilder"));
17
39
  const TableChartViewComponent_1 = __importDefault(require("./TableChartViewComponent"));
18
40
  const expressions_4 = require("@mwater/expressions");
41
+ const XLSX = __importStar(require("xlsx-js-style"));
42
+ const color_1 = __importDefault(require("color"));
19
43
  /**
20
44
  * Table control
21
45
  */
@@ -336,5 +360,152 @@ class TableChart extends Chart_1.default {
336
360
  }
337
361
  });
338
362
  }
363
+ // Override to indicate this chart supports XLSX export
364
+ supportsXlsxExport() {
365
+ return true;
366
+ }
367
+ // Creates a SheetJS workbook for the chart data
368
+ createXlsxWorkbook(design, schema, dataSource, data, locale) {
369
+ const exprUtils = new expressions_2.ExprUtils(schema);
370
+ const axisBuilder = new AxisBuilder_1.default({ schema });
371
+ const workbook = XLSX.utils.book_new();
372
+ // Create array for headers
373
+ const headers = design.columns.map(column => column.headerText || exprUtils.summarizeExpr(column.textAxis?.expr || null, locale));
374
+ // Create arrays for data
375
+ const rows = data.main.map((record) => {
376
+ return design.columns.map((column, columnIndex) => {
377
+ const value = record[`c${columnIndex}`];
378
+ if (value == null) {
379
+ return "";
380
+ }
381
+ const exprType = exprUtils.getExprType(column.textAxis?.expr);
382
+ // Handle images as URLs
383
+ if (exprType === "image" && value) {
384
+ return dataSource.getImageUrl(value.id);
385
+ }
386
+ if (exprType === "imagelist" && value) {
387
+ return value.map((img) => dataSource.getImageUrl(img.id)).join(", ");
388
+ }
389
+ // Handle dates properly for Excel
390
+ if (exprType === "date" && value) {
391
+ // Convert date string to JavaScript Date object
392
+ const date = new Date(value);
393
+ // Return a date that Excel can properly handle
394
+ return date;
395
+ }
396
+ // Handle datetime properly for Excel
397
+ if (exprType === "datetime" && value) {
398
+ // Convert datetime string to JavaScript Date object
399
+ const date = new Date(value);
400
+ // Return a date that Excel can properly handle
401
+ return date;
402
+ }
403
+ return exprUtils.stringifyExprLiteral(column.textAxis?.expr, value, locale);
404
+ });
405
+ });
406
+ // Add summary row if exists
407
+ if (data.summary) {
408
+ const summaryRow = design.columns.map((column, columnIndex) => {
409
+ if (data.summary[`c${columnIndex}`] != null) {
410
+ return data.summary[`c${columnIndex}`];
411
+ }
412
+ return "";
413
+ });
414
+ rows.push(summaryRow);
415
+ }
416
+ // Create worksheet from data
417
+ const worksheet = XLSX.utils.aoa_to_sheet([headers, ...rows]);
418
+ // Set column widths based on content
419
+ const colWidths = headers.map((header, colIndex) => {
420
+ // Start with header width
421
+ let maxWidth = header.length;
422
+ // Check data rows
423
+ rows.forEach((row) => {
424
+ const cellValue = row[colIndex];
425
+ if (cellValue) {
426
+ maxWidth = Math.max(maxWidth, String(cellValue).length);
427
+ }
428
+ });
429
+ // Add some padding and cap at 50 characters
430
+ return Math.min(maxWidth + 2, 50);
431
+ });
432
+ worksheet['!cols'] = colWidths.map(width => ({ wch: width }));
433
+ // Apply cell styles and background colors
434
+ const range = XLSX.utils.decode_range(worksheet['!ref']);
435
+ for (let rowIndex = 0; rowIndex <= range.e.r; rowIndex++) {
436
+ for (let colIndex = 0; colIndex <= range.e.c; colIndex++) {
437
+ const cellAddress = XLSX.utils.encode_cell({ r: rowIndex, c: colIndex });
438
+ const cell = worksheet[cellAddress];
439
+ // Skip empty cells
440
+ if (!cell)
441
+ continue;
442
+ // Initialize style object if needed
443
+ if (!cell.s)
444
+ cell.s = {};
445
+ // Apply header styles
446
+ if (rowIndex === 0) {
447
+ cell.s = {
448
+ ...cell.s,
449
+ font: { bold: true },
450
+ alignment: { horizontal: "center" },
451
+ border: {
452
+ bottom: { style: "thin" }
453
+ }
454
+ };
455
+ }
456
+ // Apply background colors for data cells
457
+ if (rowIndex > 0 && rowIndex <= data.main.length && colIndex < design.columns.length) {
458
+ const record = data.main[rowIndex - 1];
459
+ const column = design.columns[colIndex];
460
+ // Check if this column has a background color axis and the bc property exists
461
+ if (column?.backgroundColorAxis && record[`bc${colIndex}`] !== undefined) {
462
+ // Use the Color library to handle the color value safely
463
+ try {
464
+ // Call getValueColor to get the actual color
465
+ const axisBuilder = new AxisBuilder_1.default({ schema });
466
+ const bgColor = axisBuilder.getValueColor(column.backgroundColorAxis, record[`bc${colIndex}`]);
467
+ if (bgColor) {
468
+ const color = (0, color_1.default)(bgColor);
469
+ const hex = color.hex().substring(1); // Remove #
470
+ // Apply the background color
471
+ cell.s.fill = {
472
+ patternType: "solid",
473
+ fgColor: { rgb: hex },
474
+ bgColor: { rgb: hex }
475
+ };
476
+ // Adjust text color based on background lightness
477
+ const lightness = color.luminosity();
478
+ cell.s.font = {
479
+ ...cell.s.font,
480
+ color: { rgb: lightness < 0.3 ? "CCCCCC" : "000000" }
481
+ };
482
+ }
483
+ }
484
+ catch (e) {
485
+ // Silently ignore color errors
486
+ console.error("Error applying background color", e);
487
+ }
488
+ }
489
+ }
490
+ // Apply summary row styling
491
+ if (data.summary && rowIndex === rows.length) {
492
+ cell.s = {
493
+ ...cell.s,
494
+ font: { bold: true },
495
+ border: {
496
+ top: { style: "thin" }
497
+ }
498
+ };
499
+ }
500
+ }
501
+ }
502
+ console.log(worksheet);
503
+ // Add the worksheet to the workbook
504
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Data");
505
+ // Convert workbook to blob
506
+ const workbookBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
507
+ const blob = new Blob([workbookBuffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
508
+ return blob;
509
+ }
339
510
  }
340
511
  exports.default = TableChart;
@@ -17,25 +17,15 @@ export default class TableChartDesignerComponent extends React.Component<TableCh
17
17
  handleColumnChange: (index: any, column: any) => void;
18
18
  handleRemoveColumn: (index: any) => void;
19
19
  handleAddColumn: () => void;
20
- renderTable(): React.DetailedReactHTMLElement<{
21
- className: string;
22
- }, HTMLElement>;
23
- renderTitle(): React.DetailedReactHTMLElement<{
24
- className: string;
25
- }, HTMLElement>;
20
+ renderTable(): React.JSX.Element;
21
+ renderTitle(): React.JSX.Element;
26
22
  renderColumn: (column: any, index: any, connectDragSource: any, connectDragPreview: any, connectDropTarget: any) => any;
27
23
  handleReorder: (map: any) => void;
28
- renderColumns(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | undefined;
29
- renderOrderings(): React.DetailedReactHTMLElement<{
30
- className: string;
31
- }, HTMLElement> | null;
32
- renderFilter(): React.DetailedReactHTMLElement<{
33
- className: string;
34
- }, HTMLElement> | null;
35
- renderLimit(): React.DetailedReactHTMLElement<{
36
- className: string;
37
- }, HTMLElement> | null;
38
- render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
24
+ renderColumns(): React.JSX.Element | undefined;
25
+ renderOrderings(): React.JSX.Element | null;
26
+ renderFilter(): React.JSX.Element | null;
27
+ renderLimit(): React.JSX.Element | null;
28
+ render(): React.JSX.Element;
39
29
  }
40
30
  export interface TableChartColumnDesignerComponentProps {
41
31
  design: TableChartDesign;