revite/src/pages/settings/server/Members.tsx

143 lines
4.8 KiB
TypeScript
Raw Normal View History

import { ChevronDown } from "@styled-icons/boxicons-regular";
import { isEqual } from "lodash";
2021-07-29 15:11:21 +01:00
import { observer } from "mobx-react-lite";
import { Virtuoso } from "react-virtuoso";
2022-04-27 20:18:51 +01:00
import { Member } from "revolt.js";
import { Server } from "revolt.js";
2021-07-05 11:23:23 +01:00
import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { useEffect, useMemo, useState } from "preact/hooks";
2021-07-05 11:23:23 +01:00
import UserIcon from "../../../components/common/user/UserIcon";
import { Username } from "../../../components/common/user/UserShort";
import Button from "../../../components/ui/Button";
import Checkbox from "../../../components/ui/Checkbox";
import IconButton from "../../../components/ui/IconButton";
import InputBox from "../../../components/ui/InputBox";
import Overline from "../../../components/ui/Overline";
2022-04-30 15:22:06 +01:00
import { Preloader } from "@revoltchat/ui";
interface InnerProps {
member: Member;
}
const Inner = observer(({ member }: InnerProps) => {
const [open, setOpen] = useState(false);
const [roles, setRoles] = useState<string[]>(member.roles ?? []);
useEffect(() => {
setRoles(member.roles ?? []);
}, [member.roles]);
const server_roles = member.server?.roles ?? {};
const user = member.user;
return (
<>
<div
className={styles.member}
data-open={open}
onClick={() => setOpen(!open)}>
<span>
<UserIcon target={user} size={24} />{" "}
<Username user={member.user} showServerIdentity="both" />
</span>
<IconButton className={styles.chevron}>
<ChevronDown size={24} />
</IconButton>
</div>
{open && (
<div className={styles.memberView}>
<Overline type="subtle">Roles</Overline>
{Object.keys(server_roles).map((key) => {
const role = server_roles[key];
return (
<Checkbox
key={key}
checked={roles.includes(key) ?? false}
onChange={(v) => {
if (v) {
setRoles([...roles, key]);
} else {
setRoles(
roles.filter((x) => x !== key),
);
}
}}>
<span
style={{
color: role.colour,
}}>
{role.name}
</span>
</Checkbox>
);
})}
<Button
compact
disabled={isEqual(member.roles ?? [], roles)}
onClick={() =>
member.edit({
roles,
})
}>
<Text id="app.special.modals.actions.save" />
</Button>
</div>
)}
</>
);
});
2021-06-19 22:37:12 +01:00
interface Props {
2021-07-29 19:01:40 +01:00
server: Server;
2021-06-19 22:37:12 +01:00
}
export const Members = ({ server }: Props) => {
const [data, setData] = useState<Member[] | undefined>(undefined);
const [query, setQuery] = useState("");
2021-07-01 17:36:34 +01:00
2021-07-05 11:25:20 +01:00
useEffect(() => {
server
.fetchMembers()
.then((data) => data.members)
.then(setData);
2021-08-05 14:47:00 +01:00
}, [server, setData]);
2021-06-19 22:37:12 +01:00
const members = useMemo(
() =>
query
? data?.filter((x) =>
x.user?.username
.toLowerCase()
.includes(query.toLowerCase()),
)
: data,
[data, query],
);
2021-07-05 11:25:20 +01:00
return (
<div className={styles.userList}>
<InputBox
placeholder="Search for a specific user..."
value={query}
onChange={(e) => setQuery(e.currentTarget.value)}
contrast
/>
<div className={styles.subtitle}>{data?.length ?? 0} Members</div>
2022-04-30 15:22:06 +01:00
{members ? (
<div className={styles.virtual}>
<Virtuoso
totalCount={members.length}
itemContent={(index) => (
<Inner member={members[index]} />
)}
/>
</div>
2022-04-30 15:22:06 +01:00
) : (
<Preloader type="ring" />
)}
2021-07-05 11:25:20 +01:00
</div>
);
};