@infinite-table/infinite-react 0.4.13 → 0.5.1
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/.vscode/settings.json +3 -0
- package/API.md +0 -0
- package/build/buildPackageJson.js +43 -0
- package/build/scripts/test.js +37 -0
- package/bundler.config.js +25 -0
- package/globals.d.ts +7 -0
- package/package.json +102 -3
- package/rollup.config.js +15 -0
- package/run-build-deepmap.js +47 -0
- package/run-build.js +45 -0
- package/run-dts-concat.js +21 -0
- package/src/components/CSSVariableWatch.tsx +82 -0
- package/src/components/DataSource/BooleanCollectionState.ts +214 -0
- package/src/components/DataSource/BooleanDeepCollectionState.ts +208 -0
- package/src/components/DataSource/DataSourceContext.ts +20 -0
- package/src/components/DataSource/GroupRowsState.ts +74 -0
- package/src/components/DataSource/Indexer.ts +27 -0
- package/src/components/DataSource/RowSelectionState.ts +763 -0
- package/src/components/DataSource/defaultFilterTypes.ts +64 -0
- package/src/components/DataSource/index.tsx +108 -0
- package/src/components/DataSource/privateHooks/getChangeDetect.ts +7 -0
- package/src/components/DataSource/privateHooks/useLoadData.ts +783 -0
- package/src/components/DataSource/publicHooks/useDataSource.ts +19 -0
- package/src/components/DataSource/publicHooks/useDataSourceActions.ts +14 -0
- package/src/components/DataSource/state/getInitialState.ts +494 -0
- package/src/components/DataSource/state/normalizeSortInfo.ts +35 -0
- package/src/components/DataSource/state/reducer.ts +466 -0
- package/src/components/DataSource/state/rowInfoStatus.ts +27 -0
- package/src/components/DataSource/types.ts +548 -0
- package/src/components/HeadlessTable/HeadlessTableWithPinnedContainers.tsx +142 -0
- package/src/components/HeadlessTable/MappedCells.ts +251 -0
- package/src/components/HeadlessTable/RawTable.tsx +98 -0
- package/src/components/HeadlessTable/ReactHeadlessTableRenderer.tsx +1516 -0
- package/src/components/HeadlessTable/index.tsx +234 -0
- package/src/components/InfiniteTable/InfiniteCls.css.ts +164 -0
- package/src/components/InfiniteTable/InfiniteTableContext.ts +16 -0
- package/src/components/InfiniteTable/api/getImperativeApi.ts +391 -0
- package/src/components/InfiniteTable/api/getSelectionApi.ts +364 -0
- package/src/components/InfiniteTable/api/type.ts +11 -0
- package/src/components/InfiniteTable/components/ActiveCellIndicator.css.ts +51 -0
- package/src/components/InfiniteTable/components/ActiveCellIndicator.tsx +116 -0
- package/src/components/InfiniteTable/components/ActiveRowIndicator.css.ts +56 -0
- package/src/components/InfiniteTable/components/ActiveRowIndicator.tsx +94 -0
- package/src/components/InfiniteTable/components/CheckBox.css.ts +13 -0
- package/src/components/InfiniteTable/components/CheckBox.tsx +96 -0
- package/src/components/InfiniteTable/components/FilterEditors.tsx +52 -0
- package/src/components/InfiniteTable/components/InfiniteTableBody/InfiniteTableBody.tsx +27 -0
- package/src/components/InfiniteTable/components/InfiniteTableBody/index.tsx +1 -0
- package/src/components/InfiniteTable/components/InfiniteTableFooter/InfiniteTableFooter.tsx +31 -0
- package/src/components/InfiniteTable/components/InfiniteTableFooter/index.tsx +1 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableColumnHeaderFilter.tsx +102 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeader.tsx +163 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderCell.tsx +574 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderGroup.tsx +79 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderTypes.tsx +25 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/InfiniteTableHeaderWrapper.tsx +185 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/GroupResizeHandle.tsx +159 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/ResizeHandle.css.ts +124 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/columnResizer.ts +166 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/ResizeHandle/index.tsx +146 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/buildColumnAndGroupTree.ts +240 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/header.css.ts +358 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/index.tsx +1 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnGroupResizeHandle.tsx +114 -0
- package/src/components/InfiniteTable/components/InfiniteTableHeader/useColumnResizeHandle.tsx +146 -0
- package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/footer.css.ts +7 -0
- package/src/components/InfiniteTable/components/InfiniteTableLicenseFooter/index.tsx +110 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCell.tsx +120 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableCellTypes.ts +74 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableColumnCell.tsx +457 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRow.tsx +107 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowClassName.ts +6 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowTypes.ts +32 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/InfiniteTableRowUnvirtualized.tsx +75 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/columnRendering.tsx +263 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/index.tsx +1 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/row.css.ts +74 -0
- package/src/components/InfiniteTable/components/InfiniteTableRow/useRowDOMProps.ts +199 -0
- package/src/components/InfiniteTable/components/LoadMask.css.ts +34 -0
- package/src/components/InfiniteTable/components/LoadMask.tsx +27 -0
- package/src/components/InfiniteTable/components/ScrollbarPlaceholder.tsx +56 -0
- package/src/components/InfiniteTable/components/cell.css.ts +192 -0
- package/src/components/InfiniteTable/components/icons/ArrowDown.tsx +14 -0
- package/src/components/InfiniteTable/components/icons/ArrowUp.tsx +14 -0
- package/src/components/InfiniteTable/components/icons/ExpanderIcon.css.ts +31 -0
- package/src/components/InfiniteTable/components/icons/ExpanderIcon.tsx +63 -0
- package/src/components/InfiniteTable/components/icons/Icon.tsx +18 -0
- package/src/components/InfiniteTable/components/icons/InfiniteTableIconClassName.ts +1 -0
- package/src/components/InfiniteTable/components/icons/LoadingIcon.css.ts +8 -0
- package/src/components/InfiniteTable/components/icons/LoadingIcon.tsx +45 -0
- package/src/components/InfiniteTable/components/icons/MenuIcon.tsx +50 -0
- package/src/components/InfiniteTable/components/icons/SortIcon.tsx +113 -0
- package/src/components/InfiniteTable/eventHandlers/eventHandlerTypes.ts +57 -0
- package/src/components/InfiniteTable/eventHandlers/index.ts +95 -0
- package/src/components/InfiniteTable/eventHandlers/keyboardNavigation.ts +232 -0
- package/src/components/InfiniteTable/eventHandlers/keyboardSelection.ts +110 -0
- package/src/components/InfiniteTable/eventHandlers/onCellClick.ts +94 -0
- package/src/components/InfiniteTable/eventHandlers/onKeyDown.ts +25 -0
- package/src/components/InfiniteTable/hooks/adjustColumnOrderForAllColumns.ts +70 -0
- package/src/components/InfiniteTable/hooks/reorderColumnsOnDrag.ts +476 -0
- package/src/components/InfiniteTable/hooks/useAutoSizeColumns.ts +206 -0
- package/src/components/InfiniteTable/hooks/useCellClassName.ts +80 -0
- package/src/components/InfiniteTable/hooks/useCellRendering.tsx +217 -0
- package/src/components/InfiniteTable/hooks/useColumnGroups.ts +71 -0
- package/src/components/InfiniteTable/hooks/useColumnMenu.ts +72 -0
- package/src/components/InfiniteTable/hooks/useColumnPointerEvents.ts +258 -0
- package/src/components/InfiniteTable/hooks/useColumnRowspan.ts +43 -0
- package/src/components/InfiniteTable/hooks/useColumnSizeFn.ts +24 -0
- package/src/components/InfiniteTable/hooks/useColumnsWhen.ts +582 -0
- package/src/components/InfiniteTable/hooks/useComputed.ts +186 -0
- package/src/components/InfiniteTable/hooks/useComputedVisibleColumns.ts +219 -0
- package/src/components/InfiniteTable/hooks/useDOMProps.ts +306 -0
- package/src/components/InfiniteTable/hooks/useEffectWithRaf.ts +47 -0
- package/src/components/InfiniteTable/hooks/useInfiniteTable.ts +10 -0
- package/src/components/InfiniteTable/hooks/useInfiniteTableState.ts +11 -0
- package/src/components/InfiniteTable/hooks/useInternalProps.ts +8 -0
- package/src/components/InfiniteTable/hooks/useLicense/LicenseDetails.ts +13 -0
- package/src/components/InfiniteTable/hooks/useLicense/crc32.ts +56 -0
- package/src/components/InfiniteTable/hooks/useLicense/decode.ts +147 -0
- package/src/components/InfiniteTable/hooks/useLicense/useLicense.ts +39 -0
- package/src/components/InfiniteTable/hooks/useRerenderOnKeyChange.ts +21 -0
- package/src/components/InfiniteTable/hooks/useRowHover.ts +18 -0
- package/src/components/InfiniteTable/hooks/useScrollToActiveCell.ts +48 -0
- package/src/components/InfiniteTable/hooks/useScrollToActiveRow.ts +44 -0
- package/src/components/InfiniteTable/hooks/useScrollbars.ts +51 -0
- package/src/components/InfiniteTable/hooks/useToggleGroupRow.ts +56 -0
- package/src/components/InfiniteTable/hooks/useUnpinnedRendering.tsx +165 -0
- package/src/components/InfiniteTable/hooks/useYourBrain.ts +55 -0
- package/src/components/InfiniteTable/index.tsx +352 -0
- package/src/components/InfiniteTable/internalProps.ts +4 -0
- package/src/components/InfiniteTable/state/computeColumnGroupsDepths.ts +29 -0
- package/src/components/InfiniteTable/state/getColumnVisibilityForHideEmptyGroupColumns.ts +127 -0
- package/src/components/InfiniteTable/state/getInitialState.ts +375 -0
- package/src/components/InfiniteTable/theme.css.ts +556 -0
- package/src/components/InfiniteTable/types/InfiniteTableAction.ts +6 -0
- package/src/components/InfiniteTable/types/InfiniteTableActionType.ts +12 -0
- package/src/components/InfiniteTable/types/InfiniteTableColumn.ts +478 -0
- package/src/components/InfiniteTable/types/InfiniteTableComputedValues.ts +43 -0
- package/src/components/InfiniteTable/types/InfiniteTableContextValue.ts +12 -0
- package/src/components/InfiniteTable/types/InfiniteTableInternalProps.ts +3 -0
- package/src/components/InfiniteTable/types/InfiniteTableProps.ts +511 -0
- package/src/components/InfiniteTable/types/InfiniteTableState.ts +195 -0
- package/src/components/InfiniteTable/types/Utility.ts +35 -0
- package/src/components/InfiniteTable/types/index.ts +96 -0
- package/src/components/InfiniteTable/utilities.css.ts +179 -0
- package/src/components/InfiniteTable/utils/MultiRowSelector.ts +111 -0
- package/src/components/InfiniteTable/utils/RenderHookComponentForInfinite.tsx +52 -0
- package/src/components/InfiniteTable/utils/adjustColumnOrderForPinning.ts +33 -0
- package/src/components/InfiniteTable/utils/assignFiltered.ts +29 -0
- package/src/components/InfiniteTable/utils/defaultGetColumContextMenuItems.tsx +108 -0
- package/src/components/InfiniteTable/utils/getColumnComputedType.ts +33 -0
- package/src/components/InfiniteTable/utils/getColumnForGroupBy.tsx +313 -0
- package/src/components/InfiniteTable/utils/getComputedVisibleColumns.ts +773 -0
- package/src/components/InfiniteTable/utils/getContextMenuForColumn.tsx +72 -0
- package/src/components/InfiniteTable/utils/infiniteDOMUtils.ts +189 -0
- package/src/components/InfiniteTable/utils/mapToObject.ts +20 -0
- package/src/components/InfiniteTable/utils/moveXatY.ts +25 -0
- package/src/components/InfiniteTable/utils/objectValuesExcept.ts +9 -0
- package/src/components/InfiniteTable/utils/progressiveSpeedScroller.ts +158 -0
- package/src/components/InfiniteTable/utils/rafFn.ts +13 -0
- package/src/components/InfiniteTable/utils/toCSSVarName.ts +1 -0
- package/src/components/InfiniteTable/utils/toMap.ts +24 -0
- package/src/components/Menu/Menu.tsx +750 -0
- package/src/components/Menu/MenuCls.css.ts +139 -0
- package/src/components/Menu/MenuContext.ts +10 -0
- package/src/components/Menu/MenuContextValue.ts +15 -0
- package/src/components/Menu/MenuProps.ts +98 -0
- package/src/components/Menu/MenuState.ts +56 -0
- package/src/components/Menu/MenuTriangleContext.ts +352 -0
- package/src/components/Menu/childrenToRuntimeItems.tsx +103 -0
- package/src/components/Menu/getMenuState.tsx +119 -0
- package/src/components/Menu/index.tsx +88 -0
- package/src/components/Menu/propToIdentifyMenu.ts +1 -0
- package/src/components/RawList/AvoidReactDiff.tsx +48 -0
- package/src/components/RawList/MappedItems.ts +143 -0
- package/src/components/RawList/ReactVirtualRenderer.tsx +307 -0
- package/src/components/RawList/index.tsx +42 -0
- package/src/components/RawList/types.ts +23 -0
- package/src/components/RawList/useVirtualRenderer.ts +36 -0
- package/src/components/RenderHookComponent.tsx +10 -0
- package/src/components/ResizeObserver/index.tsx +170 -0
- package/src/components/VirtualBrain/MatrixBrain.ts +1621 -0
- package/src/components/VirtualBrain/ScrollListener.ts +39 -0
- package/src/components/VirtualBrain/index.ts +664 -0
- package/src/components/VirtualList/ColumnListWithExternalScrolling.tsx +78 -0
- package/src/components/VirtualList/InfiniteListRootClassName.ts +1 -0
- package/src/components/VirtualList/RowListWithExternalScrolling.tsx +120 -0
- package/src/components/VirtualList/SpacePlaceholder.tsx +32 -0
- package/src/components/VirtualList/VirtualList.css.ts +29 -0
- package/src/components/VirtualList/VirtualList.tsx +141 -0
- package/src/components/VirtualList/VirtualRowList.tsx +34 -0
- package/src/components/VirtualList/types.ts +56 -0
- package/src/components/VirtualList/useCorrectHeightForRowElements.ts +14 -0
- package/src/components/VirtualScrollContainer/VirtualScrollContainer.css.ts +51 -0
- package/src/components/VirtualScrollContainer/getScrollableClassName.ts +30 -0
- package/src/components/VirtualScrollContainer/index.tsx +63 -0
- package/src/components/flexbox/index.ts +562 -0
- package/src/components/hooks/useComponentState/index.tsx +562 -0
- package/src/components/hooks/useComponentState/types.ts +32 -0
- package/src/components/hooks/useEffectOnceWithProperUnmount.ts +33 -0
- package/src/components/hooks/useEffectWithChanges.ts +56 -0
- package/src/components/hooks/useImmutableRef.ts +7 -0
- package/src/components/hooks/useInterceptedMap.ts +71 -0
- package/src/components/hooks/useLatest.tsx +8 -0
- package/src/components/hooks/useLazyLatest.ts +23 -0
- package/src/components/hooks/useMemoShallowObjectMerge.ts +16 -0
- package/src/components/hooks/useMounted.ts +18 -0
- package/src/components/hooks/useOnMount.ts +21 -0
- package/src/components/hooks/useOnScroll.ts +34 -0
- package/src/components/hooks/useOnce.ts +10 -0
- package/src/components/hooks/useOverlay/index.tsx +418 -0
- package/src/components/hooks/usePrevious.ts +8 -0
- package/src/components/hooks/usePropertyOld.ts +168 -0
- package/src/components/hooks/useRerender.ts +12 -0
- package/src/components/hooks/xuseProperty.ts +165 -0
- package/src/components/types/CellPosition.ts +4 -0
- package/src/components/types/NonUndefined.ts +1 -0
- package/src/components/types/RemoveObject.ts +22 -0
- package/src/components/types/Renderable.ts +3 -0
- package/src/components/types/ScrollPosition.ts +7 -0
- package/src/components/types/Setter.ts +2 -0
- package/src/components/types/Size.ts +6 -0
- package/src/components/types/SubscriptionCallback.ts +10 -0
- package/src/components/types/VoidFn.ts +1 -0
- package/src/components/utils/buildSubscriptionCallback.tsx +60 -0
- package/src/components/utils/clamp.ts +3 -0
- package/src/components/utils/debounce.ts +16 -0
- package/src/components/utils/decamelize.ts +11 -0
- package/src/components/utils/discardCallsWithEqualArg.ts +42 -0
- package/src/components/utils/getRenderIndexes.ts +33 -0
- package/src/components/utils/getScrollbarWidth.ts +31 -0
- package/src/components/utils/getVirtualRenderCount.ts +21 -0
- package/src/components/utils/isControlled.ts +12 -0
- package/src/components/utils/isControlledValue.ts +5 -0
- package/src/index.tsx +34 -0
- package/src/test.tsx +18 -0
- package/src/utils/DeepMap/index.ts +588 -0
- package/src/utils/DeepMap/once.ts +16 -0
- package/src/utils/DeepMap/sortAscending.ts +1 -0
- package/src/utils/DeepMap/tsconfig.deepmap.json +17 -0
- package/src/utils/DeepMap/xpackage.json +26 -0
- package/src/utils/debug.ts +40 -0
- package/src/utils/deepClone.ts +38 -0
- package/src/utils/getGlobal.ts +3 -0
- package/src/utils/groupAndPivot/defaultToKey.ts +3 -0
- package/src/utils/groupAndPivot/getGroupKeysForDataItem.ts +19 -0
- package/src/utils/groupAndPivot/getPivotColumnsAndColumnGroups.ts +361 -0
- package/src/utils/groupAndPivot/index.ts +1229 -0
- package/src/utils/groupAndPivot/types.ts +10 -0
- package/src/utils/join.ts +4 -0
- package/src/utils/mathIntersection.ts +21 -0
- package/src/utils/minified.d.ts +2 -0
- package/src/utils/minified.js +6 -0
- package/src/utils/multisort/index.ts +151 -0
- package/src/utils/multisort/sortTypes.ts +25 -0
- package/src/utils/notes-status.md +92 -0
- package/src/utils/pageGeometry/ConvexPoly.ts +34 -0
- package/src/utils/pageGeometry/Point.ts +51 -0
- package/src/utils/pageGeometry/PolyWithPoints.ts +52 -0
- package/src/utils/pageGeometry/Rectangle.ts +98 -0
- package/src/utils/pageGeometry/Triangle.ts +16 -0
- package/src/utils/pageGeometry/alignment/index.ts +221 -0
- package/src/utils/pageGeometry/polyContainsPoint.ts +182 -0
- package/src/utils/pageGeometry/types.ts +3 -0
- package/src/utils/proxyFnCall.ts +46 -0
- package/src/utils/raf.ts +13 -0
- package/src/utils/selectParent.ts +18 -0
- package/src/utils/shallowEqualObjects.ts +49 -0
- package/src/utils/stripVar.ts +3 -0
- package/src/utils/toUpperFirst.ts +5 -0
- package/todo.md +2 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.dev.json +7 -0
- package/tsconfig.json +30 -0
- package/tsconfig.typebundler.json +13 -0
- package/typedoc.json +4 -0
- package/README.md +0 -104
- package/index.css +0 -857
- package/index.d.ts +0 -2111
- package/index.esm.css +0 -857
- package/index.esm.js +0 -13695
- package/index.js +0 -13565
|
@@ -0,0 +1,1229 @@
|
|
|
1
|
+
import { RowSelectionState } from '../../components/DataSource';
|
|
2
|
+
import { GroupRowsState } from '../../components/DataSource/GroupRowsState';
|
|
3
|
+
import { Indexer } from '../../components/DataSource/Indexer';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ColumnTypeWithInherit,
|
|
7
|
+
DataSourceAggregationReducer,
|
|
8
|
+
DataSourceMappings,
|
|
9
|
+
LazyGroupDataDeepMap,
|
|
10
|
+
LazyRowInfoGroup,
|
|
11
|
+
} from '../../components/DataSource/types';
|
|
12
|
+
import {
|
|
13
|
+
InfiniteTableColumn,
|
|
14
|
+
InfiniteTablePivotColumn,
|
|
15
|
+
InfiniteTablePivotFinalColumnGroup,
|
|
16
|
+
InfiniteTablePivotFinalColumnVariant,
|
|
17
|
+
} from '../../components/InfiniteTable/types/InfiniteTableColumn';
|
|
18
|
+
import type { InfiniteTableColumnGroup } from '../../components/InfiniteTable/types/InfiniteTableProps';
|
|
19
|
+
import type { GroupBy } from './types';
|
|
20
|
+
import { deepClone } from '../deepClone';
|
|
21
|
+
import { DeepMap } from '../DeepMap';
|
|
22
|
+
import { DEFAULT_TO_KEY } from './defaultToKey';
|
|
23
|
+
import { KeyOfNoSymbol } from '../../components/InfiniteTable/types/Utility';
|
|
24
|
+
|
|
25
|
+
export const LAZY_ROOT_KEY_FOR_GROUPS = '____root____';
|
|
26
|
+
|
|
27
|
+
export const NOT_LOADED_YET_KEY_PREFIX = '____not_loaded_yet____';
|
|
28
|
+
|
|
29
|
+
export type AggregationReducer<
|
|
30
|
+
T,
|
|
31
|
+
AggregationResultType = any,
|
|
32
|
+
> = DataSourceAggregationReducer<T, AggregationResultType> & {
|
|
33
|
+
id: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type AggregationReducerResult<AggregationResultType extends any = any> =
|
|
37
|
+
AggregationResultType;
|
|
38
|
+
// {
|
|
39
|
+
// value: AggregationResultType;
|
|
40
|
+
// id: string;
|
|
41
|
+
// };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* InfiniteTableRowInfo can have different object shape depending on the presence or absence of grouping.
|
|
45
|
+
*
|
|
46
|
+
* You can use `dataSourceHasGrouping: boolean` as a discriminator to determine the shape of the object, to know
|
|
47
|
+
* if the dataSource had grouping or not. Furthermore, for when the dataSource has grouping,
|
|
48
|
+
* you can use `isGroupRow: boolean` to discriminate between group rows vs normal rows.
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
export type InfiniteTableRowInfo<T> =
|
|
52
|
+
| InfiniteTable_HasGrouping_RowInfoNormal<T>
|
|
53
|
+
| InfiniteTable_HasGrouping_RowInfoGroup<T>
|
|
54
|
+
| InfiniteTable_NoGrouping_RowInfoNormal<T>;
|
|
55
|
+
|
|
56
|
+
export type InfiniteTableRowInfoDataDiscriminator_RowInfoNormal<T> = {
|
|
57
|
+
data: T;
|
|
58
|
+
isGroupRow: false;
|
|
59
|
+
rowActive: boolean;
|
|
60
|
+
rowInfo:
|
|
61
|
+
| InfiniteTable_NoGrouping_RowInfoNormal<T>
|
|
62
|
+
| InfiniteTable_HasGrouping_RowInfoNormal<T>;
|
|
63
|
+
field?: keyof T;
|
|
64
|
+
value: any;
|
|
65
|
+
rowSelected: boolean | null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type InfiniteTableRowInfoDataDiscriminator_RowInfoGroup<T> = {
|
|
69
|
+
rowActive: boolean;
|
|
70
|
+
data: Partial<T> | null;
|
|
71
|
+
rowInfo: InfiniteTable_HasGrouping_RowInfoGroup<T>;
|
|
72
|
+
isGroupRow: true;
|
|
73
|
+
field?: keyof T;
|
|
74
|
+
value: any;
|
|
75
|
+
rowSelected: boolean | null;
|
|
76
|
+
};
|
|
77
|
+
export type InfiniteTableRowInfoDataDiscriminator<T> =
|
|
78
|
+
| InfiniteTableRowInfoDataDiscriminator_RowInfoNormal<T>
|
|
79
|
+
| InfiniteTableRowInfoDataDiscriminator_RowInfoGroup<T>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* This is the base row info for all scenarios - things every
|
|
83
|
+
* rowInfo is guaranteed to have (be it group or normal row, or dataSource with or without grouping)
|
|
84
|
+
*
|
|
85
|
+
*/
|
|
86
|
+
export type InfiniteTable_RowInfoBase<_T> = {
|
|
87
|
+
id: any;
|
|
88
|
+
value?: any;
|
|
89
|
+
indexInAll: number;
|
|
90
|
+
rowSelected: boolean | null;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type InfiniteTable_HasGrouping_RowInfoNormal<T> = {
|
|
94
|
+
dataSourceHasGrouping: true;
|
|
95
|
+
data: T;
|
|
96
|
+
isGroupRow: false;
|
|
97
|
+
} & InfiniteTable_HasGrouping_RowInfoBase<T> &
|
|
98
|
+
InfiniteTable_RowInfoBase<T>;
|
|
99
|
+
|
|
100
|
+
export type InfiniteTable_HasGrouping_RowInfoGroup<T> = {
|
|
101
|
+
dataSourceHasGrouping: true;
|
|
102
|
+
data: Partial<T> | null;
|
|
103
|
+
isGroupRow: true;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* This array contains all the (uncollapsed, so visible) row infos under this group, at any level of nesting,
|
|
107
|
+
* in the order in which they are visible in the table
|
|
108
|
+
*/
|
|
109
|
+
deepRowInfoArray: (
|
|
110
|
+
| InfiniteTable_HasGrouping_RowInfoNormal<T>
|
|
111
|
+
| InfiniteTable_HasGrouping_RowInfoGroup<T>
|
|
112
|
+
)[];
|
|
113
|
+
|
|
114
|
+
error?: string;
|
|
115
|
+
|
|
116
|
+
reducerResults?: Record<string, AggregationReducerResult>;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The count of all leaf nodes (normal rows) that are inside this group.
|
|
120
|
+
* This count is the same as the length of the groupData array property.
|
|
121
|
+
*
|
|
122
|
+
*/
|
|
123
|
+
groupCount: number;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The array of all leaf nodes (normal rows) that are inside this group.
|
|
127
|
+
*/
|
|
128
|
+
groupData: T[];
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The count of all selected leaf nodes (normal rows) inside the group that are selected
|
|
132
|
+
*/
|
|
133
|
+
selectedChildredCount: number;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The count of all deselected leaf nodes (normal rows) inside the group that are selected
|
|
137
|
+
*/
|
|
138
|
+
deselectedChildredCount: number;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Will be used only with lazy loading, if the server provides this info on the data items.
|
|
142
|
+
*
|
|
143
|
+
* Represents the total count of all leaf nodes (normal rows) that are under this group
|
|
144
|
+
* at any level (so not only direct children). This is needed for multiple selection to work properly,
|
|
145
|
+
* so the table component knows how many rows are on the remote backend, and whether to show a group as selected or not
|
|
146
|
+
* when it has a certain number of rows selected
|
|
147
|
+
*/
|
|
148
|
+
totalChildrenCount?: number;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The count of all leaf nodes (normal rows) inside the group that are not being visible
|
|
152
|
+
* due to collapsing (either the current row is collapsed or any of its children)
|
|
153
|
+
*/
|
|
154
|
+
collapsedChildrenCount: number;
|
|
155
|
+
|
|
156
|
+
// TODO document this
|
|
157
|
+
collapsedGroupsCount: number;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The count of the direct children of the current group. Direct children can be either normal rows or groups.
|
|
161
|
+
*/
|
|
162
|
+
directChildrenCount: number;
|
|
163
|
+
|
|
164
|
+
directChildrenLoadedCount: number;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
*
|
|
168
|
+
* A DeepMap of pivot values.
|
|
169
|
+
*
|
|
170
|
+
* For each pivot reducer result, it contains all the items that make up the pivot value.
|
|
171
|
+
*
|
|
172
|
+
*/
|
|
173
|
+
pivotValuesMap?: PivotValuesDeepMap<T, any>;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* For non-lazy grouping, this is always true.
|
|
177
|
+
* For lazy/batched grouping, this is true if the group has been expanded at least once (and if the remote call has been configured with cache: true),
|
|
178
|
+
* since if the remote call is not cached, collapsing the row group should lose all the data that was loaded for it, and it's as if it was never loaded, so in that case, childrenAvailable is false.
|
|
179
|
+
*
|
|
180
|
+
* NOTE: if this is true, it doesn't mean that all the children have been loaded, it only means that some children have been loaded and are available
|
|
181
|
+
*
|
|
182
|
+
* Use directChildrenCount and directChildrenLoadedCount to know if all the children have been loaded or not.
|
|
183
|
+
*/
|
|
184
|
+
childrenAvailable: boolean;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Boolean flag that will be true while lazy loading direct children of the current row group.
|
|
188
|
+
*
|
|
189
|
+
* NOTE: with batched loading, if the user is no longer scrolling, after everything
|
|
190
|
+
* in the viewport has loaded (and thus for example a certain row group had childrenLoading: true)
|
|
191
|
+
* if no new batches are being loaded, childrenLoading will be false again, even though
|
|
192
|
+
* the current row group still has children that are not loaded yet.
|
|
193
|
+
* Use directChildrenLoadedCount and directChildrenCount to know if all the children have been loaded or not.
|
|
194
|
+
*/
|
|
195
|
+
childrenLoading: boolean;
|
|
196
|
+
} & InfiniteTable_HasGrouping_RowInfoBase<T> &
|
|
197
|
+
InfiniteTable_RowInfoBase<T>;
|
|
198
|
+
|
|
199
|
+
export type InfiniteTable_NoGrouping_RowInfoNormal<T> = {
|
|
200
|
+
dataSourceHasGrouping: false;
|
|
201
|
+
data: T;
|
|
202
|
+
isGroupRow: false;
|
|
203
|
+
selfLoaded: boolean;
|
|
204
|
+
} & InfiniteTable_RowInfoBase<T>;
|
|
205
|
+
|
|
206
|
+
export type InfiniteTable_HasGrouping_RowInfoBase<T> = {
|
|
207
|
+
indexInGroup: number;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Available on all rowInfo objects when the datasource is grouped, otherwise, it will be undefined.
|
|
211
|
+
*
|
|
212
|
+
* For group rows, the group keys will have all the keys starting from the topmost parent
|
|
213
|
+
* down to the current group row (including the group row).
|
|
214
|
+
* For normal rows, the group keys will have all the keys starting from the topmost parent
|
|
215
|
+
* down to the last group row in the hierarchy (the direct parent of the current row).
|
|
216
|
+
*
|
|
217
|
+
* Example: People grouped by country and city
|
|
218
|
+
*
|
|
219
|
+
* Italy - country - groupKeys: ['Italy']
|
|
220
|
+
* Rome - city - groupKeys: ['Italy', 'Rome']
|
|
221
|
+
* Marco - person - groupKeys: ['Italy', 'Rome']
|
|
222
|
+
* Luca - person - groupKeys: ['Italy', 'Rome']
|
|
223
|
+
* Giuseppe - person - groupKeys: ['Italy', 'Rome']
|
|
224
|
+
*
|
|
225
|
+
*/
|
|
226
|
+
groupKeys: any[];
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Available on all rowInfo objects when the datasource is grouped, otherwise, it will be undefined.
|
|
230
|
+
*
|
|
231
|
+
* Has the same structure as groupKeys, but it will contain the fields used to group the rows.
|
|
232
|
+
*
|
|
233
|
+
* Example: People grouped by country and city
|
|
234
|
+
*
|
|
235
|
+
* Italy - country - groupKeys: ['country']
|
|
236
|
+
* Rome - city - groupKeys: ['country', 'city']
|
|
237
|
+
* Marco - person - groupKeys: ['country', 'city']
|
|
238
|
+
* Luca - person - groupKeys: ['country', 'city']
|
|
239
|
+
* Giuseppe - person - groupKeys: ['country', 'city']
|
|
240
|
+
*/
|
|
241
|
+
groupBy: (keyof T)[];
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The groupBy value of the DataSource component, mapped to the groupBy.field
|
|
245
|
+
*/
|
|
246
|
+
rootGroupBy: (keyof T)[];
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Available on all rowInfo objects when the datasource is grouped.
|
|
250
|
+
*
|
|
251
|
+
* Italy - country - parent mapped to their ids will be: [] // rowInfo.parents.map((p: any) => p.id)
|
|
252
|
+
* Rome - city - parent mapped to their ids will be: ['Italy']
|
|
253
|
+
* Marco - person - parent mapped to their ids will be: ['Italy','Italy,Rome']
|
|
254
|
+
* Luca - person - parent mapped to their ids will be: ['Italy','Italy,Rome']
|
|
255
|
+
* Giuseppe - person - parent mapped to their ids will be: ['Italy','Italy,Rome']
|
|
256
|
+
* USA - country - parent mapped to their ids will be: []
|
|
257
|
+
* LA - city - parent mapped to their ids will be: ['USA']
|
|
258
|
+
* Bob - person - parent mapped to their ids will be: ['USA','USA,LA']
|
|
259
|
+
*/
|
|
260
|
+
parents: InfiniteTable_HasGrouping_RowInfoGroup<T>[];
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Available when the datasource is grouped, this will be set for both group and normal rows.
|
|
264
|
+
* Italy - country - indexInParentGroups: [0]
|
|
265
|
+
* Rome - city - indexInParentGroups: [0,0]
|
|
266
|
+
* Marco - person - indexInParentGroups: [0,0,0]
|
|
267
|
+
* Luca - person - indexInParentGroups: [0,0,1]
|
|
268
|
+
* Giuseppe - person - indexInParentGroups: [0,0,2]
|
|
269
|
+
* USA - country - indexInParentGroups: [1]
|
|
270
|
+
* LA - city - indexInParentGroups: [1,0]
|
|
271
|
+
* Bob - person - indexInParentGroups: [1,0,2]
|
|
272
|
+
*/
|
|
273
|
+
indexInParentGroups: number[];
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Available on all rowInfo objects when the datasource is grouped.
|
|
277
|
+
*
|
|
278
|
+
* For every rowInfo object, it counts the number of leaf/normal rows that the group contains.
|
|
279
|
+
* For normal rows, the groupCount represents the groupCount of the direct parent.
|
|
280
|
+
*
|
|
281
|
+
* Italy - country - groupCount: 3
|
|
282
|
+
* Rome - city - groupCount: 2
|
|
283
|
+
* Marco - person - groupCount: 2
|
|
284
|
+
* Luca - person - groupCount: 2
|
|
285
|
+
* Napoli - city - groupCount: 1
|
|
286
|
+
* Giuseppe - person - groupCount: 1
|
|
287
|
+
* USA - country - groupCount: 1
|
|
288
|
+
* LA - city - groupCount: 1
|
|
289
|
+
* Bob - person - groupCount: 1
|
|
290
|
+
*/
|
|
291
|
+
groupCount: number;
|
|
292
|
+
|
|
293
|
+
groupNesting: number;
|
|
294
|
+
|
|
295
|
+
collapsed: boolean;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* This is false only when the DataSource is configured with lazy batching and the current
|
|
299
|
+
* row has not been loaded yet. It has nothing to do with children, only with self.
|
|
300
|
+
*/
|
|
301
|
+
selfLoaded: boolean;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
export type GroupKeyType<T extends any = any> = T; //string | number | symbol | null | undefined;
|
|
305
|
+
|
|
306
|
+
type PivotReducerResults<T = any> = Record<string, AggregationReducerResult<T>>;
|
|
307
|
+
|
|
308
|
+
type PivotGroupValueType<DataType, KeyType> = {
|
|
309
|
+
reducerResults: PivotReducerResults<KeyType>;
|
|
310
|
+
items: DataType[];
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
export type PivotValuesDeepMap<DataType, KeyType> = DeepMap<
|
|
314
|
+
GroupKeyType<KeyType>,
|
|
315
|
+
PivotGroupValueType<DataType, KeyType>
|
|
316
|
+
>;
|
|
317
|
+
|
|
318
|
+
export type DeepMapGroupValueType<DataType, KeyType> = {
|
|
319
|
+
/**
|
|
320
|
+
* These are leaf items. This array may be empty when there is batched lazy loading
|
|
321
|
+
*/
|
|
322
|
+
items: DataType[];
|
|
323
|
+
commonData?: Partial<DataType>;
|
|
324
|
+
childrenLoading: boolean;
|
|
325
|
+
childrenAvailable: boolean;
|
|
326
|
+
totalChildrenCount?: number;
|
|
327
|
+
cache: boolean;
|
|
328
|
+
error?: string;
|
|
329
|
+
reducerResults: Record<string, AggregationReducerResult>;
|
|
330
|
+
pivotDeepMap?: DeepMap<
|
|
331
|
+
GroupKeyType<KeyType>,
|
|
332
|
+
PivotGroupValueType<DataType, KeyType>
|
|
333
|
+
>;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
export type PivotBy<DataType, KeyType> = Omit<
|
|
337
|
+
GroupBy<DataType, KeyType>,
|
|
338
|
+
'column'
|
|
339
|
+
> & {
|
|
340
|
+
column?:
|
|
341
|
+
| ColumnTypeWithInherit<Partial<InfiniteTableColumn<DataType>>>
|
|
342
|
+
| (({
|
|
343
|
+
column,
|
|
344
|
+
}: {
|
|
345
|
+
column: InfiniteTablePivotFinalColumnVariant<DataType, KeyType>;
|
|
346
|
+
}) => Partial<InfiniteTablePivotColumn<DataType>>);
|
|
347
|
+
columnGroup?:
|
|
348
|
+
| InfiniteTableColumnGroup
|
|
349
|
+
| (({
|
|
350
|
+
columnGroup,
|
|
351
|
+
}: {
|
|
352
|
+
columnGroup: InfiniteTablePivotFinalColumnGroup<DataType, KeyType>;
|
|
353
|
+
}) => ColumnTypeWithInherit<
|
|
354
|
+
Partial<InfiniteTablePivotFinalColumnGroup<DataType>>
|
|
355
|
+
>);
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
type GroupParams<DataType, KeyType> = {
|
|
359
|
+
groupBy: GroupBy<DataType, KeyType>[];
|
|
360
|
+
defaultToKey?: (value: any, item: DataType) => GroupKeyType<KeyType>;
|
|
361
|
+
|
|
362
|
+
pivot?: PivotBy<DataType, KeyType>[];
|
|
363
|
+
reducers?: Record<string, DataSourceAggregationReducer<DataType, any>>;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
type LazyGroupParams<DataType> = {
|
|
367
|
+
mappings?: DataSourceMappings;
|
|
368
|
+
indexer: Indexer<DataType>;
|
|
369
|
+
toPrimaryKey: (item: DataType) => any;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
export type DataGroupResult<DataType, KeyType extends any> = {
|
|
373
|
+
deepMap: DeepMap<
|
|
374
|
+
GroupKeyType<KeyType>,
|
|
375
|
+
DeepMapGroupValueType<DataType, KeyType>
|
|
376
|
+
>;
|
|
377
|
+
groupParams: GroupParams<DataType, KeyType>;
|
|
378
|
+
initialData: DataType[];
|
|
379
|
+
reducerResults?: Record<string, AggregationReducerResult>;
|
|
380
|
+
topLevelPivotColumns?: DeepMap<GroupKeyType<KeyType>, boolean>;
|
|
381
|
+
pivot?: PivotBy<DataType, KeyType>[];
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
function initReducers<DataType>(
|
|
385
|
+
reducers?: Record<string, DataSourceAggregationReducer<DataType, any>>,
|
|
386
|
+
): Record<string, AggregationReducerResult> {
|
|
387
|
+
if (!reducers || !Object.keys(reducers).length) {
|
|
388
|
+
return {};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const result: Record<string, AggregationReducerResult> = {};
|
|
392
|
+
|
|
393
|
+
for (const key in reducers)
|
|
394
|
+
if (reducers.hasOwnProperty(key)) {
|
|
395
|
+
result[key] = reducers[key].initialValue;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
*
|
|
403
|
+
* This fn mutates the reducerResults array!!!
|
|
404
|
+
*
|
|
405
|
+
* @param data data item
|
|
406
|
+
* @param reducers an array of reducers
|
|
407
|
+
* @param reducerResults the results on which to operate
|
|
408
|
+
*
|
|
409
|
+
*/
|
|
410
|
+
function computeReducersFor<DataType>(
|
|
411
|
+
data: DataType,
|
|
412
|
+
index: number,
|
|
413
|
+
reducers: Record<string, DataSourceAggregationReducer<DataType, any>>,
|
|
414
|
+
reducerResults: Record<string, AggregationReducerResult>,
|
|
415
|
+
groupKeys: any[] | undefined,
|
|
416
|
+
) {
|
|
417
|
+
if (!reducers || !Object.keys(reducers).length) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
for (const key in reducers)
|
|
422
|
+
if (reducers.hasOwnProperty(key)) {
|
|
423
|
+
const reducer = reducers[key];
|
|
424
|
+
if (typeof reducer.reducer !== 'function') {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
const currentValue = reducerResults[key];
|
|
428
|
+
|
|
429
|
+
const value = reducer.field
|
|
430
|
+
? data[reducer.field]
|
|
431
|
+
: reducer.getter?.(data) ?? null;
|
|
432
|
+
|
|
433
|
+
reducerResults[key] = reducer.reducer(
|
|
434
|
+
currentValue,
|
|
435
|
+
value,
|
|
436
|
+
data,
|
|
437
|
+
index,
|
|
438
|
+
groupKeys,
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
type LazyPivotContainer = {
|
|
444
|
+
values: Record<string, any>;
|
|
445
|
+
totals?: Record<string, any>;
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
export function lazyGroup<DataType, KeyType extends string = string>(
|
|
449
|
+
groupParams: GroupParams<DataType, KeyType> & LazyGroupParams<DataType>,
|
|
450
|
+
rootData: LazyGroupDataDeepMap<DataType>,
|
|
451
|
+
): DataGroupResult<DataType, KeyType> {
|
|
452
|
+
const {
|
|
453
|
+
reducers = {},
|
|
454
|
+
pivot,
|
|
455
|
+
groupBy,
|
|
456
|
+
|
|
457
|
+
indexer,
|
|
458
|
+
toPrimaryKey,
|
|
459
|
+
mappings,
|
|
460
|
+
} = groupParams;
|
|
461
|
+
|
|
462
|
+
const deepMap = new DeepMap<
|
|
463
|
+
GroupKeyType<KeyType>,
|
|
464
|
+
DeepMapGroupValueType<DataType, KeyType>
|
|
465
|
+
>();
|
|
466
|
+
|
|
467
|
+
function traverseValues(
|
|
468
|
+
pivotDeepMap: DeepMap<
|
|
469
|
+
GroupKeyType<KeyType>,
|
|
470
|
+
PivotGroupValueType<DataType, KeyType>
|
|
471
|
+
>,
|
|
472
|
+
container: LazyPivotContainer,
|
|
473
|
+
pivot: PivotBy<DataType, KeyType>[],
|
|
474
|
+
pivotIndex = 0,
|
|
475
|
+
currentPivotKeys: KeyType[] = [],
|
|
476
|
+
) {
|
|
477
|
+
const last = !pivot.length || pivotIndex === pivot.length - 1;
|
|
478
|
+
const values = container[(mappings?.values || 'values') as 'values'] || {};
|
|
479
|
+
for (const k in values)
|
|
480
|
+
if (values.hasOwnProperty(k)) {
|
|
481
|
+
const pivotKey = k;
|
|
482
|
+
currentPivotKeys.push(pivotKey as any as KeyType);
|
|
483
|
+
|
|
484
|
+
topLevelPivotColumns!.set(currentPivotKeys, true);
|
|
485
|
+
pivotDeepMap.set(currentPivotKeys, {
|
|
486
|
+
reducerResults: values[k][mappings?.totals || 'totals'] || {},
|
|
487
|
+
items: [],
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
if (!last) {
|
|
491
|
+
traverseValues(
|
|
492
|
+
pivotDeepMap,
|
|
493
|
+
values[k],
|
|
494
|
+
pivot,
|
|
495
|
+
pivotIndex + 1,
|
|
496
|
+
currentPivotKeys,
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
currentPivotKeys.pop();
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const topLevelPivotColumns = pivot
|
|
505
|
+
? new DeepMap<GroupKeyType<KeyType>, boolean>()
|
|
506
|
+
: undefined;
|
|
507
|
+
|
|
508
|
+
const currentPivotKeys: GroupKeyType<KeyType>[] = [];
|
|
509
|
+
|
|
510
|
+
const initialReducerValue = initReducers<DataType>(reducers);
|
|
511
|
+
|
|
512
|
+
const globalReducerResults = deepClone(initialReducerValue);
|
|
513
|
+
|
|
514
|
+
rootData.visitDepthFirst(
|
|
515
|
+
(lazyGroupRowInfo: LazyRowInfoGroup<DataType>, keys, _index, next) => {
|
|
516
|
+
const [_rootKey, ...currentGroupKeys] = keys;
|
|
517
|
+
const dataArray = lazyGroupRowInfo.children;
|
|
518
|
+
|
|
519
|
+
const current = deepMap.get(currentGroupKeys as KeyType[]);
|
|
520
|
+
if (current) {
|
|
521
|
+
current.cache = lazyGroupRowInfo.cache;
|
|
522
|
+
current.childrenLoading = lazyGroupRowInfo.childrenLoading;
|
|
523
|
+
current.childrenAvailable = lazyGroupRowInfo.childrenAvailable;
|
|
524
|
+
current.error = lazyGroupRowInfo.error;
|
|
525
|
+
}
|
|
526
|
+
if (currentGroupKeys.length == groupBy.length && groupBy.length) {
|
|
527
|
+
if (current) {
|
|
528
|
+
//@ts-ignore
|
|
529
|
+
current.items = dataArray;
|
|
530
|
+
|
|
531
|
+
for (let i = 0, len = currentGroupKeys.length; i < len; i++) {
|
|
532
|
+
const currentKeys = currentGroupKeys.slice(0, i);
|
|
533
|
+
const deepMapGroupValue = deepMap.get(
|
|
534
|
+
currentKeys as KeyType[],
|
|
535
|
+
) as DeepMapGroupValueType<DataType, KeyType>;
|
|
536
|
+
|
|
537
|
+
if (deepMapGroupValue) {
|
|
538
|
+
deepMapGroupValue.items = deepMapGroupValue.items || [];
|
|
539
|
+
deepMapGroupValue.items = deepMapGroupValue.items.concat(
|
|
540
|
+
dataArray as any as DataType[],
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
indexer.indexArray(dataArray as any as DataType[], toPrimaryKey);
|
|
546
|
+
}
|
|
547
|
+
return next?.();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
for (let i = 0, len = dataArray.length; i < len; i++) {
|
|
551
|
+
if (!dataArray[i]) {
|
|
552
|
+
// we're in the case of lazy loading, so some records might not be available just yet
|
|
553
|
+
const deepMapGroupValue: DeepMapGroupValueType<DataType, KeyType> = {
|
|
554
|
+
items: [],
|
|
555
|
+
reducerResults: {},
|
|
556
|
+
cache: false,
|
|
557
|
+
childrenLoading: false,
|
|
558
|
+
childrenAvailable: false,
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
deepMap.set(
|
|
562
|
+
[
|
|
563
|
+
...currentGroupKeys,
|
|
564
|
+
`${NOT_LOADED_YET_KEY_PREFIX}${i}`,
|
|
565
|
+
] as KeyType[],
|
|
566
|
+
deepMapGroupValue,
|
|
567
|
+
);
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
const dataObject = dataArray[i].data;
|
|
571
|
+
const dataKeys = dataArray[i].keys || [];
|
|
572
|
+
// const item = dataObject as Partial<DataType>;
|
|
573
|
+
|
|
574
|
+
if (dataKeys.length) {
|
|
575
|
+
// we need to take the key that comes from the server, and not from the property
|
|
576
|
+
// although they should probably be the same
|
|
577
|
+
const key = dataKeys[dataKeys.length - 1];
|
|
578
|
+
currentGroupKeys.push(key);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const deepMapGroupValue: DeepMapGroupValueType<DataType, KeyType> = {
|
|
582
|
+
items: [],
|
|
583
|
+
cache: false,
|
|
584
|
+
childrenLoading: false,
|
|
585
|
+
childrenAvailable: false,
|
|
586
|
+
commonData: dataObject,
|
|
587
|
+
totalChildrenCount: dataArray[i].totalChildrenCount,
|
|
588
|
+
reducerResults: dataArray[i].aggregations || {},
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
deepMap.set(currentGroupKeys as KeyType[], deepMapGroupValue);
|
|
592
|
+
|
|
593
|
+
if (pivot) {
|
|
594
|
+
const pivotDeepMap = (deepMapGroupValue.pivotDeepMap = new DeepMap<
|
|
595
|
+
GroupKeyType<KeyType>,
|
|
596
|
+
PivotGroupValueType<DataType, KeyType>
|
|
597
|
+
>());
|
|
598
|
+
|
|
599
|
+
const pivotContainer = dataArray[i]
|
|
600
|
+
.pivot as any as LazyPivotContainer;
|
|
601
|
+
|
|
602
|
+
traverseValues(
|
|
603
|
+
pivotDeepMap,
|
|
604
|
+
pivotContainer,
|
|
605
|
+
pivot,
|
|
606
|
+
0,
|
|
607
|
+
currentPivotKeys,
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (dataKeys.length) {
|
|
612
|
+
currentGroupKeys.pop();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
next?.();
|
|
617
|
+
},
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
const result: DataGroupResult<DataType, KeyType> = {
|
|
621
|
+
deepMap,
|
|
622
|
+
groupParams,
|
|
623
|
+
//@ts-ignore
|
|
624
|
+
initialData: rootData,
|
|
625
|
+
|
|
626
|
+
reducerResults: globalReducerResults,
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
if (pivot) {
|
|
630
|
+
result.topLevelPivotColumns = topLevelPivotColumns;
|
|
631
|
+
result.pivot = pivot;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return result;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function processGroup<KeyType, DataType>(
|
|
638
|
+
deepMap: DeepMap<
|
|
639
|
+
GroupKeyType<KeyType>,
|
|
640
|
+
DeepMapGroupValueType<DataType, KeyType>
|
|
641
|
+
>,
|
|
642
|
+
currentGroupKeys: KeyType[],
|
|
643
|
+
currentPivotKeys: KeyType[],
|
|
644
|
+
item: DataType,
|
|
645
|
+
itemIndex: number,
|
|
646
|
+
pivot: GroupParams<DataType, KeyType>['pivot'],
|
|
647
|
+
reducers: GroupParams<DataType, KeyType>['reducers'],
|
|
648
|
+
topLevelPivotColumns: DeepMap<GroupKeyType<KeyType>, boolean>,
|
|
649
|
+
initialReducerValue: Record<string, AggregationReducerResult>,
|
|
650
|
+
defaultToKey: GroupParams<DataType, KeyType>['defaultToKey'] = DEFAULT_TO_KEY,
|
|
651
|
+
) {
|
|
652
|
+
const {
|
|
653
|
+
items: currentGroupItems,
|
|
654
|
+
reducerResults,
|
|
655
|
+
pivotDeepMap,
|
|
656
|
+
} = deepMap.get(currentGroupKeys)!;
|
|
657
|
+
|
|
658
|
+
currentGroupItems.push(item);
|
|
659
|
+
|
|
660
|
+
if (reducers) {
|
|
661
|
+
computeReducersFor<DataType>(
|
|
662
|
+
item,
|
|
663
|
+
itemIndex,
|
|
664
|
+
reducers,
|
|
665
|
+
reducerResults,
|
|
666
|
+
currentGroupKeys,
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
if (pivot) {
|
|
670
|
+
for (
|
|
671
|
+
let pivotIndex = 0, pivotLength = pivot.length;
|
|
672
|
+
pivotIndex < pivotLength;
|
|
673
|
+
pivotIndex++
|
|
674
|
+
) {
|
|
675
|
+
const { field: pivotField, toKey: pivotToKey } = pivot[pivotIndex];
|
|
676
|
+
const pivotKey: GroupKeyType<KeyType> = (pivotToKey || defaultToKey)(
|
|
677
|
+
item[pivotField],
|
|
678
|
+
item,
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
currentPivotKeys.push(pivotKey);
|
|
682
|
+
if (!pivotDeepMap!.has(currentPivotKeys)) {
|
|
683
|
+
topLevelPivotColumns!.set(currentPivotKeys, true);
|
|
684
|
+
pivotDeepMap?.set(currentPivotKeys, {
|
|
685
|
+
reducerResults: deepClone(initialReducerValue),
|
|
686
|
+
items: [],
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
const { reducerResults: pivotReducerResults, items: pivotGroupItems } =
|
|
690
|
+
pivotDeepMap!.get(currentPivotKeys)!;
|
|
691
|
+
|
|
692
|
+
pivotGroupItems.push(item);
|
|
693
|
+
if (reducers) {
|
|
694
|
+
computeReducersFor<DataType>(
|
|
695
|
+
item,
|
|
696
|
+
itemIndex,
|
|
697
|
+
reducers,
|
|
698
|
+
pivotReducerResults,
|
|
699
|
+
currentGroupKeys,
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
currentPivotKeys.length = 0;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
export function group<DataType, KeyType = any>(
|
|
708
|
+
groupParams: GroupParams<DataType, KeyType>,
|
|
709
|
+
data: DataType[],
|
|
710
|
+
): DataGroupResult<DataType, KeyType> {
|
|
711
|
+
const {
|
|
712
|
+
groupBy,
|
|
713
|
+
defaultToKey = DEFAULT_TO_KEY,
|
|
714
|
+
pivot,
|
|
715
|
+
reducers,
|
|
716
|
+
} = groupParams;
|
|
717
|
+
|
|
718
|
+
const groupByLength = groupBy.length;
|
|
719
|
+
|
|
720
|
+
const topLevelPivotColumns = pivot
|
|
721
|
+
? new DeepMap<GroupKeyType<KeyType>, boolean>()
|
|
722
|
+
: undefined;
|
|
723
|
+
|
|
724
|
+
const deepMap = new DeepMap<
|
|
725
|
+
GroupKeyType<KeyType>,
|
|
726
|
+
DeepMapGroupValueType<DataType, KeyType>
|
|
727
|
+
>();
|
|
728
|
+
|
|
729
|
+
const currentGroupKeys: GroupKeyType<KeyType>[] = [];
|
|
730
|
+
const currentPivotKeys: GroupKeyType<KeyType>[] = [];
|
|
731
|
+
|
|
732
|
+
const initialReducerValue = initReducers<DataType>(reducers);
|
|
733
|
+
|
|
734
|
+
const globalReducerResults = deepClone(initialReducerValue);
|
|
735
|
+
|
|
736
|
+
if (!groupByLength) {
|
|
737
|
+
const deepMapGroupValue: DeepMapGroupValueType<DataType, KeyType> = {
|
|
738
|
+
items: [],
|
|
739
|
+
cache: false,
|
|
740
|
+
childrenLoading: false,
|
|
741
|
+
childrenAvailable: false,
|
|
742
|
+
reducerResults: deepClone(initialReducerValue),
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
if (pivot) {
|
|
746
|
+
deepMapGroupValue.pivotDeepMap = new DeepMap<
|
|
747
|
+
GroupKeyType<KeyType>,
|
|
748
|
+
PivotGroupValueType<DataType, KeyType>
|
|
749
|
+
>();
|
|
750
|
+
}
|
|
751
|
+
deepMap.set(currentGroupKeys, deepMapGroupValue);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
for (let i = 0, len = data.length; i < len; i++) {
|
|
755
|
+
const item = data[i];
|
|
756
|
+
|
|
757
|
+
const commonData: Partial<DataType> = {};
|
|
758
|
+
for (let groupByIndex = 0; groupByIndex < groupByLength; groupByIndex++) {
|
|
759
|
+
const { field: groupByProperty, toKey: groupToKey } =
|
|
760
|
+
groupBy[groupByIndex];
|
|
761
|
+
const key: GroupKeyType<KeyType> = (groupToKey || defaultToKey)(
|
|
762
|
+
item[groupByProperty],
|
|
763
|
+
item,
|
|
764
|
+
);
|
|
765
|
+
|
|
766
|
+
commonData[groupByProperty] =
|
|
767
|
+
key as any as DataType[KeyOfNoSymbol<DataType>];
|
|
768
|
+
currentGroupKeys.push(key);
|
|
769
|
+
|
|
770
|
+
if (!deepMap.has(currentGroupKeys)) {
|
|
771
|
+
const deepMapGroupValue: DeepMapGroupValueType<DataType, KeyType> = {
|
|
772
|
+
items: [],
|
|
773
|
+
cache: false,
|
|
774
|
+
commonData: { ...commonData },
|
|
775
|
+
childrenLoading: false,
|
|
776
|
+
childrenAvailable: false,
|
|
777
|
+
reducerResults: deepClone(initialReducerValue),
|
|
778
|
+
};
|
|
779
|
+
if (pivot) {
|
|
780
|
+
deepMapGroupValue.pivotDeepMap = new DeepMap<
|
|
781
|
+
GroupKeyType<KeyType>,
|
|
782
|
+
PivotGroupValueType<DataType, KeyType>
|
|
783
|
+
>();
|
|
784
|
+
}
|
|
785
|
+
deepMap.set(currentGroupKeys, deepMapGroupValue);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
processGroup(
|
|
789
|
+
deepMap,
|
|
790
|
+
currentGroupKeys,
|
|
791
|
+
currentPivotKeys,
|
|
792
|
+
item,
|
|
793
|
+
i,
|
|
794
|
+
pivot,
|
|
795
|
+
reducers,
|
|
796
|
+
topLevelPivotColumns!,
|
|
797
|
+
initialReducerValue,
|
|
798
|
+
defaultToKey,
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (!groupByLength) {
|
|
803
|
+
processGroup(
|
|
804
|
+
deepMap,
|
|
805
|
+
currentGroupKeys,
|
|
806
|
+
currentPivotKeys,
|
|
807
|
+
item,
|
|
808
|
+
i,
|
|
809
|
+
pivot,
|
|
810
|
+
reducers,
|
|
811
|
+
topLevelPivotColumns!,
|
|
812
|
+
initialReducerValue,
|
|
813
|
+
defaultToKey,
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
if (reducers) {
|
|
818
|
+
computeReducersFor<DataType>(
|
|
819
|
+
item,
|
|
820
|
+
i,
|
|
821
|
+
reducers,
|
|
822
|
+
globalReducerResults,
|
|
823
|
+
currentGroupKeys,
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
currentGroupKeys.length = 0;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
if (reducers) {
|
|
831
|
+
deepMap.visitDepthFirst(
|
|
832
|
+
(deepMapValue, _keys: KeyType[], _indexInGroup, next) => {
|
|
833
|
+
completeReducers(
|
|
834
|
+
reducers,
|
|
835
|
+
deepMapValue.reducerResults,
|
|
836
|
+
deepMapValue.items,
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
if (pivot) {
|
|
840
|
+
// do we need this check
|
|
841
|
+
deepMapValue.pivotDeepMap!.visitDepthFirst(
|
|
842
|
+
(
|
|
843
|
+
{ items, reducerResults: pivotReducerResults },
|
|
844
|
+
_keys: KeyType[],
|
|
845
|
+
_indexInGroup,
|
|
846
|
+
next,
|
|
847
|
+
) => {
|
|
848
|
+
completeReducers(reducers, pivotReducerResults, items);
|
|
849
|
+
next?.();
|
|
850
|
+
},
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
next?.();
|
|
854
|
+
},
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (reducers) {
|
|
859
|
+
completeReducers(reducers, globalReducerResults, data);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
const result: DataGroupResult<DataType, KeyType> = {
|
|
863
|
+
deepMap,
|
|
864
|
+
groupParams,
|
|
865
|
+
initialData: data,
|
|
866
|
+
|
|
867
|
+
reducerResults: globalReducerResults,
|
|
868
|
+
};
|
|
869
|
+
if (pivot) {
|
|
870
|
+
result.topLevelPivotColumns = topLevelPivotColumns;
|
|
871
|
+
result.pivot = pivot;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return result;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
export function flatten<DataType, KeyType extends any>(
|
|
878
|
+
groupResult: DataGroupResult<DataType, KeyType>,
|
|
879
|
+
): DataType[] {
|
|
880
|
+
const { groupParams, deepMap } = groupResult;
|
|
881
|
+
const groupByLength = groupParams.groupBy.length;
|
|
882
|
+
|
|
883
|
+
const result: DataType[] = [];
|
|
884
|
+
|
|
885
|
+
deepMap.topDownKeys().reduce((acc: DataType[], key) => {
|
|
886
|
+
if (key.length === groupByLength) {
|
|
887
|
+
const items = deepMap.get(key)!.items;
|
|
888
|
+
acc.push(...items);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
return acc;
|
|
892
|
+
}, result);
|
|
893
|
+
|
|
894
|
+
return result;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
type GetEnhancedGroupDataOptions<DataType> = {
|
|
898
|
+
lazyLoad: boolean;
|
|
899
|
+
groupKeys: any[];
|
|
900
|
+
groupBy: (keyof DataType)[];
|
|
901
|
+
|
|
902
|
+
error?: string;
|
|
903
|
+
parents: InfiniteTable_HasGrouping_RowInfoGroup<DataType>[];
|
|
904
|
+
indexInParentGroups: number[];
|
|
905
|
+
indexInGroup: number;
|
|
906
|
+
indexInAll: number;
|
|
907
|
+
childrenLoading: boolean;
|
|
908
|
+
childrenAvailable: boolean;
|
|
909
|
+
totalChildrenCount?: number;
|
|
910
|
+
directChildrenCount: number;
|
|
911
|
+
directChildrenLoadedCount: number;
|
|
912
|
+
reducers: Record<string, DataSourceAggregationReducer<DataType, any>>;
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
function getEnhancedGroupData<DataType>(
|
|
916
|
+
options: GetEnhancedGroupDataOptions<DataType>,
|
|
917
|
+
deepMapValue: DeepMapGroupValueType<DataType, any>,
|
|
918
|
+
) {
|
|
919
|
+
const { groupBy, groupKeys, parents, reducers, lazyLoad } = options;
|
|
920
|
+
const groupNesting = groupKeys.length;
|
|
921
|
+
const {
|
|
922
|
+
items: groupItems,
|
|
923
|
+
reducerResults,
|
|
924
|
+
|
|
925
|
+
pivotDeepMap,
|
|
926
|
+
commonData,
|
|
927
|
+
} = deepMapValue;
|
|
928
|
+
|
|
929
|
+
let data = commonData ?? (null as Partial<DataType> | null);
|
|
930
|
+
|
|
931
|
+
if (Object.keys(reducerResults).length > 0) {
|
|
932
|
+
data = { ...commonData } as Partial<DataType>;
|
|
933
|
+
|
|
934
|
+
for (const key in reducers)
|
|
935
|
+
if (reducers.hasOwnProperty(key)) {
|
|
936
|
+
const reducer = reducers[key];
|
|
937
|
+
|
|
938
|
+
const field = reducer.field as keyof DataType;
|
|
939
|
+
if (field) {
|
|
940
|
+
data[field] = reducerResults[key] as any;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
let selfLoaded = true;
|
|
946
|
+
|
|
947
|
+
let theValue =
|
|
948
|
+
// if there is a value for the current groupBy in the data object, use it
|
|
949
|
+
(data != null ? data[groupBy[groupKeys.length - 1]] : null) ??
|
|
950
|
+
// otherwise just use the group key
|
|
951
|
+
groupKeys[groupKeys.length - 1];
|
|
952
|
+
|
|
953
|
+
if (
|
|
954
|
+
typeof theValue === 'string' &&
|
|
955
|
+
theValue.startsWith(NOT_LOADED_YET_KEY_PREFIX)
|
|
956
|
+
) {
|
|
957
|
+
selfLoaded = false;
|
|
958
|
+
theValue = null;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
const enhancedGroupData: InfiniteTable_HasGrouping_RowInfoGroup<DataType> = {
|
|
962
|
+
data,
|
|
963
|
+
groupCount: groupItems.length,
|
|
964
|
+
groupData: groupItems,
|
|
965
|
+
groupKeys,
|
|
966
|
+
|
|
967
|
+
rowSelected: false,
|
|
968
|
+
selectedChildredCount: 0,
|
|
969
|
+
deselectedChildredCount: 0,
|
|
970
|
+
id: `${groupKeys}`, //TODO improve this
|
|
971
|
+
collapsed: false,
|
|
972
|
+
dataSourceHasGrouping: true,
|
|
973
|
+
selfLoaded,
|
|
974
|
+
error: options.error,
|
|
975
|
+
|
|
976
|
+
parents,
|
|
977
|
+
deepRowInfoArray: [],
|
|
978
|
+
collapsedChildrenCount: 0,
|
|
979
|
+
collapsedGroupsCount: 0,
|
|
980
|
+
totalChildrenCount: options.totalChildrenCount,
|
|
981
|
+
// childrenAvailable: collapsed ? (!lazyLoad ? false : cacheExists) : true,
|
|
982
|
+
childrenAvailable: lazyLoad ? options.childrenAvailable : true,
|
|
983
|
+
childrenLoading: options.childrenLoading,
|
|
984
|
+
indexInParentGroups: options.indexInParentGroups,
|
|
985
|
+
indexInGroup: options.indexInGroup,
|
|
986
|
+
indexInAll: options.indexInAll,
|
|
987
|
+
directChildrenCount: options.directChildrenCount,
|
|
988
|
+
directChildrenLoadedCount: lazyLoad
|
|
989
|
+
? options.directChildrenLoadedCount
|
|
990
|
+
: options.directChildrenCount,
|
|
991
|
+
value: theValue,
|
|
992
|
+
rootGroupBy: groupBy,
|
|
993
|
+
groupBy:
|
|
994
|
+
groupNesting === groupBy.length
|
|
995
|
+
? groupBy
|
|
996
|
+
: (groupBy.slice(0, groupNesting) as (keyof DataType)[]),
|
|
997
|
+
isGroupRow: true,
|
|
998
|
+
pivotValuesMap: pivotDeepMap,
|
|
999
|
+
groupNesting,
|
|
1000
|
+
reducerResults,
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
return enhancedGroupData;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
function completeReducers<DataType>(
|
|
1007
|
+
reducers: Record<string, DataSourceAggregationReducer<DataType, any>>,
|
|
1008
|
+
reducerResults: Record<string, AggregationReducerResult>,
|
|
1009
|
+
items: DataType[],
|
|
1010
|
+
) {
|
|
1011
|
+
if (reducers) {
|
|
1012
|
+
for (const key in reducers)
|
|
1013
|
+
if (reducers.hasOwnProperty(key)) {
|
|
1014
|
+
const reducer = reducers[key];
|
|
1015
|
+
if (reducer.done) {
|
|
1016
|
+
reducerResults[key] = reducer.done!(reducerResults[key], items);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
return reducerResults;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export type EnhancedFlattenParam<DataType, KeyType = any> = {
|
|
1025
|
+
lazyLoad: boolean;
|
|
1026
|
+
|
|
1027
|
+
groupResult: DataGroupResult<DataType, KeyType>;
|
|
1028
|
+
toPrimaryKey: (data: DataType, index: number) => any;
|
|
1029
|
+
groupRowsState?: GroupRowsState;
|
|
1030
|
+
isRowSelected?: (rowInfo: InfiniteTableRowInfo<DataType>) => boolean | null;
|
|
1031
|
+
|
|
1032
|
+
reducers?: Record<string, DataSourceAggregationReducer<DataType, any>>;
|
|
1033
|
+
rowSelectionState?: RowSelectionState;
|
|
1034
|
+
generateGroupRows: boolean;
|
|
1035
|
+
};
|
|
1036
|
+
export function enhancedFlatten<DataType, KeyType = any>(
|
|
1037
|
+
param: EnhancedFlattenParam<DataType, KeyType>,
|
|
1038
|
+
): { data: InfiniteTableRowInfo<DataType>[]; groupRowsIndexes: number[] } {
|
|
1039
|
+
const {
|
|
1040
|
+
lazyLoad,
|
|
1041
|
+
groupResult,
|
|
1042
|
+
toPrimaryKey,
|
|
1043
|
+
groupRowsState,
|
|
1044
|
+
isRowSelected,
|
|
1045
|
+
rowSelectionState,
|
|
1046
|
+
generateGroupRows,
|
|
1047
|
+
reducers = {},
|
|
1048
|
+
} = param;
|
|
1049
|
+
const { groupParams, deepMap, pivot } = groupResult;
|
|
1050
|
+
const { groupBy } = groupParams;
|
|
1051
|
+
|
|
1052
|
+
const groupByStrings = groupBy.map((g) => g.field);
|
|
1053
|
+
|
|
1054
|
+
const result: InfiniteTableRowInfo<DataType>[] = [];
|
|
1055
|
+
const groupRowsIndexes: number[] = [];
|
|
1056
|
+
|
|
1057
|
+
const parents: InfiniteTable_HasGrouping_RowInfoGroup<DataType>[] = [];
|
|
1058
|
+
const indexInParentGroups: number[] = [];
|
|
1059
|
+
|
|
1060
|
+
deepMap.visitDepthFirst(
|
|
1061
|
+
(deepMapValue, groupKeys: any[], indexInGroup, next?: () => void) => {
|
|
1062
|
+
const items = deepMapValue.items;
|
|
1063
|
+
|
|
1064
|
+
const groupNesting = groupKeys.length;
|
|
1065
|
+
|
|
1066
|
+
let collapsed = groupRowsState?.isGroupRowCollapsed(groupKeys) ?? false;
|
|
1067
|
+
|
|
1068
|
+
indexInParentGroups.push(indexInGroup);
|
|
1069
|
+
|
|
1070
|
+
const enhancedGroupData: InfiniteTable_HasGrouping_RowInfoGroup<DataType> =
|
|
1071
|
+
getEnhancedGroupData(
|
|
1072
|
+
{
|
|
1073
|
+
lazyLoad,
|
|
1074
|
+
groupBy: groupByStrings,
|
|
1075
|
+
parents: Array.from(parents),
|
|
1076
|
+
reducers,
|
|
1077
|
+
indexInGroup,
|
|
1078
|
+
indexInParentGroups: Array.from(indexInParentGroups),
|
|
1079
|
+
indexInAll: result.length,
|
|
1080
|
+
groupKeys,
|
|
1081
|
+
error: deepMapValue.error,
|
|
1082
|
+
totalChildrenCount: deepMapValue.totalChildrenCount,
|
|
1083
|
+
childrenLoading:
|
|
1084
|
+
(deepMapValue.childrenLoading ||
|
|
1085
|
+
(!collapsed && !deepMapValue.childrenAvailable)) &&
|
|
1086
|
+
lazyLoad,
|
|
1087
|
+
childrenAvailable: deepMapValue.childrenAvailable,
|
|
1088
|
+
directChildrenCount:
|
|
1089
|
+
groupKeys.length === groupByStrings.length
|
|
1090
|
+
? deepMapValue.items.length
|
|
1091
|
+
: deepMap.getDirectChildrenSizeFor(groupKeys),
|
|
1092
|
+
directChildrenLoadedCount: 0,
|
|
1093
|
+
},
|
|
1094
|
+
deepMapValue,
|
|
1095
|
+
);
|
|
1096
|
+
|
|
1097
|
+
if (isRowSelected) {
|
|
1098
|
+
enhancedGroupData.rowSelected = isRowSelected(enhancedGroupData);
|
|
1099
|
+
if (rowSelectionState) {
|
|
1100
|
+
const selectionCount = rowSelectionState.getSelectionCountFor(
|
|
1101
|
+
enhancedGroupData.groupKeys,
|
|
1102
|
+
);
|
|
1103
|
+
enhancedGroupData.selectedChildredCount =
|
|
1104
|
+
selectionCount.selectedCount;
|
|
1105
|
+
enhancedGroupData.deselectedChildredCount =
|
|
1106
|
+
selectionCount.deselectedCount;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
const parent = parents[parents.length - 1];
|
|
1111
|
+
|
|
1112
|
+
const parentCollapsed = parent?.collapsed ?? false;
|
|
1113
|
+
|
|
1114
|
+
if (parentCollapsed) {
|
|
1115
|
+
collapsed = true;
|
|
1116
|
+
}
|
|
1117
|
+
enhancedGroupData.collapsed = collapsed;
|
|
1118
|
+
|
|
1119
|
+
// const itemHidden = collapsed || parentCollapsed;
|
|
1120
|
+
|
|
1121
|
+
let include = generateGroupRows || collapsed;
|
|
1122
|
+
|
|
1123
|
+
if (parentCollapsed) {
|
|
1124
|
+
include = false;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
if (include) {
|
|
1128
|
+
result.push(enhancedGroupData);
|
|
1129
|
+
groupRowsIndexes.push(result.length - 1);
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
enhancedGroupData.collapsedChildrenCount = 0;
|
|
1133
|
+
parents.forEach((parent) => {
|
|
1134
|
+
parent.deepRowInfoArray.push(enhancedGroupData);
|
|
1135
|
+
|
|
1136
|
+
parent.collapsedGroupsCount += collapsed ? 1 : 0;
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
if (parent && enhancedGroupData.selfLoaded && lazyLoad) {
|
|
1140
|
+
parent.directChildrenLoadedCount += 1;
|
|
1141
|
+
}
|
|
1142
|
+
parents.push(enhancedGroupData);
|
|
1143
|
+
|
|
1144
|
+
const continueWithChildren = true; //!collapsed || lazyLoad;
|
|
1145
|
+
|
|
1146
|
+
if (continueWithChildren) {
|
|
1147
|
+
if (!next) {
|
|
1148
|
+
if (!pivot) {
|
|
1149
|
+
const startIndex = result.length;
|
|
1150
|
+
|
|
1151
|
+
// using items.map would have been easier
|
|
1152
|
+
// but we have sparse arrays, and if the last items are sparse
|
|
1153
|
+
// eg: var a = Array(10); a[0] = 1; a[1] = 2 but the rest of the positions
|
|
1154
|
+
// are not assigned
|
|
1155
|
+
// then iterating over it with `.map` or `.forEach` wont get to the end
|
|
1156
|
+
// which we need
|
|
1157
|
+
|
|
1158
|
+
// this is a use-case we have when there is server-side batching
|
|
1159
|
+
|
|
1160
|
+
// we prefer index assignment, see we have to increment the length
|
|
1161
|
+
// of the result array
|
|
1162
|
+
// by the number of items we want to add
|
|
1163
|
+
// this is in order to make the whole loop a tiny bit faster
|
|
1164
|
+
if (!collapsed) {
|
|
1165
|
+
result.length += items.length;
|
|
1166
|
+
}
|
|
1167
|
+
for (let index = 0, len = items.length; index < len; index++) {
|
|
1168
|
+
const item = items[index];
|
|
1169
|
+
const indexInAll = startIndex + index;
|
|
1170
|
+
const itemId = item
|
|
1171
|
+
? toPrimaryKey(item, indexInAll)
|
|
1172
|
+
: `${groupKeys}-${index}`;
|
|
1173
|
+
const rowInfo: InfiniteTable_HasGrouping_RowInfoNormal<DataType> =
|
|
1174
|
+
{
|
|
1175
|
+
id: itemId,
|
|
1176
|
+
data: item,
|
|
1177
|
+
dataSourceHasGrouping: true,
|
|
1178
|
+
isGroupRow: false,
|
|
1179
|
+
selfLoaded: !!item,
|
|
1180
|
+
rowSelected: false,
|
|
1181
|
+
rootGroupBy: groupByStrings,
|
|
1182
|
+
collapsed,
|
|
1183
|
+
groupKeys,
|
|
1184
|
+
parents: Array.from(parents),
|
|
1185
|
+
indexInParentGroups: [...indexInParentGroups, index],
|
|
1186
|
+
indexInGroup: index,
|
|
1187
|
+
indexInAll,
|
|
1188
|
+
groupBy: groupByStrings,
|
|
1189
|
+
groupNesting: groupNesting + 1,
|
|
1190
|
+
groupCount: enhancedGroupData.groupCount,
|
|
1191
|
+
};
|
|
1192
|
+
if (isRowSelected) {
|
|
1193
|
+
rowInfo.rowSelected = isRowSelected(rowInfo);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
parents.forEach((parent, i) => {
|
|
1197
|
+
const last = i === parents.length - 1;
|
|
1198
|
+
if (last && item) {
|
|
1199
|
+
parent.directChildrenLoadedCount += 1;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
if (collapsed) {
|
|
1203
|
+
// if the current parent is collapsed - this will be true if there is any collapsed parent
|
|
1204
|
+
parent.collapsedChildrenCount += 1;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
parent.deepRowInfoArray.push(rowInfo);
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
if (!collapsed) {
|
|
1211
|
+
// we prefer index assignment, see above
|
|
1212
|
+
result[startIndex + index] = rowInfo;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
} else {
|
|
1217
|
+
next();
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
parents.pop();
|
|
1221
|
+
indexInParentGroups.pop();
|
|
1222
|
+
},
|
|
1223
|
+
);
|
|
1224
|
+
|
|
1225
|
+
return {
|
|
1226
|
+
data: result,
|
|
1227
|
+
groupRowsIndexes,
|
|
1228
|
+
};
|
|
1229
|
+
}
|