collapse individual server settings

pull/12/head
Patrick Cleavelin 2024-06-10 17:25:09 -05:00
parent d8d9fb578c
commit 13ac538ca2
2 changed files with 129 additions and 92 deletions

View File

@ -43,6 +43,22 @@ impl Database {
Ok(users) Ok(users)
} }
pub fn get_guild(&self, guild_id: u64) -> Result<String> {
let mut query = self.conn.prepare(
"
SELECT
Guild.name
FROM Guild
WHERE Guild.id = :guild_id
",
)?;
let guild_name =
query.query_row(&[(":guild_id", &guild_id.to_string())], |row| row.get(0))?;
Ok(guild_name)
}
pub(crate) fn get_guilds(&self) -> Result<Vec<Guild>> { pub(crate) fn get_guilds(&self) -> Result<Vec<Guild>> {
let mut query = self.conn.prepare( let mut query = self.conn.prepare(
" "

View File

@ -176,9 +176,15 @@ pub(crate) async fn guild_dashboard(
user: User, user: User,
Path(guild_id): Path<u64>, Path(guild_id): Path<u64>,
) -> Result<Html<String>, Redirect> { ) -> Result<Html<String>, Redirect> {
let (guild_intros, guild_channels, all_user_intros, user_permissions) = { let (guild_name, guild_intros, guild_channels, all_user_intros, user_permissions) = {
let db = state.db.lock().await; let db = state.db.lock().await;
let guild_name = db.get_guild(guild_id).map_err(|err| {
error!(?err, %guild_id, "couldn't get guild");
// TODO: change to actual error
Redirect::to(&format!("{}/login", state.origin))
})?;
let guild_intros = db.get_guild_intros(guild_id).map_err(|err| { let guild_intros = db.get_guild_intros(guild_id).map_err(|err| {
error!(?err, %guild_id, "couldn't get guild intros"); error!(?err, %guild_id, "couldn't get guild intros");
// TODO: change to actual error // TODO: change to actual error
@ -199,6 +205,7 @@ pub(crate) async fn guild_dashboard(
.unwrap_or_default(); .unwrap_or_default();
( (
guild_name,
guild_intros, guild_intros,
guild_channels, guild_channels,
all_user_intros, all_user_intros,
@ -207,8 +214,10 @@ pub(crate) async fn guild_dashboard(
}; };
let can_upload = user_permissions.can(auth::Permission::UploadSounds); let can_upload = user_permissions.can(auth::Permission::UploadSounds);
let can_add_channel = user_permissions.can(auth::Permission::AddChannel);
let is_moderator = user_permissions.can(auth::Permission::Moderator); let is_moderator = user_permissions.can(auth::Permission::Moderator);
let mod_dashboard = moderator_dashboard(&state, &state.secrets.bot_token, guild_id).await; let mod_dashboard =
moderator_dashboard(&state, &state.secrets.bot_token, guild_id, user_permissions).await;
let user_intros = all_user_intros let user_intros = all_user_intros
.iter() .iter()
@ -222,17 +231,16 @@ pub(crate) async fn guild_dashboard(
b.builder(Tag::HeaderGroup, |b| { b.builder(Tag::HeaderGroup, |b| {
b.attribute("class", "container") b.attribute("class", "container")
.builder(Tag::Header1, |b| b.text("MemeJoin - A bot for user intros")) .builder(Tag::Header1, |b| b.text("MemeJoin - A bot for user intros"))
.builder_text(Tag::Header6, &user.name) .builder_text(Tag::Header6, &format!("{} - {}", user.name, guild_name))
}) })
}) })
.builder(Tag::Empty, |b| { .builder(Tag::Empty, |b| {
let mut b = if is_moderator { let mut b = if is_moderator || can_add_channel {
b.builder(Tag::Div, |b| { b.builder(Tag::Div, |b| {
b.attribute("class", "container") b.attribute("class", "container")
.builder(Tag::Article, |b| { .builder(Tag::Article, |b| {
b.builder_text(Tag::Header, "Wow, you're a moderator") b.builder_text(Tag::Header, "Server Settings")
.push_builder(mod_dashboard) .push_builder(mod_dashboard)
.builder_text(Tag::Footer, "End of super cool mod section")
}) })
}) })
} else { } else {
@ -338,16 +346,14 @@ fn upload_form(origin: &str, guild_id: u64) -> HtmxBuilder {
.attribute("hx-encoding", "multipart/form-data") .attribute("hx-encoding", "multipart/form-data")
.builder(Tag::FieldSet, |b| { .builder(Tag::FieldSet, |b| {
b.attribute("class", "container") b.attribute("class", "container")
.attribute("role", "group")
.input(|b| b.attribute("type", "file").attribute("name", "file"))
.input(|b| { .input(|b| {
b.attribute("name", "name") b.attribute("name", "name")
.attribute("placeholder", "enter intro title") .attribute("placeholder", "enter intro title")
}) })
.label(|b| { .button(|b| b.attribute("type", "submit").text("Upload"))
b.text("Choose File")
.input(|b| b.attribute("type", "file").attribute("name", "file"))
})
}) })
.button(|b| b.attribute("type", "submit").text("Upload"))
}) })
} }
@ -357,29 +363,39 @@ fn ytdl_form(origin: &str, guild_id: u64) -> HtmxBuilder {
.hx_get(&format!("{}/v2/intros/{}/add", origin, guild_id)) .hx_get(&format!("{}/v2/intros/{}/add", origin, guild_id))
.builder(Tag::FieldSet, |b| { .builder(Tag::FieldSet, |b| {
b.attribute("class", "container") b.attribute("class", "container")
.label(|b| { .attribute("role", "group")
b.text("Video Url").input(|b| { .input(|b| {
b.attribute("placeholder", "enter video url") b.attribute("placeholder", "enter video url")
.attribute("name", "url") .attribute("name", "url")
})
}) })
.label(|b| { .input(|b| {
b.text("Intro Title").input(|b| { b.attribute("placeholder", "enter intro title")
b.attribute("placeholder", "enter intro title") .attribute("name", "name")
.attribute("name", "name")
})
}) })
.button(|b| b.attribute("type", "submit").text("Upload"))
}) })
.button(|b| b.attribute("type", "submit").text("Upload"))
}) })
} }
async fn moderator_dashboard(state: &ApiState, bot_token: &str, guild_id: u64) -> HtmxBuilder { async fn moderator_dashboard(
state: &ApiState,
bot_token: &str,
guild_id: u64,
user_permissions: auth::Permissions,
) -> HtmxBuilder {
let permissions_editor = permissions_editor(state, guild_id).await; let permissions_editor = permissions_editor(state, guild_id).await;
let channel_editor = channel_editor(state, bot_token, guild_id).await; let channel_editor = channel_editor(state, bot_token, guild_id).await;
HtmxBuilder::new(Tag::Empty)
.push_builder(permissions_editor) let mut b = HtmxBuilder::new(Tag::Empty);
.push_builder(channel_editor)
if user_permissions.can(auth::Permission::Moderator) {
b = b.push_builder(permissions_editor);
}
if user_permissions.can(auth::Permission::AddChannel) {
b = b.push_builder(channel_editor);
}
b
} }
async fn channel_editor(state: &ApiState, bot_token: &str, guild_id: u64) -> HtmxBuilder { async fn channel_editor(state: &ApiState, bot_token: &str, guild_id: u64) -> HtmxBuilder {
@ -422,28 +438,30 @@ async fn channel_editor(state: &ApiState, bot_token: &str, guild_id: u64) -> Htm
}; };
if got_channels && !channels.is_empty() { if got_channels && !channels.is_empty() {
HtmxBuilder::new(Tag::Empty).form(|b| { HtmxBuilder::new(Tag::Details)
b.attribute("class", "container") .builder_text(Tag::Summary, "Add Channels")
.hx_post(&format!("{}/guild/{}/add_channel", state.origin, guild_id)) .form(|b| {
.attribute("hx-encoding", "multipart/form-data") b.attribute("class", "container")
.builder(Tag::FieldSet, |b| { .hx_post(&format!("{}/guild/{}/add_channel", state.origin, guild_id))
let mut b = b .attribute("hx-encoding", "multipart/form-data")
.attribute("class", "container") .builder(Tag::FieldSet, |b| {
.attribute("style", "max-height: 50%; overflow-y: scroll"); let mut b = b
for channel_name in channels { .attribute("class", "container")
b = b.builder(Tag::Label, |b| { .attribute("style", "max-height: 50%; overflow-y: scroll");
b.builder(Tag::Input, |b| { for channel_name in channels {
b.attribute("type", "checkbox") b = b.builder(Tag::Label, |b| {
.attribute("name", &channel_name.to_string()) b.builder(Tag::Input, |b| {
}) b.attribute("type", "checkbox")
.builder_text(Tag::Paragraph, &channel_name) .attribute("name", &channel_name.to_string())
}); })
} .builder_text(Tag::Paragraph, &channel_name)
});
}
b b
}) })
.button(|b| b.attribute("type", "submit").text("Add Channel")) .button(|b| b.attribute("type", "submit").text("Add Channel"))
}) })
} else if channels.is_empty() { } else if channels.is_empty() {
HtmxBuilder::new(Tag::Empty) HtmxBuilder::new(Tag::Empty)
} else { } else {
@ -455,63 +473,66 @@ async fn permissions_editor(state: &ApiState, guild_id: u64) -> HtmxBuilder {
let db = state.db.lock().await; let db = state.db.lock().await;
let user_permissions = db.get_all_user_permissions(guild_id).unwrap_or_default(); let user_permissions = db.get_all_user_permissions(guild_id).unwrap_or_default();
HtmxBuilder::new(Tag::Empty).form(|b| { HtmxBuilder::new(Tag::Details)
b.hx_post(&format!( .builder_text(Tag::Summary, "Permissions")
"{}/guild/{}/permissions/update", .form(|b| {
state.origin, guild_id b.hx_post(&format!(
)) "{}/guild/{}/permissions/update",
.attribute("hx-encoding", "multipart/form-data") state.origin, guild_id
.builder(Tag::Table, |b| { ))
let mut b = b.attribute("role", "grid").builder(Tag::TableHead, |b| { .attribute("hx-encoding", "multipart/form-data")
let mut b = b.builder_text(Tag::TableHeader, "User"); .builder(Tag::Table, |b| {
let mut b = b.attribute("role", "grid").builder(Tag::TableHead, |b| {
for perm in enum_iterator::all::<auth::Permission>() { let mut b = b.builder_text(Tag::TableHeader, "User");
if perm == auth::Permission::Moderator || perm == auth::Permission::None {
continue;
}
b = b.builder_text(Tag::TableHeader, &perm.to_string());
}
b
});
for permission in user_permissions {
b = b.builder(Tag::TableRow, |b| {
let mut b = b.builder_text(Tag::TableData, permission.0.as_str());
for perm in enum_iterator::all::<auth::Permission>() { for perm in enum_iterator::all::<auth::Permission>() {
if perm == auth::Permission::Moderator || perm == auth::Permission::None { if perm == auth::Permission::Moderator || perm == auth::Permission::None {
continue; continue;
} }
b = b.builder(Tag::TableData, |b| { b = b.builder_text(Tag::TableHeader, &perm.to_string());
b.builder(Tag::Input, |b| {
let mut b = b
.attribute("type", "checkbox")
.attribute("name", &format!("{}#{}", permission.0, perm));
if permission.1.can(auth::Permission::Moderator) {
b = b.flag("disabled");
}
if permission.1.can(perm) {
return b.flag("checked");
}
b
})
});
} }
b b
}); });
}
b for permission in user_permissions {
b = b.builder(Tag::TableRow, |b| {
let mut b = b.builder_text(Tag::TableData, permission.0.as_str());
for perm in enum_iterator::all::<auth::Permission>() {
if perm == auth::Permission::Moderator || perm == auth::Permission::None
{
continue;
}
b = b.builder(Tag::TableData, |b| {
b.builder(Tag::Input, |b| {
let mut b = b
.attribute("type", "checkbox")
.attribute("name", &format!("{}#{}", permission.0, perm));
if permission.1.can(auth::Permission::Moderator) {
b = b.flag("disabled");
}
if permission.1.can(perm) {
return b.flag("checked");
}
b
})
});
}
b
});
}
b
})
.button(|b| b.attribute("type", "submit").text("Update Permissions"))
}) })
.button(|b| b.attribute("type", "submit").text("Update Permissions"))
})
} }
pub(crate) async fn login( pub(crate) async fn login(