ui: fixing bars under comparison
This commit is contained in:
parent
8e1f50e4a3
commit
1c200452b5
4 changed files with 114 additions and 78 deletions
|
|
@ -44,6 +44,7 @@ function ColumnChart(props: ColumnChartProps) {
|
|||
|
||||
const { yAxisData, series } = buildColumnChart(chartUuid.current, data, compData);
|
||||
|
||||
console.log(yAxisData)
|
||||
chart.setOption({
|
||||
...defaultOptions,
|
||||
tooltip: {
|
||||
|
|
@ -51,6 +52,7 @@ function ColumnChart(props: ColumnChartProps) {
|
|||
formatter: customTooltipFormatter(chartUuid.current),
|
||||
},
|
||||
legend: {
|
||||
...defaultOptions.legend,
|
||||
data: series
|
||||
.filter((s: any) => !s._hideInLegend)
|
||||
.map((s: any) => s.name),
|
||||
|
|
@ -64,7 +66,6 @@ function ColumnChart(props: ColumnChartProps) {
|
|||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01],
|
||||
name: label ?? 'Total',
|
||||
nameLocation: 'middle',
|
||||
nameGap: 35,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { DataProps, DataItem } from './utils';
|
||||
import { createDataset, assignColorsByBaseName } from './utils';
|
||||
import { createDataset, assignColorsByBaseName, assignColorsByCategory } from './utils';
|
||||
|
||||
export function createBarSeries(
|
||||
data: DataProps['data'],
|
||||
|
|
@ -48,94 +48,82 @@ export function buildBarDatasetsAndSeries(props: DataProps) {
|
|||
}
|
||||
|
||||
|
||||
// START GEN
|
||||
function sumSeries(chart: DataItem[], seriesName: string): number {
|
||||
return chart.reduce((acc, row) => acc + (Number(row[seriesName]) || 0), 0);
|
||||
}
|
||||
|
||||
export function buildColumnChart(chartUuid: string, data: DataProps['data'], compData: DataProps['compData'],) {
|
||||
const baseNamesSet = new Set<string>();
|
||||
/**
|
||||
* Build a horizontal bar chart with:
|
||||
* - yAxis categories = each name in data.namesMap
|
||||
* - 1 bar series for "Current"
|
||||
* - 1 bar series for "Previous" (optional, if compData present)
|
||||
*/
|
||||
export function buildColumnChart(
|
||||
chartUuid: string,
|
||||
data: DataProps['data'],
|
||||
compData: DataProps['compData']
|
||||
) {
|
||||
const categories = data.namesMap.filter(Boolean);
|
||||
|
||||
data.namesMap.filter(Boolean).forEach((fullName) => {
|
||||
const baseName = fullName.replace(/^Previous\s+/, '');
|
||||
baseNamesSet.add(baseName);
|
||||
const currentValues = categories.map((name) => {
|
||||
const val = sumSeries(data.chart, name);
|
||||
(window as any).__seriesValueMap[chartUuid][name] = val;
|
||||
return val;
|
||||
});
|
||||
|
||||
let previousValues: number[] = [];
|
||||
if (compData && compData.chart?.length) {
|
||||
compData.namesMap.filter(Boolean).forEach((fullName) => {
|
||||
const baseName = fullName.replace(/^Previous\s+/, '');
|
||||
baseNamesSet.add(baseName);
|
||||
previousValues = categories.map((name) => {
|
||||
const val = sumSeries(compData.chart, `Previous ${name}`);
|
||||
(window as any).__seriesValueMap[chartUuid][`Previous ${name}`] = val;
|
||||
return val;
|
||||
});
|
||||
}
|
||||
|
||||
const baseNames = Array.from(baseNamesSet); // e.g. ["Series 1","Series 2"]
|
||||
const currentSeries = {
|
||||
name: 'Current',
|
||||
type: 'bar',
|
||||
barWidth: 16,
|
||||
data: currentValues,
|
||||
_baseName: 'Current',
|
||||
itemStyle: {
|
||||
borderRadius: [0, 6, 6, 0],
|
||||
},
|
||||
};
|
||||
|
||||
const yAxisData = baseNames;
|
||||
|
||||
const series: any[] = [];
|
||||
|
||||
data.namesMap.filter(Boolean).forEach((fullName) => {
|
||||
const baseName = fullName.replace(/^Previous\s+/, '');
|
||||
const idx = baseNames.indexOf(baseName);
|
||||
|
||||
const val = sumSeries(data.chart, fullName);
|
||||
const dataArr = new Array(baseNames.length).fill(0);
|
||||
dataArr[idx] = val;
|
||||
(window as any).__seriesValueMap[chartUuid][
|
||||
`Previous ${fullName}`
|
||||
] = val;
|
||||
series.push({
|
||||
name: fullName,
|
||||
let previousSeries: any = null;
|
||||
if (previousValues.length > 0) {
|
||||
previousSeries = {
|
||||
name: 'Previous',
|
||||
type: 'bar',
|
||||
barWidth: 16,
|
||||
data: dataArr,
|
||||
_hideInLegend: false,
|
||||
_baseName: baseName,
|
||||
data: previousValues,
|
||||
_baseName: 'Previous',
|
||||
itemStyle: {
|
||||
borderRadius: [0, 6, 6, 0],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
if (compData && compData.chart?.length) {
|
||||
compData.namesMap.filter(Boolean).forEach((fullName) => {
|
||||
const baseName = fullName.replace(/^Previous\s+/, '');
|
||||
const idx = baseNames.indexOf(baseName);
|
||||
const val = sumSeries(compData.chart, fullName);
|
||||
|
||||
const dataArr = new Array(baseNames.length).fill(0);
|
||||
dataArr[idx] = val;
|
||||
(window as any).__seriesValueMap[chartUuid][baseName] = val;
|
||||
series.push({
|
||||
name: fullName,
|
||||
type: 'bar',
|
||||
barWidth: 16,
|
||||
barGap: '1%',
|
||||
data: dataArr,
|
||||
_hideInLegend: true,
|
||||
_baseName: baseName,
|
||||
itemStyle: {
|
||||
borderRadius: [0, 6, 6, 0],
|
||||
decal: {
|
||||
show: true,
|
||||
symbol: 'line',
|
||||
symbolSize: 6,
|
||||
rotation: 1,
|
||||
dashArrayX: 4,
|
||||
dashArrayY: 4,
|
||||
},
|
||||
decal: {
|
||||
show: true,
|
||||
symbol: 'line',
|
||||
symbolSize: 6,
|
||||
rotation: 1,
|
||||
dashArrayX: 4,
|
||||
dashArrayY: 4,
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
assignColorsByBaseName(series);
|
||||
const series = previousSeries ? [currentSeries, previousSeries] : [currentSeries];
|
||||
|
||||
assignColorsByCategory(series, categories);
|
||||
|
||||
series.forEach((s) => {
|
||||
(window as any).__seriesColorMap[chartUuid][s.name] =
|
||||
s.itemStyle.color;
|
||||
(window as any).__seriesColorMap[chartUuid][s.name] = s.itemStyle.color;
|
||||
});
|
||||
|
||||
return {
|
||||
yAxisData,
|
||||
yAxisData: categories,
|
||||
series,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ export function assignColorsByBaseName(series: any[]) {
|
|||
}
|
||||
});
|
||||
|
||||
// Then apply color to each series
|
||||
series.forEach((s) => {
|
||||
const baseName = s._baseName || s.name;
|
||||
const color = colorMap[baseName];
|
||||
|
|
@ -49,6 +48,45 @@ export function assignColorsByBaseName(series: any[]) {
|
|||
});
|
||||
}
|
||||
|
||||
function buildCategoryColorMap(categories: string[]): Record<number, string> {
|
||||
const colorMap: Record<number, string> = {};
|
||||
categories.forEach((_, i) => {
|
||||
colorMap[i] = colors[i % colors.length];
|
||||
});
|
||||
return colorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each series, transform its data array to an array of objects
|
||||
* with `value` and `itemStyle.color` based on the category index.
|
||||
*/
|
||||
export function assignColorsByCategory(
|
||||
series: any[],
|
||||
categories: string[]
|
||||
) {
|
||||
const categoryColorMap = buildCategoryColorMap(categories);
|
||||
|
||||
series.forEach((s, si) => {
|
||||
s.data = s.data.map((val: any, i: number) => {
|
||||
const color = categoryColorMap[i];
|
||||
if (typeof val === 'number') {
|
||||
return {
|
||||
value: val,
|
||||
itemStyle: { color },
|
||||
};
|
||||
}
|
||||
return {
|
||||
...val,
|
||||
itemStyle: {
|
||||
...(val.itemStyle || {}),
|
||||
color,
|
||||
},
|
||||
};
|
||||
});
|
||||
s.itemStyle = { ...s.itemStyle, color: colors[si] };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the hovered “current” or “previous” line + the matching partner (if it exists).
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import { Space, Segmented, Tooltip } from 'antd';
|
|||
import { renderClickmapThumbnail } from 'Components/Dashboard/components/WidgetForm/renderMap';
|
||||
import Widget from 'App/mstore/types/widget';
|
||||
import { LayoutPanelTop, LayoutPanelLeft } from 'lucide-react';
|
||||
import classNames from 'classnames';
|
||||
import cn from 'classnames'
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
|
|
@ -34,13 +34,13 @@ interface Props {
|
|||
}
|
||||
|
||||
function WidgetView(props: Props) {
|
||||
const [layout, setLayout] = useState('horizontal');
|
||||
const [layout, setLayout] = useState('flex-row');
|
||||
const {
|
||||
match: {
|
||||
params: { siteId, dashboardId, metricId },
|
||||
},
|
||||
} = props;
|
||||
const { metricStore, dashboardStore } = useStore();
|
||||
const { metricStore, dashboardStore, settingsStore } = useStore();
|
||||
const widget = metricStore.instance;
|
||||
const loading = metricStore.isLoading;
|
||||
const [expanded, setExpanded] = useState(!metricId || metricId === 'create');
|
||||
|
|
@ -65,6 +65,7 @@ function WidgetView(props: Props) {
|
|||
metricStore.init();
|
||||
}
|
||||
}
|
||||
settingsStore.updateMenuCollapsed(true)
|
||||
}, []);
|
||||
|
||||
const undoChanges = () => {
|
||||
|
|
@ -150,7 +151,7 @@ function WidgetView(props: Props) {
|
|||
onChange={setLayout}
|
||||
options={[
|
||||
{
|
||||
value: 'horizontal',
|
||||
value: 'flex-row',
|
||||
icon: (
|
||||
<Tooltip title="Horizontal Layout">
|
||||
<LayoutPanelLeft size={16} />
|
||||
|
|
@ -158,22 +159,30 @@ function WidgetView(props: Props) {
|
|||
)
|
||||
},
|
||||
{
|
||||
value: 'vertical',
|
||||
value: 'flex-col',
|
||||
icon: (
|
||||
<Tooltip title="Vertical Layout">
|
||||
<LayoutPanelTop size={16} />
|
||||
</Tooltip>
|
||||
)
|
||||
},
|
||||
{
|
||||
value: 'flex-row-reverse',
|
||||
icon: (
|
||||
<Tooltip title="Reversed Horizontal Layout">
|
||||
<div className={'rotate-180'}><LayoutPanelLeft size={16} /></div>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<div className={layout === 'horizontal' ? 'flex gap-4' : ''}>
|
||||
<div className={layout === 'horizontal' ? 'w-1/3 ' : 'w-full'}>
|
||||
<div className={cn('flex gap-4', layout)}>
|
||||
<div className={layout.startsWith('flex-row') ? 'w-1/3 ' : 'w-full'}>
|
||||
<WidgetFormNew />
|
||||
</div>
|
||||
<div className={layout === 'horizontal' ? 'w-2/3' : 'w-full'}>
|
||||
<div className={layout.startsWith('flex-row') ? 'w-2/3' : 'w-full'}>
|
||||
<WidgetPreview name={widget.name} isEditing={expanded} />
|
||||
|
||||
{widget.metricOf !== FilterKey.SESSIONS &&
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue