Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v5

- name: Install modules
run: yarn

- name: Run ESLint
run: yarn run lint

Expand All @@ -17,4 +19,4 @@ jobs:
slack_hook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
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 }}"
success: ${{ job.status }}
if: always()
if: always()
6 changes: 4 additions & 2 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v5

- uses: actions/setup-node@v6
with:
node-version: '16.x'
registry-url: 'https://registry.npmjs.org'

- run: yarn && yarn build

- uses: JS-DevTools/npm-publish@v1
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ dist
/lib

*.iml
*.ipr
*.iws
88 changes: 83 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,16 @@ return `Course` object
Course = {
id: string,
name: string,
description?: string,
modules: Module[],
assignments: Assignment[],
creationDate: Date,
archivedDate?: Date,
archived: boolen
archivedDate: Date,
archived: boolean,
start?: Date,
end?: Date,
timezone?: string,
tags?: string[]
}
Module = {
id: string,
Expand All @@ -169,8 +174,16 @@ return `Course` object
Course = {
id: string,
name: string,
description?: string,
modules: Module[],
assignments: Assignment[]
assignments: Assignment[],
creationDate: Date,
archivedDate: Date,
archived: boolean,
start?: Date,
end?: Date,
timezone?: string,
tags?: string[]
}
Module = {
id: string,
Expand Down Expand Up @@ -271,6 +284,71 @@ Fetch course teachers
```
returns user `User[]` object

Add teacher to course

```
await codio.v1.course.addTeacher(courseId, userId, readOnly?)
```
- `readOnly` (optional, default `false`): when `true`, the user is added as a read‑only teacher.
- returns `boolean` — true if the teacher was successfully added

Example:
```javascript
// Add full teacher (default)
await codio.v1.course.addTeacher(courseId, userId)

// Add read-only teacher
await codio.v1.course.addTeacher(courseId, userId, true)
```

#### Course management

Create course

```
await codio.v1.course.createCourse(courseData)
```
Parameters:
```
CreateCourseRequest = {
name: string,
description?: string,
start?: string,
end?: string,
timezone?: string,
tags?: string[]
}
```
Notes:
- `start` and `end` are ISO 8601 strings (e.g., `2025-09-01T13:00:00Z`).
- `timezone` should be an IANA timezone name (e.g., `America/New_York`).
- In responses, `Course.start` is a `Date` (or absent), while `CreateCourseRequest.start` is a string.
returns `string` — newly created courseId

Example:
```javascript
const courseId = await codio.v1.course.createCourse({
name: 'Intro to CS',
description: 'Fall 2025 section',
start: '2025-09-01T13:00:00Z', // ISO 8601 string
end: '2025-12-20T23:59:59Z', // ISO 8601 string
timezone: 'America/New_York',
tags: ['CS101','Fall-2025']
})
```

Create module

```
await codio.v1.course.createModule(courseId, moduleName)
```
returns `string` — newly created moduleId

Example:
```javascript
const moduleId = await codio.v1.course.createModule(courseId, 'Module 1: Basics')
```


#### Export student CSV

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

```javascript
```
enableResetAssignmentByStudent?: boolean
disableDownloadByStudent?: boolean
visibilityOnDisabled?: string, // "READ_ONLY", "NO_ACCESS",
Expand Down Expand Up @@ -575,7 +653,7 @@ Set time limits on a per-student basis

```javascript
await codio.assignment.updateStudentTimeExtension(courseId, assignmentId, studentId, {
extendedDeadline: minutes
extendedDeadline: minutes,
extendedTimeLimit: minutes
})
```
Expand Down
13 changes: 13 additions & 0 deletions examples/course/addTeacher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { codio, auth } = require('../auth.js')
const { courseId, userIdToAdd } = require('../data.js')

async function main() {
await auth

// Add the user as a read-only teacher (third param is optional; default is false)
const result = await codio.course.addTeacher(courseId, userIdToAdd, true)
console.log(result)

}

main()
23 changes: 22 additions & 1 deletion examples/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,26 @@ const assignmentData = {
}
}
}
const userIdToAdd = "your user id"

module.exports = { courseId, courseName, assignmentId, studentId, studentEmail, studentLogin, libraryId, libraryName, projectPath, stackId, stackVersionId, archivePath, yamlMapDir, courseIdToArchive, leanersMapping, moduleName, courseData, assignmentData }
module.exports = {
courseId,
courseName,
assignmentId,
studentId,
studentEmail,
studentLogin,
libraryId,
libraryName,
projectPath,
stackId,
stackVersionId,
archivePath,
yamlMapDir,
courseIdToArchive,
leanersMapping,
moduleName,
courseData,
assignmentData,
userIdToAdd
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codio-api-js",
"version": "0.16.0",
"version": "0.17.0",
"description": "JS client to Codio API",
"repository": "https://github.com/codio/codio-api-js",
"author": "Max Kraev <maxim.kraev@gmail.com>",
Expand Down
33 changes: 32 additions & 1 deletion src/lib/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ export type Module = {
export type Course = {
id: string
name: string
description: string | undefined
modules: Module[]
assignments: Assignment[]
creationDate: Date
archivedDate: Date
archived: boolean
start: Date | undefined
end: Date | undefined
timezone: string | undefined
tags: string[] | undefined
}

export type StudentProgress = {
Expand Down Expand Up @@ -94,6 +99,12 @@ function flattenAssignments(course: any) {
if (course.archivedDate) {
course.archivedDate = new Date(course.archivedDate)
}
if (course.start) {
course.start = new Date(course.start)
}
if (course.end) {
course.end = new Date(course.end)
}
}

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

export async function addTeacher(courseId: string, userId: string, readOnly = false): Promise<boolean> {
const api = bent(getApiV1Url(), 'POST', 'json', 200)
try {
const body = { userId: userId, readOnly: readOnly }
const res = await api(`/courses/${courseId}/teachers`, body, getBearer())
const completed = res['completed']
if (!completed) {
throw new Error('Something went wrong')
}
return completed
} catch (error: any) {
if (error.json) {
const message = JSON.stringify(await error.json())
throw new Error(message)
}
throw error
}
}

const course = {
assignmentStudentsProgress,
info,
Expand Down Expand Up @@ -654,7 +684,8 @@ const course = {
exportLLMProxyData,
filterLearnersForMentors,
createCourse,
createModule
createModule,
addTeacher
}

export default course