@revolist/revogrid
Version:
Virtual reactive data grid spreadsheet component - RevoGrid.
130 lines (129 loc) • 4.78 kB
JavaScript
/*!
* Built by Revolist OU ❤️
*/
import { gatherTrimmedItems } from "../../store/index";
import { GROUP_DEPTH } from "./grouping.const";
import { isGrouping } from "./grouping.service";
export const TRIMMED_GROUPING = 'grouping';
/**
* Converts a trim row index through the index maps produced while regrouping.
*
* Group rows are synthetic, so they may not exist in the first map. When a
* second map is available, fall back to the original index so trims created
* against the grouped physical source can still be remapped. If neither path
* resolves to a number, the caller drops the stale trim entry.
*/
function convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap) {
const sourceIndex = Number.parseInt(initialIndex, 10);
const firstConversionIndex = firstLevelMap[sourceIndex];
if (!secondLevelMap) {
return firstConversionIndex;
}
const secondConversionKey = typeof firstConversionIndex === 'number' ? firstConversionIndex : sourceIndex;
return secondLevelMap[secondConversionKey];
}
/**
* Prepare trimming updated indexes for grouping
* @param initiallyTrimed
* @param firstLevelMap
* @param secondLevelMap
*/
export function processDoubleConversionTrimmed(initiallyTrimed, firstLevelMap, secondLevelMap) {
const trimemedOptionsToUpgrade = {};
/**
* go through all groups except grouping
*/
for (let type in initiallyTrimed) {
if (type === TRIMMED_GROUPING) {
continue;
}
const items = initiallyTrimed[type];
const newItems = {};
for (let initialIndex in items) {
if (!items[initialIndex]) {
continue;
}
/**
* if item exists we find it in collection
* we support 2 level of conversions
*/
const newConversionIndex = convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap);
// Group rows do not exist in the ungrouped index map and must not leak into new trims.
if (typeof newConversionIndex !== 'number') {
continue;
}
/**
* if item was trimmed previously
* trimming makes sense to apply
*/
newItems[newConversionIndex] = true;
}
trimemedOptionsToUpgrade[type] = newItems;
}
return trimemedOptionsToUpgrade;
}
function hasVisibleGroupItems(source, trimmed, groupIndex) {
var _a;
const depth = (_a = source[groupIndex]) === null || _a === void 0 ? void 0 : _a[GROUP_DEPTH];
if (depth == null) {
return false;
}
// A group is visible when at least one descendant data row survives filtering.
for (let i = groupIndex + 1; i < source.length; i++) {
const model = source[i];
if (isGrouping(model)) {
if (model[GROUP_DEPTH] <= depth) {
break;
}
continue;
}
if (!trimmed[i]) {
return true;
}
}
return false;
}
/**
* Preserves data-row filter results and recalculates group-row visibility
* from the filtered state of each group's descendant data rows.
*
* @param source - Grouped row source that contains group rows and data rows.
* @param filterTrimmed - Current filter trim map keyed by physical row index.
* @returns Filter trim map with empty group rows hidden and matching group rows visible.
*/
export function filterOutEmptyGroupRows(source, filterTrimmed) {
const trimmed = Object.assign({}, filterTrimmed);
// Recalculate only group rows; data-row filter results are preserved as-is.
source.forEach((model, index) => {
if (!isGrouping(model)) {
return;
}
if (hasVisibleGroupItems(source, trimmed, index)) {
delete trimmed[index];
}
else {
trimmed[index] = true;
}
});
return trimmed;
}
/**
* Builds grouping trims from an explicit group-to-children map by hiding
* groups whose children are all hidden by any active trim type.
*
* @param allTrimmedGroups - Active trim maps keyed by trim type.
* @param childrenByGroup - Child row indexes keyed by group row index.
* @returns Grouping trim map that hides groups without visible children.
*/
export function filterOutEmptyGroups(allTrimmedGroups, childrenByGroup = {}) {
const trimmedGroup = {};
const allTrimmed = gatherTrimmedItems(allTrimmedGroups);
// find is groups are filled
for (let groupIndex in childrenByGroup) {
const hasChidlren = childrenByGroup[groupIndex].filter(childIndex => !allTrimmed[childIndex]).length > 0;
if (!hasChidlren) {
trimmedGroup[groupIndex] = true;
}
}
return trimmedGroup;
}