Helpers
This commit is contained in:
parent
ce997cb7c8
commit
2f7e6358e8
@ -36,7 +36,7 @@
|
||||
<ow-nav>
|
||||
{% if page.is_public() %}
|
||||
<ow-path path="/" selected="{{ page.select_index() }}">Lokalne Usługi</ow-path>
|
||||
<ow-path path="/" selected="{{ page.select_marketplace() }}">Targ</ow-path>
|
||||
<ow-path path="/marketplace" selected="{{ page.select_marketplace() }}">Targ</ow-path>
|
||||
<ow-path path="/news" selected="{{ page.select_news() }}">Aktualności</ow-path>
|
||||
<ow-path path="/account" selected="{{ page.select_account() }}">Konto</ow-path>
|
||||
{% match account.as_ref() %}
|
||||
@ -44,8 +44,11 @@
|
||||
<ow-path path="/account/business-items" selected="{{ page.select_business_items() }}">Moje usługi</ow-path>
|
||||
{% when None %}
|
||||
{% endmatch %}
|
||||
{% else if page.is_admin() %}
|
||||
{% if h.is_admin(account) %}
|
||||
<ow-path path="/admin" selected="{{ page.select_admin_news() }}">Admin</ow-path>
|
||||
{% endif %}
|
||||
{% else if page.is_admin() %}
|
||||
<ow-path path="/">Home</ow-path>
|
||||
<ow-path path="/admin/news" selected="{{ page.select_admin_news() }}">News</ow-path>
|
||||
<ow-path path="/admin/businesses" selected="{{ page.select_admin_businesses() }}">Localne Usługi</ow-path>
|
||||
{% endif %}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{FromRow, Type};
|
||||
use uuid::Uuid;
|
||||
@ -29,8 +29,9 @@ pub enum Role {
|
||||
Admin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Type)]
|
||||
pub enum LocalBusinessState {
|
||||
#[default]
|
||||
Pending,
|
||||
Approved,
|
||||
Banned,
|
||||
@ -88,7 +89,7 @@ pub struct Token {
|
||||
pub role: Role,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
||||
#[derive(Debug, Default, Serialize, Deserialize, FromRow)]
|
||||
pub struct LocalBusiness {
|
||||
pub id: i32,
|
||||
pub owner_id: i32,
|
||||
@ -117,6 +118,19 @@ pub struct NewsArticle {
|
||||
pub created_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
impl Default for NewsArticle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
title: "".to_string(),
|
||||
body: "".to_string(),
|
||||
status: NewsStatus::Pending,
|
||||
published_at: None,
|
||||
created_at: Utc::now().naive_utc(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
||||
pub struct CreateNewsArticleInput {
|
||||
pub title: String,
|
||||
|
@ -2,8 +2,9 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::model::db;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub enum Page {
|
||||
#[default]
|
||||
LocalBusinesses,
|
||||
News,
|
||||
Account,
|
||||
|
@ -9,7 +9,9 @@ use crate::routes::{Identity, Result};
|
||||
pub mod admin;
|
||||
mod business_item;
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
use crate::view::Helper;
|
||||
|
||||
#[derive(Debug, Default, Template)]
|
||||
#[template(path = "business-items.html")]
|
||||
struct BusinessItemsTemplate {
|
||||
page: view::Page,
|
||||
@ -17,6 +19,7 @@ struct BusinessItemsTemplate {
|
||||
account: Option<db::Account>,
|
||||
items: Vec<db::LocalBusinessItem>,
|
||||
business: db::LocalBusiness,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@ -71,10 +74,10 @@ async fn handle_business_items_page(
|
||||
let items: Vec<db::LocalBusinessItem> = queries::account_items(t, account.id).await;
|
||||
let page = BusinessItemsTemplate {
|
||||
page: view::Page::BusinessItems,
|
||||
error: None,
|
||||
account: Some(account),
|
||||
items,
|
||||
business,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/html")
|
||||
|
@ -6,14 +6,14 @@ use sqlx::PgPool;
|
||||
use crate::model::view::{Page, SetStateBusinessInput};
|
||||
use crate::model::{db, view};
|
||||
use crate::routes::{Identity, JsonResult, Result};
|
||||
use crate::view::filters;
|
||||
use crate::view::{filters, Helper};
|
||||
use crate::{authorize, queries};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! require_admin {
|
||||
($t: expr, $id: expr) => {{
|
||||
let account = authorize!(&mut $t, $id);
|
||||
if account.account_type == crate::model::db::AccountType::Admin {
|
||||
if account.account_type != crate::model::db::AccountType::Admin {
|
||||
return Err(crate::routes::Error::Forbidden);
|
||||
}
|
||||
account
|
||||
@ -27,13 +27,14 @@ macro_rules! require_admin {
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
#[derive(Debug, Default, Template)]
|
||||
#[template(path = "admin/news.html")]
|
||||
struct AdminNewsTemplate {
|
||||
page: view::Page,
|
||||
error: Option<String>,
|
||||
account: Option<db::Account>,
|
||||
news: Vec<db::NewsArticle>,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[get("")]
|
||||
@ -60,22 +61,22 @@ async fn admin_news(db: Data<PgPool>, id: Identity) -> Result<HttpResponse> {
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
AdminNewsTemplate {
|
||||
page: Page::AdminNews,
|
||||
error: None,
|
||||
account: None,
|
||||
news,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
#[derive(Debug, Default, Template)]
|
||||
#[template(path = "admin/edit.html")]
|
||||
struct EditTemplate {
|
||||
page: view::Page,
|
||||
page: Page,
|
||||
error: Option<String>,
|
||||
account: Option<db::Account>,
|
||||
article: db::NewsArticle,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[get("/{id}")]
|
||||
@ -102,9 +103,8 @@ async fn edit_news_article(
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
EditTemplate {
|
||||
page: Page::AdminNews,
|
||||
error: None,
|
||||
account: None,
|
||||
article,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -139,8 +139,7 @@ async fn create_news_article(
|
||||
AdminNewsTemplate {
|
||||
page: Page::AdminCreateNews,
|
||||
error: Some("Failed".into()),
|
||||
account: None,
|
||||
news: vec![],
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -242,13 +241,14 @@ async fn news_article_upload(
|
||||
crate::routes::uploads::hande_upload(payload, Some(account.id), "news").await
|
||||
}
|
||||
|
||||
#[derive(Debug, Template)]
|
||||
#[derive(Debug, Default, Template)]
|
||||
#[template(path = "admin/businesses.html")]
|
||||
struct AdminBusinessesTemplate {
|
||||
page: view::Page,
|
||||
page: Page,
|
||||
error: Option<String>,
|
||||
account: Option<db::Account>,
|
||||
businesses: Vec<view::LocalBusiness>,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[get("")]
|
||||
@ -278,9 +278,8 @@ async fn admin_businesses(db: Data<PgPool>, id: Identity) -> Result<HttpResponse
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
AdminBusinessesTemplate {
|
||||
page: Page::AdminBusinesses,
|
||||
error: None,
|
||||
account: None,
|
||||
businesses,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
|
@ -11,26 +11,25 @@ use tracing::*;
|
||||
use crate::model::db;
|
||||
use crate::model::view::{self, Page};
|
||||
use crate::routes::{Identity, JsonResult, Result};
|
||||
use crate::view::filters;
|
||||
use crate::view::{filters, Helper};
|
||||
use crate::{not_xss, queries, routes, utils};
|
||||
|
||||
#[derive(Template)]
|
||||
#[derive(Default, Template)]
|
||||
#[template(path = "index.html")]
|
||||
pub struct IndexTemplate {
|
||||
services: Vec<view::LocalBusiness>,
|
||||
account: Option<db::Account>,
|
||||
error: Option<String>,
|
||||
page: Page,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn render_index() -> HttpResponse {
|
||||
HttpResponse::NotFound().content_type("text/html").body(
|
||||
IndexTemplate {
|
||||
services: vec![],
|
||||
account: None,
|
||||
error: None,
|
||||
page: Page::LocalBusinesses,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -69,8 +68,8 @@ pub async fn index(db: Data<PgPool>, id: Identity) -> Result<HttpResponse> {
|
||||
let body = IndexTemplate {
|
||||
services,
|
||||
account: record,
|
||||
error: None,
|
||||
page: Page::LocalBusinesses,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap();
|
||||
@ -80,12 +79,13 @@ pub async fn index(db: Data<PgPool>, id: Identity) -> Result<HttpResponse> {
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[derive(Default, Template)]
|
||||
#[template(path = "account.html")]
|
||||
struct AccountTemplate {
|
||||
account: Option<db::Account>,
|
||||
error: Option<String>,
|
||||
page: Page,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[get("/account")]
|
||||
@ -104,8 +104,8 @@ async fn account_page(id: Identity, db: Data<PgPool>) -> Result<HttpResponse> {
|
||||
Ok(HttpResponse::Ok().body(
|
||||
AccountTemplate {
|
||||
account,
|
||||
error: None,
|
||||
page: Page::Account,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -199,9 +199,9 @@ async fn register(
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Zapisanie hasła nie powiodło się".into()),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -234,9 +234,9 @@ RETURNING id, login, email, pass, facebook_id, account_type
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Problem z utworzeniem konta".into()),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -272,9 +272,9 @@ RETURNING id, owner_id, name, description, state
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Problem z utworzeniem konta".into()),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -308,11 +308,11 @@ RETURNING id, local_business_id, name, price, item_order, picture_url
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().content_type("text/html").body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some(
|
||||
"Problem z utworzeniem konta. Nie można zapisać zdjęcia.".into(),
|
||||
),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -325,11 +325,11 @@ RETURNING id, local_business_id, name, price, item_order, picture_url
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().content_type("text/html").body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some(
|
||||
"Problem z utworzeniem konta. Nie można zapisać zdjęcia.".into(),
|
||||
),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -350,9 +350,9 @@ RETURNING id, local_business_id, name, price, item_order, picture_url
|
||||
t.rollback().await.unwrap();
|
||||
return Ok(HttpResponse::BadRequest().content_type("text/html").body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Problem z utworzeniem konta".into()),
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -369,8 +369,8 @@ RETURNING id, local_business_id, name, price, item_order, picture_url
|
||||
.body(
|
||||
AccountTemplate {
|
||||
account: Some(account),
|
||||
error: None,
|
||||
page: Page::Register,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -385,10 +385,8 @@ async fn logout(id: Identity) -> HttpResponse {
|
||||
.append_header(("Location", "/"))
|
||||
.body(
|
||||
IndexTemplate {
|
||||
services: vec![],
|
||||
account: None,
|
||||
error: None,
|
||||
page: Page::LocalBusinesses,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -415,9 +413,9 @@ async fn login(form: web::Form<LoginForm>, db: Data<PgPool>, id: Identity) -> Re
|
||||
t.rollback().await.ok();
|
||||
return Ok(HttpResponse::Ok().body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Nie znaleziono konta".into()),
|
||||
page: Page::Login,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -430,9 +428,9 @@ async fn login(form: web::Form<LoginForm>, db: Data<PgPool>, id: Identity) -> Re
|
||||
t.rollback().await.ok();
|
||||
return Ok(HttpResponse::BadRequest().body(
|
||||
AccountTemplate {
|
||||
account: None,
|
||||
error: Some("Hasło i/lub adres e-mail są nieprawidłowe".into()),
|
||||
page: Page::Login,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -444,8 +442,9 @@ async fn login(form: web::Form<LoginForm>, db: Data<PgPool>, id: Identity) -> Re
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
AccountTemplate {
|
||||
account: Some(record),
|
||||
error: None,
|
||||
|
||||
page: Page::Login,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
@ -468,13 +467,14 @@ async fn upload(
|
||||
routes::uploads::hande_upload(payload, id, "accounts").await
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[derive(Default, Template)]
|
||||
#[template(path = "news.html")]
|
||||
pub struct NewsTemplate {
|
||||
account: Option<db::Account>,
|
||||
error: Option<String>,
|
||||
page: Page,
|
||||
news: Vec<db::NewsArticle>,
|
||||
h: Helper,
|
||||
}
|
||||
|
||||
#[get("/news")]
|
||||
@ -492,9 +492,9 @@ async fn news(id: Identity, db: Data<PgPool>) -> Result<HttpResponse> {
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
NewsTemplate {
|
||||
account,
|
||||
error: None,
|
||||
page: Page::News,
|
||||
news,
|
||||
..Default::default()
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
|
@ -1,7 +1,22 @@
|
||||
pub mod filters {
|
||||
|
||||
pub fn opt_time(s: &Option<chrono::NaiveDateTime>) -> ::askama::Result<String> {
|
||||
Ok(s.as_ref()
|
||||
.map(|t| serde_json::to_string(t).unwrap_or_default())
|
||||
.unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Helper;
|
||||
|
||||
impl Helper {
|
||||
pub fn is_admin(&self, account: &Option<crate::model::db::Account>) -> bool {
|
||||
use crate::model::db::AccountType;
|
||||
|
||||
account
|
||||
.as_ref()
|
||||
.map(|a| a.account_type == AccountType::Admin)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user