shared/domain/course/
unit.rs

1//! Types for Course Units
2
3use crate::{
4    api::endpoints::PathPart,
5    domain::{
6        audio::AudioId, image::ImageId, module::body::_groups::design::YoutubeEmbed, pdf::PdfId,
7    },
8};
9use macros::make_path_parts;
10use serde::{Deserialize, Serialize};
11
12use super::CourseId;
13
14wrap_uuid! {
15    /// Wrapper type around [`Uuid`](Uuid), represents the ID of a Course Unit.
16    pub struct CourseUnitId
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone)]
20#[serde(rename_all = "camelCase")]
21/// Unit attached to a Course.
22pub struct CourseUnit {
23    /// Unit Id
24    pub id: CourseUnitId,
25    /// Name for Course Unit
26    pub display_name: String,
27
28    /// Description of Course Unit
29    pub description: String,
30
31    /// Content of Course Unit
32    #[serde(flatten)]
33    pub value: CourseUnitValue,
34}
35
36make_path_parts!(CreateCourseUnitPath => "/v1/course/{}/unit" => CourseId);
37
38/// Request to create a new `CourseUnit`.
39///
40/// [`course::unit::Create`](crate::api::endpoints::course::unit::Create)
41#[derive(Serialize, Deserialize, Debug)]
42#[serde(rename_all = "camelCase")]
43pub struct CourseUnitCreateRequest {
44    /// Display name for Course Unit
45    pub display_name: String,
46
47    /// Type of Course Unit
48    pub description: String,
49
50    /// Value of Course Unit
51    #[serde(flatten)]
52    pub value: CourseUnitValue,
53}
54
55make_path_parts!(UpdateCourseUnitPath => "/v1/course/{}/unit/{}" => CourseId, CourseUnitId);
56
57/// Request to update an `CourseUnit`.
58///
59/// [`course::unit::Update`](crate::api::endpoints::course::unit::Update)
60#[derive(Serialize, Deserialize, Debug, Default)]
61#[serde(rename_all = "camelCase")]
62pub struct CourseUnitUpdateRequest {
63    /// Course Unit display name
64    #[serde(skip_serializing_if = "Option::is_none")]
65    #[serde(default)]
66    pub display_name: Option<String>,
67
68    /// Description of Course Unit
69    #[serde(skip_serializing_if = "Option::is_none")]
70    #[serde(default)]
71    pub description: Option<String>,
72
73    /// Kind of Course Unit
74    #[serde(skip_serializing_if = "Option::is_none")]
75    #[serde(default)]
76    #[serde(flatten)]
77    pub value: Option<CourseUnitValue>,
78
79    /// Kind of Course Unit
80    #[serde(default)]
81    pub index: Option<u16>,
82}
83
84make_path_parts!(GetCourseUnitDraftPath => "/v1/course/{}/unit/{}/draft" => CourseId, CourseUnitId);
85
86make_path_parts!(GetCourseUnitLivePath => "/v1/course/{}/unit/{}/live" => CourseId, CourseUnitId);
87
88make_path_parts!(DeleteCourseUnitPath => "/v1/course/{}/unit/{}/draft" => CourseId, CourseUnitId);
89
90/// Value of Course Unit
91#[derive(Deserialize, Serialize, Debug, Clone)]
92#[serde(rename_all = "camelCase")]
93pub enum CourseUnitValue {
94    /// Course Unit kind: image
95    ImageId(ImageId),
96    /// Course Unit kind: audioFile
97    AudioId(AudioId),
98    /// Course Unit kind: link
99    Link(url::Url),
100    /// Course Unit kind: pdf
101    PdfId(PdfId),
102    /// Course Unit kind: YouTube Video
103    Video(YoutubeEmbed),
104}