chrono_datepicker_core/config/
mod.rs1pub mod date_constraints;
2
3use crate::dialog_view_type::DialogViewType;
4use chrono::prelude::*;
5
6use self::date_constraints::HasDateConstraints;
7
8#[derive(Default, Debug, Builder, Getters)]
10#[builder(setter(strip_option))]
11#[builder(default)]
12#[builder(build_fn(validate = "Self::validate"))]
13pub struct PickerConfig<T: HasDateConstraints + Default + Clone> {
14 #[getter(skip)]
16 date_constraints: T,
17
18 initial_date: Option<NaiveDate>,
20
21 initial_view_type: DialogViewType,
23
24 selection_type: DialogViewType,
26
27 initially_opened: bool,
29
30 #[builder(default = "String::from(\"%b %Y\")", setter(into))]
32 month_title_format: String,
33}
34
35impl<T: HasDateConstraints + std::default::Default + Clone> HasDateConstraints for PickerConfig<T> {
36 fn is_day_forbidden(&self, date: &NaiveDate) -> bool {
37 self.date_constraints.is_day_forbidden(date)
38 }
39
40 fn is_month_forbidden(&self, year_month_info: &NaiveDate) -> bool {
41 self.date_constraints.is_month_forbidden(year_month_info)
42 }
43
44 fn is_year_forbidden(&self, year: i32) -> bool {
45 self.date_constraints.is_year_forbidden(year)
46 }
47
48 fn is_year_group_forbidden(&self, year: i32) -> bool {
49 self.date_constraints.is_year_group_forbidden(year)
50 }
51}
52
53impl<T: HasDateConstraints + std::default::Default + Clone> PickerConfigBuilder<T> {
54 fn validate(&self) -> Result<(), String> {
55 if self.initial_view_type > self.selection_type {
56 return Err("initial_view_type can have at most selection_type scale".into());
57 }
58 match (self.initial_date, &self.date_constraints) {
59 (Some(Some(initial_date)), Some(date_constraints)) => {
60 if date_constraints.is_day_forbidden(&initial_date) {
61 return Err(format!(
62 "The initial_date {:?} is forbidden by the date_constraints.",
63 initial_date
64 ));
65 }
66 }
67 (_, _) => {}
68 }
69 Ok(())
70 }
71}
72
73impl<T: HasDateConstraints + std::default::Default + Clone> PickerConfig<T> {
74 pub fn guess_allowed_year_month(&self) -> NaiveDate {
75 if let Some(init_date) = self.initial_date {
76 return init_date;
77 }
78 Local::now().date().naive_local()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 use super::date_constraints::MockHasDateConstraints;
88 use mockall::predicate;
89
90 #[test]
91 fn picker_config_initial_view_type_greater_than_selection_type() {
92 let config = PickerConfigBuilder::<MockHasDateConstraints>::default()
93 .initial_view_type(DialogViewType::Days)
94 .selection_type(DialogViewType::Months)
95 .build();
96 assert!(config.is_err());
97 assert_eq!(
98 config.unwrap_err().to_string(),
99 "initial_view_type can have at most selection_type scale"
100 );
101 }
102
103 #[test]
104 fn picker_config_initial_view_type_equal_to_selection_type() {
105 let config = PickerConfigBuilder::<MockHasDateConstraints>::default()
106 .initial_view_type(DialogViewType::Months)
107 .selection_type(DialogViewType::Months)
108 .build();
109 assert!(config.is_ok());
110 }
111
112 #[test]
113 fn picker_config_initial_view_type_smaller_than_selection_type() {
114 let config = PickerConfigBuilder::<MockHasDateConstraints>::default()
115 .initial_view_type(DialogViewType::Years)
116 .selection_type(DialogViewType::Months)
117 .build();
118 assert!(config.is_ok());
119 }
120
121 #[test]
122 fn picker_config_initial_date_forbidden() {
123 let mut date_constraints_mock = MockHasDateConstraints::new();
124 date_constraints_mock
125 .expect_is_day_forbidden()
126 .returning(|_| true);
127 let config = PickerConfigBuilder::default()
128 .initial_date(NaiveDate::from_ymd(2020, 1, 1))
129 .date_constraints(date_constraints_mock)
130 .build();
131 assert!(config.is_err());
132 assert_eq!(
133 config.unwrap_err().to_string(),
134 "The initial_date 2020-01-01 is forbidden by the date_constraints."
135 );
136 }
137
138 fn create_picker_config_with_mocked_date_constraints<
140 T: HasDateConstraints + Clone + std::default::Default,
141 >(
142 builder: PickerConfigBuilder<T>,
143 mock_constraints: T,
144 ) -> PickerConfig<T> {
145 let config = builder.build().unwrap();
146 PickerConfig {
147 date_constraints: mock_constraints,
148 initial_date: *config.initial_date(),
149 initial_view_type: *config.initial_view_type(),
150 selection_type: *config.selection_type(),
151 initially_opened: *config.initially_opened(),
152 month_title_format: config.month_title_format().to_owned().clone(),
153 }
154 }
155
156 #[test]
157 fn test_is_day_forbidden() {
158 let date = NaiveDate::from_ymd(2020, 1, 1);
159 let mut date_constraints_mock = MockHasDateConstraints::new();
160 date_constraints_mock
161 .expect_is_day_forbidden()
162 .with(predicate::eq(date))
163 .times(1)
164 .returning(|_| true);
165 let builder = PickerConfigBuilder::default();
166 let config =
167 create_picker_config_with_mocked_date_constraints(builder, date_constraints_mock);
168 assert!(config.is_day_forbidden(&date));
169 }
170
171 #[test]
172 fn test_is_month_forbidden() {
173 let year_month = NaiveDate::from_ymd(2000, 2, 24);
174 let mut date_constraints_mock = MockHasDateConstraints::new();
175 date_constraints_mock
176 .expect_is_month_forbidden()
177 .with(predicate::eq(year_month.clone()))
178 .times(1)
179 .returning(|_| true);
180 let builder = PickerConfigBuilder::default();
181 let config =
182 create_picker_config_with_mocked_date_constraints(builder, date_constraints_mock);
183 assert!(config.is_month_forbidden(&year_month));
184 }
185
186 #[test]
187 fn test_is_year_forbidden() {
188 let year = 2000i32;
189 let mut date_constraints_mock = MockHasDateConstraints::new();
190 date_constraints_mock
191 .expect_is_year_forbidden()
192 .with(predicate::eq(year))
193 .times(1)
194 .returning(|_| true);
195 let builder = PickerConfigBuilder::default();
196 let config =
197 create_picker_config_with_mocked_date_constraints(builder, date_constraints_mock);
198 assert!(config.is_year_forbidden(year));
199 }
200
201 #[test]
202 fn test_is_year_group_forbidden() {
203 let year = 2000i32;
204 let mut date_constraints_mock = MockHasDateConstraints::new();
205 date_constraints_mock
206 .expect_is_year_group_forbidden()
207 .with(predicate::eq(year))
208 .times(1)
209 .returning(|_| true);
210 let builder = PickerConfigBuilder::default();
211 let config =
212 create_picker_config_with_mocked_date_constraints(builder, date_constraints_mock);
213 assert!(config.is_year_group_forbidden(year));
214 }
215
216 #[test]
217 fn guess_allowed_year_month_with_initial_date() {
218 let initial_date = NaiveDate::from_ymd(2020, 3, 24);
219 let config = PickerConfigBuilder::<MockHasDateConstraints>::default()
220 .initial_date(initial_date)
221 .build()
222 .unwrap();
223 let expected = initial_date;
224 assert_eq!(expected, config.guess_allowed_year_month());
225 }
226}