extern crate assemble_app;
extern crate serde;
extern crate maud;
use assemble_app::*;
use maud::html;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, VecDeque};
assemble_init! {{
register_root_view!(ViewHandler);
}}
#[derive(Deserialize, Serialize)]
struct MyEvent {
description: String,
face: String,
}
#[derive(Deserialize, Serialize)]
struct ViewHandler {
recent_events: VecDeque<MyEvent>
}
const LIMIT: u32 = 10;
impl View for ViewHandler {
fn start(_is_connected: bool, _params: HashMap<String, String>) -> Result<Self> {
pubsub_subscribe("events")?;
let mut vd = VecDeque::new();
let events = kv_scan::<MyEvent>("event_bucket", &ScanOpts::default().reverse(true).limit(LIMIT))?;
for (_, event) in events {
vd.push_front(event);
}
Ok(ViewHandler { recent_events: vd })
}
fn render(&self) -> Result<Html> {
let markup = html! {
div class="bg-indigo-700" {
div class="max-w-2xl mx-auto text-center py-16 px-4 sm:py-20 sm:px-6 lg:px-8" {
button assemble-click="click" assemble-value-description="Panda" assemble-value-face="🐼" class="mt-8 w-full inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-indigo-600 bg-white hover:bg-indigo-50 sm:w-auto" {
"Pick panda (🐼)"
}
button assemble-click="click" assemble-value-description="Gorilla" assemble-value-face="🦍" class="mx-4 mt-8 w-full inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-indigo-600 bg-white hover:bg-indigo-50 sm:w-auto" {
"Pick gorilla (🦍)"
}
button assemble-click="click" assemble-value-description="Tiger" assemble-value-face="🐯" class="mt-8 w-full inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-indigo-600 bg-white hover:bg-indigo-50 sm:w-auto" {
"Pick tiger (🐯)"
}
h2 class="mt-4 text-3xl font-extrabold text-white sm:text-4xl" {
span class="block" {
"Last 100 Events"
}
}
@for (event) in &self.recent_events {
p class="mt-4 text-lg leading-6 text-indigo-200" {
"Somebody picked a " (event.description) " " (event.face)
}
}
}
}
};
Ok(markup.into_string())
}
fn local_event(&mut self, msg: &str, payload: &[u8]) -> Result<()> {
match msg {
"click" => {
let ev: MyEvent = deserialize(payload)?;
kv_set("event_bucket", &utc_now()?.to_rfc3339(), &ev)?;
pubsub_publish_from("events", "new_event", &ev)?;
self.recent_events.push_front(ev);
self.recent_events.truncate(LIMIT as usize);
Ok(())
}
_ => Ok(())
}
}
fn pubsub_event(&mut self, topic: &str, event: &str, payload: &[u8]) -> Result<()> {
match &(topic, event) {
("events", "new_event") => {
self.recent_events.push_front(deserialize(payload)?);
self.recent_events.truncate(LIMIT as usize);
Ok(())
}
_ => Ok(())
}
}
}