@studious-lms/server 1.2.29 → 1.2.31

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.
@@ -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;AAGxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAga1B,CAAC"}
1
+ {"version":3,"file":"worksheet.d.ts","sourceRoot":"","sources":["../../src/routers/worksheet.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA2KA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4ShC,CAAC"}
@@ -119,6 +119,48 @@ export const worksheetRouter = createTRPCRouter({
119
119
  });
120
120
  return newQuestion;
121
121
  }),
122
+ reorderQuestions: protectedProcedure
123
+ .input(z.object({
124
+ worksheetId: z.string(),
125
+ movedId: z.string(),
126
+ position: z.enum(['before', 'after']),
127
+ targetId: z.string(),
128
+ }))
129
+ .mutation(async ({ ctx, input }) => {
130
+ const { worksheetId, movedId, position, targetId } = input;
131
+ const worksheet = await prisma.worksheet.findUnique({
132
+ where: { id: worksheetId },
133
+ });
134
+ if (!worksheet) {
135
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Worksheet not found' });
136
+ }
137
+ const questions = await prisma.worksheetQuestion.findMany({
138
+ where: { worksheetId },
139
+ orderBy: { order: 'asc' },
140
+ });
141
+ const movedIdx = questions.findIndex(question => question.id === movedId);
142
+ if (movedIdx === -1) {
143
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Moved question not found' });
144
+ }
145
+ const targetIdx = questions.findIndex(question => question.id === targetId);
146
+ if (targetIdx === -1) {
147
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Target question not found' });
148
+ }
149
+ const withoutMoved = questions.filter(question => question.id !== movedId);
150
+ let next = [];
151
+ if (position === 'before') {
152
+ next = [...withoutMoved.slice(0, targetIdx).map(item => ({ id: item.id })), { id: movedId }, ...withoutMoved.slice(targetIdx).map(item => ({ id: item.id }))];
153
+ }
154
+ else {
155
+ next = [...withoutMoved.slice(0, targetIdx + 1).map(item => ({ id: item.id })), { id: movedId }, ...withoutMoved.slice(targetIdx + 1).map(item => ({ id: item.id }))];
156
+ }
157
+ // Update the order of each question
158
+ await prisma.$transaction(next.map((item, index) => prisma.worksheetQuestion.update({
159
+ where: { id: item.id },
160
+ data: { order: index },
161
+ })));
162
+ return next;
163
+ }),
122
164
  updateQuestion: protectedProcedure
123
165
  .input(z.object({
124
166
  worksheetId: z.string(),
@@ -6,7 +6,6 @@ export declare function createUser(email: string, password: string, username: st
6
6
  password: string;
7
7
  verified: boolean;
8
8
  role: import(".prisma/client").$Enums.UserRole;
9
- profileId: string | null;
10
9
  schoolId: string | null;
11
10
  }>;
12
11
  export declare function addNotification(userId: string, title: string, content: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"seedDatabase.d.ts","sourceRoot":"","sources":["../src/seedDatabase.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,kBAuClC;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;GAOjF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;GAQnF;AAED,eAAO,MAAM,YAAY,qBAq+CxB,CAAC"}
1
+ {"version":3,"file":"seedDatabase.d.ts","sourceRoot":"","sources":["../src/seedDatabase.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,kBAuClC;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;GAOjF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;GAQnF;AAED,eAAO,MAAM,YAAY,qBAq+CxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studious-lms/server",
3
- "version": "1.2.29",
3
+ "version": "1.2.31",
4
4
  "description": "Backend server for Studious application",
5
5
  "main": "dist/exportType.js",
6
6
  "types": "dist/exportType.d.ts",
@@ -81,8 +81,6 @@ model User {
81
81
  verified Boolean @default(false)
82
82
  role UserRole @default(NONE)
83
83
 
84
- profileId String? @unique
85
-
86
84
  teacherIn Class[] @relation("UserTeacherToClass")
87
85
  studentIn Class[] @relation("UserStudentToClass")
88
86
 
@@ -90,6 +88,7 @@ model User {
90
88
  sessions Session[]
91
89
  files File[]
92
90
  assignments Assignment[]
91
+ specificAssignments Assignment[] @relation("SpecificAssignmentAssignedTo")
93
92
  events Event[]
94
93
  announcements Announcement[]
95
94
  notificationsSent Notification[] @relation("SentNotifications")
@@ -143,15 +142,16 @@ model Class {
143
142
  events Event[]
144
143
  sections Section[]
145
144
  sessions Session[]
146
- worksheets Worksheet[]
145
+ worksheets Worksheet[]
147
146
  students User[] @relation("UserStudentToClass")
148
147
  teachers User[] @relation("UserTeacherToClass")
149
- markSchemes MarkScheme[] @relation("ClassToMarkScheme")
150
- gradingBoundaries GradingBoundary[] @relation("ClassToGradingBoundary")
148
+ // markSchemes MarkScheme[] @relation("ClassToMarkScheme")
149
+ // gradingBoundaries GradingBoundary[] @relation("ClassToGradingBoundary")
151
150
  draftFiles File[] @relation("ClassDraftFiles")
152
151
  classFiles Folder? @relation("ClassFiles")
153
152
  labChats LabChat[] @relation("ClassLabChats")
154
-
153
+ markSchemes MarkScheme[]
154
+ gradingBoundaries GradingBoundary[]
155
155
  school School? @relation(fields: [schoolId], references: [id])
156
156
  schoolId String?
157
157
  }
@@ -159,7 +159,8 @@ model Class {
159
159
  model MarkScheme {
160
160
  id String @id @default(uuid())
161
161
  classId String
162
- class Class[] @relation("ClassToMarkScheme")
162
+ // class Class[] @relation("ClassToMarkScheme")
163
+ class Class? @relation(fields: [classId], references: [id], onDelete: Cascade)
163
164
  structured String
164
165
  assignments Assignment[]
165
166
  }
@@ -167,7 +168,8 @@ model MarkScheme {
167
168
  model GradingBoundary {
168
169
  id String @id @default(uuid())
169
170
  classId String
170
- class Class[] @relation("ClassToGradingBoundary")
171
+ // class Class[] @relation("ClassToGradingBoundary")
172
+ class Class? @relation(fields: [classId], references: [id], onDelete: Cascade)
171
173
  structured String
172
174
  assignments Assignment[]
173
175
  }
@@ -251,7 +253,13 @@ model Assignment {
251
253
  class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
252
254
  classId String
253
255
  attachments File[]
256
+ acceptFiles Boolean @default(false)
257
+ acceptExtendedResponse Boolean @default(false)
258
+ acceptWorksheet Boolean @default(false)
259
+ gradeWithAI Boolean @default(false)
260
+
254
261
  submissions Submission[]
262
+ assignedTo User[] @relation("SpecificAssignmentAssignedTo")
255
263
  section Section? @relation(fields: [sectionId], references: [id], onDelete: Cascade)
256
264
  sectionId String?
257
265
  graded Boolean @default(false)
@@ -333,6 +341,7 @@ model Submission {
333
341
  attachments File[] @relation("SubmissionFile")
334
342
  annotations File[] @relation("SubmissionAnnotations")
335
343
  worksheetResponses StudentWorksheetResponse[]
344
+ extendedResponse String?
336
345
 
337
346
  gradeReceived Int?
338
347
 
@@ -507,6 +516,7 @@ model WorksheetQuestion {
507
516
  answer String
508
517
  options Json? @default("{}")
509
518
  markScheme Json? @default("{}")
519
+ order Int? @default(0)
510
520
  createdAt DateTime @default(now())
511
521
  updatedAt DateTime @updatedAt
512
522
  studentResponses StudentQuestionProgress[]
@@ -25,6 +25,10 @@ const createAssignmentSchema = z.object({
25
25
  dueDate: z.string(),
26
26
  files: z.array(directFileSchema).optional(), // Use direct file schema
27
27
  existingFileIds: z.array(z.string()).optional(),
28
+ acceptFiles: z.boolean().optional(),
29
+ acceptExtendedResponse: z.boolean().optional(),
30
+ acceptWorksheet: z.boolean().optional(),
31
+ gradeWithAI: z.boolean().optional(),
28
32
  maxGrade: z.number().optional(),
29
33
  graded: z.boolean().optional(),
30
34
  weight: z.number().optional(),
@@ -42,6 +46,10 @@ const updateAssignmentSchema = z.object({
42
46
  instructions: z.string().optional(),
43
47
  dueDate: z.string().optional(),
44
48
  files: z.array(directFileSchema).optional(), // Use direct file schema
49
+ acceptFiles: z.boolean().optional(),
50
+ acceptExtendedResponse: z.boolean().optional(),
51
+ acceptWorksheet: z.boolean().optional(),
52
+ gradeWithAI: z.boolean().optional(),
45
53
  existingFileIds: z.array(z.string()).optional(),
46
54
  removedAttachments: z.array(z.string()).optional(),
47
55
  maxGrade: z.number().optional(),
@@ -307,7 +315,7 @@ export const assignmentRouter = createTRPCRouter({
307
315
  create: protectedProcedure
308
316
  .input(createAssignmentSchema)
309
317
  .mutation(async ({ ctx, input }) => {
310
- const { classId, title, instructions, dueDate, files, existingFileIds, maxGrade, graded, weight, sectionId, type, markSchemeId, gradingBoundaryId, inProgress } = input;
318
+ const { classId, title, instructions, dueDate, files, existingFileIds, acceptFiles, acceptExtendedResponse, acceptWorksheet, gradeWithAI, maxGrade, graded, weight, sectionId, type, markSchemeId, gradingBoundaryId, inProgress } = input;
311
319
 
312
320
  if (!ctx.user) {
313
321
  throw new TRPCError({
@@ -364,7 +372,11 @@ export const assignmentRouter = createTRPCRouter({
364
372
  graded,
365
373
  weight,
366
374
  type,
367
- order: 1,
375
+ acceptFiles,
376
+ acceptExtendedResponse,
377
+ acceptWorksheet,
378
+ gradeWithAI,
379
+ order: 1,
368
380
  inProgress: inProgress || false,
369
381
  class: {
370
382
  connect: { id: classId }
@@ -499,7 +511,7 @@ export const assignmentRouter = createTRPCRouter({
499
511
  update: protectedProcedure
500
512
  .input(updateAssignmentSchema)
501
513
  .mutation(async ({ ctx, input }) => {
502
- const { id, title, instructions, dueDate, files, existingFileIds, maxGrade, graded, weight, sectionId, type, inProgress } = input;
514
+ const { id, title, instructions, dueDate, files, existingFileIds, maxGrade, graded, weight, sectionId, type, inProgress, acceptFiles, acceptExtendedResponse, acceptWorksheet, gradeWithAI } = input;
503
515
 
504
516
  if (!ctx.user) {
505
517
  throw new TRPCError({
@@ -590,6 +602,10 @@ export const assignmentRouter = createTRPCRouter({
590
602
  ...(weight && { weight }),
591
603
  ...(type && { type }),
592
604
  ...(inProgress !== undefined && { inProgress }),
605
+ ...(acceptFiles !== undefined && { acceptFiles }),
606
+ ...(acceptExtendedResponse !== undefined && { acceptExtendedResponse }),
607
+ ...(acceptWorksheet !== undefined && { acceptWorksheet }),
608
+ ...(gradeWithAI !== undefined && { gradeWithAI }),
593
609
  ...(sectionId !== undefined && {
594
610
  section: sectionId ? {
595
611
  connect: { id: sectionId }
@@ -669,7 +669,9 @@ export const classRouter = createTRPCRouter({
669
669
 
670
670
  const markSchemes = await prisma.markScheme.findMany({
671
671
  where: {
672
- classId: classId,
672
+ class: {
673
+ id: classId,
674
+ },
673
675
  },
674
676
  });
675
677
 
@@ -687,7 +689,11 @@ export const classRouter = createTRPCRouter({
687
689
 
688
690
  const markScheme = await prisma.markScheme.create({
689
691
  data: {
690
- classId: classId,
692
+ class: {
693
+ connect: {
694
+ id: classId,
695
+ },
696
+ },
691
697
  structured: validatedStructure,
692
698
  },
693
699
  });
@@ -707,7 +713,14 @@ export const classRouter = createTRPCRouter({
707
713
 
708
714
  const markScheme = await prisma.markScheme.update({
709
715
  where: { id: markSchemeId },
710
- data: { structured: validatedStructure },
716
+ data: {
717
+ class: {
718
+ connect: {
719
+ id: classId,
720
+ },
721
+ },
722
+ structured: validatedStructure,
723
+ },
711
724
  });
712
725
 
713
726
  return markScheme;
@@ -735,7 +748,9 @@ export const classRouter = createTRPCRouter({
735
748
 
736
749
  const gradingBoundaries = await prisma.gradingBoundary.findMany({
737
750
  where: {
738
- classId: classId,
751
+ class: {
752
+ id: classId,
753
+ },
739
754
  },
740
755
  });
741
756
 
@@ -753,7 +768,11 @@ export const classRouter = createTRPCRouter({
753
768
 
754
769
  const gradingBoundary = await prisma.gradingBoundary.create({
755
770
  data: {
756
- classId: classId,
771
+ class: {
772
+ connect: {
773
+ id: classId,
774
+ },
775
+ },
757
776
  structured: validatedStructure,
758
777
  },
759
778
  });
@@ -773,7 +792,14 @@ export const classRouter = createTRPCRouter({
773
792
 
774
793
  const gradingBoundary = await prisma.gradingBoundary.update({
775
794
  where: { id: gradingBoundaryId },
776
- data: { structured: validatedStructure },
795
+ data: {
796
+ class: {
797
+ connect: {
798
+ id: classId,
799
+ },
800
+ },
801
+ structured: validatedStructure,
802
+ },
777
803
  });
778
804
 
779
805
  return gradingBoundary;
@@ -2,6 +2,7 @@ import { TRPCError } from "@trpc/server";
2
2
  import { createTRPCRouter, protectedProcedure } from "src/trpc";
3
3
  import { z } from "zod";
4
4
  import { prisma } from "src/lib/prisma";
5
+ import { WorksheetQuestionType } from "@prisma/client";
5
6
 
6
7
  export const worksheetRouter = createTRPCRouter({
7
8
  // Get a single worksheet with all questions
@@ -139,6 +140,61 @@ export const worksheetRouter = createTRPCRouter({
139
140
 
140
141
  return newQuestion;
141
142
  }),
143
+ reorderQuestions: protectedProcedure
144
+ .input(z.object({
145
+ worksheetId: z.string(),
146
+ movedId: z.string(),
147
+ position: z.enum(['before', 'after']),
148
+ targetId: z.string(),
149
+ }))
150
+ .mutation(async ({ ctx, input }) => {
151
+ const { worksheetId, movedId, position, targetId } = input;
152
+
153
+ const worksheet = await prisma.worksheet.findUnique({
154
+ where: { id: worksheetId },
155
+ });
156
+
157
+ if (!worksheet) {
158
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Worksheet not found' });
159
+ }
160
+
161
+ const questions = await prisma.worksheetQuestion.findMany({
162
+ where: { worksheetId },
163
+ orderBy: { order: 'asc' },
164
+ });
165
+
166
+ const movedIdx = questions.findIndex(question => question.id === movedId);
167
+ if (movedIdx === -1) {
168
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Moved question not found' });
169
+ }
170
+
171
+ const targetIdx = questions.findIndex(question => question.id === targetId);
172
+ if (targetIdx === -1) {
173
+ throw new TRPCError({ code: 'NOT_FOUND', message: 'Target question not found' });
174
+ }
175
+
176
+ const withoutMoved = questions.filter(question => question.id !== movedId);
177
+
178
+ let next: Array<{ id: string }> = [];
179
+
180
+ if (position === 'before') {
181
+ next = [...withoutMoved.slice(0, targetIdx).map(item => ({ id: item.id })), { id: movedId }, ...withoutMoved.slice(targetIdx).map(item => ({ id: item.id }))];
182
+ } else {
183
+ next = [...withoutMoved.slice(0, targetIdx + 1).map(item => ({ id: item.id })), { id: movedId }, ...withoutMoved.slice(targetIdx + 1).map(item => ({ id: item.id }))];
184
+ }
185
+
186
+ // Update the order of each question
187
+ await prisma.$transaction(
188
+ next.map((item, index) =>
189
+ prisma.worksheetQuestion.update({
190
+ where: { id: item.id },
191
+ data: { order: index },
192
+ })
193
+ )
194
+ );
195
+
196
+ return next;
197
+ }),
142
198
  updateQuestion: protectedProcedure
143
199
  .input(z.object({
144
200
  worksheetId: z.string(),