This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-25 10:18:20 +01:00
parent 3bbeb927cc
commit 958ba535d6
6 changed files with 34 additions and 17 deletions

View File

@@ -13,7 +13,7 @@ import { Summary } from './summary';
export function ReportConversionChart() { export function ReportConversionChart() {
const { isLazyLoading, report } = useReportChartContext(); const { isLazyLoading, report } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
console.log(report.limit);
const res = useQuery( const res = useQuery(
trpc.chart.conversion.queryOptions(report, { trpc.chart.conversion.queryOptions(report, {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -40,6 +40,7 @@ export function ReportFunnelChart() {
metric: 'sum', metric: 'sum',
startDate, startDate,
endDate, endDate,
limit: 20,
}; };
const trpc = useTRPC(); const trpc = useTRPC();
const res = useQuery( const res = useQuery(

View File

@@ -26,6 +26,7 @@ export function format(
}>, }>,
includeAlphaIds: boolean, includeAlphaIds: boolean,
previousSeries: ConcreteSeries[] | null = null, previousSeries: ConcreteSeries[] | null = null,
limit: number | undefined = undefined,
): FinalChart { ): FinalChart {
const series = concreteSeries.map((cs) => { const series = concreteSeries.map((cs) => {
// Find definition for this series // Find definition for this series
@@ -124,6 +125,9 @@ export function format(
}; };
}); });
// Sort series by sum (biggest first)
series.sort((a, b) => b.metrics.sum - a.metrics.sum);
// Calculate global metrics // Calculate global metrics
const allValues = concreteSeries.flatMap((cs) => cs.data.map((d) => d.count)); const allValues = concreteSeries.flatMap((cs) => cs.data.map((d) => d.count));
const globalMetrics = { const globalMetrics = {
@@ -135,7 +139,7 @@ export function format(
}; };
return { return {
series, series: limit ? series.slice(0, limit) : series,
metrics: globalMetrics, metrics: globalMetrics,
}; };
} }

View File

@@ -18,8 +18,6 @@ import type { ConcreteSeries } from './types';
* Executes the pipeline: normalize -> plan -> fetch -> compute -> format * Executes the pipeline: normalize -> plan -> fetch -> compute -> format
*/ */
export async function executeChart(input: IChartInput): Promise<FinalChart> { export async function executeChart(input: IChartInput): Promise<FinalChart> {
const { timezone } = await getSettingsForProject(input.projectId);
// Stage 1: Normalize input // Stage 1: Normalize input
const normalized = await normalize(input); const normalized = await normalize(input);

View File

@@ -20,6 +20,7 @@ export class ConversionService {
funnelWindow = 24, funnelWindow = 24,
series, series,
breakdowns = [], breakdowns = [],
limit,
interval, interval,
timezone, timezone,
}: Omit<IChartInput, 'range' | 'previous' | 'metric' | 'chartType'> & { }: Omit<IChartInput, 'range' | 'previous' | 'metric' | 'chartType'> & {
@@ -114,18 +115,20 @@ export class ConversionService {
} }
const results = await query.execute(); const results = await query.execute();
return this.toSeries(results, breakdowns).map((serie, serieIndex) => { return this.toSeries(results, breakdowns, limit).map(
return { (serie, serieIndex) => {
...serie, return {
data: serie.data.map((d, index) => ({ ...serie,
...d, data: serie.data.map((d, index) => ({
timestamp: new Date(d.date).getTime(), ...d,
serieIndex, timestamp: new Date(d.date).getTime(),
index, serieIndex,
serie: omit(['data'], serie), index,
})), serie: omit(['data'], serie),
}; })),
}); };
},
);
} }
private toSeries( private toSeries(
@@ -137,6 +140,7 @@ export class ConversionService {
[key: string]: string | number; [key: string]: string | number;
}[], }[],
breakdowns: { name: string }[] = [], breakdowns: { name: string }[] = [],
limit: number | undefined = undefined,
) { ) {
if (!breakdowns.length) { if (!breakdowns.length) {
return [ return [
@@ -156,6 +160,10 @@ export class ConversionService {
// Group by breakdown values // Group by breakdown values
const series = data.reduce( const series = data.reduce(
(acc, d) => { (acc, d) => {
if (limit && Object.keys(acc).length >= limit) {
return acc;
}
const key = const key =
breakdowns.map((b, index) => d[`b_${index}`]).join('|') || breakdowns.map((b, index) => d[`b_${index}`]).join('|') ||
NOT_SET_VALUE; NOT_SET_VALUE;

View File

@@ -126,6 +126,7 @@ export class FunnelService {
toSeries( toSeries(
funnel: { level: number; count: number; [key: string]: any }[], funnel: { level: number; count: number; [key: string]: any }[],
breakdowns: { name: string }[] = [], breakdowns: { name: string }[] = [],
limit: number | undefined = undefined,
) { ) {
if (!breakdowns.length) { if (!breakdowns.length) {
return [ return [
@@ -141,6 +142,10 @@ export class FunnelService {
// Group by breakdown values // Group by breakdown values
const series = funnel.reduce( const series = funnel.reduce(
(acc, f) => { (acc, f) => {
if (limit && Object.keys(acc).length >= limit) {
return acc;
}
const key = breakdowns.map((b, index) => f[`b_${index}`]).join('|'); const key = breakdowns.map((b, index) => f[`b_${index}`]).join('|');
if (!acc[key]) { if (!acc[key]) {
acc[key] = []; acc[key] = [];
@@ -183,6 +188,7 @@ export class FunnelService {
funnelWindow = 24, funnelWindow = 24,
funnelGroup, funnelGroup,
breakdowns = [], breakdowns = [],
limit,
timezone = 'UTC', timezone = 'UTC',
}: IChartInput & { timezone: string; events?: IChartEvent[] }) { }: IChartInput & { timezone: string; events?: IChartEvent[] }) {
if (!startDate || !endDate) { if (!startDate || !endDate) {
@@ -267,7 +273,7 @@ export class FunnelService {
.orderBy('level', 'DESC'); .orderBy('level', 'DESC');
const funnelData = await funnelQuery.execute(); const funnelData = await funnelQuery.execute();
const funnelSeries = this.toSeries(funnelData, breakdowns); const funnelSeries = this.toSeries(funnelData, breakdowns, limit);
return funnelSeries return funnelSeries
.map((data) => { .map((data) => {