@visactor/vmind
Version:
<div align="center"> <a href="https://github.com/VisActor#gh-light-mode-only" target="_blank"> <img alt="VisActor Logo" width="200" src="https://github.com/VisActor/.github/blob/main/profile/logo_500_200_light.svg"/> </a> <a href="https://githu
271 lines (255 loc) • 11.7 kB
JavaScript
import { array, isArray, isString, merge, uniqArray } from "@visactor/vutils";
import { ChartType } from "../types";
import { getFieldInfoFromDataset } from "./field";
import { COLOR_FIELD, FOLD_NAME, FOLD_VALUE, FOLD_VALUE_MAIN, FOLD_VALUE_SUB, GROUP_FIELD } from "@visactor/chart-advisor";
import { data, discreteLegend as legend } from "../atom/chartGenerator/spec/transformers/common";
import { funnelData } from "../atom/chartGenerator/spec/transformers/funnel";
import { sankeyData } from "../atom/chartGenerator/spec/transformers/sankey";
import { sequenceData } from "../atom/chartGenerator/spec/transformers/rankingBar";
import { wordCloudData } from "../atom/chartGenerator/spec/transformers/wordcloud";
import { foldDataTableByYField, foldDatasetByYField } from "./dataTable";
export const getChartTypeFromSpec = (spec, vchartType) => {
if (!spec) return;
const type = null != vchartType ? vchartType : null == spec ? void 0 : spec.type;
if ("bar" === type) return ChartType.BarChart;
if ("line" === type) return ChartType.LineChart;
if ("area" === type) return ChartType.AreaChart;
if ("pie" === type) return ChartType.PieChart;
if ("wordCloud" === type) return ChartType.WordCloud;
if ("scatter" === type) return ChartType.ScatterPlot;
if ("funnel" === type) return ChartType.FunnelChart;
if ("rose" === type) return ChartType.RoseChart;
if ("radar" === type) return ChartType.RadarChart;
if ("sankey" === type) return ChartType.SankeyChart;
if ("waterfall" === type) return ChartType.WaterFallChart;
if ("boxPlot" === type) return ChartType.BoxPlot;
if ("common" === type) {
const {series: series} = spec;
if (1 === uniqArray(series.map((s => s.type))).length) return getChartTypeFromSpec(series[0], vchartType);
if (series.length > 1 && series.every((s => "bar" === s.type || "line" === s.type || "area" === s.type))) return ChartType.DualAxisChart;
}
};
export const getDatasetFromSpec = spec => {
if (!spec) return [];
return array(spec.data).map((d => d.values)).flat(2);
};
export const getFieldMappingFromSpec = spec => {
if (!spec) return {};
let res = {};
return array(spec.data).forEach((d => {
(null == d ? void 0 : d.fields) && (res = merge(res, d.fields));
})), res;
};
export const getCellFromSpec = (spec, vmindChartType) => {
var _a, _b, _c, _d;
if (!spec) return {};
const {type: type, direction: direction} = spec, isTransposed = "horizontal" === direction;
if ("bar" === type && spec.player) {
return {
time: spec.timeField,
x: spec.yField,
y: spec.xField,
color: spec.seriesField,
isTransposed: isTransposed
};
}
if ([ "bar", "line", "area" ].includes(type)) {
return {
x: spec.xField,
y: spec.yField,
color: spec.seriesField,
isTransposed: isTransposed
};
}
if ("radar" === type) return {
x: spec.categoryField,
y: spec.valueField,
color: spec.seriesField
};
if ([ "pie", "rose" ].includes(type)) return {
x: spec.categoryField,
y: spec.valueField,
color: spec.categoryField,
angle: spec.valueField
};
if ("scatter" === type) return {
color: spec.seriesField,
size: spec.sizeField,
x: spec.xField,
y: spec.yField
};
if ("boxPlot" === type) return {
x: spec.xField,
y: [ spec.minField, spec.q1Field, spec.medianField, spec.q3Field, spec.maxField ].filter(Boolean)
};
if ("common" === type) {
if ([ ChartType.BarChart, ChartType.AreaChart, ChartType.LineChart ].includes(vmindChartType)) return {
x: uniqArray(spec.series.map((s => s.xField)).filter((xField => !!xField)).flat()),
y: uniqArray(spec.series.map((s => s.yField)).filter((yField => !!yField)).flat()),
color: spec.series[0].seriesField,
isTransposed: isTransposed || spec.series.every((s => "horizontal" === s.direction))
};
const series = null !== (_a = spec.series) && void 0 !== _a ? _a : [];
if (vmindChartType === ChartType.DualAxisChart) {
const seriesField = uniqArray(series.map((s => null == s ? void 0 : s.seriesField)).filter((v => !!v)));
return {
x: null === (_b = series[0]) || void 0 === _b ? void 0 : _b.xField,
y: uniqArray([ null === (_c = series[0]) || void 0 === _c ? void 0 : _c.yField, null === (_d = series[1]) || void 0 === _d ? void 0 : _d.yField ].filter(Boolean)),
color: 1 === (null == seriesField ? void 0 : seriesField.length) ? seriesField[0] : void 0,
isTransposed: isTransposed
};
}
return getCellFromSpec(series[0], vmindChartType);
}
return "wordCloud" === type ? {
color: spec.nameField,
size: spec.valueField
} : "funnel" === type ? {
x: spec.categoryField,
y: spec.valueField
} : "waterfall" === type ? {
x: spec.xField,
y: spec.yField,
color: null == spec ? void 0 : spec.seriesField
} : "sankey" === type ? {
source: spec.sourceField,
target: spec.targetField,
value: spec.valueField
} : {};
};
export const revisedCell = (cell, dataset) => {
const {color: color} = cell, colorField = isArray(color) ? color[0] : color;
if (colorField) {
uniqArray(dataset.map((d => d[colorField]))).length <= 1 && (cell.color = void 0);
}
if (cell.isTransposed) {
const temp = cell.x;
cell.x = cell.y, cell.y = temp;
}
return cell;
};
const removeInvalidFieldFromCell = (cell, fieldInfo) => {
const fieldList = fieldInfo.map((f => f.fieldName)).concat([ FOLD_NAME.toString(), FOLD_VALUE.toString(), FOLD_VALUE_MAIN.toString(), FOLD_VALUE_SUB.toString(), COLOR_FIELD.toString(), GROUP_FIELD.toString() ]), cellNew = Object.assign({}, cell);
return Object.keys(cellNew).forEach((key => {
const fields = cellNew[key];
if (isArray(fields)) {
const filteredFields = fields.filter((field => fieldList.includes(field)));
cellNew[key] = 0 === filteredFields.length ? void 0 : filteredFields;
} else isString(fields) && (cellNew[key] = fieldList.includes(fields) ? fields : void 0);
})), cellNew;
};
export const fillSpecTemplateWithData = (template, dataset, propsCell, totalTime) => {
const {type: type} = template, fieldInfo = getFieldInfoFromDataset(dataset), tempCell = null != propsCell ? propsCell : getCellFromSpec(template);
let cellNew = Object.assign({}, tempCell), datasetNew = dataset;
const hasFold = isArray(cellNew.y) ? cellNew.y[0] === FOLD_VALUE.toString() || cellNew.y[0] === FOLD_VALUE_MAIN.toString() && cellNew.y[1] === FOLD_VALUE_SUB.toString() : cellNew.y === FOLD_VALUE.toString();
cellNew = removeInvalidFieldFromCell(cellNew, fieldInfo);
const context = {
spec: template,
dataset: datasetNew,
cells: [ cellNew ],
totalTime: totalTime
};
if ("bar" === type && template.player) {
const {spec: spec} = sequenceData(context);
return spec;
}
if ([ "bar", "line" ].includes(type)) {
if (hasFold) {
const {foldInfo: foldInfo} = cellNew, {foldMap: foldMap} = foldInfo;
datasetNew = foldDataTableByYField(datasetNew, Object.keys(foldMap), fieldInfo);
}
if (cellNew.color === COLOR_FIELD.toString()) {
const {cartesianInfo: cartesianInfo} = cellNew, colorFields = cartesianInfo.fieldList;
datasetNew = datasetNew.map((data => {
const colorItem = colorFields.map((field => data[field])).join("-");
return Object.assign(Object.assign({}, data), {
[COLOR_FIELD]: colorItem
});
}));
}
const contextNew = {
spec: template,
dataset: datasetNew,
cells: [ cellNew ],
totalTime: totalTime
}, {spec: spec1} = data(contextNew), {spec: spec} = legend(Object.assign(Object.assign({}, contextNew), {
spec: spec1
}));
return spec;
}
if ([ "pie", "scatter", "rose", "radar", "waterfall", "boxPlot" ].includes(type)) {
if (hasFold) {
const {foldInfo: foldInfo} = cellNew, {foldMap: foldMap} = foldInfo;
datasetNew = foldDatasetByYField(datasetNew, Object.keys(foldMap), fieldInfo);
}
if (cellNew.color === COLOR_FIELD.toString()) {
const {cartesianInfo: cartesianInfo} = cellNew, colorFields = cartesianInfo.fieldList;
datasetNew = datasetNew.map((data => {
const colorItem = colorFields.map((field => data[field])).join("-");
return Object.assign(Object.assign({}, data), {
[COLOR_FIELD]: colorItem
});
}));
}
const contextNew = {
spec: template,
dataset: datasetNew,
cells: [ cellNew ],
totalTime: totalTime
}, {spec: spec} = data(contextNew);
return spec;
}
if ("common" === type) {
let mainSeriesData = datasetNew, subSeriesData = datasetNew;
if (hasFold) {
const {foldInfo: foldInfo} = cellNew, {foldMap: foldMap} = foldInfo;
mainSeriesData = foldDatasetByYField(datasetNew, [ Object.keys(foldMap)[0] ], fieldInfo, FOLD_NAME, FOLD_VALUE_MAIN),
subSeriesData = foldDatasetByYField(datasetNew, [ Object.keys(foldMap)[1] ], fieldInfo, FOLD_NAME, FOLD_VALUE_SUB);
}
const {spec: spec1} = data(context), {spec: finalSpec} = legend(Object.assign(Object.assign({}, context), {
spec: spec1
})), {cartesianInfo: cartesianInfo, y: y} = cellNew;
if (finalSpec.series && finalSpec.series[0]) {
finalSpec.series[0].seriesField = COLOR_FIELD;
const colorFields = cartesianInfo ? cartesianInfo.fieldList : void 0;
finalSpec.series[0].data = {
id: finalSpec.data.id + "_bar",
values: mainSeriesData.map((d => {
const colorItem = isArray(colorFields) ? colorFields.map((field => d[field])).join("-") : y[0];
return Object.assign(Object.assign({}, d), {
[COLOR_FIELD]: colorItem
});
}))
};
}
if (finalSpec.series && finalSpec.series[1]) {
finalSpec.series[1].seriesField = COLOR_FIELD;
const colorFields = cartesianInfo ? cartesianInfo.fieldList : void 0;
finalSpec.series[1].data = {
id: finalSpec.data.id + "_line",
values: subSeriesData.map((d => {
const colorItem = isArray(colorFields) ? colorFields.map((field => d[field])).join("-") : y[1];
return Object.assign(Object.assign({}, d), {
[COLOR_FIELD]: colorItem
});
}))
};
}
return finalSpec;
}
if ("wordCloud" === type) {
const {spec: spec} = wordCloudData(context);
return spec;
}
if ("funnel" === type) {
const {spec: spec} = funnelData(context);
return spec;
}
if ("sankey" === type) {
const {spec: spec} = sankeyData(context);
return spec;
}
const {spec: spec} = data(context);
return spec;
};
//# sourceMappingURL=spec.js.map