mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 12:20:31 +00:00
fix(exchangeRate): fix pagination & add sorting.
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { DataTable } from 'components';
|
||||
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
|
||||
import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
||||
|
||||
import { useExchangeRatesContext } from './ExchangeRatesProvider';
|
||||
import { useExchangeRatesTableColumns, ActionMenuList } from './components';
|
||||
|
||||
import withExchangeRates from './withExchangeRates';
|
||||
import withExchangeRatesActions from './withExchangeRatesActions';
|
||||
|
||||
import withDialogActions from 'containers/Dialog/withDialogActions';
|
||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
@@ -23,6 +26,12 @@ function ExchangeRateTable({
|
||||
|
||||
// #withAlertActions
|
||||
openAlert,
|
||||
|
||||
// #withExchangeRatesActions
|
||||
setExchangeRateTableState,
|
||||
|
||||
// #withExchangeRates
|
||||
exchangeRatesTableState,
|
||||
}) {
|
||||
const {
|
||||
isExchangeRatesFetching,
|
||||
@@ -48,28 +57,51 @@ function ExchangeRateTable({
|
||||
});
|
||||
};
|
||||
|
||||
const handleFetchData = useCallback(
|
||||
({ pageSize, pageIndex, sortBy }) => {
|
||||
setExchangeRateTableState({
|
||||
pageIndex,
|
||||
pageSize,
|
||||
sortBy,
|
||||
});
|
||||
},
|
||||
[setExchangeRateTableState],
|
||||
);
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={exchangesRates}
|
||||
noInitialFetch={true}
|
||||
initialState={exchangeRatesTableState}
|
||||
loading={isExchangeRatesLoading}
|
||||
headerLoading={isExchangeRatesLoading}
|
||||
progressBarLoading={isExchangeRatesFetching}
|
||||
selectionColumn={true}
|
||||
manualSortBy={true}
|
||||
expandable={true}
|
||||
sticky={true}
|
||||
// pagination={true}
|
||||
manualSortBy={true}
|
||||
onFetchData={handleFetchData}
|
||||
pagination={true}
|
||||
manualPagination={true}
|
||||
pagesCount={pagination.pagesCount}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
ContextMenu={ActionMenuList}
|
||||
payload={{
|
||||
onDeleteExchangeRate: handleDeleteExchangeRate,
|
||||
onEditExchangeRate: handelEditExchangeRate,
|
||||
}}
|
||||
ContextMenu={ActionMenuList}
|
||||
{...tableProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogActions, withAlertActions)(ExchangeRateTable);
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
withAlertActions,
|
||||
withExchangeRates(({ exchangeRatesTableState }) => ({
|
||||
exchangeRatesTableState,
|
||||
})),
|
||||
withExchangeRatesActions,
|
||||
)(ExchangeRateTable);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { compose } from 'utils';
|
||||
|
||||
import { DashboardContentTable, DashboardPageContent } from 'components';
|
||||
|
||||
@@ -7,13 +8,20 @@ import ExchangeRateActionsBar from './ExchangeRateActionsBar';
|
||||
|
||||
import { ExchangeRatesProvider } from './ExchangeRatesProvider';
|
||||
import ExchangeRatesAlerts from './ExchangeRatesAlerts';
|
||||
import withExchangeRates from './withExchangeRates';
|
||||
import { transformTableStateToQuery } from 'utils';
|
||||
|
||||
/**
|
||||
* Exchange Rates list.
|
||||
*/
|
||||
export default function ExchangeRatesList() {
|
||||
function ExchangeRatesList({
|
||||
// #withExchangeRates
|
||||
exchangeRatesTableState,
|
||||
}) {
|
||||
return (
|
||||
<ExchangeRatesProvider>
|
||||
<ExchangeRatesProvider
|
||||
query={transformTableStateToQuery(exchangeRatesTableState)}
|
||||
>
|
||||
<ExchangeRateActionsBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
@@ -25,3 +33,8 @@ export default function ExchangeRatesList() {
|
||||
</ExchangeRatesProvider>
|
||||
);
|
||||
}
|
||||
export default compose(
|
||||
withExchangeRates(({ exchangeRatesTableState }) => ({
|
||||
exchangeRatesTableState,
|
||||
})),
|
||||
)(ExchangeRatesList);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { transformTableQueryToParams } from 'utils';
|
||||
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useExchangeRates } from 'hooks/query';
|
||||
|
||||
@@ -9,10 +11,15 @@ const ExchangesRatesContext = createContext();
|
||||
*/
|
||||
function ExchangeRatesProvider({ query, ...props }) {
|
||||
const {
|
||||
data: { exchangesRates, pagination },
|
||||
data: { exchangesRates, pagination, filterMeta },
|
||||
isFetching: isExchangeRatesFetching,
|
||||
isLoading: isExchangeRatesLoading,
|
||||
} = useExchangeRates();
|
||||
} = useExchangeRates(
|
||||
{
|
||||
...transformTableQueryToParams(query),
|
||||
},
|
||||
{ keepPreviousData: true },
|
||||
);
|
||||
|
||||
const state = {
|
||||
isExchangeRatesFetching,
|
||||
@@ -20,11 +27,10 @@ function ExchangeRatesProvider({ query, ...props }) {
|
||||
|
||||
exchangesRates,
|
||||
pagination,
|
||||
query,
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'exchange-rate-list'}>
|
||||
<DashboardInsider name={'exchange-rate'}>
|
||||
<ExchangesRatesContext.Provider value={state} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
getExchangeRatesList,
|
||||
getExchangeRatePaginationMetaFactory,
|
||||
getExchangeRatesTableQueryFactory,
|
||||
} from 'store/ExchangeRate/exchange.selector';
|
||||
import { getExchangeRatesTableStateFactory } from 'store/ExchangeRate/exchange.selector';
|
||||
|
||||
export default (mapState) => {
|
||||
const getExchangeRatesPaginationMeta = getExchangeRatePaginationMetaFactory();
|
||||
|
||||
const getExchangeRatesTableState = getExchangeRatesTableStateFactory();
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const query = getExchangeRatesTableQueryFactory(state, props);
|
||||
|
||||
const mapped = {
|
||||
exchangeRatesList: getExchangeRatesList(state, props),
|
||||
exchangeRatesLoading: state.exchangeRates.loading,
|
||||
exchangeRatesPageination: getExchangeRatesPaginationMeta(
|
||||
state,
|
||||
props,
|
||||
query,
|
||||
),
|
||||
exchangeRatesTableState: getExchangeRatesTableState(state, props),
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
submitExchangeRate,
|
||||
fetchExchangeRates,
|
||||
deleteExchangeRate,
|
||||
editExchangeRate,
|
||||
deleteBulkExchangeRates
|
||||
} from 'store/ExchangeRate/exchange.actions';
|
||||
import { setExchangeRateTableState } from 'store/ExchangeRate/exchange.actions';
|
||||
|
||||
const mapActionsToProps = (dispatch) => ({
|
||||
requestSubmitExchangeRate: (form) => dispatch(submitExchangeRate({ form })),
|
||||
requestFetchExchangeRates: () => dispatch(fetchExchangeRates()),
|
||||
requestDeleteExchangeRate: (id) => dispatch(deleteExchangeRate(id)),
|
||||
requestEditExchangeRate: (id, form) => dispatch(editExchangeRate(id, form)),
|
||||
requestDeleteBulkExchangeRates:(ids)=>dispatch(deleteBulkExchangeRates({ids})),
|
||||
addExchangeRatesTableQueries: (queries) =>
|
||||
dispatch({
|
||||
type: 'ExchangeRates_TABLE_QUERIES_ADD',
|
||||
queries,
|
||||
}),
|
||||
export const mapDispatchToProps = (dispatch) => ({
|
||||
setExchangeRateTableState: (queries) =>
|
||||
dispatch(setExchangeRateTableState(queries)),
|
||||
});
|
||||
|
||||
export default connect(null, mapActionsToProps);
|
||||
export default connect(null, mapDispatchToProps);
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { useQuery, useMutation, useQueryClient } from 'react-query';
|
||||
import { defaultTo } from 'lodash';
|
||||
import { transformPagination, transformResponse } from 'utils';
|
||||
import useApiRequest from '../useRequest';
|
||||
|
||||
const defaultPagination = {
|
||||
pageSize: 12,
|
||||
page: 0,
|
||||
pagesCount: 0,
|
||||
};
|
||||
/**
|
||||
* Creates a new exchange rate.
|
||||
*/
|
||||
@@ -50,14 +56,6 @@ export function useDeleteExchangeRate(props) {
|
||||
});
|
||||
}
|
||||
|
||||
// Transforms items categories.
|
||||
const transformExchangesRates = (response) => {
|
||||
return {
|
||||
exchangesRates: response.data.exchange_rates.results,
|
||||
pagination: response.data.exchange_rates.pagination,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the exchange rate list.
|
||||
*/
|
||||
@@ -66,18 +64,27 @@ export function useExchangeRates(query, props) {
|
||||
|
||||
const states = useQuery(
|
||||
['EXCHANGES_RATES', query],
|
||||
() =>
|
||||
apiRequest.get('exchange_rates', { params: { query } }).then(
|
||||
transformExchangesRates,
|
||||
),
|
||||
props,
|
||||
() => apiRequest.get('exchange_rates', { params: query }),
|
||||
{
|
||||
select: (res) => ({
|
||||
exchangesRates: res.data.exchange_rates.results,
|
||||
pagination: transformPagination(res.data.exchange_rates.pagination),
|
||||
filterMeta: res.data.filter_meta,
|
||||
}),
|
||||
...props,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...states,
|
||||
data: defaultTo(states.data, {
|
||||
exchangesRates: [],
|
||||
pagination: {},
|
||||
pagination: {
|
||||
page: 1,
|
||||
pageSize: 12,
|
||||
total: 0,
|
||||
},
|
||||
filterMeta: {},
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,116 +1,8 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchExchangeRates = () => {
|
||||
return (dispatch) =>
|
||||
new Promise((resolve, reject) => {
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATE_TABLE_LOADING,
|
||||
payload: {
|
||||
loading: true,
|
||||
},
|
||||
});
|
||||
|
||||
ApiService.get('exchange_rates')
|
||||
.then((response) => {
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATES_PAGE_SET,
|
||||
payload: {
|
||||
exchange_rates: response.data.exchange_rates.results,
|
||||
pagination: response.data.exchange_rates.pagination,
|
||||
customViewId: response.data.exchange_rates.customViewId || -1,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATE_LIST_SET,
|
||||
exchange_rates: response.data.exchange_rates.results,
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATES_PAGINATION_SET,
|
||||
payload: {
|
||||
pagination: response.data.exchange_rates.pagination,
|
||||
customViewId: response.data.customViewId || -1,
|
||||
},
|
||||
});
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATE_TABLE_LOADING,
|
||||
payload: {
|
||||
loading: false,
|
||||
},
|
||||
});
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const submitExchangeRate = ({ form }) => {
|
||||
return (dispatch) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ApiService.post('exchange_rates', form)
|
||||
.then((response) => {
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
reject(data?.errors);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteExchangeRate = (id) => {
|
||||
return (dispatch) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ApiService.delete(`exchange_rates/${id}`)
|
||||
.then((response) => {
|
||||
dispatch({ type: t.EXCHANGE_RATE_DELETE, id });
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error.response.data.errors || []);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const editExchangeRate = (id, form) => {
|
||||
return (dispatch) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ApiService.post(`exchange_rates/${id}`, form)
|
||||
.then((response) => {
|
||||
dispatch({ type: t.CLEAR_EXCHANGE_RATE_FORM_ERRORS });
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
const { errors } = data;
|
||||
|
||||
dispatch({ type: t.CLEAR_EXCHANGE_RATE_FORM_ERRORS });
|
||||
if (errors) {
|
||||
dispatch({ type: t.CLEAR_EXCHANGE_RATE_FORM_ERRORS, errors });
|
||||
}
|
||||
reject(data?.errors);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteBulkExchangeRates = ({ ids }) => {
|
||||
return (dispatch) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ApiService.delete(`exchange_rates/bulk`, { params: { ids } })
|
||||
.then((response) => {
|
||||
dispatch({
|
||||
type: t.EXCHANGE_RATES_BULK_DELETE,
|
||||
payload: { ids },
|
||||
});
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
export const setExchangeRateTableState = (queries) => {
|
||||
return {
|
||||
type: t.EXCHANGE_RATES_TABLE_STATE_SET,
|
||||
payload: { queries },
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,88 +1,13 @@
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import { createTableQueryReducers } from 'store/queryReducers';
|
||||
import t from 'store/types';
|
||||
import { createTableStateReducers } from 'store/tableState.reducer';
|
||||
|
||||
const initialState = {
|
||||
exchangeRates: {},
|
||||
loading: false,
|
||||
views: {},
|
||||
tableQuery: {
|
||||
page_size: 5,
|
||||
page: 1,
|
||||
tableState: {
|
||||
pageSize: 12,
|
||||
pageIndex: 0,
|
||||
},
|
||||
currentViewId: -1,
|
||||
};
|
||||
|
||||
const reducer = createReducer(initialState, {
|
||||
[t.EXCHANGE_RATE_LIST_SET]: (state, action) => {
|
||||
const _exchangeRates = {};
|
||||
action.exchange_rates.forEach((exchange_rate) => {
|
||||
_exchangeRates[exchange_rate.id] = exchange_rate;
|
||||
});
|
||||
|
||||
state.exchangeRates = {
|
||||
...state.exchangeRates,
|
||||
..._exchangeRates,
|
||||
};
|
||||
},
|
||||
|
||||
[t.EXCHANGE_RATE_TABLE_LOADING]: (state, action) => {
|
||||
const { loading } = action.payload;
|
||||
state.loading = loading;
|
||||
},
|
||||
|
||||
[t.EXCHANGE_RATES_PAGE_SET]: (state, action) => {
|
||||
const { customViewId, exchange_rates, pagination } = action.payload;
|
||||
|
||||
const viewId = customViewId || -1;
|
||||
const view = state.views[viewId] || {};
|
||||
state.views[viewId] = {
|
||||
...view,
|
||||
pages: {
|
||||
...(state.views?.[viewId]?.pages || {}),
|
||||
[pagination.page]: {
|
||||
ids: exchange_rates.map((i) => i.id),
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
[t.EXCHANGE_RATES_PAGINATION_SET]: (state, action) => {
|
||||
const { pagination, customViewId } = action.payload;
|
||||
|
||||
const mapped = {
|
||||
pageSize: parseInt(pagination.pageSize, 10),
|
||||
page: parseInt(pagination.page, 10),
|
||||
total: parseInt(pagination.total, 10),
|
||||
};
|
||||
const paginationMeta = {
|
||||
...mapped,
|
||||
pagesCount: Math.ceil(mapped.total / mapped.pageSize),
|
||||
pageIndex: Math.max(mapped.page - 1, 0),
|
||||
};
|
||||
|
||||
state.views = {
|
||||
...state.views,
|
||||
[customViewId]: {
|
||||
...(state.views?.[customViewId] || {}),
|
||||
paginationMeta,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
[t.EXCHANGE_RATES_BULK_DELETE]: (state, action) => {
|
||||
const { ids } = action.payload;
|
||||
ids.forEach((id) => {
|
||||
if (typeof state.exchangeRates[id] !== 'undefined') {
|
||||
delete state.exchangeRates[id];
|
||||
}
|
||||
});
|
||||
},
|
||||
[t.EXCHANGE_RATE_DELETE]: (state, action) => {
|
||||
if (typeof state.exchangeRates[action.id] !== 'undefined') {
|
||||
delete state.exchangeRates[action.id];
|
||||
}
|
||||
},
|
||||
export default createReducer(initialState, {
|
||||
...createTableStateReducers('EXCHANGE_RATES'),
|
||||
});
|
||||
|
||||
export default createTableQueryReducers('exchange_rates', reducer);
|
||||
|
||||
@@ -1,47 +1,18 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
pickItemsFromIds,
|
||||
getItemById,
|
||||
paginationLocationQuery,
|
||||
} from 'store/selectors';
|
||||
import { createDeepEqualSelector } from 'utils';
|
||||
import { paginationLocationQuery } from 'store/selectors';
|
||||
|
||||
const exchangeRateItemsSelector = (state) => state.exchangeRates.exchangeRates;
|
||||
const exchangeRateIdPropSelector = (state, props) => props.exchangeRateId;
|
||||
const exchangeRateTableQuery = (state) => state.exchangeRates.tableQuery;
|
||||
|
||||
const exchangeRatesCurrentViewSelector = (state, props) => {
|
||||
const viewId = state.exchangeRates.currentViewId;
|
||||
return state.exchangeRates.views?.[viewId];
|
||||
const exchangeRateTableState = (state) => {
|
||||
return state.exchangeRates.tableState;
|
||||
};
|
||||
|
||||
export const getExchangeRatesList = createSelector(
|
||||
exchangeRateItemsSelector,
|
||||
(exchangeRateItems) => {
|
||||
return Object.values(exchangeRateItems);
|
||||
},
|
||||
);
|
||||
|
||||
export const getExchangeRateById = createSelector(
|
||||
exchangeRateItemsSelector,
|
||||
exchangeRateIdPropSelector,
|
||||
(exchangeRates, exchangeRateId) => {
|
||||
return getItemById(exchangeRates, exchangeRateId);
|
||||
},
|
||||
);
|
||||
|
||||
export const getExchangeRatePaginationMetaFactory = () =>
|
||||
createSelector(exchangeRatesCurrentViewSelector, (exchangeRateView) => {
|
||||
return exchangeRateView?.paginationMeta || {};
|
||||
});
|
||||
|
||||
export const getExchangeRatesTableQueryFactory = () =>
|
||||
createSelector(
|
||||
export const getExchangeRatesTableStateFactory = () =>
|
||||
createDeepEqualSelector(
|
||||
paginationLocationQuery,
|
||||
exchangeRateTableQuery,
|
||||
(locationQuery, tableQuery) => {
|
||||
exchangeRateTableState,
|
||||
(locationQuery, tableState) => {
|
||||
return {
|
||||
...locationQuery,
|
||||
...tableQuery,
|
||||
...tableState,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
export default {
|
||||
EXCHANGE_RATE_DATA_TABLE: 'EXCHANGE_RATE_DATA_TABLE',
|
||||
EXCHANGE_RATE_DELETE: 'EXCHANGE_RATE_DELETE',
|
||||
EXCHANGE_RATE_LIST_SET: 'EXCHANGE_RATE_LIST_SET',
|
||||
CLEAR_EXCHANGE_RATE_FORM_ERRORS: 'CLEAR_EXCHANGE_RATE_FORM_ERRORS',
|
||||
ExchangeRates_TABLE_QUERIES_ADD: 'ExchangeRates_TABLE_QUERIES_ADD',
|
||||
EXCHANGE_RATE_TABLE_LOADING: 'EXCHANGE_RATE_TABLE_LOADING',
|
||||
EXCHANGE_RATES_BULK_DELETE: 'EXCHANGE_RATES_BULK_DELETE',
|
||||
EXCHANGE_RATES_PAGE_SET: 'EXCHANGE_RATES_PAGE_SET',
|
||||
EXCHANGE_RATES_PAGINATION_SET: 'EXCHANGE_RATES_PAGINATION_SET',
|
||||
EXCHANGE_RATES_TABLE_STATE_SET: 'EXCHANGE_RATES/TABLE_STATE_SET',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user