From e08a46af3ac41968bd5a256f85d7162211476d98 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Fri, 26 Jul 2024 00:50:38 +0100 Subject: [PATCH] week: Create new weeks and change active one Implement a way for admins to introduce new weeks and set them as the last active one. The last active week is the last one that is accessible to players, and will also prevent the graph from being displayed. Implement arrows for navigating between the weeks in the HTML. --- README.md | 4 +- src/main.rs | 6 ++- src/week.rs | 96 +++++++++++++++++++++++++++++++++++++++ static_files/style.css | 16 +++++++ templates/index.html.tera | 35 +++++++++++++- 5 files changed, 153 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 800fc5e..ac48cb6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ vote and who we think wrote them and see some stats ! A list of things that could be implemented/added to the application, some of them are needed for "feature completeness" ! - - [ ] Being able to change from one week to the next - - [ ] Create new weeks for the admin + - [x] Being able to change from one week to the next + - [x] Create new weeks for the admin - [ ] Proper week redirection - [ ] Correctly handle non-existing week number - [x] Add introduction to the weekly truths diff --git a/src/main.rs b/src/main.rs index 6915128..655d9af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,7 +42,11 @@ async fn index(mut db: Connection) -> Redirect { fn rocket() -> _ { rocket::build() .mount("/", FileServer::from(relative!("static_files"))) - .mount("/", routes![index, vote::fetch_vote_data, vote::vote, truth::create_truth, truth::edit_truth, week::week, week::update_week, auth::login]) + .mount("/", routes![index, + vote::fetch_vote_data, vote::vote, + truth::create_truth, truth::edit_truth, + week::week, week::update_week, week::set_last_week, week::create_week, + auth::login]) .attach(database::stage()) .attach(Template::fairing()) } diff --git a/src/week.rs b/src/week.rs index cbc2e9e..6e6de1a 100644 --- a/src/week.rs +++ b/src/week.rs @@ -6,6 +6,7 @@ use rocket::response::Redirect; use rocket_db_pools::{sqlx, Connection}; use rocket_dyn_templates::{context, Template}; +use sqlx::{Acquire, Executor}; use crate::auth; use crate::auth::User; use crate::database::Db; @@ -114,3 +115,98 @@ pub async fn update_week(week: u8, raw_intro: Form, Redirect::to(uri!("/")) } + +#[post("//set_last")] +pub async fn set_last_week(week: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { + let user = auth::get_user(week, &mut db, cookies).await; + if !user.is_admin { + cookies.add(("toast_error", "Vous n'avez pas la permission de changer la semaine.")); + return Redirect::to(uri!(week(week))); + } + + let add_error_cookie = || + cookies.add(("toast_error", "Erreur lors du changement d'état de la semaine.")); + + let db_transaction_connection = db.begin().await; + if db_transaction_connection.is_err() { + error!("Could not start database transaction for last week change : {:?}", db_transaction_connection.unwrap_err()); + add_error_cookie(); + return Redirect::to(uri!(week(week))); + } + let mut db_transaction = db_transaction_connection.unwrap(); + + // Remove the last flag from other weeks, if set. + match db_transaction.execute("UPDATE Weeks SET is_last_week = 0 WHERE is_last_week == 1;") + .await { + Ok(_) => debug!("Succesfully cleared is_last_week"), + Err(error) => { + error!("Failed to clear last week status : {error}"); + add_error_cookie(); + return Redirect::to(uri!(week(week))); + } + }; + + // We should set one week, if not there's something wrong : rollback. + if match sqlx::query("UPDATE Weeks SET is_last_week = 1 WHERE number == $1;") + .bind(week) + .execute(&mut *db_transaction) + .await { + Ok(result) => result.rows_affected(), + Err(error) => { + error!("Error while setting last week status : {error}"); + 0 + } + } == 1 { + db_transaction.commit().await.unwrap_or_else(|error| { + error!("Error while committing week is last transaction : {error}"); + add_error_cookie(); + }) + } else { + db_transaction.rollback().await.unwrap_or_else(|error| { + error!("Error while rolling back week is last transaction : {error}"); + add_error_cookie(); + }) + } + + Redirect::to(uri!(week(week))) +} + +#[get("//create")] +pub async fn create_week(week: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { + let user = auth::get_user(week, &mut db, cookies).await; + if !user.is_admin { + cookies.add(("toast_error", "Vous n'avez pas la permission de changer la semaine.")); + return Redirect::to(uri!(week(week - 1))); + } + + let week_check: Result, sqlx::Error> = sqlx::query_scalar("SELECT number from Weeks WHERE number == $1;") + .bind(week) + .fetch_optional(&mut **db) + .await; + + if week_check.is_err() { + error!("Error while checking week existence : {:?}", week_check.unwrap_err()); + cookies.add(("toast_error", "Erreur en vérifiant que la semaine n'existe pas déjà")); + return Redirect::to(uri!(week(week - 1))); + } + + if week_check.unwrap().is_some() { + debug!("Week {week} already exists, not creating."); + return Redirect::to(uri!(week(week))); + } + + match sqlx::query("INSERT INTO Weeks (number, is_last_week, rendered_text, raw_text) VALUES ($1, 0, \"\", \"\");") + .bind(week) + .execute(&mut **db) + .await { + Ok(_) => { + debug!("Succesfully created new week {week}"); + Redirect::to(uri!(week(week))) + }, + Err(error) => { + error!("Error while creating new week {week} : {error}"); + cookies.add(("toast_error", "Erreur en créant la nouvelle selmaine.")); + Redirect::to(uri!(week(week - 1))) + } + } +} diff --git a/static_files/style.css b/static_files/style.css index 57eb5dc..f6cc018 100644 --- a/static_files/style.css +++ b/static_files/style.css @@ -47,6 +47,22 @@ top: 25%; } +.week_change:link, .week_change:visited { + color: black; + text-decoration: none; + transition: all .2s ease-in-out; +} + +.week_change:hover, .week_change:focus { + color: mediumpurple; + text-shadow: 0 2px 2px slategray; +} + +.week_change_hidden { + padding-left: 0.5eM; + padding-right: 0.5eM; +} + @media (orientation: portrait) { .truth_list { width: 60vw; diff --git a/templates/index.html.tera b/templates/index.html.tera index f3c3c42..cd11ae4 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -12,6 +12,30 @@ +{#{% import "week_change_arrows" as week_macro %}#} +{# For some reason the import does not work ? Figure it out at some point... #} +{%- macro display(display_character, to, enabled) -%} + {%- set class = "week_change" -%} + {%- if enabled == true %} + {% set target = ("href=/" ~ to) %} + {%- else -%} + {% set class = class ~ " week_change_hidden" -%} + {% set target = "" %} + {%- endif -%} + {%- if enabled == true -%}{{- display_character -}}{%- endif -%} +{%- endmacro display -%} + + +{% set back_arrow_enabled = week_data.number > 1 %} +{% set next_arrow_enabled = (week_data.is_last_week != true or user.is_admin == true) %} +{% set next_arrow_href = (week_data.number + 1) %} +{% if user.is_admin == true %} + {% set next_arrow_href = next_arrow_href ~ "/create" %} + {% set next_arrow_chara = '⥅' %} +{% else %} + {% set next_arrow_chara = '⟹' %} +{% endif %} +

{{ title }}

@@ -26,9 +50,18 @@ {% endif %}
-

Semaine {{ week_data.number }}

+

{{- self::display(display_character='⟸', to=(week_data.number - 1), enabled=back_arrow_enabled) }} + Semaine {{ week_data.number }} + {{- self::display(display_character=next_arrow_chara, to=next_arrow_href, enabled=next_arrow_enabled) -}}

+ {% if user.is_admin == true and week_data.is_last_week != true %} +
+ +
+ {% endif %}
{{ week_data.rendered_text | safe }} {%- if user.is_admin == true -%}