fix: adjusted pageInfo

This commit is contained in:
Wyatt Johnson
2018-07-11 14:24:51 -06:00
parent 5118d5ae58
commit bfede26ddd
3 changed files with 116 additions and 56 deletions
@@ -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
}
+50 -54
View File
@@ -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;
}
+54 -2
View File
@@ -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),
}));
}