add upstream calendars page
This commit is contained in:
parent
830f45423f
commit
ef0d32f0b7
4 changed files with 103 additions and 33 deletions
25
src/main.rs
25
src/main.rs
|
@ -51,6 +51,26 @@ impl Config {
|
|||
)
|
||||
.chain(self.icals.iter().map(|ical| ical.dl.clone()))
|
||||
}
|
||||
|
||||
fn upstreams(&self) -> Vec<CalendarUi> {
|
||||
let Self {
|
||||
campfires,
|
||||
common_ninjas,
|
||||
icals,
|
||||
output: _,
|
||||
} = self;
|
||||
|
||||
let mut upstreams: Vec<_> = campfires
|
||||
.iter()
|
||||
.map(|cfg| &cfg.ui)
|
||||
.cloned()
|
||||
.chain(common_ninjas.iter().map(|cfg| &cfg.ui).cloned())
|
||||
.chain(icals.iter().map(|cfg| &cfg.ui).cloned())
|
||||
.collect();
|
||||
upstreams.sort_by_key(|ui| ui.short_name.clone());
|
||||
|
||||
upstreams
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
|
@ -238,7 +258,7 @@ async fn do_everything(cli: &CliAuto) -> Result<()> {
|
|||
|
||||
let data = read_data_from_disk(&config)?;
|
||||
let instances = process_data(&data, &config.output, now)?;
|
||||
output::write_html(&config.output, &instances, now)?;
|
||||
output::write_html(&config.output, &config.upstreams(), &instances, now)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -276,7 +296,8 @@ fn main_debug_output(cli: CliDebugOutput) -> Result<()> {
|
|||
let tz = &config.output.timezone;
|
||||
let now = Utc::now().with_timezone(tz);
|
||||
let instances = process_data(&data, &config.output, now).context("Failed to process data")?;
|
||||
output::write_html(&config.output, &instances, now).context("Failed to output HTML")?;
|
||||
output::write_html(&config.output, &config.upstreams(), &instances, now)
|
||||
.context("Failed to output HTML")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -5,6 +5,24 @@ use std::{collections::BTreeSet, io::Write as _};
|
|||
|
||||
use crate::{EventInstance, prelude::*};
|
||||
|
||||
const CSS: &str = r#"
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 14pt;
|
||||
line-height: 1.6;
|
||||
max-width: 700px;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.past {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
"#;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub(crate) struct Config {
|
||||
/// Used as the OpenGraph description in meta tags
|
||||
|
@ -40,8 +58,17 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn calendar_link(calendar_ui: &crate::CalendarUi) -> maud::PreEscaped<String> {
|
||||
if let Some(html_url) = &calendar_ui.html_url {
|
||||
maud::html! { a href=(html_url) { (calendar_ui.short_name) } }
|
||||
} else {
|
||||
maud::html! { (calendar_ui.short_name)}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_html(
|
||||
config: &Config,
|
||||
upstreams: &[crate::CalendarUi],
|
||||
instances: &[EventInstance],
|
||||
now: DateTime<chrono_tz::Tz>,
|
||||
) -> Result<()> {
|
||||
|
@ -118,12 +145,6 @@ pub(crate) fn write_html(
|
|||
li class="past" { (time) " - " (summary) }
|
||||
});
|
||||
} else {
|
||||
let calendar_link = if let Some(html_url) = &ei.calendar_ui.html_url {
|
||||
maud::html! { a href=(html_url) { (ei.calendar_ui.short_name) } }
|
||||
} else {
|
||||
maud::html! { (ei.calendar_ui.short_name)}
|
||||
};
|
||||
|
||||
// This is where the main stuff happens
|
||||
|
||||
tracing::debug!(uid = ei.uid, summary = ei.summary);
|
||||
|
@ -131,7 +152,7 @@ pub(crate) fn write_html(
|
|||
li { details {
|
||||
summary { (time) " - " (summary) }
|
||||
ul {
|
||||
li { (calendar_link) " calendar" }
|
||||
li { (calendar_link(&ei.calendar_ui)) " calendar" }
|
||||
@if let Some(location) = &ei.location {
|
||||
li { "Location: " (location) }
|
||||
}
|
||||
|
@ -155,7 +176,49 @@ pub(crate) fn write_html(
|
|||
let final_path = "output/calendars.html";
|
||||
let mut f = std::fs::File::create(temp_path)?;
|
||||
|
||||
f.write_all("".as_bytes())?;
|
||||
let description = "A list of upstream calendars used by this Wide-Angle Calendar instance";
|
||||
let title = "Upstream calendars";
|
||||
|
||||
let s = maud::html! {
|
||||
(maud::PreEscaped("<!DOCTYPE html>"))
|
||||
html lang="en" {
|
||||
head {
|
||||
meta http-equiv="Content-Type" content="text/html; charset=utf-8" {}
|
||||
meta name="viewport" content="width=device-width, initial-scale=1" {}
|
||||
(maud::PreEscaped(CSS))
|
||||
|
||||
meta property="og:locale" content="en" {}
|
||||
meta property="og:type" content="website" {}
|
||||
|
||||
meta name="description" content=(description) {}
|
||||
meta property="description" content=(description) {}
|
||||
meta property="og:description" content=(description) {}
|
||||
|
||||
title { (title) }
|
||||
met property="og:title" content=(title) {}
|
||||
}
|
||||
body {
|
||||
h1 { (title) }
|
||||
p {
|
||||
a href="index.html" { "Wide-Angle Calendar" }
|
||||
" / "
|
||||
a href="calendars.html" { (title) }
|
||||
}
|
||||
|
||||
p { "Written at: " (now.format("%F %T")) }
|
||||
p { "These are the calendars that Wide-Angle Calendar pulls from." }
|
||||
|
||||
ol {
|
||||
@for upstream in upstreams {
|
||||
li { (calendar_link(upstream)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string();
|
||||
|
||||
f.write_all(s.as_bytes())?;
|
||||
std::fs::rename(temp_path, final_path)?;
|
||||
}
|
||||
|
||||
|
@ -163,23 +226,6 @@ pub(crate) fn write_html(
|
|||
let temp_path = "output/index.html.tmp";
|
||||
let final_path = "output/index.html";
|
||||
let mut f = std::fs::File::create(temp_path)?;
|
||||
let css = r#"
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 14pt;
|
||||
line-height: 1.6;
|
||||
max-width: 700px;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.past {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
"#;
|
||||
|
||||
let description = &config.description;
|
||||
let title = &config.title;
|
||||
|
@ -190,7 +236,7 @@ pub(crate) fn write_html(
|
|||
head {
|
||||
meta http-equiv="Content-Type" content="text/html; charset=utf-8" {}
|
||||
meta name="viewport" content="width=device-width, initial-scale=1" {}
|
||||
(maud::PreEscaped(css))
|
||||
(maud::PreEscaped(CSS))
|
||||
|
||||
meta property="og:locale" content="en" {}
|
||||
meta property="og:type" content="website" {}
|
||||
|
@ -206,6 +252,7 @@ pub(crate) fn write_html(
|
|||
h1 { (title) }
|
||||
img src="hero.webp" width="700" height="233" {}
|
||||
p { "Written at: " (now.format("%F %T")) }
|
||||
p { a href = "calendars.html" { "Upstream calendars" } }
|
||||
@for entry in html_list {
|
||||
(entry)
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@ pub(crate) struct Config {
|
|||
|
||||
#[derive(Deserialize)]
|
||||
struct Event {
|
||||
description: String,
|
||||
#[serde(alias = "description")]
|
||||
_description: String,
|
||||
#[serde(alias = "endDate")]
|
||||
end_date: Option<String>,
|
||||
_end_date: Option<String>,
|
||||
#[serde(alias = "endTime")]
|
||||
end_time: Option<String>,
|
||||
_end_time: Option<String>,
|
||||
#[serde(alias = "eventName")]
|
||||
event_name: String,
|
||||
location: String,
|
||||
|
|
|
@ -36,10 +36,11 @@ impl Config {
|
|||
#[derive(Deserialize)]
|
||||
struct Event {
|
||||
#[serde(alias = "durationInMinutes")]
|
||||
duration_in_minutes: u32,
|
||||
_duration_in_minutes: u32,
|
||||
timestamp: i64,
|
||||
title: String,
|
||||
description: String,
|
||||
#[serde(alias = "description")]
|
||||
_description: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue