Update schemas and resolve some warnings

This commit is contained in:
jude 2024-07-16 10:42:32 +01:00
parent 54ee3594eb
commit febd04c374
26 changed files with 221 additions and 164 deletions

4
Cargo.lock generated
View File

@ -2645,9 +2645,9 @@ dependencies = [
[[package]] [[package]]
name = "rocket_dyn_templates" name = "rocket_dyn_templates"
version = "0.1.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04bfc006e547e4f72b760ab861f5943b688aed8a82c4977b5500c98f5d17dbfa" checksum = "5bbab919c9e67df3f7ac6624a32ef897df4cd61c0969f4d66f3ced0534660d7a"
dependencies = [ dependencies = [
"normpath", "normpath",
"notify", "notify",

View File

@ -30,7 +30,7 @@ secrecy = "0.8.0"
futures = "0.3.30" futures = "0.3.30"
prometheus = "0.13.3" prometheus = "0.13.3"
rocket = { version = "0.5.0", features = ["tls", "secrets", "json"] } rocket = { version = "0.5.0", features = ["tls", "secrets", "json"] }
rocket_dyn_templates = { version = "0.1.0", features = ["tera"] } rocket_dyn_templates = { version = "0.2.0", features = ["tera"] }
serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] } serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
oauth2 = "4" oauth2 = "4"
csv = "1.2" csv = "1.2"

View File

@ -136,9 +136,9 @@ CREATE TABLE reminders (
set_by INT UNSIGNED, set_by INT UNSIGNED,
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE RESTRICT, CONSTRAINT `reminder_message_fk` FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE RESTRICT,
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE, CONSTRAINT `reminder_channel_fk` FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE,
FOREIGN KEY (set_by) REFERENCES users(id) ON DELETE SET NULL CONSTRAINT `reminder_user_fk` FOREIGN KEY (set_by) REFERENCES users(id) ON DELETE SET NULL
); );
CREATE TRIGGER message_cleanup AFTER DELETE ON reminders CREATE TRIGGER message_cleanup AFTER DELETE ON reminders
@ -157,9 +157,9 @@ CREATE TABLE todos (
value VARCHAR(2000) NOT NULL, value VARCHAR(2000) NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL, CONSTRAINT todos_ibfk_5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE, CONSTRAINT todos_ibfk_4 FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE SET NULL CONSTRAINT todos_ibfk_3 FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE SET NULL
); );
CREATE TABLE command_restrictions ( CREATE TABLE command_restrictions (

View File

@ -46,7 +46,7 @@ CREATE TABLE reminders_new (
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY (`channel_id`) REFERENCES channels (`id`) ON DELETE CASCADE, FOREIGN KEY (`channel_id`) REFERENCES channels (`id`) ON DELETE CASCADE,
FOREIGN KEY (`set_by`) REFERENCES users (`id`) ON DELETE SET NULL CONSTRAINT `reminders_ibfk_2` FOREIGN KEY (`set_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
# disallow having a reminder as restartable if it has no interval # disallow having a reminder as restartable if it has no interval
-- , CONSTRAINT restartable_interval_mutex CHECK (`restartable` = 0 OR `interval` IS NULL) -- , CONSTRAINT restartable_interval_mutex CHECK (`restartable` = 0 OR `interval` IS NULL)

View File

@ -1,3 +1,7 @@
-- Tables no longer needed as old dashboard is decomm.
DROP TABLE guild_users;
DROP TABLE events;
ALTER TABLE users ADD COLUMN `reset_inputs_on_create` BOOLEAN NOT NULL DEFAULT 0; 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 `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 ADD COLUMN `dashboard_color_scheme` ENUM('system', 'light', 'dark') NOT NULL DEFAULT 'system';
@ -7,4 +11,14 @@ ALTER TABLE users DROP COLUMN `patreon`;
ALTER TABLE users DROP COLUMN `name`; ALTER TABLE users DROP COLUMN `name`;
ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (`user`); ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (`user`);
ALTER TABLE todos DROP CONSTRAINT todos_ibfk_5, MODIFY COLUMN user_id BIGINT UNSIGNED;
UPDATE todos SET user_id = (SELECT user FROM users WHERE id = user_id);
ALTER TABLE todos ADD CONSTRAINT todos_user_fk FOREIGN KEY (user_id) REFERENCES users(user);
ALTER TABLE reminders DROP CONSTRAINT reminders_ibfk_2, MODIFY COLUMN set_by BIGINT UNSIGNED;
UPDATE reminders SET set_by = (SELECT user FROM users WHERE id = set_by);
ALTER TABLE reminders ADD CONSTRAINT reminder_user_fk FOREIGN KEY (set_by) REFERENCES users(user);
ALTER TABLE users DROP COLUMN `id`;
ALTER TABLE users RENAME COLUMN `user` TO `id`; ALTER TABLE users RENAME COLUMN `user` TO `id`;

View File

@ -22,7 +22,6 @@
<title>Reminder Bot | Dashboard</title> <title>Reminder Bot | Dashboard</title>
<!-- styles --> <!-- styles -->
<link rel="stylesheet" href="/static/css/bulma.min.css">
<link rel="stylesheet" href="/static/css/fa.css"> <link rel="stylesheet" href="/static/css/fa.css">
<link rel="stylesheet" href="/static/css/font.css"> <link rel="stylesheet" href="/static/css/font.css">
<link rel="stylesheet" href="/static/css/style.css"> <link rel="stylesheet" href="/static/css/style.css">

View File

@ -1,10 +1,27 @@
import axios from "axios"; import axios from "axios";
enum ColorScheme {
System = "system",
Dark = "dark",
Light = "light",
}
type UserInfo = { type UserInfo = {
name: string; name: string;
patreon: boolean; patreon: boolean;
timezone: string | null; preferences: {
reset_inputs_on_create: boolean; timezone: string | null;
reset_inputs_on_create: boolean;
dashboard_color_scheme: ColorScheme;
use_browser_timezone: boolean;
};
};
type UpdateUserInfo = {
timezone?: string;
reset_inputs_on_create?: boolean;
dashboard_color_scheme?: ColorScheme;
use_browser_timezone?: boolean;
}; };
export type GuildInfo = { export type GuildInfo = {
@ -110,7 +127,7 @@ export const fetchUserInfo = () => ({
}); });
export const patchUserInfo = () => ({ export const patchUserInfo = () => ({
mutationFn: (timezone: string) => axios.patch(`/dashboard/api/user`, { timezone }), mutationFn: (userInfo: UpdateUserInfo) => axios.patch(`/dashboard/api/user`, userInfo),
}); });
export const fetchUserGuilds = () => ({ export const fetchUserGuilds = () => ({

View File

@ -1,15 +1,27 @@
import { createContext } from "preact"; import { createContext } from "preact";
import { useContext } from "preact/compat"; import { useContext } from "preact/compat";
import { useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { fetchUserInfo } from "../../api";
import { useQuery } from "react-query";
type TTimezoneContext = [string, (tz: string) => void]; type TTimezoneContext = [string, (tz: string) => void];
const TimezoneContext = createContext(["UTC", () => {}] as TTimezoneContext); const TimezoneContext = createContext(["UTC", () => {}] as TTimezoneContext);
export const TimezoneProvider = ({ children }) => { export const TimezoneProvider = ({ children }) => {
const { data } = useQuery({ ...fetchUserInfo() });
const [timezone, setTimezone] = useState(DateTime.now().zoneName); const [timezone, setTimezone] = useState(DateTime.now().zoneName);
useEffect(() => {
setTimezone(
data === undefined || data.preferences.use_browser_timezone
? DateTime.now().zoneName
: data.preferences.timezone,
);
}, [data]);
return ( return (
<TimezoneContext.Provider value={[timezone, setTimezone]}> <TimezoneContext.Provider value={[timezone, setTimezone]}>
{children} {children}

View File

@ -13,14 +13,14 @@ export function App() {
const queryClient = new QueryClient(); const queryClient = new QueryClient();
let scheme = "light"; let scheme = "light";
if (window.matchMedia("(prefers-color-scheme: dark)").matches) { // if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
scheme = "dark"; // scheme = "dark";
} // }
return ( return (
<TimezoneProvider> <QueryClientProvider client={queryClient}>
<FlashProvider> <TimezoneProvider>
<QueryClientProvider client={queryClient}> <FlashProvider>
<Router base={"/dashboard"}> <Router base={"/dashboard"}>
<div class={`columns is-gapless dashboard-frame scheme-${scheme}`}> <div class={`columns is-gapless dashboard-frame scheme-${scheme}`}>
<Sidebar /> <Sidebar />
@ -52,8 +52,8 @@ export function App() {
</div> </div>
</div> </div>
</Router> </Router>
</QueryClientProvider> </FlashProvider>
</FlashProvider> </TimezoneProvider>
</TimezoneProvider> </QueryClientProvider>
); );
} }

View File

@ -11,7 +11,7 @@ import { useGuild } from "../App/useGuild";
export const Settings = () => { export const Settings = () => {
const guild = useGuild(); const guild = useGuild();
const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo()); const { isSuccess: userFetched, data: userInfo } = useQuery({ ...fetchUserInfo() });
const [reminder, setReminder] = useReminder(); const [reminder, setReminder] = useReminder();

View File

@ -26,3 +26,11 @@
textarea.autoresize { textarea.autoresize {
resize: vertical !important; resize: vertical !important;
} }
div.reminderContent {
margin-top: 10px;
margin-bottom: 10px;
padding: 14px;
background-color: #f5f5f5;
border-radius: 8px;
}

View File

@ -24,7 +24,7 @@ const SidebarContent = ({ guilds }: ContentProps) => {
<Brand /> <Brand />
</a> </a>
<Wave /> <Wave />
<aside class="menu"> <aside class="menu theme-dark">
<ul class="menu-list"> <ul class="menu-list">
<li> <li>
<Link <Link
@ -44,7 +44,6 @@ const SidebarContent = ({ guilds }: ContentProps) => {
style={{ style={{
position: "sticky", position: "sticky",
bottom: "0px", bottom: "0px",
backgroundColor: "rgb(54, 54, 54)",
}} }}
> >
<p class="menu-label">Options</p> <p class="menu-label">Options</p>

View File

@ -39,7 +39,7 @@ aside.menu {
} }
.dashboard-sidebar { .dashboard-sidebar {
display: flex; display: flex !important;
flex-direction: column; flex-direction: column;
background-color: #363636; background-color: #363636;
width: 230px !important; width: 230px !important;
@ -49,3 +49,19 @@ aside.menu {
.aside-footer { .aside-footer {
justify-self: end; justify-self: end;
} }
.menu a {
color: #fff !important;
}
.menu a:hover {
color: #424242 !important;
}
.menu .menu-label {
color: #bbb;
}
.menu {
padding-left: 4px;
}

View File

@ -53,10 +53,10 @@ export const TimezonePicker = () => {
const TimezoneModal = ({ setModalOpen }) => { const TimezoneModal = ({ setModalOpen }) => {
const browserTimezone = DateTime.now().zoneName; const browserTimezone = DateTime.now().zoneName;
const [selectedZone] = useTimezone(); const [selectedZone, setTimezone] = useTimezone();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { isLoading, isError, data } = useQuery(fetchUserInfo()); const { isLoading, isError, data } = useQuery({ ...fetchUserInfo() });
const userInfoMutation = useMutation({ const userInfoMutation = useMutation({
...patchUserInfo(), ...patchUserInfo(),
onSuccess: () => { onSuccess: () => {
@ -79,7 +79,7 @@ const TimezoneModal = ({ setModalOpen }) => {
{isLoading ? ( {isLoading ? (
<i className="fas fa-cog fa-spin"></i> <i className="fas fa-cog fa-spin"></i>
) : ( ) : (
<TimezoneDisplay timezone={data.timezone || "UTC"}></TimezoneDisplay> <TimezoneDisplay timezone={data.preferences.timezone || "UTC"} />
)} )}
</> </>
)} )}
@ -93,10 +93,29 @@ const TimezoneModal = ({ setModalOpen }) => {
margin: "2px", margin: "2px",
}} }}
onClick={() => { onClick={() => {
userInfoMutation.mutate(browserTimezone); userInfoMutation.mutate({ timezone: browserTimezone });
}} }}
> >
Set Bot Timezone Set bot timezone
</button>
<button
class="button is-success is-outlined"
id="update-bot-timezone"
style={{
margin: "2px",
}}
onClick={() => {
userInfoMutation.mutate({
use_browser_timezone: !data.preferences.use_browser_timezone,
});
setTimezone(
data.preferences.use_browser_timezone
? data.preferences.timezone
: DateTime.now().zoneName,
);
}}
>
Use {data.preferences.use_browser_timezone ? "bot" : "browser"} timezone
</button> </button>
</div> </div>
</Modal> </Modal>

View File

@ -1,3 +1,5 @@
@import "node_modules/bulma/bulma";
/* override styles for when the div is collapsed */ /* override styles for when the div is collapsed */
div.reminderContent.is-collapsed .column.discord-frame { div.reminderContent.is-collapsed .column.discord-frame {
display: none; display: none;
@ -47,3 +49,11 @@ div.reminderContent.is-collapsed .hide-box {
div.reminderContent.is-collapsed .hide-box i { div.reminderContent.is-collapsed .hide-box i {
transform: rotate(90deg); transform: rotate(90deg);
} }
.button.is-success:not(.is-outlined) {
color: white;
}
.button.is-outlined.is-success:not(.is-focused, :hover, :focus) {
background-color: white;
}

View File

@ -0,0 +1,13 @@
$primary-background-light: #ffffff;
$secondary-background-light: #f5f5f5;
$contrast-background-light: #363636;
$primary-text-light: #4a4a4a;
$secondary-text-light: #4a4a4a;
$contrast-text-light: #ffffff;
$primary-background-dark: #363636;
$secondary-background-dark: #424242;
$contrast-background-dark: #242424;
$primary-text-dark: #ffffff;
$secondary-text-dark: #ffffff;
$contrast-text-dark: #ffffff;

View File

@ -17,10 +17,7 @@ impl Recordable for Options {
sqlx::query!( sqlx::query!(
" "
INSERT INTO todos (user_id, value) INSERT INTO todos (user_id, value)
VALUES ( VALUES (?, ?)
(SELECT id FROM users WHERE user = ?),
?
)
", ",
ctx.author().id.get(), ctx.author().id.get(),
self.task self.task

View File

@ -14,8 +14,7 @@ impl Recordable for Options {
let values = sqlx::query!( let values = sqlx::query!(
" "
SELECT todos.id, value FROM todos SELECT todos.id, value FROM todos
INNER JOIN users ON todos.user_id = users.id WHERE user_id = ?
WHERE users.user = ?
", ",
ctx.author().id.get(), ctx.author().id.get(),
) )

View File

@ -191,8 +191,7 @@ impl ComponentDataModel {
sqlx::query!( sqlx::query!(
" "
SELECT todos.id, value FROM todos SELECT todos.id, value FROM todos
INNER JOIN users ON todos.user_id = users.id WHERE user_id = ?
WHERE users.user = ?
", ",
uid, uid,
) )
@ -285,10 +284,9 @@ impl ComponentDataModel {
let values = if let Some(uid) = selector.user_id { let values = if let Some(uid) = selector.user_id {
sqlx::query!( sqlx::query!(
" "
SELECT todos.id, value FROM todos SELECT todos.id, value FROM todos
INNER JOIN users ON todos.user_id = users.id WHERE user_id = ?
WHERE users.user = ? ",
",
uid, uid,
) )
.fetch_all(&data.database) .fetch_all(&data.database)

View File

@ -1,6 +1,6 @@
use poise::{ use poise::{
serenity_prelude as serenity, serenity_prelude as serenity,
serenity_prelude::{ActivityData, CreateEmbed, CreateMessage, FullEvent}, serenity_prelude::{CreateEmbed, CreateMessage, FullEvent},
}; };
use crate::{ use crate::{

View File

@ -1,4 +1,4 @@
use poise::{serenity_prelude::model::channel::Channel, CommandInteractionType, CreateReply}; use poise::{CommandInteractionType, CreateReply};
use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error}; use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error};

View File

@ -85,17 +85,13 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
INNER JOIN INNER JOIN
channels channels
ON ON
reminders.channel_id = channels.id reminders.channel_id = channels.id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
reminders.uid = ? reminders.uid = ?
", ",
@ -122,17 +118,13 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
INNER JOIN INNER JOIN
channels channels
ON ON
reminders.channel_id = channels.id reminders.channel_id = channels.id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
reminders.id = ? reminders.id = ?
", ",
@ -166,17 +158,13 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
INNER JOIN INNER JOIN
channels channels
ON ON
reminders.channel_id = channels.id reminders.channel_id = channels.id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND `status` = 'pending' AND
channels.channel = ? AND channels.channel = ? AND
@ -230,17 +218,13 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
LEFT JOIN LEFT JOIN
channels channels
ON ON
channels.id = reminders.channel_id channels.id = reminders.channel_id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND `status` = 'pending' AND
FIND_IN_SET(channels.channel, ?) FIND_IN_SET(channels.channel, ?)
@ -266,17 +250,13 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
LEFT JOIN LEFT JOIN
channels channels
ON ON
channels.id = reminders.channel_id channels.id = reminders.channel_id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND `status` = 'pending' AND
channels.guild_id = (SELECT id FROM guilds WHERE guild = ?) channels.guild_id = (SELECT id FROM guilds WHERE guild = ?)
@ -303,20 +283,16 @@ impl Reminder {
reminders.enabled, reminders.enabled,
reminders.content, reminders.content,
reminders.embed_description, reminders.embed_description,
users.user AS set_by reminders.set_by
FROM FROM
reminders reminders
INNER JOIN INNER JOIN
channels channels
ON ON
channels.id = reminders.channel_id channels.id = reminders.channel_id
LEFT JOIN
users
ON
reminders.set_by = users.id
WHERE WHERE
`status` = 'pending' AND `status` = 'pending' AND
channels.id = (SELECT dm_channel FROM users WHERE user = ?) channels.id = (SELECT dm_channel FROM users WHERE id = ?)
", ",
user.get() user.get()
) )

View File

@ -16,17 +16,15 @@ pub async fn get_guild_roles(id: u64, cookies: &CookieJar<'_>, ctx: &State<Conte
offline!(Ok(json!(vec![RoleInfo { name: "@everyone".to_string(), id: "1".to_string() }]))); offline!(Ok(json!(vec![RoleInfo { name: "@everyone".to_string(), id: "1".to_string() }])));
check_authorization(cookies, ctx.inner(), id).await?; check_authorization(cookies, ctx.inner(), id).await?;
let roles_res = ctx.cache.guild_roles(id); let roles_res = ctx.cache.guild(id).map(|g| {
g.roles
.iter()
.map(|(_, r)| RoleInfo { id: r.id.to_string(), name: r.name.to_string() })
.collect::<Vec<RoleInfo>>()
});
match roles_res { match roles_res {
Some(roles) => { Some(roles) => Ok(json!(roles)),
let roles = roles
.iter()
.map(|(_, r)| RoleInfo { id: r.id.to_string(), name: r.name.to_string() })
.collect::<Vec<RoleInfo>>();
Ok(json!(roles))
}
None => { None => {
warn!("Could not fetch roles from {}", id); warn!("Could not fetch roles from {}", id);

View File

@ -6,6 +6,7 @@ use std::env;
use chrono_tz::Tz; use chrono_tz::Tz;
pub use guilds::*; pub use guilds::*;
use log::warn;
pub use reminders::*; pub use reminders::*;
use rocket::{ use rocket::{
get, get,
@ -57,7 +58,7 @@ pub async fn get_user_info(
patreon: true, patreon: true,
preferences: UserPreferences { preferences: UserPreferences {
timezone: "UTC".to_string(), timezone: "UTC".to_string(),
use_browser_timezone: false, use_browser_timezone: true,
dashboard_color_scheme: "system".to_string(), dashboard_color_scheme: "system".to_string(),
reset_inputs_on_create: false, reset_inputs_on_create: false,
} }
@ -70,10 +71,10 @@ pub async fn get_user_info(
.member(&ctx.inner(), user_id) .member(&ctx.inner(), user_id)
.await; .await;
let prefs = sqlx::query!( let preferences = sqlx::query!(
" "
SELECT SELECT
IFNULL(timezone, 'UTC') AS timezone, timezone,
use_browser_timezone, use_browser_timezone,
dashboard_color_scheme, dashboard_color_scheme,
reset_inputs_on_create reset_inputs_on_create
@ -84,7 +85,20 @@ pub async fn get_user_info(
) )
.fetch_one(pool.inner()) .fetch_one(pool.inner())
.await .await
.map_or(None, |q| Some(q.timezone)); .map_or(
UserPreferences {
timezone: "UTC".to_string(),
use_browser_timezone: false,
dashboard_color_scheme: "system".to_string(),
reset_inputs_on_create: false,
},
|q| UserPreferences {
timezone: q.timezone,
use_browser_timezone: q.use_browser_timezone != 0,
dashboard_color_scheme: q.dashboard_color_scheme,
reset_inputs_on_create: q.reset_inputs_on_create != 0,
},
);
let user_info = UserInfo { let user_info = UserInfo {
name: cookies name: cookies
@ -95,12 +109,7 @@ pub async fn get_user_info(
.roles .roles
.contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap())) .contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap()))
}), }),
preferences: UserPreferences { preferences,
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) json!(user_info)
@ -137,7 +146,7 @@ pub async fn update_user_info(
} }
if let Some(dashboard_color_scheme) = &preferences.dashboard_color_scheme { if let Some(dashboard_color_scheme) = &preferences.dashboard_color_scheme {
if vec!["system", "light", "dark"].contains(dashboard_color_scheme) { if vec!["system", "light", "dark"].contains(&dashboard_color_scheme.as_str()) {
let _ = sqlx::query!( let _ = sqlx::query!(
" "
UPDATE users UPDATE users
@ -154,10 +163,42 @@ pub async fn update_user_info(
} }
} }
// todo handle other two options if let Some(reset_inputs_on_create) = &preferences.reset_inputs_on_create {
let _ = sqlx::query!(
"
UPDATE users
SET reset_inputs_on_create = ?
WHERE id = ?
",
reset_inputs_on_create,
user_id,
)
.execute(transaction.executor())
.await;
}
transaction.commit().await; if let Some(use_browser_timezone) = &preferences.use_browser_timezone {
json!({}) let _ = sqlx::query!(
"
UPDATE users
SET use_browser_timezone = ?
WHERE id = ?
",
use_browser_timezone,
user_id,
)
.execute(transaction.executor())
.await;
}
match transaction.commit().await {
Ok(_) => json!({}),
Err(e) => {
warn!("Error updating user preferences for {}: {:?}", user_id, e);
json!({"error": "Couldn't update preferences"})
}
}
} else { } else {
json!({"error": "Not authorized"}) json!({"error": "Not authorized"})
} }

View File

@ -593,18 +593,11 @@ pub(crate) async fn create_reminder(
} }
fn check_channel_matches_guild(ctx: &Context, channel_id: ChannelId, guild_id: GuildId) -> bool { fn check_channel_matches_guild(ctx: &Context, channel_id: ChannelId, guild_id: GuildId) -> bool {
// validate channel return match ctx.cache.guild(guild_id) {
let channel = channel_id.to_channel_cached(&ctx.cache); Some(guild) => guild.channels.get(&channel_id).is_some(),
let channel_exists = channel.is_some();
if !channel_exists { None => false,
return false; };
}
let channel_matches_guild =
channel.map_or(false, |c| c.guild(&ctx.cache).map_or(false, |g| g.id == guild_id));
channel_matches_guild
} }
async fn create_database_channel( async fn create_database_channel(

View File

@ -100,14 +100,6 @@ div.split-controls {
flex-basis: 50%; flex-basis: 50%;
} }
div.reminderContent {
margin-top: 10px;
margin-bottom: 10px;
padding: 14px;
background-color: #f5f5f5;
border-radius: 8px;
}
.left-pad { .left-pad {
padding-left: 1rem; padding-left: 1rem;
padding-right: 0.2rem; padding-right: 0.2rem;
@ -214,18 +206,6 @@ div.dashboard-frame {
min-width: auto; min-width: auto;
} }
.menu a {
color: #fff;
}
.menu .menu-label {
color: #bbb;
}
.menu {
padding-left: 4px;
}
.dashboard-navbar { .dashboard-navbar {
background-color: #8fb677 !important; background-color: #8fb677 !important;
position: absolute; position: absolute;
@ -680,14 +660,6 @@ div.reminderError .reminderMessage {
margin: 0 12px 12px 12px; margin: 0 12px 12px 12px;
} }
.button.is-success:not(.is-outlined) {
color: white;
}
.button.is-outlined.is-success {
background-color: white;
}
a.switch-pane { a.switch-pane {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
@ -733,27 +705,3 @@ a.switch-pane.is-active ~ .guild-submenu {
.is-locked .field:last-of-type { .is-locked .field:last-of-type {
display: none; display: none;
} }
.stat-row {
display: flex;
flex-direction: row;
}
.stat-box {
flex-grow: 1;
border-radius: 6px;
background-color: #fcfcfc;
border-color: #efefef;
border-style: solid;
border-width: 1px;
margin: 4px;
padding: 4px;
}
.figure {
text-align: center;
}
.figure-num {
font-size: 2rem;
}