New layout

This commit is contained in:
eraden 2023-08-11 22:31:02 +02:00
parent bb1f1e4a3e
commit 6d42bb477a
8 changed files with 86 additions and 62 deletions

3
Cargo.lock generated
View File

@ -2594,6 +2594,8 @@ dependencies = [
"askama", "askama",
"askama_actix", "askama_actix",
"oswilno-contract", "oswilno-contract",
"oswilno-session",
"oswilno-view",
"sea-orm", "sea-orm",
"serde", "serde",
"serde_json", "serde_json",
@ -2636,6 +2638,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"actix-web", "actix-web",
"askama", "askama",
"askama_actix",
"futures-core", "futures-core",
"garde", "garde",
"tracing", "tracing",

View File

@ -32,6 +32,7 @@ pub struct Model {
pub account_id: i32, pub account_id: i32,
pub created_at: DateTime, pub created_at: DateTime,
pub updated_at: DateTime, pub updated_at: DateTime,
pub spot: Option<i32>,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
@ -42,6 +43,7 @@ pub enum Column {
AccountId, AccountId,
CreatedAt, CreatedAt,
UpdatedAt, UpdatedAt,
Spot,
} }
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
@ -72,6 +74,7 @@ impl ColumnTrait for Column {
Self::AccountId => ColumnType::Integer.def(), Self::AccountId => ColumnType::Integer.def(),
Self::CreatedAt => ColumnType::DateTime.def(), Self::CreatedAt => ColumnType::DateTime.def(),
Self::UpdatedAt => ColumnType::DateTime.def(), Self::UpdatedAt => ColumnType::DateTime.def(),
Self::Spot => ColumnType::Integer.def().null(),
} }
} }
} }

View File

@ -10,6 +10,8 @@ actix-web = "4.3.1"
askama = { version = "0.12.0", features = ["serde", "with-actix-web", "comrak", "mime"] } askama = { version = "0.12.0", features = ["serde", "with-actix-web", "comrak", "mime"] }
askama_actix = "0.14.0" askama_actix = "0.14.0"
oswilno-contract = { path = "../oswilno-contract" } oswilno-contract = { path = "../oswilno-contract" }
oswilno-session = { path = "../oswilno-session" }
oswilno-view = { path = "../oswilno-view" }
sea-orm = { version = "0.11.1", features = ["runtime-actix-rustls", "sqlx", "sqlx-postgres", "debug-print"] } sea-orm = { version = "0.11.1", features = ["runtime-actix-rustls", "sqlx", "sqlx-postgres", "debug-print"] }
serde = { version = "1.0.176", features = ["derive"] } serde = { version = "1.0.176", features = ["derive"] }
serde_json = "1.0.104" serde_json = "1.0.104"

View File

@ -5,25 +5,22 @@ use oswilno_contract::accounts;
use oswilno_contract::parking_space_rents; use oswilno_contract::parking_space_rents;
use oswilno_contract::parking_spaces; use oswilno_contract::parking_spaces;
use sea_orm::prelude::*; use sea_orm::prelude::*;
use sea_orm::ActiveValue::{NotSet, Set};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use oswilno_view::Layout;
use oswilno_session::UserSession;
pub fn mount(config: &mut ServiceConfig) { pub fn mount(config: &mut ServiceConfig) {
config.service( config.service(
scope("/parking_spaces") scope("/parking_spaces")
.service(all_parking_spaces) .service(all_parking_spaces)
.service(all_parial_parking_spaces), .service(all_parial_parking_spaces)
.service(create),
); );
} }
#[derive(Template)]
#[template(path = "../templates/parking-spaces/all.html")]
struct AllParkingSpace {
parking_space_rents: Vec<parking_space_rents::Model>,
parking_space_by_id: HashMap<i32, parking_spaces::Model>,
account_by_id: HashMap<i32, accounts::Model>,
}
#[derive(Template)] #[derive(Template)]
#[template(path = "../templates/parking-spaces/all-partial.html")] #[template(path = "../templates/parking-spaces/all-partial.html")]
struct AllPartialParkingSpace { struct AllPartialParkingSpace {
@ -33,10 +30,11 @@ struct AllPartialParkingSpace {
} }
#[get("/all")] #[get("/all")]
async fn all_parking_spaces(db: Data<sea_orm::DatabaseConnection>) -> AllParkingSpace { async fn all_parking_spaces(db: Data<sea_orm::DatabaseConnection>) -> Layout<AllPartialParkingSpace> {
let db = db.into_inner(); let db = db.into_inner();
load_parking_spaces(db).await let main = load_parking_spaces(db).await;
oswilno_view::Layout { main }
} }
#[get("/all-partial")] #[get("/all-partial")]
@ -44,20 +42,10 @@ async fn all_parial_parking_spaces(
db: Data<sea_orm::DatabaseConnection>, db: Data<sea_orm::DatabaseConnection>,
) -> AllPartialParkingSpace { ) -> AllPartialParkingSpace {
let db = db.into_inner(); let db = db.into_inner();
load_parking_spaces(db).await
let AllParkingSpace {
parking_space_rents,
parking_space_by_id,
account_by_id,
} = load_parking_spaces(db).await;
AllPartialParkingSpace {
parking_space_rents,
parking_space_by_id,
account_by_id,
}
} }
async fn load_parking_spaces(db: Arc<DatabaseConnection>) -> AllParkingSpace { async fn load_parking_spaces(db: Arc<DatabaseConnection>) -> AllPartialParkingSpace {
let rents = parking_space_rents::Entity::find().all(&*db).await.unwrap(); let rents = parking_space_rents::Entity::find().all(&*db).await.unwrap();
let (parking_space_by_id, account_ids) = { let (parking_space_by_id, account_ids) = {
let ids = rents let ids = rents
@ -94,13 +82,19 @@ async fn load_parking_spaces(db: Arc<DatabaseConnection>) -> AllParkingSpace {
}) })
}; };
AllParkingSpace { AllPartialParkingSpace {
account_by_id, account_by_id,
parking_space_rents: rents, parking_space_rents: rents,
parking_space_by_id, parking_space_by_id,
} }
} }
#[derive(Debug, Template)]
#[template(path = "../templates/parking-spaces/form-partial.html")]
struct ParkingSpaceFormPartial {
form: CreateParkingSpace,
}
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
struct CreateParkingSpace { struct CreateParkingSpace {
location: String, location: String,
@ -111,7 +105,28 @@ struct CreateParkingSpace {
async fn create( async fn create(
db: Data<sea_orm::DatabaseConnection>, db: Data<sea_orm::DatabaseConnection>,
p: Form<CreateParkingSpace>, p: Form<CreateParkingSpace>,
session: UserSession,
) -> HttpResponse { ) -> HttpResponse {
let p = p.into_inner(); use oswilno_contract::parking_spaces::*;
let CreateParkingSpace { location, spot } = p.into_inner();
let db = db.into_inner();
let model = ActiveModel {
id: NotSet,
location: Set(location.clone()),
spot: Set(spot.map(|n| n as i32)),
account_id: Set(session.claims.account_id()),
..Default::default()
};
if let Err(_e) = model.save(&*db).await {
return HttpResponse::BadRequest().body(
ParkingSpaceFormPartial {
form: CreateParkingSpace { location, spot },
}
.render()
.unwrap(),
);
}
unreachable!() unreachable!()
} }

View File

@ -11,7 +11,7 @@ use futures::stream::Stream;
use futures::SinkExt; use futures::SinkExt;
use garde::Validate; use garde::Validate;
use jsonwebtoken::*; use jsonwebtoken::*;
use oswilno_view::{Errors, Lang, TranslationStorage}; use oswilno_view::{Errors, Lang, Layout, TranslationStorage};
use ring::rand::SystemRandom; use ring::rand::SystemRandom;
use ring::signature::{Ed25519KeyPair, KeyPair}; use ring::signature::{Ed25519KeyPair, KeyPair};
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
@ -51,6 +51,17 @@ pub struct Claims {
jwt_id: uuid::Uuid, jwt_id: uuid::Uuid,
} }
impl Claims {
pub fn account_id(&self) -> i32 {
self.subject
.split_once('-')
.filter(|(desc, _id)| *desc == "account")
.map(|(_d, id)| id)
.and_then(|id| id.parse().ok())
.unwrap_or_default()
}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct EmptyResponse {} pub struct EmptyResponse {}
@ -141,15 +152,6 @@ impl SessionConfigurator {
} }
} }
#[derive(Template)]
#[template(path = "./sign-in/full.html")]
struct SignInTemplate {
form: SignInPayload,
lang: Lang,
t: Arc<TranslationStorage>,
errors: Errors,
}
#[derive(Template)] #[derive(Template)]
#[template(path = "./sign-in/partial.html")] #[template(path = "./sign-in/partial.html")]
struct SignInPartialTemplate { struct SignInPartialTemplate {
@ -166,12 +168,14 @@ pub struct SignInPayload {
} }
#[get("/login")] #[get("/login")]
async fn login_view(t: Data<TranslationStorage>) -> SignInTemplate { async fn login_view(t: Data<TranslationStorage>) -> Layout<SignInPartialTemplate> {
SignInTemplate { oswilno_view::Layout {
form: SignInPayload::default(), main: SignInPartialTemplate {
lang: Lang::Pl, form: SignInPayload::default(),
t: t.into_inner(), lang: Lang::Pl,
errors: Errors::default(), t: t.into_inner(),
errors: Errors::default(),
},
} }
} }
#[get("/p/login")] #[get("/p/login")]
@ -336,27 +340,20 @@ struct AccountInfo {
password: String, password: String,
} }
#[derive(askama_actix::Template)]
#[template(path = "./register/full.html")]
struct RegisterTemplate {
form: AccountInfo,
t: Arc<TranslationStorage>,
lang: Lang,
errors: oswilno_view::Errors,
}
#[get("/register")] #[get("/register")]
async fn register_view(t: Data<TranslationStorage>) -> RegisterTemplate { async fn register_view(t: Data<TranslationStorage>) -> Layout<RegisterPartialTemplate> {
RegisterTemplate { Layout {
form: AccountInfo::default(), main: RegisterPartialTemplate {
t: t.into_inner(), form: AccountInfo::default(),
lang: Lang::Pl, t: t.into_inner(),
errors: oswilno_view::Errors::default(), lang: Lang::Pl,
errors: oswilno_view::Errors::default(),
},
} }
} }
#[get("/p/register")] #[get("/p/register")]
async fn register_partial_view(t: Data<TranslationStorage>) -> RegisterTemplate { async fn register_partial_view(t: Data<TranslationStorage>) -> RegisterPartialTemplate {
RegisterTemplate { RegisterPartialTemplate {
form: AccountInfo::default(), form: AccountInfo::default(),
t: t.into_inner(), t: t.into_inner(),
lang: Lang::Pl, lang: Lang::Pl,

View File

@ -6,6 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
actix-web = "4.3.1" actix-web = "4.3.1"
askama = { version = "0.12.0", features = ["serde", "with-actix-web", "comrak", "mime"] } askama = { version = "0.12.0", features = ["serde", "with-actix-web", "comrak", "mime"] }
askama_actix = { version = "0.14.0" }
futures-core = "0.3.28" futures-core = "0.3.28"
garde = { version = "0.14.0", features = ["derive"] } garde = { version = "0.14.0", features = ["derive"] }
tracing = "0.1.37" tracing = "0.1.37"

View File

@ -6,6 +6,12 @@ pub use lang::*;
pub mod filters; pub mod filters;
pub mod lang; pub mod lang;
#[derive(Debug, askama_actix::Template)]
#[template(path = "../templates/base.html")]
pub struct Layout<BodyTemplate: askama::DynTemplate + std::fmt::Display> {
pub main: BodyTemplate,
}
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct Errors { pub struct Errors {
errors: Vec<String>, errors: Vec<String>,

View File

@ -11,9 +11,6 @@
</head> </head>
<body> <body>
<base url="/" /> <base url="/" />
<main> <main>{{ main }}</main>
{% block body %}
{% endblock %}
</main>
</body> </body>
</html> </html>