diff --git a/src/components/Sidebar/SidebarMenu.js b/src/components/Sidebar/SidebarMenu.js
index 56c667806..5a8d2bd82 100644
--- a/src/components/Sidebar/SidebarMenu.js
+++ b/src/components/Sidebar/SidebarMenu.js
@@ -1,7 +1,7 @@
import React from 'react';
import { Menu, MenuDivider } from '@blueprintjs/core';
import { useHistory, useLocation } from 'react-router-dom';
-import sidebarMenuList from 'config/sidebarMenu';
+
import { Choose } from 'components';
import Icon from 'components/Icon';
import MenuItem from 'components/MenuItem';
@@ -24,7 +24,7 @@ function SidebarMenuItemSpace({ space }) {
return ;
}
-function SidebarMenu({ isSubscriptionActive }) {
+function SidebarMenu({ menu, isSubscriptionActive }) {
const history = useHistory();
const location = useLocation();
@@ -93,7 +93,7 @@ function SidebarMenu({ isSubscriptionActive }) {
});
};
- const filterItems = sidebarMenuList.filter(
+ const filterItems = menu.filter(
(item) => isSubscriptionActive || item.enableBilling,
);
const items = menuItemsMapper(filterItems);
diff --git a/src/components/Sidebar/utils.js b/src/components/Sidebar/utils.js
new file mode 100644
index 000000000..fcf056fac
--- /dev/null
+++ b/src/components/Sidebar/utils.js
@@ -0,0 +1,48 @@
+import sidebarMenuList from 'config/sidebarMenu';
+import { isArray, isEmpty } from 'lodash';
+import { useAbilityContext } from 'hooks/utils';
+
+export function useGetSidebarMenu() {
+ const ability = useAbilityContext();
+
+ return sidebarMenuList
+ .map((item) => {
+ const children = isArray(item.children)
+ ? item.children.filter((childItem) => {
+ return isArray(childItem.permission)
+ ? childItem.permission.some((perm) =>
+ ability.can(perm.ability, perm.subject),
+ )
+ : childItem?.permission?.ability && childItem?.permission?.subject
+ ? ability.can(
+ childItem.permission.ability,
+ childItem.permission.subject,
+ )
+ : true;
+ })
+ : [];
+
+ return {
+ ...item,
+ ...(isArray(item.children)
+ ? {
+ children,
+ }
+ : {}),
+ };
+ })
+ .filter((item) => {
+ return isArray(item.permission)
+ ? item.permission.some((per) =>
+ ability.can(per.ability, per.subject),
+ )
+ : item?.permission?.ability && item?.permission?.subject
+ ? ability.can(item.permission.ability, item.permission.subject)
+ : true;
+ })
+ .filter((item) =>
+ isEmpty(item.children) && !item.href && !item.label && !item.divider
+ ? false
+ : true,
+ );
+}
diff --git a/src/config/financialReportsMenu.js b/src/config/financialReportsMenu.js
index 4c3226a4f..83e6ffd25 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 { ReportsAction, AbilitySubject } from '../common/abilityOption';
export const financialReportMenus = [
{
@@ -11,6 +12,8 @@ export const financialReportMenus = [
),
link: '/financial-reports/balance-sheet',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_BALANCE_SHEET,
},
{
title:
,
@@ -18,11 +21,15 @@ export const financialReportMenus = [
),
link: '/financial-reports/trial-balance-sheet',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_TRIAL_BALANCE_SHEET,
},
{
title:
,
desc:
,
link: '/financial-reports/profit-loss-sheet',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PROFIT_LOSS,
},
{
title:
,
@@ -30,16 +37,22 @@ export const financialReportMenus = [
),
link: '/financial-reports/cash-flow',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CASHFLOW,
},
{
title:
,
desc:
,
link: '/financial-reports/journal-sheet',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_JOURNAL,
},
{
title:
,
desc:
,
link: '/financial-reports/general-ledger',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_GENERAL_LEDGET,
},
{
title:
,
@@ -47,11 +60,15 @@ export const financialReportMenus = [
),
link: '/financial-reports/receivable-aging-summary',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_AR_AGING_SUMMARY,
},
{
title:
,
desc:
,
link: '/financial-reports/payable-aging-summary',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_AP_AGING_SUMMARY,
},
],
},
@@ -71,6 +88,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/purchases-by-items',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PURCHASES_BY_ITEMS,
},
{
title:
,
@@ -82,6 +101,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/sales-by-items',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_SALES_BY_ITEMS,
},
{
title:
,
@@ -93,6 +114,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/inventory-valuation',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
},
{
title:
,
@@ -104,6 +127,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/customers-balance-summary',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
},
{
title:
,
@@ -111,6 +136,8 @@ export const SalesAndPurchasesReportMenus = [
),
link: '/financial-reports/vendors-balance-summary',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
},
{
title:
,
@@ -120,6 +147,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/transactions-by-customers',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
},
{
title:
,
@@ -131,6 +160,8 @@ export const SalesAndPurchasesReportMenus = [
/>
),
link: '/financial-reports/transactions-by-vendors',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_TRANSACTIONS,
},
{
title:
,
@@ -138,6 +169,8 @@ export const SalesAndPurchasesReportMenus = [
),
link: '/financial-reports/inventory-item-details',
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
},
],
},
diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js
index bb02d9100..a847f8e52 100644
--- a/src/config/sidebarMenu.js
+++ b/src/config/sidebarMenu.js
@@ -1,5 +1,26 @@
import React from 'react';
import { FormattedMessage as T } from 'components';
+import {
+ ReportsAction,
+ AbilitySubject,
+ ItemAction,
+ InventoryAdjustmentAction,
+ SaleEstimateAction,
+ SaleInvoiceAction,
+ SaleReceiptAction,
+ PaymentReceiveAction,
+ BillAction,
+ PaymentMadeAction,
+ CustomerAction,
+ VendorAction,
+ AccountAction,
+ ManualJournalAction,
+ ExpenseAction,
+ CashflowAction,
+ PreferencesAbility,
+ ExchangeRateAbility,
+ SubscriptionBillingAbility,
+} from '../common/abilityOption';
export default [
{
@@ -11,6 +32,32 @@ export default [
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.View,
+ },
+ {
+ subject: AbilitySubject.InventoryAdjustment,
+ ability: InventoryAdjustmentAction.View,
+ },
+ {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.View,
+ },
+ {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.View,
+ },
+ {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.View,
+ },
+ {
+ subject: AbilitySubject.PaymentReceive,
+ ability: PaymentReceiveAction.View,
+ },
+ ],
},
{
text:
,
@@ -18,37 +65,70 @@ export default [
{
text:
,
href: '/items',
+ permission: {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.View,
+ },
},
{
text:
,
href: '/inventory-adjustments',
+ permission: {
+ subject: AbilitySubject.InventoryAdjustment,
+ ability: InventoryAdjustmentAction.View,
+ },
},
{
text:
,
href: '/items/categories',
+ permission: {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.View,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.Create,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.Create,
+ },
+ ],
},
{
text:
,
href: '/items/new',
+ permission: {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.Create,
+ },
},
{
text:
,
href: '/items/new',
+ permission: {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.Create,
+ },
},
{
text:
,
href: '/items/categories/new',
+ permission: {
+ subject: AbilitySubject.Item,
+ ability: ItemAction.Create,
+ },
},
- // {
- // text:
,
- // },
],
},
{
@@ -57,43 +137,109 @@ export default [
{
text:
,
href: '/estimates',
- newTabHref: '/estimates/new',
+ permission: {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.View,
+ },
},
{
text:
,
href: '/invoices',
- newTabHref: '/invoices/new',
+ permission: {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.View,
+ },
},
{
text:
,
href: '/receipts',
+ permission: {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.View,
+ },
},
{
text:
,
href: '/payment-receives',
+ permission: {
+ subject: AbilitySubject.PaymentReceive,
+ ability: PaymentReceiveAction.View,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.Create,
+ },
+ {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.Create,
+ },
+ {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.Create,
+ },
+ {
+ subject: AbilitySubject.PaymentReceive,
+ ability: PaymentReceiveAction.Create,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.Create,
+ },
+ {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.Create,
+ },
+ {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.Create,
+ },
+ {
+ subject: AbilitySubject.PaymentReceive,
+ ability: PaymentReceiveAction.Create,
+ },
+ ],
},
{
text:
,
href: '/estimates/new',
+ permission: {
+ subject: AbilitySubject.Estimate,
+ ability: SaleEstimateAction.Create,
+ },
},
{
text:
,
href: '/invoices/new',
+ permission: {
+ subject: AbilitySubject.Invoice,
+ ability: SaleInvoiceAction.Create,
+ },
},
{
text:
,
href: '/receipts/new',
+ permission: {
+ subject: AbilitySubject.Receipt,
+ ability: SaleReceiptAction.Create,
+ },
},
{
text:
,
href: '/payment-receives/new',
+ permission: {
+ subject: AbilitySubject.PaymentReceive,
+ ability: PaymentReceiveAction.Create,
+ },
},
],
},
@@ -103,27 +249,62 @@ export default [
{
text:
,
href: '/bills',
- newTabHref: '/bills/new',
+ permission: {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.View,
+ },
},
{
text:
,
href: '/payment-mades',
newTabHref: '/payment-mades/new',
+ permission: {
+ subject: AbilitySubject.PaymentMade,
+ ability: PaymentMadeAction.View,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.Create,
+ },
+ {
+ subject: AbilitySubject.PaymentMade,
+ ability: PaymentMadeAction.Create,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.Create,
+ },
+ {
+ subject: AbilitySubject.PaymentMade,
+ ability: PaymentMadeAction.Create,
+ },
+ ],
},
{
text:
,
href: '/bills/new',
+ permission: {
+ subject: AbilitySubject.Bill,
+ ability: BillAction.Create,
+ },
},
{
text:
,
href: '/payment-mades/new',
+ permission: {
+ subject: AbilitySubject.PaymentMade,
+ ability: PaymentMadeAction.Create,
+ },
},
],
},
@@ -133,33 +314,77 @@ export default [
{
text:
,
href: '/customers',
- newTabHref: '/customers/new',
+ permission: {
+ subject: AbilitySubject.Customer,
+ ability: CustomerAction.View,
+ },
},
{
text:
,
href: '/vendors',
- newTabHref: '/vendors/new',
+ permission: {
+ subject: AbilitySubject.Vendor,
+ ability: VendorAction.Create,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Customer,
+ ability: CustomerAction.View,
+ },
+ {
+ subject: AbilitySubject.Vendor,
+ ability: VendorAction.View,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Customer,
+ ability: CustomerAction.View,
+ },
+ {
+ subject: AbilitySubject.Vendor,
+ ability: VendorAction.View,
+ },
+ ],
},
{
text:
,
href: '/customers/new',
+ permission: {
+ subject: AbilitySubject.Customer,
+ ability: CustomerAction.View,
+ },
},
{
text:
,
href: '/vendors/new',
+ permission: {
+ subject: AbilitySubject.Vendor,
+ ability: VendorAction.View,
+ },
},
],
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Account,
+ ability: AccountAction.View,
+ },
+ {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.View,
+ },
+ ],
},
{
text:
,
@@ -167,29 +392,57 @@ export default [
{
text:
,
href: '/accounts',
+ permission: {
+ subject: AbilitySubject.Account,
+ ability: AccountAction.View,
+ },
},
{
text:
,
href: '/manual-journals',
+ permission: {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.View,
+ },
},
{
text: ,
href: '/transactions-locking',
+ permission: {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.TransactionLocking,
+ },
},
{
text:
,
href: '/exchange-rates',
+ permission: {
+ subject: AbilitySubject.ExchangeRate,
+ ability: ExchangeRateAbility.View,
+ },
},
{
text:
,
label: true,
+ permission: {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.Create,
+ },
},
{
divider: true,
+ permission: {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.Create,
+ },
},
{
text:
,
href: '/make-journal-entry',
+ permission: {
+ subject: AbilitySubject.ManualJournal,
+ ability: ManualJournalAction.Create,
+ },
},
],
},
@@ -199,29 +452,61 @@ export default [
{
text:
,
href: '/cashflow-accounts',
+ permission: {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.View,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
+ ],
},
{
text:
,
href: '/cashflow-accounts',
+ permission: {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
},
{
text:
,
href: '/cashflow-accounts',
+ permission: {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
},
{
text:
,
href: '/cashflow-accounts',
+ permission: {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
},
{
text:
,
href: '/cashflow-accounts',
+ permission: {
+ subject: AbilitySubject.Cashflow,
+ ability: CashflowAction.Create,
+ },
},
],
},
@@ -231,17 +516,33 @@ export default [
{
text:
,
href: '/expenses',
+ permission: {
+ subject: AbilitySubject.Expense,
+ ability: ExpenseAction.View,
+ },
},
{
text:
,
label: true,
+ permission: {
+ subject: AbilitySubject.Expense,
+ ability: ExpenseAction.Create,
+ },
},
{
divider: true,
+ permission: {
+ subject: AbilitySubject.Expense,
+ ability: ExpenseAction.Create,
+ },
},
{
text:
,
href: '/expenses/new',
+ permission: {
+ subject: AbilitySubject.Expense,
+ ability: ExpenseAction.Create,
+ },
},
],
},
@@ -251,80 +552,216 @@ export default [
{
text:
,
href: '/financial-reports/balance-sheet',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_BALANCE_SHEET,
+ },
},
{
text:
,
href: '/financial-reports/trial-balance-sheet',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_TRIAL_BALANCE_SHEET,
+ },
},
{
text:
,
href: '/financial-reports/journal-sheet',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_JOURNAL,
+ },
},
{
text:
,
href: '/financial-reports/general-ledger',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_GENERAL_LEDGET,
+ },
},
{
text:
,
href: '/financial-reports/profit-loss-sheet',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PROFIT_LOSS,
+ },
},
{
text:
,
href: '/financial-reports/cash-flow',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CASHFLOW_ACCOUNT_TRANSACTION,
+ },
},
{
text:
,
href: '/financial-reports/receivable-aging-summary',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_AR_AGING_SUMMARY,
+ },
},
{
text:
,
href: '/financial-reports/payable-aging-summary',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_AP_AGING_SUMMARY,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PURCHASES_BY_ITEMS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_SALES_BY_ITEMS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_TRANSACTIONS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PURCHASES_BY_ITEMS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_SALES_BY_ITEMS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_TRANSACTIONS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
+ },
+ ],
},
{
text:
,
href: '/financial-reports/purchases-by-items',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_PURCHASES_BY_ITEMS,
+ },
},
{
text:
,
href: '/financial-reports/sales-by-items',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_SALES_BY_ITEMS,
+ },
},
{
text:
,
href: '/financial-reports/transactions-by-customers',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
+ },
},
{
text:
,
href: '/financial-reports/transactions-by-vendors',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_TRANSACTIONS,
+ },
},
{
text:
,
href: '/financial-reports/customers-balance-summary',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
+ },
},
{
text:
,
href: '/financial-reports/vendors-balance-summary',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
+ },
},
{
text:
,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
+ },
+ ],
},
{
divider: true,
+ permission: [
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
+ },
+ {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
+ },
+ ],
},
{
text:
,
href: '/financial-reports/inventory-item-details',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
+ },
},
{
text:
,
href: '/financial-reports/inventory-valuation',
+ permission: {
+ subject: AbilitySubject.Report,
+ ability: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
+ },
},
],
},
@@ -332,14 +769,32 @@ export default [
text:
,
enableBilling: true,
label: true,
+ permission: [
+ {
+ subject: AbilitySubject.Preferences,
+ ability: PreferencesAbility.Mutate,
+ },
+ {
+ subject: AbilitySubject.SubscriptionBilling,
+ ability: SubscriptionBillingAbility.View,
+ },
+ ],
},
{
text:
,
href: '/preferences',
+ permission: {
+ subject: AbilitySubject.Preferences,
+ ability: PreferencesAbility.Mutate,
+ },
},
{
text:
,
href: '/billing',
enableBilling: true,
+ permission: {
+ subject: AbilitySubject.SubscriptionBilling,
+ ability: SubscriptionBillingAbility.View,
+ },
},
];
diff --git a/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js b/src/containers/Accounting/JournalsLanding/ManualJournalActionsBar.js
index a3f65be13..b90238018 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 {
+ ManualJournalAction,
+ AbilitySubject,
+} from '../../../common/abilityOption';
import { compose } from 'utils';
/**
@@ -86,13 +89,14 @@ function ManualJournalActionsBar({
onChange={handleTabChange}
/>
-
-
}
- text={
}
- onClick={onClickNewManualJournal}
- />
+
+ }
+ text={}
+ onClick={onClickNewManualJournal}
+ />
+
-
+
+
-
+
+
>
}
/>
diff --git a/src/containers/Accounting/JournalsLanding/components.js b/src/containers/Accounting/JournalsLanding/components.js
index af986e522..fab711e72 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 {
+ ManualJournalAction,
+ 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/Accounting/ManualJournalUniversalSearch.js b/src/containers/Accounting/ManualJournalUniversalSearch.js
index 4cde8bafe..6c4a6266a 100644
--- a/src/containers/Accounting/ManualJournalUniversalSearch.js
+++ b/src/containers/Accounting/ManualJournalUniversalSearch.js
@@ -1,6 +1,10 @@
import intl from 'react-intl-universal';
import { RESOURCES_TYPES } from 'common/resourcesTypes';
import withDrawerActions from '../Drawer/withDrawerActions';
+import {
+ AbilitySubject,
+ ManualJournalAction,
+} from '../../common/abilityOption';
/**
* Universal search manual journal item select action.
@@ -44,4 +48,8 @@ export const universalSearchJournalBind = () => ({
optionItemLabel: intl.get('manual_journals'),
selectItemAction: JournalUniversalSearchSelectAction,
itemSelect: manualJournalsToSearch,
+ permission: {
+ ability: ManualJournalAction.View,
+ subject: AbilitySubject.ManualJournal,
+ },
});
diff --git a/src/containers/Accounts/AccountUniversalSearch.js b/src/containers/Accounts/AccountUniversalSearch.js
index a1af66eb3..afa8744d5 100644
--- a/src/containers/Accounts/AccountUniversalSearch.js
+++ b/src/containers/Accounts/AccountUniversalSearch.js
@@ -1,7 +1,10 @@
import intl from 'react-intl-universal';
-import { RESOURCES_TYPES } from '../../common/resourcesTypes';
+
import withDrawerActions from '../Drawer/withDrawerActions';
+import { AbilitySubject, AccountAction } from '../../common/abilityOption';
+import { RESOURCES_TYPES } from '../../common/resourcesTypes';
+
function AccountUniversalSearchItemSelectComponent({
// #ownProps
resourceType,
@@ -42,4 +45,8 @@ export const universalSearchAccountBind = () => ({
optionItemLabel: intl.get('accounts'),
selectItemAction: AccountUniversalSearchItemSelect,
itemSelect: accountToSearch,
+ permission: {
+ ability: AccountAction.View,
+ subject: AbilitySubject.Account,
+ },
});
diff --git a/src/containers/Accounts/AccountsActionsBar.js b/src/containers/Accounts/AccountsActionsBar.js
index e96d69c8a..d77f309fc 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 { AccountAction, AbilitySubject } from '../../common/abilityOption';
+
import { compose } from 'utils';
/**
@@ -116,13 +119,14 @@ function AccountsActionsBar({
onChange={handleTabChange}
/>
-
- }
- text={}
- onClick={onClickNewAccount}
- />
+
+ }
+ text={}
+ onClick={onClickNewAccount}
+ />
+
- }
- defaultChecked={accountsInactiveMode}
- onChange={handleInactiveSwitchChange}
- />
+
+ }
+ defaultChecked={accountsInactiveMode}
+ onChange={handleInactiveSwitchChange}
+ />
+
-
- }
- text={intl.get('edit_account')}
- onClick={safeCallback(onEdit, original)}
- />
- }
- text={intl.get('new_child_account')}
- onClick={safeCallback(onNewChild, original)}
- />
-
-
+
+
}
- onClick={safeCallback(onInactivate, original)}
+ icon={}
+ text={intl.get('edit_account')}
+ onClick={safeCallback(onEdit, original)}
/>
-
-
+
}
- onClick={safeCallback(onActivate, original)}
+ icon={}
+ text={intl.get('new_child_account')}
+ onClick={safeCallback(onNewChild, original)}
/>
-
- }
- intent={Intent.DANGER}
- onClick={safeCallback(onDelete, original)}
- />
+
+
+
+
+ }
+ onClick={safeCallback(onInactivate, original)}
+ />
+
+
+ }
+ onClick={safeCallback(onActivate, original)}
+ />
+
+
+
+ }
+ intent={Intent.DANGER}
+ onClick={safeCallback(onDelete, original)}
+ />
+
);
}
diff --git a/src/containers/Alerts/Roles/RoleDeleteAlert.js b/src/containers/Alerts/Roles/RoleDeleteAlert.js
index c3b5e1946..ff240ebaa 100644
--- a/src/containers/Alerts/Roles/RoleDeleteAlert.js
+++ b/src/containers/Alerts/Roles/RoleDeleteAlert.js
@@ -5,6 +5,7 @@ import { Intent, Alert } from '@blueprintjs/core';
import { AppToaster } from 'components';
import { useDeleteRole } from 'hooks/query';
+import { handleDeleteErrors } from '../../Preferences/Users/Roles/utils';
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
import withAlertActions from 'containers/Alert/withAlertActions';
@@ -45,7 +46,9 @@ function RoleDeleteAlert({
response: {
data: { errors },
},
- }) => {},
+ }) => {
+ handleDeleteErrors(errors);
+ },
)
.finally(() => {
closeAlert(name);
diff --git a/src/containers/CashFlow/AccountTransactions/components.js b/src/containers/CashFlow/AccountTransactions/components.js
index 528d6afe2..4597ee9fb 100644
--- a/src/containers/CashFlow/AccountTransactions/components.js
+++ b/src/containers/CashFlow/AccountTransactions/components.js
@@ -4,9 +4,10 @@ import intl from 'react-intl-universal';
import { Intent, Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
import { MaterialProgressBar } from 'components';
-import { FormatDateCell, If, Icon } from 'components';
+import { Can, FormatDateCell, If, Icon } from 'components';
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
import { TRANSACRIONS_TYPE } from 'common/cashflowOptions';
+import { AbilitySubject, CashflowAction } from '../../../common/abilityOption';
import { safeCallback } from 'utils';
export function ActionsMenu({
@@ -20,15 +21,17 @@ export function ActionsMenu({
text={intl.get('view_details')}
onClick={safeCallback(onViewDetails, original)}
/>
-
-
- }
- />
-
+
+
+
+ }
+ />
+
+
);
}
@@ -83,7 +86,7 @@ export function useAccountTransactionsColumns() {
className: 'deposit',
textOverview: true,
align: 'right',
- clickable: true
+ clickable: true,
},
{
id: 'withdrawal',
@@ -93,7 +96,7 @@ export function useAccountTransactionsColumns() {
width: 150,
textOverview: true,
align: 'right',
- clickable: true
+ clickable: true,
},
{
id: 'running_balance',
@@ -103,7 +106,7 @@ export function useAccountTransactionsColumns() {
width: 150,
textOverview: true,
align: 'right',
- clickable: true
+ clickable: true,
},
{
id: 'balance',
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js
index cb9e86b84..f21b9f463 100644
--- a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js
+++ b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js
@@ -7,8 +7,9 @@ import {
Alignment,
Switch,
} from '@blueprintjs/core';
-import { Icon, FormattedMessage as T } from 'components';
+import { Can, Icon, FormattedMessage as T } from 'components';
import { useRefreshCashflowAccounts } from 'hooks/query';
+import { CashflowAction, AbilitySubject } from '../../../common/abilityOption';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
@@ -56,19 +57,22 @@ function CashFlowAccountsActionsBar({
return (
- }
- text={}
- onClick={handleAddBankAccount}
- />
- }
- text={}
- onClick={handleAddCashAccount}
- />
-
+
+ }
+ text={}
+ onClick={handleAddBankAccount}
+ />
+
+ }
+ text={}
+ onClick={handleAddCashAccount}
+ />
+
+
}
@@ -85,13 +89,15 @@ function CashFlowAccountsActionsBar({
text={}
/>
-
- }
- defaultChecked={false}
- onChange={handleInactiveSwitchChange}
- />
+
+ }
+ defaultChecked={false}
+ onChange={handleInactiveSwitchChange}
+ />
+
+
-
- }
- icon={}
- >
-
-
-
- }
- icon={}
- >
-
-
-
-
- }
- text={intl.get('edit_account')}
- onClick={safeCallback(onEditClick)}
- />
-
-
+
+
}
- onClick={safeCallback(onInactivateClick)}
- />
-
-
+ text={}
+ icon={}
+ >
+
+
+
}
- onClick={safeCallback(onActivateClick)}
+ text={}
+ icon={}
+ >
+
+
+
+
+
+
+ }
+ text={intl.get('edit_account')}
+ onClick={safeCallback(onEditClick)}
/>
-
- }
- intent={Intent.DANGER}
- onClick={safeCallback(onDeleteClick)}
- />
+
+
+
+
+ }
+ onClick={safeCallback(onInactivateClick)}
+ />
+
+
+ }
+ onClick={safeCallback(onActivateClick)}
+ />
+
+
+
+ }
+ intent={Intent.DANGER}
+ onClick={safeCallback(onDeleteClick)}
+ />
+
);
}
diff --git a/src/containers/Customers/CustomersLanding/CustomersActionsBar.js b/src/containers/Customers/CustomersLanding/CustomersActionsBar.js
index 8ca0e6750..9aa31e958 100644
--- a/src/containers/Customers/CustomersLanding/CustomersActionsBar.js
+++ b/src/containers/Customers/CustomersLanding/CustomersActionsBar.js
@@ -14,6 +14,7 @@ import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import {
If,
Icon,
+ Can,
FormattedMessage as T,
DashboardActionViewsList,
AdvancedFilterPopover,
@@ -29,6 +30,7 @@ import withCustomersActions from './withCustomersActions';
import withAlertActions from 'containers/Alert/withAlertActions';
import withSettingsActions from '../../Settings/withSettingsActions';
import withSettings from '../../Settings/withSettings';
+import { CustomerAction, AbilitySubject } from '../../../common/abilityOption';
import { compose } from 'utils';
@@ -103,15 +105,15 @@ function CustomerActionsBar({
onChange={handleTabChange}
/>
-
- }
- text={}
- onClick={onClickNewCustomer}
- />
-
-
+
+ }
+ text={}
+ onClick={onClickNewCustomer}
+ />
+
+
- }
- defaultChecked={accountsInactiveMode}
- onChange={handleInactiveSwitchChange}
- />
+
+ }
+ defaultChecked={accountsInactiveMode}
+ onChange={handleInactiveSwitchChange}
+ />
+