From f26682e6de83d506e87903b1b4fe18805c98faad Mon Sep 17 00:00:00 2001 From: jude Date: Thu, 4 Jul 2024 20:52:36 +0100 Subject: [PATCH] Working on user preferences for dashboards --- .../20240630150936_dashboard_preferences.sql | 10 + reminder-dashboard/src/api.ts | 1 + .../src/components/App/index.tsx | 7 +- .../Reminder/ButtonRow/CreateButtonRow.tsx | 16 +- .../components/Reminder/CreateReminder.tsx | 2 +- src/models/user_data.rs | 26 +- src/web/routes/dashboard/api/user/mod.rs | 106 ++++- templates/dashboard.html.tera | 389 ------------------ .../reminder_dashboard/guild_error.html.tera | 17 - .../guild_reminder.html.tera | 269 ------------ .../reminder_dashboard.html.tera | 52 --- .../reminder_errors.html.tera | 5 - .../reminder_dashboard/user_error.html.tera | 12 - 13 files changed, 132 insertions(+), 780 deletions(-) create mode 100644 migrations/20240630150936_dashboard_preferences.sql delete mode 100644 templates/dashboard.html.tera delete mode 100644 templates/reminder_dashboard/guild_error.html.tera delete mode 100644 templates/reminder_dashboard/guild_reminder.html.tera delete mode 100644 templates/reminder_dashboard/reminder_dashboard.html.tera delete mode 100644 templates/reminder_dashboard/reminder_errors.html.tera delete mode 100644 templates/reminder_dashboard/user_error.html.tera diff --git a/migrations/20240630150936_dashboard_preferences.sql b/migrations/20240630150936_dashboard_preferences.sql new file mode 100644 index 0000000..2069663 --- /dev/null +++ b/migrations/20240630150936_dashboard_preferences.sql @@ -0,0 +1,10 @@ +ALTER TABLE users ADD COLUMN `reset_inputs_on_create` BOOLEAN NOT NULL DEFAULT 0; +ALTER TABLE users ADD COLUMN `use_browser_timezone` BOOLEAN NOT NULL DEFAULT 1; +ALTER TABLE users ADD COLUMN `dashboard_color_scheme` ENUM('system', 'light', 'dark') NOT NULL DEFAULT 'system'; + +ALTER TABLE users DROP COLUMN `language`; +ALTER TABLE users DROP COLUMN `patreon`; +ALTER TABLE users DROP COLUMN `name`; + +ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (`user`); +ALTER TABLE users RENAME COLUMN `user` TO `id`; diff --git a/reminder-dashboard/src/api.ts b/reminder-dashboard/src/api.ts index d97ea1a..defe690 100644 --- a/reminder-dashboard/src/api.ts +++ b/reminder-dashboard/src/api.ts @@ -4,6 +4,7 @@ type UserInfo = { name: string; patreon: boolean; timezone: string | null; + reset_inputs_on_create: boolean; }; export type GuildInfo = { diff --git a/reminder-dashboard/src/components/App/index.tsx b/reminder-dashboard/src/components/App/index.tsx index a1f7bc3..8dfe394 100644 --- a/reminder-dashboard/src/components/App/index.tsx +++ b/reminder-dashboard/src/components/App/index.tsx @@ -12,12 +12,17 @@ import { GuildTodos } from "../Guild/GuildTodos"; export function App() { const queryClient = new QueryClient(); + let scheme = "light"; + if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + scheme = "dark"; + } + return ( -
+
diff --git a/reminder-dashboard/src/components/Reminder/ButtonRow/CreateButtonRow.tsx b/reminder-dashboard/src/components/Reminder/ButtonRow/CreateButtonRow.tsx index b12ca3b..31c3da5 100644 --- a/reminder-dashboard/src/components/Reminder/ButtonRow/CreateButtonRow.tsx +++ b/reminder-dashboard/src/components/Reminder/ButtonRow/CreateButtonRow.tsx @@ -1,21 +1,28 @@ import { LoadTemplate } from "../LoadTemplate"; import { useReminder } from "../ReminderContext"; -import { useMutation, useQueryClient } from "react-query"; -import { postGuildReminder, postGuildTemplate, postUserReminder } from "../../../api"; +import { useMutation, useQuery, useQueryClient } from "react-query"; +import { + fetchUserInfo, + postGuildReminder, + postGuildTemplate, + postUserReminder, +} from "../../../api"; import { useState } from "preact/hooks"; import { ICON_FLASH_TIME } from "../../../consts"; import { useFlash } from "../../App/FlashContext"; import { useGuild } from "../../App/useGuild"; +import { defaultReminder } from "../CreateReminder"; export const CreateButtonRow = () => { const guild = useGuild(); - const [reminder] = useReminder(); + const [reminder, setReminder] = useReminder(); const [recentlyCreated, setRecentlyCreated] = useState(false); const [templateRecentlyCreated, setTemplateRecentlyCreated] = useState(false); const flash = useFlash(); const queryClient = useQueryClient(); + const { data: userInfo } = useQuery({ ...fetchUserInfo() }); const mutation = useMutation({ ...(guild ? postGuildReminder(guild) : postUserReminder()), onError: (error) => { @@ -44,6 +51,9 @@ export const CreateButtonRow = () => { queryKey: ["USER_REMINDERS"], }); } + if (userInfo.reset_inputs_on_create) { + setReminder(() => defaultReminder()); + } setRecentlyCreated(true); setTimeout(() => { setRecentlyCreated(false); diff --git a/reminder-dashboard/src/components/Reminder/CreateReminder.tsx b/reminder-dashboard/src/components/Reminder/CreateReminder.tsx index cb197b6..f284558 100644 --- a/reminder-dashboard/src/components/Reminder/CreateReminder.tsx +++ b/reminder-dashboard/src/components/Reminder/CreateReminder.tsx @@ -11,7 +11,7 @@ import "./styles.scss"; import { useGuild } from "../App/useGuild"; import { DEFAULT_COLOR } from "./Embed"; -function defaultReminder(): Reminder { +export function defaultReminder(): Reminder { return { attachment: null, attachment_name: null, diff --git a/src/models/user_data.rs b/src/models/user_data.rs index e0c7588..bc30739 100644 --- a/src/models/user_data.rs +++ b/src/models/user_data.rs @@ -6,9 +6,7 @@ use sqlx::MySqlPool; use crate::consts::LOCAL_TIMEZONE; pub struct UserData { - pub id: u32, - #[allow(dead_code)] - pub user: u64, + pub id: u64, pub dm_channel: u32, pub timezone: String, pub allowed_dm: bool, @@ -23,7 +21,9 @@ impl UserData { match sqlx::query!( " - SELECT IFNULL(timezone, 'UTC') AS timezone FROM users WHERE user = ? + SELECT IFNULL(timezone, 'UTC') AS timezone + FROM users + WHERE id = ? ", user_id ) @@ -48,7 +48,9 @@ impl UserData { match sqlx::query_as_unchecked!( Self, " -SELECT id, user, dm_channel, IF(timezone IS NULL, ?, timezone) AS timezone, allowed_dm FROM users WHERE user = ? + SELECT id, dm_channel, IF(timezone IS NULL, ?, timezone) AS timezone, allowed_dm + FROM users + WHERE id = ? ", *LOCAL_TIMEZONE, user_id.get() @@ -64,7 +66,8 @@ SELECT id, user, dm_channel, IF(timezone IS NULL, ?, timezone) AS timezone, allo sqlx::query!( " -INSERT IGNORE INTO channels (channel) VALUES (?) + INSERT IGNORE INTO channels (channel) + VALUES (?) ", dm_channel.id.get() ) @@ -73,7 +76,8 @@ INSERT IGNORE INTO channels (channel) VALUES (?) sqlx::query!( " -INSERT INTO users (name, user, dm_channel, timezone) VALUES ('', ?, (SELECT id FROM channels WHERE channel = ?), ?) + INSERT INTO users (id, dm_channel, timezone) + VALUES (?, (SELECT id FROM channels WHERE channel = ?), ?) ", user_id.get(), dm_channel.id.get(), @@ -85,7 +89,9 @@ INSERT INTO users (name, user, dm_channel, timezone) VALUES ('', ?, (SELECT id F Ok(sqlx::query_as_unchecked!( Self, " -SELECT id, user, dm_channel, timezone, allowed_dm FROM users WHERE user = ? + SELECT id, dm_channel, timezone, allowed_dm + FROM users + WHERE id = ? ", user_id.get() ) @@ -104,7 +110,9 @@ SELECT id, user, dm_channel, timezone, allowed_dm FROM users WHERE user = ? pub async fn commit_changes(&self, pool: &MySqlPool) { sqlx::query!( " -UPDATE users SET timezone = ?, allowed_dm = ? WHERE id = ? + UPDATE users + SET timezone = ?, allowed_dm = ? + WHERE id = ? ", self.timezone, self.allowed_dm, diff --git a/src/web/routes/dashboard/api/user/mod.rs b/src/web/routes/dashboard/api/user/mod.rs index 073af07..388c434 100644 --- a/src/web/routes/dashboard/api/user/mod.rs +++ b/src/web/routes/dashboard/api/user/mod.rs @@ -21,16 +21,29 @@ use serenity::{ }; use sqlx::{MySql, Pool}; +use crate::web::guards::transaction::Transaction; + +#[derive(Serialize)] +struct UserPreferences { + timezone: String, + use_browser_timezone: bool, + dashboard_color_scheme: String, + reset_inputs_on_create: bool, +} + #[derive(Serialize)] struct UserInfo { name: String, patreon: bool, - timezone: Option, + preferences: UserPreferences, } #[derive(Deserialize)] -pub struct UpdateUser { - timezone: String, +pub struct UpdateUserPreferences { + timezone: Option, + use_browser_timezone: Option, + dashboard_color_scheme: Option, + reset_inputs_on_create: Option, } #[get("/api/user")] @@ -39,7 +52,16 @@ pub async fn get_user_info( ctx: &State, pool: &State>, ) -> JsonValue { - offline!(json!(UserInfo { name: "Discord".to_string(), patreon: true, timezone: None })); + offline!(json!(UserInfo { + name: "Discord".to_string(), + patreon: true, + preferences: UserPreferences { + timezone: "UTC".to_string(), + use_browser_timezone: false, + dashboard_color_scheme: "system".to_string(), + reset_inputs_on_create: false, + } + })); if let Some(user_id) = cookies.get_private("userid").map(|u| u.value().parse::().ok()).flatten() @@ -48,8 +70,16 @@ pub async fn get_user_info( .member(&ctx.inner(), user_id) .await; - let timezone = sqlx::query!( - "SELECT IFNULL(timezone, 'UTC') AS timezone FROM users WHERE user = ?", + let prefs = sqlx::query!( + " + SELECT + IFNULL(timezone, 'UTC') AS timezone, + use_browser_timezone, + dashboard_color_scheme, + reset_inputs_on_create + FROM users + WHERE id = ? + ", user_id ) .fetch_one(pool.inner()) @@ -65,7 +95,12 @@ pub async fn get_user_info( .roles .contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap())) }), - timezone, + preferences: UserPreferences { + timezone: prefs.timezone, + use_browser_timezone: prefs.use_browser_timezone, + dashboard_color_scheme: prefs.dashboard_color_scheme, + reset_inputs_on_create: prefs.reset_inputs_on_create, + }, }; json!(user_info) @@ -74,28 +109,55 @@ pub async fn get_user_info( } } -#[patch("/api/user", data = "")] +#[patch("/api/user", data = "")] pub async fn update_user_info( cookies: &CookieJar<'_>, - user: Json, - pool: &State>, + preferences: Json, + mut transaction: Transaction<'_>, ) -> JsonValue { if let Some(user_id) = cookies.get_private("userid").map(|u| u.value().parse::().ok()).flatten() { - if user.timezone.parse::().is_ok() { - let _ = sqlx::query!( - "UPDATE users SET timezone = ? WHERE user = ?", - user.timezone, - user_id, - ) - .execute(pool.inner()) - .await; - - json!({}) - } else { - json!({"error": "Timezone not recognized"}) + if let Some(timezone) = &preferences.timezone { + if timezone.parse::().is_ok() { + let _ = sqlx::query!( + " + UPDATE users + SET timezone = ? + WHERE id = ? + ", + timezone, + user_id, + ) + .execute(transaction.executor()) + .await; + } else { + return json!({"error": "Timezone not recognised"}); + } } + + if let Some(dashboard_color_scheme) = &preferences.dashboard_color_scheme { + if vec!["system", "light", "dark"].contains(dashboard_color_scheme) { + let _ = sqlx::query!( + " + UPDATE users + SET dashboard_color_scheme = ? + WHERE id = ? + ", + dashboard_color_scheme, + user_id, + ) + .execute(transaction.executor()) + .await; + } else { + return json!({"error": "Color scheme not recognised"}); + } + } + + // todo handle other two options + + transaction.commit().await; + json!({}) } else { json!({"error": "Not authorized"}) } diff --git a/templates/dashboard.html.tera b/templates/dashboard.html.tera deleted file mode 100644 index 980f318..0000000 --- a/templates/dashboard.html.tera +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Reminder Bot | Dashboard - - - - - - - - - - - - - - - - - - - - -
- -
- -
- -
- - - - - - - - - - - - - -
-
- -
- Reminder bot logo -
-
- - - - - - -
- -
- -
- Reminder bot logo -
-
- - - - - - -
- - -
-

-
-
-

Welcome!

-

Select an option from the side to get started

-

Press the to get started

-
-
- - - - -
- -
- - - - - - - - - - - - - - - - diff --git a/templates/reminder_dashboard/guild_error.html.tera b/templates/reminder_dashboard/guild_error.html.tera deleted file mode 100644 index 5d34ce1..0000000 --- a/templates/reminder_dashboard/guild_error.html.tera +++ /dev/null @@ -1,17 +0,0 @@ -
-
-
-

- We couldn't get this server's data -

-

- Please check Reminder Bot is in the server, and has correct permissions. -

- -

- Add to Server -

-
-
-
-
diff --git a/templates/reminder_dashboard/guild_reminder.html.tera b/templates/reminder_dashboard/guild_reminder.html.tera deleted file mode 100644 index 60f8d25..0000000 --- a/templates/reminder_dashboard/guild_reminder.html.tera +++ /dev/null @@ -1,269 +0,0 @@ -
-
- {% if not creating %} -
- #channel -
- {% endif %} -
-
-
- - -
-
-
-
- -
-
-
-
-
-
-

- - Image for discord avatar - -

-
-
-
-
- - -
- - - -
-
- -
-
-
-

- - Image for embed author - -

-
- -
- - -
-
- - - -
- - -
- -
-
- -
- - -
- - - -
-
-
- -
-

- - Square thumbnail embedded image - -

-
-
- -

- - Large embedded image - -

- - -
-
-
-
-
-
-
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- -
-
-
-
- Intervals available on Patreon or self-hosting -
-
- -
-
-
- - - - - - - - - -
- -
-
-
- -
-
- -
-
-
- -
-
-
- -
-
-
-
- -
-
-
-
-
-
-
- {% if creating %} -
-
- -
-
-
- -
-
- -
-
-
- {% else %} -
- - - -
- {% endif %} -
diff --git a/templates/reminder_dashboard/reminder_dashboard.html.tera b/templates/reminder_dashboard/reminder_dashboard.html.tera deleted file mode 100644 index 8849767..0000000 --- a/templates/reminder_dashboard/reminder_dashboard.html.tera +++ /dev/null @@ -1,52 +0,0 @@ -
- Create Reminder -
- {% set creating = true %} - {% include "reminder_dashboard/guild_reminder" %} - {% set creating = false %} -
-
- -
-
-
- Reminders -
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
- -
-
-
-
-
- -
- -
-
- - - diff --git a/templates/reminder_dashboard/reminder_errors.html.tera b/templates/reminder_dashboard/reminder_errors.html.tera deleted file mode 100644 index a53f2f8..0000000 --- a/templates/reminder_dashboard/reminder_errors.html.tera +++ /dev/null @@ -1,5 +0,0 @@ -
- -
- - diff --git a/templates/reminder_dashboard/user_error.html.tera b/templates/reminder_dashboard/user_error.html.tera deleted file mode 100644 index 16845f0..0000000 --- a/templates/reminder_dashboard/user_error.html.tera +++ /dev/null @@ -1,12 +0,0 @@ -
-
-
-

- You do not have permissions for this server -

-

- Ask an admin to grant you the "Manage Messages" permission. -

-
-
-