pivot-chart
Version:
pivot table react component
705 lines • 27.6 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(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 };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
import { useCallback, useState, useMemo } from 'react';
import produce from 'immer';
import { sum } from 'cube-core';
import { getTheme } from './theme';
import { DynamicCube } from './cube';
var theme = getTheme();
export function useNestTree() {
var _a = __read(useState({ id: theme.root.label, path: [] }), 2), nestTree = _a[0], setNestTree = _a[1];
var repaint = useCallback(function (path) {
setNestTree(function (tree) {
var newTree = produce(tree, function (draft) {
var e_1, _a;
var node = draft;
try {
for (var path_1 = __values(path), path_1_1 = path_1.next(); !path_1_1.done; path_1_1 = path_1.next()) {
var i = path_1_1.value;
node = node.children[i];
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (path_1_1 && !path_1_1.done && (_a = path_1.return)) _a.call(path_1);
}
finally { if (e_1) throw e_1.error; }
}
node.expanded = !node.expanded;
});
return newTree;
});
}, [setNestTree]);
return { nestTree: nestTree, setNestTree: setNestTree, repaint: repaint };
}
var alphabetCmp = function (a, b) {
if (a > b)
return 1;
if (a === b)
return 0;
if (a < b)
return -1;
};
export function sortPureNestTree(tree, dimensions, depth) {
var e_2, _a;
if (depth === void 0) { depth = 0; }
if (depth <= dimensions.length && tree.children && tree.children.length > 0) {
if (dimensions[depth].cmp) {
tree.children.sort(function (a, b) { return dimensions[depth].cmp(a.id, b.id); });
}
else {
tree.children.sort(function (a, b) { return alphabetCmp(a.id, b.id); });
}
try {
for (var _b = __values(tree.children), _c = _b.next(); !_c.done; _c = _b.next()) {
var child = _c.value;
sortPureNestTree(child, dimensions, depth + 1);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
}
}
export function getPureNestTree(dataSource, dimensions) {
var hashTree = new Map();
var dataLen = dataSource.length;
for (var i = 0; i < dataLen; i++) {
insertNode(hashTree, dimensions, dataSource[i], 0);
}
return transHashTree2NestTree(hashTree);
}
;
function insertNode(tree, dimensions, record, depth) {
if (depth === dimensions.length) {
return;
}
var childKey = record[dimensions[depth]];
if (!tree.has(childKey)) {
tree.set(childKey, new Map());
}
insertNode(tree.get(childKey), dimensions, record, depth + 1);
}
function transHashTree2NestTree(hasTree) {
var tree = { id: theme.root.label };
transHashDFS(hasTree, tree);
return tree;
}
function transHashDFS(hashNode, node) {
var e_3, _a;
if (hashNode.size === 0) {
return;
}
node.children = [];
try {
for (var hashNode_1 = __values(hashNode), hashNode_1_1 = hashNode_1.next(); !hashNode_1_1.done; hashNode_1_1 = hashNode_1.next()) {
var child = hashNode_1_1.value;
var childInNode = { id: child[0] };
transHashDFS(child[1], childInNode);
node.children.push(childInNode);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (hashNode_1_1 && !hashNode_1_1.done && (_a = hashNode_1.return)) _a.call(hashNode_1);
}
finally { if (e_3) throw e_3.error; }
}
}
export function transTree2LeafPathList(tree, hasAggChild) {
var lpList = [];
// 根左右序
var dfs = function (node, path) {
var e_4, _a;
if (hasAggChild) {
lpList.push(path);
}
else {
if (!(node.expanded && node.children && node.children.length > 0)) {
lpList.push(path);
}
}
if (node.expanded && node.children && node.children.length > 0) {
try {
for (var _b = __values(node.children), _c = _b.next(); !_c.done; _c = _b.next()) {
var child = _c.value;
dfs(child, __spread(path, [child.id]));
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
}
};
dfs(tree, []);
return lpList;
}
/**
*
* @param cube
* @param path
* @param cubeDimensions
* @param measures
*/
export function queryCube(cube, path, cubeDimensions) {
var e_5, _a, e_6, _b, e_7, _c;
var tree = cube.tree;
var queryPath = [];
var _loop_1 = function (dim) {
var target = path.find(function (p) { return p.dimCode === dim; });
if (target) {
queryPath.push(target);
}
else {
queryPath.push({
dimCode: dim,
dimValue: '*'
});
}
};
try {
for (var cubeDimensions_1 = __values(cubeDimensions), cubeDimensions_1_1 = cubeDimensions_1.next(); !cubeDimensions_1_1.done; cubeDimensions_1_1 = cubeDimensions_1.next()) {
var dim = cubeDimensions_1_1.value;
_loop_1(dim);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (cubeDimensions_1_1 && !cubeDimensions_1_1.done && (_a = cubeDimensions_1.return)) _a.call(cubeDimensions_1);
}
finally { if (e_5) throw e_5.error; }
}
var queryNodeList = queryNode(tree, queryPath, 0);
var subset = [];
try {
for (var queryNodeList_1 = __values(queryNodeList), queryNodeList_1_1 = queryNodeList_1.next(); !queryNodeList_1_1.done; queryNodeList_1_1 = queryNodeList_1.next()) {
var node = queryNodeList_1_1.value;
try {
for (var _d = (e_7 = void 0, __values(node.rawData)), _e = _d.next(); !_e.done; _e = _d.next()) {
var record = _e.value;
subset.push(record);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
}
finally { if (e_7) throw e_7.error; }
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (queryNodeList_1_1 && !queryNodeList_1_1.done && (_b = queryNodeList_1.return)) _b.call(queryNodeList_1);
}
finally { if (e_6) throw e_6.error; }
}
return subset;
}
function queryNode(node, path, depth) {
var e_8, _a;
if (depth >= path.length)
return [];
var targetMember = path[depth].dimValue;
var children = __spread(node.children.entries());
if (depth === path.length - 1) {
if (targetMember === '*') {
return children.map(function (child) { return child[1]; });
}
return children.filter(function (child) {
return child[0] === targetMember;
}).map(function (child) { return child[1]; });
}
var ans = [];
try {
for (var children_1 = __values(children), children_1_1 = children_1.next(); !children_1_1.done; children_1_1 = children_1.next()) {
var child = children_1_1.value;
if (targetMember === '*' || child[0] === targetMember) {
ans.push.apply(ans, __spread(queryNode(child[1], path, depth + 1)));
}
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (children_1_1 && !children_1_1.done && (_a = children_1.return)) _a.call(children_1);
}
finally { if (e_8) throw e_8.error; }
}
return ans;
}
function aggregateAll(dataSource, measures) {
var e_9, _a;
// todo different handler for holistic and algebra.
var result = {};
try {
for (var measures_1 = __values(measures), measures_1_1 = measures_1.next(); !measures_1_1.done; measures_1_1 = measures_1.next()) {
var mea = measures_1_1.value;
var aggObj = mea.aggregator ? mea.aggregator(dataSource, [mea.id]) : sum(dataSource, [mea.id]);
result[mea.id] = aggObj[mea.id];
}
}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {
try {
if (measures_1_1 && !measures_1_1.done && (_a = measures_1.return)) _a.call(measures_1);
}
finally { if (e_9) throw e_9.error; }
}
return result;
}
export function getCossMatrix(visType, cube, rowLPList, columnLPList, rows, columns, measures, dimensionsInView) {
if (rowLPList === void 0) { rowLPList = []; }
if (columnLPList === void 0) { columnLPList = []; }
var rowLen = rowLPList.length;
var columnLen = columnLPList.length;
var dimensions = rows.concat(columns);
var crossMatrix = [];
// function getCell (node: Node, path: string[], depth: number): Record {
// if (typeof node === 'undefined') return null;
// if (depth === path.length) {
// return node._aggData;
// }
// return getCell(node.children.get(path[depth]), path, depth + 1);
// }
for (var i = 0; i < rowLen; i++) {
crossMatrix.push([]);
for (var j = 0; j < columnLen; j++) {
var path = __spread(rowLPList[i].map(function (d, i) { return ({
dimCode: rows[i],
dimValue: d
}); }), columnLPList[j].map(function (d, i) { return ({
dimCode: columns[i],
dimValue: d
}); }));
var result = queryCube(cube, path, dimensions);
switch (visType) {
case 'bar':
case 'line':
case 'scatter':
crossMatrix[i].push(aggregateOnGroupBy(result, dimensionsInView, measures));
break;
// case 'scatter':
// crossMatrix[i].push(result);
// break;
case 'number':
default:
crossMatrix[i].push(aggregateAll(result, measures));
break;
}
}
}
return crossMatrix;
}
export function getNestFields(visType, rows, columns, measures) {
switch (visType) {
case 'number':
return {
nestRows: rows,
nestColumns: columns,
dimensionsInView: [],
facetMeasures: measures,
viewMeasures: measures
};
case 'bar':
case 'line':
return {
nestRows: rows,
nestColumns: columns.slice(0, -1),
dimensionsInView: columns.slice(-1),
facetMeasures: measures,
viewMeasures: measures
};
case 'scatter':
return {
nestRows: rows,
nestColumns: columns.slice(0, -1),
dimensionsInView: columns.slice(-1),
facetMeasures: measures,
viewMeasures: measures.slice(-1),
};
default:
return {
nestRows: rows,
nestColumns: columns,
dimensionsInView: [],
facetMeasures: measures,
viewMeasures: measures
};
}
}
export function useNestFields(visType, rows, columns, measures) {
var nestRows = rows;
var _a = useMemo(function () {
if (visType !== 'number') {
return {
nestColumns: columns.slice(0, -1),
dimensionsInView: columns.slice(-1)
};
}
return {
nestColumns: columns,
dimensionsInView: []
};
}, [visType, columns]), nestColumns = _a.nestColumns, dimensionsInView = _a.dimensionsInView;
var _b = useMemo(function () {
if (visType === 'scatter') {
return {
facetMeasures: measures,
viewMeasures: measures.slice(-1)
};
}
return {
facetMeasures: measures,
viewMeasures: measures
};
}, [visType, measures]), facetMeasures = _b.facetMeasures, viewMeasures = _b.viewMeasures;
return {
nestRows: nestRows,
nestColumns: nestColumns,
dimensionsInView: dimensionsInView,
facetMeasures: facetMeasures,
viewMeasures: viewMeasures
};
}
export function aggregateOnGroupBy(dataSource, fields, measures) {
var e_10, _a, e_11, _b, _c, e_12, _d;
var groups = new Map();
// todo: support multi-dimensions.
var field = fields[0];
var data = [];
try {
for (var dataSource_1 = __values(dataSource), dataSource_1_1 = dataSource_1.next(); !dataSource_1_1.done; dataSource_1_1 = dataSource_1.next()) {
var record = dataSource_1_1.value;
if (!groups.has(record[field])) {
groups.set(record[field], []);
}
groups.get(record[field]).push(record);
}
}
catch (e_10_1) { e_10 = { error: e_10_1 }; }
finally {
try {
if (dataSource_1_1 && !dataSource_1_1.done && (_a = dataSource_1.return)) _a.call(dataSource_1);
}
finally { if (e_10) throw e_10.error; }
}
try {
for (var _e = __values(groups.entries()), _f = _e.next(); !_f.done; _f = _e.next()) {
var dataFrame = _f.value;
var record = (_c = {},
_c[field] = dataFrame[0],
_c);
try {
for (var measures_2 = (e_12 = void 0, __values(measures)), measures_2_1 = measures_2.next(); !measures_2_1.done; measures_2_1 = measures_2.next()) {
var mea = measures_2_1.value;
record[mea.id] = (mea.aggregator || sum)(dataFrame[1], [mea.id])[mea.id];
}
}
catch (e_12_1) { e_12 = { error: e_12_1 }; }
finally {
try {
if (measures_2_1 && !measures_2_1.done && (_d = measures_2.return)) _d.call(measures_2);
}
finally { if (e_12) throw e_12.error; }
}
data.push(record);
}
}
catch (e_11_1) { e_11 = { error: e_11_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_11) throw e_11.error; }
}
return data;
}
var AsyncCacheCube = /** @class */ (function () {
function AsyncCacheCube(props) {
// private measures: string
this.dimCompare = function (a, b) {
if (a > b)
return 1;
if (a === b)
return 0;
if (a < b)
return -1;
};
var dimensions = props.dimensions, cmp = props.cmp, asyncCubeQuery = props.asyncCubeQuery;
if (cmp) {
this.dimCompare = cmp;
}
// this.dimensions = [...dimensions].sort(cmp);
this.dynamicCube = new DynamicCube({ computeCuboid: asyncCubeQuery });
this.asyncCubeQuery = asyncCubeQuery;
}
// public appendDimension(dimension: string) {
// let i = 0;
// for (; i < this.dimensions.length; i++) {
// let cmp = this.dimCompare(dimension, this.dimensions[i]);
// if (cmp === 1) {
// break;
// } else if (cmp === 0) {
// return;
// }
// }
// this.dimensions.splice(i, 1, dimension);
// }
// public deleteDimension(dimension: string) {
// for (let i = 0; i < this.dimensions.length; i++) {
// let cmp = this.dimCompare(dimension, this.dimensions[i]);
// if (cmp === 0) {
// this.dimensions.splice(i, 1);
// break;
// }
// }
// }
// private encode (values: string[]): string {
// return values.join('-');
// }
AsyncCacheCube.prototype.cacheQuery = function (originPath, measures) {
return __awaiter(this, void 0, void 0, function () {
var path, cuboidKey, cuboid;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
path = __spread(originPath).sort(function (a, b) { return _this.dimCompare(a.dimCode, b.dimCode); });
cuboidKey = path.map(function (p) { return p.dimCode; });
return [4 /*yield*/, this.dynamicCube.getCuboid(cuboidKey, measures)];
case 1:
cuboid = _a.sent();
return [2 /*return*/, cuboid.get(path)];
}
});
});
};
AsyncCacheCube.prototype.getCuboidNestTree = function (originPath, branchFilters) {
return __awaiter(this, void 0, void 0, function () {
var originPathCode, pathCode, cuboid, viewData, pureNestTree;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
originPathCode = originPath.map(function (p) { return p.id; });
pathCode = __spread(originPathCode).sort(this.dimCompare);
return [4 /*yield*/, this.dynamicCube.getCuboid(pathCode, [])];
case 1:
cuboid = _a.sent();
viewData = cuboid.dataSource;
if (branchFilters && branchFilters.every(function (f) { return originPathCode.includes(f.id); })) {
viewData = cuboid.dataSource.filter(function (record) {
// must use == not === for key in map is string while the origin value is number, might try
return branchFilters.every(function (f) { return f.values.find(function (v) { return v == record[f.id]; }); });
});
}
pureNestTree = getPureNestTree(viewData, originPathCode);
sortPureNestTree(pureNestTree, originPath, 0);
return [2 /*return*/, pureNestTree];
}
});
});
};
AsyncCacheCube.prototype.requestCossMatrix = function (visType, rowLPList, columnLPList, rows, columns, measures, dimensionsInView) {
if (rowLPList === void 0) { rowLPList = []; }
if (columnLPList === void 0) { columnLPList = []; }
return __awaiter(this, void 0, void 0, function () {
var rowLen, columnLen, crossMatrix, measureCodeList, i, j, path, dimensionsInView_1, dimensionsInView_1_1, dim, result;
var e_13, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
rowLen = rowLPList.length;
columnLen = columnLPList.length;
crossMatrix = [];
measureCodeList = measures.map(function (m) { return m.id; });
i = 0;
_b.label = 1;
case 1:
if (!(i < rowLen)) return [3 /*break*/, 6];
crossMatrix.push([]);
j = 0;
_b.label = 2;
case 2:
if (!(j < columnLen)) return [3 /*break*/, 5];
path = __spread(rowLPList[i].map(function (d, index) { return ({
dimCode: rows[index].id,
dimValue: d
}); }), columnLPList[j].map(function (d, index) { return ({
dimCode: columns[index].id,
dimValue: d
}); }));
try {
for (dimensionsInView_1 = (e_13 = void 0, __values(dimensionsInView)), dimensionsInView_1_1 = dimensionsInView_1.next(); !dimensionsInView_1_1.done; dimensionsInView_1_1 = dimensionsInView_1.next()) {
dim = dimensionsInView_1_1.value;
path.push({
dimCode: dim.id,
dimValue: '*'
});
}
}
catch (e_13_1) { e_13 = { error: e_13_1 }; }
finally {
try {
if (dimensionsInView_1_1 && !dimensionsInView_1_1.done && (_a = dimensionsInView_1.return)) _a.call(dimensionsInView_1);
}
finally { if (e_13) throw e_13.error; }
}
return [4 /*yield*/, this.cacheQuery(path, measureCodeList)];
case 3:
result = _b.sent();
switch (visType) {
case 'bar':
case 'line':
case 'scatter':
crossMatrix[i].push(result);
break;
case 'number':
default:
crossMatrix[i].push(result[0]);
break;
}
_b.label = 4;
case 4:
j++;
return [3 /*break*/, 2];
case 5:
i++;
return [3 /*break*/, 1];
case 6: return [2 /*return*/, crossMatrix];
}
});
});
};
return AsyncCacheCube;
}());
export { AsyncCacheCube };
export function arrayEqual(arr1, arr2) {
if (arr1.length !== arr2.length)
return false;
for (var i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i])
return false;
}
return true;
}
export function labelHighlightNode(tree, valuePath, hlPath, depth) {
var e_14, _a;
tree.isHighlight = true;
if (tree.children) {
try {
for (var _b = __values(tree.children), _c = _b.next(); !_c.done; _c = _b.next()) {
var child = _c.value;
// == not ===
if (child.id == hlPath[depth]) {
labelHighlightNode(child, __spread(valuePath, [child.id]), hlPath, depth + 1);
}
}
}
catch (e_14_1) { e_14 = { error: e_14_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_14) throw e_14.error; }
}
}
}
export function clearHighlight(tree) {
var e_15, _a;
tree.isHighlight = false;
if (tree.children) {
try {
for (var _b = __values(tree.children), _c = _b.next(); !_c.done; _c = _b.next()) {
var child = _c.value;
clearHighlight(child);
}
}
catch (e_15_1) { e_15 = { error: e_15_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_15) throw e_15.error; }
}
}
}
//# sourceMappingURL=utils.js.map