From 9ef180a805e20bce953c7b43027fd34ad80853d9 Mon Sep 17 00:00:00 2001
From: elforjani3
Date: Sat, 23 May 2020 19:39:20 +0200
Subject: [PATCH] WIP feature/Bulk delete items
---
client/src/containers/Items/ItemForm.js | 32 +++++-------
.../src/containers/Items/ItemsActionsBar.js | 21 +++++---
client/src/containers/Items/ItemsDataTable.js | 3 ++
client/src/containers/Items/ItemsList.js | 50 +++++++++++++++++--
.../src/containers/Items/withItemsActions.js | 2 +
client/src/lang/en/index.js | 5 +-
client/src/store/items/items.actions.js | 16 ++++++
client/src/store/items/items.types.js | 2 +
8 files changed, 101 insertions(+), 30 deletions(-)
diff --git a/client/src/containers/Items/ItemForm.js b/client/src/containers/Items/ItemForm.js
index cde7897fc..0faf86e95 100644
--- a/client/src/containers/Items/ItemForm.js
+++ b/client/src/containers/Items/ItemForm.js
@@ -15,7 +15,7 @@ import { Row, Col } from 'react-grid-system';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { Select } from '@blueprintjs/select';
import { queryCache } from 'react-query';
-import {useParams} from 'react-router-dom';
+import {useParams ,useHistory} from 'react-router-dom';
import AppToaster from 'components/AppToaster';
import { compose } from 'utils';
import ErrorMessage from 'components/ErrorMessage';
@@ -27,13 +27,13 @@ import withAccounts from 'containers/Accounts/withAccounts';
import withMediaActions from 'containers/Media/withMediaActions';
import MoneyInputGroup from 'components/MoneyInputGroup';
-import { useHistory } from 'react-router-dom';
import Dragzone from 'components/Dragzone';
import useMedia from 'hooks/useMedia';
import withItems from './withItems';
import withItemDetail from 'containers/Items/withItemDetail'
import { pick } from 'lodash';
import withDashboardActions from 'containers/Dashboard/withDashboard';
+import withAccountDetail from 'containers/Accounts/withAccountDetail';
const ItemForm = ({
@@ -42,11 +42,10 @@ const ItemForm = ({
requestSubmitItem,
requestEditItem,
-
accounts,
- accountsTypes,
itemDetail,
-
+ onFormSubmit,
+ onCancelForm,
// #withDashboard
@@ -65,7 +64,7 @@ const ItemForm = ({
}) => {
const [selectedAccounts, setSelectedAccounts] = useState({});
- const [selectedAccountType, setSelectedAccountType] = useState(null);
+ const [payload, setPayload] = useState({});
const history = useHistory();
const { formatMessage } = useIntl();
@@ -132,6 +131,9 @@ const ItemForm = ({
}
}), [itemDetail, defaultInitialValues]);
+ const saveInvokeSubmit = useCallback((payload) => {
+ onFormSubmit && onFormSubmit(payload)
+ }, [onFormSubmit]);
useEffect(() => {
itemDetail && itemDetail.id ?
@@ -170,6 +172,8 @@ const ItemForm = ({
intent:Intent.SUCCESS
});
setSubmitting(false);
+ saveInvokeSubmit({action:'update',...payload})
+ history.push('/items');
resetForm();
}).catch((errors)=>{
setSubmitting(false)
@@ -229,18 +233,6 @@ const ItemForm = ({
};
-// Set default
- // useEffect(()=>{
-
- // if(itemDetail && itemDetail.id){
- // const defaultType = itemDetail.find(
- // (t) => t.id === itemDetail.id
- // );
-
- // defaultType && setSelectedAccountType(defaultType);
- // }
-
- // },[])
const onItemAccountSelect = useCallback(
(filedName) => {
return (account) => {
@@ -637,10 +629,10 @@ const ItemForm = ({
};
export default compose(
- withAccounts(({accounts,accountsTypes})=>({
+ withAccounts(({accounts})=>({
accounts,
- accountsTypes
})),
+ withAccountDetail,
withItemsActions,
withItemDetail,
withItemCategories(({ categoriesList }) => ({
diff --git a/client/src/containers/Items/ItemsActionsBar.js b/client/src/containers/Items/ItemsActionsBar.js
index 99f647168..1b061c2bd 100644
--- a/client/src/containers/Items/ItemsActionsBar.js
+++ b/client/src/containers/Items/ItemsActionsBar.js
@@ -17,7 +17,7 @@ import { compose } from 'utils';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import Icon from 'components/Icon';
import FilterDropdown from 'components/FilterDropdown';
-import DialogConnect from 'connectors/Dialog.connector';
+import withDialog from 'connectors/Dialog.connector';
import withResourceDetail from 'containers/Resources/withResourceDetails';
import withItems from 'containers/Items/withItems';
import { If } from 'components';
@@ -34,6 +34,7 @@ const ItemsActionsBar = ({
onFilterChanged,
selectedRows = [],
+ onBulkDelete,
}) => {
const { path } = useRouteMatch();
const history = useHistory();
@@ -43,9 +44,11 @@ const ItemsActionsBar = ({
));
- const onClickNewItem = () => {
+
+ const onClickNewItem = useCallback(() => {
history.push('/items/new');
- };
+ }, [history]);
+
const hasSelectedRows = useMemo(() => selectedRows.length > 0, [
selectedRows,
]);
@@ -61,6 +64,11 @@ const ItemsActionsBar = ({
const onClickNewCategory = useCallback(() => {
openDialog('item-form', {});
}, [openDialog]);
+
+ const handleBulkDelete = useCallback(() => {
+ onBulkDelete && onBulkDelete(selectedRows.map(r => r.id));
+ }, [onBulkDelete, selectedRows]);
+
return (
@@ -116,9 +124,10 @@ const ItemsActionsBar = ({
}
+ text={}
intent={Intent.DANGER}
- icon={}
- text={}
+ onClick={handleBulkDelete}
/>
@@ -138,7 +147,7 @@ const ItemsActionsBar = ({
};
export default compose(
- DialogConnect,
+ withDialog,
withItems(({ itemsViews }) => ({
itemsViews,
})),
diff --git a/client/src/containers/Items/ItemsDataTable.js b/client/src/containers/Items/ItemsDataTable.js
index 948592498..5fe5e6260 100644
--- a/client/src/containers/Items/ItemsDataTable.js
+++ b/client/src/containers/Items/ItemsDataTable.js
@@ -137,6 +137,9 @@ const ItemsDataTable = ({
onFetchData={handleFetchData}
loading={itemsTableLoading && !initialMount}
noInitialFetch={true}
+ expandable={true}
+ treeGraph={true}
+ spinnerProps={{size: 30}}
onSelectedRowsChange={handleSelectedRowsChange} />
);
diff --git a/client/src/containers/Items/ItemsList.js b/client/src/containers/Items/ItemsList.js
index 9648b4519..e7e2a4df9 100644
--- a/client/src/containers/Items/ItemsList.js
+++ b/client/src/containers/Items/ItemsList.js
@@ -1,4 +1,4 @@
-import React, { useEffect, useCallback, useState } from 'react';
+import React, { useEffect, useCallback, useState,useMemo } from 'react';
import {
Route,
Switch,
@@ -43,10 +43,12 @@ function ItemsList({
requestDeleteItem,
requestFetchItems,
addItemsTableQueries,
+ requestDeleteBulkItems,
}) {
const [deleteItem, setDeleteItem] = useState(false);
const [selectedRows, setSelectedRows] = useState([]);
const [tableLoading, setTableLoading] = useState(false);
+ const [bulkDelete, setBulkDelete] = useState(false);
const { formatMessage } = useIntl();
@@ -130,8 +132,35 @@ function ItemsList({
const handleSelectedRowsChange = useCallback((accounts) => {
setSelectedRows(accounts);
}, [setSelectedRows]);
-
+ // Calculates the data table selected rows count.
+ const selectedRowsCount = useMemo(() => Object.values(selectedRows).length, [selectedRows]);
+
+
+
+ // Handle items bulk delete button click.,
+
+ const handleBulkDelete = useCallback((itemsIds) => {
+ setBulkDelete(itemsIds);
+ }, [setBulkDelete]);
+
+ // Handle confirm items bulk delete.
+ const handleConfirmBulkDelete = useCallback(() => {
+ requestDeleteBulkItems(bulkDelete).then(() => {
+ setBulkDelete(false);
+ AppToaster.show({
+ message: formatMessage({ id: 'the_items_has_been_successfully_deleted' }),
+ intent: Intent.SUCCESS,
+ });
+ }).catch((errors) => {
+ setBulkDelete(false);
+ });
+ }, [requestDeleteBulkItems, bulkDelete]);
+
+ // Handle cancel accounts bulk delete.
+ const handleCancelBulkDelete = useCallback(() => {
+ setBulkDelete(false);
+ }, []);
return (
@@ -140,8 +169,9 @@ function ItemsList({
name={'items-list'}>
+ onBulkDelete={handleBulkDelete}/>
@@ -174,6 +204,20 @@ function ItemsList({
id={'once_delete_this_item_you_will_able_to_restore_it'} />
+
+ }
+ confirmButtonText={`${formatMessage({id:'delete'})} (${selectedRowsCount})`}
+ icon="trash"
+ intent={Intent.DANGER}
+ isOpen={bulkDelete}
+ onCancel={handleCancelBulkDelete}
+ onConfirm={handleConfirmBulkDelete}
+ >
+
+
+
+
diff --git a/client/src/containers/Items/withItemsActions.js b/client/src/containers/Items/withItemsActions.js
index 9be79e2e3..fc8cafe94 100644
--- a/client/src/containers/Items/withItemsActions.js
+++ b/client/src/containers/Items/withItemsActions.js
@@ -4,12 +4,14 @@ import {
deleteItem,
submitItem,
editItem,
+ deleteBulkItems
} from 'store/items/items.actions';
import t from 'store/types';
export const mapDispatchToProps = (dispatch) => ({
requestFetchItems: (query) => dispatch(fetchItems({ query })),
requestDeleteItem: (id) => dispatch(deleteItem({ id })),
+ requestDeleteBulkItems:(ids)=>dispatch(deleteBulkItems({ids})),
requestSubmitItem: (form) => dispatch(submitItem({ form })),
requestEditItem:(id,form) => dispatch(editItem({id,form})),
addBulkActionItem: (id) => dispatch({
diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js
index b32e523f8..0d0e5a735 100644
--- a/client/src/lang/en/index.js
+++ b/client/src/lang/en/index.js
@@ -322,7 +322,10 @@ export default {
organization_industry_:'Organization industry',
base_currency_:'Base currency',
date_format_:'Date format',
- view_name_:'View name'
+ category_name_:'Category name',
+ view_name_:'View name',
+ the_items_has_been_successfully_deleted: 'The items have been successfully deleted.',
+ once_delete_these_items_you_will_not_able_restore_them: 'Once you delete these items, you won\'t be able to retrieve them later. Are you sure you want to delete them?',
};
diff --git a/client/src/store/items/items.actions.js b/client/src/store/items/items.actions.js
index bbb1a3eef..461bd949b 100644
--- a/client/src/store/items/items.actions.js
+++ b/client/src/store/items/items.actions.js
@@ -76,3 +76,19 @@ export const deleteItem = ({ id }) => {
}).catch((error) => { reject(error); });
});
};
+
+
+
+export const deleteBulkItems = ({ ids }) => {
+ return dispatch => new Promise((resolve, reject) => {
+ ApiService.delete(`items`, { params: { ids }}).then((response) => {
+ dispatch({
+ type: t.ITEMS_BULK_DELETE,
+ payload: { ids }
+ });
+ resolve(response);
+ }).catch((error) => {
+ reject(error);
+ });
+ });
+};
diff --git a/client/src/store/items/items.types.js b/client/src/store/items/items.types.js
index 3d9c5b621..44561af21 100644
--- a/client/src/store/items/items.types.js
+++ b/client/src/store/items/items.types.js
@@ -12,4 +12,6 @@ export default {
ITEMS_TABLE_LOADING: 'ITEMS_TABLE_LOADING',
ITEMS_SET_CURRENT_VIEW: 'ITEMS_SET_CURRENT_VIEW',
+ ITEMS_BULK_DELETE:'ITEMS_BULK_DELETE'
+
};