ag-grid-enterprise
Version:
ag-Grid Enterprise Features
467 lines (466 loc) • 21.7 kB
JavaScript
// ag-grid-enterprise v19.1.4
"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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
var ag_grid_community_1 = require("ag-grid-community");
var serverSideBlock_1 = require("./serverSideBlock");
var ServerSideCache = /** @class */ (function (_super) {
__extends(ServerSideCache, _super);
function ServerSideCache(cacheParams, parentRowNode) {
var _this = _super.call(this, cacheParams) || this;
// this will always be zero for the top level cache only,
// all the other ones change as the groups open and close
_this.displayIndexStart = 0;
_this.displayIndexEnd = 0; // not sure if setting this one to zero is necessary
_this.cacheTop = 0;
_this.blockHeights = {};
_this.parentRowNode = parentRowNode;
return _this;
}
ServerSideCache.prototype.setBeans = function (loggerFactory) {
this.logger = loggerFactory.create('ServerSideCache');
};
ServerSideCache.prototype.init = function () {
_super.prototype.init.call(this);
};
ServerSideCache.prototype.getRowBounds = function (index) {
var _this = this;
this.logger.log("getRowBounds(" + index + ")");
// we return null if row not found
var result;
var blockFound = false;
var lastBlock;
this.forEachBlockInOrder(function (block) {
if (blockFound)
return;
if (block.isDisplayIndexInBlock(index)) {
result = block.getRowBounds(index, _this.getVirtualRowCount());
blockFound = true;
}
else if (block.isBlockBefore(index)) {
lastBlock = block;
}
});
if (!blockFound) {
var nextRowTop = void 0;
var nextRowIndex = void 0;
if (lastBlock) {
nextRowTop = lastBlock.getBlockTop() + lastBlock.getBlockHeight();
nextRowIndex = lastBlock.getDisplayIndexEnd();
}
else {
nextRowTop = this.cacheTop;
nextRowIndex = this.displayIndexStart;
}
var rowsBetween = index - nextRowIndex;
result = {
rowHeight: this.cacheParams.rowHeight,
rowTop: nextRowTop + rowsBetween * this.cacheParams.rowHeight
};
}
// NOTE: what about purged blocks
this.logger.log("getRowBounds(" + index + "), result = " + result);
return result;
};
ServerSideCache.prototype.destroyBlock = function (block) {
_super.prototype.destroyBlock.call(this, block);
};
ServerSideCache.prototype.getRowIndexAtPixel = function (pixel) {
var _this = this;
this.logger.log("getRowIndexAtPixel(" + pixel + ")");
// we return null if row not found
var result;
var blockFound = false;
var lastBlock;
this.forEachBlockInOrder(function (block) {
if (blockFound)
return;
if (block.isPixelInRange(pixel)) {
result = block.getRowIndexAtPixel(pixel, _this.getVirtualRowCount());
blockFound = true;
}
else if (block.getBlockTop() < pixel) {
lastBlock = block;
}
});
if (!blockFound) {
var nextRowTop = void 0;
var nextRowIndex = void 0;
if (lastBlock) {
nextRowTop = lastBlock.getBlockTop() + lastBlock.getBlockHeight();
nextRowIndex = lastBlock.getDisplayIndexEnd();
}
else {
nextRowTop = this.cacheTop;
nextRowIndex = this.displayIndexStart;
}
var pixelsBetween = pixel - nextRowTop;
var rowsBetween = (pixelsBetween / this.cacheParams.rowHeight) | 0;
result = nextRowIndex + rowsBetween;
}
var lastAllowedIndex = this.getDisplayIndexEnd() - 1;
if (result > lastAllowedIndex) {
result = lastAllowedIndex;
}
//NOTE: purged
this.logger.log("getRowIndexAtPixel(" + pixel + ") result = " + result);
return result;
};
ServerSideCache.prototype.clearRowTops = function () {
var _this = this;
this.forEachBlockInOrder(function (block) { return block.clearRowTops(_this.getVirtualRowCount()); });
};
ServerSideCache.prototype.setDisplayIndexes = function (displayIndexSeq, nextRowTop) {
var _this = this;
this.displayIndexStart = displayIndexSeq.peek();
this.cacheTop = nextRowTop.value;
var lastBlockId = -1;
this.forEachBlockInOrder(function (currentBlock, blockId) {
// if we skipped blocks, then we need to skip the row indexes. we assume that all missing
// blocks are made up of closed RowNodes only (if they were groups), as we never expire from
// the cache if any row nodes are open.
var blocksSkippedCount = blockId - lastBlockId - 1;
var rowsSkippedCount = blocksSkippedCount * _this.cacheParams.blockSize;
if (rowsSkippedCount > 0) {
displayIndexSeq.skip(rowsSkippedCount);
}
for (var i = 1; i <= blocksSkippedCount; i++) {
var blockToAddId = blockId - i;
if (ag_grid_community_1._.exists(_this.blockHeights[blockToAddId])) {
nextRowTop.value += _this.blockHeights[blockToAddId];
}
else {
nextRowTop.value += _this.cacheParams.blockSize * _this.cacheParams.rowHeight;
}
}
lastBlockId = blockId;
currentBlock.setDisplayIndexes(displayIndexSeq, _this.getVirtualRowCount(), nextRowTop);
_this.blockHeights[blockId] = currentBlock.getBlockHeight();
});
// if any blocks missing at the end, need to increase the row index for them also
// eg if block size = 10, we have total rows of 25 (indexes 0 .. 24), but first 2 blocks loaded (because
// last row was ejected from cache), then:
// lastVisitedRow = 19, virtualRowCount = 25, rows not accounted for = 5 (24 - 19)
var lastVisitedRow = ((lastBlockId + 1) * this.cacheParams.blockSize) - 1;
var rowCount = this.getVirtualRowCount();
var rowsNotAccountedFor = rowCount - lastVisitedRow - 1;
if (rowsNotAccountedFor > 0) {
displayIndexSeq.skip(rowsNotAccountedFor);
nextRowTop.value += rowsNotAccountedFor * this.cacheParams.rowHeight;
}
this.displayIndexEnd = displayIndexSeq.peek();
this.cacheHeight = nextRowTop.value - this.cacheTop;
};
// gets called in a) init() above and b) by the grid
ServerSideCache.prototype.getRow = function (displayRowIndex, dontCreateBlock) {
var _this = this;
if (dontCreateBlock === void 0) { dontCreateBlock = false; }
// this can happen if asking for a row that doesn't exist in the model,
// eg if a cell range is selected, and the user filters so rows no longer
// exist
if (!this.isDisplayIndexInCache(displayRowIndex)) {
return null;
}
// if we have the block, then this is the block
var block = null;
// this is the last block that we have BEFORE the right block
var beforeBlock = null;
this.forEachBlockInOrder(function (currentBlock) {
if (currentBlock.isDisplayIndexInBlock(displayRowIndex)) {
block = currentBlock;
}
else if (currentBlock.isBlockBefore(displayRowIndex)) {
// this will get assigned many times, but the last time will
// be the closest block to the required block that is BEFORE
beforeBlock = currentBlock;
}
});
// when we are moving rows around, we don't want to trigger loads
if (ag_grid_community_1._.missing(block) && dontCreateBlock) {
return null;
}
// if block not found, we need to load it
if (ag_grid_community_1._.missing(block)) {
var blockNumber = void 0;
var displayIndexStart_1;
var nextRowTop = void 0;
// because missing blocks are always fully closed, we can work out
// the start index of the block we want by hopping from the closest block,
// as we know the row count in closed blocks is equal to the page size
if (beforeBlock) {
blockNumber = beforeBlock.getBlockNumber() + 1;
displayIndexStart_1 = beforeBlock.getDisplayIndexEnd();
nextRowTop = beforeBlock.getBlockHeight() + beforeBlock.getBlockTop();
var isInRange = function () {
return displayRowIndex >= displayIndexStart_1 && displayRowIndex < (displayIndexStart_1 + _this.cacheParams.blockSize);
};
while (!isInRange()) {
displayIndexStart_1 += this.cacheParams.blockSize;
var cachedBlockHeight = this.blockHeights[blockNumber];
if (ag_grid_community_1._.exists(cachedBlockHeight)) {
nextRowTop += cachedBlockHeight;
}
else {
nextRowTop += this.cacheParams.rowHeight * this.cacheParams.blockSize;
}
blockNumber++;
}
}
else {
var localIndex = displayRowIndex - this.displayIndexStart;
blockNumber = Math.floor(localIndex / this.cacheParams.blockSize);
displayIndexStart_1 = this.displayIndexStart + (blockNumber * this.cacheParams.blockSize);
nextRowTop = this.cacheTop + (blockNumber * this.cacheParams.blockSize * this.cacheParams.rowHeight);
}
block = this.createBlock(blockNumber, displayIndexStart_1, { value: nextRowTop });
this.logger.log("block missing, rowIndex = " + displayRowIndex + ", creating #" + blockNumber + ", displayIndexStart = " + displayIndexStart_1);
}
var rowNode = block.getRow(displayRowIndex);
return rowNode;
};
ServerSideCache.prototype.createBlock = function (blockNumber, displayIndex, nextRowTop) {
var newBlock = new serverSideBlock_1.ServerSideBlock(blockNumber, this.parentRowNode, this.cacheParams, this);
this.context.wireBean(newBlock);
var displayIndexSequence = new ag_grid_community_1.NumberSequence(displayIndex);
newBlock.setDisplayIndexes(displayIndexSequence, this.getVirtualRowCount(), nextRowTop);
this.postCreateBlock(newBlock);
return newBlock;
};
ServerSideCache.prototype.getDisplayIndexEnd = function () {
return this.displayIndexEnd;
};
ServerSideCache.prototype.isDisplayIndexInCache = function (displayIndex) {
if (this.getVirtualRowCount() === 0) {
return false;
}
return displayIndex >= this.displayIndexStart && displayIndex < this.displayIndexEnd;
};
ServerSideCache.prototype.getChildCache = function (keys) {
var _this = this;
if (ag_grid_community_1._.missingOrEmpty(keys)) {
return this;
}
var nextKey = keys[0];
var nextServerSideCache = null;
this.forEachBlockInOrder(function (block) {
// callback: (rowNode: RowNode, index: number) => void, sequence: NumberSequence, rowCount: number
block.forEachNodeShallow(function (rowNode) {
if (rowNode.key === nextKey) {
nextServerSideCache = rowNode.childrenCache;
}
}, new ag_grid_community_1.NumberSequence(), _this.getVirtualRowCount());
});
if (nextServerSideCache) {
var keyListForNextLevel = keys.slice(1, keys.length);
return nextServerSideCache.getChildCache(keyListForNextLevel);
}
else {
return null;
}
};
ServerSideCache.prototype.isPixelInRange = function (pixel) {
if (this.getVirtualRowCount() === 0) {
return false;
}
return pixel >= this.cacheTop && pixel < (this.cacheTop + this.cacheHeight);
};
ServerSideCache.prototype.removeFromCache = function (items) {
var _this = this;
// create map of id's for quick lookup
var itemsToDeleteById = {};
var idForNodeFunc = this.gridOptionsWrapper.getRowNodeIdFunc();
items.forEach(function (item) {
var id = idForNodeFunc(item);
itemsToDeleteById[id] = item;
});
var deletedCount = 0;
this.forEachBlockInOrder(function (block) {
var startRow = block.getStartRow();
var endRow = block.getEndRow();
var deletedCountFromThisBlock = 0;
for (var rowIndex = startRow; rowIndex < endRow; rowIndex++) {
var rowNode = block.getRowUsingLocalIndex(rowIndex, true);
if (!rowNode) {
continue;
}
var deleteThisRow = !!itemsToDeleteById[rowNode.id];
if (deleteThisRow) {
deletedCountFromThisBlock++;
deletedCount++;
block.setDirty();
rowNode.clearRowTop();
continue;
}
// if rows were deleted, then we need to move this row node to
// it's new location
if (deletedCount > 0) {
block.setDirty();
var newIndex = rowIndex - deletedCount;
var blockId = Math.floor(newIndex / _this.cacheParams.blockSize);
var blockToInsert = _this.getBlock(blockId);
if (blockToInsert) {
blockToInsert.setRowNode(newIndex, rowNode);
}
}
}
if (deletedCountFromThisBlock > 0) {
for (var i = deletedCountFromThisBlock; i > 0; i--) {
block.setBlankRowNode(endRow - i);
}
}
});
if (this.isMaxRowFound()) {
this.hack_setVirtualRowCount(this.getVirtualRowCount() - deletedCount);
}
this.onCacheUpdated();
var event = {
type: ag_grid_community_1.Events.EVENT_ROW_DATA_UPDATED,
api: this.gridOptionsWrapper.getApi(),
columnApi: this.gridOptionsWrapper.getColumnApi()
};
this.eventService.dispatchEvent(event);
};
ServerSideCache.prototype.addToCache = function (items, indexToInsert) {
var _this = this;
var newNodes = [];
this.forEachBlockInReverseOrder(function (block) {
var pageEndRow = block.getEndRow();
// if the insertion is after this page, then this page is not impacted
if (pageEndRow <= indexToInsert) {
return;
}
_this.moveItemsDown(block, indexToInsert, items.length);
var newNodesThisPage = _this.insertItems(block, indexToInsert, items);
newNodesThisPage.forEach(function (rowNode) { return newNodes.push(rowNode); });
});
if (this.isMaxRowFound()) {
this.hack_setVirtualRowCount(this.getVirtualRowCount() + items.length);
}
this.onCacheUpdated();
var event = {
type: ag_grid_community_1.Events.EVENT_ROW_DATA_UPDATED,
api: this.gridOptionsWrapper.getApi(),
columnApi: this.gridOptionsWrapper.getColumnApi()
};
this.eventService.dispatchEvent(event);
};
ServerSideCache.prototype.moveItemsDown = function (block, moveFromIndex, moveCount) {
var startRow = block.getStartRow();
var endRow = block.getEndRow();
var indexOfLastRowToMove = moveFromIndex + moveCount;
// all rows need to be moved down below the insertion index
for (var currentRowIndex = endRow - 1; currentRowIndex >= startRow; currentRowIndex--) {
// don't move rows at or before the insertion index
if (currentRowIndex < indexOfLastRowToMove) {
continue;
}
var indexOfNodeWeWant = currentRowIndex - moveCount;
var nodeForThisIndex = this.getRow(indexOfNodeWeWant, true);
if (nodeForThisIndex) {
block.setRowNode(currentRowIndex, nodeForThisIndex);
}
else {
block.setBlankRowNode(currentRowIndex);
block.setDirty();
}
}
};
ServerSideCache.prototype.insertItems = function (block, indexToInsert, items) {
var pageStartRow = block.getStartRow();
var pageEndRow = block.getEndRow();
var newRowNodes = [];
// next stage is insert the rows into this page, if applicable
for (var index = 0; index < items.length; index++) {
var rowIndex = indexToInsert + index;
var currentRowInThisPage = rowIndex >= pageStartRow && rowIndex < pageEndRow;
if (currentRowInThisPage) {
var dataItem = items[index];
var newRowNode = block.setNewData(rowIndex, dataItem);
newRowNodes.push(newRowNode);
}
}
return newRowNodes;
};
ServerSideCache.prototype.refreshCacheAfterSort = function (changedColumnsInSort, rowGroupColIds) {
var _this = this;
var level = this.parentRowNode.level + 1;
var grouping = level < this.cacheParams.rowGroupCols.length;
var shouldPurgeCache;
if (grouping) {
var groupColVo = this.cacheParams.rowGroupCols[level];
var groupField = groupColVo.field;
var rowGroupBlock = rowGroupColIds.indexOf(groupField) > -1;
var sortingByGroup = changedColumnsInSort.indexOf(groupField) > -1;
shouldPurgeCache = rowGroupBlock && sortingByGroup;
}
else {
shouldPurgeCache = true;
}
if (shouldPurgeCache) {
this.purgeCache();
}
else {
this.forEachBlockInOrder(function (block) {
if (block.isGroupLevel()) {
var callback = function (rowNode) {
var nextCache = rowNode.childrenCache;
if (nextCache) {
nextCache.refreshCacheAfterSort(changedColumnsInSort, rowGroupColIds);
}
};
block.forEachNodeShallow(callback, new ag_grid_community_1.NumberSequence(), _this.getVirtualRowCount());
}
});
}
};
__decorate([
ag_grid_community_1.Autowired('eventService'),
__metadata("design:type", ag_grid_community_1.EventService)
], ServerSideCache.prototype, "eventService", void 0);
__decorate([
ag_grid_community_1.Autowired('context'),
__metadata("design:type", ag_grid_community_1.Context)
], ServerSideCache.prototype, "context", void 0);
__decorate([
ag_grid_community_1.Autowired('gridOptionsWrapper'),
__metadata("design:type", ag_grid_community_1.GridOptionsWrapper)
], ServerSideCache.prototype, "gridOptionsWrapper", void 0);
__decorate([
__param(0, ag_grid_community_1.Qualifier('loggerFactory')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [ag_grid_community_1.LoggerFactory]),
__metadata("design:returntype", void 0)
], ServerSideCache.prototype, "setBeans", null);
__decorate([
ag_grid_community_1.PostConstruct,
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], ServerSideCache.prototype, "init", null);
return ServerSideCache;
}(ag_grid_community_1.RowNodeCache));
exports.ServerSideCache = ServerSideCache;