Skip to content

Commit

Permalink
Merge branch 'staging' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Nephelite authored Mar 4, 2025
2 parents a45683f + b22ed13 commit 3b0ab1d
Show file tree
Hide file tree
Showing 15 changed files with 43 additions and 39 deletions.
4 changes: 2 additions & 2 deletions backend/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import submissionRoutes from './routes/submissionRoutes';
import assessmentAssignmentSetRoutes from './routes/assessmentAssignmentSetRoutes';
import assessmentResultRoutes from './routes/assessmentResultRoutes';
import notificationRoutes from './routes/notificationRoutes';
import setupNotificationJob from 'jobs/notificationJob';
import setupTutorialDataJob from 'jobs/tutorialDataJob';
import setupTutorialDataJob from './jobs/tutorialDataJob';
import setupNotificationJob from './jobs/notificationJob';

const env = process.env.NODE_ENV ?? 'development';
config({ path: `.env.${env}` });
Expand Down
3 changes: 2 additions & 1 deletion backend/jobs/codeAnalysisJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,15 @@ const getMedianAndMeanCodeData = async (course: any) => {

const codeAnalysisData = await codeAnalysisDataModel.find({
gitHubOrgName: course.gitHubOrgName,
repoName: { $regex: `^${course.repoNameFilter}` },
executionTime: {
$gte: startOfDay,
$lte: endOfDay,
},
});

console.log(
`Getting mean and median code analysis values for ${course.gitHubOrgName} - ${codeAnalysisData.length} records`
`Getting mean and median code analysis values for ${course.gitHubOrgName}, ${course.repoNameFilter} - ${codeAnalysisData.length} records`
);

if (codeAnalysisData.length === 0) return;
Expand Down
3 changes: 2 additions & 1 deletion backend/jobs/githubJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Review, TeamContribution, TeamPR } from '@shared/types/TeamData';
import cron from 'node-cron';
import { App, Octokit } from 'octokit';
import TeamData from '../models/TeamData';
import { getGitHubApp, getTeamMembers } from '../utils/github';
import { getGitHubApp } from '../utils/github';

const fetchAndSaveTeamData = async () => {
const app: App = getGitHubApp();
Expand Down Expand Up @@ -238,6 +238,7 @@ const getCourseData = async (octokit: Octokit, course: any) => {
}

const teamData = {
course: course._id,
gitHubOrgName: gitHubOrgName.toLowerCase(),
teamId: repo.id,
repoName: repo.name,
Expand Down
2 changes: 1 addition & 1 deletion backend/jobs/notificationJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { User } from '../models/User';
import InternalAssessmentModel, {
InternalAssessment,
} from '@models/InternalAssessment';
import { getUnmarkedAssignmentsByTAId } from 'services/assessmentAssignmentSetService';
import { getUnmarkedAssignmentsByTAId } from '../services/assessmentAssignmentSetService';
import { sendTelegramMessage } from '../clients/telegramClient';

/**
Expand Down
1 change: 1 addition & 0 deletions backend/jobs/publicGithubJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ const getPublicCourseData = async (course: any) => {

const teamData = {
gitHubOrgName: owner.toLowerCase(),
course: course._id,
teamId: repoData.data.id,
repoName: repo,
commits: commits.length,
Expand Down
1 change: 1 addition & 0 deletions backend/models/TeamData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const milestoneSchema = new Schema<Milestone>(

const teamDataSchema = new Schema<TeamData>({
teamId: { type: Number, required: true },
course: { type: Schema.Types.ObjectId, ref: 'Course', required: true },
gitHubOrgName: { type: String, required: true },
repoName: { type: String, required: true },
commits: { type: Number, required: true },
Expand Down
12 changes: 1 addition & 11 deletions backend/services/githubService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,8 @@ export const getAuthorizedTeamDataByCourse = async (
throw new NotFoundError('User is not authorized to view course');
}

// Extract the owner names from the course's GitHub repo links
const ownersFromRepoLinks = (course.gitHubRepoLinks || []).map(repoUrl => {
const urlParts = (repoUrl as string).split('/');
return urlParts[3].toLowerCase(); // Get the 'owner' part of the URL in lowercase
});

// Query for team data based on gitHubOrgName or gitHubRepoLinks
const teamDatas = await TeamDataModel.find({
$or: [
{ gitHubOrgName: course.gitHubOrgName },
{ gitHubOrgName: { $in: ownersFromRepoLinks } },
],
course: courseId,
});

if (!teamDatas) {
Expand Down
3 changes: 3 additions & 0 deletions backend/test/services/codeAnalysisService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ describe('codeAnalysisService', () => {
const teamData1 = new TeamDataModel({
teamId: 1,
gitHubOrgName: 'org',
course: mockCourse._id,
repoName: 'team1',
teamContributions: {},
teamPRs: [],
Expand All @@ -146,6 +147,7 @@ describe('codeAnalysisService', () => {
const teamData2 = new TeamDataModel({
teamId: 2,
gitHubOrgName: 'org',
course: mockCourse._id,
repoName: 'team2',
teamContributions: {},
teamPRs: [],
Expand Down Expand Up @@ -468,6 +470,7 @@ describe('codeAnalysisService', () => {
const teamDataA = new TeamDataModel({
teamId: 123,
gitHubOrgName: 'NoCodeAnalysisDataOrg',
course: courseWithoutCodeAnalysisData._id,
repoName: 'teamA',
teamContributions: {},
teamPRs: [],
Expand Down
4 changes: 2 additions & 2 deletions backend/test/services/githubService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('gitHubService', () => {
const teamData1 = new TeamDataModel({
repoName: 'team1',
gitHubOrgName: 'org',
courseId: mockFacultyCourseId,
course: mockCourse._id,
teamContributions: [],
pullRequests: 0,
issues: 0,
Expand All @@ -89,7 +89,7 @@ describe('gitHubService', () => {
const teamData2 = new TeamDataModel({
repoName: 'team2',
gitHubOrgName: 'org',
courseId: mockFacultyCourseId,
course: mockCourse._id,
teamContributions: [],
pullRequests: 0,
issues: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ const ConnectTrofosForm = ({

// Optional: Add validation for the fields
validate: {
apiKey: value => (value.length === 0 ? 'API key is required' : null),
trofosCourseId: value =>
apiKey: (value: string) =>
value.length === 0 ? 'API key is required' : null,
trofosCourseId: (value: number) =>
value < 0 ? 'This is not a valid Course ID' : null,
},
});
Expand Down
18 changes: 10 additions & 8 deletions multi-git-dashboard/src/components/forms/CreateCourseForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,25 @@ const CreateCourse: React.FC = () => {
installationId: '',
},
validate: {
name: value =>
name: (value: string) =>
value.trim().length > 0 ? null : 'Course name is required',
code: value =>
code: (value: string) =>
value.trim().length > 0 ? null : 'Course code is required',
semester: value =>
semester: (value: string) =>
value.trim().length > 0 ? null : 'Semester is required',
startDate: value => (value ? null : 'Start date is required'),
duration: value => (value ? null : 'Duration is required'),
courseType: value => (value ? null : 'Course type is required'),
startDate: (value: Date | null) =>
value ? null : 'Start date is required',
duration: (value: number) => (value ? null : 'Duration is required'),
courseType: (value: CourseType) =>
value ? null : 'Course type is required',
// field should be valid only if courseType is Normal, or if courseType is GitHubOrg and installation check is successful
gitHubOrgName: (value, values) =>
gitHubOrgName: (value: string, values: CreateCourseFormValues) =>
values.courseType === CourseType.Normal ||
(values.courseType === CourseType.GitHubOrg &&
appInstallationStatus === InstallationStatus.SUCCESS)
? null
: 'GitHub Org name is required',
repoNameFilter: (value, values) =>
repoNameFilter: (value: string, values: CreateCourseFormValues) =>
values.courseType === CourseType.Normal ||
(values.courseType === CourseType.GitHubOrg &&
appInstallationStatus === InstallationStatus.SUCCESS)
Expand Down
4 changes: 2 additions & 2 deletions multi-git-dashboard/src/components/forms/MilestoneForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const MilestoneForm: React.FC<MilestoneFormProps> = ({
description: '',
},
validate: {
number: value =>
number: (value: number) =>
value >= 1 && value <= 100 ? null : 'Invalid milestone number',
dateline: value => (value ? null : 'Dateline is required'),
dateline: (value: Date) => (value ? null : 'Dateline is required'),
},
});

Expand Down
6 changes: 3 additions & 3 deletions multi-git-dashboard/src/components/forms/SprintForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ const SprintForm: React.FC<SprintFormProps> = ({
endDate: new Date(),
},
validate: {
number: value =>
number: (value: number) =>
value >= 1 && value <= 100 ? null : 'Invalid sprint number',
startDate: value => (value ? null : 'Start date is required'),
endDate: value => (value ? null : 'End date is required'),
startDate: (value: Date) => (value ? null : 'Start date is required'),
endDate: (value: Date) => (value ? null : 'End date is required'),
},
});

Expand Down
13 changes: 7 additions & 6 deletions multi-git-dashboard/src/pages/auth/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,21 @@ const RegisterPage: React.FC = () => {
role: Roles.TA,
},
validate: {
identifier: value =>
identifier: (value: string) =>
value.trim().length < 3
? 'NUSNet ID must be at least 3 characters long'
: null,
name: value =>
name: (value: string) =>
value.trim().length < 3
? 'Name must be at least 3 characters long'
: null,
email: value => (!/^\S+@\S+$/.test(value) ? 'Invalid email' : null),
password: value =>
email: (value: string) =>
!/^\S+@\S+$/.test(value) ? 'Invalid email' : null,
password: (value: string) =>
value.length < 6 ? 'Password must be at least 6 characters long' : null,
confirmPassword: (value, values) =>
confirmPassword: (value: string, values: FormValues) =>
value !== values.password ? 'Passwords do not match' : null,
role: value =>
role: (value: Role) =>
!Object.values(Roles).includes(value) ? 'Invalid role' : null,
},
});
Expand Down
3 changes: 3 additions & 0 deletions shared/types/TeamData.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Course } from './Course';

export interface TeamContribution {
commits: number;
createdIssues: number;
Expand Down Expand Up @@ -49,6 +51,7 @@ export interface Milestone {

export interface TeamData {
_id: string;
course: Course;
gitHubOrgName: string;
teamId: number;
repoName: string;
Expand Down

0 comments on commit 3b0ab1d

Please sign in to comment.