@studious-lms/server 1.2.53 → 1.4.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/.coderabbit.yaml +9 -0
- package/.env.example +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/config/env.d.ts +21 -0
- package/dist/lib/config/env.d.ts.map +1 -1
- package/dist/lib/config/env.js +8 -2
- package/dist/lib/config/env.js.map +1 -1
- package/dist/lib/fileUpload.d.ts.map +1 -1
- package/dist/lib/fileUpload.js +2 -2
- package/dist/lib/fileUpload.js.map +1 -1
- package/dist/lib/googleCloudStorage.d.ts +6 -0
- package/dist/lib/googleCloudStorage.d.ts.map +1 -1
- package/dist/lib/googleCloudStorage.js +19 -2
- package/dist/lib/googleCloudStorage.js.map +1 -1
- package/dist/lib/pusher.d.ts +4 -1
- package/dist/lib/pusher.d.ts.map +1 -1
- package/dist/lib/pusher.js +6 -3
- package/dist/lib/pusher.js.map +1 -1
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +53 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/thumbnailGenerator.d.ts +0 -21
- package/dist/lib/thumbnailGenerator.d.ts.map +1 -1
- package/dist/lib/thumbnailGenerator.js +157 -160
- package/dist/lib/thumbnailGenerator.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +33 -95
- package/dist/middleware/auth.js.map +1 -1
- package/dist/models/agenda.d.ts +97 -0
- package/dist/models/agenda.d.ts.map +1 -0
- package/dist/models/agenda.js +40 -0
- package/dist/models/agenda.js.map +1 -0
- package/dist/models/announcement.d.ts +223 -0
- package/dist/models/announcement.d.ts.map +1 -0
- package/dist/models/announcement.js +120 -0
- package/dist/models/announcement.js.map +1 -0
- package/dist/models/assignment.d.ts +1292 -0
- package/dist/models/assignment.d.ts.map +1 -0
- package/dist/models/assignment.js +309 -0
- package/dist/models/assignment.js.map +1 -0
- package/dist/models/attendance.d.ts +180 -0
- package/dist/models/attendance.d.ts.map +1 -0
- package/dist/models/attendance.js +188 -0
- package/dist/models/attendance.js.map +1 -0
- package/dist/models/auth.d.ts +153 -0
- package/dist/models/auth.d.ts.map +1 -0
- package/dist/models/auth.js +217 -0
- package/dist/models/auth.js.map +1 -0
- package/dist/models/class.d.ts +461 -0
- package/dist/models/class.d.ts.map +1 -0
- package/dist/models/class.js +645 -0
- package/dist/models/class.js.map +1 -0
- package/dist/models/comment.d.ts +171 -0
- package/dist/models/comment.d.ts.map +1 -0
- package/dist/models/comment.js +138 -0
- package/dist/models/comment.js.map +1 -0
- package/dist/models/conversation.d.ts +164 -0
- package/dist/models/conversation.d.ts.map +1 -0
- package/dist/models/conversation.js +175 -0
- package/dist/models/conversation.js.map +1 -0
- package/dist/models/event.d.ts +295 -0
- package/dist/models/event.d.ts.map +1 -0
- package/dist/models/event.js +145 -0
- package/dist/models/event.js.map +1 -0
- package/dist/models/file.d.ts +536 -0
- package/dist/models/file.d.ts.map +1 -0
- package/dist/models/file.js +126 -0
- package/dist/models/file.js.map +1 -0
- package/dist/models/folder.d.ts +295 -0
- package/dist/models/folder.d.ts.map +1 -0
- package/dist/models/folder.js +202 -0
- package/dist/models/folder.js.map +1 -0
- package/dist/models/labChat.d.ts +243 -0
- package/dist/models/labChat.d.ts.map +1 -0
- package/dist/models/labChat.js +204 -0
- package/dist/models/labChat.js.map +1 -0
- package/dist/models/marketing.d.ts +72 -0
- package/dist/models/marketing.d.ts.map +1 -0
- package/dist/models/marketing.js +26 -0
- package/dist/models/marketing.js.map +1 -0
- package/dist/models/message.d.ts +100 -0
- package/dist/models/message.d.ts.map +1 -0
- package/dist/models/message.js +131 -0
- package/dist/models/message.js.map +1 -0
- package/dist/models/newtonChat.d.ts +72 -0
- package/dist/models/newtonChat.d.ts.map +1 -0
- package/dist/models/newtonChat.js +61 -0
- package/dist/models/newtonChat.js.map +1 -0
- package/dist/models/notification.d.ts +65 -0
- package/dist/models/notification.d.ts.map +1 -0
- package/dist/models/notification.js +46 -0
- package/dist/models/notification.js.map +1 -0
- package/dist/models/section.d.ts +102 -0
- package/dist/models/section.d.ts.map +1 -0
- package/dist/models/section.js +83 -0
- package/dist/models/section.js.map +1 -0
- package/dist/models/user.d.ts +39 -0
- package/dist/models/user.d.ts.map +1 -0
- package/dist/models/user.js +38 -0
- package/dist/models/user.js.map +1 -0
- package/dist/models/worksheet.d.ts +460 -0
- package/dist/models/worksheet.d.ts.map +1 -0
- package/dist/models/worksheet.js +200 -0
- package/dist/models/worksheet.js.map +1 -0
- package/dist/pipelines/aiLabChat.d.ts +76 -0
- package/dist/pipelines/aiLabChat.d.ts.map +1 -0
- package/dist/pipelines/aiLabChat.js +599 -0
- package/dist/pipelines/aiLabChat.js.map +1 -0
- package/dist/pipelines/aiNewtonChat.d.ts +30 -0
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -0
- package/dist/pipelines/aiNewtonChat.js +289 -0
- package/dist/pipelines/aiNewtonChat.js.map +1 -0
- package/dist/pipelines/gradeWorksheet.d.ts +30 -0
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -0
- package/dist/pipelines/gradeWorksheet.js +252 -0
- package/dist/pipelines/gradeWorksheet.js.map +1 -0
- package/dist/routers/_app.d.ts +1523 -1315
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/agenda.d.ts +22 -22
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/agenda.js +4 -65
- package/dist/routers/agenda.js.map +1 -1
- package/dist/routers/announcement.d.ts +16 -16
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/announcement.js +37 -446
- package/dist/routers/announcement.js.map +1 -1
- package/dist/routers/assignment.d.ts +300 -378
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +78 -1868
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/attendance.d.ts +19 -9
- package/dist/routers/attendance.d.ts.map +1 -1
- package/dist/routers/attendance.js +7 -264
- package/dist/routers/attendance.js.map +1 -1
- package/dist/routers/auth.d.ts +2 -2
- package/dist/routers/auth.d.ts.map +1 -1
- package/dist/routers/auth.js +29 -354
- package/dist/routers/auth.js.map +1 -1
- package/dist/routers/class.d.ts +160 -68
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +82 -1052
- package/dist/routers/class.js.map +1 -1
- package/dist/routers/comment.d.ts +6 -42
- package/dist/routers/comment.d.ts.map +1 -1
- package/dist/routers/comment.js +24 -244
- package/dist/routers/comment.js.map +1 -1
- package/dist/routers/conversation.d.ts +45 -7
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/conversation.js +19 -327
- package/dist/routers/conversation.js.map +1 -1
- package/dist/routers/event.d.ts +36 -36
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/event.js +13 -433
- package/dist/routers/event.js.map +1 -1
- package/dist/routers/file.d.ts +2 -2
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/file.js +9 -323
- package/dist/routers/file.js.map +1 -1
- package/dist/routers/folder.d.ts +21 -14
- package/dist/routers/folder.d.ts.map +1 -1
- package/dist/routers/folder.js +34 -745
- package/dist/routers/folder.js.map +1 -1
- package/dist/routers/labChat.d.ts +21 -11
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +22 -570
- package/dist/routers/labChat.js.map +1 -1
- package/dist/routers/marketing.d.ts +1 -1
- package/dist/routers/marketing.d.ts.map +1 -1
- package/dist/routers/marketing.js +7 -56
- package/dist/routers/marketing.js.map +1 -1
- package/dist/routers/message.d.ts +13 -2
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/message.js +32 -520
- package/dist/routers/message.js.map +1 -1
- package/dist/routers/newtonChat.d.ts +1 -1
- package/dist/routers/newtonChat.d.ts.map +1 -1
- package/dist/routers/newtonChat.js +7 -246
- package/dist/routers/newtonChat.js.map +1 -1
- package/dist/routers/notifications.d.ts +4 -4
- package/dist/routers/notifications.d.ts.map +1 -1
- package/dist/routers/notifications.js +18 -83
- package/dist/routers/notifications.js.map +1 -1
- package/dist/routers/section.d.ts +4 -4
- package/dist/routers/section.d.ts.map +1 -1
- package/dist/routers/section.js +14 -286
- package/dist/routers/section.js.map +1 -1
- package/dist/routers/user.d.ts +1 -1
- package/dist/routers/user.d.ts.map +1 -1
- package/dist/routers/user.js +32 -207
- package/dist/routers/user.js.map +1 -1
- package/dist/routers/worksheet.d.ts +68 -55
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +79 -394
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/seedDatabase.d.ts +1 -1
- package/dist/server/pipelines/gradeWorksheet.d.ts +6 -6
- package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/server/pipelines/gradeWorksheet.js +12 -5
- package/dist/server/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/services/agenda.d.ts +100 -0
- package/dist/services/agenda.d.ts.map +1 -0
- package/dist/services/agenda.js +21 -0
- package/dist/services/agenda.js.map +1 -0
- package/dist/services/announcement.d.ts +135 -0
- package/dist/services/announcement.d.ts.map +1 -0
- package/dist/services/announcement.js +223 -0
- package/dist/services/announcement.js.map +1 -0
- package/dist/services/assignment.d.ts +1462 -0
- package/dist/services/assignment.d.ts.map +1 -0
- package/dist/services/assignment.js +898 -0
- package/dist/services/assignment.js.map +1 -0
- package/dist/services/attendance.d.ts +93 -0
- package/dist/services/attendance.d.ts.map +1 -0
- package/dist/services/attendance.js +61 -0
- package/dist/services/attendance.js.map +1 -0
- package/dist/services/auth.d.ts +68 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +218 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/services/class.d.ts +643 -0
- package/dist/services/class.d.ts.map +1 -0
- package/dist/services/class.js +486 -0
- package/dist/services/class.js.map +1 -0
- package/dist/services/comment.d.ts +100 -0
- package/dist/services/comment.d.ts.map +1 -0
- package/dist/services/comment.js +83 -0
- package/dist/services/comment.js.map +1 -0
- package/dist/services/conversation.d.ts +159 -0
- package/dist/services/conversation.d.ts.map +1 -0
- package/dist/services/conversation.js +138 -0
- package/dist/services/conversation.js.map +1 -0
- package/dist/services/event.d.ts +216 -0
- package/dist/services/event.d.ts.map +1 -0
- package/dist/services/event.js +168 -0
- package/dist/services/event.js.map +1 -0
- package/dist/services/file.d.ts +74 -0
- package/dist/services/file.d.ts.map +1 -0
- package/dist/services/file.js +133 -0
- package/dist/services/file.js.map +1 -0
- package/dist/services/folder.d.ts +239 -0
- package/dist/services/folder.d.ts.map +1 -0
- package/dist/services/folder.js +248 -0
- package/dist/services/folder.js.map +1 -0
- package/dist/services/labChat.d.ts +169 -0
- package/dist/services/labChat.d.ts.map +1 -0
- package/dist/services/labChat.js +381 -0
- package/dist/services/labChat.js.map +1 -0
- package/dist/services/marketing.d.ts +50 -0
- package/dist/services/marketing.d.ts.map +1 -0
- package/dist/services/marketing.js +32 -0
- package/dist/services/marketing.js.map +1 -0
- package/dist/services/message.d.ts +103 -0
- package/dist/services/message.d.ts.map +1 -0
- package/dist/services/message.js +422 -0
- package/dist/services/message.js.map +1 -0
- package/dist/services/newtonChat.d.ts +22 -0
- package/dist/services/newtonChat.d.ts.map +1 -0
- package/dist/services/newtonChat.js +174 -0
- package/dist/services/newtonChat.js.map +1 -0
- package/dist/services/notification.d.ts +65 -0
- package/dist/services/notification.d.ts.map +1 -0
- package/dist/services/notification.js +33 -0
- package/dist/services/notification.js.map +1 -0
- package/dist/services/section.d.ts +53 -0
- package/dist/services/section.d.ts.map +1 -0
- package/dist/services/section.js +199 -0
- package/dist/services/section.js.map +1 -0
- package/dist/services/user.d.ts +48 -0
- package/dist/services/user.d.ts.map +1 -0
- package/dist/services/user.js +141 -0
- package/dist/services/user.js.map +1 -0
- package/dist/services/worksheet.d.ts +239 -0
- package/dist/services/worksheet.d.ts.map +1 -0
- package/dist/services/worksheet.js +235 -0
- package/dist/services/worksheet.js.map +1 -0
- package/dist/utils/aiUser.d.ts +1 -3
- package/dist/utils/aiUser.d.ts.map +1 -1
- package/dist/utils/aiUser.js +6 -5
- package/dist/utils/aiUser.js.map +1 -1
- package/dist/utils/email.d.ts +3 -0
- package/dist/utils/email.d.ts.map +1 -1
- package/dist/utils/email.js +7 -4
- package/dist/utils/email.js.map +1 -1
- package/dist/utils/generateInviteCode.d.ts +1 -2
- package/dist/utils/generateInviteCode.d.ts.map +1 -1
- package/dist/utils/generateInviteCode.js +3 -4
- package/dist/utils/generateInviteCode.js.map +1 -1
- package/dist/utils/inference.d.ts +3 -0
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +7 -4
- package/dist/utils/inference.js.map +1 -1
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +5 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/prismaErrorHandler.d.ts.map +1 -1
- package/dist/utils/prismaErrorHandler.js +5 -2
- package/dist/utils/prismaErrorHandler.js.map +1 -1
- package/dist/utils/prismaWrapper.d.ts +1 -0
- package/dist/utils/prismaWrapper.d.ts.map +1 -1
- package/dist/utils/prismaWrapper.js +6 -2
- package/dist/utils/prismaWrapper.js.map +1 -1
- package/docker-compose.yml +5 -0
- package/package.json +4 -3
- package/prisma/schema.prisma +1 -1
- package/src/index.ts +119 -12
- package/src/lib/config/env.ts +6 -0
- package/src/lib/fileUpload.ts +0 -1
- package/src/lib/googleCloudStorage.ts +17 -0
- package/src/lib/pusher.ts +5 -1
- package/src/lib/redis.ts +56 -0
- package/src/lib/thumbnailGenerator.ts +170 -168
- package/src/middleware/auth.ts +80 -137
- package/src/models/agenda.ts +46 -0
- package/src/models/announcement.ts +134 -0
- package/src/models/assignment.ts +322 -0
- package/src/models/attendance.ts +208 -0
- package/src/models/auth.ts +247 -0
- package/src/models/class.ts +703 -0
- package/src/models/comment.ts +152 -0
- package/src/models/conversation.ts +200 -0
- package/src/models/event.ts +177 -0
- package/src/models/file.ts +129 -0
- package/src/models/folder.ts +225 -0
- package/src/models/labChat.ts +213 -0
- package/src/models/marketing.ts +45 -0
- package/src/models/message.ts +153 -0
- package/src/models/newtonChat.ts +70 -0
- package/src/models/notification.ts +54 -0
- package/src/models/section.ts +98 -0
- package/src/models/user.ts +47 -0
- package/src/models/worksheet.ts +294 -0
- package/src/pipelines/aiLabChat.ts +684 -0
- package/src/{server/pipelines → pipelines}/aiNewtonChat.ts +9 -5
- package/src/{server/pipelines → pipelines}/gradeWorksheet.ts +25 -14
- package/src/routers/agenda.ts +3 -66
- package/src/routers/announcement.ts +54 -495
- package/src/routers/assignment.ts +126 -2018
- package/src/routers/attendance.ts +15 -276
- package/src/routers/auth.ts +79 -442
- package/src/routers/class.ts +263 -1187
- package/src/routers/comment.ts +61 -288
- package/src/routers/conversation.ts +51 -360
- package/src/routers/event.ts +50 -481
- package/src/routers/file.ts +45 -368
- package/src/routers/folder.ts +107 -836
- package/src/routers/labChat.ts +35 -604
- package/src/routers/marketing.ts +35 -77
- package/src/routers/message.ts +54 -567
- package/src/routers/newtonChat.ts +17 -278
- package/src/routers/notifications.ts +32 -82
- package/src/routers/section.ts +46 -330
- package/src/routers/user.ts +49 -227
- package/src/routers/worksheet.ts +215 -503
- package/src/services/agenda.ts +21 -0
- package/src/services/announcement.ts +290 -0
- package/src/services/assignment.ts +1198 -0
- package/src/services/attendance.ts +85 -0
- package/src/services/auth.ts +277 -0
- package/src/services/class.ts +629 -0
- package/src/services/comment.ts +106 -0
- package/src/services/conversation.ts +213 -0
- package/src/services/event.ts +231 -0
- package/src/services/file.ts +167 -0
- package/src/services/folder.ts +316 -0
- package/src/services/labChat.ts +458 -0
- package/src/services/marketing.ts +57 -0
- package/src/services/message.ts +554 -0
- package/src/services/newtonChat.ts +222 -0
- package/src/services/notification.ts +50 -0
- package/src/services/section.ts +283 -0
- package/src/services/user.ts +172 -0
- package/src/services/worksheet.ts +358 -0
- package/src/utils/aiUser.ts +4 -3
- package/src/utils/email.ts +5 -3
- package/src/utils/generateInviteCode.ts +1 -3
- package/src/utils/inference.ts +5 -2
- package/src/utils/logger.ts +3 -1
- package/src/utils/prismaErrorHandler.ts +3 -0
- package/src/utils/prismaWrapper.ts +4 -0
- package/tests/globalSetup.ts +62 -0
- package/tests/helpers.ts +22 -0
- package/tests/middleware/security.test.ts +42 -0
- package/tests/routers/agenda.test.ts +138 -0
- package/tests/routers/announcement.test.ts +490 -0
- package/tests/routers/assignment.test.ts +837 -0
- package/tests/{attendance.test.ts → routers/attendance.test.ts} +6 -14
- package/tests/routers/auth.test.ts +171 -0
- package/tests/{class.test.ts → routers/class.test.ts} +131 -85
- package/tests/routers/comment.test.ts +126 -0
- package/tests/routers/conversation.test.ts +145 -0
- package/tests/{event.test.ts → routers/event.test.ts} +93 -32
- package/tests/routers/folder.test.ts +178 -0
- package/tests/routers/labChat.test.ts +115 -0
- package/tests/routers/marketing.test.ts +59 -0
- package/tests/routers/message.test.ts +123 -0
- package/tests/routers/notification.test.ts +69 -0
- package/tests/{section.test.ts → routers/section.test.ts} +5 -13
- package/tests/server/rateLimit.test.ts +73 -0
- package/tests/setup.ts +18 -92
- package/tests/user.test.ts +9 -31
- package/tests/utils/aiUser.test.ts +22 -0
- package/tests/utils/generateInviteCode.test.ts +24 -0
- package/tests/utils/logger.test.ts +74 -0
- package/tests/utils/prismaErrorHandler.test.ts +101 -0
- package/tests/utils/prismaWrapper.test.ts +82 -0
- package/tests/worksheet.test.ts +181 -0
- package/vitest.config.ts +6 -3
- package/vitest.unit.config.ts +21 -0
- package/TODO.md +0 -2
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -12110
- package/coverage/coverage-final.json +0 -44
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -221
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/server/index.html +0 -116
- package/coverage/server/src/exportType.ts.html +0 -109
- package/coverage/server/src/index.html +0 -161
- package/coverage/server/src/index.ts.html +0 -1702
- package/coverage/server/src/instrument.ts.html +0 -130
- package/coverage/server/src/lib/config/env.ts.html +0 -448
- package/coverage/server/src/lib/config/index.html +0 -116
- package/coverage/server/src/lib/fileUpload.ts.html +0 -1138
- package/coverage/server/src/lib/googleCloudStorage.ts.html +0 -334
- package/coverage/server/src/lib/index.html +0 -206
- package/coverage/server/src/lib/jsonConversion.ts.html +0 -2323
- package/coverage/server/src/lib/jsonStyles.ts.html +0 -193
- package/coverage/server/src/lib/notificationHandler.ts.html +0 -193
- package/coverage/server/src/lib/pusher.ts.html +0 -121
- package/coverage/server/src/lib/thumbnailGenerator.ts.html +0 -592
- package/coverage/server/src/middleware/auth.ts.html +0 -646
- package/coverage/server/src/middleware/index.html +0 -146
- package/coverage/server/src/middleware/logging.ts.html +0 -244
- package/coverage/server/src/middleware/security.ts.html +0 -271
- package/coverage/server/src/routers/_app.ts.html +0 -232
- package/coverage/server/src/routers/agenda.ts.html +0 -319
- package/coverage/server/src/routers/announcement.ts.html +0 -3481
- package/coverage/server/src/routers/assignment.ts.html +0 -7633
- package/coverage/server/src/routers/attendance.ts.html +0 -1030
- package/coverage/server/src/routers/auth.ts.html +0 -1081
- package/coverage/server/src/routers/class.ts.html +0 -3535
- package/coverage/server/src/routers/comment.ts.html +0 -991
- package/coverage/server/src/routers/conversation.ts.html +0 -982
- package/coverage/server/src/routers/event.ts.html +0 -1609
- package/coverage/server/src/routers/file.ts.html +0 -1144
- package/coverage/server/src/routers/folder.ts.html +0 -2797
- package/coverage/server/src/routers/index.html +0 -386
- package/coverage/server/src/routers/labChat.ts.html +0 -3073
- package/coverage/server/src/routers/marketing.ts.html +0 -340
- package/coverage/server/src/routers/message.ts.html +0 -1912
- package/coverage/server/src/routers/notifications.ts.html +0 -364
- package/coverage/server/src/routers/section.ts.html +0 -1120
- package/coverage/server/src/routers/user.ts.html +0 -862
- package/coverage/server/src/routers/worksheet.ts.html +0 -1729
- package/coverage/server/src/trpc.ts.html +0 -397
- package/coverage/server/src/types/index.html +0 -116
- package/coverage/server/src/types/trpc.ts.html +0 -127
- package/coverage/server/src/utils/aiUser.ts.html +0 -280
- package/coverage/server/src/utils/email.ts.html +0 -121
- package/coverage/server/src/utils/generateInviteCode.ts.html +0 -106
- package/coverage/server/src/utils/index.html +0 -206
- package/coverage/server/src/utils/inference.ts.html +0 -709
- package/coverage/server/src/utils/logger.ts.html +0 -664
- package/coverage/server/src/utils/prismaErrorHandler.ts.html +0 -907
- package/coverage/server/src/utils/prismaWrapper.ts.html +0 -355
- package/coverage/server/vitest.config.ts.html +0 -196
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/src/lib/notificationHandler.ts +0 -36
- package/src/server/pipelines/aiLabChat.ts +0 -507
- package/tests/announcement.test.ts +0 -164
- package/tests/assignment.test.ts +0 -296
- package/tests/auth.test.ts +0 -48
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
|
|
2
|
-
!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]="
|
|
2
|
+
!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]="a4b6352a-4a02-5817-b542-3f6ab5651e28")}catch(e){}}();
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { createTRPCRouter, protectedClassMemberProcedure, protectedTeacherProcedure, protectedProcedure } from "../trpc.js";
|
|
5
5
|
import { prisma } from "../lib/prisma.js";
|
|
6
6
|
import { TRPCError } from "@trpc/server";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { getAllAnnouncements, getAnnouncement, createAnnouncementRecord, updateAnnouncementRecord, deleteAnnouncementRecord, } from "../services/announcement.js";
|
|
8
|
+
import { findAnnouncementByIdAndClass } from "../models/announcement.js";
|
|
9
|
+
import { findCommentWithAnnouncement, findReactionByUserAndComment, upsertReaction, deleteReactionById, } from "../models/comment.js";
|
|
10
|
+
import { getReactions as getCommentReactions } from "../services/comment.js";
|
|
9
11
|
import { createDirectUploadFiles, confirmDirectUpload } from "../lib/fileUpload.js";
|
|
10
|
-
import { deleteFile } from "../lib/googleCloudStorage.js";
|
|
11
12
|
// Schema for direct file uploads (no base64 data)
|
|
12
13
|
const directFileSchema = z.object({
|
|
13
14
|
name: z.string(),
|
|
@@ -25,91 +26,13 @@ const confirmAnnouncementUploadSchema = z.object({
|
|
|
25
26
|
uploadSuccess: z.boolean(),
|
|
26
27
|
errorMessage: z.string().optional(),
|
|
27
28
|
});
|
|
28
|
-
const AnnouncementSelect = {
|
|
29
|
-
id: true,
|
|
30
|
-
teacher: {
|
|
31
|
-
select: {
|
|
32
|
-
id: true,
|
|
33
|
-
username: true,
|
|
34
|
-
profile: {
|
|
35
|
-
select: {
|
|
36
|
-
displayName: true,
|
|
37
|
-
profilePicture: true,
|
|
38
|
-
profilePictureThumbnail: true,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
remarks: true,
|
|
44
|
-
createdAt: true,
|
|
45
|
-
modifiedAt: true,
|
|
46
|
-
attachments: {
|
|
47
|
-
select: {
|
|
48
|
-
id: true,
|
|
49
|
-
name: true,
|
|
50
|
-
type: true,
|
|
51
|
-
size: true,
|
|
52
|
-
path: true,
|
|
53
|
-
uploadedAt: true,
|
|
54
|
-
thumbnailId: true,
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
29
|
export const announcementRouter = createTRPCRouter({
|
|
59
30
|
getAll: protectedClassMemberProcedure
|
|
60
|
-
.input(z.object({
|
|
61
|
-
|
|
62
|
-
}))
|
|
63
|
-
.query(async ({ ctx, input }) => {
|
|
64
|
-
const announcements = await prisma.announcement.findMany({
|
|
65
|
-
where: {
|
|
66
|
-
classId: input.classId,
|
|
67
|
-
},
|
|
68
|
-
select: {
|
|
69
|
-
...AnnouncementSelect,
|
|
70
|
-
_count: {
|
|
71
|
-
select: {
|
|
72
|
-
comments: true,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
orderBy: {
|
|
77
|
-
createdAt: 'desc',
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
// Transform to include comment count
|
|
81
|
-
const announcementsWithCounts = announcements.map(announcement => ({
|
|
82
|
-
...announcement,
|
|
83
|
-
commentCount: announcement._count.comments,
|
|
84
|
-
_count: undefined,
|
|
85
|
-
}));
|
|
86
|
-
return {
|
|
87
|
-
announcements: announcementsWithCounts,
|
|
88
|
-
};
|
|
89
|
-
}),
|
|
31
|
+
.input(z.object({ classId: z.string() }))
|
|
32
|
+
.query(({ input }) => getAllAnnouncements(input.classId)),
|
|
90
33
|
get: protectedClassMemberProcedure
|
|
91
|
-
.input(z.object({
|
|
92
|
-
id
|
|
93
|
-
classId: z.string(),
|
|
94
|
-
}))
|
|
95
|
-
.query(async ({ ctx, input }) => {
|
|
96
|
-
const announcement = await prisma.announcement.findUnique({
|
|
97
|
-
where: {
|
|
98
|
-
id: input.id,
|
|
99
|
-
classId: input.classId,
|
|
100
|
-
},
|
|
101
|
-
select: AnnouncementSelect,
|
|
102
|
-
});
|
|
103
|
-
if (!announcement) {
|
|
104
|
-
throw new TRPCError({
|
|
105
|
-
code: "NOT_FOUND",
|
|
106
|
-
message: "Announcement not found",
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
return {
|
|
110
|
-
announcement,
|
|
111
|
-
};
|
|
112
|
-
}),
|
|
34
|
+
.input(z.object({ id: z.string(), classId: z.string() }))
|
|
35
|
+
.query(({ input }) => getAnnouncement(input.id, input.classId)),
|
|
113
36
|
create: protectedTeacherProcedure
|
|
114
37
|
.input(z.object({
|
|
115
38
|
classId: z.string(),
|
|
@@ -117,83 +40,12 @@ export const announcementRouter = createTRPCRouter({
|
|
|
117
40
|
files: z.array(directFileSchema).optional(),
|
|
118
41
|
existingFileIds: z.array(z.string()).optional(),
|
|
119
42
|
}))
|
|
120
|
-
.mutation(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
const classData = await prisma.class.findUnique({
|
|
129
|
-
where: { id: classId },
|
|
130
|
-
include: {
|
|
131
|
-
students: {
|
|
132
|
-
select: { id: true }
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
if (!classData) {
|
|
137
|
-
throw new TRPCError({
|
|
138
|
-
code: "NOT_FOUND",
|
|
139
|
-
message: "Class not found",
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
const announcement = await prisma.announcement.create({
|
|
143
|
-
data: {
|
|
144
|
-
remarks: remarks,
|
|
145
|
-
teacher: {
|
|
146
|
-
connect: {
|
|
147
|
-
id: ctx.user.id,
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
class: {
|
|
151
|
-
connect: {
|
|
152
|
-
id: classId,
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
select: AnnouncementSelect,
|
|
157
|
-
});
|
|
158
|
-
// Handle file attachments
|
|
159
|
-
// NOTE: Files are now handled via direct upload endpoints
|
|
160
|
-
// The files field in the schema is for metadata only
|
|
161
|
-
// Actual file uploads should use getAnnouncementUploadUrls endpoint
|
|
162
|
-
// However, if files are provided here, we create the file records and return upload URLs
|
|
163
|
-
let directUploadFiles = [];
|
|
164
|
-
if (files && files.length > 0) {
|
|
165
|
-
// Create direct upload files - this creates file records with upload URLs
|
|
166
|
-
// Files are automatically connected to the announcement via announcementId
|
|
167
|
-
directUploadFiles = await createDirectUploadFiles(files, ctx.user.id, undefined, undefined, undefined, announcement.id);
|
|
168
|
-
}
|
|
169
|
-
// Connect existing files if provided
|
|
170
|
-
if (existingFileIds && existingFileIds.length > 0) {
|
|
171
|
-
await prisma.announcement.update({
|
|
172
|
-
where: { id: announcement.id },
|
|
173
|
-
data: {
|
|
174
|
-
attachments: {
|
|
175
|
-
connect: existingFileIds.map(fileId => ({ id: fileId }))
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
// Fetch announcement with attachments
|
|
181
|
-
const announcementWithAttachments = await prisma.announcement.findUnique({
|
|
182
|
-
where: { id: announcement.id },
|
|
183
|
-
select: AnnouncementSelect,
|
|
184
|
-
});
|
|
185
|
-
sendNotifications(classData.students.map(student => student.id), {
|
|
186
|
-
title: `🔔 Announcement for ${classData.name}`,
|
|
187
|
-
content: remarks
|
|
188
|
-
}).catch(error => {
|
|
189
|
-
logger.error('Failed to send announcement notifications:', error);
|
|
190
|
-
});
|
|
191
|
-
return {
|
|
192
|
-
announcement: announcementWithAttachments || announcement,
|
|
193
|
-
// Return upload URLs if files were provided
|
|
194
|
-
uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,
|
|
195
|
-
};
|
|
196
|
-
}),
|
|
43
|
+
.mutation(({ ctx, input }) => createAnnouncementRecord(ctx.user.id, {
|
|
44
|
+
classId: input.classId,
|
|
45
|
+
remarks: input.remarks,
|
|
46
|
+
files: input.files,
|
|
47
|
+
existingFileIds: input.existingFileIds,
|
|
48
|
+
})),
|
|
197
49
|
update: protectedTeacherProcedure
|
|
198
50
|
.input(z.object({
|
|
199
51
|
id: z.string(),
|
|
@@ -205,158 +57,14 @@ export const announcementRouter = createTRPCRouter({
|
|
|
205
57
|
removedAttachments: z.array(z.string()).optional(),
|
|
206
58
|
}),
|
|
207
59
|
}))
|
|
208
|
-
.mutation(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
const announcement = await prisma.announcement.findUnique({
|
|
216
|
-
where: { id: input.id },
|
|
217
|
-
include: {
|
|
218
|
-
class: {
|
|
219
|
-
include: {
|
|
220
|
-
teachers: true,
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
attachments: {
|
|
224
|
-
select: {
|
|
225
|
-
id: true,
|
|
226
|
-
name: true,
|
|
227
|
-
type: true,
|
|
228
|
-
path: true,
|
|
229
|
-
size: true,
|
|
230
|
-
uploadStatus: true,
|
|
231
|
-
thumbnail: {
|
|
232
|
-
select: {
|
|
233
|
-
path: true
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
});
|
|
240
|
-
if (!announcement) {
|
|
241
|
-
throw new TRPCError({
|
|
242
|
-
code: "NOT_FOUND",
|
|
243
|
-
message: "Announcement not found",
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
// Authorization check: user must be the creator OR a teacher in the class
|
|
247
|
-
const userId = ctx.user.id;
|
|
248
|
-
const isCreator = announcement.teacherId === userId;
|
|
249
|
-
const isClassTeacher = announcement.class.teachers.some((teacher) => teacher.id === userId);
|
|
250
|
-
if (!isCreator && !isClassTeacher) {
|
|
251
|
-
throw new TRPCError({
|
|
252
|
-
code: "FORBIDDEN",
|
|
253
|
-
message: "Only the announcement creator or class teachers can update announcements",
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
// Handle file attachments
|
|
257
|
-
// NOTE: Files are now handled via direct upload endpoints
|
|
258
|
-
let directUploadFiles = [];
|
|
259
|
-
if (input.data.files && input.data.files.length > 0) {
|
|
260
|
-
// Create direct upload files - this creates file records with upload URLs
|
|
261
|
-
// Files are automatically connected to the announcement via announcementId
|
|
262
|
-
directUploadFiles = await createDirectUploadFiles(input.data.files, userId, undefined, undefined, undefined, input.id);
|
|
263
|
-
}
|
|
264
|
-
// Delete removed attachments from storage before updating database
|
|
265
|
-
if (input.data.removedAttachments && input.data.removedAttachments.length > 0) {
|
|
266
|
-
const filesToDelete = announcement.attachments.filter((file) => input.data.removedAttachments.includes(file.id));
|
|
267
|
-
// Delete files from storage (only if they were actually uploaded)
|
|
268
|
-
await Promise.all(filesToDelete.map(async (file) => {
|
|
269
|
-
try {
|
|
270
|
-
// Only delete from GCS if the file was successfully uploaded
|
|
271
|
-
if (file.uploadStatus === 'COMPLETED') {
|
|
272
|
-
// Delete the main file
|
|
273
|
-
await deleteFile(file.path);
|
|
274
|
-
// Delete thumbnail if it exists
|
|
275
|
-
if (file.thumbnail?.path) {
|
|
276
|
-
await deleteFile(file.thumbnail.path);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
catch (error) {
|
|
281
|
-
logger.warn(`Failed to delete file ${file.path}:`, {
|
|
282
|
-
error: error instanceof Error ? {
|
|
283
|
-
name: error.name,
|
|
284
|
-
message: error.message,
|
|
285
|
-
stack: error.stack,
|
|
286
|
-
} : error
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
}));
|
|
290
|
-
}
|
|
291
|
-
const updatedAnnouncement = await prisma.announcement.update({
|
|
292
|
-
where: { id: input.id },
|
|
293
|
-
data: {
|
|
294
|
-
...(input.data.remarks && { remarks: input.data.remarks }),
|
|
295
|
-
// Note: directUploadFiles are already connected via createDirectUploadFiles
|
|
296
|
-
...(input.data.existingFileIds && input.data.existingFileIds.length > 0 && {
|
|
297
|
-
attachments: {
|
|
298
|
-
connect: input.data.existingFileIds.map(fileId => ({ id: fileId }))
|
|
299
|
-
}
|
|
300
|
-
}),
|
|
301
|
-
...(input.data.removedAttachments && input.data.removedAttachments.length > 0 && {
|
|
302
|
-
attachments: {
|
|
303
|
-
deleteMany: {
|
|
304
|
-
id: { in: input.data.removedAttachments }
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}),
|
|
308
|
-
},
|
|
309
|
-
select: AnnouncementSelect,
|
|
310
|
-
});
|
|
311
|
-
return {
|
|
312
|
-
announcement: updatedAnnouncement,
|
|
313
|
-
// Return upload URLs if new files were provided
|
|
314
|
-
uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,
|
|
315
|
-
};
|
|
316
|
-
}),
|
|
60
|
+
.mutation(({ ctx, input }) => updateAnnouncementRecord(ctx.user.id, {
|
|
61
|
+
id: input.id,
|
|
62
|
+
classId: input.classId,
|
|
63
|
+
data: input.data,
|
|
64
|
+
})),
|
|
317
65
|
delete: protectedTeacherProcedure
|
|
318
|
-
.input(z.object({
|
|
319
|
-
id
|
|
320
|
-
classId: z.string(),
|
|
321
|
-
}))
|
|
322
|
-
.mutation(async ({ ctx, input }) => {
|
|
323
|
-
if (!ctx.user) {
|
|
324
|
-
throw new TRPCError({
|
|
325
|
-
code: "UNAUTHORIZED",
|
|
326
|
-
message: "User must be authenticated",
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
const announcement = await prisma.announcement.findUnique({
|
|
330
|
-
where: { id: input.id },
|
|
331
|
-
include: {
|
|
332
|
-
class: {
|
|
333
|
-
include: {
|
|
334
|
-
teachers: true,
|
|
335
|
-
},
|
|
336
|
-
},
|
|
337
|
-
},
|
|
338
|
-
});
|
|
339
|
-
if (!announcement) {
|
|
340
|
-
throw new TRPCError({
|
|
341
|
-
code: "NOT_FOUND",
|
|
342
|
-
message: "Announcement not found",
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
// Authorization check: user must be the creator OR a teacher in the class
|
|
346
|
-
const userId = ctx.user.id;
|
|
347
|
-
const isCreator = announcement.teacherId === userId;
|
|
348
|
-
const isClassTeacher = announcement.class.teachers.some((teacher) => teacher.id === userId);
|
|
349
|
-
if (!isCreator && !isClassTeacher) {
|
|
350
|
-
throw new TRPCError({
|
|
351
|
-
code: "FORBIDDEN",
|
|
352
|
-
message: "Only the announcement creator or class teachers can delete announcements",
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
await prisma.announcement.delete({
|
|
356
|
-
where: { id: input.id },
|
|
357
|
-
});
|
|
358
|
-
return { success: true };
|
|
359
|
-
}),
|
|
66
|
+
.input(z.object({ id: z.string(), classId: z.string() }))
|
|
67
|
+
.mutation(({ ctx, input }) => deleteAnnouncementRecord(ctx.user.id, input.id, input.classId)),
|
|
360
68
|
getAnnouncementUploadUrls: protectedTeacherProcedure
|
|
361
69
|
.input(getAnnouncementUploadUrlsSchema)
|
|
362
70
|
.mutation(async ({ ctx, input }) => {
|
|
@@ -384,13 +92,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
384
92
|
message: "Class not found or you are not a teacher",
|
|
385
93
|
});
|
|
386
94
|
}
|
|
387
|
-
|
|
388
|
-
const announcement = await prisma.announcement.findFirst({
|
|
389
|
-
where: {
|
|
390
|
-
id: announcementId,
|
|
391
|
-
classId: classId,
|
|
392
|
-
},
|
|
393
|
-
});
|
|
95
|
+
const announcement = await findAnnouncementByIdAndClass(announcementId, classId);
|
|
394
96
|
if (!announcement) {
|
|
395
97
|
throw new TRPCError({
|
|
396
98
|
code: "NOT_FOUND",
|
|
@@ -454,13 +156,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
454
156
|
message: "User must be authenticated",
|
|
455
157
|
});
|
|
456
158
|
}
|
|
457
|
-
|
|
458
|
-
const announcement = await prisma.announcement.findFirst({
|
|
459
|
-
where: {
|
|
460
|
-
id: input.announcementId,
|
|
461
|
-
classId: input.classId,
|
|
462
|
-
},
|
|
463
|
-
});
|
|
159
|
+
const announcement = await findAnnouncementByIdAndClass(input.announcementId, input.classId);
|
|
464
160
|
if (!announcement) {
|
|
465
161
|
throw new TRPCError({
|
|
466
162
|
code: "NOT_FOUND",
|
|
@@ -618,13 +314,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
618
314
|
classId: z.string(),
|
|
619
315
|
}))
|
|
620
316
|
.query(async ({ ctx, input }) => {
|
|
621
|
-
|
|
622
|
-
const announcement = await prisma.announcement.findFirst({
|
|
623
|
-
where: {
|
|
624
|
-
id: input.announcementId,
|
|
625
|
-
classId: input.classId,
|
|
626
|
-
},
|
|
627
|
-
});
|
|
317
|
+
const announcement = await findAnnouncementByIdAndClass(input.announcementId, input.classId);
|
|
628
318
|
if (!announcement) {
|
|
629
319
|
throw new TRPCError({
|
|
630
320
|
code: "NOT_FOUND",
|
|
@@ -707,14 +397,8 @@ export const announcementRouter = createTRPCRouter({
|
|
|
707
397
|
});
|
|
708
398
|
}
|
|
709
399
|
const userId = ctx.user.id;
|
|
710
|
-
// Verify the announcement or comment exists and belongs to the class
|
|
711
400
|
if (input.announcementId) {
|
|
712
|
-
const announcement = await
|
|
713
|
-
where: {
|
|
714
|
-
id: input.announcementId,
|
|
715
|
-
classId: input.classId,
|
|
716
|
-
},
|
|
717
|
-
});
|
|
401
|
+
const announcement = await findAnnouncementByIdAndClass(input.announcementId, input.classId);
|
|
718
402
|
if (!announcement) {
|
|
719
403
|
throw new TRPCError({
|
|
720
404
|
code: "NOT_FOUND",
|
|
@@ -756,17 +440,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
756
440
|
return { reaction };
|
|
757
441
|
}
|
|
758
442
|
else if (input.commentId) {
|
|
759
|
-
|
|
760
|
-
const comment = await prisma.comment.findUnique({
|
|
761
|
-
where: { id: input.commentId },
|
|
762
|
-
include: {
|
|
763
|
-
announcement: {
|
|
764
|
-
select: {
|
|
765
|
-
classId: true,
|
|
766
|
-
},
|
|
767
|
-
},
|
|
768
|
-
},
|
|
769
|
-
});
|
|
443
|
+
const comment = await findCommentWithAnnouncement(input.commentId);
|
|
770
444
|
if (!comment) {
|
|
771
445
|
throw new TRPCError({
|
|
772
446
|
code: "NOT_FOUND",
|
|
@@ -779,37 +453,10 @@ export const announcementRouter = createTRPCRouter({
|
|
|
779
453
|
message: "Comment does not belong to this class",
|
|
780
454
|
});
|
|
781
455
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
userId,
|
|
787
|
-
commentId: input.commentId,
|
|
788
|
-
},
|
|
789
|
-
},
|
|
790
|
-
update: {
|
|
791
|
-
type: input.type,
|
|
792
|
-
},
|
|
793
|
-
create: {
|
|
794
|
-
type: input.type,
|
|
795
|
-
userId,
|
|
796
|
-
commentId: input.commentId,
|
|
797
|
-
},
|
|
798
|
-
include: {
|
|
799
|
-
user: {
|
|
800
|
-
select: {
|
|
801
|
-
id: true,
|
|
802
|
-
username: true,
|
|
803
|
-
profile: {
|
|
804
|
-
select: {
|
|
805
|
-
displayName: true,
|
|
806
|
-
profilePicture: true,
|
|
807
|
-
profilePictureThumbnail: true,
|
|
808
|
-
},
|
|
809
|
-
},
|
|
810
|
-
},
|
|
811
|
-
},
|
|
812
|
-
},
|
|
456
|
+
const reaction = await upsertReaction({
|
|
457
|
+
userId,
|
|
458
|
+
commentId: input.commentId,
|
|
459
|
+
type: input.type,
|
|
813
460
|
});
|
|
814
461
|
return { reaction };
|
|
815
462
|
}
|
|
@@ -859,23 +506,14 @@ export const announcementRouter = createTRPCRouter({
|
|
|
859
506
|
return { success: true };
|
|
860
507
|
}
|
|
861
508
|
else if (input.commentId) {
|
|
862
|
-
const reaction = await
|
|
863
|
-
where: {
|
|
864
|
-
userId_commentId: {
|
|
865
|
-
userId,
|
|
866
|
-
commentId: input.commentId,
|
|
867
|
-
},
|
|
868
|
-
},
|
|
869
|
-
});
|
|
509
|
+
const reaction = await findReactionByUserAndComment(userId, input.commentId);
|
|
870
510
|
if (!reaction) {
|
|
871
511
|
throw new TRPCError({
|
|
872
512
|
code: "NOT_FOUND",
|
|
873
513
|
message: "Reaction not found",
|
|
874
514
|
});
|
|
875
515
|
}
|
|
876
|
-
await
|
|
877
|
-
where: { id: reaction.id },
|
|
878
|
-
});
|
|
516
|
+
await deleteReactionById(reaction.id);
|
|
879
517
|
return { success: true };
|
|
880
518
|
}
|
|
881
519
|
throw new TRPCError({
|
|
@@ -905,13 +543,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
905
543
|
}
|
|
906
544
|
const userId = ctx.user.id;
|
|
907
545
|
if (input.announcementId) {
|
|
908
|
-
|
|
909
|
-
const announcement = await prisma.announcement.findFirst({
|
|
910
|
-
where: {
|
|
911
|
-
id: input.announcementId,
|
|
912
|
-
classId: input.classId,
|
|
913
|
-
},
|
|
914
|
-
});
|
|
546
|
+
const announcement = await findAnnouncementByIdAndClass(input.announcementId, input.classId);
|
|
915
547
|
if (!announcement) {
|
|
916
548
|
throw new TRPCError({
|
|
917
549
|
code: "NOT_FOUND",
|
|
@@ -952,17 +584,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
952
584
|
};
|
|
953
585
|
}
|
|
954
586
|
else if (input.commentId) {
|
|
955
|
-
|
|
956
|
-
const comment = await prisma.comment.findUnique({
|
|
957
|
-
where: { id: input.commentId },
|
|
958
|
-
include: {
|
|
959
|
-
announcement: {
|
|
960
|
-
select: {
|
|
961
|
-
classId: true,
|
|
962
|
-
},
|
|
963
|
-
},
|
|
964
|
-
},
|
|
965
|
-
});
|
|
587
|
+
const comment = await findCommentWithAnnouncement(input.commentId);
|
|
966
588
|
if (!comment) {
|
|
967
589
|
throw new TRPCError({
|
|
968
590
|
code: "NOT_FOUND",
|
|
@@ -975,38 +597,7 @@ export const announcementRouter = createTRPCRouter({
|
|
|
975
597
|
message: "Comment does not belong to this class",
|
|
976
598
|
});
|
|
977
599
|
}
|
|
978
|
-
|
|
979
|
-
const reactionCounts = await prisma.reaction.groupBy({
|
|
980
|
-
by: ['type'],
|
|
981
|
-
where: { commentId: input.commentId },
|
|
982
|
-
_count: { type: true },
|
|
983
|
-
});
|
|
984
|
-
// Get current user's reaction
|
|
985
|
-
const userReaction = await prisma.reaction.findUnique({
|
|
986
|
-
where: {
|
|
987
|
-
userId_commentId: {
|
|
988
|
-
userId,
|
|
989
|
-
commentId: input.commentId,
|
|
990
|
-
},
|
|
991
|
-
},
|
|
992
|
-
});
|
|
993
|
-
// Format counts
|
|
994
|
-
const counts = {
|
|
995
|
-
THUMBSUP: 0,
|
|
996
|
-
CELEBRATE: 0,
|
|
997
|
-
CARE: 0,
|
|
998
|
-
HEART: 0,
|
|
999
|
-
IDEA: 0,
|
|
1000
|
-
HAPPY: 0,
|
|
1001
|
-
};
|
|
1002
|
-
reactionCounts.forEach((item) => {
|
|
1003
|
-
counts[item.type] = item._count.type;
|
|
1004
|
-
});
|
|
1005
|
-
return {
|
|
1006
|
-
counts,
|
|
1007
|
-
userReaction: userReaction?.type || null,
|
|
1008
|
-
total: reactionCounts.reduce((sum, item) => sum + item._count.type, 0),
|
|
1009
|
-
};
|
|
600
|
+
return getCommentReactions(userId, input.commentId);
|
|
1010
601
|
}
|
|
1011
602
|
throw new TRPCError({
|
|
1012
603
|
code: "INTERNAL_SERVER_ERROR",
|
|
@@ -1015,4 +606,4 @@ export const announcementRouter = createTRPCRouter({
|
|
|
1015
606
|
}),
|
|
1016
607
|
});
|
|
1017
608
|
//# sourceMappingURL=announcement.js.map
|
|
1018
|
-
//# debugId=
|
|
609
|
+
//# debugId=a4b6352a-4a02-5817-b542-3f6ab5651e28
|