Implemented public form appearance settings.

This commit is contained in:
2024-02-22 21:54:00 +01:00
parent 653249287d
commit 2119c2e56b
15 changed files with 469 additions and 4 deletions
+156
View File
@@ -0,0 +1,156 @@
use cfg_if::cfg_if;
use leptos::*;
use validator::Validate;
use crate::backend::data::{ApiResponse, Appearance};
use crate::components::data_form::ForValidation;
cfg_if! { if #[cfg(feature = "ssr")] {
use actix_web::{post, Responder};
use actix_multipart::Multipart;
use actix_session::Session;
use actix_web::web::Redirect;
use std::fs::File;
use std::io::{Write, Read};
use futures_util::{StreamExt, TryStreamExt};
use crate::backend::data::User;
use crate::error::AppError;
use sqlx::{query, query_as, PgPool};
use crate::backend::get_pool;
use actix_web::web::Data;
use crate::backend::AppData;
use regex::Regex;
pub async fn check_appearance(pool: &PgPool) -> Result<(), AppError> {
let count: (i64,) = query_as("SELECT COUNT(id) FROM appearance")
.fetch_one(pool)
.await?;
if count.0 == 0 {
query("INSERT INTO appearance(title) VALUES('Rezervovator')")
.execute(pool)
.await?;
}
Ok(())
}
async fn set_banner_name(file_name: &str, pool: &PgPool) -> Result<(), AppError> {
query("UPDATE appearance SET banner = $1")
.bind(file_name)
.execute(pool)
.await?;
Ok(())
}
async fn modify_style(file_name: &str) -> Result<(), AppError> {
let mut css_file = File::open("target/site/banner.css")?;
let mut css_str= String::new();
css_file.read_to_string(&mut css_str)?;
if css_str.contains("/*bg-img*/") {
css_str = css_str.replace("/*bg-img*/", &format!("background-image: url('{}');", file_name));
} else {
let re = Regex::new(r#"background-image: url\('[aA-zZ._0-9\-]+'\)"#).unwrap();
css_str = re.replace(&css_str, &format!("background-image: url('{}')", file_name)).to_string();
}
let mut css_file = File::create("target/site/banner.css")?;
css_file.write_all(css_str.as_bytes())?;
Ok(())
}
#[post("/upload")]
pub async fn upload(mut data: Multipart, session: Session, app_data: Data<AppData>) -> impl Responder {
let user = session.get::<User>("user").unwrap_or(None);
if user.is_none() {
return Redirect::to("/login").see_other();
}
if let Some(u) = user {
if !u.admin {
return Redirect::to("/admin/appearance").see_other();
}
}
if let Ok(Some(mut field)) = data.try_next().await {
let content_disp = field.content_disposition().clone();
let file_name = content_disp.get_filename().unwrap();
if file_name.is_empty() {
return Redirect::to("/admin/appearance").see_other();
}
let mut file = File::create(format!("target/site/{}", file_name)).unwrap();
let _name = field.name();
while let Some(chunk) = field.next().await {
let c = chunk.unwrap();
let _ = file.write_all(&c);
}
let _ = set_banner_name(file_name, &app_data.db_pool).await;
let _ = modify_style(file_name).await;
}
Redirect::to("/admin/appearance").see_other()
}
}}
#[server]
pub async fn get_appearance() -> Result<Appearance, ServerFnError> {
let pool = get_pool().await?;
let appearance = query_as::<_, Appearance>("SELECT * FROM appearance")
.fetch_one(&pool)
.await?;
Ok(appearance)
}
#[server]
pub async fn update_appearance(appearance: Appearance) -> Result<ApiResponse<()>, ServerFnError> {
use crate::perm_check;
perm_check!(is_admin);
let pool = get_pool().await?;
let id = appearance.id();
query("UPDATE appearance SET title = $1, text = $2 WHERE id = $3")
.bind(appearance.title)
.bind(appearance.text)
.bind(id)
.execute(&pool)
.await?;
Ok(ApiResponse::Data(()))
}
impl ForValidation for UpdateAppearance {
fn entity(&self) -> &dyn Validate {
&self.appearance
}
}
#[server]
pub async fn delete_banner() -> Result<ApiResponse<()>, ServerFnError> {
use std::fs;
use crate::perm_check;
perm_check!(is_admin);
let appearance = get_appearance().await?;
let pool = get_pool().await?;
query("UPDATE appearance SET banner = $1 WHERE id = $2")
.bind(None::<String>)
.bind(appearance.id())
.execute(&pool)
.await?;
if let Some(f) = appearance.banner {
fs::remove_file(format!("target/site/{}", f))?;
}
Ok(ApiResponse::Data(()))
}
+15
View File
@@ -622,3 +622,18 @@ pub struct ChartData {
pub count: i64,
pub period: f64
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct Appearance {
id: i32,
pub banner: Option<String>,
pub text: Option<String>,
pub title: Option<String>
}
impl Appearance {
pub fn id(&self) -> i32 {
self.id
}
}
+1
View File
@@ -8,6 +8,7 @@ pub mod property;
pub mod reservation;
pub mod customer;
pub mod mail;
pub mod appearance;
#[macro_export]
macro_rules! perm_check {