Unlocking the power of Compose SDK to build and publish visualizations and add-ons
By Steven Griffith, Director of SDK
1
2
3
4
5
6
7
8
9
10
return (
<Histogram
dataSource={DM.DataSource}
dataOptions={{
category: [DM.Commerce.AgeRange],
value: DM.Commerce.Revenue,
}}
styleOptions={{ subtype: 'stacked' }}
/>
);
1
2
3
4
5
6
7
8
9
10
export type HistogramProps = {
dataSource?: DataSource;
dataOptions: HistogramDataOptions;
filters?: Filter[];
styleOptions?: HistogramStyleOptions;
};
export interface HistogramDataOptions {
value: Attribute;
category: Attribute[];
}
1
2
3
export interface HistogramStyleOptions {
binCount?: number | "auto";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// construct a query to get min, max, and count of data points based on the input value
const minMeas = useMemo(() => measureFactory.min(dataOptions.value, 'min'), [dataOptions.value]);
const maxMeas = useMemo(() => measureFactory.max(dataOptions.value, 'max'), [dataOptions.value]);
const countMeas = useMemo(
() => measureFactory.count(dataOptions.value, 'count'),
[dataOptions.value],
);
const queryMinMax = useMemo(
() => ({
measures: [minMeas, maxMeas, countMeas],
filters,
}),
[minMeas, maxMeas, countMeas, filters],
);
const {
data: minMaxData,
isLoading: isMinMaxLoading,
error: isMinMaxError,
} = useExecuteQuery(queryMinMax);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const MAX_BARS = 60;
const MIN_BARS = 3;
let binCount =
!styleOptions?.binCount || styleOptions.binCount === 'auto'
? Math.floor(Math.sqrt(count)) : styleOptions.binCount;
binCount = Math.max(binCount, MIN_BARS);
binCount = Math.min(binCount, MAX_BARS);
const binRange = (maxValue - minValue) / binCount;
const binMeasures = Array(binCount)
.fill(0)
.map((_v, index) => {
const min = minValue + index * binRange;
const max = min + binRange;
const binFilter = filterFactory.between(dataOptions.value, min, max);
return measureFactory.measuredValue(
countMeas,
[binFilter],
binLabel(min, max, styleOptions?.binSizePrecision),
);
});
1
2
3
4
5
6
7
8
9
10
const {
data: binData,
isLoading,
error,
} = useExecuteQuery({
measures: binMeasures,
filters,
dimensions: dataOptions.category,
}
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
export const useProcessResults = ({
binData,
dataOptions,
}: {
binData?: QueryResultData;
dataOptions: HistogramDataOptions;
}) => {
return useMemo(() => {
if (!binData) return { columns: [], rows: [] };
const rows: (number | string)[][] = [];
binData.rows.forEach((_row, rowIndex) => {
binData.columns.forEach((column, colIndex) => {
if (colIndex >= dataOptions.category.length) {
const row: (number | string)[] = [];
const currentRow = binData.rows[rowIndex];
if (currentRow) {
dataOptions.category.forEach((_d, dimIndex) => {
row.push(currentRow[dimIndex]?.data as number);
});
row.push(currentRow[colIndex]?.data as number);
row.push(parseFloat(column.name));
rows.push(row);
}
}
});
});
return {
columns: [
...dataOptions.category.map((d) => ({ name: d.name, type: d.type })),
{ name: FREQUENCY, type: 'number', aggregation: 'sum' },
{ name: dataOptions.value.name, type: 'number' },
],
rows: rows,
} as Data;
}, [binData, dataOptions.value.name, dataOptions.category]);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const columnStyleOptions = useMemo<StackableStyleOptions>(
() => ({
subtype: styleOptions?.subtype === 'stacked' ? 'column/stackedcolumn' : 'column/classic',
}),
[styleOptions?.subtype],
);
const columnChartDataOptions = useMemo(
() => ({
category: [dataOptions.value],
value: [{ name: FREQUENCY }],
breakBy: dataOptions.category,
}),
[dataOptions.value, dataOptions.category],
);
return (
<ColumnChart
dataSet={histogramData}
dataOptions={columnChartDataOptions}
onBeforeRender={onBeforeRender}
styleOptions={columnStyleOptions}
/>
);
1
yarn add more-compose-sdk-charts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from "react";
import { Histogram } from "more-compose-sdk-charts";
import { filters } from "@sisense/sdk-data";
import * as DM from "./sample-ecommerce";
export default function App() {
const revenueFilter = filters.between(DM.Commerce.Revenue, 0.01, 1000);
const yearFilter = filters.members(DM.Commerce.Date.Years, ['2012-01-01']);
return (
<Histogram
dataSource={DM.DataSource}
dataOptions={{
category: [DM.Commerce.AgeRange],
value: DM.Commerce.Revenue,
}}
filters={[revenueFilter, yearFilter]}
styleOptions={{ subtype: 'stacked' }}
/>
);
}