diff --git a/apps/web/src/app/(private)/_data-access/index.ts b/apps/web/src/app/(private)/_data-access/index.ts index f290fb664..d3157c9c7 100644 --- a/apps/web/src/app/(private)/_data-access/index.ts +++ b/apps/web/src/app/(private)/_data-access/index.ts @@ -28,7 +28,8 @@ export const getFirstProjectCached = cache( export const getActiveProjectsCached = cache( async ({ workspaceId }: { workspaceId: number }) => { const projectsScope = new ProjectsRepository(workspaceId) - const result = await projectsScope.findAllActive() + const result = + await projectsScope.findAllActiveDocumentsWithAgreggatedData() const projects = result.unwrap() return projects diff --git a/apps/web/src/app/(private)/dashboard/_components/ProjectsTable.tsx b/apps/web/src/app/(private)/dashboard/_components/ProjectsTable/index.tsx similarity index 73% rename from apps/web/src/app/(private)/dashboard/_components/ProjectsTable.tsx rename to apps/web/src/app/(private)/dashboard/_components/ProjectsTable/index.tsx index 223f7b6c1..c27128ab6 100644 --- a/apps/web/src/app/(private)/dashboard/_components/ProjectsTable.tsx +++ b/apps/web/src/app/(private)/dashboard/_components/ProjectsTable/index.tsx @@ -1,6 +1,6 @@ 'use client' -import { DocumentVersion, Project } from '@latitude-data/core/browser' +import { Project } from '@latitude-data/core/browser' import { Icon, Table, @@ -16,18 +16,16 @@ import { relativeTime } from '$/lib/relativeTime' import { ROUTES } from '$/services/routes' import Link from 'next/link' -import { getDocumentsFromMergedCommitsCache } from '../../_data-access' - +type ProjectWithAgreggatedData = Project & { + documentCount: number + lastCreatedAtDocument: Date | null +} export function ProjectsTable({ - documents, projects, }: { - documents: Awaited> - projects: Project[] + projects: ProjectWithAgreggatedData[] }) { const navigate = useNavigate() - const findDocuments = (projectId: number) => - documents.filter((d) => d.projectId === projectId) return ( @@ -54,17 +52,12 @@ export function ProjectsTable({ - {findDocuments(project.id).length || '-'} + {project.documentCount || '-'} - {relativeTime( - findDocuments(project.id).sort( - (a: DocumentVersion, b: DocumentVersion) => - b.createdAt.getTime() - a.createdAt.getTime(), - )?.[0]?.createdAt, - )} + {relativeTime(project.lastCreatedAtDocument)} diff --git a/apps/web/src/app/(private)/dashboard/layout.tsx b/apps/web/src/app/(private)/dashboard/layout.tsx index 7b4408cfb..fcad431ea 100644 --- a/apps/web/src/app/(private)/dashboard/layout.tsx +++ b/apps/web/src/app/(private)/dashboard/layout.tsx @@ -14,10 +14,7 @@ import { ROUTES } from '$/services/routes' import Link from 'next/link' import { redirect } from 'next/navigation' -import { - getActiveProjectsCached, - getDocumentsFromMergedCommitsCache, -} from '../_data-access' +import { getActiveProjectsCached } from '../_data-access' import { NAV_LINKS } from '../_lib/constants' import { ProjectsTable } from './_components/ProjectsTable' @@ -31,7 +28,6 @@ export default async function DashboardLayout({ const { workspace, user } = await getCurrentUser() const projects = await getActiveProjectsCached({ workspaceId: workspace.id }) - const documents = await getDocumentsFromMergedCommitsCache(workspace.id) const breadcrumbs = [ { name: {workspace.name}, @@ -59,9 +55,7 @@ export default async function DashboardLayout({ } table={ <> - {projects.length > 0 && ( - - )} + {projects.length > 0 && } {projects.length === 0 && ( { return Result.ok(result) } + + async findAllActiveDocumentsWithAgreggatedData() { + const lastMergedCommit = this.db.$with('lastMergedCommit').as( + this.db + .select({ + projectId: commits.projectId, + maxVersion: max(commits.version).as('maxVersion'), + }) + .from(commits) + .where(isNotNull(commits.mergedAt)) + .groupBy(commits.projectId), + ) + const aggredatedData = this.db.$with('aggredatedData').as( + this.db + .with(lastMergedCommit) + .select({ + id: this.scope.id, + documentCount: count(documentVersions.id).as('documentCount'), + lastCreatedAtDocument: max(documentVersions.createdAt).as( + 'lastCreatedAtDocument', + ), + }) + .from(this.scope) + .innerJoin(commits, eq(commits.projectId, this.scope.id)) + .innerJoin( + lastMergedCommit, + and( + eq(lastMergedCommit.projectId, this.scope.id), + eq(commits.version, lastMergedCommit.maxVersion), + ), + ) + .innerJoin(documentVersions, eq(documentVersions.commitId, commits.id)) + .where(isNull(this.scope.deletedAt)) + .groupBy(this.scope.id), + ) + + const result = await this.db + .with(aggredatedData) + .select({ + ...this.scope._.selectedFields, + documentCount: aggredatedData.documentCount, + lastCreatedAtDocument: aggredatedData.lastCreatedAtDocument, + }) + .from(this.scope) + .innerJoin(aggredatedData, eq(aggredatedData.id, this.scope.id)) + + return Result.ok(result) + } }