sub-aligator/src/templates.rs
SW 6e24ce541a feat: rename to SUB-ALIGATOR, dark theme, pool deletion, header nav
- Rename app title to SUB-ALIGATOR (header, page titles, exports, README)
- Add dark amber-terminal theme with a header toggle, persisted in localStorage
- Add pool deletion (soft delete): allocations are kept in history and
  block the address space again when the same or an overlapping pool is
  re-added (re-enable on exact CIDR match, re-attach contained allocations)
- Reject new pools that overlap an enabled pool
- Move Home link into the page header, keep other links in the footer
- Load app.js globally via base template, add theme.js (CSP-safe, no inline JS)
2026-10-01 18:00:32 +02:00

168 lines
4.2 KiB
Rust

use crate::models::{AllocationDetail, AllocationListItem, AuditEventDisplay, Pool};
use askama::Template;
#[derive(Template)]
#[template(path = "base.html")]
pub struct BaseTemplate {
pub title: String,
}
#[derive(Template)]
#[template(path = "index.html")]
pub struct IndexTemplate {
pub pools: Vec<PoolTemplate>,
pub all_pools: Vec<Pool>,
pub allocations: Vec<AllocationListItem>,
pub page: i64,
pub total_pages: i64,
pub total_count: i64,
pub query: String,
pub pool_filter: String,
pub status_filter: String,
pub csrf_token: String,
pub flash: FlashData,
}
#[derive(Clone, Debug)]
pub struct PoolTemplate {
pub id: i64,
pub slug: String,
pub name: String,
pub cidr: String,
pub kind: String,
pub allowed_prefixes: Vec<String>,
pub allowed_prefixes_json: String,
}
impl From<Pool> for PoolTemplate {
fn from(p: Pool) -> Self {
let allowed: Vec<i32> = p.allowed_prefixes();
Self {
id: p.id,
slug: p.slug.clone(),
name: p.name,
cidr: p.cidr,
kind: p.kind,
allowed_prefixes_json: serde_json::to_string(&allowed).unwrap_or_default(),
allowed_prefixes: allowed.into_iter().map(|x| x.to_string()).collect(),
}
}
}
#[derive(Clone, Debug)]
pub struct SuccessMessage {
pub cidr: String,
pub note: String,
pub network: String,
pub broadcast: String,
pub first_host: String,
pub last_host: String,
pub usable_host_count: i32,
}
#[derive(Clone, Debug, Default)]
pub struct FlashData {
pub has_success: bool,
pub success_cidr: String,
pub success_note: String,
pub success_network: String,
pub success_broadcast: String,
pub success_first_host: String,
pub success_last_host: String,
pub success_usable_host_count: i32,
pub has_error: bool,
pub error: String,
}
impl From<Option<SuccessMessage>> for FlashData {
fn from(success: Option<SuccessMessage>) -> Self {
match success {
Some(s) => FlashData {
has_success: true,
success_cidr: s.cidr,
success_note: s.note,
success_network: s.network,
success_broadcast: s.broadcast,
success_first_host: s.first_host,
success_last_host: s.last_host,
success_usable_host_count: s.usable_host_count,
has_error: false,
error: String::new(),
},
None => FlashData::default(),
}
}
}
impl FlashData {
pub fn error(message: impl Into<String>) -> Self {
FlashData {
has_error: true,
error: message.into(),
..Default::default()
}
}
}
#[derive(Template)]
#[template(path = "partials/pool_preview.html")]
pub struct PoolPreviewTemplate {
pub cidr: String,
pub prefix_length: i32,
pub address_count: i32,
pub usable_host_count: i32,
pub has_error: bool,
pub error: String,
}
#[derive(Template)]
#[template(path = "fragments/flash.html")]
pub struct FlashTemplate {
pub flash: FlashData,
}
#[derive(Template)]
#[template(path = "fragments/allocations_table.html")]
pub struct AllocationsTableTemplate {
pub allocations: Vec<AllocationListItem>,
pub page: i64,
pub total_pages: i64,
pub total_count: i64,
pub query: String,
pub pool_filter: String,
pub status_filter: String,
pub csrf_token: String,
}
#[derive(Template)]
#[template(path = "allocation_detail.html")]
pub struct AllocationDetailTemplate {
pub allocation: AllocationDetail,
pub audit_events: Vec<AuditEventDisplay>,
pub csrf_token: String,
pub flash: FlashData,
}
#[derive(Template)]
#[template(path = "setup.html")]
pub struct SetupTemplate {
pub csrf_token: String,
pub error: String,
}
#[derive(Clone, Debug)]
pub struct PoolRow {
pub pool: Pool,
pub active_count: i64,
pub reserved_count: i64,
pub released_count: i64,
pub total_count: i64,
}
#[derive(Template)]
#[template(path = "pools.html")]
pub struct PoolListTemplate {
pub pools: Vec<PoolRow>,
pub csrf_token: String,
pub error: String,
}