Skip to content

Commit 8dbf1dd

Browse files
xda2023huacnlee
andauthored
Add the Preset Ranges and add border for today (sentriz#365)
Preset Ranges have been added. The “Today” border has also been added. ![2024-10-18 17 41 13](https://github.com/user-attachments/assets/be6106a6-9138-462c-ab0d-1332b4a6eba5) --------- Co-authored-by: Jason Lee <huacnlee@gmail.com>
1 parent a798bd8 commit 8dbf1dd

3 files changed

Lines changed: 135 additions & 10 deletions

File tree

crates/story/src/calendar_story.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use chrono::Days;
1+
use chrono::{Days, Duration, Utc};
22
use gpui::{
33
px, IntoElement, ParentElement as _, Render, Styled as _, View, ViewContext,
44
VisualContext as _, WindowContext,
55
};
66
use ui::{
7-
date_picker::{DatePicker, DatePickerEvent},
7+
date_picker::{DatePicker, DatePickerEvent, DateRangePreset},
88
v_flex, Sizable as _,
99
};
1010

@@ -37,11 +37,48 @@ impl CalendarStory {
3737
}
3838

3939
fn new(cx: &mut ViewContext<Self>) -> Self {
40+
let presets = vec![
41+
DateRangePreset::single(
42+
"Yesterday",
43+
(Utc::now() - Duration::days(1)).naive_local().date(),
44+
),
45+
DateRangePreset::single(
46+
"Last Week",
47+
(Utc::now() - Duration::weeks(1)).naive_local().date(),
48+
),
49+
DateRangePreset::single(
50+
"Last Month",
51+
(Utc::now() - Duration::days(30)).naive_local().date(),
52+
),
53+
];
54+
let range_presets = vec![
55+
DateRangePreset::range(
56+
"Last 7 Days",
57+
(Utc::now() - Duration::days(7)).naive_local().date(),
58+
Utc::now().naive_local().date(),
59+
),
60+
DateRangePreset::range(
61+
"Last 14 Days",
62+
(Utc::now() - Duration::days(14)).naive_local().date(),
63+
Utc::now().naive_local().date(),
64+
),
65+
DateRangePreset::range(
66+
"Last 30 Days",
67+
(Utc::now() - Duration::days(30)).naive_local().date(),
68+
Utc::now().naive_local().date(),
69+
),
70+
DateRangePreset::range(
71+
"Last 90 Days",
72+
(Utc::now() - Duration::days(90)).naive_local().date(),
73+
Utc::now().naive_local().date(),
74+
),
75+
];
4076
let now = chrono::Local::now().naive_local().date();
4177
let date_picker = cx.new_view(|cx| {
4278
let mut picker = DatePicker::new("date_picker_medium", cx)
4379
.cleanable()
44-
.width(px(220.));
80+
.width(px(220.))
81+
.presets(presets);
4582
picker.set_date(now, cx);
4683
picker
4784
});
@@ -62,7 +99,8 @@ impl CalendarStory {
6299
let mut picker = DatePicker::new("date_range_picker", cx)
63100
.width(px(300.))
64101
.number_of_months(2)
65-
.cleanable();
102+
.cleanable()
103+
.presets(range_presets.clone());
66104
picker.set_date((now, now.checked_add_days(Days::new(4)).unwrap()), cx);
67105
picker
68106
});
@@ -85,6 +123,7 @@ impl CalendarStory {
85123
.width(px(300.))
86124
.placeholder("Range mode picker")
87125
.cleanable()
126+
.presets(range_presets.clone())
88127
});
89128

90129
cx.subscribe(&default_range_mode_picker, |this, _, ev, _| match ev {

crates/ui/src/time/calendar.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ pub struct Calendar {
159159
year_page: i32,
160160
/// Number of the months view to show.
161161
number_of_months: usize,
162+
today: NaiveDate,
162163
}
163164

164165
impl Calendar {
@@ -173,6 +174,7 @@ impl Calendar {
173174
years: vec![],
174175
year_page: 0,
175176
number_of_months: 1,
177+
today,
176178
}
177179
.year_range((today.year() - 50, today.year() + 50))
178180
}
@@ -399,6 +401,7 @@ impl Calendar {
399401
let is_in_range = self.date.is_in_range(d);
400402

401403
let date = *d;
404+
let is_today = *d == self.today;
402405

403406
self.item_button(
404407
ix,
@@ -408,6 +411,9 @@ impl Calendar {
408411
!is_current_month,
409412
cx,
410413
)
414+
.when(is_today && !is_active, |this| {
415+
this.border_1().border_color(cx.theme().border)
416+
}) // Add border for today
411417
.on_click(cx.listener(move |view, _: &ClickEvent, cx| {
412418
if view.date.is_single() {
413419
view.set_date(date, cx);

crates/ui/src/time/date_picker.rs

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
use chrono::NaiveDate;
12
use gpui::{
23
anchored, deferred, div, prelude::FluentBuilder as _, px, AppContext, ElementId, EventEmitter,
34
FocusHandle, FocusableView, InteractiveElement as _, KeyBinding, Length, MouseButton,
4-
ParentElement as _, Render, SharedString, StatefulInteractiveElement as _, Styled as _, View,
5+
ParentElement as _, Render, SharedString, StatefulInteractiveElement as _, Styled, View,
56
ViewContext, VisualContext as _,
67
};
78
use rust_i18n::t;
89

910
use crate::{
10-
dropdown::Escape, h_flex, input::ClearButton, theme::ActiveTheme as _, Icon, IconName, Sizable,
11-
Size, StyleSized as _, StyledExt as _,
11+
button::{Button, ButtonStyled as _},
12+
dropdown::Escape,
13+
h_flex,
14+
input::ClearButton,
15+
theme::ActiveTheme,
16+
v_flex, Icon, IconName, Sizable, Size, StyleSized as _, StyledExt as _,
1217
};
1318

1419
use super::calendar::{Calendar, CalendarEvent, Date};
@@ -23,6 +28,34 @@ pub enum DatePickerEvent {
2328
Change(Date),
2429
}
2530

31+
#[derive(Clone)]
32+
pub enum DateRangePresetValue {
33+
Single(NaiveDate),
34+
Range(NaiveDate, NaiveDate),
35+
}
36+
37+
#[derive(Clone)]
38+
pub struct DateRangePreset {
39+
label: SharedString,
40+
value: DateRangePresetValue,
41+
}
42+
43+
impl DateRangePreset {
44+
/// Creates a new DateRangePreset with single date.
45+
pub fn single(label: impl Into<SharedString>, single: NaiveDate) -> Self {
46+
DateRangePreset {
47+
label: label.into(),
48+
value: DateRangePresetValue::Single(single),
49+
}
50+
}
51+
/// Creates a new DateRangePreset with a range of dates.
52+
pub fn range(label: impl Into<SharedString>, start: NaiveDate, end: NaiveDate) -> Self {
53+
DateRangePreset {
54+
label: label.into(),
55+
value: DateRangePresetValue::Range(start, end),
56+
}
57+
}
58+
}
2659
pub struct DatePicker {
2760
id: ElementId,
2861
focus_handle: FocusHandle,
@@ -35,6 +68,7 @@ pub struct DatePicker {
3568
date_format: SharedString,
3669
calendar: View<Calendar>,
3770
number_of_months: usize,
71+
presets: Option<Vec<DateRangePreset>>,
3872
}
3973

4074
impl DatePicker {
@@ -82,6 +116,7 @@ impl DatePicker {
82116
cleanable: false,
83117
number_of_months: 1,
84118
placeholder: None,
119+
presets: None,
85120
}
86121
}
87122

@@ -115,6 +150,12 @@ impl DatePicker {
115150
self
116151
}
117152

153+
/// Set preset ranges for the date picker.
154+
pub fn presets(mut self, presets: Vec<DateRangePreset>) -> Self {
155+
self.presets = Some(presets);
156+
self
157+
}
158+
118159
/// Get the date of the date picker.
119160
pub fn date(&self) -> Date {
120161
self.date
@@ -158,6 +199,17 @@ impl DatePicker {
158199
self.open = !self.open;
159200
cx.notify();
160201
}
202+
203+
fn select_preset(&mut self, preset: &DateRangePreset, cx: &mut ViewContext<Self>) {
204+
match preset.value {
205+
DateRangePresetValue::Single(single) => {
206+
self.update_date(Date::Single(Some(single)), true, cx)
207+
}
208+
DateRangePresetValue::Range(start, end) => {
209+
self.update_date(Date::Range(Some(start), Some(end)), true, cx)
210+
}
211+
}
212+
}
161213
}
162214

163215
impl EventEmitter<DatePickerEvent> for DatePicker {}
@@ -190,8 +242,9 @@ impl Render for DatePicker {
190242
view.set_number_of_months(self.number_of_months, cx);
191243
});
192244

193-
let popover_width =
194-
285.0 * self.number_of_months as f32 + (self.number_of_months - 1) as f32 * 16.0;
245+
let popover_width = self.presets.as_ref().map_or(0.0, |_| 136.0)
246+
+ 285.0 * self.number_of_months as f32
247+
+ (self.number_of_months - 1) as f32 * 16.0;
195248

196249
div()
197250
.id(self.id.clone())
@@ -266,7 +319,34 @@ impl Render for DatePicker {
266319
MouseButton::Left,
267320
cx.listener(|view, _, cx| view.escape(&Escape, cx)),
268321
)
269-
.child(self.calendar.clone()),
322+
.child(
323+
h_flex()
324+
.gap_3()
325+
.h_full()
326+
.items_start()
327+
.when_some(self.presets.clone(), |this, presets| {
328+
this.child(
329+
v_flex().my_1().gap_2().justify_end().children(
330+
presets.into_iter().enumerate().map(
331+
|(i, preset)| {
332+
Button::new(("preset", i))
333+
.small()
334+
.ghost()
335+
.label(preset.label.clone())
336+
.on_click(cx.listener(
337+
move |this, _, cx| {
338+
this.select_preset(
339+
&preset, cx,
340+
);
341+
},
342+
))
343+
},
344+
),
345+
),
346+
)
347+
})
348+
.child(self.calendar.clone()),
349+
),
270350
),
271351
)
272352
.with_priority(2),

0 commit comments

Comments
 (0)