Skip to content

Commit a4a5b19

Browse files
authored
Merge pull request #63 from FrostCord/FROS-Kicks-And-Bans
FROS Kicking and Banning
2 parents 2248529 + e3d8e66 commit a4a5b19

14 files changed

Lines changed: 463 additions & 140 deletions

components/forms/MiniProfile.tsx

Lines changed: 101 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ export function MiniProfile({ server_user_profile }: { server_user_profile: Serv
3131

3232
const serverRoles = useServerRoles(channel!.server_id!);
3333
const userHighestRole = useServerUserProfileHighestRolePosition(
34-
server_user_profile.server_user.server_id,
34+
channel!.server_id,
3535
user!.id
3636
);
3737
const currentUserPerms = useServerUserProfilePermissions(
38-
server_user_profile.server_user.server_id,
38+
channel!.server_id,
3939
user!.id
4040
);
4141

@@ -44,7 +44,8 @@ export function MiniProfile({ server_user_profile }: { server_user_profile: Serv
4444
const filteredRoles = serverRoles
4545
.filter(
4646
role => (
47-
role.position > userHighestRole
47+
server_user_profile.roles
48+
&& role.position > userHighestRole
4849
&& role.position !== serverRoles.length - 1
4950
&& !server_user_profile.roles.some(r => r.id === role.id)
5051
)
@@ -53,111 +54,115 @@ export function MiniProfile({ server_user_profile }: { server_user_profile: Serv
5354
return (
5455
<div className="flex flex-col space-y-2 items-center p-3">
5556
<UserIcon user={server_user_profile} className="!w-9 !h-9" />
56-
{server_user_profile.server_user.nickname && (
57+
{server_user_profile.server_user?.nickname && (
5758
<h2 className="text-lg">{server_user_profile.server_user.nickname}</h2>
5859
)}
59-
<h2 className={server_user_profile.server_user.nickname ? 'text-base' : 'text-lg'}>
60+
<h2 className={server_user_profile.server_user?.nickname ? 'text-base' : 'text-lg'}>
6061
{server_user_profile.username}
6162
</h2>
6263
<hr />
63-
<h2 className="text-sm text-gray-400 text-left w-full">Roles</h2>
64-
65-
<div className="flex flex-col w-full items-center space-y-1">
66-
{server_user_profile.roles.map((role) => (
67-
<span
68-
key={role.id}
69-
className="text-sm text-gray-400 py-1 px-2 border-2 border-solid w-full rounded-sm flex flex-row items-center"
70-
style={{
71-
border: `1px solid #${!!role.color ? role.color : 'cacacacc'}`,
72-
color: `#${!!role.color ? role.color : 'cacacacc'}`,
73-
}}
74-
>
75-
<p className="flex-grow">{role.name}</p>
76-
{(
77-
(currentUserPerms & ServerPermissions.MANAGE_ROLES) === ServerPermissions.MANAGE_ROLES
78-
&& role.position > userHighestRole
79-
&& role.position !== serverRoles.length - 1
80-
) && (
81-
<button
82-
type="button"
83-
className="align-middle self-end"
64+
{server_user_profile.roles && (
65+
<>
66+
<h2 className="text-sm text-gray-400 text-left w-full">Roles</h2>
67+
<div className="flex flex-col w-full items-center space-y-1">
68+
{(server_user_profile.roles).map((role) => (
69+
<span
70+
key={role.id}
71+
className="text-sm text-gray-400 py-1 px-2 border-2 border-solid w-full rounded-sm flex flex-row items-center"
8472
style={{
85-
fill: `#${!!role.color ? role.color : 'cacacacc'}`,
86-
}}
87-
onClick={async () => {
88-
const { error } = await revokeRoleFromUser(
89-
supabase,
90-
role.id,
91-
server_user_profile.server_user.id,
92-
);
93-
94-
if (error) {
95-
console.error(error);
96-
toast.error('Failed to revoke role from user');
97-
return;
98-
}
99-
100-
toast.success('Role revoked from user');
73+
border: `1px solid #${!!role.color ? role.color : 'cacacacc'}`,
74+
color: `#${!!role.color ? role.color : 'cacacacc'}`,
10175
}}
10276
>
103-
<XIcon className="w-4 h-4" />
104-
</button>
105-
)}
106-
</span>
107-
))}
77+
<p className="flex-grow">{role.name}</p>
78+
{(
79+
server_user_profile.server_user !== null
80+
&& (currentUserPerms & ServerPermissions.MANAGE_ROLES) === ServerPermissions.MANAGE_ROLES
81+
&& role.position > userHighestRole
82+
&& role.position !== serverRoles.length - 1
83+
) && (
84+
<button
85+
type="button"
86+
className="align-middle self-end"
87+
style={{
88+
fill: `#${!!role.color ? role.color : 'cacacacc'}`,
89+
}}
90+
onClick={async () => {
91+
const { error } = await revokeRoleFromUser(
92+
supabase,
93+
role.id,
94+
server_user_profile.server_user!.id,
95+
);
10896

109-
{(
110-
(currentUserPerms & ServerPermissions.MANAGE_ROLES) === ServerPermissions.MANAGE_ROLES
111-
&& filteredRoles.length > 0
112-
) && (
113-
<DropdownMenu.Root>
114-
<DropdownMenu.Trigger
115-
asChild
116-
>
117-
<button
118-
type="button"
119-
className="text-sm text-gray-400 py-1 px-2 border-2 border-solid w-full rounded-sm text-center"
120-
style={{
121-
border: '1px solid #cacacacc'
122-
}}
123-
>
124-
+
125-
</button>
126-
</DropdownMenu.Trigger>
127-
<DropdownMenu.Content
128-
side="right"
129-
className="ContextMenuContent"
130-
>
131-
{filteredRoles.map((role) => (
132-
<DropdownMenu.Item
133-
key={role.id}
134-
className="ContextMenuItem"
135-
style={{
136-
color: `#${!!role.color ? role.color : 'cacacacc'}`,
137-
}}
138-
onSelect={async () => {
139-
const { error } = await grantRoleToUser(
140-
supabase,
141-
role.id,
142-
server_user_profile.server_user.id,
143-
);
97+
if (error) {
98+
console.error(error);
99+
toast.error('Failed to revoke role from user');
100+
return;
101+
}
144102

145-
if (error) {
146-
console.error(error);
147-
toast.error('Failed to grant role to user');
148-
return;
149-
}
103+
toast.success('Role revoked from user');
104+
}}
105+
>
106+
<XIcon className="w-4 h-4" />
107+
</button>
108+
)}
109+
</span>
110+
))}
150111

151-
toast.success('Role granted to user');
152-
}}
112+
{(
113+
(currentUserPerms & ServerPermissions.MANAGE_ROLES) === ServerPermissions.MANAGE_ROLES
114+
&& filteredRoles.length > 0
115+
) && (
116+
<DropdownMenu.Root>
117+
<DropdownMenu.Trigger
118+
asChild
153119
>
154-
{role.name}
155-
</DropdownMenu.Item>
156-
))}
157-
</DropdownMenu.Content>
158-
</DropdownMenu.Root>
159-
)}
160-
</div>
120+
<button
121+
type="button"
122+
className="text-sm text-gray-400 py-1 px-2 border-2 border-solid w-full rounded-sm text-center"
123+
style={{
124+
border: '1px solid #cacacacc'
125+
}}
126+
>
127+
+
128+
</button>
129+
</DropdownMenu.Trigger>
130+
<DropdownMenu.Content
131+
side="right"
132+
className="ContextMenuContent"
133+
>
134+
{filteredRoles.map((role) => (
135+
<DropdownMenu.Item
136+
key={role.id}
137+
className="ContextMenuItem"
138+
style={{
139+
color: `#${!!role.color ? role.color : 'cacacacc'}`,
140+
}}
141+
onSelect={async () => {
142+
const { error } = await grantRoleToUser(
143+
supabase,
144+
role.id,
145+
server_user_profile.server_user!.id,
146+
);
147+
148+
if (error) {
149+
console.error(error);
150+
toast.error('Failed to grant role to user');
151+
return;
152+
}
153+
154+
toast.success('Role granted to user');
155+
}}
156+
>
157+
{role.name}
158+
</DropdownMenu.Item>
159+
))}
160+
</DropdownMenu.Content>
161+
</DropdownMenu.Root>
162+
)}
163+
</div>
164+
</>
165+
)}
161166
<hr />
162167
{server_user_profile.id !== user?.id && (<form>
163168
<input

components/home/BanListItem.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { OverflowMarquee } from '@/components/home/OverflowMarquee';
2+
import UserIcon from '@/components/icons/UserIcon';
3+
import { unbanUser } from '@/services/server.service';
4+
import { ServerBanWithProfile, User } from '@/types/dbtypes';
5+
import { useSupabaseClient } from '@supabase/auth-helpers-react';
6+
import { Dispatch, SetStateAction } from 'react';
7+
import { toast } from 'react-toastify';
8+
9+
export function BanListItem({ ban, serverId, setServerBans }: { ban: ServerBanWithProfile, serverId: number, setServerBans: Dispatch<SetStateAction<ServerBanWithProfile[]>> }) {
10+
const supabase = useSupabaseClient();
11+
12+
return (
13+
<div className="flex flex-row items-center justify-between w-full h-7 px-4 my-2 rounded-md hover:bg-gray-600">
14+
<div className="flex flex-row flex-grow w-full align-middle">
15+
<UserIcon user={ban.profiles} indicator={false} className="!w-6 !h-6"/>
16+
<span className="text-sm font-bold text-gray-300">{ban.profiles.username}</span>
17+
</div>
18+
<div className='flex-grow'>
19+
<OverflowMarquee content={ban.reason} maxLength={50} />
20+
</div>
21+
<button
22+
className="text-red-400 p-2 hover:text-red-500 transition-colors"
23+
onClick={async () => {
24+
const { error } = await unbanUser(
25+
supabase,
26+
ban.profiles.id,
27+
serverId,
28+
);
29+
30+
if (error) {
31+
console.error(error);
32+
toast.error('Failed to unban user');
33+
return;
34+
}
35+
36+
toast.success('User unbanned');
37+
setServerBans((bans) => bans.filter((b) => b.id !== ban.id));
38+
}}
39+
>
40+
Unban
41+
</button>
42+
</div>
43+
);
44+
}

components/home/InviteEmbed.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import LoadingIcon from '../icons/LoadingIcon';
1111
import ServersIcon from '../icons/ServersIcon';
1212
import { OverflowMarquee } from './OverflowMarquee';
1313
import { ServerMemberStats } from './ServerMemberStats';
14+
import { toast } from 'react-toastify';
1415

1516
export function InviteEmbed({ invite_code }: { invite_code: string }) {
1617
const servers = useServers();
@@ -126,7 +127,13 @@ export function InviteEmbed({ invite_code }: { invite_code: string }) {
126127
"
127128
disabled={userInServer}
128129
onClick={async () => {
129-
await addUserToServer(supabase, invite.servers.id);
130+
const { error } = await addUserToServer(supabase, invite.servers.id);
131+
132+
if (error) {
133+
toast.error('You cannot join this server.');
134+
return;
135+
}
136+
130137
router.push(`/?c=${invite.channel_id}`, '/');
131138
}}
132139
>

0 commit comments

Comments
 (0)