feat: admin monthly active users metric (#1724)

This commit is contained in:
Ephraim Duncan
2025-06-19 05:12:17 +00:00
committed by GitHub
parent 1be0e2842c
commit 2345de679b
4 changed files with 132 additions and 6 deletions

View File

@ -1,7 +1,7 @@
import { SubscriptionStatus } from '@prisma/client';
import { DateTime } from 'luxon';
import { prisma } from '@documenso/prisma';
import { kyselyPrisma, prisma, sql } from '@documenso/prisma';
import { SubscriptionStatus, UserSecurityAuditLogType } from '@documenso/prisma/client';
export const getUsersCount = async () => {
return await prisma.user.count();
@ -49,3 +49,37 @@ export const getUserWithSignedDocumentMonthlyGrowth = async () => {
signed_count: Number(row.signed_count),
}));
};
export type GetMonthlyActiveUsersResult = Array<{
month: string;
count: number;
cume_count: number;
}>;
export const getMonthlyActiveUsers = async () => {
const qb = kyselyPrisma.$kysely
.selectFrom('UserSecurityAuditLog')
.select(({ fn }) => [
fn<Date>('DATE_TRUNC', [sql.lit('MONTH'), 'UserSecurityAuditLog.createdAt']).as('month'),
fn.count('userId').distinct().as('count'),
fn
.sum(fn.count('userId').distinct())
.over((ob) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
ob.orderBy(fn('DATE_TRUNC', [sql.lit('MONTH'), 'UserSecurityAuditLog.createdAt']) as any),
)
.as('cume_count'),
])
.where(sql`type = ${UserSecurityAuditLogType.SIGN_IN}::"UserSecurityAuditLogType"`)
.groupBy(({ fn }) => fn('DATE_TRUNC', [sql.lit('MONTH'), 'UserSecurityAuditLog.createdAt']))
.orderBy('month', 'desc')
.limit(12);
const result = await qb.execute();
return result.map((row) => ({
month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'),
count: Number(row.count),
cume_count: Number(row.cume_count),
}));
};

View File

@ -1,10 +1,15 @@
import { useEffect } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans } from '@lingui/react/macro';
import { useLingui } from '@lingui/react/macro';
import { DocumentVisibility, TeamMemberRole } from '@prisma/client';
import { DocumentStatus, type Field, type Recipient, SendStatus } from '@prisma/client';
import { Trans, useLingui } from '@lingui/react/macro';
import {
DocumentStatus,
DocumentVisibility,
type Field,
type Recipient,
SendStatus,
TeamMemberRole,
} from '@prisma/client';
import { InfoIcon } from 'lucide-react';
import { useForm } from 'react-hook-form';
import { match } from 'ts-pattern';