UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

919 lines • 62.7 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var ag_grid_react_1 = require("ag-grid-react"); var classNames = require("classnames"); var CustomEvent = require("custom-event"); var invariant = require("invariant"); var React = require("react"); require("../../../styles/css/pivotTable.css"); var visualizationTypes_1 = require("../../constants/visualizationTypes"); var domUtils_1 = require("../../helpers/domUtils"); var headerPredicate_1 = require("../../helpers/headerPredicate"); var tableCell_1 = require("../../helpers/tableCell"); var DrillEvents_1 = require("../../interfaces/DrillEvents"); var MappingHeader_1 = require("../../interfaces/MappingHeader"); var PivotTable_1 = require("../../interfaces/PivotTable"); var LoadingComponent_1 = require("../simple/LoadingComponent"); var utils_1 = require("../visualizations/table/totals/utils"); var BaseVisualization_1 = require("./base/BaseVisualization"); var VisualizationLoadingHOC_1 = require("./base/VisualizationLoadingHOC"); var aggregationsMenuHelper_1 = require("./pivotTable/aggregationsMenuHelper"); var agGridApiWrapper_1 = require("./pivotTable/agGridApiWrapper"); var agGridConst_1 = require("./pivotTable/agGridConst"); var agGridDataSource_1 = require("./pivotTable/agGridDataSource"); var agGridDrilling_1 = require("./pivotTable/agGridDrilling"); var agGridSorting_1 = require("./pivotTable/agGridSorting"); var agGridUtils_1 = require("./pivotTable/agGridUtils"); var ColumnGroupHeader_1 = require("./pivotTable/ColumnGroupHeader"); var ColumnHeader_1 = require("./pivotTable/ColumnHeader"); var GroupingProvider_1 = require("./pivotTable/GroupingProvider"); var RowLoadingElement_1 = require("./pivotTable/RowLoadingElement"); var stickyRowHandler_1 = require("./pivotTable/stickyRowHandler"); var utils_2 = require("../../helpers/utils"); var drilldownEventing_1 = require("../visualizations/utils/drilldownEventing"); var drilldownEventingLegacy_1 = require("../visualizations/utils/drilldownEventingLegacy"); var cloneDeep = require("lodash/cloneDeep"); var get = require("lodash/get"); var isEqual = require("lodash/isEqual"); var noop = require("lodash/noop"); var sumBy = require("lodash/sumBy"); var difference = require("lodash/difference"); var debounce = require("lodash/debounce"); var agGridColumnSizing_1 = require("./pivotTable/agGridColumnSizing"); var agColumnWrapper_1 = require("./pivotTable/agColumnWrapper"); var ResizedColumnsStore_1 = require("./pivotTable/ResizedColumnsStore"); var DEFAULT_ROW_HEIGHT = 28; var DEFAULT_AUTOSIZE_PADDING = 10; var AG_NUMERIC_CELL_CLASSNAME = "ag-numeric-cell"; var AG_NUMERIC_HEADER_CLASSNAME = "ag-numeric-header"; exports.WATCHING_TABLE_RENDERED_INTERVAL = 500; var AGGRID_RENDER_NEW_COLUMNS_TIMEOUT = 100; var AGGRID_BEFORE_RESIZE_TIMEOUT = 100; var AGGRID_ON_RESIZE_TIMEOUT = 300; var COLUMN_RESIZE_TIMEOUT = 300; exports.DEFAULT_COLUMN_WIDTH = 200; /** * Pivot Table react component */ var PivotTableInner = /** @class */ (function (_super) { __extends(PivotTableInner, _super); function PivotTableInner(props) { var _this = _super.call(this, props) || this; _this.lastScrollPosition = { top: 0, left: 0, }; _this.autoResizedColumns = {}; _this.growToFittedColumns = {}; _this.resizing = false; _this.lastResizedWidth = 0; _this.lastResizedHeight = 0; _this.numberOfColumnResizedCalls = 0; _this.columnWidthsChangeWaitingForExecution = true; _this.isMetaOrCtrlKeyPressed = false; _this.isAltKeyPressed = false; // // getters / setters / manipulators // _this.setContainerRef = function (container) { _this.containerRef = container; }; _this.setGroupingProvider = function (sortedByFirstAttr) { _this.groupingProvider = GroupingProvider_1.GroupingProviderFactory.createProvider(sortedByFirstAttr); }; _this.updateGrouping = function () { _this.setGroupingProvider(_this.props.groupRows && _this.state.sortedByFirstAttribute); }; _this.getExecutionResponse = function () { return _this.state.execution ? _this.state.execution.executionResponse : null; }; _this.getExecutionResult = function () { return _this.state.execution ? _this.state.execution.executionResult : null; }; _this.getAfmFilters = function () { return _this.props.dataSource.getAfm().filters || []; }; _this.getColumnTotals = function () { return _this.state.columnTotals; }; _this.getExecution = function () { return _this.state.execution; }; _this.getGridApi = function () { return _this.gridApi; }; _this.getColumnIds = function (columns) { return columns.map(function (column) { return column.getColId(); }); }; _this.getAutoResizedColumns = function (columns) { return columns.reduce(function (acc, col) { var _a; var columnId = agGridUtils_1.getColumnIdentifier(col); var resizedColumn = acc[columnId]; if (resizedColumn) { return acc; } return __assign({}, acc, (_a = {}, _a[columnId] = { width: col.getActualWidth(), }, _a)); }, _this.autoResizedColumns); }; _this.autoresizeVisibleColumns = function (columnApi, previouslyResizedColumnIds, firstCall) { if (firstCall === void 0) { firstCall = true; } return __awaiter(_this, void 0, void 0, function () { var displayedVirtualColumns, autoWidthColumnIds; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.shouldPerformAutoresize()) { return [2 /*return*/, Promise.resolve()]; } if (!this.isColumnAutoresizeEnabled()) { return [2 /*return*/, Promise.resolve()]; } if (!firstCall) return [3 /*break*/, 2]; return [4 /*yield*/, utils_2.sleep(AGGRID_BEFORE_RESIZE_TIMEOUT)]; case 1: _a.sent(); _a.label = 2; case 2: displayedVirtualColumns = columnApi.getAllDisplayedVirtualColumns(); autoWidthColumnIds = this.getColumnIds(displayedVirtualColumns); if (previouslyResizedColumnIds.length >= autoWidthColumnIds.length) { this.autoResizedColumns = this.getAutoResizedColumns(columnApi.getAllDisplayedVirtualColumns()); return [2 /*return*/, Promise.resolve()]; } return [2 /*return*/, new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { var newColumnIds; return __generator(this, function (_a) { switch (_a.label) { case 0: newColumnIds = difference(autoWidthColumnIds, previouslyResizedColumnIds); this.autoresizeColumnsByColumnId(columnApi, newColumnIds); return [4 /*yield*/, utils_2.sleep(AGGRID_RENDER_NEW_COLUMNS_TIMEOUT)]; case 1: _a.sent(); resolve(this.autoresizeVisibleColumns(columnApi, autoWidthColumnIds, false)); return [2 /*return*/]; } }); }); })]; } }); }); }; _this.isColumnAutoresizeEnabled = function () { return _this.getDefaultWidthFromProps(_this.props) === "viewport"; }; _this.isGrowToFitEnabled = function (props) { if (props === void 0) { props = _this.props; } return props.config && props.config.columnSizing ? !!props.config.columnSizing.growToFit : false; }; _this.isPivotTableReady = function (api) { var noRowHeadersOrRows = function (executionResult) { return executionResult && (executionResult.data.length === 0 && executionResult.headerItems[0] && executionResult.headerItems[0].length === 0); }; var dataRendered = function () { var executionResult = _this.getExecutionResult(); return (noRowHeadersOrRows(executionResult) || (executionResult && api.getRenderedNodes().length > 0)); }; var tablePagesLoaded = function () { var pages = api.getCacheBlockState(); return (pages && Object.keys(pages).every(function (pageId) { return pages[pageId].pageStatus === "loaded" || pages[pageId].pageStatus === "failed"; })); }; return _this.state.execution && tablePagesLoaded() && dataRendered(); }; _this.autoresizeColumns = function (event, force, previouslyResizedColumnIds) { if (force === void 0) { force = false; } if (previouslyResizedColumnIds === void 0) { previouslyResizedColumnIds = []; } return __awaiter(_this, void 0, void 0, function () { var alreadyResized, columns; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: alreadyResized = function () { return _this.state.resized || _this.resizing; }; if (!(this.isPivotTableReady(event.api) && (!alreadyResized() || (alreadyResized() && force)))) return [3 /*break*/, 2]; this.resizing = true; // we need to know autosize width for each column, even manually resized ones, to support removal of columnWidth def from props return [4 /*yield*/, this.autoresizeVisibleColumns(event.columnApi, previouslyResizedColumnIds)]; case 1: // we need to know autosize width for each column, even manually resized ones, to support removal of columnWidth def from props _a.sent(); // after that we need to reset manually resized columns back to its manually set width by growToFit or by helper. See UT resetColumnsWidthToDefault for width priorities if (this.isGrowToFitEnabled()) { this.growToFit(event.columnApi); } else if (this.shouldPerformAutoresize() && this.isColumnAutoresizeEnabled()) { columns = this.columnApi.getAllColumns(); this.resetColumnsWidthToDefault(this.columnApi, columns); } this.resizing = false; this.setState({ resized: true, }); _a.label = 2; case 2: return [2 /*return*/]; } }); }); }; _this.gridSizeChanged = function (gridSizeChangedEvent) { return __awaiter(_this, void 0, void 0, function () { var resizedColumnsGridIds; return __generator(this, function (_a) { if (!this.resizing && (this.lastResizedWidth !== gridSizeChangedEvent.clientWidth || this.lastResizedHeight !== gridSizeChangedEvent.clientHeight)) { this.lastResizedWidth = gridSizeChangedEvent.clientWidth; this.lastResizedHeight = gridSizeChangedEvent.clientHeight; resizedColumnsGridIds = this.mapFieldIdToGridId(gridSizeChangedEvent.columnApi, Object.keys(this.autoResizedColumns)); this.autoresizeColumns(gridSizeChangedEvent, true, resizedColumnsGridIds); } return [2 /*return*/]; }); }); }; _this.gridColumnsChanged = function () { _this.updateStickyRow(); }; _this.shouldAutoResizeColumns = function () { var columnAutoresize = _this.isColumnAutoresizeEnabled() && _this.getExecution(); var growToFit = _this.isGrowToFitEnabled() && _this.getExecution(); return columnAutoresize || growToFit; }; _this.onModelUpdated = function (event) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.shouldAutoResizeColumns()) return [3 /*break*/, 2]; return [4 /*yield*/, this.autoresizeColumns(event)]; case 1: _a.sent(); this.updateStickyRow(); return [3 /*break*/, 3]; case 2: if (this.columnApi && this.isGrowToFitEnabled()) { this.growToFit(this.columnApi); } this.updateStickyRow(); _a.label = 3; case 3: return [2 /*return*/]; } }); }); }; _this.sortChanged = function (event) { return __awaiter(_this, void 0, void 0, function () { var execution, sortModel, sortItems; return __generator(this, function (_a) { execution = this.getExecution(); invariant(execution, "changing sorts without prior execution cannot work"); sortModel = event.columnApi .getAllColumns() .filter(function (col) { return col.getSort() !== undefined && col.getSort() !== null; }) .map(function (col) { return ({ colId: col.getColDef().field, sort: col.getSort(), }); }); sortItems = agGridSorting_1.getSortsFromModel(sortModel, execution); this.props.pushData({ properties: { sortItems: sortItems, }, }); this.updateGrouping(); return [2 /*return*/]; }); }); }; // // event handlers // _this.onGridReady = function (params) { _this.gridApi = params.api; _this.columnApi = params.columnApi; _this.setGridDataSource(); if (_this.props.groupRows) { stickyRowHandler_1.initializeStickyRow(_this.gridApi); } }; _this.startWatchingTableRendered = function () { var missingContainerRef = !_this.containerRef; // table having no data will be unmounted, it causes ref null var isTableRendered = _this.shouldAutoResizeColumns() ? _this.state.resized : _this.isPivotTableReady(_this.gridApi); if (missingContainerRef || isTableRendered) { _this.stopWatchingTableRendered(); } }; _this.stopWatchingTableRendered = function () { clearInterval(_this.watchingIntervalId); _this.watchingIntervalId = null; _this.props.afterRender(); }; _this.onFirstDataRendered = function () { // Since issue here is not resolved, https://github.com/ag-grid/ag-grid/issues/3263, // work-around by using 'setInterval' if (!_this.watchingIntervalId) { // onFirstDataRendered can be called multiple times _this.watchingIntervalId = window.setInterval(_this.startWatchingTableRendered, exports.WATCHING_TABLE_RENDERED_INTERVAL); } }; _this.getItemAndAttributeHeaders = function (attributeItemHeaders, columnDefs) { return Object.keys(attributeItemHeaders).reduce(function (headers, colId) { var attributeHeader = _this.getAttributeHeader(colId, columnDefs); if (attributeHeader) { headers.push(attributeItemHeaders[colId]); headers.push(attributeHeader); } return headers; }, []); }; _this.getAttributeDrillItemsForMeasureDrill = function (cellEvent, columnDefs) { var rowDrillItems = get(cellEvent, ["data", "headerItemMap"]); return _this.getItemAndAttributeHeaders(rowDrillItems, columnDefs); }; _this.isSomeTotal = function (rowType) { var isRowTotal = rowType === agGridConst_1.ROW_TOTAL; var isRowSubtotal = rowType === agGridConst_1.ROW_SUBTOTAL; return isRowTotal || isRowSubtotal; }; _this.getRowDrillItem = function (cellEvent) { return get(cellEvent, ["data", "headerItemMap", cellEvent.colDef.field]); }; _this.getDrillItems = function (cellEvent) { var colDef = cellEvent.colDef; var rowDrillItem = _this.getRowDrillItem(cellEvent); return rowDrillItem ? [rowDrillItem].concat(colDef.drillItems) : colDef.drillItems; }; _this.getDrillIntersection = function (cellEvent, drillItems, columnDefs) { var rowDrillItem = _this.getRowDrillItem(cellEvent); var completeDrillItems = rowDrillItem ? drillItems : drillItems.concat(_this.getAttributeDrillItemsForMeasureDrill(cellEvent, columnDefs)); return drilldownEventing_1.getDrillIntersection(completeDrillItems); }; _this.cellClicked = function (cellEvent) { var _a = _this.props, onDrill = _a.onDrill, executionResponse = _a.execution.executionResponse; var columnDefs = _this.state.columnDefs; var afm = _this.props.dataSource.getAfm(); var drillablePredicates = _this.getDrillablePredicates(); var colDef = cellEvent.colDef, rowIndex = cellEvent.rowIndex; var rowType = get(cellEvent, ["data", "type"], ""); if (_this.isSomeTotal(rowType)) { return false; } var drillItems = _this.getDrillItems(cellEvent); var drillableHeaders = drillItems.filter(function (drillItem) { return headerPredicate_1.isSomeHeaderPredicateMatched(drillablePredicates, drillItem, afm, executionResponse); }); if (drillableHeaders.length === 0) { return false; } var leafColumnDefs = agGridUtils_1.getTreeLeaves(columnDefs); var columnIndex = leafColumnDefs.findIndex(function (gridHeader) { return gridHeader.field === colDef.field; }); var row = agGridDrilling_1.getDrillRowData(leafColumnDefs, cellEvent.data); var intersection = _this.getDrillIntersection(cellEvent, drillItems, columnDefs); var drillContextExtended = { type: visualizationTypes_1.VisualizationTypes.TABLE, element: "cell", columnIndex: columnIndex, rowIndex: rowIndex, row: row, intersection: intersection, }; var drillEventExtended = { executionContext: afm, drillContext: drillContextExtended, }; if (onDrill) { onDrill(drillEventExtended); } return _this.handleLegacyOnFireDrillEvent(drillEventExtended, cellEvent); }; _this.handleLegacyOnFireDrillEvent = function (drillEventExtended, cellEvent) { var onFiredDrillEvent = _this.props.onFiredDrillEvent; var executionContext = drillEventExtended.executionContext, drillContext = drillEventExtended.drillContext; // this type guard is here only for casting because drillContext came from event as IDrillEventContextExtended if (DrillEvents_1.isDrillEventContextTableExtended(drillContext)) { // Old drill event for backward compatibility var drillContextLegacy = drilldownEventingLegacy_1.convertDrillContextToLegacy(drillContext, executionContext); var drillEvent = { executionContext: executionContext, drillContext: drillContextLegacy, }; if (onFiredDrillEvent(drillEvent)) { // This is needed for /analyze/embedded/ drilling with post message // tslint:disable-next-line:max-line-length // More info: https://github.com/gooddata/gdc-analytical-designer/blob/develop/test/drillEventing/drillEventing_page.html var event_1 = new CustomEvent("drill", { detail: drillEvent, bubbles: true, }); cellEvent.event.target.dispatchEvent(event_1); return true; } } return false; }; _this.getDefaultWidth = function () { return exports.DEFAULT_COLUMN_WIDTH; }; _this.onGridColumnResized = function (columnEvent) { return __awaiter(_this, void 0, void 0, function () { var executionResult; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!columnEvent.finished) { return [2 /*return*/]; // only update the height once the user is done setting the column size } executionResult = this.getExecutionResult(); if (executionResult) { this.updateDesiredHeight(executionResult); } if (!this.isManualResizing(columnEvent)) return [3 /*break*/, 4]; this.numberOfColumnResizedCalls++; return [4 /*yield*/, utils_2.sleep(COLUMN_RESIZE_TIMEOUT)]; case 1: _a.sent(); if (!(this.numberOfColumnResizedCalls === PivotTable_1.UIClick.DOUBLE_CLICK)) return [3 /*break*/, 3]; this.numberOfColumnResizedCalls = 0; return [4 /*yield*/, this.onColumnsManualReset(columnEvent.columns)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: if (this.numberOfColumnResizedCalls === PivotTable_1.UIClick.CLICK) { this.numberOfColumnResizedCalls = 0; this.onColumnsManualResized(columnEvent.columns); } _a.label = 4; case 4: return [2 /*return*/]; } }); }); }; _this.onColumnsManualReset = function (columns) { return __awaiter(_this, void 0, void 0, function () { var columnsToReset, _i, columnsToReset_1, column; return __generator(this, function (_a) { switch (_a.label) { case 0: columnsToReset = columns; if (this.isAllMeasureResizeOperation(columns)) { this.resizedColumnsStore.removeAllMeasureColumns(); columnsToReset = this.getAllMeasureColumns(); } if (this.isWeakMeasureResizeOperation(columns)) { columnsToReset = this.resizedColumnsStore.getMatchingColumnsByMeasure(columns[0], this.getAllMeasureColumns()); this.resizedColumnsStore.removeWeakMeasureColumn(columns[0]); } _i = 0, columnsToReset_1 = columnsToReset; _a.label = 1; case 1: if (!(_i < columnsToReset_1.length)) return [3 /*break*/, 4]; column = columnsToReset_1[_i]; return [4 /*yield*/, this.resetResizedColumn(column)]; case 2: _a.sent(); _a.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: this.afterOnResizeColumns(); return [2 /*return*/]; } }); }); }; _this.onColumnsManualResized = function (columns) { if (_this.isAllMeasureResizeOperation(columns)) { agGridColumnSizing_1.resizeAllMeasuresColumns(_this.columnApi, _this.resizedColumnsStore, columns[0]); } else if (_this.isWeakMeasureResizeOperation(columns)) { agGridColumnSizing_1.resizeWeakMeasureColumns(_this.columnApi, _this.resizedColumnsStore, columns[0]); } else { columns.forEach(function (column) { _this.resizedColumnsStore.addToManuallyResizedColumn(column); }); } _this.afterOnResizeColumns(); }; _this.onMenuAggregationClick = function (menuAggregationClickConfig) { var newColumnTotals = aggregationsMenuHelper_1.getUpdatedColumnTotals(_this.getColumnTotals(), menuAggregationClickConfig); _this.props.pushData({ properties: { totals: newColumnTotals, }, }); _this.setState({ columnTotals: newColumnTotals }); _this.updateGrouping(); }; _this.onBodyScroll = function (event) { var scrollPosition = { top: Math.max(event.top, 0), left: event.left, }; _this.updateStickyRowContent(scrollPosition); }; _this.onContainerMouseDown = function (event) { if (event.target && _this.isHeaderResizer(event.target)) { event.stopPropagation(); } _this.isMetaOrCtrlKeyPressed = event.metaKey || event.ctrlKey; _this.isAltKeyPressed = event.altKey; }; _this.getColumnWidths = function (props) { return props.config && props.config.columnSizing && props.config.columnSizing.columnWidths; }; _this.hasColumnWidths = function () { return !!_this.getColumnWidths(_this.props); }; _this.getDefaultWidthFromProps = function (props) { return ((props.config && props.config.columnSizing && props.config.columnSizing.defaultWidth) || "unset"); }; // // grid options & styling // _this.createGridOptions = function () { var _a; var _b = _this.state, columnDefs = _b.columnDefs, rowData = _b.rowData; var pageSize = _this.props.pageSize; var separators = get(_this.props, ["config", "separators"], undefined); var menu = get(_this.props, ["config", "menu"]); var commonHeaderComponentParams = { onMenuAggregationClick: _this.onMenuAggregationClick, getExecutionResponse: _this.getExecutionResponse, getColumnTotals: _this.getColumnTotals, getAfmFilters: _this.getAfmFilters, intl: _this.props.intl, }; return { // Initial data columnDefs: columnDefs, rowData: rowData, defaultColDef: { cellClass: _this.getCellClass(null), headerComponentFramework: ColumnHeader_1.default, headerComponentParams: __assign({ menu: menu, enableSorting: true }, commonHeaderComponentParams), minWidth: agGridColumnSizing_1.MIN_WIDTH, sortable: true, resizable: true, }, defaultColGroupDef: { headerClass: _this.getHeaderClass(null), children: [], headerGroupComponentFramework: ColumnGroupHeader_1.default, headerGroupComponentParams: __assign({ menu: menu }, commonHeaderComponentParams), }, onCellClicked: _this.cellClicked, onSortChanged: _this.sortChanged, onColumnResized: _this.onGridColumnResized, onGridSizeChanged: _this.gridSizeChanged, onGridColumnsChanged: _this.gridColumnsChanged, // Basic options suppressMovableColumns: true, suppressCellSelection: true, suppressAutoSize: _this.hasColumnWidths(), enableFilter: false, // infinite scrolling model rowModelType: "infinite", paginationPageSize: pageSize, cacheOverflowSize: pageSize, cacheBlockSize: pageSize, maxConcurrentDatasourceRequests: 1, infiniteInitialRowCount: _this.getInfiniteInitialRowCountRowCount(), maxBlocksInCache: 10, onGridReady: _this.onGridReady, onFirstDataRendered: _this.onFirstDataRendered, onModelUpdated: _this.onModelUpdated, onBodyScroll: _this.onBodyScroll, // this provides persistent row selection (if enabled) getRowNodeId: agGridUtils_1.getRowNodeId, // Column types columnTypes: (_a = {}, _a[agGridConst_1.ROW_ATTRIBUTE_COLUMN] = { cellClass: _this.getCellClass("gd-row-attribute-column"), headerClass: _this.getHeaderClass("gd-row-attribute-column-header"), colSpan: function (params) { if ( // params.data is undefined when rows are in loading state params.data && params.data.colSpan && utils_1.AVAILABLE_TOTALS.find(function (item) { return item === params.data[params.data.colSpan.headerKey]; })) { return params.data.colSpan.count; } return 1; }, valueFormatter: function (params) { return params.value === undefined ? null : params.value; }, cellRenderer: agGridUtils_1.cellRenderer, }, _a[agGridConst_1.COLUMN_ATTRIBUTE_COLUMN] = { cellClass: _this.getCellClass("gd-column-attribute-column"), headerClass: _this.getHeaderClass("gd-column-attribute-column-header"), }, _a[agGridConst_1.MEASURE_COLUMN] = { cellClass: _this.getCellClass(classNames(AG_NUMERIC_CELL_CLASSNAME, "gd-measure-column")), headerClass: _this.getHeaderClass(classNames(AG_NUMERIC_HEADER_CLASSNAME, "gd-measure-column-header")), // wrong params type from ag-grid, we need any valueFormatter: function (params) { return agGridUtils_1.isMeasureColumnReadyToRender(params, _this.state.execution) ? tableCell_1.getMeasureCellFormattedValue(params.value, agGridUtils_1.getMeasureFormat(params.colDef, _this.state.execution), separators) : null; }, cellStyle: function (params) { return agGridUtils_1.isMeasureColumnReadyToRender(params, _this.state.execution) ? tableCell_1.getMeasureCellStyle(params.value, agGridUtils_1.getMeasureFormat(params.colDef, _this.state.execution), separators, true) : null; }, cellRenderer: agGridUtils_1.cellRenderer, }, _a), // Custom renderers frameworkComponents: { // any is needed here because of incompatible types with AgGridReact types loadingRenderer: RowLoadingElement_1.RowLoadingElement, }, // Custom CSS classes rowClass: "gd-table-row", rowHeight: DEFAULT_ROW_HEIGHT, autoSizePadding: DEFAULT_AUTOSIZE_PADDING, }; }; /** * getCellClass returns class for drillable cells. (maybe format in the future as well) */ _this.getCellClass = function (classList) { return function (cellClassParams) { var _a = _this.props, dataSource = _a.dataSource, executionResponse = _a.execution.executionResponse; var rowIndex = cellClassParams.rowIndex; var colDef = cellClassParams.colDef; var drillablePredicates = _this.getDrillablePredicates(); // return none if no drillableItems are specified var afm = dataSource.getAfm(); var hasDrillableHeader = false; var rowType = get(cellClassParams, ["data", "type"], ""); var isRowTotal = rowType === agGridConst_1.ROW_TOTAL; var isRowSubtotal = rowType === agGridConst_1.ROW_SUBTOTAL; if (drillablePredicates.length !== 0 && !isRowTotal && !isRowSubtotal) { var rowDrillItem = get(cellClassParams, ["data", "headerItemMap", colDef.field]); var headers = rowDrillItem ? colDef.drillItems.concat([rowDrillItem]) : colDef.drillItems; hasDrillableHeader = headers.some(function (drillItem) { return headerPredicate_1.isSomeHeaderPredicateMatched(drillablePredicates, drillItem, afm, executionResponse); }); } var attributeId = colDef.field; var isPinnedRow = cellClassParams.node.isRowPinned(); var hiddenCell = !isPinnedRow && _this.groupingProvider.isRepeatedValue(attributeId, rowIndex); var rowSeparator = !hiddenCell && _this.groupingProvider.isGroupBoundary(rowIndex); var subtotalStyle = get(cellClassParams, ["data", "subtotalStyle"]); return classNames(classList, tableCell_1.getCellClassNames(rowIndex, colDef.index, hasDrillableHeader), colDef.index !== undefined ? "gd-column-index-" + colDef.index : null, colDef.measureIndex !== undefined ? "gd-column-measure-" + colDef.measureIndex : null, isRowTotal ? "gd-row-total" : null, subtotalStyle ? "gd-table-row-subtotal gd-table-row-subtotal-" + subtotalStyle : null, hiddenCell ? "gd-cell-hide s-gd-cell-hide" : null, rowSeparator ? "gd-table-row-separator s-gd-table-row-separator" : null); }; }; _this.getHeaderClass = function (classList) { return function (headerClassParams) { var colDef = headerClassParams.colDef; var field = colDef.field, measureIndex = colDef.measureIndex, index = colDef.index; var treeIndexes = colDef ? agGridUtils_1.indexOfTreeNode(colDef, _this.state.columnDefs, function (nodeA, nodeB) { return nodeA.field !== undefined && nodeA.field === nodeB.field; }) : null; var colGroupIndex = treeIndexes ? treeIndexes[treeIndexes.length - 1] : null; var isFirstColumn = treeIndexes !== null && !treeIndexes.some(function (index) { return index !== 0; }); return classNames(classList, "gd-column-group-header", colGroupIndex !== null ? "gd-column-group-header-" + colGroupIndex : null, colGroupIndex !== null ? "s-table-measure-column-header-group-cell-" + colGroupIndex : null, measureIndex !== null && measureIndex !== undefined ? "s-table-measure-column-header-cell-" + measureIndex : null, index ? "s-table-measure-column-header-index-" + index : null, !field ? "gd-column-group-header--empty" : null, isFirstColumn ? "gd-column-group-header--first" : null); }; }; _this.state = { columnDefs: [], rowData: [], execution: null, columnTotals: cloneDeep(utils_1.default.getColumnTotalsFromResultSpec(_this.props.resultSpec)), agGridRerenderNumber: 1, desiredHeight: props.config.maxHeight, sortedByFirstAttribute: true, resized: false, }; _this.agGridDataSource = null; _this.gridApi = null; _this.resizedColumnsStore = new ResizedColumnsStore_1.ResizedColumnsStore(); _this.setGroupingProvider(props.groupRows); _this.gridSizeChanged = debounce(_this.gridSizeChanged, AGGRID_ON_RESIZE_TIMEOUT); return _this; } PivotTableInner.prototype.componentWillMount = function () { this.createAGGridDataSource(); }; PivotTableInner.prototype.componentDidMount = function () { if (this.containerRef) { this.containerRef.addEventListener("mousedown", this.onContainerMouseDown); } }; PivotTableInner.prototype.componentWillUnmount = function () { if (this.containerRef) { this.containerRef.removeEventListener("mousedown", this.onContainerMouseDown); } }; PivotTableInner.prototype.componentWillUpdate = function (nextProps, nextState) { if (this.props.groupRows !== nextProps.groupRows || this.state.sortedByFirstAttribute !== nextState.sortedByFirstAttribute) { this.setGroupingProvider(nextProps.groupRows && nextState.sortedByFirstAttribute); } }; PivotTableInner.prototype.componentDidUpdate = function (prevProps, prevState) { var _this = this; var prevPropsTotals = utils_1.default.getColumnTotalsFromResultSpec(prevProps.resultSpec); var currentPropsTotals = utils_1.default.getColumnTotalsFromResultSpec(this.props.resultSpec); var totalsPropsChanged = !isEqual(prevPropsTotals, currentPropsTotals); var prevStateTotals = prevState.columnTotals; var currentStateTotals = this.state.columnTotals; var totalsStateChanged = !isEqual(prevStateTotals, currentStateTotals); var prevColumnWidths = this.getColumnWidths(prevProps); var columnWidths = this.getColumnWidths(this.props); new Promise(function (resolve) { if (totalsPropsChanged) { _this.setState({ columnTotals: currentPropsTotals, }, resolve); } else { resolve(); } }).then(function () { var agGridDataSourceUpdateNeeded = false; if (totalsStateChanged) { _this.props.updateTotals(_this.state.columnTotals); agGridDataSourceUpdateNeeded = true; } if (_this.isNewAGGridDataSourceNeeded(prevProps)) { _this.groupingProvider.reset(); agGridDataSourceUpdateNeeded = true; } var fingerprint = agGridUtils_1.sanitizeFingerprint(_this.props.dataSource.getFingerprint()); var prevFingerprint = agGridUtils_1.sanitizeFingerprint(prevProps.dataSource.getFingerprint()); var dataSourceChanged = fingerprint !== prevFingerprint; if (dataSourceChanged) { _this.columnWidthsChangeWaitingForExecution = true; } if (dataSourceChanged || totalsPropsChanged || totalsStateChanged) { // we need update last scroll position to be able call updateStickyRow // solve blank cell after scroll and sort change _this.lastScrollPosition = { top: 0, left: 0, }; _this.autoResizedColumns = {}; _this.clearFittedColumns(); _this.setState({ resized: false, }); } if (_this.isGrowToFitEnabled(prevProps) !== _this.isGrowToFitEnabled()) { _this.growToFit(_this.columnApi); } if (!isEqual(prevColumnWidths, columnWidths) && !_this.columnWidthsChangeWaitingForExecution) { if (_this.shouldWaitForExecution(totalsPropsChanged, totalsStateChanged)) { _this.columnWidthsChangeWaitingForExecution = true; } else { _this.handleColumnWidthsChange(columnWidths); } } if (agGridDataSourceUpdateNeeded) { _this.updateAGGridDataSource(); } }); if (this.isAgGridRerenderNeeded(this.props, prevProps)) { this.forceRerender(); } if (this.props.config.maxHeight && this.state.execution) { this.updateDesiredHeight(this.state.execution.executionResult); } }; PivotTableInner.prototype.renderVisualization = function () { var desiredHeight = this.state.desiredHeight; var gridOptions = this.createGridOptions(); var CustomLoadingComponent = this.props.LoadingComponent; // wait for columnDefs are loaded with first page request and initial column resizing is done. // Show overlay loading before first page is available. var tableLoadingOverlay = this.isTableHidden() ? (React.createElement("div", { style: { position: "absolute", left: 0, right: 0, top: 0, bottom: 0, background: "white", }, className: "s-loading" }, CustomLoadingComponent !== null ? (CustomLoadingComponent ? (React.createElement(CustomLoadingComponent, null)) : (React.createElement(LoadingComponent_1.LoadingComponent, null))) : null)) : null; var style = { height: desiredHeight || "100%", position: "relative", overflow: "hidden", }; return (React.createElement("div", { className: "gd-table-component", style: style }, React.createElement("div", { className: "gd-table ag-theme-balham s-pivot-table", style: style, ref: this.setContainerRef }, React.createElement(ag_grid_react_1.AgGridReact, __assign({}, gridOptions, { // To force Ag grid rerender because AFAIK there is no way // to tell Ag grid header cell to rerender key: agGridUtils_1.generateAgGridComponentKey(this.props.dataSource.getAfm(), this.state.agGridRerenderNumber) })), tableLoadingOverlay))); }; PivotTableInner.prototype.isTableHidden = function () { return (this.state.columnDefs.length === 0 || ((this.isColumnAutoresizeEnabled() || this.isGrowToFitEnabled()) && !this.state.resized)); }; PivotTableInner.prototype.forceRerender = function () { this.setState(function (state) { return ({ agGridRerenderNumber: state.agGridRerenderNumber + 1, }); }); }; // // working with data source // PivotTableInner.prototype.isNewAGGridDataSourceNeeded = function (prevProps) { var _this = this; // cannot compare dataSource using deep equal as it stores execution promises that almost always differ var dataSourceChanged = this.props.dataSource.getFingerprint() !== prevProps.dataSource.getFingerprint(); var dataSourceInvalidatingPropNames = [ "resultSpec", "getPage", // drillable items need fresh execution because drillable context for row attribute is kept in rowData // It could be refactored to assign drillability without execution, // but it would suffer a significant performance hit "drillableItems", ]; var dataSourceInvalidatingPropChanged = dataSourceInvalidatingPropNames.some(function (propKey) { return !isEqual(_this.props[propKey], prevProps[propKey]); }); return dataSourceChanged || dataSourceInvalidatingPropChanged; }; PivotTableInner.prototype.isAgGridRerenderNeeded = function (props, prevProps) { var propsRequiringAgGridRerender = [["config", "menu"]]; return propsRequiringAgGridRerender.some(function (propKey) { return !isEqual(get(props, propKey), get(prevProps, propKey)); }); }; PivotTableInner.prototype.updateAGGridDataSource = function () { this.createAGGridDataSource(); this.setGridDataSource(); }; PivotTableInner.prototype.autoresizeColumnsByColumnId = function (columnApi, columnIds) { agColumnWrapper_1.setColumnMaxWidth(columnApi, columnIds, agGridColumnSizing_1.AUTO_SIZED_MAX_WIDTH); columnApi.autoSizeColumns(columnIds); agColumnWrapper_1.setColumnMaxWidth(columnApi, columnIds, agGridColumnSizing_1.MANUALLY_SIZED_MAX_WIDTH); }; PivotTableInner.prototype.shouldPerformAutoresize = function () { var _this = this; var execution = this.state.execution; var tableIsNotScrolled = funct