2023-08-29 21:34:01 +02:00
|
|
|
use std::fmt;
|
2023-08-29 21:34:00 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
use base64::Engine as _;
|
|
|
|
|
use sha2::{Digest, Sha256};
|
2023-05-08 00:05:45 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
use crate::Context;
|
|
|
|
|
use maud::Markup;
|
|
|
|
|
|
|
|
|
|
pub mod error;
|
2023-05-08 00:05:45 +02:00
|
|
|
pub mod home;
|
|
|
|
|
pub mod inventory;
|
2023-08-29 21:34:01 +02:00
|
|
|
pub mod root;
|
2023-05-18 00:11:52 +02:00
|
|
|
pub mod trip;
|
2023-05-17 17:47:26 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
pub use error::ErrorPage;
|
|
|
|
|
pub use root::Root;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum HtmxAction {
|
|
|
|
|
Get(String),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for HtmxAction {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
match self {
|
2023-09-11 19:47:51 +02:00
|
|
|
Self::Get(path) => write!(f, "{path}"),
|
2023-08-29 21:34:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum FallbackAction {
|
|
|
|
|
Get(String),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for FallbackAction {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
match self {
|
2023-09-11 19:47:51 +02:00
|
|
|
Self::Get(path) => write!(f, "{path}"),
|
2023-08-29 21:34:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-08 00:05:45 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct ComponentId(String);
|
2023-05-08 00:05:45 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
impl ComponentId {
|
|
|
|
|
#[tracing::instrument]
|
|
|
|
|
// fn new() -> Self {
|
|
|
|
|
// NOTE: this could also use a static AtomicUsize incrementing integer, which might be faster
|
|
|
|
|
// Self(random::<u32>())
|
|
|
|
|
// }
|
2023-08-29 21:34:01 +02:00
|
|
|
#[tracing::instrument]
|
2023-08-29 21:34:01 +02:00
|
|
|
fn html_id(&self) -> String {
|
|
|
|
|
let id = {
|
|
|
|
|
let mut hasher = Sha256::new();
|
|
|
|
|
hasher.update(self.0.as_bytes());
|
|
|
|
|
hasher.finalize()
|
2023-08-29 21:34:00 +02:00
|
|
|
};
|
|
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
// 9 bytes is enough to be unique
|
|
|
|
|
// If this is divisible by 3, it means that we can base64-encode it without
|
|
|
|
|
// any "=" padding
|
|
|
|
|
//
|
|
|
|
|
// cannot panic, as the output for sha256 will always be bit
|
|
|
|
|
let id = &id[..9];
|
|
|
|
|
|
|
|
|
|
// URL_SAFE because we cannot have slashes in the output
|
2023-09-11 19:47:51 +02:00
|
|
|
base64::engine::general_purpose::URL_SAFE.encode(id)
|
2023-08-29 21:34:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for ComponentId {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
write!(f, "{}", self.html_id())
|
2023-05-08 00:05:45 +02:00
|
|
|
}
|
2023-08-29 21:33:59 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum HtmxTarget {
|
|
|
|
|
Myself,
|
|
|
|
|
Component(ComponentId),
|
|
|
|
|
}
|
2023-05-08 00:05:45 +02:00
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct HtmxComponent {
|
|
|
|
|
id: ComponentId,
|
|
|
|
|
action: HtmxAction,
|
|
|
|
|
fallback_action: FallbackAction,
|
|
|
|
|
target: HtmxTarget,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl HtmxComponent {
|
|
|
|
|
fn target(&self) -> &ComponentId {
|
|
|
|
|
match self.target {
|
|
|
|
|
HtmxTarget::Myself => &self.id,
|
|
|
|
|
HtmxTarget::Component(ref id) => id,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum Parent {
|
|
|
|
|
Root,
|
|
|
|
|
Component(ComponentId),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Parent> for ComponentId {
|
|
|
|
|
fn from(value: Parent) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
Parent::Root => ComponentId("/".into()),
|
|
|
|
|
Parent::Component(c) => c,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ComponentId> for Parent {
|
|
|
|
|
fn from(value: ComponentId) -> Self {
|
|
|
|
|
Self::Component(value)
|
2023-05-08 00:05:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-08-29 21:34:01 +02:00
|
|
|
|
|
|
|
|
pub trait Component {
|
|
|
|
|
type Args;
|
|
|
|
|
|
|
|
|
|
fn init(parent: Parent, args: Self::Args) -> Self;
|
|
|
|
|
fn build(self, context: &Context) -> Markup;
|
|
|
|
|
}
|