Github Commits
use wasm_bindgen::prelude::*;
struct GitHubCommits {
repo: String,
response: Option<Response>,
}
type Response = Result<Vec<Record>, Box<dyn std::error::Error>>;
#[derive(serde::Deserialize)]
struct Record {
html_url: String,
sha: String,
commit: Commit,
}
#[derive(serde::Deserialize)]
struct Commit {
author: Author,
message: String,
}
#[derive(serde::Deserialize)]
struct Author {
name: String,
date: String,
}
impl GitHubCommits {
fn new() -> Self {
GitHubCommits {
repo: "rust-lang/rust".into(),
response: None,
}
}
}
enum Message {
Fetch,
UpdateRepo(String),
UpdateResponse(Response),
}
impl draco::Application for GitHubCommits {
type Message = Message;
fn update(&mut self, message: Self::Message, mailbox: &draco::Mailbox<Self::Message>) {
use self::Message::*;
match message {
Fetch => {
let url = format!(
"https://api.github.com/repos/{}/commits?per_page=10",
self.repo
);
match url.parse::<reqwest::Url>() {
Ok(url) => mailbox.spawn(
// TODO: s/text()/json()/ and remove serde_json when it's implemented for WASM
async {
Ok(serde_json::from_str(
&reqwest::get(url).await?.text().await?,
)?)
},
Message::UpdateResponse,
),
Err(err) => draco::console::error(&err.to_string()),
}
}
UpdateRepo(repo) => self.repo = repo,
UpdateResponse(response) => self.response = Some(response),
}
}
fn view(&self) -> draco::VNode<Self::Message> {
use draco::html as h;
h::form()
.on("submit", |event| {
event.prevent_default();
Message::Fetch
})
.with((
h::input()
.value(self.repo.clone())
.on_input(Message::UpdateRepo),
h::button().with("Fetch").on("click", |_| Message::Fetch),
match &self.response {
Some(Ok(records)) => h::ul().append(records.iter().map(|record| {
h::li().with(
h::p().with((
h::a()
.href(record.html_url.clone())
.with(record.sha[0..8].to_string()),
" ",
record
.commit
.message
.lines()
.next()
.unwrap_or("")
.to_string(),
h::br(),
"By ",
h::strong().with(record.commit.author.name.clone()),
" at ",
record.commit.author.date.clone(),
)),
)
})),
Some(Err(err)) => h::pre().with(format!("{:#?}", err)),
None => h::div(),
},
))
.into()
}
}
#[wasm_bindgen(start)]
pub fn start() {
draco::start(
GitHubCommits::new(),
draco::select("main").expect("<main>").into(),
);
}