mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +00:00
feat: permissions service full access.
This commit is contained in:
@@ -46,6 +46,7 @@
|
|||||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||||
"eslint-plugin-react": "7.18.0",
|
"eslint-plugin-react": "7.18.0",
|
||||||
"eslint-plugin-react-hooks": "^1.6.1",
|
"eslint-plugin-react-hooks": "^1.6.1",
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
"file-loader": "4.3.0",
|
"file-loader": "4.3.0",
|
||||||
"flow-bin": "^0.123.0",
|
"flow-bin": "^0.123.0",
|
||||||
"formik": "^2.2.5",
|
"formik": "^2.2.5",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { chain } from 'lodash';
|
||||||
import {
|
import {
|
||||||
AbilitySubject,
|
AbilitySubject,
|
||||||
AccountAction,
|
AccountAction,
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
SaleInvoiceAction,
|
SaleInvoiceAction,
|
||||||
SaleReceiptAction,
|
SaleReceiptAction,
|
||||||
VendorAction,
|
VendorAction,
|
||||||
VendorCreditAction
|
VendorCreditAction,
|
||||||
} from './abilityOption';
|
} from './abilityOption';
|
||||||
|
|
||||||
export const ModulePermissionsStyle = {
|
export const ModulePermissionsStyle = {
|
||||||
@@ -26,8 +27,8 @@ const PermissionColumn = {
|
|||||||
View: 'view',
|
View: 'view',
|
||||||
Create: 'create',
|
Create: 'create',
|
||||||
Delete: 'delete',
|
Delete: 'delete',
|
||||||
Edit: 'edit'
|
Edit: 'edit',
|
||||||
}
|
};
|
||||||
|
|
||||||
export const permissions = [
|
export const permissions = [
|
||||||
{
|
{
|
||||||
@@ -46,20 +47,52 @@ export const permissions = [
|
|||||||
label: 'Items',
|
label: 'Items',
|
||||||
subject: AbilitySubject.Item,
|
subject: AbilitySubject.Item,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: ItemAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: ItemAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: ItemAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: ItemAction.View,
|
||||||
{ label: 'Delete', key: ItemAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: ItemAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: ItemAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: ItemAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Inventory adjustments',
|
label: 'Inventory adjustments',
|
||||||
subject: AbilitySubject.InventoryAdjustment,
|
subject: AbilitySubject.InventoryAdjustment,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: ItemAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: ItemAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: ItemAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: ItemAction.View,
|
||||||
{ label: 'Delete', key: ItemAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: ItemAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: ItemAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: ItemAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -80,23 +113,55 @@ export const permissions = [
|
|||||||
label: 'Customers',
|
label: 'Customers',
|
||||||
subject: AbilitySubject.Customer,
|
subject: AbilitySubject.Customer,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: CustomerAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: CustomerAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: CustomerAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: CustomerAction.View,
|
||||||
{ label: 'Delete', key: CustomerAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: CustomerAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: CustomerAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: CustomerAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Vendors',
|
label: 'Vendors',
|
||||||
subject: AbilitySubject.Customer,
|
subject: AbilitySubject.Vendor,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: VendorAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: VendorAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: VendorAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: VendorAction.View,
|
||||||
{ label: 'Delete', key: VendorAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: VendorAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: VendorAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: VendorAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Sales',
|
label: 'Sales',
|
||||||
@@ -114,55 +179,135 @@ export const permissions = [
|
|||||||
label: 'Sale Invoice',
|
label: 'Sale Invoice',
|
||||||
subject: AbilitySubject.Invoice,
|
subject: AbilitySubject.Invoice,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: SaleInvoiceAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: SaleInvoiceAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: SaleInvoiceAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: SaleInvoiceAction.View,
|
||||||
{ label: 'Delete', key: SaleInvoiceAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
{ label: 'Written-off invoice', key: SaleInvoiceAction.Writeoff }
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: SaleInvoiceAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: SaleInvoiceAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: SaleInvoiceAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
|
{ label: 'Written-off invoice', key: SaleInvoiceAction.Writeoff },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Sale Estimate',
|
label: 'Sale Estimate',
|
||||||
subject: AbilitySubject.Estimate,
|
subject: AbilitySubject.Estimate,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: SaleEstimateAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: SaleEstimateAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: SaleEstimateAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: SaleEstimateAction.View,
|
||||||
{ label: 'Delete', key: SaleEstimateAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: SaleEstimateAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: SaleEstimateAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: SaleEstimateAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Sale Receipt',
|
label: 'Sale Receipt',
|
||||||
subject: AbilitySubject.Receipt,
|
subject: AbilitySubject.Receipt,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: SaleReceiptAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: SaleReceiptAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: SaleReceiptAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: SaleReceiptAction.View,
|
||||||
{ label: 'Delete', key: SaleReceiptAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: SaleReceiptAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: SaleReceiptAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: SaleReceiptAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Credit note',
|
label: 'Credit note',
|
||||||
subject: AbilitySubject.CreditNote,
|
subject: AbilitySubject.CreditNote,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: CreditNoteAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: CreditNoteAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: CreditNoteAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: CreditNoteAction.View,
|
||||||
{ label: 'Delete', key: CreditNoteAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
{ label: 'Refund credit note', key: CreditNoteAction.Refund }
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: CreditNoteAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: CreditNoteAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: CreditNoteAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
|
{ label: 'Refund credit note', key: CreditNoteAction.Refund },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Payment Receive',
|
label: 'Payment Receive',
|
||||||
subject: AbilitySubject.PaymentReceive,
|
subject: AbilitySubject.PaymentReceive,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: PaymentReceiveAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: PaymentReceiveAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: PaymentReceiveAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: PaymentReceiveAction.View,
|
||||||
{ label: 'Delete', key: PaymentReceiveAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: PaymentReceiveAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: PaymentReceiveAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: PaymentReceiveAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Purchases',
|
label: 'Purchases',
|
||||||
@@ -170,44 +315,92 @@ export const permissions = [
|
|||||||
serviceFullAccess: true,
|
serviceFullAccess: true,
|
||||||
moduleFullAccess: true,
|
moduleFullAccess: true,
|
||||||
columns: [
|
columns: [
|
||||||
{ label: 'View', key: 'view' },
|
{ label: 'View', key: 'view' },
|
||||||
{ label: 'Create', key: 'create' },
|
{ label: 'Create', key: 'create' },
|
||||||
{ label: 'Edit', key: 'edit' },
|
{ label: 'Edit', key: 'edit' },
|
||||||
{ label: 'Delete', key: 'delete' },
|
{ label: 'Delete', key: 'delete' },
|
||||||
],
|
],
|
||||||
services: [
|
services: [
|
||||||
{
|
{
|
||||||
label: 'Bills',
|
label: 'Bills',
|
||||||
subject: AbilitySubject.Bill,
|
subject: AbilitySubject.Bill,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: BillAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: BillAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: BillAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: BillAction.View,
|
||||||
{ label: 'Delete', key: BillAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: BillAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: BillAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: BillAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Vendor Credits',
|
label: 'Vendor Credits',
|
||||||
subject: AbilitySubject.VendorCredit,
|
subject: AbilitySubject.VendorCredit,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: VendorCreditAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: VendorCreditAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: VendorCreditAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: VendorCreditAction.View,
|
||||||
{ label: 'Delete', key: VendorCreditAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
{ label: 'Refund vendor credit', key: VendorCreditAction.Refund }
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: VendorCreditAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: VendorCreditAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: VendorCreditAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
|
{ label: 'Refund vendor credit', key: VendorCreditAction.Refund },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Payment Made',
|
label: 'Payment Made',
|
||||||
subject: AbilitySubject.PaymentMade,
|
subject: AbilitySubject.PaymentMade,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: PaymentMadeAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: PaymentMadeAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: PaymentMadeAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: PaymentMadeAction.View,
|
||||||
{ label: 'Delete', key: PaymentMadeAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: PaymentMadeAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: PaymentMadeAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: PaymentMadeAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Financial Accounting',
|
label: 'Financial Accounting',
|
||||||
@@ -225,34 +418,85 @@ export const permissions = [
|
|||||||
label: 'Manual Journals',
|
label: 'Manual Journals',
|
||||||
subject: AbilitySubject.ManualJournal,
|
subject: AbilitySubject.ManualJournal,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: ManualJournalAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: ManualJournalAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: ManualJournalAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: ManualJournalAction.View,
|
||||||
{ label: 'Delete', key: ManualJournalAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: ManualJournalAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: ManualJournalAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: ManualJournalAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Chart of Accounts',
|
label: 'Chart of Accounts',
|
||||||
subject: AbilitySubject.Account,
|
subject: AbilitySubject.Account,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: AccountAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: AccountAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: AccountAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: AccountAction.View,
|
||||||
{ label: 'Delete', key: AccountAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
{ label: 'Transactions locking', key: AccountAction.TransactionsLocking },
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: AccountAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: AccountAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: AccountAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Transactions locking',
|
||||||
|
key: AccountAction.TransactionsLocking,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Expenses',
|
label: 'Expenses',
|
||||||
subject: AbilitySubject.Expense,
|
subject: AbilitySubject.Expense,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'View', key: ExpenseAction.View, relatedColumn: PermissionColumn.View },
|
{
|
||||||
{ label: 'Create', key: ExpenseAction.Create, relatedColumn: PermissionColumn.Create },
|
label: 'View',
|
||||||
{ label: 'Edit', key: ExpenseAction.Edit, relatedColumn: PermissionColumn.Edit },
|
key: ExpenseAction.View,
|
||||||
{ label: 'Delete', key: ExpenseAction.Delete, relatedColumn: PermissionColumn.Delete },
|
relatedColumn: PermissionColumn.View,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create',
|
||||||
|
key: ExpenseAction.Create,
|
||||||
|
relatedColumn: PermissionColumn.Create,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Edit',
|
||||||
|
key: ExpenseAction.Edit,
|
||||||
|
relatedColumn: PermissionColumn.Edit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete',
|
||||||
|
key: ExpenseAction.Delete,
|
||||||
|
relatedColumn: PermissionColumn.Delete,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Financial Reports',
|
label: 'Financial Reports',
|
||||||
@@ -264,25 +508,73 @@ export const permissions = [
|
|||||||
label: 'Financial reprots',
|
label: 'Financial reprots',
|
||||||
subject: AbilitySubject.Report,
|
subject: AbilitySubject.Report,
|
||||||
permissions: [
|
permissions: [
|
||||||
{ label: 'Balance sheet', key: ReportsAction.READ_BALANCE_SHEET },
|
{ label: 'Balance sheet', key: ReportsAction.READ_BALANCE_SHEET },
|
||||||
{ label: 'Trial Balance sheet', key: ReportsAction.READ_TRIAL_BALANCE_SHEET },
|
{
|
||||||
{ label: 'Profit & Loss sheet', key: ReportsAction.READ_PROFIT_LOSS },
|
label: 'Trial Balance sheet',
|
||||||
{ label: 'Cash flow sheet', key: ReportsAction.READ_CASHFLOW },
|
key: ReportsAction.READ_TRIAL_BALANCE_SHEET,
|
||||||
{ label: 'Journal sheet', key: ReportsAction.READ_JOURNAL },
|
},
|
||||||
{ label: 'General ledger', key: ReportsAction.READ_GENERAL_LEDGET },
|
{ label: 'Profit & Loss sheet', key: ReportsAction.READ_PROFIT_LOSS },
|
||||||
{ label: 'A/R Aging Summary report', key: ReportsAction.READ_AR_AGING_SUMMARY },
|
{ label: 'Cash flow sheet', key: ReportsAction.READ_CASHFLOW },
|
||||||
{ label: 'A/P Aging Summary report', key: ReportsAction.READ_AP_AGING_SUMMARY },
|
{ label: 'Journal sheet', key: ReportsAction.READ_JOURNAL },
|
||||||
{ label: 'Purchases by items', key: ReportsAction.READ_PURCHASES_BY_ITEMS },
|
{ label: 'General ledger', key: ReportsAction.READ_GENERAL_LEDGET },
|
||||||
{ label: 'Sales by items', key: ReportsAction.READ_SALES_BY_ITEMS },
|
{
|
||||||
{ label: 'Customers transactions', key: ReportsAction.READ_CUSTOMERS_TRANSACTIONS },
|
label: 'A/R Aging Summary report',
|
||||||
{ label: 'Vendors transactions', key: ReportsAction.READ_VENDORS_TRANSACTIONS },
|
key: ReportsAction.READ_AR_AGING_SUMMARY,
|
||||||
{ label: 'Customers summary balance', key: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE },
|
},
|
||||||
{ label: 'Vendors summary balance', key: ReportsAction.READ_VENDORS_SUMMARY_BALANCE },
|
{
|
||||||
{ label: 'Inventory valuation summary', key: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY },
|
label: 'A/P Aging Summary report',
|
||||||
{ label: 'Inventory items details', key: ReportsAction.READ_INVENTORY_ITEM_DETAILS },
|
key: ReportsAction.READ_AP_AGING_SUMMARY,
|
||||||
{ label: 'Cashflow account transactions', key: ReportsAction.READ_CASHFLOW_ACCOUNT_TRANSACTION },
|
},
|
||||||
|
{
|
||||||
|
label: 'Purchases by items',
|
||||||
|
key: ReportsAction.READ_PURCHASES_BY_ITEMS,
|
||||||
|
},
|
||||||
|
{ label: 'Sales by items', key: ReportsAction.READ_SALES_BY_ITEMS },
|
||||||
|
{
|
||||||
|
label: 'Customers transactions',
|
||||||
|
key: ReportsAction.READ_CUSTOMERS_TRANSACTIONS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Vendors transactions',
|
||||||
|
key: ReportsAction.READ_VENDORS_TRANSACTIONS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Customers summary balance',
|
||||||
|
key: ReportsAction.READ_CUSTOMERS_SUMMARY_BALANCE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Vendors summary balance',
|
||||||
|
key: ReportsAction.READ_VENDORS_SUMMARY_BALANCE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Inventory valuation summary',
|
||||||
|
key: ReportsAction.READ_INVENTORY_VALUATION_SUMMARY,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Inventory items details',
|
||||||
|
key: ReportsAction.READ_INVENTORY_ITEM_DETAILS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cashflow account transactions',
|
||||||
|
key: ReportsAction.READ_CASHFLOW_ACCOUNT_TRANSACTION,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function getPermissionsSchemaService(subject) {
|
||||||
|
return chain(permissions)
|
||||||
|
.map((perm) => perm.services)
|
||||||
|
.flatten()
|
||||||
|
.find((service) => service.subject === subject)
|
||||||
|
.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPermissionsSchemaServices() {
|
||||||
|
return chain(permissions)
|
||||||
|
.map((module) => module.services)
|
||||||
|
.flatten()
|
||||||
|
.value();
|
||||||
|
}
|
||||||
|
|||||||
14
src/components/Forms/FormikObserver.js
Normal file
14
src/components/Forms/FormikObserver.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import { useDeepCompareEffect } from 'hooks/utils';
|
||||||
|
|
||||||
|
export function FormikObserver({ onChange, values }) {
|
||||||
|
useDeepCompareEffect(() => {
|
||||||
|
onChange(values);
|
||||||
|
}, [values]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
FormikObserver.defaultProps = {
|
||||||
|
onChange: () => null,
|
||||||
|
};
|
||||||
@@ -1 +1,2 @@
|
|||||||
export * from './FormObserver';
|
export * from './FormObserver';
|
||||||
|
export * from './FormikObserver';
|
||||||
@@ -11,9 +11,13 @@ import { FormattedMessage as T } from 'components';
|
|||||||
* @returns {React.JSX}
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export function RoleFormFloatingActions() {
|
export function RoleFormFloatingActions() {
|
||||||
|
// Formik form context.
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
|
// History context.
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
|
// Handle close click.
|
||||||
const handleCloseClick = () => {
|
const handleCloseClick = () => {
|
||||||
history.go(-1);
|
history.go(-1);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ErrorMessage, FastField } from 'formik';
|
||||||
|
import { FormGroup, InputGroup, TextArea } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { inputIntent } from 'utils';
|
||||||
|
import { FormattedMessage as T, FieldRequiredHint, Card } from 'components';
|
||||||
|
import { useAutofocus } from 'hooks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role form header.
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
export function RoleFormHeader() {
|
||||||
|
const roleNameFieldRef = useAutofocus();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
{/* ---------- name ---------- */}
|
||||||
|
<FastField name={'role_name'}>
|
||||||
|
{({ field, meta: { error, touched } }) => (
|
||||||
|
<FormGroup
|
||||||
|
label={
|
||||||
|
<strong>
|
||||||
|
<T id={'role_name'} />
|
||||||
|
</strong>
|
||||||
|
}
|
||||||
|
labelInfo={<FieldRequiredHint />}
|
||||||
|
className={'form-group--name'}
|
||||||
|
intent={inputIntent({ error, touched })}
|
||||||
|
helperText={<ErrorMessage name="role_name" />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<InputGroup
|
||||||
|
medium={true}
|
||||||
|
inputRef={(ref) => (roleNameFieldRef.current = ref)}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
|
</FastField>
|
||||||
|
|
||||||
|
{/* ---------- description ---------- */}
|
||||||
|
<FastField name={'role_description'}>
|
||||||
|
{({ field, meta: { error, touched } }) => (
|
||||||
|
<FormGroup
|
||||||
|
label={<T id={'description'} />}
|
||||||
|
className={'form-group--description'}
|
||||||
|
intent={inputIntent({ error, touched })}
|
||||||
|
helperText={<ErrorMessage name={'role_description'} />}
|
||||||
|
inline={true}
|
||||||
|
>
|
||||||
|
<TextArea
|
||||||
|
growVertically={true}
|
||||||
|
height={280}
|
||||||
|
{...field}
|
||||||
|
placeholder="Max. 500 characters"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
|
</FastField>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
import { FormikObserver } from 'components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role form observer.
|
||||||
|
* @returns {React.JSX}
|
||||||
|
*/
|
||||||
|
export function RoleFormObserver() {
|
||||||
|
const { values } = useFormikContext();
|
||||||
|
|
||||||
|
// Handles the form change.
|
||||||
|
const handleFormChange = () => {};
|
||||||
|
|
||||||
|
return <FormikObserver onChange={handleFormChange} values={values} />;
|
||||||
|
}
|
||||||
@@ -3,32 +3,28 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
|
||||||
import 'style/pages/Preferences/Roles/Form.scss';
|
import 'style/pages/Preferences/Roles/Form.scss';
|
||||||
|
|
||||||
import { Intent } from '@blueprintjs/core';
|
|
||||||
|
|
||||||
import { AppToaster, FormattedMessage as T } from 'components';
|
import { AppToaster, FormattedMessage as T } from 'components';
|
||||||
|
|
||||||
import { CreateRolesFormSchema, EditRolesFormSchema } from './RolesForm.schema';
|
import { CreateRolesFormSchema, EditRolesFormSchema } from './RolesForm.schema';
|
||||||
|
|
||||||
import { useRolesFormContext } from './RolesFormProvider';
|
import { useRolesFormContext } from './RolesFormProvider';
|
||||||
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
|
import RolesFormContent from './RolesFormContent';
|
||||||
import {
|
import {
|
||||||
getNewRoleInitialValues,
|
getNewRoleInitialValues,
|
||||||
transformToArray,
|
transformToArray,
|
||||||
transformToObject,
|
transformToObject,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
import RolesFormContent from './RolesFormContent';
|
|
||||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
|
||||||
import { handleDeleteErrors } from '../utils';
|
import { handleDeleteErrors } from '../utils';
|
||||||
|
|
||||||
import { compose, transformToForm } from 'utils';
|
import { compose, transformToForm } from 'utils';
|
||||||
|
|
||||||
const defaultValues = {
|
const defaultValues = {
|
||||||
role_name: '',
|
role_name: '',
|
||||||
role_description: '',
|
role_description: '',
|
||||||
permissions: {},
|
permissions: {},
|
||||||
|
serviceFullAccess: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,67 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ErrorMessage, FastField, Form } from 'formik';
|
import { Form } from 'formik';
|
||||||
import { FormGroup, InputGroup, TextArea } from '@blueprintjs/core';
|
|
||||||
|
|
||||||
import { inputIntent } from 'utils';
|
import { RoleFormHeader } from './RoleFormHeader';
|
||||||
import { FormattedMessage as T, FieldRequiredHint, Card } from 'components';
|
|
||||||
import { useAutofocus } from 'hooks';
|
|
||||||
import { RolesPermissionList } from './components';
|
import { RolesPermissionList } from './components';
|
||||||
import { RoleFormFloatingActions } from './RoleFormFloatingActions';
|
import { RoleFormFloatingActions } from './RoleFormFloatingActions';
|
||||||
|
import { RoleFormObserver } from './RoleFormObserver';
|
||||||
/**
|
|
||||||
* Role form header.
|
|
||||||
* @returns {React.JSX}
|
|
||||||
*/
|
|
||||||
function RoleFormHeader() {
|
|
||||||
const roleNameFieldRef = useAutofocus();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
{/* ---------- name ---------- */}
|
|
||||||
<FastField name={'role_name'}>
|
|
||||||
{({ field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<strong><T id={'role_name'} /></strong>}
|
|
||||||
labelInfo={<FieldRequiredHint />}
|
|
||||||
className={'form-group--name'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name="role_name" />}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<InputGroup
|
|
||||||
medium={true}
|
|
||||||
inputRef={(ref) => (roleNameFieldRef.current = ref)}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
{/* ---------- description ---------- */}
|
|
||||||
<FastField name={'role_description'}>
|
|
||||||
{({ field, meta: { error, touched } }) => (
|
|
||||||
<FormGroup
|
|
||||||
label={<T id={'description'} />}
|
|
||||||
className={'form-group--description'}
|
|
||||||
intent={inputIntent({ error, touched })}
|
|
||||||
helperText={<ErrorMessage name={'role_description'} />}
|
|
||||||
inline={true}
|
|
||||||
>
|
|
||||||
<TextArea
|
|
||||||
growVertically={true}
|
|
||||||
height={280}
|
|
||||||
{...field}
|
|
||||||
placeholder="Max. 500 characters"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferences - Roles Form content.
|
* Preferences - Roles Form content.
|
||||||
|
* @returns {React.JSX}
|
||||||
*/
|
*/
|
||||||
export default function RolesFormContent() {
|
export default function RolesFormContent() {
|
||||||
return (
|
return (
|
||||||
@@ -69,6 +16,7 @@ export default function RolesFormContent() {
|
|||||||
<RoleFormHeader />
|
<RoleFormHeader />
|
||||||
<RolesPermissionList />
|
<RolesPermissionList />
|
||||||
<RoleFormFloatingActions />
|
<RoleFormFloatingActions />
|
||||||
|
<RoleFormObserver />
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Checkbox, Switch, Popover } from '@blueprintjs/core';
|
import { Checkbox, Popover } from '@blueprintjs/core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { FastField } from 'formik';
|
import { Field } from 'formik';
|
||||||
|
|
||||||
import { permissions, ModulePermissionsStyle } from 'common/permissionsSchema';
|
import { permissions, ModulePermissionsStyle } from 'common/permissionsSchema';
|
||||||
import { Card, If, ButtonLink, Choose } from 'components';
|
import { Card, If, ButtonLink, Choose } from 'components';
|
||||||
import {
|
import {
|
||||||
getSerivceColumnPermission,
|
getSerivceColumnPermission,
|
||||||
getServiceExtraPermissions,
|
getServiceExtraPermissions,
|
||||||
|
FULL_ACCESS_CHECKBOX_STATE,
|
||||||
|
handleCheckboxFullAccessChange,
|
||||||
|
handleCheckboxPermissionChange,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
// Module permissions context.
|
// Module permissions context.
|
||||||
@@ -66,15 +69,20 @@ function PermissionBodyColumn({ column }) {
|
|||||||
if (!permission) {
|
if (!permission) {
|
||||||
return <td class={'permission-checkbox'}></td>;
|
return <td class={'permission-checkbox'}></td>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<td class={'permission-checkbox'}>
|
<td class={'permission-checkbox'}>
|
||||||
<FastField
|
<Field
|
||||||
name={`permissions.${service.subject}/${permission.key}`}
|
name={`permissions.${service.subject}/${permission.key}`}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
{({ field }) => <PermissionCheckbox inline={true} {...field} />}
|
{({ field, form }) => (
|
||||||
</FastField>
|
<PermissionCheckbox
|
||||||
|
inline={true}
|
||||||
|
{...field}
|
||||||
|
onChange={handleCheckboxPermissionChange(form, permission, service)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -103,18 +111,23 @@ function ModuleExtraPermissionsPopover() {
|
|||||||
|
|
||||||
<ExtraPermissionsRoot>
|
<ExtraPermissionsRoot>
|
||||||
{extraPermissions.map((permission) => (
|
{extraPermissions.map((permission) => (
|
||||||
<FastField
|
<Field
|
||||||
name={`permissions.${service.subject}/${permission.key}`}
|
name={`permissions.${service.subject}/${permission.key}`}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
{({ form: { setFieldValue, values }, field }) => (
|
{({ form, field }) => (
|
||||||
<PermissionCheckbox
|
<PermissionCheckbox
|
||||||
inline={true}
|
inline={true}
|
||||||
label={permission.label}
|
label={permission.label}
|
||||||
{...field}
|
{...field}
|
||||||
|
onChange={handleCheckboxPermissionChange(
|
||||||
|
form,
|
||||||
|
permission,
|
||||||
|
service,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</Field>
|
||||||
))}
|
))}
|
||||||
</ExtraPermissionsRoot>
|
</ExtraPermissionsRoot>
|
||||||
</Popover>
|
</Popover>
|
||||||
@@ -179,14 +192,18 @@ function ModulePermissionsServiceFullAccess() {
|
|||||||
return (
|
return (
|
||||||
<If condition={module.serviceFullAccess}>
|
<If condition={module.serviceFullAccess}>
|
||||||
<td class="full-access-permission">
|
<td class="full-access-permission">
|
||||||
<FastField
|
<Field name={`serviceFullAccess.${service.subject}`} type="checkbox">
|
||||||
name={`serviceFullAccess.${service.subject}`}
|
{({ form, field }) => (
|
||||||
type="checkbox"
|
<PermissionCheckbox
|
||||||
>
|
inline={true}
|
||||||
{({ form: { setFieldValue, values }, field }) => (
|
{...field}
|
||||||
<PermissionCheckbox inline={true} />
|
indeterminate={
|
||||||
|
field.value === FULL_ACCESS_CHECKBOX_STATE.INDETARMINE
|
||||||
|
}
|
||||||
|
onChange={handleCheckboxFullAccessChange(service, form)}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</Field>
|
||||||
</td>
|
</td>
|
||||||
</If>
|
</If>
|
||||||
);
|
);
|
||||||
@@ -242,18 +259,23 @@ function ModuleVerticalTableCells() {
|
|||||||
<td class={'permissions'}>
|
<td class={'permissions'}>
|
||||||
{service.permissions.map((permission) => (
|
{service.permissions.map((permission) => (
|
||||||
<div>
|
<div>
|
||||||
<FastField
|
<Field
|
||||||
name={`permissions.${service.subject}/${permission.key}`}
|
name={`permissions.${service.subject}/${permission.key}`}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
>
|
>
|
||||||
{({ form: { setFieldValue, values }, field }) => (
|
{({ form, field }) => (
|
||||||
<PermissionCheckbox
|
<PermissionCheckbox
|
||||||
inline={true}
|
inline={true}
|
||||||
label={permission.label}
|
label={permission.label}
|
||||||
{...field}
|
{...field}
|
||||||
|
onChange={handleCheckboxPermissionChange(
|
||||||
|
form,
|
||||||
|
permission,
|
||||||
|
service,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FastField>
|
</Field>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</td>
|
</td>
|
||||||
@@ -319,12 +341,6 @@ function ModulePermissions({ module }) {
|
|||||||
<ModulePermissionsProvider module={module}>
|
<ModulePermissionsProvider module={module}>
|
||||||
<ModulePermissionHead>
|
<ModulePermissionHead>
|
||||||
<ModulePermissionTitle>{module.label} </ModulePermissionTitle>
|
<ModulePermissionTitle>{module.label} </ModulePermissionTitle>
|
||||||
|
|
||||||
<If condition={module.moduleFullAccess}>
|
|
||||||
<ModulePermissionFullControlRoot>
|
|
||||||
<Switch />
|
|
||||||
</ModulePermissionFullControlRoot>
|
|
||||||
</If>
|
|
||||||
</ModulePermissionHead>
|
</ModulePermissionHead>
|
||||||
|
|
||||||
<ModulePermissionsBody />
|
<ModulePermissionsBody />
|
||||||
@@ -380,15 +396,6 @@ const ModulePermissionTitle = styled.div`
|
|||||||
color: #878787;
|
color: #878787;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ModulePermissionFullControlRoot = styled.div`
|
|
||||||
margin-left: auto;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.bp3-switch {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ModulePermissionBodyRoot = styled.div``;
|
const ModulePermissionBodyRoot = styled.div``;
|
||||||
|
|
||||||
const ModulePermissionsTableRoot = styled.table`
|
const ModulePermissionsTableRoot = styled.table`
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
import { chain } from 'lodash';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import {
|
||||||
|
getPermissionsSchemaService,
|
||||||
|
getPermissionsSchemaServices,
|
||||||
|
} from 'common/permissionsSchema';
|
||||||
|
|
||||||
|
export const FULL_ACCESS_CHECKBOX_STATE = {
|
||||||
|
INDETARMINE: -1,
|
||||||
|
ON: true,
|
||||||
|
OFF: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes the permissions object to array.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const transformToArray = ({ permissions }) => {
|
export const transformToArray = ({ permissions }) => {
|
||||||
return Object.keys(permissions).map((index) => {
|
return Object.keys(permissions).map((index) => {
|
||||||
const [value, key] = index.split('/');
|
const [value, key] = index.split('/');
|
||||||
@@ -10,6 +27,20 @@ export const transformToArray = ({ permissions }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function transformPermissions(permissions) {
|
||||||
|
return Object.keys(permissions).map((permissionKey) => {
|
||||||
|
const [subject, key] = permissionKey.split('/');
|
||||||
|
const value = permissions[permissionKey];
|
||||||
|
|
||||||
|
return { key, subject, value };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes permissions array to object.
|
||||||
|
* @param {*} permissions -
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const transformPermissionsToObject = (permissions) => {
|
export const transformPermissionsToObject = (permissions) => {
|
||||||
const output = {};
|
const output = {};
|
||||||
permissions.forEach((item) => {
|
permissions.forEach((item) => {
|
||||||
@@ -18,6 +49,11 @@ export const transformPermissionsToObject = (permissions) => {
|
|||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} role
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const transformToObject = (role) => {
|
export const transformToObject = (role) => {
|
||||||
return {
|
return {
|
||||||
role_name: role.name,
|
role_name: role.name,
|
||||||
@@ -44,22 +80,162 @@ export const getDefaultValuesFromSchema = (schema) => {
|
|||||||
.flat();
|
.flat();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve initial values of full access services.
|
||||||
|
* @param {*} formPermissions
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getInitialServicesFullAccess = (formPermissions) => {
|
||||||
|
const services = getPermissionsSchemaServices();
|
||||||
|
|
||||||
|
return chain(services)
|
||||||
|
.map((service) => {
|
||||||
|
const { subject } = service;
|
||||||
|
const isFullChecked = isServiceFullChecked(subject, formPermissions);
|
||||||
|
const isFullUnchecked = isServiceFullUnchecked(subject, formPermissions);
|
||||||
|
const value = detarmineCheckboxState(isFullChecked, isFullUnchecked);
|
||||||
|
|
||||||
|
return [service.subject, value];
|
||||||
|
})
|
||||||
|
.fromPairs()
|
||||||
|
.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} schema
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const getNewRoleInitialValues = (schema) => {
|
export const getNewRoleInitialValues = (schema) => {
|
||||||
|
const permissions = transformPermissionsToObject(
|
||||||
|
getDefaultValuesFromSchema(schema),
|
||||||
|
);
|
||||||
|
const serviceFullAccess = getInitialServicesFullAccess(permissions);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
permissions: transformPermissionsToObject(
|
permissions,
|
||||||
getDefaultValuesFromSchema(schema),
|
serviceFullAccess,
|
||||||
),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} service
|
||||||
|
* @param {*} columnKey
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export function getSerivceColumnPermission(service, columnKey) {
|
export function getSerivceColumnPermission(service, columnKey) {
|
||||||
return service.permissions.find((permission) => {
|
return service.permissions.find((permission) => {
|
||||||
return permission.relatedColumn === columnKey;
|
return permission.relatedColumn === columnKey;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} service
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export function getServiceExtraPermissions(service) {
|
export function getServiceExtraPermissions(service) {
|
||||||
return service.permissions.filter((permission) => {
|
return service.permissions.filter((permission) => {
|
||||||
return !permission.relatedColumn;
|
return !permission.relatedColumn;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the given service subject is full permissions checked.
|
||||||
|
*/
|
||||||
|
export function isServiceFullChecked(subject, permissions) {
|
||||||
|
const serviceSchema = getPermissionsSchemaService(subject);
|
||||||
|
|
||||||
|
return serviceSchema.permissions.every(
|
||||||
|
(permission) => permissions[`${subject}/${permission.key}`],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the given service subject is fully associated permissions unchecked.
|
||||||
|
* @param {string} subject -
|
||||||
|
* @param {Object} permissionsMap -
|
||||||
|
*/
|
||||||
|
export function isServiceFullUnchecked(subject, permissionsMap) {
|
||||||
|
const serviceSchema = getPermissionsSchemaService(subject);
|
||||||
|
|
||||||
|
return serviceSchema.permissions.every(
|
||||||
|
(permission) => !permissionsMap[`${subject}/${permission.key}`],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles permission checkbox change.
|
||||||
|
*/
|
||||||
|
export const handleCheckboxPermissionChange = R.curry(
|
||||||
|
(form, permission, service, event) => {
|
||||||
|
const { subject } = service;
|
||||||
|
const isChecked = event.currentTarget.checked;
|
||||||
|
const newValues = {
|
||||||
|
...form.values,
|
||||||
|
permissions: {
|
||||||
|
...form.values.permissions,
|
||||||
|
[`${subject}/${permission.key}`]: isChecked,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const isFullChecked = isServiceFullChecked(subject, newValues.permissions);
|
||||||
|
const isFullUnchecked = isServiceFullUnchecked(
|
||||||
|
subject,
|
||||||
|
newValues.permissions,
|
||||||
|
);
|
||||||
|
form.setFieldValue(`permissions.${subject}/${permission.key}`, isChecked);
|
||||||
|
form.setFieldValue(
|
||||||
|
`serviceFullAccess.${subject}`,
|
||||||
|
detarmineCheckboxState(isFullChecked, isFullUnchecked),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the permission checkbox state.
|
||||||
|
* @param {boolean} isFullChecked
|
||||||
|
* @param {boolean} isFullUnchecked
|
||||||
|
* @returns {FULL_ACCESS_CHECKBOX_STATE}
|
||||||
|
*/
|
||||||
|
function detarmineCheckboxState(isFullChecked, isFullUnchecked) {
|
||||||
|
return isFullChecked
|
||||||
|
? FULL_ACCESS_CHECKBOX_STATE.ON
|
||||||
|
: isFullUnchecked
|
||||||
|
? FULL_ACCESS_CHECKBOX_STATE.OFF
|
||||||
|
: FULL_ACCESS_CHECKBOX_STATE.INDETARMINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retreive the service all permissions paths.
|
||||||
|
* @param {string} subject
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
export function getServiceAllPermissionsPaths(subject) {
|
||||||
|
const service = getPermissionsSchemaService(subject);
|
||||||
|
|
||||||
|
return service.permissions.map(
|
||||||
|
(perm) => `permissions.${subject}/${perm.key}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle full access service checkbox change.
|
||||||
|
*/
|
||||||
|
export const handleCheckboxFullAccessChange = R.curry(
|
||||||
|
(service, form, event) => {
|
||||||
|
const isChecked = event.currentTarget.checked;
|
||||||
|
const permsPaths = getServiceAllPermissionsPaths(service.subject);
|
||||||
|
|
||||||
|
form.setFieldValue(`serviceFullAccess.${service.subject}`, isChecked);
|
||||||
|
|
||||||
|
permsPaths.forEach((permissionPath) => {
|
||||||
|
form.setFieldValue(
|
||||||
|
permissionPath,
|
||||||
|
isChecked
|
||||||
|
? FULL_ACCESS_CHECKBOX_STATE.ON
|
||||||
|
: FULL_ACCESS_CHECKBOX_STATE.OFF,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ export * from './useRequestPdf';
|
|||||||
export * from './useAsync';
|
export * from './useAsync';
|
||||||
export * from './useIntersectionObserver';
|
export * from './useIntersectionObserver';
|
||||||
export * from './useAbilityContext';
|
export * from './useAbilityContext';
|
||||||
|
export * from './useCustomCompareEffect';
|
||||||
|
export * from './useDeepCompareEffect';
|
||||||
|
|||||||
44
src/hooks/utils/useCustomCompareEffect.ts
Normal file
44
src/hooks/utils/useCustomCompareEffect.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { DependencyList, EffectCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
const isPrimitive = (val: any) => val !== Object(val);
|
||||||
|
|
||||||
|
type DepsEqualFnType<TDeps extends DependencyList> = (
|
||||||
|
prevDeps: TDeps,
|
||||||
|
nextDeps: TDeps,
|
||||||
|
) => boolean;
|
||||||
|
|
||||||
|
const useCustomCompareEffect = <TDeps extends DependencyList>(
|
||||||
|
effect: EffectCallback,
|
||||||
|
deps: TDeps,
|
||||||
|
depsEqual: DepsEqualFnType<TDeps>,
|
||||||
|
) => {
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
if (!(deps instanceof Array) || !deps.length) {
|
||||||
|
console.warn(
|
||||||
|
'`useCustomCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deps.every(isPrimitive)) {
|
||||||
|
console.warn(
|
||||||
|
'`useCustomCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof depsEqual !== 'function') {
|
||||||
|
console.warn(
|
||||||
|
'`useCustomCompareEffect` should be used with depsEqual callback for comparing deps list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref = useRef<TDeps | undefined>(undefined);
|
||||||
|
|
||||||
|
if (!ref.current || !depsEqual(deps, ref.current)) {
|
||||||
|
ref.current = deps;
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(effect, ref.current);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useCustomCompareEffect };
|
||||||
24
src/hooks/utils/useDeepCompareEffect.ts
Normal file
24
src/hooks/utils/useDeepCompareEffect.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { DependencyList, EffectCallback } from 'react';
|
||||||
|
import isDeepEqualReact from 'fast-deep-equal/react';
|
||||||
|
import { useCustomCompareEffect } from './useCustomCompareEffect';
|
||||||
|
|
||||||
|
const isPrimitive = (val: any) => val !== Object(val);
|
||||||
|
|
||||||
|
const useDeepCompareEffect = (effect: EffectCallback, deps: DependencyList) => {
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
if (!(deps instanceof Array) || !deps.length) {
|
||||||
|
console.warn(
|
||||||
|
'`useDeepCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deps.every(isPrimitive)) {
|
||||||
|
console.warn(
|
||||||
|
'`useDeepCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useCustomCompareEffect(effect, deps, isDeepEqualReact);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useDeepCompareEffect };
|
||||||
Reference in New Issue
Block a user