refactor: rewrite useRoles with RQ

This commit is contained in:
Rıdvan Akca
2024-03-14 16:33:08 +03:00
parent 29341f81e1
commit 9218091c33
6 changed files with 67 additions and 22 deletions

View File

@@ -11,14 +11,18 @@ import Paper from '@mui/material/Paper';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import EditIcon from '@mui/icons-material/Edit'; import EditIcon from '@mui/icons-material/Edit';
import DeleteRoleButton from 'components/DeleteRoleButton/index.ee'; import DeleteRoleButton from 'components/DeleteRoleButton/index.ee';
import ListLoader from 'components/ListLoader'; import ListLoader from 'components/ListLoader';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useRoles from 'hooks/useRoles.ee'; import useRoles from 'hooks/useRoles.ee';
import * as URLS from 'config/urls'; import * as URLS from 'config/urls';
export default function RoleList() { export default function RoleList() {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { roles, loading } = useRoles(); const { data, isLoading: isRolesLoading } = useRoles();
const roles = data?.data;
return ( return (
<TableContainer component={Paper}> <TableContainer component={Paper}>
<Table> <Table>
@@ -46,15 +50,15 @@ export default function RoleList() {
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{loading && ( {isRolesLoading && (
<ListLoader <ListLoader
rowsNumber={3} rowsNumber={3}
columnsNumber={2} columnsNumber={2}
data-test="roles-list-loader" data-test="roles-list-loader"
/> />
)} )}
{!loading && {!isRolesLoading &&
roles.map((role) => ( roles?.map((role) => (
<TableRow <TableRow
key={role.id} key={role.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}

View File

@@ -1,11 +1,17 @@
import { useQuery } from '@apollo/client'; import { useQuery } from '@tanstack/react-query';
import { GET_ROLES } from 'graphql/queries/get-roles.ee'; import api from 'helpers/api';
export default function useRoles() { export default function useRoles() {
const { data, loading } = useQuery(GET_ROLES, { const query = useQuery({
context: { autoSnackbar: false }, queryKey: ['roles'],
queryFn: async ({ signal }) => {
const { data } = await api.get('/v1/admin/roles', {
signal,
});
return data;
},
}); });
return {
roles: data?.getRoles || [], return query;
loading,
};
} }

View File

@@ -4,24 +4,32 @@ import Stack from '@mui/material/Stack';
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { Divider, Typography } from '@mui/material';
import useRoles from 'hooks/useRoles.ee'; import useRoles from 'hooks/useRoles.ee';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import ControlledAutocomplete from 'components/ControlledAutocomplete'; import ControlledAutocomplete from 'components/ControlledAutocomplete';
import TextField from 'components/TextField'; import TextField from 'components/TextField';
import { Divider, Typography } from '@mui/material';
function generateRoleOptions(roles) { function generateRoleOptions(roles) {
return roles?.map(({ name: label, id: value }) => ({ label, value })); return roles?.map(({ name: label, id: value }) => ({ label, value }));
} }
function RoleMappingsFieldArray() { function RoleMappingsFieldArray() {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { control } = useFormContext(); const { control } = useFormContext();
const { roles, loading: rolesLoading } = useRoles(); const { data, isLoading: isRolesLoading } = useRoles();
const roles = data?.data;
const { fields, append, remove } = useFieldArray({ const { fields, append, remove } = useFieldArray({
control, control,
name: 'roleMappings', name: 'roleMappings',
}); });
const handleAppendMapping = () => append({ roleId: '', remoteRoleName: '' }); const handleAppendMapping = () => append({ roleId: '', remoteRoleName: '' });
const handleRemoveMapping = (index) => () => remove(index); const handleRemoveMapping = (index) => () => remove(index);
return ( return (
<> <>
{fields.length === 0 && ( {fields.length === 0 && (
@@ -60,7 +68,7 @@ function RoleMappingsFieldArray() {
label={formatMessage('roleMappingsForm.role')} label={formatMessage('roleMappingsForm.role')}
/> />
)} )}
loading={rolesLoading} loading={isRolesLoading}
required required
/> />
</Stack> </Stack>

View File

@@ -2,8 +2,9 @@ import { useMutation } from '@apollo/client';
import LoadingButton from '@mui/lab/LoadingButton'; import LoadingButton from '@mui/lab/LoadingButton';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
import MuiTextField from '@mui/material/TextField'; import MuiTextField from '@mui/material/TextField';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
import * as React from 'react'; import * as React from 'react';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
import ControlledAutocomplete from 'components/ControlledAutocomplete'; import ControlledAutocomplete from 'components/ControlledAutocomplete';
import Form from 'components/Form'; import Form from 'components/Form';
import Switch from 'components/Switch'; import Switch from 'components/Switch';
@@ -11,6 +12,7 @@ import TextField from 'components/TextField';
import { UPSERT_SAML_AUTH_PROVIDER } from 'graphql/mutations/upsert-saml-auth-provider'; import { UPSERT_SAML_AUTH_PROVIDER } from 'graphql/mutations/upsert-saml-auth-provider';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useRoles from 'hooks/useRoles.ee'; import useRoles from 'hooks/useRoles.ee';
const defaultValues = { const defaultValues = {
active: false, active: false,
name: '', name: '',
@@ -24,16 +26,21 @@ const defaultValues = {
roleAttributeName: '', roleAttributeName: '',
defaultRoleId: '', defaultRoleId: '',
}; };
function generateRoleOptions(roles) { function generateRoleOptions(roles) {
return roles?.map(({ name: label, id: value }) => ({ label, value })); return roles?.map(({ name: label, id: value }) => ({ label, value }));
} }
function SamlConfiguration({ provider, providerLoading, refetchProvider }) { function SamlConfiguration({ provider, providerLoading, refetchProvider }) {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const { roles, loading: rolesLoading } = useRoles(); const { data, loading: isRolesLoading } = useRoles();
const roles = data?.data;
const enqueueSnackbar = useEnqueueSnackbar(); const enqueueSnackbar = useEnqueueSnackbar();
const [upsertSamlAuthProvider, { loading }] = useMutation( const [upsertSamlAuthProvider, { loading }] = useMutation(
UPSERT_SAML_AUTH_PROVIDER, UPSERT_SAML_AUTH_PROVIDER,
); );
const handleProviderUpdate = async (providerDataToUpdate) => { const handleProviderUpdate = async (providerDataToUpdate) => {
try { try {
const { const {
@@ -66,9 +73,11 @@ function SamlConfiguration({ provider, providerLoading, refetchProvider }) {
}, },
}, },
}); });
if (!provider?.id) { if (!provider?.id) {
await refetchProvider(); await refetchProvider();
} }
enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), { enqueueSnackbar(formatMessage('authenticationForm.successfullySaved'), {
variant: 'success', variant: 'success',
SnackbarProps: { SnackbarProps: {
@@ -79,9 +88,11 @@ function SamlConfiguration({ provider, providerLoading, refetchProvider }) {
throw new Error('Failed while saving!'); throw new Error('Failed while saving!');
} }
}; };
if (providerLoading) { if (providerLoading) {
return null; return null;
} }
return ( return (
<Form <Form
defaultValues={provider || defaultValues} defaultValues={provider || defaultValues}
@@ -170,7 +181,7 @@ function SamlConfiguration({ provider, providerLoading, refetchProvider }) {
label={formatMessage('authenticationForm.defaultRole')} label={formatMessage('authenticationForm.defaultRole')}
/> />
)} )}
loading={rolesLoading} loading={isRolesLoading}
/> />
<LoadingButton <LoadingButton
type="submit" type="submit"

View File

@@ -6,6 +6,7 @@ import MuiTextField from '@mui/material/TextField';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar'; import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
import * as React from 'react'; import * as React from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Can from 'components/Can'; import Can from 'components/Can';
import Container from 'components/Container'; import Container from 'components/Container';
import ControlledAutocomplete from 'components/ControlledAutocomplete'; import ControlledAutocomplete from 'components/ControlledAutocomplete';
@@ -16,15 +17,19 @@ import * as URLS from 'config/urls';
import { CREATE_USER } from 'graphql/mutations/create-user.ee'; import { CREATE_USER } from 'graphql/mutations/create-user.ee';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useRoles from 'hooks/useRoles.ee'; import useRoles from 'hooks/useRoles.ee';
function generateRoleOptions(roles) { function generateRoleOptions(roles) {
return roles?.map(({ name: label, id: value }) => ({ label, value })); return roles?.map(({ name: label, id: value }) => ({ label, value }));
} }
export default function CreateUser() { export default function CreateUser() {
const navigate = useNavigate(); const navigate = useNavigate();
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [createUser, { loading }] = useMutation(CREATE_USER); const [createUser, { loading }] = useMutation(CREATE_USER);
const { roles, loading: rolesLoading } = useRoles(); const { data, loading: isRolesLoading } = useRoles();
const roles = data?.data;
const enqueueSnackbar = useEnqueueSnackbar(); const enqueueSnackbar = useEnqueueSnackbar();
const handleUserCreation = async (userData) => { const handleUserCreation = async (userData) => {
try { try {
await createUser({ await createUser({
@@ -39,6 +44,7 @@ export default function CreateUser() {
}, },
}, },
}); });
enqueueSnackbar(formatMessage('createUser.successfullyCreated'), { enqueueSnackbar(formatMessage('createUser.successfullyCreated'), {
variant: 'success', variant: 'success',
persist: true, persist: true,
@@ -46,11 +52,13 @@ export default function CreateUser() {
'data-test': 'snackbar-create-user-success', 'data-test': 'snackbar-create-user-success',
}, },
}); });
navigate(URLS.USERS); navigate(URLS.USERS);
} catch (error) { } catch (error) {
throw new Error('Failed while creating!'); throw new Error('Failed while creating!');
} }
}; };
return ( return (
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}> <Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}> <Grid container item xs={12} sm={10} md={9}>
@@ -101,7 +109,7 @@ export default function CreateUser() {
label={formatMessage('userForm.role')} label={formatMessage('userForm.role')}
/> />
)} )}
loading={rolesLoading} loading={isRolesLoading}
/> />
</Can> </Can>

View File

@@ -7,6 +7,7 @@ import MuiTextField from '@mui/material/TextField';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar'; import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
import * as React from 'react'; import * as React from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import Can from 'components/Can'; import Can from 'components/Can';
import Container from 'components/Container'; import Container from 'components/Container';
import ControlledAutocomplete from 'components/ControlledAutocomplete'; import ControlledAutocomplete from 'components/ControlledAutocomplete';
@@ -18,17 +19,21 @@ import { UPDATE_USER } from 'graphql/mutations/update-user.ee';
import useFormatMessage from 'hooks/useFormatMessage'; import useFormatMessage from 'hooks/useFormatMessage';
import useRoles from 'hooks/useRoles.ee'; import useRoles from 'hooks/useRoles.ee';
import useUser from 'hooks/useUser'; import useUser from 'hooks/useUser';
function generateRoleOptions(roles) { function generateRoleOptions(roles) {
return roles?.map(({ name: label, id: value }) => ({ label, value })); return roles?.map(({ name: label, id: value }) => ({ label, value }));
} }
export default function EditUser() { export default function EditUser() {
const formatMessage = useFormatMessage(); const formatMessage = useFormatMessage();
const [updateUser, { loading }] = useMutation(UPDATE_USER); const [updateUser, { loading }] = useMutation(UPDATE_USER);
const { userId } = useParams(); const { userId } = useParams();
const { user, loading: userLoading } = useUser(userId); const { user, loading: userLoading } = useUser(userId);
const { roles, loading: rolesLoading } = useRoles(); const { data, loading: isRolesLoading } = useRoles();
const roles = data?.data;
const enqueueSnackbar = useEnqueueSnackbar(); const enqueueSnackbar = useEnqueueSnackbar();
const navigate = useNavigate(); const navigate = useNavigate();
const handleUserUpdate = async (userDataToUpdate) => { const handleUserUpdate = async (userDataToUpdate) => {
try { try {
await updateUser({ await updateUser({
@@ -43,6 +48,7 @@ export default function EditUser() {
}, },
}, },
}); });
enqueueSnackbar(formatMessage('editUser.successfullyUpdated'), { enqueueSnackbar(formatMessage('editUser.successfullyUpdated'), {
variant: 'success', variant: 'success',
SnackbarProps: { SnackbarProps: {
@@ -50,11 +56,13 @@ export default function EditUser() {
persist: true, persist: true,
}, },
}); });
navigate(URLS.USERS); navigate(URLS.USERS);
} catch (error) { } catch (error) {
throw new Error('Failed while updating!'); throw new Error('Failed while updating!');
} }
}; };
return ( return (
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}> <Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}> <Grid container item xs={12} sm={10} md={9}>
@@ -106,7 +114,7 @@ export default function EditUser() {
label={formatMessage('userForm.role')} label={formatMessage('userForm.role')}
/> />
)} )}
loading={rolesLoading} loading={isRolesLoading}
/> />
</Can> </Can>