feat(dashboard): edit log channels page
This commit is contained in:
parent
ec7aa9faba
commit
32ddb9fae2
16 changed files with 471 additions and 95 deletions
|
|
@ -137,156 +137,156 @@ public class GuildsController(
|
||||||
|
|
||||||
// i love repeating myself wheeeeee
|
// i love repeating myself wheeeeee
|
||||||
if (
|
if (
|
||||||
req.GuildUpdate != null
|
req.GuildUpdate == null
|
||||||
&& (req.GuildUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.GuildUpdate))
|
|| (req.GuildUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.GuildUpdate))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildUpdate = req.GuildUpdate.Value;
|
guildConfig.Channels.GuildUpdate = req.GuildUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildEmojisUpdate != null
|
req.GuildEmojisUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildEmojisUpdate == 0
|
req.GuildEmojisUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildEmojisUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildEmojisUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildEmojisUpdate = req.GuildEmojisUpdate.Value;
|
guildConfig.Channels.GuildEmojisUpdate = req.GuildEmojisUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildRoleCreate != null
|
req.GuildRoleCreate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildRoleCreate == 0
|
req.GuildRoleCreate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleCreate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleCreate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildRoleCreate = req.GuildRoleCreate.Value;
|
guildConfig.Channels.GuildRoleCreate = req.GuildRoleCreate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildRoleUpdate != null
|
req.GuildRoleUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildRoleUpdate == 0
|
req.GuildRoleUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildRoleUpdate = req.GuildRoleUpdate.Value;
|
guildConfig.Channels.GuildRoleUpdate = req.GuildRoleUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildRoleDelete != null
|
req.GuildRoleDelete == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildRoleDelete == 0
|
req.GuildRoleDelete == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleDelete)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildRoleDelete)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildRoleDelete = req.GuildRoleDelete.Value;
|
guildConfig.Channels.GuildRoleDelete = req.GuildRoleDelete ?? 0;
|
||||||
if (
|
if (
|
||||||
req.ChannelCreate != null
|
req.ChannelCreate == null
|
||||||
&& (req.ChannelCreate == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelCreate))
|
|| (req.ChannelCreate == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelCreate))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.ChannelCreate = req.ChannelCreate.Value;
|
guildConfig.Channels.ChannelCreate = req.ChannelCreate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.ChannelUpdate != null
|
req.ChannelUpdate == null
|
||||||
&& (req.ChannelUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelUpdate))
|
|| (req.ChannelUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelUpdate))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.ChannelUpdate = req.ChannelUpdate.Value;
|
guildConfig.Channels.ChannelUpdate = req.ChannelUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.ChannelDelete != null
|
req.ChannelDelete == null
|
||||||
&& (req.ChannelDelete == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelDelete))
|
|| (req.ChannelDelete == 0 || guildChannels.Any(c => c.ID.Value == req.ChannelDelete))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.ChannelDelete = req.ChannelDelete.Value;
|
guildConfig.Channels.ChannelDelete = req.ChannelDelete ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberAdd != null
|
req.GuildMemberAdd == null
|
||||||
&& (req.GuildMemberAdd == 0 || guildChannels.Any(c => c.ID.Value == req.GuildMemberAdd))
|
|| (req.GuildMemberAdd == 0 || guildChannels.Any(c => c.ID.Value == req.GuildMemberAdd))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberAdd = req.GuildMemberAdd.Value;
|
guildConfig.Channels.GuildMemberAdd = req.GuildMemberAdd ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberUpdate != null
|
req.GuildMemberUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberUpdate == 0
|
req.GuildMemberUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberUpdate = req.GuildMemberUpdate.Value;
|
guildConfig.Channels.GuildMemberUpdate = req.GuildMemberUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildKeyRoleUpdate != null
|
req.GuildKeyRoleUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildKeyRoleUpdate == 0
|
req.GuildKeyRoleUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildKeyRoleUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildKeyRoleUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildKeyRoleUpdate = req.GuildKeyRoleUpdate.Value;
|
guildConfig.Channels.GuildKeyRoleUpdate = req.GuildKeyRoleUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberNickUpdate != null
|
req.GuildMemberNickUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberNickUpdate == 0
|
req.GuildMemberNickUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberNickUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberNickUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberNickUpdate = req.GuildMemberNickUpdate.Value;
|
guildConfig.Channels.GuildMemberNickUpdate = req.GuildMemberNickUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberAvatarUpdate != null
|
req.GuildMemberAvatarUpdate == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberAvatarUpdate == 0
|
req.GuildMemberAvatarUpdate == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberAvatarUpdate)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberAvatarUpdate)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberAvatarUpdate = req.GuildMemberAvatarUpdate.Value;
|
guildConfig.Channels.GuildMemberAvatarUpdate = req.GuildMemberAvatarUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberTimeout != null
|
req.GuildMemberTimeout == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberTimeout == 0
|
req.GuildMemberTimeout == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberTimeout)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberTimeout)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberTimeout = req.GuildMemberTimeout.Value;
|
guildConfig.Channels.GuildMemberTimeout = req.GuildMemberTimeout ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberRemove != null
|
req.GuildMemberRemove == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberRemove == 0
|
req.GuildMemberRemove == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberRemove)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberRemove)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberRemove = req.GuildMemberRemove.Value;
|
guildConfig.Channels.GuildMemberRemove = req.GuildMemberRemove ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildMemberKick != null
|
req.GuildMemberKick == null
|
||||||
&& (
|
|| (
|
||||||
req.GuildMemberKick == 0
|
req.GuildMemberKick == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberKick)
|
|| guildChannels.Any(c => c.ID.Value == req.GuildMemberKick)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildMemberKick = req.GuildMemberKick.Value;
|
guildConfig.Channels.GuildMemberKick = req.GuildMemberKick ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildBanAdd != null
|
req.GuildBanAdd == null
|
||||||
&& (req.GuildBanAdd == 0 || guildChannels.Any(c => c.ID.Value == req.GuildBanAdd))
|
|| (req.GuildBanAdd == 0 || guildChannels.Any(c => c.ID.Value == req.GuildBanAdd))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildBanAdd = req.GuildBanAdd.Value;
|
guildConfig.Channels.GuildBanAdd = req.GuildBanAdd ?? 0;
|
||||||
if (
|
if (
|
||||||
req.GuildBanRemove != null
|
req.GuildBanRemove == null
|
||||||
&& (req.GuildBanRemove == 0 || guildChannels.Any(c => c.ID.Value == req.GuildBanRemove))
|
|| (req.GuildBanRemove == 0 || guildChannels.Any(c => c.ID.Value == req.GuildBanRemove))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.GuildBanRemove = req.GuildBanRemove.Value;
|
guildConfig.Channels.GuildBanRemove = req.GuildBanRemove ?? 0;
|
||||||
if (
|
if (
|
||||||
req.InviteCreate != null
|
req.InviteCreate == null
|
||||||
&& (req.InviteCreate == 0 || guildChannels.Any(c => c.ID.Value == req.InviteCreate))
|
|| (req.InviteCreate == 0 || guildChannels.Any(c => c.ID.Value == req.InviteCreate))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.InviteCreate = req.InviteCreate.Value;
|
guildConfig.Channels.InviteCreate = req.InviteCreate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.InviteDelete != null
|
req.InviteDelete == null
|
||||||
&& (req.InviteDelete == 0 || guildChannels.Any(c => c.ID.Value == req.InviteDelete))
|
|| (req.InviteDelete == 0 || guildChannels.Any(c => c.ID.Value == req.InviteDelete))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.InviteDelete = req.InviteDelete.Value;
|
guildConfig.Channels.InviteDelete = req.InviteDelete ?? 0;
|
||||||
if (
|
if (
|
||||||
req.MessageUpdate != null
|
req.MessageUpdate == null
|
||||||
&& (req.MessageUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.MessageUpdate))
|
|| (req.MessageUpdate == 0 || guildChannels.Any(c => c.ID.Value == req.MessageUpdate))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.MessageUpdate = req.MessageUpdate.Value;
|
guildConfig.Channels.MessageUpdate = req.MessageUpdate ?? 0;
|
||||||
if (
|
if (
|
||||||
req.MessageDelete != null
|
req.MessageDelete == null
|
||||||
&& (req.MessageDelete == 0 || guildChannels.Any(c => c.ID.Value == req.MessageDelete))
|
|| (req.MessageDelete == 0 || guildChannels.Any(c => c.ID.Value == req.MessageDelete))
|
||||||
)
|
)
|
||||||
guildConfig.Channels.MessageDelete = req.MessageDelete.Value;
|
guildConfig.Channels.MessageDelete = req.MessageDelete ?? 0;
|
||||||
if (
|
if (
|
||||||
req.MessageDeleteBulk != null
|
req.MessageDeleteBulk == null
|
||||||
&& (
|
|| (
|
||||||
req.MessageDeleteBulk == 0
|
req.MessageDeleteBulk == 0
|
||||||
|| guildChannels.Any(c => c.ID.Value == req.MessageDeleteBulk)
|
|| guildChannels.Any(c => c.ID.Value == req.MessageDeleteBulk)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
guildConfig.Channels.MessageDeleteBulk = req.MessageDeleteBulk.Value;
|
guildConfig.Channels.MessageDeleteBulk = req.MessageDeleteBulk ?? 0;
|
||||||
|
|
||||||
db.Update(guildConfig);
|
db.Update(guildConfig);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.1.2",
|
||||||
"sass": "^1.80.1",
|
"sass": "^1.80.1",
|
||||||
|
"svelecte": "^4.3.1",
|
||||||
"svelte": "^4.2.7",
|
"svelte": "^4.2.7",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,34 @@
|
||||||
@use "bootstrap/scss/bootstrap" with (
|
@use "bootstrap/scss/bootstrap" with (
|
||||||
$color-mode-type: media-query
|
$color-mode-type: media-query
|
||||||
);
|
);
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--sv-min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Svelecte doesn't have a built in dark mode :)
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--sv-bg: #32363f;
|
||||||
|
--sv-disabled-bg: #eee;
|
||||||
|
--sv-border: 1px solid #626262;
|
||||||
|
--sv-item-selected-bg: #626262;
|
||||||
|
--sv-item-btn-color: #ccc;
|
||||||
|
--sv-item-btn-color-hover: #ccc;
|
||||||
|
--sv-item-btn-bg: #626262;
|
||||||
|
--sv-item-btn-bg-hover: #bc6063;
|
||||||
|
--sv-icon-color: #bbb;
|
||||||
|
--sv-icon-color-hover: #ccc;
|
||||||
|
--sv-separator-bg: #626262;
|
||||||
|
--sv-placeholder-color: #ccccd6;
|
||||||
|
--sv-dropdown-bg: var(--sv-bg);
|
||||||
|
--sv-dropdown-border: var(--sv-border);
|
||||||
|
--sv-dropdown-shadow: 0 1px 3px #555;
|
||||||
|
--sv-dropdown-active-bg: #553d3d;
|
||||||
|
--sv-dropdown-selected-bg: #754545;
|
||||||
|
--sv-create-kbd-border: 1px solid #626262;
|
||||||
|
--sv-create-kbd-bg: #626262;
|
||||||
|
--sv-create-disabled-bg: #fcbaba;
|
||||||
|
--sv-loader-border: 2px solid #626262;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,3 @@
|
||||||
export type User = {
|
|
||||||
id: string;
|
|
||||||
tag: string;
|
|
||||||
avatar_url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PartialGuild = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
icon_url: string;
|
|
||||||
bot_in_guild: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CurrentUser = {
|
|
||||||
user: User;
|
|
||||||
guilds: PartialGuild[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AuthCallback = CurrentUser & { token: string };
|
|
||||||
|
|
||||||
export type ApiError = {
|
|
||||||
error_code: string;
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TOKEN_KEY = "catalogger-token";
|
export const TOKEN_KEY = "catalogger-token";
|
||||||
|
|
||||||
export default async function apiFetch<T>(
|
export default async function apiFetch<T>(
|
||||||
|
|
@ -53,3 +28,83 @@ export default async function apiFetch<T>(
|
||||||
|
|
||||||
return (await resp.json()) as T;
|
return (await resp.json()) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
id: string;
|
||||||
|
tag: string;
|
||||||
|
avatar_url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PartialGuild = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon_url: string;
|
||||||
|
bot_in_guild: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FullGuild = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
icon_url: string;
|
||||||
|
categories: GuildCategory[];
|
||||||
|
channels_without_category: GuildChannel[];
|
||||||
|
config: GuildConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GuildCategory = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
channels: GuildChannel[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GuildChannel = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
can_log_to: boolean;
|
||||||
|
can_redirect_from: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CurrentUser = {
|
||||||
|
user: User;
|
||||||
|
guilds: PartialGuild[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthCallback = CurrentUser & { token: string };
|
||||||
|
|
||||||
|
export type ApiError = {
|
||||||
|
error_code: string;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GuildConfig = GuildChannelConfig & {
|
||||||
|
ignored_channels: string[];
|
||||||
|
ignored_users: string[];
|
||||||
|
ignored_users_per_channel: Record<string, string[]>;
|
||||||
|
redirects: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GuildChannelConfig = {
|
||||||
|
guild_update: string;
|
||||||
|
guild_emojis_update: string;
|
||||||
|
guild_role_create: string;
|
||||||
|
guild_role_update: string;
|
||||||
|
guild_role_delete: string;
|
||||||
|
channel_create: string;
|
||||||
|
channel_update: string;
|
||||||
|
channel_delete: string;
|
||||||
|
guild_member_add: string;
|
||||||
|
guild_member_update: string;
|
||||||
|
guild_key_role_update: string;
|
||||||
|
guild_member_nick_update: string;
|
||||||
|
guild_member_avatar_update: string;
|
||||||
|
guild_member_timeout: string;
|
||||||
|
guild_member_remove: string;
|
||||||
|
guild_member_kick: string;
|
||||||
|
guild_ban_add: string;
|
||||||
|
guild_ban_remove: string;
|
||||||
|
invite_create: string;
|
||||||
|
invite_delete: string;
|
||||||
|
message_update: string;
|
||||||
|
message_delete: string;
|
||||||
|
message_delete_bulk: string;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Catalogger</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
<h1>Welcome to SvelteKit</h1>
|
<h1>Welcome to SvelteKit</h1>
|
||||||
<p>
|
<p>
|
||||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||||
|
|
|
||||||
1
Catalogger.Frontend/src/routes/callback/+page.ts
Normal file
1
Catalogger.Frontend/src/routes/callback/+page.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const prerender = false;
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { addToast } from "$lib/toast";
|
import { addToast } from "$lib/toast";
|
||||||
import { redirect } from "@sveltejs/kit";
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export const prerender = false;
|
||||||
|
|
||||||
export const load = async ({ parent }) => {
|
export const load = async ({ parent }) => {
|
||||||
const data = await parent();
|
const data = await parent();
|
||||||
if (!data.user) {
|
if (!data.user) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@
|
||||||
$: unjoinedGuilds = data.guilds.filter((g) => !g.bot_in_guild);
|
$: unjoinedGuilds = data.guilds.filter((g) => !g.bot_in_guild);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Catalogger - Dashboard</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
<h1>Manage your servers</h1>
|
<h1>Manage your servers</h1>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
||||||
86
Catalogger.Frontend/src/routes/dash/[guildId]/+layout.svelte
Normal file
86
Catalogger.Frontend/src/routes/dash/[guildId]/+layout.svelte
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Button, Nav, NavItem, NavLink } from "@sveltestrap/sveltestrap";
|
||||||
|
import type { LayoutData } from "./$types";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import apiFetch, { type ApiError, type GuildConfig } from "$lib/api";
|
||||||
|
import { addToast } from "$lib/toast";
|
||||||
|
|
||||||
|
export let data: LayoutData;
|
||||||
|
|
||||||
|
// This only saves log channels. All other pages are lists and are saved immediately upon adding/removing an entry.
|
||||||
|
const save = async () => {
|
||||||
|
try {
|
||||||
|
const resp = await apiFetch<GuildConfig>(
|
||||||
|
"PATCH",
|
||||||
|
`/api/guilds/${data.guild.id}`,
|
||||||
|
data.guild.config,
|
||||||
|
);
|
||||||
|
data.guild.config = resp;
|
||||||
|
} catch (e) {
|
||||||
|
addToast({
|
||||||
|
header: "Error saving changes to log channels",
|
||||||
|
body:
|
||||||
|
(e as ApiError).message || "Unknown error. Please try again later.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Catalogger - Managing {data.guild.name}</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-lg-row justify-content-lg-between">
|
||||||
|
<Nav pills={true} class="flex-column flex-lg-row">
|
||||||
|
<NavItem
|
||||||
|
><NavLink href="#" disabled>Managing {data.guild.name}</NavLink></NavItem
|
||||||
|
>
|
||||||
|
<NavItem
|
||||||
|
><NavLink
|
||||||
|
href="/dash/{data.guild.id}"
|
||||||
|
active={$page.url.pathname === `/dash/${data.guild.id}`}
|
||||||
|
>
|
||||||
|
Log channels
|
||||||
|
</NavLink></NavItem
|
||||||
|
>
|
||||||
|
<NavItem
|
||||||
|
><NavLink
|
||||||
|
href="/dash/{data.guild.id}/redirects"
|
||||||
|
active={$page.url.pathname === `/dash/${data.guild.id}/redirects`}
|
||||||
|
>
|
||||||
|
Redirects
|
||||||
|
</NavLink></NavItem
|
||||||
|
>
|
||||||
|
<NavItem
|
||||||
|
><NavLink
|
||||||
|
href="/dash/{data.guild.id}/ignored-channels"
|
||||||
|
active={$page.url.pathname ===
|
||||||
|
`/dash/${data.guild.id}/ignored-channels`}
|
||||||
|
>
|
||||||
|
Ignored channels
|
||||||
|
</NavLink></NavItem
|
||||||
|
>
|
||||||
|
<NavItem
|
||||||
|
><NavLink
|
||||||
|
href="/dash/{data.guild.id}/ignored-users"
|
||||||
|
active={$page.url.pathname === `/dash/${data.guild.id}/ignored-users`}
|
||||||
|
>
|
||||||
|
Ignored users
|
||||||
|
</NavLink></NavItem
|
||||||
|
>
|
||||||
|
<NavItem
|
||||||
|
><NavLink
|
||||||
|
href="/dash/{data.guild.id}/key-roles"
|
||||||
|
active={$page.url.pathname === `/dash/${data.guild.id}/key-roles`}
|
||||||
|
>
|
||||||
|
Key roles
|
||||||
|
</NavLink></NavItem
|
||||||
|
>
|
||||||
|
</Nav>
|
||||||
|
|
||||||
|
{#if $page.url.pathname === `/dash/${data.guild.id}`}
|
||||||
|
<Button on:click={save}>Save changes</Button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
17
Catalogger.Frontend/src/routes/dash/[guildId]/+layout.ts
Normal file
17
Catalogger.Frontend/src/routes/dash/[guildId]/+layout.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import apiFetch, { type ApiError, type FullGuild } from "$lib/api";
|
||||||
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export const load = async ({ params }) => {
|
||||||
|
try {
|
||||||
|
const guild = await apiFetch<FullGuild>(
|
||||||
|
"GET",
|
||||||
|
`/api/guilds/${params.guildId}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { guild };
|
||||||
|
} catch (e) {
|
||||||
|
const err = e as ApiError;
|
||||||
|
console.log("Fetching guild", params.guildId, ":", e);
|
||||||
|
error(404, err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
138
Catalogger.Frontend/src/routes/dash/[guildId]/+page.svelte
Normal file
138
Catalogger.Frontend/src/routes/dash/[guildId]/+page.svelte
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Label } from "@sveltestrap/sveltestrap";
|
||||||
|
import type { FullGuild, GuildChannelConfig } from "$lib/api";
|
||||||
|
import type { PageData } from "./$types";
|
||||||
|
import ChannelSelect from "./ChannelSelect.svelte";
|
||||||
|
|
||||||
|
export let data: PageData;
|
||||||
|
|
||||||
|
$: channels = data.guild.config as GuildChannelConfig;
|
||||||
|
|
||||||
|
const logChannelOptions = (g: FullGuild) => {
|
||||||
|
let options = [];
|
||||||
|
|
||||||
|
const channelsWithoutCategory = g.channels_without_category.filter(
|
||||||
|
(c) => c.can_log_to,
|
||||||
|
);
|
||||||
|
if (channelsWithoutCategory.length > 0)
|
||||||
|
options.push({
|
||||||
|
label: "(no category)",
|
||||||
|
options: channelsWithoutCategory.map((c) => ({
|
||||||
|
value: c.id,
|
||||||
|
label: `#${c.name}`,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
options.push(
|
||||||
|
...data.guild.categories
|
||||||
|
.map((cat) => ({
|
||||||
|
label: cat.name,
|
||||||
|
options: cat.channels
|
||||||
|
.filter((c) => c.can_log_to)
|
||||||
|
.map((c) => ({ value: c.id, label: `#${c.name}` })),
|
||||||
|
}))
|
||||||
|
.filter((c) => c.options.length > 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
|
$: options = logChannelOptions(data.guild);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Server changes</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Changes to emotes</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_emojis_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>New roles</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_role_create} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Changes to roles</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_role_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Deleted roles</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_role_delete} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>New channels</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.channel_create} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Changes to channels</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.channel_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Deleted channels</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.channel_delete} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Users joining</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_add} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Users leaving</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_remove} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Changes to key roles</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_update} {options} />
|
||||||
|
<small>
|
||||||
|
Key roles can be designated with the <code>/key-roles</code> command or the
|
||||||
|
"Key roles" tab above.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Member name changes</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_nick_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Member icon changes</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_avatar_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Timeouts</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_timeout} {options} />
|
||||||
|
<small> Note that this will not log timeouts naturally expiring. </small>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Kicked users</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_member_kick} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Banned users</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_ban_add} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Unbanned users</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.guild_ban_remove} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>New invites</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.invite_create} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Deleted invites</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.invite_delete} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Edited messages</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.message_update} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Deleted messages</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.message_delete} {options} />
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Bulk deleted messages</strong></Label>
|
||||||
|
<ChannelSelect bind:value={channels.message_delete_bulk} {options} />
|
||||||
|
<small> This will only be triggered by bots, not normal users. </small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import Svelecte from "svelecte";
|
||||||
|
|
||||||
|
type Group = { label: string; options: Option[] };
|
||||||
|
type Option = { label: string; value: string };
|
||||||
|
|
||||||
|
export let options: Group[];
|
||||||
|
export let placeholder: string = "Select a channel";
|
||||||
|
export let value: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Svelecte
|
||||||
|
bind:value
|
||||||
|
{options}
|
||||||
|
{placeholder}
|
||||||
|
labelField="label"
|
||||||
|
valueField="value"
|
||||||
|
groupLabelField="label"
|
||||||
|
groupItemsField="options"
|
||||||
|
searchable={true}
|
||||||
|
/>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<h1>aaaaaaaaa</h1>
|
||||||
|
|
@ -12,7 +12,7 @@ const config = {
|
||||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
fallback: "index.html",
|
fallback: "spa.html",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { defineConfig } from "vite";
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [sveltekit()],
|
||||||
server: {
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
strictPort: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/api": {
|
||||||
target: "http://localhost:5005",
|
target: "http://localhost:5005",
|
||||||
|
|
@ -12,6 +14,7 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
hmr: {
|
hmr: {
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
|
port: 5173,
|
||||||
protocol: "ws",
|
protocol: "ws",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1497,6 +1497,13 @@ supports-color@^7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
svelecte@^4.3.1:
|
||||||
|
version "4.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/svelecte/-/svelecte-4.3.1.tgz#d7bfb8c14ef080ac43e36f42c6020aae044dd2fe"
|
||||||
|
integrity sha512-0wyPDel4J16ecwaDHvgdXsI5QvuC1pU8n2FY3tO4X39e6gcrnoQkgV3zVWYdm7xAQaqawAgZNBDgNZlonPLOmw==
|
||||||
|
dependencies:
|
||||||
|
svelte-tiny-virtual-list "^2.1.0"
|
||||||
|
|
||||||
svelte-check@^4.0.0:
|
svelte-check@^4.0.0:
|
||||||
version "4.0.5"
|
version "4.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-4.0.5.tgz#5cd910c3b1d50f38159c17cc3bae127cbbb55c8d"
|
resolved "https://registry.yarnpkg.com/svelte-check/-/svelte-check-4.0.5.tgz#5cd910c3b1d50f38159c17cc3bae127cbbb55c8d"
|
||||||
|
|
@ -1524,6 +1531,11 @@ svelte-hmr@^0.16.0:
|
||||||
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.16.0.tgz#9f345b7d1c1662f1613747ed7e82507e376c1716"
|
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.16.0.tgz#9f345b7d1c1662f1613747ed7e82507e376c1716"
|
||||||
integrity sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==
|
integrity sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==
|
||||||
|
|
||||||
|
svelte-tiny-virtual-list@^2.1.0:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/svelte-tiny-virtual-list/-/svelte-tiny-virtual-list-2.1.2.tgz#db826e5915f0374b793798bc8125b8a66fbc6c34"
|
||||||
|
integrity sha512-jeP/WMvgFUR4mYXHGPiCexjX5DuzSO+3xzHNhxfcsFyy+uYPtnqI5UGb383swpzQAyXB0OBqYfzpYihD/5gxnA==
|
||||||
|
|
||||||
svelte@^4.2.7:
|
svelte@^4.2.7:
|
||||||
version "4.2.19"
|
version "4.2.19"
|
||||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-4.2.19.tgz#4e6e84a8818e2cd04ae0255fcf395bc211e61d4c"
|
resolved "https://registry.yarnpkg.com/svelte/-/svelte-4.2.19.tgz#4e6e84a8818e2cd04ae0255fcf395bc211e61d4c"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue