Add the Preset Ranges and add border for today (#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>
This commit is contained in:
xda 2024-10-18 21:38:16 +09:00 committed by GitHub
parent a798bd81c6
commit 8dbf1dd5d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 135 additions and 10 deletions

View file

@ -1,10 +1,10 @@
use chrono::Days;
use chrono::{Days, Duration, Utc};
use gpui::{
px, IntoElement, ParentElement as _, Render, Styled as _, View, ViewContext,
VisualContext as _, WindowContext,
};
use ui::{
date_picker::{DatePicker, DatePickerEvent},
date_picker::{DatePicker, DatePickerEvent, DateRangePreset},
v_flex, Sizable as _,
};
@ -37,11 +37,48 @@ impl CalendarStory {
}
fn new(cx: &mut ViewContext<Self>) -> Self {
let presets = vec![
DateRangePreset::single(
"Yesterday",
(Utc::now() - Duration::days(1)).naive_local().date(),
),
DateRangePreset::single(
"Last Week",
(Utc::now() - Duration::weeks(1)).naive_local().date(),
),
DateRangePreset::single(
"Last Month",
(Utc::now() - Duration::days(30)).naive_local().date(),
),
];
let range_presets = vec![
DateRangePreset::range(
"Last 7 Days",
(Utc::now() - Duration::days(7)).naive_local().date(),
Utc::now().naive_local().date(),
),
DateRangePreset::range(
"Last 14 Days",
(Utc::now() - Duration::days(14)).naive_local().date(),
Utc::now().naive_local().date(),
),
DateRangePreset::range(
"Last 30 Days",
(Utc::now() - Duration::days(30)).naive_local().date(),
Utc::now().naive_local().date(),
),
DateRangePreset::range(
"Last 90 Days",
(Utc::now() - Duration::days(90)).naive_local().date(),
Utc::now().naive_local().date(),
),
];
let now = chrono::Local::now().naive_local().date();
let date_picker = cx.new_view(|cx| {
let mut picker = DatePicker::new("date_picker_medium", cx)
.cleanable()
.width(px(220.));
.width(px(220.))
.presets(presets);
picker.set_date(now, cx);
picker
});
@ -62,7 +99,8 @@ impl CalendarStory {
let mut picker = DatePicker::new("date_range_picker", cx)
.width(px(300.))
.number_of_months(2)
.cleanable();
.cleanable()
.presets(range_presets.clone());
picker.set_date((now, now.checked_add_days(Days::new(4)).unwrap()), cx);
picker
});
@ -85,6 +123,7 @@ impl CalendarStory {
.width(px(300.))
.placeholder("Range mode picker")
.cleanable()
.presets(range_presets.clone())
});
cx.subscribe(&default_range_mode_picker, |this, _, ev, _| match ev {

View file

@ -159,6 +159,7 @@ pub struct Calendar {
year_page: i32,
/// Number of the months view to show.
number_of_months: usize,
today: NaiveDate,
}
impl Calendar {
@ -173,6 +174,7 @@ impl Calendar {
years: vec![],
year_page: 0,
number_of_months: 1,
today,
}
.year_range((today.year() - 50, today.year() + 50))
}
@ -399,6 +401,7 @@ impl Calendar {
let is_in_range = self.date.is_in_range(d);
let date = *d;
let is_today = *d == self.today;
self.item_button(
ix,
@ -408,6 +411,9 @@ impl Calendar {
!is_current_month,
cx,
)
.when(is_today && !is_active, |this| {
this.border_1().border_color(cx.theme().border)
}) // Add border for today
.on_click(cx.listener(move |view, _: &ClickEvent, cx| {
if view.date.is_single() {
view.set_date(date, cx);

View file

@ -1,14 +1,19 @@
use chrono::NaiveDate;
use gpui::{
anchored, deferred, div, prelude::FluentBuilder as _, px, AppContext, ElementId, EventEmitter,
FocusHandle, FocusableView, InteractiveElement as _, KeyBinding, Length, MouseButton,
ParentElement as _, Render, SharedString, StatefulInteractiveElement as _, Styled as _, View,
ParentElement as _, Render, SharedString, StatefulInteractiveElement as _, Styled, View,
ViewContext, VisualContext as _,
};
use rust_i18n::t;
use crate::{
dropdown::Escape, h_flex, input::ClearButton, theme::ActiveTheme as _, Icon, IconName, Sizable,
Size, StyleSized as _, StyledExt as _,
button::{Button, ButtonStyled as _},
dropdown::Escape,
h_flex,
input::ClearButton,
theme::ActiveTheme,
v_flex, Icon, IconName, Sizable, Size, StyleSized as _, StyledExt as _,
};
use super::calendar::{Calendar, CalendarEvent, Date};
@ -23,6 +28,34 @@ pub enum DatePickerEvent {
Change(Date),
}
#[derive(Clone)]
pub enum DateRangePresetValue {
Single(NaiveDate),
Range(NaiveDate, NaiveDate),
}
#[derive(Clone)]
pub struct DateRangePreset {
label: SharedString,
value: DateRangePresetValue,
}
impl DateRangePreset {
/// Creates a new DateRangePreset with single date.
pub fn single(label: impl Into<SharedString>, single: NaiveDate) -> Self {
DateRangePreset {
label: label.into(),
value: DateRangePresetValue::Single(single),
}
}
/// Creates a new DateRangePreset with a range of dates.
pub fn range(label: impl Into<SharedString>, start: NaiveDate, end: NaiveDate) -> Self {
DateRangePreset {
label: label.into(),
value: DateRangePresetValue::Range(start, end),
}
}
}
pub struct DatePicker {
id: ElementId,
focus_handle: FocusHandle,
@ -35,6 +68,7 @@ pub struct DatePicker {
date_format: SharedString,
calendar: View<Calendar>,
number_of_months: usize,
presets: Option<Vec<DateRangePreset>>,
}
impl DatePicker {
@ -82,6 +116,7 @@ impl DatePicker {
cleanable: false,
number_of_months: 1,
placeholder: None,
presets: None,
}
}
@ -115,6 +150,12 @@ impl DatePicker {
self
}
/// Set preset ranges for the date picker.
pub fn presets(mut self, presets: Vec<DateRangePreset>) -> Self {
self.presets = Some(presets);
self
}
/// Get the date of the date picker.
pub fn date(&self) -> Date {
self.date
@ -158,6 +199,17 @@ impl DatePicker {
self.open = !self.open;
cx.notify();
}
fn select_preset(&mut self, preset: &DateRangePreset, cx: &mut ViewContext<Self>) {
match preset.value {
DateRangePresetValue::Single(single) => {
self.update_date(Date::Single(Some(single)), true, cx)
}
DateRangePresetValue::Range(start, end) => {
self.update_date(Date::Range(Some(start), Some(end)), true, cx)
}
}
}
}
impl EventEmitter<DatePickerEvent> for DatePicker {}
@ -190,8 +242,9 @@ impl Render for DatePicker {
view.set_number_of_months(self.number_of_months, cx);
});
let popover_width =
285.0 * self.number_of_months as f32 + (self.number_of_months - 1) as f32 * 16.0;
let popover_width = self.presets.as_ref().map_or(0.0, |_| 136.0)
+ 285.0 * self.number_of_months as f32
+ (self.number_of_months - 1) as f32 * 16.0;
div()
.id(self.id.clone())
@ -266,7 +319,34 @@ impl Render for DatePicker {
MouseButton::Left,
cx.listener(|view, _, cx| view.escape(&Escape, cx)),
)
.child(self.calendar.clone()),
.child(
h_flex()
.gap_3()
.h_full()
.items_start()
.when_some(self.presets.clone(), |this, presets| {
this.child(
v_flex().my_1().gap_2().justify_end().children(
presets.into_iter().enumerate().map(
|(i, preset)| {
Button::new(("preset", i))
.small()
.ghost()
.label(preset.label.clone())
.on_click(cx.listener(
move |this, _, cx| {
this.select_preset(
&preset, cx,
);
},
))
},
),
),
)
})
.child(self.calendar.clone()),
),
),
)
.with_priority(2),