diff --git a/client/src/api/api.ts b/client/src/api/api.ts index dc35cbf43..e34b2d312 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -7559,6 +7559,12 @@ export interface Validations { * @memberof Validations */ 'githubIdInUrl': boolean; + /** + * + * @type {boolean} + * @memberof Validations + */ + 'githubPrInUrl': boolean; } /** * diff --git a/client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx b/client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx index 353d8404e..9fc0ac519 100644 --- a/client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx +++ b/client/src/modules/Course/pages/Student/CrossCheckSubmit/index.tsx @@ -13,7 +13,7 @@ import { useRouter } from 'next/router'; import { useEffect, useMemo, useState, useContext } from 'react'; import { useAsync } from 'react-use'; import { CourseService, CrossCheckComment, CrossCheckCriteria, CrossCheckReview, TaskSolution } from 'services/course'; -import { privateRsRepoPattern, urlWithIpPattern } from 'services/validators'; +import { githubPrUrl, privateRsRepoPattern, urlWithIpPattern } from 'services/validators'; import { getQueryString } from 'utils/queryParams-utils'; import { CoursesTasksApi, CrossCheckFeedbackDto, CrossCheckMessageDtoRoleEnum } from 'api'; import { SessionContext, useActiveCourseContext } from 'modules/Course/contexts'; @@ -34,6 +34,12 @@ const validUrlRule: Rule = { message: 'Please provide a valid link (must start with `http://` or `https://`)', }; +const githubPrInUrlRule: Rule = { + required: true, + pattern: githubPrUrl, + message: 'Link should be a valid GitHub Pull Request URL', +}; + const notPrivateRsRepoRule: Rule = { validator: (_, value) => { if (privateRsRepoPattern.test(value)) { @@ -199,6 +205,7 @@ export function CrossCheckSubmit() { validUrlRule, notPrivateRsRepoRule, ...(task.validations?.githubIdInUrl ? [createGithubInUrlRule(session.githubId)] : []), + ...(task.validations?.githubPrInUrl ? [githubPrInUrlRule] : []), ]} > diff --git a/client/src/modules/CourseManagement/components/CourseTaskModal/index.tsx b/client/src/modules/CourseManagement/components/CourseTaskModal/index.tsx index 25ee95dc0..49dad6772 100644 --- a/client/src/modules/CourseManagement/components/CourseTaskModal/index.tsx +++ b/client/src/modules/CourseManagement/components/CourseTaskModal/index.tsx @@ -219,6 +219,9 @@ export function CourseTaskModal(props: Props) { Require Github Username in URL + + Require Github Pull Request in URL + ) : null} diff --git a/nestjs/src/courses/course-tasks/dto/course-task.dto.ts b/nestjs/src/courses/course-tasks/dto/course-task.dto.ts index 132f45b76..3a56b841c 100644 --- a/nestjs/src/courses/course-tasks/dto/course-task.dto.ts +++ b/nestjs/src/courses/course-tasks/dto/course-task.dto.ts @@ -8,6 +8,8 @@ import { TaskSolutionDto } from 'src/courses/task-solutions/dto'; class Validations { @ApiProperty() [CourseTaskValidation.githubIdInUrl]: boolean; + @ApiProperty() + [CourseTaskValidation.githubPrInUrl]: boolean; } @ApiResponse({}) diff --git a/nestjs/src/spec.json b/nestjs/src/spec.json index 6d7229f0d..58b847359 100644 --- a/nestjs/src/spec.json +++ b/nestjs/src/spec.json @@ -3070,8 +3070,8 @@ }, "Validations": { "type": "object", - "properties": { "githubIdInUrl": { "type": "boolean" } }, - "required": ["githubIdInUrl"] + "properties": { "githubIdInUrl": { "type": "boolean" }, "githubPrInUrl": { "type": "boolean" } }, + "required": ["githubIdInUrl", "githubPrInUrl"] }, "CourseTaskDto": { "type": "object", diff --git a/server/src/models/courseTask.ts b/server/src/models/courseTask.ts index 6e7ec315c..e3293df0f 100644 --- a/server/src/models/courseTask.ts +++ b/server/src/models/courseTask.ts @@ -33,6 +33,7 @@ export enum CrossCheckStatus { export enum CourseTaskValidation { githubIdInUrl = 'githubIdInUrl', + githubPrInUrl = 'githubPrInUrl', } @Entity()