feat: paginate and merge frequent activities (#274)
* feat: paginate and merge frequent activities * feat: due date activities * fix: requested changes fixes * refactor: slight reshuffle and improve types * chore: translations --------- Co-authored-by: Henry <henry_ball@hotmail.co.uk>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { and, asc, desc, eq, gt, inArray, isNull, sql } from "drizzle-orm";
|
||||
import { and, asc, desc, eq, gt, inArray, isNull, lt, sql } from "drizzle-orm";
|
||||
|
||||
import type { dbClient } from "@kan/db/client";
|
||||
import {
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
cardToWorkspaceMembers,
|
||||
checklistItems,
|
||||
checklists,
|
||||
comments,
|
||||
labels,
|
||||
lists,
|
||||
workspaceMembers,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { and, asc, eq, gt, inArray, isNull, or } from "drizzle-orm";
|
||||
|
||||
import type { dbClient } from "@kan/db/client";
|
||||
import type { ActivityType } from "@kan/db/schema";
|
||||
import { cardActivities } from "@kan/db/schema";
|
||||
import { cardActivities, comments } from "@kan/db/schema";
|
||||
import { generateUID } from "@kan/shared/utils";
|
||||
|
||||
export const create = async (
|
||||
@@ -89,3 +91,114 @@ export const bulkCreate = async (
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
export const getPaginatedActivities = async (
|
||||
db: dbClient,
|
||||
cardId: number,
|
||||
options?: {
|
||||
limit?: number;
|
||||
cursor?: Date; // createdAt cursor for pagination
|
||||
},
|
||||
) => {
|
||||
const limit = options?.limit ?? 20;
|
||||
const cursor = options?.cursor;
|
||||
|
||||
const validComments = await db
|
||||
.select({ id: comments.id })
|
||||
.from(comments)
|
||||
.where(and(eq(comments.cardId, cardId), isNull(comments.deletedAt)));
|
||||
|
||||
const validCommentIds = validComments.map((comment) => comment.id);
|
||||
|
||||
const activities = await db.query.cardActivities.findMany({
|
||||
columns: {
|
||||
publicId: true,
|
||||
type: true,
|
||||
createdAt: true,
|
||||
fromIndex: true,
|
||||
toIndex: true,
|
||||
fromTitle: true,
|
||||
toTitle: true,
|
||||
fromDescription: true,
|
||||
toDescription: true,
|
||||
fromDueDate: true,
|
||||
toDueDate: true,
|
||||
},
|
||||
where: and(
|
||||
eq(cardActivities.cardId, cardId),
|
||||
cursor ? gt(cardActivities.createdAt, cursor) : undefined,
|
||||
or(
|
||||
isNull(cardActivities.commentId),
|
||||
inArray(cardActivities.commentId, validCommentIds),
|
||||
),
|
||||
),
|
||||
with: {
|
||||
fromList: {
|
||||
columns: {
|
||||
publicId: true,
|
||||
name: true,
|
||||
index: true,
|
||||
},
|
||||
},
|
||||
toList: {
|
||||
columns: {
|
||||
publicId: true,
|
||||
name: true,
|
||||
index: true,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
columns: {
|
||||
publicId: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
member: {
|
||||
columns: {
|
||||
publicId: true,
|
||||
},
|
||||
with: {
|
||||
user: {
|
||||
columns: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
columns: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
comment: {
|
||||
columns: {
|
||||
publicId: true,
|
||||
comment: true,
|
||||
createdBy: true,
|
||||
updatedAt: true,
|
||||
deletedAt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: asc(cardActivities.createdAt), // required for merging and pagination
|
||||
limit: limit + 1, // fetch one extra to check if there are more
|
||||
});
|
||||
|
||||
const hasMore = activities.length > limit;
|
||||
const items = activities.slice(0, limit);
|
||||
const nextCursor = hasMore ? items[items.length - 1]?.createdAt : undefined;
|
||||
|
||||
return {
|
||||
activities: items,
|
||||
hasMore,
|
||||
nextCursor,
|
||||
};
|
||||
};
|
||||
|
||||
export type PaginatedActivitiesResult = Awaited<
|
||||
ReturnType<typeof getPaginatedActivities>
|
||||
>;
|
||||
|
||||
Reference in New Issue
Block a user