Add flash messages

This commit is contained in:
Sam Samai 2021-09-16 22:47:11 +10:00
parent 237dcaa6a9
commit 8b46a89e2c
3 changed files with 53 additions and 13 deletions

View File

@ -14,6 +14,7 @@ futures = { version = "^0.3" }
futures-util = { version = "^0.3" } futures-util = { version = "^0.3" }
actix-http = "2" actix-http = "2"
actix-web = "3" actix-web = "3"
actix-flash = "0.2"
actix-files = "0.5" actix-files = "0.5"
tera = "1.8.0" tera = "1.8.0"
dotenv = "0.15" dotenv = "0.15"

View File

@ -13,7 +13,7 @@ use listenfd::ListenFd;
use sea_orm::entity::*; use sea_orm::entity::*;
use sea_orm::query::*; use sea_orm::query::*;
use sea_orm::EntityTrait; use sea_orm::EntityTrait;
use serde::Deserialize; use serde::{Deserialize, Serialize};
use std::env; use std::env;
use tera::Tera; use tera::Tera;
@ -34,8 +34,18 @@ pub struct Params {
posts_per_page: Option<usize>, posts_per_page: Option<usize>,
} }
#[derive(Deserialize, Serialize, Debug, Clone)]
struct FlashData {
kind: String,
message: String,
}
#[get("/")] #[get("/")]
async fn list(req: HttpRequest, data: web::Data<AppState>) -> Result<HttpResponse, Error> { async fn list(
req: HttpRequest,
data: web::Data<AppState>,
opt_flash: Option<actix_flash::Message<FlashData>>,
) -> Result<HttpResponse, Error> {
let template = &data.templates; let template = &data.templates;
let conn = sea_orm::Database::connect(&data.db_url).await.unwrap(); let conn = sea_orm::Database::connect(&data.db_url).await.unwrap();
@ -47,6 +57,15 @@ async fn list(req: HttpRequest, data: web::Data<AppState>) -> Result<HttpRespons
let paginator = Post::find().paginate(&conn, posts_per_page); let paginator = Post::find().paginate(&conn, posts_per_page);
let num_pages = paginator.num_pages().await.ok().unwrap(); let num_pages = paginator.num_pages().await.ok().unwrap();
let mut flash_message = String::new();
let mut flash_kind = String::new();
if let Some(flash) = opt_flash {
let flash_inner = flash.into_inner();
flash_message = flash_inner.message.to_owned();
flash_kind = flash_inner.kind.to_owned();
}
let posts = paginator let posts = paginator
.fetch_page(page) .fetch_page(page)
.await .await
@ -56,6 +75,8 @@ async fn list(req: HttpRequest, data: web::Data<AppState>) -> Result<HttpRespons
ctx.insert("page", &page); ctx.insert("page", &page);
ctx.insert("posts_per_page", &posts_per_page); ctx.insert("posts_per_page", &posts_per_page);
ctx.insert("num_pages", &num_pages); ctx.insert("num_pages", &num_pages);
ctx.insert("flash_message", &flash_message);
ctx.insert("flash_kind", &flash_kind);
let body = template let body = template
.render("index.html.tera", &ctx) .render("index.html.tera", &ctx)
@ -77,7 +98,7 @@ async fn new(data: web::Data<AppState>) -> Result<HttpResponse, Error> {
async fn create( async fn create(
data: web::Data<AppState>, data: web::Data<AppState>,
post_form: web::Form<post::Model>, post_form: web::Form<post::Model>,
) -> Result<HttpResponse, Error> { ) -> actix_flash::Response<HttpResponse, FlashData> {
let conn = sea_orm::Database::connect(&data.db_url).await.unwrap(); let conn = sea_orm::Database::connect(&data.db_url).await.unwrap();
let form = post_form.into_inner(); let form = post_form.into_inner();
@ -91,7 +112,12 @@ async fn create(
.await .await
.expect("could not insert post"); .expect("could not insert post");
Ok(HttpResponse::Found().header("location", "/").finish()) let flash = FlashData {
kind: "success".to_owned(),
message: "Post successfully added.".to_owned(),
};
actix_flash::Response::with_redirect(flash.clone(), "/")
} }
#[get("/{id}")] #[get("/{id}")]
@ -119,7 +145,7 @@ async fn update(
data: web::Data<AppState>, data: web::Data<AppState>,
id: web::Path<i32>, id: web::Path<i32>,
post_form: web::Form<post::Model>, post_form: web::Form<post::Model>,
) -> Result<HttpResponse, Error> { ) -> actix_flash::Response<HttpResponse, FlashData> {
let conn = sea_orm::Database::connect(&data.db_url).await.unwrap(); let conn = sea_orm::Database::connect(&data.db_url).await.unwrap();
let form = post_form.into_inner(); let form = post_form.into_inner();
@ -132,11 +158,19 @@ async fn update(
.await .await
.expect("could not edit post"); .expect("could not edit post");
Ok(HttpResponse::Found().header("location", "/").finish()) let flash = FlashData {
kind: "success".to_owned(),
message: "Post successfully updated.".to_owned(),
};
actix_flash::Response::with_redirect(flash.clone(), "/")
} }
#[post("/delete/{id}")] #[post("/delete/{id}")]
async fn delete(data: web::Data<AppState>, id: web::Path<i32>) -> Result<HttpResponse, Error> { async fn delete(
data: web::Data<AppState>,
id: web::Path<i32>,
) -> actix_flash::Response<HttpResponse, FlashData> {
let conn = sea_orm::Database::connect(&data.db_url).await.unwrap(); let conn = sea_orm::Database::connect(&data.db_url).await.unwrap();
let post: post::ActiveModel = Post::find_by_id(id.into_inner()) let post: post::ActiveModel = Post::find_by_id(id.into_inner())
@ -148,8 +182,12 @@ async fn delete(data: web::Data<AppState>, id: web::Path<i32>) -> Result<HttpRes
post.delete(&conn).await.unwrap(); post.delete(&conn).await.unwrap();
// Flash::success(Redirect::to("/"), "Post successfully deleted.") let flash = FlashData {
Ok(HttpResponse::Found().header("location", "/").finish()) kind: "success".to_owned(),
message: "Post successfully deleted.".to_owned(),
};
actix_flash::Response::with_redirect(flash.clone(), "/")
} }
#[actix_web::main] #[actix_web::main]
@ -177,6 +215,7 @@ async fn main() -> std::io::Result<()> {
templates: templates, templates: templates,
}) })
.wrap(middleware::Logger::default()) // enable logger .wrap(middleware::Logger::default()) // enable logger
.wrap(actix_flash::Flash::default())
.configure(init) .configure(init)
.service(fs::Files::new("/static", "./static").show_files_listing()) .service(fs::Files::new("/static", "./static").show_files_listing())
}); });

View File

@ -2,11 +2,11 @@
<div class="container"> <div class="container">
<p><!--Nothing to see here --></p> <p><!--Nothing to see here --></p>
<h1>Posts</h1> <h1>Posts</h1>
{# {% if flash %} {% if flash_message %}
<small class="field-{{ flash.0 }}-flash"> <small class="field-{{ flash_kind }}-flash">
{{ flash.1 }} {{ flash_message }}
</small> </small>
{% endif %} #} {% endif %}
<table> <table>
<tbody> <tbody>
<thead> <thead>