diff --git a/client/src/components/Dashboard/Dashboard.js b/client/src/components/Dashboard/Dashboard.js
index c9039f7a5..4488809d3 100644
--- a/client/src/components/Dashboard/Dashboard.js
+++ b/client/src/components/Dashboard/Dashboard.js
@@ -1,6 +1,5 @@
import React from 'react';
import { Switch, Route } from 'react-router';
-import { useQuery } from 'react-query';
import 'style/pages/Dashboard/Dashboard.scss';
diff --git a/client/src/components/Preferences/PreferencesSubContent.js b/client/src/components/Preferences/PreferencesSubContent.js
index df50dee30..6584a16b0 100644
--- a/client/src/components/Preferences/PreferencesSubContent.js
+++ b/client/src/components/Preferences/PreferencesSubContent.js
@@ -4,7 +4,7 @@ import {Switch, Route, useRouteMatch} from 'react-router-dom';
export default function PreferencesSubContent({ preferenceTab }) {
const routes = preferencesTabs[preferenceTab];
- const {path} = useRouteMatch();
+ const { path } = useRouteMatch();
if (routes.length <= 0) { return null; }
diff --git a/client/src/containers/Alerts/Users/UserActivateAlert.js b/client/src/containers/Alerts/Users/UserActivateAlert.js
new file mode 100644
index 000000000..e9d98a6e8
--- /dev/null
+++ b/client/src/containers/Alerts/Users/UserActivateAlert.js
@@ -0,0 +1,6 @@
+
+
+
+function UserActivateAlert() {
+
+}
\ No newline at end of file
diff --git a/client/src/containers/Alerts/Users/UserDeleteAlert.js b/client/src/containers/Alerts/Users/UserDeleteAlert.js
new file mode 100644
index 000000000..13ccbb1da
--- /dev/null
+++ b/client/src/containers/Alerts/Users/UserDeleteAlert.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import { Intent, Alert } from '@blueprintjs/core';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+
+import { useDeleteUser } from 'hooks/query';
+import { AppToaster } from 'components';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'redux';
+
+/**
+ * User delete alert.
+ */
+function UserDeleteAlert({
+ // #ownProps
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { userId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { formatMessage } = useIntl();
+ const { mutateAsync: deleteUserMutate, isLoading } = useDeleteUser();
+
+ const handleCancelUserDelete = () => {
+ closeAlert(name);
+ };
+
+ const handleConfirmUserDelete = () => {
+ deleteUserMutate(userId)
+ .then((response) => {
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_user_has_been_deleted_successfully',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch(({ response: { data: { errors } } }) => {
+ if (errors.find(e => e.type === 'CANNOT_DELETE_LAST_USER')) {
+ AppToaster.show({
+ message: 'Cannot delete the last user in the system.',
+ intent: Intent.DANGER,
+ });
+ }
+ closeAlert(name);
+ });
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ intent={Intent.DANGER}
+ isOpen={isOpen}
+ onCancel={handleCancelUserDelete}
+ onConfirm={handleConfirmUserDelete}
+ loading={isLoading}
+ >
+
+ Once you delete this user, you won't be able to restore it later. Are
+ you sure you want to delete ?
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(UserDeleteAlert);
diff --git a/client/src/containers/Alerts/Users/UserInactivateAlert.js b/client/src/containers/Alerts/Users/UserInactivateAlert.js
new file mode 100644
index 000000000..335452283
--- /dev/null
+++ b/client/src/containers/Alerts/Users/UserInactivateAlert.js
@@ -0,0 +1,68 @@
+import React from 'react';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import { Alert, Intent } from '@blueprintjs/core';
+import { AppToaster } from 'components';
+import { useInactivateUser } from 'hooks/query';
+
+import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
+import withAlertActions from 'containers/Alert/withAlertActions';
+
+import { compose } from 'utils';
+
+/**
+ * User inactivate alert.
+ */
+function UserInactivateAlert({
+ // #ownProps
+ name,
+
+ // #withAlertStoreConnect
+ isOpen,
+ payload: { userId },
+
+ // #withAlertActions
+ closeAlert,
+}) {
+ const { formatMessage } = useIntl();
+
+ const { mutateAsync: userInactivateMutate } = useInactivateUser();
+
+ const handleConfirmInactivate = () => {
+ userInactivateMutate(userId)
+ .then(() => {
+ AppToaster.show({
+ message: formatMessage({
+ id: 'the_user_has_been_inactivated_successfully',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ })
+ .catch((error) => {
+
+ });
+ };
+
+ const handleCancel = () => {
+ closeAlert(name);
+ };
+
+ return (
+ }
+ confirmButtonText={}
+ intent={Intent.WARNING}
+ isOpen={isOpen}
+ onCancel={handleCancel}
+ onConfirm={handleConfirmInactivate}
+ >
+
+
+
+
+ );
+}
+
+export default compose(
+ withAlertStoreConnect(),
+ withAlertActions,
+)(UserInactivateAlert);
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js
index 31f10bed2..61df70c3f 100644
--- a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js
@@ -1,19 +1,14 @@
-import React, { useMemo, useCallback } from 'react';
+import React from 'react';
import {
- Button,
Classes,
FormGroup,
InputGroup,
- Intent,
} from '@blueprintjs/core';
-import { Form, useFormikContext, FastField } from 'formik';
-import { FormattedMessage as T, useIntl } from 'react-intl';
-import { pick } from 'lodash';
+import { FastField } from 'formik';
+import { FormattedMessage as T } from 'react-intl';
import {
ErrorMessage,
- AppToaster,
FieldRequiredHint,
- DialogContent,
} from 'components';
import { useAutofocus } from 'hooks';
@@ -33,7 +28,7 @@ export default function CurrencyFormFields() {
className={'form-group--currency-name'}
intent={inputIntent({ error, touched })}
helperText={}
- inline={true}
+ // inline={true}
>
(currencyNameFieldRef.current = ref)}
@@ -51,7 +46,7 @@ export default function CurrencyFormFields() {
className={'form-group--currency-code'}
intent={inputIntent({ error, touched })}
helperText={}
- inline={true}
+ // inline={true}
>
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js
index 6098b5649..545b86b47 100644
--- a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js
@@ -14,7 +14,7 @@ function CurrencyFormProvider({ isEditMode, currency, dialogName, ...props }) {
const { mutateAsync: editCurrencyMutate } = useEditCurrency();
// fetch Currencies list.
- const { data: currencies, isFetching: isCurrenciesLoading } = useCurrencies();
+ const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
// Provider state.
const provider = {
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/index.js b/client/src/containers/Dialogs/CurrencyFormDialog/index.js
index fe98130f2..5125602b9 100644
--- a/client/src/containers/Dialogs/CurrencyFormDialog/index.js
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/index.js
@@ -1,5 +1,5 @@
import React, { lazy } from 'react';
-import { FormattedMessage as T, useIntl } from 'react-intl';
+import { FormattedMessage as T } from 'react-intl';
import { Dialog, DialogSuspense } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
@@ -30,6 +30,7 @@ function CurrencyFormDialog({
isOpen={isOpen}
autoFocus={true}
canEscapeKeyClose={true}
+ style={{ width: '450px' }}
>
{
- const fields = {};
-
- if (errors.find(error => error.type === 'EMAIL.ALREADY.INVITED')) {
- fields.email = formatMessage({ id: 'email_is_already_used' });
- }
- return fields;
- }
\ No newline at end of file
+ const fields = {};
+
+ if (errors.find((error) => error.type === 'EMAIL.ALREADY.INVITED')) {
+ fields.email = formatMessage({ id: 'email_is_already_used' });
+ }
+ return fields;
+};
diff --git a/client/src/containers/Preferences/Currencies/CurrenciesProvider.js b/client/src/containers/Preferences/Currencies/CurrenciesProvider.js
index 19bc96928..cdf777fb1 100644
--- a/client/src/containers/Preferences/Currencies/CurrenciesProvider.js
+++ b/client/src/containers/Preferences/Currencies/CurrenciesProvider.js
@@ -8,7 +8,7 @@ const CurrenciesContext = createContext();
*/
function CurrenciesProvider({ ...props }) {
// fetches the currencies list.
- const { data: currencies, isFetching: isCurrenciesLoading } = useCurrencies();
+ const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
const state = {
currencies,
@@ -16,9 +16,7 @@ function CurrenciesProvider({ ...props }) {
};
return (
- <>
-
- >
+
);
}
diff --git a/client/src/containers/Preferences/Users/Users.js b/client/src/containers/Preferences/Users/Users.js
index ebb0405cf..31ec33693 100644
--- a/client/src/containers/Preferences/Users/Users.js
+++ b/client/src/containers/Preferences/Users/Users.js
@@ -2,10 +2,16 @@ import React from 'react';
import { Tabs, Tab } from '@blueprintjs/core';
import classNames from 'classnames';
+import 'style/pages/Preferences/Users.scss'
+
import { CLASSES } from 'common/classes';
import PreferencesSubContent from 'components/Preferences/PreferencesSubContent';
+
import withUserPreferences from 'containers/Preferences/Users/withUserPreferences';
+/**
+ * Preferences page - Users page.
+ */
function UsersPreferences({ openDialog }) {
const onChangeTabs = (currentTabId) => {};
diff --git a/client/src/containers/Preferences/Users/UsersAlerts.js b/client/src/containers/Preferences/Users/UsersAlerts.js
new file mode 100644
index 000000000..73717281f
--- /dev/null
+++ b/client/src/containers/Preferences/Users/UsersAlerts.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import UserDeleteAlert from 'containers/Alerts/Users/UserDeleteAlert';
+import UserInactivateAlert from 'containers/Alerts/Users/UserInactivateAlert';
+// import UserActivateAlert from 'containers/Alerts/UserActivateAlert';
+
+export default function UsersAlerts() {
+ return (
+ <>
+
+
+ {/* */}
+ >
+ );
+}
diff --git a/client/src/containers/Preferences/Users/UsersDataTable.js b/client/src/containers/Preferences/Users/UsersDataTable.js
index a2c9f05d6..3243b860a 100644
--- a/client/src/containers/Preferences/Users/UsersDataTable.js
+++ b/client/src/containers/Preferences/Users/UsersDataTable.js
@@ -1,178 +1,78 @@
-import React, { useCallback, useState, useMemo } from 'react';
-import {
- Intent,
- Button,
- Popover,
- Menu,
- MenuDivider,
- Tag,
- MenuItem,
- Position,
-} from '@blueprintjs/core';
-import { withRouter } from 'react-router';
-import { snakeCase } from 'lodash';
+import React, { useCallback } from 'react';
-import { FormattedMessage as T, useIntl } from 'react-intl';
-import { compose, firstLettersArgs } from 'utils';
-
-import { DataTable, Icon, If } from 'components';
+import { compose } from 'utils';
+import { DataTable } from 'components';
import withDialogActions from 'containers/Dialog/withDialogActions';
-import withUsers from 'containers/Users/withUsers';
+import withAlertActions from 'containers/Alert/withAlertActions';
-const AvatarCell = (row) => {
- return { firstLettersArgs(row.email) };
-}
+import { ActionsMenu, useUsersListColumns } from './components';
+import { useUsersListContext } from './UsersProvider';
+/**
+ * Users datatable.
+ */
function UsersDataTable({
// #withDialogActions
openDialog,
- // #withUsers
- usersList,
- usersLoading,
-
- // #ownProps
- loading,
- onFetchData,
- onInactiveUser,
- onDeleteUser,
- onSelectedRowsChange,
+ // #withAlertActions
+ openAlert,
}) {
- const { formatMessage } = useIntl();
-
- const onEditUser = useCallback(
- (user) => () => {
- const form = Object.keys(user).reduce((obj, key) => {
- const camelKey = snakeCase(key);
- obj[camelKey] = user[key];
- return obj;
- }, {});
-
- openDialog('userList-form', { action: 'edit', user: form });
+ // Handle edit user action.
+ const handleEditUserAction = useCallback(
+ (user) => {
+ openDialog('userList-form', { action: 'edit', userId: user.id });
},
[openDialog],
);
-
- const actionMenuList = useCallback(
- (user) => (
-
- ),
- [onInactiveUser, onDeleteUser, onEditUser, formatMessage],
- );
- const onRowContextMenu = useCallback(
- (cell) => {
- return actionMenuList(cell.row.original);
+ // Handle inactivate user action.
+ const handleInactivateUser = useCallback(
+ (user) => {
+ openAlert('user-inactivate', { userId: user.id });
},
- [actionMenuList],
+ [openAlert]
);
-
- const columns = useMemo(
- () => [
- {
- id: 'avatar',
- Header: '',
- accessor: AvatarCell,
- width: 100,
- },
- {
- id: 'full_name',
- Header: formatMessage({ id: 'full_name' }),
- accessor: 'full_name',
- width: 150,
- },
- {
- id: 'email',
- Header: formatMessage({ id: 'email' }),
- accessor: 'email',
- width: 150,
- },
- {
- id: 'phone_number',
- Header: formatMessage({ id: 'phone_number' }),
- accessor: 'phone_number',
- width: 120,
- },
- {
- id: 'status',
- Header: 'Status',
- accessor: (user) =>
- !user.invite_accepted_at ? (
-
-
-
- ) : user.active ? (
-
-
-
- ) : (
-
-
-
- ),
- width: 80,
- className: 'status',
- },
- {
- id: 'actions',
- Header: '',
- Cell: ({ cell }) => (
-
- } />
-
- ),
- className: 'actions',
- width: 50,
- disableResizing: true,
- },
- ],
- [actionMenuList, formatMessage],
- );
-
- const handelDataTableFetchData = useCallback(
- (...args) => {
- onFetchData && onFetchData(...args);
+ // Handle activate user action.
+ const handleActivateuser = useCallback(
+ (user) => {
+ openAlert('user-activate', { userId: user.id });
},
- [onFetchData],
+ [openAlert]
);
+ // Handle delete user action.
+ const handleDeleteUser = useCallback(
+ (user) => {
+ openAlert('user-delete', { userId: user.id });
+ },
+ [openAlert]
+ );
+ // Users list columns.
+ const columns = useUsersListColumns();
+
+ // Users list context.
+ const { users, isUsersLoading, isUsersFetching } = useUsersListContext();
+
return (
);
}
export default compose(
- withRouter,
withDialogActions,
- withUsers(({ usersList, usersLoading }) => ({ usersList, usersLoading })),
+ withAlertActions
)(UsersDataTable);
diff --git a/client/src/containers/Preferences/Users/UsersList.js b/client/src/containers/Preferences/Users/UsersList.js
index 73e3a4a5f..840aaa0f6 100644
--- a/client/src/containers/Preferences/Users/UsersList.js
+++ b/client/src/containers/Preferences/Users/UsersList.js
@@ -1,140 +1,34 @@
-import React, { useState, useCallback, useEffect } from 'react';
-import { queryCache, useQuery } from 'react-query';
-import { Alert, Intent } from '@blueprintjs/core';
+import React, { useEffect } from 'react';
+import { useIntl } from 'react-intl';
+import {UsersListProvider } from './UsersProvider';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
-import withUsersActions from 'containers/Users/withUsersActions';
import UsersDataTable from './UsersDataTable';
-import {
- FormattedMessage as T,
- FormattedHTMLMessage,
- useIntl,
-} from 'react-intl';
-
-import AppToaster from 'components/AppToaster';
-
+import UsersAlerts from './UsersAlerts';
import { compose } from 'utils';
+/**
+ * Users list.
+ */
function UsersListPreferences({
// #withDashboardActions
changePreferencesPageTitle,
-
- // #withUsersActions
- requestDeleteUser,
- requestInactiveUser,
- requestFetchUsers,
}) {
- const [deleteUserState, setDeleteUserState] = useState(false);
- const [inactiveUserState, setInactiveUserState] = useState(false);
-
const { formatMessage } = useIntl();
- const fetchUsers = useQuery('users-table', () => requestFetchUsers());
-
useEffect(() => {
changePreferencesPageTitle(formatMessage({ id: 'users' }));
}, [changePreferencesPageTitle, formatMessage]);
- // Handle cancel/confirm user inactive.
- const handleInactiveUser = useCallback((user) => {
- setInactiveUserState(user);
- }, []);
-
- // Handle cancel inactive user alert
- const handleCancelInactiveUser = useCallback(() => {
- setInactiveUserState(false);
- }, []);
-
- // handel confirm user activation
- const handleConfirmUserActive = useCallback(() => {
- requestInactiveUser(inactiveUserState.id)
- .then(() => {
- setInactiveUserState(false);
- AppToaster.show({
- message: formatMessage({
- id: 'the_user_has_been_inactivated_successfully',
- }),
- intent: Intent.SUCCESS,
- });
- queryCache.invalidateQueries('users-table');
- })
- .catch((error) => {
- setInactiveUserState(false);
- });
- }, [inactiveUserState, requestInactiveUser, formatMessage]);
-
- // Handle click and cancel/confirm user delete
- const handleDeleteUser = useCallback((user) => {
- setDeleteUserState(user);
- }, []);
-
- // handle cancel delete user alert.
- const handleCancelUserDelete = () => {
- setDeleteUserState(false);
- };
-
- const handleEditUser = useCallback(() => {}, []);
-
- // Handle confirm User delete
- const handleConfirmUserDelete = useCallback(() => {
- if (!deleteUserState) {
- return;
- }
- requestDeleteUser(deleteUserState.id)
- .then((response) => {
- setDeleteUserState(false);
- AppToaster.show({
- message: formatMessage({
- id: 'the_user_has_been_deleted_successfully',
- }),
- intent: Intent.SUCCESS,
- });
- queryCache.invalidateQueries('users-table');
- })
- .catch((errors) => {
- setDeleteUserState(false);
- });
- }, [deleteUserState, requestDeleteUser, formatMessage]);
-
-
return (
- <>
-
- }
- confirmButtonText={}
- intent={Intent.DANGER}
- isOpen={deleteUserState}
- onCancel={handleCancelUserDelete}
- onConfirm={handleConfirmUserDelete}
- >
-
- Once you delete this user, you won't be able to restore it later. Are you sure you want to delete ?
-
-
- }
- confirmButtonText={}
- intent={Intent.WARNING}
- isOpen={inactiveUserState}
- onCancel={handleCancelInactiveUser}
- onConfirm={handleConfirmUserActive}
- >
-
-
-
-
- >
+
+
+
+
);
}
export default compose(
withDashboardActions,
- withUsersActions,
)(UsersListPreferences);
diff --git a/client/src/containers/Preferences/Users/UsersProvider.js b/client/src/containers/Preferences/Users/UsersProvider.js
new file mode 100644
index 000000000..eabf0fe40
--- /dev/null
+++ b/client/src/containers/Preferences/Users/UsersProvider.js
@@ -0,0 +1,25 @@
+import React, { createContext } from 'react';
+import { useUsers } from 'hooks/query';
+
+const UsersListContext = createContext();
+
+/**
+ * Users list provider.
+ */
+function UsersListProvider(props) {
+ const { data: users, isLoading, isFetching } = useUsers();
+
+ const state = {
+ isUsersLoading: isLoading,
+ isUsersFetching: isFetching,
+ users,
+ };
+
+ return (
+
+ );
+}
+
+const useUsersListContext = () => React.useContext(UsersListContext);
+
+export { UsersListProvider, useUsersListContext };
diff --git a/client/src/containers/Preferences/Users/components.js b/client/src/containers/Preferences/Users/components.js
new file mode 100644
index 000000000..e4235c077
--- /dev/null
+++ b/client/src/containers/Preferences/Users/components.js
@@ -0,0 +1,143 @@
+import React from 'react';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import {
+ Intent,
+ Button,
+ Popover,
+ Menu,
+ MenuDivider,
+ Tag,
+ MenuItem,
+ Position,
+} from '@blueprintjs/core';
+import { safeCallback, firstLettersArgs } from 'utils';
+import { Icon, If } from 'components';
+
+/**
+ * Avatar cell.
+ */
+function AvatarCell(row) {
+ return {firstLettersArgs(row.email)};
+}
+
+/**
+ * Users table actions menu.
+ */
+export function ActionsMenu({
+ row: { original },
+ payload: {
+ onEdit,
+ onInactivate,
+ onActivate,
+ onDelete
+ }
+}) {
+ const { formatMessage } = useIntl();
+
+ return (
+
+ );
+}
+
+/**
+ * Status accessor.
+ */
+function StatusAccessor(user) {
+ return !user.invite_accepted_at ? (
+
+
+
+ ) : user.active ? (
+
+
+
+ ) : (
+
+
+
+ );
+}
+
+/**
+ * Actions cell.
+ */
+function ActionsCell(props) {
+ return (
+ }
+ position={Position.RIGHT_BOTTOM}
+ >
+ } />
+
+ );
+}
+
+export const useUsersListColumns = () => {
+ const { formatMessage } = useIntl();
+
+ return React.useMemo(
+ () => [
+ {
+ id: 'avatar',
+ Header: '',
+ accessor: AvatarCell,
+ width: 40,
+ },
+ {
+ id: 'full_name',
+ Header: formatMessage({ id: 'full_name' }),
+ accessor: 'full_name',
+ width: 150,
+ },
+ {
+ id: 'email',
+ Header: formatMessage({ id: 'email' }),
+ accessor: 'email',
+ width: 150,
+ },
+ {
+ id: 'phone_number',
+ Header: formatMessage({ id: 'phone_number' }),
+ accessor: 'phone_number',
+ width: 120,
+ },
+ {
+ id: 'status',
+ Header: 'Status',
+ accessor: StatusAccessor,
+ width: 80,
+ className: 'status',
+ },
+ {
+ id: 'actions',
+ Header: '',
+ Cell: ActionsCell,
+ className: 'actions',
+ width: 50,
+ disableResizing: true,
+ },
+ ],
+ [formatMessage],
+ );
+};
diff --git a/client/src/hooks/query/users.js b/client/src/hooks/query/users.js
index 9bb908730..0298e8c0c 100644
--- a/client/src/hooks/query/users.js
+++ b/client/src/hooks/query/users.js
@@ -1,6 +1,5 @@
import { useMutation, useQueryClient } from 'react-query';
-import { defaultTo } from 'lodash';
-import { useQueryTenant } from '../useQueryRequest';
+import { useQueryTenant, useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import t from './types';
@@ -43,6 +42,24 @@ export function useEditUser(props) {
});
}
+export function useInactivateUser(props) {
+ const apiRequest = useApiRequest();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ ([id, values]) => apiRequest.post(`users/${id}/inactivate`, values),
+ {
+ onSuccess: (res, [id, values]) => {
+ queryClient.invalidateQueries([t.USER, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
/**
* Deletes the given user.
*/
@@ -53,7 +70,7 @@ export function useDeleteUser(props) {
return useMutation((id) => apiRequest.delete(`users/${id}`), {
onSuccess: (res, id) => {
queryClient.invalidateQueries([t.USER, id]);
-
+
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -65,18 +82,18 @@ export function useDeleteUser(props) {
* Retrieves users list.
*/
export function useUsers(props) {
- const apiRequest = useApiRequest();
-
- const result = useQueryTenant(
+ return useRequestQuery(
[t.USERS],
- () => apiRequest.get(`USERS`).then((response) => response.data.users),
- props,
+ {
+ method: 'get',
+ url: 'users',
+ },
+ {
+ select: (res) => res.data.users,
+ defaultData: [],
+ ...props,
+ },
);
-
- return {
- ...result,
- data: defaultTo(result.data, {}),
- };
}
/**
diff --git a/client/src/style/pages/Preferences/Sidebar.scss b/client/src/style/pages/Preferences/Sidebar.scss
index 2c49edbae..6966e30fc 100644
--- a/client/src/style/pages/Preferences/Sidebar.scss
+++ b/client/src/style/pages/Preferences/Sidebar.scss
@@ -41,6 +41,7 @@
align-items: center;
height: 60px;
padding: 0 22px;
+ border-bottom: 1px solid #c9d9de;
h2 {
font-size: 22px;
diff --git a/client/src/style/pages/Preferences/UsersList.scss b/client/src/style/pages/Preferences/Users.scss
similarity index 91%
rename from client/src/style/pages/Preferences/UsersList.scss
rename to client/src/style/pages/Preferences/Users.scss
index 1045182c2..9046fb9f1 100644
--- a/client/src/style/pages/Preferences/UsersList.scss
+++ b/client/src/style/pages/Preferences/Users.scss
@@ -3,10 +3,11 @@
// ---------------------------------
.preferences-page__inside-content--users{
- .bigcapital-datatable {
+.bigcapital-datatable {
.td{
.avatar{
+ display: block;
height: 28px;
width: 28px;
text-align: center;