diff --git a/src/common/abilityOption.js b/src/common/abilityOption.js new file mode 100644 index 000000000..9b140a5ff --- /dev/null +++ b/src/common/abilityOption.js @@ -0,0 +1,135 @@ +export const AbilitySubject = { + Item: 'Item', + Inventory_Adjustment: 'InventoryAdjustment', + Estimate: 'SaleEstimate', + Invoice: 'SaleInvoice', + Receipt: 'SaleReceipt', + PaymentReceive: 'PaymentReceive', + Bill: 'Bill', + PaymentMade: 'PaymentMade', + Customer: 'Customer', + Vendor: 'Vendor', + Account: 'Account', + ManualJournal: 'ManualJournal', + Expense: 'Expense', + Cashflow: 'Cashflow', + Report: 'Report', +}; + +export const Item_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Inventory_Adjustment_Abilities = { + Create: 'create', + View: 'view', + Delete: 'delete', +}; + +export const Estimate_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Invoice_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', + BadDebt: 'bad-debt', +}; + +export const Receipt_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Payment_Receive_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Bill_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Payment_Made_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Customer_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Vendor_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Account_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', + Transactions_Locking: 'TransactionsLocking', +}; + +export const Manual_Journal_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Expense_Abilities = { + View: 'view', + Create: 'create', + Edit: 'edit', + Delete: 'delete', +}; + +export const Cashflow_Abilities = { + View: 'view', + Create: 'create', + Delete: 'delete', +}; + +export const Report_Abilities = { + READ_BALANCE_SHEET: 'read-balance-sheet', + READ_TRIAL_BALANCE_SHEET: 'read-trial-balance-sheet', + READ_PROFIT_LOSS: 'read-profit-loss', + READ_JOURNAL: 'read-journal', + READ_GENERAL_LEDGET: 'read-general-ledger', + READ_CASHFLOW: 'read-cashflow', + READ_AR_AGING_SUMMARY: 'read-ar-aging-summary', + READ_AP_AGING_SUMMARY: 'read-ap-aging-summary', + READ_PURCHASES_BY_ITEMS: 'read-purchases-by-items', + READ_SALES_BY_ITEMS: 'read-sales-by-items', + READ_CUSTOMERS_TRANSACTIONS: 'read-customers-transactions', + READ_VENDORS_TRANSACTIONS: 'read-vendors-transactions', + READ_CUSTOMERS_SUMMARY_BALANCE: 'read-customers-summary-balance', + READ_VENDORS_SUMMARY_BALANCE: 'read-vendors-summary-balance', + READ_INVENTORY_VALUATION_SUMMARY: 'read-inventory-valuation-summary', + READ_INVENTORY_ITEM_DETAILS: 'read-inventory-item-details', + READ_CASHFLOW_ACCOUNT_TRANSACTION: 'read-cashflow-account-transactions', +}; diff --git a/src/common/homepageOptions.js b/src/common/homepageOptions.js index 82972db3a..6f61b7172 100644 --- a/src/common/homepageOptions.js +++ b/src/common/homepageOptions.js @@ -1,5 +1,20 @@ import React from 'react'; import { FormattedMessage as T } from 'components'; +import { + Invoice_Abilities, + Estimate_Abilities, + AbilitySubject, + Receipt_Abilities, + Customer_Abilities, + Payment_Receive_Abilities, + Bill_Abilities, + Vendor_Abilities, + Payment_Made_Abilities, + Account_Abilities, + Manual_Journal_Abilities, + Expense_Abilities, + Item_Abilities, +} from '../common/abilityOption'; export const accountsReceivable = [ { @@ -9,21 +24,29 @@ export const accountsReceivable = [ title: , description: , link: '/invoices', + subject: AbilitySubject.Invoice, + ability: Invoice_Abilities.View, }, { title: , description: , link: '/estimates', + subject: AbilitySubject.Estimate, + ability: Estimate_Abilities.View, }, { title: , description: , link: '/receipts', + subject: AbilitySubject.Receipt, + ability: Receipt_Abilities.View, }, { title: , description: , link: '/customers', + subject: AbilitySubject.Customer, + ability: Customer_Abilities.View, }, { title: , @@ -31,6 +54,8 @@ export const accountsReceivable = [ ), link: '/payment-receives', + subject: AbilitySubject.PaymentReceive, + ability: Payment_Receive_Abilities.View, }, ], }, @@ -46,6 +71,8 @@ export const accountsPayable = [ ), link: '/bills', + subject: AbilitySubject.Bill, + ability: Bill_Abilities.View, }, { title: , @@ -53,11 +80,15 @@ export const accountsPayable = [ ), link: '/vendors', + subject: AbilitySubject.Vendor, + ability: Vendor_Abilities.View, }, { title: , description: , link: '/payment-mades', + subject: AbilitySubject.PaymentMade, + ability: Payment_Made_Abilities.View, }, ], }, @@ -77,20 +108,32 @@ export const financialAccounting = [ /> ), link: '/accounts', + subject: AbilitySubject.Account, + ability: Account_Abilities.View, }, { - title: , - description:, + title: , + description: ( + + ), link: '/manual-journals', + subject: AbilitySubject.ManualJournal, + ability: Manual_Journal_Abilities.View, }, { - title: , - description:, + title: , + description: ( + + ), link: '/expenses', + subject: AbilitySubject.Expense, + ability: Expense_Abilities.View, }, { - title: , - description:, + title: , + description: ( + + ), link: '/financial-reports', }, ], @@ -102,19 +145,27 @@ export const productsServices = [ sectionTitle: , shortcuts: [ { - title: , - description:, + title: , + description: ( + + ), link: '/items', + subject: AbilitySubject.Item, + ability: Item_Abilities.View, }, { - title: , - description:, + title: , + description: , link: 'items/categories', }, { - title: , - description: , + title: , + description: ( + + ), link: '/inventory-adjustments', + subject: AbilitySubject.Inventory_Adjustment, + ability: Invoice_Abilities.View, }, ], }, diff --git a/src/components/Can.js b/src/components/Can.js new file mode 100644 index 000000000..a24a8d1f4 --- /dev/null +++ b/src/components/Can.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { Ability } from '@casl/ability'; +import { createContextualCan } from '@casl/react'; + +import { + Item_Abilities, + AbilitySubject, + Inventory_Adjustment_Abilities, + Estimate_Abilities, + Invoice_Abilities, + Receipt_Abilities, + PaymentReceive, + Bill_Abilities, + Payment_Made_Abilities, + Customer_Abilities, + Vendor_Abilities, + Account_Abilities, +} from '../common/abilityOption'; + +export const AbilityContext = React.createContext(); +export const Can = createContextualCan(AbilityContext.Consumer); + +const AbilityContextProvider = (props) => { + const ability = new Ability([ + { + subject: [AbilitySubject.Account], + action: [Account_Abilities.Create], + }, + { + subject: [AbilitySubject.Invoice], + action: [], + }, + ]); + + return ( + + {props.children} + + ); +}; + +export default AbilityContextProvider; diff --git a/src/components/Dashboard/DashboardProvider.js b/src/components/Dashboard/DashboardProvider.js index 5a5fce966..77195b3c1 100644 --- a/src/components/Dashboard/DashboardProvider.js +++ b/src/components/Dashboard/DashboardProvider.js @@ -1,8 +1,9 @@ import React from 'react'; +import AbilityContextProvider from '../../components/Can'; /** * Dashboard provider. */ export default function DashboardProvider({ children }) { - return children; + return {children}; } diff --git a/src/components/index.js b/src/components/index.js index f30398145..5dc3efeb7 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -59,6 +59,7 @@ import AvaterCell from './AvaterCell'; import { ItemsMultiSelect } from './Items'; import MoreMenuItems from './MoreMenutItems'; +import { Can } from './Can'; export * from './Dialog'; export * from './Menu'; @@ -156,4 +157,5 @@ export { Card, AvaterCell, MoreMenuItems, + Can, }; diff --git a/src/config/financialReportsMenu.js b/src/config/financialReportsMenu.js index 4c3226a4f..714049581 100644 --- a/src/config/financialReportsMenu.js +++ b/src/config/financialReportsMenu.js @@ -1,5 +1,6 @@ import React from 'react'; import { FormattedMessage as T } from 'components'; +import { Report_Abilities, AbilitySubject } from '../common/abilityOption'; export const financialReportMenus = [ { @@ -11,6 +12,8 @@ export const financialReportMenus = [ ), link: '/financial-reports/balance-sheet', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_BALANCE_SHEET, }, { title: , @@ -18,11 +21,15 @@ export const financialReportMenus = [ ), link: '/financial-reports/trial-balance-sheet', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_TRIAL_BALANCE_SHEET, }, { title: , desc: , link: '/financial-reports/profit-loss-sheet', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_PROFIT_LOSS, }, { title: , @@ -30,16 +37,22 @@ export const financialReportMenus = [ ), link: '/financial-reports/cash-flow', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_CASHFLOW, }, { title: , desc: , link: '/financial-reports/journal-sheet', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_JOURNAL, }, { title: , desc: , link: '/financial-reports/general-ledger', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_GENERAL_LEDGET, }, { title: , @@ -47,11 +60,15 @@ export const financialReportMenus = [ ), link: '/financial-reports/receivable-aging-summary', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_AR_AGING_SUMMARY, }, { title: , desc: , link: '/financial-reports/payable-aging-summary', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_AP_AGING_SUMMARY, }, ], }, @@ -71,6 +88,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/purchases-by-items', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_PURCHASES_BY_ITEMS, }, { title: , @@ -82,6 +101,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/sales-by-items', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_SALES_BY_ITEMS, }, { title: , @@ -93,6 +114,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/inventory-valuation', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_INVENTORY_VALUATION_SUMMARY, }, { title: , @@ -104,6 +127,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/customers-balance-summary', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_CUSTOMERS_SUMMARY_BALANCE, }, { title: , @@ -111,6 +136,8 @@ export const SalesAndPurchasesReportMenus = [ ), link: '/financial-reports/vendors-balance-summary', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_VENDORS_SUMMARY_BALANCE, }, { title: , @@ -120,6 +147,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/transactions-by-customers', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_CUSTOMERS_TRANSACTIONS, }, { title: , @@ -131,6 +160,8 @@ export const SalesAndPurchasesReportMenus = [ /> ), link: '/financial-reports/transactions-by-vendors', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_VENDORS_TRANSACTIONS, }, { title: , @@ -138,6 +169,8 @@ export const SalesAndPurchasesReportMenus = [ ), link: '/financial-reports/inventory-item-details', + subject: AbilitySubject.Report, + ability: Report_Abilities.READ_INVENTORY_ITEM_DETAILS, }, ], }, diff --git a/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js b/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js index a3f65be13..483c0457c 100644 --- a/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js +++ b/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js @@ -26,8 +26,11 @@ import withManualJournals from './withManualJournals'; import withSettingsActions from '../../Settings/withSettingsActions'; import withSettings from '../../Settings/withSettings'; -import { If, DashboardActionViewsList } from 'components'; - +import { Can, If, DashboardActionViewsList } from 'components'; +import { + Manual_Journal_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { compose } from 'utils'; /** @@ -86,13 +89,17 @@ function ManualJournalActionsBar({ onChange={handleTabChange} /> - - + - + + } /> diff --git a/src/containers/Accounting/JournalsLanding/components.js b/src/containers/Accounting/JournalsLanding/components.js index af986e522..996099d3b 100644 --- a/src/containers/Accounting/JournalsLanding/components.js +++ b/src/containers/Accounting/JournalsLanding/components.js @@ -13,7 +13,18 @@ import { } from '@blueprintjs/core'; import intl from 'react-intl-universal'; -import { FormattedMessage as T, Choose, Money, If, Icon } from 'components'; +import { + Can, + FormattedMessage as T, + Choose, + Money, + If, + Icon, +} from 'components'; +import { + Manual_Journal_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { safeCallback } from 'utils'; /** @@ -150,25 +161,31 @@ export const ActionsMenu = ({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - + + + + } + text={intl.get('publish_journal')} + onClick={safeCallback(onPublish, original)} + /> + + + } - text={intl.get('publish_journal')} - onClick={safeCallback(onPublish, original)} + icon={} + text={intl.get('edit_journal')} + onClick={safeCallback(onEdit, original)} /> - - } - text={intl.get('edit_journal')} - onClick={safeCallback(onEdit, original)} - /> - } - intent={Intent.DANGER} - onClick={safeCallback(onDelete, original)} - /> + + + } + intent={Intent.DANGER} + onClick={safeCallback(onDelete, original)} + /> + ); }; diff --git a/src/containers/Accounts/AccountsActionsBar.js b/src/containers/Accounts/AccountsActionsBar.js index e96d69c8a..001fb64bf 100644 --- a/src/containers/Accounts/AccountsActionsBar.js +++ b/src/containers/Accounts/AccountsActionsBar.js @@ -15,6 +15,7 @@ import { FormattedMessage as T } from 'components'; import { AdvancedFilterPopover, If, + Can, DashboardActionViewsList, DashboardFilterButton, DashboardRowsHeightButton, @@ -30,6 +31,8 @@ import withAlertActions from 'containers/Alert/withAlertActions'; import withAccountsTableActions from './withAccountsTableActions'; import withSettings from '../Settings/withSettings'; import withSettingsActions from '../Settings/withSettingsActions'; +import { Account_Abilities, AbilitySubject } from '../../common/abilityOption'; + import { compose } from 'utils'; /** @@ -116,13 +119,14 @@ function AccountsActionsBar({ onChange={handleTabChange} /> - - + + - + + } /> diff --git a/src/containers/Customers/CustomersLanding/components.js b/src/containers/Customers/CustomersLanding/components.js index 0cce24139..569c1a336 100644 --- a/src/containers/Customers/CustomersLanding/components.js +++ b/src/containers/Customers/CustomersLanding/components.js @@ -4,7 +4,11 @@ import clsx from 'classnames'; import intl from 'react-intl-universal'; -import { Icon, Money, If, AvaterCell } from 'components'; +import { Can, Icon, Money, If, AvaterCell } from 'components'; +import { + Customer_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { safeCallback } from 'utils'; @@ -29,37 +33,46 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_customer')} - onClick={safeCallback(onEdit, original)} - /> - } - text={intl.get('duplicate')} - onClick={safeCallback(onDuplicate, original)} - /> - + + + } - onClick={safeCallback(onInactivate, original)} + icon={} + text={intl.get('edit_customer')} + onClick={safeCallback(onEdit, original)} /> - - + + } - onClick={safeCallback(onActivate, original)} + icon={} + text={intl.get('duplicate')} + onClick={safeCallback(onDuplicate, original)} /> - - } - text={intl.get('delete_customer')} - intent={Intent.DANGER} - onClick={safeCallback(onDelete, original)} - /> + + + + } + onClick={safeCallback(onInactivate, original)} + /> + + + } + onClick={safeCallback(onActivate, original)} + /> + + + + } + text={intl.get('delete_customer')} + intent={Intent.DANGER} + onClick={safeCallback(onDelete, original)} + /> + ); } diff --git a/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js b/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js index cd4f11d90..9e18120b3 100644 --- a/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js +++ b/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js @@ -7,13 +7,17 @@ import { Intent, NavbarDivider, } from '@blueprintjs/core'; -import { FormattedMessage as T } from 'components'; +import { Can, FormattedMessage as T } from 'components'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import withDialogActions from 'containers/Dialog/withDialogActions'; import withAlertsActions from 'containers/Alert/withAlertActions'; import { safeCallback } from 'utils'; +import { + Account_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { compose } from 'utils'; import { useAccountDrawerContext } from './AccountDrawerProvider'; @@ -53,26 +57,31 @@ function AccountDrawerActionBar({ return ( - + + - + + } /> diff --git a/src/containers/Expenses/ExpensesLanding/components.js b/src/containers/Expenses/ExpensesLanding/components.js index f288c1fc2..95c873b43 100644 --- a/src/containers/Expenses/ExpensesLanding/components.js +++ b/src/containers/Expenses/ExpensesLanding/components.js @@ -12,13 +12,17 @@ import { MenuDivider, } from '@blueprintjs/core'; import intl from 'react-intl-universal'; - +import { + Expense_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { FormatDateCell, FormattedMessage as T, Money, Icon, If, + Can, } from 'components'; import { safeCallback } from 'utils'; @@ -54,25 +58,31 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - + + + + } + text={intl.get('publish_expense')} + onClick={safeCallback(onPublish, original)} + /> + + + } - text={intl.get('publish_expense')} - onClick={safeCallback(onPublish, original)} + icon={} + text={intl.get('edit_expense')} + onClick={safeCallback(onEdit, original)} /> - - } - text={intl.get('edit_expense')} - onClick={safeCallback(onEdit, original)} - /> - } - text={intl.get('delete_expense')} - intent={Intent.DANGER} - onClick={safeCallback(onDelete, original)} - /> + + + } + text={intl.get('delete_expense')} + intent={Intent.DANGER} + onClick={safeCallback(onDelete, original)} + /> + ); } diff --git a/src/containers/InventoryAdjustments/components.js b/src/containers/InventoryAdjustments/components.js index eaa923e08..ff74e48f6 100644 --- a/src/containers/InventoryAdjustments/components.js +++ b/src/containers/InventoryAdjustments/components.js @@ -12,10 +12,14 @@ import { import intl from 'react-intl-universal'; import moment from 'moment'; -import { FormattedMessage as T } from 'components'; +import { FormattedMessage as T, Can } from 'components'; import { isNumber } from 'lodash'; import { Icon, Money, If } from 'components'; import { isBlank, safeCallback } from 'utils'; +import { + Inventory_Adjustment_Abilities, + AbilitySubject, +} from '../../common/abilityOption'; /** * Publish accessor @@ -102,20 +106,31 @@ export const ActionsMenu = ({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - + + + + + } + text={intl.get('publish_adjustment')} + onClick={safeCallback(onPublish, original)} + /> + + + } - text={intl.get('publish_adjustment')} - onClick={safeCallback(onPublish, original)} + text={intl.get('delete_adjustment')} + intent={Intent.DANGER} + onClick={safeCallback(onDelete, original)} + icon={} /> - - } - /> + ); }; diff --git a/src/containers/Items/ItemsActionsBar.js b/src/containers/Items/ItemsActionsBar.js index 67e30c732..a5b71fa4c 100644 --- a/src/containers/Items/ItemsActionsBar.js +++ b/src/containers/Items/ItemsActionsBar.js @@ -14,6 +14,7 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import Icon from 'components/Icon'; import { If, + Can, DashboardActionViewsList, AdvancedFilterPopover, DashboardFilterButton, @@ -30,6 +31,8 @@ import withSettings from '../Settings/withSettings'; import { compose } from 'utils'; import withSettingsActions from '../Settings/withSettingsActions'; +import { Item_Abilities, AbilitySubject } from '../../common/abilityOption'; + /** * Items actions bar. */ @@ -101,13 +104,14 @@ function ItemsActionsBar({ /> - + + - + + } /> diff --git a/src/containers/Items/components.js b/src/containers/Items/components.js index d573f4aaf..3e3a8840c 100644 --- a/src/containers/Items/components.js +++ b/src/containers/Items/components.js @@ -12,8 +12,13 @@ import { import intl from 'react-intl-universal'; import { isNumber } from 'lodash'; -import { FormattedMessage as T, Icon, Money, If } from 'components'; +import { FormattedMessage as T, Icon, Money, If, Can } from 'components'; import { isBlank, safeCallback } from 'utils'; +import { + AbilitySubject, + Item_Abilities, + Inventory_Adjustment_Abilities, +} from '../../common/abilityOption'; /** * Publish accessor @@ -90,44 +95,58 @@ export function ItemsActionMenuList({ text={} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_item')} - onClick={safeCallback(onEditItem, original)} - /> - } - text={intl.get('duplicate')} - onClick={safeCallback(onDuplicate, original)} - /> - + + } - onClick={safeCallback(onInactivateItem, original)} + icon={} + text={intl.get('edit_item')} + onClick={safeCallback(onEditItem, original)} /> - - + + } - onClick={safeCallback(onActivateItem, original)} + icon={} + text={intl.get('duplicate')} + onClick={safeCallback(onDuplicate, original)} /> - - + + + + } + onClick={safeCallback(onInactivateItem, original)} + /> + + + + } + onClick={safeCallback(onActivateItem, original)} + /> + + + + + } + onClick={safeCallback(onMakeAdjustment, original)} + /> + + + } - onClick={safeCallback(onMakeAdjustment, original)} + text={intl.get('delete_item')} + icon={} + onClick={safeCallback(onDeleteItem, original)} + intent={Intent.DANGER} /> - - } - onClick={safeCallback(onDeleteItem, original)} - intent={Intent.DANGER} - /> + ); } diff --git a/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.js b/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.js index d021d63b2..78ca384f0 100644 --- a/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.js +++ b/src/containers/Purchases/Bills/BillsLanding/BillsActionsBar.js @@ -14,12 +14,14 @@ import { useHistory } from 'react-router-dom'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import { If, + Can, FormattedMessage as T, DashboardActionViewsList, DashboardFilterButton, AdvancedFilterPopover, DashboardRowsHeightButton, } from 'components'; +import { Bill_Abilities, AbilitySubject } from '../../../../common/abilityOption'; import withBillsActions from './withBillsActions'; import withBills from './withBills'; @@ -86,12 +88,14 @@ function BillActionsBar({ onChange={handleTabChange} /> - + + - + + } /> diff --git a/src/containers/Purchases/Bills/BillsLanding/components.js b/src/containers/Purchases/Bills/BillsLanding/components.js index 9cd1ec6fa..13799617b 100644 --- a/src/containers/Purchases/Bills/BillsLanding/components.js +++ b/src/containers/Purchases/Bills/BillsLanding/components.js @@ -16,8 +16,14 @@ import { If, Choose, Money, + Can, } from 'components'; import { formattedAmount, safeCallback, isBlank, calculateStatus } from 'utils'; +import { + Bill_Abilities, + Payment_Made_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; /** * Actions menu. @@ -40,38 +46,44 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_bill')} - onClick={safeCallback(onEdit, original)} - /> + + + } + text={intl.get('edit_bill')} + onClick={safeCallback(onEdit, original)} + /> - - } - text={intl.get('mark_as_opened')} - onClick={safeCallback(onOpen, original)} - /> - - - } - text={intl.get('add_payment')} - onClick={safeCallback(onQuick, original)} - /> - + + } + text={intl.get('mark_as_opened')} + onClick={safeCallback(onOpen, original)} + /> + + + + + } + text={intl.get('add_payment')} + onClick={safeCallback(onQuick, original)} + /> + + } text={intl.get('allocate_landed_coast')} onClick={safeCallback(onAllocateLandedCost, original)} /> - } - /> + + } + /> + ); } diff --git a/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeActionsBar.js b/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeActionsBar.js index b3c8776c0..069833b27 100644 --- a/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeActionsBar.js +++ b/src/containers/Purchases/PaymentMades/PaymentsLanding/PaymentMadeActionsBar.js @@ -14,6 +14,7 @@ import { useHistory } from 'react-router-dom'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import { If, + Can, FormattedMessage as T, DashboardActionViewsList, DashboardFilterButton, @@ -29,6 +30,10 @@ import withSettings from 'containers/Settings/withSettings'; import { usePaymentMadesListContext } from './PaymentMadesListProvider'; import { useRefreshPaymentMades } from 'hooks/query/paymentMades'; +import { + Payment_Made_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; import { compose } from 'utils'; @@ -70,7 +75,7 @@ function PaymentMadeActionsBar({ const handleRefreshBtnClick = () => { refresh(); }; - + // Handle table row size change. const handleTableRowSizeChange = (size) => { addSetting('billPayments', 'tableSize', size); @@ -85,12 +90,14 @@ function PaymentMadeActionsBar({ onChange={handleTabChange} /> - + + - + + } /> diff --git a/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js b/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js index 875817ca7..e6572de48 100644 --- a/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js +++ b/src/containers/Purchases/PaymentMades/PaymentsLanding/components.js @@ -10,7 +10,12 @@ import { } from '@blueprintjs/core'; import intl from 'react-intl-universal'; -import { Icon, Money, FormatDateCell } from 'components'; +import { Icon, Money, FormatDateCell, Can } from 'components'; +import { + Payment_Made_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; + import { safeCallback } from 'utils'; export function AmountAccessor(row) { @@ -31,18 +36,23 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_payment_made')} - onClick={safeCallback(onEdit, original)} - /> - } - /> + + + + } + text={intl.get('edit_payment_made')} + onClick={safeCallback(onEdit, original)} + /> + + + } + /> + ); } diff --git a/src/containers/Sales/Estimates/EstimatesLanding/EstimatesActionsBar.js b/src/containers/Sales/Estimates/EstimatesLanding/EstimatesActionsBar.js index e25b09083..6a6553040 100644 --- a/src/containers/Sales/Estimates/EstimatesLanding/EstimatesActionsBar.js +++ b/src/containers/Sales/Estimates/EstimatesLanding/EstimatesActionsBar.js @@ -11,6 +11,7 @@ import { import { useHistory } from 'react-router-dom'; import { + Can, FormattedMessage as T, AdvancedFilterPopover, If, @@ -28,6 +29,10 @@ import withSettings from 'containers/Settings/withSettings'; import { useEstimatesListContext } from './EstimatesListProvider'; import { useRefreshEstimates } from 'hooks/query/estimates'; +import { + Estimate_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; import { compose } from 'utils'; @@ -87,12 +92,14 @@ function EstimateActionsBar({ onChange={handleTabChange} /> - - + + + + } /> diff --git a/src/containers/Sales/Estimates/EstimatesLanding/components.js b/src/containers/Sales/Estimates/EstimatesLanding/components.js index 22c95f3ae..404c190f9 100644 --- a/src/containers/Sales/Estimates/EstimatesLanding/components.js +++ b/src/containers/Sales/Estimates/EstimatesLanding/components.js @@ -2,6 +2,10 @@ import React from 'react'; import { Intent, Tag, Menu, MenuItem, MenuDivider } from '@blueprintjs/core'; import intl from 'react-intl-universal'; import clsx from 'classnames'; +import { + Estimate_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; import { CLASSES } from '../../../../common/classes'; import { @@ -11,6 +15,7 @@ import { Choose, Icon, If, + Can, } from 'components'; import { safeCallback } from 'utils'; @@ -68,63 +73,74 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_estimate')} - onClick={safeCallback(onEdit, original)} - /> - } - text={intl.get('convert_to_invoice')} - onClick={safeCallback(onConvert, original)} - /> - + + } - text={intl.get('mark_as_delivered')} - onClick={safeCallback(onDeliver, original)} + icon={} + text={intl.get('edit_estimate')} + onClick={safeCallback(onEdit, original)} /> - - - - } - text={intl.get('mark_as_rejected')} - onClick={safeCallback(onReject, original)} - /> - - + } + text={intl.get('convert_to_invoice')} + onClick={safeCallback(onConvert, original)} + /> + + } - text={intl.get('mark_as_approved')} - onClick={safeCallback(onApprove, original)} + text={intl.get('mark_as_delivered')} + onClick={safeCallback(onDeliver, original)} /> - - - } - text={intl.get('mark_as_approved')} - onClick={safeCallback(onApprove, original)} - /> - } - text={intl.get('mark_as_rejected')} - onClick={safeCallback(onReject, original)} - /> - - - } - text={intl.get('print')} - onClick={safeCallback(onPrint, original)} - /> - } - /> + + + + } + text={intl.get('mark_as_rejected')} + onClick={safeCallback(onReject, original)} + /> + + + } + text={intl.get('mark_as_approved')} + onClick={safeCallback(onApprove, original)} + /> + + + } + text={intl.get('mark_as_approved')} + onClick={safeCallback(onApprove, original)} + /> + } + text={intl.get('mark_as_rejected')} + onClick={safeCallback(onReject, original)} + /> + + + + + } + text={intl.get('print')} + onClick={safeCallback(onPrint, original)} + /> + + + } + /> + ); } diff --git a/src/containers/Sales/Invoices/InvoicesLanding/InvoicesActionsBar.js b/src/containers/Sales/Invoices/InvoicesLanding/InvoicesActionsBar.js index 6b03ab3a7..c91b96e96 100644 --- a/src/containers/Sales/Invoices/InvoicesLanding/InvoicesActionsBar.js +++ b/src/containers/Sales/Invoices/InvoicesLanding/InvoicesActionsBar.js @@ -18,7 +18,11 @@ import { import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; -import { If, DashboardActionViewsList } from 'components'; +import { Can, If, DashboardActionViewsList } from 'components'; +import { + Invoice_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; import { useRefreshInvoices } from 'hooks/query/invoices'; import { useInvoicesListContext } from './InvoicesListProvider'; @@ -84,12 +88,14 @@ function InvoiceActionsBar({ onChange={handleTabChange} /> - - - + + + + } /> diff --git a/src/containers/Sales/Invoices/InvoicesLanding/components.js b/src/containers/Sales/Invoices/InvoicesLanding/components.js index 2efde999e..126355429 100644 --- a/src/containers/Sales/Invoices/InvoicesLanding/components.js +++ b/src/containers/Sales/Invoices/InvoicesLanding/components.js @@ -18,8 +18,14 @@ import { Choose, If, Icon, + Can, } from 'components'; import { formattedAmount, safeCallback, calculateStatus } from 'utils'; +import { + Invoice_Abilities, + Payment_Receive_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; export const statusAccessor = (row) => { return ( @@ -55,7 +61,6 @@ export const statusAccessor = (row) => { })} - - } - text={intl.get('edit_invoice')} - onClick={safeCallback(onEdit, original)} - /> - + + } - text={intl.get('mark_as_delivered')} - onClick={safeCallback(onDeliver, original)} + icon={} + text={intl.get('edit_invoice')} + onClick={safeCallback(onEdit, original)} /> - - + + + } + text={intl.get('mark_as_delivered')} + onClick={safeCallback(onDeliver, original)} + /> + + + + + } + text={intl.get('add_payment')} + onClick={safeCallback(onQuick, original)} + /> + + + } - text={intl.get('add_payment')} - onClick={safeCallback(onQuick, original)} + icon={} + text={intl.get('print')} + onClick={safeCallback(onPrint, original)} /> - - } - text={intl.get('print')} - onClick={safeCallback(onPrint, original)} - /> - } - /> + + + } + /> + ); } diff --git a/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiveActionsBar.js b/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiveActionsBar.js index bb67f91a3..13b31fa98 100644 --- a/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiveActionsBar.js +++ b/src/containers/Sales/PaymentReceives/PaymentsLanding/PaymentReceiveActionsBar.js @@ -19,14 +19,17 @@ import { import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; -import { If, DashboardActionViewsList } from 'components'; +import { Can, If, DashboardActionViewsList } from 'components'; import withPaymentReceivesActions from './withPaymentReceivesActions'; import withPaymentReceives from './withPaymentReceives'; import withSettingsActions from 'containers/Settings/withSettingsActions'; import withSettings from 'containers/Settings/withSettings'; - +import { + Payment_Receive_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; import { compose } from 'utils'; import { usePaymentReceivesListContext } from './PaymentReceiptsListProvider'; import { useRefreshPaymentReceive } from 'hooks/query/paymentReceives'; @@ -85,12 +88,14 @@ function PaymentReceiveActionsBar({ onChange={handleTabChange} /> - + - + + } /> diff --git a/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js b/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js index aa5d7c8cf..8faa17f3d 100644 --- a/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js +++ b/src/containers/Sales/PaymentReceives/PaymentsLanding/components.js @@ -11,10 +11,13 @@ import { import intl from 'react-intl-universal'; import clsx from 'classnames'; -import { FormatDateCell, Money, Icon } from 'components'; +import { FormatDateCell, Money, Icon, Can } from 'components'; import { safeCallback } from 'utils'; import { CLASSES } from '../../../../common/classes'; - +import { + Payment_Receive_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; /** * Table actions menu. */ @@ -29,18 +32,22 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, paymentReceive)} /> - - } - text={intl.get('edit_payment_receive')} - onClick={safeCallback(onEdit, paymentReceive)} - /> - } - /> + + + } + text={intl.get('edit_payment_receive')} + onClick={safeCallback(onEdit, paymentReceive)} + /> + + + } + /> + ); } diff --git a/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptActionsBar.js b/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptActionsBar.js index 4f7020d2d..ecbe64055 100644 --- a/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptActionsBar.js +++ b/src/containers/Sales/Receipts/ReceiptsLanding/ReceiptActionsBar.js @@ -17,7 +17,7 @@ import { DashboardRowsHeightButton, } from 'components'; -import { If, DashboardActionViewsList } from 'components'; +import { Can, If, DashboardActionViewsList } from 'components'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import withReceiptsActions from './withReceiptsActions'; @@ -28,6 +28,11 @@ import withSettings from 'containers/Settings/withSettings'; import { useReceiptsListContext } from './ReceiptsListProvider'; import { useRefreshReceipts } from 'hooks/query/receipts'; +import { + Receipt_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; + import { compose } from 'utils'; /** @@ -87,12 +92,14 @@ function ReceiptActionsBar({ /> - + + - + + } /> diff --git a/src/containers/Sales/Receipts/ReceiptsLanding/components.js b/src/containers/Sales/Receipts/ReceiptsLanding/components.js index 7f7f0cbda..7fbaf9546 100644 --- a/src/containers/Sales/Receipts/ReceiptsLanding/components.js +++ b/src/containers/Sales/Receipts/ReceiptsLanding/components.js @@ -15,7 +15,11 @@ import clsx from 'classnames'; import { CLASSES } from '../../../../common/classes'; import { safeCallback } from 'utils'; -import { FormatDateCell, Choose, Money, Icon, If } from 'components'; +import { FormatDateCell, Choose, Money, Icon, If, Can } from 'components'; +import { + Receipt_Abilities, + AbilitySubject, +} from '../../../../common/abilityOption'; export function ActionsMenu({ payload: { onEdit, onDelete, onClose, onDrawer, onViewDetails, onPrint }, @@ -28,30 +32,37 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, receipt)} /> - - } - text={intl.get('edit_receipt')} - onClick={safeCallback(onEdit, receipt)} - /> - + + } - text={intl.get('mark_as_closed')} - onClick={safeCallback(onClose, receipt)} + icon={} + text={intl.get('edit_receipt')} + onClick={safeCallback(onEdit, receipt)} /> - - } - text={intl.get('print')} - onClick={safeCallback(onPrint, receipt)} - /> - } - /> + + + } + text={intl.get('mark_as_closed')} + onClick={safeCallback(onClose, receipt)} + /> + + + + } + text={intl.get('print')} + onClick={safeCallback(onPrint, receipt)} + /> + + + } + /> + ); } diff --git a/src/containers/Vendors/VendorsLanding/VendorActionsBar.js b/src/containers/Vendors/VendorsLanding/VendorActionsBar.js index 6f392cb7c..bcd20c9ab 100644 --- a/src/containers/Vendors/VendorsLanding/VendorActionsBar.js +++ b/src/containers/Vendors/VendorsLanding/VendorActionsBar.js @@ -13,6 +13,7 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import Icon from 'components/Icon'; import { If, + Can, FormattedMessage as T, DashboardActionViewsList, DashboardFilterButton, @@ -29,7 +30,10 @@ import withVendors from './withVendors'; import withSettingsActions from '../../Settings/withSettingsActions'; import withSettings from '../../Settings/withSettings'; - +import { + Vendor_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { compose } from 'utils'; /** @@ -90,13 +94,15 @@ function VendorActionsBar({ onChange={handleTabChange} /> - + + - + + } /> diff --git a/src/containers/Vendors/VendorsLanding/components.js b/src/containers/Vendors/VendorsLanding/components.js index 680c1469c..c2a580e56 100644 --- a/src/containers/Vendors/VendorsLanding/components.js +++ b/src/containers/Vendors/VendorsLanding/components.js @@ -10,7 +10,11 @@ import { } from '@blueprintjs/core'; import intl from 'react-intl-universal'; -import { Icon, Money, If, AvaterCell } from 'components'; +import { Can, Icon, Money, If, AvaterCell } from 'components'; +import { + Vendor_Abilities, + AbilitySubject, +} from '../../../common/abilityOption'; import { safeCallback, firstLettersArgs } from 'utils'; /** @@ -34,37 +38,45 @@ export function ActionsMenu({ text={intl.get('view_details')} onClick={safeCallback(onViewDetails, original)} /> - - } - text={intl.get('edit_vendor')} - onClick={safeCallback(onEdit, original)} - /> - } - text={intl.get('duplicate')} - onClick={safeCallback(onDuplicate, original)} - /> - + + } - onClick={safeCallback(onInactivate, original)} + icon={} + text={intl.get('edit_vendor')} + onClick={safeCallback(onEdit, original)} /> - - + + } - onClick={safeCallback(onActivate, original)} + icon={} + text={intl.get('duplicate')} + onClick={safeCallback(onDuplicate, original)} /> - - } - text={intl.get('delete_vendor')} - intent={Intent.DANGER} - onClick={safeCallback(onDelete, original)} - /> + + + + } + onClick={safeCallback(onInactivate, original)} + /> + + + } + onClick={safeCallback(onActivate, original)} + /> + + + + } + text={intl.get('delete_vendor')} + intent={Intent.DANGER} + onClick={safeCallback(onDelete, original)} + /> + ); } diff --git a/src/hooks/utils/index.js b/src/hooks/utils/index.js index d4d6152a6..5d189d42e 100644 --- a/src/hooks/utils/index.js +++ b/src/hooks/utils/index.js @@ -1,5 +1,3 @@ - - export * from './useLocalStorage'; export * from './usePrevious'; export * from './useUpdateEffect'; @@ -7,4 +5,5 @@ export * from './useWatch'; export * from './useWhen'; export * from './useRequestPdf'; export * from './useAsync'; -export * from './useIntersectionObserver'; \ No newline at end of file +export * from './useIntersectionObserver'; +export * from './useAbilityContext'; \ No newline at end of file diff --git a/src/hooks/utils/useAbilityContext.js b/src/hooks/utils/useAbilityContext.js new file mode 100644 index 000000000..8eee4ec39 --- /dev/null +++ b/src/hooks/utils/useAbilityContext.js @@ -0,0 +1,6 @@ +import React from 'react'; +import { useAbility } from '@casl/react'; +import { AbilityContext } from '../../components/Can'; + +export const useAbilityContext = () => useAbility(AbilityContext); +