diff --git a/client/src/components/DataTable.js b/client/src/components/DataTable.js index 7ad733d26..f8c63d862 100644 --- a/client/src/components/DataTable.js +++ b/client/src/components/DataTable.js @@ -13,6 +13,7 @@ import classnames from 'classnames'; import { FixedSizeList } from 'react-window' import { ConditionalWrapper } from 'utils'; import { useUpdateEffect } from 'hooks'; +import { If } from 'components'; const IndeterminateCheckbox = React.forwardRef( ({ indeterminate, ...rest }, ref) => { @@ -257,16 +258,19 @@ export default function DataTable({ ))}
- { !loading && RenderTBody() } - - { !loading && (page.length === 0) && ( + + { RenderTBody() } + + +
{ noResults }
- )} - { loading && ( +
+ +
- ) } +
diff --git a/client/src/components/Preferences/PreferencesContent.js b/client/src/components/Preferences/PreferencesContent.js index 33fad9d86..dd19013fe 100644 --- a/client/src/components/Preferences/PreferencesContent.js +++ b/client/src/components/Preferences/PreferencesContent.js @@ -1,8 +1,10 @@ import React from 'react'; + import PreferencesTopbar from 'components/Preferences/PreferencesTopbar'; import PreferencesContentRoute from 'components/Preferences/PreferencesContentRoute'; -export default function () { + +export default function PreferencesContent() { return (
diff --git a/client/src/components/Preferences/PreferencesContentRoute.js b/client/src/components/Preferences/PreferencesContentRoute.js index 127a1a167..fcf0fa0aa 100644 --- a/client/src/components/Preferences/PreferencesContentRoute.js +++ b/client/src/components/Preferences/PreferencesContentRoute.js @@ -2,6 +2,7 @@ import React from 'react'; import { Route, Switch, Redirect } from 'react-router-dom'; import preferencesRoutes from 'routes/preferences' + export default function DashboardContentRoute() { const defaultTab = '/dashboard/preferences/general'; diff --git a/client/src/components/Preferences/PreferencesPage.js b/client/src/components/Preferences/PreferencesPage.js index 4689231c6..7cdfb59c6 100644 --- a/client/src/components/Preferences/PreferencesPage.js +++ b/client/src/components/Preferences/PreferencesPage.js @@ -1,6 +1,7 @@ import React from 'react'; import PreferencesSidebar from 'components/Preferences/PreferencesSidebar'; + export default function PreferencesPage() { return (
diff --git a/client/src/components/Preferences/PreferencesTopbar.js b/client/src/components/Preferences/PreferencesTopbar.js index 829d170e7..605d5577f 100644 --- a/client/src/components/Preferences/PreferencesTopbar.js +++ b/client/src/components/Preferences/PreferencesTopbar.js @@ -1,8 +1,8 @@ import React from 'react'; import { Route, Switch } from 'react-router-dom'; import DashboardTopbarUser from 'components/Dashboard/TopbarUser'; -import UsersActions from 'containers/Preferences/UsersActions'; -import CurrenciesActions from 'containers/Preferences/CurrenciesActions'; +import UsersActions from 'containers/Preferences/Users/UsersActions'; +import CurrenciesActions from 'containers/Preferences/Currencies/CurrenciesActions'; export default function PreferencesTopbar() { diff --git a/client/src/connectors/ManualJournals.connect.js b/client/src/connectors/ManualJournals.connect.js deleted file mode 100644 index 6f543ce54..000000000 --- a/client/src/connectors/ManualJournals.connect.js +++ /dev/null @@ -1,41 +0,0 @@ -import { connect } from 'react-redux'; -import { - deleteManualJournal, - fetchManualJournalsTable, - publishManualJournal, - deleteBulkManualJournals, -} from 'store/manualJournals/manualJournals.actions'; -import { getResourceViews } from 'store/customViews/customViews.selectors'; -import t from 'store/types'; -import { - getManualJournalsItems, -} from 'store/manualJournals/manualJournals.selectors' - -const mapStateToProps = (state, props) => ({ - views: getResourceViews(state, 'manual_journals'), - manualJournals: getManualJournalsItems(state, state.manualJournals.currentViewId), - manualJournalsItems: state.manualJournals.items, - tableQuery: state.manualJournals.tableQuery, - manualJournalsLoading: state.manualJournals.loading, -}); - -const mapActionsToProps = (dispatch) => ({ - requestDeleteManualJournal: (id) => dispatch(deleteManualJournal({ id })), - changeCurrentView: (id) => - dispatch({ - type: t.MANUAL_JOURNALS_SET_CURRENT_VIEW, - currentViewId: parseInt(id, 10), - }), - addManualJournalsTableQueries: (queries) => - dispatch({ - type: t.MANUAL_JOURNALS_TABLE_QUERIES_ADD, - queries, - }), - fetchManualJournalsTable: (query = {}) => - dispatch(fetchManualJournalsTable({ query: { ...query } })), - - requestPublishManualJournal: (id) => dispatch(publishManualJournal({ id })), - requestDeleteBulkManualJournals: (ids) => dispatch(deleteBulkManualJournals({ ids })), -}); - -export default connect(mapStateToProps, mapActionsToProps); diff --git a/client/src/containers/Currencies/withCurrencies.js b/client/src/containers/Currencies/withCurrencies.js new file mode 100644 index 000000000..f672e6470 --- /dev/null +++ b/client/src/containers/Currencies/withCurrencies.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux'; + +export default (mapState) => { + const mapStateToProps = (state, props) => { + const mapped = { + currencies: state.currencies.data, + currenciesList: Object.values(state.currencies.data), + }; + return mapState ? mapState(mapped, state, props) : mapped; + }; + + return connect(mapStateToProps); +} diff --git a/client/src/containers/Currencies/withCurrenciesActions.js b/client/src/containers/Currencies/withCurrenciesActions.js new file mode 100644 index 000000000..e835bebbc --- /dev/null +++ b/client/src/containers/Currencies/withCurrenciesActions.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { + fetchCurrencies, + submitCurrencies, + deleteCurrency, + editCurrency, +} from 'store/currencies/currencies.actions'; + + +export const mapDispatchToProps = (dispatch) => ({ + requestFetchCurrencies: () => dispatch(fetchCurrencies({})), + requestSubmitCurrencies: (form) => dispatch(submitCurrencies({ form })), + requestEditCurrency: (id, form) => dispatch(editCurrency({ id, form })), + requestDeleteCurrency: (currency_code) => dispatch(deleteCurrency({ currency_code })), +}); + +export default connect(null, mapDispatchToProps); diff --git a/client/src/containers/Currencies/withCurrency.js b/client/src/containers/Currencies/withCurrency.js new file mode 100644 index 000000000..cb38db924 --- /dev/null +++ b/client/src/containers/Currencies/withCurrency.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux'; +import { + getCurrencyById, + getCurrencyByCode, +} from 'store/currencies/currencies.selector'; + + +const mapStateToProps = (state, props) => ({ + ...(props.currencyId) ? { + currency: getCurrencyById(state.currencies.data, props.currencyId), + } : (props.currencyCode) ? { + currency: getCurrencyByCode(state.currencies.data, props.currencyCode), + } : {}, +}); + +export default connect(mapStateToProps); \ No newline at end of file diff --git a/client/src/containers/Dialogs/CurrencyDialog.js b/client/src/containers/Dialogs/CurrencyDialog.js index e5d6e4b93..5688b46e2 100644 --- a/client/src/containers/Dialogs/CurrencyDialog.js +++ b/client/src/containers/Dialogs/CurrencyDialog.js @@ -1,4 +1,4 @@ -import React, { useState, useMemo, useCallback } from 'react'; +import React, { useMemo, useCallback } from 'react'; import { Button, Classes, @@ -9,26 +9,40 @@ import { import * as Yup from 'yup'; import { useIntl } from 'react-intl'; import { useFormik } from 'formik'; +import { useQuery } from 'react-query'; +import { connect } from 'react-redux'; + import { compose } from 'utils'; import Dialog from 'components/Dialog'; -import useAsync from 'hooks/async'; + import AppToaster from 'components/AppToaster'; import DialogConnect from 'connectors/Dialog.connector'; import DialogReduxConnect from 'components/DialogReduxConnect'; -import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'; +import withCurrency from 'containers/Currencies/withCurrency'; +import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions'; + import ErrorMessage from 'components/ErrorMessage'; import classNames from 'classnames'; import { pick } from 'lodash'; +import { getDialogPayload } from 'store/dashboard/dashboard.reducer'; + function CurrencyDialog({ name, payload, isOpen, + + // #withDialog closeDialog, + + // #withCurrency + currencyCode, + currency, + + // #wihtCurrenciesActions requestFetchCurrencies, requestSubmitCurrencies, requestEditCurrency, - editCurrency, }) { const intl = useIntl(); @@ -40,70 +54,72 @@ function CurrencyDialog({ .max(4) .required(intl.formatMessage({ id: 'required' })), }); - const initialValues = useMemo( - () => ({ - currency_name: '', - currency_code: '', - }), - [] - ); + const initialValues = useMemo(() => ({ + currency_name: '', + currency_code: '', + }), []); - const formik = useFormik({ + const { + values, + errors, + touched, + setFieldValue, + getFieldProps, + isSubmitting, + handleSubmit, + resetForm, + } = useFormik({ enableReinitialize: true, - initialValues: { ...(payload.action === 'edit' && - pick(editCurrency, Object.keys(initialValues))), + pick(currency, Object.keys(initialValues))), }, - validationSchema: ValidationSchema, onSubmit: (values, { setSubmitting }) => { if (payload.action === 'edit') { - requestEditCurrency(editCurrency.id, values) - .then((response) => { - closeDialog(name); - AppToaster.show({ - message: 'the_currency_has_been_edited', - }); - setSubmitting(false); - }) - .catch((error) => { - setSubmitting(false); + requestEditCurrency(currency.id, values).then((response) => { + closeDialog(name); + AppToaster.show({ + message: 'the_currency_has_been_edited', + intent: Intent.SUCCESS, }); + setSubmitting(false); + }) + .catch((error) => { + setSubmitting(false); + }); } else { - requestSubmitCurrencies(values) - .then((response) => { - closeDialog(name); - AppToaster.show({ - message: 'the_currency_has_been_submit', - }); - setSubmitting(false); - }) - .catch((error) => { - setSubmitting(false); + requestSubmitCurrencies(values).then((response) => { + closeDialog(name); + AppToaster.show({ + message: 'the_currency_has_been_submit', + intent: Intent.SUCCESS, }); + setSubmitting(false); + }) + .catch((error) => { + setSubmitting(false); + }); } }, }); - const { values, errors, touched } = useMemo(() => formik, [formik]); - const handleClose = useCallback(() => { closeDialog(name); }, [name, closeDialog]); - const fetchHook = useAsync(async () => { - await Promise.all([requestFetchCurrencies()]); - }); + const fetchCurrencies = useQuery('currencies', + () => { requestFetchCurrencies(); }, + { manual: true }); const onDialogOpening = useCallback(() => { - fetchHook.execute(); - }, [fetchHook]); + fetchCurrencies.refetch(); + }, [fetchCurrencies]); const onDialogClosed = useCallback(() => { - formik.resetForm(); + resetForm(); closeDialog(name); - }, [formik, closeDialog, name]); + }, [closeDialog, name]); const requiredSpan = useMemo(() => *, []); @@ -113,59 +129,53 @@ function CurrencyDialog({ title={payload.action === 'edit' ? 'Edit Currency' : ' New Currency'} className={classNames( { - 'dialog--loading': fetchHook.pending, + 'dialog--loading': fetchCurrencies.isFetching, }, 'dialog--currency-form' )} isOpen={isOpen} onClosed={onDialogClosed} onOpening={onDialogOpening} - isLoading={fetchHook.pending} + isLoading={fetchCurrencies.isFetching} onClose={handleClose} > -
+
} + intent={(errors.currency_name && touched.currency_name) && Intent.DANGER} + helperText={} inline={true} > + } + intent={(errors.currency_code && touched.currency_code) && Intent.DANGER} + helperText={} inline={true} >
+
-
@@ -175,8 +185,22 @@ function CurrencyDialog({ ); } +const mapStateToProps = (state, props) => { + const dialogPayload = getDialogPayload(state, 'currency-form'); + + return { + name: 'currency-form', + payload: { action: 'new', currencyCode: null, ...dialogPayload }, + currencyCode: dialogPayload?.currencyCode || null, + } +} + +const withCurrencyFormDialog = connect(mapStateToProps); + export default compose( - CurrencyFromDialogConnect, + withCurrencyFormDialog, DialogConnect, - DialogReduxConnect + DialogReduxConnect, + withCurrenciesActions, + withCurrency, )(CurrencyDialog); diff --git a/client/src/containers/Preferences/Accountant.js b/client/src/containers/Preferences/Accountant/Accountant.js similarity index 100% rename from client/src/containers/Preferences/Accountant.js rename to client/src/containers/Preferences/Accountant/Accountant.js diff --git a/client/src/containers/Preferences/Accounts.js b/client/src/containers/Preferences/Accounts/Accounts.js similarity index 100% rename from client/src/containers/Preferences/Accounts.js rename to client/src/containers/Preferences/Accounts/Accounts.js diff --git a/client/src/containers/Preferences/AccountsCustomFields.js b/client/src/containers/Preferences/Accounts/AccountsCustomFields.js similarity index 100% rename from client/src/containers/Preferences/AccountsCustomFields.js rename to client/src/containers/Preferences/Accounts/AccountsCustomFields.js diff --git a/client/src/containers/Preferences/AccountsGeneral.js b/client/src/containers/Preferences/Accounts/AccountsGeneral.js similarity index 100% rename from client/src/containers/Preferences/AccountsGeneral.js rename to client/src/containers/Preferences/Accounts/AccountsGeneral.js diff --git a/client/src/containers/Preferences/Currencies.js b/client/src/containers/Preferences/Currencies/Currencies.js similarity index 100% rename from client/src/containers/Preferences/Currencies.js rename to client/src/containers/Preferences/Currencies/Currencies.js diff --git a/client/src/containers/Preferences/CurrenciesActions.js b/client/src/containers/Preferences/Currencies/CurrenciesActions.js similarity index 100% rename from client/src/containers/Preferences/CurrenciesActions.js rename to client/src/containers/Preferences/Currencies/CurrenciesActions.js diff --git a/client/src/containers/Preferences/CurrenciesList.js b/client/src/containers/Preferences/Currencies/CurrenciesList.js similarity index 52% rename from client/src/containers/Preferences/CurrenciesList.js rename to client/src/containers/Preferences/Currencies/CurrenciesList.js index 6554f56e7..8572ef696 100644 --- a/client/src/containers/Preferences/CurrenciesList.js +++ b/client/src/containers/Preferences/Currencies/CurrenciesList.js @@ -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) => ( - - + const actionMenuList = useCallback((currency) => ( + + handleEditCurrency(currency)} /> - onDeleteCurrency(currency)} - /> - - ), - [] - ); + onDeleteCurrency(currency)} + /> + + ), []); + + 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 }) => ( + +