From 46e45e8b685993b5909cd086ab0b8e3bd1a2c417 Mon Sep 17 00:00:00 2001 From: asonix Date: Thu, 7 Jan 2021 22:44:43 -0600 Subject: [PATCH] Add settings page, improve navigation --- server/Cargo.toml | 2 +- server/scss/layout.scss | 56 ++++++ server/src/accounts.rs | 40 +++-- server/src/back.rs | 145 +++++++++++++++ server/src/main.rs | 75 ++++++-- server/src/profiles/middleware.rs | 10 +- server/src/profiles/mod.rs | 170 ++++++++++++------ server/templates/account.rs.html | 20 --- server/templates/delete_account.rs.html | 9 - server/templates/error.rs.html | 9 +- server/templates/index.rs.html | 30 ++-- server/templates/layouts/home.rs.html | 26 +++ server/templates/layouts/main.rs.html | 14 ++ .../{layout.rs.html => layouts/root.rs.html} | 10 +- server/templates/login.rs.html | 9 - server/templates/nav/nav.rs.html | 18 ++ server/templates/nav/page.rs.html | 18 ++ server/templates/not_found.rs.html | 9 +- .../templates/profiles/create/banner.rs.html | 18 +- server/templates/profiles/create/bio.rs.html | 17 +- server/templates/profiles/create/done.rs.html | 15 +- .../templates/profiles/create/handle.rs.html | 14 +- server/templates/profiles/create/icon.rs.html | 18 +- .../profiles/create/require_login.rs.html | 17 +- server/templates/profiles/current.rs.html | 21 ++- server/templates/profiles/list.rs.html | 36 ++-- server/templates/register.rs.html | 9 - server/templates/session/account.rs.html | 23 +++ .../templates/{ => session}/cookies.rs.html | 4 +- .../templates/session/delete_account.rs.html | 9 + server/templates/session/login.rs.html | 11 ++ server/templates/session/register.rs.html | 11 ++ server/templates/settings.rs.html | 30 ++++ 33 files changed, 678 insertions(+), 245 deletions(-) create mode 100644 server/src/back.rs delete mode 100644 server/templates/account.rs.html delete mode 100644 server/templates/delete_account.rs.html create mode 100644 server/templates/layouts/home.rs.html create mode 100644 server/templates/layouts/main.rs.html rename server/templates/{layout.rs.html => layouts/root.rs.html} (73%) delete mode 100644 server/templates/login.rs.html create mode 100644 server/templates/nav/nav.rs.html create mode 100644 server/templates/nav/page.rs.html delete mode 100644 server/templates/register.rs.html create mode 100644 server/templates/session/account.rs.html rename server/templates/{ => session}/cookies.rs.html (62%) create mode 100644 server/templates/session/delete_account.rs.html create mode 100644 server/templates/session/login.rs.html create mode 100644 server/templates/session/register.rs.html create mode 100644 server/templates/settings.rs.html diff --git a/server/Cargo.toml b/server/Cargo.toml index b8c0eb5..e3f0033 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -23,7 +23,7 @@ hyaenidae-profiles = { version = "0.1.0", path = "../profiles" } hyaenidae-toolkit = { version = "0.1.0", path = "../toolkit" } log = "0.4" mime = "0.3.16" -minify-html = "0.3.9" +minify-html = "0.4.0" rand = "0.7" once_cell = "1.5.2" serde = { version = "1.0", features = ["derive"] } diff --git a/server/scss/layout.scss b/server/scss/layout.scss index 2031002..034e823 100644 --- a/server/scss/layout.scss +++ b/server/scss/layout.scss @@ -1,8 +1,53 @@ + .error { color: #c92a60; font-style: italic; } +.top-bar__mobile { + display: none; + justify-content: space-between; + align-items: center; + background-color: #333; + padding: 8px 16px; + border-bottom: 3px solid #555; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); + + a { + color: #fff; + + &:hover, + &:focus, + &:active { + color: #e5e5e5; + } + } + + h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; + margin: 0; + } +} + +.top-bar { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #222; + padding: 8px 16px; + border-bottom: 2px solid #999; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); + + h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; + margin: 0; + } +} + +.home-content { + padding: 32px 0; +} + .account-page { margin-bottom: 32px; } @@ -13,6 +58,10 @@ color: #f5f5f5; overflow: hidden; + &.card-top { + border-radius: 3px 3px 0 0; + } + &.standalone { margin: 0; border-radius: 3px; @@ -118,6 +167,13 @@ } @media (max-width: 700px) { + .top-bar { + display: none; + } + .top-bar__mobile { + display: flex; + } + .columns { flex-direction: column; diff --git a/server/src/accounts.rs b/server/src/accounts.rs index cf8a316..e3f538e 100644 --- a/server/src/accounts.rs +++ b/server/src/accounts.rs @@ -4,9 +4,9 @@ use crate::{ }; use actix_web::{http::header::LOCATION, web, HttpResponse, Scope}; use hyaenidae_accounts::{ - Authenticated, CookiesArgs, CookiesPageArgs, DeleteUserArgs, DeleteUserPageArgs, LoginArgs, - LoginPageArgs, LogoutArgs, Pages as _, RegisterArgs, RegisterPageArgs, UpdatePasswordArgs, - UpdatePasswordPageArgs, UpdateUsernameArgs, UpdateUsernamePageArgs, + CookiesArgs, CookiesPageArgs, DeleteUserArgs, DeleteUserPageArgs, LoginArgs, LoginPageArgs, + LogoutArgs, LogoutState, Pages as _, RegisterArgs, RegisterPageArgs, UpdatePasswordArgs, + UpdatePasswordPageArgs, UpdateUsernameArgs, UpdateUsernamePageArgs, User, }; pub(crate) struct Pages; @@ -109,7 +109,7 @@ async fn cookies_page( }; rendered(HttpResponse::Ok(), |cursor| { - crate::templates::cookies(cursor, &cookie_state) + crate::templates::session::cookies(cursor, &cookie_state) }) .state(&state) } @@ -128,7 +128,7 @@ async fn login_page( }; rendered(HttpResponse::Ok(), |cursor| { - crate::templates::login(cursor, &login_state) + crate::templates::session::login(cursor, &login_state) }) .state(&state) } @@ -140,7 +140,7 @@ async fn login(args: LoginArgs, state: web::Data) -> Result) -> Result HttpResponse { async fn account_page( uname_args: UpdateUsernamePageArgs, pass_args: UpdatePasswordPageArgs, - authenticated: Authenticated, + user: User, + logout: LogoutState, state: web::Data, ) -> Result { let uname_state = hyaenidae_accounts::update_username_page(uname_args); let pass_state = hyaenidae_accounts::update_password_page(pass_args); - let user = authenticated.user(); rendered(HttpResponse::Ok(), |cursor| { - crate::templates::account(cursor, &user, &uname_state, &pass_state) + crate::templates::session::account(cursor, &user, &uname_state, &pass_state, logout) }) .state(&state) } @@ -201,7 +201,8 @@ async fn to_account() -> HttpResponse { async fn update_username( uname_args: UpdateUsernameArgs, pass_args: UpdatePasswordPageArgs, - authenticated: Authenticated, + user: User, + logout: LogoutState, state: web::Data, ) -> Result { let uname_state = match hyaenidae_accounts::update_username(uname_args) @@ -212,10 +213,9 @@ async fn update_username( Err(res) => return Ok(res), }; let pass_state = hyaenidae_accounts::update_password_page(pass_args); - let user = authenticated.user(); rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::account(cursor, &user, &uname_state, &pass_state) + crate::templates::session::account(cursor, &user, &uname_state, &pass_state, logout) }) .state(&state) } @@ -223,7 +223,8 @@ async fn update_username( async fn update_password( uname_args: UpdateUsernamePageArgs, pass_args: UpdatePasswordArgs, - authenticated: Authenticated, + user: User, + logout: LogoutState, state: web::Data, ) -> Result { let uname_state = hyaenidae_accounts::update_username_page(uname_args); @@ -234,16 +235,16 @@ async fn update_password( Ok(state) => state, Err(res) => return Ok(res), }; - let user = authenticated.user(); rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::account(cursor, &user, &uname_state, &pass_state) + crate::templates::session::account(cursor, &user, &uname_state, &pass_state, logout) }) .state(&state) } async fn delete_account_page( args: DeleteUserPageArgs, + logout: LogoutState, state: web::Data, ) -> Result { let delete_state = match hyaenidae_accounts::delete_user_page(args) { @@ -252,13 +253,14 @@ async fn delete_account_page( }; rendered(HttpResponse::Ok(), |cursor| { - crate::templates::delete_account(cursor, &delete_state) + crate::templates::session::delete_account(cursor, &delete_state, logout) }) .state(&state) } async fn delete_account( args: DeleteUserArgs, + logout: LogoutState, state: web::Data, ) -> Result { let delete_state = match hyaenidae_accounts::delete_user(args).await.state(&state)? { @@ -267,7 +269,7 @@ async fn delete_account( }; rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::delete_account(cursor, &delete_state) + crate::templates::session::delete_account(cursor, &delete_state, logout) }) .state(&state) } diff --git a/server/src/back.rs b/server/src/back.rs new file mode 100644 index 0000000..142c874 --- /dev/null +++ b/server/src/back.rs @@ -0,0 +1,145 @@ +use actix_session::{Session, UserSession}; +use actix_web::{ + dev::{Payload, Service, ServiceRequest, ServiceResponse, Transform}, + FromRequest, HttpRequest, HttpResponse, Responder, +}; +use futures_core::future::LocalBoxFuture; +use futures_util::future::{ok, Ready}; +use hyaenidae_accounts::AcceptedCookies; +use std::fmt; + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct Back { + path: String, +} + +pub(crate) struct BackPage; +pub(crate) struct BackMiddleware(S); + +impl FromRequest for Back { + type Config = (); + type Error = actix_web::Error; + type Future = LocalBoxFuture<'static, Result>; + + fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let session = req.get_session(); + + Box::pin(async move { + Ok(Back::data(&session)?.unwrap_or(Back { + path: "/".to_owned(), + })) + }) + } +} + +impl fmt::Display for Back { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.path, f) + } +} + +impl Responder for Back { + type Error = actix_web::Error; + type Future = Ready>; + + fn respond_to(self, _: &HttpRequest) -> Self::Future { + ok(HttpResponse::SeeOther() + .header("Location", self.path) + .finish()) + } +} + +impl Back { + fn set_data(path: String, session: &Session) -> Result<(), actix_web::Error> { + session.set("back-data", Back { path })?; + Ok(()) + } + + fn data(session: &Session) -> Result, actix_web::Error> { + Ok(session.get("back-data")?) + } + + pub(crate) fn as_str(&self) -> &str { + &self.path + } +} + +impl AsRef for Back { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl Transform for BackPage +where + S: Service, Error = actix_web::Error>, + S::Future: 'static, +{ + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type InitError = (); + type Transform = BackMiddleware; + type Future = Ready>; + + fn new_transform(&self, service: S) -> Self::Future { + ok(BackMiddleware(service)) + } +} + +impl Service for BackMiddleware +where + S: Service, Error = actix_web::Error>, + S::Future: 'static, +{ + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type Future = LocalBoxFuture<'static, Result>; + + fn poll_ready( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.0.poll_ready(cx) + } + + fn call(&mut self, req: S::Request) -> Self::Future { + let session = req.get_session(); + + let path = req + .uri() + .path_and_query() + .map(|paq| paq.as_str()) + .unwrap_or("/") + .to_owned(); + + let (req, pl) = req.into_parts(); + let cookie_fut = AcceptedCookies::extract(&req); + let req = ServiceRequest::from_parts(req, pl) + .map_err(|_| ()) + .expect("Request has been cloned"); + + let fut = self.0.call(req); + + Box::pin(async move { + if let Err(_) = cookie_fut.await { + return fut.await; + } + + match fut.await { + Ok(response) => { + if let Some(content_type) = response.headers().get("Content-Type") { + if let Ok(s) = content_type.to_str() { + if s == "text/html" { + Back::set_data(path, &session)?; + } + } + } + Ok(response) + } + Err(e) => Err(e), + } + }) + } +} diff --git a/server/src/main.rs b/server/src/main.rs index f066ef9..0cf1975 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,20 +5,22 @@ use actix_web::{ middleware::{Compress, Logger}, web, App, HttpResponse, HttpServer, }; -use hyaenidae_accounts::{Auth, Authenticated}; +use hyaenidae_accounts::{Auth, LogoutState, User}; use sled::Db; use std::{fmt, time::SystemTime}; use structopt::StructOpt; mod accounts; mod apub; +mod back; mod error; mod images; mod jobs; mod profiles; +use back::{Back, BackPage}; use error::{Error, OptionExt, ResultExt, StateError}; -use profiles::CurrentProfile; +use profiles::{CurrentProfile, Profile}; include!(concat!(env!("OUT_DIR"), "/templates.rs")); @@ -87,17 +89,20 @@ async fn main() -> anyhow::Result<()> { let accounts_state = accounts_state.clone(); App::new() - .wrap(Logger::default()) - .wrap(Compress::default()) + .wrap(BackPage) .wrap(CurrentProfile(state.clone())) .data(state) .wrap(Auth(accounts_state.clone())) .data(accounts_state) .data(SystemTime::now()) .wrap(hyaenidae_accounts::cookie_middlware(&accounts_config)) + .wrap(Compress::default()) + .wrap(Logger::default()) .route("/", web::get().to(home)) + .route("/nav", web::get().to(nav_page)) .route("/404", web::get().to(not_found)) .route("/500", web::get().to(serve_error)) + .route("/settings", web::get().to(settings)) .route("/toolkit/{name}", web::get().to(toolkit)) .route("/static/{name}", web::get().to(statics)) .service(accounts::scope()) @@ -271,20 +276,29 @@ async fn statics(path: web::Path, startup: web::Data) -> Htt async fn home( state: web::Data, - authenticated: Option, - logout_args: Option, + user: Option, + profile: Option, + logout: Option, ) -> Result { - let logout_opt = logout_args.map(|args| hyaenidae_accounts::logout_page(args)); - let authenticated_opt = authenticated.and_then(|a| logout_opt.map(|l| (a.user(), l))); - + if user.is_some() && profile.is_none() { + return Ok(profiles::to_create()); + } rendered(HttpResponse::Ok(), |cursor| { - templates::index(cursor, authenticated_opt) + templates::index(cursor, &logout, &profile) }) .state(&state) } fn to_404() -> HttpResponse { - HttpResponse::SeeOther().header("Location", "/404").finish() + redirect("/404") +} + +fn to_home() -> HttpResponse { + redirect("/") +} + +fn redirect(path: &str) -> HttpResponse { + HttpResponse::SeeOther().header("Location", path).finish() } async fn not_found(state: web::Data) -> Result { @@ -301,17 +315,42 @@ async fn serve_error(state: web::Data) -> Result, + back: Back, + state: web::Data, +) -> Result { + rendered(HttpResponse::Ok(), |cursor| { + templates::nav::page(cursor, &logout, &back) + }) + .state(&state) +} + +async fn settings( + logout: LogoutState, + state: web::Data, +) -> Result { + rendered(HttpResponse::Ok(), |cursor| { + templates::settings(cursor, logout) + }) + .state(&state) +} + fn rendered( mut builder: HttpResponseBuilder, - f: impl FnOnce(&mut std::io::Cursor>) -> std::io::Result<()>, + f: impl FnOnce(&mut std::io::Cursor<&mut Vec>) -> std::io::Result<()>, ) -> Result { - let mut cursor = std::io::Cursor::new(vec![]); - (f)(&mut cursor).map_err(Error::Render)?; - let mut html = cursor.into_inner(); - let len = minify_html::in_place(&mut html, &minify_html::Cfg { minify_js: false })?; - html.truncate(len); + let mut bytes = vec![]; + (f)(&mut std::io::Cursor::new(&mut bytes)).map_err(Error::Render)?; + minify_html::truncate( + &mut bytes, + &minify_html::Cfg { + minify_js: false, + minify_css: false, + }, + )?; Ok(builder .content_type(mime::TEXT_HTML.essence_str()) - .body(html)) + .body(bytes)) } diff --git a/server/src/profiles/middleware.rs b/server/src/profiles/middleware.rs index 545f837..5351cf6 100644 --- a/server/src/profiles/middleware.rs +++ b/server/src/profiles/middleware.rs @@ -114,7 +114,7 @@ pub(crate) struct ProfileMiddleware(State, S); #[derive(Clone)] struct ProfileExtractor(Rc>>, Rc>, Rc); -struct ProfileDropGuard(Rc); +struct ProfileDropGuard(Rc, Rc>); fn profile_extractor() -> (ProfileExtractor, ProfileDropGuard) { let event = Rc::new(Event::new()); @@ -122,13 +122,14 @@ fn profile_extractor() -> (ProfileExtractor, ProfileDropGuard) { let flag = Rc::new(Cell::new(false)); ( - ProfileExtractor(state, flag, Rc::clone(&event)), - ProfileDropGuard(event), + ProfileExtractor(state, Rc::clone(&flag), Rc::clone(&event)), + ProfileDropGuard(event, flag), ) } impl Drop for ProfileDropGuard { fn drop(&mut self) { + self.1.set(true); self.0.notify(usize::MAX); } } @@ -188,6 +189,7 @@ where let user_id = if let Ok(auth) = user_fut.await { auth.user().id() } else { + drop(drop_guard); return fut.await; }; @@ -210,8 +212,8 @@ where } } - extractor.1.set(true); drop(drop_guard); + fut.await }) } diff --git a/server/src/profiles/mod.rs b/server/src/profiles/mod.rs index 1cf2024..a4b6971 100644 --- a/server/src/profiles/mod.rs +++ b/server/src/profiles/mod.rs @@ -4,7 +4,7 @@ use crate::{ }; use actix_session::Session; use actix_web::{dev::Payload, web, HttpRequest, HttpResponse, Scope}; -use hyaenidae_accounts::Authenticated; +use hyaenidae_accounts::{LogoutState, User}; use uuid::Uuid; mod middleware; @@ -75,7 +75,7 @@ pub(super) fn scope() -> Scope { ) } -fn to_create() -> HttpResponse { +pub(super) fn to_create() -> HttpResponse { redirect("/profiles/create/handle") } @@ -269,25 +269,27 @@ async fn profiles() -> HttpResponse { async fn current_profile( profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_profile(profile).await.state(&state) + do_profile(profile, logout).await.state(&state) } -async fn do_profile(profile: Profile) -> Result { +async fn do_profile(profile: Profile, logout: LogoutState) -> Result { let profile_state = ProfileState::new(profile); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::current(cursor, &profile_state) + crate::templates::profiles::current(cursor, &profile_state, logout) }) } async fn update_bio( form: web::Form, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_update_bio(form.into_inner(), profile, &state) + do_update_bio(form.into_inner(), profile, logout, &state) .await .state(&state) } @@ -295,6 +297,7 @@ async fn update_bio( async fn do_update_bio( form: BioForm, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let display_name = form.display_name.clone(); @@ -321,7 +324,7 @@ async fn do_update_bio( }; crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::current(cursor, &state) + crate::templates::profiles::current(cursor, &state, logout) }) } @@ -329,9 +332,10 @@ async fn update_icon( request: HttpRequest, payload: web::Payload, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_update_icon(request, payload.into_inner(), profile, &state) + do_update_icon(request, payload.into_inner(), profile, logout, &state) .await .state(&state) } @@ -340,6 +344,7 @@ async fn do_update_icon( request: HttpRequest, payload: Payload, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let res = state.profiles.upload_image(request, payload).await; @@ -366,7 +371,7 @@ async fn do_update_icon( state.icon_error(&error); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::current(cursor, &state) + crate::templates::profiles::current(cursor, &state, logout) }) } @@ -374,9 +379,10 @@ async fn update_banner( request: HttpRequest, payload: web::Payload, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_update_banner(request, payload.into_inner(), profile, &state) + do_update_banner(request, payload.into_inner(), profile, logout, &state) .await .state(&state) } @@ -385,6 +391,7 @@ async fn do_update_banner( request: HttpRequest, payload: Payload, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let res = state.profiles.upload_image(request, payload).await; @@ -411,16 +418,17 @@ async fn do_update_banner( state.banner_error(&error); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::current(cursor, &state) + crate::templates::profiles::current(cursor, &state, logout) }) } async fn update_require_login( form: web::Form, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_update_require_login(form.into_inner(), profile, &state) + do_update_require_login(form.into_inner(), profile, logout, &state) .await .state(&state) } @@ -428,6 +436,7 @@ async fn update_require_login( async fn do_update_require_login( form: RequireLoginForm, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let login_required = form.require_login.is_some(); @@ -452,7 +461,7 @@ async fn do_update_require_login( }; crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::current(cursor, &state) + crate::templates::profiles::current(cursor, &state, logout) }) } @@ -462,15 +471,20 @@ struct ChangeProfileForm { } async fn change_profile_page( - auth: Authenticated, + user: User, + logout: LogoutState, state: web::Data, ) -> Result { - let user_id = auth.user().id(); - - do_change_profile_page(user_id, &state).await.state(&state) + do_change_profile_page(user.id(), logout, &state) + .await + .state(&state) } -async fn do_change_profile_page(user_id: Uuid, state: &State) -> Result { +async fn do_change_profile_page( + user_id: Uuid, + logout: LogoutState, + state: &State, +) -> Result { let profiles = state .profiles .store @@ -480,18 +494,17 @@ async fn do_change_profile_page(user_id: Uuid, state: &State) -> Result>(); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::list(cursor, &profiles) + crate::templates::profiles::list(cursor, &profiles, logout) }) } async fn change_profile( - auth: Authenticated, + user: User, session: Session, form: web::Form, state: web::Data, ) -> Result { - let user_id = auth.user().id(); - do_change_profile(user_id, session, form.into_inner(), &state) + do_change_profile(user.id(), session, form.into_inner(), &state) .await .state(&state) } @@ -511,7 +524,7 @@ async fn do_change_profile( .ok() .req()?; - Ok(to_current_profile()) + Ok(crate::to_home()) } #[derive(Clone, Debug, serde::Deserialize)] @@ -519,34 +532,39 @@ pub struct HandleForm { pub(crate) handle: String, } -async fn new_handle(_: Authenticated, state: web::Data) -> Result { +async fn new_handle( + _: User, + logout: LogoutState, + state: web::Data, +) -> Result { let mut handle_input = hyaenidae_toolkit::TextInput::new("handle"); handle_input.placeholder("Handle").title("Handle"); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::create::handle(cursor, &handle_input) + crate::templates::profiles::create::handle(cursor, &handle_input, logout) }) .state(&state) } async fn create_handle( - auth: Authenticated, + user: User, form: web::Form, session: Session, + logout: LogoutState, state: web::Data, ) -> Result { - do_create_handle(auth, form.into_inner(), session, &state) + do_create_handle(user.id(), form.into_inner(), session, logout, &state) .await .state(&state) } async fn do_create_handle( - auth: Authenticated, + user_id: Uuid, form: HandleForm, session: Session, + logout: LogoutState, state: &State, ) -> Result { - let user_id = auth.user().id(); let domain = state.domain.clone(); let handle = form.handle.clone(); @@ -585,7 +603,7 @@ async fn do_create_handle( .error_opt(error); crate::rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::profiles::create::handle(cursor, &handle_input) + crate::templates::profiles::create::handle(cursor, &handle_input, logout) }) } @@ -595,11 +613,15 @@ pub struct BioForm { pub(crate) description: String, } -async fn new_bio(profile: Profile, state: web::Data) -> Result { - do_new_bio(profile).await.state(&state) +async fn new_bio( + profile: Profile, + logout: LogoutState, + state: web::Data, +) -> Result { + do_new_bio(profile, logout).await.state(&state) } -async fn do_new_bio(profile: Profile) -> Result { +async fn do_new_bio(profile: Profile, logout: LogoutState) -> Result { let mut display_name = hyaenidae_toolkit::TextInput::new("display_name"); display_name .title("Display Name") @@ -618,16 +640,23 @@ async fn do_new_bio(profile: Profile) -> Result { } crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::create::bio(cursor, &display_name, &description, &profile) + crate::templates::profiles::create::bio( + cursor, + &display_name, + &description, + &profile, + logout, + ) }) } async fn create_bio( form: web::Form, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_create_bio(form.into_inner(), profile, &state) + do_create_bio(form.into_inner(), profile, logout, &state) .await .state(&state) } @@ -635,6 +664,7 @@ async fn create_bio( async fn do_create_bio( form: BioForm, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let display_name = form.display_name.clone(); @@ -671,21 +701,31 @@ async fn do_create_bio( let profile = profile.refresh(state)?; crate::rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::profiles::create::bio(cursor, &display_name, &description, &profile) + crate::templates::profiles::create::bio( + cursor, + &display_name, + &description, + &profile, + logout, + ) }) } -async fn new_icon(profile: Profile, state: web::Data) -> Result { - do_new_icon(profile).await.state(&state) +async fn new_icon( + profile: Profile, + logout: LogoutState, + state: web::Data, +) -> Result { + do_new_icon(profile, logout).await.state(&state) } -async fn do_new_icon(profile: Profile) -> Result { +async fn do_new_icon(profile: Profile, logout: LogoutState) -> Result { let mut icon_input = hyaenidae_toolkit::FileInput::secondary("images[]", "Select Icon", "icon-input"); icon_input.accept(ACCEPT_TYPES); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::create::icon(cursor, &icon_input, None, &profile) + crate::templates::profiles::create::icon(cursor, &icon_input, None, &profile, logout) }) } @@ -693,9 +733,10 @@ async fn create_icon( request: HttpRequest, payload: web::Payload, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_create_icon(request, payload.into_inner(), profile, &state) + do_create_icon(request, payload.into_inner(), profile, logout, &state) .await .state(&state) } @@ -704,6 +745,7 @@ async fn do_create_icon( request: HttpRequest, payload: Payload, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let res = state.profiles.upload_image(request, payload).await; @@ -732,21 +774,25 @@ async fn do_create_icon( let profile = profile.refresh(state)?; crate::rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::profiles::create::icon(cursor, &icon_input, error, &profile) + crate::templates::profiles::create::icon(cursor, &icon_input, error, &profile, logout) }) } -async fn new_banner(profile: Profile, state: web::Data) -> Result { - do_new_banner(profile).await.state(&state) +async fn new_banner( + profile: Profile, + logout: LogoutState, + state: web::Data, +) -> Result { + do_new_banner(profile, logout).await.state(&state) } -async fn do_new_banner(profile: Profile) -> Result { +async fn do_new_banner(profile: Profile, logout: LogoutState) -> Result { let mut banner_input = hyaenidae_toolkit::FileInput::secondary("images[]", "Select Banner", "banner-input"); banner_input.accept(ACCEPT_TYPES); crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::create::banner(cursor, &banner_input, None, &profile) + crate::templates::profiles::create::banner(cursor, &banner_input, None, &profile, logout) }) } @@ -754,9 +800,10 @@ async fn create_banner( request: HttpRequest, payload: web::Payload, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_create_banner(request, payload.into_inner(), profile, &state) + do_create_banner(request, payload.into_inner(), profile, logout, &state) .await .state(&state) } @@ -765,6 +812,7 @@ async fn do_create_banner( request: HttpRequest, payload: Payload, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { let res = state.profiles.upload_image(request, payload).await; @@ -793,7 +841,7 @@ async fn do_create_banner( let profile = profile.refresh(state)?; crate::rendered(HttpResponse::BadRequest(), |cursor| { - crate::templates::profiles::create::banner(cursor, &banner_input, error, &profile) + crate::templates::profiles::create::banner(cursor, &banner_input, error, &profile, logout) }) } @@ -804,18 +852,23 @@ struct RequireLoginForm { async fn new_require_login( profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_new_require_login(profile).await.state(&state) + do_new_require_login(profile, logout).await.state(&state) } -async fn do_new_require_login(profile: Profile) -> Result { +async fn do_new_require_login( + profile: Profile, + logout: LogoutState, +) -> Result { crate::rendered(HttpResponse::Ok(), |cursor| { crate::templates::profiles::create::require_login( cursor, profile.inner.login_required(), None, &profile, + logout, ) }) } @@ -823,9 +876,10 @@ async fn do_new_require_login(profile: Profile) -> Result { async fn create_require_login( form: web::Form, profile: Profile, + logout: LogoutState, state: web::Data, ) -> Result { - do_create_require_login(form.into_inner(), profile, &state) + do_create_require_login(form.into_inner(), profile, logout, &state) .await .state(&state) } @@ -833,6 +887,7 @@ async fn create_require_login( async fn do_create_require_login( form: RequireLoginForm, profile: Profile, + logout: LogoutState, state: &State, ) -> Result { use hyaenidae_profiles::apub::actions::UpdateProfile; @@ -857,16 +912,21 @@ async fn do_create_require_login( form.require_login.is_some(), error, &profile, + logout, ) }) } -async fn done(profile: Profile, state: web::Data) -> Result { - do_done(profile).await.state(&state) +async fn done( + profile: Profile, + logout: LogoutState, + state: web::Data, +) -> Result { + do_done(profile, logout).await.state(&state) } -async fn do_done(profile: Profile) -> Result { +async fn do_done(profile: Profile, logout: LogoutState) -> Result { crate::rendered(HttpResponse::Ok(), |cursor| { - crate::templates::profiles::create::done(cursor, &profile) + crate::templates::profiles::create::done(cursor, &profile, logout) }) } diff --git a/server/templates/account.rs.html b/server/templates/account.rs.html deleted file mode 100644 index 833e22e..0000000 --- a/server/templates/account.rs.html +++ /dev/null @@ -1,20 +0,0 @@ -@use super::layout; -@use hyaenidae_accounts::{templates::{update_password, update_username}, UpdatePasswordState, UpdateUsernameState, User}; -@use hyaenidae_toolkit::{templates::{button, card, card_body, link}, Button, Card, Link}; - -@(user: &User, uname_state: &UpdateUsernameState, pass_state: &UpdatePasswordState) - -@:layout(&format!("Account Settings for {}", user.username()), "Update account information", {}, { - @:update_username(Card::full_width().classes(&["account-page"]), uname_state) - @:update_password(Card::full_width().classes(&["account-page"]), pass_state) - @:card(Card::full_width().classes(&["account-page"]), { Danger }, { - @:card_body({ - @:button(Button::primary("Delete Account").href("/session/account/delete")) - }) - }) - @:card(Card::full_width().classes(&["account-page"]), { Nav }, { - @:card_body({ - @:link(&Link::current_tab("/"), { Return Home }) - }) - }) -}) diff --git a/server/templates/delete_account.rs.html b/server/templates/delete_account.rs.html deleted file mode 100644 index 4dd530e..0000000 --- a/server/templates/delete_account.rs.html +++ /dev/null @@ -1,9 +0,0 @@ -@use super::layout; -@use hyaenidae_accounts::{templates::delete_user, DeleteUserState}; -@use hyaenidae_toolkit::Card; - -@(state: &DeleteUserState) - -@:layout("Delete Account", "Are you sure you want to delete your account?", {}, { - @:delete_user(&Card::full_width(), state) -}) diff --git a/server/templates/error.rs.html b/server/templates/error.rs.html index e9de84c..beb0c73 100644 --- a/server/templates/error.rs.html +++ b/server/templates/error.rs.html @@ -1,12 +1,11 @@ -@use super::layout; -@use hyaenidae_toolkit::{templates::{card, card_body, link}, Card, Link}; +@use crate::templates::layouts::main; +@use hyaenidae_toolkit::{templates::{card, card_body, card_title, link}, Card, Link}; @(error: String) -@:layout("Error", "There was an error processing your request", {}, { +@:main("Error", "There was an error processing your request", {}, { @:card(&Card::full_width(), { - There was an error processing your request - }, { + @:card_title({ There was an error processing your request }) @:card_body({ @error }) @:card_body({ @:link(&Link::current_tab("/"), { Return Home }) diff --git a/server/templates/index.rs.html b/server/templates/index.rs.html index 8ae12af..0b1164a 100644 --- a/server/templates/index.rs.html +++ b/server/templates/index.rs.html @@ -1,28 +1,22 @@ -@use super::layout; -@use hyaenidae_accounts::{LogoutState, User}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body, link}, Button, Card, Link}; +@use crate::{profiles::Profile, templates::layouts::home}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{card, card_body, card_title}, Card}; -@(logout_opt: Option<(User, LogoutState)>) +@(logout_opt: &Option, profile: &Option) -@:layout("Hyaenidae", "A simple website", {}, { - @if let Some((user, logout_state)) = logout_opt { - @:card(&Card::full_width(), { Welcome, @user.username() }, { +@:home("Hyaenidae", "A simple website", logout_opt, {}, { + @if let Some(profile) = profile { + @:card(&Card::full_width(), { + @:card_title({ Welcome, @profile.name() }) @:card_body({ - @:link(&Link::current_tab("/session/account"), { Account Settings }) - }) - @:card_body({ - @:button_group(&[ - Button::primary_outline("Profile").href("/profiles"), - logout_state.button(&Button::primary_outline("Logout")) - ]) + e }) }) } else { - @:card(&Card::full_width(), { Home... }, { + @:card(&Card::full_width(), { + @:card_title({ Home }) @:card_body({ - @:button_group(&[ - Button::primary_outline("Login").href("/session/auth/login") - ]) + e }) }) } diff --git a/server/templates/layouts/home.rs.html b/server/templates/layouts/home.rs.html new file mode 100644 index 0000000..0e6774b --- /dev/null +++ b/server/templates/layouts/home.rs.html @@ -0,0 +1,26 @@ +@use crate::templates::{layouts::root, nav::nav}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{centered, link}, Link}; + +@(title: &str, description: &str, logout_opt: &Option, head: Content, body: Content) + +@:root(title, description, { @:head() }, { +
+
+

@title

+
+
+ @:nav(logout_opt) +
+
+
+

@title

+

@:link(&Link::current_tab("/nav"), { Nav })

+
+
+ @:centered(false, { + @:body() + }) +
+}) + diff --git a/server/templates/layouts/main.rs.html b/server/templates/layouts/main.rs.html new file mode 100644 index 0000000..777aebe --- /dev/null +++ b/server/templates/layouts/main.rs.html @@ -0,0 +1,14 @@ +@use crate::templates::layouts::root; +@use hyaenidae_toolkit::templates::centered; + +@(title: &str, description: &str, head: Content, body: Content) + +@:root(title, description, { @:head() }, { + @:centered(true, { +

@title

+

@description

+ }) + @:centered(false, { + @:body() + }) +}) diff --git a/server/templates/layout.rs.html b/server/templates/layouts/root.rs.html similarity index 73% rename from server/templates/layout.rs.html rename to server/templates/layouts/root.rs.html index 016a674..a1b76a8 100644 --- a/server/templates/layout.rs.html +++ b/server/templates/layouts/root.rs.html @@ -1,5 +1,5 @@ @use crate::{toolkit_path, statics_path, templates::statics::layout_css}; -@use hyaenidae_toolkit::templates::{centered, statics::toolkit_css}; +@use hyaenidae_toolkit::templates::statics::toolkit_css; @(title: &str, description: &str, head: Content, body: Content) @@ -18,12 +18,6 @@ @:head() - @:centered(true, { -

@title

-

@description

- }) - @:centered(false, { - @:body() - }) + @:body() diff --git a/server/templates/login.rs.html b/server/templates/login.rs.html deleted file mode 100644 index 749b398..0000000 --- a/server/templates/login.rs.html +++ /dev/null @@ -1,9 +0,0 @@ -@use super::layout; -@use hyaenidae_accounts::{templates::login, LoginState}; -@use hyaenidae_toolkit::Card; - -@(login_state: &LoginState) - -@:layout("Login", "Log into Hyaenidae", {}, { - @:login(&Card::full_width(), login_state) -}) diff --git a/server/templates/nav/nav.rs.html b/server/templates/nav/nav.rs.html new file mode 100644 index 0000000..59e95f9 --- /dev/null +++ b/server/templates/nav/nav.rs.html @@ -0,0 +1,18 @@ +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::button_group, Button}; + +@(user_opt: &Option) + +@if let Some(logout_state) = user_opt.as_ref() { + @:button_group(&[ + Button::primary("Home").href("/"), + Button::secondary("Settings").href("/settings"), + Button::secondary("Switch Profile").href("/profiles/change"), + logout_state.button(&Button::primary_outline("Logout")) + ]) +} else { + @:button_group(&[ + Button::primary_outline("Login").href("/session/auth/login"), + Button::primary_outline("Register").href("/session/auth/register"), + ]) +} diff --git a/server/templates/nav/page.rs.html b/server/templates/nav/page.rs.html new file mode 100644 index 0000000..bd8ca31 --- /dev/null +++ b/server/templates/nav/page.rs.html @@ -0,0 +1,18 @@ +@use crate::{templates::{layouts::root, nav::nav}, Back}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, centered}, Button, Card}; + +@(user_opt: &Option, back: &Back) + +@:root("Navigation", "Links to get around", {}, { + @:centered(false, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_body({ + @:nav(user_opt) + }) + @:card_body({ + @:button_group(&[Button::primary_outline("Back").href(back.as_str())]) + }) + }) + }) +}) diff --git a/server/templates/not_found.rs.html b/server/templates/not_found.rs.html index 281b953..7c2879b 100644 --- a/server/templates/not_found.rs.html +++ b/server/templates/not_found.rs.html @@ -1,10 +1,11 @@ -@use super::layout; -@use hyaenidae_toolkit::{templates::{card, card_body, link}, Card, Link}; +@use crate::templates::layouts::main; +@use hyaenidae_toolkit::{templates::{card, card_body, card_title, link}, Card, Link}; @() -@:layout("404", "Not Found", {}, { - @:card(&Card::full_width(), { We couldn't find that }, { +@:main("404", "Not Found", {}, { + @:card(&Card::full_width(), { + @:card_title({ We couldn't find that }) @:card_body({ @:link(&Link::current_tab("/"), { Return Home }) }) diff --git a/server/templates/profiles/create/banner.rs.html b/server/templates/profiles/create/banner.rs.html index 060ce68..bf14077 100644 --- a/server/templates/profiles/create/banner.rs.html +++ b/server/templates/profiles/create/banner.rs.html @@ -1,11 +1,16 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body, file_input}, Button, Card, FileInput}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, file_input, statics::{button_js, file_input_js}}, Button, Card, FileInput}; -@(banner_input: &FileInput, error: Option, profile: &Profile) +@(banner_input: &FileInput, error: Option, profile: &Profile, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Add a banner }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), { + + +}, { + @:card(&Card::full_width().classes(&["account-page"]), {
+ @:card_title({ Add a banner }) @:card_body({

This banner will be displayed on your profile behind your icon. @@ -29,7 +34,8 @@ })

}) - @:card(&Card::full_width().classes(&["account-page"]), { Preview }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Preview }) @:view("", profile) }) }) diff --git a/server/templates/profiles/create/bio.rs.html b/server/templates/profiles/create/bio.rs.html index 83b5506..869327c 100644 --- a/server/templates/profiles/create/bio.rs.html +++ b/server/templates/profiles/create/bio.rs.html @@ -1,11 +1,15 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body, text_input}, Button, Card, TextInput}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, text_input, statics::button_js}, Button, Card, TextInput}; -@(display_name_input: &TextInput, description_input: &TextInput, profile: &Profile) +@(display_name_input: &TextInput, description_input: &TextInput, profile: &Profile, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Create a Bio }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), { + +}, { + @:card(&Card::full_width().classes(&["account-page"]), {
+ @:card_title({ Create a Bio }) @:card_body({

This is where you can talk a bit about yourself. the Display Name is the name @@ -25,7 +29,8 @@ })

}) - @:card(&Card::full_width().classes(&["account-page"]), { Preview }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Preview }) @:view("", profile) }) }) diff --git a/server/templates/profiles/create/done.rs.html b/server/templates/profiles/create/done.rs.html index 1e9d9da..3f8985a 100644 --- a/server/templates/profiles/create/done.rs.html +++ b/server/templates/profiles/create/done.rs.html @@ -1,10 +1,12 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body}, Button, Card}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title}, Button, Card}; -@(profile: &Profile) +@(profile: &Profile, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Finished! }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), {}, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Finished! }) @:card_body({

Congratulations! You're profile is all set up! Now you can start to browse @@ -22,7 +24,8 @@ ]) }) }) - @:card(&Card::full_width().classes(&["account-page"]), { Preview }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Preview }) @:view("", profile) }) }) diff --git a/server/templates/profiles/create/handle.rs.html b/server/templates/profiles/create/handle.rs.html index 651131d..e8b769b 100644 --- a/server/templates/profiles/create/handle.rs.html +++ b/server/templates/profiles/create/handle.rs.html @@ -1,11 +1,15 @@ -@use crate::templates::layout; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body, text_input}, Button, Card, TextInput}; +@use crate::templates::layouts::home; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, text_input, statics::button_js}, Button, Card, TextInput}; -@(handle_input: &TextInput) +@(handle_input: &TextInput, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width(), { Create a Handle }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), { + +}, { + @:card(&Card::full_width().classes(&["account-page"]), {

+ @:card_title({ Create a Handle }) @:card_body({

A handle is how people on Hyaenidae will find your account. You can make this the diff --git a/server/templates/profiles/create/icon.rs.html b/server/templates/profiles/create/icon.rs.html index ffe0245..12e399e 100644 --- a/server/templates/profiles/create/icon.rs.html +++ b/server/templates/profiles/create/icon.rs.html @@ -1,11 +1,16 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body, file_input}, Button, Card, FileInput}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, file_input, statics::{button_js, file_input_js}}, Button, Card, FileInput}; -@(icon_input: &FileInput, error: Option, profile: &Profile) +@(icon_input: &FileInput, error: Option, profile: &Profile, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Add an Icon }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), { + + +}, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Add an Icon }) @:card_body({

This icon will be displayed on your profile, and next to submissions @@ -30,7 +35,8 @@ })

}) - @:card(&Card::full_width().classes(&["account-page"]), { Preview }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Preview }) @:view("", profile) }) }) diff --git a/server/templates/profiles/create/require_login.rs.html b/server/templates/profiles/create/require_login.rs.html index 9a6fd82..7832459 100644 --- a/server/templates/profiles/create/require_login.rs.html +++ b/server/templates/profiles/create/require_login.rs.html @@ -1,11 +1,15 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body}, Button, Card}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, statics::button_js}, Button, Card}; -@(require_login: bool, error: Option, profile: &Profile) +@(require_login: bool, error: Option, profile: &Profile, logout: LogoutState) -@:layout("Create Profile", "Create a new profile on Hyaenidae", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Require Login }, { +@:home("Create Profile", "Create a new profile on Hyaenidae", &Some(logout), { + +}, { + @:card(&Card::full_width().classes(&["account-page"]), {
+ @:card_title({ Require Login }) @:card_body({

If you would like to hide your profile from people without accounts, you @@ -43,7 +47,8 @@ })

}) - @:card(&Card::full_width().classes(&["account-page"]), { Preview }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Preview }) @:view("", profile) }) }) diff --git a/server/templates/profiles/current.rs.html b/server/templates/profiles/current.rs.html index cba67d2..670e77d 100644 --- a/server/templates/profiles/current.rs.html +++ b/server/templates/profiles/current.rs.html @@ -1,11 +1,16 @@ -@use crate::{templates::{layout, profiles::{banner, icon, view}}, profiles::ProfileState}; -@use hyaenidae_toolkit::{templates::{button, button_group, card, card_body, file_input, text_input}, Button, Card}; +@use crate::{templates::{layouts::home, profiles::{banner, icon, view}}, profiles::ProfileState}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button, button_group, card, card_body, card_title, file_input, text_input, statics::{button_js, file_input_js}}, Button, Card}; -@(state: &ProfileState) +@(state: &ProfileState, logout: LogoutState) -@:layout("Profile Settings", &format!("{}'s profile", state.profile.name()), {}, { +@:home("Profile Settings", &format!("{}'s profile", state.profile.name()), &Some(logout), { + + +}, { @:view("standalone account-page", &state.profile) - @:card(&Card::full_width().classes(&["account-page"]), { Update Profile }, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Update Profile }) @:card_body({
@@ -131,10 +136,4 @@ }) }) - @:card(&Card::full_width().classes(&["account-page"]), { - @:button_group(&[ - Button::primary_outline("Create New Profile").href("/profiles/create/handle"), - Button::primary_outline("Switch Profile").href("/profiles/change"), - ]) - }, {}) }) diff --git a/server/templates/profiles/list.rs.html b/server/templates/profiles/list.rs.html index a899f27..82fb222 100644 --- a/server/templates/profiles/list.rs.html +++ b/server/templates/profiles/list.rs.html @@ -1,27 +1,27 @@ -@use crate::{templates::{layout, profiles::view}, profiles::Profile}; -@use hyaenidae_toolkit::{templates::{button_group, card, card_body}, Button, Card}; +@use crate::{templates::{layouts::home, profiles::view}, profiles::Profile}; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title}, Button, Card}; -@(profiles: &[Profile]) +@(profiles: &[Profile], logout: LogoutState) -@:layout("Switch Profile", "Select the profile you wish to use", {}, { - @:card(&Card::full_width().classes(&["account-page"]), { Create New Profile }, { +@:home("Switch Profile", "Select the profile you wish to use", &Some(logout), {}, { + @for profile in profiles { + @:card(&Card::full_width().classes(&["account-page"]), { + @:view("card-top", profile) + @:card_body({ +
+ + @:button_group(&[&Button::primary(&format!("Select {}", profile.name()))]) +
+ }) + }) + } + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Create a New Profile }) @:card_body({ @:button_group(&[ Button::primary_outline("Create").href("/profiles/create/handle"), ]) }) }) - @for profile in profiles { - @:card(&Card::full_width().classes(&["account-page"]), { - @profile.name() - }, { - @:view("", profile) - @:card_body({ -
- - @:button_group(&[&Button::primary("Select")]) -
- }) - }) - } }) diff --git a/server/templates/register.rs.html b/server/templates/register.rs.html deleted file mode 100644 index 43c1a59..0000000 --- a/server/templates/register.rs.html +++ /dev/null @@ -1,9 +0,0 @@ -@use super::layout; -@use hyaenidae_accounts::{templates::register, RegisterState}; -@use hyaenidae_toolkit::Card; - -@(register_state: &RegisterState) - -@:layout("Register", "Register for Hyaenidae", {}, { - @:register(&Card::full_width(), register_state) -}) diff --git a/server/templates/session/account.rs.html b/server/templates/session/account.rs.html new file mode 100644 index 0000000..c4530d9 --- /dev/null +++ b/server/templates/session/account.rs.html @@ -0,0 +1,23 @@ +@use crate::templates::layouts::home; +@use hyaenidae_accounts::{templates::{update_password, update_username}, LogoutState, UpdatePasswordState, UpdateUsernameState, User}; +@use hyaenidae_toolkit::{templates::{button, card, card_body, card_title, link, statics::button_js}, Button, Card, Link}; + +@(user: &User, uname_state: &UpdateUsernameState, pass_state: &UpdatePasswordState, logout: LogoutState) + +@:home(&format!("Account Settings for {}", user.username()), "Update account information", &Some(logout), { + +}, { + @:update_username(Card::full_width().classes(&["account-page"]), uname_state) + @:update_password(Card::full_width().classes(&["account-page"]), pass_state) + @:card(Card::full_width().classes(&["account-page"]), { + @:card_title({ Danger }) + @:card_body({ + @:button(Button::primary("Delete Account").href("/session/account/delete")) + }) + }) + @:card(Card::full_width().classes(&["account-page"]), { + @:card_body({ + @:link(&Link::current_tab("/"), { Return Home }) + }) + }) +}) diff --git a/server/templates/cookies.rs.html b/server/templates/session/cookies.rs.html similarity index 62% rename from server/templates/cookies.rs.html rename to server/templates/session/cookies.rs.html index 3d7187d..68403d7 100644 --- a/server/templates/cookies.rs.html +++ b/server/templates/session/cookies.rs.html @@ -1,10 +1,10 @@ -@use super::layout; +@use crate::templates::layouts::home; @use hyaenidae_accounts::{templates::cookies, CookiesState}; @use hyaenidae_toolkit::Card; @(cookie_state: &CookiesState) -@:layout("Accept Cookies", "Review the cookie policy", {}, { +@:home("Accept Cookies", "Review the cookie policy", &None, {}, { @:cookies(&Card::full_width(), cookie_state) }) diff --git a/server/templates/session/delete_account.rs.html b/server/templates/session/delete_account.rs.html new file mode 100644 index 0000000..8679fdb --- /dev/null +++ b/server/templates/session/delete_account.rs.html @@ -0,0 +1,9 @@ +@use crate::templates::layouts::home; +@use hyaenidae_accounts::{templates::delete_user, DeleteUserState, LogoutState}; +@use hyaenidae_toolkit::Card; + +@(state: &DeleteUserState, logout: LogoutState) + +@:home("Delete Account", "Are you sure you want to delete your account?", &Some(logout), {}, { + @:delete_user(&Card::full_width(), state) +}) diff --git a/server/templates/session/login.rs.html b/server/templates/session/login.rs.html new file mode 100644 index 0000000..9be123d --- /dev/null +++ b/server/templates/session/login.rs.html @@ -0,0 +1,11 @@ +@use crate::templates::layouts::home; +@use hyaenidae_accounts::{templates::login, LoginState}; +@use hyaenidae_toolkit::{templates::statics::button_js, Card}; + +@(login_state: &LoginState) + +@:home("Login", "Log into Hyaenidae", &None, { + +}, { + @:login(&Card::full_width(), login_state) +}) diff --git a/server/templates/session/register.rs.html b/server/templates/session/register.rs.html new file mode 100644 index 0000000..4c8f671 --- /dev/null +++ b/server/templates/session/register.rs.html @@ -0,0 +1,11 @@ +@use crate::templates::layouts::home; +@use hyaenidae_accounts::{templates::register, RegisterState}; +@use hyaenidae_toolkit::{templates::statics::button_js, Card}; + +@(register_state: &RegisterState) + +@:home("Register", "Register for Hyaenidae", &None, { + +}, { + @:register(&Card::full_width(), register_state) +}) diff --git a/server/templates/settings.rs.html b/server/templates/settings.rs.html new file mode 100644 index 0000000..9adc89c --- /dev/null +++ b/server/templates/settings.rs.html @@ -0,0 +1,30 @@ +@use crate::templates::layouts::home; +@use hyaenidae_accounts::LogoutState; +@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, link}, Button, Card, Link}; + +@(logout: LogoutState) + +@:home("Settings", "Update settings", &Some(logout.clone()), {}, { + @:card(&Card::full_width().classes(&["account-page"]), { + @:card_title({ Settings }) + @:card_body({ +
    +
  • + @:link(&Link::current_tab("/profiles"), { + Profile Settings + }) +
  • +
  • + @:link(&Link::current_tab("/session/account"), { + Account Settings + }) +
  • +
+ }) + @:card_body({ + @:button_group(&[ + logout.button(&Button::primary_outline("Logout")) + ]) + }) + }) +})