code: upgrade to axum 0.7, working on repo info system
This commit is contained in:
parent
0adae154c8
commit
9f4067e94c
238
Cargo.lock
generated
238
Cargo.lock
generated
@ -79,9 +79,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.5"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
|
||||
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@ -364,13 +364,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"axum-core 0.3.4",
|
||||
"bitflags 1.3.2",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"http 0.2.9",
|
||||
"http-body 0.4.5",
|
||||
"hyper 0.14.27",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core 0.4.3",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"hyper 1.1.0",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
@ -387,6 +417,7 @@ dependencies = [
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -398,14 +429,35 @@ dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http 0.2.9",
|
||||
"http-body 0.4.5",
|
||||
"mime",
|
||||
"rustversion",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"sync_wrapper",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
@ -821,16 +873,26 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.1"
|
||||
name = "env_filter"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
|
||||
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
|
||||
dependencies = [
|
||||
"humantime",
|
||||
"is-terminal",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eeb342678d785662fd2514be38c459bb925f02b68dd2a3e0f21d7ef82d979dd"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"env_filter",
|
||||
"humantime",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1158,6 +1220,25 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@ -1245,6 +1326,17 @@ dependencies = [
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.5"
|
||||
@ -1252,7 +1344,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"http 0.2.9",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body-util"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http-body 1.0.0",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
@ -1284,8 +1399,8 @@ dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http 0.2.9",
|
||||
"http-body 0.4.5",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
@ -1297,6 +1412,43 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http 1.0.0",
|
||||
"http-body 1.0.0",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"http 1.0.0",
|
||||
"http-body 1.0.0",
|
||||
"hyper 1.1.0",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.4",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
@ -1391,17 +1543,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix 0.38.28",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
@ -1581,9 +1722,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "minijinja"
|
||||
version = "1.0.8"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80084fa3099f58b7afab51e5f92e24c2c2c68dcad26e96ad104bd6011570461d"
|
||||
checksum = "431d72874542d43aba1ca605870eacab134fdeb0c8fe27666ecf4b2662239df2"
|
||||
dependencies = [
|
||||
"memo-map",
|
||||
"percent-encoding",
|
||||
@ -1612,7 +1753,7 @@ name = "miniweb"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
"axum 0.7.4",
|
||||
"barrel",
|
||||
"dotenvy",
|
||||
"dunce",
|
||||
@ -1630,6 +1771,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"slug",
|
||||
"sqlformat",
|
||||
"strinto",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@ -2279,7 +2421,7 @@ version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum 0.6.20",
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"tokio",
|
||||
@ -3013,6 +3155,15 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strinto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
@ -3090,15 +3241,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.51"
|
||||
@ -3214,6 +3356,20 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.3"
|
||||
|
@ -17,6 +17,7 @@ use_barrel = ["barrel", "sqlformat"]
|
||||
default = ["use_barrel"]
|
||||
|
||||
[dependencies]
|
||||
strinto = { path = "./strinto" }
|
||||
entity = { path = "./entity" }
|
||||
sea-orm = { version = "0.12.10", features = [
|
||||
"runtime-tokio-native-tls",
|
||||
@ -24,14 +25,15 @@ sea-orm = { version = "0.12.10", features = [
|
||||
] }
|
||||
sqlformat = { version = "0.2.2", optional = true }
|
||||
anyhow = "1.0.75"
|
||||
axum = "0.6.20"
|
||||
axum = "0.7"
|
||||
barrel = { version = "0.7.0", optional = true, features = ["pg"] }
|
||||
dotenvy = "0.15.7"
|
||||
mime_guess = "2.0.4"
|
||||
minijinja = { version = "1.0.8", features = [
|
||||
minijinja = { version = "1.0.11", features = [
|
||||
"loader",
|
||||
"builtins",
|
||||
"urlencode",
|
||||
"deserialization",
|
||||
] }
|
||||
minijinja-autoreload = "1.0.8"
|
||||
once_cell = "1.18.0"
|
||||
@ -45,6 +47,6 @@ serde = { version = "1.0.188", features = ["derive"] }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
dunce = "1.0.4"
|
||||
log = "0.4.20"
|
||||
env_logger = "0.10.1"
|
||||
env_logger = "0.11"
|
||||
serde_json = "1.0.108"
|
||||
slug = "0.1.5"
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub use config::AdminModelConfig;
|
||||
pub use dto::AdminApp;
|
||||
pub use dto::AdminModel;
|
||||
pub use repository::{AdminRepository, RepositoryList};
|
||||
pub use repository::{AdminRepository, RepositoryInfo, RepositoryList};
|
||||
|
||||
mod auth {
|
||||
|
||||
@ -95,8 +95,33 @@ pub mod repository {
|
||||
}
|
||||
}
|
||||
|
||||
// each repository has to implement a repo info.
|
||||
#[derive(Serialize)]
|
||||
pub struct RepositoryInfo {
|
||||
name: String,
|
||||
lookup_key: String,
|
||||
display_list: Vec<String>,
|
||||
}
|
||||
|
||||
impl RepositoryInfo {
|
||||
pub fn new(name: &str, lookup_key: &str) -> Self {
|
||||
RepositoryInfo {
|
||||
name: name.to_owned(),
|
||||
lookup_key: lookup_key.to_owned(),
|
||||
display_list: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_list(mut self, display_list: &[&str]) -> RepositoryInfo {
|
||||
self.display_list = display_list.iter().map(|&e| e.to_string()).collect();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AdminRepository: Send + Sync {
|
||||
fn get_item(&self, id: usize) -> Option<Value>;
|
||||
|
||||
fn get_repo_info(&self) -> RepositoryInfo;
|
||||
fn get_list(&self) -> RepositoryList;
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,49 @@
|
||||
// implementation of static repository
|
||||
|
||||
use super::domain::{AdminModelConfig, AdminRepository, RepositoryList};
|
||||
use super::domain::{AdminModelConfig, AdminRepository, RepositoryInfo, RepositoryList};
|
||||
use super::state::AdminRegistry;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
struct MyStaticRepository {}
|
||||
|
||||
impl AdminRepository for MyStaticRepository {
|
||||
fn get_item(&self, id: usize) -> Option<Value> {
|
||||
Some(json!({
|
||||
"name": "Adam",
|
||||
"age": id,
|
||||
}))
|
||||
struct MyStaticRepository {
|
||||
content: Vec<Value>,
|
||||
}
|
||||
|
||||
fn get_list(&self) -> RepositoryList {
|
||||
RepositoryList::List {
|
||||
values: vec![
|
||||
json!({"name": "Strange", "age": 150 }),
|
||||
json!({"name": "Adam", "age": 12}),
|
||||
impl MyStaticRepository {
|
||||
pub fn new() -> Self {
|
||||
MyStaticRepository {
|
||||
content: vec![
|
||||
json!({"id": 1, "name": "Strange", "age": 150, "level": "master" }),
|
||||
json!({"id": 2, "name": "Adam", "age": 12, "powers": 8}),
|
||||
json!({"id": 3, "name": "Tony", "age": 42, "powers": 0}),
|
||||
json!({"id": 4, "name": "Rex", "age": 72}),
|
||||
json!({"id": 5, "name": "Justin", "age": 46}),
|
||||
json!({"id": 6, "name": "Reacher", "age": 39, "level": "adept", "powers": 0}),
|
||||
json!({"id": 7, "name": "Arnold", "age": 64}),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AdminRepository for MyStaticRepository {
|
||||
fn get_item(&self, id: usize) -> Option<Value> {
|
||||
self.content.get(id).cloned()
|
||||
}
|
||||
|
||||
fn get_list(&self) -> RepositoryList {
|
||||
RepositoryList::List {
|
||||
values: self.content.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_repo_info(&self) -> RepositoryInfo {
|
||||
RepositoryInfo::new("My Static Repository", "id")
|
||||
.display_list(&["id", "name", "age", "level"])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_example(registry: &mut AdminRegistry) {
|
||||
let app_key = registry.register_app("Example App");
|
||||
let repo = MyStaticRepository {};
|
||||
let repo = MyStaticRepository::new();
|
||||
let model_config = AdminModelConfig {
|
||||
app_key: app_key,
|
||||
name: "ExampleModel".to_owned(),
|
||||
|
@ -10,7 +10,7 @@ use crate::service::templates;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::domain::RepositoryList;
|
||||
use super::domain::{RepositoryInfo, RepositoryList};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Question {
|
||||
@ -43,6 +43,7 @@ pub struct AdminContext {
|
||||
|
||||
pub request: AdminRequest,
|
||||
pub available_apps: Vec<AdminApp>,
|
||||
pub item_info: Option<RepositoryInfo>,
|
||||
pub item_list: RepositoryList,
|
||||
pub item: Option<Value>,
|
||||
}
|
||||
@ -64,6 +65,7 @@ impl Default for AdminContext {
|
||||
request: AdminRequest {
|
||||
path: "".to_owned(),
|
||||
},
|
||||
item_info: None,
|
||||
item_list: RepositoryList::Empty,
|
||||
item: None,
|
||||
}
|
||||
@ -106,6 +108,8 @@ pub async fn list_item_collection(
|
||||
// we should consider using Vec<Value> instead in get_list.
|
||||
AdminContext {
|
||||
available_apps: registry.get_apps(),
|
||||
content: model_key.to_owned(),
|
||||
item_info: Some(repo.get_repo_info()),
|
||||
item_list: repo.get_list(),
|
||||
..Default::default()
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use log::info;
|
||||
use std::env;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
async fn home(templates: State<templates::Templates>) -> impl IntoResponse {
|
||||
templates.render_html("index.html", ())
|
||||
@ -70,11 +71,13 @@ async fn main() {
|
||||
};
|
||||
info!("listening on {}", listen_addr);
|
||||
info!("admin on: http://{}/admin", server_addr);
|
||||
axum::Server::bind(&listen_addr)
|
||||
.serve(app.into_make_service())
|
||||
let listener = TcpListener::bind(&listen_addr)
|
||||
.await
|
||||
.expect("Could not bind TCP Listener.");
|
||||
axum::serve(listener, app.into_make_service())
|
||||
.with_graceful_shutdown(shutdown_signal())
|
||||
.await
|
||||
.unwrap();
|
||||
.expect("Could not start serving Axum");
|
||||
}
|
||||
|
||||
async fn shutdown_signal() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Default handlers */
|
||||
use crate::service::templates::Templates;
|
||||
use axum::{
|
||||
body::{boxed, Full},
|
||||
body::Body,
|
||||
extract::State,
|
||||
http::{header, StatusCode, Uri},
|
||||
response::{IntoResponse, Response},
|
||||
@ -55,7 +55,7 @@ where
|
||||
let path: &str = self.path.as_ref();
|
||||
match E::get(path) {
|
||||
Some(content) => {
|
||||
let body = boxed(Full::from(content.data));
|
||||
let body = Body::from(content.data);
|
||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
||||
Response::builder()
|
||||
.header(header::CONTENT_TYPE, mime.as_ref())
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::service::error::Error;
|
||||
use axum::response::Html;
|
||||
use minijinja::value::ValueKind;
|
||||
use minijinja::{path_loader, Environment, Value};
|
||||
use minijinja_autoreload::AutoReloader;
|
||||
use pulldown_cmark::Event;
|
||||
use serde::Deserializer;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -19,6 +21,7 @@ impl Templates {
|
||||
environment.add_filter("none", none);
|
||||
environment.add_filter("markdown", markdown);
|
||||
environment.add_filter("yesno", filter_yesno);
|
||||
environment.add_filter("table_keys", collect_unique_keys);
|
||||
environment.add_function("static", tpl_static);
|
||||
environment.add_function("url", tpl_url);
|
||||
environment.add_function("csrf_token", tpl_to_be_implemented);
|
||||
@ -93,3 +96,71 @@ pub fn none(value: Value, other: Option<Value>) -> Value {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
fn tpl_table(values: Vec<Value>) -> Value {
|
||||
Value::from_safe_string(format!(
|
||||
"Output: {}",
|
||||
values.first().expect("No values found.").kind()
|
||||
))
|
||||
}
|
||||
|
||||
mod helper {
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct OrderedSet<T> {
|
||||
set: HashSet<T>,
|
||||
vec: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Eq + std::hash::Hash + Clone> OrderedSet<T> {
|
||||
pub fn new() -> Self {
|
||||
OrderedSet {
|
||||
set: HashSet::new(),
|
||||
vec: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, value: T) {
|
||||
if self.set.insert(value.clone()) {
|
||||
self.vec.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
for item in iter {
|
||||
self.insert(item);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<T> {
|
||||
self.vec.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for OrderedSet<T> {
|
||||
type Item = T;
|
||||
type IntoIter = std::vec::IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.vec.into_iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_unique_keys(values: Value) -> Value {
|
||||
use helper::OrderedSet;
|
||||
use serde::Deserialize;
|
||||
let mut unique_keys: OrderedSet<String> = OrderedSet::new();
|
||||
|
||||
if let Ok(vec) = Vec::<serde_json::Value>::deserialize(values) {
|
||||
for value in vec.iter() {
|
||||
if let Some(dict) = value.as_object() {
|
||||
let keys_vec: Vec<String> = dict.keys().map(|s| s.to_owned()).collect();
|
||||
unique_keys.extend(keys_vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let keys_list = unique_keys.into_iter().collect::<Vec<_>>();
|
||||
Value::from(keys_list)
|
||||
}
|
||||
|
@ -10,23 +10,42 @@
|
||||
{% endblock %}
|
||||
|
||||
{% if item_list %}
|
||||
{% set item_keys = item_info.display_list or item_list|table_keys %}
|
||||
|
||||
{% if item_info.lookup_key in item_keys %}
|
||||
{% set primary_key = item_info.lookup_key %}
|
||||
{% endif %}
|
||||
|
||||
<div class="ui short scrolling container">
|
||||
<table class="ui very compact celled table head stuck unstackable">
|
||||
<caption>Table Caption</caption>
|
||||
<caption>{{ item_info.name|none(content) }}</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Header1</th>
|
||||
<th>Header2</th>
|
||||
<th>Header3</th>
|
||||
{% for key in item_keys %}
|
||||
{% if key==primary_key %}
|
||||
<th class="blue"><i class="key icon"></i>
|
||||
{{ key|capitalize }}
|
||||
</th>
|
||||
{% else %}
|
||||
<th>{{ key|capitalize }}</th>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for item in item_list %}
|
||||
<tr>
|
||||
<td>{{ item.name}}</td>
|
||||
<td>{{ item.age }}</td>
|
||||
<td>{{ item }}</td>
|
||||
{% for key in item_keys %}
|
||||
{% if key==primary_key %}
|
||||
<td class="selectable warning">
|
||||
<a href="#">{{ item[key] }}</a>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>{{ item[key] }}</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -34,13 +53,6 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{% set x="name" %}
|
||||
|
||||
|
||||
|
||||
<li>{{ item[x] }}</li>
|
||||
|
||||
</ul>
|
||||
{% else %}
|
||||
No Items found.
|
||||
{% endif %}
|
||||
|
@ -24,6 +24,9 @@
|
||||
{% include "fomantic.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
{% endblock extrahead %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
@ -1,4 +1,18 @@
|
||||
{% extends "base.html.j2" %}
|
||||
{% extends "base.jinja" %}
|
||||
|
||||
{% block extrahead %}
|
||||
<style type="text/css">
|
||||
.hidden.menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.masthead.segment {
|
||||
min-height: 700px;
|
||||
padding: 1em 0em;
|
||||
}
|
||||
</style>
|
||||
{% endblock extrahead %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="pusher">
|
||||
|
Loading…
Reference in New Issue
Block a user