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

Major changes in student classes api,classes controller,new relation,,instructor side api #224

Merged
merged 5 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 11 additions & 0 deletions drizzle/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2519,9 +2519,20 @@ export const bootcampsEnrollmentsRelations = relations(
zuvyBootcamps,
({ one, many }) => ({
students: many(zuvyBatchEnrollments),
sessions: many(zuvySessions)
}),
);

export const sessionBootcampRelations = relations(
zuvySessions,
({one}) => ({
bootcampDetail:one(zuvyBootcamps,{
fields: [zuvySessions.bootcampId],
references: [zuvyBootcamps.id]
})
})
)

// export const batchEnrollmentsRelations = relations(batches, ({one, many}) => ({
// // enrolles: many(batchEnrollments, {
// // relationName: bootcampsEnrollmentsRelations,
Expand Down
5 changes: 4 additions & 1 deletion src/constants/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ export const helperVariable= {
admin: 'admin',
instructor:'instructor',
success: 'success',
error: 'error'
error: 'error',
ongoing: 'ongoing',
upcoming: 'upcoming',
completed: 'completed'
};
12 changes: 6 additions & 6 deletions src/controller/classes/classes.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ export class ClassesService {
return { success: 'not success', message: 'Class creation failed' };
}
} catch (error) {
console.log('Error creating class', error);
Logger.log(`error: ${error.message}`)
return {
status: 'not success',
message: 'error creating class',
Expand Down Expand Up @@ -858,14 +858,14 @@ export class ClassesService {
}
}

async updatingStatusOfClass(bootcamp_id:number){
async updatingStatusOfClass(bootcamp_id:number,batch_id:number){
try {
const currentTime = new Date();
// Fetch all classes
let classes = await db
.select()
.from(zuvySessions)
.where(sql`${zuvySessions.bootcampId} = ${bootcamp_id}`);
.where(sql`${zuvySessions.bootcampId} = ${bootcamp_id} AND ${zuvySessions.batchId} = ${batch_id}`);

// Update the status of each class in the database
for (let classObj of classes) {
Expand All @@ -890,7 +890,7 @@ export class ClassesService {
}
}
} catch (error) {
console.log('Error fetching class Links', error);
Logger.log(`error: ${error.message}`)
return {
success: 'not success',
message: 'Error fetching class Links',
Expand All @@ -914,7 +914,7 @@ export class ClassesService {
async getClassesBy(bootcamp_id: number, user, batch_id: number, limit: number, offset: number, search_term: string, status: string) {
try {
// update the status of the classes in the database
await this.updatingStatusOfClass(bootcamp_id);
await this.updatingStatusOfClass(bootcamp_id,batch_id);

if (user?.roles?.includes('admin')) {
} else if (bootcamp_id && user.id) {
Expand Down Expand Up @@ -1016,7 +1016,7 @@ export class ClassesService {
code: 200,
};
} catch (error) {
console.log('Error deleting class', error);
Logger.log(`error: ${error.message}`)
return {
status: 'error',
message: 'Error deleting class',
Expand Down
4 changes: 3 additions & 1 deletion src/controller/content/content.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ export class ContentService {
moduleId: number;
topicId: number;
order: number;
completionDate: string;
quizQuestionDetails?: any[];
codingQuestionDetails?: any[];
formQuestionDetails?: any[];
Expand All @@ -716,6 +717,7 @@ export class ContentService {
moduleId: chapterDetails[0].moduleId,
topicId: chapterDetails[0].topicId,
order: chapterDetails[0].order,
completionDate:chapterDetails[0].completionDate
};
if (chapterDetails.length > 0) {
if (chapterDetails[0].topicId == 4) {
Expand Down Expand Up @@ -761,7 +763,7 @@ export class ContentService {
description: chapterDetails[0].description,
links: chapterDetails[0].links,
file: chapterDetails[0].file,
content: chapterDetails[0].articleContent,
content: chapterDetails[0].articleContent
},
];
modifiedChapterDetails.contentDetails = content;
Expand Down
45 changes: 45 additions & 0 deletions src/controller/instructor/instructor.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,49 @@ import {
const res = await this.instructorService.allCourses(req.user[0].id);
return res;
}


@Get('/getAllUpcomingClasses')
@ApiOperation({ summary: 'Get all upcoming classes by instructorId' })
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add another query with the status ["all", 'upcoming', "ongoing", "completed"], as well as other query strings?

In status, if we pass all, it will fetch all the classes sorted by the start time of the class. if we pass the upcoming only then it will return only to the upcoming class. so on.

@ApiQuery({
name: 'limit',
required: true,
type: Number,
description: 'Number of classes per page',
})
@ApiQuery({
name: 'offset',
required: true,
type: Number,
description: 'Offset for pagination (min value 1)',
})
@ApiQuery({
name: 'batchId',
required: false,
type: Number,
description: 'batchId',
})
@ApiBearerAuth()
getAllUpcomingClasses(
@Query('limit') limit: number,
@Query('offset') offset: number,
@Query('timeFrame') timeFrame: string,
@Query('batchId') batchId:number,
@Req() req
): Promise<object> {
return this.instructorService.getAllUpcomingClasses(
req.user[0].id,
limit,
offset,
timeFrame,
batchId
);
}
@Get('/batchOfInstructor')
@ApiOperation({ summary: 'Get all batches of a particular instructor' })
@ApiBearerAuth()
async getBatchOfInstructor(@Req() req) {
const res = await this.instructorService.getBatchOfInstructor(req.user[0].id);
return res;
}
}
166 changes: 164 additions & 2 deletions src/controller/instructor/instructor.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ import { Injectable, Logger } from '@nestjs/common';
import { db } from '../../db/index';
import { helperVariable } from 'src/constants/helper';
import { eq, sql, inArray, and, desc, arrayContains, notInArray } from 'drizzle-orm';
import axios from 'axios';
import { error, log } from 'console';
import * as _ from 'lodash';
import {
zuvyBatches,
zuvySessions
} from 'drizzle/schema';


const { ZUVY_CONTENT_URL, ZUVY_CONTENTS_API_URL } = process.env; // INPORTING env VALUSE ZUVY_CONTENT

@Injectable()
export class InstructorService {

async allCourses(userId : number)
{
try {
Expand Down Expand Up @@ -44,4 +48,162 @@ export class InstructorService {
throw err;
}
}


async getAllUpcomingClasses(
instructorId: number,
limit: number,
offset: number,
timeFrame: string,
batchId:number
) {
try {
const responses = {
upcoming: [],
ongoing: [],
};
let queryString;
if(!isNaN(batchId))
{
queryString = sql`${zuvyBatches.instructorId} = ${instructorId} AND ${zuvyBatches.id}= ${batchId}`
}
else {
queryString = sql`${zuvyBatches.instructorId} = ${instructorId}`
}
const batches = await db
.select()
.from(zuvyBatches)
.where(queryString);

if (batches.length === 0) {
return {
status: helperVariable.error,
message: 'No batches found for the given instructorId',
};
}
for (const batch of batches) {
const currentTime = new Date();
const classDetails = await db.query.zuvySessions.findMany({
where: (session, { sql }) =>
sql`${session.batchId} = ${batch.id}`,
with : {
bootcampDetail : {
columns : {
id:true,
name:true
}
}
}
})
const sortedClasses = _.orderBy(
classDetails,
(classObj) => new Date(classObj.startTime),
'asc',
);
const completedClasses = [];
const ongoingClasses = [];
const upcomingClasses = [];

for (const classObj of sortedClasses) {
const startTime = new Date(classObj.startTime);
const endTime = new Date(classObj.endTime);
if (currentTime > endTime) {
completedClasses.push(classObj);
} else if (currentTime >= startTime && currentTime <= endTime) {
const {status,...rest} = classObj;
ongoingClasses.push({...rest,status:helperVariable.ongoing});
} else {
upcomingClasses.push(classObj);
}
}
const paginatedUpcomingClasses = upcomingClasses.slice(
offset,limit+offset
);
const paginatedOngoingClasses = ongoingClasses.slice(
offset,limit+offset
);
let filteredClasses;
let filteredOngoingClasses = paginatedOngoingClasses;

switch (timeFrame) {
case '1 week':
filteredClasses = paginatedUpcomingClasses.filter(classObj => {
const startTime = new Date(classObj.startTime);
return startTime <= new Date(currentTime.getTime() + 7 * 24 * 60 * 60 * 1000);
});
break;
case '2 weeks':
filteredClasses = paginatedUpcomingClasses.filter(classObj => {
const startTime = new Date(classObj.startTime);
return startTime <= new Date(currentTime.getTime() + 14 * 24 * 60 * 60 * 1000);
});
break;
default:
filteredClasses = paginatedUpcomingClasses;
break;
}

const batchUpcomingClasses = filteredClasses.map(classObj => {
const { bootcampDetail, ...rest } = classObj;
return {
...rest,
bootcampName: bootcampDetail.name,
batchId: batch.id,
batchName: batch.name,
};
});

const batchOngoingClasses = filteredOngoingClasses.map(classObj => {
const { bootcampDetail, ...rest } = classObj;
return {
...rest,
bootcampName: bootcampDetail.name,
batchId: batch.id,
batchName: batch.name,
};
});
responses.upcoming.push(...batchUpcomingClasses);
responses.ongoing.push(...batchOngoingClasses);
}
responses.upcoming.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
responses.ongoing.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());

return {
status: helperVariable.success,
message: 'Upcoming classes fetched successfully',
data: responses,
};
} catch (error) {
Logger.log(`error: ${error.message}`)
throw error;
}
}

async getBatchOfInstructor(instructorId:number)
{
try {
const batchDetails = await db.select({batchId:zuvyBatches.id,batchName: zuvyBatches.name}).from(zuvyBatches).where(eq(zuvyBatches.instructorId,instructorId));

if(batchDetails.length > 0)
{
return {
status: helperVariable.success,
code:200,
batchDetails
}
}
else {
return {
status: helperVariable.error,
code:201,
message: 'You are not assigned as an instructor to any batch'
}
}
}
catch(error)
{
Logger.log(`error: ${error.message}`)
}
}

}
17 changes: 15 additions & 2 deletions src/controller/student/student.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,28 @@ export class StudentController {
@Get('/Dashboard/classes')
@ApiOperation({ summary: 'Get dashboard upcoming class' })
@ApiBearerAuth()
@ApiQuery({
name: 'limit',
type: Number,
description: 'limit',
required:false
})
@ApiQuery({
name: 'offset',
type: Number,
description: 'offset',
required:false
})
@ApiQuery({
name: 'batch_id',
required: false,
type: String,
description: 'batch_id',
})
async getUpcomingClass(@Req() req, @Query('batch_id') batchID: number
async getUpcomingClass(@Req() req, @Query('batch_id')batchID: number,@Query('limit') limit: number,
@Query('offset') offset : number
) {
return await this.studentService.getUpcomingClass(req.user[0].id, batchID);
return await this.studentService.getUpcomingClass(req.user[0].id, batchID,limit,offset);
}

@Get('/Dashboard/attendance')
Expand Down
Loading