Display locations

This commit is contained in:
Adrian Woźniak 2023-08-22 16:25:40 +02:00
parent 5e806454f9
commit 4edccc7661
6 changed files with 132 additions and 6 deletions

View File

@ -78,7 +78,7 @@
//!
//! #[actix_web::post("/access-storage")]
//! async fn storage_access(
//! session_store: Data<SessionStorage<AppClaims>>,
//! session_store: Data<SessionStorage<AppClaims>>,
//! p: actix_web::web::Json<SessionData>,
//! ) -> HttpResponse {
//! let p = p.into_inner();

View File

@ -76,6 +76,18 @@ impl MigrationTrait for Migration {
)
.await?;
m.create_index(
IndexCreateStatement::default()
.unique()
.name("uniq-location")
.table(ParkingSpaceLocation::ParkingSpaceLocations)
.col(ParkingSpaceLocation::Name)
.col(ParkingSpaceLocation::Number)
.col(ParkingSpaceLocation::Stage)
.to_owned(),
)
.await?;
Ok(())
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

View File

@ -3,16 +3,23 @@ use actix_web::web::{scope, Data, Form, ServiceConfig};
use actix_web::{get, post, HttpRequest, HttpResponse};
use askama_actix::Template;
use autometrics::autometrics;
use oswilno_contract::accounts;
use oswilno_contract::parking_space_rents;
use oswilno_contract::parking_spaces;
use oswilno_contract::{accounts, parking_space_locations};
use oswilno_session::{Authenticated, MaybeAuthenticated};
use oswilno_view::{is_partial, Blank, Layout, Main, MainOpts, SearchOpts, SessionOpts};
use oswilno_view::{
filters, is_partial, Blank, Errors, Lang, Layout, Main, MainOpts, SearchOpts, SessionOpts,
TranslationStorage,
};
use sea_orm::prelude::*;
use sea_orm::ActiveValue::{NotSet, Set};
use std::collections::HashMap;
use std::sync::Arc;
pub async fn init(db: Arc<sea_orm::DatabaseConnection>) {
ensure_locations(db).await;
}
pub fn mount(config: &mut ServiceConfig) {
config.service(root).service(
scope("/parking-spaces")
@ -36,6 +43,7 @@ struct AllPartialParkingSpace {
parking_space_rents: Vec<parking_space_rents::Model>,
parking_space_by_id: HashMap<i32, parking_spaces::Model>,
account_by_id: HashMap<i32, accounts::Model>,
locations: Vec<parking_space_locations::Model>,
session: Option<SessionOpts>,
}
@ -114,19 +122,45 @@ async fn load_parking_spaces(db: Arc<DatabaseConnection>) -> AllPartialParkingSp
})
};
let locations = load_locations(db).await;
AllPartialParkingSpace {
account_by_id,
parking_space_rents: rents,
parking_space_by_id,
locations,
session: None,
}
}
async fn load_locations(db: Arc<DatabaseConnection>) -> Vec<parking_space_locations::Model> {
use oswilno_contract::parking_space_locations::*;
let mut v = Entity::find().all(&*db).await.unwrap();
v.sort_by(|l, r| {
l.name
.cmp(&r.name)
.cmp(&l.number.cmp(&r.number))
.cmp(&l.stage.cmp(&r.stage))
});
v
}
#[get("/form")]
async fn form_show(req: HttpRequest, session: Authenticated) -> HttpResponse {
async fn form_show(
req: HttpRequest,
session: Authenticated,
t: Data<TranslationStorage>,
lang: Lang,
db: Data<DatabaseConnection>,
) -> HttpResponse {
let db = db.into_inner();
let session = session.into();
let body = ParkingSpaceFormPartial {
..Default::default()
form: Default::default(),
locations: load_locations(db.clone()).await,
lang,
errors: Default::default(),
t: t.into_inner(),
};
let main = Main {
body,
@ -147,10 +181,14 @@ async fn form_show(req: HttpRequest, session: Authenticated) -> HttpResponse {
.body(html.unwrap())
}
#[derive(Debug, Default, Template)]
#[derive(Debug, Template)]
#[template(path = "../templates/parking-spaces/form-partial.html")]
struct ParkingSpaceFormPartial {
form: CreateParkingSpace,
lang: Lang,
errors: Errors,
t: Arc<TranslationStorage>,
locations: Vec<parking_space_locations::Model>,
}
#[derive(Debug, Default, serde::Deserialize)]
@ -165,6 +203,8 @@ async fn create(
db: Data<sea_orm::DatabaseConnection>,
p: Form<CreateParkingSpace>,
session: Authenticated,
t: Data<TranslationStorage>,
lang: Lang,
) -> HttpResponse {
use oswilno_contract::parking_spaces::*;
let CreateParkingSpace { location_id, spot } = p.into_inner();
@ -181,6 +221,10 @@ async fn create(
return HttpResponse::BadRequest().body(
ParkingSpaceFormPartial {
form: CreateParkingSpace { location_id, spot },
t: t.into_inner(),
lang,
errors: Default::default(),
locations: load_locations(db.clone()).await,
}
.render()
.unwrap(),
@ -189,3 +233,39 @@ async fn create(
unreachable!()
}
async fn ensure_locations(db: Arc<sea_orm::DatabaseConnection>) {
for (name, number, stage) in [
("Wilno", 1, "1a"),
("Wilno", 1, "1b"),
("Wilno", 1, "2AF1"),
("Wilno", 1, "2AF2"),
("Wilno", 1, "3"),
("Wilno", 1, "4"),
("Wilno", 2, "1"),
("Wilno", 2, "2"),
("Wilno", 2, "3"),
("Wilno", 3, "1"),
("Wilno", 3, "2"),
("Wilno", 3, "3"),
("Wilno", 3, "4"),
("Wilno", 3, "5"),
// 4
("Wilno", 4, "1"),
("Wilno", 4, "2"),
("Wilno", 4, "3"),
// 5
("Wilno", 5, "1"),
("Wilno", 5, "2"),
] {
let _model = oswilno_contract::parking_space_locations::ActiveModel {
name: Set(name.to_string()),
number: Set(number),
stage: Set(stage.to_string()),
..Default::default()
}
.save(&*db)
.await
.ok();
}
}

View File

@ -0,0 +1,31 @@
<section id="main-view" class="min-h-screen flex items-center justify-center">
<section class="max-w-md w-full p-6 bg-white rounded-lg shadow-lg">
{% for error in errors.global() %}
<oswilno-error>{{error|t(lang,t)}}</oswilno-error>
{% endfor %}
<form hx-post="/login" hx-target="#main-view">
<div class="mb-4">
<label for="location_id" class="block mb-2 text-sm text-gray-600">location_id</label>
<select id="location_id" name="location_id" value="{{ form.location_id }}" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-cyan-500">
{% for loc in locations %}
<option value="{{loc.id}}">
{{ loc.name }}
{{ loc.number }}
{{ loc.stage }}
</option>
{% endfor %}
</select>
{% for error in errors.field("login") %}
<oswilno-error>{{error|t(lang,t)}}</oswilno-error>
{% endfor %}
</div>
<div class="mb-6">
<input
type="submit"
value="{{"Submit"|t(lang,t)}}"
class="w-32 bg-cyan-600 text-white py-2 rounded-lg mx-auto block focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-cyan-500 mb-2"
/>
</div>
</form>
</section>
</section>

View File

@ -1,3 +1,4 @@
use std::sync::Arc;
use std::time::Duration;
use actix_web::web::Data;
@ -48,6 +49,8 @@ async fn main() -> std::io::Result<()> {
let session_config = oswilno_session::SessionConfigurator::new(redis.clone());
session_config.translations(&mut l10n);
oswilno_parking_space::init(Arc::new(conn.clone())).await;
HttpServer::new(move || {
let session_config = session_config.clone();
let session_factory = session_config.factory();