mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-06-16 09:39:09 +00:00
feat: add access control
This commit is contained in:
parent
9c07ff0e54
commit
3f45153b66
47 changed files with 1084 additions and 164 deletions
|
@ -1,16 +1,13 @@
|
|||
import { Button } from '@roleypoly/design-system/atoms/button';
|
||||
import { Popover } from '@roleypoly/design-system/atoms/popover';
|
||||
import { Role } from '@roleypoly/design-system/atoms/role';
|
||||
import { TextInput } from '@roleypoly/design-system/atoms/text-input';
|
||||
import { Toggle } from '@roleypoly/design-system/atoms/toggle';
|
||||
import { Text } from '@roleypoly/design-system/atoms/typography';
|
||||
import { RoleSearch } from '@roleypoly/design-system/molecules/role-search';
|
||||
import { EditableRoleList } from '@roleypoly/design-system/molecules/editable-role-list';
|
||||
import { Category as CategoryT, CategoryType, Role as RoleT } from '@roleypoly/types';
|
||||
import { sortBy, uniq } from 'lodash';
|
||||
import * as React from 'react';
|
||||
import { GoHistory, GoPlus, GoTrashcan } from 'react-icons/go';
|
||||
import { GoHistory, GoTrashcan } from 'react-icons/go';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { AddRoleButton, Box, RoleContainer, Section } from './EditorCategory.styled';
|
||||
import { Box, Section } from './EditorCategory.styled';
|
||||
|
||||
export type CategoryProps = {
|
||||
title: string;
|
||||
|
@ -23,25 +20,12 @@ export type CategoryProps = {
|
|||
};
|
||||
|
||||
export const EditorCategory = (props: CategoryProps) => {
|
||||
const [searchOpen, setSearchOpen] = React.useState(false);
|
||||
|
||||
const updateValue = <T extends keyof CategoryT>(key: T, value: CategoryT[T]) => {
|
||||
props.onChange({ ...props.category, [key]: value });
|
||||
};
|
||||
|
||||
const handleRoleDelete = (role: RoleT) => () => {
|
||||
const updatedRoles = props.category.roles.filter((r) => r !== role.id);
|
||||
updateValue('roles', updatedRoles);
|
||||
};
|
||||
|
||||
const handleRoleAdd = (role: RoleT) => {
|
||||
const updatedRoles = uniq([...props.category.roles, role.id]);
|
||||
updateValue('roles', updatedRoles);
|
||||
setSearchOpen(false);
|
||||
};
|
||||
|
||||
const handleSearchOpen = () => {
|
||||
setSearchOpen(true);
|
||||
const handleRoleListUpdate = (roles: RoleT['id'][]) => () => {
|
||||
updateValue('roles', roles);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -92,81 +76,15 @@ export const EditorCategory = (props: CategoryProps) => {
|
|||
<div>
|
||||
<Text>Roles</Text>
|
||||
</div>
|
||||
<RoleContainer>
|
||||
{props.roles.length > 0 ? (
|
||||
<>
|
||||
{sortBy(props.roles, 'position').map((role) => (
|
||||
<Role
|
||||
key={role.id}
|
||||
role={role}
|
||||
selected={false}
|
||||
type="delete"
|
||||
onClick={handleRoleDelete(role)}
|
||||
/>
|
||||
))}
|
||||
<RoleAddButton onClick={handleSearchOpen} tooltipId={props.category.id} />
|
||||
</>
|
||||
) : (
|
||||
<RoleAddButton
|
||||
long
|
||||
onClick={handleSearchOpen}
|
||||
tooltipId={props.category.id}
|
||||
/>
|
||||
)}
|
||||
<RoleSearchPopover
|
||||
isOpen={searchOpen}
|
||||
onExit={() => setSearchOpen(false)}
|
||||
unselectedRoles={props.unselectedRoles}
|
||||
onSelect={handleRoleAdd}
|
||||
/>
|
||||
</RoleContainer>
|
||||
<EditableRoleList
|
||||
roles={props.roles}
|
||||
unselectedRoles={props.unselectedRoles}
|
||||
selectedRoles={props.category.roles}
|
||||
onChange={handleRoleListUpdate}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<ReactTooltip id={props.category.id} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const RoleAddButton = (props: {
|
||||
onClick: () => void;
|
||||
tooltipId: string;
|
||||
long?: boolean;
|
||||
}) => (
|
||||
<AddRoleButton
|
||||
data-tip="Add a role to the category"
|
||||
data-for={props.tooltipId}
|
||||
onClick={props.onClick}
|
||||
long={props.long}
|
||||
>
|
||||
{props.long && <>Add a role </>}
|
||||
<GoPlus />
|
||||
</AddRoleButton>
|
||||
);
|
||||
|
||||
const RoleSearchPopover = (props: {
|
||||
onSelect: (role: RoleT) => void;
|
||||
onExit: (type: string) => void;
|
||||
isOpen: boolean;
|
||||
unselectedRoles: RoleT[];
|
||||
}) => {
|
||||
const [searchTerm, setSearchTerm] = React.useState('');
|
||||
|
||||
return (
|
||||
<Popover
|
||||
position="top left"
|
||||
active={props.isOpen}
|
||||
canDefocus
|
||||
onExit={props.onExit}
|
||||
headContent={null}
|
||||
>
|
||||
{() => (
|
||||
<RoleSearch
|
||||
onSelect={props.onSelect}
|
||||
roles={props.unselectedRoles}
|
||||
searchTerm={searchTerm}
|
||||
onSearchUpdate={setSearchTerm}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue