Skip to content

Commit d62a8d9

Browse files
authored
Add API method to add a teacher to a course (#64)
* Add API method to add a teacher to a course see https://bugtracker.codiodev.com/issue/codio-17247
1 parent bacfb4b commit d62a8d9

8 files changed

Lines changed: 161 additions & 12 deletions

File tree

.github/workflows/lint.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ jobs:
55
build:
66
runs-on: ubuntu-latest
77
steps:
8-
- uses: actions/checkout@v2
8+
- uses: actions/checkout@v5
9+
910
- name: Install modules
1011
run: yarn
12+
1113
- name: Run ESLint
1214
run: yarn run lint
1315

@@ -17,4 +19,4 @@ jobs:
1719
slack_hook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
1820
message: "<https://github.com/${{ github.repository }}/actions/runs/${{github.run_id}}|${{ github.workflow }} release-proto-check> for ${{ github.repository }} by ${{ github.actor }} has ${{ job.status }} on branch ${{ github.ref }}"
1921
success: ${{ job.status }}
20-
if: always()
22+
if: always()

.github/workflows/publish.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ jobs:
88
build:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@v3
12-
- uses: actions/setup-node@v3
11+
- uses: actions/checkout@v5
12+
13+
- uses: actions/setup-node@v6
1314
with:
1415
node-version: '16.x'
1516
registry-url: 'https://registry.npmjs.org'
17+
1618
- run: yarn && yarn build
1719

1820
- uses: JS-DevTools/npm-publish@v1

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,5 @@ dist
106106
/lib
107107

108108
*.iml
109+
*.ipr
110+
*.iws

README.md

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,16 @@ return `Course` object
140140
Course = {
141141
id: string,
142142
name: string,
143+
description?: string,
143144
modules: Module[],
144145
assignments: Assignment[],
145146
creationDate: Date,
146-
archivedDate?: Date,
147-
archived: boolen
147+
archivedDate: Date,
148+
archived: boolean,
149+
start?: Date,
150+
end?: Date,
151+
timezone?: string,
152+
tags?: string[]
148153
}
149154
Module = {
150155
id: string,
@@ -169,8 +174,16 @@ return `Course` object
169174
Course = {
170175
id: string,
171176
name: string,
177+
description?: string,
172178
modules: Module[],
173-
assignments: Assignment[]
179+
assignments: Assignment[],
180+
creationDate: Date,
181+
archivedDate: Date,
182+
archived: boolean,
183+
start?: Date,
184+
end?: Date,
185+
timezone?: string,
186+
tags?: string[]
174187
}
175188
Module = {
176189
id: string,
@@ -271,6 +284,71 @@ Fetch course teachers
271284
```
272285
returns user `User[]` object
273286

287+
Add teacher to course
288+
289+
```
290+
await codio.v1.course.addTeacher(courseId, userId, readOnly?)
291+
```
292+
- `readOnly` (optional, default `false`): when `true`, the user is added as a read‑only teacher.
293+
- returns `boolean` — true if the teacher was successfully added
294+
295+
Example:
296+
```javascript
297+
// Add full teacher (default)
298+
await codio.v1.course.addTeacher(courseId, userId)
299+
300+
// Add read-only teacher
301+
await codio.v1.course.addTeacher(courseId, userId, true)
302+
```
303+
304+
#### Course management
305+
306+
Create course
307+
308+
```
309+
await codio.v1.course.createCourse(courseData)
310+
```
311+
Parameters:
312+
```
313+
CreateCourseRequest = {
314+
name: string,
315+
description?: string,
316+
start?: string,
317+
end?: string,
318+
timezone?: string,
319+
tags?: string[]
320+
}
321+
```
322+
Notes:
323+
- `start` and `end` are ISO 8601 strings (e.g., `2025-09-01T13:00:00Z`).
324+
- `timezone` should be an IANA timezone name (e.g., `America/New_York`).
325+
- In responses, `Course.start` is a `Date` (or absent), while `CreateCourseRequest.start` is a string.
326+
returns `string` — newly created courseId
327+
328+
Example:
329+
```javascript
330+
const courseId = await codio.v1.course.createCourse({
331+
name: 'Intro to CS',
332+
description: 'Fall 2025 section',
333+
start: '2025-09-01T13:00:00Z', // ISO 8601 string
334+
end: '2025-12-20T23:59:59Z', // ISO 8601 string
335+
timezone: 'America/New_York',
336+
tags: ['CS101','Fall-2025']
337+
})
338+
```
339+
340+
Create module
341+
342+
```
343+
await codio.v1.course.createModule(courseId, moduleName)
344+
```
345+
returns `string` — newly created moduleId
346+
347+
Example:
348+
```javascript
349+
const moduleId = await codio.v1.course.createModule(courseId, 'Module 1: Basics')
350+
```
351+
274352

275353
#### Export student CSV
276354

@@ -509,7 +587,7 @@ returns `AssignmentSettings` - Settings, missed properties won't be updated
509587
const settings = await codio.assignment.getSettings('<course>', '<assignments>')
510588
```
511589

512-
```javascript
590+
```
513591
enableResetAssignmentByStudent?: boolean
514592
disableDownloadByStudent?: boolean
515593
visibilityOnDisabled?: string, // "READ_ONLY", "NO_ACCESS",
@@ -575,7 +653,7 @@ Set time limits on a per-student basis
575653

576654
```javascript
577655
await codio.assignment.updateStudentTimeExtension(courseId, assignmentId, studentId, {
578-
extendedDeadline: minutes
656+
extendedDeadline: minutes,
579657
extendedTimeLimit: minutes
580658
})
581659
```

examples/course/addTeacher.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { codio, auth } = require('../auth.js')
2+
const { courseId, userIdToAdd } = require('../data.js')
3+
4+
async function main() {
5+
await auth
6+
7+
// Add the user as a read-only teacher (third param is optional; default is false)
8+
const result = await codio.course.addTeacher(courseId, userIdToAdd, true)
9+
console.log(result)
10+
11+
}
12+
13+
main()

examples/data.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,26 @@ const assignmentData = {
4343
}
4444
}
4545
}
46+
const userIdToAdd = "your user id"
4647

47-
module.exports = { courseId, courseName, assignmentId, studentId, studentEmail, studentLogin, libraryId, libraryName, projectPath, stackId, stackVersionId, archivePath, yamlMapDir, courseIdToArchive, leanersMapping, moduleName, courseData, assignmentData }
48+
module.exports = {
49+
courseId,
50+
courseName,
51+
assignmentId,
52+
studentId,
53+
studentEmail,
54+
studentLogin,
55+
libraryId,
56+
libraryName,
57+
projectPath,
58+
stackId,
59+
stackVersionId,
60+
archivePath,
61+
yamlMapDir,
62+
courseIdToArchive,
63+
leanersMapping,
64+
moduleName,
65+
courseData,
66+
assignmentData,
67+
userIdToAdd
68+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codio-api-js",
3-
"version": "0.16.0",
3+
"version": "0.17.0",
44
"description": "JS client to Codio API",
55
"repository": "https://github.com/codio/codio-api-js",
66
"author": "Max Kraev <maxim.kraev@gmail.com>",

src/lib/course.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@ export type Module = {
2121
export type Course = {
2222
id: string
2323
name: string
24+
description: string | undefined
2425
modules: Module[]
2526
assignments: Assignment[]
2627
creationDate: Date
2728
archivedDate: Date
2829
archived: boolean
30+
start: Date | undefined
31+
end: Date | undefined
32+
timezone: string | undefined
33+
tags: string[] | undefined
2934
}
3035

3136
export type StudentProgress = {
@@ -94,6 +99,12 @@ function flattenAssignments(course: any) {
9499
if (course.archivedDate) {
95100
course.archivedDate = new Date(course.archivedDate)
96101
}
102+
if (course.start) {
103+
course.start = new Date(course.start)
104+
}
105+
if (course.end) {
106+
course.end = new Date(course.end)
107+
}
97108
}
98109

99110
export async function info(courseId: string, withHiddenAssignments = true): Promise<Course> {
@@ -625,6 +636,25 @@ export async function createModule(courseId: string, moduleName: string): Promis
625636
}
626637
}
627638

639+
export async function addTeacher(courseId: string, userId: string, readOnly = false): Promise<boolean> {
640+
const api = bent(getApiV1Url(), 'POST', 'json', 200)
641+
try {
642+
const body = { userId: userId, readOnly: readOnly }
643+
const res = await api(`/courses/${courseId}/teachers`, body, getBearer())
644+
const completed = res['completed']
645+
if (!completed) {
646+
throw new Error('Something went wrong')
647+
}
648+
return completed
649+
} catch (error: any) {
650+
if (error.json) {
651+
const message = JSON.stringify(await error.json())
652+
throw new Error(message)
653+
}
654+
throw error
655+
}
656+
}
657+
628658
const course = {
629659
assignmentStudentsProgress,
630660
info,
@@ -654,7 +684,8 @@ const course = {
654684
exportLLMProxyData,
655685
filterLearnersForMentors,
656686
createCourse,
657-
createModule
687+
createModule,
688+
addTeacher
658689
}
659690

660691
export default course

0 commit comments

Comments
 (0)