mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
WIP fix-general
This commit is contained in:
@@ -3,10 +3,12 @@ import AccountFormDialog from 'containers/Dashboard/Dialogs/AccountFormDialog';
|
|||||||
import UserFormDialog from 'containers/Dashboard/Dialogs/UserFormDialog';
|
import UserFormDialog from 'containers/Dashboard/Dialogs/UserFormDialog';
|
||||||
import ItemCategoryDialog from 'containers/Dashboard/Dialogs/ItemCategoryDialog';
|
import ItemCategoryDialog from 'containers/Dashboard/Dialogs/ItemCategoryDialog';
|
||||||
import CurrencyDialog from 'containers/Dashboard/Dialogs/CurrencyDialog';
|
import CurrencyDialog from 'containers/Dashboard/Dialogs/CurrencyDialog';
|
||||||
|
import InviteUserDialog from 'containers/Dashboard/Dialogs/InviteUserDialog';
|
||||||
|
|
||||||
export default function DialogsContainer() {
|
export default function DialogsContainer() {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
<InviteUserDialog />
|
||||||
<CurrencyDialog />
|
<CurrencyDialog />
|
||||||
<ItemCategoryDialog />
|
<ItemCategoryDialog />
|
||||||
<AccountFormDialog />
|
<AccountFormDialog />
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { submitInvite, editUser, fetchUser } from 'store/users/users.actions';
|
||||||
submitUser,
|
import { getUserDetails } from 'store/users/users.reducer';
|
||||||
editUser,
|
|
||||||
fetchUser,
|
|
||||||
} from 'store/users/users.actions';
|
|
||||||
import {
|
|
||||||
getUserDetails
|
|
||||||
} from 'store/users/users.reducer';
|
|
||||||
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
@@ -15,18 +9,22 @@ export const mapStateToProps = (state, props) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'user-form',
|
name: 'user-form',
|
||||||
payload: {action: 'new', id: null},
|
payload: { action: 'new', id: null },
|
||||||
userDetails: dialogPayload.action === 'edit'
|
userDetails:
|
||||||
? getUserDetails(state, dialogPayload.user.id) : {},
|
dialogPayload.action === 'edit'
|
||||||
|
? getUserDetails(state, dialogPayload.user.id)
|
||||||
|
: {},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
openDialog: (name, payload) => dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
openDialog: (name, payload) =>
|
||||||
closeDialog: (name, payload) => dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
dispatch({ type: t.OPEN_DIALOG, name, payload }),
|
||||||
submitUser: (form) => dispatch(submitUser({ form })),
|
closeDialog: (name, payload) =>
|
||||||
editUser: (id, form) => dispatch(editUser({ form, id })),
|
dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
||||||
fetchUser: (id) => dispatch(fetchUser({ id })),
|
requestSubmitInvite: (form) => dispatch(submitInvite({ form })),
|
||||||
|
requestEditUser: (id, form) => dispatch(editUser({ form, id })),
|
||||||
|
requestFetchUser: (id) => dispatch(fetchUser({ id })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
@@ -1,10 +1,32 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { fetchUsers, fetchUser, deleteUser } from 'store/users/users.actions';
|
import {
|
||||||
|
fetchUsers,
|
||||||
|
fetchUser,
|
||||||
|
deleteUser,
|
||||||
|
inactiveUser,
|
||||||
|
editUser,
|
||||||
|
} from 'store/users/users.actions';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
import { getUserDetails } from 'store/users/users.reducer';
|
||||||
|
import { getDialogPayload } from 'store/dashboard/dashboard.reducer';
|
||||||
|
|
||||||
export const mapStateToProps = (state, props) => ({
|
export const mapStateToProps = (state, props) => {
|
||||||
usersList: state.users.list.results,
|
const dialogPayload = getDialogPayload(state, 'userList-form');
|
||||||
});
|
|
||||||
|
return {
|
||||||
|
name: 'userList-form',
|
||||||
|
payload: { action: 'new', id: null },
|
||||||
|
userDetails:
|
||||||
|
dialogPayload.action === 'edit'
|
||||||
|
? getUserDetails(state, dialogPayload.user.id)
|
||||||
|
: {},
|
||||||
|
editUser:
|
||||||
|
dialogPayload && dialogPayload.action === 'edit'
|
||||||
|
? state.users.list.results[dialogPayload.user.id]
|
||||||
|
: {},
|
||||||
|
usersList: state.users.list.results,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const mapDispatchToProps = (dispatch) => ({
|
export const mapDispatchToProps = (dispatch) => ({
|
||||||
openDialog: (name, payload) =>
|
openDialog: (name, payload) =>
|
||||||
@@ -12,9 +34,11 @@ export const mapDispatchToProps = (dispatch) => ({
|
|||||||
closeDialog: (name, payload) =>
|
closeDialog: (name, payload) =>
|
||||||
dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
dispatch({ type: t.CLOSE_DIALOG, name, payload }),
|
||||||
|
|
||||||
fetchUsers: () => dispatch(fetchUsers({})),
|
requestFetchUsers: () => dispatch(fetchUsers({})),
|
||||||
fetchUser: (id) => dispatch(fetchUser({ id })),
|
requestFetchUser: (id) => dispatch(fetchUser({ id })),
|
||||||
deleteUser: (id) => dispatch(deleteUser({ id })),
|
requestDeleteUser: (id) => dispatch(deleteUser({ id })),
|
||||||
|
requestInactiveUser: (id) => dispatch(inactiveUser({ id })),
|
||||||
|
requestEditUser: (id, form) => dispatch(editUser({ form, id })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps);
|
export default connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
192
client/src/containers/Dashboard/Dialogs/InviteUserDialog.js
Normal file
192
client/src/containers/Dashboard/Dialogs/InviteUserDialog.js
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { useFormik } from 'formik';
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
Button,
|
||||||
|
FormGroup,
|
||||||
|
InputGroup,
|
||||||
|
Intent,
|
||||||
|
Classes,
|
||||||
|
} from '@blueprintjs/core';
|
||||||
|
import UserListDialogConnect from 'connectors/UsersList.connector';
|
||||||
|
import DialogReduxConnect from 'components/DialogReduxConnect';
|
||||||
|
import useAsync from 'hooks/async';
|
||||||
|
import { objectKeysTransform } from 'utils';
|
||||||
|
import { pick, snakeCase } from 'lodash';
|
||||||
|
import ErrorMessage from 'components/ErrorMessage';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import AppToaster from 'components/AppToaster';
|
||||||
|
import { compose } from 'utils';
|
||||||
|
|
||||||
|
function InviteUserDialog({
|
||||||
|
name,
|
||||||
|
payload,
|
||||||
|
isOpen,
|
||||||
|
closeDialog,
|
||||||
|
requestFetchUser,
|
||||||
|
requestEditUser,
|
||||||
|
}) {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const fetchHook = useAsync(async () => {
|
||||||
|
await Promise.all([
|
||||||
|
...(payload.action === 'edit' ? [requestFetchUser(payload.user.id)] : []),
|
||||||
|
]);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
first_name: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
|
last_name: Yup.string().required(intl.formatMessage({ id: 'required' })),
|
||||||
|
email: Yup.string()
|
||||||
|
.email()
|
||||||
|
.required(intl.formatMessage({ id: 'required' })),
|
||||||
|
phone_number: Yup.number().required(intl.formatMessage({ id: 'required' })),
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialValues = useMemo(
|
||||||
|
() => ({
|
||||||
|
first_name: '',
|
||||||
|
last_name: '',
|
||||||
|
email: '',
|
||||||
|
phone_number: '',
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const formik = useFormik({
|
||||||
|
enableReinitialize: true,
|
||||||
|
initialValues: {
|
||||||
|
...(payload.action === 'edit' &&
|
||||||
|
pick(
|
||||||
|
objectKeysTransform(payload.user, snakeCase),
|
||||||
|
Object.keys(initialValues)
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
validationSchema,
|
||||||
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
|
const form = {
|
||||||
|
...values,
|
||||||
|
};
|
||||||
|
if (payload.action === 'edit') {
|
||||||
|
requestEditUser(payload.user.id, form)
|
||||||
|
.then((response) => {
|
||||||
|
closeDialog(name);
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'the_user_details_has_been_updated',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { values, errors, touched } = useMemo(() => formik, [formik]);
|
||||||
|
|
||||||
|
const onDialogOpening = () => {
|
||||||
|
fetchHook.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDialogClosed = () => {
|
||||||
|
formik.resetForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
closeDialog(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
name={name}
|
||||||
|
title={payload.action === 'edit' ? 'Edit invite' : ''}
|
||||||
|
className={classNames({
|
||||||
|
'dialog--loading': fetchHook.pending,
|
||||||
|
'dialog--invite-user': true,
|
||||||
|
})}
|
||||||
|
autoFocus={true}
|
||||||
|
canEscapeKeyClose={true}
|
||||||
|
isOpen={isOpen}
|
||||||
|
isLoading={fetchHook.pending}
|
||||||
|
onClosed={onDialogClosed}
|
||||||
|
onOpening={onDialogOpening}
|
||||||
|
>
|
||||||
|
<form onSubmit={formik.handleSubmit}>
|
||||||
|
<div className={Classes.DIALOG_BODY}>
|
||||||
|
<FormGroup
|
||||||
|
label={'First Name'}
|
||||||
|
className={'form-group--first-name'}
|
||||||
|
intent={errors.first_name && touched.first_name && Intent.DANGER}
|
||||||
|
helperText={<ErrorMessage name='first_name' {...formik} />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={errors.first_name && touched.first_name && Intent.DANGER}
|
||||||
|
{...formik.getFieldProps('first_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={'Last Name'}
|
||||||
|
className={'form-group--last-name'}
|
||||||
|
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
||||||
|
helperText={<ErrorMessage name='last_name' {...formik} />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={errors.last_name && touched.last_name && Intent.DANGER}
|
||||||
|
{...formik.getFieldProps('last_name')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={'Email'}
|
||||||
|
className={'form-group--email'}
|
||||||
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
|
helperText={<ErrorMessage name='email' {...formik} />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
medium={true}
|
||||||
|
intent={errors.email && touched.email && Intent.DANGER}
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup
|
||||||
|
label={'Phone Number'}
|
||||||
|
className={'form-group--phone-number'}
|
||||||
|
intent={
|
||||||
|
errors.phone_number && touched.phone_number && Intent.DANGER
|
||||||
|
}
|
||||||
|
helperText={<ErrorMessage name='phone_number' {...formik} />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
intent={
|
||||||
|
errors.phone_number && touched.phone_number && Intent.DANGER
|
||||||
|
}
|
||||||
|
{...formik.getFieldProps('phone_number')}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
|
<Button onClick={handleClose}>Close</Button>
|
||||||
|
<Button intent={Intent.PRIMARY} type='submit'>
|
||||||
|
{payload.action === 'edit' ? 'Edit' : ''}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
UserListDialogConnect,
|
||||||
|
DialogReduxConnect
|
||||||
|
)(InviteUserDialog);
|
||||||
@@ -21,9 +21,9 @@ import classNames from 'classnames';
|
|||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
function UserFormDialog({
|
function UserFormDialog({
|
||||||
fetchUser,
|
requestFetchUser,
|
||||||
submitUser,
|
requestSubmitInvite,
|
||||||
editUser,
|
requestEditUser,
|
||||||
name,
|
name,
|
||||||
payload,
|
payload,
|
||||||
isOpen,
|
isOpen,
|
||||||
@@ -32,12 +32,12 @@ function UserFormDialog({
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const fetchHook = useAsync(async () => {
|
const fetchHook = useAsync(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
...(payload.action === 'edit' ? [fetchUser(payload.user.id)] : []),
|
...(payload.action === 'edit' ? [requestFetchUser(payload.user.id)] : []),
|
||||||
]);
|
]);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
email: Yup.string().email().required(),
|
email: Yup.string().email().required(intl.formatMessage({id:'required'})),
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
@@ -47,7 +47,6 @@ function UserFormDialog({
|
|||||||
objectKeysTransform(payload.user, snakeCase),
|
objectKeysTransform(payload.user, snakeCase),
|
||||||
Object.keys(validationSchema.fields)
|
Object.keys(validationSchema.fields)
|
||||||
)),
|
)),
|
||||||
password: '',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@@ -57,17 +56,16 @@ function UserFormDialog({
|
|||||||
onSubmit: (values) => {
|
onSubmit: (values) => {
|
||||||
const form = {
|
const form = {
|
||||||
...values,
|
...values,
|
||||||
confirm_password: values.password,
|
|
||||||
};
|
};
|
||||||
if (payload.action === 'edit') {
|
if (payload.action === 'edit') {
|
||||||
editUser(payload.user.id, form).then((response) => {
|
requestEditUser(payload.user.id, form).then((response) => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: 'the_user_details_has_been_updated',
|
message: 'the_user_details_has_been_updated',
|
||||||
});
|
});
|
||||||
closeDialog(name);
|
closeDialog(name);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
submitUser(form).then((response) => {
|
requestSubmitInvite(form).then((response) => {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: 'the_user_has_been_invited',
|
message: 'the_user_has_been_invited',
|
||||||
});
|
});
|
||||||
@@ -93,7 +91,7 @@ function UserFormDialog({
|
|||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
name={name}
|
name={name}
|
||||||
title={payload.action === 'edit' ? 'Edit invite' : 'New invite'}
|
title={payload.action === 'edit' ? 'Edit invite' : 'invite User'}
|
||||||
className={classNames({
|
className={classNames({
|
||||||
'dialog--loading': fetchHook.pending,
|
'dialog--loading': fetchHook.pending,
|
||||||
'dialog--invite-form': true,
|
'dialog--invite-form': true,
|
||||||
@@ -120,19 +118,6 @@ function UserFormDialog({
|
|||||||
{...formik.getFieldProps('email')}
|
{...formik.getFieldProps('email')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
|
||||||
label={'Email'}
|
|
||||||
className={'form-group--email'}
|
|
||||||
intent={errors.email && touched.email && Intent.DANGER}
|
|
||||||
helperText={<ErrorMessage name='email' {...formik} />}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
medium={true}
|
|
||||||
intent={errors.email && touched.email && Intent.DANGER}
|
|
||||||
{...formik.getFieldProps('email')}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={Classes.DIALOG_FOOTER}>
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
|
|||||||
@@ -1,47 +1,34 @@
|
|||||||
import React, {useCallback} from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import {
|
import { Tabs, Tab, Button, Intent } from '@blueprintjs/core';
|
||||||
Tabs,
|
|
||||||
Tab,
|
|
||||||
Button,
|
|
||||||
Intent,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import PreferencesSubContent from 'components/Preferences/PreferencesSubContent';
|
import PreferencesSubContent from 'components/Preferences/PreferencesSubContent';
|
||||||
import connector from 'connectors/UsersPreferences.connector';
|
import connector from 'connectors/UsersPreferences.connector';
|
||||||
|
|
||||||
function UsersPreferences({
|
function UsersPreferences({ openDialog }) {
|
||||||
openDialog,
|
const onChangeTabs = (currentTabId) => {};
|
||||||
}) {
|
|
||||||
const onChangeTabs = (currentTabId) => {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const onClickNewUser = useCallback(() => {
|
const onClickNewUser = useCallback(() => {
|
||||||
openDialog('user-form');
|
openDialog('user-form');
|
||||||
}, [openDialog]);
|
}, [openDialog]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="preferences__inside-content preferences__inside-content--users-roles">
|
<div class='preferences__inside-content preferences__inside-content--users-roles'>
|
||||||
<div class="preferences__tabs">
|
<div class='preferences__tabs'>
|
||||||
<Tabs
|
<Tabs animate={true} large={true} onChange={onChangeTabs}>
|
||||||
animate={true}
|
<Tab id='users' title='Users' />
|
||||||
large={true}
|
<Tab id='roles' title='Roles' />
|
||||||
onChange={onChangeTabs}>
|
|
||||||
<Tab id="users" title="Users" />
|
|
||||||
<Tab id="roles" title="Roles" />
|
|
||||||
|
|
||||||
|
<div class='preferences__tabs-extra-actions'>
|
||||||
|
<Button intent={Intent.PRIMARY} onClick={onClickNewUser}>
|
||||||
|
Invite User
|
||||||
|
</Button>
|
||||||
|
|
||||||
<div class="preferences__tabs-extra-actions">
|
<Button intent={Intent.PRIMARY} onClick={onClickNewUser}>
|
||||||
<Button
|
New Role
|
||||||
intent={Intent.PRIMARY}
|
</Button>
|
||||||
onClick={onClickNewUser}>New invite</Button>
|
</div>
|
||||||
|
|
||||||
<Button
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
onClick={onClickNewUser}>New Role</Button>
|
|
||||||
</div>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
<PreferencesSubContent preferenceTab="users" />
|
<PreferencesSubContent preferenceTab='users' />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,30 +21,48 @@ import DialogConnect from 'connectors/Dialog.connector';
|
|||||||
import DashboardConnect from 'connectors/Dashboard.connector';
|
import DashboardConnect from 'connectors/Dashboard.connector';
|
||||||
|
|
||||||
function UsersListPreferences({
|
function UsersListPreferences({
|
||||||
fetchUsers,
|
requestFetchUsers,
|
||||||
usersList,
|
usersList,
|
||||||
openDialog,
|
openDialog,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
deleteUser,
|
requestDeleteUser,
|
||||||
|
requestInactiveUser,
|
||||||
onFetchData,
|
onFetchData,
|
||||||
}) {
|
}) {
|
||||||
const [deleteUserState, setDeleteUserState] = useState(false);
|
const [deleteUserState, setDeleteUserState] = useState(false);
|
||||||
const [inactiveUserState, setInactiveUserState] = useState(false);
|
const [inactiveUserState, setInactiveUserState] = useState(false);
|
||||||
|
|
||||||
const asyncHook = useAsync(async () => {
|
const asyncHook = useAsync(async () => {
|
||||||
await Promise.all([fetchUsers()]);
|
await Promise.all([requestFetchUsers()]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onInactiveUser = (user) => {};
|
const onInactiveUser = (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);
|
||||||
|
requestFetchUsers();
|
||||||
|
AppToaster.show({ message: 'the_user_has_been_inactivated' });
|
||||||
|
});
|
||||||
|
}, [inactiveUserState, requestInactiveUser, requestFetchUsers]);
|
||||||
|
|
||||||
const onDeleteUser = (user) => {
|
const onDeleteUser = (user) => {
|
||||||
setDeleteUserState(user);
|
setDeleteUserState(user);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancelUserDelete = () => {
|
const handleCancelUserDelete = () => {
|
||||||
setDeleteUserState(false);
|
setDeleteUserState(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEditUser = (user) => () => {
|
const onEditInviteUser = (user) => () => {
|
||||||
const form = Object.keys(user).reduce((obj, key) => {
|
const form = Object.keys(user).reduce((obj, key) => {
|
||||||
const camelKey = snakeCase(key);
|
const camelKey = snakeCase(key);
|
||||||
obj[camelKey] = user[key];
|
obj[camelKey] = user[key];
|
||||||
@@ -54,12 +72,22 @@ function UsersListPreferences({
|
|||||||
openDialog('user-form', { action: 'edit', user: form });
|
openDialog('user-form', { action: 'edit', user: form });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onEditUser = (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 });
|
||||||
|
};
|
||||||
|
|
||||||
const handleConfirmUserDelete = () => {
|
const handleConfirmUserDelete = () => {
|
||||||
if (!deleteUserState) {
|
if (!deleteUserState) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteUser(deleteUserState.id).then((response) => {
|
requestDeleteUser(deleteUserState.id).then((response) => {
|
||||||
setDeleteUserState(false);
|
setDeleteUserState(false);
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: 'the_user_has_been_deleted',
|
message: 'the_user_has_been_deleted',
|
||||||
@@ -67,16 +95,18 @@ function UsersListPreferences({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const actionMenuList = (user) => (
|
const actionMenuList = useCallback(
|
||||||
<Menu>
|
(user) => (
|
||||||
<MenuItem text='Edit User' onClick={onEditUser(user)} />
|
<Menu>
|
||||||
<MenuItem text='New Account' />
|
<MenuItem text='Edit User' onClick={onEditUser(user)} />
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem text='Inactivate User' onClick={() => onInactiveUser(user)} />
|
<MenuItem text='Edit Invite ' onClick={onEditInviteUser(user)} />
|
||||||
<MenuItem text='Delete User' onClick={() => onDeleteUser(user)} />
|
<MenuItem text='Inactivate User' onClick={() => onInactiveUser(user)} />
|
||||||
</Menu>
|
<MenuItem text='Delete User' onClick={() => onDeleteUser(user)} />
|
||||||
|
</Menu>
|
||||||
|
),
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
console.log(usersList, 'X');
|
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@@ -151,6 +181,21 @@ function UsersListPreferences({
|
|||||||
able to restore it later, but it will become private to you.
|
able to restore it later, but it will become private to you.
|
||||||
</p>
|
</p>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
<Alert
|
||||||
|
cancelButtonText='Cancel'
|
||||||
|
confirmButtonText='Inactivate'
|
||||||
|
icon='trash'
|
||||||
|
intent={Intent.WARNING}
|
||||||
|
isOpen={inactiveUserState}
|
||||||
|
onCancel={handleCancelInactiveUser}
|
||||||
|
onConfirm={handleConfirmUserActive}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Are you sure you want to move <b>filename</b> to Trash? You will be
|
||||||
|
able to restore it later, but it will become private to you.
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
</LoadingIndicator>
|
</LoadingIndicator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,46 @@
|
|||||||
import ApiService from "services/ApiService";
|
import ApiService from 'services/ApiService';
|
||||||
import t from 'store/types';
|
import t from 'store/types';
|
||||||
|
|
||||||
export const fetchUsers = () => {
|
export const fetchUsers = () => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) =>
|
||||||
ApiService.get(`users`).then((response) => {
|
new Promise((resolve, reject) => {
|
||||||
dispatch({
|
ApiService.get(`users`)
|
||||||
type: t.USERS_LIST_SET,
|
.then((response) => {
|
||||||
users: response.data.users,
|
dispatch({
|
||||||
});
|
type: t.USERS_LIST_SET,
|
||||||
resolve(response);
|
users: response.data.users,
|
||||||
}).catch((error) => { reject(error); });
|
});
|
||||||
});
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchUser = ({ id }) => {
|
export const fetchUser = ({ id }) => {
|
||||||
return (dispatch) => new Promise((resolve, reject) => {
|
return (dispatch) =>
|
||||||
ApiService.get(`users/${id}`).then((response) => {
|
new Promise((resolve, reject) => {
|
||||||
dispatch({
|
ApiService.get(`users/${id}`)
|
||||||
type: t.USER_DETAILS_SET,
|
.then((response) => {
|
||||||
user: response.data.user,
|
dispatch({
|
||||||
});
|
type: t.USER_DETAILS_SET,
|
||||||
resolve(response);
|
user: response.data.user,
|
||||||
}).catch(error => { reject(error); });
|
});
|
||||||
});
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteUser = ({ id }) => {
|
export const deleteUser = ({ id }) => {
|
||||||
return (dispatch) => ApiService.delete(`users/${id}`);
|
return (dispatch) => ApiService.delete(`users/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const submitUser = ({ form }) => {
|
export const submitInvite = ({ form }) => {
|
||||||
return (dispatch) => ApiService.post(`users`, form);
|
return (dispatch) => ApiService.post(`invite/send`, form);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editUser = ({ form, id }) => {
|
export const editUser = ({ form, id }) => {
|
||||||
@@ -38,9 +48,9 @@ export const editUser = ({ form, id }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const inactiveUser = ({ id }) => {
|
export const inactiveUser = ({ id }) => {
|
||||||
return (dispatch) => ApiService.post(`users/${id}/inactive`);
|
return (dispatch) => ApiService.put(`users/${id}/inactive`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const activeUser = ({ id }) => {
|
export const activeUser = ({ id }) => {
|
||||||
return (dispatch) => ApiService.post(`users/${id}/active`);
|
return (dispatch) => ApiService.put(`users/${id}/active`);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ $pt-font-family: Noto Sans, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
|||||||
@import 'pages/items';
|
@import 'pages/items';
|
||||||
@import 'pages/invite-form.scss';
|
@import 'pages/invite-form.scss';
|
||||||
@import "pages/currency";
|
@import "pages/currency";
|
||||||
|
@import "pages/invite-user.scss";
|
||||||
|
|
||||||
// Views
|
// Views
|
||||||
@import 'views/filter-dropdown';
|
@import 'views/filter-dropdown';
|
||||||
|
|||||||
@@ -8,5 +8,8 @@
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.bp3-dialog-header {
|
||||||
|
height: 170px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// .dialog--invite-form {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
.dialog--invite-form {
|
.dialog--invite-form {
|
||||||
&.bp3-dialog {
|
&.bp3-dialog {
|
||||||
@@ -30,18 +27,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .bp3-dialog-body {
|
|
||||||
// .bp3-form-group.bp3-inline {
|
|
||||||
// .bp3-label {
|
|
||||||
// min-width: 100px;
|
|
||||||
// }
|
|
||||||
// .bp3-form-content {
|
|
||||||
// width: 250px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// .bp3-dialog-footer-actions {
|
|
||||||
// display: flex;
|
|
||||||
// justify-content: flex-end;
|
|
||||||
// margin-right: 100px;
|
|
||||||
// }
|
|
||||||
|
|||||||
12
client/src/style/pages/invite-user.scss
Normal file
12
client/src/style/pages/invite-user.scss
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.dialog--invite-user {
|
||||||
|
.bp3-dialog-body {
|
||||||
|
.bp3-form-group.bp3-inline {
|
||||||
|
.bp3-label {
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
.bp3-form-content {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&-menu {
|
&-menu {
|
||||||
width: 240px;
|
width: 374px;
|
||||||
}
|
}
|
||||||
&-button {
|
&-button {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
min-width: 140px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
.bp3-form-content {
|
.bp3-form-content {
|
||||||
width: 250px;
|
width: 384px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user