Skip to content

Commit

Permalink
feat(partitions): small multipies events pass on smAccessorValue (ope…
Browse files Browse the repository at this point in the history
  • Loading branch information
monfera authored Apr 6, 2021
1 parent dcdbc6f commit 0e1f7de
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 27 deletions.
5 changes: 2 additions & 3 deletions packages/osd-charts/api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -817,11 +817,9 @@ export interface GroupBrushExtent {
// @alpha (undocumented)
export const GroupBy: React_2.FunctionComponent<GroupByProps>;

// @alpha (undocumented)
// @public (undocumented)
export type GroupByAccessor = (spec: Spec, datum: any) => string | number;

// Warning: (ae-incompatible-release-tags) The symbol "GroupByFormatter" is marked as @public, but its signature references "GroupByAccessor" which is marked as @alpha
//
// @public
export type GroupByFormatter = (value: ReturnType<GroupByAccessor>) => string;

Expand Down Expand Up @@ -1073,6 +1071,7 @@ export interface LayerValue {
depth: number;
groupByRollup: PrimitiveValue;
path: LegendPath;
smAccessorValue: ReturnType<GroupByAccessor>;
sortIndex: number;
value: number;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const getPickedShapesLayerValues = createCachedSelector(
const elements = pickedShapes.map<Array<LayerValue>>((model) => {
const values: Array<LayerValue> = [];
values.push({
smAccessorValue: '',
groupByRollup: 'Actual',
value: model.actual,
sortIndex: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
SizeRatio,
} from '../../../../common/geometry';
import { Font, VerticalAlignments } from '../../../../common/text_utils';
import { GroupByAccessor } from '../../../../specs';
import { LegendPath } from '../../../../state/actions/legend';
import { Color } from '../../../../utils/common';
import { ContinuousDomainFocus } from '../../renderer/canvas/partition';
Expand Down Expand Up @@ -89,13 +90,14 @@ export interface RowSet {
}

/** @internal */
export interface SmallMultiplesIndices {
export interface SmallMultiplesDescriptors {
smAccessorValue: ReturnType<GroupByAccessor>;
index: number;
innerIndex: number;
}

/** @internal */
export interface QuadViewModel extends ShapeTreeNode, SmallMultiplesIndices {
export interface QuadViewModel extends ShapeTreeNode, SmallMultiplesDescriptors {
strokeWidth: number;
strokeStyle: string;
fillColor: string;
Expand All @@ -111,8 +113,9 @@ export interface OutsideLinksViewModel {
export type PickFunction = (x: Pixels, y: Pixels, focus: ContinuousDomainFocus) => Array<QuadViewModel>;

/** @internal */
export interface PartitionSmallMultiplesModel extends SmallMultiplesIndices {
export interface PartitionSmallMultiplesModel extends SmallMultiplesDescriptors {
panelTitle: string;
smAccessorValue: number | string;
partitionLayout: PartitionLayout;
top: SizeRatio;
left: SizeRatio;
Expand Down Expand Up @@ -154,6 +157,7 @@ const defaultFont: Font = {
export const nullPartitionSmallMultiplesModel = (partitionLayout: PartitionLayout): PartitionSmallMultiplesModel => ({
index: 0,
innerIndex: 0,
smAccessorValue: '',
panelTitle: '',
top: 0,
left: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,22 @@ export function pickShapesLayerValues(shapes: QuadViewModel[]): LayerValue[][] {
return shapes
.filter(({ depth }) => depth === maxDepth) // eg. lowest layer in a treemap, where layers overlap in screen space; doesn't apply to sunburst/flame
.map<Array<LayerValue>>((viewModel) => {
const values: Array<LayerValue> = [];
values.push({
groupByRollup: viewModel.dataName,
value: viewModel[AGGREGATE_KEY],
depth: viewModel[DEPTH_KEY],
sortIndex: viewModel[SORT_INDEX_KEY],
path: viewModel[PATH_KEY],
});
const values: Array<LayerValue> = [
{
smAccessorValue: viewModel.smAccessorValue,
groupByRollup: viewModel.dataName,
value: viewModel[AGGREGATE_KEY],
depth: viewModel[DEPTH_KEY],
sortIndex: viewModel[SORT_INDEX_KEY],
path: viewModel[PATH_KEY],
},
];
let node = viewModel[MODEL_KEY];
while (node[DEPTH_KEY] > 0) {
const value = node[AGGREGATE_KEY];
const dataName = getNodeName(node);
values.push({
smAccessorValue: viewModel.smAccessorValue,
groupByRollup: dataName,
value,
depth: node[DEPTH_KEY],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
trueBearingToStandardPositionAngle,
} from '../../../../common/geometry';
import { Part, TextMeasure } from '../../../../common/text_utils';
import { SmallMultiplesStyle } from '../../../../specs';
import { GroupByAccessor, SmallMultiplesStyle } from '../../../../specs';
import { StrokeStyle, ValueFormatter, Color, RecursivePartial } from '../../../../utils/common';
import { Layer } from '../../specs';
import { config as defaultConfig, MODEL_KEY, percentValueGetter } from '../config';
Expand Down Expand Up @@ -137,6 +137,7 @@ export function makeQuadViewModel(
layers: Layer[],
sectorLineWidth: Pixels,
sectorLineStroke: StrokeStyle,
smAccessorValue: ReturnType<GroupByAccessor>,
index: number,
innerIndex: number,
fillLabel: FillLabelConfig,
Expand All @@ -159,7 +160,7 @@ export function makeQuadViewModel(
!isSunburstLayout && textNegligible
? 'transparent'
: fillTextColor(textColor, textInvertible, textContrast, fillColor, containerBackgroundColor);
return { index, innerIndex, strokeWidth, strokeStyle, fillColor, textColor: color, ...node };
return { index, innerIndex, smAccessorValue, strokeWidth, strokeStyle, fillColor, textColor: color, ...node };
});
}

Expand Down Expand Up @@ -360,6 +361,7 @@ export function shapeViewModel(
layers,
config.sectorLineWidth,
config.sectorLineStroke,
panel.smAccessorValue,
panel.index,
panel.innerIndex,
config.fillLabel,
Expand Down Expand Up @@ -463,7 +465,7 @@ export function shapeViewModel(
// combined viewModel
return {
partitionLayout: config?.partitionLayout ?? defaultConfig.partitionLayout,

smAccessorValue: panel.smAccessorValue,
panelTitle: panel.panelTitle,
index: panel.index,
innerIndex: panel.innerIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
nullShapeViewModel,
QuadViewModel,
ShapeViewModel,
SmallMultiplesIndices,
SmallMultiplesDescriptors,
} from '../../layout/types/viewmodel_types';
import { INPUT_KEY } from '../../layout/utils/group_by_rollup';
import { isSimpleLinear } from '../../layout/viewmodel/viewmodel';
Expand All @@ -50,7 +50,7 @@ export interface ContinuousDomainFocus {
}

/** @internal */
export interface IndexedContinuousDomainFocus extends ContinuousDomainFocus, SmallMultiplesIndices {}
export interface IndexedContinuousDomainFocus extends ContinuousDomainFocus, SmallMultiplesDescriptors {}

interface ReactiveChartStateProps {
initialized: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ export const partitionMultiGeometries = createCachedSelector(
const marginBottom = spec.config.margin?.bottom ?? config.margin.bottom;

const chartHeight = getInterMarginSize(marginedHeight, marginTop, marginBottom);

return trees.map(({ name, style, tree: t }: StyledTree, innerIndex, a) => {
return trees.map(({ name, smAccessorValue, style, tree: t }: StyledTree, innerIndex, a) => {
const innerPanelCount = a.length;
const outerPanelWidth = chartWidth * outerWidthRatio;
const outerPanelHeight = chartHeight * outerHeightRatio;
Expand Down Expand Up @@ -190,6 +189,7 @@ export const partitionMultiGeometries = createCachedSelector(
innerIndex,
partitionLayout: spec.config.partitionLayout ?? config.partitionLayout,
panelTitle: String(name),
smAccessorValue,
top: topOuterRatio + topInnerRatio,
height: panelHeightRatio,
left: leftOuterRatio + leftInnerRatio,
Expand Down Expand Up @@ -227,10 +227,10 @@ export const partitionDrilldownFocus = createCachedSelector(
(state) => state.interactions.prevDrilldown,
],
(multiGeometries, chartDimensions, drilldown, prevDrilldown): IndexedContinuousDomainFocus[] =>
multiGeometries.map(({ quadViewModel, index, innerIndex }) => {
multiGeometries.map(({ quadViewModel, smAccessorValue, index, innerIndex }) => {
const { x0: currentFocusX0, x1: currentFocusX1 } = focusRect(quadViewModel, chartDimensions, drilldown);
const { x0: prevFocusX0, x1: prevFocusX1 } = focusRect(quadViewModel, chartDimensions, prevDrilldown);
return { currentFocusX0, currentFocusX1, prevFocusX0, prevFocusX1, index, innerIndex };
return { currentFocusX0, currentFocusX1, prevFocusX0, prevFocusX1, smAccessorValue, index, innerIndex };
}),
)((state) => state.chartId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@

import { createStore, Store } from 'redux';

import { Predicate } from '../../../../common/predicate';
import { MockGlobalSpec, MockSeriesSpec } from '../../../../mocks/specs';
import { SettingsSpec, XYChartElementEvent, PartitionElementEvent, HeatmapElementEvent } from '../../../../specs';
import {
SettingsSpec,
XYChartElementEvent,
PartitionElementEvent,
HeatmapElementEvent,
GroupBySpec,
SmallMultiplesSpec,
} from '../../../../specs';
import { updateParentDimensions } from '../../../../state/actions/chart_settings';
import { onMouseDown, onMouseUp, onPointerMove } from '../../../../state/actions/mouse';
import { upsertSpec, specParsed } from '../../../../state/actions/specs';
import { chartStoreReducer, GlobalChartState } from '../../../../state/chart_state';
import { Datum } from '../../../../utils/common';
import { HIERARCHY_ROOT_KEY } from '../../layout/utils/group_by_rollup';
import { PartitionSpec } from '../../specs';
import { partitionGeometries } from './geometries';
Expand All @@ -41,6 +50,20 @@ describe('Picked shapes selector', () => {
store.dispatch(specParsed());
store.dispatch(updateParentDimensions({ width: 300, height: 300, top: 0, left: 0 }));
}
function addSmallMultiplesSeries(
store: Store<GlobalChartState>,
groupBy: Partial<GroupBySpec>,
sm: Partial<SmallMultiplesSpec>,
spec: PartitionSpec,
settings?: Partial<SettingsSpec>,
) {
store.dispatch(upsertSpec(MockGlobalSpec.settings(settings)));
store.dispatch(upsertSpec(MockGlobalSpec.groupBy(groupBy)));
store.dispatch(upsertSpec(MockGlobalSpec.smallMultiple(sm)));
store.dispatch(upsertSpec(spec));
store.dispatch(specParsed());
store.dispatch(updateParentDimensions({ width: 300, height: 300, top: 0, left: 0 }));
}
let store: Store<GlobalChartState>;
let treemapSpec: PartitionSpec;
let sunburstSpec: PartitionSpec;
Expand Down Expand Up @@ -98,6 +121,7 @@ describe('Picked shapes selector', () => {
[
[
{
smAccessorValue: '',
groupByRollup: 'b',
value: 2,
depth: 1,
Expand All @@ -108,6 +132,7 @@ describe('Picked shapes selector', () => {
],
},
{
smAccessorValue: '',
groupByRollup: 'b',
value: 1,
depth: 2,
Expand All @@ -126,6 +151,74 @@ describe('Picked shapes selector', () => {
],
]);
});
test('small multiples pie chart check picked geometries', () => {
const onClickListener = jest.fn<
undefined,
Array<(XYChartElementEvent | PartitionElementEvent | HeatmapElementEvent)[]>
>((): undefined => undefined);
addSmallMultiplesSeries(
store,
{
id: 'splitGB',
by: (_, d: Datum) => d.g1,
sort: Predicate.AlphaAsc,
format: (d: Datum) => String(d),
},
{ id: 'sm', splitHorizontally: 'splitGB' },
MockSeriesSpec.sunburst({
smallMultiples: 'sm',
valueAccessor: (d: { v: number }) => d.v,
data: [
{ g1: 'a', g2: 'a', v: 1 },
{ g1: 'a', g2: 'b', v: 1 },
{ g1: 'b', g2: 'a', v: 1 },
{ g1: 'b', g2: 'b', v: 1 },
],
layers: [
{
groupByRollup: (datum: { g2: string }) => datum.g2,
},
],
}),
{
onElementClick: onClickListener,
},
);
const geometries = partitionGeometries(store.getState())[0];
expect(geometries.quadViewModel).toHaveLength(2);

const onElementClickCaller = createOnElementClickCaller();
store.subscribe(() => {
onElementClickCaller(store.getState());
});
const x = 50;
const y = 150;
store.dispatch(onPointerMove({ x, y }, 0));
store.dispatch(onMouseDown({ x, y }, 1));
store.dispatch(onMouseUp({ x, y }, 2));
expect(onClickListener).toBeCalled();
expect(onClickListener.mock.calls[0][0]).toEqual([
[
[
{
smAccessorValue: 'a',
groupByRollup: 'a',
value: 1,
depth: 1,
sortIndex: 0,
path: [
{ index: 0, value: HIERARCHY_ROOT_KEY },
{ index: 0, value: 'a' },
],
},
],
{
specId: sunburstSpec.id,
key: `spec{${sunburstSpec.id}}`,
},
],
]);
});
test('sunburst check picked geometries', () => {
const onClickListener = jest.fn<
undefined,
Expand All @@ -149,6 +242,7 @@ describe('Picked shapes selector', () => {
[
[
{
smAccessorValue: '',
groupByRollup: 'b',
value: 2,
depth: 1,
Expand All @@ -159,6 +253,7 @@ describe('Picked shapes selector', () => {
],
},
{
smAccessorValue: '',
groupByRollup: 'b',
value: 1,
depth: 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ const getGroupBySpecs = createCachedSelector([getSpecs], (specs) =>
)(getChartIdSelector);

/** @internal */
export type StyledTree = { name: string | number; style: SmallMultiplesStyle; tree: HierarchyOfArrays };
export type StyledTree = {
smAccessorValue: ReturnType<GroupByAccessor>;
name: string;
style: SmallMultiplesStyle;
tree: HierarchyOfArrays;
};

function getTreesForSpec(
spec: PartitionSpec,
Expand Down Expand Up @@ -81,6 +86,7 @@ function getTreesForSpec(
.sort(getPredicateFn(sort))
.map(([groupKey, subData]) => ({
name: format(groupKey),
smAccessorValue: groupKey,
style: smStyle,
tree: partitionTree(
subData,
Expand All @@ -94,6 +100,7 @@ function getTreesForSpec(
return [
{
name: '',
smAccessorValue: '',
style: smStyle,
tree: partitionTree(data, valueAccessor, layers, configMetadata.partitionLayout.dflt, config.partitionLayout),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const getPickedShapesLayerValues = createCachedSelector(
const elements = pickedShapes.map<Array<LayerValue>>((model) => {
const values: Array<LayerValue> = [];
values.push({
smAccessorValue: '',
groupByRollup: 'Word count',
value: model.data.length,
sortIndex: 0,
Expand Down
2 changes: 1 addition & 1 deletion packages/osd-charts/src/specs/group_by.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { Predicate } from '../common/predicate';
import { getConnect, specComponentFactory } from '../state/spec_factory';
import { SpecType } from './constants';

/** @alpha */
/** @public */
export type GroupByAccessor = (spec: Spec, datum: any) => string | number;
/** @alpha */
export type GroupBySort = Predicate;
Expand Down
Loading

0 comments on commit 0e1f7de

Please sign in to comment.