Skip to content

Commit 90b132c

Browse files
committed
Merge branch 'develop' of https://github.com/makeopensource/devU into #121-Link-Matching-pair-page-into-edit-assignment
2 parents 1753290 + 37dfdfe commit 90b132c

File tree

67 files changed

+2054
-430
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2054
-430
lines changed

devU-api/src/entities/assignment/assignment.model.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111

1212
import CourseModel from '../course/course.model'
1313

14+
import { ScoringType } from 'devu-shared-modules'
15+
1416
@Entity('assignments')
1517
export default class AssignmentModel {
1618
/**
@@ -58,6 +60,11 @@ export default class AssignmentModel {
5860
* type: string
5961
* array: true
6062
* description: filenames of stored attachments, matches the index of the fileHashes, i.e. filename[i] is the name of hash[i]
63+
* scoringType:
64+
* type: string
65+
* enum: [highest-score, latest-submission, no-score]
66+
* default: highest-score
67+
* description: Determines how the final score is chosen for the assignment
6168
*/
6269

6370
@PrimaryGeneratedColumn()
@@ -109,4 +116,12 @@ export default class AssignmentModel {
109116

110117
@Column({ name: 'attachmentsFilenames', array: true, default: [], type: 'text', nullable: false })
111118
attachmentsFilenames: string[]
119+
120+
@Column({
121+
type: 'enum',
122+
enum: ScoringType,
123+
default: ScoringType.HIGHEST_SCORE,
124+
name: 'scoring_type'
125+
})
126+
scoringType: ScoringType
112127
}

devU-api/src/entities/assignment/assignment.router.ts

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,10 @@ Router.get('/:assignmentId', asInt('assignmentId'), isAuthorizedByAssignmentStat
123123
* tags:
124124
* - Assignments
125125
* responses:
126-
* '200':
127-
* description: OK
126+
* '201':
127+
* description: Created
128+
* '400':
129+
* description: Bad Request
128130
* parameters:
129131
* - name: courseId
130132
* in: path
@@ -136,7 +138,41 @@ Router.get('/:assignmentId', asInt('assignmentId'), isAuthorizedByAssignmentStat
136138
* content:
137139
* application/x-www-form-urlencoded:
138140
* schema:
139-
* $ref: '#/components/schemas/Assignment'
141+
* type: object
142+
* required: [courseId, name, categoryName, maxFileSize, disableHandins, startDate, dueDate, endDate]
143+
* properties:
144+
* courseId:
145+
* type: integer
146+
* name:
147+
* type: string
148+
* maxLength: 128
149+
* categoryName:
150+
* type: string
151+
* maxLength: 128
152+
* description:
153+
* type: string
154+
* nullable: true
155+
* maxFileSize:
156+
* type: integer
157+
* maxSubmissions:
158+
* type: integer
159+
* nullable: true
160+
* disableHandins:
161+
* type: boolean
162+
* startDate:
163+
* type: string
164+
* format: date-time
165+
* dueDate:
166+
* type: string
167+
* format: date-time
168+
* endDate:
169+
* type: string
170+
* format: date-time
171+
* scoringType:
172+
* type: string
173+
* enum: [highest-score, latest-submission, no-score]
174+
* default: highest-score
175+
* description: Determines how the final score is chosen for the assignment
140176
*/
141177

142178

@@ -151,7 +187,9 @@ Router.post('/', isAuthorized('assignmentEditAll'), upload.array('files', 5), va
151187
* - Assignments
152188
* responses:
153189
* '200':
154-
* description: OK
190+
* description: Updated
191+
* '404':
192+
* description: Not Found
155193
* parameters:
156194
* - name: courseId
157195
* in: path
@@ -168,7 +206,37 @@ Router.post('/', isAuthorized('assignmentEditAll'), upload.array('files', 5), va
168206
* content:
169207
* application/x-www-form-urlencoded:
170208
* schema:
171-
* $ref: '#/components/schemas/Assignment'
209+
* type: object
210+
* properties:
211+
* name:
212+
* type: string
213+
* maxLength: 128
214+
* categoryName:
215+
* type: string
216+
* maxLength: 128
217+
* description:
218+
* type: string
219+
* nullable: true
220+
* maxFileSize:
221+
* type: integer
222+
* maxSubmissions:
223+
* type: integer
224+
* nullable: true
225+
* disableHandins:
226+
* type: boolean
227+
* startDate:
228+
* type: string
229+
* format: date-time
230+
* dueDate:
231+
* type: string
232+
* format: date-time
233+
* endDate:
234+
* type: string
235+
* format: date-time
236+
* scoringType:
237+
* type: string
238+
* enum: [highest-score, latest-submission, no-score]
239+
* description: Determines how the final score is chosen for the assignment
172240
*/
173241
Router.put(
174242
'/:assignmentId',

devU-api/src/entities/assignment/assignment.serializer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export function serialize(assignment: AssignmentModel): Assignment {
1717
disableHandins: assignment.disableHandins,
1818
createdAt: assignment.createdAt.toISOString(),
1919
updatedAt: assignment.updatedAt.toISOString(),
20+
scoringType: assignment.scoringType,
2021
attachmentsHashes: assignment.attachmentsHashes,
21-
attachmentsFilenames: assignment.attachmentsFilenames
22+
attachmentsFilenames: assignment.attachmentsFilenames,
2223
}
2324
}

devU-api/src/entities/assignment/assignment.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export async function update(assignment: Assignment) {
2828
disableHandins,
2929
attachmentsHashes,
3030
attachmentsFilenames,
31+
scoringType,
3132
} = assignment
3233

3334
if (!id) throw new Error('Missing Id')
@@ -44,6 +45,7 @@ export async function update(assignment: Assignment) {
4445
disableHandins,
4546
attachmentsHashes,
4647
attachmentsFilenames,
48+
scoringType,
4749
})
4850
}
4951

@@ -112,8 +114,6 @@ async function processFiles(req: Request) {
112114
} else {
113115
console.warn(`Files where not in array format ${req.files}`)
114116
}
115-
} else {
116-
console.warn(`No files where processed`)
117117
}
118118

119119
return { fileHashes, fileNames }

devU-api/src/entities/assignment/assignment.validator.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { check } from 'express-validator'
22

33
import validate from '../../middleware/validator/generic.validator'
44
import { isBeforeParam, isAfterParam } from '../../middleware/validator/date.validator'
5+
import { ScoringType } from 'devu-shared-modules'
56

67
const courseId = check('courseId').isNumeric()
78
const name = check('name').isString().trim().isLength({ max: 128 })
@@ -10,6 +11,10 @@ const description = check('description').isString().trim()
1011
const maxFileSize = check('maxFileSize').isNumeric()
1112
const maxSubmissions = check('maxSubmissions').isNumeric().optional({ nullable: true })
1213
const disableHandins = check('disableHandins').isBoolean()
14+
const scoringType = check('scoringType')
15+
.optional()
16+
.isIn(Object.values(ScoringType))
17+
.withMessage(`scoringType must be one of: ${Object.values(ScoringType).join(', ')}`)
1318

1419
const startDate = check('startDate')
1520
.trim()
@@ -43,6 +48,7 @@ const validator = [
4348
maxFileSize,
4449
maxSubmissions,
4550
disableHandins,
51+
scoringType,
4652
validate,
4753
]
4854

devU-api/src/entities/assignmentProblem/assignmentProblem.controller.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Request, Response, NextFunction } from 'express'
1+
import { NextFunction, Request, Response } from 'express'
22

33
import AssignmentProblemService from './assignmentProblem.service'
44

@@ -33,15 +33,21 @@ export async function detail(req: Request, res: Response, next: NextFunction) {
3333
}
3434
}
3535

36-
export async function post(req: Request, res: Response, next: NextFunction) {
36+
export async function post(req: Request, res: Response, _: NextFunction) {
3737
try {
38-
const assignmentProblem = await AssignmentProblemService.create(req.body)
38+
req.body.assignmentId = parseInt(req.params.assignmentId)
39+
const assignmentProblem = await AssignmentProblemService.create(
40+
req.body.assignmentId,
41+
req.body.problemName,
42+
req.body.maxScore,
43+
req.body.metadata,
44+
)
3945
const response = serialize(assignmentProblem)
4046

4147
res.status(201).json(response)
4248
} catch (err) {
4349
if (err instanceof Error) {
44-
res.status(400).json(new GenericResponse(err.message))
50+
res.status(400).json(new GenericResponse(err.message))
4551
}
4652
}
4753
}

devU-api/src/entities/assignmentProblem/assignmentProblem.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export default class AssignmentProblemModel {
2828
* type: integer
2929
* problemName:
3030
* type: string
31+
* metadata:
32+
* type: string
33+
* description: A json string containing additional problem metadata
3134
* maxScore:
3235
* type: integer
3336
*/
@@ -43,6 +46,9 @@ export default class AssignmentProblemModel {
4346
@Column({ name: 'problem_name', length: 128 })
4447
problemName: string
4548

49+
@Column({ name: 'metadata', type: 'jsonb', nullable: true, default: {} })
50+
metadata: any // use any since this can be any arbitrary structure
51+
4652
@Column({ name: 'max_score' })
4753
maxScore: number
4854

devU-api/src/entities/assignmentProblem/assignmentProblem.router.ts

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ const Router = express.Router({ mergeParams: true })
2121
* responses:
2222
* '200':
2323
* description: OK
24+
* content:
25+
* application/json:
26+
* schema:
27+
* type: array
28+
* items:
29+
* type: object
30+
* properties:
31+
* id:
32+
* type: integer
33+
* assignmentId:
34+
* type: integer
35+
* problemName:
36+
* type: string
37+
* metadata:
38+
* type: string
39+
* description: A json string containing additional problem metadata
40+
* maxScore:
41+
* type: integer
2442
* parameters:
2543
* - name: assignmentId
2644
* description: Enter Assignment Id
@@ -43,6 +61,22 @@ Router.get('/', isAuthorized('enrolled'), AssignmentProblemController.get)
4361
* responses:
4462
* '200':
4563
* description: OK
64+
* content:
65+
* application/json:
66+
* schema:
67+
* type: object
68+
* properties:
69+
* id:
70+
* type: integer
71+
* assignmentId:
72+
* type: integer
73+
* problemName:
74+
* type: string
75+
* metadata:
76+
* type: string
77+
* description: A json string containing additional problem metadata
78+
* maxScore:
79+
* type: integer
4680
* parameters:
4781
* - name: id
4882
* description: Enter AssignmentProblem Id
@@ -63,8 +97,33 @@ Router.get('/:id', isAuthorized('assignmentEditAll'), asInt(), AssignmentProblem
6397
* tags:
6498
* - AssignmentProblems
6599
* responses:
66-
* '200':
67-
* description: OK
100+
* '201':
101+
* description: Created
102+
* content:
103+
* application/json:
104+
* schema:
105+
* type: object
106+
* properties:
107+
* id:
108+
* type: integer
109+
* assignmentId:
110+
* type: integer
111+
* problemName:
112+
* type: string
113+
* metadata:
114+
* type: string
115+
* description: A json string containing additional problem metadata
116+
* maxScore:
117+
* type: integer
118+
* '400':
119+
* description: Bad Request
120+
* content:
121+
* application/json:
122+
* schema:
123+
* type: object
124+
* properties:
125+
* message:
126+
* type: string
68127
* requestBody:
69128
* content:
70129
* application/x-www-form-urlencoded:
@@ -75,14 +134,37 @@ Router.post('/', isAuthorized('assignmentEditAll'), validator, AssignmentProblem
75134

76135
/**
77136
* @swagger
78-
* /course/:courseId/assignment/:assignmentId/assignment-problems:
137+
* /course/:courseId/assignment/:assignmentId/assignment-problems/{id}:
79138
* put:
80139
* summary: Update an assignment problem
81140
* tags:
82141
* - AssignmentProblems
83142
* responses:
84143
* '200':
85144
* description: OK
145+
* content:
146+
* application/json:
147+
* schema:
148+
* type: object
149+
* properties:
150+
* message:
151+
* type: string
152+
* '404':
153+
* description: Not Found
154+
* content:
155+
* application/json:
156+
* schema:
157+
* type: object
158+
* properties:
159+
* message:
160+
* type: string
161+
* parameters:
162+
* - name: id
163+
* description: Enter AssignmentProblem Id
164+
* in: path
165+
* required: true
166+
* schema:
167+
* type: integer
86168
* requestBody:
87169
* content:
88170
* application/x-www-form-urlencoded:

devU-api/src/entities/assignmentProblem/assignmentProblem.serializer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export function serialize(assignmentProblem: AssignmentProblemModel): Assignment
88
assignmentId: assignmentProblem.assignmentId,
99
problemName: assignmentProblem.problemName,
1010
maxScore: assignmentProblem.maxScore,
11+
metadata: assignmentProblem.metadata,
1112
createdAt: assignmentProblem.createdAt.toISOString(),
1213
updatedAt: assignmentProblem.updatedAt.toISOString(),
1314
}

0 commit comments

Comments
 (0)