Skip to content

Commit

Permalink
Merge pull request #10 from aelporg/AA-78-assessment-screen
Browse files Browse the repository at this point in the history
Add assessment creation
  • Loading branch information
talhabalaj authored Mar 23, 2022
2 parents cc1b116 + 78fb422 commit fc5e4d6
Show file tree
Hide file tree
Showing 49 changed files with 1,474 additions and 347 deletions.
2 changes: 2 additions & 0 deletions apps/api/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { environment } from '../environments/environment'
import { EnvironmentModule } from '../modules/environment/environment.module'
import AssessmentModule from '../modules/assessment/assessment.module'
import QuestionsModule from '../modules/question/question.module'
import LanguageModule from '../modules/language/language.module'

function onWebsocketConnection(connectionParams: any) {
return {
Expand All @@ -36,6 +37,7 @@ function onWebsocketConnection(connectionParams: any) {
EnvironmentModule,
AssessmentModule,
QuestionsModule,
LanguageModule,

// Main GraphQL module
GraphQLModule.forRoot<ApolloDriverConfig>({
Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/modules/assessment/assessment.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ModelsModule } from '@aelp-app/models'
import { Module } from '@nestjs/common'
import QuestionsModule from '../question/question.module'
import AssessmentResolver from './assessment.resolver'
import AssessmentService from './assessment.service'

@Module({
imports: [ModelsModule],
imports: [ModelsModule, QuestionsModule],
providers: [AssessmentService, AssessmentResolver],
})
export default class AssessmentModule {}
60 changes: 51 additions & 9 deletions apps/api/src/modules/assessment/assessment.service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { PrismaService } from '@aelp-app/models'
import { Injectable } from '@nestjs/common'
import { UserInputError } from 'apollo-server-express'
import { ClassroomRole } from '../../global-types'
import { ClassroomRole, QuestionType } from '../../global-types'
import QuestionService from '../question/question.service'
import { User } from '../user/types/user.model'
import { AssessmentCreateInput } from './types/assessment-create.input'
@Injectable()
export default class AssessmentService {
constructor(private prismaService: PrismaService) {}
constructor(
private prismaService: PrismaService,
private questionService: QuestionService
) {}

async createAssessment(data: AssessmentCreateInput, user: User) {
const { classroomId, ...rest } = data
const { classroomId, questions, ...rest } = data

if (classroomId) {
const classroom = await this.prismaService.classroom.findUnique({
Expand All @@ -29,12 +33,50 @@ export default class AssessmentService {
}
}

return this.prismaService.assessment.create({
data: {
...rest,
user: { connect: { id: user.id } },
classroom: classroomId ? { connect: { id: classroomId } } : undefined,
},
return this.prismaService.$transaction(async prisma => {
const questionsTransformed = questions.map(
this.questionService.transformQuestionToCreateQuery
)

const questionsIds = []
for (const question of questionsTransformed) {
const { programmingQuestion, multipleChoiceQuestion, ...rest } =
question

const createdQuestion = await prisma.question.create({
data: { ...rest },
})

if (programmingQuestion) {
await prisma.programmingQuestion.create({
data: {

...programmingQuestion,
baseQuestion: { connect: { id: createdQuestion.id } },
},
})
} else if (multipleChoiceQuestion) {
await prisma.multipleChoiceQuestion.create({
data: {
...multipleChoiceQuestion,
baseQuestion: { connect: { id: createdQuestion.id } },
},
})
}

questionsIds.push(createdQuestion.id)
}

return prisma.assessment.create({
data: {
...rest,
questions: {
connect: questionsIds.map(id => ({ id })),
},
user: { connect: { id: user.id } },
classroom: classroomId ? { connect: { id: classroomId } } : undefined,
},
})
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Field } from '@nestjs/graphql'
import { InputType } from '@nestjs/graphql'
import { Int } from '@nestjs/graphql'
import { AssessmentType } from '../../../global-types'
import { QuestionCreateInput } from '../../question/types/question-create-input'

@InputType()
export class AssessmentCreateInput {
Expand All @@ -12,7 +13,10 @@ export class AssessmentCreateInput {
description!: string

@Field(() => AssessmentType, { nullable: false })
assessmentType!: keyof typeof AssessmentType
assessmentType!: AssessmentType

@Field(() => [QuestionCreateInput], { nullable: false })
questions!: QuestionCreateInput[]

@Field(() => Date, { nullable: true })
startTime?: Date | string
Expand Down
4 changes: 3 additions & 1 deletion apps/api/src/modules/environment/environment.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ export class EnvironmentService {
}

const defaultLanguageId =
programmingQuestion.singleFileProgrammingQuestion?.defaultCodes[0]?.id ||
programmingQuestion.singleFileProgrammingQuestion?.defaultCodes[0]?.languageId ||
programmingQuestion.multipleFilesProgrammingQuestion.languageId

if (!defaultLanguageId) throw new Error('No default language')

const answer = this.prismaService.questionAnswer.create({
data: {
question: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Field, InputType, Int } from '@nestjs/graphql'
import { EvaluationCriteriaType } from '../../../global-types'
import { InputOutputEvaluationCriteriaCreateInput } from './input-output-evaluation-criteria-create-input'

@InputType()
export class EvaluationCriteriaCreateInput {
@Field(() => String, { nullable: false })
name!: string

@Field(() => EvaluationCriteriaType, { nullable: false })
type!: EvaluationCriteriaType

@Field(() => Int, { nullable: false })
totalPoints!: number

@Field(() => InputOutputEvaluationCriteriaCreateInput, { nullable: true })
inputOutputEvaluationCriteria?: InputOutputEvaluationCriteriaCreateInput
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Field } from '@nestjs/graphql';
import { ObjectType } from '@nestjs/graphql';
import { Int } from '@nestjs/graphql';

@ObjectType()
export class InputOutputEvaluationCriteriaCount {

@Field(() => Int, {nullable:false})
baseCriteria!: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Field } from '@nestjs/graphql'
import { InputType } from '@nestjs/graphql'
@InputType()
export class InputOutputEvaluationCriteriaCreateInput {
@Field(() => [String], {
nullable: true,
})
inputs?: string[]

@Field(() => [String], {
nullable: true,
})
outputs?: string[]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Field } from '@nestjs/graphql';
import { ObjectType } from '@nestjs/graphql';
import { ID } from '@nestjs/graphql';
import { EvaluationCriteria } from './evaluation-criteria.model';
import { InputOutputEvaluationCriteriaCount } from './input-output-evaluation-criteria-count.output';

@ObjectType()
export class InputOutputEvaluationCriteria {

@Field(() => ID, {nullable:false})
id!: string;

@Field(() => [String], {nullable:true})
inputs!: Array<string>;

@Field(() => [String], {nullable:true})
outputs!: Array<string>;

@Field(() => [EvaluationCriteria], {nullable:true})
baseCriteria?: Array<EvaluationCriteria>;

@Field(() => Date, {nullable:false})
updatedAt!: Date;

@Field(() => Date, {nullable:false})
createdAt!: Date;

@Field(() => InputOutputEvaluationCriteriaCount, {nullable:false})
_count?: InputOutputEvaluationCriteriaCount;
}
6 changes: 6 additions & 0 deletions apps/api/src/modules/language/language.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ModelsModule } from '@aelp-app/models'
import { Module } from '@nestjs/common'
import LanguageResolver from './language.resolver'

@Module({ imports: [ModelsModule], providers: [LanguageResolver] })
export default class LanguageModule {}
14 changes: 14 additions & 0 deletions apps/api/src/modules/language/language.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { PrismaService } from '@aelp-app/models'
import { Query } from '@nestjs/graphql'
import { Resolver } from '@nestjs/graphql'
import { Language } from './types/language.model'

@Resolver(() => Language)
export default class LanguageResolver {
constructor(private prismaService: PrismaService) {}

@Query(() => [Language])
async languages() {
return this.prismaService.language.findMany()
}
}
34 changes: 27 additions & 7 deletions apps/api/src/modules/language/types/language.model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Field } from '@nestjs/graphql'
import { ObjectType } from '@nestjs/graphql'
import { ID } from '@nestjs/graphql'
import { Environment } from '../../environment/types/environment.model'
import { File } from '../../environment/types/file.model'
import { MultipleFilesProgrammingQuestion } from '../../question/types/multiple-files-programming-question.model'
import { SingleFileProgrammingQuestion } from '../../question/types/single-file-programming-question.model'
import { LanguageCount } from './language-count.output'


@ObjectType()
export class Language {
@Field(() => ID, { nullable: false })
Expand All @@ -16,21 +18,39 @@ export class Language {
@Field(() => String, { nullable: false })
extension!: string

@Field(() => String, { nullable: false })
editorConfigName!: string

@Field(() => [SingleFileProgrammingQuestion], { nullable: true })
singleFileQuestions?: Array<SingleFileProgrammingQuestion>

@Field(() => Date, { nullable: false })
createdAt!: Date

@Field(() => Date, { nullable: false })
updatedAt!: Date

@Field(() => String, { nullable: false, defaultValue: 'main.${extension}' })
defaultFileName!: string

@Field(() => String, { nullable: false, defaultValue: '${extension}' })
editorConfigName!: string

@Field(() => String, { nullable: false, defaultValue: '' })
defaultCode!: string

@Field(() => String, { nullable: false, defaultValue: '' })
compilerPackageName!: string

@Field(() => String, { nullable: false, defaultValue: '' })
version!: string

@Field(() => [File], { nullable: true })
File?: Array<File>

@Field(() => [Environment], { nullable: true })
Environment?: Array<Environment>

@Field(() => [MultipleFilesProgrammingQuestion], { nullable: true })
MultipleFilesProgrammingQuestion?: Array<MultipleFilesProgrammingQuestion>

// @Field(() => [SingleFileProgrammingQuestionDefaultCode], { nullable: true })
// SingleFileProgrammingQuestionDefaultCode?: Array<SingleFileProgrammingQuestionDefaultCode>

@Field(() => LanguageCount, { nullable: false })
_count?: LanguageCount
}
3 changes: 2 additions & 1 deletion apps/api/src/modules/question/question.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { QuestionAnswer } from './types/question-answer.model'
QuestionResolver,
ProgrammingQuestionAnswerResolver,
QuestionAnswerResolver,
QuestionAnswerService
QuestionAnswerService,
],
exports: [QuestionService],
})
export default class QuestionsModule {}
16 changes: 7 additions & 9 deletions apps/api/src/modules/question/question.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { Args, Mutation, ResolveField, Resolver, Root } from '@nestjs/graphql'
import { LoggedInUser } from '../../utils/decorators/LoggedInUser'
import { User } from '../user/types/user.model'
import { ResolveField, Resolver, Root } from '@nestjs/graphql'
import QuestionService from './question.service'
import { MultipleChoiceQuestion } from './types/multiple-choice-question.model'
import { ProgrammingQuestion } from './types/programming-question.model'
import { QuestionCreateInput } from './types/question-create-input'
import { Question } from './types/question.model'

@Resolver(() => Question)
export default class QuestionResolver {
constructor(private questionService: QuestionService) {}

@Mutation(() => Question)
async createQuestion(@Args('data') data: QuestionCreateInput, @LoggedInUser() user: User) {
return this.questionService.createQuestion(data, user)
}

@ResolveField(() => ProgrammingQuestion)
async programmingQuestion(@Root() question: Question) {
return this.questionService.getById(question.id).programmingQuestion()
}

@ResolveField(() => MultipleChoiceQuestion)
async multipleChoiceQuestion(@Root() question: Question) {
return this.questionService.getById(question.id).multipleChoiceQuestion()
}
}
Loading

0 comments on commit fc5e4d6

Please sign in to comment.