@memberjunction/ng-record-selector 2.32.2 → 2.33.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 +250 -0
  2. package/package.json +6 -6
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ # Record Selector Component
2
+
3
+ An Angular component for selecting records from a list of available items in MemberJunction applications. This package provides both a standalone selection component and a dialog wrapper component for easy integration.
4
+
5
+ ## Features
6
+
7
+ - **Dual Listbox Interface**: Easy selection between available and selected items
8
+ - **Drag and Drop**: Intuitive item movement between lists
9
+ - **Double-Click Support**: Quickly move items by double-clicking
10
+ - **Icon Support**: Display icons alongside item text
11
+ - **Configurable Toolbar**: Customize available toolbar actions
12
+ - **Dialog Integration**: Optional dialog wrapper for modal usage
13
+ - **Entity Integration**: Works with MemberJunction BaseEntity objects
14
+ - **Memory Management**: Maintains selection state within dialog sessions
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @memberjunction/ng-record-selector
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Import the Module
25
+
26
+ ```typescript
27
+ import { RecordSelectorModule } from '@memberjunction/ng-record-selector';
28
+
29
+ @NgModule({
30
+ imports: [
31
+ RecordSelectorModule,
32
+ // other imports
33
+ ],
34
+ // ...
35
+ })
36
+ export class YourModule { }
37
+ ```
38
+
39
+ ### Basic Component Usage
40
+
41
+ ```html
42
+ <!-- Standalone selector component -->
43
+ <mj-record-selector
44
+ [EntityName]="'Users'"
45
+ [DisplayField]="'UserName'"
46
+ [DisplayIconField]="'UserIcon'"
47
+ [AvailableRecords]="allUsers"
48
+ [SelectedRecords]="selectedUsers"
49
+ [UnselectedRecords]="unselectedUsers"
50
+ (RecordSelected)="onUserSelected($event)"
51
+ (RecordUnselected)="onUserUnselected($event)">
52
+ </mj-record-selector>
53
+ ```
54
+
55
+ ### Dialog Component Usage
56
+
57
+ ```html
58
+ <!-- Selector component in a dialog -->
59
+ <button kendoButton (click)="showSelectorDialog = true">
60
+ Select Users
61
+ </button>
62
+
63
+ <mj-record-selector-dialog
64
+ *ngIf="showSelectorDialog"
65
+ [EntityName]="'Users'"
66
+ [DisplayField]="'UserName'"
67
+ [AvailableRecords]="allUsers"
68
+ [SelectedRecords]="selectedUsers"
69
+ [UnselectedRecords]="unselectedUsers"
70
+ [DialogTitle]="'Select Users'"
71
+ [DialogVisible]="showSelectorDialog"
72
+ (DialogClosed)="onDialogClosed($event)"
73
+ (RecordSelected)="onUserSelected($event)"
74
+ (RecordUnselected)="onUserUnselected($event)">
75
+ </mj-record-selector-dialog>
76
+ ```
77
+
78
+ ### TypeScript Component Example
79
+
80
+ ```typescript
81
+ import { Component, OnInit } from '@angular/core';
82
+ import { BaseEntity, Metadata, RunView } from '@memberjunction/core';
83
+ import { ListBoxToolbarConfig } from '@progress/kendo-angular-listbox';
84
+
85
+ @Component({
86
+ selector: 'app-user-role-assignment',
87
+ template: `
88
+ <h3>Assign Users to Role</h3>
89
+ <button kendoButton (click)="openUserSelector()">Select Users</button>
90
+
91
+ <div *ngIf="selectedUsers.length > 0">
92
+ <h4>Selected Users ({{ selectedUsers.length }}):</h4>
93
+ <ul>
94
+ <li *ngFor="let user of selectedUsers">
95
+ {{ user.Get('UserName') }} - {{ user.Get('Email') }}
96
+ </li>
97
+ </ul>
98
+ <button kendoButton (click)="saveUserAssignments()">Save Assignments</button>
99
+ </div>
100
+
101
+ <mj-record-selector-dialog
102
+ *ngIf="selectorDialogVisible"
103
+ [EntityName]="'Users'"
104
+ [DisplayField]="'UserName'"
105
+ [DisplayIconField]="'UserIcon'"
106
+ [AvailableRecords]="allUsers"
107
+ [SelectedRecords]="selectedUsers"
108
+ [UnselectedRecords]="unselectedUsers"
109
+ [ToolbarSettings]="toolbarSettings"
110
+ [DialogTitle]="'Select Users for Role'"
111
+ [DialogVisible]="selectorDialogVisible"
112
+ [DialogWidth]="'800px'"
113
+ [DialogHeight]="'600px'"
114
+ (DialogClosed)="onSelectorDialogClosed($event)">
115
+ </mj-record-selector-dialog>
116
+ `
117
+ })
118
+ export class UserRoleAssignmentComponent implements OnInit {
119
+ allUsers: BaseEntity[] = [];
120
+ selectedUsers: BaseEntity[] = [];
121
+ unselectedUsers: BaseEntity[] = [];
122
+ selectorDialogVisible = false;
123
+
124
+ toolbarSettings: ListBoxToolbarConfig = {
125
+ position: "right",
126
+ tools: ["transferFrom", "transferAllFrom", "transferAllTo", "transferTo"]
127
+ };
128
+
129
+ constructor(private metadata: Metadata) {}
130
+
131
+ async ngOnInit() {
132
+ await this.loadUsers();
133
+ }
134
+
135
+ async loadUsers() {
136
+ // Load all users
137
+ const rv = new RunView();
138
+ const result = await rv.RunView({
139
+ EntityName: 'Users',
140
+ ResultType: 'entity_object'
141
+ });
142
+
143
+ if (result.Success) {
144
+ this.allUsers = result.Results;
145
+ // Initially all users are unselected
146
+ this.unselectedUsers = [...this.allUsers];
147
+ this.selectedUsers = [];
148
+ } else {
149
+ console.error('Failed to load users:', result.ErrorMessage);
150
+ }
151
+ }
152
+
153
+ openUserSelector() {
154
+ this.selectorDialogVisible = true;
155
+ }
156
+
157
+ onSelectorDialogClosed(confirmed: boolean) {
158
+ this.selectorDialogVisible = false;
159
+
160
+ if (confirmed) {
161
+ console.log('User selection confirmed:', this.selectedUsers);
162
+ } else {
163
+ console.log('User selection cancelled');
164
+ }
165
+ }
166
+
167
+ saveUserAssignments() {
168
+ // Logic to save user role assignments
169
+ console.log('Saving role assignments for users:', this.selectedUsers);
170
+ }
171
+ }
172
+ ```
173
+
174
+ ## API Reference
175
+
176
+ ### RecordSelectorComponent
177
+
178
+ Standalone component for selecting records.
179
+
180
+ #### Inputs
181
+
182
+ - `EntityName`: string - The name of the entity to show records for
183
+ - `DisplayField`: string - The field name to display in the list items
184
+ - `DisplayIconField`: string - The field name containing CSS class for icons (optional)
185
+ - `AvailableRecords`: BaseEntity[] - List of all available records
186
+ - `SelectedRecords`: BaseEntity[] - List of selected records
187
+ - `UnselectedRecords`: BaseEntity[] - List of unselected records
188
+ - `ToolbarSettings`: ListBoxToolbarConfig - Configuration for the listbox toolbar
189
+
190
+ #### Outputs
191
+
192
+ - `RecordSelected`: EventEmitter<BaseEntity[]> - Emitted when records are selected
193
+ - `RecordUnselected`: EventEmitter<BaseEntity[]> - Emitted when records are unselected
194
+
195
+ ### RecordSelectorDialogComponent
196
+
197
+ Dialog wrapper for the RecordSelectorComponent.
198
+
199
+ #### Inputs
200
+
201
+ - All inputs from RecordSelectorComponent, plus:
202
+ - `DialogTitle`: string - Title of the dialog (default: 'Select Records')
203
+ - `DialogWidth`: string - Width of the dialog (default: '700px')
204
+ - `DialogHeight`: string - Height of the dialog (default: '450px')
205
+ - `DialogVisible`: boolean - Controls the visibility of the dialog
206
+
207
+ #### Outputs
208
+
209
+ - All outputs from RecordSelectorComponent, plus:
210
+ - `DialogClosed`: EventEmitter<boolean> - Emitted when the dialog is closed (true if confirmed, false if canceled)
211
+
212
+ ## Toolbar Configuration
213
+
214
+ The component accepts a `ListBoxToolbarConfig` object to customize the available toolbar actions:
215
+
216
+ ```typescript
217
+ const toolbarSettings: ListBoxToolbarConfig = {
218
+ position: "right", // or "left", "top", "bottom"
219
+ tools: [
220
+ "moveUp", // Move selected item up
221
+ "transferFrom", // Move selected item from unselected to selected
222
+ "transferAllFrom", // Move all items from unselected to selected
223
+ "transferAllTo", // Move all items from selected to unselected
224
+ "transferTo", // Move selected item from selected to unselected
225
+ "moveDown" // Move selected item down
226
+ ]
227
+ };
228
+ ```
229
+
230
+ ## Selection Behavior
231
+
232
+ The component uses Kendo UI ListBox components with the following behavior:
233
+
234
+ 1. Items can be moved between lists using the toolbar buttons
235
+ 2. Items can be dragged and dropped between lists
236
+ 3. Double-clicking an item moves it to the other list
237
+ 4. When used in a dialog, changes are only committed when the OK button is clicked; Cancel reverts to the previous state
238
+
239
+ ## Styling
240
+
241
+ The component uses Kendo UI ListBox component styles and includes basic CSS that can be overridden in your application.
242
+
243
+ ## Dependencies
244
+
245
+ - `@memberjunction/core`: For metadata and entity types
246
+ - `@memberjunction/core-entities`: For entity types
247
+ - `@memberjunction/global`: For global utilities
248
+ - `@progress/kendo-angular-listbox`: For the list box component
249
+ - `@progress/kendo-angular-buttons`: For UI buttons
250
+ - `@progress/kendo-angular-dialog`: For dialog wrapper
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-record-selector",
3
- "version": "2.32.2",
3
+ "version": "2.33.0",
4
4
  "description": "MemberJunction: Angular Components to allow a user to select/deselect items from a possible set",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -28,11 +28,11 @@
28
28
  "@progress/kendo-angular-listbox": "16.2.0"
29
29
  },
30
30
  "dependencies": {
31
- "@memberjunction/core-entities": "2.32.2",
32
- "@memberjunction/global": "2.32.2",
33
- "@memberjunction/core": "2.32.2",
34
- "@memberjunction/ng-container-directives": "2.32.2",
35
- "@memberjunction/ng-shared": "2.32.2",
31
+ "@memberjunction/core-entities": "2.33.0",
32
+ "@memberjunction/global": "2.33.0",
33
+ "@memberjunction/core": "2.33.0",
34
+ "@memberjunction/ng-container-directives": "2.33.0",
35
+ "@memberjunction/ng-shared": "2.33.0",
36
36
  "tslib": "^2.3.0"
37
37
  },
38
38
  "sideEffects": false