2019-03-10 18:23:44 -07:00
|
|
|
use actix_files::NamedFile;
|
|
|
|
use actix_session::Session;
|
2019-03-26 04:29:00 +01:00
|
|
|
use actix_web::middleware::errhandlers::ErrorHandlerResponse;
|
2019-03-10 18:23:44 -07:00
|
|
|
use actix_web::{dev, error, http, web, Error, HttpResponse, Responder, Result};
|
|
|
|
use futures::future::{err, Either, Future, IntoFuture};
|
2018-08-27 10:56:26 +01:00
|
|
|
use tera::{Context, Tera};
|
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
use crate::db;
|
|
|
|
use crate::session::{self, FlashMessage};
|
2018-08-27 10:56:26 +01:00
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
pub fn index(
|
2019-03-16 20:23:09 -07:00
|
|
|
pool: web::Data<db::PgPool>,
|
|
|
|
tmpl: web::Data<Tera>,
|
2019-03-10 18:23:44 -07:00
|
|
|
session: Session,
|
|
|
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
|
|
|
web::block(move || db::get_all_tasks(&pool))
|
2018-08-27 10:56:26 +01:00
|
|
|
.from_err()
|
2019-03-10 18:23:44 -07:00
|
|
|
.then(move |res| match res {
|
2018-08-27 10:56:26 +01:00
|
|
|
Ok(tasks) => {
|
|
|
|
let mut context = Context::new();
|
2019-03-10 18:23:44 -07:00
|
|
|
context.insert("tasks", &tasks);
|
2018-08-27 10:56:26 +01:00
|
|
|
|
2018-09-05 12:46:55 +03:00
|
|
|
//Session is set during operations on other endpoints
|
|
|
|
//that can redirect to index
|
2019-03-10 18:23:44 -07:00
|
|
|
if let Some(flash) = session::get_flash(&session)? {
|
|
|
|
context.insert("msg", &(flash.kind, flash.message));
|
|
|
|
session::clear_flash(&session);
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
let rendered =
|
|
|
|
tmpl.render("index.html.tera", &context).map_err(|e| {
|
2018-08-27 10:56:26 +01:00
|
|
|
error::ErrorInternalServerError(e.description().to_owned())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(HttpResponse::Ok().body(rendered))
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct CreateForm {
|
|
|
|
description: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn create(
|
2019-03-10 18:23:44 -07:00
|
|
|
params: web::Form<CreateForm>,
|
2019-03-16 20:23:09 -07:00
|
|
|
pool: web::Data<db::PgPool>,
|
2019-03-10 18:23:44 -07:00
|
|
|
session: Session,
|
|
|
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
2018-08-27 10:56:26 +01:00
|
|
|
if params.description.is_empty() {
|
2019-03-10 18:23:44 -07:00
|
|
|
Either::A(
|
2018-08-27 10:56:26 +01:00
|
|
|
session::set_flash(
|
2019-03-10 18:23:44 -07:00
|
|
|
&session,
|
2018-08-27 10:56:26 +01:00
|
|
|
FlashMessage::error("Description cannot be empty"),
|
2019-03-10 18:23:44 -07:00
|
|
|
)
|
|
|
|
.map(|_| redirect_to("/"))
|
|
|
|
.into_future(),
|
|
|
|
)
|
2018-08-27 10:56:26 +01:00
|
|
|
} else {
|
2019-03-10 18:23:44 -07:00
|
|
|
Either::B(
|
|
|
|
web::block(move || db::create_task(params.into_inner().description, &pool))
|
|
|
|
.from_err()
|
|
|
|
.then(move |res| match res {
|
|
|
|
Ok(_) => {
|
|
|
|
session::set_flash(
|
|
|
|
&session,
|
|
|
|
FlashMessage::success("Task successfully added"),
|
|
|
|
)?;
|
|
|
|
Ok(redirect_to("/"))
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}),
|
|
|
|
)
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct UpdateParams {
|
|
|
|
id: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct UpdateForm {
|
|
|
|
_method: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update(
|
2019-03-16 20:23:09 -07:00
|
|
|
db: web::Data<db::PgPool>,
|
2019-03-10 18:23:44 -07:00
|
|
|
params: web::Path<UpdateParams>,
|
|
|
|
form: web::Form<UpdateForm>,
|
|
|
|
session: Session,
|
|
|
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
2018-08-27 10:56:26 +01:00
|
|
|
match form._method.as_ref() {
|
2019-03-10 18:23:44 -07:00
|
|
|
"put" => Either::A(Either::A(toggle(db, params))),
|
|
|
|
"delete" => Either::A(Either::B(delete(db, params, session))),
|
2018-08-27 10:56:26 +01:00
|
|
|
unsupported_method => {
|
|
|
|
let msg = format!("Unsupported HTTP method: {}", unsupported_method);
|
2019-03-10 18:23:44 -07:00
|
|
|
Either::B(err(error::ErrorBadRequest(msg)))
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn toggle(
|
2019-03-16 20:23:09 -07:00
|
|
|
pool: web::Data<db::PgPool>,
|
2019-03-10 18:23:44 -07:00
|
|
|
params: web::Path<UpdateParams>,
|
|
|
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
|
|
|
web::block(move || db::toggle_task(params.id, &pool))
|
2018-08-27 10:56:26 +01:00
|
|
|
.from_err()
|
2019-03-10 18:23:44 -07:00
|
|
|
.then(move |res| match res {
|
2018-08-27 10:56:26 +01:00
|
|
|
Ok(_) => Ok(redirect_to("/")),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn delete(
|
2019-03-16 20:23:09 -07:00
|
|
|
pool: web::Data<db::PgPool>,
|
2019-03-10 18:23:44 -07:00
|
|
|
params: web::Path<UpdateParams>,
|
|
|
|
session: Session,
|
|
|
|
) -> impl Future<Item = HttpResponse, Error = Error> {
|
|
|
|
web::block(move || db::delete_task(params.id, &pool))
|
2018-08-27 10:56:26 +01:00
|
|
|
.from_err()
|
2019-03-10 18:23:44 -07:00
|
|
|
.then(move |res| match res {
|
2018-08-27 10:56:26 +01:00
|
|
|
Ok(_) => {
|
2019-03-10 18:23:44 -07:00
|
|
|
session::set_flash(
|
|
|
|
&session,
|
|
|
|
FlashMessage::success("Task was deleted."),
|
|
|
|
)?;
|
2018-08-27 10:56:26 +01:00
|
|
|
Ok(redirect_to("/"))
|
|
|
|
}
|
|
|
|
Err(e) => Err(e),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn redirect_to(location: &str) -> HttpResponse {
|
|
|
|
HttpResponse::Found()
|
|
|
|
.header(http::header::LOCATION, location)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
pub fn bad_request<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
2018-08-27 10:56:26 +01:00
|
|
|
let new_resp = NamedFile::open("static/errors/400.html")?
|
2019-03-10 18:23:44 -07:00
|
|
|
.set_status_code(res.status())
|
|
|
|
.respond_to(res.request())?;
|
|
|
|
Ok(ErrorHandlerResponse::Response(
|
|
|
|
res.into_response(new_resp.into_body()),
|
|
|
|
))
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
pub fn not_found<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
|
2018-08-27 10:56:26 +01:00
|
|
|
let new_resp = NamedFile::open("static/errors/404.html")?
|
2019-03-10 18:23:44 -07:00
|
|
|
.set_status_code(res.status())
|
|
|
|
.respond_to(res.request())?;
|
|
|
|
Ok(ErrorHandlerResponse::Response(
|
|
|
|
res.into_response(new_resp.into_body()),
|
|
|
|
))
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|
|
|
|
|
2019-03-10 18:23:44 -07:00
|
|
|
pub fn internal_server_error<B>(
|
|
|
|
res: dev::ServiceResponse<B>,
|
|
|
|
) -> Result<ErrorHandlerResponse<B>> {
|
2018-08-27 10:56:26 +01:00
|
|
|
let new_resp = NamedFile::open("static/errors/500.html")?
|
2019-03-10 18:23:44 -07:00
|
|
|
.set_status_code(res.status())
|
|
|
|
.respond_to(res.request())?;
|
|
|
|
Ok(ErrorHandlerResponse::Response(
|
|
|
|
res.into_response(new_resp.into_body()),
|
|
|
|
))
|
2018-08-27 10:56:26 +01:00
|
|
|
}
|