mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat: global hotkeys.
This commit is contained in:
@@ -73,6 +73,7 @@
|
|||||||
"react-error-boundary": "^3.0.2",
|
"react-error-boundary": "^3.0.2",
|
||||||
"react-grid-system": "^6.2.3",
|
"react-grid-system": "^6.2.3",
|
||||||
"react-hook-form": "^4.9.4",
|
"react-hook-form": "^4.9.4",
|
||||||
|
"react-hotkeys-hook": "^3.0.3",
|
||||||
"react-intl": "^3.12.0",
|
"react-intl": "^3.12.0",
|
||||||
"react-loadable": "^5.5.0",
|
"react-loadable": "^5.5.0",
|
||||||
"react-query": "^2.4.6",
|
"react-query": "^2.4.6",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export default [
|
export default [
|
||||||
{ id: 'invoices', name: 'Sale invoice' },
|
{ id: 'invoices', name: 'Sale invoice', label: 'Shift+I' },
|
||||||
{ id: 'Purchase invoice', name: 'Purchase invoice' },
|
{ id: 'Purchase invoice', name: 'Purchase invoice' },
|
||||||
{ id: 'manual-journals', name: 'Manual journal' },
|
{ id: 'manual-journals', name: 'Manual journal', label: 'Shift+M' },
|
||||||
{ id: 'expenses', name: 'Expense' },
|
{ id: 'expenses', name: 'Expense', label: 'Shift+X' },
|
||||||
{ id: 'customers', name: 'Customer' },
|
{ id: 'customers', name: 'Customer', label: 'Shift+C' },
|
||||||
{ id: 'vendors', name: 'Vendor' },
|
{ id: 'vendors', name: 'Vendor', label: 'Shift+V' },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import DialogsContainer from 'components/DialogsContainer';
|
|||||||
import PreferencesPage from 'components/Preferences/PreferencesPage';
|
import PreferencesPage from 'components/Preferences/PreferencesPage';
|
||||||
import Search from 'containers/GeneralSearch/Search';
|
import Search from 'containers/GeneralSearch/Search';
|
||||||
import DashboardSplitPane from 'components/Dashboard/DashboardSplitePane';
|
import DashboardSplitPane from 'components/Dashboard/DashboardSplitePane';
|
||||||
|
import GlobalHotkeys from './GlobalHotkeys';
|
||||||
import withSettingsActions from 'containers/Settings/withSettingsActions';
|
import withSettingsActions from 'containers/Settings/withSettingsActions';
|
||||||
|
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
import 'style/pages/Dashboard/Dashboard.scss'
|
import 'style/pages/Dashboard/Dashboard.scss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard page.
|
* Dashboard page.
|
||||||
@@ -46,6 +46,7 @@ function Dashboard({
|
|||||||
|
|
||||||
<Search />
|
<Search />
|
||||||
<DialogsContainer />
|
<DialogsContainer />
|
||||||
|
<GlobalHotkeys />
|
||||||
</DashboardLoadingIndicator>
|
</DashboardLoadingIndicator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
43
client/src/components/Dashboard/GlobalHotkeys.js
Normal file
43
client/src/components/Dashboard/GlobalHotkeys.js
Normal file
@@ -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 <div></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(withDashboardActions)(GlobalHotkeys);
|
||||||
@@ -21,6 +21,7 @@ function QuickNewDropdown() {
|
|||||||
items={quickNewOptions}
|
items={quickNewOptions}
|
||||||
onItemSelect={(type) => handleClickQuickNew(type)}
|
onItemSelect={(type) => handleClickQuickNew(type)}
|
||||||
textProp={'name'}
|
textProp={'name'}
|
||||||
|
labelProp={'label'}
|
||||||
filterable={false}
|
filterable={false}
|
||||||
popoverProps={{ minimal: false, position: Position.BOTTOM }}
|
popoverProps={{ minimal: false, position: Position.BOTTOM }}
|
||||||
defaultText={'Select'}
|
defaultText={'Select'}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export default [
|
|||||||
loader: () => import('containers/Accounts/AccountsChart'),
|
loader: () => import('containers/Accounts/AccountsChart'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Accounts Chart',
|
breadcrumb: 'Accounts Chart',
|
||||||
|
hotkey: 'shift+a',
|
||||||
},
|
},
|
||||||
// Custom views.
|
// Custom views.
|
||||||
{
|
{
|
||||||
@@ -41,6 +42,7 @@ export default [
|
|||||||
loader: () => import('containers/Accounting/MakeJournalEntriesPage'),
|
loader: () => import('containers/Accounting/MakeJournalEntriesPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Make Journal Entry',
|
breadcrumb: 'Make Journal Entry',
|
||||||
|
hotkey: 'ctrl+shift+m',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/manual-journals/:id/edit`,
|
path: `/manual-journals/:id/edit`,
|
||||||
@@ -55,6 +57,7 @@ export default [
|
|||||||
loader: () => import('containers/Accounting/ManualJournalsList'),
|
loader: () => import('containers/Accounting/ManualJournalsList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Manual Journals',
|
breadcrumb: 'Manual Journals',
|
||||||
|
hotkey: 'shift+m',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/items/categories`,
|
path: `/items/categories`,
|
||||||
@@ -77,6 +80,7 @@ export default [
|
|||||||
loader: () => import('containers/Items/ItemFormPage'),
|
loader: () => import('containers/Items/ItemFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Item',
|
breadcrumb: 'New Item',
|
||||||
|
hotkey: 'ctrl+shift+w',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/items`,
|
path: `/items`,
|
||||||
@@ -84,6 +88,7 @@ export default [
|
|||||||
loader: () => import('containers/Items/ItemsList'),
|
loader: () => import('containers/Items/ItemsList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Items',
|
breadcrumb: 'Items',
|
||||||
|
hotkey: 'shift+w',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Inventory adjustments.
|
// Inventory adjustments.
|
||||||
@@ -103,6 +108,7 @@ export default [
|
|||||||
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
|
import('containers/FinancialStatements/GeneralLedger/GeneralLedger'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'General Ledger',
|
breadcrumb: 'General Ledger',
|
||||||
|
hotkey: 'shift+4',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/financial-reports/balance-sheet`,
|
path: `/financial-reports/balance-sheet`,
|
||||||
@@ -111,6 +117,7 @@ export default [
|
|||||||
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
|
import('containers/FinancialStatements/BalanceSheet/BalanceSheet'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Balance Sheet',
|
breadcrumb: 'Balance Sheet',
|
||||||
|
hotkey: 'shift+1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/financial-reports/trial-balance-sheet`,
|
path: `/financial-reports/trial-balance-sheet`,
|
||||||
@@ -121,6 +128,7 @@ export default [
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Trial Balance Sheet',
|
breadcrumb: 'Trial Balance Sheet',
|
||||||
|
hotkey: 'shift+5',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/financial-reports/profit-loss-sheet`,
|
path: `/financial-reports/profit-loss-sheet`,
|
||||||
@@ -131,6 +139,7 @@ export default [
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Profit Loss Sheet',
|
breadcrumb: 'Profit Loss Sheet',
|
||||||
|
hotkey: 'shift+2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/financial-reports/receivable-aging-summary',
|
path: '/financial-reports/receivable-aging-summary',
|
||||||
@@ -146,6 +155,7 @@ export default [
|
|||||||
loader: () => import('containers/FinancialStatements/Journal/Journal'),
|
loader: () => import('containers/FinancialStatements/Journal/Journal'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Journal Sheet',
|
breadcrumb: 'Journal Sheet',
|
||||||
|
hotkey: 'shift+3',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/financial-reports',
|
path: '/financial-reports',
|
||||||
@@ -169,6 +179,7 @@ export default [
|
|||||||
loader: () => import('containers/Expenses/ExpenseFormPage'),
|
loader: () => import('containers/Expenses/ExpenseFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Expenses',
|
breadcrumb: 'Expenses',
|
||||||
|
hotkey: 'ctrl+shift+x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/expenses/:id/edit`,
|
path: `/expenses/:id/edit`,
|
||||||
@@ -183,6 +194,7 @@ export default [
|
|||||||
loader: () => import('containers/Expenses/ExpensesList'),
|
loader: () => import('containers/Expenses/ExpensesList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Expenses List',
|
breadcrumb: 'Expenses List',
|
||||||
|
hotkey: 'shift+x',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Customers
|
// Customers
|
||||||
@@ -199,6 +211,7 @@ export default [
|
|||||||
loader: () => import('containers/Customers/CustomerFormPage'),
|
loader: () => import('containers/Customers/CustomerFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Customer',
|
breadcrumb: 'New Customer',
|
||||||
|
hotkey: 'ctrl+shift+c',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/customers`,
|
path: `/customers`,
|
||||||
@@ -206,6 +219,7 @@ export default [
|
|||||||
loader: () => import('containers/Customers/CustomersList'),
|
loader: () => import('containers/Customers/CustomersList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Customers',
|
breadcrumb: 'Customers',
|
||||||
|
hotkey: 'shift+c',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Vendors
|
// Vendors
|
||||||
@@ -222,6 +236,7 @@ export default [
|
|||||||
loader: () => import('containers/Vendors/VendorFormPage'),
|
loader: () => import('containers/Vendors/VendorFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Vendor',
|
breadcrumb: 'New Vendor',
|
||||||
|
hotkey: 'ctrl+shift+v',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/vendors`,
|
path: `/vendors`,
|
||||||
@@ -229,6 +244,7 @@ export default [
|
|||||||
loader: () => import('containers/Vendors/VendorsList'),
|
loader: () => import('containers/Vendors/VendorsList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Vendors',
|
breadcrumb: 'Vendors',
|
||||||
|
hotkey: 'shift+v',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Estimates
|
// Estimates
|
||||||
@@ -245,6 +261,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Estimate/EstimateFormPage'),
|
loader: () => import('containers/Sales/Estimate/EstimateFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Estimate',
|
breadcrumb: 'New Estimate',
|
||||||
|
hotkey: 'ctrl+shift+e',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/estimates`,
|
path: `/estimates`,
|
||||||
@@ -252,6 +269,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Estimate/EstimatesList'),
|
loader: () => import('containers/Sales/Estimate/EstimatesList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Estimates List',
|
breadcrumb: 'Estimates List',
|
||||||
|
hotkey: 'shift+e',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Invoices.
|
// Invoices.
|
||||||
@@ -268,6 +286,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Invoice/InvoiceFormPage'),
|
loader: () => import('containers/Sales/Invoice/InvoiceFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Invoice',
|
breadcrumb: 'New Invoice',
|
||||||
|
hotkey: 'ctrl+shift+i',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/invoices`,
|
path: `/invoices`,
|
||||||
@@ -275,6 +294,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Invoice/InvoicesList'),
|
loader: () => import('containers/Sales/Invoice/InvoicesList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Invoices List',
|
breadcrumb: 'Invoices List',
|
||||||
|
hotkey: 'shift+i',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sales Receipts.
|
// Sales Receipts.
|
||||||
@@ -291,6 +311,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Receipt/ReceiptFormPage'),
|
loader: () => import('containers/Sales/Receipt/ReceiptFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Receipt',
|
breadcrumb: 'New Receipt',
|
||||||
|
hotkey: 'ctrl+shift+r',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/receipts`,
|
path: `/receipts`,
|
||||||
@@ -298,6 +319,7 @@ export default [
|
|||||||
loader: () => import('containers/Sales/Receipt/ReceiptsList'),
|
loader: () => import('containers/Sales/Receipt/ReceiptsList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Receipts List',
|
breadcrumb: 'Receipts List',
|
||||||
|
hotkey: 'shift+r',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Payment receives
|
// Payment receives
|
||||||
@@ -340,6 +362,7 @@ export default [
|
|||||||
loader: () => import('containers/Purchases/Bill/BillFormPage'),
|
loader: () => import('containers/Purchases/Bill/BillFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Bill',
|
breadcrumb: 'New Bill',
|
||||||
|
hotkey: 'ctrl+shift+b',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/bills`,
|
path: `/bills`,
|
||||||
@@ -347,6 +370,7 @@ export default [
|
|||||||
loader: () => import('containers/Purchases/Bill/BillsList'),
|
loader: () => import('containers/Purchases/Bill/BillsList'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Bills List',
|
breadcrumb: 'Bills List',
|
||||||
|
hotkey: 'shift+b',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Subscription billing.
|
// Subscription billing.
|
||||||
@@ -361,14 +385,16 @@ export default [
|
|||||||
{
|
{
|
||||||
path: `/payment-mades/:id/edit`,
|
path: `/payment-mades/:id/edit`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
|
loader: () =>
|
||||||
|
import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'Edit',
|
breadcrumb: 'Edit',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: `/payment-mades/new`,
|
path: `/payment-mades/new`,
|
||||||
component: LazyLoader({
|
component: LazyLoader({
|
||||||
loader: () => import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
|
loader: () =>
|
||||||
|
import('containers/Purchases/PaymentMades/PaymentMadeFormPage'),
|
||||||
}),
|
}),
|
||||||
breadcrumb: 'New Payment Made',
|
breadcrumb: 'New Payment Made',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user