Sample layout with test data
This commit is contained in:
parent
43472a2fc3
commit
2f597030b5
57
src/db.rs
Normal file
57
src/db.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use rusqlite::{Connection, Result};
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use rusqlite::types::Value;
|
||||||
|
|
||||||
|
pub struct Db {
|
||||||
|
conn: Mutex<Connection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Db {
|
||||||
|
pub fn open(path: &str) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
conn: Mutex::new(Connection::open(path)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_users(&self) -> Result<(Vec<String>, Vec<Vec<String>>)> {
|
||||||
|
let conn = self.conn.lock().unwrap();
|
||||||
|
|
||||||
|
let mut stmt = conn.prepare("SELECT * FROM users")?;
|
||||||
|
|
||||||
|
let columns = stmt
|
||||||
|
.column_names()
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let col_count = stmt.column_count();
|
||||||
|
|
||||||
|
let rows_iter = stmt.query_map([], move |row| {
|
||||||
|
let mut r = Vec::new();
|
||||||
|
|
||||||
|
for i in 0..col_count {
|
||||||
|
let val: Value = row.get(i)?;
|
||||||
|
|
||||||
|
let s = match val {
|
||||||
|
Value::Null => "<null>".to_string(),
|
||||||
|
Value::Integer(i) => i.to_string(),
|
||||||
|
Value::Real(f) => f.to_string(),
|
||||||
|
Value::Text(t) => t, // already String
|
||||||
|
Value::Blob(_) => "<blob>".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
r.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(r)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut rows = Vec::new();
|
||||||
|
for r in rows_iter {
|
||||||
|
rows.push(r?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((columns, rows))
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/main.rs
37
src/main.rs
@ -1,3 +1,36 @@
|
|||||||
fn main() {
|
use axum::{routing::get, Router};
|
||||||
println!("Hello, world!");
|
use clap::Parser;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
|
mod db;
|
||||||
|
mod routes;
|
||||||
|
|
||||||
|
use db::Db;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
struct Args {
|
||||||
|
#[arg(long)]
|
||||||
|
db: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
let db = Arc::new(Db::open(&args.db).expect("db open failed"));
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/", get(routes::index))
|
||||||
|
.with_state(db);
|
||||||
|
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:8040")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("http://127.0.0.1:8040");
|
||||||
|
|
||||||
|
axum::serve(listener, app)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
29
src/routes.rs
Normal file
29
src/routes.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use askama::Template; // REQUIRED
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::State,
|
||||||
|
response::Html,
|
||||||
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::db::Db;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "table.html")]
|
||||||
|
pub struct TableTemplate {
|
||||||
|
pub table_name: String,
|
||||||
|
pub columns: Vec<String>,
|
||||||
|
pub rows: Vec<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn index(State(db): State<Arc<Db>>) -> Html<String> {
|
||||||
|
let (columns, rows) = db.get_users().unwrap();
|
||||||
|
|
||||||
|
let tmpl = TableTemplate {
|
||||||
|
table_name: "users".into(),
|
||||||
|
columns,
|
||||||
|
rows,
|
||||||
|
};
|
||||||
|
|
||||||
|
Html(tmpl.render().unwrap())
|
||||||
|
}
|
||||||
32
templates/table.html
Normal file
32
templates/table.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ table_name }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>{{ table_name }}</h1>
|
||||||
|
|
||||||
|
<table border="1" cellspacing="0" cellpadding="4">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{% for col in columns %}
|
||||||
|
<th>{{ col }}</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for row in rows %}
|
||||||
|
<tr>
|
||||||
|
{% for cell in row %}
|
||||||
|
<td>{{ cell }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user