diff --git a/client/src/common/classes.js b/client/src/common/classes.js index 213774aed..22d3c1b2f 100644 --- a/client/src/common/classes.js +++ b/client/src/common/classes.js @@ -29,6 +29,9 @@ const CLASSES = { CLOUD_SPINNER: 'cloud-spinner', IS_LOADING: 'is-loading', + + DATATABLE_EMPTY_STATE: 'datatable-empty-state', + DATATABLE_EMPTY_STATE_TITLE: 'datatable-empty-state__title', ...Classes, }; diff --git a/client/src/components/DataTable.js b/client/src/components/DataTable.js index 84ae9520a..6db7f3536 100644 --- a/client/src/components/DataTable.js +++ b/client/src/components/DataTable.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useCallback } from 'react'; +import React, { useEffect, useRef, useCallback, useMemo } from 'react'; import { useTable, useExpanded, @@ -7,20 +7,18 @@ import { useResizeColumns, useSortBy, useFlexLayout, + useAsyncDebounce, } from 'react-table'; -import { - Checkbox, - Spinner, - ContextMenu, -} from '@blueprintjs/core'; +import { Checkbox, Spinner, ContextMenu } from '@blueprintjs/core'; import classnames from 'classnames'; import { FixedSizeList } from 'react-window'; import { useSticky } from 'react-table-sticky'; import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync'; -import { ConditionalWrapper } from 'utils'; import { useUpdateEffect } from 'hooks'; -import { If, Pagination } from 'components'; +import { If, Pagination, Choose } from 'components'; + +import { ConditionalWrapper, saveInvoke } from 'utils'; const IndeterminateCheckbox = React.forwardRef( ({ indeterminate, ...rest }, ref) => { @@ -31,10 +29,13 @@ const IndeterminateCheckbox = React.forwardRef( export default function DataTable({ columns, data, + loading, onFetchData, + onSelectedRowsChange, manualSortBy = false, + manualPagination = true, selectionColumn = false, expandSubRows = true, className, @@ -53,11 +54,24 @@ export default function DataTable({ pagination = false, pagesCount: controlledPageCount, - initialPageIndex, - initialPageSize, + + // Pagination props. + initialPageIndex = 0, + initialPageSize = 10, rowContextMenu, expandColumnSpace = 1.5, + + updateDebounceTime = 200, + + // Read this document to know why! https://bit.ly/2Uw9SEc + autoResetPage = true, + autoResetExpanded = true, + autoResetGroupBy = true, + autoResetSelectedRows = true, + autoResetSortBy = true, + autoResetFilters = true, + autoResetRowState = true, }) { const { getTableProps, @@ -85,18 +99,25 @@ export default function DataTable({ } = useTable( { columns, - data: data, + data, initialState: { pageIndex: initialPageIndex, pageSize: initialPageSize, - expanded, - }, // Pass our hoisted table state - manualPagination: true, + }, + manualPagination, pageCount: controlledPageCount, getSubRows: (row) => row.children, manualSortBy, expandSubRows, payload, + + autoResetPage, + autoResetExpanded, + autoResetGroupBy, + autoResetSelectedRows, + autoResetSortBy, + autoResetFilters, + autoResetRowState, }, useSortBy, useExpanded, @@ -145,18 +166,23 @@ export default function DataTable({ ); const isInitialMount = useRef(noInitialFetch); - + const onFetchDataDebounced = useAsyncDebounce( + (...args) => { + saveInvoke(onFetchData, ...args); + }, + updateDebounceTime, + ); // When these table states change, fetch new data! useEffect(() => { if (isInitialMount.current) { isInitialMount.current = false; } else { - onFetchData && onFetchData({ pageIndex, pageSize, sortBy }); + onFetchDataDebounced({ pageIndex, pageSize, sortBy }); } - }, [pageIndex, pageSize, manualSortBy ? sortBy : null, onFetchData]); + }, [pageIndex, pageSize, sortBy, onFetchDataDebounced]); useUpdateEffect(() => { - onSelectedRowsChange && onSelectedRowsChange(selectedFlatRows); + saveInvoke(onSelectedRowsChange, selectedFlatRows); }, [selectedRowIds, onSelectedRowsChange]); // Renders table cell. @@ -177,40 +203,50 @@ export default function DataTable({ { // Use the row.canExpand and row.getToggleRowExpandedProps prop getter // to build the toggle for expanding a row - row.canExpand && expandable && index === expandToggleColumn && ( - - - - ) } + + + + + {cell.render('Cell')} ), - [expandable, expandToggleColumn], + [expandable, expandToggleColumn, expandColumnSpace], ); - const handleRowContextMenu = (cell, row) => (e) => { - if (typeof rowContextMenu === 'function') { - e.preventDefault(); - const tr = e.currentTarget.closest('.tr'); - tr.classList.add('is-context-menu-active'); + // Handle rendering row context menu. + const handleRowContextMenu = useMemo( + () => (cell, row) => (e) => { + if (typeof rowContextMenu === 'function') { + e.preventDefault(); + const tr = e.currentTarget.closest('.tr'); + tr.classList.add('is-context-menu-active'); - const DropdownEl = rowContextMenu(cell, row); + const DropdownEl = rowContextMenu(cell, row); - ContextMenu.show(DropdownEl, { left: e.clientX, top: e.clientY }, () => { - tr.classList.remove('is-context-menu-active'); - }); - } - }; + ContextMenu.show( + DropdownEl, + { left: e.clientX, top: e.clientY }, + () => { + tr.classList.remove('is-context-menu-active'); + }, + ); + } + }, + [rowContextMenu], + ); // Renders table row. const RenderRow = useCallback( @@ -221,9 +257,13 @@ export default function DataTable({ return (
@@ -243,7 +283,7 @@ export default function DataTable({
); }, - [prepareRow, rowClassNames, expandable, RenderCell, expandToggleColumn], + [prepareRow, rowClassNames, RenderCell, handleRowContextMenu], ); // Renders virtualize circle table rows. @@ -254,7 +294,7 @@ export default function DataTable({ }, [RenderRow, rows], ); - + // Renders page with multi-rows. const RenderPage = useCallback( ({ style, index } = {}) => { return page.map((row, index) => RenderRow({ row })); @@ -284,6 +324,21 @@ export default function DataTable({ RenderPage, ]); + const handlePageChange = useCallback( + (currentPage) => { + gotoPage(currentPage - 1); + }, + [gotoPage], + ); + + const handlePageSizeChange = useCallback( + (pageSize, currentPage) => { + gotoPage(0); + setPageSize(pageSize); + }, + [gotoPage, setPageSize], + ); + return (
- {expandable && index + 1 === expandToggleColumn && ( + - )} +
{column.render('Header')} - {column.isSorted && ( + - )} +
{column.canResize && ( @@ -358,37 +417,36 @@ export default function DataTable({
- {RenderTBody()} + + +
+ +
+
- -
-
{noResults}
-
-
+ + {RenderTBody()} + + +
+
{noResults}
+
+
+
+
- - -
- -
-
- + { - gotoPage(currentPage - 1); - }} - onPageSizeChange={(pageSize, currentPage) => { - gotoPage(currentPage - 1); - setPageSize(pageSize); - }} + onPageChange={handlePageChange} + onPageSizeChange={handlePageSizeChange} /> diff --git a/client/src/containers/Accounting/ManualJournalsDataTable.js b/client/src/containers/Accounting/ManualJournalsDataTable.js index 52e5523ca..484a4d545 100644 --- a/client/src/containers/Accounting/ManualJournalsDataTable.js +++ b/client/src/containers/Accounting/ManualJournalsDataTable.js @@ -15,13 +15,22 @@ import { withRouter, useParams } from 'react-router-dom'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { DataTable, If, Money, Choose, Icon } from 'components'; -import { compose } from 'utils'; +import { + DataTable, + If, + Money, + Choose, + Icon, + LoadingIndicator, +} from 'components'; +import { useIsValuePassed } from 'hooks'; import withDialogActions from 'containers/Dialog/withDialogActions'; import withManualJournals from 'containers/Accounting/withManualJournals'; import withManualJournalsActions from 'containers/Accounting/withManualJournalsActions'; +import { compose, saveInvoke } from 'utils'; + /** * Status column accessor. */ @@ -68,44 +77,36 @@ function ManualJournalsDataTable({ manualJournalsPagination, manualJournalsTableQuery, - onFetchData, + // #withManualJournalsActions + addManualJournalsTableQueries, + + // #ownProps onEditJournal, onDeleteJournal, onPublishJournal, onSelectedRowsChange, }) { - const [isMounted, setIsMounted] = useState(false); const { custom_view_id: customViewId } = useParams(); - const { formatMessage } = useIntl(); - - useEffect(() => { - setIsMounted(false); - }, [customViewId]); - - useEffect(() => { - if (!manualJournalsLoading) { - setIsMounted(true); - } - }, [manualJournalsLoading, setIsMounted]); + const isLoadedBefore = useIsValuePassed(manualJournalsLoading, false); const handlePublishJournal = useCallback( (journal) => () => { - onPublishJournal && onPublishJournal(journal); + saveInvoke(onPublishJournal, journal); }, [onPublishJournal], ); const handleEditJournal = useCallback( (journal) => () => { - onEditJournal && onEditJournal(journal); + saveInvoke(onEditJournal, journal); }, [onEditJournal], ); const handleDeleteJournal = useCallback( (journal) => () => { - onDeleteJournal && onDeleteJournal(journal); + saveInvoke(onDeleteJournal, journal); }, [onDeleteJournal], ); @@ -115,7 +116,8 @@ function ManualJournalsDataTable({ } - text={formatMessage({ id: 'view_details' })} /> + text={formatMessage({ id: 'view_details' })} + /> StatusAccessor(row), + accessor: (row) => StatusAccessor(row), width: 95, className: 'status', }, @@ -221,46 +223,52 @@ function ManualJournalsDataTable({ ); const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); + ({ pageIndex, pageSize, sortBy }) => { + addManualJournalsTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); }, - [onFetchData], + [addManualJournalsTableQueries], ); const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); - const selectionColumn = useMemo( - () => ({ - minWidth: 40, - width: 40, - maxWidth: 40, - }), - [], - ); return ( - + + + ); } diff --git a/client/src/containers/Accounting/ManualJournalsList.js b/client/src/containers/Accounting/ManualJournalsList.js index abeece894..b9e3f6191 100644 --- a/client/src/containers/Accounting/ManualJournalsList.js +++ b/client/src/containers/Accounting/ManualJournalsList.js @@ -161,8 +161,6 @@ function ManualJournalsTable({ const handleFetchData = useCallback( ({ pageIndex, pageSize, sortBy }) => { const page = pageIndex + 1; - // addQuery('page_size', pageSize); - // addQuery('page', page); addManualJournalsTableQueries({ ...(sortBy.length > 0 @@ -224,7 +222,6 @@ function ManualJournalsTable({ ({ }), addManualJournalsTableQueries: (queries) => dispatch({ type: t.MANUAL_JOURNALS_TABLE_QUERIES_ADD, - queries, + payload: { queries }, }), setJournalNumberChanged: (isChanged) => dispatch({ type: t.MANUAL_JOURNAL_NUMBER_CHANGED, diff --git a/client/src/containers/Customers/CustomerTable.js b/client/src/containers/Customers/CustomerTable.js index 0bcc12e01..dbe4226c6 100644 --- a/client/src/containers/Customers/CustomerTable.js +++ b/client/src/containers/Customers/CustomerTable.js @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useMemo } from 'react'; +import React, { useRef, useEffect, useCallback, useMemo } from 'react'; import { Button, Popover, @@ -8,14 +8,15 @@ import { Position, Intent, } from '@blueprintjs/core'; - import { FormattedMessage as T, useIntl } from 'react-intl'; -import { useUpdateEffect } from 'hooks'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { DataTable, Icon, Money } from 'components'; import withCustomers from './withCustomers'; +import withCustomersActions from './withCustomersActions'; + import { compose, firstLettersArgs, saveInvoke } from 'utils'; const AvatarCell = (row) => { @@ -27,6 +28,10 @@ const CustomerTable = ({ customers, customersLoading, customerPagination, + customersTableQuery, + + // #withCustomersActions + addCustomersTableQueries, //#OwnProps loading, @@ -36,13 +41,7 @@ const CustomerTable = ({ onSelectedRowsChange, }) => { const { formatMessage } = useIntl(); - const [initialMount, setInitialMount] = useState(false); - - useUpdateEffect(() => { - if (!customersLoading) { - setInitialMount(true); - } - }, [customersLoading, setInitialMount]); + const isLoadedBefore = useIsValuePassed(loading, false); // Customers actions list. const renderContextMenu = useMemo( @@ -94,6 +93,7 @@ const CustomerTable = ({ [onDeleteCustomer, onEditCustomer, renderContextMenu], ); + // Table columns. const columns = useMemo( () => [ { @@ -150,19 +150,23 @@ const CustomerTable = ({ [formatMessage, renderActionsCell], ); - const selectionColumn = useMemo( - () => ({ - minWidth: 42, - width: 42, - maxWidth: 42, - }), - [], + // Handle fetch data table. + const handleFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + addCustomersTableQueries({ + page: pageIndex + 1, + page_size: pageSize, + ...(sortBy.length > 0 + ? { + column_sort_order: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + }); + }, + [addCustomersTableQueries], ); - const handleFetchDate = useCallback((...args) => { - onFetchData && onFetchData(...args); - }); - const handleSelectedRowsChange = useCallback( (selectedRows) => { onSelectedRowsChange && @@ -179,32 +183,47 @@ const CustomerTable = ({ }); return ( - + ); }; export default compose( - withCustomers(({ customers, customersLoading, customerPagination }) => ({ - customers, - customersLoading, - customerPagination, - })), + withCustomers( + ({ + customers, + customersLoading, + customerPagination, + customersTableQuery, + }) => ({ + customers, + customersLoading, + customerPagination, + customersTableQuery, + }), + ), + withCustomersActions, )(CustomerTable); diff --git a/client/src/containers/Customers/CustomersList.js b/client/src/containers/Customers/CustomersList.js index c901c3704..6b133f8f0 100644 --- a/client/src/containers/Customers/CustomersList.js +++ b/client/src/containers/Customers/CustomersList.js @@ -52,15 +52,12 @@ function CustomersList({ useEffect(() => { changePageTitle(formatMessage({ id: 'customers_list' })); - }, [changePageTitle]); + }, [changePageTitle, formatMessage]); // Fetch customers resource views and fields. - // const fetchHook = useQuery('resource-customers', () => { - // return Promise.all([ - // requestFetchResourceViews('customers'), - // requestFetchResourceFields('customers'), - // ]); - // }); + // const fetchResourceViews = useQuery(['resource-views', 'customers'], + // () => requestFetchResourceViews('customers') + // ); const fetchCustomers = useQuery( ['customers-table', customersTableQuery], @@ -116,22 +113,6 @@ function CustomersList({ }); }, [requestDeleteCustomer, deleteCustomer, formatMessage]); - // Handle fetch data table. - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - addCustomersTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_order: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - }); - fetchCustomers.refetch(); - }, - [fetchCustomers, addCustomersTableQueries], - ); - // Handle selected rows change. const handleSelectedRowsChange = useCallback( (customer) => { @@ -154,9 +135,9 @@ function CustomersList({ // Handle filter change to re-fetch the items. const handleFilterChanged = useCallback( (filterConditions) => { - addCustomersTableQueries({ - filter_roles: filterConditions || '', - }); + // addCustomersTableQueries({ + // filter_roles: filterConditions || '', + // }); }, [addCustomersTableQueries], ); @@ -210,7 +191,6 @@ function CustomersList({ loading={fetchCustomers.isFetching} onDeleteCustomer={handleDeleteCustomer} onEditCustomer={handleEditCustomer} - onfetchData={handleFetchData} onSelectedRowsChange={handleSelectedRowsChange} /> @@ -258,5 +238,6 @@ export default compose( withResourceActions, withCustomersActions, withDashboardActions, + withViewsActions, withCustomers(({ customersTableQuery }) => ({ customersTableQuery })), )(CustomersList); diff --git a/client/src/containers/Customers/CustomersViewsTabs.js b/client/src/containers/Customers/CustomersViewsTabs.js index a71f2d91a..88288308b 100644 --- a/client/src/containers/Customers/CustomersViewsTabs.js +++ b/client/src/containers/Customers/CustomersViewsTabs.js @@ -39,9 +39,9 @@ function CustomersViewsTabs({ useEffect(() => { setTopbarEditView(customViewId); changePageSubtitle(customViewId && viewItem ? viewItem.name : ''); - addCustomersTableQueries({ - custom_view_id: customViewId, - }); + // addCustomersTableQueries({ + // custom_view_id: customViewId, + // }); return () => { setTopbarEditView(null); changePageSubtitle(''); diff --git a/client/src/containers/Customers/withCustomersActions.js b/client/src/containers/Customers/withCustomersActions.js index ae3808859..c42169ce3 100644 --- a/client/src/containers/Customers/withCustomersActions.js +++ b/client/src/containers/Customers/withCustomersActions.js @@ -19,7 +19,7 @@ export const mapDispatchToProps = (dispatch) => ({ addCustomersTableQueries: (queries) => dispatch({ type: t.CUSTOMERS_TABLE_QUERIES_ADD, - queries, + payload: { queries } }), }); diff --git a/client/src/containers/Expenses/ExpenseDataTable.js b/client/src/containers/Expenses/ExpenseDataTable.js index 82643c1d9..0abc80b35 100644 --- a/client/src/containers/Expenses/ExpenseDataTable.js +++ b/client/src/containers/Expenses/ExpenseDataTable.js @@ -17,8 +17,8 @@ import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; import Icon from 'components/Icon'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { If, Money } from 'components'; @@ -32,11 +32,15 @@ import withExpensesActions from 'containers/Expenses/withExpensesActions'; import withCurrentView from 'containers/Views/withCurrentView'; function ExpensesDataTable({ - //#withExpenes + // #withExpenes expensesCurrentPage, expensesLoading, expensesPagination, - + expensesTableQuery, + + // #withExpensesActions + addExpensesTableQueries, + // #withDashboardActions changeCurrentView, changePageSubtitle, @@ -46,27 +50,16 @@ function ExpensesDataTable({ viewMeta, // #ownProps - loading, - onFetchData, onEditExpense, onDeleteExpense, onPublishExpense, onSelectedRowsChange, }) { const { custom_view_id: customViewId } = useParams(); - const [initialMount, setInitialMount] = useState(false); + const isLoadedBefore = useIsValuePassed(expensesLoading, false); + const { formatMessage } = useIntl(); - useEffect(()=>{ - setInitialMount(false) - },[customViewId]) - - useUpdateEffect(() => { - if (!expensesLoading) { - setInitialMount(true); - } - }, [expensesLoading, setInitialMount]); - useEffect(() => { if (customViewId) { changeCurrentView(customViewId); @@ -81,23 +74,40 @@ function ExpensesDataTable({ viewMeta, ]); + // Handle fetch data of manual jouranls datatable. + const handleFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + addExpensesTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); + }, + [addExpensesTableQueries], + ); + const handlePublishExpense = useCallback( (expense) => () => { - onPublishExpense && onPublishExpense(expense); + saveInvoke(onPublishExpense, expense); }, [onPublishExpense], ); const handleEditExpense = useCallback( (expense) => () => { - onEditExpense && onEditExpense(expense); + saveInvoke(onEditExpense, expense); }, [onEditExpense], ); const handleDeleteExpense = useCallback( (expense) => () => { - onDeleteExpense && onDeleteExpense(expense); + saveInvoke(onDeleteExpense, expense); }, [onDeleteExpense], ); @@ -107,7 +117,8 @@ function ExpensesDataTable({ } - text={formatMessage({ id: 'view_details' })} /> + text={formatMessage({ id: 'view_details' })} + /> { - onFetchData && onFetchData(...args); - }, - [onFetchData], - ); - const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); return ( -
- - - -
+ + + ); } @@ -289,10 +297,18 @@ export default compose( withDialogActions, withDashboardActions, withExpensesActions, - withExpenses(({ expensesCurrentPage, expensesLoading, expensesPagination }) => ({ - expensesCurrentPage, - expensesLoading, - expensesPagination, - })), + withExpenses( + ({ + expensesCurrentPage, + expensesLoading, + expensesPagination, + expensesTableQuery, + }) => ({ + expensesCurrentPage, + expensesLoading, + expensesPagination, + expensesTableQuery, + }), + ), withViewDetails(), )(ExpensesDataTable); diff --git a/client/src/containers/Expenses/ExpensesList.js b/client/src/containers/Expenses/ExpensesList.js index b2d41abf8..153c2f721 100644 --- a/client/src/containers/Expenses/ExpensesList.js +++ b/client/src/containers/Expenses/ExpensesList.js @@ -137,25 +137,6 @@ function ExpensesList({ // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, []); - // Handle fetch data of manual jouranls datatable. - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addExpensesTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addExpensesTableQueries], - ); - // const fetchExpenses = useQuery(['expenses-table', expensesTableQuery], () => // requestFetchExpensesTable(), // ); @@ -217,9 +198,7 @@ function ExpensesList({ ({ addExpensesTableQueries: (queries) => dispatch({ type: t.EXPENSES_TABLE_QUERIES_ADD, - queries, + payload: { queries }, }), }); diff --git a/client/src/containers/Items/ItemFormBody.js b/client/src/containers/Items/ItemFormBody.js index 71699c721..3241258cf 100644 --- a/client/src/containers/Items/ItemFormBody.js +++ b/client/src/containers/Items/ItemFormBody.js @@ -101,7 +101,7 @@ function ItemFormBody({ accountsList }) { {/*------------- Sellable checkbox ------------- */} - {({ field, field: { value }, meta: { error, touched } }) => ( + {({ form, field: { value, onChange }, meta: { error, touched } }) => ( } checked={value} - {...field} + onChange={onChange} /> )} diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js index 30e8b675a..4f073b292 100644 --- a/client/src/containers/Items/ItemsDataTable.js +++ b/client/src/containers/Items/ItemsDataTable.js @@ -10,34 +10,46 @@ import { Tag, } from '@blueprintjs/core'; import { FormattedMessage as T, useIntl } from 'react-intl'; -import { Icon, DataTable, Money, If, Choose } from 'components'; +import { Icon, DataTable, Money } from 'components'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import withItems from 'containers/Items/withItems'; -import { compose } from 'utils'; - - -const ItemsDataTable = ({ - loading, +import withItemsActions from 'containers/Items/withItemsActions'; +import { compose, saveInvoke } from 'utils'; +function ItemsDataTable({ // #withItems itemsTableLoading, itemsCurrentPage, + itemsTableQuery, + + // #withItemsActions + addItemsTableQueries, // props onEditItem, onDeleteItem, - onFetchData, onSelectedRowsChange, -}) => { +}) { const { formatMessage } = useIntl(); - const [initialMount, setInitialMount] = useState(false); + const isLoadedBefore = useIsValuePassed(itemsTableLoading, false); - useEffect(() => { - if (!itemsTableLoading) { - setInitialMount(true); - } - }, [itemsTableLoading, setInitialMount]); + const handleFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + addItemsTableQueries({ + page_size: pageSize, + page: pageIndex + 1, + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + }); + }, + [addItemsTableQueries], + ); const handleEditItem = useCallback( (item) => () => { @@ -46,7 +58,6 @@ const ItemsDataTable = ({ [onEditItem], ); - // const handleDeleteItem = (item) => () => { onDeleteItem(item); }; const handleDeleteItem = useCallback( (item) => () => { onDeleteItem(item); @@ -158,48 +169,49 @@ const ItemsDataTable = ({ [actionMenuList, formatMessage], ); - const selectionColumn = useMemo( - () => ({ - minWidth: 42, - width: 42, - maxWidth: 42, - }), - [], - ); - - const handleFetchData = useCallback((...args) => { - onFetchData && onFetchData(...args); - }, []); - + // Handle selected row change. const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); + return ( - + ); }; export default compose( - withItems(({ itemsCurrentPage, itemsTableLoading }) => ({ + withItems(({ itemsCurrentPage, itemsTableLoading, itemsTableQuery }) => ({ itemsCurrentPage, itemsTableLoading, + itemsTableQuery, })), + withItemsActions, )(ItemsDataTable); diff --git a/client/src/containers/Items/ItemsList.js b/client/src/containers/Items/ItemsList.js index 6f034cf9b..387d1bba4 100644 --- a/client/src/containers/Items/ItemsList.js +++ b/client/src/containers/Items/ItemsList.js @@ -43,7 +43,6 @@ function ItemsList({ }) { const [deleteItem, setDeleteItem] = useState(false); const [selectedRows, setSelectedRows] = useState([]); - const [tableLoading, setTableLoading] = useState(false); const [bulkDelete, setBulkDelete] = useState(false); const { formatMessage } = useIntl(); @@ -53,16 +52,19 @@ function ItemsList({ changePageTitle(formatMessage({ id: 'items_list' })); }, [changePageTitle]); + // Handle fetching the resource views. const fetchResourceViews = useQuery( ['resource-views', 'items'], (key, resourceName) => requestFetchResourceViews(resourceName), ); + // Handle fetching the resource fields. const fetchResourceFields = useQuery( ['resource-fields', 'items'], (key, resourceName) => requestFetchResourceFields(resourceName), ); + // Handle fetching the items table based on the given query. const fetchItems = useQuery(['items-table', itemsTableQuery], () => requestFetchItems({}), ); @@ -112,18 +114,7 @@ function ItemsList({ const handleFetchData = useCallback( ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addItemsTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); + }, [addItemsTableQueries], ); @@ -135,23 +126,9 @@ function ItemsList({ filter_roles: filterConditions || '', }); }, - [fetchItems], + [addItemsTableQueries], ); - // Handle custom view change to re-fetch the items. - const handleCustomViewChanged = useCallback( - (customViewId) => { - setTableLoading(true); - }, - [fetchItems], - ); - - useEffect(() => { - if (tableLoading && !fetchItems.isFetching) { - setTableLoading(false); - } - }, [tableLoading, fetchItems.isFetching]); - // Handle selected rows change. const handleSelectedRowsChange = useCallback( (accounts) => { @@ -213,16 +190,13 @@ function ItemsList({ exact={true} path={['/items/:custom_view_id/custom_view', '/items']} > - + - } confirmButtonText={} diff --git a/client/src/containers/Items/withItems.js b/client/src/containers/Items/withItems.js index 8286faf54..ead8096ba 100644 --- a/client/src/containers/Items/withItems.js +++ b/client/src/containers/Items/withItems.js @@ -10,6 +10,7 @@ import { export default (mapState) => { const mapStateToProps = (state, props) => { const viewPages = getViewPages(state.items.views, state.items.currentViewId); + const mapped = { itemsViews: getResourceViews(state, props, 'items'), itemsCurrentPage: getCurrentPageResults( diff --git a/client/src/containers/Items/withItemsActions.js b/client/src/containers/Items/withItemsActions.js index eb95e8cff..f117728c4 100644 --- a/client/src/containers/Items/withItemsActions.js +++ b/client/src/containers/Items/withItemsActions.js @@ -1,11 +1,11 @@ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import { fetchItems, fetchItem, deleteItem, submitItem, editItem, - deleteBulkItems + deleteBulkItems, } from 'store/items/items.actions'; import t from 'store/types'; @@ -13,26 +13,36 @@ export const mapDispatchToProps = (dispatch) => ({ requestFetchItems: (query) => dispatch(fetchItems({ query })), requestFetchItem: (id) => dispatch(fetchItem({ id })), requestDeleteItem: (id) => dispatch(deleteItem({ id })), - requestDeleteBulkItems:(ids)=>dispatch(deleteBulkItems({ids})), + requestDeleteBulkItems: (ids) => dispatch(deleteBulkItems({ ids })), requestSubmitItem: (form) => dispatch(submitItem({ form })), - requestEditItem:(id,form) => dispatch(editItem({id,form})), - addBulkActionItem: (id) => dispatch({ - type: t.ITEM_BULK_ACTION_ADD, itemId: id - }), - removeBulkActionItem: (id) => dispatch({ - type: t.ITEM_BULK_ACTION_REMOVE, itemId: id, - }), - setItemsTableQuery: (key, value) => dispatch({ - type: t.ITEMS_TABLE_QUERY_SET, key, value, - }), - addItemsTableQueries: (queries) => dispatch({ - type: t.ITEMS_TABLE_QUERIES_ADD, queries, - }), + requestEditItem: (id, form) => dispatch(editItem({ id, form })), + addBulkActionItem: (id) => + dispatch({ + type: t.ITEM_BULK_ACTION_ADD, + itemId: id, + }), + removeBulkActionItem: (id) => + dispatch({ + type: t.ITEM_BULK_ACTION_REMOVE, + itemId: id, + }), + setItemsTableQuery: (key, value) => + dispatch({ + type: t.ITEMS_TABLE_QUERY_SET, + key, + value, + }), + addItemsTableQueries: (queries) => + dispatch({ + type: t.ITEMS_TABLE_QUERIES_ADD, + payload: { queries }, + }), - changeItemsCurrentView: (id) => dispatch({ - type: t.ITEMS_SET_CURRENT_VIEW, - currentViewId: parseInt(id, 10), - }), + changeItemsCurrentView: (id) => + dispatch({ + type: t.ITEMS_SET_CURRENT_VIEW, + currentViewId: parseInt(id, 10), + }), }); export default connect(null, mapDispatchToProps); diff --git a/client/src/containers/Purchases/Bill/BillList.js b/client/src/containers/Purchases/Bill/BillList.js index 158c9a61b..35dbcfdd5 100644 --- a/client/src/containers/Purchases/Bill/BillList.js +++ b/client/src/containers/Purchases/Bill/BillList.js @@ -90,23 +90,7 @@ function BillList({ history.push(`/bills/${bill.id}/edit`); }); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addBillsTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addBillsTableQueries], - ); + // Handle selected rows change. const handleSelectedRowsChange = useCallback( @@ -141,9 +125,7 @@ function BillList({ diff --git a/client/src/containers/Purchases/Bill/BillsDataTable.js b/client/src/containers/Purchases/Bill/BillsDataTable.js index 9c6fa993a..bb73b2574 100644 --- a/client/src/containers/Purchases/Bill/BillsDataTable.js +++ b/client/src/containers/Purchases/Bill/BillsDataTable.js @@ -16,8 +16,8 @@ import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; import Icon from 'components/Icon'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import DataTable from 'components/DataTable'; @@ -41,29 +41,22 @@ function BillsDataTable({ changePageSubtitle, setTopbarEditView, + // #withBillsActions + addBillsTableQueries, + // #withView viewMeta, - //#OwnProps + // #ownProps loading, onFetchData, onEditBill, onDeleteBill, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); const { custom_view_id: customViewId } = useParams(); const { formatMessage } = useIntl(); - - useEffect(() => { - setInitialMount(false); - }, [customViewId]); - - useUpdateEffect(() => { - if (!billsLoading) { - setInitialMount(true); - } - }, [billsLoading, setInitialMount]); + const isLoadedBefore = useIsValuePassed(billsLoading, false); useEffect(() => { if (customViewId) { @@ -79,16 +72,34 @@ function BillsDataTable({ viewMeta, ]); + const handleFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + const page = pageIndex + 1; + + addBillsTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page, + }); + }, + [addBillsTableQueries], + ); + const handleEditBill = useCallback( (_bill) => () => { - onEditBill && onEditBill(_bill); + saveInvoke(onEditBill, _bill); }, [onEditBill], ); const handleDeleteBill = useCallback( (_bill) => () => { - onDeleteBill && onDeleteBill(_bill); + saveInvoke(onDeleteBill, _bill); }, [onDeleteBill], ); @@ -147,7 +158,6 @@ function BillsDataTable({ width: 140, className: 'bill_number', }, - { id: 'due_date', Header: formatMessage({ id: 'due_date' }), @@ -195,41 +205,34 @@ function BillsDataTable({ [actionMenuList, formatMessage], ); - const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); - }, - [onFetchData], - ); const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); return ( -
- - - -
+ + + ); } @@ -239,10 +242,18 @@ export default compose( withDialogActions, withDashboardActions, withBillActions, - withBills(({ billsCurrentPage, billsLoading, billsPageination }) => ({ - billsCurrentPage, - billsLoading, - billsPageination, - })), + withBills( + ({ + billsCurrentPage, + billsLoading, + billsPageination, + billsTableQuery, + }) => ({ + billsCurrentPage, + billsLoading, + billsPageination, + billsTableQuery, + }), + ), withViewDetails(), )(BillsDataTable); diff --git a/client/src/containers/Purchases/Bill/withBillActions.js b/client/src/containers/Purchases/Bill/withBillActions.js index 2fb0c9710..0db005614 100644 --- a/client/src/containers/Purchases/Bill/withBillActions.js +++ b/client/src/containers/Purchases/Bill/withBillActions.js @@ -27,7 +27,7 @@ const mapDispatchToProps = (dispatch) => ({ addBillsTableQueries: (queries) => dispatch({ type: t.BILLS_TABLE_QUERIES_ADD, - queries, + payload: { queries } }), setBillNumberChanged: (isChanged) => dispatch({ diff --git a/client/src/containers/Purchases/PaymentMades/PaymentMadeDataTable.js b/client/src/containers/Purchases/PaymentMades/PaymentMadeDataTable.js index f0a5b150f..edb49e75c 100644 --- a/client/src/containers/Purchases/PaymentMades/PaymentMadeDataTable.js +++ b/client/src/containers/Purchases/PaymentMades/PaymentMadeDataTable.js @@ -1,81 +1,58 @@ -import React, { useEffect, useCallback, useState, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Intent, Button, - Classes, Popover, Menu, MenuItem, MenuDivider, Position, } from '@blueprintjs/core'; -import { useParams } from 'react-router-dom'; import { withRouter } from 'react-router'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { DataTable, Money, Icon } from 'components'; -import withDialogActions from 'containers/Dialog/withDialogActions'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; -import withViewDetails from 'containers/Views/withViewDetails'; - import withPaymentMade from './withPaymentMade'; import withPaymentMadeActions from './withPaymentMadeActions'; import withCurrentView from 'containers/Views/withCurrentView'; +/** + * Payment made datatable transactions. + */ function PaymentMadeDataTable({ - //#withPaymentMades + // #withPaymentMades paymentMadeCurrentPage, paymentMadePageination, - paymentMadeLoading, - paymentMadeItems, + paymentMadesLoading, + paymentMadeTableQuery, - // #withDashboardActions - changeCurrentView, - changePageSubtitle, - setTopbarEditView, + // #withPaymentMadeActions + addPaymentMadesTableQueries, - // #withView - viewMeta, - - //#OwnProps - loading, - onFetchData, + // #ownProps onEditPaymentMade, onDeletePaymentMade, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); - const { custom_view_id: customViewId } = useParams(); + const isLoaded = useIsValuePassed(paymentMadesLoading, false); const { formatMessage } = useIntl(); - useEffect(() => { - setInitialMount(false); - }, [customViewId]); - - useUpdateEffect(() => { - if (!paymentMadeLoading) { - setInitialMount(true); - } - }, [paymentMadeLoading, setInitialMount]); - - - const handleEditPaymentMade = useCallback( (paymentMade) => () => { - onEditPaymentMade && onEditPaymentMade(paymentMade); + saveInvoke(onEditPaymentMade, paymentMade); }, [onEditPaymentMade], ); const handleDeletePaymentMade = useCallback( (paymentMade) => () => { - onDeletePaymentMade && onDeletePaymentMade(paymentMade); + saveInvoke(onDeletePaymentMade, paymentMade); }, [onDeletePaymentMade], ); @@ -89,7 +66,7 @@ function PaymentMadeDataTable({ /> } + icon={} text={formatMessage({ id: 'edit_payment_made' })} onClick={handleEditPaymentMade(paymentMade)} /> @@ -176,59 +153,69 @@ function PaymentMadeDataTable({ ); const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); + ({ pageIndex, pageSize, sortBy }) => { + addPaymentMadesTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); }, - [onFetchData], + [addPaymentMadesTableQueries], ); + const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); return ( -
- - - -
+ + + ); } export default compose( withRouter, withCurrentView, - withDialogActions, - withDashboardActions, withPaymentMadeActions, withPaymentMade( ({ paymentMadeCurrentPage, - paymentMadeLoading, + paymentMadesLoading, paymentMadePageination, + paymentMadeTableQuery, }) => ({ paymentMadeCurrentPage, - paymentMadeLoading, + paymentMadesLoading, paymentMadePageination, + paymentMadeTableQuery, }), ), - withViewDetails(), )(PaymentMadeDataTable); diff --git a/client/src/containers/Purchases/PaymentMades/PaymentMadeList.js b/client/src/containers/Purchases/PaymentMades/PaymentMadeList.js index f8718205a..a7986f4d8 100644 --- a/client/src/containers/Purchases/PaymentMades/PaymentMadeList.js +++ b/client/src/containers/Purchases/PaymentMades/PaymentMadeList.js @@ -95,24 +95,6 @@ function PaymentMadeList({ selectedRows, ]); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addPaymentMadesTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addPaymentMadesTableQueries], - ); - // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, [fetchPaymentMades]); @@ -145,14 +127,13 @@ function PaymentMadeList({ >
+ } confirmButtonText={} diff --git a/client/src/containers/Purchases/PaymentMades/withPaymentMadeActions.js b/client/src/containers/Purchases/PaymentMades/withPaymentMadeActions.js index 626161f3e..9d21d1988 100644 --- a/client/src/containers/Purchases/PaymentMades/withPaymentMadeActions.js +++ b/client/src/containers/Purchases/PaymentMades/withPaymentMadeActions.js @@ -27,8 +27,8 @@ const mapDispatchToProps = (dispatch) => ({ addPaymentMadesTableQueries: (queries) => dispatch({ - type: t.PAYMENT_MADE_TABLE_QUERIES_ADD, - queries, + type: t.PAYMENT_MADES_TABLE_QUERIES_ADD, + payload: { queries }, }), setPaymentNumberChange: (isChanged) => dispatch({ diff --git a/client/src/containers/Sales/Estimate/EstimateList.js b/client/src/containers/Sales/Estimate/EstimateList.js index ba96eca58..feab8e7c7 100644 --- a/client/src/containers/Sales/Estimate/EstimateList.js +++ b/client/src/containers/Sales/Estimate/EstimateList.js @@ -29,7 +29,7 @@ function EstimateList({ requestFetchResourceFields, // #withEstimate - estimateTableQuery, + estimatesTableQuery, estimateViews, //#withEistimateActions @@ -52,7 +52,7 @@ function EstimateList({ // (key, resourceName) => requestFetchResourceFields(resourceName), // ); - const fetchEstimate = useQuery(['estimates-table', estimateTableQuery], () => + const fetchEstimate = useQuery(['estimates-table', estimatesTableQuery], () => requestFetchEstimatesTable(), ); @@ -100,23 +100,6 @@ function EstimateList({ }, [history], ); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addEstimatesTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addEstimatesTableQueries], - ); const handleSelectedRowsChange = useCallback( (estimate) => { @@ -142,14 +125,13 @@ function EstimateList({ > + } confirmButtonText={} @@ -173,8 +155,8 @@ export default compose( withEstimateActions, withDashboardActions, withViewsActions, - withEstimates(({ estimateTableQuery, estimateViews }) => ({ - estimateTableQuery, + withEstimates(({ estimatesTableQuery, estimateViews }) => ({ + estimatesTableQuery, estimateViews, })), )(EstimateList); diff --git a/client/src/containers/Sales/Estimate/EstimatesDataTable.js b/client/src/containers/Sales/Estimate/EstimatesDataTable.js index 43ce0ba9c..543288541 100644 --- a/client/src/containers/Sales/Estimate/EstimatesDataTable.js +++ b/client/src/containers/Sales/Estimate/EstimatesDataTable.js @@ -8,85 +8,48 @@ import { MenuDivider, Position, } from '@blueprintjs/core'; -import { useParams } from 'react-router-dom'; import { withRouter } from 'react-router'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { DataTable, Money, Icon } from 'components'; -import withDialogActions from 'containers/Dialog/withDialogActions'; -import withDashboardActions from 'containers/Dashboard/withDashboardActions'; -import withViewDetails from 'containers/Views/withViewDetails'; - import withEstimates from './withEstimates'; import withEstimateActions from './withEstimateActions'; -import withCurrentView from 'containers/Views/withCurrentView'; +// Estimates transactions datatable. function EstimatesDataTable({ - //#withEitimates + // #withEstimates estimatesCurrentPage, estimatesLoading, estimatesPageination, - estimateItems, + estimatesTableQuery, - // #withDashboardActions - changeCurrentView, - changePageSubtitle, - setTopbarEditView, + // #withEstimatesActions + addEstimatesTableQueries, - // #withView - viewMeta, - - //#OwnProps - loading, - onFetchData, + // #ownProps onEditEstimate, onDeleteEstimate, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); - const { custom_view_id: customViewId } = useParams(); const { formatMessage } = useIntl(); - - useEffect(() => { - setInitialMount(false); - }, []); - - useUpdateEffect(() => { - if (!estimatesLoading) { - setInitialMount(true); - } - }, [estimatesLoading, setInitialMount]); - - useEffect(() => { - if (customViewId) { - changeCurrentView(customViewId); - setTopbarEditView(customViewId); - } - changePageSubtitle(customViewId && viewMeta ? viewMeta.name : ''); - }, [ - customViewId, - changeCurrentView, - changePageSubtitle, - setTopbarEditView, - viewMeta, - ]); + const isLoaded = useIsValuePassed(estimatesLoading, false); const handleEditEstimate = useCallback( (estimate) => () => { - onEditEstimate && onEditEstimate(estimate); + saveInvoke(onEditEstimate, estimate); }, [onEditEstimate], ); const handleDeleteEstimate = useCallback( (estimate) => () => { - onDeleteEstimate && onDeleteEstimate(estimate); + saveInvoke(onDeleteEstimate, estimate); }, [onDeleteEstimate], ); @@ -185,74 +148,64 @@ function EstimatesDataTable({ ], [actionMenuList, formatMessage], ); - const selectionColumn = useMemo( - () => ({ - minWidth: 40, - width: 40, - maxWidth: 40, - }), - [], - ); - const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); + const handleFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + const page = pageIndex + 1; + + addEstimatesTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page, + }); }, - [onFetchData], + [addEstimatesTableQueries], ); const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); - console.log(estimatesCurrentPage, 'estimatesCurrentPage'); - console.log(estimateItems, 'estimateItems'); return ( -
- - - -
+ + + ); } export default compose( - withRouter, - withCurrentView, - withDialogActions, - withDashboardActions, withEstimateActions, withEstimates( - ({ + ({ estimatesCurrentPage, estimatesLoading, estimatesPageination, estimatesTableQuery }) => ({ estimatesCurrentPage, estimatesLoading, estimatesPageination, - estimateItems, - }) => ({ - estimatesCurrentPage, - estimatesLoading, - estimatesPageination, - estimateItems, + estimatesTableQuery }), ), - withViewDetails(), )(EstimatesDataTable); diff --git a/client/src/containers/Sales/Estimate/withEstimateActions.js b/client/src/containers/Sales/Estimate/withEstimateActions.js index 411437256..7145e1a23 100644 --- a/client/src/containers/Sales/Estimate/withEstimateActions.js +++ b/client/src/containers/Sales/Estimate/withEstimateActions.js @@ -25,7 +25,7 @@ const mapDipatchToProps = (dispatch) => ({ addEstimatesTableQueries: (queries) => dispatch({ type: t.ESTIMATES_TABLE_QUERIES_ADD, - queries, + payload: { queries }, }), setEstimateNumberChanged: (isChanged) => dispatch({ diff --git a/client/src/containers/Sales/Estimate/withEstimates.js b/client/src/containers/Sales/Estimate/withEstimates.js index 9d637e4b6..b16cae887 100644 --- a/client/src/containers/Sales/Estimate/withEstimates.js +++ b/client/src/containers/Sales/Estimate/withEstimates.js @@ -18,8 +18,8 @@ export default (mapState) => { estimatesCurrentPage: getEstimatesItems(state, props, query), estimateViews: getResourceViews(state, props, 'sales_estimates'), estimateItems: state.salesEstimates.items, - estimateTableQuery: query, - + + estimatesTableQuery: query, estimatesPageination: getEstimatesPaginationMeta(state, props, query), estimatesLoading: state.salesEstimates.loading, diff --git a/client/src/containers/Sales/Invoice/InvoiceList.js b/client/src/containers/Sales/Invoice/InvoiceList.js index da94dff50..9f88b427f 100644 --- a/client/src/containers/Sales/Invoice/InvoiceList.js +++ b/client/src/containers/Sales/Invoice/InvoiceList.js @@ -20,6 +20,9 @@ import withViewsActions from 'containers/Views/withViewsActions'; import { compose } from 'utils'; +/** + * Invoices list. + */ function InvoiceList({ // #withDashboardActions changePageTitle, @@ -94,26 +97,8 @@ function InvoiceList({ selectedRows, ]); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addInvoiceTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addInvoiceTableQueries], - ); - // Handle filter change to re-fetch data-table. - const handleFilterChanged = useCallback(() => {}, [fetchInvoices]); + const handleFilterChanged = useCallback(() => {}, []); // Handle selected rows change. const handleSelectedRowsChange = useCallback( @@ -140,14 +125,13 @@ function InvoiceList({ > + } confirmButtonText={} diff --git a/client/src/containers/Sales/Invoice/InvoicesDataTable.js b/client/src/containers/Sales/Invoice/InvoicesDataTable.js index d150e1813..4f1c3d5d6 100644 --- a/client/src/containers/Sales/Invoice/InvoicesDataTable.js +++ b/client/src/containers/Sales/Invoice/InvoicesDataTable.js @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback, useState, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Intent, Button, @@ -8,13 +8,12 @@ import { MenuDivider, Position, } from '@blueprintjs/core'; -import { useParams } from 'react-router-dom'; import { withRouter } from 'react-router'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { DataTable, Money, Icon } from 'components'; @@ -27,66 +26,34 @@ import withInvoices from './withInvoices'; import withInvoiceActions from './withInvoiceActions'; import withCurrentView from 'containers/Views/withCurrentView'; +// Invoices datatable. function InvoicesDataTable({ - //#withInvoices + // #withInvoices invoicesCurrentPage, invoicesLoading, invoicesPageination, - invoicesItems, - // #withDashboardActions - changeCurrentView, - changePageSubtitle, - setTopbarEditView, + // #withInvoicesActions + addInvoiceTableQueries, - // #withView - viewMeta, - - //#OwnProps - loading, - onFetchData, + // #OwnProps onEditInvoice, onDeleteInvoice, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); - const { custom_view_id: customViewId } = useParams(); const { formatMessage } = useIntl(); - - useEffect(() => { - setInitialMount(false); - }, [customViewId]); - - useUpdateEffect(() => { - if (!invoicesLoading) { - setInitialMount(true); - } - }, [invoicesLoading, setInitialMount]); - - // useEffect(() => { - // if (customViewId) { - // changeCurrentView(customViewId); - // setTopbarEditView(customViewId); - // } - // changePageSubtitle(customViewId && viewMeta ? viewMeta.name : ''); - // }, [ - // customViewId, - // changeCurrentView, - // changePageSubtitle, - // setTopbarEditView, - // viewMeta, - // ]); + const isLoadedBefore = useIsValuePassed(invoicesLoading, false); const handleEditInvoice = useCallback( (_invoice) => () => { - onEditInvoice && onEditInvoice(_invoice); + saveInvoke(onEditInvoice, _invoice); }, [onEditInvoice], ); const handleDeleteInvoice = useCallback( (_invoice) => () => { - onDeleteInvoice && onDeleteInvoice(_invoice); + saveInvoke(onDeleteInvoice, _invoice); }, [onDeleteInvoice], ); @@ -194,49 +161,54 @@ function InvoicesDataTable({ ); const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); + ({ pageSize, pageIndex, sortBy }) => { + addInvoiceTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); }, - [onFetchData], + [addInvoiceTableQueries], ); + const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); - const selectionColumn = useMemo( - () => ({ - minWidth: 40, - width: 40, - maxWidth: 40, - }), - [], - ); - return ( -
- - - -
+ + + ); } @@ -247,10 +219,16 @@ export default compose( withDashboardActions, withInvoiceActions, withInvoices( - ({ invoicesCurrentPage, invoicesLoading, invoicesPageination }) => ({ + ({ invoicesCurrentPage, invoicesLoading, invoicesPageination, + invoicesTableQuery, + }) => ({ + invoicesCurrentPage, + invoicesLoading, + invoicesPageination, + invoicesTableQuery, }), ), withViewDetails(), diff --git a/client/src/containers/Sales/Invoice/withInvoiceActions.js b/client/src/containers/Sales/Invoice/withInvoiceActions.js index ab11b52f1..69a379b09 100644 --- a/client/src/containers/Sales/Invoice/withInvoiceActions.js +++ b/client/src/containers/Sales/Invoice/withInvoiceActions.js @@ -16,19 +16,20 @@ const mapDipatchToProps = (dispatch) => ({ requestFetchInvoiceTable: (query = {}) => dispatch(fetchInvoicesTable({ query: { ...query } })), requestDeleteInvoice: (id) => dispatch(deleteInvoice({ id })), - requestFetchDueInvoices: (customerId) => dispatch(fetchDueInvoices({ customerId })), + requestFetchDueInvoices: (customerId) => + dispatch(fetchDueInvoices({ customerId })), changeInvoiceView: (id) => dispatch({ type: t.INVOICES_SET_CURRENT_VIEW, currentViewId: parseInt(id, 10), }), - addInvoiceTableQueries: (_queries) => + addInvoiceTableQueries: (queries) => dispatch({ type: t.INVOICES_TABLE_QUERIES_ADD, - _queries, + payload: { queries }, }), - - setInvoiceNumberChanged: (isChanged) => dispatch({ + setInvoiceNumberChanged: (isChanged) => + dispatch({ type: t.INVOICE_NUMBER_CHANGED, payload: { isChanged }, }), diff --git a/client/src/containers/Sales/Invoice/withInvoices.js b/client/src/containers/Sales/Invoice/withInvoices.js index dd2d1a474..4ac74e14a 100644 --- a/client/src/containers/Sales/Invoice/withInvoices.js +++ b/client/src/containers/Sales/Invoice/withInvoices.js @@ -29,7 +29,6 @@ export default (mapState) => { state, props, ), - invoiceNumberChanged: state.salesInvoices.journalNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceiveList.js b/client/src/containers/Sales/PaymentReceive/PaymentReceiveList.js index f17b74991..8b3d36a88 100644 --- a/client/src/containers/Sales/PaymentReceive/PaymentReceiveList.js +++ b/client/src/containers/Sales/PaymentReceive/PaymentReceiveList.js @@ -60,7 +60,7 @@ function PaymentReceiveList({ () => requestFetchPaymentReceiveTable(), ); - //handle dalete Payment Receive + // Handle dalete Payment Receive const handleDeletePaymentReceive = useCallback( (paymentReceive) => { setDeletePaymentReceive(paymentReceive); @@ -68,12 +68,12 @@ function PaymentReceiveList({ [setDeletePaymentReceive], ); - // handle cancel Payment Receive + // Handle cancel payment Receive. const handleCancelPaymentReceiveDelete = useCallback(() => { setDeletePaymentReceive(false); }, [setDeletePaymentReceive]); - // handleConfirm delete payment receive + // Handle confirm delete payment receive. const handleConfirmPaymentReceiveDelete = useCallback(() => { requestDeletePaymentReceive(deletePaymentReceive.id).then(() => { AppToaster.show({ @@ -95,24 +95,6 @@ function PaymentReceiveList({ selectedRows, ]); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addPaymentReceivesTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addPaymentReceivesTableQueries], - ); - // Handle filter change to re-fetch data-table. const handleFilterChanged = useCallback(() => {}, [fetchPaymentReceives]); @@ -145,9 +127,7 @@ function PaymentReceiveList({ > diff --git a/client/src/containers/Sales/PaymentReceive/PaymentReceivesDataTable.js b/client/src/containers/Sales/PaymentReceive/PaymentReceivesDataTable.js index acacb7e4a..bae523957 100644 --- a/client/src/containers/Sales/PaymentReceive/PaymentReceivesDataTable.js +++ b/client/src/containers/Sales/PaymentReceive/PaymentReceivesDataTable.js @@ -1,21 +1,19 @@ -import React, { useEffect, useCallback, useState, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Intent, Button, - Classes, Popover, Menu, MenuItem, MenuDivider, Position, } from '@blueprintjs/core'; -import { useParams } from 'react-router-dom'; import { withRouter } from 'react-router'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; import LoadingIndicator from 'components/LoadingIndicator'; import { DataTable, Money, Icon } from 'components'; @@ -29,58 +27,26 @@ import withPaymentReceivesActions from './withPaymentReceivesActions'; import withCurrentView from 'containers/Views/withCurrentView'; function PaymentReceivesDataTable({ - //#withPaymentReceives + // #withPaymentReceives PaymentReceivesCurrentPage, paymentReceivesPageination, paymentReceivesLoading, - paymentReceivesItems, + paymentReceivesTableQuery, - // #withDashboardActions - changeCurrentView, - changePageSubtitle, - setTopbarEditView, + // #withPaymentReceivesActions + addPaymentReceivesTableQueries, - // #withView - viewMeta, - - //#OwnProps - loading, - onFetchData, + // #OwnProps onEditPaymentReceive, onDeletePaymentReceive, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); - const { custom_view_id: customViewId } = useParams(); + const isLoaded = useIsValuePassed(paymentReceivesLoading, false); const { formatMessage } = useIntl(); - useEffect(() => { - setInitialMount(false); - }, [customViewId]); - - useUpdateEffect(() => { - if (!paymentReceivesLoading) { - setInitialMount(true); - } - }, [paymentReceivesLoading, setInitialMount]); - - // useEffect(() => { - // if (customViewId) { - // changeCurrentView(customViewId); - // setTopbarEditView(customViewId); - // } - // changePageSubtitle(customViewId && viewMeta ? viewMeta.name : ''); - // }, [ - // customViewId, - // changeCurrentView, - // changePageSubtitle, - // setTopbarEditView, - // viewMeta, - // ]); - const handleEditPaymentReceive = useCallback( (paymentReceive) => () => { - onEditPaymentReceive && onEditPaymentReceive(paymentReceive); + saveInvoke(onEditPaymentReceive, paymentReceive); }, [onEditPaymentReceive], ); @@ -92,6 +58,32 @@ function PaymentReceivesDataTable({ [onDeletePaymentReceive], ); + const handleDataTableFetchData = useCallback( + ({ pageIndex, pageSize, sortBy }) => { + addPaymentReceivesTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page: pageIndex + 1, + }); + }, + [addPaymentReceivesTableQueries], + ); + + const handleSelectedRowsChange = useCallback( + (selectedRows) => { + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); + }, + [onSelectedRowsChange], + ); + const actionMenuList = useCallback( (paymentReceive) => ( @@ -142,7 +134,8 @@ function PaymentReceivesDataTable({ { id: 'payment_receive_no', Header: formatMessage({ id: 'payment_receive_no' }), - accessor: (row) => (row.payment_receive_no ? `#${row.payment_receive_no}` : null), + accessor: (row) => + row.payment_receive_no ? `#${row.payment_receive_no}` : null, width: 140, className: 'payment_receive_no', }, @@ -186,41 +179,29 @@ function PaymentReceivesDataTable({ [actionMenuList, formatMessage], ); - const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); - }, - [onFetchData], - ); - const handleSelectedRowsChange = useCallback( - (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); - }, - [onSelectedRowsChange], - ); - return ( -
- - - -
+ + + ); } @@ -235,10 +216,12 @@ export default compose( PaymentReceivesCurrentPage, paymentReceivesLoading, paymentReceivesPageination, + paymentReceivesTableQuery }) => ({ PaymentReceivesCurrentPage, paymentReceivesLoading, paymentReceivesPageination, + paymentReceivesTableQuery }), ), withViewDetails(), diff --git a/client/src/containers/Sales/PaymentReceive/withPaymentReceives.js b/client/src/containers/Sales/PaymentReceive/withPaymentReceives.js index 080d01de9..97c13e74f 100644 --- a/client/src/containers/Sales/PaymentReceive/withPaymentReceives.js +++ b/client/src/containers/Sales/PaymentReceive/withPaymentReceives.js @@ -22,7 +22,6 @@ export default (mapState) => { query, ), paymentReceivesLoading: state.paymentReceives.loading, - paymentReceiveNumberChanged: state.paymentReceives.journalNumberChanged, }; return mapState ? mapState(mapped, state, props) : mapped; diff --git a/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js b/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js index 4b526a95c..169d5e3f0 100644 --- a/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js +++ b/client/src/containers/Sales/PaymentReceive/withPaymentReceivesActions.js @@ -20,16 +20,17 @@ const mapDispatchToProps = (dispatch) => ({ changePaymentReceiveView: (id) => dispatch({ - type: t.PAYMENT_RECEIVE_SET_CURRENT_VIEW, + type: t.PAYMENT_RECEIVES_SET_CURRENT_VIEW, currentViewId: parseInt(id, 10), }), addPaymentReceivesTableQueries: (queries) => dispatch({ - type: t.PAYMENT_RECEIVE_TABLE_QUERIES_ADD, - queries, + type: t.PAYMENT_RECEIVES_TABLE_QUERIES_ADD, + payload: { queries } }), - setPaymentReceiveNumberChanged: (isChanged) => + + setPaymentReceiveNumberChanged: (isChanged) => dispatch({ type: t.PAYMENT_RECEIVE_NUMBER_CHANGED, payload: { isChanged }, diff --git a/client/src/containers/Sales/Receipt/ReceiptList.js b/client/src/containers/Sales/Receipt/ReceiptList.js index 1d3a6ea85..f945a2c24 100644 --- a/client/src/containers/Sales/Receipt/ReceiptList.js +++ b/client/src/containers/Sales/Receipt/ReceiptList.js @@ -30,7 +30,6 @@ function ReceiptList({ //#withReceipts receiptTableQuery, - receiptview, //#withReceiptActions requestFetchReceiptsTable, @@ -96,10 +95,8 @@ function ReceiptList({ // [fetchReceipt], // ); - // Handle filter change to re-fetch data-table. - const handleFilterChanged = useCallback(() => {}, [fetchReceipts]); - - + // Handle filter change to re-fetch data-table. + const handleFilterChanged = useCallback(() => {}, [fetchReceipts]); // Calculates the selected rows const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [ @@ -112,23 +109,6 @@ function ReceiptList({ }, [history], ); - const handleFetchData = useCallback( - ({ pageIndex, pageSize, sortBy }) => { - const page = pageIndex + 1; - - addReceiptsTableQueries({ - ...(sortBy.length > 0 - ? { - column_sort_by: sortBy[0].id, - sort_order: sortBy[0].desc ? 'desc' : 'asc', - } - : {}), - page_size: pageSize, - page, - }); - }, - [addReceiptsTableQueries], - ); const handleSelectedRowsChange = useCallback( (estimate) => { @@ -154,14 +134,13 @@ function ReceiptList({ > + } confirmButtonText={} diff --git a/client/src/containers/Sales/Receipt/ReceiptsDataTable.js b/client/src/containers/Sales/Receipt/ReceiptsDataTable.js index 819a87988..cf1526d7c 100644 --- a/client/src/containers/Sales/Receipt/ReceiptsDataTable.js +++ b/client/src/containers/Sales/Receipt/ReceiptsDataTable.js @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback, useState, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Intent, Button, @@ -8,85 +8,50 @@ import { MenuDivider, Position, } from '@blueprintjs/core'; -import { useParams } from 'react-router-dom'; import { withRouter } from 'react-router'; import { FormattedMessage as T, useIntl } from 'react-intl'; import moment from 'moment'; -import { compose } from 'utils'; -import { useUpdateEffect } from 'hooks'; +import { compose, saveInvoke } from 'utils'; +import { useIsValuePassed } from 'hooks'; -import LoadingIndicator from 'components/LoadingIndicator'; -import { DataTable, Money, Icon } from 'components'; +import { LoadingIndicator, DataTable, Money, Icon } from 'components'; import withDialogActions from 'containers/Dialog/withDialogActions'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; -import withViewDetails from 'containers/Views/withViewDetails'; import withReceipts from './withReceipts'; import withReceiptActions from './withReceiptActions'; -import withCurrentView from 'containers/Views/withCurrentView'; function ReceiptsDataTable({ //#withReceipts receiptsCurrentPage, receiptsLoading, receiptsPagination, - receiptItems, - // #withDashboardActions - changeCurrentView, - changePageSubtitle, - setTopbarEditView, + receiptTableQuery, - // #withView - viewMeta, + // #withReceiptsActions + addReceiptsTableQueries, // #Own Props - loading, - onFetchData, onEditReceipt, onDeleteReceipt, onSelectedRowsChange, }) { - const [initialMount, setInitialMount] = useState(false); - const { custom_view_id: customViewId } = useParams(); const { formatMessage } = useIntl(); - - useUpdateEffect(() => { - if (!receiptsLoading) { - setInitialMount(true); - } - }, [receiptsLoading, setInitialMount]); - - useEffect(() => { - setInitialMount(false); - }, []); - - useEffect(() => { - if (customViewId) { - changeCurrentView(customViewId); - setTopbarEditView(customViewId); - } - changePageSubtitle(customViewId && viewMeta ? viewMeta.name : ''); - }, [ - customViewId, - changeCurrentView, - changePageSubtitle, - setTopbarEditView, - viewMeta, - ]); + const isLoadedBefore = useIsValuePassed(receiptsLoading, false); const handleEditReceipt = useCallback( (receipt) => () => { - onEditReceipt && onEditReceipt(receipt); + saveInvoke(onEditReceipt, receipt); }, [onEditReceipt], ); const handleDeleteReceipt = useCallback( (receipt) => () => { - onDeleteReceipt && onDeleteReceipt(receipt); + saveInvoke(onDeleteReceipt, receipt); }, [onDeleteReceipt], ); @@ -194,50 +159,61 @@ function ReceiptsDataTable({ ); const handleDataTableFetchData = useCallback( - (...args) => { - onFetchData && onFetchData(...args); + ({ sortBy, pageIndex, pageSize }) => { + const page = pageIndex + 1; + + addReceiptsTableQueries({ + ...(sortBy.length > 0 + ? { + column_sort_by: sortBy[0].id, + sort_order: sortBy[0].desc ? 'desc' : 'asc', + } + : {}), + page_size: pageSize, + page, + }); }, - [onFetchData], + [addReceiptsTableQueries], ); const handleSelectedRowsChange = useCallback( (selectedRows) => { - onSelectedRowsChange && - onSelectedRowsChange(selectedRows.map((s) => s.original)); + saveInvoke( + onSelectedRowsChange, + selectedRows.map((s) => s.original), + ); }, [onSelectedRowsChange], ); - console.log(receiptsCurrentPage, 'receiptCurrnetPage'); - console.log(receiptItems, 'receiptItems'); - return ( -
- - - -
+ + + ); } export default compose( withRouter, - withCurrentView, withDialogActions, withDashboardActions, withReceiptActions, @@ -246,13 +222,12 @@ export default compose( receiptsCurrentPage, receiptsLoading, receiptsPagination, - receiptItems, + receiptTableQuery, }) => ({ receiptsCurrentPage, receiptsLoading, receiptsPagination, - receiptItems, + receiptTableQuery, }), ), - withViewDetails(), )(ReceiptsDataTable); diff --git a/client/src/containers/Sales/Receipt/withReceiptActions.js b/client/src/containers/Sales/Receipt/withReceiptActions.js index 34c6b8938..63703b331 100644 --- a/client/src/containers/Sales/Receipt/withReceiptActions.js +++ b/client/src/containers/Sales/Receipt/withReceiptActions.js @@ -26,7 +26,7 @@ const mapDispatchToProps = (dispatch) => ({ addReceiptsTableQueries: (queries) => dispatch({ type: t.RECEIPTS_TABLE_QUERIES_ADD, - queries, + payload: { queries }, }), setReceiptNumberChanged:(isChanged) => dispatch({ type: t.RECEIPT_NUMBER_CHANGED, diff --git a/client/src/containers/Sales/Receipt/withReceipts.js b/client/src/containers/Sales/Receipt/withReceipts.js index ab69a2f86..73f5a0711 100644 --- a/client/src/containers/Sales/Receipt/withReceipts.js +++ b/client/src/containers/Sales/Receipt/withReceipts.js @@ -22,7 +22,6 @@ export default (mapState) => { receiptsPagination: getReceiptPaginationMeta(state, props, tableQuery), receiptsLoading: state.salesReceipts.loading, - receiptNumberChanged: state.salesReceipts.journalNumberChanged, }; diff --git a/client/src/hooks/index.js b/client/src/hooks/index.js index 07ae38ffb..9f654ad77 100644 --- a/client/src/hooks/index.js +++ b/client/src/hooks/index.js @@ -21,6 +21,20 @@ export function useUpdateEffect(effect, dependencies = []) { }, dependencies); } + +export function useIsValuePassed(value, compatatorValue) { + const cache = useRef([value]); + + useEffect(() => { + if (cache.current.indexOf(value) === -1) { + cache.current.push(value); + } + }, [value]); + + return cache.current.indexOf(compatatorValue) !== -1; +} + + export default { useAsync, useUpdateEffect, diff --git a/client/src/store/Bills/bills.reducer.js b/client/src/store/Bills/bills.reducer.js index f7c9642ff..4d524a203 100644 --- a/client/src/store/Bills/bills.reducer.js +++ b/client/src/store/Bills/bills.reducer.js @@ -1,5 +1,8 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; +import { + createTableQueryReducers, + viewPaginationSetReducer, +} from 'store/journalNumber.reducer'; import t from 'store/types'; @@ -9,7 +12,7 @@ const initialState = { loading: false, currentViewId: -1, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, nextBillNumberChanged: false, @@ -24,7 +27,8 @@ const defaultBill = { entries: [], }; -const reducer = createReducer(initialState, { + +export default createReducer(initialState, { [t.BILL_SET]: (state, action) => { const { id, bill } = action.payload; const _bill = state.items[id] || {}; @@ -83,27 +87,6 @@ const reducer = createReducer(initialState, { }; }, - [t.BILLS_PAGINATION_SET]: (state, action) => { - const { pagination, customViewId } = action.payload; - const mapped = { - pageSize: parseInt(pagination.page_size, 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.BILL_NUMBER_CHANGED]: (state, action) => { const { isChanged } = action.payload; state.nextBillNumberChanged = isChanged; @@ -141,7 +124,8 @@ const reducer = createReducer(initialState, { const billsIds = bills.map((bill) => bill.id); state.byBillPayamentId[billPaymentId] = billsIds; - } -}); + }, -export default createTableQueryReducers('bills', reducer); + ...viewPaginationSetReducer(t.BILLS_PAGINATION_SET), + ...createTableQueryReducers('BILLS'), +}); \ No newline at end of file diff --git a/client/src/store/Bills/bills.selectors.js b/client/src/store/Bills/bills.selectors.js index 600df6088..91f2302b9 100644 --- a/client/src/store/Bills/bills.selectors.js +++ b/client/src/store/Bills/bills.selectors.js @@ -1,12 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { + pickItemsFromIds, + paginationLocationQuery, + defaultPaginationMeta, + getCurrentPageResults, +} from 'store/selectors'; // Retreive bills table query. const billTableQuery = (state) => state.bills.tableQuery; const billPageSelector = (state, props, query) => { const viewId = state.bills.currentViewId; - return state.bills.views?.[viewId]?.pages?.[query.page]; + const currentView = state.bills.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; // Retreive bills items. const billItemsSelector = (state) => state.bills.items; @@ -15,7 +23,8 @@ const billItemsSelector = (state) => state.bills.items; const billByIdSelector = (state, props) => state.bills.items[props.billId]; // Retrieve vendor due bills ids. -const billsPayableVendorSelector = (state, props) => state.bills.payable.byVendorId[props.vendorId]; +const billsPayableVendorSelector = (state, props) => + state.bills.payable.byVendorId[props.vendorId]; const billPaginationSelector = (state, props) => { const viewId = state.bills.currentViewId; @@ -58,13 +67,16 @@ export const getBillByIdFactory = () => */ export const getBillPaginationMetaFactory = () => createSelector(billPaginationSelector, (billPage) => { - return billPage?.paginationMeta || {}; + return { + ...defaultPaginationMeta(), + ...(billPage?.paginationMeta || {}), + }; }); /** * Retrieve vendor payable bills. */ -export const getVendorPayableBillsFactory = () => +export const getVendorPayableBillsFactory = () => createSelector( billItemsSelector, billsPayableVendorSelector, @@ -78,7 +90,7 @@ export const getVendorPayableBillsFactory = () => /** * Retrieve vendor payable bills entries. */ -export const getVendorPayableBillsEntriesFactory = () => +export const getVendorPayableBillsEntriesFactory = () => createSelector( billItemsSelector, billsPayableVendorSelector, @@ -94,5 +106,5 @@ export const getVendorPayableBillsEntriesFactory = () => id: null, payment_amount: null, })); - } - ); \ No newline at end of file + }, + ); diff --git a/client/src/store/Bills/bills.type.js b/client/src/store/Bills/bills.type.js index 8c93e8072..d20c14fd0 100644 --- a/client/src/store/Bills/bills.type.js +++ b/client/src/store/Bills/bills.type.js @@ -4,7 +4,7 @@ export default { BILLS_LIST_SET: 'BILLS_LIST_SET', BILL_SET: 'BILL_SET', BILLS_SET_CURRENT_VIEW: 'BILLS_SET_CURRENT_VIEW', - BILLS_TABLE_QUERIES_ADD: 'BILLS_TABLE_QUERIES_ADD', + BILLS_TABLE_QUERIES_ADD: 'BILLS/TABLE_QUERIES_ADD', BILLS_TABLE_LOADING: 'BILLS_TABLE_LOADING', BILLS_PAGINATION_SET: 'BILLS_PAGINATION_SET', BILLS_PAGE_SET: 'BILLS_PAGE_SET', diff --git a/client/src/store/Estimate/estimates.reducer.js b/client/src/store/Estimate/estimates.reducer.js index d3548748e..410b140e4 100644 --- a/client/src/store/Estimate/estimates.reducer.js +++ b/client/src/store/Estimate/estimates.reducer.js @@ -1,6 +1,8 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; -import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; +import { + journalNumberChangedReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; import t from 'store/types'; @@ -9,18 +11,17 @@ const initialState = { views: {}, loading: false, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, currentViewId: -1, - }; const defaultEstimate = { entries: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.ESTIMATE_SET]: (state, action) => { const { id, estimate } = action.payload; const _estimate = state.items[id] || {}; @@ -102,10 +103,9 @@ const reducer = createReducer(initialState, { }, ...journalNumberChangedReducer(t.ESTIMATE_NUMBER_CHANGED), + ...createTableQueryReducers('ESTIMATES'), }); -export default createTableQueryReducers('sales_estimates', reducer); - export const getEstimateById = (state, id) => { return state.sales_estimates.items[id]; }; diff --git a/client/src/store/Estimate/estimates.selectors.js b/client/src/store/Estimate/estimates.selectors.js index e9be4abc0..9cc8b6f36 100644 --- a/client/src/store/Estimate/estimates.selectors.js +++ b/client/src/store/Estimate/estimates.selectors.js @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { pickItemsFromIds, paginationLocationQuery, defaultPaginationMeta } from 'store/selectors'; const estimateTableQuery = (state) => state.salesEstimates.tableQuery; @@ -14,9 +14,12 @@ const estimateItemsSelector = (state) => state.salesEstimates.items; const estimatesPageSelector = (state, props, query) => { const viewId = state.salesEstimates.currentViewId; - return state.salesEstimates.views?.[viewId]?.pages?.[query.page]; + const currentPageId = state.salesEstimates.views?.[viewId]?.paginationMeta?.page; + + return state.salesEstimates.views?.[viewId]?.pages?.[currentPageId]; }; +// Retrieve estimates table query. export const getEstimatesTableQueryFactory = () => createSelector( paginationLocationQuery, @@ -29,6 +32,7 @@ export const getEstimatesTableQueryFactory = () => }, ); +// Retreive estimate results of the current page. export const getEstimateCurrentPageFactory = () => createSelector( estimatesPageSelector, @@ -40,12 +44,17 @@ export const getEstimateCurrentPageFactory = () => }, ); +// Retrieve specific estimate by the passed estimate id. export const getEstimateByIdFactory = () => createSelector(estimateByIdSelector, (estimate) => { return estimate; }); +// Retrieve estimates pagination meta. export const getEstimatesPaginationMetaFactory = () => createSelector(estimatesCurrentViewSelector, (estimateView) => { - return estimateView?.paginationMeta || {}; + return { + ...defaultPaginationMeta(), + ...(estimateView?.paginationMeta || {}), + }; }); diff --git a/client/src/store/Estimate/estimates.types.js b/client/src/store/Estimate/estimates.types.js index 357b9c955..5a8801081 100644 --- a/client/src/store/Estimate/estimates.types.js +++ b/client/src/store/Estimate/estimates.types.js @@ -3,8 +3,8 @@ export default { ESTIMATE_SET: 'ESTIMATE_SET', ESTIMATE_DELETE: 'ESTIMATE_DELETE', ESTIMATES_BULK_DELETE: 'ESTIMATES_BULK_DELETE', - ESTIMATES_SET_CURRENT_VIEW: 'ESTIMATES_SET_CURRENT_VIEW', - ESTIMATES_TABLE_QUERIES_ADD: 'ESTIMATES_TABLE_QUERIES_ADD', + ESTIMATES_SET_CURRENT_VIEW: 'ESTIMATES/SET_CURRENT_VIEW', + ESTIMATES_TABLE_QUERIES_ADD: 'ESTIMATES/TABLE_QUERIES_ADD', ESTIMATES_TABLE_LOADING: 'ESTIMATES_TABLE_LOADING', ESTIMATES_PAGINATION_SET: 'ESTIMATES_PAGINATION_SET', ESTIMATES_PAGE_SET: 'ESTIMATES_PAGE_SET', diff --git a/client/src/store/Invoice/invoices.reducer.js b/client/src/store/Invoice/invoices.reducer.js index 1c5ecbe4c..a06dde2d8 100644 --- a/client/src/store/Invoice/invoices.reducer.js +++ b/client/src/store/Invoice/invoices.reducer.js @@ -1,7 +1,9 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; -import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; - +import { + journalNumberChangedReducer, + viewPaginationSetReducer, + createTableQueryReducers, + } from 'store/journalNumber.reducer'; import t from 'store/types'; const initialState = { @@ -10,7 +12,7 @@ const initialState = { loading: false, currentViewId: -1, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, dueInvoices: {}, @@ -25,7 +27,7 @@ const defaultInvoice = { entries: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.INVOICE_SET]: (state, action) => { const { id, sale_invoice } = action.payload; const _invoice = state.items[id] || {}; @@ -82,28 +84,6 @@ const reducer = createReducer(initialState, { }; }, - [t.INVOICES_PAGINATION_SET]: (state, action) => { - const { pagination, customViewId } = action.payload; - - const mapped = { - pageSize: parseInt(pagination.page_size, 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.INVOICES_RECEIVABLE_BY_PAYMENT_ID]: (state, action) => { const { paymentReceiveId, saleInvoices } = action.payload; const saleInvoicesIds = saleInvoices.map((saleInvoice) => saleInvoice.id); @@ -126,10 +106,10 @@ const reducer = createReducer(initialState, { }, ...journalNumberChangedReducer(t.INVOICE_NUMBER_CHANGED), + ...viewPaginationSetReducer(t.INVOICES_PAGINATION_SET), + ...createTableQueryReducers('INVOICES'), }); -export default createTableQueryReducers('sales_invoices', reducer); - export const getInvoiceById = (state, id) => { return state.sales_invoices.items[id]; }; diff --git a/client/src/store/Invoice/invoices.selector.js b/client/src/store/Invoice/invoices.selector.js index af41919b2..5688e2911 100644 --- a/client/src/store/Invoice/invoices.selector.js +++ b/client/src/store/Invoice/invoices.selector.js @@ -2,7 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { pickItemsFromIds, paginationLocationQuery, - getItemById, + defaultPaginationMeta, } from 'store/selectors'; const invoiceTableQuery = (state) => state.salesInvoices.tableQuery; @@ -17,10 +17,15 @@ const invoicesPaginationSelector = (state, props) => { const invoicesPageSelector = (state, props, query) => { const viewId = state.salesInvoices.currentViewId; - return state.salesInvoices.views?.[viewId]?.pages?.[query.page]; + const currentView = state.salesInvoices.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; + const invoicesItemsSelector = (state) => state.salesInvoices.items; -const invoicesReceiableCustomerSelector = (state, props) => state.salesInvoices.receivable.byCustomerId[props.customerId]; +const invoicesReceiableCustomerSelector = (state, props) => + state.salesInvoices.receivable.byCustomerId[props.customerId]; export const getInvoiceTableQueryFactory = () => createSelector( @@ -34,6 +39,7 @@ export const getInvoiceTableQueryFactory = () => }, ); +// Retrieve invoices of the current view and view. export const getInvoiceCurrentPageFactory = () => createSelector( invoicesPageSelector, @@ -45,24 +51,27 @@ export const getInvoiceCurrentPageFactory = () => }, ); +// Retrieve specific invoice by the passed invoice id. export const getInvoiecsByIdFactory = () => createSelector(invoicesByIdSelector, (invoice) => { return invoice; }); +// Retrieve invoices pagination meta. export const getInvoicePaginationMetaFactory = () => createSelector(invoicesPaginationSelector, (invoicePage) => { - return invoicePage?.paginationMeta || {}; + return { + ...defaultPaginationMeta(), + ...(invoicePage?.paginationMeta || {}), + }; }); -export const getCustomerReceivableInvoicesEntriesFactory = () => +export const getCustomerReceivableInvoicesEntriesFactory = () => createSelector( invoicesItemsSelector, invoicesReceiableCustomerSelector, (invoicesItems, customerInvoicesIds) => { - const invoicesIds = [ - ...(customerInvoicesIds || []), - ]; + const invoicesIds = [...(customerInvoicesIds || [])]; const invoices = pickItemsFromIds(invoicesItems, invoicesIds); return invoices.map((invoice) => ({ @@ -73,4 +82,4 @@ export const getCustomerReceivableInvoicesEntriesFactory = () => payment_amount: 0, })); }, - ) \ No newline at end of file + ); diff --git a/client/src/store/Invoice/invoices.types.js b/client/src/store/Invoice/invoices.types.js index ee504ba2b..bea84fde4 100644 --- a/client/src/store/Invoice/invoices.types.js +++ b/client/src/store/Invoice/invoices.types.js @@ -4,7 +4,7 @@ export default { INVOICES_LIST_SET: 'INVOICES_LIST_SET', INVOICE_SET: 'INVOICE_SET', INVOICES_SET_CURRENT_VIEW: 'INVOICES_SET_CURRENT_VIEW', - INVOICES_TABLE_QUERIES_ADD: 'INVOICES_TABLE_QUERIES_ADD', + INVOICES_TABLE_QUERIES_ADD: 'INVOICES/TABLE_QUERIES_ADD', INVOICES_TABLE_LOADING: 'INVOICES_TABLE_LOADING', INVOICES_PAGINATION_SET: 'INVOICES_PAGINATION_SET', INVOICES_PAGE_SET: 'INVOICES_PAGE_SET', diff --git a/client/src/store/PaymentMades/paymentMade.reducer.js b/client/src/store/PaymentMades/paymentMade.reducer.js index 4ce3b8c95..882d8d667 100644 --- a/client/src/store/PaymentMades/paymentMade.reducer.js +++ b/client/src/store/PaymentMades/paymentMade.reducer.js @@ -1,6 +1,8 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; -import { omit } from 'lodash'; +import { + createTableQueryReducers, + viewPaginationSetReducer, +} from 'store/journalNumber.reducer'; import t from 'store/types'; const initialState = { @@ -9,7 +11,7 @@ const initialState = { loading: false, currentViewId: -1, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, nextPaymentNumberChanged: false, @@ -19,11 +21,12 @@ const defaultPaymentMade = { entries: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.PAYMENT_MADES_TABLE_LOADING]: (state, action) => { const { loading } = action.payload; state.loading = loading; }, + [t.PAYMENT_MADES_ITEMS_SET]: (state, action) => { const { bill_payments } = action.payload; const _bill_payments = {}; @@ -41,7 +44,7 @@ const reducer = createReducer(initialState, { [t.PAYMENT_MADE_SET]: (state, action) => { const { id, paymentMade } = action.payload; - const _oldPaymentMade = (state.items[id] || {}); + const _oldPaymentMade = state.items[id] || {}; state.items[id] = { ...defaultPaymentMade, @@ -58,28 +61,6 @@ const reducer = createReducer(initialState, { } }, - [t.PAYMENT_MADES_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.PAYMENT_MADES_PAGE_SET]: (state, action) => { const { customViewId, bill_payments, pagination } = action.payload; @@ -97,10 +78,11 @@ const reducer = createReducer(initialState, { }; }, - [t.PAYMENT_MADES_NUMBER_CHANGED]:(state,action)=>{ + [t.PAYMENT_MADES_NUMBER_CHANGED]: (state, action) => { const { isChanged } = action.payload; - state.nextPaymentNumberChanged = isChanged + state.nextPaymentNumberChanged = isChanged; + }, - } + ...viewPaginationSetReducer(t.PAYMENT_MADES_PAGINATION_SET), + ...createTableQueryReducers('PAYMENT_MADES'), }); -export default createTableQueryReducers('bill_payments', reducer); diff --git a/client/src/store/PaymentMades/paymentMade.selector.js b/client/src/store/PaymentMades/paymentMade.selector.js index fc249b2db..f058d72ec 100644 --- a/client/src/store/PaymentMades/paymentMade.selector.js +++ b/client/src/store/PaymentMades/paymentMade.selector.js @@ -1,12 +1,19 @@ import { createSelector } from '@reduxjs/toolkit'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { + pickItemsFromIds, + paginationLocationQuery, + defaultPaginationMeta, +} from 'store/selectors'; import { transformToObject } from 'utils'; const paymentMadeTableQuery = (state) => state.paymentMades.tableQuery; -const paymentMadesPageSelector = (state, props, query) => { +const paymentMadesPageSelector = (state) => { const viewId = state.paymentMades.currentViewId; - return state.paymentMades.views?.[viewId]?.pages?.[query.page]; + const currentView = state.paymentMades.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; const paymentMadesItemsSelector = (state) => state.paymentMades.items; @@ -16,12 +23,15 @@ const PaymentMadePaginationSelector = (state, props) => { return state.paymentMades.views?.[viewId]; }; -const paymentMadeById = (state, props) => state.paymentMades.items[props.paymentMadeId]; +const paymentMadeById = (state, props) => + state.paymentMades.items[props.paymentMadeId]; const paymentMadeEntries = (state, props) => props.paymentMadeEntries; const billsItemsSelector = (state, props) => state.bills.items; -const billsPayableByPaymentMadeSelector = (state, props) => state.bills.payable.byBillPayamentId[props.paymentMadeId]; -const paymentMadeBillsSelector = (state, props) => state.bills.byBillPayamentId[props.paymentMadeId]; +const billsPayableByPaymentMadeSelector = (state, props) => + state.bills.payable.byBillPayamentId[props.paymentMadeId]; +const paymentMadeBillsSelector = (state, props) => + state.bills.byBillPayamentId[props.paymentMadeId]; export const getPaymentMadeCurrentPageFactory = () => createSelector( @@ -46,8 +56,11 @@ export const getPaymentMadeTableQuery = createSelector( ); export const getPaymentMadePaginationMetaFactory = () => - createSelector(PaymentMadePaginationSelector, (Page) => { - return Page?.paginationMeta || {}; + createSelector(PaymentMadePaginationSelector, (page) => { + return { + ...defaultPaginationMeta(), + ...(page?.paginationMeta || {}), + }; }); export const getPaymentMadeByIdFactory = () => @@ -55,39 +68,40 @@ export const getPaymentMadeByIdFactory = () => return payment_Made; }); -export const getPaymentMadeEntriesDataFactory = () => +export const getPaymentMadeEntriesDataFactory = () => createSelector( billsItemsSelector, paymentMadeEntries, (billsItems, paymentEntries) => { - return Array.isArray(paymentEntries) ? - paymentEntries.map((entry) => ({ - ...entry, ...(billsItems[entry.bill_id] || {}), - })) : []; - } + return Array.isArray(paymentEntries) + ? paymentEntries.map((entry) => ({ + ...entry, + ...(billsItems[entry.bill_id] || {}), + })) + : []; + }, ); -export const getPaymentMadeEntriesFactory = () => +// Retrieve payment made entries. +export const getPaymentMadeEntriesFactory = () => createSelector( billsItemsSelector, billsPayableByPaymentMadeSelector, paymentMadeBillsSelector, paymentMadeById, - ( - billsItems, - paymentPayableBillsIds, - paymentMadeBillsIds, - paymentMade, - ) => { + (billsItems, paymentPayableBillsIds, paymentMadeBillsIds, paymentMade) => { const billsIds = [ ...(paymentPayableBillsIds || []), ...(paymentMadeBillsIds || []), ]; const bills = pickItemsFromIds(billsItems, billsIds); - const billEntries = transformToObject((paymentMade?.entries || []), 'bill_id'); + const billEntries = transformToObject( + paymentMade?.entries || [], + 'bill_id', + ); return bills.map((bill) => { - const paymentMadeEntry = (billEntries?.[bill.id] || {}); + const paymentMadeEntry = billEntries?.[bill.id] || {}; return { ...bill, @@ -98,4 +112,4 @@ export const getPaymentMadeEntriesFactory = () => }; }); }, - ); \ No newline at end of file + ); diff --git a/client/src/store/PaymentMades/paymentMade.type.js b/client/src/store/PaymentMades/paymentMade.type.js index 337248745..f97220202 100644 --- a/client/src/store/PaymentMades/paymentMade.type.js +++ b/client/src/store/PaymentMades/paymentMade.type.js @@ -3,7 +3,7 @@ export default { PAYMENT_MADE_DELETE: 'PAYMENT_MADE_DELETE', PAYMENT_MADE_SET: 'PAYMENT_MADE_SET', PAYMENT_MADE_SET_CURRENT_VIEW: 'PAYMENT_MADE_SET_CURRENT_VIEW', - PAYMENT_MADE_TABLE_QUERIES_ADD: 'PAYMENT_MADE_TABLE_QUERIES_ADD', + PAYMENT_MADES_TABLE_QUERIES_ADD: 'PAYMENT_MADES/TABLE_QUERIES_ADD', PAYMENT_MADES_TABLE_LOADING: 'PAYMENT_MADES_TABLE_LOADING', PAYMENT_MADES_PAGE_SET: 'PAYMENT_MADES_PAGE_SET', PAYMENT_MADES_ITEMS_SET: 'PAYMENT_MADES_ITEMS_SET', diff --git a/client/src/store/PaymentReceive/paymentReceive.reducer.js b/client/src/store/PaymentReceive/paymentReceive.reducer.js index 699c62e49..7a67d9dbb 100644 --- a/client/src/store/PaymentReceive/paymentReceive.reducer.js +++ b/client/src/store/PaymentReceive/paymentReceive.reducer.js @@ -1,8 +1,10 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; import { omit } from 'lodash'; -import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; - +import { + journalNumberChangedReducer, + viewPaginationSetReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; import t from 'store/types'; const initialState = { @@ -11,7 +13,7 @@ const initialState = { loading: false, currentViewId: -1, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, }; @@ -20,7 +22,7 @@ const defaultPaymentReceive = { entries: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.PAYMENT_RECEIVE_SET]: (state, action) => { const { id, paymentReceive } = action.payload; @@ -71,27 +73,6 @@ const reducer = createReducer(initialState, { } }, - [t.PAYMENT_RECEIVES_PAGINATION_SET]: (state, action) => { - const { pagination, customViewId } = action.payload; - const mapped = { - pageSize: parseInt(pagination.page_size, 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.PAYMENT_RECEIVES_PAGE_SET]: (state, action) => { const { customViewId, payment_receives, pagination } = action.payload; @@ -109,5 +90,6 @@ const reducer = createReducer(initialState, { }, ...journalNumberChangedReducer(t.PAYMENT_RECEIVE_NUMBER_CHANGED), + ...viewPaginationSetReducer(t.PAYMENT_RECEIVES_PAGINATION_SET), + ...createTableQueryReducers('PAYMENT_RECEIVES'), }); -export default createTableQueryReducers('payment_receives', reducer); diff --git a/client/src/store/PaymentReceive/paymentReceive.selector.js b/client/src/store/PaymentReceive/paymentReceive.selector.js index 216c533f3..ef25af5fa 100644 --- a/client/src/store/PaymentReceive/paymentReceive.selector.js +++ b/client/src/store/PaymentReceive/paymentReceive.selector.js @@ -1,10 +1,17 @@ import { createSelector } from '@reduxjs/toolkit'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { + pickItemsFromIds, + paginationLocationQuery, + defaultPaginationMeta, +} from 'store/selectors'; import { transformToObject } from 'utils'; -const paymentReceivesPageSelector = (state, props, query) => { +const paymentReceivesPageSelector = (state) => { const viewId = state.paymentReceives.currentViewId; - return state.paymentReceives.views?.[viewId]?.pages?.[query.page]; + const viewMeta = state.paymentReceives.views?.[viewId]; + + const currentPageId = viewMeta?.paginationMeta?.page; + return viewMeta?.pages?.[currentPageId]; }; const paymentReceivesItemsSelector = (state) => state.paymentReceives.items; @@ -28,17 +35,19 @@ const paymentReceiveInvoicesSelector = (state, props) => const paymentReceiveByIdSelector = (state, props) => state.paymentReceives.items[props.paymentReceiveId]; +// Retrieve payment receive current page results. export const getPaymentReceiveCurrentPageFactory = () => createSelector( paymentReceivesPageSelector, paymentReceivesItemsSelector, - (Page, Items) => { - return typeof Page === 'object' - ? pickItemsFromIds(Items, Page.ids) || [] + (expensesPage, expensesItems) => { + return typeof expensesPage === 'object' + ? pickItemsFromIds(expensesItems, expensesPage.ids) || [] : []; }, ); +// Retrieve payment receives table fetch query. export const getPaymentReceiveTableQuery = createSelector( paginationLocationQuery, paymentReceiveTableQuery, @@ -50,16 +59,22 @@ export const getPaymentReceiveTableQuery = createSelector( }, ); +// Retrieve payment receive pagination meta. export const getPaymentReceivePaginationMetaFactory = () => - createSelector(PaymentReceivePaginationSelector, (Page) => { - return Page?.paginationMeta || {}; + createSelector(PaymentReceivePaginationSelector, (page) => { + return { + ...defaultPaginationMeta(), + ...(page?.paginationMeta || {}), + }; }); +// Retrieve payment receive based on the passed payment receive id. export const getPaymentReceiveByIdFactory = () => createSelector(payemntReceiveById, (payment_receive) => { return payment_receive; }); +// Retrieve the payment receive associated invoices. export const getPaymentReceiveInvoices = createSelector( payemntReceiveById, invoicesItemsSelector, @@ -73,9 +88,7 @@ export const getPaymentReceiveInvoices = createSelector( }, ); -/** - * Retrieve payment receive invoices entries. - */ +// Retrieve payment receive invoices entries. export const getPaymentReceiveEntriesFactory = () => createSelector( invoicesItemsSelector, diff --git a/client/src/store/PaymentReceive/paymentReceive.type.js b/client/src/store/PaymentReceive/paymentReceive.type.js index b872d7afd..c2429f3b5 100644 --- a/client/src/store/PaymentReceive/paymentReceive.type.js +++ b/client/src/store/PaymentReceive/paymentReceive.type.js @@ -2,12 +2,11 @@ export default { PAYMENT_RECEIVE_LIST_SET: 'PAYMENT_RECEIVE_LIST_SET', PAYMENT_RECEIVE_DELETE: 'PAYMENT_RECEIVE_DELETE', PAYMENT_RECEIVE_SET: 'PAYMENT_RECEIVE_SET', - PAYMENT_RECEIVE_SET_CURRENT_VIEW: 'PAYMENT_RECEIVE_SET_CURRENT_VIEW', - PAYMENT_RECEIVE_TABLE_QUERIES_ADD: 'PAYMENT_RECEIVE_TABLE_QUERIES_ADD', + PAYMENT_RECEIVES_SET_CURRENT_VIEW: 'PAYMENT_RECEIVES_SET_CURRENT_VIEW', + PAYMENT_RECEIVES_TABLE_QUERIES_ADD: 'PAYMENT_RECEIVES/TABLE_QUERIES_ADD', PAYMENT_RECEIVES_TABLE_LOADING: 'PAYMENT_RECEIVES_TABLE_LOADING', PAYMENT_RECEIVES_PAGE_SET: 'PAYMENT_RECEIVES_PAGE_SET', PAYMENT_RECEIVES_ITEMS_SET: 'PAYMENT_RECEIVES_ITEMS_SET', PAYMENT_RECEIVES_PAGINATION_SET: 'PAYMENT_RECEIVES_PAGINATION_SET', - PAYMENT_RECEIVE_NUMBER_CHANGED: 'PAYMENT_RECEIVE_NUMBER_CHANGED', }; diff --git a/client/src/store/customers/customers.reducer.js b/client/src/store/customers/customers.reducer.js index fb95f60bc..dec6ecf15 100644 --- a/client/src/store/customers/customers.reducer.js +++ b/client/src/store/customers/customers.reducer.js @@ -1,21 +1,25 @@ import t from 'store/types'; -import { snakeCase } from 'lodash'; import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; +import { + viewPaginationSetReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; const initialState = { items: {}, views: {}, loading: false, currentViewId: -1, + + // Responsible for data fetch query based on this query. tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, errors: [], }; -const customersReducer = createReducer(initialState, { +export default createReducer(initialState, { [t.CUSTOMER_SET]: (state, action) => { const { id, customer } = action.payload; const _customers = state.items[id] || {}; @@ -65,28 +69,6 @@ const customersReducer = createReducer(initialState, { state.loading = loading; }, - [t.CUSTOMERS_PAGINATION_SET]: (state, action) => { - const { pagination, customViewId } = action.payload; - - const mapped = { - pageSize: parseInt(pagination.page_size, 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.CUSTOMERS_BULK_DELETE]: (state, action) => { const { ids } = action.payload; const items = { ...state.items }; @@ -98,9 +80,10 @@ const customersReducer = createReducer(initialState, { }); state.items = items; }, -}); -export default createTableQueryReducers('customers', customersReducer); + ...viewPaginationSetReducer(t.CUSTOMERS_PAGINATION_SET), + ...createTableQueryReducers('CUSTOMERS'), +}); export const getCustomerById = (state, id) => { return state.customers.items[id]; diff --git a/client/src/store/customers/customers.selectors.js b/client/src/store/customers/customers.selectors.js index 881dee9ad..9c4ffb1bf 100644 --- a/client/src/store/customers/customers.selectors.js +++ b/client/src/store/customers/customers.selectors.js @@ -1,5 +1,9 @@ import { createSelector } from 'reselect'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { + pickItemsFromIds, + paginationLocationQuery, + defaultPaginationMeta, +} from 'store/selectors'; const customerTableQuery = (state) => state.customers.tableQuery; @@ -12,9 +16,12 @@ const customersPaginationSelector = (state, props) => { return state.customers.views?.[viewId]; }; -const customerPageSelector = (state, props, query) => { +const customerPageSelector = (state, props) => { const viewId = state.customers.currentViewId; - return state.customers.views?.[viewId]?.pages?.[query.page]; + const currentView = state.customers.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; const customersItemsSelector = (state) => state.customers.items; @@ -49,6 +56,8 @@ export const getCustomersByIdFactory = () => export const getCustomerPaginationMetaFactory = () => createSelector(customersPaginationSelector, (customerPage) => { - return customerPage?.paginationMeta || {}; + return { + ...defaultPaginationMeta(), + ...(customerPage?.paginationMeta || {}), + }; }); - diff --git a/client/src/store/customers/customers.type.js b/client/src/store/customers/customers.type.js index 2d6b6169b..344af1bf3 100644 --- a/client/src/store/customers/customers.type.js +++ b/client/src/store/customers/customers.type.js @@ -3,7 +3,7 @@ export default { CUSTOMER_SET: 'CUSTOMER_SET', CUSTOMERS_PAGE_SET: 'CUSTOMERS_PAGE_SET', CUSTOMERS_TABLE_LOADING: 'CUSTOMERS_TABLE_LOADING', - CUSTOMERS_TABLE_QUERIES_ADD: 'CUSTOMERS_TABLE_QUERIES_ADD', + CUSTOMERS_TABLE_QUERIES_ADD: 'CUSTOMERS/TABLE_QUERIES_ADD', CUSTOMER_DELETE: 'CUSTOMER_DELETE', CUSTOMERS_BULK_DELETE: 'CUSTOMERS_BULK_DELETE', CUSTOMERS_PAGINATION_SET: 'CUSTOMERS_PAGINATION_SET', diff --git a/client/src/store/expenses/expenses.reducer.js b/client/src/store/expenses/expenses.reducer.js index 3df7c9ef1..f4fbfea18 100644 --- a/client/src/store/expenses/expenses.reducer.js +++ b/client/src/store/expenses/expenses.reducer.js @@ -1,5 +1,8 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; +import { + viewPaginationSetReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; import t from 'store/types'; @@ -7,6 +10,7 @@ const initialState = { items: {}, views: {}, loading: false, + // tableQuery: { page_size: 12, page: 1, @@ -18,7 +22,7 @@ const defaultExpense = { categories: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.EXPENSE_SET]: (state, action) => { const { id, expense } = action.payload; const oldExpense = state.items[id] || {}; @@ -66,29 +70,6 @@ const reducer = createReducer(initialState, { }; }, - [t.EXPENSES_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.EXPENSES_TABLE_LOADING]: (state, action) => { const { loading } = action.payload; state.loading = loading; @@ -117,9 +98,10 @@ const reducer = createReducer(initialState, { }); state.items = items; }, -}); -export default createTableQueryReducers('expenses', reducer); + ...viewPaginationSetReducer(t.EXPENSES_PAGINATION_SET), + ...createTableQueryReducers('EXPENSES'), +}); export const getExpenseById = (state, id) => { return state.expenses.items[id]; diff --git a/client/src/store/expenses/expenses.selectors.js b/client/src/store/expenses/expenses.selectors.js index 1d9f7cc09..f5cf9eea0 100644 --- a/client/src/store/expenses/expenses.selectors.js +++ b/client/src/store/expenses/expenses.selectors.js @@ -1,8 +1,29 @@ import { createSelector } from '@reduxjs/toolkit'; import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; -const expensesTableQuery = state => state.expenses.tableQuery; +const expensesTableQuery = (state) => state.expenses.tableQuery; +const getPageExpensesQuery = (state, props) => { + const currentPageId = state.expenses.views?.[props.viewId]?.paginationMeta?.page; + return currentPageId || 0; +}; + +const expensesPageSelector = (state, props, query) => { + const viewId = state.expenses.currentViewId; + const currentPageId = getPageExpensesQuery(state, { viewId }); + + return state.expenses.views?.[viewId]?.pages?.[currentPageId]; +}; + +const expensesItemsSelector = (state) => state.expenses.items; +const expenseByIdSelector = (state, props) => state.expenses.items[props.expenseId]; + +const manualJournalsPaginationSelector = (state, props) => { + const viewId = state.expenses.currentViewId; + return state.expenses.views?.[viewId]; +}; + +// Retrive expenses table query. export const getExpensesTableQuery = createSelector( paginationLocationQuery, expensesTableQuery, @@ -14,13 +35,7 @@ export const getExpensesTableQuery = createSelector( }, ); -const expensesPageSelector = (state, props, query) => { - const viewId = state.expenses.currentViewId; - return state.expenses.views?.[viewId]?.pages?.[query.page]; -}; - -const expensesItemsSelector = (state) => state.expenses.items; - +// Retrieve expenses results of the current page. export const getExpensesCurrentPageFactory = () => createSelector( expensesPageSelector, expensesItemsSelector, @@ -31,8 +46,7 @@ export const getExpensesCurrentPageFactory = () => createSelector( }, ); -const expenseByIdSelector = (state, props) => state.expenses.items[props.expenseId]; - +// Retrieve specific expense by the passed expense id. export const getExpenseByIdFactory = () => createSelector( expenseByIdSelector, (expense) => { @@ -40,11 +54,7 @@ export const getExpenseByIdFactory = () => createSelector( } ); -const manualJournalsPaginationSelector = (state, props) => { - const viewId = state.expenses.currentViewId; - return state.expenses.views?.[viewId]; -}; - +// Retrieve expenses pagination meta. export const getExpensesPaginationMetaFactory = () => createSelector( manualJournalsPaginationSelector, (expensesPage) => { diff --git a/client/src/store/expenses/expenses.types.js b/client/src/store/expenses/expenses.types.js index 4cf9714e3..bfade79bb 100644 --- a/client/src/store/expenses/expenses.types.js +++ b/client/src/store/expenses/expenses.types.js @@ -4,7 +4,7 @@ export default { EXPENSE_DELETE: 'EXPENSE_DELETE', EXPENSES_BULK_DELETE: 'EXPENSES_BULK_DELETE', EXPENSES_SET_CURRENT_VIEW: 'EXPENSES_SET_CURRENT_VIEW', - EXPENSES_TABLE_QUERIES_ADD:'EXPENSES_TABLE_QUERIES_ADD', + EXPENSES_TABLE_QUERIES_ADD:'EXPENSES/TABLE_QUERIES_ADD', EXPENSE_PUBLISH: 'EXPENSE_PUBLISH', EXPENSES_TABLE_LOADING: 'EXPENSES_TABLE_LOADING', EXPENSES_PAGE_SET: 'EXPENSES_PAGE_SET', diff --git a/client/src/store/items/items.actions.js b/client/src/store/items/items.actions.js index 20e634bb4..d836990aa 100644 --- a/client/src/store/items/items.actions.js +++ b/client/src/store/items/items.actions.js @@ -30,13 +30,17 @@ export const fetchItems = ({ query }) => { customViewId: response.data?.filter_meta?.view?.custom_view_id, paginationMeta: response.data.pagination, }); + dispatch({ + type: t.ITEMS_PAGINATION_SET, + payload: { + pagination: response.data.pagination, + customViewId: response.data.customViewId || -1, + } + }) dispatch({ type: t.ITEMS_TABLE_LOADING, payload: { loading: false }, }); - dispatch({ - type: t.SET_DASHBOARD_REQUEST_COMPLETED, - }); resolve(response); }) .catch((error) => { diff --git a/client/src/store/items/items.reducer.js b/client/src/store/items/items.reducer.js index 028eb9aeb..bc44fc477 100644 --- a/client/src/store/items/items.reducer.js +++ b/client/src/store/items/items.reducer.js @@ -1,7 +1,10 @@ import t from 'store/types'; import { createReducer } from '@reduxjs/toolkit'; import { getItemsViewPages } from 'store/items/items.selectors'; -import { createTableQueryReducers } from 'store/queryReducers'; +import { + viewPaginationSetReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; const initialState = { items: {}, @@ -9,12 +12,15 @@ const initialState = { itemsRelation: {}, currentPage: 1, currentViewId: -1, - tableQuery: {}, bulkActions: {}, loading: false, + tableQuery: { + page_size: 12, + page: 1, + }, }; -const itemsReducer = createReducer(initialState, { +export default createReducer(initialState, { [t.ITEMS_SET]: (state, action) => { const _items = {}; @@ -111,9 +117,10 @@ const itemsReducer = createReducer(initialState, { }); state.items = items; }, -}); -export default createTableQueryReducers('items', itemsReducer); + ...viewPaginationSetReducer(t.ITEMS_PAGINATION_SET), + ...createTableQueryReducers('ITEMS'), +}); export const getItemById = (state, id) => { return state.items.items[id]; diff --git a/client/src/store/items/items.types.js b/client/src/store/items/items.types.js index e35fb5cfe..7bcc2b765 100644 --- a/client/src/store/items/items.types.js +++ b/client/src/store/items/items.types.js @@ -2,12 +2,13 @@ export default { ITEMS_SET: 'ITEMS_SET', ITEM_SET: 'ITEM_SET', ITEMS_PAGE_SET: 'ITEMS_PAGE_SET', + ITEMS_PAGINATION_SET: 'ITEMS_PAGINATION_SET', ITEM_DELETE: 'ITEM_DELETE', ITEM_BULK_ACTION_ADD: 'ITEM_BULK_ACTION_ADD', ITEM_BULK_ACTION_REMOVE: 'ITEM_BULK_ACTION_REMOVE', - ITEMS_TABLE_QUERY_SET: 'ITEMS_TABLE_QUERY_SET', - ITEMS_TABLE_QUERIES_ADD: 'ITEMS_TABLE_QUERIES_ADD', + ITEMS_TABLE_QUERY_SET: 'ITEMS/TABLE_QUERY_SET', + ITEMS_TABLE_QUERIES_ADD: 'ITEMS/TABLE_QUERIES_ADD', ITEMS_TABLE_LOADING: 'ITEMS_TABLE_LOADING', ITEMS_SET_CURRENT_VIEW: 'ITEMS_SET_CURRENT_VIEW', diff --git a/client/src/store/journalNumber.reducer.js b/client/src/store/journalNumber.reducer.js index 188f9389a..d9dcda832 100644 --- a/client/src/store/journalNumber.reducer.js +++ b/client/src/store/journalNumber.reducer.js @@ -4,4 +4,44 @@ export const journalNumberChangedReducer = (type) => ({ const { isChanged } = action.payload; state.journalNumberChanged = isChanged; }, +}); + +export const viewPaginationSetReducer = (type) => ({ + [type]: (state, action) => { + const { pagination, customViewId } = action.payload; + + const mapped = { + pageSize: parseInt(pagination.page_size, 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, + }, + }; + }, +}); + +export const createTableQueryReducers = (RESOURCE_NAME) => ({ + [`${RESOURCE_NAME}/TABLE_QUERY_SET`]: (state, action) => { + state.tableQuery = { + ...state.tableQuery, + [state.key]: action.payload.value, + }; + }, + + [`${RESOURCE_NAME}/TABLE_QUERIES_ADD`]: (state, action) => { + state.tableQuery = { + ...state.tableQuery, + ...action.payload.queries, + }; + }, }); \ No newline at end of file diff --git a/client/src/store/manualJournals/manualJournals.actions.js b/client/src/store/manualJournals/manualJournals.actions.js index b334f4c56..a89aef2d7 100644 --- a/client/src/store/manualJournals/manualJournals.actions.js +++ b/client/src/store/manualJournals/manualJournals.actions.js @@ -138,7 +138,7 @@ export const fetchManualJournalsTable = ({ query } = {}) => { manual_journals: response.data.manual_journals, }); dispatch({ - type: 'MANUAL_JOURNALS_PAGINATION_SET', + type: t.MANUAL_JOURNALS_PAGINATION_SET, payload: { pagination: response.data.pagination, customViewId: diff --git a/client/src/store/manualJournals/manualJournals.reducers.js b/client/src/store/manualJournals/manualJournals.reducers.js index c4eeaebdf..b523a06f4 100644 --- a/client/src/store/manualJournals/manualJournals.reducers.js +++ b/client/src/store/manualJournals/manualJournals.reducers.js @@ -1,8 +1,11 @@ import t from 'store/types'; import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; import { omit } from 'lodash'; -import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; +import { + journalNumberChangedReducer, + viewPaginationSetReducer, + createTableQueryReducers, +} from 'store/journalNumber.reducer'; const initialState = { items: {}, @@ -10,7 +13,7 @@ const initialState = { loading: false, currentViewId: -1, tableQuery: { - page_size: 6, + page_size: 12, page: 1, }, paginationMeta: { @@ -23,8 +26,7 @@ const defaultJournal = { entries: [], }; -const reducer = createReducer(initialState, { - +export default createReducer(initialState, { [t.MANUAL_JOURNAL_SET]: (state, action) => { const { id, manualJournal } = action.payload; state.items[id] = { ...defaultJournal, ...manualJournal }; @@ -32,7 +34,7 @@ const reducer = createReducer(initialState, { [t.MANUAL_JOURNAL_PUBLISH]: (state, action) => { const { id } = action.payload; - const item = state.items[id] || {} + const item = state.items[id] || {}; state.items[id] = { ...item, status: 1 }; }, @@ -57,15 +59,15 @@ const reducer = createReducer(initialState, { const viewId = customViewId || -1; const view = state.views[viewId] || {}; - + state.views[viewId] = { ...view, pages: { ...(state.views?.[viewId]?.pages || {}), [pagination.page]: { - ids: (manualJournals.map((i) => i.id)), + ids: manualJournals.map((i) => i.id), }, - } + }, }; }, @@ -95,34 +97,11 @@ const reducer = createReducer(initialState, { state.items = items; }, - [t.MANUAL_JOURNALS_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, - }, - }; - }, - + ...viewPaginationSetReducer(t.MANUAL_JOURNALS_PAGINATION_SET), ...journalNumberChangedReducer(t.MANUAL_JOURNAL_NUMBER_CHANGED), + ...createTableQueryReducers('MANUAL_JOURNALS'), }); -export default createTableQueryReducers('manual_journals', reducer); - export const getManualJournal = (state, id) => { return state.manualJournals.items[id]; -} \ No newline at end of file +}; diff --git a/client/src/store/manualJournals/manualJournals.selectors.js b/client/src/store/manualJournals/manualJournals.selectors.js index 6ebe366ed..5931ce6fd 100644 --- a/client/src/store/manualJournals/manualJournals.selectors.js +++ b/client/src/store/manualJournals/manualJournals.selectors.js @@ -1,9 +1,12 @@ import { createSelector } from 'reselect'; -import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; +import { pickItemsFromIds, paginationLocationQuery, defaultPaginationMeta } from 'store/selectors'; -const manualJournalsPageSelector = (state, props, query) => { +const manualJournalsPageSelector = (state) => { const viewId = state.manualJournals.currentViewId; - return state.manualJournals.views?.[viewId]?.pages?.[query.page]; + const currentView = state.manualJournals.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; const manualJournalsPaginationSelector = (state, props) => { @@ -15,6 +18,7 @@ const manualJournalsTableQuery = (state) => state.manualJournals.tableQuery; const manualJournalsDataSelector = (state) => state.manualJournals.items; +// Retrieve manual jounral current page results. export const getManualJournalsItems = createSelector( manualJournalsPageSelector, manualJournalsDataSelector, @@ -25,13 +29,18 @@ export const getManualJournalsItems = createSelector( }, ); +// Retrieve manual journals pagination meta. export const getManualJournalsPagination = createSelector( manualJournalsPaginationSelector, (manualJournalsPage) => { - return manualJournalsPage?.paginationMeta || {}; + return { + ...defaultPaginationMeta(), + ...(manualJournalsPage?.paginationMeta || {}), + }; }, ); +// Retrieve manual jouranls table query. export const getManualJournalsTableQuery = createSelector( paginationLocationQuery, manualJournalsTableQuery, diff --git a/client/src/store/manualJournals/manualJournals.types.js b/client/src/store/manualJournals/manualJournals.types.js index b6452a051..e53d041ce 100644 --- a/client/src/store/manualJournals/manualJournals.types.js +++ b/client/src/store/manualJournals/manualJournals.types.js @@ -6,7 +6,7 @@ export default { MANUAL_JOURNALS_PAGE_SET: 'MANUAL_JOURNALS_PAGE_SET', MANUAL_JOURNALS_ITEMS_SET: 'MANUAL_JOURNALS_ITEMS_SET', MANUAL_JOURNALS_SET_CURRENT_VIEW: 'MANUAL_JOURNALS_SET_CURRENT_VIEW', - MANUAL_JOURNALS_TABLE_QUERIES_ADD: 'MANUAL_JOURNALS_TABLE_QUERIES_ADD', + MANUAL_JOURNALS_TABLE_QUERIES_ADD: 'MANUAL_JOURNALS/TABLE_QUERIES_ADD', MANUAL_JOURNAL_REMOVE: 'MANUAL_JOURNAL_REMOVE', MANUAL_JOURNAL_PUBLISH: 'MANUAL_JOURNAL_PUBLISH', diff --git a/client/src/store/paginator.reducer.js b/client/src/store/paginator.reducer.js index a4297f715..e69de29bb 100644 --- a/client/src/store/paginator.reducer.js +++ b/client/src/store/paginator.reducer.js @@ -1,27 +0,0 @@ -const pages = (pages, action) => { - const { type, items, meta } = action; - - switch(type) { - case REQUEST_PAGE: - return { - ...pages, - [meta.currentPage]: { - ...pages[meta.currentPage], - ids: [], - fetching: true, - }, - }; - case RECEIVE_PAGE: - return { - ...pages, - [meta.currentPage]: { - ...pages[meta.currentPage], - ids: items.map(i => i.id), - fetching: false, - }, - }; - } -}; - - - diff --git a/client/src/store/queryReducers.js b/client/src/store/queryReducers.js index fddcb5d3b..9225eab3b 100644 --- a/client/src/store/queryReducers.js +++ b/client/src/store/queryReducers.js @@ -6,7 +6,7 @@ export const createTableQueryReducers = const RESOURCE_NAME = resourceName.toUpperCase(); switch (action.type) { - case `${RESOURCE_NAME}_TABLE_QUERY_SET`: + case `${RESOURCE_NAME}/TABLE_QUERY_SET`: return { ...state, tableQuery: { @@ -14,15 +14,11 @@ export const createTableQueryReducers = [state.key]: state.value, } }; - case `${RESOURCE_NAME}_TABLE_QUERIES_ADD`: + case `${RESOURCE_NAME}/TABLE_QUERIES_ADD`: return { - ...state, - tableQuery: { - ...state.tableQuery, - ...action.queries - }, + }; default: return reducer(state, action); - } + } } \ No newline at end of file diff --git a/client/src/store/receipt/receipt.reducer.js b/client/src/store/receipt/receipt.reducer.js index 6c5f7a8b9..298f749aa 100644 --- a/client/src/store/receipt/receipt.reducer.js +++ b/client/src/store/receipt/receipt.reducer.js @@ -1,14 +1,13 @@ import { createReducer } from '@reduxjs/toolkit'; -import { createTableQueryReducers } from 'store/queryReducers'; import t from 'store/types'; -import { journalNumberChangedReducer } from 'store/journalNumber.reducer'; +import { journalNumberChangedReducer, createTableQueryReducers } from 'store/journalNumber.reducer'; const initialState = { items: {}, views: {}, loading: false, tableQuery: { - page_size: 5, + page_size: 12, page: 1, }, currentViewId: -1, @@ -18,7 +17,7 @@ const defaultReceipt = { entries: [], }; -const reducer = createReducer(initialState, { +export default createReducer(initialState, { [t.RECEIPT_SET]: (state, action) => { const { id, sale_receipt } = action.payload; const _receipt = state.items[id] || {}; @@ -94,10 +93,9 @@ const reducer = createReducer(initialState, { }; }, ...journalNumberChangedReducer(t.RECEIPT_NUMBER_CHANGED), + ...createTableQueryReducers('RECEIPTS'), }); -export default createTableQueryReducers('sales_receipts', reducer); - export const getReceiptById = (state, id) => { return state.receipts.items[id]; }; diff --git a/client/src/store/receipt/receipt.selector.js b/client/src/store/receipt/receipt.selector.js index 28e7de52c..05ee4066c 100644 --- a/client/src/store/receipt/receipt.selector.js +++ b/client/src/store/receipt/receipt.selector.js @@ -1,9 +1,12 @@ import { createSelector } from '@reduxjs/toolkit'; import { pickItemsFromIds, paginationLocationQuery } from 'store/selectors'; -const receiptsPageSelector = (state, props, query) => { +const receiptsPageSelector = (state) => { const viewId = state.salesReceipts.currentViewId; - return state.salesReceipts.views?.[viewId]?.pages?.[query.page]; + const currentView = state.salesReceipts.views?.[viewId]; + const currentPageId = currentView?.paginationMeta?.page; + + return currentView?.pages?.[currentPageId]; }; const receiptsPaginationSelector = (state, props) => { @@ -17,7 +20,7 @@ const receiptTableQuery = (state) => state.salesReceipts.tableQuery; const receiptByIdSelector = (state, props) => state.salesReceipts.items[props.receiptId]; - +// Retrieve current page sale receipts results. export const getReceiptCurrentPageFactory = () => createSelector( receiptsPageSelector, @@ -29,6 +32,7 @@ export const getReceiptCurrentPageFactory = () => }, ); +// Retrieve receipts table query. export const getReceiptsTableQueryFactory = () => createSelector( paginationLocationQuery, @@ -41,11 +45,13 @@ export const getReceiptsTableQueryFactory = () => }, ); +// Retrieve specific receipts by the passed receipt id. export const getReceiptByIdFactory = () => createSelector(receiptByIdSelector, (receipt) => { return receipt; }); +// Retrieve receipts pagination meta. export const getReceiptsPaginationMetaFactory = () => createSelector(receiptsPaginationSelector, (receiptPage) => { return receiptPage?.paginationMeta || {}; diff --git a/client/src/store/receipt/receipt.type.js b/client/src/store/receipt/receipt.type.js index b68ae5984..62a809717 100644 --- a/client/src/store/receipt/receipt.type.js +++ b/client/src/store/receipt/receipt.type.js @@ -4,7 +4,7 @@ export default { RECEIPTS_LIST_SET: 'RECEIPTS_LIST_SET', RECEIPT_SET: 'RECEIPT_SET', RECEIPTS_SET_CURRENT_VIEW: 'RECEIPTS_SET_CURRENT_VIEW', - RECEIPTS_TABLE_QUERIES_ADD: 'RECEIPTS_TABLE_QUERIES_ADD', + RECEIPTS_TABLE_QUERIES_ADD: 'RECEIPTS/TABLE_QUERIES_ADD', RECEIPTS_TABLE_LOADING: 'RECEIPTS_TABLE_LOADING', RECEIPTS_PAGINATION_SET: 'RECEIPTS_PAGINATION_SET', RECEIPTS_PAGE_SET: 'RECEIPTS_PAGE_SET', diff --git a/client/src/store/selectors.js b/client/src/store/selectors.js index 839241592..6f9292226 100644 --- a/client/src/store/selectors.js +++ b/client/src/store/selectors.js @@ -47,4 +47,12 @@ export const paginationLocationQuery = (state, props) => { parseInt(v, 10), ) : null; -} \ No newline at end of file +} + +export const defaultPaginationMeta = () => ({ + pageSize: 0, + page: 1, + total: 0, + pagesCount: 0, + pageIndex: 0, +}) \ No newline at end of file diff --git a/client/src/style/components/pagination.scss b/client/src/style/components/pagination.scss index 8ebafc8a6..fc193804e 100644 --- a/client/src/style/components/pagination.scss +++ b/client/src/style/components/pagination.scss @@ -84,9 +84,19 @@ font-size: 13px; border-radius: 3px; color: #666; - padding-right: 8px; + padding-right: 14px; + padding-left: 8px; + } + + &::after{ + border-left-width: 3px; + border-right-width: 3px; + border-top-width: 4px; + margin-right: 6px; } } + + } &__goto-control{