mirror of
https://github.com/wassname/talk.git
synced 2026-07-12 01:07:03 +08:00
fix: adjusted pageInfo
This commit is contained in:
@@ -233,8 +233,20 @@ type PageInfo {
|
||||
Indicates that there are more nodes after this subset.
|
||||
"""
|
||||
hasNextPage: Boolean
|
||||
|
||||
"""
|
||||
Included for legacy Relay reasons. Always set to false.
|
||||
"""
|
||||
hasPreviousPage: Boolean
|
||||
|
||||
"""
|
||||
Included for legacy Relay reasons. Always set to null.
|
||||
"""
|
||||
startCursor: Cursor
|
||||
|
||||
"""
|
||||
Specifies the last node's cursor for forwards pagination.
|
||||
"""
|
||||
endCursor: Cursor
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,15 @@ import { merge } from "lodash";
|
||||
import { Db } from "mongodb";
|
||||
import { Omit, Sub } from "talk-common/types";
|
||||
import { ActionCounts } from "talk-server/models/actions";
|
||||
import { Connection, Cursor } from "talk-server/models/connection";
|
||||
import {
|
||||
Connection,
|
||||
Cursor,
|
||||
Edge,
|
||||
getPageInfo,
|
||||
nodesToEdges,
|
||||
NodeToCursorTransformer,
|
||||
PageInfo,
|
||||
} from "talk-server/models/connection";
|
||||
import Query from "talk-server/models/query";
|
||||
import { TenantResource } from "talk-server/models/tenant";
|
||||
import uuid from "uuid";
|
||||
@@ -134,31 +142,18 @@ export interface ConnectionInput {
|
||||
after?: Cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* nodesToEdge converts a set of nodes and configuration options into a set of
|
||||
* edges.
|
||||
*
|
||||
* @param input connection configuration
|
||||
* @param nodes nodes returned from the query
|
||||
*/
|
||||
function nodesToEdge(input: ConnectionInput, nodes: Comment[]) {
|
||||
let getCursor: (comment: Comment, index: number) => Cursor;
|
||||
function cursorGetterFactory(
|
||||
input: ConnectionInput
|
||||
): NodeToCursorTransformer<Comment> {
|
||||
switch (input.orderBy) {
|
||||
case CommentSort.CREATED_AT_DESC:
|
||||
case CommentSort.CREATED_AT_ASC:
|
||||
getCursor = comment => comment.created_at;
|
||||
break;
|
||||
return comment => comment.created_at;
|
||||
case CommentSort.REPLIES_DESC:
|
||||
case CommentSort.RESPECT_DESC:
|
||||
getCursor = (_, index) =>
|
||||
return (_, index) =>
|
||||
(input.after ? (input.after as number) : 0) + index + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return nodes.map((comment, index) => ({
|
||||
node: comment,
|
||||
cursor: getCursor(comment, index),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,8 +218,43 @@ export async function retrieveAssetConnection(
|
||||
async function retrieveConnection(
|
||||
input: ConnectionInput,
|
||||
query: Query<Comment>
|
||||
) {
|
||||
): Promise<Readonly<Connection<Readonly<Comment>>>> {
|
||||
// Apply some sorting options.
|
||||
applyInputToQuery(input, query);
|
||||
|
||||
// We load one more than the limit so we can determine if there is
|
||||
// another page of entries. This gets trimmed off below after we've checked to
|
||||
// see if this constitutes another page of edges.
|
||||
query.first(input.first + 1);
|
||||
|
||||
// Get the cursor.
|
||||
const cursor = await query.exec();
|
||||
|
||||
// Get the comments from the cursor.
|
||||
const nodes = await cursor.toArray();
|
||||
|
||||
// Convert the nodes to edges (which will include the extra edge we don't need
|
||||
// if there is more results).
|
||||
const edges = nodesToEdges(nodes, cursorGetterFactory(input));
|
||||
|
||||
// Get the pageInfo for the connection. We will use this to also determine if
|
||||
// we need to trim off the extra edge that we requested by comparing its
|
||||
// hasNextPage parameter.
|
||||
const pageInfo = getPageInfo(input, edges);
|
||||
if (pageInfo.hasNextPage) {
|
||||
// Because this means that we got one more than expected, we should trim off
|
||||
// the extra edge that was retrieved.
|
||||
edges.splice(input.first, 1);
|
||||
}
|
||||
|
||||
// Return the connection.
|
||||
return {
|
||||
edges,
|
||||
pageInfo,
|
||||
};
|
||||
}
|
||||
|
||||
function applyInputToQuery(input: ConnectionInput, query: Query<Comment>) {
|
||||
switch (input.orderBy) {
|
||||
case CommentSort.CREATED_AT_DESC:
|
||||
query.orderBy({ created_at: -1 });
|
||||
@@ -251,38 +281,4 @@ async function retrieveConnection(
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// We load one more than the limit so we can determine if there is
|
||||
// another page of entries.
|
||||
query.first(input.first + 1);
|
||||
|
||||
// Get the cursor.
|
||||
const cursor = await query.exec();
|
||||
|
||||
// Get the comments from the cursor.
|
||||
const nodes = await cursor.toArray();
|
||||
|
||||
// The hasNextPage is always handled the same (ask for one more than we need,
|
||||
// if there is one more, than there is more).
|
||||
let hasNextPage = false;
|
||||
if (input.first >= 0 && nodes.length > input.first) {
|
||||
// There was one more than we expected! Set hasNextPage = true and remove
|
||||
// the last item from the array that we requested.
|
||||
hasNextPage = true;
|
||||
nodes.splice(input.first, 1);
|
||||
}
|
||||
|
||||
// Convert the nodes to edges.
|
||||
const edges = nodesToEdge(input, nodes);
|
||||
|
||||
// Return the connection.
|
||||
const connection: Readonly<Connection<Readonly<Comment>>> = {
|
||||
edges,
|
||||
pageInfo: {
|
||||
hasNextPage,
|
||||
endCursor: (nodes.length && nodes[nodes.length - 1].created_at) || null,
|
||||
},
|
||||
};
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,63 @@ export interface Edge<T> {
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
hasNextPage: boolean;
|
||||
endCursor: Cursor;
|
||||
hasNextPage?: boolean;
|
||||
hasPreviousPage?: boolean;
|
||||
startCursor?: Cursor;
|
||||
endCursor?: Cursor;
|
||||
}
|
||||
|
||||
export interface Connection<T> {
|
||||
edges: Array<Edge<T>>;
|
||||
pageInfo: PageInfo;
|
||||
}
|
||||
|
||||
export interface PaginationArgs {
|
||||
first: number;
|
||||
}
|
||||
|
||||
export function getPageInfo<T>(args: PaginationArgs, edges: Array<Edge<T>>) {
|
||||
const pageInfo: PageInfo = {
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
startCursor: null,
|
||||
endCursor: null,
|
||||
};
|
||||
|
||||
if (edges.length === 0) {
|
||||
// If there are no edges, then there's nothing to paginate!
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
// The hasNextPage is always handled the same (ask for one more than we need,
|
||||
// if there is one more, than there is more).
|
||||
if (args.first >= 0 && edges.length > args.first) {
|
||||
// There was one more than we expected! Set hasNextPage = true.
|
||||
pageInfo.hasNextPage = true;
|
||||
}
|
||||
|
||||
if (pageInfo.hasNextPage && edges.length > 1) {
|
||||
// There was more than one expected, and there is two entries in the edges
|
||||
// array. We should grab the second last one because the last one will have
|
||||
// to be trimmed off after.
|
||||
pageInfo.endCursor = edges[edges.length - 2].cursor;
|
||||
} else {
|
||||
// There was not more than expected, so we should just grab the last edge to
|
||||
// get the endCursor.
|
||||
pageInfo.endCursor = edges[edges.length - 1].cursor;
|
||||
}
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
export type NodeToCursorTransformer<T> = (node: T, index: number) => Cursor;
|
||||
|
||||
export function nodesToEdges<T>(
|
||||
nodes: T[],
|
||||
transformer: NodeToCursorTransformer<T>
|
||||
): Array<Edge<T>> {
|
||||
return nodes.map((node, index) => ({
|
||||
node,
|
||||
cursor: transformer(node, index),
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user