refactor: changed the findTasksByTaskPhase to include task info like remark, etc
This commit is contained in:
@@ -49,26 +49,21 @@ export class TaskRepository extends Repository<TMTask> {
|
||||
.getOne();
|
||||
}
|
||||
|
||||
async findTasksByTaskPhase(
|
||||
taskPhaseId: string,
|
||||
pagination: CursorPaginationDto,
|
||||
): Promise<{ items: TMTask[]; hasMore: boolean }> {
|
||||
async findTasksByTaskPhase(taskPhaseId: string, pagination: CursorPaginationDto): Promise<{ items: TMTask[]; hasMore: boolean }> {
|
||||
const limit = pagination.limit || 10;
|
||||
const isBackward = pagination.direction === CursorDirection.PREV;
|
||||
|
||||
// truncated to milliseconds because a JS Date (and therefore the encoded cursor) only
|
||||
// has millisecond precision, while Postgres timestamptz stores microseconds - comparing
|
||||
// the raw column against the cursor would otherwise re-match the boundary row itself.
|
||||
const createdAtExpr = `date_trunc('milliseconds', task.createdAt)`;
|
||||
|
||||
const queryBuilder = this.createQueryBuilder("task")
|
||||
const seekQuery = this.createQueryBuilder("task")
|
||||
.select(["task.id", "task.priority", "task.createdAt"])
|
||||
.where("task.taskPhaseId = :taskPhaseId", { taskPhaseId })
|
||||
.limit(limit + 1); // fetch one extra to check whether there's a further page
|
||||
|
||||
if (isBackward) {
|
||||
queryBuilder.orderBy("task.priority", "ASC").addOrderBy(createdAtExpr, "DESC").addOrderBy("task.id", "DESC");
|
||||
seekQuery.orderBy("task.priority", "ASC").addOrderBy(createdAtExpr, "DESC").addOrderBy("task.id", "DESC");
|
||||
} else {
|
||||
queryBuilder.orderBy("task.priority", "DESC").addOrderBy(createdAtExpr, "ASC").addOrderBy("task.id", "ASC");
|
||||
seekQuery.orderBy("task.priority", "DESC").addOrderBy(createdAtExpr, "ASC").addOrderBy("task.id", "ASC");
|
||||
}
|
||||
|
||||
if (pagination.cursor) {
|
||||
@@ -76,7 +71,7 @@ export class TaskRepository extends Repository<TMTask> {
|
||||
const priorityOp = isBackward ? ">" : "<";
|
||||
const seekOp = isBackward ? "<" : ">";
|
||||
|
||||
queryBuilder.andWhere(
|
||||
seekQuery.andWhere(
|
||||
`(task.priority ${priorityOp} :cursorPriority
|
||||
OR (task.priority = :cursorPriority AND ${createdAtExpr} ${seekOp} :cursorCreatedAt)
|
||||
OR (task.priority = :cursorPriority AND ${createdAtExpr} = :cursorCreatedAt AND task.id ${seekOp} :cursorId))`,
|
||||
@@ -84,13 +79,32 @@ export class TaskRepository extends Repository<TMTask> {
|
||||
);
|
||||
}
|
||||
|
||||
const rows = await queryBuilder.getMany();
|
||||
const hasMore = rows.length > limit;
|
||||
if (hasMore) rows.pop();
|
||||
const seekRows = await seekQuery.getMany();
|
||||
const hasMore = seekRows.length > limit;
|
||||
if (hasMore) seekRows.pop();
|
||||
|
||||
// backward queries fetch in reverse order to seek from the cursor, so flip back to
|
||||
// the normal display order before returning
|
||||
const items = isBackward ? rows.reverse() : rows;
|
||||
const orderedRows = isBackward ? seekRows.reverse() : seekRows;
|
||||
const ids = orderedRows.map((row) => row.id);
|
||||
|
||||
if (!ids.length) return { items: [], hasMore };
|
||||
|
||||
// Detail query: hydrates exactly the ids picked above with the relations/counts the
|
||||
// response needs. IN (:...ids) doesn't preserve order, so re-order to match seekQuery.
|
||||
const detailRows = await this.createQueryBuilder("task")
|
||||
.leftJoinAndSelect("task.remarks", "remark")
|
||||
.loadRelationCountAndMap("task.attachmentCount", "task.attachments")
|
||||
.loadRelationCountAndMap("task.checkListItemCount", "task.checkListItems")
|
||||
.loadRelationCountAndMap("task.completedCheckListItemCount", "task.checkListItems", "completedCheckListItems", (qb) =>
|
||||
qb.where("completedCheckListItems.isDone = :isDone", { isDone: true }),
|
||||
)
|
||||
.select(["task", "remark.id", "remark.title", "remark.color"])
|
||||
.where("task.id IN (:...ids)", { ids })
|
||||
.getMany();
|
||||
|
||||
const detailById = new Map(detailRows.map((task) => [task.id, task]));
|
||||
const items = ids.map((id) => detailById.get(id)).filter((task): task is TMTask => task !== undefined);
|
||||
|
||||
return { items, hasMore };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user