@studious-lms/server 1.4.2 → 1.4.3
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/.coderabbit.yaml +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/fileUpload.d.ts +10 -2
- package/dist/lib/fileUpload.d.ts.map +1 -1
- package/dist/lib/fileUpload.js +38 -6
- package/dist/lib/fileUpload.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +18 -5
- package/dist/middleware/auth.js.map +1 -1
- package/dist/models/auth.d.ts +19 -14
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/auth.js +53 -30
- package/dist/models/auth.js.map +1 -1
- package/dist/models/class.d.ts +3 -1
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +16 -4
- package/dist/models/class.js.map +1 -1
- package/dist/models/notification.d.ts +11 -10
- package/dist/models/notification.d.ts.map +1 -1
- package/dist/models/notification.js +13 -9
- package/dist/models/notification.js.map +1 -1
- package/dist/models/worksheet.d.ts +378 -7
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/models/worksheet.js +168 -2
- package/dist/models/worksheet.js.map +1 -1
- package/dist/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/pipelines/aiLabChat.js +11 -3
- package/dist/pipelines/aiLabChat.js.map +1 -1
- package/dist/pipelines/aiLabChatContract.d.ts +3 -3
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
- package/dist/pipelines/aiNewtonChat.js +25 -14
- package/dist/pipelines/aiNewtonChat.js.map +1 -1
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/pipelines/gradeWorksheet.js +10 -3
- package/dist/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/routers/_app.d.ts +124 -18
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/class.d.ts +2 -1
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +3 -3
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/labChat.d.ts +6 -0
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +5 -3
- package/dist/routers/labChat.js.map +1 -1
- package/dist/routers/message.d.ts +31 -0
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/message.js +27 -4
- package/dist/routers/message.js.map +1 -1
- package/dist/routers/newtonChat.d.ts +6 -0
- package/dist/routers/newtonChat.d.ts.map +1 -1
- package/dist/routers/newtonChat.js +5 -4
- package/dist/routers/newtonChat.js.map +1 -1
- package/dist/routers/notifications.d.ts +9 -2
- package/dist/routers/notifications.d.ts.map +1 -1
- package/dist/routers/notifications.js +4 -4
- package/dist/routers/notifications.js.map +1 -1
- package/dist/routers/worksheet.d.ts +8 -6
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +18 -16
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/services/auth.d.ts +1 -1
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +19 -12
- package/dist/services/auth.js.map +1 -1
- package/dist/services/class.d.ts +1 -1
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +6 -3
- package/dist/services/class.js.map +1 -1
- package/dist/services/file.d.ts.map +1 -1
- package/dist/services/file.js +7 -2
- package/dist/services/file.js.map +1 -1
- package/dist/services/labChat.d.ts +6 -0
- package/dist/services/labChat.d.ts.map +1 -1
- package/dist/services/labChat.js +30 -18
- package/dist/services/labChat.js.map +1 -1
- package/dist/services/message.d.ts +30 -0
- package/dist/services/message.d.ts.map +1 -1
- package/dist/services/message.js +97 -21
- package/dist/services/message.js.map +1 -1
- package/dist/services/newtonChat.d.ts +6 -1
- package/dist/services/newtonChat.d.ts.map +1 -1
- package/dist/services/newtonChat.js +36 -18
- package/dist/services/newtonChat.js.map +1 -1
- package/dist/services/notification.d.ts +12 -5
- package/dist/services/notification.d.ts.map +1 -1
- package/dist/services/notification.js +24 -9
- package/dist/services/notification.js.map +1 -1
- package/dist/services/studentProgress.d.ts.map +1 -1
- package/dist/services/studentProgress.js +6 -3
- package/dist/services/studentProgress.js.map +1 -1
- package/dist/services/worksheet.d.ts +15 -15
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +138 -54
- package/dist/services/worksheet.js.map +1 -1
- package/dist/trpc.d.ts.map +1 -1
- package/dist/trpc.js +11 -17
- package/dist/trpc.js.map +1 -1
- package/dist/utils/inference.d.ts +9 -1
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +138 -50
- package/dist/utils/inference.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260415103500_add_session_type/migration.sql +33 -0
- package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +19 -0
- package/prisma/schema.prisma +27 -1
- package/scripts/test-pre-push.ts +6 -2
- package/src/index.ts +80 -28
- package/src/lib/fileUpload.ts +55 -5
- package/src/middleware/auth.ts +19 -4
- package/src/models/auth.ts +59 -29
- package/src/models/class.ts +15 -4
- package/src/models/notification.ts +13 -7
- package/src/models/worksheet.ts +202 -0
- package/src/pipelines/aiLabChat.ts +9 -1
- package/src/pipelines/aiNewtonChat.ts +24 -14
- package/src/pipelines/gradeWorksheet.ts +8 -0
- package/src/routers/class.ts +2 -2
- package/src/routers/labChat.ts +3 -1
- package/src/routers/message.ts +38 -1
- package/src/routers/newtonChat.ts +4 -2
- package/src/routers/notifications.ts +2 -2
- package/src/routers/worksheet.ts +31 -19
- package/src/services/auth.ts +26 -12
- package/src/services/class.ts +4 -1
- package/src/services/file.ts +6 -0
- package/src/services/labChat.ts +42 -18
- package/src/services/message.ts +163 -18
- package/src/services/newtonChat.ts +49 -18
- package/src/services/notification.ts +27 -8
- package/src/services/studentProgress.ts +4 -1
- package/src/services/worksheet.ts +191 -51
- package/src/trpc.ts +12 -18
- package/src/utils/inference.ts +209 -55
- package/tests/globalSetup.ts +13 -4
- package/tests/routers/auth.test.ts +120 -17
- package/tests/routers/class.test.ts +7 -1
- package/tests/routers/message.test.ts +236 -9
- package/tests/routers/newtonChat.test.ts +81 -0
- package/tests/routers/notification.test.ts +12 -0
- package/tests/routers/worksheet.test.ts +194 -0
- package/tests/setup.ts +22 -5
- package/tests/utils/inference.test.ts +218 -0
package/src/models/worksheet.ts
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
import { prisma } from "../lib/prisma.js";
|
|
5
5
|
import type { WorksheetQuestionType, GenerationStatus } from "@prisma/client";
|
|
6
6
|
|
|
7
|
+
const worksheetClassMemberWhere = (userId: string) => ({
|
|
8
|
+
class: {
|
|
9
|
+
OR: [
|
|
10
|
+
{ teachers: { some: { id: userId } } },
|
|
11
|
+
{ students: { some: { id: userId } } },
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const worksheetTeacherWhere = (userId: string) => ({
|
|
17
|
+
class: {
|
|
18
|
+
teachers: { some: { id: userId } },
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
7
22
|
/** @returns Worksheet with questions and class. */
|
|
8
23
|
export function findWorksheetById(id: string) {
|
|
9
24
|
return prisma.worksheet.findUnique({
|
|
@@ -22,6 +37,34 @@ export function findWorksheetByIdMinimal(id: string) {
|
|
|
22
37
|
});
|
|
23
38
|
}
|
|
24
39
|
|
|
40
|
+
/** @returns Worksheet by ID for an authorized class member. */
|
|
41
|
+
export function findWorksheetByIdForClassMember(id: string, userId: string) {
|
|
42
|
+
return prisma.worksheet.findFirst({
|
|
43
|
+
where: {
|
|
44
|
+
id,
|
|
45
|
+
...worksheetClassMemberWhere(userId),
|
|
46
|
+
},
|
|
47
|
+
include: {
|
|
48
|
+
questions: { orderBy: { createdAt: "asc" as const } },
|
|
49
|
+
class: true,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @returns Worksheet by ID for an authorized teacher. */
|
|
55
|
+
export function findWorksheetByIdForTeacher(id: string, userId: string) {
|
|
56
|
+
return prisma.worksheet.findFirst({
|
|
57
|
+
where: {
|
|
58
|
+
id,
|
|
59
|
+
...worksheetTeacherWhere(userId),
|
|
60
|
+
},
|
|
61
|
+
include: {
|
|
62
|
+
questions: { orderBy: { createdAt: "asc" as const } },
|
|
63
|
+
class: true,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
25
68
|
/** @returns Worksheets for a class. */
|
|
26
69
|
export function findWorksheetsByClassId(classId: string) {
|
|
27
70
|
return prisma.worksheet.findMany({
|
|
@@ -33,6 +76,26 @@ export function findWorksheetsByClassId(classId: string) {
|
|
|
33
76
|
});
|
|
34
77
|
}
|
|
35
78
|
|
|
79
|
+
/** @returns Worksheet question by ID for an authorized teacher. */
|
|
80
|
+
export function findWorksheetQuestionByIdForTeacher(id: string, userId: string) {
|
|
81
|
+
return prisma.worksheetQuestion.findFirst({
|
|
82
|
+
where: {
|
|
83
|
+
id,
|
|
84
|
+
worksheet: worksheetTeacherWhere(userId),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** @returns Worksheet question scoped to a worksheet. */
|
|
90
|
+
export function findWorksheetQuestionByIdInWorksheet(
|
|
91
|
+
id: string,
|
|
92
|
+
worksheetId: string
|
|
93
|
+
) {
|
|
94
|
+
return prisma.worksheetQuestion.findFirst({
|
|
95
|
+
where: { id, worksheetId },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
36
99
|
/** Create a worksheet. */
|
|
37
100
|
export function createWorksheet(data: { classId: string; name: string }) {
|
|
38
101
|
return prisma.worksheet.create({
|
|
@@ -118,6 +181,45 @@ export function findSubmissionById(id: string) {
|
|
|
118
181
|
});
|
|
119
182
|
}
|
|
120
183
|
|
|
184
|
+
/** @returns Submission if requester is the owning student or a class teacher for the worksheet. */
|
|
185
|
+
export function findSubmissionByIdForWorksheetAccess(
|
|
186
|
+
id: string,
|
|
187
|
+
worksheetId: string,
|
|
188
|
+
worksheetClassId: string,
|
|
189
|
+
userId: string
|
|
190
|
+
) {
|
|
191
|
+
return prisma.submission.findFirst({
|
|
192
|
+
where: {
|
|
193
|
+
id,
|
|
194
|
+
assignment: {
|
|
195
|
+
classId: worksheetClassId,
|
|
196
|
+
worksheets: { some: { id: worksheetId } },
|
|
197
|
+
},
|
|
198
|
+
OR: [
|
|
199
|
+
{
|
|
200
|
+
studentId: userId,
|
|
201
|
+
assignment: {
|
|
202
|
+
class: {
|
|
203
|
+
students: { some: { id: userId } },
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
assignment: {
|
|
209
|
+
class: {
|
|
210
|
+
teachers: { some: { id: userId } },
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
select: {
|
|
217
|
+
id: true,
|
|
218
|
+
studentId: true,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
121
223
|
const worksheetResponseInclude = {
|
|
122
224
|
responses: {
|
|
123
225
|
include: {
|
|
@@ -182,6 +284,29 @@ export function findWorksheetResponseById(id: string) {
|
|
|
182
284
|
});
|
|
183
285
|
}
|
|
184
286
|
|
|
287
|
+
/** @returns Worksheet response if requester is the owning student. */
|
|
288
|
+
export function findWorksheetResponseByIdForStudent(id: string, userId: string) {
|
|
289
|
+
return prisma.studentWorksheetResponse.findFirst({
|
|
290
|
+
where: {
|
|
291
|
+
id,
|
|
292
|
+
studentId: userId,
|
|
293
|
+
worksheet: worksheetClassMemberWhere(userId),
|
|
294
|
+
},
|
|
295
|
+
include: { responses: true, worksheet: true },
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** @returns Worksheet response if requester is a class teacher. */
|
|
300
|
+
export function findWorksheetResponseByIdForTeacher(id: string, userId: string) {
|
|
301
|
+
return prisma.studentWorksheetResponse.findFirst({
|
|
302
|
+
where: {
|
|
303
|
+
id,
|
|
304
|
+
worksheet: worksheetTeacherWhere(userId),
|
|
305
|
+
},
|
|
306
|
+
include: { responses: true, worksheet: true },
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
185
310
|
/** @returns Worksheet response with question responses. */
|
|
186
311
|
export function findWorksheetResponseWithResponses(
|
|
187
312
|
id: string,
|
|
@@ -197,6 +322,43 @@ export function findWorksheetResponseWithResponses(
|
|
|
197
322
|
});
|
|
198
323
|
}
|
|
199
324
|
|
|
325
|
+
/** @returns Worksheet response with scoped responses if requester is the owning student. */
|
|
326
|
+
export function findWorksheetResponseWithResponsesForStudent(
|
|
327
|
+
id: string,
|
|
328
|
+
userId: string,
|
|
329
|
+
questionId?: string
|
|
330
|
+
) {
|
|
331
|
+
return prisma.studentWorksheetResponse.findFirst({
|
|
332
|
+
where: {
|
|
333
|
+
id,
|
|
334
|
+
studentId: userId,
|
|
335
|
+
worksheet: worksheetClassMemberWhere(userId),
|
|
336
|
+
},
|
|
337
|
+
include: {
|
|
338
|
+
worksheet: true,
|
|
339
|
+
responses: questionId ? { where: { questionId } } : true,
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** @returns Worksheet response with scoped responses if requester is a class teacher. */
|
|
345
|
+
export function findWorksheetResponseWithResponsesForTeacher(
|
|
346
|
+
id: string,
|
|
347
|
+
userId: string,
|
|
348
|
+
questionId?: string
|
|
349
|
+
) {
|
|
350
|
+
return prisma.studentWorksheetResponse.findFirst({
|
|
351
|
+
where: {
|
|
352
|
+
id,
|
|
353
|
+
worksheet: worksheetTeacherWhere(userId),
|
|
354
|
+
},
|
|
355
|
+
include: {
|
|
356
|
+
worksheet: true,
|
|
357
|
+
responses: questionId ? { where: { questionId } } : true,
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
200
362
|
/** @returns Worksheet question by ID. */
|
|
201
363
|
export function findWorksheetQuestionById(id: string) {
|
|
202
364
|
return prisma.worksheetQuestion.findUnique({
|
|
@@ -204,6 +366,46 @@ export function findWorksheetQuestionById(id: string) {
|
|
|
204
366
|
});
|
|
205
367
|
}
|
|
206
368
|
|
|
369
|
+
/** @returns Student question progress if requester is a class teacher. */
|
|
370
|
+
export function findStudentQuestionProgressByIdForTeacher(
|
|
371
|
+
id: string,
|
|
372
|
+
userId: string
|
|
373
|
+
) {
|
|
374
|
+
return prisma.studentQuestionProgress.findFirst({
|
|
375
|
+
where: {
|
|
376
|
+
id,
|
|
377
|
+
question: {
|
|
378
|
+
worksheet: worksheetTeacherWhere(userId),
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
include: {
|
|
382
|
+
question: true,
|
|
383
|
+
studentWorksheetResponse: true,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/** @returns Student question progress by id and worksheet response if requester is a class teacher. */
|
|
389
|
+
export function findStudentQuestionProgressByIdForTeacherAndResponse(
|
|
390
|
+
id: string,
|
|
391
|
+
studentWorksheetResponseId: string,
|
|
392
|
+
userId: string
|
|
393
|
+
) {
|
|
394
|
+
return prisma.studentQuestionProgress.findFirst({
|
|
395
|
+
where: {
|
|
396
|
+
id,
|
|
397
|
+
studentWorksheetResponseId,
|
|
398
|
+
question: {
|
|
399
|
+
worksheet: worksheetTeacherWhere(userId),
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
include: {
|
|
403
|
+
question: true,
|
|
404
|
+
studentWorksheetResponse: true,
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
207
409
|
/** Update student's question progress. */
|
|
208
410
|
export function updateStudentQuestionProgress(
|
|
209
411
|
id: string,
|
|
@@ -479,7 +479,15 @@ export const generateAndSendLabIntroduction = async (
|
|
|
479
479
|
// });
|
|
480
480
|
|
|
481
481
|
const response = await withTimeout(
|
|
482
|
-
inference<LabChatResponse>(messages, labChatResponseSchema
|
|
482
|
+
inference<LabChatResponse>(messages, labChatResponseSchema, {
|
|
483
|
+
reason: 'lab_chat_response',
|
|
484
|
+
metadata: {
|
|
485
|
+
labChatId,
|
|
486
|
+
conversationId,
|
|
487
|
+
classId: fullLabChat.classId,
|
|
488
|
+
...(emitOptions?.messageId ? { messageId: emitOptions.messageId } : {}),
|
|
489
|
+
},
|
|
490
|
+
}),
|
|
483
491
|
LAB_CHAT_RESPONSE_TIMEOUT_MS,
|
|
484
492
|
"Lab chat response generation",
|
|
485
493
|
);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Uses assignment context and AI policy levels for tutoring.
|
|
4
4
|
*/
|
|
5
5
|
import { prisma } from "../lib/prisma.js";
|
|
6
|
-
import { inference
|
|
6
|
+
import { inference } from "../utils/inference.js";
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
8
|
import { sendAIMessage } from "../utils/inference.js";
|
|
9
9
|
import { isAIUser } from "../utils/aiUser.js";
|
|
@@ -132,20 +132,23 @@ export const generateAndSendNewtonIntroduction = async (
|
|
|
132
132
|
|
|
133
133
|
Do not use markdown formatting in your responses - use plain text only.`;
|
|
134
134
|
|
|
135
|
-
const
|
|
135
|
+
const response = await inference<string>([
|
|
136
|
+
{ role: 'system', content: systemPrompt },
|
|
137
|
+
{
|
|
138
|
+
role: 'user',
|
|
139
|
+
content: 'Please introduce yourself to the student. Explain that you are Newton, their AI tutor, and you are here to help them with their assignment. Ask them what they would like help with.'
|
|
140
|
+
},
|
|
141
|
+
], undefined, {
|
|
142
|
+
reason: 'newton_chat_introduction',
|
|
143
|
+
metadata: {
|
|
144
|
+
newtonChatId,
|
|
145
|
+
conversationId,
|
|
146
|
+
submissionId: submission.id,
|
|
147
|
+
},
|
|
136
148
|
model: 'command-a-03-2025',
|
|
137
|
-
|
|
138
|
-
{ role: 'system', content: systemPrompt },
|
|
139
|
-
{
|
|
140
|
-
role: 'user',
|
|
141
|
-
content: 'Please introduce yourself to the student. Explain that you are Newton, their AI tutor, and you are here to help them with their assignment. Ask them what they would like help with.'
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
max_tokens: 300,
|
|
149
|
+
maxTokens: 300,
|
|
145
150
|
temperature: 0.8,
|
|
146
151
|
});
|
|
147
|
-
|
|
148
|
-
const response = completion.choices[0]?.message?.content;
|
|
149
152
|
|
|
150
153
|
if (!response) {
|
|
151
154
|
throw new Error('No response generated from inference API');
|
|
@@ -320,7 +323,14 @@ export const generateAndSendNewtonIntroduction = async (
|
|
|
320
323
|
content: `SYSTEM: ${formatAssignmentString(assignmentData)}`,
|
|
321
324
|
});
|
|
322
325
|
|
|
323
|
-
const response = await inference<string>(messages
|
|
326
|
+
const response = await inference<string>(messages, undefined, {
|
|
327
|
+
reason: 'newton_chat_response',
|
|
328
|
+
metadata: {
|
|
329
|
+
newtonChatId,
|
|
330
|
+
conversationId,
|
|
331
|
+
submissionId: submission.id,
|
|
332
|
+
},
|
|
333
|
+
});
|
|
324
334
|
|
|
325
335
|
if (!response) {
|
|
326
336
|
throw new Error('No response generated from inference API');
|
|
@@ -344,4 +354,4 @@ export const generateAndSendNewtonIntroduction = async (
|
|
|
344
354
|
});
|
|
345
355
|
}
|
|
346
356
|
}
|
|
347
|
-
|
|
357
|
+
|
|
@@ -97,6 +97,14 @@ const gradeWorksheetQuestion = async (worksheetResponseId: string, worksheetQues
|
|
|
97
97
|
})), // @note: this has to be converted to [id: string]: correct boolean
|
|
98
98
|
comments: z.array(z.string()),
|
|
99
99
|
}),
|
|
100
|
+
{
|
|
101
|
+
reason: 'worksheet_autograde',
|
|
102
|
+
metadata: {
|
|
103
|
+
worksheetResponseId: worksheetResponse.id,
|
|
104
|
+
questionId: worksheetQuestionProgressId,
|
|
105
|
+
studentId: worksheetResponse.studentId,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
100
108
|
).catch((error) => {
|
|
101
109
|
logger.error('Failed to grade worksheet response', { error });
|
|
102
110
|
throw error;
|
package/src/routers/class.ts
CHANGED
|
@@ -46,7 +46,7 @@ export const classRouter = createTRPCRouter({
|
|
|
46
46
|
getAllClasses(ctx.user?.id ?? "")
|
|
47
47
|
),
|
|
48
48
|
|
|
49
|
-
get:
|
|
49
|
+
get: protectedClassMemberProcedure
|
|
50
50
|
.input(z.object({ classId: z.string() }))
|
|
51
51
|
.query(({ ctx, input }) =>
|
|
52
52
|
getClass(ctx.user?.id ?? "", input.classId)
|
|
@@ -329,4 +329,4 @@ export const classRouter = createTRPCRouter({
|
|
|
329
329
|
.mutation(({ ctx, input }) =>
|
|
330
330
|
importClass(input.classId, ctx.user?.id ?? "", input.year, input.classData)
|
|
331
331
|
),
|
|
332
|
-
});
|
|
332
|
+
});
|
package/src/routers/labChat.ts
CHANGED
|
@@ -38,8 +38,9 @@ export const labChatRouter = createTRPCRouter({
|
|
|
38
38
|
.input(
|
|
39
39
|
z.object({
|
|
40
40
|
labChatId: z.string(),
|
|
41
|
-
content: z.string().
|
|
41
|
+
content: z.string().max(4000),
|
|
42
42
|
mentionedUserIds: z.array(z.string()).optional(),
|
|
43
|
+
fileIds: z.array(z.string()).max(10).optional(),
|
|
43
44
|
})
|
|
44
45
|
)
|
|
45
46
|
.mutation(({ ctx, input }) =>
|
|
@@ -47,6 +48,7 @@ export const labChatRouter = createTRPCRouter({
|
|
|
47
48
|
labChatId: input.labChatId,
|
|
48
49
|
content: input.content,
|
|
49
50
|
mentionedUserIds: input.mentionedUserIds,
|
|
51
|
+
fileIds: input.fileIds,
|
|
50
52
|
})
|
|
51
53
|
),
|
|
52
54
|
|
package/src/routers/message.ts
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
sendMessage,
|
|
6
6
|
updateMessage,
|
|
7
7
|
deleteMessage,
|
|
8
|
+
getMessageUploadUrls,
|
|
9
|
+
confirmMessageUpload,
|
|
8
10
|
markAsRead,
|
|
9
11
|
markMentionsAsRead,
|
|
10
12
|
markSuggestionCreated,
|
|
@@ -32,8 +34,9 @@ export const messageRouter = createTRPCRouter({
|
|
|
32
34
|
.input(
|
|
33
35
|
z.object({
|
|
34
36
|
conversationId: z.string(),
|
|
35
|
-
content: z.string().
|
|
37
|
+
content: z.string().max(4000),
|
|
36
38
|
mentionedUserIds: z.array(z.string()).optional(),
|
|
39
|
+
fileIds: z.array(z.string()).max(10).optional(),
|
|
37
40
|
})
|
|
38
41
|
)
|
|
39
42
|
.mutation(({ ctx, input }) =>
|
|
@@ -41,9 +44,43 @@ export const messageRouter = createTRPCRouter({
|
|
|
41
44
|
conversationId: input.conversationId,
|
|
42
45
|
content: input.content,
|
|
43
46
|
mentionedUserIds: input.mentionedUserIds,
|
|
47
|
+
fileIds: input.fileIds,
|
|
44
48
|
})
|
|
45
49
|
),
|
|
46
50
|
|
|
51
|
+
getUploadUrls: protectedProcedure
|
|
52
|
+
.input(
|
|
53
|
+
z.object({
|
|
54
|
+
conversationId: z.string(),
|
|
55
|
+
files: z
|
|
56
|
+
.array(
|
|
57
|
+
z.object({
|
|
58
|
+
name: z.string().min(1),
|
|
59
|
+
type: z.string().min(1),
|
|
60
|
+
size: z.number().int().nonnegative(),
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
.min(1)
|
|
64
|
+
.max(10),
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
.mutation(({ ctx, input }) =>
|
|
68
|
+
getMessageUploadUrls(ctx.user!.id, input)
|
|
69
|
+
),
|
|
70
|
+
|
|
71
|
+
confirmUpload: protectedProcedure
|
|
72
|
+
.input(
|
|
73
|
+
z.object({
|
|
74
|
+
conversationId: z.string(),
|
|
75
|
+
fileId: z.string(),
|
|
76
|
+
uploadSuccess: z.boolean(),
|
|
77
|
+
errorMessage: z.string().optional(),
|
|
78
|
+
})
|
|
79
|
+
)
|
|
80
|
+
.mutation(({ ctx, input }) =>
|
|
81
|
+
confirmMessageUpload(ctx.user!.id, input)
|
|
82
|
+
),
|
|
83
|
+
|
|
47
84
|
update: protectedProcedure
|
|
48
85
|
.input(
|
|
49
86
|
z.object({
|
|
@@ -21,8 +21,9 @@ export const newtonChatRouter = createTRPCRouter({
|
|
|
21
21
|
.input(
|
|
22
22
|
z.object({
|
|
23
23
|
newtonChatId: z.string(),
|
|
24
|
-
content: z.string().
|
|
24
|
+
content: z.string().max(4000),
|
|
25
25
|
mentionedUserIds: z.array(z.string()).optional(),
|
|
26
|
+
fileIds: z.array(z.string()).max(10).optional(),
|
|
26
27
|
})
|
|
27
28
|
)
|
|
28
29
|
.mutation(({ ctx, input }) =>
|
|
@@ -30,7 +31,8 @@ export const newtonChatRouter = createTRPCRouter({
|
|
|
30
31
|
ctx.user!.id,
|
|
31
32
|
input.newtonChatId,
|
|
32
33
|
input.content,
|
|
33
|
-
input.mentionedUserIds ?? []
|
|
34
|
+
input.mentionedUserIds ?? [],
|
|
35
|
+
input.fileIds ?? []
|
|
34
36
|
)
|
|
35
37
|
),
|
|
36
38
|
});
|
|
@@ -15,7 +15,7 @@ export const notificationRouter = createTRPCRouter({
|
|
|
15
15
|
|
|
16
16
|
get: protectedProcedure
|
|
17
17
|
.input(z.object({ id: z.string() }))
|
|
18
|
-
.query(({ input }) => getNotification(input.id)),
|
|
18
|
+
.query(({ ctx, input }) => getNotification(ctx.user!.id, input.id)),
|
|
19
19
|
|
|
20
20
|
sendTo: protectedProcedure
|
|
21
21
|
.input(
|
|
@@ -39,5 +39,5 @@ export const notificationRouter = createTRPCRouter({
|
|
|
39
39
|
|
|
40
40
|
markAsRead: protectedProcedure
|
|
41
41
|
.input(z.object({ id: z.string() }))
|
|
42
|
-
.mutation(({ input }) => markAsRead(input.id)),
|
|
42
|
+
.mutation(({ ctx, input }) => markAsRead(ctx.user!.id, input.id)),
|
|
43
43
|
});
|
package/src/routers/worksheet.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
createTRPCRouter,
|
|
4
4
|
protectedClassMemberProcedure,
|
|
5
5
|
protectedProcedure,
|
|
6
|
+
protectedTeacherProcedure,
|
|
6
7
|
} from "../trpc.js";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
import {
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
export const worksheetRouter = createTRPCRouter({
|
|
28
29
|
getWorksheet: protectedProcedure
|
|
29
30
|
.input(z.object({ worksheetId: z.string() }))
|
|
30
|
-
.query(({ input }) => getWorksheet(input.worksheetId)),
|
|
31
|
+
.query(({ ctx, input }) => getWorksheet(input.worksheetId, ctx.user!.id)),
|
|
31
32
|
|
|
32
33
|
exists: protectedClassMemberProcedure
|
|
33
34
|
.input(z.object({ id: z.string() }))
|
|
@@ -41,21 +42,25 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
41
42
|
return worksheetExists(input.id);
|
|
42
43
|
}),
|
|
43
44
|
|
|
44
|
-
listWorksheets:
|
|
45
|
+
listWorksheets: protectedClassMemberProcedure
|
|
45
46
|
.input(z.object({ classId: z.string() }))
|
|
46
47
|
.query(({ input }) => listWorksheets(input.classId)),
|
|
47
48
|
|
|
48
49
|
updateWorksheet: protectedProcedure
|
|
49
50
|
.input(z.object({ worksheetId: z.string(), name: z.string().optional() }))
|
|
50
|
-
.mutation(({ input }) =>
|
|
51
|
-
updateWorksheetRecord(input.worksheetId,
|
|
51
|
+
.mutation(({ ctx, input }) =>
|
|
52
|
+
updateWorksheetRecord(input.worksheetId, ctx.user!.id, {
|
|
53
|
+
name: input.name,
|
|
54
|
+
})
|
|
52
55
|
),
|
|
53
56
|
|
|
54
57
|
deleteWorksheet: protectedProcedure
|
|
55
58
|
.input(z.object({ worksheetId: z.string() }))
|
|
56
|
-
.mutation(({ input }) =>
|
|
59
|
+
.mutation(({ ctx, input }) =>
|
|
60
|
+
deleteWorksheetRecord(input.worksheetId, ctx.user!.id)
|
|
61
|
+
),
|
|
57
62
|
|
|
58
|
-
create:
|
|
63
|
+
create: protectedTeacherProcedure
|
|
59
64
|
.input(z.object({ classId: z.string(), name: z.string() }))
|
|
60
65
|
.mutation(({ input }) =>
|
|
61
66
|
createWorksheetRecord(input.classId, input.name)
|
|
@@ -80,8 +85,8 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
80
85
|
]),
|
|
81
86
|
})
|
|
82
87
|
)
|
|
83
|
-
.mutation(({ input }) =>
|
|
84
|
-
addQuestionToWorksheet(input.worksheetId, {
|
|
88
|
+
.mutation(({ ctx, input }) =>
|
|
89
|
+
addQuestionToWorksheet(input.worksheetId, ctx.user!.id, {
|
|
85
90
|
question: input.question,
|
|
86
91
|
answer: input.answer,
|
|
87
92
|
points: input.points,
|
|
@@ -100,9 +105,10 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
100
105
|
targetId: z.string(),
|
|
101
106
|
})
|
|
102
107
|
)
|
|
103
|
-
.mutation(({ input }) =>
|
|
108
|
+
.mutation(({ ctx, input }) =>
|
|
104
109
|
reorderWorksheetQuestions(
|
|
105
110
|
input.worksheetId,
|
|
111
|
+
ctx.user!.id,
|
|
106
112
|
input.movedId,
|
|
107
113
|
input.position,
|
|
108
114
|
input.targetId
|
|
@@ -131,10 +137,11 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
131
137
|
.optional(),
|
|
132
138
|
})
|
|
133
139
|
)
|
|
134
|
-
.mutation(({ input }) =>
|
|
140
|
+
.mutation(({ ctx, input }) =>
|
|
135
141
|
updateWorksheetQuestionRecord(
|
|
136
142
|
input.worksheetId,
|
|
137
143
|
input.questionId,
|
|
144
|
+
ctx.user!.id,
|
|
138
145
|
{
|
|
139
146
|
question: input.question,
|
|
140
147
|
answer: input.answer,
|
|
@@ -153,8 +160,12 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
153
160
|
questionId: z.string(),
|
|
154
161
|
})
|
|
155
162
|
)
|
|
156
|
-
.mutation(({ input }) =>
|
|
157
|
-
deleteWorksheetQuestionRecord(
|
|
163
|
+
.mutation(({ ctx, input }) =>
|
|
164
|
+
deleteWorksheetQuestionRecord(
|
|
165
|
+
input.worksheetId,
|
|
166
|
+
input.questionId,
|
|
167
|
+
ctx.user!.id
|
|
168
|
+
)
|
|
158
169
|
),
|
|
159
170
|
|
|
160
171
|
getWorksheetSubmission: protectedProcedure
|
|
@@ -164,8 +175,8 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
164
175
|
submissionId: z.string(),
|
|
165
176
|
})
|
|
166
177
|
)
|
|
167
|
-
.query(({ input }) =>
|
|
168
|
-
getWorksheetSubmission(input.worksheetId, input.submissionId)
|
|
178
|
+
.query(({ ctx, input }) =>
|
|
179
|
+
getWorksheetSubmission(input.worksheetId, input.submissionId, ctx.user!.id)
|
|
169
180
|
),
|
|
170
181
|
|
|
171
182
|
answerQuestion: protectedProcedure
|
|
@@ -192,8 +203,8 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
192
203
|
progressId: z.string(),
|
|
193
204
|
})
|
|
194
205
|
)
|
|
195
|
-
.mutation(({ input }) =>
|
|
196
|
-
cancelGrading(input.worksheetResponseId, input.progressId)
|
|
206
|
+
.mutation(({ ctx, input }) =>
|
|
207
|
+
cancelGrading(input.worksheetResponseId, input.progressId, ctx.user!.id)
|
|
197
208
|
),
|
|
198
209
|
|
|
199
210
|
regradeQuestion: protectedProcedure
|
|
@@ -203,8 +214,8 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
203
214
|
progressId: z.string(),
|
|
204
215
|
})
|
|
205
216
|
)
|
|
206
|
-
.mutation(({ input }) =>
|
|
207
|
-
regradeQuestion(input.worksheetResponseId, input.progressId)
|
|
217
|
+
.mutation(({ ctx, input }) =>
|
|
218
|
+
regradeQuestion(input.worksheetResponseId, input.progressId, ctx.user!.id)
|
|
208
219
|
),
|
|
209
220
|
|
|
210
221
|
gradeAnswer: protectedProcedure
|
|
@@ -220,10 +231,11 @@ export const worksheetRouter = createTRPCRouter({
|
|
|
220
231
|
points: z.number().optional(),
|
|
221
232
|
})
|
|
222
233
|
)
|
|
223
|
-
.mutation(({ input }) =>
|
|
234
|
+
.mutation(({ ctx, input }) =>
|
|
224
235
|
gradeAnswer(
|
|
225
236
|
input.questionId,
|
|
226
237
|
input.studentWorksheetResponseId,
|
|
238
|
+
ctx.user!.id,
|
|
227
239
|
{
|
|
228
240
|
responseId: input.responseId,
|
|
229
241
|
response: input.response,
|