WIP optimize connect with redux state in preferences pages.

This commit is contained in:
Ahmed Bouhuolia
2020-05-10 23:22:36 +02:00
parent a0653674ff
commit 464c36d532
32 changed files with 403 additions and 327 deletions

View File

@@ -4,41 +4,53 @@ import {
Popover,
Menu,
MenuItem,
MenuDivider,
Position,
Classes,
Tooltip,
Alert,
Intent,
} from '@blueprintjs/core';
import { useQuery } from 'react-query';
import Icon from 'components/Icon';
import { snakeCase } from 'lodash';
import { compose } from 'utils';
import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect';
import DialogConnect from 'connectors/Dialog.connector';
import DashboardConnect from 'connectors/Dashboard.connector';
import LoadingIndicator from 'components/LoadingIndicator';
import DataTable from 'components/DataTable';
import AppToaster from 'components/AppToaster';
import withDashboard from 'connectors/Dashboard.connector';
import withCurrencies from 'containers/Currencies/withCurrencies';
import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions';
function CurrenciesList({
currencies,
// #withCurrencies
currenciesList,
// #withCurrenciesActions
requestDeleteCurrency,
requestFetchCurrencies,
// #withDialog
openDialog,
onFetchData,
requestDeleteCurrency,
}) {
const [deleteCurrencyState, setDeleteCurrencyState] = useState(false);
const handleEditCurrency = (currency) => () => {
const fetchCurrencies = useQuery(['currencies-table'],
() => requestFetchCurrencies());
const handleEditCurrency = (currency) => {
openDialog('currency-form', {
action: 'edit',
currency_code: currency.currency_code,
currencyCode: currency.currency_code,
});
};
const onDeleteCurrency = (currency) => {
setDeleteCurrencyState(currency);
};
const handleCancelCurrencyDelete = () => {
setDeleteCurrencyState(false);
};
@@ -54,56 +66,51 @@ function CurrenciesList({
);
}, [deleteCurrencyState]);
const actionMenuList = useCallback(
(currency) => (
<Menu>
<MenuItem text='Edit Currency' onClick={handleEditCurrency(currency)} />
const actionMenuList = useCallback((currency) => (
<Menu>
<MenuItem
text='Edit Currency'
onClick={() => handleEditCurrency(currency)} />
<MenuItem
text='Delete Currency'
onClick={() => onDeleteCurrency(currency)}
/>
</Menu>
),
[]
);
<MenuItem
text='Delete Currency'
onClick={() => onDeleteCurrency(currency)}
/>
</Menu>
), []);
const columns = useMemo(() => [
{
Header: 'Currency Name',
accessor: 'currency_name',
width: 100,
},
{
Header: 'Currency Code',
accessor: 'currency_code',
className: 'currency_code',
width: 100,
},
{
Header: 'Currency sign',
width: 50,
},
{
id: 'actions',
Header: '',
Cell: ({ cell }) => (
<Popover
content={actionMenuList(cell.row.original)}
position={Position.RIGHT_TOP}
>
<Button icon={<Icon icon='ellipsis-h' />} />
</Popover>
),
className: 'actions',
width: 50,
},
], [actionMenuList]);
const columns = useMemo(
() => [
{
id: 'currency_name',
Header: 'Currency Name',
accessor: 'currency_name',
width: 100,
},
{
id: 'currency_code',
Header: 'Currency Code',
accessor: 'currency_code',
className: 'currency_code',
width: 100,
},
{
Header: 'Currency sign',
width: 50,
},
{
id: 'actions',
Header: '',
Cell: ({ cell }) => (
<Popover
content={actionMenuList(cell.row.original)}
position={Position.RIGHT_TOP}
>
<Button icon={<Icon icon='ellipsis-h' />} />
</Popover>
),
className: 'actions',
width: 50,
},
],
[actionMenuList]
);
const handleDatatableFetchData = useCallback(() => {
onFetchData && onFetchData();
}, []);
@@ -112,9 +119,9 @@ function CurrenciesList({
<LoadingIndicator>
<DataTable
columns={columns}
data={Object.values(currencies)}
onFetchData={handleDatatableFetchData()}
selectionColumn={true}
data={currenciesList}
loading={fetchCurrencies.isFetching}
selectionColumn={false}
/>
<Alert
@@ -136,7 +143,10 @@ function CurrenciesList({
}
export default compose(
CurrencyFromDialogConnect,
withCurrencies(({ currenciesList }) => ({
currenciesList,
})),
withCurrenciesActions,
DialogConnect,
DashboardConnect
withDashboard
)(CurrenciesList);

View File

@@ -9,27 +9,36 @@ import {
MenuItem,
Classes,
} from '@blueprintjs/core';
import { optionsMapToArray, momentFormatter, optionsArrayToMap } from 'utils';
import classNames from 'classnames';
import { TimezonePicker } from '@blueprintjs/timezone';
import { Select } from '@blueprintjs/select';
import classNames from 'classnames';
import ErrorMessage from 'components/ErrorMessage';
import Icon from 'components/Icon';
import { compose } from 'utils';
import SettingsConnect from 'connectors/Settings.connect';
import AppToaster from 'components/AppToaster';
import { useIntl } from 'react-intl';
import useAsync from 'hooks/async';
import { useQuery } from 'react-query';
import { compose, optionsMapToArray } from 'utils';
import ErrorMessage from 'components/ErrorMessage';
import AppToaster from 'components/AppToaster';
import withSettings from 'containers/Settings/withSettings';
import withSettingsActions from 'containers/Settings/withSettingsActions';
function GeneralPreferences({
// #withSettings
organizationSettings,
// #withSettingsActions
requestSubmitOptions,
requestFetchOptions,
}) {
const intl = useIntl();
const [selectedItems, setSelectedItems] = useState({});
const [timeZone, setTimeZone] = useState('');
const fetchHook = useQuery(['settings'],
() => { requestFetchOptions(); });
const businessLocation = [
{ id: 218, name: 'LIBYA', code: 'LY' },
{ id: 380, name: 'UKRAINE', code: 'UA' },
@@ -55,8 +64,6 @@ function GeneralPreferences({
{ id: 6, name: 'Saturday, Apr 11, 2020', format: 'EEEE, MMM d, yyyy' },
];
const intl = useIntl();
const validationSchema = Yup.object().shape({
name: Yup.string().required(intl.formatMessage({ id: 'required' })),
industry: Yup.string().required(intl.formatMessage({ id: 'required' })),
@@ -69,15 +76,22 @@ function GeneralPreferences({
// time_zone: Yup.object().required(intl.formatMessage({ id: 'required' })),
date_format: Yup.date().required(intl.formatMessage({ id: 'required' })),
});
console.log(organizationSettings.name);
const formik = useFormik({
const {
errors,
values,
touched,
isSubmitting,
setFieldValue,
getFieldProps,
handleSubmit,
resetForm,
} = useFormik({
enableReinitialize: true,
initialValues: {
...organizationSettings,
},
validationSchema: validationSchema,
validationSchema,
onSubmit: (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => {
return { key: option.key, ...option, group: 'organization' };
@@ -96,12 +110,6 @@ function GeneralPreferences({
},
});
const { errors, values, touched } = useMemo(() => formik, [formik]);
const fetchHook = useAsync(async () => {
await Promise.all([requestFetchOptions()]);
});
const businessLocationItem = (item, { handleClick }) => (
<MenuItem
className={'preferences-menu'}
@@ -156,7 +164,7 @@ function GeneralPreferences({
...selectedItems,
[filedName]: filed,
});
formik.setFieldValue(filedName, filed.name);
setFieldValue(filedName, filed.name);
};
};
@@ -170,30 +178,30 @@ function GeneralPreferences({
return (
<div className='preferences__inside-content--general'>
<form onSubmit={formik.handleSubmit}>
<form onSubmit={handleSubmit}>
<FormGroup
label={'Organization Name'}
inline={true}
intent={errors.name && touched.name && Intent.DANGER}
helperText={<ErrorMessage name='name' {...formik} />}
intent={(errors.name && touched.name) && Intent.DANGER}
helperText={<ErrorMessage name='name' {...{errors, touched}} />}
>
<InputGroup
medium={'true'}
intent={errors.name && touched.name && Intent.DANGER}
{...formik.getFieldProps('name')}
intent={(errors.name && touched.name) && Intent.DANGER}
{...getFieldProps('name')}
/>
</FormGroup>
<FormGroup
label={'Organization Industry'}
inline={true}
intent={errors.industry && touched.industry && Intent.DANGER}
helperText={<ErrorMessage name='industry' {...formik} />}
intent={(errors.industry && touched.industry) && Intent.DANGER}
helperText={<ErrorMessage name='industry' {...{errors, touched}} />}
>
<InputGroup
medium={'true'}
intent={errors.industry && touched.industry && Intent.DANGER}
{...formik.getFieldProps('industry')}
intent={(errors.industry && touched.industry) && Intent.DANGER}
{...getFieldProps('industry')}
/>
</FormGroup>
@@ -205,8 +213,8 @@ function GeneralPreferences({
Classes.FILL
)}
inline={true}
helperText={<ErrorMessage name='location' {...formik} />}
intent={errors.location && touched.location && Intent.DANGER}
helperText={<ErrorMessage name='location' {...{errors, touched}} />}
intent={(errors.location && touched.location) && Intent.DANGER}
>
<Select
items={businessLocation}
@@ -234,10 +242,8 @@ function GeneralPreferences({
Classes.FILL
)}
inline={true}
helperText={<ErrorMessage name='base_currency' {...formik} />}
intent={
errors.base_currency && touched.base_currency && Intent.DANGER
}
helperText={<ErrorMessage name='base_currency' {...{ errors, touched }} />}
intent={(errors.base_currency && touched.base_currency) && Intent.DANGER}
>
<Select
items={currencies}
@@ -265,8 +271,8 @@ function GeneralPreferences({
Classes.FILL
)}
inline={true}
helperText={<ErrorMessage name='fiscal_year' {...formik} />}
intent={errors.fiscal_year && touched.fiscal_year && Intent.DANGER}
helperText={<ErrorMessage name='fiscal_year' {...{errors, touched}} />}
intent={(errors.fiscal_year && touched.fiscal_year) && Intent.DANGER}
>
<Select
items={fiscalYear}
@@ -294,8 +300,8 @@ function GeneralPreferences({
'form-group--select-list',
Classes.FILL
)}
intent={errors.language && touched.language && Intent.DANGER}
helperText={<ErrorMessage name='language' {...formik} />}
intent={(errors.language && touched.language) && Intent.DANGER}
helperText={<ErrorMessage name='language' {...{errors, touched}} />}
>
<Select
items={languagesDisplay}
@@ -321,8 +327,8 @@ function GeneralPreferences({
'form-group--select-list',
Classes.FILL
)}
intent={errors.time_zone && touched.time_zone && Intent.DANGER}
helperText={<ErrorMessage name='time_zone' {...formik} />}
intent={(errors.time_zone && touched.time_zone) && Intent.DANGER}
helperText={<ErrorMessage name='time_zone' {...{errors, touched}} />}
>
<TimezonePicker
value={timeZone}
@@ -339,8 +345,8 @@ function GeneralPreferences({
'form-group--select-list',
Classes.FILL
)}
intent={errors.date_format && touched.date_format && Intent.DANGER}
helperText={<ErrorMessage name='date_format' {...formik} />}
intent={(errors.date_format && touched.date_format) && Intent.DANGER}
helperText={<ErrorMessage name='date_format' {...{errors, touched}} />}
>
<Select
items={dateFormat}
@@ -374,4 +380,7 @@ function GeneralPreferences({
);
}
export default compose(SettingsConnect)(GeneralPreferences);
export default compose(
withSettings,
withSettingsActions,
)(GeneralPreferences);

View File

@@ -1,5 +1,5 @@
import React, { useState, useMemo, useCallback } from 'react';
import { useAsync } from 'react-use';
import { useQuery } from 'react-query';
import DataTable from 'components/DataTable';
import {
Alert,
@@ -11,30 +11,42 @@ import {
Position,
Intent,
} from '@blueprintjs/core';
import { snakeCase } from 'lodash';
import Icon from 'components/Icon';
import LoadingIndicator from 'components/LoadingIndicator';
import { snakeCase } from 'lodash';
import UserListConnect from 'connectors/UsersList.connector';
import AppToaster from 'components/AppToaster';
import { compose } from 'utils';
import DialogConnect from 'connectors/Dialog.connector';
import DashboardConnect from 'connectors/Dashboard.connector';
import withDashboard from 'containers/Dashboard/withDashboard';
import withUsers from 'containers/Users/withUsers';
import withUsersActions from 'containers/Users/withUsersActions';
import { compose } from 'utils';
function UsersListPreferences({
requestFetchUsers,
usersList,
// #withDialog
openDialog,
closeDialog,
// #withUsers
usersList,
// #withUsersActions
requestDeleteUser,
requestInactiveUser,
requestFetchUsers,
// #ownProps
onFetchData,
}) {
const [deleteUserState, setDeleteUserState] = useState(false);
const [inactiveUserState, setInactiveUserState] = useState(false);
const asyncHook = useAsync(async () => {
await Promise.all([requestFetchUsers()]);
}, []);
const fetchUsers = useQuery('users-table',
() => requestFetchUsers());
const onInactiveUser = (user) => {
setInactiveUserState(user);
@@ -49,7 +61,6 @@ function UsersListPreferences({
const handleConfirmUserActive = useCallback(() => {
requestInactiveUser(inactiveUserState.id).then(() => {
setInactiveUserState(false);
requestFetchUsers();
AppToaster.show({ message: 'the_user_has_been_inactivated' });
});
}, [inactiveUserState, requestInactiveUser, requestFetchUsers]);
@@ -105,50 +116,47 @@ function UsersListPreferences({
[]
);
const columns = useMemo(
() => [
{
id: 'full_name',
Header: 'Full Name',
accessor: 'full_name',
width: 170,
},
{
id: 'email',
Header: 'Email',
accessor: 'email',
width: 150,
},
{
id: 'phone_number',
Header: 'Phone Number',
accessor: 'phone_number',
width: 150,
},
{
id: 'active',
Header: 'Status',
accessor: (user) =>
user.active ? <span>Active</span> : <span>Inactivate</span>,
width: 50,
},
{
id: 'actions',
Header: '',
Cell: ({ cell }) => (
<Popover
content={actionMenuList(cell.row.original)}
position={Position.RIGHT_TOP}
>
<Button icon={<Icon icon='ellipsis-h' />} />
</Popover>
),
className: 'actions',
width: 50,
},
],
[actionMenuList]
);
const columns = useMemo(() => [
{
id: 'full_name',
Header: 'Full Name',
accessor: 'full_name',
width: 170,
},
{
id: 'email',
Header: 'Email',
accessor: 'email',
width: 150,
},
{
id: 'phone_number',
Header: 'Phone Number',
accessor: 'phone_number',
width: 150,
},
{
id: 'active',
Header: 'Status',
accessor: (user) =>
user.active ? <span>Active</span> : <span>Inactivate</span>,
width: 50,
},
{
id: 'actions',
Header: '',
Cell: ({ cell }) => (
<Popover
content={actionMenuList(cell.row.original)}
position={Position.RIGHT_TOP}
>
<Button icon={<Icon icon='ellipsis-h' />} />
</Popover>
),
className: 'actions',
width: 50,
},
], [actionMenuList]);
const handelDataTableFetchData = useCallback(() => {
onFetchData && onFetchData();
@@ -160,6 +168,7 @@ function UsersListPreferences({
columns={columns}
data={usersList}
onFetchData={handelDataTableFetchData()}
loading={fetchUsers.isFetching}
manualSortBy={true}
expandable={false}
/>
@@ -198,7 +207,8 @@ function UsersListPreferences({
}
export default compose(
UserListConnect,
DialogConnect,
DashboardConnect
withDashboard,
withUsers,
withUsersActions,
)(UsersListPreferences);

View File

@@ -1,9 +0,0 @@
import { connect } from 'react-redux';
export const mapStateToProps = (state, props) => {
return {
usersList: state.users.list.results,
};
};
export default connect(mapStateToProps);

View File

@@ -1,18 +0,0 @@
import { connect } from 'react-redux';
import {
fetchUsers,
fetchUser,
deleteUser,
inactiveUser,
editUser,
} from 'store/users/users.actions';
export const mapDispatchToProps = (dispatch) => ({
requestFetchUsers: () => dispatch(fetchUsers({})),
requestFetchUser: (id) => dispatch(fetchUser({ id })),
requestDeleteUser: (id) => dispatch(deleteUser({ id })),
requestInactiveUser: (id) => dispatch(inactiveUser({ id })),
requestEditUser: (id, form) => dispatch(editUser({ form, id })),
});
export default connect(null, mapDispatchToProps);