@studious-lms/server 1.2.34 → 1.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/routers/_app.d.ts +362 -204
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +2 -0
- package/dist/routers/announcement.d.ts +8 -4
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/comment.d.ts +163 -0
- package/dist/routers/comment.d.ts.map +1 -0
- package/dist/routers/comment.js +286 -0
- package/dist/routers/worksheet.d.ts +64 -111
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +94 -76
- package/package.json +1 -1
- package/prisma/schema.prisma +11 -4
- package/src/routers/_app.ts +2 -0
- package/src/routers/announcement.ts +3 -3
- package/src/routers/comment.ts +314 -0
- package/src/routers/worksheet.ts +95 -79
|
@@ -38,7 +38,7 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
38
38
|
order: number | null;
|
|
39
39
|
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
40
40
|
updatedAt: Date;
|
|
41
|
-
points: number
|
|
41
|
+
points: number;
|
|
42
42
|
question: string;
|
|
43
43
|
worksheetId: string;
|
|
44
44
|
answer: string;
|
|
@@ -128,7 +128,7 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
128
128
|
order: number | null;
|
|
129
129
|
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
130
130
|
updatedAt: Date;
|
|
131
|
-
points: number
|
|
131
|
+
points: number;
|
|
132
132
|
question: string;
|
|
133
133
|
worksheetId: string;
|
|
134
134
|
answer: string;
|
|
@@ -166,7 +166,7 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
166
166
|
order: number | null;
|
|
167
167
|
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
168
168
|
updatedAt: Date;
|
|
169
|
-
points: number
|
|
169
|
+
points: number;
|
|
170
170
|
question: string;
|
|
171
171
|
worksheetId: string;
|
|
172
172
|
answer: string;
|
|
@@ -186,7 +186,7 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
186
186
|
order: number | null;
|
|
187
187
|
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
188
188
|
updatedAt: Date;
|
|
189
|
-
points: number
|
|
189
|
+
points: number;
|
|
190
190
|
question: string;
|
|
191
191
|
worksheetId: string;
|
|
192
192
|
answer: string;
|
|
@@ -199,17 +199,47 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
199
199
|
worksheetId: string;
|
|
200
200
|
};
|
|
201
201
|
output: {
|
|
202
|
-
responses: {
|
|
202
|
+
responses: ({
|
|
203
|
+
comments: {
|
|
204
|
+
reactions: {
|
|
205
|
+
type: import(".prisma/client").$Enums.ReactionType;
|
|
206
|
+
user: {
|
|
207
|
+
id: string;
|
|
208
|
+
username: string;
|
|
209
|
+
profile: {
|
|
210
|
+
displayName: string | null;
|
|
211
|
+
profilePicture: string | null;
|
|
212
|
+
profilePictureThumbnail: string | null;
|
|
213
|
+
} | null;
|
|
214
|
+
};
|
|
215
|
+
}[];
|
|
216
|
+
replies: {
|
|
217
|
+
id: string;
|
|
218
|
+
content: string;
|
|
219
|
+
author: {
|
|
220
|
+
id: string;
|
|
221
|
+
username: string;
|
|
222
|
+
profile: {
|
|
223
|
+
displayName: string | null;
|
|
224
|
+
profilePicture: string | null;
|
|
225
|
+
profilePictureThumbnail: string | null;
|
|
226
|
+
} | null;
|
|
227
|
+
};
|
|
228
|
+
}[];
|
|
229
|
+
}[];
|
|
230
|
+
} & {
|
|
203
231
|
id: string;
|
|
204
232
|
feedback: string | null;
|
|
205
233
|
studentId: string;
|
|
206
234
|
createdAt: Date;
|
|
207
|
-
updatedAt: Date;
|
|
235
|
+
updatedAt: Date | null;
|
|
236
|
+
points: number;
|
|
208
237
|
questionId: string;
|
|
209
238
|
response: string;
|
|
210
|
-
isCorrect: boolean;
|
|
211
239
|
studentWorksheetResponseId: string | null;
|
|
212
|
-
|
|
240
|
+
isCorrect: boolean;
|
|
241
|
+
markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
242
|
+
})[];
|
|
213
243
|
} & {
|
|
214
244
|
id: string;
|
|
215
245
|
submissionId: string | null;
|
|
@@ -234,11 +264,13 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
234
264
|
feedback: string | null;
|
|
235
265
|
studentId: string;
|
|
236
266
|
createdAt: Date;
|
|
237
|
-
updatedAt: Date;
|
|
267
|
+
updatedAt: Date | null;
|
|
268
|
+
points: number;
|
|
238
269
|
questionId: string;
|
|
239
270
|
response: string;
|
|
240
|
-
isCorrect: boolean;
|
|
241
271
|
studentWorksheetResponseId: string | null;
|
|
272
|
+
isCorrect: boolean;
|
|
273
|
+
markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
242
274
|
}[];
|
|
243
275
|
} & {
|
|
244
276
|
id: string;
|
|
@@ -262,55 +294,14 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
262
294
|
feedback: string | null;
|
|
263
295
|
studentId: string;
|
|
264
296
|
createdAt: Date;
|
|
265
|
-
updatedAt: Date;
|
|
297
|
+
updatedAt: Date | null;
|
|
298
|
+
points: number;
|
|
266
299
|
questionId: string;
|
|
267
300
|
response: string;
|
|
268
|
-
isCorrect: boolean;
|
|
269
301
|
studentWorksheetResponseId: string | null;
|
|
270
|
-
}[];
|
|
271
|
-
} & {
|
|
272
|
-
id: string;
|
|
273
|
-
submissionId: string | null;
|
|
274
|
-
studentId: string;
|
|
275
|
-
createdAt: Date;
|
|
276
|
-
updatedAt: Date;
|
|
277
|
-
submittedAt: Date | null;
|
|
278
|
-
submitted: boolean;
|
|
279
|
-
worksheetId: string;
|
|
280
|
-
};
|
|
281
|
-
meta: object;
|
|
282
|
-
}>;
|
|
283
|
-
getOrCreateWorksheetResponse: import("@trpc/server").TRPCMutationProcedure<{
|
|
284
|
-
input: {
|
|
285
|
-
studentId: string;
|
|
286
|
-
worksheetId: string;
|
|
287
|
-
};
|
|
288
|
-
output: {
|
|
289
|
-
responses: ({
|
|
290
|
-
question: {
|
|
291
|
-
type: import(".prisma/client").$Enums.WorksheetQuestionType;
|
|
292
|
-
id: string;
|
|
293
|
-
options: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
294
|
-
createdAt: Date;
|
|
295
|
-
order: number | null;
|
|
296
|
-
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
297
|
-
updatedAt: Date;
|
|
298
|
-
points: number | null;
|
|
299
|
-
question: string;
|
|
300
|
-
worksheetId: string;
|
|
301
|
-
answer: string;
|
|
302
|
-
};
|
|
303
|
-
} & {
|
|
304
|
-
id: string;
|
|
305
|
-
feedback: string | null;
|
|
306
|
-
studentId: string;
|
|
307
|
-
createdAt: Date;
|
|
308
|
-
updatedAt: Date;
|
|
309
|
-
questionId: string;
|
|
310
|
-
response: string;
|
|
311
302
|
isCorrect: boolean;
|
|
312
|
-
|
|
313
|
-
}
|
|
303
|
+
markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
304
|
+
}[];
|
|
314
305
|
} & {
|
|
315
306
|
id: string;
|
|
316
307
|
submissionId: string | null;
|
|
@@ -323,72 +314,34 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
323
314
|
};
|
|
324
315
|
meta: object;
|
|
325
316
|
}>;
|
|
326
|
-
|
|
317
|
+
gradeAnswer: import("@trpc/server").TRPCMutationProcedure<{
|
|
327
318
|
input: {
|
|
328
|
-
|
|
319
|
+
questionId: string;
|
|
320
|
+
studentWorksheetResponseId: string;
|
|
321
|
+
isCorrect: boolean;
|
|
322
|
+
feedback?: string | undefined;
|
|
323
|
+
points?: number | undefined;
|
|
324
|
+
response?: string | undefined;
|
|
325
|
+
responseId?: string | undefined;
|
|
326
|
+
markschemeState?: any;
|
|
329
327
|
};
|
|
330
|
-
output:
|
|
331
|
-
student: {
|
|
332
|
-
id: string;
|
|
333
|
-
username: string;
|
|
334
|
-
profile: {
|
|
335
|
-
displayName: string | null;
|
|
336
|
-
profilePicture: string | null;
|
|
337
|
-
} | null;
|
|
338
|
-
};
|
|
339
|
-
responses: ({
|
|
340
|
-
question: {
|
|
341
|
-
type: import(".prisma/client").$Enums.WorksheetQuestionType;
|
|
342
|
-
id: string;
|
|
343
|
-
options: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
344
|
-
createdAt: Date;
|
|
345
|
-
order: number | null;
|
|
346
|
-
markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
347
|
-
updatedAt: Date;
|
|
348
|
-
points: number | null;
|
|
349
|
-
question: string;
|
|
350
|
-
worksheetId: string;
|
|
351
|
-
answer: string;
|
|
352
|
-
};
|
|
353
|
-
} & {
|
|
354
|
-
id: string;
|
|
355
|
-
feedback: string | null;
|
|
356
|
-
studentId: string;
|
|
357
|
-
createdAt: Date;
|
|
358
|
-
updatedAt: Date;
|
|
359
|
-
questionId: string;
|
|
360
|
-
response: string;
|
|
361
|
-
isCorrect: boolean;
|
|
362
|
-
studentWorksheetResponseId: string | null;
|
|
363
|
-
})[];
|
|
364
|
-
} & {
|
|
365
|
-
id: string;
|
|
366
|
-
submissionId: string | null;
|
|
367
|
-
studentId: string;
|
|
368
|
-
createdAt: Date;
|
|
369
|
-
updatedAt: Date;
|
|
370
|
-
submittedAt: Date | null;
|
|
371
|
-
submitted: boolean;
|
|
372
|
-
worksheetId: string;
|
|
373
|
-
}) | null;
|
|
328
|
+
output: any;
|
|
374
329
|
meta: object;
|
|
375
330
|
}>;
|
|
376
|
-
|
|
331
|
+
addComment: import("@trpc/server").TRPCMutationProcedure<{
|
|
377
332
|
input: {
|
|
333
|
+
comment: string;
|
|
378
334
|
responseId: string;
|
|
379
|
-
isCorrect: boolean;
|
|
380
|
-
feedback?: string | undefined;
|
|
381
335
|
};
|
|
382
336
|
output: {
|
|
383
337
|
id: string;
|
|
384
|
-
|
|
385
|
-
studentId: string;
|
|
338
|
+
content: string;
|
|
386
339
|
createdAt: Date;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
340
|
+
modifiedAt: Date | null;
|
|
341
|
+
announcementId: string | null;
|
|
342
|
+
parentCommentId: string | null;
|
|
343
|
+
authorId: string;
|
|
344
|
+
studentQuestionProgressId: string | null;
|
|
392
345
|
};
|
|
393
346
|
meta: object;
|
|
394
347
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worksheet.d.ts","sourceRoot":"","sources":["../../src/routers/worksheet.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"worksheet.d.ts","sourceRoot":"","sources":["../../src/routers/worksheet.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA8KA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwVhC,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { TRPCError } from "@trpc/server";
|
|
|
2
2
|
import { createTRPCRouter, protectedProcedure } from "../trpc.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { prisma } from "../lib/prisma.js";
|
|
5
|
+
import { commentSelect } from "./comment.js";
|
|
5
6
|
export const worksheetRouter = createTRPCRouter({
|
|
6
7
|
// Get a single worksheet with all questions
|
|
7
8
|
getWorksheet: protectedProcedure
|
|
@@ -15,6 +16,7 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
15
16
|
include: {
|
|
16
17
|
questions: {
|
|
17
18
|
orderBy: { createdAt: 'asc' },
|
|
19
|
+
// select: { id: true, type: true, question: true, answer: true, points: true },
|
|
18
20
|
},
|
|
19
21
|
class: true,
|
|
20
22
|
},
|
|
@@ -235,7 +237,13 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
235
237
|
worksheetId
|
|
236
238
|
},
|
|
237
239
|
include: {
|
|
238
|
-
responses:
|
|
240
|
+
responses: {
|
|
241
|
+
include: {
|
|
242
|
+
comments: {
|
|
243
|
+
select: commentSelect,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
239
247
|
},
|
|
240
248
|
});
|
|
241
249
|
if (existing) {
|
|
@@ -249,7 +257,13 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
249
257
|
studentId: submission.studentId,
|
|
250
258
|
},
|
|
251
259
|
include: {
|
|
252
|
-
responses:
|
|
260
|
+
responses: {
|
|
261
|
+
include: {
|
|
262
|
+
comments: {
|
|
263
|
+
select: commentSelect,
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
253
267
|
},
|
|
254
268
|
});
|
|
255
269
|
return created;
|
|
@@ -344,95 +358,99 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
344
358
|
// You could integrate with an AI service to auto-grade certain question types
|
|
345
359
|
return submittedWorksheet;
|
|
346
360
|
}),
|
|
347
|
-
//
|
|
348
|
-
|
|
361
|
+
// Grade a student's answer
|
|
362
|
+
gradeAnswer: protectedProcedure
|
|
349
363
|
.input(z.object({
|
|
350
|
-
|
|
351
|
-
|
|
364
|
+
questionId: z.string(),
|
|
365
|
+
responseId: z.string().optional(), // StudentQuestionProgress ID (optional for upsert)
|
|
366
|
+
studentWorksheetResponseId: z.string(), // Required for linking to worksheet response
|
|
367
|
+
response: z.string().optional(), // The actual response text (needed if creating new)
|
|
368
|
+
isCorrect: z.boolean(),
|
|
369
|
+
feedback: z.string().optional(),
|
|
370
|
+
markschemeState: z.any().optional(),
|
|
371
|
+
points: z.number().optional(),
|
|
352
372
|
}))
|
|
353
373
|
.mutation(async ({ ctx, input }) => {
|
|
354
|
-
const {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
submitted: false, // Only get unsubmitted responses
|
|
361
|
-
},
|
|
362
|
-
include: {
|
|
363
|
-
responses: {
|
|
364
|
-
include: {
|
|
365
|
-
question: true,
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
});
|
|
370
|
-
// Create new response if none exists
|
|
371
|
-
if (!worksheetResponse) {
|
|
372
|
-
worksheetResponse = await prisma.studentWorksheetResponse.create({
|
|
374
|
+
const { responseId, questionId, studentWorksheetResponseId, response, isCorrect, feedback, markschemeState, points } = input;
|
|
375
|
+
let gradedResponse;
|
|
376
|
+
if (responseId) {
|
|
377
|
+
// Update existing progress by ID
|
|
378
|
+
gradedResponse = await prisma.studentQuestionProgress.update({
|
|
379
|
+
where: { id: responseId },
|
|
373
380
|
data: {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
responses: {
|
|
379
|
-
include: {
|
|
380
|
-
question: true,
|
|
381
|
-
},
|
|
382
|
-
},
|
|
381
|
+
isCorrect,
|
|
382
|
+
...(feedback !== undefined && { feedback }),
|
|
383
|
+
...(markschemeState !== undefined && { markschemeState }),
|
|
384
|
+
...(points !== undefined && { points }),
|
|
383
385
|
},
|
|
384
386
|
});
|
|
385
387
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
profilePicture: true,
|
|
406
|
-
},
|
|
407
|
-
},
|
|
408
|
-
},
|
|
388
|
+
else {
|
|
389
|
+
// Get the studentId from the worksheet response
|
|
390
|
+
const worksheetResponse = await prisma.studentWorksheetResponse.findUnique({
|
|
391
|
+
where: { id: studentWorksheetResponseId },
|
|
392
|
+
select: { studentId: true },
|
|
393
|
+
});
|
|
394
|
+
if (!worksheetResponse) {
|
|
395
|
+
throw new TRPCError({
|
|
396
|
+
code: 'NOT_FOUND',
|
|
397
|
+
message: 'Student worksheet response not found',
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
const { studentId } = worksheetResponse;
|
|
401
|
+
// Upsert - find or create the progress record
|
|
402
|
+
const existing = await prisma.studentQuestionProgress.findFirst({
|
|
403
|
+
where: {
|
|
404
|
+
studentId,
|
|
405
|
+
questionId,
|
|
406
|
+
studentWorksheetResponseId,
|
|
409
407
|
},
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
408
|
+
});
|
|
409
|
+
if (existing) {
|
|
410
|
+
// Update existing
|
|
411
|
+
gradedResponse = await prisma.studentQuestionProgress.update({
|
|
412
|
+
where: { id: existing.id },
|
|
413
|
+
data: {
|
|
414
|
+
isCorrect,
|
|
415
|
+
...(response !== undefined && { response }),
|
|
416
|
+
...(feedback !== undefined && { feedback }),
|
|
417
|
+
...(markschemeState !== undefined && { markschemeState }),
|
|
418
|
+
...(points !== undefined && { points }),
|
|
413
419
|
},
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// Create new
|
|
424
|
+
gradedResponse = await prisma.studentQuestionProgress.create({
|
|
425
|
+
data: {
|
|
426
|
+
studentId,
|
|
427
|
+
questionId,
|
|
428
|
+
studentWorksheetResponseId,
|
|
429
|
+
response: response || '',
|
|
430
|
+
isCorrect,
|
|
431
|
+
...(feedback !== undefined && { feedback }),
|
|
432
|
+
...(markschemeState !== undefined && { markschemeState }),
|
|
433
|
+
...(points !== undefined && { points: points || 0 }),
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return gradedResponse;
|
|
419
439
|
}),
|
|
420
|
-
|
|
421
|
-
gradeAnswer: protectedProcedure
|
|
440
|
+
addComment: protectedProcedure
|
|
422
441
|
.input(z.object({
|
|
423
|
-
responseId: z.string(),
|
|
424
|
-
|
|
425
|
-
feedback: z.string().optional(),
|
|
442
|
+
responseId: z.string(),
|
|
443
|
+
comment: z.string(),
|
|
426
444
|
}))
|
|
427
445
|
.mutation(async ({ ctx, input }) => {
|
|
428
|
-
const { responseId,
|
|
429
|
-
const
|
|
430
|
-
where: { id: responseId },
|
|
446
|
+
const { responseId, comment } = input;
|
|
447
|
+
const newComment = await prisma.comment.create({
|
|
431
448
|
data: {
|
|
432
|
-
|
|
433
|
-
|
|
449
|
+
studentQuestionProgressId: responseId,
|
|
450
|
+
content: comment,
|
|
451
|
+
authorId: ctx.user.id,
|
|
434
452
|
},
|
|
435
453
|
});
|
|
436
|
-
return
|
|
454
|
+
return newComment;
|
|
437
455
|
}),
|
|
438
456
|
});
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -301,14 +301,16 @@ model Comment {
|
|
|
301
301
|
content String
|
|
302
302
|
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
303
303
|
authorId String
|
|
304
|
-
announcement Announcement @relation(fields: [announcementId], references: [id], onDelete: Cascade)
|
|
305
|
-
announcementId String
|
|
304
|
+
announcement Announcement? @relation(fields: [announcementId], references: [id], onDelete: Cascade)
|
|
305
|
+
announcementId String?
|
|
306
306
|
parentComment Comment? @relation("CommentReplies", fields: [parentCommentId], references: [id], onDelete: Cascade)
|
|
307
307
|
parentCommentId String?
|
|
308
308
|
replies Comment[] @relation("CommentReplies")
|
|
309
309
|
reactions Reaction[]
|
|
310
310
|
createdAt DateTime @default(now())
|
|
311
311
|
modifiedAt DateTime? @updatedAt
|
|
312
|
+
studentQuestionProgress StudentQuestionProgress? @relation("StudentQuestionProgressComments", fields: [studentQuestionProgressId], references: [id], onDelete: Cascade)
|
|
313
|
+
studentQuestionProgressId String?
|
|
312
314
|
}
|
|
313
315
|
|
|
314
316
|
model Reaction {
|
|
@@ -517,7 +519,7 @@ model WorksheetQuestion {
|
|
|
517
519
|
answer String
|
|
518
520
|
options Json? @default("{}")
|
|
519
521
|
markScheme Json? @default("{}")
|
|
520
|
-
points Int
|
|
522
|
+
points Int @default(0)
|
|
521
523
|
order Int? @default(0)
|
|
522
524
|
createdAt DateTime @default(now())
|
|
523
525
|
updatedAt DateTime @updatedAt
|
|
@@ -547,11 +549,16 @@ model StudentQuestionProgress {
|
|
|
547
549
|
question WorksheetQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
548
550
|
response String
|
|
549
551
|
isCorrect Boolean @default(false)
|
|
552
|
+
markschemeState Json? @default("{}")
|
|
553
|
+
points Int @default(0)
|
|
554
|
+
comments Comment[] @relation("StudentQuestionProgressComments")
|
|
550
555
|
feedback String?
|
|
551
556
|
createdAt DateTime @default(now())
|
|
552
|
-
updatedAt DateTime @updatedAt
|
|
557
|
+
updatedAt DateTime? @updatedAt
|
|
553
558
|
studentWorksheetResponseId String?
|
|
554
559
|
studentWorksheetResponse StudentWorksheetResponse? @relation(fields: [studentWorksheetResponseId], references: [id], onDelete: Cascade)
|
|
560
|
+
|
|
561
|
+
@@index([studentId, questionId])
|
|
555
562
|
}
|
|
556
563
|
|
|
557
564
|
model SchoolDevelopementProgram {
|
package/src/routers/_app.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { messageRouter } from "./message.js";
|
|
|
18
18
|
import { labChatRouter } from "./labChat.js";
|
|
19
19
|
import { marketingRouter } from "./marketing.js";
|
|
20
20
|
import { worksheetRouter } from "./worksheet.js";
|
|
21
|
+
import { commentRouter } from "./comment.js";
|
|
21
22
|
|
|
22
23
|
export const appRouter = createTRPCRouter({
|
|
23
24
|
class: classRouter,
|
|
@@ -37,6 +38,7 @@ export const appRouter = createTRPCRouter({
|
|
|
37
38
|
labChat: labChatRouter,
|
|
38
39
|
marketing: marketingRouter,
|
|
39
40
|
worksheet: worksheetRouter,
|
|
41
|
+
comment: commentRouter,
|
|
40
42
|
});
|
|
41
43
|
|
|
42
44
|
// Export type router type definition
|
|
@@ -667,7 +667,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
667
667
|
// Only the author or a class teacher can delete comments
|
|
668
668
|
const userId = ctx.user.id;
|
|
669
669
|
const isAuthor = comment.authorId === userId;
|
|
670
|
-
const isClassTeacher = comment.announcement
|
|
670
|
+
const isClassTeacher = comment.announcement!.class.teachers.some(
|
|
671
671
|
(teacher) => teacher.id === userId
|
|
672
672
|
);
|
|
673
673
|
|
|
@@ -858,7 +858,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
858
858
|
});
|
|
859
859
|
}
|
|
860
860
|
|
|
861
|
-
if (comment.announcement
|
|
861
|
+
if (comment.announcement!.classId !== input.classId) {
|
|
862
862
|
throw new TRPCError({
|
|
863
863
|
code: "FORBIDDEN",
|
|
864
864
|
message: "Comment does not belong to this class",
|
|
@@ -1078,7 +1078,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
1078
1078
|
});
|
|
1079
1079
|
}
|
|
1080
1080
|
|
|
1081
|
-
if (comment.announcement
|
|
1081
|
+
if (comment.announcement!.classId !== input.classId) {
|
|
1082
1082
|
throw new TRPCError({
|
|
1083
1083
|
code: "FORBIDDEN",
|
|
1084
1084
|
message: "Comment does not belong to this class",
|