Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagination to branch list page #98

Merged
merged 3 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions graphql-server/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ type Branch {
"""
scalar Timestamp

type BranchNamesList {
type BranchList {
nextOffset: Int
list: [Branch!]!
}

Expand Down Expand Up @@ -282,7 +283,8 @@ type TagList {
type Query {
branch(databaseName: String!, branchName: String!): Branch
branchOrDefault(databaseName: String!, branchName: String): Branch
branches(databaseName: String!, sortBy: SortBranchesBy): BranchNamesList!
branches(offset: Int, databaseName: String!, sortBy: SortBranchesBy): BranchList!
allBranches(offset: Int, databaseName: String!, sortBy: SortBranchesBy): [Branch!]!
defaultBranch(databaseName: String!): Branch
commits(offset: Int, databaseName: String!, refName: String, afterCommitId: String, twoDot: Boolean, excludingCommitsFromRefName: String): CommitList!
currentDatabase: String
Expand Down
3 changes: 2 additions & 1 deletion graphql-server/src/branches/branch.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Field, GraphQLTimestamp, ID, ObjectType } from "@nestjs/graphql";
import { RawRow } from "../queryFactory/types";
import * as table from "../tables/table.model";
import { convertToUTCDate } from "../utils";
import { ListOffsetRes } from "../utils/commonTypes";

@ObjectType()
export class Branch {
Expand Down Expand Up @@ -31,7 +32,7 @@ export class Branch {
}

@ObjectType()
export class BranchNamesList {
export class BranchList extends ListOffsetRes {
@Field(_type => [Branch])
list: Branch[];
}
Expand Down
37 changes: 28 additions & 9 deletions graphql-server/src/branches/branch.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
Resolver,
} from "@nestjs/graphql";
import { ConnectionResolver } from "../connections/connection.resolver";
import { RawRow } from "../queryFactory/types";
import { Table } from "../tables/table.model";
import { TableResolver } from "../tables/table.resolver";
import { BranchArgs, DBArgs } from "../utils/commonTypes";
import { ROW_LIMIT, getNextOffset } from "../utils";
import { BranchArgs, DBArgs, DBArgsWithOffset } from "../utils/commonTypes";
import { SortBranchesBy } from "./branch.enum";
import { Branch, BranchNamesList, fromDoltBranchesRow } from "./branch.model";
import { Branch, BranchList, fromDoltBranchesRow } from "./branch.model";

@ArgsType()
export class GetBranchOrDefaultArgs extends DBArgs {
Expand Down Expand Up @@ -43,7 +45,7 @@ export class CreateBranchArgs extends DBArgs {
}

@ArgsType()
class ListBranchesArgs extends DBArgs {
class ListBranchesArgs extends DBArgsWithOffset {
@Field(_type => SortBranchesBy, { nullable: true })
sortBy?: SortBranchesBy;
}
Expand Down Expand Up @@ -75,13 +77,18 @@ export class BranchResolver {
return branch;
}

@Query(_returns => BranchNamesList)
async branches(@Args() args: ListBranchesArgs): Promise<BranchNamesList> {
@Query(_returns => BranchList)
async branches(@Args() args: ListBranchesArgs): Promise<BranchList> {
const conn = this.conn.connection();
const res = await conn.getBranches(args);
return {
list: res.map(b => fromDoltBranchesRow(args.databaseName, b)),
};
const res = await conn.getBranches({ ...args, offset: args.offset ?? 0 });
return fromBranchListRes(res, args);
}

@Query(_returns => [Branch])
async allBranches(@Args() args: ListBranchesArgs): Promise<Branch[]> {
const conn = this.conn.connection();
const res = await conn.getAllBranches(args);
return res.map(b => fromDoltBranchesRow(args.databaseName, b));
}

@Query(_returns => Branch, { nullable: true })
Expand Down Expand Up @@ -162,3 +169,15 @@ export function getDefaultBranchFromBranchesList(

return options[0];
}

function fromBranchListRes(
branches: RawRow[],
args: ListBranchesArgs,
): BranchList {
return {
list: branches
.slice(0, ROW_LIMIT)
.map(b => fromDoltBranchesRow(args.databaseName, b)),
nextOffset: getNextOffset(branches.length, args.offset ?? 0),
};
}
31 changes: 25 additions & 6 deletions graphql-server/src/queryFactory/dolt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,35 @@ export class DoltQueryFactory
);
}

async getBranches(args: t.DBArgs & { sortBy?: SortBranchesBy }): t.PR {
async getBranches(
args: t.DBArgs & { sortBy?: SortBranchesBy; offset: number },
): t.PR {
return this.queryForBuilder(async em => {
let sel = em.createQueryBuilder().select("*").from("dolt_branches", "");
if (args.sortBy) {
sel = sel.addOrderBy(qh.getOrderByColForBranches(args.sortBy), "DESC");
}
return sel.getRawMany();
const [orderBy, dir] = qh.getOrderByColForBranches(args.sortBy);
return em
.createQueryBuilder()
.select("*")
.from("dolt_branches", "")
.addOrderBy(orderBy, dir)
.limit(ROW_LIMIT + 1)
.offset(args.offset)
.getRawMany();
}, args.databaseName);
}

async getAllBranches(args: t.DBArgs): t.PR {
return this.queryForBuilder(
async em =>
em
.createQueryBuilder()
.select("*")
.from("dolt_branches", "")
.limit(1000)
.getRawMany(),
args.databaseName,
);
}

async createNewBranch(args: t.BranchArgs & { fromRefName: string }): t.PR {
return this.query(
qh.callNewBranch,
Expand Down
8 changes: 5 additions & 3 deletions graphql-server/src/queryFactory/dolt/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ export const callNewBranch = `CALL DOLT_BRANCH(?, ?)`;

export const callDeleteBranch = `CALL DOLT_BRANCH("-D", ?)`;

export function getOrderByColForBranches(sortBy?: SortBranchesBy): string {
export function getOrderByColForBranches(
sortBy?: SortBranchesBy,
): [string, "ASC" | "DESC"] {
switch (sortBy) {
case SortBranchesBy.LastUpdated:
return "latest_commit_date";
return ["latest_commit_date", "DESC"];
default:
return "";
return ["name", "ASC"];
}
}

Expand Down
6 changes: 5 additions & 1 deletion graphql-server/src/queryFactory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ export declare class QueryFactory {

getBranch(args: t.BranchArgs): t.UPR;

getBranches(args: t.DBArgs & { sortBy?: SortBranchesBy }): t.PR;
getBranches(
args: t.DBArgs & { sortBy?: SortBranchesBy; offset: number },
): t.PR;

getAllBranches(args: t.DBArgs): t.PR;

createNewBranch(args: t.BranchArgs & { fromRefName: string }): t.PR;

Expand Down
6 changes: 5 additions & 1 deletion graphql-server/src/queryFactory/mysql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ export class MySQLQueryFactory
];
}

async getBranches(args: t.DBArgs): t.PR {
async getBranches(args: t.DBArgs & { offset: number }): t.PR {
return this.getAllBranches(args);
}

async getAllBranches(args: t.DBArgs): t.PR {
const branch = await this.getBranch({ ...args, branchName: "main" });
return branch ?? [];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function BranchSelectorQuery(props: BranchSelectorForRepoProps) {
<Inner
{...props}
onChangeValue={handleChangeBranch}
branches={data.branches.list}
branches={data.allBranches}
defaultName={props.defaultName ?? defaultBranchName}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function BranchSelectorWithTableQuery(
<Inner
{...props}
onChangeValue={handleChangeBranch}
branches={data.branches.list}
branches={data.allBranches}
defaultName={props.defaultName ?? defaultBranchName}
/>
)}
Expand Down
2 changes: 1 addition & 1 deletion web/components/CustomFormSelect/BranchSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function CustomBranchSelector(props: CustomProps): JSX.Element {
render={data => (
<Inner
{...props}
branches={data.branches.list}
branches={data.allBranches}
defaultName={props.defaultName ?? defaultBranchName}
/>
)}
Expand Down
15 changes: 3 additions & 12 deletions web/components/CustomFormSelect/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ export const branchSelectorMock = (
},
result: {
data: {
branches: {
__typename: "BranchNamesList",
list: empty ? [] : [testBranch(params), mainBranch(params)],
},
allBranches: empty ? [] : [testBranch(params), mainBranch(params)],
},
},
};
Expand All @@ -95,10 +92,7 @@ export const noBranchMock = (params: DatabaseParams): MockedResponse => {
},
result: {
data: {
branches: {
__typename: "BranchNamesList",
list: [],
},
allBranches: [],
},
},
};
Expand All @@ -112,10 +106,7 @@ export const oneBranchMock = (params: DatabaseParams): MockedResponse => {
},
result: {
data: {
branches: {
__typename: "BranchNamesList",
list: [mainBranch(params)],
},
allBranches: [mainBranch(params)],
},
},
};
Expand Down
6 changes: 2 additions & 4 deletions web/components/CustomFormSelect/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ export const BRANCH_SELECTOR_QUERY = gql`
databaseName
}
query BranchesForSelector($databaseName: String!) {
branches(databaseName: $databaseName) {
list {
...BranchForBranchSelector
}
allBranches(databaseName: $databaseName) {
...BranchForBranchSelector
}
}
`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
import { BranchFragment } from "@gen/graphql-types";
import InfiniteScroll from "react-infinite-scroller";
import BranchRow from "./BranchRow";
import css from "./index.module.css";

type Props = {
branches: BranchFragment[];
onDeleteClicked: (b: BranchFragment) => void;
loadMore: () => Promise<void>;
hasMore: boolean;
};

export default function BranchList(props: Props): JSX.Element {
return (
<table className={css.table} data-cy="branch-list">
<thead>
<tr>
<th>Branch name</th>
<th>Last updated by</th>
<th>Last updated</th>
<th aria-hidden="true" />
</tr>
</thead>
<tbody>
{props.branches.map(b => (
<BranchRow
onDeleteClicked={() => props.onDeleteClicked(b)}
key={b._id}
branch={b}
/>
))}
</tbody>
</table>
<InfiniteScroll
// Passing extra props to infinite scroll seems to apply those props to the top level div,
// so we can't spread props here.
loadMore={props.loadMore}
hasMore={props.hasMore}
loader={<div className={css.loader}>Loading branches ...</div>}
useWindow={false}
initialLoad={false}
getScrollParent={() => document.getElementById("main-content")}
>
<table className={css.table} data-cy="branch-list">
<thead>
<tr>
<th>Branch name</th>
<th>Last updated by</th>
<th>Last updated</th>
<th aria-hidden="true" />
</tr>
</thead>
<tbody>
{props.branches.map(b => (
<BranchRow
onDeleteClicked={() => props.onDeleteClicked(b)}
key={b._id}
branch={b}
/>
))}
</tbody>
</table>
</InfiniteScroll>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Props = {

type InnerProps = {
branches: BranchFragment[];
loadMore: () => Promise<void>;
hasMore: boolean;
sortBranches: (sortBy?: SortBranchesBy) => Promise<void>;
sortBy?: SortBranchesBy;
} & Props;
Expand Down Expand Up @@ -119,6 +121,8 @@ export default function BranchesPage({ params }: Props): JSX.Element {
<Inner
params={params}
branches={data}
loadMore={res.loadMore}
hasMore={res.hasMore}
sortBranches={res.sortBranches}
sortBy={res.sortBy}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ export const BRANCHES_FOR_BRANCHES_PAGE_QUERY = gql`
lastUpdated
lastCommitter
}
query BranchList($databaseName: String!, $sortBy: SortBranchesBy) {
branches(databaseName: $databaseName, sortBy: $sortBy) {
query BranchList(
$databaseName: String!
$sortBy: SortBranchesBy
$offset: Int
) {
branches(databaseName: $databaseName, sortBy: $sortBy, offset: $offset) {
list {
...Branch
}
nextOffset
}
}
`;
Expand Down
Loading
Loading