shared/domain/module/body/
resource_cover.rs

1use crate::domain::module::{
2    body::{Body, BodyConvert, BodyExt, StepExt, ThemeId, _groups::design::*},
3    ModuleKind,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8/// The body for [`Cover`](crate::domain::module::ModuleKind::Cover) modules.
9#[derive(Clone, Serialize, Deserialize, Debug)]
10pub struct ModuleData {
11    /// The content
12    pub content: Option<Content>,
13}
14
15// cover always has data
16impl Default for ModuleData {
17    fn default() -> Self {
18        Self {
19            content: Some(Content::default()),
20        }
21    }
22}
23
24impl BodyExt<(), Step> for ModuleData {
25    fn as_body(&self) -> Body {
26        Body::ResourceCover(self.clone())
27    }
28
29    fn is_complete(&self) -> bool {
30        self.content.is_some()
31    }
32
33    fn kind() -> ModuleKind {
34        ModuleKind::ResourceCover
35    }
36
37    fn new_with_mode_and_theme(_mode: (), _theme_id: ThemeId) -> Self {
38        ModuleData {
39            content: Some(Content::default()),
40        }
41    }
42
43    fn mode(&self) -> Option<()> {
44        None
45    }
46
47    fn requires_choose_mode(&self) -> bool {
48        false
49    }
50
51    fn set_editor_state_step(&mut self, step: Step) {
52        if let Some(content) = self.content.as_mut() {
53            content.editor_state.step = step;
54        }
55    }
56    fn set_editor_state_steps_completed(&mut self, steps_completed: HashSet<Step>) {
57        if let Some(content) = self.content.as_mut() {
58            content.editor_state.steps_completed = steps_completed;
59        }
60    }
61
62    fn get_editor_state_step(&self) -> Option<Step> {
63        self.content
64            .as_ref()
65            .map(|content| content.editor_state.step)
66    }
67
68    fn get_editor_state_steps_completed(&self) -> Option<HashSet<Step>> {
69        self.content
70            .as_ref()
71            .map(|content| content.editor_state.steps_completed.clone())
72    }
73
74    fn set_theme(&mut self, theme_id: ThemeId) {
75        if let Some(content) = self.content.as_mut() {
76            content.base.theme = theme_id;
77        }
78    }
79
80    fn get_theme(&self) -> Option<ThemeId> {
81        self.content.as_ref().map(|content| content.base.theme)
82    }
83}
84
85impl BodyConvert for ModuleData {}
86
87impl TryFrom<Body> for ModuleData {
88    type Error = &'static str;
89
90    fn try_from(body: Body) -> Result<Self, Self::Error> {
91        match body {
92            Body::ResourceCover(data) => Ok(data),
93            _ => Err("cannot convert body to cover!"),
94        }
95    }
96}
97
98/// The body for [`Cover`](crate::domain::module::ModuleKind::Cover) modules.
99#[derive(Default, Clone, Serialize, Deserialize, Debug)]
100pub struct Content {
101    /// The editor state
102    pub editor_state: EditorState,
103
104    /// The base content for all design modules
105    pub base: BaseContent,
106}
107
108/// Editor state
109#[derive(Default, Clone, Serialize, Deserialize, Debug)]
110pub struct EditorState {
111    /// the current step
112    pub step: Step,
113
114    /// the completed steps
115    pub steps_completed: HashSet<Step>,
116}
117
118/// The Steps
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
120pub enum Step {
121    /// Step 1
122    One,
123    /// Step 2
124    Two,
125    /// Step 3
126    Three,
127}
128
129impl Default for Step {
130    fn default() -> Self {
131        Self::One
132    }
133}
134
135impl StepExt for Step {
136    fn next(&self) -> Option<Self> {
137        match self {
138            Self::One => Some(Self::Two),
139            Self::Two => Some(Self::Three),
140            Self::Three => None,
141        }
142    }
143
144    fn as_number(&self) -> usize {
145        match self {
146            Self::One => 1,
147            Self::Two => 2,
148            Self::Three => 3,
149        }
150    }
151
152    fn label(&self) -> &'static str {
153        const STR_DESIGN: &'static str = "Design";
154        const STR_CONTENT: &'static str = "Content";
155        const STR_PREVIEW: &'static str = "Preview";
156
157        match self {
158            Self::One => STR_DESIGN,
159            Self::Two => STR_CONTENT,
160            Self::Three => STR_PREVIEW,
161        }
162    }
163
164    fn get_list() -> Vec<Self> {
165        vec![Self::One, Self::Two, Self::Three]
166    }
167    fn get_preview() -> Self {
168        Self::Three
169    }
170}