Skip to content

Commit

Permalink
feat: Mentor Review - Sort by date (#2519)
Browse files Browse the repository at this point in the history
* feat(mentor-review): sort by submitted and reviewed date

* chore: rename file

* fix: sort order
  • Loading branch information
nataliagulko authored Jul 25, 2024
1 parent c957ad5 commit 5e03769
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 48 deletions.
60 changes: 33 additions & 27 deletions client/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3396,19 +3396,13 @@ export interface InviteMentorsDto {
* @type {Array<string>}
* @memberof InviteMentorsDto
*/
'preselectedCourses': Array<string>;
'disciplines': Array<string>;
/**
*
* @type {boolean}
* @memberof InviteMentorsDto
*/
'certificate': boolean;
/**
*
* @type {boolean}
* @memberof InviteMentorsDto
*/
'mentor': boolean;
'isMentor': boolean;
/**
*
* @type {string}
Expand Down Expand Up @@ -13389,21 +13383,19 @@ export const MentorReviewsApiAxiosParamCreator = function (configuration?: Confi
*
* @param {string} current
* @param {string} pageSize
* @param {string} tasks
* @param {string} student
* @param {number} courseId
* @param {string} [tasks]
* @param {string} [student]
* @param {string} [sortField]
* @param {string} [sortOrder]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMentorReviews: async (current: string, pageSize: string, tasks: string, student: string, courseId: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
getMentorReviews: async (current: string, pageSize: string, courseId: number, tasks?: string, student?: string, sortField?: string, sortOrder?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'current' is not null or undefined
assertParamExists('getMentorReviews', 'current', current)
// verify required parameter 'pageSize' is not null or undefined
assertParamExists('getMentorReviews', 'pageSize', pageSize)
// verify required parameter 'tasks' is not null or undefined
assertParamExists('getMentorReviews', 'tasks', tasks)
// verify required parameter 'student' is not null or undefined
assertParamExists('getMentorReviews', 'student', student)
// verify required parameter 'courseId' is not null or undefined
assertParamExists('getMentorReviews', 'courseId', courseId)
const localVarPath = `/course/{courseId}/mentor-reviews`
Expand Down Expand Up @@ -13435,6 +13427,14 @@ export const MentorReviewsApiAxiosParamCreator = function (configuration?: Confi
localVarQueryParameter['student'] = student;
}

if (sortField !== undefined) {
localVarQueryParameter['sortField'] = sortField;
}

if (sortOrder !== undefined) {
localVarQueryParameter['sortOrder'] = sortOrder;
}



setSearchParams(localVarUrlObj, localVarQueryParameter);
Expand All @@ -13460,14 +13460,16 @@ export const MentorReviewsApiFp = function(configuration?: Configuration) {
*
* @param {string} current
* @param {string} pageSize
* @param {string} tasks
* @param {string} student
* @param {number} courseId
* @param {string} [tasks]
* @param {string} [student]
* @param {string} [sortField]
* @param {string} [sortOrder]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getMentorReviews(current: string, pageSize: string, tasks: string, student: string, courseId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MentorReviewsDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMentorReviews(current, pageSize, tasks, student, courseId, options);
async getMentorReviews(current: string, pageSize: string, courseId: number, tasks?: string, student?: string, sortField?: string, sortOrder?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<MentorReviewsDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMentorReviews(current, pageSize, courseId, tasks, student, sortField, sortOrder, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
}
Expand All @@ -13484,14 +13486,16 @@ export const MentorReviewsApiFactory = function (configuration?: Configuration,
*
* @param {string} current
* @param {string} pageSize
* @param {string} tasks
* @param {string} student
* @param {number} courseId
* @param {string} [tasks]
* @param {string} [student]
* @param {string} [sortField]
* @param {string} [sortOrder]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMentorReviews(current: string, pageSize: string, tasks: string, student: string, courseId: number, options?: any): AxiosPromise<MentorReviewsDto> {
return localVarFp.getMentorReviews(current, pageSize, tasks, student, courseId, options).then((request) => request(axios, basePath));
getMentorReviews(current: string, pageSize: string, courseId: number, tasks?: string, student?: string, sortField?: string, sortOrder?: string, options?: any): AxiosPromise<MentorReviewsDto> {
return localVarFp.getMentorReviews(current, pageSize, courseId, tasks, student, sortField, sortOrder, options).then((request) => request(axios, basePath));
},
};
};
Expand All @@ -13507,15 +13511,17 @@ export class MentorReviewsApi extends BaseAPI {
*
* @param {string} current
* @param {string} pageSize
* @param {string} tasks
* @param {string} student
* @param {number} courseId
* @param {string} [tasks]
* @param {string} [student]
* @param {string} [sortField]
* @param {string} [sortOrder]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof MentorReviewsApi
*/
public getMentorReviews(current: string, pageSize: string, tasks: string, student: string, courseId: number, options?: AxiosRequestConfig) {
return MentorReviewsApiFp(this.configuration).getMentorReviews(current, pageSize, tasks, student, courseId, options).then((request) => request(this.axios, this.basePath));
public getMentorReviews(current: string, pageSize: string, courseId: number, tasks?: string, student?: string, sortField?: string, sortOrder?: string, options?: AxiosRequestConfig) {
return MentorReviewsApiFp(this.configuration).getMentorReviews(current, pageSize, courseId, tasks, student, sortField, sortOrder, options).then((request) => request(this.axios, this.basePath));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const getColumns = (tasks: CourseTaskDto[]): ColumnsType<MentorReviewDto>
title: ColumnName.SubmittedDate,
dataIndex: ColumnKey.SubmittedDate,
width: '15%',
sorter: true,
render: (_v, review) => dateTimeRenderer(review.submittedAt),
},
{
Expand All @@ -75,6 +76,7 @@ export const getColumns = (tasks: CourseTaskDto[]): ColumnsType<MentorReviewDto>
title: ColumnName.ReviewedDate,
dataIndex: ColumnKey.ReviewedDate,
width: '15%',
sorter: true,
render: (_v, review) => dateTimeRenderer(review.reviewedAt),
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const sortDirectionMap = {
ascend: 'ASC',
descend: 'DESC',
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import type { PageProps } from './getServerSideProps';
import MentorReviewsTable from '../components/ReviewsTable';
import { FilterValue } from 'antd/es/table/interface';
import { ColumnKey } from '../components/ReviewsTable/renderers';
import { SorterResult } from 'antd/lib/table/interface';
import { sortDirectionMap } from './MentorTasksReview.constants';

const { Text } = Typography;

Expand All @@ -30,14 +32,24 @@ export const MentorTasksReview = ({ tasks }: PageProps) => {
const [loading, withLoading] = useLoading(false);

const getMentorReviews = withLoading(
async (pagination: TablePaginationConfig, filters?: Record<ColumnKey, FilterValue | null>) => {
async (
pagination: TablePaginationConfig,
filters?: Record<ColumnKey, FilterValue | null>,
sorter?: SorterResult<MentorReviewDto> | SorterResult<MentorReviewDto>[],
) => {
const sortValues =
sorter && !Array.isArray(sorter) && sorter.order
? [sorter.field?.toString(), sortDirectionMap[sorter.order]]
: [undefined, undefined];

try {
const { data } = await mentorReviewsApi.getMentorReviews(
String(pagination.current),
String(pagination.pageSize),
filters?.taskName ? filters.taskName.toString() : '',
filters?.student ? filters.student.toString() : '',
course.id,
filters?.taskName?.toString(),
filters?.student?.toString(),
...sortValues,
);
setReviews({ ...reviews, ...data });
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/course/admin/mentor-tasks-review.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ActiveCourseProvider, SessionProvider } from 'modules/Course/contexts';
import { MentorTasksReview } from 'modules/MetorTasksReview/pages/MentorTasksReview';
import { getServerSideProps, PageProps } from 'modules/MetorTasksReview/pages/getServerSideProps';
import { MentorTasksReview } from 'modules/MentorTasksReview/pages/MentorTasksReview';
import { getServerSideProps, PageProps } from 'modules/MentorTasksReview/pages/getServerSideProps';
import { CourseRole } from 'services/models';

export { getServerSideProps };
Expand Down
16 changes: 13 additions & 3 deletions nestjs/src/courses/mentor-reviews/dto/mentor-reviews-query.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApiProperty } from '@nestjs/swagger';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';

export class MentorReviewsQueryDto {
Expand All @@ -10,13 +10,23 @@ export class MentorReviewsQueryDto {
@IsString()
public pageSize: string;

@ApiProperty()
@ApiPropertyOptional()
@IsString()
@IsOptional()
public tasks: string;

@ApiProperty()
@ApiPropertyOptional()
@IsString()
@IsOptional()
public student: string;

@ApiPropertyOptional()
@IsString()
@IsOptional()
public sortField: string;

@ApiPropertyOptional()
@IsString()
@IsOptional()
public sortOrder: 'ASC' | 'DESC';
}
12 changes: 10 additions & 2 deletions nestjs/src/courses/mentor-reviews/mentor-reviews.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@ export class MentorReviewsController {
public async getScore(@Query() query: MentorReviewsQueryDto, @Param('courseId', ParseIntPipe) courseId: number) {
const page = parseInt(query.current);
const limit = parseInt(query.pageSize);
const { student, tasks } = query;
const mentorReviews = await this.mentorReviewsService.getMentorReviews(courseId, page, limit, tasks, student);
const { student, tasks, sortField, sortOrder } = query;
const mentorReviews = await this.mentorReviewsService.getMentorReviews(
courseId,
page,
limit,
tasks,
student,
sortField,
sortOrder,
);

return new MentorReviewsDto(mentorReviews);
}
Expand Down
41 changes: 36 additions & 5 deletions nestjs/src/courses/mentor-reviews/mentor-reviews.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,19 @@ export class MentorReviewsService {
readonly taskSolutionRepository: Repository<TaskSolution>,
) {}

private buildMentorReviewsQuery({ courseId, tasks, student }: { courseId: number; tasks: string; student: string }) {
private buildMentorReviewsQuery({
courseId,
tasks,
student,
sortField,
sortOrder,
}: {
courseId: number;
tasks?: string;
student?: string;
sortField?: string;
sortOrder?: 'ASC' | 'DESC';
}) {
const query = this.taskSolutionRepository
.createQueryBuilder('taskSolution')
.innerJoin('taskSolution.courseTask', 'courseTask')
Expand Down Expand Up @@ -60,8 +72,7 @@ export class MentorReviewsService {
'studentMentor.id',
'studentMentorUser.githubId',
'lastChecker.githubId',
])
.addOrderBy('taskSolution.id', 'ASC');
]);

if (tasks) {
const taskIds = tasks.split(',').map(id => parseInt(id));
Expand All @@ -72,11 +83,31 @@ export class MentorReviewsService {
query.andWhere('studentUser.githubId ILIKE :student', { student: `%${student}%` });
}

if (sortField && sortOrder) {
if (sortField === 'submittedAt') {
query.orderBy('taskSolution.createdDate', sortOrder);
}

if (sortField === 'reviewedAt') {
query.orderBy('taskResult.updatedDate', sortOrder);
}
}

query.addOrderBy('taskSolution.id', 'ASC');

return query;
}

public async getMentorReviews(courseId: number, page: number, limit: number, tasks: string, student: string) {
const query = this.buildMentorReviewsQuery({ courseId, tasks, student: student });
public async getMentorReviews(
courseId: number,
page: number,
limit: number,
tasks?: string,
student?: string,
sortField?: string,
sortOrder?: 'ASC' | 'DESC',
) {
const query = this.buildMentorReviewsQuery({ courseId, tasks, student: student, sortField, sortOrder });
const data = await paginate(query, { page, limit });

return data;
Expand Down
13 changes: 7 additions & 6 deletions nestjs/src/spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1487,8 +1487,10 @@
"parameters": [
{ "name": "current", "required": true, "in": "query", "schema": { "type": "string" } },
{ "name": "pageSize", "required": true, "in": "query", "schema": { "type": "string" } },
{ "name": "tasks", "required": true, "in": "query", "schema": { "type": "string" } },
{ "name": "student", "required": true, "in": "query", "schema": { "type": "string" } },
{ "name": "tasks", "required": false, "in": "query", "schema": { "type": "string" } },
{ "name": "student", "required": false, "in": "query", "schema": { "type": "string" } },
{ "name": "sortField", "required": false, "in": "query", "schema": { "type": "string" } },
{ "name": "sortOrder", "required": false, "in": "query", "schema": { "type": "string" } },
{ "name": "courseId", "required": true, "in": "path", "schema": { "type": "number" } }
],
"responses": {
Expand Down Expand Up @@ -4445,12 +4447,11 @@
"InviteMentorsDto": {
"type": "object",
"properties": {
"preselectedCourses": { "type": "array", "items": { "type": "string" } },
"certificate": { "type": "boolean" },
"mentor": { "type": "boolean" },
"disciplines": { "type": "array", "items": { "type": "string" } },
"isMentor": { "type": "boolean" },
"text": { "type": "string" }
},
"required": ["preselectedCourses", "certificate", "mentor", "text"]
"required": ["disciplines", "isMentor", "text"]
},
"SaveCertificateDto": {
"type": "object",
Expand Down

0 comments on commit 5e03769

Please sign in to comment.