224 lines
9.0 KiB
TypeScript
224 lines
9.0 KiB
TypeScript
import isEqual from "lodash.isequal";
|
|
import { observer } from "mobx-react-lite";
|
|
import { Server } from "revolt.js/esm/maps/Servers";
|
|
|
|
import { useMemo, useState } from "preact/hooks";
|
|
|
|
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
|
|
|
import Checkbox from "../../../components/ui/Checkbox";
|
|
import ColourSwatches from "../../../components/ui/ColourSwatches";
|
|
import InputBox from "../../../components/ui/InputBox";
|
|
import Overline from "../../../components/ui/Overline";
|
|
import { Button, PermissionsLayout, SpaceBetween, H1 } from "@revoltchat/ui";
|
|
|
|
import { PermissionList } from "../../../components/settings/roles/PermissionList";
|
|
import { RoleOrDefault } from "../../../components/settings/roles/RoleSelection";
|
|
|
|
interface Props {
|
|
server: Server;
|
|
}
|
|
|
|
/**
|
|
* Hook to memo-ize role information.
|
|
* @param server Target server
|
|
* @returns Role array
|
|
*/
|
|
export function useRoles(server: Server) {
|
|
return useMemo(
|
|
() =>
|
|
[
|
|
// Pull in known server roles.
|
|
...server.orderedRoles,
|
|
// Include the default server permissions.
|
|
{
|
|
id: "default",
|
|
name: "Default",
|
|
permissions: server.default_permissions,
|
|
},
|
|
] as RoleOrDefault[],
|
|
[server.roles, server.default_permissions],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Roles settings menu
|
|
*/
|
|
export const Roles = observer(({ server }: Props) => {
|
|
// Consolidate all permissions that we can change right now.
|
|
const currentRoles = useRoles(server);
|
|
|
|
// Pull in modal context.
|
|
const { openScreen } = useIntermediate();
|
|
|
|
return (
|
|
<PermissionsLayout
|
|
server={server}
|
|
onCreateRole={(callback) =>
|
|
openScreen({
|
|
id: "special_input",
|
|
type: "create_role",
|
|
server: server as any,
|
|
callback,
|
|
})
|
|
}
|
|
editor={({ selected }) => {
|
|
const currentRole = currentRoles.find(
|
|
(x) => x.id === selected,
|
|
)!;
|
|
|
|
if (!currentRole) return null;
|
|
|
|
// Keep track of whatever role we're editing right now.
|
|
const [value, setValue] = useState<Partial<RoleOrDefault>>({});
|
|
|
|
const currentRoleValue = { ...currentRole, ...value };
|
|
|
|
// Calculate permissions we have access to on this server.
|
|
const current = server.permission;
|
|
|
|
// Upload new role information to server.
|
|
function save() {
|
|
const { permissions: permsCurrent, ...current } =
|
|
currentRole;
|
|
const { permissions: permsValue, ...value } =
|
|
currentRoleValue;
|
|
|
|
if (!isEqual(permsCurrent, permsValue)) {
|
|
server.setPermissions(
|
|
selected,
|
|
typeof permsValue === "number"
|
|
? permsValue
|
|
: {
|
|
allow: permsValue.a,
|
|
deny: permsValue.d,
|
|
},
|
|
);
|
|
}
|
|
|
|
if (!isEqual(current, value)) {
|
|
server.editRole(selected, value);
|
|
}
|
|
}
|
|
|
|
// Delete the role from this server.
|
|
function deleteRole() {
|
|
server.deleteRole(selected);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<SpaceBetween>
|
|
<H1>Edit {currentRole.name}</H1>
|
|
<Button
|
|
palette="secondary"
|
|
disabled={isEqual(
|
|
currentRole,
|
|
currentRoleValue,
|
|
)}
|
|
onClick={save}>
|
|
Save
|
|
</Button>
|
|
</SpaceBetween>
|
|
<hr />
|
|
{selected !== "default" && (
|
|
<>
|
|
<section>
|
|
<Overline type="subtle">Role Name</Overline>
|
|
<p>
|
|
<InputBox
|
|
value={currentRoleValue.name}
|
|
onChange={(e) =>
|
|
setValue({
|
|
...value,
|
|
name: e.currentTarget.value,
|
|
})
|
|
}
|
|
contrast
|
|
/>
|
|
</p>
|
|
</section>
|
|
<section>
|
|
<Overline type="subtle">
|
|
Role Colour
|
|
</Overline>
|
|
<p>
|
|
<ColourSwatches
|
|
value={
|
|
currentRoleValue.colour ??
|
|
"gray"
|
|
}
|
|
onChange={(colour) =>
|
|
setValue({ ...value, colour })
|
|
}
|
|
/>
|
|
</p>
|
|
</section>
|
|
<section>
|
|
<Overline type="subtle">
|
|
Role Options
|
|
</Overline>
|
|
<p>
|
|
<Checkbox
|
|
checked={
|
|
currentRoleValue.hoist ?? false
|
|
}
|
|
onChange={(hoist) =>
|
|
setValue({ ...value, hoist })
|
|
}
|
|
description="Display this role above others.">
|
|
Hoist Role
|
|
</Checkbox>
|
|
</p>
|
|
</section>
|
|
<section>
|
|
<Overline type="subtle">
|
|
Role Ranking
|
|
</Overline>
|
|
<p>
|
|
<InputBox
|
|
type="number"
|
|
value={currentRoleValue.rank ?? 0}
|
|
onChange={(e) =>
|
|
setValue({
|
|
...value,
|
|
rank: parseInt(
|
|
e.currentTarget.value,
|
|
),
|
|
})
|
|
}
|
|
contrast
|
|
/>
|
|
</p>
|
|
</section>
|
|
</>
|
|
)}
|
|
<h1>Edit Permissions</h1>
|
|
<PermissionList
|
|
value={currentRoleValue.permissions}
|
|
onChange={(permissions) =>
|
|
setValue({
|
|
...value,
|
|
permissions,
|
|
} as RoleOrDefault)
|
|
}
|
|
/>
|
|
{selected !== "default" && (
|
|
<>
|
|
<hr />
|
|
<h1>Danger Zone</h1>
|
|
<Button
|
|
palette="error"
|
|
compact
|
|
onClick={deleteRole}>
|
|
Delete Role
|
|
</Button>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}}
|
|
/>
|
|
);
|
|
});
|