Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { generateChart } from '../../src';

const MOCK_DATA_TABLE = [
{ group: 'A', name: 'Category1', value: 10 },
{ group: 'A', name: 'Category2', value: 15 },
{ group: 'B', name: 'Category1', value: 20 },
{ group: 'B', name: 'Category2', value: 25 }
];

const layout = {
type: 'grid',
col: 3,
row: 3,
colWidth: [
{
index: 1,
size: 120
}
],
elements: [
{
modelId: 'title',
col: 0,
row: 0,
colSpan: 3
},
{
modelId: 'legend',
col: 0,
row: 1,
colSpan: 3
},
{
modelId: 'left',
col: 0,
row: 2
},
{
modelId: 'right',
col: 2,
row: 2
}
]
};

const region = [
{
id: 'left'
},
{
id: 'right'
}
];

describe('generate comparative funnel chart', () => {
it('should generate comparative funnel chart with dataTable', () => {
const { spec } = generateChart('comparativeFunnel', {
dataTable: MOCK_DATA_TABLE,
cell: {
x: 'name',
y: 'value',
category: 'group'
},
spec: {}
});
expect(spec.type).toBe('common');
expect(spec.layout).toEqual(layout);
expect(spec.region).toEqual(region);
expect(spec.data).toEqual(
Object.entries(
MOCK_DATA_TABLE.reduce((acc, curr) => {
if (!acc[curr.group]) {
acc[curr.group] = [];
}
acc[curr.group].push(curr);
return acc;
}, {} as any)
).map(([group, data]) => ({
id: group,
values: data
}))
);
const serialize = (obj: any) => JSON.parse(JSON.stringify(obj));
expect(serialize(spec.series)).toEqual(
serialize([
{
type: 'funnel',
dataIndex: 0,
regionIndex: 0,
isTransform: true,
gap: 2,
maxSize: '60%',
shape: 'rect',
funnelAlign: 'right',
categoryField: 'name',
valueField: 'value',
heightRatio: 1.5,
funnel: {
style: {
fill: { field: 'group', scale: 'color' },
cornerRadius: 4
}
},
transform: {
style: {
fill: { field: 'group', scale: 'color' },
fillOpacity: 0.1
}
},
outerLabel: {
visible: true,
line: { visible: false },
style: {
fontSize: 24,
fontWeight: 'bold',
fill: 'black',
limit: Infinity
}
},
extensionMark: [
{
type: 'text',
dataIndex: 0,
style: {
fontSize: 24,
fill: 'grey',
textAlign: 'center'
}
}
]
},
{
type: 'funnel',
dataIndex: 1,
regionIndex: 1,
isTransform: true,
gap: 2,
maxSize: '60%',
shape: 'rect',
funnelAlign: 'left',
categoryField: 'name',
valueField: 'value',
heightRatio: 1.5,
funnel: {
style: {
fill: { field: 'group', scale: 'color' },
cornerRadius: 4
}
},
transform: {
style: {
fill: { field: 'group', scale: 'color' },
fillOpacity: 0.1
}
},
outerLabel: {
visible: true,
line: { visible: false },
style: {
fontSize: 24,
fontWeight: 'bold',
fill: 'black',
limit: Infinity
}
},
extensionMark: []
}
])
);
});
});
10 changes: 10 additions & 0 deletions packages/generate-vchart/__tests__/transformers/heatmap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ describe('generateChart', () => {
grid: {
visible: false
},
label: {
style: {
angle: 90
}
},
domainLine: {
visible: false
}
Expand Down Expand Up @@ -261,6 +266,11 @@ describe('generateChart', () => {
grid: {
visible: false
},
label: {
style: {
angle: 90
}
},
domainLine: {
visible: false
},
Expand Down
4 changes: 3 additions & 1 deletion packages/generate-vchart/src/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const {
pipelineWaterfall,
pipelineWordCloud,
pipelineBidirectionalBar,
pipelineComparativeFunnel,
addSimpleComponents,
theme
} = allTransformers;
Expand Down Expand Up @@ -70,7 +71,8 @@ const pipelineMap: {
gauge: { type: 'gauge', aliasName: 'Gauge Chart', pipline: pipelineGauge },
heatmap: { type: 'heatmap', aliasName: 'Basic Heat Map', pipline: pipelineBasicHeatMap },
venn: { type: 'venn', aliasName: 'Venn Chart', pipline: pipelineVenn },
bidirectionalBar: { type: 'common', aliasName: 'Bidirectional Bar Chart', pipline: pipelineBidirectionalBar }
bidirectionalBar: { type: 'common', aliasName: 'Bidirectional Bar Chart', pipline: pipelineBidirectionalBar },
comparativeFunnel: { type: 'common', aliasName: 'Comparative Funnel Chart', pipline: pipelineComparativeFunnel }
};

export const findPipelineByType = (type: string) => {
Expand Down
133 changes: 133 additions & 0 deletions packages/generate-vchart/src/transformers/comparativeFunnel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { array } from '@visactor/vutils';
import { DataItem, GenerateChartInput } from '../types';
import { data, discreteLegend, formatXFields } from './common';

const title = (context: GenerateChartInput) => {
const { spec } = context;
const { title } = spec;
spec.title = {
...title,
id: 'title'
};
return { spec };
};

const layout = (context: GenerateChartInput) => {
const { spec } = context;
spec.layout = {
type: 'grid',
col: 3,
row: 3,
colWidth: [{ index: 1, size: 120 }],
elements: [
{ modelId: 'title', col: 0, row: 0, colSpan: 3 },
{ modelId: 'legend', col: 0, row: 1, colSpan: 3 },
{ modelId: 'left', col: 0, row: 2 },
{ modelId: 'right', col: 2, row: 2 }
]
};
spec.region = [{ id: 'left' }, { id: 'right' }];
return { spec };
};

const comparativeFunnelSeries = (context: GenerateChartInput) => {
const { spec, cell } = context;
const generateSeries = (index: number, align: 'left' | 'right') => {
return {
type: 'funnel',
dataIndex: index,
regionIndex: index,
isTransform: true,
gap: 2,
maxSize: '60%',
shape: 'rect',
funnelAlign: align,
categoryField: cell.x,
valueField: cell.y,
heightRatio: 1.5,
funnel: {
style: {
fill: { field: cell.category, scale: 'color' },
cornerRadius: 4
}
},
transform: {
style: {
fill: { field: cell.category, scale: 'color' },
fillOpacity: 0.1
}
},
outerLabel: {
visible: true,
line: { visible: false },
formatMethod: (data: any, datum: DataItem) => datum[array(cell.y)[0]],
style: {
fontSize: 24,
fontWeight: 'bold',
fill: 'black',
limit: Infinity
}
},
extensionMark: [
index === 0
? {
type: 'text',
dataIndex: 0,
style: {
text: (data: any) => data[array(cell.x)[0]],
fontSize: 24,
fill: 'grey',
textAlign: 'center',
x: (data: any, ctx: any) => {
const { vchart } = ctx;
return vchart.getCurrentSize().width / 2 - 10;
},
y: (data: DataItem, ctx: any) => {
const { getPoints } = ctx;
const [tl, tr, br, bl] = getPoints(data);
return (tl.y + bl.y) / 2;
}
}
}
: null
].filter(Boolean)
};
};
spec.series = [generateSeries(0, 'right'), generateSeries(1, 'left')];
return { spec };
};

const comparativeFunnelLegend = (context: GenerateChartInput) => {
const { spec, cell } = context;
spec.seriesField = cell.category;
spec.legends = array(spec.legends).map(legend => ({
...legend,
id: 'legend',
orient: 'top'
}));
return { spec };
};

const comparativeFunnelData = (context: GenerateChartInput) => {
const { spec, dataTable } = context;
const mp = {};
dataTable.forEach(item => {
const { group } = item;
if (!mp[group]) {
mp[group] = [];
}
mp[group].push(item);
});
spec.data = Object.entries(mp).map(([group, data]) => ({ id: group, values: data }));
return { spec };
};

export const pipelineComparativeFunnel = [
title,
formatXFields,
layout,
comparativeFunnelData,
comparativeFunnelSeries,
discreteLegend,
comparativeFunnelLegend
];
7 changes: 6 additions & 1 deletion packages/generate-vchart/src/transformers/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ export const basicHeatMapAxes = (context: GenerateChartInput) => {
}
},
userConfig: {
type: 'band'
type: 'band',
label: {
style: {
angle: 90
}
}
},
filters: [axis => axis.orient === 'bottom', axis => axis.orient === 'top']
},
Expand Down
1 change: 1 addition & 0 deletions packages/generate-vchart/src/transformers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ export * from './waterfall';
export * from './wordcloud';

export * from './bidirectionalBar';
export * from './comparativeFunnel';
Loading