Skip to content

Commit

Permalink
#26 Add new default sort option when getting users to be sorted by th…
Browse files Browse the repository at this point in the history
…e number of quizzes they have completed with the current authenticated user
  • Loading branch information
danielemery committed Oct 21, 2023
1 parent 120c89e commit e1c385d
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 11 deletions.
11 changes: 10 additions & 1 deletion src/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ const typeDefs = gql`
QUESTION_AND_ANSWER
}
enum UserSortOption {
EMAIL_ASC
NAME_ASC
NUMBER_OF_QUIZZES_COMPLETED_WITH_DESC
}
type PageInfo {
hasNextPage: Boolean
startCursor: String
Expand Down Expand Up @@ -133,7 +139,10 @@ const typeDefs = gql`
filters: QuizFilters
): QuizConnection
quiz(id: String!): QuizDetails
users(first: Int, after: String): UserConnection
"""
Get a paged list of users.
"""
users(first: Int, after: String, sortedBy: UserSortOption): UserConnection
me: UserDetails
}
Expand Down
2 changes: 2 additions & 0 deletions src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ export interface CreateQuizResult {
link: string;
}[];
}

export type UserSortOption = 'EMAIL_ASC' | 'NAME_ASC' | 'NUMBER_OF_QUIZZES_COMPLETED_WITH_DESC';
63 changes: 55 additions & 8 deletions src/persistence/persistence.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PrismaClient, Quiz as QuizPersistence, QuizImage as QuizImagePersistence, Role } from '@prisma/client';
import { PrismaClient, Quiz as QuizPersistence, QuizImage as QuizImagePersistence, Role, User } from '@prisma/client';
import { types } from 'pg';
import { v4 as uuidv4 } from 'uuid';
import { QuizFilters } from '../models';
import { QuizFilters, UserSortOption } from '../models';

export interface PersistenceResult<T> {
data: T[];
Expand Down Expand Up @@ -256,8 +256,20 @@ class Persistence {
return roles.map((r) => r.role);
}

async getUsersWithRole({ role, afterId, limit }: { role: Role; afterId?: string; limit: number }) {
const result = await this.getPrismaClient().user.findMany({
async getUsersWithRole({
role,
afterId,
limit,
sortedBy,
currentUserId,
}: {
role: Role;
afterId?: string;
limit: number;
sortedBy: UserSortOption;
currentUserId: string;
}) {
const pagedWhereQuery = {
...getPagedQuery(limit, afterId),
where: {
roles: {
Expand All @@ -266,10 +278,45 @@ class Persistence {
},
},
},
orderBy: {
email: 'asc',
},
});
};

let result;
switch (sortedBy) {
case 'EMAIL_ASC':
result = await this.getPrismaClient().user.findMany({
...pagedWhereQuery,
orderBy: {
email: 'asc',
},
});
break;
case 'NAME_ASC':
result = await this.getPrismaClient().user.findMany({
...pagedWhereQuery,
orderBy: {
name: 'asc',
},
});
break;
case 'NUMBER_OF_QUIZZES_COMPLETED_WITH_DESC':
default:
/**
* Prisma does not yet support ordering by a relation with anything other than count.
* We need to do something quite a bit more complex.
*/
result = (await this.getPrismaClient().$queryRaw`
select id, email, name from
(
select "user".*, count(quiz_completion.id) as completions from "user"
left outer join quiz_completion_user as their_completion on "user".id = their_completion.user_id
left outer join quiz_completion on their_completion.quiz_completion_id = quiz_completion.id
left outer join quiz_completion_user as my_completion on my_completion.quiz_completion_id = quiz_completion.id and my_completion.user_id = ${currentUserId}
group by "user".id
) as completions_with_current_user
order by completions_with_current_user.completions desc;
`) as User[];
break;
}

return slicePagedResults(result, limit, afterId !== undefined);
}
Expand Down
10 changes: 8 additions & 2 deletions src/resolvers/userResolvers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { User as UserPersistence } from '@prisma/client';

import { QuizlordContext } from '..';
import { User, UserDetails } from '../models';
import { User, UserDetails, UserSortOption } from '../models';
import { persistence } from '../persistence/persistence';
import { base64Decode, base64Encode, PagedResult, requireUserRole } from './helpers';

Expand All @@ -14,7 +14,11 @@ function userPersistenceToUser(user: UserPersistence): User {

export async function users(
_: unknown,
{ first = 100, after }: { first: number; after?: string },
{
first = 100,
after,
sortedBy = 'NUMBER_OF_QUIZZES_COMPLETED_WITH_DESC',
}: { first: number; after?: string; sortedBy: UserSortOption },
context: QuizlordContext,
): Promise<PagedResult<User>> {
requireUserRole(context, 'USER');
Expand All @@ -23,6 +27,8 @@ export async function users(
role: 'USER',
afterId,
limit: first,
sortedBy,
currentUserId: context.userId,
});
const edges = data.map((user) => ({
node: userPersistenceToUser(user),
Expand Down

0 comments on commit e1c385d

Please sign in to comment.