Skip to content

Commit

Permalink
feat(react-chart): add API to manage series in stacks (#1227)
Browse files Browse the repository at this point in the history
BREAKING CHANGES:

The 'SeriesFamily' plugin has been renamed to 'Stack' to make it meaning more transparent.
  • Loading branch information
Krijovnick authored Jul 12, 2018
1 parent cd03c72 commit 4239e7f
Show file tree
Hide file tree
Showing 16 changed files with 308 additions and 64 deletions.
2 changes: 1 addition & 1 deletion packages/dx-chart-core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export * from './plugins/axis/computeds';
export * from './plugins/series/computeds';
export * from './utils/scale';
export * from './constants';
export * from './plugins/series-family/computeds';
export * from './plugins/stack/computeds';
export * from './plugins/theme-manager/computeds';
export * from './plugins/chart/computeds';
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ const collectAxesTypes = axes =>
{},
);

const calculateDomainField = (getFieldItem, data, domain = [], type) => {
const calculateDomainField = (getFieldItemFirst, getFieldItemSecond, data, domain = [], type) => {
const getCategories = (prev, cur) => {
const categories = getFieldItem(cur);
const categories = getFieldItemFirst(cur);
if (isDefined(categories)) {
return [...prev, categories];
}
Expand All @@ -29,7 +29,8 @@ const calculateDomainField = (getFieldItem, data, domain = [], type) => {
}
return extent([
...domain,
...extent(data, getFieldItem),
...extent(data, getFieldItemFirst),
...extent(data, getFieldItemSecond),
]);
};

Expand All @@ -40,6 +41,8 @@ const getCorrectAxisType = (type, data, field) => {
return type;
};

const getFieldStack = (index, object) => (object && object[index] ? object[index] : undefined);

const calculateDomain = (series, data, axesTypes, argumentAxisName) =>
series.reduce(
(domains, {
Expand All @@ -59,7 +62,8 @@ const calculateDomain = (series, data, axesTypes, argumentAxisName) =>
...domains,
[axisName]: {
domain: calculateDomainField(
object => object[`${valueField}-${name}-stack`] && object[`${valueField}-${name}-stack`][1],
object => getFieldStack(1, object[`${valueField}-${name}-stack`]),
object => getFieldStack(0, object[`${valueField}-${name}-stack`]),
data,
domains[axisName] && domains[axisName].domain,
valueType,
Expand All @@ -70,6 +74,7 @@ const calculateDomain = (series, data, axesTypes, argumentAxisName) =>
[argumentAxisName]: {
domain: calculateDomainField(
object => object[argumentField],
null,
data,
domains[argumentAxisName] && domains[argumentAxisName].domain,
argumentType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,27 @@ describe('calculateDomain', () => {
});
});

it('should be computed from data, negative values', () => {
const calculatedDomains = domains(
[argumentAxis, valueAxis],
[{
axisName: 'valueAxis', argumentField: 'arg', valueField: 'val', name: 'name',
}],
[{
arg: 1, val: 9, 'val-name-stack': [0, 9],
}, {
arg: 2, val: -10, 'val-name-stack': [-10, 0],
}],
'argumentAxis',
{},
);

expect(calculatedDomains).toEqual({
argumentAxis: { domain: [1, 2], orientation: 'horizontal', type: undefined },
valueAxis: { domain: [-10, 9], orientation: 'vertical', type: undefined },
});
});

it('should be computed from data and series option, startFromZero option set for value axis', () => {
const calculatedDomains = domains(
[argumentAxis, valueAxis],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
stack,
stackOrderNone,
stackOffsetNone,
} from 'd3-shape';
import { stack } from 'd3-shape';

const getStacks = series => series.reduce((
prevValue,
Expand All @@ -27,15 +23,17 @@ const getStacks = series => series.reduce((
};
}, {});

export const processData = (series, data) => {
const filtering = ({ stack: seriesStack }) => seriesStack;

export const processData = (offset, order) => (series, data) => {
const stacks = getStacks(series);

const arrayOfStacks = Object.entries(stacks).reduce((prevValue, item) => ({
...prevValue,
[item[0]]: stack()
.keys(item[1].keys)
.order(stackOrderNone)
.offset(stackOffsetNone)(data),
.order(order)
.offset(offset)(data),
}), {});


Expand All @@ -57,7 +55,8 @@ export const seriesWithStacks = series =>
return [...prevResult, { ...singleSeries, stack: seriesStack }];
}, []);

export const stacks = series => series.reduce((prevResult, singleSeries) => {
const { stack: seriesStack } = singleSeries;
return [...prevResult, seriesStack];
}, []);
export const stacks = series => [
...new Set(series
.filter(singleSeries => filtering(singleSeries))
.map(({ stack: seriesStack }) => seriesStack)),
];
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import {
stack,
stackOrderNone,
stackOffsetNone,
} from 'd3-shape';
import { stack } from 'd3-shape';
import { seriesWithStacks, processData, stacks } from './computeds';

jest.mock('d3-shape', () => ({
stack: jest.fn(),
stackOrderNone: jest.fn(),
stackOffsetNone: jest.fn(),
}));

const mockStackOrderNone = jest.fn();
const mockStackOffsetNone = jest.fn();

const mockStack = jest.fn().mockReturnThis();
mockStack.keys = jest.fn().mockReturnThis();
mockStack.order = jest.fn().mockReturnThis();
Expand All @@ -25,7 +16,7 @@ mockStack.offset = jest.fn(() => jest.fn(() => [

describe('stacks', () => {
it('should return stacks', () => {
const series = [{ name: '1', stack: 'one' }, { name: '2', stack: 'two' }];
const series = [{ name: '1', stack: 'one' }, { name: '2', stack: null }, { name: '3', stack: 'two' }, { name: '4', stack: 'one' }];
expect(stacks(series)).toEqual(['one', 'two']);
});
});
Expand All @@ -46,8 +37,6 @@ describe('series with stacks', () => {
describe('processData', () => {
beforeAll(() => {
stack.mockImplementation(() => mockStack);
stackOrderNone.mockImplementation(() => mockStackOrderNone);
stackOffsetNone.mockImplementation(() => mockStackOffsetNone);
});
afterEach(() => {
jest.clearAllMocks();
Expand All @@ -67,12 +56,15 @@ describe('processData', () => {
];
const data = [{ arg: 1, val: 11 }, { arg: 2, val: 22 }, { arg: 3, val: 33 }];

const processedData = processData(series, data);
const order = jest.fn();
const offset = jest.fn();

const processedData = processData(offset, order)(series, data);

expect(stack).toHaveBeenCalledTimes(2);
expect(mockStack.keys).toHaveBeenCalledWith(['val', 'val']);
expect(mockStack.order).toHaveBeenCalledWith(stackOrderNone);
expect(mockStack.offset).toHaveBeenCalledWith(stackOffsetNone);
expect(mockStack.order).toHaveBeenCalledWith(order);
expect(mockStack.offset).toHaveBeenCalledWith(offset);

expect(processedData).toEqual([{
arg: 1,
Expand Down
98 changes: 98 additions & 0 deletions packages/dx-react-chart-demos/src/demo-data/data-vizualization.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,104 @@ export const born = [
},
];

export const booksSale = [{
year: 1970, mysteries: 9, scienceFiction: 16, romance: 5, fantasy: 4, thrillers: 19,
}, {
year: 1971, mysteries: 15, scienceFiction: 18, romance: 2, fantasy: 4, thrillers: 14,
}, {
year: 1972, mysteries: 10, scienceFiction: 20, romance: 1, fantasy: 16, thrillers: 11,
}, {
year: 1973, mysteries: 12, scienceFiction: 17, romance: 15, fantasy: 5, thrillers: 14,
}, {
year: 1974, mysteries: 8, scienceFiction: 13, romance: 10, fantasy: 19, thrillers: 5,
}, {
year: 1975, mysteries: 7, scienceFiction: 18, romance: 20, fantasy: 18, thrillers: 12,
}, {
year: 1976, mysteries: 12, scienceFiction: 12, romance: 5, fantasy: 2, thrillers: 3,
}, {
year: 1977, mysteries: 18, scienceFiction: 16, romance: 1, fantasy: 6, thrillers: 3,
}, {
year: 1978, mysteries: 3, scienceFiction: 13, romance: 9, fantasy: 15, thrillers: 11,
}, {
year: 1979, mysteries: 11, scienceFiction: 13, romance: 14, fantasy: 1, thrillers: 12,
}, {
year: 1980, mysteries: 6, scienceFiction: 19, romance: 16, fantasy: 6, thrillers: 16,
}, {
year: 1981, mysteries: 2, scienceFiction: 15, romance: 4, fantasy: 6, thrillers: 13,
}, {
year: 1982, mysteries: 4, scienceFiction: 17, romance: 20, fantasy: 7, thrillers: 10,
}, {
year: 1983, mysteries: 3, scienceFiction: 2, romance: 18, fantasy: 18, thrillers: 17,
}, {
year: 1984, mysteries: 10, scienceFiction: 19, romance: 6, fantasy: 13, thrillers: 11,
}, {
year: 1985, mysteries: 16, scienceFiction: 6, romance: 5, fantasy: 2, thrillers: 7,
}, {
year: 1986, mysteries: 17, scienceFiction: 4, romance: 8, fantasy: 10, thrillers: 4,
}, {
year: 1987, mysteries: 9, scienceFiction: 18, romance: 17, fantasy: 6, thrillers: 9,
}, {
year: 1988, mysteries: 6, scienceFiction: 8, romance: 17, fantasy: 13, thrillers: 1,
}, {
year: 1989, mysteries: 3, scienceFiction: 10, romance: 13, fantasy: 17, thrillers: 2,
}, {
year: 1990, mysteries: 10, scienceFiction: 8, romance: 14, fantasy: 12, thrillers: 7,
}, {
year: 1991, mysteries: 18, scienceFiction: 1, romance: 2, fantasy: 8, thrillers: 16,
}, {
year: 1992, mysteries: 19, scienceFiction: 18, romance: 11, fantasy: 20, thrillers: 11,
}, {
year: 1993, mysteries: 7, scienceFiction: 14, romance: 4, fantasy: 8, thrillers: 10,
}, {
year: 1994, mysteries: 2, scienceFiction: 18, romance: 13, fantasy: 11, thrillers: 15,
}, {
year: 1995, mysteries: 2, scienceFiction: 6, romance: 7, fantasy: 11, thrillers: 10,
}, {
year: 1996, mysteries: 10, scienceFiction: 19, romance: 17, fantasy: 17, thrillers: 9,
}, {
year: 1997, mysteries: 3, scienceFiction: 7, romance: 4, fantasy: 15, thrillers: 9,
}, {
year: 1998, mysteries: 13, scienceFiction: 1, romance: 7, fantasy: 16, thrillers: 13,
}, {
year: 1999, mysteries: 19, scienceFiction: 7, romance: 18, fantasy: 14, thrillers: 1,
}, {
year: 2000, mysteries: 2, scienceFiction: 11, romance: 12, fantasy: 11, thrillers: 5,
}, {
year: 2001, mysteries: 16, scienceFiction: 9, romance: 12, fantasy: 6, thrillers: 8,
}, {
year: 2002, mysteries: 11, scienceFiction: 15, romance: 2, fantasy: 9, thrillers: 3,
}, {
year: 2003, mysteries: 1, scienceFiction: 6, romance: 9, fantasy: 9, thrillers: 16,
}, {
year: 2004, mysteries: 18, scienceFiction: 14, romance: 3, fantasy: 2, thrillers: 11,
}, {
year: 2005, mysteries: 9, scienceFiction: 16, romance: 7, fantasy: 8, thrillers: 20,
}, {
year: 2006, mysteries: 18, scienceFiction: 2, romance: 5, fantasy: 6, thrillers: 16,
}, {
year: 2007, mysteries: 5, scienceFiction: 17, romance: 14, fantasy: 4, thrillers: 7,
}, {
year: 2008, mysteries: 15, scienceFiction: 2, romance: 12, fantasy: 3, thrillers: 8,
}, {
year: 2009, mysteries: 16, scienceFiction: 20, romance: 7, fantasy: 14, thrillers: 11,
}, {
year: 2010, mysteries: 14, scienceFiction: 11, romance: 3, fantasy: 1, thrillers: 6,
}, {
year: 2011, mysteries: 18, scienceFiction: 20, romance: 5, fantasy: 4, thrillers: 5,
}, {
year: 2012, mysteries: 3, scienceFiction: 3, romance: 10, fantasy: 5, thrillers: 18,
}, {
year: 2013, mysteries: 1, scienceFiction: 1, romance: 0, fantasy: 6, thrillers: 16,
}, {
year: 2014, mysteries: 15, scienceFiction: 7, romance: 1, fantasy: 2, thrillers: 20,
}, {
year: 2015, mysteries: 12, scienceFiction: 19, romance: 3, fantasy: 3, thrillers: 12,
}, {
year: 2016, mysteries: 11, scienceFiction: 20, romance: 11, fantasy: 5, thrillers: 17,
}, {
year: 2017, mysteries: 4, scienceFiction: 20, romance: 3, fantasy: 12, thrillers: 5,
}];

export const ageStructure = [{
state: 'Germany',
young: 6.7,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
BarSeries,
} from '@devexpress/dx-react-chart-<%&themeName%>';

import { SeriesFamily } from '@devexpress/dx-react-chart';
import { Stack } from '@devexpress/dx-react-chart';

import { ageStructure } from '../../../demo-data/data-vizualization';

Expand Down Expand Up @@ -51,7 +51,7 @@ export default class Demo extends React.PureComponent {
axisName="age"
name="Older"
/>
<SeriesFamily />
<Stack />
</Chart>
</<%&wrapperTag%>>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
BarSeries,
} from '@devexpress/dx-react-chart-<%&themeName%>';

import { SeriesFamily } from '@devexpress/dx-react-chart';
import { Stack } from '@devexpress/dx-react-chart';

import { ageStructure } from '../../../demo-data/data-vizualization';

Expand Down Expand Up @@ -39,7 +39,7 @@ export default class Demo extends React.PureComponent {
argumentField="state"
axisName="age"
/>
<SeriesFamily />
<Stack />
</Chart>
</<%&wrapperTag%>>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
AreaSeries,
Grid,
} from '@devexpress/dx-react-chart-<%&themeName%>';
import { SeriesFamily } from '@devexpress/dx-react-chart';
import { Stack } from '@devexpress/dx-react-chart';

import { ageStructure } from '../../../demo-data/data-vizualization';

Expand Down Expand Up @@ -53,7 +53,7 @@ export default class Demo extends React.PureComponent {
axisName="age"
stack="a"
/>
<SeriesFamily />
<Stack />
</Chart>
</<%&wrapperTag%>>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Chart,
BarSeries,
} from '@devexpress/dx-react-chart-<%&themeName%>';
import { SeriesFamily } from '@devexpress/dx-react-chart';
import { Stack } from '@devexpress/dx-react-chart';

import { ageStructure } from '../../../demo-data/data-vizualization';

Expand Down Expand Up @@ -41,7 +41,7 @@ export default class Demo extends React.PureComponent {
axisName="age"
stack="a"
/>
<SeriesFamily />
<Stack />
</Chart>
</<%&wrapperTag%>>
);
Expand Down
Loading

0 comments on commit 4239e7f

Please sign in to comment.