feat(auth): add loading state for user and role management (#1188)

This commit is contained in:
Rıdvan Akca
2023-08-09 22:51:07 +03:00
committed by GitHub
parent ce8c9906cb
commit 5046c4c911
10 changed files with 308 additions and 171 deletions

View File

@@ -0,0 +1,47 @@
import {
IconButton,
Skeleton,
Stack,
TableCell,
TableRow,
} from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';
type ListLoaderProps = {
rowsNumber: number;
columnsNumber: number;
};
const ListLoader = ({ rowsNumber, columnsNumber }: ListLoaderProps) => {
return (
<>
{[...Array(rowsNumber)].map((row, index) => (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
{[...Array(columnsNumber)].map((cell, index) => (
<TableCell key={index} scope="row">
<Skeleton />
</TableCell>
))}
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton size="small">
<EditIcon />
</IconButton>
<IconButton size="small">
<DeleteIcon />
</IconButton>
</Stack>
</TableCell>
</TableRow>
))}
</>
);
};
export default ListLoader;

View File

@@ -0,0 +1,61 @@
import {
IconButton,
Skeleton,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
} from '@mui/material';
import SettingsIcon from '@mui/icons-material/Settings';
import ControlledCheckbox from 'components/ControlledCheckbox';
const PermissionCatalogFieldLoader = () => {
return (
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell component="th" />
{[...Array(5)].map((row, index) => (
<TableCell key={index} component="th">
<Skeleton />
</TableCell>
))}
<TableCell component="th" />
</TableRow>
</TableHead>
<TableBody>
{[...Array(3)].map((row, index) => (
<TableRow key={index} sx={{ '&:last-child td': { border: 0 } }}>
<TableCell scope="row">
<Skeleton width={40} />
</TableCell>
{[...Array(5)].map((action, index) => (
<TableCell key={index} align="center">
<Typography variant="subtitle2">
<ControlledCheckbox name="value" />
</Typography>
</TableCell>
))}
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton color="info" size="small">
<SettingsIcon />
</IconButton>
</Stack>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
export default PermissionCatalogFieldLoader;

View File

@@ -14,17 +14,21 @@ import * as React from 'react';
import ControlledCheckbox from 'components/ControlledCheckbox';
import usePermissionCatalog from 'hooks/usePermissionCatalog.ee';
import PermissionSettings from './PermissionSettings.ee';
import PermissionCatalogFieldLoader from './PermissionCatalogFieldLoader';
type PermissionCatalogFieldProps = {
name?: string;
disabled?: boolean;
};
const PermissionCatalogField = ({ name = 'permissions', disabled = false }: PermissionCatalogFieldProps) => {
const permissionCatalog = usePermissionCatalog();
const PermissionCatalogField = ({
name = 'permissions',
disabled = false,
}: PermissionCatalogFieldProps) => {
const { permissionCatalog, loading } = usePermissionCatalog();
const [dialogName, setDialogName] = React.useState<string>();
if (!permissionCatalog) return (<React.Fragment />);
if (loading) return <PermissionCatalogFieldLoader />;
return (
<TableContainer component={Paper}>
@@ -33,14 +37,14 @@ const PermissionCatalogField = ({ name = 'permissions', disabled = false }: Perm
<TableRow>
<TableCell component="th" />
{permissionCatalog.actions.map(action => (
{permissionCatalog.actions.map((action) => (
<TableCell component="th" key={action.key}>
<Typography
variant="subtitle1"
align="center"
sx={{
color: 'text.secondary',
fontWeight: 700
fontWeight: 700,
}}
>
{action.label}
@@ -58,21 +62,12 @@ const PermissionCatalogField = ({ name = 'permissions', disabled = false }: Perm
sx={{ '&:last-child td': { border: 0 } }}
>
<TableCell scope="row">
<Typography
variant="subtitle2"
>
{subject.label}
</Typography>
<Typography variant="subtitle2">{subject.label}</Typography>
</TableCell>
{permissionCatalog.actions.map((action) => (
<TableCell
key={`${subject.key}.${action.key}`}
align="center"
>
<Typography
variant="subtitle2"
>
<TableCell key={`${subject.key}.${action.key}`} align="center">
<Typography variant="subtitle2">
{action.subjects.includes(subject.key) && (
<ControlledCheckbox
disabled={disabled}
@@ -86,11 +81,7 @@ const PermissionCatalogField = ({ name = 'permissions', disabled = false }: Perm
))}
<TableCell>
<Stack
direction="row"
gap={1}
justifyContent="right"
>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton
color="info"
size="small"
@@ -116,7 +107,7 @@ const PermissionCatalogField = ({ name = 'permissions', disabled = false }: Perm
</TableBody>
</Table>
</TableContainer>
)
);
};
export default PermissionCatalogField;

View File

@@ -13,14 +13,14 @@ import Typography from '@mui/material/Typography';
import EditIcon from '@mui/icons-material/Edit';
import DeleteRoleButton from 'components/DeleteRoleButton/index.ee';
import ListLoader from 'components/ListLoader';
import useFormatMessage from 'hooks/useFormatMessage';
import useRoles from 'hooks/useRoles.ee';
import * as URLS from 'config/urls';
// TODO: introduce loading bar
export default function RoleList(): React.ReactElement {
const formatMessage = useFormatMessage();
const { roles } = useRoles();
const { roles, loading } = useRoles();
return (
<TableContainer component={Paper}>
@@ -49,34 +49,41 @@ export default function RoleList(): React.ReactElement {
</TableRow>
</TableHead>
<TableBody>
{roles.map((role) => (
<TableRow
key={role.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">
<Typography variant="subtitle2">{role.name}</Typography>
</TableCell>
{loading && <ListLoader rowsNumber={3} columnsNumber={2} />}
{!loading &&
roles.map((role) => (
<TableRow
key={role.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">
<Typography variant="subtitle2">{role.name}</Typography>
</TableCell>
<TableCell scope="row">
<Typography variant="subtitle2">{role.description}</Typography>
</TableCell>
<TableCell scope="row">
<Typography variant="subtitle2">
{role.description}
</Typography>
</TableCell>
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton
size="small"
component={Link}
to={URLS.ROLE(role.id)}
>
<EditIcon />
</IconButton>
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton
size="small"
component={Link}
to={URLS.ROLE(role.id)}
>
<EditIcon />
</IconButton>
<DeleteRoleButton disabled={role.isAdmin} roleId={role.id} />
</Stack>
</TableCell>
</TableRow>
))}
<DeleteRoleButton
disabled={role.isAdmin}
roleId={role.id}
/>
</Stack>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>

View File

@@ -13,11 +13,11 @@ import Typography from '@mui/material/Typography';
import EditIcon from '@mui/icons-material/Edit';
import DeleteUserButton from 'components/DeleteUserButton/index.ee';
import ListLoader from 'components/ListLoader';
import useUsers from 'hooks/useUsers';
import useFormatMessage from 'hooks/useFormatMessage';
import * as URLS from 'config/urls';
// TODO: introduce loading bar
export default function UserList(): React.ReactElement {
const formatMessage = useFormatMessage();
const { users, loading } = useUsers();
@@ -49,34 +49,36 @@ export default function UserList(): React.ReactElement {
</TableRow>
</TableHead>
<TableBody>
{users.map((user) => (
<TableRow
key={user.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">
<Typography variant="subtitle2">{user.fullName}</Typography>
</TableCell>
{loading && <ListLoader rowsNumber={3} columnsNumber={2} />}
{!loading &&
users.map((user) => (
<TableRow
key={user.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">
<Typography variant="subtitle2">{user.fullName}</Typography>
</TableCell>
<TableCell>
<Typography variant="subtitle2">{user.email}</Typography>
</TableCell>
<TableCell>
<Typography variant="subtitle2">{user.email}</Typography>
</TableCell>
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton
size="small"
component={Link}
to={URLS.USER(user.id)}
>
<EditIcon />
</IconButton>
<TableCell>
<Stack direction="row" gap={1} justifyContent="right">
<IconButton
size="small"
component={Link}
to={URLS.USER(user.id)}
>
<EditIcon />
</IconButton>
<DeleteUserButton userId={user.id} />
</Stack>
</TableCell>
</TableRow>
))}
<DeleteUserButton userId={user.id} />
</Stack>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>