Skip to main content

canvas_lms_api/resources/
section.rs

1use crate::{error::Result, http::Requester, pagination::PageStream, params::wrap_params};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6use crate::resources::{enrollment::Enrollment, progress::Progress, submission::Submission};
7
8/// Parameters for updating a Canvas section.
9#[derive(Debug, Default, Clone, Serialize)]
10pub struct UpdateSectionParams {
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub name: Option<String>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub start_at: Option<DateTime<Utc>>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub end_at: Option<DateTime<Utc>>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub restrict_enrollments_to_section_dates: Option<bool>,
19}
20
21/// Parameters for enrolling a user in a section.
22#[derive(Debug, Default, Clone, Serialize)]
23pub struct EnrollUserParams {
24    pub user_id: u64,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub r#type: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub role: Option<String>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub enrollment_state: Option<String>,
31}
32
33/// A section within a Canvas course.
34#[derive(Debug, Clone, Deserialize, Serialize, canvas_lms_api_derive::CanvasResource)]
35pub struct Section {
36    pub id: u64,
37    pub course_id: Option<u64>,
38    pub name: Option<String>,
39    pub sis_section_id: Option<String>,
40    pub integration_id: Option<String>,
41    pub sis_import_id: Option<u64>,
42    pub start_at: Option<DateTime<Utc>>,
43    pub end_at: Option<DateTime<Utc>>,
44    pub restrict_enrollments_to_section_dates: Option<bool>,
45    pub nonxlist_course_id: Option<u64>,
46    pub total_students: Option<u64>,
47
48    #[serde(skip)]
49    pub(crate) requester: Option<Arc<Requester>>,
50}
51
52impl Section {
53    /// Update this section's name or dates.
54    ///
55    /// # Canvas API
56    /// `PUT /api/v1/sections/:id`
57    pub async fn edit(&self, params: UpdateSectionParams) -> Result<Section> {
58        let form = wrap_params("course_section", &params);
59        let mut s: Section = self
60            .req()
61            .put(&format!("sections/{}", self.id), &form)
62            .await?;
63        s.requester = self.requester.clone();
64        Ok(s)
65    }
66
67    /// Delete this section.
68    ///
69    /// # Canvas API
70    /// `DELETE /api/v1/sections/:id`
71    pub async fn delete(&self) -> Result<Section> {
72        let mut s: Section = self
73            .req()
74            .delete(&format!("sections/{}", self.id), &[])
75            .await?;
76        s.requester = self.requester.clone();
77        Ok(s)
78    }
79
80    /// Enroll a user in this section.
81    ///
82    /// # Canvas API
83    /// `POST /api/v1/sections/:section_id/enrollments`
84    pub async fn enroll_user(&self, params: EnrollUserParams) -> Result<Enrollment> {
85        let form = wrap_params("enrollment", &params);
86        let mut e: Enrollment = self
87            .req()
88            .post(&format!("sections/{}/enrollments", self.id), &form)
89            .await?;
90        e.requester = self.requester.clone();
91        Ok(e)
92    }
93
94    /// Stream all enrollments in this section.
95    ///
96    /// # Canvas API
97    /// `GET /api/v1/sections/:section_id/enrollments`
98    pub fn get_enrollments(&self) -> PageStream<Enrollment> {
99        PageStream::new_with_injector(
100            Arc::clone(self.req()),
101            &format!("sections/{}/enrollments", self.id),
102            vec![],
103            |mut e: Enrollment, req| {
104                e.requester = Some(Arc::clone(&req));
105                e
106            },
107        )
108    }
109
110    /// Move this section to another course (cross-list).
111    ///
112    /// # Canvas API
113    /// `POST /api/v1/sections/:id/crosslist/:new_course_id`
114    pub async fn cross_list_section(&self, new_course_id: u64) -> Result<Section> {
115        let mut s: Section = self
116            .req()
117            .post(
118                &format!("sections/{}/crosslist/{new_course_id}", self.id),
119                &[],
120            )
121            .await?;
122        s.requester = self.requester.clone();
123        Ok(s)
124    }
125
126    /// Undo cross-listing of this section.
127    ///
128    /// # Canvas API
129    /// `DELETE /api/v1/sections/:id/crosslist`
130    pub async fn decross_list_section(&self) -> Result<Section> {
131        let mut s: Section = self
132            .req()
133            .delete(&format!("sections/{}/crosslist", self.id), &[])
134            .await?;
135        s.requester = self.requester.clone();
136        Ok(s)
137    }
138
139    /// Get the assignment override for a specific assignment in this section.
140    ///
141    /// # Canvas API
142    /// `GET /api/v1/sections/:course_section_id/assignments/:assignment_id/override`
143    pub async fn get_assignment_override(&self, assignment_id: u64) -> Result<serde_json::Value> {
144        self.req()
145            .get(
146                &format!("sections/{}/assignments/{assignment_id}/override", self.id),
147                &[],
148            )
149            .await
150    }
151
152    /// Stream submissions for multiple assignments in this section.
153    ///
154    /// # Canvas API
155    /// `GET /api/v1/sections/:section_id/students/submissions`
156    pub fn get_multiple_submissions(&self) -> PageStream<Submission> {
157        PageStream::new(
158            Arc::clone(self.req()),
159            &format!("sections/{}/students/submissions", self.id),
160            vec![],
161        )
162    }
163
164    /// Bulk-update grades for this section asynchronously.
165    ///
166    /// # Canvas API
167    /// `POST /api/v1/sections/:section_id/submissions/update_grades`
168    pub async fn submissions_bulk_update(&self, params: &[(String, String)]) -> Result<Progress> {
169        let mut p: Progress = self
170            .req()
171            .post(
172                &format!("sections/{}/submissions/update_grades", self.id),
173                params,
174            )
175            .await?;
176        p.requester = self.requester.clone();
177        Ok(p)
178    }
179}