mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
feat: Pagination component.
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
Position,
|
||||
Tag,
|
||||
} from '@blueprintjs/core';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { withRouter, useParams } from 'react-router-dom';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
|
||||
@@ -29,18 +29,21 @@ import withViewDetails from 'containers/Views/withViewDetails';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
|
||||
|
||||
function ManualJournalsDataTable({
|
||||
loading,
|
||||
|
||||
manualJournals,
|
||||
// #withManualJournals
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
|
||||
// #withDashboardActions
|
||||
changeCurrentView,
|
||||
changePageSubtitle,
|
||||
setTopbarEditView,
|
||||
|
||||
// #withViewDetails
|
||||
viewId,
|
||||
viewMeta,
|
||||
|
||||
@@ -96,27 +99,6 @@ function ManualJournalsDataTable({
|
||||
[onDeleteJournal],
|
||||
);
|
||||
|
||||
// const actionMenuList = (journal) => (
|
||||
// <Menu>
|
||||
// <MenuItem text={<T id={'view_details'} />} />
|
||||
// <MenuDivider />
|
||||
// {!journal.status && (
|
||||
// <MenuItem
|
||||
// text={<T id={'publish_journal'} />}
|
||||
// onClick={handlePublishJournal(journal)}
|
||||
// />
|
||||
// )}
|
||||
// <MenuItem
|
||||
// text={<T id={'edit_journal'} />}
|
||||
// onClick={handleEditJournal(journal)}
|
||||
// />
|
||||
// <MenuItem
|
||||
// text={<T id={'delete_journal'} />}
|
||||
// intent={Intent.DANGER}
|
||||
// onClick={handleDeleteJournal(journal)}
|
||||
// />
|
||||
// </Menu>
|
||||
// );
|
||||
const actionMenuList = useCallback(
|
||||
(journal) => (
|
||||
<Menu>
|
||||
@@ -171,13 +153,9 @@ function ManualJournalsDataTable({
|
||||
Header: formatMessage({ id: 'status' }),
|
||||
accessor: (r) => {
|
||||
return r.status ? (
|
||||
<Tag minimal={true}>
|
||||
<T id={'published'} />
|
||||
</Tag>
|
||||
<Tag minimal={true}><T id={'published'} /></Tag>
|
||||
) : (
|
||||
<Tag minimal={true} intent={Intent.WARNING}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
<Tag minimal={true} intent={Intent.WARNING}><T id={'draft'} /></Tag>
|
||||
);
|
||||
},
|
||||
disableResizing: true,
|
||||
@@ -227,7 +205,7 @@ function ManualJournalsDataTable({
|
||||
content={actionMenuList(cell.row.original)}
|
||||
position={Position.RIGHT_BOTTOM}
|
||||
>
|
||||
<Button icon={<Icon icon='more-h-16' iconSize={16} />} />
|
||||
<Button icon={<Icon icon="more-h-16" iconSize={16} />} />
|
||||
</Popover>
|
||||
),
|
||||
className: 'actions',
|
||||
@@ -257,26 +235,41 @@ function ManualJournalsDataTable({
|
||||
<LoadingIndicator loading={loading} mount={false}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={manualJournals}
|
||||
data={manualJournalsCurrentPage}
|
||||
onFetchData={handleDataTableFetchData}
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
loading={manualJournalsLoading && !initialMount}
|
||||
loading={manualJournalsLoading && !manualJournalsCurrentPage.length > 0}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
pagination={true}
|
||||
|
||||
pagesCount={manualJournalsPagination.pagesCount}
|
||||
initialPageSize={manualJournalsTableQuery.page_size}
|
||||
initialPageIndex={manualJournalsTableQuery.page - 1}
|
||||
/>
|
||||
</LoadingIndicator>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withDialogActions,
|
||||
withDashboardActions,
|
||||
withManualJournalsActions,
|
||||
withManualJournals(({ manualJournals, manualJournalsLoading }) => ({
|
||||
manualJournals,
|
||||
manualJournalsLoading,
|
||||
})),
|
||||
withManualJournals(
|
||||
({
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
}) => ({
|
||||
manualJournalsCurrentPage,
|
||||
manualJournalsLoading,
|
||||
manualJournalsPagination,
|
||||
manualJournalsTableQuery,
|
||||
}),
|
||||
),
|
||||
withViewDetails,
|
||||
)(ManualJournalsDataTable);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import { Route, Switch, useHistory } from 'react-router-dom';
|
||||
import { Route, Switch, useHistory, withRouter } from 'react-router-dom';
|
||||
import { useQuery } from 'react-query';
|
||||
import { Alert, Intent } from '@blueprintjs/core';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
@@ -13,8 +13,10 @@ import ManualJournalsDataTable from 'containers/Accounting/ManualJournalsDataTab
|
||||
import ManualJournalsActionsBar from 'containers/Accounting/ManualJournalActionsBar';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withManualJournals from 'containers/Accounting/withManualJournals';
|
||||
import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions';
|
||||
import withViewsActions from 'containers/Views/withViewsActions';
|
||||
import withRouteActions from 'containers/Router/withRouteActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
@@ -28,12 +30,17 @@ function ManualJournalsTable({
|
||||
// #withViewsActions
|
||||
requestFetchResourceViews,
|
||||
|
||||
// #withManualJournals
|
||||
manualJournalsTableQuery,
|
||||
|
||||
// #withManualJournalsActions
|
||||
requestFetchManualJournalsTable,
|
||||
requestDeleteManualJournal,
|
||||
requestPublishManualJournal,
|
||||
requestDeleteBulkManualJournals,
|
||||
addManualJournalsTableQueries,
|
||||
|
||||
addQuery,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
@@ -47,19 +54,21 @@ function ManualJournalsTable({
|
||||
return requestFetchResourceViews('manual_journals');
|
||||
});
|
||||
|
||||
const fetchManualJournals = useQuery('manual-journals-table',
|
||||
() => requestFetchManualJournalsTable());
|
||||
const fetchManualJournals = useQuery(
|
||||
['manual-journals-table', manualJournalsTableQuery],
|
||||
(key, q) => requestFetchManualJournalsTable(q),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
changePageTitle(formatMessage({id:'manual_journals'}));
|
||||
}, [changePageTitle,formatMessage]);
|
||||
changePageTitle(formatMessage({ id: 'manual_journals' }));
|
||||
}, [changePageTitle, formatMessage]);
|
||||
|
||||
// Handle delete manual journal click.
|
||||
const handleDeleteJournal = useCallback(
|
||||
(journal) => {
|
||||
setDeleteManualJournal(journal);
|
||||
},
|
||||
[setDeleteManualJournal]
|
||||
[setDeleteManualJournal],
|
||||
);
|
||||
|
||||
// Handle cancel delete manual journal.
|
||||
@@ -71,28 +80,26 @@ function ManualJournalsTable({
|
||||
const handleConfirmManualJournalDelete = useCallback(() => {
|
||||
requestDeleteManualJournal(deleteManualJournal.id).then(() => {
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_journal_has_been_successfully_deleted',
|
||||
}, {
|
||||
number: deleteManualJournal.journal_number,
|
||||
}),
|
||||
message: formatMessage(
|
||||
{ id: 'the_journal_has_been_successfully_deleted' },
|
||||
{ number: deleteManualJournal.journal_number },
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setDeleteManualJournal(false);
|
||||
});
|
||||
}, [deleteManualJournal, requestDeleteManualJournal,formatMessage]);
|
||||
|
||||
}, [deleteManualJournal, requestDeleteManualJournal, formatMessage]);
|
||||
|
||||
// Calculates the selected rows count.
|
||||
const selectedRowsCount = useMemo(
|
||||
() => Object.values(selectedRows).length,
|
||||
[selectedRows]);
|
||||
const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [
|
||||
selectedRows,
|
||||
]);
|
||||
|
||||
const handleBulkDelete = useCallback(
|
||||
(accountsIds) => {
|
||||
setBulkDelete(accountsIds);
|
||||
},
|
||||
[setBulkDelete]
|
||||
[setBulkDelete],
|
||||
);
|
||||
|
||||
// Handle confirm journals bulk delete.
|
||||
@@ -100,11 +107,10 @@ function ManualJournalsTable({
|
||||
requestDeleteBulkManualJournals(bulkDelete)
|
||||
.then(() => {
|
||||
AppToaster.show({
|
||||
message: formatMessage({
|
||||
id: 'the_journals_has_been_successfully_deleted',
|
||||
}, {
|
||||
count: selectedRowsCount,
|
||||
}),
|
||||
message: formatMessage(
|
||||
{ id: 'the_journals_has_been_successfully_deleted', },
|
||||
{ count: selectedRowsCount, },
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setBulkDelete(false);
|
||||
@@ -112,7 +118,12 @@ function ManualJournalsTable({
|
||||
.catch((error) => {
|
||||
setBulkDelete(false);
|
||||
});
|
||||
}, [requestDeleteBulkManualJournals, bulkDelete,formatMessage,selectedRowsCount]);
|
||||
}, [
|
||||
requestDeleteBulkManualJournals,
|
||||
bulkDelete,
|
||||
formatMessage,
|
||||
selectedRowsCount,
|
||||
]);
|
||||
|
||||
// Handle cancel bulk delete alert.
|
||||
const handleCancelBulkDelete = useCallback(() => {
|
||||
@@ -123,38 +134,49 @@ function ManualJournalsTable({
|
||||
(journal) => {
|
||||
history.push(`/manual-journals/${journal.id}/edit`);
|
||||
},
|
||||
[history]
|
||||
[history],
|
||||
);
|
||||
|
||||
// Handle filter change to re-fetch data-table.
|
||||
const handleFilterChanged = useCallback(() => {
|
||||
|
||||
}, [fetchManualJournals]);
|
||||
const handleFilterChanged = useCallback(() => {}, [fetchManualJournals]);
|
||||
|
||||
// Handle view change to re-fetch data table.
|
||||
// const handleViewChanged = useCallback(() => {
|
||||
|
||||
|
||||
// }, [fetchManualJournals]);
|
||||
|
||||
// Handle fetch data of manual jouranls datatable.
|
||||
const handleFetchData = useCallback(({ pageIndex, pageSize, sortBy }) => {
|
||||
addManualJournalsTableQueries({
|
||||
...(sortBy.length > 0) ? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||
} : {},
|
||||
});
|
||||
}, [addManualJournalsTableQueries]);
|
||||
const handleFetchData = useCallback(
|
||||
({ pageIndex, pageSize, sortBy }) => {
|
||||
const page = pageIndex + 1;
|
||||
// addQuery('page_size', pageSize);
|
||||
// addQuery('page', page);
|
||||
|
||||
addManualJournalsTableQueries({
|
||||
...(sortBy.length > 0
|
||||
? {
|
||||
column_sort_by: sortBy[0].id,
|
||||
sort_order: sortBy[0].desc ? 'desc' : 'asc',
|
||||
}
|
||||
: {}),
|
||||
page_size: pageSize,
|
||||
page,
|
||||
});
|
||||
},
|
||||
[addManualJournalsTableQueries],
|
||||
);
|
||||
|
||||
const handlePublishJournal = useCallback(
|
||||
(journal) => {
|
||||
requestPublishManualJournal(journal.id).then(() => {
|
||||
AppToaster.show({
|
||||
message: formatMessage({id:'the_manual_journal_id_has_been_published'})
|
||||
message: formatMessage({
|
||||
id: 'the_manual_journal_id_has_been_published',
|
||||
}),
|
||||
});
|
||||
});
|
||||
},
|
||||
[requestPublishManualJournal,formatMessage]
|
||||
[requestPublishManualJournal, formatMessage],
|
||||
);
|
||||
|
||||
// Handle selected rows change.
|
||||
@@ -162,12 +184,12 @@ function ManualJournalsTable({
|
||||
(accounts) => {
|
||||
setSelectedRows(accounts);
|
||||
},
|
||||
[setSelectedRows]
|
||||
[setSelectedRows],
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={fetchViews.isFetching || fetchManualJournals.isFetching}
|
||||
loading={fetchViews.isFetching}
|
||||
name={'manual-journals'}
|
||||
>
|
||||
<ManualJournalsActionsBar
|
||||
@@ -183,7 +205,8 @@ function ManualJournalsTable({
|
||||
path={[
|
||||
'/manual-journals/:custom_view_id/custom_view',
|
||||
'/manual-journals',
|
||||
]}>
|
||||
]}
|
||||
>
|
||||
<ManualJournalsViewTabs />
|
||||
|
||||
<ManualJournalsDataTable
|
||||
@@ -199,25 +222,37 @@ function ManualJournalsTable({
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete'} />}
|
||||
icon='trash'
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={deleteManualJournal}
|
||||
onCancel={handleCancelManualJournalDelete}
|
||||
onConfirm={handleConfirmManualJournalDelete}
|
||||
>
|
||||
<p><T id={'once_delete_this_journal_category_you_will_able_to_restore_it'} /></p>
|
||||
<p>
|
||||
<T
|
||||
id={
|
||||
'once_delete_this_journal_category_you_will_able_to_restore_it'
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete_count'} values={{ count: selectedRowsCount }} />}
|
||||
icon='trash'
|
||||
confirmButtonText={
|
||||
<T id={'delete_count'} values={{ count: selectedRowsCount }} />
|
||||
}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={bulkDelete}
|
||||
onCancel={handleCancelBulkDelete}
|
||||
onConfirm={handleConfirmBulkDelete}
|
||||
>
|
||||
<p><T id={'once_delete_these_journalss_you_will_not_able_restore_them'} /></p>
|
||||
<p>
|
||||
<T
|
||||
id={'once_delete_these_journalss_you_will_not_able_restore_them'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
</DashboardPageContent>
|
||||
</DashboardInsider>
|
||||
@@ -225,7 +260,12 @@ function ManualJournalsTable({
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withRouter,
|
||||
withRouteActions,
|
||||
withDashboardActions,
|
||||
withManualJournalsActions,
|
||||
withViewsActions
|
||||
withViewsActions,
|
||||
withManualJournals(({ manualJournalsTableQuery }) => ({
|
||||
manualJournalsTableQuery,
|
||||
})),
|
||||
)(ManualJournalsTable);
|
||||
|
||||
@@ -1,20 +1,41 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { pick, mapValues } from 'lodash';
|
||||
import { getResourceViews } from 'store/customViews/customViews.selectors';
|
||||
import {
|
||||
getManualJournalsItems,
|
||||
} from 'store/manualJournals/manualJournals.selectors'
|
||||
import { getManualJournalsItems } from 'store/manualJournals/manualJournals.selectors';
|
||||
|
||||
const queryParamsKeys = ['page_size', 'page'];
|
||||
|
||||
export default (mapState) => {
|
||||
const mapStateToProps = (state, props) => {
|
||||
const queryParams = props.location
|
||||
? new URLSearchParams(props.location.search)
|
||||
: null;
|
||||
|
||||
const manualJournalsTableQuery = {
|
||||
...state.manualJournals.tableQuery,
|
||||
...(queryParams
|
||||
? mapValues(
|
||||
pick(Object.fromEntries(queryParams), queryParamsKeys),
|
||||
(v) => parseInt(v, 10),
|
||||
)
|
||||
: {}),
|
||||
};
|
||||
|
||||
const mapped = {
|
||||
manualJournals: getManualJournalsItems(state, state.manualJournals.currentViewId),
|
||||
manualJournalsCurrentPage: getManualJournalsItems(
|
||||
state,
|
||||
state.manualJournals.currentViewId,
|
||||
manualJournalsTableQuery.page,
|
||||
),
|
||||
manualJournalsTableQuery,
|
||||
manualJournalsViews: getResourceViews(state, 'manual_journals'),
|
||||
manualJournalsItems: state.manualJournals.items,
|
||||
manualJournalsTableQuery: state.manualJournals.tableQuery,
|
||||
|
||||
manualJournalsPagination: state.manualJournals.paginationMeta,
|
||||
manualJournalsLoading: state.manualJournals.loading,
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
|
||||
return connect(mapStateToProps);
|
||||
};
|
||||
|
||||
@@ -10,11 +10,10 @@ import {
|
||||
|
||||
const mapActionsToProps = (dispatch) => ({
|
||||
requestDeleteManualJournal: (id) => dispatch(deleteManualJournal({ id })),
|
||||
requestFetchManualJournalsTable: (query = {}) => dispatch(fetchManualJournalsTable({ query: { ...query } })),
|
||||
requestFetchManualJournalsTable: (query = {}) => dispatch(fetchManualJournalsTable({ query })),
|
||||
requestFetchManualJournal: (id) => dispatch(fetchManualJournal({ id })),
|
||||
requestPublishManualJournal: (id) => dispatch(publishManualJournal({ id })),
|
||||
requestDeleteBulkManualJournals: (ids) => dispatch(deleteBulkManualJournals({ ids })),
|
||||
|
||||
changeCurrentView: (id) => dispatch({
|
||||
type: t.MANUAL_JOURNALS_SET_CURRENT_VIEW,
|
||||
currentViewId: parseInt(id, 10),
|
||||
|
||||
31
client/src/containers/Router/withRouteActions.js
Normal file
31
client/src/containers/Router/withRouteActions.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
||||
const mapDispatchToProps = (dispatch, props) => {
|
||||
return {
|
||||
addQuery: (key, value) => {
|
||||
let pathname = props.location.pathname;
|
||||
let searchParams = new URLSearchParams(props.location.search);
|
||||
|
||||
searchParams.set(key, value);
|
||||
|
||||
props.history.push({
|
||||
pathname: pathname,
|
||||
search: searchParams.toString(),
|
||||
});
|
||||
},
|
||||
|
||||
removeQuery: (key) => {
|
||||
let pathname = props.location.pathname;
|
||||
let searchParams = new URLSearchParams(props.location.search);
|
||||
// returns the existing query string: '?type=fiction&author=fahid'
|
||||
searchParams.delete(key);
|
||||
props.history.push({
|
||||
pathname: pathname,
|
||||
search: searchParams.toString(),
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)
|
||||
Reference in New Issue
Block a user