#![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate rocket; #[macro_use] extern crate serde; use serde_json::Value; //use rocket::request::FromSegments; //use rocket::http::uri::Segments; use rocket_contrib::serve::StaticFiles; use rocket_contrib::templates::Template; mod store; use crate::store::form::{render_card_fields, render_empty_fields, RenderedCard, RenderedField, MapFromForm, collect_card_form}; use crate::store::Store; use parking_lot::RwLock; use rocket::request::Form; use rocket::response::Redirect; use rocket::State; use std::env; #[derive(Serialize, Debug)] pub struct ListContext<'a> { pub fields: Vec>, pub cards: Vec>, pub page: usize, pub pages: usize, } const PER_PAGE: usize = 20; // TODO configurable fn find_page_with_card(store: &Store, card_id: usize) -> Option { if let Some((n, _)) = store .data .cards .iter() .enumerate() .find(|(_n, (id, _card))| **id == card_id) { Some(n / PER_PAGE) } else { None } } #[get("/?")] fn route_index(store: State>, page: Option) -> Template { let rg = store.read(); let mut page = page.unwrap_or_default(); let n_pages = (rg.data.cards.len() as f64 / PER_PAGE as f64).ceil() as usize; if page >= n_pages { page = n_pages - 1; } let context = ListContext { fields: render_empty_fields(&rg), pages: n_pages, page, cards: rg .data .cards .iter() .skip(page * PER_PAGE) .take(PER_PAGE) .filter_map(|(id, card)| { if let Value::Object(ref map) = card { Some(RenderedCard { fields: render_card_fields(&rg, map), id: *id, }) } else { None } }) .collect(), }; Template::render("index", context) } #[derive(Serialize)] struct AddCardContext<'a> { pub fields: Vec>, } #[derive(Serialize)] struct EditCardContext<'a> { pub fields: Vec>, pub id: usize, } #[get("/add")] fn route_add(store: State>) -> Template { let rg = store.read(); let context = AddCardContext { fields: render_empty_fields(&rg), }; Template::render("add", context) } #[post("/add", data = "
")] fn route_add_save(form: Form, store: State>) -> Redirect { let mut wg = store.write(); let card = collect_card_form(&wg, form.into_inner()); let id = wg.add_card(card); let page = find_page_with_card(&wg, id).unwrap_or(0); Redirect::found(uri!(route_index: page)) } #[get("/edit/")] fn route_edit(id: usize, store: State>) -> Option