@studious-lms/server 1.0.8 → 1.1.1
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 +200 -14
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts +56 -0
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +14 -0
- package/dist/routers/class.d.ts +14 -5
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +13 -10
- package/dist/routers/event.d.ts +2 -0
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/folder.d.ts +11 -2
- package/dist/routers/folder.d.ts.map +1 -1
- package/dist/routers/folder.js +17 -6
- package/dist/routers/section.d.ts +17 -0
- package/dist/routers/section.d.ts.map +1 -1
- package/dist/routers/section.js +46 -0
- package/package.json +1 -1
- package/prisma/schema.prisma +5 -0
- package/src/routers/assignment.ts +17 -0
- package/src/routers/class.ts +16 -11
- package/src/routers/folder.ts +17 -6
- package/src/routers/section.ts +51 -0
package/dist/routers/section.js
CHANGED
|
@@ -5,11 +5,13 @@ import { prisma } from "../lib/prisma.js";
|
|
|
5
5
|
const createSectionSchema = z.object({
|
|
6
6
|
classId: z.string(),
|
|
7
7
|
name: z.string(),
|
|
8
|
+
color: z.string().optional(),
|
|
8
9
|
});
|
|
9
10
|
const updateSectionSchema = z.object({
|
|
10
11
|
id: z.string(),
|
|
11
12
|
classId: z.string(),
|
|
12
13
|
name: z.string(),
|
|
14
|
+
color: z.string().optional(),
|
|
13
15
|
});
|
|
14
16
|
const deleteSectionSchema = z.object({
|
|
15
17
|
id: z.string(),
|
|
@@ -48,6 +50,9 @@ export const sectionRouter = createTRPCRouter({
|
|
|
48
50
|
class: {
|
|
49
51
|
connect: { id: input.classId },
|
|
50
52
|
},
|
|
53
|
+
...(input.color && {
|
|
54
|
+
color: input.color,
|
|
55
|
+
}),
|
|
51
56
|
},
|
|
52
57
|
});
|
|
53
58
|
return section;
|
|
@@ -82,10 +87,51 @@ export const sectionRouter = createTRPCRouter({
|
|
|
82
87
|
where: { id: input.id },
|
|
83
88
|
data: {
|
|
84
89
|
name: input.name,
|
|
90
|
+
...(input.color && {
|
|
91
|
+
color: input.color,
|
|
92
|
+
}),
|
|
85
93
|
},
|
|
86
94
|
});
|
|
87
95
|
return section;
|
|
88
96
|
}),
|
|
97
|
+
reOrder: protectedProcedure
|
|
98
|
+
.input(z.object({
|
|
99
|
+
id: z.string(),
|
|
100
|
+
classId: z.string(),
|
|
101
|
+
order: z.number(),
|
|
102
|
+
}))
|
|
103
|
+
.mutation(async ({ ctx, input }) => {
|
|
104
|
+
if (!ctx.user) {
|
|
105
|
+
throw new TRPCError({
|
|
106
|
+
code: "UNAUTHORIZED",
|
|
107
|
+
message: "User must be authenticated",
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Verify user is a teacher of the class
|
|
111
|
+
const classData = await prisma.class.findFirst({
|
|
112
|
+
where: {
|
|
113
|
+
id: input.classId,
|
|
114
|
+
teachers: {
|
|
115
|
+
some: {
|
|
116
|
+
id: ctx.user.id,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
if (!classData) {
|
|
122
|
+
throw new TRPCError({
|
|
123
|
+
code: "NOT_FOUND",
|
|
124
|
+
message: "Class not found or you are not a teacher",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
await prisma.section.update({
|
|
128
|
+
where: { id: input.id },
|
|
129
|
+
data: {
|
|
130
|
+
order: input.order,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
return { id: input.id };
|
|
134
|
+
}),
|
|
89
135
|
delete: protectedProcedure
|
|
90
136
|
.input(deleteSectionSchema)
|
|
91
137
|
.mutation(async ({ ctx, input }) => {
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -132,6 +132,7 @@ model Folder {
|
|
|
132
132
|
childFolders Folder[] @relation("ParentChildFolders")
|
|
133
133
|
parentFolder Folder? @relation("ParentChildFolders", fields: [parentFolderId], references: [id])
|
|
134
134
|
parentFolderId String?
|
|
135
|
+
color String? @default("#3B82F6")
|
|
135
136
|
class Class? @relation("ClassFiles", fields: [classId], references: [id])
|
|
136
137
|
classId String? @unique
|
|
137
138
|
}
|
|
@@ -194,6 +195,7 @@ model Assignment {
|
|
|
194
195
|
eventId String?
|
|
195
196
|
markScheme MarkScheme? @relation(fields: [markSchemeId], references: [id], onDelete: Cascade)
|
|
196
197
|
markSchemeId String?
|
|
198
|
+
order Int?
|
|
197
199
|
gradingBoundary GradingBoundary? @relation(fields: [gradingBoundaryId], references: [id], onDelete: Cascade)
|
|
198
200
|
gradingBoundaryId String?
|
|
199
201
|
}
|
|
@@ -227,6 +229,7 @@ model Submission {
|
|
|
227
229
|
gradeReceived Int?
|
|
228
230
|
|
|
229
231
|
rubricState String?
|
|
232
|
+
teacherComments String?
|
|
230
233
|
|
|
231
234
|
submittedAt DateTime?
|
|
232
235
|
submitted Boolean? @default(false)
|
|
@@ -239,6 +242,8 @@ model Section {
|
|
|
239
242
|
classId String
|
|
240
243
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
241
244
|
assignments Assignment[]
|
|
245
|
+
color String? @default("#3B82F6")
|
|
246
|
+
order Int?
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
model Session {
|
|
@@ -84,6 +84,23 @@ const updateSubmissionSchema = z.object({
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
export const assignmentRouter = createTRPCRouter({
|
|
87
|
+
order: protectedTeacherProcedure
|
|
88
|
+
.input(z.object({
|
|
89
|
+
id: z.string(),
|
|
90
|
+
classId: z.string(),
|
|
91
|
+
order: z.number(),
|
|
92
|
+
}))
|
|
93
|
+
.mutation(async ({ ctx, input }) => {
|
|
94
|
+
const { id, order } = input;
|
|
95
|
+
|
|
96
|
+
const assignment = await prisma.assignment.update({
|
|
97
|
+
where: { id },
|
|
98
|
+
data: { order },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return assignment;
|
|
102
|
+
}),
|
|
103
|
+
|
|
87
104
|
create: protectedProcedure
|
|
88
105
|
.input(createAssignmentSchema)
|
|
89
106
|
.mutation(async ({ ctx, input }) => {
|
package/src/routers/class.ts
CHANGED
|
@@ -168,25 +168,30 @@ export const classRouter = createTRPCRouter({
|
|
|
168
168
|
},
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
+
|
|
172
|
+
if (!classData) {
|
|
173
|
+
throw new Error('Class not found');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const formattedClassData = {
|
|
177
|
+
...classData,
|
|
178
|
+
assignments: classData.assignments.map(assignment => ({
|
|
179
|
+
...assignment,
|
|
180
|
+
late: assignment.dueDate < new Date(),
|
|
181
|
+
submitted: assignment.submissions.some(submission => submission.studentId === ctx.user?.id),
|
|
182
|
+
returned: assignment.submissions.some(submission => submission.studentId === ctx.user?.id && submission.returned),
|
|
183
|
+
})),
|
|
184
|
+
}
|
|
185
|
+
|
|
171
186
|
const sections = await prisma.section.findMany({
|
|
172
187
|
where: {
|
|
173
188
|
classId: classId,
|
|
174
189
|
},
|
|
175
190
|
});
|
|
176
191
|
|
|
177
|
-
if (!classData) {
|
|
178
|
-
throw new Error('Class not found');
|
|
179
|
-
}
|
|
180
|
-
|
|
181
192
|
return {
|
|
182
193
|
class: {
|
|
183
|
-
...
|
|
184
|
-
assignments: classData.assignments.map(assignment => ({
|
|
185
|
-
...assignment,
|
|
186
|
-
late: assignment.dueDate < new Date(),
|
|
187
|
-
submitted: assignment.submissions.some(submission => submission.studentId === ctx.user?.id),
|
|
188
|
-
returned: assignment.submissions.some(submission => submission.studentId === ctx.user?.id && submission.returned),
|
|
189
|
-
})),
|
|
194
|
+
...formattedClassData,
|
|
190
195
|
sections,
|
|
191
196
|
},
|
|
192
197
|
};
|
package/src/routers/folder.ts
CHANGED
|
@@ -14,6 +14,7 @@ const fileSchema = z.object({
|
|
|
14
14
|
const createFolderSchema = z.object({
|
|
15
15
|
name: z.string(),
|
|
16
16
|
parentFolderId: z.string().optional(),
|
|
17
|
+
color: z.string().optional(),
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
const uploadFilesToFolderSchema = z.object({
|
|
@@ -29,7 +30,7 @@ export const folderRouter = createTRPCRouter({
|
|
|
29
30
|
create: protectedTeacherProcedure
|
|
30
31
|
.input(createFolderSchema)
|
|
31
32
|
.mutation(async ({ ctx, input }) => {
|
|
32
|
-
const { classId, name } = input;
|
|
33
|
+
const { classId, name, color } = input;
|
|
33
34
|
let parentFolderId = input.parentFolderId || null;
|
|
34
35
|
|
|
35
36
|
if (!ctx.user) {
|
|
@@ -75,6 +76,9 @@ export const folderRouter = createTRPCRouter({
|
|
|
75
76
|
class: {
|
|
76
77
|
connect: { id: classId },
|
|
77
78
|
},
|
|
79
|
+
...(color && {
|
|
80
|
+
color: color,
|
|
81
|
+
}),
|
|
78
82
|
},
|
|
79
83
|
});
|
|
80
84
|
}
|
|
@@ -104,6 +108,9 @@ export const folderRouter = createTRPCRouter({
|
|
|
104
108
|
connect: { id: parentFolderId },
|
|
105
109
|
},
|
|
106
110
|
}),
|
|
111
|
+
...(color && {
|
|
112
|
+
color: color,
|
|
113
|
+
}),
|
|
107
114
|
},
|
|
108
115
|
include: {
|
|
109
116
|
files: {
|
|
@@ -682,14 +689,15 @@ export const folderRouter = createTRPCRouter({
|
|
|
682
689
|
return updatedFolder;
|
|
683
690
|
}),
|
|
684
691
|
|
|
685
|
-
|
|
692
|
+
update: protectedTeacherProcedure
|
|
686
693
|
.input(z.object({
|
|
687
694
|
folderId: z.string(),
|
|
688
|
-
|
|
695
|
+
name: z.string(),
|
|
696
|
+
color: z.string().optional(),
|
|
689
697
|
classId: z.string(),
|
|
690
698
|
}))
|
|
691
699
|
.mutation(async ({ ctx, input }) => {
|
|
692
|
-
const { folderId,
|
|
700
|
+
const { folderId, name, color, classId } = input;
|
|
693
701
|
|
|
694
702
|
// Get the folder
|
|
695
703
|
const folder = await prisma.folder.findFirst({
|
|
@@ -706,7 +714,7 @@ export const folderRouter = createTRPCRouter({
|
|
|
706
714
|
}
|
|
707
715
|
|
|
708
716
|
// Validate new name
|
|
709
|
-
if (!
|
|
717
|
+
if (!name.trim()) {
|
|
710
718
|
throw new TRPCError({
|
|
711
719
|
code: "BAD_REQUEST",
|
|
712
720
|
message: "Folder name cannot be empty",
|
|
@@ -717,7 +725,10 @@ export const folderRouter = createTRPCRouter({
|
|
|
717
725
|
const updatedFolder = await prisma.folder.update({
|
|
718
726
|
where: { id: folderId },
|
|
719
727
|
data: {
|
|
720
|
-
name:
|
|
728
|
+
name: name.trim(),
|
|
729
|
+
...(color && {
|
|
730
|
+
color: color,
|
|
731
|
+
}),
|
|
721
732
|
},
|
|
722
733
|
include: {
|
|
723
734
|
files: {
|
package/src/routers/section.ts
CHANGED
|
@@ -6,12 +6,14 @@ import { prisma } from "../lib/prisma.js";
|
|
|
6
6
|
const createSectionSchema = z.object({
|
|
7
7
|
classId: z.string(),
|
|
8
8
|
name: z.string(),
|
|
9
|
+
color: z.string().optional(),
|
|
9
10
|
});
|
|
10
11
|
|
|
11
12
|
const updateSectionSchema = z.object({
|
|
12
13
|
id: z.string(),
|
|
13
14
|
classId: z.string(),
|
|
14
15
|
name: z.string(),
|
|
16
|
+
color: z.string().optional(),
|
|
15
17
|
});
|
|
16
18
|
|
|
17
19
|
const deleteSectionSchema = z.object({
|
|
@@ -55,6 +57,9 @@ export const sectionRouter = createTRPCRouter({
|
|
|
55
57
|
class: {
|
|
56
58
|
connect: { id: input.classId },
|
|
57
59
|
},
|
|
60
|
+
...(input.color && {
|
|
61
|
+
color: input.color,
|
|
62
|
+
}),
|
|
58
63
|
},
|
|
59
64
|
});
|
|
60
65
|
|
|
@@ -94,12 +99,58 @@ export const sectionRouter = createTRPCRouter({
|
|
|
94
99
|
where: { id: input.id },
|
|
95
100
|
data: {
|
|
96
101
|
name: input.name,
|
|
102
|
+
...(input.color && {
|
|
103
|
+
color: input.color,
|
|
104
|
+
}),
|
|
97
105
|
},
|
|
98
106
|
});
|
|
99
107
|
|
|
100
108
|
return section;
|
|
101
109
|
}),
|
|
102
110
|
|
|
111
|
+
reOrder: protectedProcedure
|
|
112
|
+
.input(z.object({
|
|
113
|
+
id: z.string(),
|
|
114
|
+
classId: z.string(),
|
|
115
|
+
order: z.number(),
|
|
116
|
+
}))
|
|
117
|
+
.mutation(async ({ ctx, input }) => {
|
|
118
|
+
if (!ctx.user) {
|
|
119
|
+
throw new TRPCError({
|
|
120
|
+
code: "UNAUTHORIZED",
|
|
121
|
+
message: "User must be authenticated",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Verify user is a teacher of the class
|
|
126
|
+
const classData = await prisma.class.findFirst({
|
|
127
|
+
where: {
|
|
128
|
+
id: input.classId,
|
|
129
|
+
teachers: {
|
|
130
|
+
some: {
|
|
131
|
+
id: ctx.user.id,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!classData) {
|
|
138
|
+
throw new TRPCError({
|
|
139
|
+
code: "NOT_FOUND",
|
|
140
|
+
message: "Class not found or you are not a teacher",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
await prisma.section.update({
|
|
145
|
+
where: { id: input.id },
|
|
146
|
+
data: {
|
|
147
|
+
order: input.order,
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return { id: input.id };
|
|
152
|
+
}),
|
|
153
|
+
|
|
103
154
|
delete: protectedProcedure
|
|
104
155
|
.input(deleteSectionSchema)
|
|
105
156
|
.mutation(async ({ ctx, input }) => {
|