diff options
author | Matthew Sotoudeh <matthewsot@outlook.com> | 2021-12-27 17:55:50 -0800 |
---|---|---|
committer | Matthew Sotoudeh <matthewsot@outlook.com> | 2021-12-27 17:55:50 -0800 |
commit | de421d9cbf18c7d013f91541326c3cb1d05784a7 (patch) | |
tree | fa71e6fe94c777a0a3ced4ba609490cff82007fa | |
parent | 9072d3649de0530208ba2c6a87d2a51a719d7a27 (diff) |
Generate both public + private versions of the HTML cal
Also better handling of tasks without times
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | calendar_style.css | 5 | ||||
-rw-r--r-- | src/main.rs | 90 |
3 files changed, 71 insertions, 29 deletions
@@ -30,10 +30,11 @@ which case they are printed out to the public calendar along with a short description. Events on the public calendar can also be styled according to these `public_tags`, see `calendar_style.css`. -To generate the public calendar, run: +To generate the HTML calendars, run: ``` -$ cargo run > calendar.html +$ cargo run ``` +You should now see `public.html` and `private.html` in the current directory. The calendar does not require Javascript and should work very well in, e.g., `w3m`. diff --git a/calendar_style.css b/calendar_style.css index b70e5b5..be41270 100644 --- a/calendar_style.css +++ b/calendar_style.css @@ -1,13 +1,10 @@ /*table, th, td {*/ -table { - border-collapse: collapse; -} th, td { border: 1px solid black; padding: 0; } td { - border-collapse: collapse; + overflow: hidden; } th { padding: 3px; diff --git a/src/main.rs b/src/main.rs index e89dc0a..5bf0b3d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,7 +139,12 @@ fn does_overlap(timespan_start: &NaiveTime, timespan_end: &NaiveTime, task: &Tas } } -fn tasks_to_html(tasks: &Vec<Task>) -> String { +enum CalendarPrivacy { + Public, + Private, +} + +fn tasks_to_html(tasks: &Vec<Task>, privacy: CalendarPrivacy) -> String { let public_tags = HashMap::from([ ("busy", "I will be genuinely busy, e.g., a meeting with others."), ("rough", "The nature of the event (e.g., a hike) makes it difficult to preduct the exact start/end times."), @@ -244,16 +249,27 @@ fn tasks_to_html(tasks: &Vec<Task>) -> String { html.push_str("task-"); html.push_str(idx.to_string().as_str()); html.push_str("\">"); - if all_tags.len() == 0 { - html.push_str("has-task"); - } - let mut any_yet = false; - for tag in all_tags { - if any_yet { - html.push_str(", "); - } - html.push_str(tag.as_str()); - any_yet = true; + match privacy { + CalendarPrivacy::Public => { + let mut any_yet = false; + for tag in all_tags { + if any_yet { html.push_str(", "); } + html.push_str(tag.as_str()); + any_yet = true; + } + if tasks[idx].tags.contains(&&"public".to_string()) { + if any_yet { html.push_str(": \""); } + html.push_str(&tasks[idx].details.as_str()); + html.push_str("\""); + any_yet = true; + } + if !any_yet { + html.push_str("has-task"); + } + }, + CalendarPrivacy::Private => { + html.push_str(&tasks[idx].details.as_str()); + }, } html.push_str("</a></td>"); } @@ -268,6 +284,12 @@ fn tasks_to_html(tasks: &Vec<Task>) -> String { html.push_str("</table><ul>"); for i in week_task_ids.iter() { let task = &tasks[*i]; + let task_public_tags: Vec<&String> + = task.tags.iter().filter(|&t| t == "public" || public_tags.contains_key(t.as_str())).collect(); + match (&privacy, &task.start_time, &task_public_tags[..]) { + (CalendarPrivacy::Public, None, []) => continue, + _ => (), + } html.push_str("<li id=\"task-"); html.push_str(i.to_string().as_str()); html.push_str("\">"); @@ -281,17 +303,33 @@ fn tasks_to_html(tasks: &Vec<Task>) -> String { _ => (), } html.push_str("<ul>"); - if task.tags.contains(&"public".to_string()) { - html.push_str("<li><b>Description:</b> "); - html.push_str(task.details.as_str()); - html.push_str("</li>"); - } - for tag in &task.tags { - if public_tags.contains_key(&tag.as_str()) { - html.push_str("<li>Tagged <b>"); - html.push_str(tag.as_str()); - html.push_str(":</b> "); - html.push_str(public_tags.get(&tag.as_str()).expect("")); + match privacy { + CalendarPrivacy::Public => { + if task.tags.contains(&"public".to_string()) { + html.push_str("<li><b>Description:</b> "); + html.push_str(task.details.as_str()); + html.push_str("</li>"); + } + for tag in &task.tags { + if public_tags.contains_key(&tag.as_str()) { + html.push_str("<li>Tagged <b>"); + html.push_str(tag.as_str()); + html.push_str(":</b> "); + html.push_str(public_tags.get(&tag.as_str()).expect("")); + html.push_str("</li>"); + } + } + }, + CalendarPrivacy::Private => { + html.push_str("<li><b>Description:</b> "); + html.push_str(task.details.as_str()); + html.push_str("</li><li>Tagged: "); + for (i, tag) in task.tags.iter().enumerate() { + if i > 0 { html.push_str(", "); } + html.push_str("<b>"); + html.push_str(tag.as_str()); + html.push_str("</b>"); + } html.push_str("</li>"); } } @@ -359,7 +397,13 @@ fn main() { } } } - print!("{}\n", tasks_to_html(&tasks)); + let public_html = tasks_to_html(&tasks, CalendarPrivacy::Public); + let private_html = tasks_to_html(&tasks, CalendarPrivacy::Private); + // https://riptutorial.com/rust/example/4276/write-in-a-file + let mut public = File::create(Path::new("public.html")).unwrap(); + writeln!(&mut public, "{}", public_html).unwrap(); + let mut private = File::create(Path::new("private.html")).unwrap(); + writeln!(&mut private, "{}", private_html).unwrap(); } } } |