From 2facc0e3318b0aafbf5579fd283779adbdb2b3a6 Mon Sep 17 00:00:00 2001 From: Ephraim Atta-Duncan Date: Wed, 20 Mar 2024 10:17:31 +0000 Subject: [PATCH 1/3] feat: add completed documents per month graph --- ...monthly-completed-documents-chart copy.tsx | 57 +++++++++++++++++++ .../src/app/(marketing)/open/page.tsx | 8 +++ .../user/get-monthly-completed-document.ts | 35 ++++++++++++ .../seed/pr-711-deletion-of-documents.ts | 1 + 4 files changed, 101 insertions(+) create mode 100644 apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart copy.tsx create mode 100644 packages/lib/server-only/user/get-monthly-completed-document.ts diff --git a/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart copy.tsx b/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart copy.tsx new file mode 100644 index 000000000..ce438145b --- /dev/null +++ b/apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart copy.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { DateTime } from 'luxon'; +import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; + +import type { GetUserMonthlyGrowthResult } from '@documenso/lib/server-only/user/get-user-monthly-growth'; +import { cn } from '@documenso/ui/lib/utils'; + +export type MonthlyCompletedDocumentsChartProps = { + className?: string; + data: GetUserMonthlyGrowthResult; +}; + +export const MonthlyCompletedDocumentsChart = ({ + className, + data, +}: MonthlyCompletedDocumentsChartProps) => { + const formattedData = [...data].reverse().map(({ month, cume_count: count }) => { + return { + month: DateTime.fromFormat(month, 'yyyy-MM').toFormat('LLLL'), + count: Number(count), + }; + }); + + return ( +
+
+

Completed Documents per Month

+
+ +
+ + + + + + [Number(value).toLocaleString('en-US'), 'Total Users']} + cursor={{ fill: 'hsl(var(--primary) / 10%)' }} + /> + + + + +
+
+ ); +}; diff --git a/apps/marketing/src/app/(marketing)/open/page.tsx b/apps/marketing/src/app/(marketing)/open/page.tsx index 10ab71aa7..77e36ca78 100644 --- a/apps/marketing/src/app/(marketing)/open/page.tsx +++ b/apps/marketing/src/app/(marketing)/open/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from 'next'; import { z } from 'zod'; +import { getCompletedDocumentsMonthly } from '@documenso/lib/server-only/user/get-monthly-completed-document'; import { getUserMonthlyGrowth } from '@documenso/lib/server-only/user/get-user-monthly-growth'; import { FUNDING_RAISED } from '~/app/(marketing)/open/data'; @@ -12,6 +13,7 @@ import { CallToAction } from '~/components/(marketing)/call-to-action'; import { BarMetric } from './bar-metrics'; import { CapTable } from './cap-table'; import { FundingRaised } from './funding-raised'; +import { MonthlyCompletedDocumentsChart } from './monthly-completed-documents-chart copy'; import { MonthlyNewUsersChart } from './monthly-new-users-chart'; import { MonthlyTotalUsersChart } from './monthly-total-users-chart'; import { TeamMembers } from './team-members'; @@ -140,6 +142,7 @@ export default async function OpenPage() { ]); const MONTHLY_USERS = await getUserMonthlyGrowth(); + const MONTHLY_COMPLETED_DOCUMENTS = await getCompletedDocumentsMonthly(); return (
@@ -240,6 +243,11 @@ export default async function OpenPage() { + +
diff --git a/packages/lib/server-only/user/get-monthly-completed-document.ts b/packages/lib/server-only/user/get-monthly-completed-document.ts new file mode 100644 index 000000000..ef1bcd4b9 --- /dev/null +++ b/packages/lib/server-only/user/get-monthly-completed-document.ts @@ -0,0 +1,35 @@ +import { DateTime } from 'luxon'; + +import { prisma } from '@documenso/prisma'; + +export type GetCompletedDocumentsMonthlyResult = Array<{ + month: string; + count: number; + cume_count: number; +}>; + +type GetCompletedDocumentsMonthlyQueryResult = Array<{ + month: Date; + count: bigint; + cume_count: bigint; +}>; + +export const getCompletedDocumentsMonthly = async () => { + const result = await prisma.$queryRaw` + SELECT + DATE_TRUNC('month', "completedAt") AS "month", + COUNT("id") as "count", + SUM(COUNT("id")) OVER (ORDER BY DATE_TRUNC('month', "completedAt")) as "cume_count" + FROM "Document" + WHERE "status" = 'COMPLETED' + GROUP BY "month" + ORDER BY "month" DESC + LIMIT 12 + `; + + return result.map((row) => ({ + month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'), + count: Number(row.count), + cume_count: Number(row.cume_count), + })); +}; diff --git a/packages/prisma/seed/pr-711-deletion-of-documents.ts b/packages/prisma/seed/pr-711-deletion-of-documents.ts index 5365ecf47..d2706b734 100644 --- a/packages/prisma/seed/pr-711-deletion-of-documents.ts +++ b/packages/prisma/seed/pr-711-deletion-of-documents.ts @@ -182,6 +182,7 @@ const createCompletedDocument = async (sender: User, recipients: User[]) => { title: `[${PULL_REQUEST_NUMBER}] Document 1 - Completed`, status: DocumentStatus.COMPLETED, documentDataId: documentData.id, + completedAt: new Date(), userId: sender.id, }, }); From 48858cfdd00748767852c72c315c2d0c4c5309e4 Mon Sep 17 00:00:00 2001 From: Ephraim Atta-Duncan Date: Wed, 20 Mar 2024 10:31:19 +0000 Subject: [PATCH 2/3] chore: restructure open page --- .../src/app/(marketing)/open/page.tsx | 51 +++++++++++-------- .../src/app/(marketing)/open/team-members.tsx | 2 +- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/apps/marketing/src/app/(marketing)/open/page.tsx b/apps/marketing/src/app/(marketing)/open/page.tsx index 77e36ca78..41f0aceba 100644 --- a/apps/marketing/src/app/(marketing)/open/page.tsx +++ b/apps/marketing/src/app/(marketing)/open/page.tsx @@ -164,7 +164,7 @@ export default async function OpenPage() {

-
+
+
+

Finances

+
+
- - data={EARLY_ADOPTERS_DATA} - metricKey="earlyAdopters" - title="Early Adopters" - label="Early Adopters" - className="col-span-12 lg:col-span-6" - extraInfo={} - /> - +

Community

+
data={STARGAZERS_DATA} metricKey="stars" @@ -240,6 +237,20 @@ export default async function OpenPage() { className="col-span-12 lg:col-span-6" /> + +
+ +

Growth

+
+ + data={EARLY_ADOPTERS_DATA} + metricKey="earlyAdopters" + title="Early Adopters" + label="Early Adopters" + className="col-span-12 lg:col-span-6" + extraInfo={} + /> + @@ -247,20 +258,18 @@ export default async function OpenPage() { data={MONTHLY_COMPLETED_DOCUMENTS} className="col-span-12 lg:col-span-6" /> - - - -
-

Where's the rest?

- -

- We're still working on getting all our metrics together. We'll update this page as - soon as we have more to share. -

-
+
+

Where's the rest?

+ +

+ We're still working on getting all our metrics together. We'll update this page as soon as + we have more to share. +

+
+
); diff --git a/apps/marketing/src/app/(marketing)/open/team-members.tsx b/apps/marketing/src/app/(marketing)/open/team-members.tsx index a79fcd182..288d48a0b 100644 --- a/apps/marketing/src/app/(marketing)/open/team-members.tsx +++ b/apps/marketing/src/app/(marketing)/open/team-members.tsx @@ -1,4 +1,4 @@ -import { HTMLAttributes } from 'react'; +import type { HTMLAttributes } from 'react'; import { cn } from '@documenso/ui/lib/utils'; import { From 574cd176c20ac43d5366581f6972bfc44c1442ce Mon Sep 17 00:00:00 2001 From: Timur Ercan Date: Wed, 20 Mar 2024 12:34:03 +0100 Subject: [PATCH 3/3] chore: update copy to have more swag --- apps/marketing/src/app/(marketing)/open/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/marketing/src/app/(marketing)/open/page.tsx b/apps/marketing/src/app/(marketing)/open/page.tsx index 41f0aceba..4f2b0d857 100644 --- a/apps/marketing/src/app/(marketing)/open/page.tsx +++ b/apps/marketing/src/app/(marketing)/open/page.tsx @@ -262,10 +262,10 @@ export default async function OpenPage() {
-

Where's the rest?

+

Is there more?

- We're still working on getting all our metrics together. We'll update this page as soon as + This page is evolving as we learn what makes a great signing company. We'll update it when we have more to share.