fix: report intervals

This commit is contained in:
Carl-Gerhard Lindesvärd
2026-01-22 21:49:13 +01:00
parent 32ea28b2f6
commit 9e5b482447
11 changed files with 37 additions and 85 deletions

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -12,18 +11,12 @@ import { Chart } from './chart';
export function ReportAreaChart() { export function ReportAreaChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.chart.queryOptions( trpc.chart.chart.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { cn } from '@/utils/cn'; import { cn } from '@/utils/cn';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
@@ -12,18 +11,12 @@ import { Chart } from './chart';
export function ReportBarChart() { export function ReportBarChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.aggregate.queryOptions( trpc.chart.aggregate.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { cn } from '@/utils/cn'; import { cn } from '@/utils/cn';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
@@ -14,18 +13,11 @@ import { Summary } from './summary';
export function ReportConversionChart() { export function ReportConversionChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
console.log(report.limit);
const res = useQuery( const res = useQuery(
trpc.chart.conversion.queryOptions( trpc.chart.conversion.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -12,18 +11,12 @@ import { Chart } from './chart';
export function ReportHistogramChart() { export function ReportHistogramChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.chart.queryOptions( trpc.chart.chart.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,8 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { cn } from '@/utils/cn';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -13,18 +11,11 @@ import { Chart } from './chart';
export function ReportLineChart() { export function ReportLineChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.chart.queryOptions( trpc.chart.chart.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -12,18 +11,12 @@ import { Chart } from './chart';
export function ReportMapChart() { export function ReportMapChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.chart.queryOptions( trpc.chart.chart.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -11,18 +10,12 @@ import { Chart } from './chart';
export function ReportMetricChart() { export function ReportMetricChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.chart.queryOptions( trpc.chart.chart.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -1,7 +1,6 @@
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { keepPreviousData, useQuery } from '@tanstack/react-query'; import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { AspectContainer } from '../aspect-container'; import { AspectContainer } from '../aspect-container';
import { ReportChartEmpty } from '../common/empty'; import { ReportChartEmpty } from '../common/empty';
import { ReportChartError } from '../common/error'; import { ReportChartError } from '../common/error';
@@ -12,18 +11,12 @@ import { Chart } from './chart';
export function ReportPieChart() { export function ReportPieChart() {
const { isLazyLoading, report, shareId } = useReportChartContext(); const { isLazyLoading, report, shareId } = useReportChartContext();
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const res = useQuery( const res = useQuery(
trpc.chart.aggregate.queryOptions( trpc.chart.aggregate.queryOptions(
{ {
...report, ...report,
shareId, shareId,
reportId: 'id' in report ? report.id : undefined,
range: range ?? report.range,
startDate: startDate ?? report.startDate,
endDate: endDate ?? report.endDate,
interval: interval ?? report.interval,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -53,7 +53,7 @@ export function ReportRetentionChart() {
criteria, criteria,
interval: overviewInterval ?? interval, interval: overviewInterval ?? interval,
shareId, shareId,
reportId: id, id,
}, },
{ {
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@@ -4,6 +4,7 @@ import FullPageLoadingState from '@/components/full-page-loading-state';
import { LoginNavbar } from '@/components/login-navbar'; import { LoginNavbar } from '@/components/login-navbar';
import { OverviewInterval } from '@/components/overview/overview-interval'; import { OverviewInterval } from '@/components/overview/overview-interval';
import { OverviewRange } from '@/components/overview/overview-range'; import { OverviewRange } from '@/components/overview/overview-range';
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { ReportChart } from '@/components/report-chart'; import { ReportChart } from '@/components/report-chart';
import { useTRPC } from '@/integrations/trpc/react'; import { useTRPC } from '@/integrations/trpc/react';
import { useSuspenseQuery } from '@tanstack/react-query'; import { useSuspenseQuery } from '@tanstack/react-query';
@@ -63,6 +64,7 @@ function RouteComponent() {
const { shareId } = Route.useParams(); const { shareId } = Route.useParams();
const { header } = useSearch({ from: '/share/report/$shareId' }); const { header } = useSearch({ from: '/share/report/$shareId' });
const trpc = useTRPC(); const trpc = useTRPC();
const { range, startDate, endDate, interval } = useOverviewOptions();
const shareQuery = useSuspenseQuery( const shareQuery = useSuspenseQuery(
trpc.share.report.queryOptions({ trpc.share.report.queryOptions({
shareId, shareId,
@@ -81,8 +83,6 @@ function RouteComponent() {
const share = shareQuery.data; const share = shareQuery.data;
console.log('share', share);
// Handle password protection // Handle password protection
if (share.password && !hasAccess) { if (share.password && !hasAccess) {
return <ShareEnterPassword shareId={share.id} shareType="report" />; return <ShareEnterPassword shareId={share.id} shareType="report" />;
@@ -114,7 +114,16 @@ function RouteComponent() {
<div className="font-medium text-xl">{share.report.name}</div> <div className="font-medium text-xl">{share.report.name}</div>
</div> </div>
<div className="p-4"> <div className="p-4">
<ReportChart report={share.report} shareId={shareId} /> <ReportChart
report={{
...share.report,
range: range ?? share.report.range,
startDate: startDate ?? share.report.startDate,
endDate: endDate ?? share.report.endDate,
interval: interval ?? share.report.interval,
}}
shareId={shareId}
/>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -27,10 +27,10 @@ import {
} from '@openpanel/db'; } from '@openpanel/db';
import { import {
type IChartEvent, type IChartEvent,
zReportInput,
zChartSeries, zChartSeries,
zCriteria, zCriteria,
zRange, zRange,
zReportInput,
zTimeInterval, zTimeInterval,
} from '@openpanel/validation'; } from '@openpanel/validation';
@@ -338,7 +338,7 @@ export const chartRouter = createTRPCRouter({
zReportInput.and( zReportInput.and(
z.object({ z.object({
shareId: z.string().optional(), shareId: z.string().optional(),
reportId: z.string().optional(), id: z.string().optional(),
}), }),
), ),
) )
@@ -347,14 +347,14 @@ export const chartRouter = createTRPCRouter({
if (input.shareId) { if (input.shareId) {
// Require reportId when shareId provided // Require reportId when shareId provided
if (!input.reportId) { if (!input.id) {
throw new Error('reportId required with shareId'); throw new Error('reportId required with shareId');
} }
// Validate share access // Validate share access
const shareValidation = await validateShareAccess( const shareValidation = await validateShareAccess(
input.shareId, input.shareId,
input.reportId, input.id,
{ {
cookies: ctx.cookies, cookies: ctx.cookies,
session: ctx.session?.userId session: ctx.session?.userId
@@ -367,7 +367,7 @@ export const chartRouter = createTRPCRouter({
} }
// Fetch report and merge date overrides // Fetch report and merge date overrides
const report = await getReportById(input.reportId); const report = await getReportById(input.id);
if (!report) { if (!report) {
throw TRPCAccessError('Report not found'); throw TRPCAccessError('Report not found');
} }
@@ -420,7 +420,7 @@ export const chartRouter = createTRPCRouter({
zReportInput.and( zReportInput.and(
z.object({ z.object({
shareId: z.string().optional(), shareId: z.string().optional(),
reportId: z.string().optional(), id: z.string().optional(),
}), }),
), ),
) )
@@ -429,14 +429,14 @@ export const chartRouter = createTRPCRouter({
if (input.shareId) { if (input.shareId) {
// Require reportId when shareId provided // Require reportId when shareId provided
if (!input.reportId) { if (!input.id) {
throw new Error('reportId required with shareId'); throw new Error('reportId required with shareId');
} }
// Validate share access // Validate share access
const shareValidation = await validateShareAccess( const shareValidation = await validateShareAccess(
input.shareId, input.shareId,
input.reportId, input.id,
{ {
cookies: ctx.cookies, cookies: ctx.cookies,
session: ctx.session?.userId session: ctx.session?.userId
@@ -449,7 +449,7 @@ export const chartRouter = createTRPCRouter({
} }
// Fetch report and merge date overrides // Fetch report and merge date overrides
const report = await getReportById(input.reportId); const report = await getReportById(input.id);
if (!report) { if (!report) {
throw TRPCAccessError('Report not found'); throw TRPCAccessError('Report not found');
} }
@@ -549,23 +549,24 @@ export const chartRouter = createTRPCRouter({
zReportInput.and( zReportInput.and(
z.object({ z.object({
shareId: z.string().optional(), shareId: z.string().optional(),
reportId: z.string().optional(), id: z.string().optional(),
}), }),
), ),
) )
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
let chartInput = input; let chartInput = input;
console.log('input', input);
if (input.shareId) { if (input.shareId) {
// Require reportId when shareId provided // Require reportId when shareId provided
if (!input.reportId) { if (!input.id) {
throw new Error('reportId required with shareId'); throw new Error('reportId required with shareId');
} }
// Validate share access // Validate share access
const shareValidation = await validateShareAccess( const shareValidation = await validateShareAccess(
input.shareId, input.shareId,
input.reportId, input.id,
ctx, ctx,
); );
@@ -574,7 +575,7 @@ export const chartRouter = createTRPCRouter({
} }
// Fetch report and merge date overrides // Fetch report and merge date overrides
const report = await getReportById(input.reportId); const report = await getReportById(input.id);
if (!report) { if (!report) {
throw TRPCAccessError('Report not found'); throw TRPCAccessError('Report not found');
} }
@@ -609,7 +610,7 @@ export const chartRouter = createTRPCRouter({
zReportInput.and( zReportInput.and(
z.object({ z.object({
shareId: z.string().optional(), shareId: z.string().optional(),
reportId: z.string().optional(), id: z.string().optional(),
}), }),
), ),
) )
@@ -618,14 +619,14 @@ export const chartRouter = createTRPCRouter({
if (input.shareId) { if (input.shareId) {
// Require reportId when shareId provided // Require reportId when shareId provided
if (!input.reportId) { if (!input.id) {
throw new Error('reportId required with shareId'); throw new Error('reportId required with shareId');
} }
// Validate share access // Validate share access
const shareValidation = await validateShareAccess( const shareValidation = await validateShareAccess(
input.shareId, input.shareId,
input.reportId, input.id,
{ {
cookies: ctx.cookies, cookies: ctx.cookies,
session: ctx.session?.userId session: ctx.session?.userId
@@ -638,7 +639,7 @@ export const chartRouter = createTRPCRouter({
} }
// Fetch report and merge date overrides // Fetch report and merge date overrides
const report = await getReportById(input.reportId); const report = await getReportById(input.id);
if (!report) { if (!report) {
throw TRPCAccessError('Report not found'); throw TRPCAccessError('Report not found');
} }
@@ -680,7 +681,7 @@ export const chartRouter = createTRPCRouter({
interval: zTimeInterval.default('day'), interval: zTimeInterval.default('day'),
range: zRange, range: zRange,
shareId: z.string().optional(), shareId: z.string().optional(),
reportId: z.string().optional(), id: z.string().optional(),
}), }),
) )
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
@@ -695,14 +696,14 @@ export const chartRouter = createTRPCRouter({
if (input.shareId) { if (input.shareId) {
// Require reportId when shareId provided // Require reportId when shareId provided
if (!input.reportId) { if (!input.id) {
throw new Error('reportId required with shareId'); throw new Error('reportId required with shareId');
} }
// Validate share access // Validate share access
const shareValidation = await validateShareAccess( const shareValidation = await validateShareAccess(
input.shareId, input.shareId,
input.reportId, input.id,
{ {
cookies: ctx.cookies, cookies: ctx.cookies,
session: ctx.session?.userId session: ctx.session?.userId
@@ -715,13 +716,14 @@ export const chartRouter = createTRPCRouter({
} }
// Fetch report and extract events // Fetch report and extract events
const report = await getReportById(input.reportId); const report = await getReportById(input.id);
if (!report) { if (!report) {
throw TRPCAccessError('Report not found'); throw TRPCAccessError('Report not found');
} }
projectId = report.projectId; projectId = report.projectId;
const retentionOptions = report.options?.type === 'retention' ? report.options : undefined; const retentionOptions =
report.options?.type === 'retention' ? report.options : undefined;
criteria = retentionOptions?.criteria ?? criteria; criteria = retentionOptions?.criteria ?? criteria;
dateRange = input.range ?? report.range; dateRange = input.range ?? report.range;
startDate = input.startDate ?? report.startDate; startDate = input.startDate ?? report.startDate;