@studious-lms/server 1.9.0 → 1.12.0
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/.env.example +3 -0
- package/dist/index.js +40 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/config/cors.d.ts.map +1 -1
- package/dist/lib/config/cors.js +7 -2
- package/dist/lib/config/cors.js.map +1 -1
- package/dist/lib/config/env.d.ts +8 -0
- package/dist/lib/config/env.d.ts.map +1 -1
- package/dist/lib/config/env.js +5 -2
- package/dist/lib/config/env.js.map +1 -1
- package/dist/lib/pusher.d.ts +2 -1
- package/dist/lib/pusher.d.ts.map +1 -1
- package/dist/lib/pusher.js +4 -3
- package/dist/lib/pusher.js.map +1 -1
- package/dist/models/agenda.d.ts +6 -0
- package/dist/models/agenda.d.ts.map +1 -1
- package/dist/models/announcement.d.ts +3 -0
- package/dist/models/announcement.d.ts.map +1 -1
- package/dist/models/assignment.d.ts +61 -0
- package/dist/models/assignment.d.ts.map +1 -1
- package/dist/models/auth.d.ts +6 -0
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/class.d.ts +18 -0
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +5 -2
- package/dist/models/class.js.map +1 -1
- package/dist/models/comment.d.ts +6 -0
- package/dist/models/comment.d.ts.map +1 -1
- package/dist/models/event.d.ts +12 -0
- package/dist/models/event.d.ts.map +1 -1
- package/dist/models/file.d.ts +38 -0
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/folder.d.ts +6 -0
- package/dist/models/folder.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +6 -0
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/newtonChat.d.ts +3 -0
- package/dist/models/newtonChat.d.ts.map +1 -1
- package/dist/models/school.d.ts +3 -0
- package/dist/models/school.d.ts.map +1 -1
- package/dist/models/section.d.ts +3 -0
- package/dist/models/section.d.ts.map +1 -1
- package/dist/models/worksheet.d.ts +58 -0
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/models/worksheet.js +26 -2
- package/dist/models/worksheet.js.map +1 -1
- package/dist/routers/_app.d.ts +6400 -4078
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +6 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/admin.d.ts +190 -0
- package/dist/routers/admin.d.ts.map +1 -0
- package/dist/routers/admin.js +50 -0
- package/dist/routers/admin.js.map +1 -0
- package/dist/routers/agenda.d.ts +6 -0
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/announcement.d.ts +2 -0
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts +50 -0
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/class.d.ts +31 -0
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +5 -2
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/comment.d.ts +2 -0
- package/dist/routers/comment.d.ts.map +1 -1
- package/dist/routers/discussion.d.ts +823 -0
- package/dist/routers/discussion.d.ts.map +1 -0
- package/dist/routers/discussion.js +151 -0
- package/dist/routers/discussion.js.map +1 -0
- package/dist/routers/event.d.ts +3 -0
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/file.d.ts +4 -0
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/school.d.ts +6 -0
- package/dist/routers/school.d.ts.map +1 -1
- package/dist/routers/studentProgress.d.ts +45 -0
- package/dist/routers/studentProgress.d.ts.map +1 -1
- package/dist/routers/studentProgress.js +12 -3
- package/dist/routers/studentProgress.js.map +1 -1
- package/dist/routers/worksheet.d.ts +3 -0
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/seedDatabase.d.ts.map +1 -1
- package/dist/seedDatabase.js +1490 -1307
- package/dist/seedDatabase.js.map +1 -1
- package/dist/services/adminInstitution.d.ts +102 -0
- package/dist/services/adminInstitution.d.ts.map +1 -0
- package/dist/services/adminInstitution.js +117 -0
- package/dist/services/adminInstitution.js.map +1 -0
- package/dist/services/adminRunJob.d.ts +45 -0
- package/dist/services/adminRunJob.d.ts.map +1 -0
- package/dist/services/adminRunJob.js +41 -0
- package/dist/services/adminRunJob.js.map +1 -0
- package/dist/services/agenda.d.ts +6 -0
- package/dist/services/agenda.d.ts.map +1 -1
- package/dist/services/assignment.d.ts +50 -0
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +8 -3
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/class.d.ts +31 -0
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +14 -2
- package/dist/services/class.js.map +1 -1
- package/dist/services/comment.d.ts +2 -0
- package/dist/services/comment.d.ts.map +1 -1
- package/dist/services/discussion.d.ts +762 -0
- package/dist/services/discussion.d.ts.map +1 -0
- package/dist/services/discussion.js +625 -0
- package/dist/services/discussion.js.map +1 -0
- package/dist/services/event.d.ts +3 -0
- package/dist/services/event.d.ts.map +1 -1
- package/dist/services/file.d.ts +8 -0
- package/dist/services/file.d.ts.map +1 -1
- package/dist/services/school.d.ts +6 -0
- package/dist/services/school.d.ts.map +1 -1
- package/dist/services/studentProgress.d.ts +94 -0
- package/dist/services/studentProgress.d.ts.map +1 -1
- package/dist/services/studentProgress.js +116 -3
- package/dist/services/studentProgress.js.map +1 -1
- package/dist/services/studentProgressInferenceCache.d.ts +16 -0
- package/dist/services/studentProgressInferenceCache.d.ts.map +1 -0
- package/dist/services/studentProgressInferenceCache.js +43 -0
- package/dist/services/studentProgressInferenceCache.js.map +1 -0
- package/dist/services/worksheet.d.ts +3 -0
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +5 -5
- package/dist/services/worksheet.js.map +1 -1
- package/dist/trpc.d.ts +12 -0
- package/dist/trpc.d.ts.map +1 -1
- package/dist/trpc.js +16 -3
- package/dist/trpc.js.map +1 -1
- package/dist/utils/adminPanelAccess.d.ts +8 -0
- package/dist/utils/adminPanelAccess.d.ts.map +1 -0
- package/dist/utils/adminPanelAccess.js +44 -0
- package/dist/utils/adminPanelAccess.js.map +1 -0
- package/package.json +1 -1
- package/prisma/migrations/20260510183000_add_discussions/migration.sql +151 -0
- package/prisma/schema.prisma +97 -0
- package/src/index.ts +39 -2
- package/src/lib/config/cors.ts +5 -0
- package/src/lib/config/env.ts +3 -0
- package/src/lib/pusher.ts +2 -1
- package/src/models/class.ts +3 -0
- package/src/models/worksheet.ts +28 -0
- package/src/routers/_app.ts +4 -0
- package/src/routers/admin.ts +70 -0
- package/src/routers/class.ts +3 -0
- package/src/routers/discussion.ts +205 -0
- package/src/routers/studentProgress.ts +21 -0
- package/src/seedDatabase.ts +1713 -1361
- package/src/services/adminInstitution.ts +140 -0
- package/src/services/adminRunJob.ts +46 -0
- package/src/services/assignment.ts +11 -1
- package/src/services/class.ts +18 -0
- package/src/services/discussion.ts +701 -0
- package/src/services/studentProgress.ts +274 -11
- package/src/services/studentProgressInferenceCache.ts +64 -0
- package/src/services/worksheet.ts +4 -2
- package/src/trpc.ts +15 -0
- package/src/utils/adminPanelAccess.ts +46 -0
- package/tests/integration/routers/discussion.test.ts +253 -0
- package/tests/unit/services/discussion.test.ts +356 -0
- package/tests/unit/services/studentProgress.test.ts +168 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discussion.js","sources":["services/discussion.ts"],"sourceRoot":"/","sourcesContent":["import type { DiscussionType, Prisma, ReactionType } from \"@prisma/client\";\nimport { TRPCError } from \"@trpc/server\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { discussionChannel, pusher } from \"../lib/pusher.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { classMemberOrSchoolAdminWhere, classTeacherOrSchoolAdminWhere } from \"../models/access.js\";\nimport { sendNotification } from \"./notification.js\";\n\nconst authorSelect = {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n} as const;\n\nconst attachmentSelect = {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n uploadStatus: true,\n thumbnailId: true,\n thumbnail: { select: { id: true, path: true } },\n} as const;\n\nconst reactionCounts = {\n THUMBSUP: 0,\n CELEBRATE: 0,\n CARE: 0,\n HEART: 0,\n IDEA: 0,\n HAPPY: 0,\n} satisfies Record<ReactionType, number>;\n\nconst discussionInclude = {\n author: { select: authorSelect },\n attachments: { select: attachmentSelect },\n tags: { select: { id: true, name: true, color: true } },\n reactions: { select: { type: true, userId: true } },\n _count: { select: { replies: { where: { deletedAt: null } } } },\n} as const;\n\nconst replyInclude = {\n author: { select: authorSelect },\n attachments: { select: attachmentSelect },\n reactions: { select: { type: true, userId: true } },\n} as const;\n\nconst unclaimedAttachmentWhere = {\n assignmentId: null,\n submissionId: null,\n annotationId: null,\n classDraftId: null,\n folderId: null,\n messageId: null,\n announcementId: null,\n discussionId: null,\n discussionReplyId: null,\n} satisfies Prisma.FileWhereInput;\n\ntype DiscussionWithInclude = Prisma.DiscussionGetPayload<{ include: typeof discussionInclude }>;\ntype ReplyWithInclude = Prisma.DiscussionReplyGetPayload<{ include: typeof replyInclude }>;\n\nexport type DiscussionReplyTree = ReturnType<typeof serializeReply> & {\n children: DiscussionReplyTree[];\n};\n\nfunction summarizeReactions(reactions: { type: ReactionType; userId: string }[], userId: string) {\n const counts = { ...reactionCounts };\n for (const reaction of reactions) {\n counts[reaction.type] += 1;\n }\n return {\n counts,\n userReaction: reactions.find((reaction) => reaction.userId === userId)?.type ?? null,\n total: reactions.length,\n };\n}\n\nfunction serializeDiscussion(discussion: DiscussionWithInclude, userId: string, unreadCount = 0) {\n return {\n id: discussion.id,\n classId: discussion.classId,\n authorId: discussion.authorId,\n title: discussion.title,\n body: discussion.body,\n type: discussion.type,\n isPinned: discussion.isPinned,\n isLocked: discussion.isLocked,\n allowReplies: discussion.allowReplies,\n createdAt: discussion.createdAt,\n updatedAt: discussion.updatedAt,\n lastActivityAt: discussion.lastActivityAt,\n author: discussion.author,\n attachments: discussion.attachments,\n tags: discussion.tags,\n replyCount: discussion._count.replies,\n hasAcceptedAnswer: false,\n reactions: summarizeReactions(discussion.reactions, userId),\n unreadCount,\n };\n}\n\nfunction serializeReply(reply: ReplyWithInclude, userId: string) {\n return {\n id: reply.id,\n discussionId: reply.discussionId,\n authorId: reply.authorId,\n parentId: reply.parentId,\n body: reply.deletedAt ? \"[deleted]\" : reply.body,\n deletedAt: reply.deletedAt,\n isAcceptedAnswer: reply.isAcceptedAnswer,\n createdAt: reply.createdAt,\n modifiedAt: reply.modifiedAt,\n author: reply.author,\n attachments: reply.deletedAt ? [] : reply.attachments,\n reactions: summarizeReactions(reply.reactions, userId),\n };\n}\n\nexport function buildReplyTree(replies: ReplyWithInclude[], userId: string): DiscussionReplyTree[] {\n const byId = new Map<string, DiscussionReplyTree>();\n const roots: DiscussionReplyTree[] = [];\n\n for (const reply of replies) {\n byId.set(reply.id, { ...serializeReply(reply, userId), children: [] });\n }\n\n for (const reply of replies) {\n const node = byId.get(reply.id)!;\n if (reply.parentId && byId.has(reply.parentId)) {\n byId.get(reply.parentId)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n}\n\nfunction isWithinAuthorEditWindow(createdAt: Date) {\n return Date.now() - createdAt.getTime() <= 24 * 60 * 60 * 1000;\n}\n\nexport async function getDiscussionClassAccess(classId: string, userId: string) {\n const classData = await prisma.class.findFirst({\n where: { id: classId, ...classMemberOrSchoolAdminWhere(userId) },\n select: {\n id: true,\n name: true,\n discussionsEnabled: true,\n studentsCanCreateDiscussions: true,\n studentsCanReply: true,\n students: { where: { id: userId }, select: { id: true } },\n teachers: { where: { id: userId }, select: { id: true } },\n school: {\n select: {\n memberships: {\n where: { userId, role: \"ADMIN\", status: \"ACTIVE\" },\n select: { userId: true },\n },\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Not a member in this class\" });\n }\n if (!classData.discussionsEnabled) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Discussions are disabled for this class\" });\n }\n\n const isTeacher = classData.teachers.length > 0 || Boolean(classData.school?.memberships.length);\n const isStudent = classData.students.length > 0;\n\n return { ...classData, isTeacher, isStudent };\n}\n\nasync function getDiscussionForUser(discussionId: string, userId: string) {\n const discussion = await prisma.discussion.findUnique({\n where: { id: discussionId },\n include: {\n class: {\n select: {\n id: true,\n discussionsEnabled: true,\n studentsCanReply: true,\n teachers: { where: { id: userId }, select: { id: true } },\n students: { where: { id: userId }, select: { id: true } },\n school: {\n select: {\n memberships: {\n where: { userId, role: \"ADMIN\", status: \"ACTIVE\" },\n select: { userId: true },\n },\n },\n },\n },\n },\n },\n });\n\n if (!discussion) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Discussion not found\" });\n }\n\n const isTeacher = discussion.class.teachers.length > 0 || Boolean(discussion.class.school?.memberships.length);\n const isStudent = discussion.class.students.length > 0;\n if (!isTeacher && !isStudent) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Not a member in this class\" });\n }\n if (!discussion.class.discussionsEnabled) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Discussions are disabled for this class\" });\n }\n\n return { discussion, isTeacher, isStudent };\n}\n\nasync function claimDiscussionAttachments(\n tx: Prisma.TransactionClient,\n userId: string,\n discussionId: string,\n attachmentIds: string[] = []\n) {\n const uniqueIds = [...new Set(attachmentIds)];\n if (!uniqueIds.length) return;\n const { count } = await tx.file.updateMany({\n where: { id: { in: uniqueIds }, userId, uploadStatus: \"COMPLETED\", ...unclaimedAttachmentWhere },\n data: { discussionId },\n });\n if (count !== uniqueIds.length) {\n throw new TRPCError({ code: \"BAD_REQUEST\", message: \"Some attachments are missing, unfinished, or unavailable\" });\n }\n}\n\nasync function claimReplyAttachments(\n tx: Prisma.TransactionClient,\n userId: string,\n replyId: string,\n attachmentIds: string[] = []\n) {\n const uniqueIds = [...new Set(attachmentIds)];\n if (!uniqueIds.length) return;\n const { count } = await tx.file.updateMany({\n where: { id: { in: uniqueIds }, userId, uploadStatus: \"COMPLETED\", ...unclaimedAttachmentWhere },\n data: { discussionReplyId: replyId },\n });\n if (count !== uniqueIds.length) {\n throw new TRPCError({ code: \"BAD_REQUEST\", message: \"Some attachments are missing, unfinished, or unavailable\" });\n }\n}\n\nfunction triggerDiscussionEvent(classId: string, event: string, payload: unknown) {\n pusher.trigger(discussionChannel(classId), event, payload).catch((error) => {\n logger.error(\"Failed to trigger discussion pusher event\", { event, classId, error });\n });\n}\n\nasync function notify(receiverId: string | null | undefined, senderId: string, title: string, content: string) {\n if (!receiverId || receiverId === senderId) return;\n await sendNotification({ receiverId, title, content }).catch((error) => {\n logger.error(\"Failed to send discussion notification\", { receiverId, error });\n });\n}\n\nasync function notifyMentionedUsers(classId: string, senderId: string, body: string, link: string) {\n const usernames = [...new Set(Array.from(body.matchAll(/(^|\\s)@([a-zA-Z0-9_.-]{2,32})/g)).map((match) => match[2]))];\n if (!usernames.length) return;\n const members = await prisma.user.findMany({\n where: {\n username: { in: usernames },\n OR: [\n { teacherIn: { some: { id: classId } } },\n { studentIn: { some: { id: classId } } },\n { schoolMemberships: { some: { status: \"ACTIVE\", school: { classes: { some: { id: classId } } } } } },\n ],\n },\n select: { id: true },\n });\n await Promise.all(members.map((member) => notify(member.id, senderId, \"You were mentioned in a discussion\", link)));\n}\n\nasync function unreadCountsForDiscussions(userId: string, discussionIds: string[]) {\n if (!discussionIds.length) return new Map<string, number>();\n const reads = await prisma.discussionRead.findMany({\n where: { userId, discussionId: { in: discussionIds } },\n select: { discussionId: true, lastReadAt: true },\n });\n const readMap = new Map(reads.map((read) => [read.discussionId, read.lastReadAt]));\n const neverRead = discussionIds.filter((discussionId) => !readMap.has(discussionId));\n const readPredicates = Array.from(readMap.entries()).map(([discussionId, lastReadAt]) => ({\n discussionId,\n createdAt: { gt: lastReadAt },\n }));\n const counts = new Map<string, number>();\n\n const [neverReadCounts, readCounts] = await Promise.all([\n neverRead.length\n ? prisma.discussionReply.groupBy({\n by: [\"discussionId\"],\n where: { discussionId: { in: neverRead }, deletedAt: null, authorId: { not: userId } },\n _count: true,\n })\n : Promise.resolve([]),\n readPredicates.length\n ? prisma.discussionReply.groupBy({\n by: [\"discussionId\"],\n where: { deletedAt: null, authorId: { not: userId }, OR: readPredicates },\n _count: true,\n })\n : Promise.resolve([]),\n ]);\n\n for (const item of [...neverReadCounts, ...readCounts]) {\n counts.set(item.discussionId, item._count);\n }\n return counts;\n}\n\nexport async function listDiscussions(userId: string, input: {\n classId: string;\n tagId?: string;\n type?: DiscussionType;\n search?: string;\n sort: \"recent\" | \"activity\" | \"top\";\n cursor?: string;\n limit: number;\n}) {\n await getDiscussionClassAccess(input.classId, userId);\n const where: Prisma.DiscussionWhereInput = {\n classId: input.classId,\n ...(input.tagId ? { tags: { some: { id: input.tagId } } } : {}),\n ...(input.type ? { type: input.type } : {}),\n ...(input.search?.trim()\n ? {\n OR: [\n { title: { contains: input.search.trim(), mode: \"insensitive\" } },\n { body: { contains: input.search.trim(), mode: \"insensitive\" } },\n ],\n }\n : {}),\n };\n const orderBy: Prisma.DiscussionOrderByWithRelationInput[] =\n input.sort === \"recent\"\n ? [{ isPinned: \"desc\" }, { createdAt: \"desc\" }]\n : input.sort === \"top\"\n ? [{ isPinned: \"desc\" }, { replies: { _count: \"desc\" } }, { lastActivityAt: \"desc\" }]\n : [{ isPinned: \"desc\" }, { lastActivityAt: \"desc\" }];\n\n const items = await prisma.discussion.findMany({\n where,\n include: discussionInclude,\n orderBy,\n cursor: input.cursor ? { id: input.cursor } : undefined,\n skip: input.cursor ? 1 : 0,\n take: input.limit + 1,\n });\n const next = items.length > input.limit ? items.pop() : undefined;\n const unreadMap = await unreadCountsForDiscussions(userId, items.map((item) => item.id));\n const accepted = await prisma.discussionReply.groupBy({\n by: [\"discussionId\"],\n where: { discussionId: { in: items.map((item) => item.id) }, isAcceptedAnswer: true, deletedAt: null },\n });\n const acceptedIds = new Set(accepted.map((item) => item.discussionId));\n\n return {\n items: items.map((item) => ({\n ...serializeDiscussion(item, userId, unreadMap.get(item.id) ?? 0),\n hasAcceptedAnswer: acceptedIds.has(item.id),\n })),\n nextCursor: next?.id,\n };\n}\n\nexport async function getDiscussion(userId: string, discussionId: string) {\n const { discussion: accessDiscussion, isTeacher } = await getDiscussionForUser(discussionId, userId);\n const [discussion, replies, myReaction] = await Promise.all([\n prisma.discussion.findUniqueOrThrow({ where: { id: discussionId }, include: discussionInclude }),\n prisma.discussionReply.findMany({ where: { discussionId }, include: replyInclude, orderBy: { createdAt: \"asc\" } }),\n prisma.reaction.findUnique({ where: { userId_discussionId: { userId, discussionId } }, select: { type: true } }),\n prisma.discussionRead.upsert({\n where: { userId_discussionId: { userId, discussionId } },\n update: { lastReadAt: new Date() },\n create: { userId, discussionId },\n }),\n ]);\n const canAuthorEdit = accessDiscussion.authorId === userId && isWithinAuthorEditWindow(accessDiscussion.createdAt);\n const canReply = isTeacher || (accessDiscussion.class.studentsCanReply && !accessDiscussion.isLocked && accessDiscussion.allowReplies);\n return {\n discussion: serializeDiscussion(discussion, userId),\n replies: buildReplyTree(replies, userId),\n myReaction: myReaction?.type ?? null,\n canEdit: isTeacher || canAuthorEdit,\n canPin: isTeacher,\n canLock: isTeacher,\n canDelete: isTeacher || accessDiscussion.authorId === userId,\n canReply,\n };\n}\n\nexport async function createDiscussion(userId: string, input: {\n classId: string;\n title: string;\n body: string;\n type: DiscussionType;\n tagIds?: string[];\n attachmentIds?: string[];\n}) {\n const classData = await getDiscussionClassAccess(input.classId, userId);\n if (!classData.isTeacher && !classData.studentsCanCreateDiscussions) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Students cannot create discussions in this class\" });\n }\n if (input.type === \"ANNOUNCEMENT\" && !classData.isTeacher) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can create announcement discussions\" });\n }\n\n const discussion = await prisma.$transaction(async (tx) => {\n const created = await tx.discussion.create({\n data: {\n classId: input.classId,\n authorId: userId,\n title: input.title.trim(),\n body: input.body.trim(),\n type: input.type,\n allowReplies: input.type !== \"ANNOUNCEMENT\",\n tags: input.tagIds?.length ? { connect: input.tagIds.map((id) => ({ id })) } : undefined,\n },\n });\n await claimDiscussionAttachments(tx, userId, created.id, input.attachmentIds);\n return tx.discussion.findUniqueOrThrow({ where: { id: created.id }, include: discussionInclude });\n });\n\n triggerDiscussionEvent(input.classId, \"discussion-created\", { discussion: serializeDiscussion(discussion, userId) });\n await notifyMentionedUsers(input.classId, userId, input.body, `/class/${input.classId}/discussions/${discussion.id}`);\n return { discussion: serializeDiscussion(discussion, userId) };\n}\n\nexport async function updateDiscussion(userId: string, input: {\n discussionId: string;\n title?: string;\n body?: string;\n type?: DiscussionType;\n tagIds?: string[];\n allowReplies?: boolean;\n}) {\n const { discussion, isTeacher } = await getDiscussionForUser(input.discussionId, userId);\n if (!isTeacher && !(discussion.authorId === userId && isWithinAuthorEditWindow(discussion.createdAt))) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"You cannot edit this discussion\" });\n }\n if (input.type === \"ANNOUNCEMENT\" && !isTeacher) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can create announcement discussions\" });\n }\n const updated = await prisma.discussion.update({\n where: { id: input.discussionId },\n data: {\n ...(input.title !== undefined ? { title: input.title.trim() } : {}),\n ...(input.body !== undefined ? { body: input.body.trim() } : {}),\n ...(input.type !== undefined ? { type: input.type } : {}),\n ...(input.allowReplies !== undefined ? { allowReplies: input.allowReplies } : {}),\n ...(input.tagIds ? { tags: { set: input.tagIds.map((id) => ({ id })) } } : {}),\n },\n include: discussionInclude,\n });\n triggerDiscussionEvent(updated.classId, \"discussion-updated\", { discussion: serializeDiscussion(updated, userId) });\n return { discussion: serializeDiscussion(updated, userId) };\n}\n\nexport async function deleteDiscussion(userId: string, discussionId: string) {\n const { discussion, isTeacher } = await getDiscussionForUser(discussionId, userId);\n if (!isTeacher && discussion.authorId !== userId) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"You cannot delete this discussion\" });\n }\n await prisma.discussion.delete({ where: { id: discussionId } });\n triggerDiscussionEvent(discussion.classId, \"discussion-deleted\", { discussionId });\n return { success: true };\n}\n\nexport async function replyToDiscussion(userId: string, input: {\n discussionId: string;\n parentReplyId?: string;\n body: string;\n attachmentIds?: string[];\n}) {\n const { discussion, isTeacher } = await getDiscussionForUser(input.discussionId, userId);\n const canReply = isTeacher || (discussion.class.studentsCanReply && !discussion.isLocked && discussion.allowReplies);\n if (!canReply) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"You cannot reply to this discussion\" });\n }\n let parent: { id: string; authorId: string } | null = null;\n if (input.parentReplyId) {\n parent = await prisma.discussionReply.findFirst({\n where: { id: input.parentReplyId, discussionId: input.discussionId },\n select: { id: true, authorId: true },\n });\n if (!parent) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Parent reply not found\" });\n }\n const reply = await prisma.$transaction(async (tx) => {\n const created = await tx.discussionReply.create({\n data: {\n discussionId: input.discussionId,\n authorId: userId,\n parentId: input.parentReplyId,\n body: input.body.trim(),\n },\n });\n await claimReplyAttachments(tx, userId, created.id, input.attachmentIds);\n await tx.discussion.update({\n where: { id: input.discussionId },\n data: { lastActivityAt: new Date() },\n });\n return tx.discussionReply.findUniqueOrThrow({ where: { id: created.id }, include: replyInclude });\n });\n const link = `/class/${discussion.classId}/discussions/${discussion.id}#${reply.id}`;\n await Promise.all([\n notify(discussion.authorId, userId, \"New reply to your discussion\", link),\n notify(parent?.authorId, userId, \"New reply in a discussion thread\", link),\n notifyMentionedUsers(discussion.classId, userId, input.body, link),\n ]);\n triggerDiscussionEvent(discussion.classId, \"reply-created\", { discussionId: discussion.id, reply: serializeReply(reply, userId) });\n return { reply: serializeReply(reply, userId) };\n}\n\nexport async function updateDiscussionReply(userId: string, input: { replyId: string; body: string; attachmentIds?: string[] }) {\n const existing = await prisma.discussionReply.findUnique({ where: { id: input.replyId }, include: { discussion: true } });\n if (!existing) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Reply not found\" });\n const { isTeacher } = await getDiscussionForUser(existing.discussionId, userId);\n if (!isTeacher && !(existing.authorId === userId && isWithinAuthorEditWindow(existing.createdAt))) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"You cannot edit this reply\" });\n }\n const reply = await prisma.$transaction(async (tx) => {\n await tx.file.updateMany({ where: { discussionReplyId: input.replyId }, data: { discussionReplyId: null } });\n await claimReplyAttachments(tx, userId, input.replyId, input.attachmentIds);\n return tx.discussionReply.update({\n where: { id: input.replyId },\n data: { body: input.body.trim(), deletedAt: null },\n include: replyInclude,\n });\n });\n triggerDiscussionEvent(existing.discussion.classId, \"reply-updated\", { discussionId: existing.discussionId, reply: serializeReply(reply, userId) });\n return { reply: serializeReply(reply, userId) };\n}\n\nexport async function deleteDiscussionReply(userId: string, replyId: string) {\n const existing = await prisma.discussionReply.findUnique({ where: { id: replyId }, include: { discussion: true } });\n if (!existing) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Reply not found\" });\n const { isTeacher } = await getDiscussionForUser(existing.discussionId, userId);\n if (!isTeacher && existing.authorId !== userId) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"You cannot delete this reply\" });\n }\n const reply = await prisma.discussionReply.update({\n where: { id: replyId },\n data: { body: \"[deleted]\", deletedAt: new Date(), isAcceptedAnswer: false },\n include: replyInclude,\n });\n triggerDiscussionEvent(existing.discussion.classId, \"reply-deleted\", { discussionId: existing.discussionId, reply: serializeReply(reply, userId) });\n return { reply: serializeReply(reply, userId) };\n}\n\nexport async function pinDiscussion(userId: string, discussionId: string, isPinned: boolean) {\n const { discussion, isTeacher } = await getDiscussionForUser(discussionId, userId);\n if (!isTeacher) throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can pin discussions\" });\n const updated = await prisma.discussion.update({ where: { id: discussionId }, data: { isPinned }, include: discussionInclude });\n await notify(discussion.authorId, userId, isPinned ? \"Your discussion was pinned\" : \"Your discussion was unpinned\", `/class/${discussion.classId}/discussions/${discussionId}`);\n triggerDiscussionEvent(discussion.classId, \"discussion-updated\", { discussion: serializeDiscussion(updated, userId) });\n return { discussion: serializeDiscussion(updated, userId) };\n}\n\nexport async function lockDiscussion(userId: string, discussionId: string, isLocked: boolean) {\n const { discussion, isTeacher } = await getDiscussionForUser(discussionId, userId);\n if (!isTeacher) throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can lock discussions\" });\n const updated = await prisma.discussion.update({ where: { id: discussionId }, data: { isLocked }, include: discussionInclude });\n triggerDiscussionEvent(discussion.classId, \"discussion-updated\", { discussion: serializeDiscussion(updated, userId) });\n return { discussion: serializeDiscussion(updated, userId) };\n}\n\nexport async function markAcceptedAnswer(userId: string, replyId: string, accepted: boolean) {\n const reply = await prisma.discussionReply.findUnique({ where: { id: replyId }, include: { discussion: true } });\n if (!reply) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Reply not found\" });\n const { isTeacher } = await getDiscussionForUser(reply.discussionId, userId);\n if (reply.discussion.type !== \"QUESTION\") {\n throw new TRPCError({ code: \"BAD_REQUEST\", message: \"Only question discussions can have accepted answers\" });\n }\n if (!isTeacher && reply.discussion.authorId !== userId) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only the discussion author or a teacher can mark an accepted answer\" });\n }\n const updated = await prisma.$transaction(async (tx) => {\n if (accepted) {\n await tx.discussionReply.updateMany({ where: { discussionId: reply.discussionId, isAcceptedAnswer: true }, data: { isAcceptedAnswer: false } });\n }\n return tx.discussionReply.update({ where: { id: replyId }, data: { isAcceptedAnswer: accepted }, include: replyInclude });\n });\n await notify(reply.authorId, userId, accepted ? \"Your answer was accepted\" : \"Your answer was unmarked\", `/class/${reply.discussion.classId}/discussions/${reply.discussionId}#${replyId}`);\n triggerDiscussionEvent(reply.discussion.classId, \"reply-updated\", { discussionId: reply.discussionId, reply: serializeReply(updated, userId) });\n return { reply: serializeReply(updated, userId) };\n}\n\nexport async function markDiscussionRead(userId: string, discussionId: string) {\n await getDiscussionForUser(discussionId, userId);\n return prisma.discussionRead.upsert({\n where: { userId_discussionId: { userId, discussionId } },\n update: { lastReadAt: new Date() },\n create: { userId, discussionId },\n });\n}\n\nexport async function getUnreadCounts(userId: string, classIds: string[]) {\n const allowedClasses = await prisma.class.findMany({\n where: { id: { in: classIds }, discussionsEnabled: true, ...classMemberOrSchoolAdminWhere(userId) },\n select: { id: true },\n });\n const result: Record<string, { total: number; perDiscussion: { discussionId: string; count: number }[] }> = {};\n for (const cls of allowedClasses) {\n const discussions = await prisma.discussion.findMany({\n where: { classId: cls.id },\n select: { id: true },\n });\n const countMap = await unreadCountsForDiscussions(userId, discussions.map((discussion) => discussion.id));\n const perDiscussion = Array.from(countMap.entries())\n .map(([discussionId, count]) => ({ discussionId, count }))\n .filter((item) => item.count > 0);\n result[cls.id] = {\n total: perDiscussion.reduce((sum, item) => sum + item.count, 0),\n perDiscussion,\n };\n }\n return result;\n}\n\nexport async function toggleDiscussionReaction(userId: string, input: { discussionId?: string; discussionReplyId?: string; type: ReactionType }) {\n if (!input.discussionId && !input.discussionReplyId) {\n throw new TRPCError({ code: \"BAD_REQUEST\", message: \"A discussion or reply is required\" });\n }\n if (input.discussionId && input.discussionReplyId) {\n throw new TRPCError({ code: \"BAD_REQUEST\", message: \"React to either a discussion or a reply\" });\n }\n const target = input.discussionId\n ? await getDiscussionForUser(input.discussionId, userId).then(({ discussion }) => ({ classId: discussion.classId, discussionId: discussion.id }))\n : await prisma.discussionReply.findUnique({ where: { id: input.discussionReplyId }, include: { discussion: true } }).then(async (reply) => {\n if (!reply) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Reply not found\" });\n await getDiscussionForUser(reply.discussionId, userId);\n return { classId: reply.discussion.classId, discussionId: reply.discussionId };\n });\n const where = input.discussionId\n ? { userId_discussionId: { userId, discussionId: input.discussionId } }\n : { userId_discussionReplyId: { userId, discussionReplyId: input.discussionReplyId! } };\n const existing = await prisma.reaction.findUnique({ where });\n if (existing?.type === input.type) {\n await prisma.reaction.delete({ where: { id: existing.id } });\n triggerDiscussionEvent(target.classId, \"reaction-removed\", { discussionId: target.discussionId, discussionReplyId: input.discussionReplyId, userId });\n return { reaction: null };\n }\n const reaction = input.discussionId\n ? await prisma.reaction.upsert({\n where: { userId_discussionId: { userId, discussionId: input.discussionId } },\n update: { type: input.type },\n create: { userId, discussionId: input.discussionId, type: input.type },\n })\n : await prisma.reaction.upsert({\n where: { userId_discussionReplyId: { userId, discussionReplyId: input.discussionReplyId! } },\n update: { type: input.type },\n create: { userId, discussionReplyId: input.discussionReplyId!, type: input.type },\n });\n triggerDiscussionEvent(target.classId, \"reaction-added\", { discussionId: target.discussionId, discussionReplyId: input.discussionReplyId, reaction });\n return { reaction };\n}\n\nexport async function listDiscussionTags(userId: string, classId: string) {\n await getDiscussionClassAccess(classId, userId);\n return prisma.discussionTag.findMany({ where: { classId }, orderBy: { name: \"asc\" } });\n}\n\nexport async function createDiscussionTag(userId: string, input: { classId: string; name: string; color: string }) {\n const isTeacher = await prisma.class.findFirst({ where: { id: input.classId, ...classTeacherOrSchoolAdminWhere(userId) }, select: { id: true, discussionsEnabled: true } });\n if (!isTeacher?.discussionsEnabled) throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can manage discussion tags\" });\n return prisma.discussionTag.create({ data: { classId: input.classId, name: input.name.trim(), color: input.color } });\n}\n\nexport async function updateDiscussionTag(userId: string, input: { tagId: string; name?: string; color?: string }) {\n const tag = await prisma.discussionTag.findUnique({ where: { id: input.tagId }, select: { classId: true } });\n if (!tag) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Tag not found\" });\n const isTeacher = await prisma.class.findFirst({ where: { id: tag.classId, ...classTeacherOrSchoolAdminWhere(userId) }, select: { id: true, discussionsEnabled: true } });\n if (!isTeacher?.discussionsEnabled) throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can manage discussion tags\" });\n return prisma.discussionTag.update({ where: { id: input.tagId }, data: { name: input.name?.trim(), color: input.color } });\n}\n\nexport async function deleteDiscussionTag(userId: string, tagId: string) {\n const tag = await prisma.discussionTag.findUnique({ where: { id: tagId }, select: { classId: true } });\n if (!tag) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Tag not found\" });\n const isTeacher = await prisma.class.findFirst({ where: { id: tag.classId, ...classTeacherOrSchoolAdminWhere(userId) }, select: { id: true, discussionsEnabled: true } });\n if (!isTeacher?.discussionsEnabled) throw new TRPCError({ code: \"FORBIDDEN\", message: \"Only teachers can manage discussion tags\" });\n await prisma.discussionTag.delete({ where: { id: tagId } });\n return { success: true };\n}\n"],"names":[],"mappings":"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","debug_id":"b10e68f8-0106-57a7-be41-a32938701565"}
|
package/dist/services/event.d.ts
CHANGED
|
@@ -38,6 +38,9 @@ export declare function getEvent(userId: string, id: string): Promise<{
|
|
|
38
38
|
section: string;
|
|
39
39
|
syllabus: string | null;
|
|
40
40
|
departmentId: string | null;
|
|
41
|
+
discussionsEnabled: boolean;
|
|
42
|
+
studentsCanCreateDiscussions: boolean;
|
|
43
|
+
studentsCanReply: boolean;
|
|
41
44
|
}) | null;
|
|
42
45
|
assignmentsAttached: {
|
|
43
46
|
type: import(".prisma/client").$Enums.AssignmentType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event.d.ts","sourceRoot":"/","sources":["services/event.ts"],"names":[],"mappings":"AAmBA,6DAA6D;AAC7D,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"/","sources":["services/event.ts"],"names":[],"mappings":"AAmBA,6DAA6D;AAC7D,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAexD;AAED,wCAAwC;AACxC,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;GAwBF;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;;;;;;;;GA2BF;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;GAiBjE;AAuBD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CrB;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkBrB;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;GAkBhB"}
|
package/dist/services/file.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export declare function moveFile(fileId: string, targetFolderId: string): Promis
|
|
|
50
50
|
conversationId: string | null;
|
|
51
51
|
messageId: string | null;
|
|
52
52
|
announcementId: string | null;
|
|
53
|
+
discussionId: string | null;
|
|
54
|
+
discussionReplyId: string | null;
|
|
53
55
|
schoolDevelopementProgramId: string | null;
|
|
54
56
|
}>;
|
|
55
57
|
export declare function renameFile(fileId: string, newName: string): Promise<{
|
|
@@ -83,6 +85,8 @@ export declare function renameFile(fileId: string, newName: string): Promise<{
|
|
|
83
85
|
conversationId: string | null;
|
|
84
86
|
messageId: string | null;
|
|
85
87
|
announcementId: string | null;
|
|
88
|
+
discussionId: string | null;
|
|
89
|
+
discussionReplyId: string | null;
|
|
86
90
|
schoolDevelopementProgramId: string | null;
|
|
87
91
|
}>;
|
|
88
92
|
export declare function deleteFileRecord(fileId: string, classId: string): Promise<{
|
|
@@ -126,6 +130,8 @@ export declare function moveFileScoped(userId: string, input: {
|
|
|
126
130
|
conversationId: string | null;
|
|
127
131
|
messageId: string | null;
|
|
128
132
|
announcementId: string | null;
|
|
133
|
+
discussionId: string | null;
|
|
134
|
+
discussionReplyId: string | null;
|
|
129
135
|
schoolDevelopementProgramId: string | null;
|
|
130
136
|
}>;
|
|
131
137
|
/** Scope-aware rename. */
|
|
@@ -163,6 +169,8 @@ export declare function renameFileScoped(userId: string, input: {
|
|
|
163
169
|
conversationId: string | null;
|
|
164
170
|
messageId: string | null;
|
|
165
171
|
announcementId: string | null;
|
|
172
|
+
discussionId: string | null;
|
|
173
|
+
discussionReplyId: string | null;
|
|
166
174
|
schoolDevelopementProgramId: string | null;
|
|
167
175
|
}>;
|
|
168
176
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"/","sources":["services/file.ts"],"names":[],"mappings":"AA+CA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;GAkFpE;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"/","sources":["services/file.ts"],"names":[],"mappings":"AA+CA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;GAkFpE;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmBvB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkBhB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;GA6BrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsBlD;AAED,0BAA0B;AAC1B,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsB3C;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;GA4BrE"}
|
|
@@ -140,6 +140,9 @@ export declare function listClasses(userId: string, schoolId: string): Promise<{
|
|
|
140
140
|
section: string;
|
|
141
141
|
syllabus: string | null;
|
|
142
142
|
departmentId: string | null;
|
|
143
|
+
discussionsEnabled: boolean;
|
|
144
|
+
studentsCanCreateDiscussions: boolean;
|
|
145
|
+
studentsCanReply: boolean;
|
|
143
146
|
})[];
|
|
144
147
|
}>;
|
|
145
148
|
export declare function createSchoolClass(userId: string, input: {
|
|
@@ -178,6 +181,9 @@ export declare function createSchoolClass(userId: string, input: {
|
|
|
178
181
|
section: string;
|
|
179
182
|
syllabus: string | null;
|
|
180
183
|
departmentId: string | null;
|
|
184
|
+
discussionsEnabled: boolean;
|
|
185
|
+
studentsCanCreateDiscussions: boolean;
|
|
186
|
+
studentsCanReply: boolean;
|
|
181
187
|
};
|
|
182
188
|
}>;
|
|
183
189
|
export declare function listMembers(userId: string, schoolId: string): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAe,MAAM,gBAAgB,CAAC;AA4DnE,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyBvE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;GAcF;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;;;;;;;;GAUF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BtE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["services/school.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
type ProgressChatMessage = {
|
|
2
3
|
role: "user" | "assistant";
|
|
3
4
|
content: string;
|
|
4
5
|
};
|
|
6
|
+
declare const studentProgressInsightsSchema: z.ZodObject<{
|
|
7
|
+
summary: z.ZodString;
|
|
8
|
+
strengths: z.ZodArray<z.ZodObject<{
|
|
9
|
+
label: z.ZodString;
|
|
10
|
+
evidence: z.ZodString;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
label: string;
|
|
13
|
+
evidence: string;
|
|
14
|
+
}, {
|
|
15
|
+
label: string;
|
|
16
|
+
evidence: string;
|
|
17
|
+
}>, "many">;
|
|
18
|
+
growth: z.ZodArray<z.ZodObject<{
|
|
19
|
+
label: z.ZodString;
|
|
20
|
+
evidence: z.ZodString;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
label: string;
|
|
23
|
+
evidence: string;
|
|
24
|
+
}, {
|
|
25
|
+
label: string;
|
|
26
|
+
evidence: string;
|
|
27
|
+
}>, "many">;
|
|
28
|
+
talkingPoints: z.ZodArray<z.ZodString, "many">;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
summary: string;
|
|
31
|
+
strengths: {
|
|
32
|
+
label: string;
|
|
33
|
+
evidence: string;
|
|
34
|
+
}[];
|
|
35
|
+
growth: {
|
|
36
|
+
label: string;
|
|
37
|
+
evidence: string;
|
|
38
|
+
}[];
|
|
39
|
+
talkingPoints: string[];
|
|
40
|
+
}, {
|
|
41
|
+
summary: string;
|
|
42
|
+
strengths: {
|
|
43
|
+
label: string;
|
|
44
|
+
evidence: string;
|
|
45
|
+
}[];
|
|
46
|
+
growth: {
|
|
47
|
+
label: string;
|
|
48
|
+
evidence: string;
|
|
49
|
+
}[];
|
|
50
|
+
talkingPoints: string[];
|
|
51
|
+
}>;
|
|
52
|
+
declare const studentProgressForecastSchema: z.ZodObject<{
|
|
53
|
+
forecastLow: z.ZodNumber;
|
|
54
|
+
forecastHigh: z.ZodNumber;
|
|
55
|
+
risk: z.ZodEnum<["on_track", "watch", "at_risk"]>;
|
|
56
|
+
reason: z.ZodString;
|
|
57
|
+
}, "strip", z.ZodTypeAny, {
|
|
58
|
+
reason: string;
|
|
59
|
+
forecastLow: number;
|
|
60
|
+
forecastHigh: number;
|
|
61
|
+
risk: "on_track" | "watch" | "at_risk";
|
|
62
|
+
}, {
|
|
63
|
+
reason: string;
|
|
64
|
+
forecastLow: number;
|
|
65
|
+
forecastHigh: number;
|
|
66
|
+
risk: "on_track" | "watch" | "at_risk";
|
|
67
|
+
}>;
|
|
68
|
+
declare const studentProgressFocusSchema: z.ZodObject<{
|
|
69
|
+
focusItems: z.ZodArray<z.ZodString, "many">;
|
|
70
|
+
}, "strip", z.ZodTypeAny, {
|
|
71
|
+
focusItems: string[];
|
|
72
|
+
}, {
|
|
73
|
+
focusItems: string[];
|
|
74
|
+
}>;
|
|
75
|
+
export type StudentProgressInsights = z.infer<typeof studentProgressInsightsSchema>;
|
|
76
|
+
export type StudentProgressForecast = z.infer<typeof studentProgressForecastSchema>;
|
|
77
|
+
export type StudentProgressFocus = z.infer<typeof studentProgressFocusSchema>;
|
|
5
78
|
type RecommendationType = "missing" | "low_score" | "awaiting_feedback";
|
|
6
79
|
export declare function getStudentProgressRecommendations(viewerId: string, classId: string, studentId: string): Promise<{
|
|
7
80
|
student: {
|
|
@@ -107,6 +180,27 @@ export declare function dismissStudentRecommendation(viewerId: string, input: {
|
|
|
107
180
|
}): Promise<{
|
|
108
181
|
success: boolean;
|
|
109
182
|
}>;
|
|
183
|
+
export declare function getStudentProgressInsights(viewerId: string, classId: string, studentId: string): Promise<{
|
|
184
|
+
summary: string;
|
|
185
|
+
strengths: {
|
|
186
|
+
label: string;
|
|
187
|
+
evidence: string;
|
|
188
|
+
}[];
|
|
189
|
+
growth: {
|
|
190
|
+
label: string;
|
|
191
|
+
evidence: string;
|
|
192
|
+
}[];
|
|
193
|
+
talkingPoints: string[];
|
|
194
|
+
}>;
|
|
195
|
+
export declare function getStudentProgressForecast(viewerId: string, classId: string, studentId: string): Promise<{
|
|
196
|
+
reason: string;
|
|
197
|
+
forecastLow: number;
|
|
198
|
+
forecastHigh: number;
|
|
199
|
+
risk: "on_track" | "watch" | "at_risk";
|
|
200
|
+
}>;
|
|
201
|
+
export declare function getStudentProgressFocus(viewerId: string, classId: string, studentId: string): Promise<{
|
|
202
|
+
focusItems: string[];
|
|
203
|
+
}>;
|
|
110
204
|
export declare function chatAboutStudentProgress(viewerId: string, input: {
|
|
111
205
|
classId: string;
|
|
112
206
|
studentId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"studentProgress.d.ts","sourceRoot":"/","sources":["services/studentProgress.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"studentProgress.d.ts","sourceRoot":"/","sources":["services/studentProgress.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAgCF,QAAA,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKjC,CAAC;AAEH,QAAA,MAAM,6BAA6B;;;;;;;;;;;;;;;EAKjC,CAAC;AAEH,QAAA,MAAM,0BAA0B;;;;;;EAE9B,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,KAAK,kBAAkB,GAAG,SAAS,GAAG,WAAW,GAAG,mBAAmB,CAAC;AAwXxE,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsBlB;AAED,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2FhB;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;;GAqCF;AAyFD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;;;;;;;;;;;GA+ClB;AAED,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;;;;;GA0ClB;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM;;GA0ClB;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACjC;;;GAiGF"}
|
|
@@ -2,12 +2,33 @@
|
|
|
2
2
|
* Student progress service - assignment recommendations and progress chat.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="159c0157-8d54-553a-84a9-e84c0b152f43")}catch(e){}}();
|
|
6
6
|
import { TRPCError } from "@trpc/server";
|
|
7
|
+
import { z } from "zod";
|
|
7
8
|
import { prisma } from "../lib/prisma.js";
|
|
8
9
|
import { isTeacherInClass } from "../models/class.js";
|
|
9
10
|
import { inference } from "../utils/inference.js";
|
|
10
11
|
import { logger } from "../utils/logger.js";
|
|
12
|
+
import { getStudentProgressInferenceCacheHit, setStudentProgressInferenceCache, } from "./studentProgressInferenceCache.js";
|
|
13
|
+
const insightItemSchema = z.object({
|
|
14
|
+
label: z.string(),
|
|
15
|
+
evidence: z.string(),
|
|
16
|
+
});
|
|
17
|
+
const studentProgressInsightsSchema = z.object({
|
|
18
|
+
summary: z.string(),
|
|
19
|
+
strengths: z.array(insightItemSchema).min(2).max(4),
|
|
20
|
+
growth: z.array(insightItemSchema).min(2).max(4),
|
|
21
|
+
talkingPoints: z.array(z.string()).min(3).max(5),
|
|
22
|
+
});
|
|
23
|
+
const studentProgressForecastSchema = z.object({
|
|
24
|
+
forecastLow: z.number().min(0).max(100),
|
|
25
|
+
forecastHigh: z.number().min(0).max(100),
|
|
26
|
+
risk: z.enum(["on_track", "watch", "at_risk"]),
|
|
27
|
+
reason: z.string(),
|
|
28
|
+
});
|
|
29
|
+
const studentProgressFocusSchema = z.object({
|
|
30
|
+
focusItems: z.array(z.string()).min(3).max(5),
|
|
31
|
+
});
|
|
11
32
|
function calculatePercentage(submission) {
|
|
12
33
|
if (submission.gradeReceived == null || !submission.assignment.maxGrade) {
|
|
13
34
|
return null;
|
|
@@ -407,6 +428,94 @@ function buildProgressSummary(submissions) {
|
|
|
407
428
|
section: submission.assignment.section?.name ?? null,
|
|
408
429
|
}));
|
|
409
430
|
}
|
|
431
|
+
function buildStructuredProgressContext(classData, student, submissions) {
|
|
432
|
+
const displayName = student.profile?.displayName ?? student.username;
|
|
433
|
+
const recommendationSummary = summarizeStudentRecommendations(student, submissions);
|
|
434
|
+
return {
|
|
435
|
+
class: classData,
|
|
436
|
+
student: { id: student.id, username: student.username, displayName },
|
|
437
|
+
progress: {
|
|
438
|
+
overallGrade: getOverallGrade(submissions),
|
|
439
|
+
trend: calculateTrend(submissions),
|
|
440
|
+
summary: recommendationSummary.summary,
|
|
441
|
+
assignments: buildProgressSummary(submissions),
|
|
442
|
+
recommendations: recommendationSummary.recommendations.map((recommendation) => ({
|
|
443
|
+
title: recommendation.title,
|
|
444
|
+
recommendationType: recommendation.recommendationType,
|
|
445
|
+
percentage: recommendation.percentage,
|
|
446
|
+
submitted: recommendation.submitted,
|
|
447
|
+
reasons: recommendation.reasons,
|
|
448
|
+
sectionName: recommendation.sectionName,
|
|
449
|
+
})),
|
|
450
|
+
},
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function buildStructuredInferenceMessages(instruction, context) {
|
|
454
|
+
return [
|
|
455
|
+
{
|
|
456
|
+
role: "system",
|
|
457
|
+
content: "You are an educational progress analyst. Use only the provided class and grade context. Be specific, concise, supportive, and do not fabricate assignments, grades, or sections.",
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
role: "user",
|
|
461
|
+
content: JSON.stringify(context),
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
role: "user",
|
|
465
|
+
content: instruction,
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
}
|
|
469
|
+
const studentProgressInsightsCache = new Map();
|
|
470
|
+
const studentProgressForecastCache = new Map();
|
|
471
|
+
const studentProgressFocusCache = new Map();
|
|
472
|
+
export async function getStudentProgressInsights(viewerId, classId, studentId) {
|
|
473
|
+
const cached = getStudentProgressInferenceCacheHit(studentProgressInsightsCache, classId, studentId);
|
|
474
|
+
const { classData, student, submissions } = await loadStudentProgressContext(viewerId, classId, studentId);
|
|
475
|
+
if (cached !== undefined) {
|
|
476
|
+
return cached;
|
|
477
|
+
}
|
|
478
|
+
const context = buildStructuredProgressContext(classData, student, submissions);
|
|
479
|
+
const value = await inference(buildStructuredInferenceMessages([
|
|
480
|
+
"Generate an AI analytics summary for this one student's dashboard.",
|
|
481
|
+
"The summary must be 2-4 plain-prose sentences: lead with overall grade and trajectory, then call out one strength and one concern with assignment titles.",
|
|
482
|
+
"Strengths and growth items need 2-6 word labels and one-line evidence grounded in assignment titles or sections.",
|
|
483
|
+
"Talking points must be 3-5 specific teacher check-in prompts with no numbering.",
|
|
484
|
+
].join(" "), context), studentProgressInsightsSchema, {
|
|
485
|
+
reason: "student_progress_insights",
|
|
486
|
+
metadata: { viewerId, classId, studentId },
|
|
487
|
+
});
|
|
488
|
+
setStudentProgressInferenceCache(studentProgressInsightsCache, classId, studentId, value);
|
|
489
|
+
return value;
|
|
490
|
+
}
|
|
491
|
+
export async function getStudentProgressForecast(viewerId, classId, studentId) {
|
|
492
|
+
const cached = getStudentProgressInferenceCacheHit(studentProgressForecastCache, classId, studentId);
|
|
493
|
+
const { classData, student, submissions } = await loadStudentProgressContext(viewerId, classId, studentId);
|
|
494
|
+
if (cached !== undefined) {
|
|
495
|
+
return cached;
|
|
496
|
+
}
|
|
497
|
+
const context = buildStructuredProgressContext(classData, student, submissions);
|
|
498
|
+
const value = await inference(buildStructuredInferenceMessages("Predict the student's next graded assignment percentage band and risk status. Base the forecast on trajectory, missing work, low scores, and assignment recency. Keep the reason to one sentence.", context), studentProgressForecastSchema, {
|
|
499
|
+
reason: "student_progress_forecast",
|
|
500
|
+
metadata: { viewerId, classId, studentId },
|
|
501
|
+
});
|
|
502
|
+
setStudentProgressInferenceCache(studentProgressForecastCache, classId, studentId, value);
|
|
503
|
+
return value;
|
|
504
|
+
}
|
|
505
|
+
export async function getStudentProgressFocus(viewerId, classId, studentId) {
|
|
506
|
+
const cached = getStudentProgressInferenceCacheHit(studentProgressFocusCache, classId, studentId);
|
|
507
|
+
const { classData, student, submissions } = await loadStudentProgressContext(viewerId, classId, studentId);
|
|
508
|
+
if (cached !== undefined) {
|
|
509
|
+
return cached;
|
|
510
|
+
}
|
|
511
|
+
const context = buildStructuredProgressContext(classData, student, submissions);
|
|
512
|
+
const value = await inference(buildStructuredInferenceMessages("Generate 3-5 student-facing weekly focus items. Each item should be specific, actionable, and grounded in the student's grade pattern or assignment titles. No numbering in the strings.", context), studentProgressFocusSchema, {
|
|
513
|
+
reason: "student_progress_focus",
|
|
514
|
+
metadata: { viewerId, classId, studentId },
|
|
515
|
+
});
|
|
516
|
+
setStudentProgressInferenceCache(studentProgressFocusCache, classId, studentId, value);
|
|
517
|
+
return value;
|
|
518
|
+
}
|
|
410
519
|
export async function chatAboutStudentProgress(viewerId, input) {
|
|
411
520
|
const { classData, student, submissions } = await loadStudentProgressContext(viewerId, input.classId, input.studentId);
|
|
412
521
|
const displayName = student.profile?.displayName ?? student.username;
|
|
@@ -437,7 +546,11 @@ export async function chatAboutStudentProgress(viewerId, input) {
|
|
|
437
546
|
try {
|
|
438
547
|
const response = await inference(messages, undefined, {
|
|
439
548
|
reason: "student_progress_chat",
|
|
440
|
-
metadata: {
|
|
549
|
+
metadata: {
|
|
550
|
+
viewerId,
|
|
551
|
+
classId: input.classId,
|
|
552
|
+
studentId: input.studentId,
|
|
553
|
+
},
|
|
441
554
|
});
|
|
442
555
|
if (typeof response !== "string" || response.trim().length === 0) {
|
|
443
556
|
throw new Error("Student progress chat returned an empty response");
|
|
@@ -481,4 +594,4 @@ export async function chatAboutStudentProgress(viewerId, input) {
|
|
|
481
594
|
}
|
|
482
595
|
}
|
|
483
596
|
//# sourceMappingURL=studentProgress.js.map
|
|
484
|
-
//# debugId=
|
|
597
|
+
//# debugId=159c0157-8d54-553a-84a9-e84c0b152f43
|