@memberjunction/ng-entity-permissions 2.42.1 → 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +402 -91
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -2,15 +2,26 @@
2
2
 
3
3
  The `@memberjunction/ng-entity-permissions` package provides Angular components for displaying and editing permissions for MemberJunction entities. It allows administrators to manage role-based access control (RBAC) for entities in a user-friendly grid interface.
4
4
 
5
+ ## Overview
6
+
7
+ This package is part of the MemberJunction platform and provides essential UI components for managing entity-level permissions. It offers two primary components:
8
+
9
+ 1. **EntityPermissionsGridComponent** - A grid that displays and allows editing of permissions for either a specific entity across all roles, or for a specific role across all entities
10
+ 2. **EntityPermissionsSelectorWithGridComponent** - A composite component that combines an entity dropdown selector with the permissions grid
11
+
5
12
  ## Features
6
13
 
7
- - Grid-based interface for viewing and editing entity permissions
8
- - Support for managing permissions in two modes: by entity or by role
9
- - Ability to toggle Read, Create, Update, and Delete permissions individually
10
- - Batch editing capabilities with transaction support
11
- - Entity selector with integrated permissions grid
12
- - Visual indication of modified permissions before saving
13
- - Quick actions to flip all permissions or reset changes
14
+ - **Dual-mode operation**: View permissions by entity (all roles for one entity) or by role (all entities for one role)
15
+ - **Grid-based interface** for intuitive permission management
16
+ - **Batch editing** with transaction support for atomic updates
17
+ - **Visual feedback** with dirty state indicators and row highlighting
18
+ - **Quick actions**:
19
+ - Flip all permissions of a specific type (Read/Create/Update/Delete)
20
+ - Toggle all permissions in a row with intelligent logic
21
+ - Revert individual row changes
22
+ - **Real-time permission change events** with cancellation support
23
+ - **Automatic permission record creation** for missing role/entity combinations
24
+ - **Responsive loading states** with Kendo UI indicators
14
25
 
15
26
  ## Installation
16
27
 
@@ -20,159 +31,459 @@ npm install @memberjunction/ng-entity-permissions
20
31
 
21
32
  ## Requirements
22
33
 
23
- - Angular 18+
24
- - @memberjunction/core
25
- - @memberjunction/core-entities
26
- - @progress/kendo-angular-grid
27
- - @progress/kendo-angular-dropdowns
28
- - @progress/kendo-angular-buttons
29
- - @progress/kendo-angular-dialog
30
- - @progress/kendo-angular-indicators
34
+ ### Peer Dependencies
35
+ - Angular 18.0.2+
36
+ - @angular/common
37
+ - @angular/core
38
+ - @angular/forms
39
+ - @angular/router
40
+
41
+ ### Runtime Dependencies
42
+ - @memberjunction/core (v2.43.0+)
43
+ - @memberjunction/core-entities (v2.43.0+)
44
+ - @memberjunction/global (v2.43.0+)
45
+ - @memberjunction/ng-container-directives (v2.43.0+)
46
+ - @memberjunction/ng-shared (v2.43.0+)
47
+ - @progress/kendo-angular-grid (v16.2.0)
48
+ - @progress/kendo-angular-dropdowns (v16.2.0)
49
+ - @progress/kendo-angular-buttons (v16.2.0)
50
+ - @progress/kendo-angular-dialog (v16.2.0)
51
+ - @progress/kendo-angular-indicators (v16.2.0)
31
52
 
32
53
  ## Usage
33
54
 
34
- ### Basic Setup
55
+ ### Module Setup
35
56
 
36
- First, import the EntityPermissionsModule in your module:
57
+ First, import the `EntityPermissionsModule` in your Angular module:
37
58
 
38
59
  ```typescript
39
60
  import { EntityPermissionsModule } from '@memberjunction/ng-entity-permissions';
40
61
 
41
62
  @NgModule({
42
63
  imports: [
43
- // other imports...
64
+ CommonModule,
65
+ FormsModule,
66
+ // ... other imports
44
67
  EntityPermissionsModule
45
68
  ],
46
69
  })
47
70
  export class YourModule { }
48
71
  ```
49
72
 
50
- ### Entity Permissions Grid
73
+ ### Basic Usage Examples
51
74
 
52
- Use the grid component to display and edit permissions for a specific entity:
75
+ #### Entity Permissions Grid - Entity Mode
53
76
 
54
- ```html
55
- <mj-entity-permissions-grid
56
- [EntityName]="'Customer'"
57
- [Mode]="'Entity'"
58
- (PermissionChanged)="handlePermissionChanged($event)">
59
- </mj-entity-permissions-grid>
77
+ Display and manage permissions for a specific entity across all roles:
78
+
79
+ ```typescript
80
+ import { Component } from '@angular/core';
81
+ import { EntityPermissionChangedEvent } from '@memberjunction/ng-entity-permissions';
82
+
83
+ @Component({
84
+ selector: 'app-entity-permissions',
85
+ template: `
86
+ <mj-entity-permissions-grid
87
+ [EntityName]="'Customers'"
88
+ [Mode]="'Entity'"
89
+ [BottomMargin]="20"
90
+ (PermissionChanged)="onPermissionChanged($event)">
91
+ </mj-entity-permissions-grid>
92
+ `
93
+ })
94
+ export class EntityPermissionsComponent {
95
+ onPermissionChanged(event: EntityPermissionChangedEvent) {
96
+ console.log(`Permission ${event.PermissionTypeChanged} changed to ${event.Value} for role ${event.RoleID}`);
97
+
98
+ // Optionally cancel the change based on business logic
99
+ if (this.shouldPreventChange(event)) {
100
+ event.Cancel = true;
101
+ }
102
+ }
103
+
104
+ private shouldPreventChange(event: EntityPermissionChangedEvent): boolean {
105
+ // Implement your business logic here
106
+ return false;
107
+ }
108
+ }
60
109
  ```
61
110
 
62
- Or to display permissions for a specific role across all entities:
111
+ #### Entity Permissions Grid - Role Mode
112
+
113
+ Display and manage permissions for a specific role across all entities:
63
114
 
64
- ```html
65
- <mj-entity-permissions-grid
66
- [RoleName]="'Administrator'"
67
- [Mode]="'Role'"
68
- (PermissionChanged)="handlePermissionChanged($event)">
69
- </mj-entity-permissions-grid>
115
+ ```typescript
116
+ @Component({
117
+ selector: 'app-role-permissions',
118
+ template: `
119
+ <mj-entity-permissions-grid
120
+ [RoleName]="selectedRole"
121
+ [Mode]="'Role'"
122
+ (PermissionChanged)="onPermissionChanged($event)">
123
+ </mj-entity-permissions-grid>
124
+ `
125
+ })
126
+ export class RolePermissionsComponent {
127
+ selectedRole = 'Administrator';
128
+
129
+ onPermissionChanged(event: EntityPermissionChangedEvent) {
130
+ // Handle permission changes for the role
131
+ console.log(`Entity ${event.EntityName}: ${event.PermissionTypeChanged} = ${event.Value}`);
132
+ }
133
+ }
70
134
  ```
71
135
 
72
- In your component:
136
+ #### Entity Selector with Permissions Grid
137
+
138
+ Provide a dropdown to select entities dynamically:
73
139
 
74
140
  ```typescript
75
- import { Component } from '@angular/core';
76
- import { EntityPermissionChangedEvent } from '@memberjunction/ng-entity-permissions';
141
+ @Component({
142
+ selector: 'app-dynamic-permissions',
143
+ template: `
144
+ <div class="permissions-container">
145
+ <h2>Entity Permissions Manager</h2>
146
+ <mj-entity-permissions-selector-with-grid
147
+ [EntityName]="initialEntity"
148
+ [BottomMargin]="30"
149
+ (PermissionChanged)="handlePermissionChange($event)">
150
+ </mj-entity-permissions-selector-with-grid>
151
+ </div>
152
+ `
153
+ })
154
+ export class DynamicPermissionsComponent {
155
+ initialEntity = 'Customers'; // Optional initial selection
156
+
157
+ handlePermissionChange(event: EntityPermissionChangedEvent) {
158
+ // Process permission changes
159
+ this.logPermissionChange(event);
160
+ }
161
+
162
+ private logPermissionChange(event: EntityPermissionChangedEvent) {
163
+ console.log('Permission change:', {
164
+ entity: event.EntityName,
165
+ role: event.RoleID,
166
+ type: event.PermissionTypeChanged,
167
+ value: event.Value
168
+ });
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Advanced Usage
174
+
175
+ #### Programmatic Grid Control
176
+
177
+ Access the grid component directly to perform operations:
178
+
179
+ ```typescript
180
+ import { ViewChild } from '@angular/core';
181
+ import { EntityPermissionsGridComponent } from '@memberjunction/ng-entity-permissions';
77
182
 
78
183
  @Component({
79
- selector: 'app-permissions-manager',
80
- templateUrl: './permissions-manager.component.html',
184
+ template: `
185
+ <mj-entity-permissions-grid #permGrid
186
+ [EntityName]="'Orders'"
187
+ [Mode]="'Entity'">
188
+ </mj-entity-permissions-grid>
189
+
190
+ <button (click)="refreshPermissions()">Refresh</button>
191
+ <button (click)="saveAllChanges()">Save All</button>
192
+ <button (click)="flipReadPermissions()">Toggle All Read</button>
193
+ `
81
194
  })
82
- export class PermissionsManagerComponent {
83
- handlePermissionChanged(event: EntityPermissionChangedEvent) {
84
- console.log('Permission changed:', event);
85
- // You can cancel the change if needed by setting event.Cancel = true
195
+ export class AdvancedPermissionsComponent {
196
+ @ViewChild('permGrid') permissionsGrid!: EntityPermissionsGridComponent;
197
+
198
+ async refreshPermissions() {
199
+ await this.permissionsGrid.Refresh();
200
+ }
201
+
202
+ async saveAllChanges() {
203
+ if (this.permissionsGrid.NumDirtyPermissions > 0) {
204
+ await this.permissionsGrid.savePermissions();
205
+ console.log('All permissions saved successfully');
206
+ }
207
+ }
208
+
209
+ flipReadPermissions() {
210
+ this.permissionsGrid.flipAllPermissions('Read');
86
211
  }
87
212
  }
88
213
  ```
89
214
 
90
- ### Entity Selector with Permissions Grid
215
+ #### Handling Transactions
91
216
 
92
- Use the selector component to allow users to choose an entity and then manage its permissions:
217
+ The component automatically handles batch updates using MemberJunction's transaction system:
93
218
 
94
- ```html
95
- <mj-entity-permissions-selector-with-grid
96
- (PermissionChanged)="handlePermissionChanged($event)">
97
- </mj-entity-permissions-selector-with-grid>
219
+ ```typescript
220
+ // The grid component internally uses transaction groups for atomic updates
221
+ // When savePermissions() is called, all dirty permissions are saved in a single transaction
222
+ // This ensures data consistency and allows for rollback if any permission update fails
98
223
  ```
99
224
 
100
225
  ## API Reference
101
226
 
102
227
  ### EntityPermissionsGridComponent
103
228
 
104
- #### Inputs
229
+ **Selector:** `mj-entity-permissions-grid`
230
+
231
+ #### Properties
232
+
233
+ ##### Inputs
105
234
 
106
235
  | Name | Type | Default | Description |
107
236
  |------|------|---------|-------------|
108
- | `Mode` | `'Entity' \| 'Role'` | `'Entity'` | Whether to display permissions for a specific entity or role |
109
- | `EntityName` | `string` | `undefined` | Name of the entity to show permissions for (when Mode is 'Entity') |
110
- | `RoleName` | `string` | `undefined` | Name of the role to show permissions for (when Mode is 'Role') |
111
- | `BottomMargin` | `number` | `0` | Margin to apply at the bottom of the grid |
237
+ | `Mode` | `'Entity' \| 'Role'` | `'Entity'` | Determines whether to display permissions for a specific entity across all roles or for a specific role across all entities |
238
+ | `EntityName` | `string` | `undefined` | Required when Mode is 'Entity'. The name of the entity to show permissions for |
239
+ | `RoleName` | `string` | `undefined` | Required when Mode is 'Role'. The name of the role to show permissions for |
240
+ | `BottomMargin` | `number` | `0` | Bottom margin in pixels to apply to the grid container |
112
241
 
113
- #### Outputs
242
+ ##### Outputs
114
243
 
115
244
  | Name | Type | Description |
116
245
  |------|------|-------------|
117
- | `PermissionChanged` | `EventEmitter<EntityPermissionChangedEvent>` | Emitted when a permission is changed |
246
+ | `PermissionChanged` | `EventEmitter<EntityPermissionChangedEvent>` | Emitted whenever a permission checkbox is toggled. The event can be cancelled by setting `event.Cancel = true` |
247
+
248
+ ##### Public Properties
249
+
250
+ | Name | Type | Description |
251
+ |------|------|-------------|
252
+ | `permissions` | `EntityPermissionEntity[]` | Array of permission records currently displayed in the grid |
253
+ | `gridHeight` | `number` | Height of the grid in pixels (default: 750) |
254
+ | `isLoading` | `boolean` | Loading state indicator |
255
+ | `NumDirtyPermissions` | `number` | Count of permissions that have been modified but not saved |
118
256
 
119
257
  #### Methods
120
258
 
121
- | Name | Parameters | Return Type | Description |
122
- |------|------------|-------------|-------------|
123
- | `Refresh` | None | `Promise<void>` | Reloads permissions data |
124
- | `savePermissions` | None | `Promise<void>` | Saves all modified permissions |
125
- | `cancelEdit` | None | `Promise<void>` | Reverts all unsaved changes |
126
- | `flipAllPermissions` | `type: 'Read' \| 'Create' \| 'Update' \| 'Delete'` | `void` | Toggles all permissions of the specified type |
259
+ | Method | Parameters | Return Type | Description |
260
+ |--------|------------|-------------|-------------|
261
+ | `Refresh()` | None | `Promise<void>` | Reloads all permissions data from the database. Automatically creates missing permission records for display |
262
+ | `savePermissions()` | None | `Promise<void>` | Saves all modified permissions in a single transaction. Only saves permissions that are truly dirty |
263
+ | `cancelEdit()` | None | `Promise<void>` | Reverts all unsaved changes to their original values |
264
+ | `flipAllPermissions(type)` | `type: 'Read' \| 'Create' \| 'Update' \| 'Delete'` | `void` | Intelligently toggles all permissions of the specified type. If majority are ON, turns all OFF; otherwise turns all ON |
265
+ | `flipRow(permission)` | `permission: EntityPermissionEntity` | `void` | Toggles all permissions in a row. If 2+ are ON, turns all OFF; otherwise turns all ON |
266
+ | `revertRow(event, permission)` | `event: MouseEvent, permission: EntityPermissionEntity` | `void` | Reverts a single row to its original state |
127
267
 
128
268
  ### EntityPermissionsSelectorWithGridComponent
129
269
 
130
- #### Inputs
270
+ **Selector:** `mj-entity-permissions-selector-with-grid`
271
+
272
+ #### Properties
273
+
274
+ ##### Inputs
131
275
 
132
276
  | Name | Type | Default | Description |
133
277
  |------|------|---------|-------------|
134
- | `EntityName` | `string` | `undefined` | Name of the initially selected entity |
135
- | `BottomMargin` | `number` | `0` | Margin to apply at the bottom of the component |
278
+ | `EntityName` | `string` | `undefined` | Optional. Name of the initially selected entity |
279
+ | `BottomMargin` | `number` | `0` | Bottom margin in pixels to apply to the component |
280
+ | `CurrentEntity` | `EntityInfo \| undefined` | `undefined` | The currently selected entity object. Can be used for two-way binding |
136
281
 
137
- #### Outputs
282
+ ##### Outputs
138
283
 
139
284
  | Name | Type | Description |
140
285
  |------|------|-------------|
141
- | `PermissionChanged` | `EventEmitter<EntityPermissionChangedEvent>` | Emitted when a permission is changed |
286
+ | `PermissionChanged` | `EventEmitter<EntityPermissionChangedEvent>` | Bubbles up permission change events from the embedded grid |
287
+
288
+ ##### Public Properties
289
+
290
+ | Name | Type | Description |
291
+ |------|------|-------------|
292
+ | `entityList` | `EntityInfo[]` | Alphabetically sorted list of all entities available for selection |
142
293
 
143
294
  ### EntityPermissionChangedEvent Interface
144
295
 
145
296
  ```typescript
146
- type EntityPermissionChangedEvent = {
147
- EntityName: string, // Name of the entity
148
- RoleID: string // ID of the role
149
- PermissionTypeChanged: 'Read' | 'Create' | 'Update' | 'Delete' // Type of permission changed
150
- Value: boolean // New value of the permission
151
- Cancel: boolean // Set to true to cancel the change
297
+ export type EntityPermissionChangedEvent = {
298
+ EntityName: string; // Name of the entity whose permission changed
299
+ RoleID: string; // ID of the role whose permission changed
300
+ PermissionTypeChanged: 'Read' | 'Create' | 'Update' | 'Delete'; // The specific permission type that was modified
301
+ Value: boolean; // The new value of the permission (true = granted, false = revoked)
302
+ Cancel: boolean; // Set to true in event handler to cancel the change
152
303
  }
153
304
  ```
154
305
 
306
+ ### Internal Behavior Notes
307
+
308
+ 1. **Automatic Record Creation**: When loading permissions, the component automatically creates unsaved EntityPermission records for any missing role/entity combinations. These appear in the grid but are only saved if the user enables at least one permission.
309
+
310
+ 2. **Dirty State Logic**: A permission is considered "really dirty" if:
311
+ - It's an existing saved record that has been modified, OR
312
+ - It's a new record with at least one permission enabled
313
+
314
+ 3. **Transaction Support**: All save operations use MemberJunction's TransactionGroup to ensure atomic updates across multiple permission records.
315
+
316
+ 4. **Event Handling**: The grid uses a sophisticated event system where clicking on checkboxes or table cells properly toggles permissions while preventing event bubbling conflicts.
317
+
155
318
  ## Styling
156
319
 
157
- The components use the following CSS classes that can be customized:
320
+ The components use standard HTML tables with custom CSS classes that can be overridden:
321
+
322
+ ### CSS Classes
323
+
324
+ | Class | Applied To | Description |
325
+ |-------|------------|-------------|
326
+ | `.grid` | `<table>` | Main permissions grid table |
327
+ | `.permission-left-col` | First `<td>` in each row | Left column containing entity/role names and revert icon |
328
+ | `.dirty-row` | `<tr>` | Applied to rows that have unsaved changes |
329
+ | `.entity-selector` | `<kendo-dropdownlist>` | Styles the entity selection dropdown |
330
+ | `.inner-grid` | `<mj-entity-permissions-grid>` | Applied to the grid within the selector component |
331
+ | `.fa-arrow-rotate-left` | `<span>` icon | Revert icon shown in dirty rows |
332
+
333
+ ### Customization Example
334
+
335
+ ```css
336
+ /* Custom styling for your application */
337
+ ::ng-deep {
338
+ .mj-entity-permissions-grid {
339
+ .grid {
340
+ border: 1px solid #ddd;
341
+ width: 100%;
342
+ }
343
+
344
+ .dirty-row {
345
+ background-color: #fff3cd;
346
+
347
+ .permission-left-col {
348
+ font-weight: bold;
349
+
350
+ .fa-arrow-rotate-left {
351
+ color: #856404;
352
+ cursor: pointer;
353
+ margin-left: 10px;
354
+
355
+ &:hover {
356
+ color: #533f03;
357
+ }
358
+ }
359
+ }
360
+ }
361
+
362
+ th {
363
+ cursor: pointer;
364
+ user-select: none;
365
+
366
+ &:hover {
367
+ background-color: #f0f0f0;
368
+ }
369
+ }
370
+ }
371
+ }
372
+ ```
373
+
374
+ ## Integration with MemberJunction
158
375
 
159
- - `.grid`: Main permissions grid
160
- - `.permission-left-col`: Left column in the grid (entity/role name)
161
- - `.dirty-row`: Applied to rows with unsaved changes
162
- - `.entity-selector`: Applied to the entity dropdown
163
- - `.inner-grid`: Applied to the grid within the selector component
376
+ This package integrates seamlessly with the MemberJunction ecosystem:
164
377
 
165
- ## Dependencies
378
+ ### Entity Permission System
379
+ - Works with the `EntityPermissionEntity` from `@memberjunction/core-entities`
380
+ - Respects the MemberJunction metadata system for entities and roles
381
+ - Uses MemberJunction's transaction system for atomic updates
166
382
 
167
- - @angular/common
168
- - @angular/core
169
- - @angular/forms
170
- - @memberjunction/core
171
- - @memberjunction/core-entities
172
- - @memberjunction/ng-container-directives
173
- - @memberjunction/ng-shared
174
- - @progress/kendo-angular-dropdowns
175
- - @progress/kendo-angular-grid
176
- - @progress/kendo-angular-buttons
177
- - @progress/kendo-angular-dialog
178
- - @progress/kendo-angular-indicators
383
+ ### Metadata Integration
384
+ - Automatically discovers all entities and roles from the Metadata provider
385
+ - Validates entity and role names against the metadata
386
+ - Creates properly typed entity objects using the metadata system
387
+
388
+ ### RunView Integration
389
+ - Uses `RunView` for efficient data loading with proper filtering
390
+ - Leverages `ResultType: 'entity_object'` for automatic entity instantiation
391
+ - Implements proper ordering for consistent display
392
+
393
+ ## Build and Development
394
+
395
+ This package uses the Angular compiler (`ngc`) for building:
396
+
397
+ ```bash
398
+ # Build the package
399
+ npm run build
400
+
401
+ # The built files will be in the dist/ directory
402
+ ```
403
+
404
+ ### TypeScript Configuration
405
+ - Targets ES2015 with ES2020 modules
406
+ - Generates declaration files with source maps
407
+ - Uses strict mode for type safety
408
+ - Configured for Angular library compilation with strict templates
409
+
410
+ ## Performance Considerations
411
+
412
+ 1. **Efficient Loading**: The component loads all permissions in a single query and creates missing records in memory
413
+ 2. **Batch Updates**: Uses transaction groups to minimize database round trips
414
+ 3. **Smart Dirty Checking**: Only saves records that have actual changes
415
+ 4. **Lazy Initialization**: Permission records for missing combinations are created on-demand
416
+
417
+ ## Common Use Cases
418
+
419
+ ### Admin Dashboard
420
+ ```typescript
421
+ // Create a comprehensive admin interface for managing all permissions
422
+ @Component({
423
+ template: `
424
+ <mat-tab-group>
425
+ <mat-tab label="By Entity">
426
+ <mj-entity-permissions-selector-with-grid></mj-entity-permissions-selector-with-grid>
427
+ </mat-tab>
428
+ <mat-tab label="By Role">
429
+ <select [(ngModel)]="selectedRole">
430
+ <option *ngFor="let role of roles" [value]="role.Name">{{role.Name}}</option>
431
+ </select>
432
+ <mj-entity-permissions-grid
433
+ *ngIf="selectedRole"
434
+ [Mode]="'Role'"
435
+ [RoleName]="selectedRole">
436
+ </mj-entity-permissions-grid>
437
+ </mat-tab>
438
+ </mat-tab-group>
439
+ `
440
+ })
441
+ export class PermissionsDashboardComponent {
442
+ // Implementation
443
+ }
444
+ ```
445
+
446
+ ### Role Creation Wizard
447
+ ```typescript
448
+ // Include permissions step in role creation
449
+ @Component({
450
+ template: `
451
+ <div *ngIf="currentStep === 'permissions'">
452
+ <h3>Configure Permissions for {{newRole.Name}}</h3>
453
+ <mj-entity-permissions-grid
454
+ [Mode]="'Role'"
455
+ [RoleName]="newRole.Name"
456
+ (PermissionChanged)="trackPermissionChanges($event)">
457
+ </mj-entity-permissions-grid>
458
+ </div>
459
+ `
460
+ })
461
+ export class RoleWizardComponent {
462
+ // Track changes and save with role
463
+ }
464
+ ```
465
+
466
+ ## Troubleshooting
467
+
468
+ ### Common Issues
469
+
470
+ 1. **"EntityName is required when Mode is 'Entity'"**
471
+ - Ensure you provide the EntityName input when using Entity mode
472
+ - Check that the entity name matches exactly (case-sensitive)
473
+
474
+ 2. **"Entity not found: [EntityName]"**
475
+ - Verify the entity exists in MemberJunction metadata
476
+ - Ensure metadata is properly loaded before component initialization
477
+
478
+ 3. **Permissions not saving**
479
+ - Check browser console for transaction errors
480
+ - Verify user has permission to modify EntityPermission records
481
+ - Ensure database constraints are not violated
482
+
483
+ 4. **Grid not displaying**
484
+ - Confirm all Kendo UI modules are properly imported
485
+ - Check that EntityPermissionsModule is imported in your module
486
+
487
+ ## License
488
+
489
+ ISC License - see the root MemberJunction repository for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-entity-permissions",
3
- "version": "2.42.1",
3
+ "version": "2.44.0",
4
4
  "description": "MemberJunction: Angular components for displaying/editing permissions for an entity, and related components.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -25,11 +25,11 @@
25
25
  "@angular/router": "18.0.2"
26
26
  },
27
27
  "dependencies": {
28
- "@memberjunction/core-entities": "2.42.1",
29
- "@memberjunction/global": "2.42.1",
30
- "@memberjunction/core": "2.42.1",
31
- "@memberjunction/ng-container-directives": "2.42.1",
32
- "@memberjunction/ng-shared": "2.42.1",
28
+ "@memberjunction/core-entities": "2.44.0",
29
+ "@memberjunction/global": "2.44.0",
30
+ "@memberjunction/core": "2.44.0",
31
+ "@memberjunction/ng-container-directives": "2.44.0",
32
+ "@memberjunction/ng-shared": "2.44.0",
33
33
  "@progress/kendo-angular-dropdowns": "16.2.0",
34
34
  "@progress/kendo-angular-grid": "16.2.0",
35
35
  "@progress/kendo-angular-buttons": "16.2.0",