server: move calendar widget to askama

This commit is contained in:
2025-08-19 16:17:22 -07:00
parent 5b48c5dbc3
commit 43d856ae7e
2 changed files with 148 additions and 54 deletions

View File

@@ -1,3 +1,29 @@
// Inline Askama filters module for template use
mod filters {
// Usage: {{ items|batch(7) }}
pub fn batch<T: Clone>(
items: &[T],
_: &dyn ::askama::Values,
size: usize,
) -> askama::Result<Vec<Vec<T>>> {
if size == 0 {
return Ok(vec![]);
}
let mut out = Vec::new();
let mut chunk = Vec::with_capacity(size);
for item in items {
chunk.push(item.clone());
if chunk.len() == size {
out.push(chunk);
chunk = Vec::with_capacity(size);
}
}
if !chunk.is_empty() {
out.push(chunk);
}
Ok(out)
}
}
use std::io::{Cursor, Read};
use askama::Template;
@@ -1099,7 +1125,9 @@ pub struct IcalSummaryTemplate<'a> {
pub local_fmt_end: &'a str,
pub organizer: &'a str,
pub organizer_cn: &'a str,
pub calendar_html: &'a str,
pub all_days: Vec<NaiveDate>,
pub event_days: Vec<NaiveDate>,
pub caption: String,
pub description_paragraphs: &'a [String],
}
@@ -1385,11 +1413,45 @@ pub fn render_ical_summary(ical_data: &str) -> Result<String, ServerError> {
(String::new(), String::new(), vec![])
};
// Render calendar table HTML
let calendar_html = if !event_days.is_empty() {
render_merged_calendar_table(&event_days)
// Compute calendar grid for template rendering
let (all_days, caption) = if !event_days.is_empty() {
let first_event = event_days.first().unwrap();
let last_event = event_days.last().unwrap();
let first_of_month =
NaiveDate::from_ymd_opt(first_event.year(), first_event.month(), 1).unwrap();
let last_of_month = {
let next_month = if last_event.month() == 12 {
NaiveDate::from_ymd_opt(last_event.year() + 1, 1, 1).unwrap()
} else {
NaiveDate::from_ymd_opt(last_event.year(), last_event.month() + 1, 1)
.unwrap()
};
next_month.pred_opt().unwrap()
};
let mut cal_start = first_of_month;
while cal_start.weekday() != chrono::Weekday::Sun {
cal_start = cal_start.pred_opt().unwrap();
}
let mut cal_end = last_of_month;
while cal_end.weekday() != chrono::Weekday::Sat {
cal_end = cal_end.succ_opt().unwrap();
}
let mut all_days = vec![];
let mut d = cal_start;
while d <= cal_end {
all_days.push(d);
d = d.succ_opt().unwrap();
}
let start_month = first_event.format("%B %Y");
let end_month = last_event.format("%B %Y");
let caption = if start_month.to_string() == end_month.to_string() {
start_month.to_string()
} else {
format!("{} {}", start_month, end_month)
};
(all_days, caption)
} else {
String::new()
(vec![], String::new())
};
// Description paragraphs
@@ -1408,7 +1470,6 @@ pub fn render_ical_summary(ical_data: &str) -> Result<String, ServerError> {
let organizer_cn_val = organizer_cn.unwrap_or("");
let local_fmt_start_val = &local_fmt_start;
let local_fmt_end_val = &local_fmt_end;
let calendar_html_val = &calendar_html;
let description_paragraphs_val = &description_paragraphs;
let template = IcalSummaryTemplate {
summary: summary_val,
@@ -1416,7 +1477,9 @@ pub fn render_ical_summary(ical_data: &str) -> Result<String, ServerError> {
local_fmt_end: local_fmt_end_val,
organizer: organizer_val,
organizer_cn: organizer_cn_val,
calendar_html: calendar_html_val,
all_days,
event_days: event_days.clone(),
caption,
description_paragraphs: description_paragraphs_val,
};
summary_parts.push(template.render()?);