@memberjunction/ng-base-types 2.43.0 → 2.45.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 +268 -63
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Foundational types and base classes for Angular components in the MemberJunction ecosystem, providing common functionality and type definitions.
4
4
 
5
- ## Features
5
+ ## Overview
6
6
 
7
- - Abstract base component for Angular integration
8
- - Provider management for data access
9
- - Common event types and coordination
10
- - Form component event handling
7
+ This package provides essential building blocks for Angular applications using MemberJunction:
8
+ - **BaseAngularComponent**: Abstract base class providing standardized provider management
9
+ - **Event Types**: Common event definitions for form component coordination
10
+ - **Type Safety**: Full TypeScript support with strict typing
11
11
 
12
12
  ## Installation
13
13
 
@@ -15,104 +15,309 @@ Foundational types and base classes for Angular components in the MemberJunction
15
15
  npm install @memberjunction/ng-base-types
16
16
  ```
17
17
 
18
- ## Usage
18
+ ## Features
19
+
20
+ ### Abstract Base Component
21
+ - Centralized provider management for data access
22
+ - Automatic provider inheritance throughout component trees
23
+ - Support for multiple concurrent API connections
24
+
25
+ ### Form Event System
26
+ - Standardized event types for form component communication
27
+ - Support for save/delete operations coordination
28
+ - Pending changes management
29
+
30
+ ### TypeScript Support
31
+ - Full type definitions for all exports
32
+ - Strict mode compatible
33
+ - Enhanced IDE intellisense
34
+
35
+ ## API Documentation
19
36
 
20
37
  ### BaseAngularComponent
21
38
 
22
- Abstract base class for all MemberJunction Angular components:
39
+ Abstract base class that all MemberJunction Angular components should extend:
23
40
 
24
41
  ```typescript
25
42
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
43
+ import { Component, OnInit } from '@angular/core';
26
44
 
27
45
  @Component({
28
- selector: 'your-component',
29
- templateUrl: './your.component.html',
30
- styleUrls: ['./your.component.css']
46
+ selector: 'my-component',
47
+ templateUrl: './my-component.html'
31
48
  })
32
- export class YourComponent extends BaseAngularComponent {
33
- // Your component implementation
34
-
49
+ export class MyComponent extends BaseAngularComponent implements OnInit {
35
50
  ngOnInit() {
36
- // Access providers through the base class
51
+ // Access the metadata provider
37
52
  const metadata = this.ProviderToUse;
38
53
 
39
- // Run views through the base class
54
+ // Use RunView functionality
40
55
  const viewProvider = this.RunViewToUse;
56
+
57
+ // Execute queries
58
+ const queryProvider = this.RunQueryToUse;
59
+
60
+ // Run reports
61
+ const reportProvider = this.RunReportToUse;
41
62
  }
42
63
  }
43
64
  ```
44
65
 
45
- The BaseAngularComponent provides:
66
+ #### Properties
67
+
68
+ | Property | Type | Description |
69
+ |----------|------|-------------|
70
+ | `Provider` | `IMetadataProvider \| null` | Optional custom provider instance. If not specified, uses the default global provider. |
71
+
72
+ #### Getter Methods
46
73
 
47
- - Provider management for connecting to different MemberJunction API instances
48
- - Accessor methods for different provider types:
49
- - `ProviderToUse`: Access the metadata provider
50
- - `RunViewToUse`: Access the RunView provider
51
- - `RunQueryToUse`: Access the RunQuery provider
52
- - `RunReportToUse`: Access the RunReport provider
74
+ | Method | Return Type | Description |
75
+ |--------|-------------|-------------|
76
+ | `ProviderToUse` | `IMetadataProvider` | Returns the Provider if specified, otherwise returns the default Metadata.Provider |
77
+ | `RunViewToUse` | `IRunViewProvider` | Returns the provider cast as IRunViewProvider for running views |
78
+ | `RunQueryToUse` | `IRunQueryProvider` | Returns the provider cast as IRunQueryProvider for executing queries |
79
+ | `RunReportToUse` | `IRunReportProvider` | Returns the provider cast as IRunReportProvider for running reports |
53
80
 
54
81
  ### Form Component Events
55
82
 
56
- Types for coordinating events between form components:
83
+ #### BaseFormComponentEventCodes
84
+
85
+ Constants for event type identification:
86
+
87
+ ```typescript
88
+ const BaseFormComponentEventCodes = {
89
+ BASE_CODE: 'BaseFormComponent_Event',
90
+ EDITING_COMPLETE: 'EDITING_COMPLETE',
91
+ REVERT_PENDING_CHANGES: 'REVERT_PENDING_CHANGES',
92
+ POPULATE_PENDING_RECORDS: 'POPULATE_PENDING_RECORDS'
93
+ }
94
+ ```
95
+
96
+ #### Event Classes
97
+
98
+ ##### BaseFormComponentEvent
99
+
100
+ Base class for all form component events:
101
+
102
+ ```typescript
103
+ class BaseFormComponentEvent {
104
+ subEventCode: string; // Event type identifier
105
+ elementRef: any; // Reference to the emitting element
106
+ returnValue: any; // Optional return value
107
+ }
108
+ ```
109
+
110
+ ##### FormEditingCompleteEvent
111
+
112
+ Specialized event emitted when form editing is complete:
113
+
114
+ ```typescript
115
+ class FormEditingCompleteEvent extends BaseFormComponentEvent {
116
+ subEventCode: string = BaseFormComponentEventCodes.EDITING_COMPLETE;
117
+ pendingChanges: PendingRecordItem[] = [];
118
+ }
119
+ ```
120
+
121
+ ##### PendingRecordItem
122
+
123
+ Represents a record pending save or delete:
124
+
125
+ ```typescript
126
+ class PendingRecordItem {
127
+ entityObject: BaseEntity; // The entity to be processed
128
+ action: 'save' | 'delete' = 'save'; // Action to perform
129
+ }
130
+ ```
131
+
132
+ ## Usage Examples
133
+
134
+ ### Implementing a Component with Custom Provider
135
+
136
+ ```typescript
137
+ import { Component, OnInit } from '@angular/core';
138
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
139
+ import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
140
+
141
+ @Component({
142
+ selector: 'app-custom-provider',
143
+ template: `
144
+ <div>
145
+ <child-component [Provider]="customProvider"></child-component>
146
+ </div>
147
+ `
148
+ })
149
+ export class CustomProviderComponent extends BaseAngularComponent implements OnInit {
150
+ customProvider: GraphQLDataProvider;
151
+
152
+ ngOnInit() {
153
+ // Create a custom provider for a different API endpoint
154
+ this.customProvider = new GraphQLDataProvider({
155
+ endpoint: 'https://api.example.com/graphql',
156
+ headers: {
157
+ 'Authorization': 'Bearer YOUR_TOKEN'
158
+ }
159
+ });
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### Handling Form Events
57
165
 
58
166
  ```typescript
167
+ import { Component, EventEmitter, Output } from '@angular/core';
59
168
  import {
60
- BaseFormComponentEventCodes,
169
+ BaseAngularComponent,
61
170
  BaseFormComponentEvent,
171
+ BaseFormComponentEventCodes,
62
172
  FormEditingCompleteEvent,
63
173
  PendingRecordItem
64
174
  } from '@memberjunction/ng-base-types';
65
175
 
66
- // Listen for form events
67
- handleFormEvent(event: BaseFormComponentEvent) {
68
- switch(event.subEventCode) {
69
- case BaseFormComponentEventCodes.EDITING_COMPLETE:
70
- const editEvent = event as FormEditingCompleteEvent;
71
- // Process pending changes
72
- editEvent.pendingChanges.forEach(item => {
176
+ @Component({
177
+ selector: 'app-form-handler',
178
+ template: `...`
179
+ })
180
+ export class FormHandlerComponent extends BaseAngularComponent {
181
+ @Output() formEvent = new EventEmitter<BaseFormComponentEvent>();
182
+
183
+ async handleFormSubmit(entities: BaseEntity[]) {
184
+ // Create the event
185
+ const event = new FormEditingCompleteEvent();
186
+
187
+ // Add pending changes
188
+ event.pendingChanges = entities.map(entity => ({
189
+ entityObject: entity,
190
+ action: 'save' as const
191
+ }));
192
+
193
+ // Emit the event
194
+ this.formEvent.emit(event);
195
+ }
196
+
197
+ onFormEvent(event: BaseFormComponentEvent) {
198
+ switch (event.subEventCode) {
199
+ case BaseFormComponentEventCodes.EDITING_COMPLETE:
200
+ const editEvent = event as FormEditingCompleteEvent;
201
+ this.processPendingChanges(editEvent.pendingChanges);
202
+ break;
203
+
204
+ case BaseFormComponentEventCodes.REVERT_PENDING_CHANGES:
205
+ this.revertChanges();
206
+ break;
207
+
208
+ case BaseFormComponentEventCodes.POPULATE_PENDING_RECORDS:
209
+ this.populateRecords();
210
+ break;
211
+ }
212
+ }
213
+
214
+ private async processPendingChanges(changes: PendingRecordItem[]) {
215
+ for (const item of changes) {
216
+ try {
73
217
  if (item.action === 'save') {
74
- // Save the entity
75
- item.entityObject.Save();
218
+ await item.entityObject.Save();
76
219
  } else if (item.action === 'delete') {
77
- // Delete the entity
78
- item.entityObject.Delete();
220
+ await item.entityObject.Delete();
79
221
  }
80
- });
81
- break;
82
-
83
- case BaseFormComponentEventCodes.REVERT_PENDING_CHANGES:
84
- // Handle reverting changes
85
- break;
86
-
87
- case BaseFormComponentEventCodes.POPULATE_PENDING_RECORDS:
88
- // Handle populating pending records
89
- break;
222
+ } catch (error) {
223
+ console.error(`Failed to ${item.action} entity:`, error);
224
+ }
225
+ }
90
226
  }
91
227
  }
92
-
93
- // Create and emit a form event
94
- const event = new FormEditingCompleteEvent();
95
- event.pendingChanges = [
96
- { entityObject: myEntity, action: 'save' }
97
- ];
98
- someEventEmitter.emit(event);
99
228
  ```
100
229
 
101
- ## Provider Configuration
102
-
103
- You can customize the data providers used by components by setting the Provider input:
230
+ ### Using Multiple Providers in an Application
104
231
 
105
232
  ```typescript
233
+ import { Component } from '@angular/core';
234
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
106
235
  import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
107
236
 
108
- // In your component template
109
- <your-component [Provider]="customProvider"></your-component>
237
+ @Component({
238
+ selector: 'app-multi-tenant',
239
+ template: `
240
+ <div class="tenant-a">
241
+ <user-list [Provider]="tenantAProvider"></user-list>
242
+ </div>
243
+ <div class="tenant-b">
244
+ <user-list [Provider]="tenantBProvider"></user-list>
245
+ </div>
246
+ `
247
+ })
248
+ export class MultiTenantComponent extends BaseAngularComponent {
249
+ tenantAProvider = new GraphQLDataProvider({
250
+ endpoint: 'https://tenant-a.example.com/graphql'
251
+ });
252
+
253
+ tenantBProvider = new GraphQLDataProvider({
254
+ endpoint: 'https://tenant-b.example.com/graphql'
255
+ });
256
+ }
257
+ ```
258
+
259
+ ## Dependencies
260
+
261
+ ### Runtime Dependencies
262
+ - `@memberjunction/core`: Core MemberJunction functionality
263
+ - `@memberjunction/core-entities`: Entity definitions
264
+ - `@memberjunction/global`: Global utilities
265
+ - `tslib`: TypeScript runtime helpers
266
+
267
+ ### Peer Dependencies
268
+ - `@angular/common`: ^18.0.2
269
+ - `@angular/core`: ^18.0.2
270
+
271
+ ## Build Configuration
272
+
273
+ This package uses Angular's `ngc` compiler for building:
110
274
 
111
- // In your component class
112
- customProvider = new GraphQLDataProvider({
113
- endpoint: 'https://your-custom-endpoint/graphql',
114
- // other configuration options
115
- });
275
+ ```bash
276
+ npm run build
116
277
  ```
117
278
 
118
- This allows different components to connect to different MemberJunction API instances within the same application.
279
+ The package is configured with:
280
+ - No side effects for better tree-shaking
281
+ - Full TypeScript declarations
282
+ - Angular Ivy compatibility
283
+
284
+ ## Integration with MemberJunction
285
+
286
+ This package is designed to work seamlessly with other MemberJunction packages:
287
+
288
+ - **@memberjunction/core**: Provides the entity and provider interfaces
289
+ - **@memberjunction/graphql-dataprovider**: Default data provider implementation
290
+ - **@memberjunction/ng-\***: Other Angular-specific packages that extend BaseAngularComponent
291
+
292
+ ## Best Practices
293
+
294
+ 1. **Always extend BaseAngularComponent** for MemberJunction Angular components
295
+ 2. **Use the provider getters** instead of directly accessing Metadata or RunView classes
296
+ 3. **Emit standardized events** using the provided event classes for better interoperability
297
+ 4. **Handle errors appropriately** when processing pending changes
298
+ 5. **Pass providers down the component tree** when working with multiple API endpoints
299
+
300
+ ## Migration Guide
301
+
302
+ If upgrading from a previous version:
303
+
304
+ 1. Update all components to extend `BaseAngularComponent`
305
+ 2. Replace direct `Metadata` usage with `this.ProviderToUse`
306
+ 3. Update event handling to use the standardized event types
307
+ 4. Remove any custom provider management code in favor of the built-in system
308
+
309
+ ## Known Issues
310
+
311
+ - The `RunQueryToUse` and `RunReportToUse` getters in the current implementation have incomplete type casting. Ensure your provider implements all required interfaces.
312
+
313
+ ## Contributing
314
+
315
+ When contributing to this package:
316
+ 1. Maintain backward compatibility
317
+ 2. Add tests for new functionality
318
+ 3. Update this README with new features
319
+ 4. Follow the MemberJunction coding standards
320
+
321
+ ## License
322
+
323
+ ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-base-types",
3
- "version": "2.43.0",
3
+ "version": "2.45.0",
4
4
  "description": "MemberJunction: Simple types that are used across many generic Angular UI components for coordination",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -23,9 +23,9 @@
23
23
  "@angular/core": "18.0.2"
24
24
  },
25
25
  "dependencies": {
26
- "@memberjunction/core-entities": "2.43.0",
27
- "@memberjunction/global": "2.43.0",
28
- "@memberjunction/core": "2.43.0",
26
+ "@memberjunction/core-entities": "2.45.0",
27
+ "@memberjunction/global": "2.45.0",
28
+ "@memberjunction/core": "2.45.0",
29
29
  "tslib": "^2.3.0"
30
30
  },
31
31
  "sideEffects": false