| 83 |
83 |
|
pub recurrence_rule: Option<RecurrenceRule>,
|
| 84 |
84 |
|
pub recurrence_display: String,
|
| 85 |
85 |
|
pub is_recurring_instance: bool,
|
|
86 |
+ |
/// True if this is the parent rule of a recurring series (recurrence set and
|
|
87 |
+ |
/// not itself a generated instance). The events view lists templates in their
|
|
88 |
+ |
/// own section; pre-computed here so JS never re-derives the rule.
|
|
89 |
+ |
pub is_template: bool,
|
| 86 |
90 |
|
pub contact_id: Option<ContactId>,
|
| 87 |
91 |
|
pub contact_name: Option<String>,
|
| 88 |
92 |
|
pub block_type: Option<String>,
|
| 184 |
188 |
|
let is_snoozed = e.is_snoozed();
|
| 185 |
189 |
|
let snoozed_until = e.snoozed_until;
|
| 186 |
190 |
|
let reminder_offsets_seconds = e.reminder_offsets_seconds.clone();
|
|
191 |
+ |
// Template = the parent rule row of a recurring series, not a generated
|
|
192 |
+ |
// occurrence. Mirrors the old JS rule, which gated on `e.recurrence` being
|
|
193 |
+ |
// truthy — i.e. a set recurrence (Recurrence::None serializes to "").
|
|
194 |
+ |
let is_template = e.recurrence != Recurrence::None && !e.is_recurring_instance;
|
| 187 |
195 |
|
|
| 188 |
196 |
|
EventResponse {
|
| 189 |
197 |
|
id: e.id,
|
| 200 |
208 |
|
recurrence_display,
|
| 201 |
209 |
|
recurrence_rule: e.recurrence_rule,
|
| 202 |
210 |
|
is_recurring_instance: e.is_recurring_instance,
|
|
211 |
+ |
is_template,
|
| 203 |
212 |
|
contact_id: e.contact_id,
|
| 204 |
213 |
|
contact_name: e.contact_name,
|
| 205 |
214 |
|
block_type: e.block_type.as_ref().map(|b| b.db_value().to_string()),
|
| 670 |
679 |
|
assert!(sanitize_reminder_offsets(&[]).is_empty());
|
| 671 |
680 |
|
}
|
| 672 |
681 |
|
}
|
|
682 |
+ |
|
|
683 |
+ |
#[cfg(test)]
|
|
684 |
+ |
mod is_template_tests {
|
|
685 |
+ |
use super::EventResponse;
|
|
686 |
+ |
use chrono::Utc;
|
|
687 |
+ |
use goingson_core::{Event, EventId, Recurrence};
|
|
688 |
+ |
|
|
689 |
+ |
fn event(recurrence: Recurrence, is_recurring_instance: bool) -> Event {
|
|
690 |
+ |
Event {
|
|
691 |
+ |
id: EventId::new(),
|
|
692 |
+ |
user_id: None,
|
|
693 |
+ |
project_id: None,
|
|
694 |
+ |
project_name: None,
|
|
695 |
+ |
contact_id: None,
|
|
696 |
+ |
contact_name: None,
|
|
697 |
+ |
title: "E".to_string(),
|
|
698 |
+ |
description: String::new(),
|
|
699 |
+ |
start_time: Utc::now(),
|
|
700 |
+ |
end_time: None,
|
|
701 |
+ |
location: None,
|
|
702 |
+ |
linked_task_id: None,
|
|
703 |
+ |
recurrence,
|
|
704 |
+ |
recurrence_rule: None,
|
|
705 |
+ |
recurrence_parent_id: None,
|
|
706 |
+ |
is_recurring_instance,
|
|
707 |
+ |
block_type: None,
|
|
708 |
+ |
external_source: None,
|
|
709 |
+ |
external_id: None,
|
|
710 |
+ |
is_read_only: false,
|
|
711 |
+ |
snoozed_until: None,
|
|
712 |
+ |
reminder_offsets_seconds: Vec::new(),
|
|
713 |
+ |
}
|
|
714 |
+ |
}
|
|
715 |
+ |
|
|
716 |
+ |
#[test]
|
|
717 |
+ |
fn recurring_parent_rule_is_a_template() {
|
|
718 |
+ |
let r = EventResponse::from(event(Recurrence::Weekly, false));
|
|
719 |
+ |
assert!(r.is_template);
|
|
720 |
+ |
}
|
|
721 |
+ |
|
|
722 |
+ |
#[test]
|
|
723 |
+ |
fn generated_instance_is_not_a_template() {
|
|
724 |
+ |
// A recurring series expands into instances; those are not the rule row.
|
|
725 |
+ |
let r = EventResponse::from(event(Recurrence::Weekly, true));
|
|
726 |
+ |
assert!(!r.is_template);
|
|
727 |
+ |
}
|
|
728 |
+ |
|
|
729 |
+ |
#[test]
|
|
730 |
+ |
fn non_recurring_event_is_not_a_template() {
|
|
731 |
+ |
let r = EventResponse::from(event(Recurrence::None, false));
|
|
732 |
+ |
assert!(!r.is_template);
|
|
733 |
+ |
}
|
|
734 |
+ |
}
|