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

feat: migrate get cross check feedback #2249

Merged
merged 10 commits into from
Aug 8, 2023
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
221 changes: 221 additions & 0 deletions client/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,108 @@ export const CriteriaDtoTypeEnum = {

export type CriteriaDtoTypeEnum = typeof CriteriaDtoTypeEnum[keyof typeof CriteriaDtoTypeEnum];

/**
*
* @export
* @interface CrossCheckAuthorDto
*/
export interface CrossCheckAuthorDto {
/**
*
* @type {number}
* @memberof CrossCheckAuthorDto
*/
'id': number;
/**
*
* @type {string}
* @memberof CrossCheckAuthorDto
*/
'name': string;
/**
*
* @type {string}
* @memberof CrossCheckAuthorDto
*/
'githubId': string;
/**
*
* @type {Discord}
* @memberof CrossCheckAuthorDto
*/
'discord': Discord | null;
}
/**
*
* @export
* @interface CrossCheckCriteriaDataDto
*/
export interface CrossCheckCriteriaDataDto {
/**
*
* @type {string}
* @memberof CrossCheckCriteriaDataDto
*/
'key': string;
/**
*
* @type {number}
* @memberof CrossCheckCriteriaDataDto
*/
'max'?: number;
/**
*
* @type {string}
* @memberof CrossCheckCriteriaDataDto
*/
'text': string;
/**
*
* @type {string}
* @memberof CrossCheckCriteriaDataDto
*/
'type': CrossCheckCriteriaDataDtoTypeEnum;
/**
*
* @type {number}
* @memberof CrossCheckCriteriaDataDto
*/
'point'?: number;
/**
*
* @type {string}
* @memberof CrossCheckCriteriaDataDto
*/
'textComment'?: string;
}

export const CrossCheckCriteriaDataDtoTypeEnum = {
Title: 'title',
Subtask: 'subtask',
Penalty: 'penalty'
} as const;

export type CrossCheckCriteriaDataDtoTypeEnum = typeof CrossCheckCriteriaDataDtoTypeEnum[keyof typeof CrossCheckCriteriaDataDtoTypeEnum];

/**
*
* @export
* @interface CrossCheckFeedbackDto
*/
export interface CrossCheckFeedbackDto {
/**
*
* @type {string}
* @memberof CrossCheckFeedbackDto
*/
'url'?: string;
/**
*
* @type {Array<CrossCheckSolutionReviewDto>}
* @memberof CrossCheckFeedbackDto
*/
'reviews'?: Array<CrossCheckSolutionReviewDto>;
}
/**
*
* @export
Expand Down Expand Up @@ -2230,6 +2332,55 @@ export interface CrossCheckPairResponseDto {
*/
'pagination': PaginationDto;
}
/**
*
* @export
* @interface CrossCheckSolutionReviewDto
*/
export interface CrossCheckSolutionReviewDto {
/**
*
* @type {number}
* @memberof CrossCheckSolutionReviewDto
*/
'id': number;
/**
*
* @type {number}
* @memberof CrossCheckSolutionReviewDto
*/
'dateTime': number;
/**
*
* @type {string}
* @memberof CrossCheckSolutionReviewDto
*/
'comment': string;
/**
*
* @type {Array<CrossCheckCriteriaDataDto>}
* @memberof CrossCheckSolutionReviewDto
*/
'criteria'?: Array<CrossCheckCriteriaDataDto>;
/**
*
* @type {CrossCheckAuthorDto}
* @memberof CrossCheckSolutionReviewDto
*/
'author': CrossCheckAuthorDto | null;
/**
*
* @type {number}
* @memberof CrossCheckSolutionReviewDto
*/
'score': number;
/**
*
* @type {Array<CrossCheckMessageDto>}
* @memberof CrossCheckSolutionReviewDto
*/
'messages': Array<CrossCheckMessageDto>;
}
/**
*
* @export
Expand Down Expand Up @@ -9445,6 +9596,43 @@ export const CoursesTasksApiAxiosParamCreator = function (configuration?: Config



setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @param {number} courseId
* @param {number} courseTaskId
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMyCrossCheckFeedbacks: async (courseId: number, courseTaskId: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'courseId' is not null or undefined
assertParamExists('getMyCrossCheckFeedbacks', 'courseId', courseId)
// verify required parameter 'courseTaskId' is not null or undefined
assertParamExists('getMyCrossCheckFeedbacks', 'courseTaskId', courseTaskId)
const localVarPath = `/courses/{courseId}/cross-checks/{courseTaskId}/myFeedbacks`
.replace(`{${"courseId"}}`, encodeURIComponent(String(courseId)))
.replace(`{${"courseTaskId"}}`, encodeURIComponent(String(courseTaskId)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;



setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
Expand Down Expand Up @@ -9646,6 +9834,17 @@ export const CoursesTasksApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.getCrossCheckPairs(courseId, pageSize, current, orderBy, orderDirection, checker, student, url, task, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @param {number} courseId
* @param {number} courseTaskId
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<CrossCheckFeedbackDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMyCrossCheckFeedbacks(courseId, courseTaskId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @param {CheckTasksDeadlineDto} checkTasksDeadlineDto
Expand Down Expand Up @@ -9773,6 +9972,16 @@ export const CoursesTasksApiFactory = function (configuration?: Configuration, b
getCrossCheckPairs(courseId: number, pageSize: number, current: number, orderBy?: string, orderDirection?: string, checker?: string, student?: string, url?: string, task?: string, options?: any): AxiosPromise<CrossCheckPairResponseDto> {
return localVarFp.getCrossCheckPairs(courseId, pageSize, current, orderBy, orderDirection, checker, student, url, task, options).then((request) => request(axios, basePath));
},
/**
*
* @param {number} courseId
* @param {number} courseTaskId
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number, options?: any): AxiosPromise<CrossCheckFeedbackDto> {
return localVarFp.getMyCrossCheckFeedbacks(courseId, courseTaskId, options).then((request) => request(axios, basePath));
},
/**
*
* @param {CheckTasksDeadlineDto} checkTasksDeadlineDto
Expand Down Expand Up @@ -9916,6 +10125,18 @@ export class CoursesTasksApi extends BaseAPI {
return CoursesTasksApiFp(this.configuration).getCrossCheckPairs(courseId, pageSize, current, orderBy, orderDirection, checker, student, url, task, options).then((request) => request(this.axios, this.basePath));
}

/**
*
* @param {number} courseId
* @param {number} courseTaskId
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof CoursesTasksApi
*/
public getMyCrossCheckFeedbacks(courseId: number, courseTaskId: number, options?: AxiosRequestConfig) {
return CoursesTasksApiFp(this.configuration).getMyCrossCheckFeedbacks(courseId, courseTaskId, options).then((request) => request(this.axios, this.basePath));
}

/**
*
* @param {CheckTasksDeadlineDto} checkTasksDeadlineDto
Expand Down
18 changes: 6 additions & 12 deletions client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,11 @@ import { NoSubmissionAvailable } from 'modules/Course/components/NoSubmissionAva
import { useRouter } from 'next/router';
import { useEffect, useMemo, useState } from 'react';
import { useAsync } from 'react-use';
import {
CourseService,
CrossCheckComment,
CrossCheckCriteria,
CrossCheckReview,
Feedback,
TaskSolution,
} from 'services/course';
import { CourseService, CrossCheckComment, CrossCheckCriteria, CrossCheckReview, TaskSolution } from 'services/course';
import { CoursePageProps } from 'services/models';
import { urlWithIpPattern } from 'services/validators';
import { getQueryString } from 'utils/queryParams-utils';
import { CrossCheckMessageDtoRoleEnum } from 'api';
import { CoursesTasksApi, CrossCheckFeedbackDto, CrossCheckMessageDtoRoleEnum } from 'api';

const colSizes = { xs: 24, sm: 18, md: 12, lg: 10 };

Expand All @@ -46,8 +39,9 @@ const createUrlRule = (): Rule => {
export function CrossCheckSubmit(props: CoursePageProps) {
const [form] = Form.useForm();
const courseService = useMemo(() => new CourseService(props.course.id), [props.course.id]);
const teamDistributionApi = useMemo(() => new CoursesTasksApi(), []);
const solutionReviewSettings = useSolutionReviewSettings();
const [feedback, setFeedback] = useState<Feedback | null>(null);
const [feedback, setFeedback] = useState<CrossCheckFeedbackDto | null>(null);
const [submittedSolution, setSubmittedSolution] = useState(null as TaskSolution | null);
const router = useRouter();
const queryTaskId = router.query.taskId ? +router.query.taskId : null;
Expand Down Expand Up @@ -139,8 +133,8 @@ export function CrossCheckSubmit(props: CoursePageProps) {
return;
}

const [feedback, submittedSolution, taskDetails] = await Promise.all([
courseService.getCrossCheckFeedback(props.session.githubId, courseTask.id),
const [{ data: feedback }, submittedSolution, taskDetails] = await Promise.all([
teamDistributionApi.getMyCrossCheckFeedbacks(props.course.id, courseTask.id),
courseService.getCrossCheckTaskSolution(props.session.githubId, courseTask.id).catch(() => null),
courseService.getCrossCheckTaskDetails(courseTask.id),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isEqual } from 'lodash';
import { SubtaskCriteria } from './criteria/SubtaskCriteria';
import { TitleCriteria } from './criteria/TitleCriteria';
import { PenaltyCriteria } from './criteria/PenaltyCriteria';
import { CrossCheckCriteriaData, SolutionReviewType } from 'services/course';
import { CrossCheckCriteriaDataDto, CrossCheckSolutionReviewDto } from 'api';

const { Text, Title } = Typography;

Expand All @@ -18,9 +18,9 @@ export interface CriteriaFormProps {
maxScore: number | undefined;
score: number;
setScore: (value: number) => void;
criteriaData: CrossCheckCriteriaData[];
setCriteriaData: (newData: CrossCheckCriteriaData[]) => void;
initialData: SolutionReviewType;
criteriaData: CrossCheckCriteriaDataDto[];
setCriteriaData: (newData: CrossCheckCriteriaDataDto[]) => void;
initialData: CrossCheckSolutionReviewDto;
setIsSkipped: (value: boolean) => void;
isSkipped: boolean;
}
Expand All @@ -39,7 +39,7 @@ export function CrossCheckCriteriaForm({

const maxScoreValue = maxScore ?? 100;
const maxScoreLabel = maxScoreValue ? ` (Max ${maxScoreValue} points)` : '';
const penaltyData: CrossCheckCriteriaData[] =
const penaltyData: CrossCheckCriteriaDataDto[] =
criteriaData?.filter(item => item.type.toLowerCase() === TaskType.Penalty) ?? [];

useEffect(() => {
Expand All @@ -57,7 +57,7 @@ export function CrossCheckCriteriaForm({
}
}, [criteriaData, initialData]);

function updateCriteriaData(updatedEntry: CrossCheckCriteriaData) {
function updateCriteriaData(updatedEntry: CrossCheckCriteriaDataDto) {
const index = criteriaData.findIndex(item => item.key === updatedEntry.key);
const updatedData = [...criteriaData];
updatedData.splice(index, 1, updatedEntry);
Expand Down Expand Up @@ -112,10 +112,10 @@ export function CrossCheckCriteriaForm({
<Title level={4}>Criteria</Title>
{criteriaData
?.filter(
(item: CrossCheckCriteriaData) =>
(item: CrossCheckCriteriaDataDto) =>
item.type.toLowerCase() === TaskType.Title || item.type.toLowerCase() === TaskType.Subtask,
)
.map((item: CrossCheckCriteriaData) => {
.map((item: CrossCheckCriteriaDataDto) => {
return item.type.toLowerCase() === TaskType.Title ? (
<TitleCriteria key={item.key} titleData={item} />
) : (
Expand All @@ -127,7 +127,7 @@ export function CrossCheckCriteriaForm({
{!!penaltyData?.length && (
<>
<Title level={4}>Penalty</Title>
{penaltyData?.map((item: CrossCheckCriteriaData) => (
{penaltyData?.map((item: CrossCheckCriteriaDataDto) => (
<PenaltyCriteria key={item.key} penaltyData={item} updateCriteriaData={updateCriteriaData} />
))}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Dispatch, SetStateAction } from 'react';
import { ClockCircleOutlined, EditFilled, EditOutlined } from '@ant-design/icons';
import { Button, Col, notification, Row, Spin, Tag, Timeline, Typography } from 'antd';
import { SolutionReviewType } from 'services/course';
import { useSolutionReviewSettings } from 'modules/CrossCheck/hooks';
import { markdownLabel } from 'components/Forms/PreparedComment';
import { SolutionReview } from 'modules/CrossCheck/components/SolutionReview';
import { SolutionReviewSettingsPanel } from 'modules/CrossCheck/components/SolutionReviewSettingsPanel';
import { CrossCheckMessageDtoRoleEnum } from 'api';
import { CrossCheckMessageDtoRoleEnum, CrossCheckSolutionReviewDto } from 'api';

type CrossCheckHistoryState = {
loading: boolean;
data: SolutionReviewType[];
data: CrossCheckSolutionReviewDto[];
};

type Props = {
Expand Down
Loading
Loading