@studious-lms/server 1.2.45 → 1.2.46
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 +45 -0
- package/.env.test.example +37 -0
- package/README.md +34 -7
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +12110 -0
- package/coverage/coverage-final.json +44 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +221 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/server/index.html +116 -0
- package/coverage/server/src/exportType.ts.html +109 -0
- package/coverage/server/src/index.html +161 -0
- package/coverage/server/src/index.ts.html +1702 -0
- package/coverage/server/src/instrument.ts.html +130 -0
- package/coverage/server/src/lib/config/env.ts.html +448 -0
- package/coverage/server/src/lib/config/index.html +116 -0
- package/coverage/server/src/lib/fileUpload.ts.html +1138 -0
- package/coverage/server/src/lib/googleCloudStorage.ts.html +334 -0
- package/coverage/server/src/lib/index.html +206 -0
- package/coverage/server/src/lib/jsonConversion.ts.html +2323 -0
- package/coverage/server/src/lib/jsonStyles.ts.html +193 -0
- package/coverage/server/src/lib/notificationHandler.ts.html +193 -0
- package/coverage/server/src/lib/pusher.ts.html +121 -0
- package/coverage/server/src/lib/thumbnailGenerator.ts.html +592 -0
- package/coverage/server/src/middleware/auth.ts.html +646 -0
- package/coverage/server/src/middleware/index.html +146 -0
- package/coverage/server/src/middleware/logging.ts.html +244 -0
- package/coverage/server/src/middleware/security.ts.html +271 -0
- package/coverage/server/src/routers/_app.ts.html +232 -0
- package/coverage/server/src/routers/agenda.ts.html +319 -0
- package/coverage/server/src/routers/announcement.ts.html +3481 -0
- package/coverage/server/src/routers/assignment.ts.html +7633 -0
- package/coverage/server/src/routers/attendance.ts.html +1030 -0
- package/coverage/server/src/routers/auth.ts.html +1081 -0
- package/coverage/server/src/routers/class.ts.html +3535 -0
- package/coverage/server/src/routers/comment.ts.html +991 -0
- package/coverage/server/src/routers/conversation.ts.html +982 -0
- package/coverage/server/src/routers/event.ts.html +1609 -0
- package/coverage/server/src/routers/file.ts.html +1144 -0
- package/coverage/server/src/routers/folder.ts.html +2797 -0
- package/coverage/server/src/routers/index.html +386 -0
- package/coverage/server/src/routers/labChat.ts.html +3073 -0
- package/coverage/server/src/routers/marketing.ts.html +340 -0
- package/coverage/server/src/routers/message.ts.html +1912 -0
- package/coverage/server/src/routers/notifications.ts.html +364 -0
- package/coverage/server/src/routers/section.ts.html +1120 -0
- package/coverage/server/src/routers/user.ts.html +862 -0
- package/coverage/server/src/routers/worksheet.ts.html +1729 -0
- package/coverage/server/src/trpc.ts.html +397 -0
- package/coverage/server/src/types/index.html +116 -0
- package/coverage/server/src/types/trpc.ts.html +127 -0
- package/coverage/server/src/utils/aiUser.ts.html +280 -0
- package/coverage/server/src/utils/email.ts.html +121 -0
- package/coverage/server/src/utils/generateInviteCode.ts.html +106 -0
- package/coverage/server/src/utils/index.html +206 -0
- package/coverage/server/src/utils/inference.ts.html +709 -0
- package/coverage/server/src/utils/logger.ts.html +664 -0
- package/coverage/server/src/utils/prismaErrorHandler.ts.html +907 -0
- package/coverage/server/src/utils/prismaWrapper.ts.html +355 -0
- package/coverage/server/vitest.config.ts.html +196 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83 -52
- package/dist/index.js.map +1 -1
- package/dist/instrument.js +15 -8
- package/dist/instrument.js.map +1 -1
- package/dist/lib/config/env.d.ts +169 -0
- package/dist/lib/config/env.d.ts.map +1 -0
- package/dist/lib/config/env.js +115 -0
- package/dist/lib/config/env.js.map +1 -0
- package/dist/lib/fileUpload.d.ts.map +1 -1
- package/dist/lib/fileUpload.js +5 -4
- package/dist/lib/fileUpload.js.map +1 -1
- package/dist/lib/googleCloudStorage.d.ts.map +1 -1
- package/dist/lib/googleCloudStorage.js +7 -8
- package/dist/lib/googleCloudStorage.js.map +1 -1
- package/dist/lib/jsonConversion.d.ts.map +1 -1
- package/dist/lib/jsonConversion.js +14 -16
- package/dist/lib/jsonConversion.js.map +1 -1
- package/dist/lib/notificationHandler.d.ts +2 -2
- package/dist/lib/prisma.d.ts +2 -2
- package/dist/lib/prisma.d.ts.map +1 -1
- package/dist/lib/prisma.js +22 -3
- package/dist/lib/prisma.js.map +1 -1
- package/dist/lib/pusher.d.ts.map +1 -1
- package/dist/lib/pusher.js +8 -7
- package/dist/lib/pusher.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +6 -5
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/security.d.ts +5 -0
- package/dist/middleware/security.d.ts.map +1 -0
- package/dist/middleware/security.js +77 -0
- package/dist/middleware/security.js.map +1 -0
- package/dist/routers/_app.d.ts +294 -98
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +4 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/agenda.js +12 -9
- package/dist/routers/agenda.js.map +1 -1
- package/dist/routers/announcement.d.ts +8 -0
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/announcement.js +6 -4
- package/dist/routers/announcement.js.map +1 -1
- package/dist/routers/assignment.d.ts +7 -4
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +35 -18
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/attendance.d.ts +1 -0
- package/dist/routers/attendance.d.ts.map +1 -1
- package/dist/routers/attendance.js +4 -4
- package/dist/routers/attendance.js.map +1 -1
- package/dist/routers/auth.d.ts +20 -0
- package/dist/routers/auth.d.ts.map +1 -1
- package/dist/routers/auth.js +132 -15
- package/dist/routers/auth.js.map +1 -1
- package/dist/routers/class.d.ts +10 -0
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +49 -5
- 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/conversation.d.ts +1 -0
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/conversation.js +46 -31
- package/dist/routers/conversation.js.map +1 -1
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/file.js +30 -7
- package/dist/routers/file.js.map +1 -1
- package/dist/routers/labChat.d.ts +1 -0
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +2 -3
- package/dist/routers/labChat.js.map +1 -1
- package/dist/routers/marketing.d.ts +1 -1
- package/dist/routers/newtonChat.d.ts +55 -0
- package/dist/routers/newtonChat.d.ts.map +1 -0
- package/dist/routers/newtonChat.js +438 -0
- package/dist/routers/newtonChat.js.map +1 -0
- package/dist/routers/notifications.d.ts +4 -4
- package/dist/routers/section.d.ts +9 -4
- package/dist/routers/section.d.ts.map +1 -1
- package/dist/routers/section.js +8 -8
- package/dist/routers/section.js.map +1 -1
- package/dist/routers/user.d.ts.map +1 -1
- package/dist/routers/user.js +5 -4
- package/dist/routers/user.js.map +1 -1
- package/dist/routers/worksheet.d.ts +30 -36
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +11 -33
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/seedDatabase.d.ts +1 -1
- package/dist/seedDatabase.js +275 -284
- package/dist/seedDatabase.js.map +1 -1
- package/dist/server/pipelines/aiLabChat.d.ts +10 -0
- package/dist/server/pipelines/aiLabChat.d.ts.map +1 -0
- package/dist/server/pipelines/aiLabChat.js +83 -0
- package/dist/server/pipelines/aiLabChat.js.map +1 -0
- package/dist/server/pipelines/gradeWorksheet.d.ts +2 -0
- package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -0
- package/dist/server/pipelines/gradeWorksheet.js +138 -0
- package/dist/server/pipelines/gradeWorksheet.js.map +1 -0
- package/dist/trpc.d.ts.map +1 -1
- package/dist/trpc.js +2 -2
- package/dist/trpc.js.map +1 -1
- package/dist/utils/email.d.ts +9 -1
- package/dist/utils/email.d.ts.map +1 -1
- package/dist/utils/email.js +20 -5
- package/dist/utils/email.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 +41 -7
- package/dist/utils/inference.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +3 -3
- package/dist/utils/logger.js.map +1 -1
- package/docker-compose.yml +14 -0
- package/package.json +13 -4
- package/prisma/schema.prisma +32 -5
- package/scripts/test-pre-push.ts +14 -0
- package/src/index.ts +98 -54
- package/src/instrument.ts +13 -6
- package/src/lib/config/env.ts +126 -0
- package/src/lib/fileUpload.ts +3 -2
- package/src/lib/googleCloudStorage.ts +6 -6
- package/src/lib/jsonConversion.ts +12 -14
- package/src/lib/prisma.ts +23 -2
- package/src/lib/pusher.ts +6 -5
- package/src/middleware/auth.ts +4 -3
- package/src/middleware/security.ts +80 -0
- package/src/routers/_app.ts +2 -0
- package/src/routers/agenda.ts +10 -7
- package/src/routers/announcement.ts +4 -2
- package/src/routers/assignment.ts +58 -40
- package/src/routers/attendance.ts +2 -2
- package/src/routers/auth.ts +143 -14
- package/src/routers/class.ts +52 -3
- package/src/routers/conversation.ts +49 -29
- package/src/routers/file.ts +29 -5
- package/src/routers/labChat.ts +0 -1
- package/src/routers/newtonChat.ts +520 -0
- package/src/routers/section.ts +6 -6
- package/src/routers/user.ts +3 -2
- package/src/routers/worksheet.ts +9 -37
- package/src/seedDatabase.ts +290 -283
- package/src/server/pipelines/aiLabChat.ts +92 -0
- package/src/server/pipelines/gradeWorksheet.ts +152 -0
- package/src/trpc.ts +2 -0
- package/src/utils/email.ts +30 -3
- package/src/utils/inference.ts +50 -5
- package/src/utils/logger.ts +2 -1
- package/tests/announcement.test.ts +164 -0
- package/tests/assignment.test.ts +296 -0
- package/tests/attendance.test.ts +168 -0
- package/tests/auth.test.ts +33 -10
- package/tests/class.test.ts +34 -9
- package/tests/event.test.ts +228 -0
- package/tests/section.test.ts +216 -0
- package/tests/setup.ts +70 -16
- package/tests/user.test.ts +158 -0
- package/vitest.config.ts +26 -0
- package/API_SPECIFICATION.md +0 -1597
- package/BASE64_REMOVAL_SUMMARY.md +0 -164
- package/CHAT_API_SPEC.md +0 -579
- package/LAB_CHAT_API_SPEC.md +0 -518
- package/dist/routers/school.d.ts +0 -208
- package/dist/routers/school.d.ts.map +0 -1
- package/dist/routers/school.js +0 -483
package/API_SPECIFICATION.md
DELETED
|
@@ -1,1597 +0,0 @@
|
|
|
1
|
-
# Easy LMS API Specification
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Easy LMS is a comprehensive Learning Management System built with tRPC, Prisma, and PostgreSQL. This document provides a complete API specification for frontend developers.
|
|
6
|
-
|
|
7
|
-
### Base URL
|
|
8
|
-
- **Development**: `http://localhost:3001/trpc`
|
|
9
|
-
- **Production**: `https://your-domain.com/trpc`
|
|
10
|
-
|
|
11
|
-
### Authentication
|
|
12
|
-
- **Method**: Bearer Token Authentication
|
|
13
|
-
- **Header**: `Authorization: Bearer <token>`
|
|
14
|
-
- **Session Management**: Token-based sessions with expiration
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 🔐 Authentication Endpoints
|
|
19
|
-
|
|
20
|
-
### `auth.register`
|
|
21
|
-
**Type**: Mutation
|
|
22
|
-
**Access**: Public
|
|
23
|
-
**Description**: Register a new user account
|
|
24
|
-
|
|
25
|
-
**Input**:
|
|
26
|
-
```typescript
|
|
27
|
-
{
|
|
28
|
-
username: string; // min 3 characters
|
|
29
|
-
email: string; // valid email format
|
|
30
|
-
password: string; // min 6 characters
|
|
31
|
-
confirmPassword: string;
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
**Output**:
|
|
36
|
-
```typescript
|
|
37
|
-
{
|
|
38
|
-
user: {
|
|
39
|
-
id: string;
|
|
40
|
-
username: string;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### `auth.login`
|
|
46
|
-
**Type**: Mutation
|
|
47
|
-
**Access**: Public
|
|
48
|
-
**Description**: Login with username and password
|
|
49
|
-
|
|
50
|
-
**Input**:
|
|
51
|
-
```typescript
|
|
52
|
-
{
|
|
53
|
-
username: string;
|
|
54
|
-
password: string;
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
**Output**:
|
|
59
|
-
```typescript
|
|
60
|
-
{
|
|
61
|
-
token: string;
|
|
62
|
-
user: {
|
|
63
|
-
id: string;
|
|
64
|
-
username: string;
|
|
65
|
-
};
|
|
66
|
-
verified?: boolean;
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### `auth.logout`
|
|
71
|
-
**Type**: Mutation
|
|
72
|
-
**Access**: Public
|
|
73
|
-
**Description**: Logout and invalidate session
|
|
74
|
-
|
|
75
|
-
**Output**:
|
|
76
|
-
```typescript
|
|
77
|
-
{
|
|
78
|
-
success: boolean;
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### `auth.check`
|
|
83
|
-
**Type**: Query
|
|
84
|
-
**Access**: Protected
|
|
85
|
-
**Description**: Verify current authentication status
|
|
86
|
-
|
|
87
|
-
**Output**:
|
|
88
|
-
```typescript
|
|
89
|
-
{
|
|
90
|
-
user: {
|
|
91
|
-
id: string;
|
|
92
|
-
username: string;
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### `auth.verify`
|
|
98
|
-
**Type**: Mutation
|
|
99
|
-
**Access**: Public
|
|
100
|
-
**Description**: Verify email with token
|
|
101
|
-
|
|
102
|
-
**Input**:
|
|
103
|
-
```typescript
|
|
104
|
-
{
|
|
105
|
-
token: string;
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### `auth.resendVerificationEmail`
|
|
110
|
-
**Type**: Mutation
|
|
111
|
-
**Access**: Public
|
|
112
|
-
**Description**: Resend verification email
|
|
113
|
-
|
|
114
|
-
**Input**:
|
|
115
|
-
```typescript
|
|
116
|
-
{
|
|
117
|
-
email: string;
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## 👤 User Management
|
|
124
|
-
|
|
125
|
-
### `user.getProfile`
|
|
126
|
-
**Type**: Query
|
|
127
|
-
**Access**: Protected
|
|
128
|
-
**Description**: Get current user profile
|
|
129
|
-
|
|
130
|
-
**Output**:
|
|
131
|
-
```typescript
|
|
132
|
-
{
|
|
133
|
-
id: string;
|
|
134
|
-
username: string;
|
|
135
|
-
profile: Record<string, any>;
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### `user.updateProfile`
|
|
140
|
-
**Type**: Mutation
|
|
141
|
-
**Access**: Protected
|
|
142
|
-
**Description**: Update user profile
|
|
143
|
-
|
|
144
|
-
**Input**:
|
|
145
|
-
```typescript
|
|
146
|
-
{
|
|
147
|
-
profile?: {
|
|
148
|
-
displayName?: string;
|
|
149
|
-
bio?: string;
|
|
150
|
-
location?: string;
|
|
151
|
-
website?: string;
|
|
152
|
-
};
|
|
153
|
-
// For custom profile picture (already uploaded to GCS)
|
|
154
|
-
profilePicture?: {
|
|
155
|
-
filePath: string;
|
|
156
|
-
fileName: string;
|
|
157
|
-
fileType: string; // image/jpeg, image/png, etc.
|
|
158
|
-
fileSize: number;
|
|
159
|
-
};
|
|
160
|
-
// OR use DiceBear avatar URL
|
|
161
|
-
dicebearAvatar?: {
|
|
162
|
-
url: string; // DiceBear avatar URL
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**Note**: Profile pictures use direct upload to GCS. First get a signed upload URL using `user.getProfilePictureUploadUrl`, upload the file directly to GCS, then call this endpoint with the file path.
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## 🏫 Class Management
|
|
172
|
-
|
|
173
|
-
### `class.getAll`
|
|
174
|
-
**Type**: Query
|
|
175
|
-
**Access**: Protected
|
|
176
|
-
**Description**: Get all classes for current user
|
|
177
|
-
|
|
178
|
-
**Output**:
|
|
179
|
-
```typescript
|
|
180
|
-
{
|
|
181
|
-
teacherInClass: Array<{
|
|
182
|
-
id: string;
|
|
183
|
-
name: string;
|
|
184
|
-
section: string;
|
|
185
|
-
subject: string;
|
|
186
|
-
color?: string;
|
|
187
|
-
dueToday: Assignment[];
|
|
188
|
-
assignments: Assignment[];
|
|
189
|
-
}>;
|
|
190
|
-
studentInClass: Array<{
|
|
191
|
-
id: string;
|
|
192
|
-
name: string;
|
|
193
|
-
section: string;
|
|
194
|
-
subject: string;
|
|
195
|
-
color?: string;
|
|
196
|
-
dueToday: Assignment[];
|
|
197
|
-
assignments: Assignment[];
|
|
198
|
-
}>;
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### `class.get`
|
|
203
|
-
**Type**: Query
|
|
204
|
-
**Access**: Protected
|
|
205
|
-
**Description**: Get specific class details
|
|
206
|
-
|
|
207
|
-
**Input**:
|
|
208
|
-
```typescript
|
|
209
|
-
{
|
|
210
|
-
classId: string;
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**Output**:
|
|
215
|
-
```typescript
|
|
216
|
-
{
|
|
217
|
-
class: {
|
|
218
|
-
id: string;
|
|
219
|
-
name: string;
|
|
220
|
-
subject: string;
|
|
221
|
-
section: string;
|
|
222
|
-
color?: string;
|
|
223
|
-
teachers: Array<{
|
|
224
|
-
id: string;
|
|
225
|
-
username: string;
|
|
226
|
-
}>;
|
|
227
|
-
students: Array<{
|
|
228
|
-
id: string;
|
|
229
|
-
username: string;
|
|
230
|
-
}>;
|
|
231
|
-
announcements: Array<{
|
|
232
|
-
id: string;
|
|
233
|
-
remarks: string;
|
|
234
|
-
createdAt: Date;
|
|
235
|
-
teacher: {
|
|
236
|
-
id: string;
|
|
237
|
-
username: string;
|
|
238
|
-
};
|
|
239
|
-
}>;
|
|
240
|
-
assignments: Assignment[];
|
|
241
|
-
sections: Section[];
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### `class.create`
|
|
247
|
-
**Type**: Mutation
|
|
248
|
-
**Access**: Protected
|
|
249
|
-
**Description**: Create a new class
|
|
250
|
-
|
|
251
|
-
**Input**:
|
|
252
|
-
```typescript
|
|
253
|
-
{
|
|
254
|
-
name: string;
|
|
255
|
-
section: string;
|
|
256
|
-
subject: string;
|
|
257
|
-
color?: string;
|
|
258
|
-
students?: string[];
|
|
259
|
-
teachers?: string[];
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### `class.update`
|
|
264
|
-
**Type**: Mutation
|
|
265
|
-
**Access**: Teacher Only
|
|
266
|
-
**Description**: Update class details
|
|
267
|
-
|
|
268
|
-
**Input**:
|
|
269
|
-
```typescript
|
|
270
|
-
{
|
|
271
|
-
classId: string;
|
|
272
|
-
name?: string;
|
|
273
|
-
section?: string;
|
|
274
|
-
subject?: string;
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
### `class.delete`
|
|
279
|
-
**Type**: Mutation
|
|
280
|
-
**Access**: Teacher Only
|
|
281
|
-
**Description**: Delete a class
|
|
282
|
-
|
|
283
|
-
**Input**:
|
|
284
|
-
```typescript
|
|
285
|
-
{
|
|
286
|
-
classId: string;
|
|
287
|
-
id: string;
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### `class.join`
|
|
292
|
-
**Type**: Mutation
|
|
293
|
-
**Access**: Protected
|
|
294
|
-
**Description**: Join class with invite code
|
|
295
|
-
|
|
296
|
-
**Input**:
|
|
297
|
-
```typescript
|
|
298
|
-
{
|
|
299
|
-
classCode: string;
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### `class.getInviteCode`
|
|
304
|
-
**Type**: Query
|
|
305
|
-
**Access**: Teacher Only
|
|
306
|
-
**Description**: Get class invite code
|
|
307
|
-
|
|
308
|
-
**Input**:
|
|
309
|
-
```typescript
|
|
310
|
-
{
|
|
311
|
-
classId: string;
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
**Output**:
|
|
316
|
-
```typescript
|
|
317
|
-
{
|
|
318
|
-
code: string;
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### `class.addStudent`
|
|
323
|
-
**Type**: Mutation
|
|
324
|
-
**Access**: Teacher Only
|
|
325
|
-
**Description**: Add student to class
|
|
326
|
-
|
|
327
|
-
**Input**:
|
|
328
|
-
```typescript
|
|
329
|
-
{
|
|
330
|
-
classId: string;
|
|
331
|
-
studentId: string;
|
|
332
|
-
}
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### `class.changeRole`
|
|
336
|
-
**Type**: Mutation
|
|
337
|
-
**Access**: Teacher Only
|
|
338
|
-
**Description**: Change user role in class
|
|
339
|
-
|
|
340
|
-
**Input**:
|
|
341
|
-
```typescript
|
|
342
|
-
{
|
|
343
|
-
classId: string;
|
|
344
|
-
userId: string;
|
|
345
|
-
type: 'teacher' | 'student';
|
|
346
|
-
}
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### `class.removeMember`
|
|
350
|
-
**Type**: Mutation
|
|
351
|
-
**Access**: Teacher Only
|
|
352
|
-
**Description**: Remove member from class
|
|
353
|
-
|
|
354
|
-
**Input**:
|
|
355
|
-
```typescript
|
|
356
|
-
{
|
|
357
|
-
classId: string;
|
|
358
|
-
userId: string;
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
## 📝 Assignment Management
|
|
365
|
-
|
|
366
|
-
### `assignment.create`
|
|
367
|
-
**Type**: Mutation
|
|
368
|
-
**Access**: Protected
|
|
369
|
-
**Description**: Create a new assignment
|
|
370
|
-
|
|
371
|
-
**Input**:
|
|
372
|
-
```typescript
|
|
373
|
-
{
|
|
374
|
-
classId: string;
|
|
375
|
-
title: string;
|
|
376
|
-
instructions: string;
|
|
377
|
-
dueDate: string;
|
|
378
|
-
files?: File[];
|
|
379
|
-
existingFileIds?: string[];
|
|
380
|
-
maxGrade?: number;
|
|
381
|
-
graded?: boolean;
|
|
382
|
-
weight?: number;
|
|
383
|
-
sectionId?: string;
|
|
384
|
-
type?: 'HOMEWORK' | 'QUIZ' | 'TEST' | 'PROJECT' | 'ESSAY' | 'DISCUSSION' | 'PRESENTATION' | 'LAB' | 'OTHER';
|
|
385
|
-
markSchemeId?: string;
|
|
386
|
-
gradingBoundaryId?: string;
|
|
387
|
-
inProgress?: boolean;
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### `assignment.update`
|
|
392
|
-
**Type**: Mutation
|
|
393
|
-
**Access**: Protected
|
|
394
|
-
**Description**: Update assignment
|
|
395
|
-
|
|
396
|
-
**Input**:
|
|
397
|
-
```typescript
|
|
398
|
-
{
|
|
399
|
-
classId: string;
|
|
400
|
-
id: string;
|
|
401
|
-
title?: string;
|
|
402
|
-
instructions?: string;
|
|
403
|
-
dueDate?: string;
|
|
404
|
-
files?: File[];
|
|
405
|
-
existingFileIds?: string[];
|
|
406
|
-
removedAttachments?: string[];
|
|
407
|
-
maxGrade?: number;
|
|
408
|
-
graded?: boolean;
|
|
409
|
-
weight?: number;
|
|
410
|
-
sectionId?: string | null;
|
|
411
|
-
type?: AssignmentType;
|
|
412
|
-
inProgress?: boolean;
|
|
413
|
-
}
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
### `assignment.delete`
|
|
417
|
-
**Type**: Mutation
|
|
418
|
-
**Access**: Protected
|
|
419
|
-
**Description**: Delete assignment
|
|
420
|
-
|
|
421
|
-
**Input**:
|
|
422
|
-
```typescript
|
|
423
|
-
{
|
|
424
|
-
id: string;
|
|
425
|
-
classId: string;
|
|
426
|
-
}
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
### `assignment.get`
|
|
430
|
-
**Type**: Query
|
|
431
|
-
**Access**: Protected
|
|
432
|
-
**Description**: Get assignment details
|
|
433
|
-
|
|
434
|
-
**Input**:
|
|
435
|
-
```typescript
|
|
436
|
-
{
|
|
437
|
-
id: string;
|
|
438
|
-
classId: string;
|
|
439
|
-
}
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
### `assignment.getSubmission`
|
|
443
|
-
**Type**: Query
|
|
444
|
-
**Access**: Class Member
|
|
445
|
-
**Description**: Get student's submission for assignment
|
|
446
|
-
|
|
447
|
-
**Input**:
|
|
448
|
-
```typescript
|
|
449
|
-
{
|
|
450
|
-
assignmentId: string;
|
|
451
|
-
classId: string;
|
|
452
|
-
}
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### `assignment.getSubmissions`
|
|
456
|
-
**Type**: Query
|
|
457
|
-
**Access**: Teacher Only
|
|
458
|
-
**Description**: Get all submissions for assignment
|
|
459
|
-
|
|
460
|
-
**Input**:
|
|
461
|
-
```typescript
|
|
462
|
-
{
|
|
463
|
-
assignmentId: string;
|
|
464
|
-
classId: string;
|
|
465
|
-
}
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### `assignment.updateSubmission`
|
|
469
|
-
**Type**: Mutation
|
|
470
|
-
**Access**: Class Member
|
|
471
|
-
**Description**: Update student submission
|
|
472
|
-
|
|
473
|
-
**Input**:
|
|
474
|
-
```typescript
|
|
475
|
-
{
|
|
476
|
-
assignmentId: string;
|
|
477
|
-
classId: string;
|
|
478
|
-
submissionId: string;
|
|
479
|
-
submit?: boolean;
|
|
480
|
-
newAttachments?: File[];
|
|
481
|
-
existingFileIds?: string[];
|
|
482
|
-
removedAttachments?: string[];
|
|
483
|
-
}
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
### `assignment.updateSubmissionAsTeacher`
|
|
487
|
-
**Type**: Mutation
|
|
488
|
-
**Access**: Teacher Only
|
|
489
|
-
**Description**: Update submission as teacher (grading)
|
|
490
|
-
|
|
491
|
-
**Input**:
|
|
492
|
-
```typescript
|
|
493
|
-
{
|
|
494
|
-
assignmentId: string;
|
|
495
|
-
classId: string;
|
|
496
|
-
submissionId: string;
|
|
497
|
-
return?: boolean;
|
|
498
|
-
gradeReceived?: number | null;
|
|
499
|
-
newAttachments?: File[];
|
|
500
|
-
existingFileIds?: string[];
|
|
501
|
-
removedAttachments?: string[];
|
|
502
|
-
rubricGrades?: Array<{
|
|
503
|
-
criteriaId: string;
|
|
504
|
-
selectedLevelId: string;
|
|
505
|
-
points: number;
|
|
506
|
-
comments: string;
|
|
507
|
-
}>;
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
## 📢 Announcements
|
|
514
|
-
|
|
515
|
-
### `announcement.getAll`
|
|
516
|
-
**Type**: Query
|
|
517
|
-
**Access**: Class Member
|
|
518
|
-
**Description**: Get all class announcements
|
|
519
|
-
|
|
520
|
-
**Input**:
|
|
521
|
-
```typescript
|
|
522
|
-
{
|
|
523
|
-
classId: string;
|
|
524
|
-
}
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**Output**:
|
|
528
|
-
```typescript
|
|
529
|
-
{
|
|
530
|
-
announcements: Array<{
|
|
531
|
-
id: string;
|
|
532
|
-
remarks: string;
|
|
533
|
-
createdAt: Date;
|
|
534
|
-
teacher: {
|
|
535
|
-
id: string;
|
|
536
|
-
username: string;
|
|
537
|
-
};
|
|
538
|
-
}>;
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
### `announcement.create`
|
|
543
|
-
**Type**: Mutation
|
|
544
|
-
**Access**: Teacher Only
|
|
545
|
-
**Description**: Create new announcement
|
|
546
|
-
|
|
547
|
-
**Input**:
|
|
548
|
-
```typescript
|
|
549
|
-
{
|
|
550
|
-
classId: string;
|
|
551
|
-
remarks: string;
|
|
552
|
-
}
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
### `announcement.update`
|
|
556
|
-
**Type**: Mutation
|
|
557
|
-
**Access**: Protected
|
|
558
|
-
**Description**: Update announcement
|
|
559
|
-
|
|
560
|
-
**Input**:
|
|
561
|
-
```typescript
|
|
562
|
-
{
|
|
563
|
-
id: string;
|
|
564
|
-
data: {
|
|
565
|
-
content: string;
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
### `announcement.delete`
|
|
571
|
-
**Type**: Mutation
|
|
572
|
-
**Access**: Protected
|
|
573
|
-
**Description**: Delete announcement
|
|
574
|
-
|
|
575
|
-
**Input**:
|
|
576
|
-
```typescript
|
|
577
|
-
{
|
|
578
|
-
id: string;
|
|
579
|
-
}
|
|
580
|
-
```
|
|
581
|
-
|
|
582
|
-
---
|
|
583
|
-
|
|
584
|
-
## 📁 Folder Management
|
|
585
|
-
|
|
586
|
-
### `folder.create`
|
|
587
|
-
**Type**: Mutation
|
|
588
|
-
**Access**: Teacher Only
|
|
589
|
-
**Description**: Create a new folder in a class
|
|
590
|
-
|
|
591
|
-
**Input**:
|
|
592
|
-
```typescript
|
|
593
|
-
{
|
|
594
|
-
classId: string;
|
|
595
|
-
name: string;
|
|
596
|
-
parentFolderId?: string;
|
|
597
|
-
}
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
### `folder.get`
|
|
601
|
-
**Type**: Query
|
|
602
|
-
**Access**: Class Member
|
|
603
|
-
**Description**: Get folder details and contents
|
|
604
|
-
|
|
605
|
-
**Input**:
|
|
606
|
-
```typescript
|
|
607
|
-
{
|
|
608
|
-
classId: string;
|
|
609
|
-
folderId: string;
|
|
610
|
-
}
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
### `folder.getChildFolders`
|
|
614
|
-
**Type**: Query
|
|
615
|
-
**Access**: Class Member
|
|
616
|
-
**Description**: Get child folders of a folder
|
|
617
|
-
|
|
618
|
-
**Input**:
|
|
619
|
-
```typescript
|
|
620
|
-
{
|
|
621
|
-
classId: string;
|
|
622
|
-
folderId: string;
|
|
623
|
-
}
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
### `folder.getFolderChildren`
|
|
627
|
-
**Type**: Query
|
|
628
|
-
**Access**: Class Member
|
|
629
|
-
**Description**: Get all children (files and folders) of a folder
|
|
630
|
-
|
|
631
|
-
**Input**:
|
|
632
|
-
```typescript
|
|
633
|
-
{
|
|
634
|
-
classId: string;
|
|
635
|
-
folderId: string;
|
|
636
|
-
}
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
### `folder.getRootFolder`
|
|
640
|
-
**Type**: Query
|
|
641
|
-
**Access**: Class Member
|
|
642
|
-
**Description**: Get root folder for a class
|
|
643
|
-
|
|
644
|
-
**Input**:
|
|
645
|
-
```typescript
|
|
646
|
-
{
|
|
647
|
-
classId: string;
|
|
648
|
-
}
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
### `folder.uploadFiles`
|
|
652
|
-
**Type**: Mutation
|
|
653
|
-
**Access**: Teacher Only
|
|
654
|
-
**Description**: Upload files to a folder
|
|
655
|
-
|
|
656
|
-
**Input**:
|
|
657
|
-
```typescript
|
|
658
|
-
{
|
|
659
|
-
classId: string;
|
|
660
|
-
folderId: string;
|
|
661
|
-
files: File[];
|
|
662
|
-
}
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
### `folder.delete`
|
|
666
|
-
**Type**: Mutation
|
|
667
|
-
**Access**: Teacher Only
|
|
668
|
-
**Description**: Delete a folder
|
|
669
|
-
|
|
670
|
-
**Input**:
|
|
671
|
-
```typescript
|
|
672
|
-
{
|
|
673
|
-
classId: string;
|
|
674
|
-
folderId: string;
|
|
675
|
-
}
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
### `folder.move`
|
|
679
|
-
**Type**: Mutation
|
|
680
|
-
**Access**: Teacher Only
|
|
681
|
-
**Description**: Move folder to different parent
|
|
682
|
-
|
|
683
|
-
**Input**:
|
|
684
|
-
```typescript
|
|
685
|
-
{
|
|
686
|
-
classId: string;
|
|
687
|
-
folderId: string;
|
|
688
|
-
newParentFolderId: string;
|
|
689
|
-
}
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
### `folder.rename`
|
|
693
|
-
**Type**: Mutation
|
|
694
|
-
**Access**: Teacher Only
|
|
695
|
-
**Description**: Rename a folder
|
|
696
|
-
|
|
697
|
-
**Input**:
|
|
698
|
-
```typescript
|
|
699
|
-
{
|
|
700
|
-
classId: string;
|
|
701
|
-
folderId: string;
|
|
702
|
-
newName: string;
|
|
703
|
-
}
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
---
|
|
707
|
-
|
|
708
|
-
## 📁 File Management
|
|
709
|
-
|
|
710
|
-
### `file.getSignedUrl`
|
|
711
|
-
**Type**: Mutation
|
|
712
|
-
**Access**: Protected
|
|
713
|
-
**Description**: Get signed URL for file download
|
|
714
|
-
|
|
715
|
-
**Input**:
|
|
716
|
-
```typescript
|
|
717
|
-
{
|
|
718
|
-
fileId: string;
|
|
719
|
-
}
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
**Output**:
|
|
723
|
-
```typescript
|
|
724
|
-
{
|
|
725
|
-
url: string;
|
|
726
|
-
}
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
### `file.move`
|
|
730
|
-
**Type**: Mutation
|
|
731
|
-
**Access**: Teacher Only
|
|
732
|
-
**Description**: Move file to different folder
|
|
733
|
-
|
|
734
|
-
**Input**:
|
|
735
|
-
```typescript
|
|
736
|
-
{
|
|
737
|
-
fileId: string;
|
|
738
|
-
targetFolderId: string;
|
|
739
|
-
classId: string;
|
|
740
|
-
}
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
### `file.rename`
|
|
744
|
-
**Type**: Mutation
|
|
745
|
-
**Access**: Teacher Only
|
|
746
|
-
**Description**: Rename file
|
|
747
|
-
|
|
748
|
-
**Input**:
|
|
749
|
-
```typescript
|
|
750
|
-
{
|
|
751
|
-
fileId: string;
|
|
752
|
-
newName: string;
|
|
753
|
-
classId: string;
|
|
754
|
-
}
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
### `file.delete`
|
|
758
|
-
**Type**: Mutation
|
|
759
|
-
**Access**: Teacher Only
|
|
760
|
-
**Description**: Delete file
|
|
761
|
-
|
|
762
|
-
**Input**:
|
|
763
|
-
```typescript
|
|
764
|
-
{
|
|
765
|
-
fileId: string;
|
|
766
|
-
classId: string;
|
|
767
|
-
}
|
|
768
|
-
```
|
|
769
|
-
|
|
770
|
-
---
|
|
771
|
-
|
|
772
|
-
## 📚 Section Management
|
|
773
|
-
|
|
774
|
-
### `section.create`
|
|
775
|
-
**Type**: Mutation
|
|
776
|
-
**Access**: Teacher Only
|
|
777
|
-
**Description**: Create a new section in a class
|
|
778
|
-
|
|
779
|
-
**Input**:
|
|
780
|
-
```typescript
|
|
781
|
-
{
|
|
782
|
-
classId: string;
|
|
783
|
-
name: string;
|
|
784
|
-
}
|
|
785
|
-
```
|
|
786
|
-
|
|
787
|
-
**Output**:
|
|
788
|
-
```typescript
|
|
789
|
-
{
|
|
790
|
-
id: string;
|
|
791
|
-
name: string;
|
|
792
|
-
classId: string;
|
|
793
|
-
}
|
|
794
|
-
```
|
|
795
|
-
|
|
796
|
-
### `section.update`
|
|
797
|
-
**Type**: Mutation
|
|
798
|
-
**Access**: Teacher Only
|
|
799
|
-
**Description**: Update section name
|
|
800
|
-
|
|
801
|
-
**Input**:
|
|
802
|
-
```typescript
|
|
803
|
-
{
|
|
804
|
-
id: string;
|
|
805
|
-
classId: string;
|
|
806
|
-
name: string;
|
|
807
|
-
}
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
**Output**:
|
|
811
|
-
```typescript
|
|
812
|
-
{
|
|
813
|
-
id: string;
|
|
814
|
-
name: string;
|
|
815
|
-
classId: string;
|
|
816
|
-
}
|
|
817
|
-
```
|
|
818
|
-
|
|
819
|
-
### `section.delete`
|
|
820
|
-
**Type**: Mutation
|
|
821
|
-
**Access**: Teacher Only
|
|
822
|
-
**Description**: Delete a section
|
|
823
|
-
|
|
824
|
-
**Input**:
|
|
825
|
-
```typescript
|
|
826
|
-
{
|
|
827
|
-
id: string;
|
|
828
|
-
classId: string;
|
|
829
|
-
}
|
|
830
|
-
```
|
|
831
|
-
|
|
832
|
-
**Output**:
|
|
833
|
-
```typescript
|
|
834
|
-
{
|
|
835
|
-
id: string;
|
|
836
|
-
}
|
|
837
|
-
```
|
|
838
|
-
|
|
839
|
-
---
|
|
840
|
-
|
|
841
|
-
## 📊 Attendance Management
|
|
842
|
-
|
|
843
|
-
### `attendance.get`
|
|
844
|
-
**Type**: Query
|
|
845
|
-
**Access**: Class Member
|
|
846
|
-
**Description**: Get attendance records for a class
|
|
847
|
-
|
|
848
|
-
**Input**:
|
|
849
|
-
```typescript
|
|
850
|
-
{
|
|
851
|
-
classId: string;
|
|
852
|
-
eventId?: string;
|
|
853
|
-
}
|
|
854
|
-
```
|
|
855
|
-
|
|
856
|
-
**Output**:
|
|
857
|
-
```typescript
|
|
858
|
-
Array<{
|
|
859
|
-
id: string;
|
|
860
|
-
date: Date;
|
|
861
|
-
event?: {
|
|
862
|
-
id: string;
|
|
863
|
-
name: string;
|
|
864
|
-
startTime: Date;
|
|
865
|
-
endTime: Date;
|
|
866
|
-
location: string;
|
|
867
|
-
color: string;
|
|
868
|
-
};
|
|
869
|
-
present: Array<{
|
|
870
|
-
id: string;
|
|
871
|
-
username: string;
|
|
872
|
-
}>;
|
|
873
|
-
late: Array<{
|
|
874
|
-
id: string;
|
|
875
|
-
username: string;
|
|
876
|
-
}>;
|
|
877
|
-
absent: Array<{
|
|
878
|
-
id: string;
|
|
879
|
-
username: string;
|
|
880
|
-
}>;
|
|
881
|
-
}>
|
|
882
|
-
```
|
|
883
|
-
|
|
884
|
-
### `attendance.update`
|
|
885
|
-
**Type**: Mutation
|
|
886
|
-
**Access**: Teacher Only
|
|
887
|
-
**Description**: Update attendance for a class event
|
|
888
|
-
|
|
889
|
-
**Input**:
|
|
890
|
-
```typescript
|
|
891
|
-
{
|
|
892
|
-
classId: string;
|
|
893
|
-
eventId?: string;
|
|
894
|
-
attendance: {
|
|
895
|
-
present: Array<{
|
|
896
|
-
id: string;
|
|
897
|
-
username: string;
|
|
898
|
-
}>;
|
|
899
|
-
late: Array<{
|
|
900
|
-
id: string;
|
|
901
|
-
username: string;
|
|
902
|
-
}>;
|
|
903
|
-
absent: Array<{
|
|
904
|
-
id: string;
|
|
905
|
-
username: string;
|
|
906
|
-
}>;
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
```
|
|
910
|
-
|
|
911
|
-
**Output**:
|
|
912
|
-
```typescript
|
|
913
|
-
{
|
|
914
|
-
id: string;
|
|
915
|
-
date: Date;
|
|
916
|
-
event?: {
|
|
917
|
-
id: string;
|
|
918
|
-
name: string;
|
|
919
|
-
startTime: Date;
|
|
920
|
-
endTime: Date;
|
|
921
|
-
location: string;
|
|
922
|
-
};
|
|
923
|
-
present: Array<{
|
|
924
|
-
id: string;
|
|
925
|
-
username: string;
|
|
926
|
-
}>;
|
|
927
|
-
late: Array<{
|
|
928
|
-
id: string;
|
|
929
|
-
username: string;
|
|
930
|
-
}>;
|
|
931
|
-
absent: Array<{
|
|
932
|
-
id: string;
|
|
933
|
-
username: string;
|
|
934
|
-
}>;
|
|
935
|
-
}
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
---
|
|
939
|
-
|
|
940
|
-
## 📅 Agenda Management
|
|
941
|
-
|
|
942
|
-
### `agenda.get`
|
|
943
|
-
**Type**: Query
|
|
944
|
-
**Access**: Protected
|
|
945
|
-
**Description**: Get user's weekly agenda with personal and class events
|
|
946
|
-
|
|
947
|
-
**Input**:
|
|
948
|
-
```typescript
|
|
949
|
-
{
|
|
950
|
-
weekStart: string; // ISO date string
|
|
951
|
-
}
|
|
952
|
-
```
|
|
953
|
-
|
|
954
|
-
**Output**:
|
|
955
|
-
```typescript
|
|
956
|
-
{
|
|
957
|
-
events: {
|
|
958
|
-
personal: Array<{
|
|
959
|
-
id: string;
|
|
960
|
-
name: string;
|
|
961
|
-
startTime: Date;
|
|
962
|
-
endTime: Date;
|
|
963
|
-
location?: string;
|
|
964
|
-
color?: string;
|
|
965
|
-
class: null;
|
|
966
|
-
}>;
|
|
967
|
-
class: Array<{
|
|
968
|
-
id: string;
|
|
969
|
-
name: string;
|
|
970
|
-
startTime: Date;
|
|
971
|
-
endTime: Date;
|
|
972
|
-
location?: string;
|
|
973
|
-
color?: string;
|
|
974
|
-
class: {
|
|
975
|
-
id: string;
|
|
976
|
-
name: string;
|
|
977
|
-
subject: string;
|
|
978
|
-
section: string;
|
|
979
|
-
};
|
|
980
|
-
}>;
|
|
981
|
-
};
|
|
982
|
-
}
|
|
983
|
-
```
|
|
984
|
-
|
|
985
|
-
---
|
|
986
|
-
|
|
987
|
-
## 🔔 Notifications
|
|
988
|
-
|
|
989
|
-
### `notification.list`
|
|
990
|
-
**Type**: Query
|
|
991
|
-
**Access**: Protected
|
|
992
|
-
**Description**: Get all notifications for user
|
|
993
|
-
|
|
994
|
-
**Output**:
|
|
995
|
-
```typescript
|
|
996
|
-
Array<{
|
|
997
|
-
id: string;
|
|
998
|
-
title: string;
|
|
999
|
-
content: string;
|
|
1000
|
-
createdAt: Date;
|
|
1001
|
-
read: boolean;
|
|
1002
|
-
sender?: {
|
|
1003
|
-
username: string;
|
|
1004
|
-
};
|
|
1005
|
-
receiver: {
|
|
1006
|
-
username: string;
|
|
1007
|
-
};
|
|
1008
|
-
}>
|
|
1009
|
-
```
|
|
1010
|
-
|
|
1011
|
-
### `notification.get`
|
|
1012
|
-
**Type**: Query
|
|
1013
|
-
**Access**: Protected
|
|
1014
|
-
**Description**: Get specific notification
|
|
1015
|
-
|
|
1016
|
-
**Input**:
|
|
1017
|
-
```typescript
|
|
1018
|
-
{
|
|
1019
|
-
id: string;
|
|
1020
|
-
}
|
|
1021
|
-
```
|
|
1022
|
-
|
|
1023
|
-
### `notification.sendTo`
|
|
1024
|
-
**Type**: Mutation
|
|
1025
|
-
**Access**: Protected
|
|
1026
|
-
**Description**: Send notification to user
|
|
1027
|
-
|
|
1028
|
-
**Input**:
|
|
1029
|
-
```typescript
|
|
1030
|
-
{
|
|
1031
|
-
receiverId: string;
|
|
1032
|
-
title: string;
|
|
1033
|
-
content: string;
|
|
1034
|
-
}
|
|
1035
|
-
```
|
|
1036
|
-
|
|
1037
|
-
### `notification.sendToMultiple`
|
|
1038
|
-
**Type**: Mutation
|
|
1039
|
-
**Access**: Protected
|
|
1040
|
-
**Description**: Send notification to multiple users
|
|
1041
|
-
|
|
1042
|
-
**Input**:
|
|
1043
|
-
```typescript
|
|
1044
|
-
{
|
|
1045
|
-
receiverIds: string[];
|
|
1046
|
-
title: string;
|
|
1047
|
-
content: string;
|
|
1048
|
-
}
|
|
1049
|
-
```
|
|
1050
|
-
|
|
1051
|
-
### `notification.markAsRead`
|
|
1052
|
-
**Type**: Mutation
|
|
1053
|
-
**Access**: Protected
|
|
1054
|
-
**Description**: Mark notification as read
|
|
1055
|
-
|
|
1056
|
-
**Input**:
|
|
1057
|
-
```typescript
|
|
1058
|
-
{
|
|
1059
|
-
id: string;
|
|
1060
|
-
}
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
---
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
## 📊 Grading & Assessment
|
|
1067
|
-
|
|
1068
|
-
### `class.getGrades`
|
|
1069
|
-
**Type**: Query
|
|
1070
|
-
**Access**: Class Member
|
|
1071
|
-
**Description**: Get grades for a user
|
|
1072
|
-
|
|
1073
|
-
**Input**:
|
|
1074
|
-
```typescript
|
|
1075
|
-
{
|
|
1076
|
-
classId: string;
|
|
1077
|
-
userId: string;
|
|
1078
|
-
}
|
|
1079
|
-
```
|
|
1080
|
-
|
|
1081
|
-
### `class.updateGrade`
|
|
1082
|
-
**Type**: Mutation
|
|
1083
|
-
**Access**: Teacher Only
|
|
1084
|
-
**Description**: Update student grade
|
|
1085
|
-
|
|
1086
|
-
**Input**:
|
|
1087
|
-
```typescript
|
|
1088
|
-
{
|
|
1089
|
-
classId: string;
|
|
1090
|
-
assignmentId: string;
|
|
1091
|
-
submissionId: string;
|
|
1092
|
-
gradeReceived: number | null;
|
|
1093
|
-
}
|
|
1094
|
-
```
|
|
1095
|
-
|
|
1096
|
-
### Mark Schemes
|
|
1097
|
-
|
|
1098
|
-
### `class.listMarkSchemes`
|
|
1099
|
-
**Type**: Query
|
|
1100
|
-
**Access**: Teacher Only
|
|
1101
|
-
|
|
1102
|
-
### `class.createMarkScheme`
|
|
1103
|
-
**Type**: Mutation
|
|
1104
|
-
**Access**: Teacher Only
|
|
1105
|
-
|
|
1106
|
-
### `class.updateMarkScheme`
|
|
1107
|
-
**Type**: Mutation
|
|
1108
|
-
**Access**: Teacher Only
|
|
1109
|
-
|
|
1110
|
-
### `class.deleteMarkScheme`
|
|
1111
|
-
**Type**: Mutation
|
|
1112
|
-
**Access**: Teacher Only
|
|
1113
|
-
|
|
1114
|
-
### Grading Boundaries
|
|
1115
|
-
|
|
1116
|
-
### `class.listGradingBoundaries`
|
|
1117
|
-
**Type**: Query
|
|
1118
|
-
**Access**: Teacher Only
|
|
1119
|
-
|
|
1120
|
-
### `class.createGradingBoundary`
|
|
1121
|
-
**Type**: Mutation
|
|
1122
|
-
**Access**: Teacher Only
|
|
1123
|
-
|
|
1124
|
-
### `class.updateGradingBoundary`
|
|
1125
|
-
**Type**: Mutation
|
|
1126
|
-
**Access**: Teacher Only
|
|
1127
|
-
|
|
1128
|
-
### `class.deleteGradingBoundary`
|
|
1129
|
-
**Type**: Mutation
|
|
1130
|
-
**Access**: Teacher Only
|
|
1131
|
-
|
|
1132
|
-
---
|
|
1133
|
-
|
|
1134
|
-
## 📅 Calendar & Events
|
|
1135
|
-
|
|
1136
|
-
### `class.getEvents`
|
|
1137
|
-
**Type**: Query
|
|
1138
|
-
**Access**: Teacher Only
|
|
1139
|
-
**Description**: Get class events
|
|
1140
|
-
|
|
1141
|
-
**Input**:
|
|
1142
|
-
```typescript
|
|
1143
|
-
{
|
|
1144
|
-
classId: string;
|
|
1145
|
-
}
|
|
1146
|
-
```
|
|
1147
|
-
|
|
1148
|
-
### `assignment.attachToEvent`
|
|
1149
|
-
**Type**: Mutation
|
|
1150
|
-
**Access**: Teacher Only
|
|
1151
|
-
**Description**: Attach assignment to event
|
|
1152
|
-
|
|
1153
|
-
**Input**:
|
|
1154
|
-
```typescript
|
|
1155
|
-
{
|
|
1156
|
-
assignmentId: string;
|
|
1157
|
-
eventId: string;
|
|
1158
|
-
}
|
|
1159
|
-
```
|
|
1160
|
-
|
|
1161
|
-
### `assignment.detachEvent`
|
|
1162
|
-
**Type**: Mutation
|
|
1163
|
-
**Access**: Teacher Only
|
|
1164
|
-
**Description**: Detach assignment from event
|
|
1165
|
-
|
|
1166
|
-
**Input**:
|
|
1167
|
-
```typescript
|
|
1168
|
-
{
|
|
1169
|
-
assignmentId: string;
|
|
1170
|
-
}
|
|
1171
|
-
```
|
|
1172
|
-
|
|
1173
|
-
### `assignment.getAvailableEvents`
|
|
1174
|
-
**Type**: Query
|
|
1175
|
-
**Access**: Teacher Only
|
|
1176
|
-
**Description**: Get available events for assignment
|
|
1177
|
-
|
|
1178
|
-
**Input**:
|
|
1179
|
-
```typescript
|
|
1180
|
-
{
|
|
1181
|
-
assignmentId: string;
|
|
1182
|
-
}
|
|
1183
|
-
```
|
|
1184
|
-
|
|
1185
|
-
---
|
|
1186
|
-
|
|
1187
|
-
## 🔧 Lab Management (Draft System)
|
|
1188
|
-
|
|
1189
|
-
### `class.listLabDrafts`
|
|
1190
|
-
**Type**: Query
|
|
1191
|
-
**Access**: Teacher Only
|
|
1192
|
-
**Description**: Get lab drafts
|
|
1193
|
-
|
|
1194
|
-
**Input**:
|
|
1195
|
-
```typescript
|
|
1196
|
-
{
|
|
1197
|
-
classId: string;
|
|
1198
|
-
}
|
|
1199
|
-
```
|
|
1200
|
-
|
|
1201
|
-
### `class.createLabDraft`
|
|
1202
|
-
**Type**: Mutation
|
|
1203
|
-
**Access**: Teacher Only
|
|
1204
|
-
**Description**: Create lab draft
|
|
1205
|
-
|
|
1206
|
-
### `class.updateLabDraft`
|
|
1207
|
-
**Type**: Mutation
|
|
1208
|
-
**Access**: Teacher Only
|
|
1209
|
-
**Description**: Update lab draft
|
|
1210
|
-
|
|
1211
|
-
### `class.deleteLabDraft`
|
|
1212
|
-
**Type**: Mutation
|
|
1213
|
-
**Access**: Teacher Only
|
|
1214
|
-
**Description**: Delete lab draft
|
|
1215
|
-
|
|
1216
|
-
### `class.publishLabDraft`
|
|
1217
|
-
**Type**: Mutation
|
|
1218
|
-
**Access**: Teacher Only
|
|
1219
|
-
**Description**: Publish lab draft as assignment
|
|
1220
|
-
|
|
1221
|
-
---
|
|
1222
|
-
|
|
1223
|
-
## 📄 Syllabus Management
|
|
1224
|
-
|
|
1225
|
-
### `class.getSyllabus`
|
|
1226
|
-
**Type**: Query
|
|
1227
|
-
**Access**: Class Member
|
|
1228
|
-
**Description**: Get class syllabus
|
|
1229
|
-
|
|
1230
|
-
**Input**:
|
|
1231
|
-
```typescript
|
|
1232
|
-
{
|
|
1233
|
-
classId: string;
|
|
1234
|
-
}
|
|
1235
|
-
```
|
|
1236
|
-
|
|
1237
|
-
**Output**:
|
|
1238
|
-
```typescript
|
|
1239
|
-
{
|
|
1240
|
-
syllabus: string;
|
|
1241
|
-
gradingBoundaries: GradingBoundary[];
|
|
1242
|
-
markSchemes: MarkScheme[];
|
|
1243
|
-
}
|
|
1244
|
-
```
|
|
1245
|
-
|
|
1246
|
-
### `class.updateSyllabus`
|
|
1247
|
-
**Type**: Mutation
|
|
1248
|
-
**Access**: Teacher Only
|
|
1249
|
-
**Description**: Update class syllabus
|
|
1250
|
-
|
|
1251
|
-
**Input**:
|
|
1252
|
-
```typescript
|
|
1253
|
-
{
|
|
1254
|
-
classId: string;
|
|
1255
|
-
contents: string;
|
|
1256
|
-
}
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
---
|
|
1260
|
-
|
|
1261
|
-
## 🗂️ File Organization
|
|
1262
|
-
|
|
1263
|
-
### `class.getFiles`
|
|
1264
|
-
**Type**: Query
|
|
1265
|
-
**Access**: Class Member
|
|
1266
|
-
**Description**: Get organized files for class
|
|
1267
|
-
|
|
1268
|
-
**Input**:
|
|
1269
|
-
```typescript
|
|
1270
|
-
{
|
|
1271
|
-
classId: string;
|
|
1272
|
-
}
|
|
1273
|
-
```
|
|
1274
|
-
|
|
1275
|
-
**Output**:
|
|
1276
|
-
```typescript
|
|
1277
|
-
Array<{
|
|
1278
|
-
id: string;
|
|
1279
|
-
title: string;
|
|
1280
|
-
teacher: {
|
|
1281
|
-
id: string;
|
|
1282
|
-
username: string;
|
|
1283
|
-
};
|
|
1284
|
-
teacherAttachments: File[];
|
|
1285
|
-
students: Array<{
|
|
1286
|
-
id: string;
|
|
1287
|
-
username: string;
|
|
1288
|
-
attachments: File[];
|
|
1289
|
-
annotations: File[];
|
|
1290
|
-
}>;
|
|
1291
|
-
}>
|
|
1292
|
-
```
|
|
1293
|
-
|
|
1294
|
-
---
|
|
1295
|
-
|
|
1296
|
-
## 🌐 Real-time Features
|
|
1297
|
-
|
|
1298
|
-
### Socket.IO Events
|
|
1299
|
-
- **Connection**: `/socket.io/`
|
|
1300
|
-
- **Events**: Class updates, new assignments, submissions, etc.
|
|
1301
|
-
|
|
1302
|
-
---
|
|
1303
|
-
|
|
1304
|
-
## 📊 Data Models
|
|
1305
|
-
|
|
1306
|
-
### File Object (Direct Upload)
|
|
1307
|
-
```typescript
|
|
1308
|
-
{
|
|
1309
|
-
name: string;
|
|
1310
|
-
type: string;
|
|
1311
|
-
size: number;
|
|
1312
|
-
// Note: No data field - files are uploaded directly to GCS
|
|
1313
|
-
}
|
|
1314
|
-
```
|
|
1315
|
-
|
|
1316
|
-
### Uploaded File Object (Database)
|
|
1317
|
-
```typescript
|
|
1318
|
-
{
|
|
1319
|
-
id: string;
|
|
1320
|
-
name: string;
|
|
1321
|
-
url: string; // GCS file path
|
|
1322
|
-
type: string;
|
|
1323
|
-
size: number;
|
|
1324
|
-
uploadStatus: 'PENDING' | 'UPLOADING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
1325
|
-
uploadProgress?: number;
|
|
1326
|
-
createdAt: Date;
|
|
1327
|
-
updatedAt: Date;
|
|
1328
|
-
}
|
|
1329
|
-
```
|
|
1330
|
-
|
|
1331
|
-
### Assignment Object
|
|
1332
|
-
```typescript
|
|
1333
|
-
{
|
|
1334
|
-
id: string;
|
|
1335
|
-
title: string;
|
|
1336
|
-
instructions: string;
|
|
1337
|
-
dueDate: Date;
|
|
1338
|
-
maxGrade?: number;
|
|
1339
|
-
graded: boolean;
|
|
1340
|
-
weight: number;
|
|
1341
|
-
type: AssignmentType;
|
|
1342
|
-
inProgress: boolean;
|
|
1343
|
-
template: boolean;
|
|
1344
|
-
attachments: File[];
|
|
1345
|
-
submissions: Submission[];
|
|
1346
|
-
section?: Section;
|
|
1347
|
-
teacher: User;
|
|
1348
|
-
class: Class;
|
|
1349
|
-
markScheme?: MarkScheme;
|
|
1350
|
-
gradingBoundary?: GradingBoundary;
|
|
1351
|
-
eventAttached?: Event;
|
|
1352
|
-
}
|
|
1353
|
-
```
|
|
1354
|
-
|
|
1355
|
-
### User Roles
|
|
1356
|
-
- `STUDENT`: Can view classes, submit assignments
|
|
1357
|
-
- `TEACHER`: Can create/manage classes, grade assignments
|
|
1358
|
-
- `ADMIN`: System administration
|
|
1359
|
-
- `NONE`: No specific role
|
|
1360
|
-
|
|
1361
|
-
### Assignment Types
|
|
1362
|
-
- `HOMEWORK`
|
|
1363
|
-
- `QUIZ`
|
|
1364
|
-
- `TEST`
|
|
1365
|
-
- `PROJECT`
|
|
1366
|
-
- `ESSAY`
|
|
1367
|
-
- `DISCUSSION`
|
|
1368
|
-
- `PRESENTATION`
|
|
1369
|
-
- `LAB`
|
|
1370
|
-
- `OTHER`
|
|
1371
|
-
|
|
1372
|
-
---
|
|
1373
|
-
|
|
1374
|
-
## 🔒 Access Control
|
|
1375
|
-
|
|
1376
|
-
### Public Endpoints
|
|
1377
|
-
- All `auth.*` endpoints
|
|
1378
|
-
|
|
1379
|
-
### Protected Endpoints
|
|
1380
|
-
- Require valid authentication token
|
|
1381
|
-
- User must be logged in
|
|
1382
|
-
|
|
1383
|
-
### Class Member Endpoints
|
|
1384
|
-
- Require `classId` parameter
|
|
1385
|
-
- User must be student or teacher in the class
|
|
1386
|
-
|
|
1387
|
-
### Teacher Only Endpoints
|
|
1388
|
-
- User must be teacher in the specified class
|
|
1389
|
-
- Full management capabilities
|
|
1390
|
-
|
|
1391
|
-
---
|
|
1392
|
-
|
|
1393
|
-
## ⚠️ Error Handling
|
|
1394
|
-
|
|
1395
|
-
### Common Error Codes
|
|
1396
|
-
- `UNAUTHORIZED`: Invalid or missing authentication
|
|
1397
|
-
- `FORBIDDEN`: Insufficient permissions
|
|
1398
|
-
- `NOT_FOUND`: Resource doesn't exist
|
|
1399
|
-
- `BAD_REQUEST`: Invalid input data
|
|
1400
|
-
- `CONFLICT`: Resource already exists
|
|
1401
|
-
- `INTERNAL_SERVER_ERROR`: Server error
|
|
1402
|
-
|
|
1403
|
-
### Error Response Format
|
|
1404
|
-
```typescript
|
|
1405
|
-
{
|
|
1406
|
-
error: {
|
|
1407
|
-
code: string;
|
|
1408
|
-
message: string;
|
|
1409
|
-
data?: {
|
|
1410
|
-
zodError?: any;
|
|
1411
|
-
prismaError?: any;
|
|
1412
|
-
};
|
|
1413
|
-
};
|
|
1414
|
-
}
|
|
1415
|
-
```
|
|
1416
|
-
|
|
1417
|
-
---
|
|
1418
|
-
|
|
1419
|
-
## 🚀 Usage Examples
|
|
1420
|
-
|
|
1421
|
-
### TypeScript Client Setup
|
|
1422
|
-
```typescript
|
|
1423
|
-
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
|
|
1424
|
-
import type { AppRouter } from '@studious-lms/server';
|
|
1425
|
-
|
|
1426
|
-
const trpc = createTRPCProxyClient<AppRouter>({
|
|
1427
|
-
links: [
|
|
1428
|
-
httpBatchLink({
|
|
1429
|
-
url: 'http://localhost:3001/trpc',
|
|
1430
|
-
headers() {
|
|
1431
|
-
return {
|
|
1432
|
-
authorization: `Bearer ${getAuthToken()}`,
|
|
1433
|
-
};
|
|
1434
|
-
},
|
|
1435
|
-
}),
|
|
1436
|
-
],
|
|
1437
|
-
});
|
|
1438
|
-
```
|
|
1439
|
-
|
|
1440
|
-
### Example API Calls
|
|
1441
|
-
```typescript
|
|
1442
|
-
// Login
|
|
1443
|
-
const loginResult = await trpc.auth.login.mutate({
|
|
1444
|
-
username: 'john_doe',
|
|
1445
|
-
password: 'password123'
|
|
1446
|
-
});
|
|
1447
|
-
|
|
1448
|
-
// Get classes
|
|
1449
|
-
const classes = await trpc.class.getAll.query();
|
|
1450
|
-
|
|
1451
|
-
// Create assignment
|
|
1452
|
-
const assignment = await trpc.assignment.create.mutate({
|
|
1453
|
-
classId: 'class-id',
|
|
1454
|
-
title: 'Math Homework',
|
|
1455
|
-
instructions: 'Complete problems 1-10',
|
|
1456
|
-
dueDate: '2024-01-15T23:59:59Z',
|
|
1457
|
-
maxGrade: 100,
|
|
1458
|
-
graded: true
|
|
1459
|
-
});
|
|
1460
|
-
```
|
|
1461
|
-
|
|
1462
|
-
---
|
|
1463
|
-
|
|
1464
|
-
## 📝 Notes for Frontend Developers
|
|
1465
|
-
|
|
1466
|
-
1. **File Uploads**: Files are uploaded directly to Google Cloud Storage (GCS) using signed URLs. See the "File Upload Flow" section below for details.
|
|
1467
|
-
2. **Date Handling**: All dates are ISO 8601 strings
|
|
1468
|
-
3. **Authentication**: Store JWT token and include in all requests
|
|
1469
|
-
4. **Real-time Updates**: Use Socket.IO for live updates
|
|
1470
|
-
5. **Error Handling**: Always handle tRPC errors appropriately
|
|
1471
|
-
6. **Type Safety**: Use the exported TypeScript types for full type safety
|
|
1472
|
-
|
|
1473
|
-
### 📤 File Upload Flow (Direct Upload to GCS)
|
|
1474
|
-
|
|
1475
|
-
**Important**: Files are NO LONGER sent as base64 encoded strings. Instead, they are uploaded directly to Google Cloud Storage for better performance and scalability.
|
|
1476
|
-
|
|
1477
|
-
#### Step-by-Step Process:
|
|
1478
|
-
|
|
1479
|
-
**1. Get Signed Upload URLs**
|
|
1480
|
-
```typescript
|
|
1481
|
-
// For assignment attachments
|
|
1482
|
-
const uploadResponse = await trpc.assignment.getAssignmentUploadUrls.mutate({
|
|
1483
|
-
assignmentId: "assignment-id",
|
|
1484
|
-
classId: "class-id",
|
|
1485
|
-
files: [
|
|
1486
|
-
{ name: "homework.pdf", type: "application/pdf", size: 102400 },
|
|
1487
|
-
{ name: "notes.docx", type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", size: 51200 }
|
|
1488
|
-
]
|
|
1489
|
-
});
|
|
1490
|
-
|
|
1491
|
-
// For submission attachments
|
|
1492
|
-
const uploadResponse = await trpc.assignment.getSubmissionUploadUrls.mutate({
|
|
1493
|
-
assignmentId: "assignment-id",
|
|
1494
|
-
classId: "class-id",
|
|
1495
|
-
files: [
|
|
1496
|
-
{ name: "solution.pdf", type: "application/pdf", size: 204800 }
|
|
1497
|
-
]
|
|
1498
|
-
});
|
|
1499
|
-
|
|
1500
|
-
// For folder files
|
|
1501
|
-
const uploadResponse = await trpc.folder.getUploadUrls.mutate({
|
|
1502
|
-
folderId: "folder-id",
|
|
1503
|
-
classId: "class-id",
|
|
1504
|
-
files: [
|
|
1505
|
-
{ name: "lecture.pptx", type: "application/vnd.openxmlformats-officedocument.presentationml.presentation", size: 512000 }
|
|
1506
|
-
]
|
|
1507
|
-
});
|
|
1508
|
-
```
|
|
1509
|
-
|
|
1510
|
-
**2. Upload Files Directly to GCS**
|
|
1511
|
-
```typescript
|
|
1512
|
-
for (const uploadFile of uploadResponse.uploadFiles) {
|
|
1513
|
-
const file = files.find(f => f.name === uploadFile.name);
|
|
1514
|
-
|
|
1515
|
-
// Optional: Track upload progress
|
|
1516
|
-
const xhr = new XMLHttpRequest();
|
|
1517
|
-
xhr.upload.addEventListener('progress', async (e) => {
|
|
1518
|
-
if (e.lengthComputable) {
|
|
1519
|
-
const progress = (e.loaded / e.total) * 100;
|
|
1520
|
-
await trpc.assignment.updateUploadProgress.mutate({
|
|
1521
|
-
fileId: uploadFile.id,
|
|
1522
|
-
progress: Math.round(progress)
|
|
1523
|
-
});
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
1526
|
-
|
|
1527
|
-
// Upload to GCS using signed URL
|
|
1528
|
-
await fetch(uploadFile.uploadUrl, {
|
|
1529
|
-
method: 'PUT',
|
|
1530
|
-
body: file,
|
|
1531
|
-
headers: {
|
|
1532
|
-
'Content-Type': file.type
|
|
1533
|
-
}
|
|
1534
|
-
});
|
|
1535
|
-
}
|
|
1536
|
-
```
|
|
1537
|
-
|
|
1538
|
-
**3. Confirm Upload Success**
|
|
1539
|
-
```typescript
|
|
1540
|
-
// Confirm each file upload
|
|
1541
|
-
for (const uploadFile of uploadResponse.uploadFiles) {
|
|
1542
|
-
await trpc.assignment.confirmAssignmentUpload.mutate({
|
|
1543
|
-
fileId: uploadFile.id,
|
|
1544
|
-
uploadSuccess: true // or false if upload failed
|
|
1545
|
-
});
|
|
1546
|
-
}
|
|
1547
|
-
```
|
|
1548
|
-
|
|
1549
|
-
#### Benefits of Direct Upload:
|
|
1550
|
-
- ✅ **33% smaller payload** (no base64 encoding overhead)
|
|
1551
|
-
- ✅ **Faster uploads** (direct to GCS, no server processing)
|
|
1552
|
-
- ✅ **Better scalability** (server doesn't handle file data)
|
|
1553
|
-
- ✅ **Upload progress tracking** (real-time progress updates)
|
|
1554
|
-
- ✅ **Better error handling** (retry failed uploads individually)
|
|
1555
|
-
|
|
1556
|
-
#### Available Direct Upload Endpoints:
|
|
1557
|
-
|
|
1558
|
-
**Assignment Attachments:**
|
|
1559
|
-
- `assignment.getAssignmentUploadUrls` - Get signed URLs for assignment files
|
|
1560
|
-
- `assignment.confirmAssignmentUpload` - Confirm file upload success
|
|
1561
|
-
|
|
1562
|
-
**Submission Attachments:**
|
|
1563
|
-
- `assignment.getSubmissionUploadUrls` - Get signed URLs for submission files
|
|
1564
|
-
- `assignment.confirmSubmissionUpload` - Confirm file upload success
|
|
1565
|
-
|
|
1566
|
-
**Folder Files:**
|
|
1567
|
-
- `folder.getUploadUrls` - Get signed URLs for folder files
|
|
1568
|
-
- `folder.confirmUpload` - Confirm file upload success
|
|
1569
|
-
|
|
1570
|
-
**Progress Tracking:**
|
|
1571
|
-
- `assignment.updateUploadProgress` - Update upload progress for any file
|
|
1572
|
-
|
|
1573
|
-
---
|
|
1574
|
-
|
|
1575
|
-
*Generated on: September 14, 2025*
|
|
1576
|
-
*Version: 1.2.0*
|
|
1577
|
-
*Last Updated: October 2025*
|
|
1578
|
-
|
|
1579
|
-
## 📋 Changelog
|
|
1580
|
-
|
|
1581
|
-
### Version 1.2.0 (October 2025)
|
|
1582
|
-
- 🚀 **BREAKING CHANGE**: Migrated from base64 file uploads to direct GCS uploads
|
|
1583
|
-
- ✅ Added comprehensive direct upload documentation with step-by-step flow
|
|
1584
|
-
- ✅ Updated File Object data models to reflect new upload system
|
|
1585
|
-
- ✅ Added upload status tracking (`PENDING`, `UPLOADING`, `COMPLETED`, `FAILED`, `CANCELLED`)
|
|
1586
|
-
- ✅ Added new direct upload endpoints for assignments, submissions, and folders
|
|
1587
|
-
- ✅ Added upload progress tracking endpoint
|
|
1588
|
-
- ✅ Updated user profile picture upload to support both custom uploads and DiceBear avatars
|
|
1589
|
-
- 📝 Documented all benefits of direct upload approach (33% smaller payload, faster uploads, etc.)
|
|
1590
|
-
|
|
1591
|
-
### Version 1.1.0 (September 2025)
|
|
1592
|
-
- ✅ Added complete Folder Management endpoints (`folder.*`)
|
|
1593
|
-
- ✅ Added Section Management endpoints (`section.*`)
|
|
1594
|
-
- ✅ Added Attendance Management endpoints (`attendance.*`)
|
|
1595
|
-
- ✅ Added Agenda Management endpoints (`agenda.*`)
|
|
1596
|
-
- ❌ Removed School Management section (not implemented)
|
|
1597
|
-
- 🔧 Improved API coverage from ~70% to ~95%
|