feat: add stacked option for histogram
This commit is contained in:
@@ -61,9 +61,14 @@ export function Chart({ data }: Props) {
|
|||||||
range,
|
range,
|
||||||
series: reportSeries,
|
series: reportSeries,
|
||||||
breakdowns,
|
breakdowns,
|
||||||
|
options: reportOptions,
|
||||||
},
|
},
|
||||||
options: { hideXAxis, hideYAxis },
|
options: { hideXAxis, hideYAxis },
|
||||||
} = useReportChartContext();
|
} = useReportChartContext();
|
||||||
|
|
||||||
|
const histogramOptions =
|
||||||
|
reportOptions?.type === 'histogram' ? reportOptions : undefined;
|
||||||
|
const isStacked = histogramOptions?.stacked ?? false;
|
||||||
const trpc = useTRPC();
|
const trpc = useTRPC();
|
||||||
const references = useQuery(
|
const references = useQuery(
|
||||||
trpc.reference.getChartReferences.queryOptions(
|
trpc.reference.getChartReferences.queryOptions(
|
||||||
@@ -176,6 +181,7 @@ export function Chart({ data }: Props) {
|
|||||||
fill={getChartColor(serie.index)}
|
fill={getChartColor(serie.index)}
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
radius={5}
|
radius={5}
|
||||||
|
stackId={isStacked ? 'prev' : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -187,8 +193,9 @@ export function Chart({ data }: Props) {
|
|||||||
name={serie.id}
|
name={serie.id}
|
||||||
dataKey={`${serie.id}:count`}
|
dataKey={`${serie.id}:count`}
|
||||||
fill={getChartColor(serie.index)}
|
fill={getChartColor(serie.index)}
|
||||||
radius={5}
|
radius={isStacked ? 0 : 4}
|
||||||
fillOpacity={1}
|
fillOpacity={1}
|
||||||
|
stackId={isStacked ? 'current' : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -361,6 +361,17 @@ export const reportSlice = createSlice({
|
|||||||
state.options.include = action.payload;
|
state.options.include = action.payload;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
changeStacked(state, action: PayloadAction<boolean>) {
|
||||||
|
state.dirty = true;
|
||||||
|
if (!state.options || state.options.type !== 'histogram') {
|
||||||
|
state.options = {
|
||||||
|
type: 'histogram',
|
||||||
|
stacked: action.payload,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
state.options.stacked = action.payload;
|
||||||
|
}
|
||||||
|
},
|
||||||
reorderEvents(
|
reorderEvents(
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{ fromIndex: number; toIndex: number }>,
|
action: PayloadAction<{ fromIndex: number; toIndex: number }>,
|
||||||
@@ -406,6 +417,7 @@ export const {
|
|||||||
changeSankeySteps,
|
changeSankeySteps,
|
||||||
changeSankeyExclude,
|
changeSankeyExclude,
|
||||||
changeSankeyInclude,
|
changeSankeyInclude,
|
||||||
|
changeStacked,
|
||||||
reorderEvents,
|
reorderEvents,
|
||||||
} = reportSlice.actions;
|
} = reportSlice.actions;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
changeSankeyInclude,
|
changeSankeyInclude,
|
||||||
changeSankeyMode,
|
changeSankeyMode,
|
||||||
changeSankeySteps,
|
changeSankeySteps,
|
||||||
|
changeStacked,
|
||||||
changeUnit,
|
changeUnit,
|
||||||
} from '../reportSlice';
|
} from '../reportSlice';
|
||||||
|
|
||||||
@@ -33,6 +34,9 @@ export function ReportSettings() {
|
|||||||
const funnelGroup = funnelOptions?.funnelGroup;
|
const funnelGroup = funnelOptions?.funnelGroup;
|
||||||
const funnelWindow = funnelOptions?.funnelWindow;
|
const funnelWindow = funnelOptions?.funnelWindow;
|
||||||
|
|
||||||
|
const histogramOptions = options?.type === 'histogram' ? options : undefined;
|
||||||
|
const stacked = histogramOptions?.stacked ?? false;
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { projectId } = useAppParams();
|
const { projectId } = useAppParams();
|
||||||
const eventNames = useEventNames({ projectId });
|
const eventNames = useEventNames({ projectId });
|
||||||
@@ -61,6 +65,10 @@ export function ReportSettings() {
|
|||||||
fields.push('sankeyInclude');
|
fields.push('sankeyInclude');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chartType === 'histogram') {
|
||||||
|
fields.push('stacked');
|
||||||
|
}
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}, [chartType]);
|
}, [chartType]);
|
||||||
|
|
||||||
@@ -259,6 +267,15 @@ export function ReportSettings() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{fields.includes('stacked') && (
|
||||||
|
<Label className="flex items-center justify-between mb-0">
|
||||||
|
<span className="whitespace-nowrap">Stack series</span>
|
||||||
|
<Switch
|
||||||
|
checked={stacked}
|
||||||
|
onCheckedChange={(val) => dispatch(changeStacked(!!val))}
|
||||||
|
/>
|
||||||
|
</Label>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -126,14 +126,21 @@ export const zSankeyOptions = z.object({
|
|||||||
include: z.array(z.string()).optional(),
|
include: z.array(z.string()).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const zHistogramOptions = z.object({
|
||||||
|
type: z.literal('histogram'),
|
||||||
|
stacked: z.boolean().default(false),
|
||||||
|
});
|
||||||
|
|
||||||
export const zReportOptions = z.discriminatedUnion('type', [
|
export const zReportOptions = z.discriminatedUnion('type', [
|
||||||
zFunnelOptions,
|
zFunnelOptions,
|
||||||
zRetentionOptions,
|
zRetentionOptions,
|
||||||
zSankeyOptions,
|
zSankeyOptions,
|
||||||
|
zHistogramOptions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export type IReportOptions = z.infer<typeof zReportOptions>;
|
export type IReportOptions = z.infer<typeof zReportOptions>;
|
||||||
export type ISankeyOptions = z.infer<typeof zSankeyOptions>;
|
export type ISankeyOptions = z.infer<typeof zSankeyOptions>;
|
||||||
|
export type IHistogramOptions = z.infer<typeof zHistogramOptions>;
|
||||||
|
|
||||||
export const zWidgetType = z.enum(['realtime', 'counter']);
|
export const zWidgetType = z.enum(['realtime', 'counter']);
|
||||||
export type IWidgetType = z.infer<typeof zWidgetType>;
|
export type IWidgetType = z.infer<typeof zWidgetType>;
|
||||||
|
|||||||
Reference in New Issue
Block a user