diff --git a/src/common/quickNewOptions.js b/src/common/quickNewOptions.js index 74b9fece8..09572523e 100644 --- a/src/common/quickNewOptions.js +++ b/src/common/quickNewOptions.js @@ -1,10 +1,71 @@ import intl from 'react-intl-universal'; +import { + AbilitySubject, + Invoice_Abilities, + Customer_Abilities, + Vendor_Abilities, + Manual_Journal_Abilities, + Expense_Abilities, +} from '../common/abilityOption'; +import { useAbilitiesFilter } from '../hooks'; export const getQuickNewActions = () => [ - { path: 'invoices/new', name: intl.get('sale_invoice') }, - { path: 'bills/new', name: intl.get('purchase_invoice') }, - { path: 'make-journal-entry', name: intl.get('manual_journal') }, - { path: 'expenses/new', name: intl.get('expense') }, - { path: 'customers/new', name: intl.get('customer') }, - { path: 'vendors/new', name: intl.get('vendor') }, + { + path: 'invoices/new', + name: intl.get('sale_invoice'), + permission: { + subject: AbilitySubject.Invoice, + ability: Invoice_Abilities.Create, + }, + }, + { + path: 'bills/new', + name: intl.get('purchase_invoice'), + permission: { + subject: AbilitySubject.Invoice, + ability: Invoice_Abilities.Create, + }, + }, + { + path: 'make-journal-entry', + name: intl.get('manual_journal'), + permission: { + subject: AbilitySubject.ManualJournal, + ability: Manual_Journal_Abilities.Create, + }, + }, + { + path: 'expenses/new', + name: intl.get('expense'), + permission: { + subject: AbilitySubject.Expense, + ability: Expense_Abilities.Create, + }, + }, + { + path: 'customers/new', + name: intl.get('customer'), + permission: { + subject: AbilitySubject.Customer, + ability: Customer_Abilities.Create, + }, + }, + { + path: 'vendors/new', + name: intl.get('vendor'), + permission: { + subject: AbilitySubject.Vendor, + ability: Vendor_Abilities.Vendor, + }, + }, ]; + +/** + * Retrieve the dashboard quick new menu items. + */ +export const useGetQuickNewMenu = () => { + const quickNewMenu = getQuickNewActions(); + const abilitiesFilter = useAbilitiesFilter(); + + return abilitiesFilter(quickNewMenu); +}; diff --git a/src/containers/QuickNewDropdown/QuickNewDropdown.js b/src/containers/QuickNewDropdown/QuickNewDropdown.js index a3489d21d..a6242e2af 100644 --- a/src/containers/QuickNewDropdown/QuickNewDropdown.js +++ b/src/containers/QuickNewDropdown/QuickNewDropdown.js @@ -4,16 +4,21 @@ import { FormattedMessage as T } from 'components'; import { useHistory } from 'react-router-dom'; import { Icon } from 'components'; import { Position } from '@blueprintjs/core'; -import { getQuickNewActions } from 'common/quickNewOptions'; import { Select } from '@blueprintjs/select'; +import { useGetQuickNewMenu } from 'common/quickNewOptions'; + /** * Quick New Dropdown. */ export default function QuickNewDropdown() { const history = useHistory(); - const quickNewOptions = getQuickNewActions(); + const quickNewOptions = useGetQuickNewMenu(); + // Can't continue if there is no any quick new menu items to display. + if (quickNewOptions.length === 0) { + return null; + } // Handle click quick new button. const handleClickQuickNew = ({ path }) => { history.push(`/${path}`); @@ -40,4 +45,4 @@ export default function QuickNewDropdown() { /> ); -} \ No newline at end of file +} diff --git a/src/hooks/utils/useAbilityContext.js b/src/hooks/utils/useAbilityContext.js index 4aca97f3d..9d530e0ec 100644 --- a/src/hooks/utils/useAbilityContext.js +++ b/src/hooks/utils/useAbilityContext.js @@ -1,4 +1,22 @@ +import React from 'react'; import { useAbility } from '@casl/react'; import { AbilityContext } from '../../components'; -export const useAbilityContext = () => useAbility(AbilityContext); \ No newline at end of file +export const useAbilityContext = () => useAbility(AbilityContext); + +/** + * + */ +export const useAbilitiesFilter = () => { + const ability = useAbilityContext(); + + return React.useCallback( + (items) => { + return items.filter((item) => + ability.can(item.permission.ability, item.permission.subject), + ); + }, + [ability], + ); +}; + \ No newline at end of file