diff --git a/client/src/api/api.ts b/client/src/api/api.ts
index 2b6b422d14..b37c6dc4e7 100644
--- a/client/src/api/api.ts
+++ b/client/src/api/api.ts
@@ -1054,6 +1054,12 @@ export interface CourseDto {
* @memberof CourseDto
*/
'certificateThreshold': number;
+ /**
+ *
+ * @type {string}
+ * @memberof CourseDto
+ */
+ 'wearecommunityUrl': string | null;
}
/**
*
@@ -1882,7 +1888,13 @@ export interface CreateCourseDto {
* @type {string}
* @memberof CreateCourseDto
*/
- 'description': string;
+ 'description'?: string;
+ /**
+ *
+ * @type {string}
+ * @memberof CreateCourseDto
+ */
+ 'descriptionUrl'?: string;
/**
*
* @type {number}
@@ -1931,6 +1943,12 @@ export interface CreateCourseDto {
* @memberof CreateCourseDto
*/
'certificateThreshold': number;
+ /**
+ *
+ * @type {string}
+ * @memberof CreateCourseDto
+ */
+ 'wearecommunityUrl': string;
}
/**
*
@@ -4812,6 +4830,12 @@ export interface ProfileCourseDto {
* @memberof ProfileCourseDto
*/
'certificateThreshold': number;
+ /**
+ *
+ * @type {string}
+ * @memberof ProfileCourseDto
+ */
+ 'wearecommunityUrl': string | null;
}
/**
*
@@ -6609,6 +6633,12 @@ export interface UpdateCourseDto {
* @memberof UpdateCourseDto
*/
'certificateThreshold': number;
+ /**
+ *
+ * @type {string}
+ * @memberof UpdateCourseDto
+ */
+ 'wearecommunityUrl'?: string | null;
}
/**
*
diff --git a/client/src/modules/CourseManagement/components/CourseModal/index.tsx b/client/src/modules/CourseManagement/components/CourseModal/index.tsx
index 5b1e1645aa..25f163d50d 100644
--- a/client/src/modules/CourseManagement/components/CourseModal/index.tsx
+++ b/client/src/modules/CourseManagement/components/CourseModal/index.tsx
@@ -7,8 +7,9 @@ import utc from 'dayjs/plugin/utc';
import { Course } from 'services/models';
dayjs.extend(utc);
-const courseApi = new CoursesApi();
+const wearecommunityRegex = new RegExp('^(https?://)?(www\\.)?wearecommunity\\.io.*$');
+const courseApi = new CoursesApi();
const courseIcons = Object.entries(DEFAULT_COURSE_ICONS).map(([key, config]) => ({ ...config, id: key }));
type CourseModalProps = {
@@ -47,6 +48,7 @@ type FormData = {
certificateIssuer?: string;
discipline?: { id: number } | null;
courseId?: number;
+ wearecommunityUrl?: string;
};
export function CourseModal(props: CourseModalProps) {
@@ -290,6 +292,18 @@ export function CourseModal(props: CourseModalProps) {
+
+
+
+
+
+
+
+
Use Private Repositories
@@ -328,6 +342,7 @@ function createRecord(values: FormData) {
logo: values.logo,
minStudentsPerMentor: values.minStudentsPerMentor,
certificateThreshold: values.certificateThreshold,
+ wearecommunityUrl: values.wearecommunityUrl,
};
return record;
}
@@ -335,6 +350,7 @@ function createRecord(values: FormData) {
function getInitialValues(modalData: Partial): FormData {
return {
...modalData,
+ wearecommunityUrl: modalData.wearecommunityUrl ?? undefined,
minStudentsPerMentor: modalData.minStudentsPerMentor || 2,
certificateThreshold: modalData.certificateThreshold ?? 70,
inviteOnly: !!modalData.inviteOnly,
diff --git a/client/src/modules/Opportunities/components/PublicLink/index.test.tsx b/client/src/modules/Opportunities/components/PublicLink/index.test.tsx
index 64d30c4203..af97da04f8 100644
--- a/client/src/modules/Opportunities/components/PublicLink/index.test.tsx
+++ b/client/src/modules/Opportunities/components/PublicLink/index.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import { fireEvent, render, screen } from '@testing-library/react';
import { PublicLink } from './index';
const mockUrl = 'https://expample.com';
@@ -40,11 +40,9 @@ describe('PublicLink', () => {
fireEvent.click(copyBtn);
- await waitFor(() => {
- expect(mockCopyToClipboard).toHaveBeenCalledWith(mockUrl);
- });
-
- const notification = screen.getByText('Copied to clipboard');
+ const notification = await screen.findByText('Copied to clipboard');
expect(notification).toBeInTheDocument();
+
+ expect(mockCopyToClipboard).toHaveBeenCalledWith(mockUrl);
});
});
diff --git a/nestjs/src/courses/dto/course.dto.ts b/nestjs/src/courses/dto/course.dto.ts
index 056777069e..7fb305e624 100644
--- a/nestjs/src/courses/dto/course.dto.ts
+++ b/nestjs/src/courses/dto/course.dto.ts
@@ -27,6 +27,7 @@ export class CourseDto {
this.discipline = course.discipline ? { id: course.discipline.id, name: course.discipline.name } : null;
this.minStudentsPerMentor = course.minStudentsPerMentor;
this.certificateThreshold = course.certificateThreshold;
+ this.wearecommunityUrl = course.wearecommunityUrl;
}
@ApiProperty()
@@ -106,4 +107,7 @@ export class CourseDto {
@ApiProperty()
certificateThreshold: number;
+
+ @ApiProperty({ nullable: true, type: String })
+ wearecommunityUrl: string | null;
}
diff --git a/nestjs/src/courses/dto/create-course.dto.ts b/nestjs/src/courses/dto/create-course.dto.ts
index 5bc4479f12..5cd255e826 100644
--- a/nestjs/src/courses/dto/create-course.dto.ts
+++ b/nestjs/src/courses/dto/create-course.dto.ts
@@ -90,4 +90,9 @@ export class CreateCourseDto {
@IsNumber()
@ApiProperty({ required: true })
certificateThreshold: number;
+
+ @IsString()
+ @IsOptional()
+ @ApiProperty()
+ wearecommunityUrl?: string;
}
diff --git a/nestjs/src/courses/dto/export-course.dto.ts b/nestjs/src/courses/dto/export-course.dto.ts
index 5235a3b96e..21db47458c 100644
--- a/nestjs/src/courses/dto/export-course.dto.ts
+++ b/nestjs/src/courses/dto/export-course.dto.ts
@@ -12,6 +12,7 @@ export class ExportCourseDto {
this.description = course.description;
this.descriptionUrl = course.descriptionUrl;
this.registrationEndDate = course.registrationEndDate?.toISOString() ?? null;
+ this.wearecommunityUrl = course.wearecommunityUrl || null;
}
id: number;
@@ -24,4 +25,5 @@ export class ExportCourseDto {
registrationEndDate: string | null;
startDate: string;
endDate: string;
+ wearecommunityUrl: string | null;
}
diff --git a/nestjs/src/courses/dto/update-course.dto.ts b/nestjs/src/courses/dto/update-course.dto.ts
index 973c06cba6..50473881ee 100644
--- a/nestjs/src/courses/dto/update-course.dto.ts
+++ b/nestjs/src/courses/dto/update-course.dto.ts
@@ -100,4 +100,9 @@ export class UpdateCourseDto {
@IsNumber()
@ApiProperty({ required: true })
certificateThreshold: number;
+
+ @IsString()
+ @IsOptional()
+ @ApiPropertyOptional({ nullable: true, type: 'string' })
+ wearecommunityUrl?: string | null;
}
diff --git a/nestjs/src/spec.json b/nestjs/src/spec.json
index 2dc6a95394..e257ef85f9 100644
--- a/nestjs/src/spec.json
+++ b/nestjs/src/spec.json
@@ -662,12 +662,12 @@
"/courses/{courseId}/interviews/{interviewId}/register": {
"post": {
"operationId": "registerToInterview",
- "summary": "",
"parameters": [
{ "name": "courseId", "required": true, "in": "path", "schema": { "type": "number" } },
{ "name": "interviewId", "required": true, "in": "path", "schema": { "type": "number" } }
],
"responses": { "200": { "description": "" }, "400": { "description": "" }, "403": { "description": "" } },
+ "summary": "",
"tags": ["courses interviews"]
}
},
@@ -2685,7 +2685,6 @@
"/contributors": {
"post": {
"operationId": "createContributor",
- "summary": "",
"parameters": [],
"requestBody": {
"required": true,
@@ -2697,11 +2696,11 @@
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContributorDto" } } }
}
},
+ "summary": "",
"tags": ["contributors"]
},
"get": {
"operationId": "getContributors",
- "summary": "",
"parameters": [],
"responses": {
"200": {
@@ -2713,13 +2712,13 @@
}
}
},
+ "summary": "",
"tags": ["contributors"]
}
},
"/contributors/{id}": {
"get": {
"operationId": "getContributor",
- "summary": "",
"parameters": [{ "name": "id", "required": true, "in": "path", "schema": { "type": "number" } }],
"responses": {
"200": {
@@ -2727,18 +2726,18 @@
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContributorDto" } } }
}
},
+ "summary": "",
"tags": ["contributors"]
},
"delete": {
"operationId": "deleteContributor",
- "summary": "",
"parameters": [{ "name": "id", "required": true, "in": "path", "schema": { "type": "number" } }],
"responses": { "200": { "description": "" } },
+ "summary": "",
"tags": ["contributors"]
},
"patch": {
"operationId": "updateContributor",
- "summary": "",
"parameters": [{ "name": "id", "required": true, "in": "path", "schema": { "type": "number" } }],
"requestBody": {
"required": true,
@@ -2750,6 +2749,7 @@
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContributorDto" } } }
}
},
+ "summary": "",
"tags": ["contributors"]
}
}
@@ -2943,7 +2943,8 @@
"logo": { "type": "string" },
"discipline": { "nullable": true, "allOf": [{ "$ref": "#/components/schemas/IdNameDto" }] },
"minStudentsPerMentor": { "type": "number" },
- "certificateThreshold": { "type": "number" }
+ "certificateThreshold": { "type": "number" },
+ "wearecommunityUrl": { "type": "string", "nullable": true }
},
"required": [
"id",
@@ -2971,7 +2972,8 @@
"logo",
"discipline",
"minStudentsPerMentor",
- "certificateThreshold"
+ "certificateThreshold",
+ "wearecommunityUrl"
]
},
"CreateCourseDto": {
@@ -2987,6 +2989,7 @@
"planned": { "type": "boolean" },
"inviteOnly": { "type": "boolean" },
"description": { "type": "string" },
+ "descriptionUrl": { "type": "string" },
"disciplineId": { "type": "number" },
"discordServerId": { "type": "number" },
"usePrivateRepositories": { "type": "boolean" },
@@ -2994,9 +2997,10 @@
"personalMentoring": { "type": "boolean" },
"logo": { "type": "string" },
"minStudentsPerMentor": { "type": "number" },
- "certificateThreshold": { "type": "number" }
+ "certificateThreshold": { "type": "number" },
+ "wearecommunityUrl": { "type": "string" }
},
- "required": ["name", "startDate", "endDate", "fullName", "alias", "description", "certificateThreshold"]
+ "required": ["name", "startDate", "endDate", "fullName", "alias", "certificateThreshold", "wearecommunityUrl"]
},
"UpdateCourseDto": {
"type": "object",
@@ -3021,7 +3025,8 @@
"logo": { "type": "string" },
"disciplineId": { "type": "number" },
"minStudentsPerMentor": { "type": "number" },
- "certificateThreshold": { "type": "number" }
+ "certificateThreshold": { "type": "number" },
+ "wearecommunityUrl": { "type": "string", "nullable": true }
},
"required": ["certificateThreshold"]
},
@@ -4441,7 +4446,8 @@
"logo": { "type": "string" },
"discipline": { "nullable": true, "allOf": [{ "$ref": "#/components/schemas/IdNameDto" }] },
"minStudentsPerMentor": { "type": "number" },
- "certificateThreshold": { "type": "number" }
+ "certificateThreshold": { "type": "number" },
+ "wearecommunityUrl": { "type": "string", "nullable": true }
},
"required": [
"id",
@@ -4469,7 +4475,8 @@
"logo",
"discipline",
"minStudentsPerMentor",
- "certificateThreshold"
+ "certificateThreshold",
+ "wearecommunityUrl"
]
},
"UpdateUserDto": {
diff --git a/server/src/migrations/1736458672717-Course.ts b/server/src/migrations/1736458672717-Course.ts
new file mode 100644
index 0000000000..8835f4d2c2
--- /dev/null
+++ b/server/src/migrations/1736458672717-Course.ts
@@ -0,0 +1,13 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class Course1736458672717 implements MigrationInterface {
+ name = 'Course1736458672717';
+
+ public async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`ALTER TABLE "course" ADD "wearecommunityUrl" character varying`);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`ALTER TABLE "course" DROP COLUMN "wearecommunityUrl"`);
+ }
+}
diff --git a/server/src/migrations/index.ts b/server/src/migrations/index.ts
index 47b25e14a0..d163faf6cd 100644
--- a/server/src/migrations/index.ts
+++ b/server/src/migrations/index.ts
@@ -57,6 +57,7 @@ import { Obfuscation1700391857109 } from './1700391857109-Obfuscation';
import { Course1712137476312 } from './1712137476312-Course';
import { CourseTask1730926720293 } from './1730926720293-CourseTask';
import { Contributor1734874453585 } from './1734874453585-Contributor';
+import { Course1736458672717 } from './1736458672717-Course';
export const migrations = [
UserMigration1630340371992,
@@ -118,4 +119,5 @@ export const migrations = [
Course1712137476312,
CourseTask1730926720293,
Contributor1734874453585,
+ Course1736458672717,
];
diff --git a/server/src/models/course.ts b/server/src/models/course.ts
index 378c661ce5..82ced64471 100644
--- a/server/src/models/course.ts
+++ b/server/src/models/course.ts
@@ -111,4 +111,7 @@ export class Course {
@Column({ default: 70 })
certificateThreshold: number;
+
+ @Column({ nullable: true, type: 'varchar' })
+ wearecommunityUrl: string | null;
}
diff --git a/setup/backup-local.sql b/setup/backup-local.sql
index 7a3df1afd1..87c5db9914 100644
--- a/setup/backup-local.sql
+++ b/setup/backup-local.sql
@@ -249,7 +249,8 @@ CREATE TABLE public.course (
logo character varying,
"disciplineId" integer,
"minStudentsPerMentor" integer DEFAULT 2,
- "certificateThreshold" integer DEFAULT 70 NOT NULL
+ "certificateThreshold" integer DEFAULT 70 NOT NULL,
+ "wearecommunityUrl" character varying
);
@@ -2602,10 +2603,10 @@ COPY public.contributor (id, created_date, updated_date, deleted_date, user_id,
-- Data for Name: course; Type: TABLE DATA; Schema: public; Owner: rs_master
--
-COPY public.course (id, "createdDate", "updatedDate", name, year, "primarySkillId", "primarySkillName", "locationName", alias, completed, description, "descriptionUrl", planned, "startDate", "endDate", "fullName", "registrationEndDate", "inviteOnly", "discordServerId", "certificateIssuer", "usePrivateRepositories", "personalMentoring", logo, "disciplineId", "minStudentsPerMentor", "certificateThreshold") FROM stdin;
-11 2019-08-27 07:36:13.565873 2020-03-13 15:39:41.477995 RS 2019 Q3 \N javascript JavaScript \N rs-2019-q3 t RS 2019 Q3 \N f 2019-09-09 07:35:20.981+00 2020-01-31 07:35:20.981+00 Rolling Scopes School 2019 Q3 \N f \N \N t t \N \N 2 70
-13 2019-10-21 08:05:31.068833 2020-04-06 15:14:44.116961 RS 2020 Q1 \N javascript JavaScript \N rs-2020-q1 f Javascript / Frontend Курс.\nВводное занятие - 2 февраля\nОрганизационный вебинар начнется 2 февраля в 12:00 по минскому времени (GMT+3). Мы расскажем о процессе обучения в RS School и выдадим задания для первого этапа обучения.\n\nВебинар будет транслироваться на канале https://www.youtube.com/c/rollingscopesschool.\nРекомендуем подписаться на канал и нажать колокольчик, чтобы не пропустить начало трансляции. \n\nЕсли у вас не будет возможности присоединиться к онлайн-трансляции, не переживайте! \nЗапись вебинара будет размещена на канале в открытом доступе.\n\nОписание тренинга\nОсновной сайт: https://rs.school/js/\n\nПодробная информация о школе: https://docs.rs.school \N f 2020-02-02 09:01:56.398+00 2020-07-31 08:01:56.398+00 Rolling Scopes School 2020 Q1: JavaScript/Front-end 2020-04-15 08:40:46.24+00 f \N \N t t \N \N 2 70
-23 2020-02-25 09:28:08.842897 2021-07-28 20:44:30.259905 TEST COURSE \N javascript JavaScript \N test-course f TEST COURSE \N f 2021-05-31 21:00:00+00 2023-06-30 21:00:00+00 TEST COURSE \N t 2 \N t t \N \N 2 70
+COPY public.course (id, "createdDate", "updatedDate", name, year, "primarySkillId", "primarySkillName", "locationName", alias, completed, description, "descriptionUrl", planned, "startDate", "endDate", "fullName", "registrationEndDate", "inviteOnly", "discordServerId", "certificateIssuer", "usePrivateRepositories", "personalMentoring", logo, "disciplineId", "minStudentsPerMentor", "certificateThreshold", "wearecommunityUrl") FROM stdin;
+11 2019-08-27 07:36:13.565873 2020-03-13 15:39:41.477995 RS 2019 Q3 \N javascript JavaScript \N rs-2019-q3 t RS 2019 Q3 \N f 2019-09-09 07:35:20.981+00 2020-01-31 07:35:20.981+00 Rolling Scopes School 2019 Q3 \N f \N \N t t \N \N 2 70 \N
+13 2019-10-21 08:05:31.068833 2020-04-06 15:14:44.116961 RS 2020 Q1 \N javascript JavaScript \N rs-2020-q1 f Javascript / Frontend Курс.\nВводное занятие - 2 февраля\nОрганизационный вебинар начнется 2 февраля в 12:00 по минскому времени (GMT+3). Мы расскажем о процессе обучения в RS School и выдадим задания для первого этапа обучения.\n\nВебинар будет транслироваться на канале https://www.youtube.com/c/rollingscopesschool.\nРекомендуем подписаться на канал и нажать колокольчик, чтобы не пропустить начало трансляции. \n\nЕсли у вас не будет возможности присоединиться к онлайн-трансляции, не переживайте! \nЗапись вебинара будет размещена на канале в открытом доступе.\n\nОписание тренинга\nОсновной сайт: https://rs.school/js/\n\nПодробная информация о школе: https://docs.rs.school \N f 2020-02-02 09:01:56.398+00 2020-07-31 08:01:56.398+00 Rolling Scopes School 2020 Q1: JavaScript/Front-end 2020-04-15 08:40:46.24+00 f \N \N t t \N \N 2 70 \N
+23 2020-02-25 09:28:08.842897 2021-07-28 20:44:30.259905 TEST COURSE \N javascript JavaScript \N test-course f TEST COURSE \N f 2021-05-31 21:00:00+00 2023-06-30 21:00:00+00 TEST COURSE \N t 2 \N t t \N \N 2 70 \N
\.
@@ -3315,6 +3316,7 @@ COPY public.migrations (id, "timestamp", name) FROM stdin;
57 1712137476312 Course1712137476312
58 1730926720293 CourseTask1730926720293
59 1734874453585 Contributor1734874453585
+60 1736458672717 Course1736458672717
\.
@@ -4248,7 +4250,7 @@ SELECT pg_catalog.setval('public.mentor_registry_id_seq', 290, true);
-- Name: migrations_id_seq; Type: SEQUENCE SET; Schema: public; Owner: rs_master
--
-SELECT pg_catalog.setval('public.migrations_id_seq', 59, true);
+SELECT pg_catalog.setval('public.migrations_id_seq', 60, true);
--