feat(api): add insights endpoints
This commit is contained in:
@@ -20,7 +20,9 @@ import {
|
||||
chQuery,
|
||||
createSqlBuilder,
|
||||
formatClickhouseDate,
|
||||
getChartPrevStartEndDate,
|
||||
getChartSql,
|
||||
getChartStartEndDate,
|
||||
getEventFiltersWhereClause,
|
||||
getOrganizationSubscriptionChartEndDate,
|
||||
getSettingsForProject,
|
||||
@@ -34,10 +36,6 @@ import type {
|
||||
IGetChartDataInput,
|
||||
} from '@openpanel/validation';
|
||||
|
||||
function getEventLegend(event: IChartEvent) {
|
||||
return event.displayName || event.name;
|
||||
}
|
||||
|
||||
export function withFormula(
|
||||
{ formula, events }: IChartInput,
|
||||
series: Awaited<ReturnType<typeof getChartSerie>>,
|
||||
@@ -116,193 +114,6 @@ export function withFormula(
|
||||
];
|
||||
}
|
||||
|
||||
export function getDatesFromRange(range: IChartRange, timezone: string) {
|
||||
if (range === '30min' || range === 'lastHour') {
|
||||
const minutes = range === '30min' ? 30 : 60;
|
||||
const startDate = DateTime.now()
|
||||
.minus({ minute: minutes })
|
||||
.startOf('minute')
|
||||
.setZone(timezone)
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('minute')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'today') {
|
||||
const startDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.startOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'yesterday') {
|
||||
const startDate = DateTime.now()
|
||||
.minus({ day: 1 })
|
||||
.setZone(timezone)
|
||||
.startOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.minus({ day: 1 })
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === '7d') {
|
||||
const startDate = DateTime.now()
|
||||
.minus({ day: 7 })
|
||||
.setZone(timezone)
|
||||
.startOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === '6m') {
|
||||
const startDate = DateTime.now()
|
||||
.minus({ month: 6 })
|
||||
.setZone(timezone)
|
||||
.startOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === '12m') {
|
||||
const startDate = DateTime.now()
|
||||
.minus({ month: 12 })
|
||||
.setZone(timezone)
|
||||
.startOf('month')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('month')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'monthToDate') {
|
||||
const startDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.startOf('month')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'lastMonth') {
|
||||
const month = DateTime.now()
|
||||
.minus({ month: 1 })
|
||||
.setZone(timezone)
|
||||
.startOf('month');
|
||||
|
||||
const startDate = month.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = month
|
||||
.endOf('month')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'yearToDate') {
|
||||
const startDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.startOf('year')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
if (range === 'lastYear') {
|
||||
const year = DateTime.now().minus({ year: 1 }).setZone(timezone);
|
||||
const startDate = year.startOf('year').toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = year.endOf('year').toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
// range === '30d'
|
||||
const startDate = DateTime.now()
|
||||
.minus({ day: 30 })
|
||||
.setZone(timezone)
|
||||
.startOf('day')
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
const endDate = DateTime.now()
|
||||
.setZone(timezone)
|
||||
.endOf('day')
|
||||
.plus({ millisecond: 1 })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
};
|
||||
}
|
||||
|
||||
function fillFunnel(funnel: { level: number; count: number }[], steps: number) {
|
||||
const filled = Array.from({ length: steps }, (_, index) => {
|
||||
const level = index + 1;
|
||||
@@ -325,56 +136,6 @@ function fillFunnel(funnel: { level: number; count: number }[], steps: number) {
|
||||
return filled.reverse();
|
||||
}
|
||||
|
||||
export function getChartStartEndDate(
|
||||
{
|
||||
startDate,
|
||||
endDate,
|
||||
range,
|
||||
}: Pick<IChartInput, 'endDate' | 'startDate' | 'range'>,
|
||||
timezone: string,
|
||||
) {
|
||||
const ranges = getDatesFromRange(range, timezone);
|
||||
|
||||
if (startDate && endDate) {
|
||||
return { startDate: startDate, endDate: endDate };
|
||||
}
|
||||
|
||||
if (!startDate && endDate) {
|
||||
return { startDate: ranges.startDate, endDate: endDate };
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
export function getChartPrevStartEndDate({
|
||||
startDate,
|
||||
endDate,
|
||||
}: {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
}) {
|
||||
let diff = DateTime.fromFormat(endDate, 'yyyy-MM-dd HH:mm:ss').diff(
|
||||
DateTime.fromFormat(startDate, 'yyyy-MM-dd HH:mm:ss'),
|
||||
);
|
||||
|
||||
// this will make sure our start and end date's are correct
|
||||
// otherwise if a day ends with 23:59:59.999 and starts with 00:00:00.000
|
||||
// the diff will be 23:59:59.999 and that will make the start date wrong
|
||||
// so we add 1 millisecond to the diff
|
||||
if ((diff.milliseconds / 1000) % 2 !== 0) {
|
||||
diff = diff.plus({ millisecond: 1 });
|
||||
}
|
||||
|
||||
return {
|
||||
startDate: DateTime.fromFormat(startDate, 'yyyy-MM-dd HH:mm:ss')
|
||||
.minus({ millisecond: diff.milliseconds })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss'),
|
||||
endDate: DateTime.fromFormat(endDate, 'yyyy-MM-dd HH:mm:ss')
|
||||
.minus({ millisecond: diff.milliseconds })
|
||||
.toFormat('yyyy-MM-dd HH:mm:ss'),
|
||||
};
|
||||
}
|
||||
|
||||
export async function getFunnelData({
|
||||
projectId,
|
||||
startDate,
|
||||
|
||||
Reference in New Issue
Block a user