@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.
- package/.storybook/head.html +0 -1
- package/lib/MWaterContextComponent.js +1 -1
- package/lib/MWaterLoaderComponent.d.ts +2 -2
- package/lib/dashboards/DashboardComponent.js +2 -1
- package/lib/dashboards/LayoutOptionsComponent.js +18 -11
- package/lib/dashboards/ServerDashboardDataSource.d.ts +10 -1
- package/lib/dashboards/ServerDashboardDataSource.js +29 -0
- package/lib/dashboards/layoutOptions.d.ts +5 -1
- package/lib/datagrids/DatagridComponent.js +1 -1
- package/lib/datagrids/ExprCellComponent.d.ts +1 -0
- package/lib/datagrids/ExprCellComponent.js +22 -20
- package/lib/maps/BufferLayer.d.ts +18 -0
- package/lib/maps/BufferLayer.js +24 -14
- package/lib/maps/ChoroplethLayer.d.ts +18 -0
- package/lib/maps/ChoroplethLayer.js +34 -25
- package/lib/maps/ChoroplethLayerDesign.d.ts +3 -2
- package/lib/maps/ChoroplethLayerDesigner.d.ts +11 -1
- package/lib/maps/DirectMapDataSource.js +17 -0
- package/lib/maps/EditHoverOver.d.ts +1 -1
- package/lib/maps/EditHoverOver.js +62 -33
- package/lib/maps/HoverContent.d.ts +10 -5
- package/lib/maps/HoverContent.js +6 -35
- package/lib/maps/Layer.d.ts +37 -0
- package/lib/maps/Layer.js +30 -4
- package/lib/maps/MWaterServerLayer.d.ts +2 -2
- package/lib/maps/MWaterServerLayer.js +6 -6
- package/lib/maps/MapLayerDataSource.d.ts +9 -0
- package/lib/maps/MapUtils.d.ts +19 -1
- package/lib/maps/MapUtils.js +71 -1
- package/lib/maps/MarkersLayer.d.ts +18 -0
- package/lib/maps/MarkersLayer.js +24 -24
- package/lib/maps/MarkersLayerDesignerComponent.d.ts +14 -1
- package/lib/maps/RasterMapViewComponent.js +1 -1
- package/lib/maps/ServerMapDataSource.d.ts +9 -0
- package/lib/maps/ServerMapDataSource.js +29 -0
- package/lib/maps/VectorMapViewComponent.js +6 -6
- package/lib/maps/maps.d.ts +4 -2
- package/lib/mwater_table_selection/FormsListComponent.d.ts +33 -0
- package/lib/mwater_table_selection/FormsListComponent.js +141 -0
- package/lib/mwater_table_selection/IndicatorsListComponent.d.ts +47 -0
- package/lib/mwater_table_selection/IndicatorsListComponent.js +182 -0
- package/lib/mwater_table_selection/IssuesListComponent.d.ts +29 -0
- package/lib/mwater_table_selection/IssuesListComponent.js +123 -0
- package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.d.ts +20 -0
- package/lib/mwater_table_selection/MWaterAccountingSystemListComponent.js +157 -0
- package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.d.ts +17 -0
- package/lib/mwater_table_selection/MWaterAssetSystemsListComponent.js +79 -0
- package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.d.ts +37 -0
- package/lib/mwater_table_selection/MWaterCompleteTableSelectComponent.js +275 -0
- package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.d.ts +17 -0
- package/lib/mwater_table_selection/MWaterCustomTablesetListComponent.js +94 -0
- package/lib/mwater_table_selection/MWaterMetricsTableListComponent.d.ts +17 -0
- package/lib/mwater_table_selection/MWaterMetricsTableListComponent.js +80 -0
- package/lib/mwater_table_selection/MWaterTableSelectComponent.d.ts +32 -0
- package/lib/mwater_table_selection/MWaterTableSelectComponent.js +158 -0
- package/lib/quickfilter/Quickfilter.d.ts +2 -0
- package/lib/quickfilter/QuickfiltersDesignComponent.js +18 -10
- package/lib/widgets/charts/Chart.d.ts +11 -0
- package/lib/widgets/charts/Chart.js +15 -0
- package/lib/widgets/charts/ChartWidgetComponent.d.ts +1 -0
- package/lib/widgets/charts/ChartWidgetComponent.js +27 -1
- package/lib/widgets/charts/layered/LayeredChartDesign.d.ts +1 -1
- package/lib/widgets/charts/layered/LayeredChartDesignerComponent.d.ts +1 -1
- package/lib/widgets/charts/layered/LayeredChartDesignerComponent.js +5 -12
- package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.d.ts +43 -57
- package/lib/widgets/charts/layered/LayeredChartLayerDesignerComponent.js +113 -110
- package/lib/widgets/charts/layered/LayeredChartUtils.d.ts +2 -1
- package/lib/widgets/charts/layered/LayeredChartUtils.js +0 -2
- package/lib/widgets/charts/pivot/PivotChart.d.ts +2 -0
- package/lib/widgets/charts/pivot/PivotChart.js +156 -0
- package/lib/widgets/charts/pivot/PivotChartDesignerComponent.d.ts +5 -20
- package/lib/widgets/charts/pivot/PivotChartDesignerComponent.js +31 -61
- package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.d.ts +4 -0
- package/lib/widgets/charts/pivot/PivotChartLayoutBuilder.js +4 -2
- package/lib/widgets/charts/pivot/PivotChartLayoutComponent.d.ts +5 -44
- package/lib/widgets/charts/pivot/PivotChartLayoutComponent.js +38 -63
- package/lib/widgets/charts/pivot/SegmentDesignerComponent.d.ts +7 -68
- package/lib/widgets/charts/pivot/SegmentDesignerComponent.js +58 -106
- package/lib/widgets/charts/table/TableChart.d.ts +2 -0
- package/lib/widgets/charts/table/TableChart.js +172 -1
- package/lib/widgets/charts/table/TableChartDesignerComponent.d.ts +7 -17
- package/lib/widgets/charts/table/TableChartDesignerComponent.js +79 -95
- package/lib/widgets/charts/table/TableChartViewComponent.d.ts +1 -7
- package/lib/widgets/charts/table/TableChartViewComponent.js +19 -27
- package/package.json +3 -8
- package/src/MWaterContextComponent.tsx +1 -1
- package/src/MWaterLoaderComponent.ts +1 -1
- package/src/dashboards/DashboardComponent.tsx +2 -1
- package/src/dashboards/LayoutOptionsComponent.tsx +22 -10
- package/src/dashboards/ServerDashboardDataSource.ts +36 -1
- package/src/dashboards/layoutOptions.tsx +5 -1
- package/src/datagrids/DatagridComponent.tsx +1 -1
- package/src/datagrids/ExprCellComponent.tsx +23 -20
- package/src/maps/BufferLayer.ts +35 -20
- package/src/maps/ChoroplethLayer.ts +51 -33
- package/src/maps/ChoroplethLayerDesign.ts +3 -2
- package/src/maps/ChoroplethLayerDesigner.tsx +2 -2
- package/src/maps/DirectMapDataSource.ts +21 -1
- package/src/maps/EditHoverOver.tsx +91 -51
- package/src/maps/HoverContent.tsx +16 -47
- package/src/maps/Layer.ts +42 -4
- package/src/maps/MWaterServerLayer.ts +6 -6
- package/src/maps/MapLayerDataSource.ts +8 -0
- package/src/maps/MapUtils.ts +70 -3
- package/src/maps/MarkersLayer.ts +34 -24
- package/src/maps/RasterMapViewComponent.ts +1 -1
- package/src/maps/ServerMapDataSource.ts +35 -0
- package/src/maps/VectorMapViewComponent.tsx +6 -6
- package/src/maps/maps.ts +4 -2
- package/src/mwater_table_selection/FormsListComponent.tsx +188 -0
- package/src/mwater_table_selection/IndicatorsListComponent.tsx +283 -0
- package/src/mwater_table_selection/IssuesListComponent.tsx +167 -0
- package/src/mwater_table_selection/MWaterAccountingSystemListComponent.tsx +225 -0
- package/src/{MWaterAssetSystemsListComponent.tsx → mwater_table_selection/MWaterAssetSystemsListComponent.tsx} +2 -2
- package/src/mwater_table_selection/MWaterCompleteTableSelectComponent.tsx +377 -0
- package/src/{MWaterCustomTablesetListComponent.tsx → mwater_table_selection/MWaterCustomTablesetListComponent.tsx} +1 -1
- package/src/{MWaterMetricsTableListComponent.tsx → mwater_table_selection/MWaterMetricsTableListComponent.tsx} +1 -1
- package/src/{MWaterTableSelectComponent.tsx → mwater_table_selection/MWaterTableSelectComponent.tsx} +83 -86
- package/src/quickfilter/Quickfilter.ts +3 -0
- package/src/quickfilter/QuickfiltersDesignComponent.tsx +19 -14
- package/src/widgets/charts/Chart.ts +17 -0
- package/src/widgets/charts/ChartWidgetComponent.tsx +36 -1
- package/src/widgets/charts/layered/LayeredChartDesign.ts +1 -1
- package/src/widgets/charts/layered/LayeredChartDesignerComponent.tsx +23 -24
- package/src/widgets/charts/layered/LayeredChartLayerDesignerComponent.tsx +260 -211
- package/src/widgets/charts/layered/LayeredChartUtils.ts +7 -7
- package/src/widgets/charts/pivot/PivotChart.ts +191 -0
- package/src/widgets/charts/pivot/PivotChartDesignerComponent.tsx +124 -129
- package/src/widgets/charts/pivot/PivotChartLayoutBuilder.ts +4 -2
- package/src/widgets/charts/pivot/PivotChartLayoutComponent.tsx +120 -149
- package/src/widgets/charts/pivot/SegmentDesignerComponent.tsx +178 -198
- package/src/widgets/charts/table/TableChart.ts +177 -1
- package/src/widgets/charts/table/TableChartDesignerComponent.tsx +422 -0
- package/src/widgets/charts/table/{TableChartViewComponent.ts → TableChartViewComponent.tsx} +65 -60
- package/src/MWaterCompleteTableSelectComponent.tsx +0 -975
- package/src/widgets/charts/table/TableChartDesignerComponent.ts +0 -441
|
@@ -440,5 +440,161 @@ class PivotChart extends Chart_1.default {
|
|
|
440
440
|
}
|
|
441
441
|
});
|
|
442
442
|
}
|
|
443
|
+
// Override to indicate this chart supports XLSX export
|
|
444
|
+
supportsXlsxExport() {
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
// Creates a SheetJS workbook for the pivot chart data
|
|
448
|
+
createXlsxWorkbook(design, schema, dataSource, data, locale) {
|
|
449
|
+
// Import XLSX here to ensure it's available
|
|
450
|
+
const XLSX = require("xlsx-js-style");
|
|
451
|
+
const Color = require("color");
|
|
452
|
+
// Create a new workbook
|
|
453
|
+
const workbook = XLSX.utils.book_new();
|
|
454
|
+
// Build layout using the layout builder
|
|
455
|
+
const layoutBuilder = new PivotChartLayoutBuilder_1.default({ schema });
|
|
456
|
+
const layout = layoutBuilder.buildLayout(design, data, locale);
|
|
457
|
+
// Create a 2D array for the worksheet data
|
|
458
|
+
const wsData = [];
|
|
459
|
+
// Process each row in the layout
|
|
460
|
+
layout.rows.forEach(layoutRow => {
|
|
461
|
+
const rowData = [];
|
|
462
|
+
// Process each cell in the row
|
|
463
|
+
layoutRow.cells.forEach(cell => {
|
|
464
|
+
// For skipped cells, still add an empty placeholder
|
|
465
|
+
if (cell.skip) {
|
|
466
|
+
rowData.push({ v: "", s: {} });
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
// Create cell value and style
|
|
470
|
+
const cellObj = {
|
|
471
|
+
v: cell.text === null || cell.text === undefined ? "" : cell.text,
|
|
472
|
+
s: {}
|
|
473
|
+
};
|
|
474
|
+
// Apply alignment based on cell type and subtype
|
|
475
|
+
if (cell.align === "right") {
|
|
476
|
+
cellObj.s.alignment = { horizontal: "right" };
|
|
477
|
+
}
|
|
478
|
+
else if (cell.align === "center") {
|
|
479
|
+
cellObj.s.alignment = { horizontal: "center" };
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
cellObj.s.alignment = { horizontal: "left" };
|
|
483
|
+
}
|
|
484
|
+
// Apply styles based on cell properties
|
|
485
|
+
if (cell.bold) {
|
|
486
|
+
cellObj.s.font = { ...cellObj.s.font, bold: true };
|
|
487
|
+
}
|
|
488
|
+
if (cell.italic) {
|
|
489
|
+
cellObj.s.font = { ...cellObj.s.font, italic: true };
|
|
490
|
+
}
|
|
491
|
+
// Apply background color if present
|
|
492
|
+
if (cell.backgroundColor) {
|
|
493
|
+
try {
|
|
494
|
+
const color = Color(cell.backgroundColor);
|
|
495
|
+
const hex = color.hex().substring(1); // Remove #
|
|
496
|
+
cellObj.s.fill = {
|
|
497
|
+
patternType: "solid",
|
|
498
|
+
fgColor: { rgb: hex },
|
|
499
|
+
bgColor: { rgb: hex }
|
|
500
|
+
};
|
|
501
|
+
// Adjust text color based on background lightness
|
|
502
|
+
const lightness = color.luminosity();
|
|
503
|
+
cellObj.s.font = {
|
|
504
|
+
...cellObj.s.font,
|
|
505
|
+
color: { rgb: lightness < 0.3 ? "FFFFFF" : "000000" }
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
catch (e) {
|
|
509
|
+
// Silently ignore color errors
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// Apply borders
|
|
513
|
+
const borders = {};
|
|
514
|
+
if (cell.borderTop) {
|
|
515
|
+
const style = cell.borderTop === 1 ? "thin" : cell.borderTop === 2 ? "medium" : "thick";
|
|
516
|
+
borders.top = { style };
|
|
517
|
+
}
|
|
518
|
+
if (cell.borderBottom) {
|
|
519
|
+
const style = cell.borderBottom === 1 ? "thin" : cell.borderBottom === 2 ? "medium" : "thick";
|
|
520
|
+
borders.bottom = { style };
|
|
521
|
+
}
|
|
522
|
+
if (cell.borderLeft) {
|
|
523
|
+
const style = cell.borderLeft === 1 ? "thin" : cell.borderLeft === 2 ? "medium" : "thick";
|
|
524
|
+
borders.left = { style };
|
|
525
|
+
}
|
|
526
|
+
if (cell.borderRight) {
|
|
527
|
+
const style = cell.borderRight === 1 ? "thin" : cell.borderRight === 2 ? "medium" : "thick";
|
|
528
|
+
borders.right = { style };
|
|
529
|
+
}
|
|
530
|
+
if (Object.keys(borders).length > 0) {
|
|
531
|
+
cellObj.s.border = borders;
|
|
532
|
+
}
|
|
533
|
+
rowData.push(cellObj);
|
|
534
|
+
});
|
|
535
|
+
wsData.push(rowData);
|
|
536
|
+
});
|
|
537
|
+
// Create a worksheet from the data
|
|
538
|
+
const worksheet = XLSX.utils.aoa_to_sheet(wsData);
|
|
539
|
+
// Process merged cells
|
|
540
|
+
const merges = [];
|
|
541
|
+
// Track current row and column position
|
|
542
|
+
let rowOffset = 0;
|
|
543
|
+
// Traverse layout again to collect merge info
|
|
544
|
+
layout.rows.forEach((layoutRow, rowIndex) => {
|
|
545
|
+
let colOffset = 0;
|
|
546
|
+
layoutRow.cells.forEach((cell, colIndex) => {
|
|
547
|
+
// Skip cells that are part of spans (already handled)
|
|
548
|
+
if (cell.skip) {
|
|
549
|
+
colOffset++;
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
// Handle row spans
|
|
553
|
+
if (cell.rowSpan && cell.rowSpan > 1) {
|
|
554
|
+
merges.push({
|
|
555
|
+
s: { r: rowOffset, c: colOffset },
|
|
556
|
+
e: { r: rowOffset + cell.rowSpan - 1, c: colOffset }
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
// Handle column spans
|
|
560
|
+
if (cell.columnSpan && cell.columnSpan > 1) {
|
|
561
|
+
merges.push({
|
|
562
|
+
s: { r: rowOffset, c: colOffset },
|
|
563
|
+
e: { r: rowOffset, c: colOffset + cell.columnSpan - 1 }
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
colOffset++;
|
|
567
|
+
});
|
|
568
|
+
rowOffset++;
|
|
569
|
+
});
|
|
570
|
+
// Apply merges to worksheet
|
|
571
|
+
if (merges.length > 0) {
|
|
572
|
+
worksheet["!merges"] = merges;
|
|
573
|
+
}
|
|
574
|
+
// Set column widths based on content
|
|
575
|
+
const colWidths = [];
|
|
576
|
+
if (wsData.length > 0) {
|
|
577
|
+
for (let colIndex = 0; colIndex < wsData[0].length; colIndex++) {
|
|
578
|
+
// Start with reasonable default width
|
|
579
|
+
let maxWidth = 10;
|
|
580
|
+
// Check all rows for this column
|
|
581
|
+
for (let rowIndex = 0; rowIndex < wsData.length; rowIndex++) {
|
|
582
|
+
const cell = wsData[rowIndex][colIndex];
|
|
583
|
+
if (cell && cell.v) {
|
|
584
|
+
maxWidth = Math.max(maxWidth, String(cell.v).length);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// Add some padding and cap at 50 characters
|
|
588
|
+
colWidths.push(Math.min(maxWidth + 2, 50));
|
|
589
|
+
}
|
|
590
|
+
worksheet['!cols'] = colWidths.map(width => ({ wch: width }));
|
|
591
|
+
}
|
|
592
|
+
// Add the worksheet to the workbook
|
|
593
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, "Pivot Table");
|
|
594
|
+
// Convert workbook to blob
|
|
595
|
+
const workbookBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
|
|
596
|
+
const blob = new Blob([workbookBuffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
597
|
+
return blob;
|
|
598
|
+
}
|
|
443
599
|
}
|
|
444
600
|
exports.default = PivotChart;
|
|
@@ -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
|
export interface PivotChartDesignerComponentProps {
|
|
5
4
|
design: any;
|
|
@@ -19,24 +18,10 @@ export default class PivotChartDesignerComponent extends React.Component<PivotCh
|
|
|
19
18
|
handleRowChange: (axis: any) => any;
|
|
20
19
|
handleFilterChange: (filter: any) => any;
|
|
21
20
|
handleIntersectionValueAxisChange: (valueAxis: any) => any;
|
|
22
|
-
renderTable(): React.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}, HTMLElement> | null;
|
|
28
|
-
renderStriping(): React.CElement<{
|
|
29
|
-
label: React.ReactNode;
|
|
30
|
-
labelMuted?: boolean;
|
|
31
|
-
hint?: React.ReactNode;
|
|
32
|
-
help?: React.ReactNode;
|
|
33
|
-
required?: boolean;
|
|
34
|
-
hasSuccess?: boolean;
|
|
35
|
-
hasWarnings?: boolean;
|
|
36
|
-
hasErrors?: boolean;
|
|
37
|
-
horizontal?: boolean;
|
|
38
|
-
}, ui.FormGroup> | null;
|
|
39
|
-
renderSetup(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
40
|
-
render(): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
21
|
+
renderTable(): React.JSX.Element;
|
|
22
|
+
renderFilter(): React.JSX.Element | null;
|
|
23
|
+
renderStriping(): React.JSX.Element | null;
|
|
24
|
+
renderSetup(): React.JSX.Element;
|
|
25
|
+
render(): React.JSX.Element;
|
|
41
26
|
}
|
|
42
27
|
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 uuid_1 = __importDefault(require("uuid"));
|
|
33
32
|
const ui = __importStar(require("@mwater/react-library/lib/bootstrap"));
|
|
34
33
|
const expressions_ui_1 = require("@mwater/expressions-ui");
|
|
@@ -76,84 +75,55 @@ class PivotChartDesignerComponent extends react_1.default.Component {
|
|
|
76
75
|
return this.updateDesign({ intersections });
|
|
77
76
|
};
|
|
78
77
|
renderTable() {
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
return (react_1.default.createElement("div", { className: "mb-3" },
|
|
79
|
+
react_1.default.createElement("label", { className: "text-muted" },
|
|
80
|
+
react_1.default.createElement("i", { className: "fa fa-database" }),
|
|
81
|
+
" ",
|
|
82
|
+
T `Data Source`),
|
|
83
|
+
": ",
|
|
84
|
+
" ",
|
|
85
|
+
react_1.default.createElement(expressions_ui_2.TableSelectComponent, { schema: this.props.schema, value: this.props.design.table, onChange: this.handleTableChange, filter: this.props.design.filter, onFilterChange: this.handleFilterChange })));
|
|
86
86
|
}
|
|
87
87
|
renderFilter() {
|
|
88
88
|
// If no table, hide
|
|
89
89
|
if (!this.props.design.table) {
|
|
90
90
|
return null;
|
|
91
91
|
}
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
return (react_1.default.createElement("div", { className: "mb-3" },
|
|
93
|
+
react_1.default.createElement("label", { className: "text-muted" },
|
|
94
|
+
react_1.default.createElement("span", { className: "fas fa-filter" }),
|
|
95
|
+
" ",
|
|
96
|
+
T `Filters`),
|
|
97
|
+
react_1.default.createElement("div", { style: { marginLeft: 8 } },
|
|
98
|
+
react_1.default.createElement(expressions_ui_1.FilterExprComponent, { schema: this.props.schema, dataSource: this.props.dataSource, onChange: this.handleFilterChange, table: this.props.design.table, value: this.props.design.filter }))));
|
|
99
99
|
}
|
|
100
100
|
renderStriping() {
|
|
101
101
|
// If no table, hide
|
|
102
102
|
if (!this.props.design.table) {
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
return (react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Striping` },
|
|
106
|
+
react_1.default.createElement(ui.Radio, { key: "none", inline: true, radioValue: null, value: this.props.design.striping || null, onChange: (value) => this.updateDesign({ striping: value }) }, T `None`),
|
|
107
|
+
react_1.default.createElement(ui.Radio, { key: "columns", inline: true, radioValue: "columns", value: this.props.design.striping, onChange: (value) => this.updateDesign({ striping: value }) }, T `Columns`),
|
|
108
|
+
react_1.default.createElement(ui.Radio, { key: "rows", inline: true, value: this.props.design.striping, radioValue: "rows", onChange: (value) => this.updateDesign({ striping: value }) }, T `Rows`)));
|
|
109
109
|
}
|
|
110
110
|
// Show setup options
|
|
111
111
|
renderSetup() {
|
|
112
112
|
const intersectionId = `${this.props.design.rows[0].id}:${this.props.design.columns[0].id}`;
|
|
113
|
-
return
|
|
114
|
-
labelMuted: true,
|
|
115
|
-
|
|
116
|
-
help: T `Field to optionally make
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
table: this.props.design.table,
|
|
121
|
-
types: ["enum", "enumset", "text", "boolean", "date"],
|
|
122
|
-
aggrNeed: "none",
|
|
123
|
-
value: this.props.design.columns[0].valueAxis,
|
|
124
|
-
onChange: this.handleColumnChange,
|
|
125
|
-
filters: this.props.filters
|
|
126
|
-
})), R(ui.FormGroup, {
|
|
127
|
-
labelMuted: true,
|
|
128
|
-
label: T `Rows`,
|
|
129
|
-
help: T `Field to optionally make rows out of`
|
|
130
|
-
}, R(AxisComponent_1.default, {
|
|
131
|
-
schema: this.props.schema,
|
|
132
|
-
dataSource: this.props.dataSource,
|
|
133
|
-
table: this.props.design.table,
|
|
134
|
-
types: ["enum", "enumset", "text", "boolean", "date"],
|
|
135
|
-
aggrNeed: "none",
|
|
136
|
-
value: this.props.design.rows[0].valueAxis,
|
|
137
|
-
onChange: this.handleRowChange,
|
|
138
|
-
filters: this.props.filters
|
|
139
|
-
})), R(ui.FormGroup, {
|
|
140
|
-
labelMuted: true,
|
|
141
|
-
label: T `Value`,
|
|
142
|
-
help: T `Field show in cells`
|
|
143
|
-
}, R(AxisComponent_1.default, {
|
|
144
|
-
schema: this.props.schema,
|
|
145
|
-
dataSource: this.props.dataSource,
|
|
146
|
-
table: this.props.design.table,
|
|
147
|
-
types: ["enum", "text", "boolean", "date", "number"],
|
|
148
|
-
aggrNeed: "required",
|
|
149
|
-
value: this.props.design.intersections[intersectionId].valueAxis,
|
|
150
|
-
onChange: this.handleIntersectionValueAxisChange,
|
|
151
|
-
showFormat: true,
|
|
152
|
-
filters: this.props.filters
|
|
153
|
-
})));
|
|
113
|
+
return (react_1.default.createElement("div", null,
|
|
114
|
+
react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Columns`, help: T `Field to optionally make columns out of` },
|
|
115
|
+
react_1.default.createElement(AxisComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, table: this.props.design.table, types: ["enum", "enumset", "text", "boolean", "date"], aggrNeed: "none", value: this.props.design.columns[0].valueAxis, onChange: this.handleColumnChange, filters: this.props.filters })),
|
|
116
|
+
react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Rows`, help: T `Field to optionally make rows out of` },
|
|
117
|
+
react_1.default.createElement(AxisComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, table: this.props.design.table, types: ["enum", "enumset", "text", "boolean", "date"], aggrNeed: "none", value: this.props.design.rows[0].valueAxis, onChange: this.handleRowChange, filters: this.props.filters })),
|
|
118
|
+
react_1.default.createElement(ui.FormGroup, { labelMuted: true, label: T `Value`, help: T `Field show in cells` },
|
|
119
|
+
react_1.default.createElement(AxisComponent_1.default, { schema: this.props.schema, dataSource: this.props.dataSource, table: this.props.design.table, types: ["enum", "text", "boolean", "date", "number"], aggrNeed: "required", value: this.props.design.intersections[intersectionId].valueAxis, onChange: this.handleIntersectionValueAxisChange, showFormat: true, filters: this.props.filters }))));
|
|
154
120
|
}
|
|
155
121
|
render() {
|
|
156
|
-
return
|
|
122
|
+
return (react_1.default.createElement("div", null,
|
|
123
|
+
this.renderTable(),
|
|
124
|
+
this.state.isNew && this.props.design.table ? this.renderSetup() : undefined,
|
|
125
|
+
this.renderFilter(),
|
|
126
|
+
this.renderStriping()));
|
|
157
127
|
}
|
|
158
128
|
}
|
|
159
129
|
exports.default = PivotChartDesignerComponent;
|
|
@@ -5,6 +5,10 @@ import { PivotChartLayout, PivotChartLayoutCell } from "./PivotChartLayout";
|
|
|
5
5
|
export type PivotChartData = {
|
|
6
6
|
[intersectionId: string]: any[];
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Builds pivot table layout from the design and data
|
|
10
|
+
* See PivotChartDesign.ts for more details
|
|
11
|
+
*/
|
|
8
12
|
export default class PivotChartLayoutBuilder {
|
|
9
13
|
schema: Schema;
|
|
10
14
|
exprUtils: ExprUtils;
|
|
@@ -34,8 +34,10 @@ const PivotChartUtils = __importStar(require("./PivotChartUtils"));
|
|
|
34
34
|
const canonical_json_1 = __importDefault(require("canonical-json"));
|
|
35
35
|
const maxRows = 500;
|
|
36
36
|
const maxColumns = 50;
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Builds pivot table layout from the design and data
|
|
39
|
+
* See PivotChartDesign.ts for more details
|
|
40
|
+
*/
|
|
39
41
|
class PivotChartLayoutBuilder {
|
|
40
42
|
schema;
|
|
41
43
|
exprUtils;
|
|
@@ -26,49 +26,10 @@ export default class PivotChartLayoutComponent extends React.Component<PivotChar
|
|
|
26
26
|
};
|
|
27
27
|
constructor(props: PivotChartLayoutComponentProps);
|
|
28
28
|
recordCellComp: (rowIndex: any, columnIndex: any, comp: any) => any;
|
|
29
|
-
renderRow(row: PivotChartLayoutRow, rowIndex: number): React.
|
|
30
|
-
renderHoverPlusIcon: (key: any, x: any, y: any, onClick: any) => React.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
position: "absolute";
|
|
35
|
-
left: number;
|
|
36
|
-
top: number;
|
|
37
|
-
border: string;
|
|
38
|
-
backgroundColor: "white";
|
|
39
|
-
paddingLeft: number;
|
|
40
|
-
paddingRight: number;
|
|
41
|
-
paddingTop: number;
|
|
42
|
-
color: "#337ab7";
|
|
43
|
-
fontSize: number;
|
|
44
|
-
cursor: "pointer";
|
|
45
|
-
opacity: number;
|
|
46
|
-
};
|
|
47
|
-
}, HTMLElement>;
|
|
48
|
-
renderHoverRemoveIcon: (key: any, x: any, y: any, onClick: any) => React.DetailedReactHTMLElement<{
|
|
49
|
-
key: any;
|
|
50
|
-
onClick: any;
|
|
51
|
-
style: {
|
|
52
|
-
position: "absolute";
|
|
53
|
-
left: number;
|
|
54
|
-
top: number;
|
|
55
|
-
border: string;
|
|
56
|
-
backgroundColor: "white";
|
|
57
|
-
paddingLeft: number;
|
|
58
|
-
paddingRight: number;
|
|
59
|
-
paddingTop: number;
|
|
60
|
-
color: "#337ab7";
|
|
61
|
-
fontSize: number;
|
|
62
|
-
cursor: "pointer";
|
|
63
|
-
opacity: number;
|
|
64
|
-
};
|
|
65
|
-
}, HTMLElement>;
|
|
66
|
-
renderHoverControls: () => React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | null | undefined;
|
|
67
|
-
render(): React.DetailedReactHTMLElement<{
|
|
68
|
-
style: {
|
|
69
|
-
position: "relative";
|
|
70
|
-
};
|
|
71
|
-
onMouseLeave: () => void;
|
|
72
|
-
}, HTMLElement>;
|
|
29
|
+
renderRow(row: PivotChartLayoutRow, rowIndex: number): React.JSX.Element;
|
|
30
|
+
renderHoverPlusIcon: (key: any, x: any, y: any, onClick: any) => React.JSX.Element;
|
|
31
|
+
renderHoverRemoveIcon: (key: any, x: any, y: any, onClick: any) => React.JSX.Element;
|
|
32
|
+
renderHoverControls: () => React.JSX.Element | null | undefined;
|
|
33
|
+
render(): React.JSX.Element;
|
|
73
34
|
}
|
|
74
35
|
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 color_1 = __importDefault(require("color"));
|
|
33
32
|
const ui = __importStar(require("@mwater/react-library/lib/bootstrap"));
|
|
34
33
|
const classnames_1 = __importDefault(require("classnames"));
|
|
@@ -55,28 +54,15 @@ class PivotChartLayoutComponent extends react_1.default.Component {
|
|
|
55
54
|
}
|
|
56
55
|
};
|
|
57
56
|
renderRow(row, rowIndex) {
|
|
58
|
-
return
|
|
59
|
-
return
|
|
60
|
-
ref: this.recordCellComp.bind(null, rowIndex, columnIndex),
|
|
61
|
-
key: columnIndex,
|
|
62
|
-
layout: this.props.layout,
|
|
63
|
-
rowIndex,
|
|
64
|
-
columnIndex,
|
|
65
|
-
onHover: this.props.editable ? () => this.setState({ hoverSection: cell.section ?? null }) : undefined,
|
|
66
|
-
hoverSection: this.props.editable ? this.state.hoverSection : undefined,
|
|
67
|
-
onEditSection: this.props.onEditSection ? this.props.onEditSection.bind(null, cell.section) : undefined,
|
|
68
|
-
onSummarizeSegment: this.props.onSummarizeSegment
|
|
57
|
+
return react_1.default.createElement("tr", { key: rowIndex }, lodash_1.default.map(row.cells, (cell, columnIndex) => {
|
|
58
|
+
return react_1.default.createElement(LayoutCellComponent, { ref: this.recordCellComp.bind(null, rowIndex, columnIndex), key: columnIndex, layout: this.props.layout, rowIndex: rowIndex, columnIndex: columnIndex, onHover: this.props.editable ? () => this.setState({ hoverSection: cell.section ?? null }) : undefined, hoverSection: this.props.editable ? this.state.hoverSection : undefined, onEditSection: this.props.onEditSection ? this.props.onEditSection.bind(null, cell.section) : undefined, onSummarizeSegment: this.props.onSummarizeSegment
|
|
69
59
|
? this.props.onSummarizeSegment.bind(null, cell.section)
|
|
70
|
-
: undefined
|
|
71
|
-
});
|
|
60
|
+
: undefined });
|
|
72
61
|
}));
|
|
73
62
|
}
|
|
74
63
|
renderHoverPlusIcon = (key, x, y, onClick) => {
|
|
75
64
|
// Render a plus box
|
|
76
|
-
return
|
|
77
|
-
key,
|
|
78
|
-
onClick,
|
|
79
|
-
style: {
|
|
65
|
+
return react_1.default.createElement("div", { key: key, onClick: onClick, style: {
|
|
80
66
|
position: "absolute",
|
|
81
67
|
left: x - 7,
|
|
82
68
|
top: y - 6,
|
|
@@ -89,15 +75,12 @@ class PivotChartLayoutComponent extends react_1.default.Component {
|
|
|
89
75
|
fontSize: 9,
|
|
90
76
|
cursor: "pointer",
|
|
91
77
|
opacity: 0.8
|
|
92
|
-
}
|
|
93
|
-
|
|
78
|
+
} },
|
|
79
|
+
react_1.default.createElement(ui.Icon, { id: "fa-plus" }));
|
|
94
80
|
};
|
|
95
81
|
renderHoverRemoveIcon = (key, x, y, onClick) => {
|
|
96
82
|
// Render a plus box
|
|
97
|
-
return
|
|
98
|
-
key,
|
|
99
|
-
onClick,
|
|
100
|
-
style: {
|
|
83
|
+
return react_1.default.createElement("div", { key: key, onClick: onClick, style: {
|
|
101
84
|
position: "absolute",
|
|
102
85
|
left: x - 7,
|
|
103
86
|
top: y - 6,
|
|
@@ -110,8 +93,8 @@ class PivotChartLayoutComponent extends react_1.default.Component {
|
|
|
110
93
|
fontSize: 9,
|
|
111
94
|
cursor: "pointer",
|
|
112
95
|
opacity: 0.8
|
|
113
|
-
}
|
|
114
|
-
|
|
96
|
+
} },
|
|
97
|
+
react_1.default.createElement(ui.Icon, { id: "fa-remove" }));
|
|
115
98
|
};
|
|
116
99
|
// Render floating hover controls
|
|
117
100
|
renderHoverControls = () => {
|
|
@@ -175,18 +158,11 @@ class PivotChartLayoutComponent extends react_1.default.Component {
|
|
|
175
158
|
if (["row", "column"].includes(sectionType) && this.props.onRemoveSegment) {
|
|
176
159
|
controls.push(this.renderHoverRemoveIcon("topright", maxX, minY, this.props.onRemoveSegment.bind(null, this.state.hoverSection)));
|
|
177
160
|
}
|
|
178
|
-
return
|
|
161
|
+
return react_1.default.createElement("div", { key: "hover-controls" }, controls);
|
|
179
162
|
};
|
|
180
163
|
render() {
|
|
181
|
-
return
|
|
182
|
-
style
|
|
183
|
-
onMouseLeave: () => this.setState({ hoverSection: null })
|
|
184
|
-
},
|
|
185
|
-
// Define CSS classes to keep HTML as small as possible
|
|
186
|
-
// https://stackoverflow.com/a/19047221/876117
|
|
187
|
-
// https://github.com/mWater/mwater-portal/issues/1183
|
|
188
|
-
// cell borders not visible in firefox when you have a cell with position relative inside a table with collapsed borders
|
|
189
|
-
R("style", null, `\
|
|
164
|
+
return react_1.default.createElement("div", { style: { position: "relative" }, onMouseLeave: () => this.setState({ hoverSection: null }) },
|
|
165
|
+
react_1.default.createElement("style", null, `\
|
|
190
166
|
.pivot-chart-table {
|
|
191
167
|
width: 100%;
|
|
192
168
|
border-spacing: 0;
|
|
@@ -214,13 +190,19 @@ vertical-align: top;
|
|
|
214
190
|
.pivot-chart-table .br1 { border-right: solid 1px #f4f4f4 }
|
|
215
191
|
.pivot-chart-table .br2 { border-right: solid 1px #ccc }
|
|
216
192
|
.pivot-chart-table .br3 { border-right: solid 1px #888 }\
|
|
217
|
-
`),
|
|
218
|
-
?
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
193
|
+
`),
|
|
194
|
+
this.props.layout.tooManyRows ? (react_1.default.createElement("div", { className: "text-warning", style: { fontSize: 12 } },
|
|
195
|
+
react_1.default.createElement("i", { className: "fa fa-exclamation-circle" }),
|
|
196
|
+
T `Warning: Too many rows in table to display`)) : undefined,
|
|
197
|
+
this.props.layout.tooManyColumns ? (react_1.default.createElement("div", { className: "text-warning", style: { fontSize: 12 } },
|
|
198
|
+
react_1.default.createElement("i", { className: "fa fa-exclamation-circle" }),
|
|
199
|
+
T `Warning: Too many columns in table to display`)) : undefined,
|
|
200
|
+
react_1.default.createElement("div", { style: { position: "relative" } },
|
|
201
|
+
react_1.default.createElement("table", { className: "pivot-chart-table" },
|
|
202
|
+
react_1.default.createElement("tbody", null, lodash_1.default.map(this.props.layout.rows, (row, rowIndex) => {
|
|
203
|
+
return this.renderRow(row, rowIndex);
|
|
204
|
+
}))),
|
|
205
|
+
this.renderHoverControls()));
|
|
224
206
|
}
|
|
225
207
|
}
|
|
226
208
|
exports.default = PivotChartLayoutComponent;
|
|
@@ -250,12 +232,12 @@ class LayoutCellComponent extends react_1.default.Component {
|
|
|
250
232
|
if (!cell.section) {
|
|
251
233
|
return null;
|
|
252
234
|
}
|
|
253
|
-
return
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
: undefined);
|
|
235
|
+
return react_1.default.createElement("span", { style: { fontSize: "90%" } },
|
|
236
|
+
react_1.default.createElement("a", { className: "link-plain", onClick: this.props.onEditSection }, T `Edit`),
|
|
237
|
+
cell.summarize ? [
|
|
238
|
+
react_1.default.createElement("span", { className: "text-muted" }, " / "),
|
|
239
|
+
react_1.default.createElement("a", { className: "link-plain", onClick: this.props.onSummarizeSegment }, T `Summarize`)
|
|
240
|
+
] : undefined);
|
|
259
241
|
}
|
|
260
242
|
render() {
|
|
261
243
|
const cell = this.props.layout.rows[this.props.rowIndex].cells[this.props.columnIndex];
|
|
@@ -291,10 +273,10 @@ class LayoutCellComponent extends react_1.default.Component {
|
|
|
291
273
|
textColor = lightness < 0.5 ? "rgb(204,204,204)" : undefined;
|
|
292
274
|
}
|
|
293
275
|
const style = {
|
|
294
|
-
backgroundColor,
|
|
276
|
+
backgroundColor: backgroundColor || undefined,
|
|
295
277
|
textAlign: cell.align,
|
|
296
278
|
cursor: isHover && !cell.unconfigured ? "pointer" : undefined,
|
|
297
|
-
color: textColor
|
|
279
|
+
color: textColor || undefined
|
|
298
280
|
};
|
|
299
281
|
const classes = (0, classnames_1.default)({
|
|
300
282
|
cell: true,
|
|
@@ -318,18 +300,11 @@ class LayoutCellComponent extends react_1.default.Component {
|
|
|
318
300
|
fontStyle: cell.italic ? "italic" : undefined,
|
|
319
301
|
marginLeft: cell.indent ? cell.indent * 5 : undefined
|
|
320
302
|
};
|
|
321
|
-
return
|
|
322
|
-
ref: (c) => {
|
|
303
|
+
return react_1.default.createElement("td", { ref: (c) => {
|
|
323
304
|
this.tdComponent = c;
|
|
324
|
-
},
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
style,
|
|
329
|
-
colSpan: cell.columnSpan || null,
|
|
330
|
-
rowSpan: cell.rowSpan || null
|
|
331
|
-
}, R("span", { style: innerStyle }, cell.unconfigured && this.props.onEditSection
|
|
332
|
-
? this.renderUnconfigured(cell)
|
|
333
|
-
: cell.text || "\u00A0\u00A0\u00A0"));
|
|
305
|
+
}, onMouseEnter: this.props.onHover, onClick: this.handleClick, className: classes, style: style, colSpan: cell.columnSpan || undefined, rowSpan: cell.rowSpan || undefined },
|
|
306
|
+
react_1.default.createElement("span", { style: innerStyle }, cell.unconfigured && this.props.onEditSection
|
|
307
|
+
? this.renderUnconfigured(cell)
|
|
308
|
+
: cell.text || "\u00A0\u00A0\u00A0"));
|
|
334
309
|
}
|
|
335
310
|
}
|