Insert defaul with 1 query
This commit is contained in:
parent
f27ed3e90e
commit
4799f92961
1
argonfand
Submodule
1
argonfand
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ece0840d56893410780b77934e85fba53335e071
|
@ -9,8 +9,8 @@ use oswilno_contract::sea_orm_active_enums::ParkingSpaceState;
|
|||||||
use oswilno_contract::{accounts, parking_space_locations};
|
use oswilno_contract::{accounts, parking_space_locations};
|
||||||
use oswilno_session::{Authenticated, MaybeAuthenticated};
|
use oswilno_session::{Authenticated, MaybeAuthenticated};
|
||||||
use oswilno_view::{
|
use oswilno_view::{
|
||||||
filters, is_partial, Blank, Errors, Lang, Layout, Main, MainOpts, SearchOpts, SessionOpts,
|
filters, is_partial, Blank, Errors, HelperContext, Lang, Layout, Main, MainOpts, SearchOpts,
|
||||||
TranslationStorage,
|
SessionOpts, TranslationStorage,
|
||||||
};
|
};
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use sea_orm::ActiveValue::{NotSet, Set};
|
use sea_orm::ActiveValue::{NotSet, Set};
|
||||||
@ -67,6 +67,7 @@ struct AllPartialParkingSpace {
|
|||||||
location_by_id: BTreeMap<i32, Rc<parking_space_locations::Model>>,
|
location_by_id: BTreeMap<i32, Rc<parking_space_locations::Model>>,
|
||||||
session: Option<SessionOpts>,
|
session: Option<SessionOpts>,
|
||||||
account_id: Option<i32>,
|
account_id: Option<i32>,
|
||||||
|
hcx: HelperContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[autometrics]
|
#[autometrics]
|
||||||
@ -75,6 +76,7 @@ async fn all_parking_spaces(
|
|||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
db: Data<sea_orm::DatabaseConnection>,
|
db: Data<sea_orm::DatabaseConnection>,
|
||||||
session: MaybeAuthenticated,
|
session: MaybeAuthenticated,
|
||||||
|
hcx: HelperContext,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let db = db.into_inner();
|
let db = db.into_inner();
|
||||||
let session = session.into_option();
|
let session = session.into_option();
|
||||||
@ -83,7 +85,7 @@ async fn all_parking_spaces(
|
|||||||
|
|
||||||
tracing::debug!("session {session:?}");
|
tracing::debug!("session {session:?}");
|
||||||
|
|
||||||
let mut parking_spaces = load_parking_spaces(db, account_id).await;
|
let mut parking_spaces = load_parking_spaces(db, account_id, htx).await;
|
||||||
parking_spaces.session = session.clone();
|
parking_spaces.session = session.clone();
|
||||||
let main = Main {
|
let main = Main {
|
||||||
body: parking_spaces,
|
body: parking_spaces,
|
||||||
@ -117,6 +119,7 @@ async fn search_parking_spaces() -> HttpResponse {
|
|||||||
async fn load_parking_spaces(
|
async fn load_parking_spaces(
|
||||||
db: Arc<DatabaseConnection>,
|
db: Arc<DatabaseConnection>,
|
||||||
account_id: Option<i32>,
|
account_id: Option<i32>,
|
||||||
|
hcx: HelperContext,
|
||||||
) -> AllPartialParkingSpace {
|
) -> AllPartialParkingSpace {
|
||||||
let rents = parking_space_rents::Entity::find().all(&*db).await.unwrap();
|
let rents = parking_space_rents::Entity::find().all(&*db).await.unwrap();
|
||||||
let ids = rents
|
let ids = rents
|
||||||
@ -180,6 +183,7 @@ async fn load_parking_spaces(
|
|||||||
locations,
|
locations,
|
||||||
location_by_id,
|
location_by_id,
|
||||||
session: None,
|
session: None,
|
||||||
|
hcx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,8 +203,7 @@ async fn load_locations(db: Arc<DatabaseConnection>) -> Vec<parking_space_locati
|
|||||||
async fn form_show(
|
async fn form_show(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
session: Authenticated,
|
session: Authenticated,
|
||||||
t: Data<TranslationStorage>,
|
hcx: HelperContext,
|
||||||
lang: Lang,
|
|
||||||
db: Data<DatabaseConnection>,
|
db: Data<DatabaseConnection>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let db = db.into_inner();
|
let db = db.into_inner();
|
||||||
@ -208,9 +211,8 @@ async fn form_show(
|
|||||||
let body = ParkingSpaceFormPartial {
|
let body = ParkingSpaceFormPartial {
|
||||||
form: Default::default(),
|
form: Default::default(),
|
||||||
locations: load_locations(db.clone()).await,
|
locations: load_locations(db.clone()).await,
|
||||||
lang,
|
|
||||||
errors: Default::default(),
|
errors: Default::default(),
|
||||||
t: t.into_inner(),
|
hcx,
|
||||||
};
|
};
|
||||||
let main = Main {
|
let main = Main {
|
||||||
body,
|
body,
|
||||||
@ -235,10 +237,9 @@ async fn form_show(
|
|||||||
#[template(path = "../templates/parking-spaces/form-partial.html")]
|
#[template(path = "../templates/parking-spaces/form-partial.html")]
|
||||||
struct ParkingSpaceFormPartial {
|
struct ParkingSpaceFormPartial {
|
||||||
form: CreateParkingSpace,
|
form: CreateParkingSpace,
|
||||||
lang: Lang,
|
|
||||||
errors: Errors,
|
errors: Errors,
|
||||||
t: Arc<TranslationStorage>,
|
|
||||||
locations: Vec<parking_space_locations::Model>,
|
locations: Vec<parking_space_locations::Model>,
|
||||||
|
hcx: HelperContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, serde::Deserialize)]
|
#[derive(Debug, Default, serde::Deserialize)]
|
||||||
@ -254,8 +255,7 @@ async fn create(
|
|||||||
db: Data<sea_orm::DatabaseConnection>,
|
db: Data<sea_orm::DatabaseConnection>,
|
||||||
p: Form<CreateParkingSpace>,
|
p: Form<CreateParkingSpace>,
|
||||||
session: Authenticated,
|
session: Authenticated,
|
||||||
t: Data<TranslationStorage>,
|
hcx: HelperContext,
|
||||||
lang: Lang,
|
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
use oswilno_contract::parking_spaces::*;
|
use oswilno_contract::parking_spaces::*;
|
||||||
let CreateParkingSpace {
|
let CreateParkingSpace {
|
||||||
@ -280,8 +280,7 @@ async fn create(
|
|||||||
spot,
|
spot,
|
||||||
id: None,
|
id: None,
|
||||||
},
|
},
|
||||||
t: t.into_inner(),
|
hcx,
|
||||||
lang,
|
|
||||||
errors: Default::default(),
|
errors: Default::default(),
|
||||||
locations: load_locations(db.clone()).await,
|
locations: load_locations(db.clone()).await,
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{% match parking_space.state %}
|
{% match parking_space.state %}
|
||||||
{% when ParkingSpaceState::Pending %}
|
{% when ParkingSpaceState::Pending %}
|
||||||
<div class="text-center p-1 text-sm text-yellow-400 bg-transparent rounded-sm hover:bg-yellow-200 hover:text-yellow-900 dark:hover:bg-yellow-800 dark:hover:text-yellow-300">
|
<div class="text-center p-1 text-sm text-yellow-400 bg-transparent rounded-sm hover:bg-yellow-200 hover:text-yellow-900 dark:hover:bg-yellow-800 dark:hover:text-yellow-300">
|
||||||
Pending
|
{{"Pending"|t(lang,t)}}
|
||||||
</div>
|
</div>
|
||||||
{% when ParkingSpaceState::Verified %}
|
{% when ParkingSpaceState::Verified %}
|
||||||
<div class="text-center p-1 text-sm text-blue-400 bg-transparent rounded-sm hover:bg-blue-200 hover:text-blue-900 dark:hover:bg-blue-800 dark:hover:text-blue-300">
|
<div class="text-center p-1 text-sm text-blue-400 bg-transparent rounded-sm hover:bg-blue-200 hover:text-blue-900 dark:hover:bg-blue-800 dark:hover:text-blue-300">
|
||||||
Accepted
|
{{"Accepted"|t(lang,t)}}
|
||||||
</div>
|
</div>
|
||||||
{% when ParkingSpaceState::Banned %}
|
{% when ParkingSpaceState::Banned %}
|
||||||
<div class="text-center p-1 text-sm text-red-400 bg-transparent rounded-sm hover:bg-red-200 hover:text-red-900 dark:hover:bg-red-800 dark:hover:text-red-300">
|
<div class="text-center p-1 text-sm text-red-400 bg-transparent rounded-sm hover:bg-red-200 hover:text-red-900 dark:hover:bg-red-800 dark:hover:text-red-300">
|
||||||
Rejected
|
{{"Rejected"|t(lang,t)}}
|
||||||
</div>
|
</div>
|
||||||
{% endmatch %}
|
{% endmatch %}
|
||||||
|
@ -7,7 +7,9 @@ use actix_web::{get, post, HttpRequest, HttpResponse};
|
|||||||
use askama_actix::Template;
|
use askama_actix::Template;
|
||||||
use autometrics::autometrics;
|
use autometrics::autometrics;
|
||||||
use garde::Validate;
|
use garde::Validate;
|
||||||
use oswilno_view::{Blank, Errors, Lang, Layout, Main, MainOpts, TranslationStorage};
|
use oswilno_view::{
|
||||||
|
Blank, Errors, HelperContext, Lang, Layout, Main, MainOpts, TranslationStorage,
|
||||||
|
};
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -148,8 +150,7 @@ impl SessionConfigurator {
|
|||||||
#[template(path = "./sign-in/partial.html")]
|
#[template(path = "./sign-in/partial.html")]
|
||||||
struct SignInPartialTemplate {
|
struct SignInPartialTemplate {
|
||||||
form: SignInPayload,
|
form: SignInPayload,
|
||||||
lang: Lang,
|
hcx: HelperContext,
|
||||||
t: Arc<TranslationStorage>,
|
|
||||||
errors: Errors,
|
errors: Errors,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,15 +161,14 @@ pub struct SignInPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/login")]
|
#[get("/login")]
|
||||||
async fn login_view(req: HttpRequest, t: Data<TranslationStorage>) -> HttpResponse {
|
async fn login_view(req: HttpRequest, hcx: HelperContext) -> HttpResponse {
|
||||||
HttpResponse::Ok().body(
|
HttpResponse::Ok().body(
|
||||||
if oswilno_view::is_partial(&req) {
|
if oswilno_view::is_partial(&req) {
|
||||||
Main {
|
Main {
|
||||||
body: SignInPartialTemplate {
|
body: SignInPartialTemplate {
|
||||||
form: SignInPayload::default(),
|
form: SignInPayload::default(),
|
||||||
lang: Lang::Pl,
|
|
||||||
t: t.into_inner(),
|
|
||||||
errors: Errors::default(),
|
errors: Errors::default(),
|
||||||
|
hcx,
|
||||||
},
|
},
|
||||||
opts: MainOpts {
|
opts: MainOpts {
|
||||||
show: true,
|
show: true,
|
||||||
@ -183,9 +183,8 @@ async fn login_view(req: HttpRequest, t: Data<TranslationStorage>) -> HttpRespon
|
|||||||
main: Main {
|
main: Main {
|
||||||
body: SignInPartialTemplate {
|
body: SignInPartialTemplate {
|
||||||
form: SignInPayload::default(),
|
form: SignInPayload::default(),
|
||||||
lang: Lang::Pl,
|
|
||||||
t: t.into_inner(),
|
|
||||||
errors: Errors::default(),
|
errors: Errors::default(),
|
||||||
|
hcx,
|
||||||
},
|
},
|
||||||
opts: MainOpts {
|
opts: MainOpts {
|
||||||
show: true,
|
show: true,
|
||||||
@ -208,10 +207,8 @@ async fn login(
|
|||||||
db: Data<DatabaseConnection>,
|
db: Data<DatabaseConnection>,
|
||||||
redis: Data<SessionStorage>,
|
redis: Data<SessionStorage>,
|
||||||
payload: Form<SignInPayload>,
|
payload: Form<SignInPayload>,
|
||||||
t: Data<oswilno_view::TranslationStorage>,
|
hcx: HelperContext,
|
||||||
lang: Lang,
|
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let t = t.into_inner();
|
|
||||||
let mut errors = Errors::default();
|
let mut errors = Errors::default();
|
||||||
let form = payload.into_inner();
|
let form = payload.into_inner();
|
||||||
match login_inner(
|
match login_inner(
|
||||||
@ -226,14 +223,9 @@ async fn login(
|
|||||||
{
|
{
|
||||||
Some(res) => Ok(res),
|
Some(res) => Ok(res),
|
||||||
None => Ok(HttpResponse::Ok().body(
|
None => Ok(HttpResponse::Ok().body(
|
||||||
(SignInPartialTemplate {
|
(SignInPartialTemplate { form, errors, hcx })
|
||||||
form,
|
.render()
|
||||||
lang,
|
.unwrap(),
|
||||||
t,
|
|
||||||
errors,
|
|
||||||
})
|
|
||||||
.render()
|
|
||||||
.unwrap(),
|
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,6 +344,7 @@ async fn find_account(
|
|||||||
async fn refresh_token(
|
async fn refresh_token(
|
||||||
refresh_token: actix_jwt_session::Authenticated<RefreshToken>,
|
refresh_token: actix_jwt_session::Authenticated<RefreshToken>,
|
||||||
storage: Data<SessionStorage>,
|
storage: Data<SessionStorage>,
|
||||||
|
_hcx: HelperContext,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let s = storage.into_inner();
|
let s = storage.into_inner();
|
||||||
let pair = match s.refresh::<Claims>(refresh_token.access_jti()).await {
|
let pair = match s.refresh::<Claims>(refresh_token.access_jti()).await {
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
use crate::{Lang, TranslationStorage};
|
use crate::HelperContext;
|
||||||
use askama::Result;
|
use askama::Result;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(htx))]
|
||||||
pub fn t<T: std::fmt::Display + std::fmt::Debug>(
|
pub fn t<T: std::fmt::Display + std::fmt::Debug>(s: T, htx: &HelperContext) -> Result<String> {
|
||||||
s: T,
|
|
||||||
lang: &Lang,
|
|
||||||
t: &Arc<TranslationStorage>,
|
|
||||||
) -> Result<String> {
|
|
||||||
// tracing::debug!("translating {s:?} to lang {lang:?} with {t:?}");
|
// tracing::debug!("translating {s:?} to lang {lang:?} with {t:?}");
|
||||||
Ok(t.to_lang(*lang, &s.to_string()))
|
Ok(htx.t.to_lang(htx.lang, &s.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_if<T: std::fmt::Display + PartialEq + Copy>(n: &T, skip: T) -> Result<String> {
|
pub fn skip_if<T: std::fmt::Display + PartialEq + Copy>(n: &T, skip: T) -> Result<String> {
|
||||||
|
57
crates/oswilno-view/src/helper_context.rs
Normal file
57
crates/oswilno-view/src/helper_context.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use crate::Lang;
|
||||||
|
use crate::{ExtractLangFuture, TranslationStorage};
|
||||||
|
use actix_web::error::Error;
|
||||||
|
use actix_web::web::Data;
|
||||||
|
use actix_web::HttpRequest;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct HelperContext {
|
||||||
|
pub t: Data<TranslationStorage>,
|
||||||
|
pub lang: Lang,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl actix_web::FromRequest for HelperContext {
|
||||||
|
type Error = actix_web::error::Error;
|
||||||
|
type Future = ExtractFuture;
|
||||||
|
|
||||||
|
fn from_request(
|
||||||
|
req: &actix_web::HttpRequest,
|
||||||
|
_payload: &mut actix_web::dev::Payload,
|
||||||
|
) -> Self::Future {
|
||||||
|
ExtractFuture {
|
||||||
|
req: Some(req.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ExtractFuture {
|
||||||
|
req: Option<HttpRequest>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for ExtractFuture {
|
||||||
|
type Output = Result<HelperContext, Error>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let this = self.get_mut();
|
||||||
|
let lang = Pin::new(&mut ExtractLangFuture {
|
||||||
|
req: this.req.clone(),
|
||||||
|
})
|
||||||
|
.poll(cx);
|
||||||
|
let lang = match lang {
|
||||||
|
Poll::Ready(Ok(lang)) => lang,
|
||||||
|
_ => panic!("{lang:?}"),
|
||||||
|
};
|
||||||
|
let t = this
|
||||||
|
.req
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.app_data::<Data<TranslationStorage>>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
Poll::Ready(Ok(HelperContext { t, lang }))
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ impl FromStr for Lang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExtractLangFuture {
|
pub struct ExtractLangFuture {
|
||||||
req: Option<HttpRequest>,
|
pub req: Option<HttpRequest>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Future for ExtractLangFuture {
|
impl Future for ExtractLangFuture {
|
||||||
|
@ -4,9 +4,12 @@ use std::sync::{Arc, RwLock};
|
|||||||
use actix_web::http::header::ContentType;
|
use actix_web::http::header::ContentType;
|
||||||
use actix_web::web::ServiceConfig;
|
use actix_web::web::ServiceConfig;
|
||||||
use actix_web::{get, HttpRequest, HttpResponse};
|
use actix_web::{get, HttpRequest, HttpResponse};
|
||||||
|
|
||||||
|
pub use helper_context::*;
|
||||||
pub use lang::*;
|
pub use lang::*;
|
||||||
|
|
||||||
pub mod filters;
|
pub mod filters;
|
||||||
|
pub mod helper_context;
|
||||||
pub mod lang;
|
pub mod lang;
|
||||||
|
|
||||||
pub fn mount(config: &mut ServiceConfig) {
|
pub fn mount(config: &mut ServiceConfig) {
|
||||||
|
Loading…
Reference in New Issue
Block a user