From b1be0d0d77a402edd5a30a89f00a7e6ebd45806d Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 31 Jul 2023 23:05:45 -0500 Subject: [PATCH 01/10] make things nice and centered, add base url to guild dashboard links --- src/htmx.rs | 4 ++ src/page.rs | 166 ++++++++++++++++++++++++++++------------------------ 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/src/htmx.rs b/src/htmx.rs index 98c5e4f..751f4e0 100644 --- a/src/htmx.rs +++ b/src/htmx.rs @@ -23,6 +23,7 @@ pub enum Tag { Dialog, Article, Header, + Footer, Div, @@ -51,6 +52,7 @@ pub enum Tag { Anchor, Button, + HeaderGroup, Header1, Header2, Header3, @@ -85,6 +87,7 @@ impl Tag { Self::Dialog => "dialog", Self::Article => "article", Self::Header => "header", + Self::Footer => "footer", Self::Div => "div", @@ -111,6 +114,7 @@ impl Tag { Self::Anchor => "a", Self::Button => "button", + Self::HeaderGroup => "hgroup", Self::Header1 => "h1", Self::Header2 => "h2", Self::Header3 => "h3", diff --git a/src/page.rs b/src/page.rs index f6c38db..d55f6ed 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,6 +1,6 @@ use crate::{ auth::{self, User}, - htmx::{Build, HtmxBuilder, SwapMethod, Tag}, + htmx::{Build, HtmxBuilder, Tag}, settings::{ApiState, Intro, IntroFriendlyName}, }; use axum::{ @@ -9,11 +9,24 @@ use axum::{ }; use tracing::error; -pub(crate) async fn home(user: Option) -> Redirect { +fn page_header(title: &str) -> HtmxBuilder { + HtmxBuilder::new(Tag::Html).head(|b| { + b.title(title) + .script( + "https://unpkg.com/htmx.org@1.9.3", + Some("sha384-lVb3Rd/Ca0AxaoZg5sACe8FJKF0tnUgR2Kd7ehUOG5GCcROv5uBIZsOqovBAcWua"), + ) + // Not currently using + // .script("https://unpkg.com/hyperscript.org@0.9.9", None) + .style_link("https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css") + }) +} + +pub(crate) async fn home(State(state): State, user: Option) -> Redirect { if user.is_some() { - Redirect::to("/guild/588149178912473103") + Redirect::to(&format!("{}/guild/588149178912473103", state.origin)) } else { - Redirect::to("/login") + Redirect::to(&format!("{}/login", state.origin)) } } @@ -29,7 +42,7 @@ fn intro_list<'a>( .builder(Tag::FieldSet, |b| { let mut b = b .attribute("class", "container") - .attribute("style", "max-height: 20%; overflow-y: scroll"); + .attribute("style", "max-height: 50%; overflow-y: scroll"); for intro in intros { b = b.builder(Tag::Label, |b| { b.builder(Tag::Input, |b| { @@ -54,107 +67,108 @@ pub(crate) async fn guild_dashboard( let Some(guild) = settings.guilds.get(&guild_id) else { error!(%guild_id, "no such guild"); - return Err(Redirect::to("/")); + return Err(Redirect::to(&format!("{}/", state.origin))); }; let Some(guild_user) = guild.users.get(&user.name) else { error!(%guild_id, %user.name, "no user in guild"); - return Err(Redirect::to("/")); + return Err(Redirect::to(&format!("{}/", state.origin))); }; let is_moderator = guild_user.permissions.can(auth::Permission::DeleteSounds); Ok(Html( HtmxBuilder::new(Tag::Html) - .head(|b| { - b.title("MemeJoin - Dashboard") - .script( - "https://unpkg.com/htmx.org@1.9.3", - Some("sha384-lVb3Rd/Ca0AxaoZg5sACe8FJKF0tnUgR2Kd7ehUOG5GCcROv5uBIZsOqovBAcWua"), - ) - .script("https://unpkg.com/hyperscript.org@0.9.9", None) - .style_link("https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css") - }) + .push_builder(page_header("MemeJoin - Dashboard")) .builder(Tag::Nav, |b| { - b.builder(Tag::Header1, |b| b.text("MemeJoin - A bot for user intros")) - .builder_text(Tag::Paragraph, &user.name) + b.builder(Tag::HeaderGroup, |b| { + b.attribute("class", "container") + .builder(Tag::Header1, |b| b.text("MemeJoin - A bot for user intros")) + .builder_text(Tag::Header6, &user.name) + }) }) - .builder(Tag::Main, |b| { + .builder(Tag::Empty, |b| { if is_moderator { - b.builder(Tag::Article, |b| { - b.builder_text(Tag::Header, "Wow, you're a moderator") + b.builder(Tag::Div, |b| { + b.attribute("class", "container") + .builder(Tag::Article, |b| { + b.builder_text(Tag::Header, "Wow, you're a moderator") + .push_builder(moderator_dashboard()) + .builder_text(Tag::Footer, "End of super cool mod section") + }) }) } else { b } - .builder(Tag::Article, |b| { - let mut b = b.builder_text(Tag::Header, "Guild Settings"); + .builder(Tag::Div, |b| { + b.attribute("class", "container") + .builder(Tag::Article, |b| { + let mut b = b.builder_text(Tag::Header, "Guild Settings"); - for (channel_name, channel_settings) in &guild.channels { - if let Some(channel_user) = channel_settings.users.get(&user.name) { - let current_intros = - channel_user.intros.iter().filter_map(|intro_index| { - Some(( - &intro_index.index, - guild.intros.get(&intro_index.index)?, - )) - }); - let available_intros = guild.intros.iter().filter_map(|intro| { - if !channel_user - .intros - .iter() - .any(|intro_index| intro.0 == &intro_index.index) - { - Some((intro.0, intro.1)) - } else { - None + for (channel_name, channel_settings) in &guild.channels { + if let Some(channel_user) = channel_settings.users.get(&user.name) { + let current_intros = + channel_user.intros.iter().filter_map(|intro_index| { + Some(( + &intro_index.index, + guild.intros.get(&intro_index.index)?, + )) + }); + let available_intros = + guild.intros.iter().filter_map(|intro| { + if !channel_user + .intros + .iter() + .any(|intro_index| intro.0 == &intro_index.index) + { + Some((intro.0, intro.1)) + } else { + None + } + }); + b = b.builder_text(Tag::Strong, channel_name).builder( + Tag::Div, + |b| { + b.builder_text(Tag::Strong, "Your Current Intros") + .push_builder(intro_list( + current_intros, + "Remove Intro", + &format!( + "{}/v2/intros/remove/{}/{}", + state.origin, guild_id, channel_name + ), + )) + .builder_text(Tag::Strong, "Select Intros") + .push_builder(intro_list( + available_intros, + "Add Intro", + &format!( + "{}/v2/intros/add/{}/{}", + state.origin, guild_id, channel_name + ), + )) + }, + ); } - }); - b = b - .builder_text(Tag::Strong, channel_name) - .builder(Tag::Div, |b| { - b.builder_text(Tag::Strong, "Your Current Intros") - .push_builder(intro_list( - current_intros, - "Remove Intro", - &format!( - "/v2/intros/remove/{}/{}", - guild_id, channel_name - ), - )) - .builder_text(Tag::Strong, "Select Intros") - .push_builder(intro_list( - available_intros, - "Add Intro", - &format!( - "/v2/intros/add/{}/{}", - guild_id, channel_name - ), - )) - }); - } - } + } - b + b + }) }) }) .build(), )) } +fn moderator_dashboard() -> HtmxBuilder { + HtmxBuilder::new(Tag::Empty) +} + pub(crate) async fn login(State(state): State) -> Html { let authorize_uri = format!("https://discord.com/api/oauth2/authorize?client_id={}&redirect_uri={}/v2/auth&response_type=code&scope=guilds.members.read%20guilds%20identify", state.secrets.client_id, state.origin); Html( HtmxBuilder::new(Tag::Html) - .head(|b| { - b.title("MemeJoin - Login") - .script( - "https://unpkg.com/htmx.org@1.9.3", - Some("sha384-lVb3Rd/Ca0AxaoZg5sACe8FJKF0tnUgR2Kd7ehUOG5GCcROv5uBIZsOqovBAcWua"), - ) - .script("https://unpkg.com/hyperscript.org@0.9.9", None) - .style_link("https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css") - }) + .push_builder(page_header("MemeJoin - Login")) .link("Login", &authorize_uri) .build(), ) -- 2.40.1 From a15a1820a80b09c3c6bc233323fc29c5131cd764 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 31 Jul 2023 23:21:57 -0500 Subject: [PATCH 02/10] add guild list to home page --- src/page.rs | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/page.rs b/src/page.rs index d55f6ed..912656f 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,7 +1,7 @@ use crate::{ auth::{self, User}, htmx::{Build, HtmxBuilder, Tag}, - settings::{ApiState, Intro, IntroFriendlyName}, + settings::{ApiState, GuildSettings, Intro, IntroFriendlyName}, }; use axum::{ extract::{Path, State}, @@ -22,14 +22,51 @@ fn page_header(title: &str) -> HtmxBuilder { }) } -pub(crate) async fn home(State(state): State, user: Option) -> Redirect { - if user.is_some() { - Redirect::to(&format!("{}/guild/588149178912473103", state.origin)) +pub(crate) async fn home( + State(state): State, + user: Option, +) -> Result, Redirect> { + if let Some(user) = user { + let settings = state.settings.lock().await; + + let guild = settings + .guilds + .iter() + .filter(|(_, guild_settings)| guild_settings.users.contains_key(&user.name)); + + Ok(Html( + page_header("MemeJoin - Home") + .builder(Tag::Div, |b| { + b.attribute("class", "container") + .builder_text(Tag::Header2, "Choose a Guild") + .push_builder(guild_list(&state.origin, guild)) + }) + .build(), + )) } else { - Redirect::to(&format!("{}/login", state.origin)) + Err(Redirect::to(&format!("{}/login", state.origin))) } } +fn guild_list<'a>( + origin: &str, + guilds: impl Iterator, +) -> HtmxBuilder { + HtmxBuilder::new(Tag::Empty).ul(|b| { + let mut b = b; + for (guild_id, guild_settings) in guilds { + b = b.li(|b| { + b.link( + &format!("Guild - {}", guild_settings.name), + &format!("{}/guild/{}", origin, guild_id), + ) + }); + } + + b + }) +} + fn intro_list<'a>( intros: impl Iterator, label: &str, -- 2.40.1 From bd3d71ae16083be590a4434c5b67fffc2cb02dad Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 31 Jul 2023 23:36:07 -0500 Subject: [PATCH 03/10] make channels more easily definable --- src/page.rs | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/page.rs b/src/page.rs index 912656f..9c1c3eb 100644 --- a/src/page.rs +++ b/src/page.rs @@ -162,29 +162,31 @@ pub(crate) async fn guild_dashboard( None } }); - b = b.builder_text(Tag::Strong, channel_name).builder( - Tag::Div, - |b| { - b.builder_text(Tag::Strong, "Your Current Intros") - .push_builder(intro_list( - current_intros, - "Remove Intro", - &format!( - "{}/v2/intros/remove/{}/{}", - state.origin, guild_id, channel_name - ), - )) - .builder_text(Tag::Strong, "Select Intros") - .push_builder(intro_list( - available_intros, - "Add Intro", - &format!( - "{}/v2/intros/add/{}/{}", - state.origin, guild_id, channel_name - ), - )) - }, - ); + b = b.builder(Tag::Article, |b| { + b.builder_text(Tag::Header, channel_name).builder( + Tag::Div, + |b| { + b.builder_text(Tag::Strong, "Your Current Intros") + .push_builder(intro_list( + current_intros, + "Remove Intro", + &format!( + "{}/v2/intros/remove/{}/{}", + state.origin, guild_id, channel_name + ), + )) + .builder_text(Tag::Strong, "Select Intros") + .push_builder(intro_list( + available_intros, + "Add Intro", + &format!( + "{}/v2/intros/add/{}/{}", + state.origin, guild_id, channel_name + ), + )) + }, + ) + }); } } -- 2.40.1 From 06ed48f4cfa5f6154dabe0b0a06f6f6b4a91a1e5 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 31 Jul 2023 23:40:37 -0500 Subject: [PATCH 04/10] support svelt login page --- src/page.rs | 2 +- src/routes.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/page.rs b/src/page.rs index 9c1c3eb..a6e067d 100644 --- a/src/page.rs +++ b/src/page.rs @@ -57,7 +57,7 @@ fn guild_list<'a>( for (guild_id, guild_settings) in guilds { b = b.li(|b| { b.link( - &format!("Guild - {}", guild_settings.name), + &guild_settings.name, &format!("{}/guild/{}", origin, guild_id), ) }); diff --git a/src/routes.rs b/src/routes.rs index dff6894..ae10ac7 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -240,7 +240,7 @@ pub(crate) async fn auth( let mut data = HashMap::new(); - let redirect_uri = format!("{}/auth", state.origin); + let redirect_uri = format!("{}/old/auth", state.origin); data.insert("client_id", state.secrets.client_id.as_str()); data.insert("client_secret", state.secrets.client_secret.as_str()); data.insert("grant_type", "authorization_code"); -- 2.40.1 From 83a0eadf6d0ae7dc9268626097d3c165c62aec53 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 31 Jul 2023 23:44:03 -0500 Subject: [PATCH 05/10] TESTING --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8e8ddf5..0f6f933 100644 --- a/flake.nix +++ b/flake.nix @@ -8,7 +8,7 @@ outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system: let - tag = "v0.1.4_4-alpha"; + tag = "super_test"; overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; -- 2.40.1 From 25bb24694c890db9e920aabba65ab18e9bf12186 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Tue, 1 Aug 2023 00:09:22 -0500 Subject: [PATCH 06/10] redirect correctly on login, and save cookie to proper path --- src/routes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes.rs b/src/routes.rs index ae10ac7..2922df6 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -222,10 +222,10 @@ pub(crate) async fn v2_auth( // TODO: add permissions based on roles let mut cookie = Cookie::new("access_token", token.clone()); - cookie.set_path("/"); + cookie.set_path(format!("{}/", state.origin)); cookie.set_secure(true); - Ok((jar.add(cookie), Redirect::to("/"))) + Ok((jar.add(cookie), Redirect::to(&format!("{}/", state.origin)))) } pub(crate) async fn auth( -- 2.40.1 From 17ec2185d07e717d16ac63d79d1e0715621e371f Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Tue, 1 Aug 2023 00:12:01 -0500 Subject: [PATCH 07/10] add link to old UI for moderators to access un-ported features --- src/page.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/page.rs b/src/page.rs index a6e067d..b4ec59b 100644 --- a/src/page.rs +++ b/src/page.rs @@ -129,7 +129,7 @@ pub(crate) async fn guild_dashboard( b.attribute("class", "container") .builder(Tag::Article, |b| { b.builder_text(Tag::Header, "Wow, you're a moderator") - .push_builder(moderator_dashboard()) + .push_builder(moderator_dashboard(&state)) .builder_text(Tag::Footer, "End of super cool mod section") }) }) @@ -198,8 +198,8 @@ pub(crate) async fn guild_dashboard( )) } -fn moderator_dashboard() -> HtmxBuilder { - HtmxBuilder::new(Tag::Empty) +fn moderator_dashboard(state: &ApiState) -> HtmxBuilder { + HtmxBuilder::new(Tag::Empty).link("Go back to old UI", &format!("{}/old", state.origin)) } pub(crate) async fn login(State(state): State) -> Html { -- 2.40.1 From 9a832a5aac860cf852e6a82e9f76828d9fa7964a Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Tue, 1 Aug 2023 11:55:18 -0500 Subject: [PATCH 08/10] only set path to relative --- src/routes.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/routes.rs b/src/routes.rs index 2922df6..92a22b5 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -9,7 +9,7 @@ use axum::{ }; use axum_extra::extract::{cookie::Cookie, CookieJar}; -use reqwest::{Proxy, StatusCode}; +use reqwest::{Proxy, StatusCode, Url}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; use tracing::{error, info}; @@ -221,8 +221,10 @@ pub(crate) async fn v2_auth( ); // TODO: add permissions based on roles + let uri = Url::parse(&state.origin).expect("should be a valid url"); + let mut cookie = Cookie::new("access_token", token.clone()); - cookie.set_path(format!("{}/", state.origin)); + cookie.set_path(uri.path().to_string()); cookie.set_secure(true); Ok((jar.add(cookie), Redirect::to(&format!("{}/", state.origin)))) -- 2.40.1 From 816d68cbe1e152c06d0f42b43bc208aa7c89efc8 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Tue, 1 Aug 2023 14:25:50 -0500 Subject: [PATCH 09/10] update title of intros list --- src/page.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page.rs b/src/page.rs index b4ec59b..0b5f3f4 100644 --- a/src/page.rs +++ b/src/page.rs @@ -139,7 +139,7 @@ pub(crate) async fn guild_dashboard( .builder(Tag::Div, |b| { b.attribute("class", "container") .builder(Tag::Article, |b| { - let mut b = b.builder_text(Tag::Header, "Guild Settings"); + let mut b = b.builder_text(Tag::Header, "Guild Intros"); for (channel_name, channel_settings) in &guild.channels { if let Some(channel_user) = channel_settings.users.get(&user.name) { -- 2.40.1 From 90eceab11dba341a6e192f463e89c0a83dd99c1c Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Tue, 1 Aug 2023 14:26:49 -0500 Subject: [PATCH 10/10] update flake version/tag --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 0f6f933..2d32066 100644 --- a/flake.nix +++ b/flake.nix @@ -8,7 +8,7 @@ outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system: let - tag = "super_test"; + tag = "v0.1.5-alpha"; overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; -- 2.40.1