Implement more tables, add more page templates, initial working db example
This commit is contained in:
@@ -1,19 +1,31 @@
|
||||
use diesel::{Connection, PgConnection};
|
||||
use diesel::{Connection, PgConnection, r2d2::ConnectionManager};
|
||||
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
|
||||
use r2d2::Pool;
|
||||
|
||||
pub mod schema;
|
||||
pub mod models;
|
||||
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations");
|
||||
|
||||
fn run_migrations(conn: &mut impl MigrationHarness<diesel::pg::Pg>) {
|
||||
|
||||
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
|
||||
|
||||
fn run_migrations(pool: &mut DbPool) {
|
||||
let mut conn = pool
|
||||
.get()
|
||||
.expect("failed to get db connection :3");
|
||||
conn.run_pending_migrations(MIGRATIONS).unwrap();
|
||||
log::info!("Running migrations");
|
||||
}
|
||||
|
||||
|
||||
pub fn start(cfg: &crate::config::Config) -> anyhow::Result<PgConnection> {
|
||||
let mut connection = PgConnection::establish(&cfg.database_url()?.to_string())?;
|
||||
run_migrations(&mut connection);
|
||||
Ok(connection)
|
||||
pub fn start(cfg: &crate::config::Config) -> anyhow::Result<DbPool> {
|
||||
let manager = ConnectionManager::<PgConnection>::new(&cfg.database_url()?.to_string());
|
||||
let mut pool = Pool::builder()
|
||||
.build(manager)
|
||||
.expect("failed to create pool :3");
|
||||
|
||||
run_migrations(&mut pool);
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
|
||||
171
src/db/models.rs
Normal file
171
src/db/models.rs
Normal file
@@ -0,0 +1,171 @@
|
||||
use diesel::prelude::*;
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(User, foreign_key=worker_user_id))]
|
||||
#[diesel(table_name = super::schema::clients)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Client {
|
||||
pub id: i64,
|
||||
pub email: String,
|
||||
pub first_name: String,
|
||||
pub last_name: String,
|
||||
pub date_of_birth: time::Date,
|
||||
pub phone_number: String,
|
||||
pub gov_id_number: String,
|
||||
pub house_number: String,
|
||||
pub address_line: String,
|
||||
pub city: String,
|
||||
pub state: String,
|
||||
pub postal_code: String,
|
||||
pub country: String,
|
||||
pub worker_user_id: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(belongs_to(Warehouse))]
|
||||
#[diesel(table_name = super::schema::assigned_warehouse_managers)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct AssignedWarehouseManager {
|
||||
pub id: i64,
|
||||
pub user_id: i64,
|
||||
pub warehouse_id: i64,
|
||||
pub assigned_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(table_name = super::schema::attachments)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Attachment {
|
||||
pub id: i64,
|
||||
pub user_id: i64,
|
||||
pub comment_id: i64,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(Warehouse))]
|
||||
#[diesel(belongs_to(InventoryCatalogEntry, foreign_key=catalog_id))]
|
||||
#[diesel(table_name = super::schema::inventory)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Inventory {
|
||||
pub id: i64,
|
||||
pub warehouse_id: i64,
|
||||
pub catalog_id: i64,
|
||||
pub count: i64
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = super::schema::inventory_catalog)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct InventoryCatalogEntry {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub code: String,
|
||||
pub description: Option<String>,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(Client))]
|
||||
#[diesel(table_name = super::schema::invoices)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Invoice {
|
||||
pub id: i64,
|
||||
pub client_id: i64,
|
||||
pub amount: f32
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = super::schema::service_catalog)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct ServiceCatalogEntry {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub value_string: Option<String>,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(Client))]
|
||||
#[diesel(belongs_to(ServiceCatalogEntry, foreign_key=catalog_id))]
|
||||
#[diesel(table_name = super::schema::assigned_services)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct AssignedService {
|
||||
pub id: i64,
|
||||
pub client_id: i64,
|
||||
pub catalog_id: i64,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(belongs_to(Ticket))]
|
||||
#[diesel(table_name = super::schema::ticket_comments)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct TicketComment {
|
||||
pub id: i64,
|
||||
pub user_id: i64,
|
||||
pub ticket_id: i64,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
pub modified_at: Option<time::OffsetDateTime>,
|
||||
pub content: Option<String>
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(AssignedService, foreign_key=service_id))]
|
||||
#[diesel(table_name = super::schema::tickets)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Ticket {
|
||||
pub id: i64,
|
||||
pub title: String,
|
||||
pub description: Option<String>,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
pub created_by_user_id: i64,
|
||||
pub service_id: i64
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = super::schema::users)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct User {
|
||||
pub id: i64,
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub password_hash: String,
|
||||
pub password_salt: String,
|
||||
pub first_name: String,
|
||||
pub last_name: String,
|
||||
pub display_name: Option<String>,
|
||||
pub date_of_birth: Option<time::Date>,
|
||||
pub phone_number: Option<String>,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
pub last_login_at: Option<time::OffsetDateTime>,
|
||||
pub permissions: i64,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Associations)]
|
||||
#[diesel(belongs_to(User))]
|
||||
#[diesel(belongs_to(Warehouse))]
|
||||
#[diesel(table_name = super::schema::warehouse_actions)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct WarehouseAction {
|
||||
pub id: i64,
|
||||
pub user_id: i64,
|
||||
pub warehouse_id: i64,
|
||||
pub count: i64,
|
||||
pub reason: String,
|
||||
pub timestamp: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = super::schema::warehouses)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Warehouse {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub created_at: time::OffsetDateTime,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
assigned_services (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
client_id -> Int8,
|
||||
catalog_id -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
assigned_warehouse_managers (id) {
|
||||
id -> Int8,
|
||||
@@ -9,21 +18,30 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
attachments (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
comment_id -> Int8,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
clients (id) {
|
||||
id -> Int8,
|
||||
email -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
date_of_birth -> Nullable<Date>,
|
||||
phone_number -> Nullable<Text>,
|
||||
gov_id_number -> Nullable<Text>,
|
||||
house_number -> Nullable<Text>,
|
||||
address_line -> Nullable<Text>,
|
||||
city -> Nullable<Text>,
|
||||
state -> Nullable<Text>,
|
||||
postal_code -> Nullable<Text>,
|
||||
country -> Nullable<Text>,
|
||||
date_of_birth -> Date,
|
||||
phone_number -> Text,
|
||||
gov_id_number -> Text,
|
||||
house_number -> Text,
|
||||
address_line -> Text,
|
||||
city -> Text,
|
||||
state -> Text,
|
||||
postal_code -> Text,
|
||||
country -> Text,
|
||||
worker_user_id -> Nullable<Int8>,
|
||||
}
|
||||
}
|
||||
@@ -42,6 +60,7 @@ diesel::table! {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
description -> Nullable<Text>,
|
||||
code -> Text,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
@@ -55,16 +74,34 @@ diesel::table! {
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
services (id) {
|
||||
service_catalog (id) {
|
||||
id -> Int8,
|
||||
name -> Text,
|
||||
client_id -> Int8,
|
||||
description -> Nullable<Text>,
|
||||
value_string -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
ticket_comments (id) {
|
||||
id -> Int8,
|
||||
user_id -> Int8,
|
||||
ticket_id -> Int8,
|
||||
created_at -> Timestamptz,
|
||||
modified_at -> Nullable<Timestamptz>,
|
||||
content -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
tickets (id) {
|
||||
id -> Int8,
|
||||
title -> Text,
|
||||
description -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
service_id -> Int8,
|
||||
created_by_user_id -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +119,7 @@ diesel::table! {
|
||||
phone_number -> Nullable<Text>,
|
||||
created_at -> Timestamptz,
|
||||
last_login_at -> Nullable<Timestamptz>,
|
||||
permissions -> Numeric,
|
||||
permissions -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,23 +142,33 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(assigned_services -> clients (client_id));
|
||||
diesel::joinable!(assigned_services -> service_catalog (catalog_id));
|
||||
diesel::joinable!(assigned_warehouse_managers -> users (user_id));
|
||||
diesel::joinable!(assigned_warehouse_managers -> warehouses (warehouse_id));
|
||||
diesel::joinable!(attachments -> ticket_comments (comment_id));
|
||||
diesel::joinable!(attachments -> users (user_id));
|
||||
diesel::joinable!(clients -> users (worker_user_id));
|
||||
diesel::joinable!(inventory -> inventory_catalog (catalog_id));
|
||||
diesel::joinable!(inventory -> warehouses (warehouse_id));
|
||||
diesel::joinable!(invoices -> clients (client_id));
|
||||
diesel::joinable!(services -> clients (client_id));
|
||||
diesel::joinable!(ticket_comments -> tickets (ticket_id));
|
||||
diesel::joinable!(ticket_comments -> users (user_id));
|
||||
diesel::joinable!(tickets -> assigned_services (service_id));
|
||||
diesel::joinable!(tickets -> users (created_by_user_id));
|
||||
diesel::joinable!(warehouse_actions -> users (user_id));
|
||||
diesel::joinable!(warehouse_actions -> warehouses (warehouse_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
assigned_services,
|
||||
assigned_warehouse_managers,
|
||||
attachments,
|
||||
clients,
|
||||
inventory,
|
||||
inventory_catalog,
|
||||
invoices,
|
||||
services,
|
||||
service_catalog,
|
||||
ticket_comments,
|
||||
tickets,
|
||||
users,
|
||||
warehouse_actions,
|
||||
|
||||
@@ -19,6 +19,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
let db = db::start(&cfg)?;
|
||||
web::start(&cfg).await?;
|
||||
web::start(&cfg, db).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
use axum::{Router, routing::get};
|
||||
use diesel::PgConnection;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
use crate::db::DbPool;
|
||||
|
||||
pub mod pages;
|
||||
|
||||
|
||||
|
||||
|
||||
pub async fn start(cfg: &crate::config::Config) -> anyhow::Result<()> {
|
||||
pub async fn start(cfg: &crate::config::Config, db: DbPool) -> anyhow::Result<()> {
|
||||
let addr = format!("{}:{}", cfg.web.host, cfg.web.port);
|
||||
let app = Router::new()
|
||||
.route("/", get(pages::home::get_page))
|
||||
.route("/login", get(pages::login::get_page))
|
||||
.route("/clients", get(pages::clients::get_page))
|
||||
.nest_service(
|
||||
"/static",
|
||||
ServiceBuilder::new()
|
||||
.service(ServeDir::new("static"))
|
||||
);
|
||||
)
|
||||
.with_state(db);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
log::info!("Listening on http://{addr}");
|
||||
|
||||
55
src/web/pages/clients/mod.rs
Normal file
55
src/web/pages/clients/mod.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use askama::Template;
|
||||
use axum::extract::State;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
use axum::http::StatusCode;
|
||||
|
||||
use crate::db::DbPool;
|
||||
use crate::db::models::Client;
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "clients/index.html")]
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
pub clients: Vec<Client>
|
||||
}
|
||||
|
||||
impl BaseTemplate for PageTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page(State(pool): State<DbPool>) -> Response {
|
||||
async fn inner(pool: &DbPool) -> anyhow::Result<(StatusCode, String)> {
|
||||
use diesel::prelude::*;
|
||||
use crate::db::schema::clients::dsl::*;
|
||||
|
||||
let results = clients
|
||||
.order(id.asc())
|
||||
.limit(50)
|
||||
.load::<Client>(&mut pool.get()?)?;
|
||||
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default(),
|
||||
clients: results
|
||||
};
|
||||
|
||||
template.set_title("Clients");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner(&pool).await {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
pub struct HomeTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for HomeTemplate {
|
||||
fn ctx(&self) -> &BaseTemplateCtx {
|
||||
&self.ctx
|
||||
}
|
||||
fn ctx_mut(&mut self) -> &mut BaseTemplateCtx {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = HomeTemplate {
|
||||
ctx: Default::default()
|
||||
};
|
||||
|
||||
template.set_title("Home");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::extract::State;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
use axum::http::StatusCode;
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::db::DbPool;
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
#[template(path = "inventory/index.html")]
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for PageTemplate {
|
||||
@@ -30,18 +23,18 @@ impl BaseTemplate for PageTemplate {
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
pub async fn get_page(State(pool): State<DbPool>) -> Response {
|
||||
async fn inner(_pool: &DbPool) -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
ctx: Default::default(),
|
||||
};
|
||||
|
||||
template.set_title("Tickets");
|
||||
template.set_title("Clients");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
match inner(&pool).await {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
@@ -1,4 +1,5 @@
|
||||
use askama::Template;
|
||||
use axum::extract::State;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
|
||||
use axum::{
|
||||
@@ -7,6 +8,7 @@ use axum::{
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::db::DbPool;
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
@@ -27,7 +29,7 @@ impl BaseTemplate for PageTemplate {
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
pub async fn get_page(State(_db): State<DbPool>) -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
|
||||
|
||||
|
||||
use askama::Template;
|
||||
use axum::extract::State;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
use axum::http::StatusCode;
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
http::StatusCode,
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use crate::db::DbPool;
|
||||
use crate::web::pages::{BaseTemplate, BaseTemplateCtx};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "home.html")]
|
||||
#[template(path = "tickets/index.html")]
|
||||
pub struct PageTemplate {
|
||||
pub ctx: BaseTemplateCtx,
|
||||
|
||||
}
|
||||
|
||||
impl BaseTemplate for PageTemplate {
|
||||
@@ -30,18 +23,18 @@ impl BaseTemplate for PageTemplate {
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn get_page() -> Response {
|
||||
fn inner() -> anyhow::Result<(StatusCode, String)> {
|
||||
pub async fn get_page(State(pool): State<DbPool>) -> Response {
|
||||
async fn inner(_pool: &DbPool) -> anyhow::Result<(StatusCode, String)> {
|
||||
let mut template = PageTemplate {
|
||||
ctx: Default::default()
|
||||
ctx: Default::default(),
|
||||
};
|
||||
|
||||
template.set_title("Home");
|
||||
template.set_title("Clients");
|
||||
|
||||
Ok((StatusCode::OK, template.render()?))
|
||||
}
|
||||
|
||||
match inner() {
|
||||
match inner(&pool).await {
|
||||
Ok((status, s)) => (status, Html(s)).into_response(),
|
||||
Err(e) => {
|
||||
let s = crate::web::pages::error::get_error_page(e.to_string()).await;
|
||||
Reference in New Issue
Block a user