diff --git a/src/db/doll.rs b/src/db/doll.rs index 2a28470..1e28579 100644 --- a/src/db/doll.rs +++ b/src/db/doll.rs @@ -87,6 +87,48 @@ pub async fn create(db: &mut DbHook, doll: CreateDollProfile<'_>) -> sqlx::Resul Ok(()) } +pub async fn edit(db: &mut DbHook, doll: CreateDollProfile<'_>) -> sqlx::Result<()> { + sqlx::query!( + r#" + update doll_profiles + set microchip_id = $1, + name = $2, + pronoun_subject = $3, + pronoun_object = $4, + pronoun_possessive = $5, + handler_name = $6, + handler_link = $7, + kind = $8, + breed = $9, + behaviour = $10, + description = $11, + chassis_type = $12, + chassis_id = $13, + chassis_color = $14 + where id = $15 + "#, + doll.microchip_id, + doll.name, + doll.pronoun_subject, + doll.pronoun_object, + doll.pronoun_possessive, + doll.handler_name, + doll.handler_link, + doll.kind, + doll.breed, + doll.behaviour, + doll.description, + doll.chassis_type, + doll.chassis_id, + doll.chassis_color, + doll.id, + ) + .execute(&mut **db) + .await?; + + Ok(()) +} + /// deleting a doll profile only wipes the data associated to it but retains two bits of info: /// - the tag's ID /// - the account which created this tag diff --git a/src/main.rs b/src/main.rs index 65860cd..1a16744 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,6 +36,8 @@ fn rocket() -> _ { account::change_password, form::register_tag::show_register, form::register_tag::handle_register, + form::register_tag::show_edit_tag, + form::register_tag::handle_edit_tag, account::ask_delete, account::confirm_delete, account::ask_terminate_account, diff --git a/src/pages.rs b/src/pages.rs index 3d7a5bc..828c5d8 100644 --- a/src/pages.rs +++ b/src/pages.rs @@ -49,3 +49,17 @@ impl<'r> FromRequest<'r> for CommonTemplateState { }) } } + +/// FakeContext exists to be used as a replacement for Context when reusing a form for creation and edition, to avoid repeating lots of code. +/// +/// Note: i made this custom context thingy because i couldn't find a way to create a real context with the right populated data. +#[derive(Debug, Serialize)] +#[serde(crate = "rocket::serde")] +pub struct FakeContext { + /// Values are made to simulate the same structure as the real Context + pub values: HashMap<&'static str, Vec>, + /// NOP, used to placehold field errors + pub errors: HashMap, + /// NOP, used to placehold global errors + pub form_errors: Vec<()>, +} diff --git a/src/routes/form/register_tag.rs b/src/routes/form/register_tag.rs index facbae2..bee7e15 100644 --- a/src/routes/form/register_tag.rs +++ b/src/routes/form/register_tag.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use rocket::{ form::{self, Contextual, Form}, response::Redirect, @@ -7,11 +9,11 @@ use rocket_dyn_templates::{context, Template}; use crate::{ db::{ doll, - schema::{CreateDollProfile, DollTagsDb, User}, + schema::{CreateDollProfile, DollProfile, DollTagsDb, User}, }, ids::{id_public_to_db, pick_ids}, - pages::CommonTemplateState, - routes::{error_handlers::PageResult, public}, + pages::{CommonTemplateState, FakeContext}, + routes::{account, error_handlers::PageResult, public}, }; #[get("/new_tag")] @@ -21,6 +23,7 @@ pub async fn show_register(db: DollTagsDb, _user: User, meta: CommonTemplateStat Ok(Template::render( "register_tag", context! { + mode: "register", ids, previous: form::Context::default(), meta, @@ -29,6 +32,78 @@ pub async fn show_register(db: DollTagsDb, _user: User, meta: CommonTemplateStat .into()) } +impl From for FakeContext { + fn from(tag: DollProfile) -> Self { + FakeContext { + values: HashMap::from([ + ("id", vec![format!("{:0>6}", tag.id)]), + ( + "microchip_id", + vec![tag.microchip_id.unwrap_or(String::from(""))], + ), + ("name", vec![tag.name]), + ("pronoun_subject", vec![tag.pronoun_subject]), + ("pronoun_object", vec![tag.pronoun_object]), + ("pronoun_possessive", vec![tag.pronoun_possessive]), + ("handler_name", vec![tag.handler_name]), + ( + "handler_link", + vec![tag.handler_link.unwrap_or(String::from(""))], + ), + ("kind", vec![tag.kind.unwrap_or(String::from(""))]), + ("breed", vec![tag.breed.unwrap_or(String::from(""))]), + ("behaviour", vec![tag.behaviour.unwrap_or(String::from(""))]), + ( + "description", + vec![tag.description.unwrap_or(String::from(""))], + ), + ( + "chassis_type", + vec![tag.chassis_type.unwrap_or(String::from(""))], + ), + ( + "chassis_id", + vec![tag.chassis_id.unwrap_or(String::from(""))], + ), + ( + "chassis_color", + vec![tag.chassis_color.unwrap_or(String::from(""))], + ), + ]), + errors: HashMap::new(), + form_errors: vec![], + } + } +} + +#[get("/edit_tag/")] +pub async fn show_edit_tag( + mut db: DollTagsDb, + id: &str, + _user: User, + meta: CommonTemplateState, +) -> PageResult { + let normalized_id = match id_public_to_db(id) { + Some(v) => v, + None => return Ok(Redirect::to(uri!("/account", account::index)).into()), + }; + let tag = match doll::get(&mut *db, normalized_id, "").await? { + Some(v) => v, + None => return Ok(Redirect::to(uri!("/account", account::index)).into()), + }; + + Ok(Template::render( + "register_tag", + context! { + mode: "edit", + id, + previous: FakeContext::from(tag), + meta, + }, + ) + .into()) +} + #[derive(Debug, FromForm)] pub struct TagForm<'a> { #[field(validate=validate_id())] @@ -109,6 +184,7 @@ pub async fn handle_register( return Ok(Template::render( "register_tag", context! { + mode: "register", ids, previous: &tag.context, meta, @@ -160,3 +236,71 @@ pub async fn handle_register( Ok(Redirect::to(uri!(public::show_profile(Some(tag.ident), microchip_id))).into()) } + +#[post("/edit_tag/", data = "")] +pub async fn handle_edit_tag( + mut db: DollTagsDb, + id: &str, + tag: Form>>, + user: User, + meta: CommonTemplateState, +) -> PageResult { + let id = match id_public_to_db(id) { + None => return Ok(Redirect::to(uri!("/account", crate::routes::account::index)).into()), + Some(v) => v, + }; + let tag = match tag.value { + Some(ref values) => values, + None => { + debug!("tag edition form invalid, context: {:?}", &tag.context); + + return Ok(Template::render( + "register_tag", + context! { + mode: "edit", + id, + previous: &tag.context, + meta, + }, + ) + .into()); + } + }; + + debug!("editing tag: {:?}", tag); + fn normalize_opt(opt: &str) -> Option<&str> { + if opt.len() != 0 { + Some(opt) + } else { + None + } + } + + let normalized_microchip_id = tag.microchip_id.to_lowercase(); + let microchip_id = normalize_opt(&normalized_microchip_id); + + doll::edit( + &mut *db, + CreateDollProfile { + id, + microchip_id, + name: tag.name, + pronoun_subject: tag.pronoun_subject, + pronoun_object: tag.pronoun_object, + pronoun_possessive: tag.pronoun_possessive, + handler_name: tag.handler_name, + handler_link: normalize_opt(tag.handler_link), + kind: normalize_opt(tag.kind), + breed: normalize_opt(tag.breed), + behaviour: normalize_opt(tag.behaviour), + description: normalize_opt(tag.description), + chassis_type: normalize_opt(tag.chassis_type), + chassis_id: normalize_opt(tag.chassis_id), + chassis_color: normalize_opt(tag.chassis_color), + bound_to_id: &user.id, + }, + ) + .await?; + + Ok(Redirect::to(uri!(public::show_profile(Some(tag.ident), microchip_id))).into()) +} diff --git a/templates/account/index.html.tera b/templates/account/index.html.tera index 714854f..435443a 100644 --- a/templates/account/index.html.tera +++ b/templates/account/index.html.tera @@ -32,7 +32,7 @@

{{profile.name}}

diff --git a/templates/register_tag.html.tera b/templates/register_tag.html.tera index 303fe77..596b97f 100644 --- a/templates/register_tag.html.tera +++ b/templates/register_tag.html.tera @@ -1,8 +1,10 @@ {% extends "base" %} {% import "macros/form" as form %} -{% block title %}Register a new tag - {% endblock title %} + +{% block title %}{% if mode == "register" %}Register a new tag{% else %}Edit {{id}}{% endif %} - {% endblock title +%} {% block main %} -

Register a new tag

+

{% if mode == "register" %}Register a new tag{% else %}Edit {{id}}{% endif %}

+ {% if mode == "register" %}

Now, to the registration!

+ {% else %} +

Now, to the editing!

+ {% endif %} {% if previous.form_errors | length > 0 %}
@@ -30,14 +36,24 @@ {% endif %}
+ {% if mode != "register" %} + + + {% endif %} +

Firstly, the tag's ID

+ {% if mode == "register" %}

You may enter your own, but in case of collision it will not be usable.
To that end, here's a few free ones you may also pick from.

+ {% else %} +

You can't change a tag's ID for now. If it's something you'd like to do, contact me directly.

+ {% endif %}
+ {% if mode == "register" %}

{{form::error(ctx=previous, name="microchip_id")}}
+ {% else %} +

+ + {{form::error(ctx=previous, name="microchip_id")}} + {% endif %}
@@ -182,7 +205,13 @@
- +