import { t } from "@lingui/core/macro"; import { permissionCategories, roles } from "@kan/shared"; import type { Permission, Role } from "@kan/shared"; import { useWorkspace } from "~/providers/workspace"; import { api } from "~/utils/api"; function formatRoleLabel(role: Role) { return role.charAt(0).toUpperCase() + role.slice(1); } const permissionLabels: Record = { "workspace:view": t`Can view workspace`, "workspace:edit": t`Can edit workspace`, "workspace:delete": t`Can delete workspace`, "workspace:manage": t`Can manage workspace settings`, "board:view": t`Can view boards`, "board:create": t`Can create boards`, "board:edit": t`Can edit boards`, "board:delete": t`Can delete boards`, "list:view": t`Can view lists`, "list:create": t`Can create lists`, "list:edit": t`Can edit lists`, "list:delete": t`Can delete lists`, "card:view": t`Can view cards`, "card:create": t`Can create cards`, "card:edit": t`Can edit cards`, "card:delete": t`Can delete cards`, "comment:view": t`Can view comments`, "comment:create": t`Can add comments`, "comment:edit": t`Can edit comments`, "comment:delete": t`Can delete comments`, "member:view": t`Can view members`, "member:invite": t`Can invite members`, "member:edit": t`Can edit member roles and permissions`, "member:remove": t`Can remove members`, }; export function RolePermissions() { const { workspace } = useWorkspace(); const utils = api.useUtils(); const { data, isLoading } = api.permission.getWorkspaceRolePermissions.useQuery( { workspacePublicId: workspace.publicId }, { enabled: !!workspace.publicId }, ); const systemRoles = (data?.roles ?? []).filter((role) => (roles).includes(role.name as Role), ); const orderedRoleNames: Role[] = ["admin", "member", "guest"].filter( (role) => systemRoles.some((r) => r.name === role), ) as Role[]; const grantMutation = api.permission.grantRolePermission.useMutation({ onSettled: async () => { if (!workspace.publicId) return; await utils.permission.getWorkspaceRolePermissions.invalidate({ workspacePublicId: workspace.publicId, }); }, }); const revokeMutation = api.permission.revokeRolePermission.useMutation({ onSettled: async () => { if (!workspace.publicId) return; await utils.permission.getWorkspaceRolePermissions.invalidate({ workspacePublicId: workspace.publicId, }); }, }); const isBusy = grantMutation.isPending || revokeMutation.isPending; const handleToggle = ( rolePublicId: string, permission: Permission, checked: boolean, ) => { if (!workspace.publicId || !rolePublicId) return; if (checked) { grantMutation.mutate({ workspacePublicId: workspace.publicId, rolePublicId, permission, }); } else { revokeMutation.mutate({ workspacePublicId: workspace.publicId, rolePublicId, permission, }); } }; return (
{orderedRoleNames.length === 0 && !isLoading ? (

{t`No roles found for this workspace yet.`}

) : null}
{orderedRoleNames.map((role) => ( ))} {Object.values(permissionCategories).map((category) => ( {category.permissions.map((permission) => ( {orderedRoleNames.map((roleName) => { const role = systemRoles.find((r) => r.name === roleName); const checked = role?.permissions.includes(permission); const isAdminRole = roleName === "admin"; const isBillingOrDeletePermission = permission === "workspace:manage" || permission === "workspace:delete"; return ( ); })} ))} ))}
{t`Permission`} {formatRoleLabel(role)}
{category.label}
{permissionLabels[permission] ?? permission} !isAdminRole && !isBillingOrDeletePermission && role && handleToggle( role.publicId, permission, e.target.checked, ) } />
); }