From 4b798e4ea0e082dfbeb9642e7a2d14c640a432ae Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Mon, 18 Jan 2021 22:53:02 +0200 Subject: [PATCH 1/2] feat: global hotkeys. --- client/package.json | 1 + client/src/common/quickNewOptions.js | 10 ++--- client/src/components/Dashboard/Dashboard.js | 5 ++- .../src/components/Dashboard/GlobalHotkeys.js | 43 +++++++++++++++++++ .../QuickNewDropdown/QuickNewDropdown.js | 1 + client/src/routes/dashboard.js | 30 ++++++++++++- 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 client/src/components/Dashboard/GlobalHotkeys.js diff --git a/client/package.json b/client/package.json index 976cf75fa..ac135d979 100644 --- a/client/package.json +++ b/client/package.json @@ -73,6 +73,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..5ad34c5de 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: 'invoices', name: 'Sale invoice', label: 'Shift+I' }, { id: 'Purchase invoice', name: 'Purchase invoice' }, - { id: 'manual-journals', name: 'Manual journal' }, - { id: 'expenses', name: 'Expense' }, - { id: 'customers', name: 'Customer' }, - { id: 'vendors', name: 'Vendor' }, + { id: 'manual-journals', name: 'Manual journal', label: 'Shift+M' }, + { id: 'expenses', name: 'Expense', label: 'Shift+X' }, + { id: 'customers', name: 'Customer', label: 'Shift+C' }, + { id: 'vendors', name: 'Vendor', label: '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..13b30623d --- /dev/null +++ b/client/src/components/Dashboard/GlobalHotkeys.js @@ -0,0 +1,43 @@ +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, + recordSidebarPreviousExpand, +}) { + const history = useHistory(); + + const globalHotkeys = (function (array) { + const result = []; + array.forEach(({ hotkey }) => + typeof hotkey !== 'undefined' ? result.push(hotkey) : null, + ); + return result.toString(); + })(routes); + + const handleSidebarToggleBtn = () => { + toggleSidebarExpend(); + recordSidebarPreviousExpand(); + }; + 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..0d9cdc982 100644 --- a/client/src/containers/QuickNewDropdown/QuickNewDropdown.js +++ b/client/src/containers/QuickNewDropdown/QuickNewDropdown.js @@ -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', }, From d14e5d6fa7d0d1783350f13cf0a90c304c26ee85 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Tue, 19 Jan 2021 12:23:05 +0200 Subject: [PATCH 2/2] fix:globalhotkeys & quick new. --- client/src/common/quickNewOptions.js | 12 ++++++------ .../src/components/Dashboard/GlobalHotkeys.js | 18 ++++++------------ .../QuickNewDropdown/QuickNewDropdown.js | 4 ++-- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/client/src/common/quickNewOptions.js b/client/src/common/quickNewOptions.js index 5ad34c5de..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', label: 'Shift+I' }, - { id: 'Purchase invoice', name: 'Purchase invoice' }, - { id: 'manual-journals', name: 'Manual journal', label: 'Shift+M' }, - { id: 'expenses', name: 'Expense', label: 'Shift+X' }, - { id: 'customers', name: 'Customer', label: 'Shift+C' }, - { id: 'vendors', name: 'Vendor', label: 'Shift+V' }, + { 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/GlobalHotkeys.js b/client/src/components/Dashboard/GlobalHotkeys.js index 13b30623d..353c1c755 100644 --- a/client/src/components/Dashboard/GlobalHotkeys.js +++ b/client/src/components/Dashboard/GlobalHotkeys.js @@ -5,25 +5,19 @@ import routes from 'routes/dashboard'; import withDashboardActions from 'containers/Dashboard/withDashboardActions'; import { compose } from 'utils'; - function GlobalHotkeys({ // #withDashboardActions toggleSidebarExpend, - recordSidebarPreviousExpand, }) { const history = useHistory(); - const globalHotkeys = (function (array) { - const result = []; - array.forEach(({ hotkey }) => - typeof hotkey !== 'undefined' ? result.push(hotkey) : null, - ); - return result.toString(); - })(routes); - - const handleSidebarToggleBtn = () => { + const globalHotkeys = routes + .filter(({ hotkey }) => hotkey) + .map(({ hotkey }) => hotkey) + .toString(); + + const handleSidebarToggleBtn = () => { toggleSidebarExpend(); - recordSidebarPreviousExpand(); }; useHotkeys( globalHotkeys, diff --git a/client/src/containers/QuickNewDropdown/QuickNewDropdown.js b/client/src/containers/QuickNewDropdown/QuickNewDropdown.js index 0d9cdc982..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 (