diff --git a/client/package.json b/client/package.json
index 15ac6d124..42dc97aed 100644
--- a/client/package.json
+++ b/client/package.json
@@ -74,6 +74,7 @@
"react-error-boundary": "^3.0.2",
"react-grid-system": "^6.2.3",
"react-hook-form": "^4.9.4",
+ "react-hotkeys-hook": "^3.0.3",
"react-intl": "^3.12.0",
"react-loadable": "^5.5.0",
"react-query": "^2.4.6",
diff --git a/client/src/common/quickNewOptions.js b/client/src/common/quickNewOptions.js
index d8b3b5003..afcec73ef 100644
--- a/client/src/common/quickNewOptions.js
+++ b/client/src/common/quickNewOptions.js
@@ -1,8 +1,8 @@
export default [
- { id: 'invoices', name: 'Sale invoice' },
- { id: 'Purchase invoice', name: 'Purchase invoice' },
- { id: 'manual-journals', name: 'Manual journal' },
- { id: 'expenses', name: 'Expense' },
- { id: 'customers', name: 'Customer' },
- { id: 'vendors', name: 'Vendor' },
+ { path: 'invoices/new', name: 'Sale invoice', label: 'Ctrl+Shift+I' },
+ { path: 'bill//new', name: 'Purchase invoice',label:'Ctrl+Shift+B' },
+ { path: 'make-journal-entry', name: 'Manual journal', label: 'Ctrl+Shift+M' },
+ { path: 'expenses/new', name: 'Expense', label: 'Ctrl+Shift+X' },
+ { path: 'customers/new', name: 'Customer', label: 'Ctrl+Shift+C' },
+ { path: 'vendors/new', name: 'Vendor', label: 'Ctrl+Shift+V' },
];
diff --git a/client/src/components/Dashboard/Dashboard.js b/client/src/components/Dashboard/Dashboard.js
index 3e46f4ce5..6ead8488c 100644
--- a/client/src/components/Dashboard/Dashboard.js
+++ b/client/src/components/Dashboard/Dashboard.js
@@ -10,12 +10,12 @@ import DialogsContainer from 'components/DialogsContainer';
import PreferencesPage from 'components/Preferences/PreferencesPage';
import Search from 'containers/GeneralSearch/Search';
import DashboardSplitPane from 'components/Dashboard/DashboardSplitePane';
-
+import GlobalHotkeys from './GlobalHotkeys';
import withSettingsActions from 'containers/Settings/withSettingsActions';
import { compose } from 'utils';
-import 'style/pages/Dashboard/Dashboard.scss'
+import 'style/pages/Dashboard/Dashboard.scss';
/**
* Dashboard page.
@@ -46,6 +46,7 @@ function Dashboard({
+
);
}
diff --git a/client/src/components/Dashboard/GlobalHotkeys.js b/client/src/components/Dashboard/GlobalHotkeys.js
new file mode 100644
index 000000000..353c1c755
--- /dev/null
+++ b/client/src/components/Dashboard/GlobalHotkeys.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useHotkeys } from 'react-hotkeys-hook';
+import { useHistory } from 'react-router-dom';
+import routes from 'routes/dashboard';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import { compose } from 'utils';
+
+function GlobalHotkeys({
+ // #withDashboardActions
+ toggleSidebarExpend,
+}) {
+ const history = useHistory();
+
+ const globalHotkeys = routes
+ .filter(({ hotkey }) => hotkey)
+ .map(({ hotkey }) => hotkey)
+ .toString();
+
+ const handleSidebarToggleBtn = () => {
+ toggleSidebarExpend();
+ };
+ useHotkeys(
+ globalHotkeys,
+ (event, handle) => {
+ routes.map(({ path, hotkey }) => {
+ if (handle.key === hotkey) {
+ history.push(path);
+ }
+ });
+ },
+ [history],
+ );
+ useHotkeys('ctrl+/', (event, handle) => handleSidebarToggleBtn());
+ return
;
+}
+
+export default compose(withDashboardActions)(GlobalHotkeys);
diff --git a/client/src/containers/QuickNewDropdown/QuickNewDropdown.js b/client/src/containers/QuickNewDropdown/QuickNewDropdown.js
index 7ad6912d9..9e82291f1 100644
--- a/client/src/containers/QuickNewDropdown/QuickNewDropdown.js
+++ b/client/src/containers/QuickNewDropdown/QuickNewDropdown.js
@@ -12,8 +12,8 @@ import quickNewOptions from 'common/quickNewOptions';
function QuickNewDropdown() {
const history = useHistory();
- const handleClickQuickNew = ({ id }) => {
- history.push(`/${id}`);
+ const handleClickQuickNew = ({path }) => {
+ history.push(`/${path}`);
};
return (
@@ -21,6 +21,7 @@ function QuickNewDropdown() {
items={quickNewOptions}
onItemSelect={(type) => handleClickQuickNew(type)}
textProp={'name'}
+ labelProp={'label'}
filterable={false}
popoverProps={{ minimal: false, position: Position.BOTTOM }}
defaultText={'Select'}
diff --git a/client/src/routes/dashboard.js b/client/src/routes/dashboard.js
index 7127cb81e..9516d827b 100644
--- a/client/src/routes/dashboard.js
+++ b/client/src/routes/dashboard.js
@@ -18,6 +18,7 @@ export default [
loader: () => import('containers/Accounts/AccountsChart'),
}),
breadcrumb: 'Accounts Chart',
+ hotkey: 'shift+a',
},
// Custom views.
{
@@ -41,6 +42,7 @@ export default [
loader: () => import('containers/Accounting/MakeJournalEntriesPage'),
}),
breadcrumb: 'Make Journal Entry',
+ hotkey: 'ctrl+shift+m',
},
{
path: `/manual-journals/:id/edit`,
@@ -55,6 +57,7 @@ export default [
loader: () => import('containers/Accounting/ManualJournalsList'),
}),
breadcrumb: 'Manual Journals',
+ hotkey: 'shift+m',
},
{
path: `/items/categories`,
@@ -77,6 +80,7 @@ export default [
loader: () => import('containers/Items/ItemFormPage'),
}),
breadcrumb: 'New Item',
+ hotkey: 'ctrl+shift+w',
},
{
path: `/items`,
@@ -84,6 +88,7 @@ export default [
loader: () => import('containers/Items/ItemsList'),
}),
breadcrumb: 'Items',
+ hotkey: 'shift+w',
},
// Inventory adjustments.
@@ -103,6 +108,7 @@ export default [
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
}),
breadcrumb: 'General Ledger',
+ hotkey: 'shift+4',
},
{
path: `/financial-reports/balance-sheet`,
@@ -111,6 +117,7 @@ export default [
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
}),
breadcrumb: 'Balance Sheet',
+ hotkey: 'shift+1',
},
{
path: `/financial-reports/trial-balance-sheet`,
@@ -121,6 +128,7 @@ export default [
),
}),
breadcrumb: 'Trial Balance Sheet',
+ hotkey: 'shift+5',
},
{
path: `/financial-reports/profit-loss-sheet`,
@@ -131,6 +139,7 @@ export default [
),
}),
breadcrumb: 'Profit Loss Sheet',
+ hotkey: 'shift+2',
},
{
path: '/financial-reports/receivable-aging-summary',
@@ -146,6 +155,7 @@ export default [
loader: () => import('containers/FinancialStatements/Journal/Journal'),
}),
breadcrumb: 'Journal Sheet',
+ hotkey: 'shift+3',
},
{
path: '/financial-reports',
@@ -169,6 +179,7 @@ export default [
loader: () => import('containers/Expenses/ExpenseFormPage'),
}),
breadcrumb: 'Expenses',
+ hotkey: 'ctrl+shift+x',
},
{
path: `/expenses/:id/edit`,
@@ -183,6 +194,7 @@ export default [
loader: () => import('containers/Expenses/ExpensesList'),
}),
breadcrumb: 'Expenses List',
+ hotkey: 'shift+x',
},
// Customers
@@ -199,6 +211,7 @@ export default [
loader: () => import('containers/Customers/CustomerFormPage'),
}),
breadcrumb: 'New Customer',
+ hotkey: 'ctrl+shift+c',
},
{
path: `/customers`,
@@ -206,6 +219,7 @@ export default [
loader: () => import('containers/Customers/CustomersList'),
}),
breadcrumb: 'Customers',
+ hotkey: 'shift+c',
},
// Vendors
@@ -222,6 +236,7 @@ export default [
loader: () => import('containers/Vendors/VendorFormPage'),
}),
breadcrumb: 'New Vendor',
+ hotkey: 'ctrl+shift+v',
},
{
path: `/vendors`,
@@ -229,6 +244,7 @@ export default [
loader: () => import('containers/Vendors/VendorsList'),
}),
breadcrumb: 'Vendors',
+ hotkey: 'shift+v',
},
// Estimates
@@ -245,6 +261,7 @@ export default [
loader: () => import('containers/Sales/Estimate/EstimateFormPage'),
}),
breadcrumb: 'New Estimate',
+ hotkey: 'ctrl+shift+e',
},
{
path: `/estimates`,
@@ -252,6 +269,7 @@ export default [
loader: () => import('containers/Sales/Estimate/EstimatesList'),
}),
breadcrumb: 'Estimates List',
+ hotkey: 'shift+e',
},
// Invoices.
@@ -268,6 +286,7 @@ export default [
loader: () => import('containers/Sales/Invoice/InvoiceFormPage'),
}),
breadcrumb: 'New Invoice',
+ hotkey: 'ctrl+shift+i',
},
{
path: `/invoices`,
@@ -275,6 +294,7 @@ export default [
loader: () => import('containers/Sales/Invoice/InvoicesList'),
}),
breadcrumb: 'Invoices List',
+ hotkey: 'shift+i',
},
// Sales Receipts.
@@ -291,6 +311,7 @@ export default [
loader: () => import('containers/Sales/Receipt/ReceiptFormPage'),
}),
breadcrumb: 'New Receipt',
+ hotkey: 'ctrl+shift+r',
},
{
path: `/receipts`,
@@ -298,6 +319,7 @@ export default [
loader: () => import('containers/Sales/Receipt/ReceiptsList'),
}),
breadcrumb: 'Receipts List',
+ hotkey: 'shift+r',
},
// Payment receives
@@ -340,6 +362,7 @@ export default [
loader: () => import('containers/Purchases/Bill/BillFormPage'),
}),
breadcrumb: 'New Bill',
+ hotkey: 'ctrl+shift+b',
},
{
path: `/bills`,
@@ -347,6 +370,7 @@ export default [
loader: () => import('containers/Purchases/Bill/BillsList'),
}),
breadcrumb: 'Bills List',
+ hotkey: 'shift+b',
},
// Subscription billing.
@@ -361,14 +385,16 @@ export default [
{
path: `/payment-mades/:id/edit`,
component: LazyLoader({
- loader: () => import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
+ loader: () =>
+ import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
}),
breadcrumb: 'Edit',
},
{
path: `/payment-mades/new`,
component: LazyLoader({
- loader: () => import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
+ loader: () =>
+ import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
}),
breadcrumb: 'New Payment Made',
},