@memberjunction/ng-explorer-core 3.4.0 → 4.1.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 (152) hide show
  1. package/README.md +117 -726
  2. package/dist/app-routing.module.d.ts.map +1 -1
  3. package/dist/app-routing.module.js +11 -0
  4. package/dist/app-routing.module.js.map +1 -1
  5. package/dist/lib/command-palette/command-palette.component.d.ts +79 -0
  6. package/dist/lib/command-palette/command-palette.component.d.ts.map +1 -0
  7. package/dist/lib/command-palette/command-palette.component.js +326 -0
  8. package/dist/lib/command-palette/command-palette.component.js.map +1 -0
  9. package/dist/lib/command-palette/command-palette.service.d.ts +49 -0
  10. package/dist/lib/command-palette/command-palette.service.d.ts.map +1 -0
  11. package/dist/lib/command-palette/command-palette.service.js +101 -0
  12. package/dist/lib/command-palette/command-palette.service.js.map +1 -0
  13. package/dist/lib/command-palette/index.d.ts +3 -0
  14. package/dist/lib/command-palette/index.d.ts.map +1 -0
  15. package/dist/lib/command-palette/index.js +3 -0
  16. package/dist/lib/command-palette/index.js.map +1 -0
  17. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
  18. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +14 -12
  19. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  20. package/dist/lib/generic/form-toolbar.d.ts.map +1 -1
  21. package/dist/lib/generic/form-toolbar.js +56 -38
  22. package/dist/lib/generic/form-toolbar.js.map +1 -1
  23. package/dist/lib/generic/resource-container-component.d.ts.map +1 -1
  24. package/dist/lib/generic/resource-container-component.js +3 -2
  25. package/dist/lib/generic/resource-container-component.js.map +1 -1
  26. package/dist/lib/oauth/oauth-callback.component.d.ts +97 -0
  27. package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -0
  28. package/dist/lib/oauth/oauth-callback.component.js +408 -0
  29. package/dist/lib/oauth/oauth-callback.component.js.map +1 -0
  30. package/dist/lib/oauth/oauth.module.d.ts +14 -0
  31. package/dist/lib/oauth/oauth.module.d.ts.map +1 -0
  32. package/dist/lib/oauth/oauth.module.js +43 -0
  33. package/dist/lib/oauth/oauth.module.js.map +1 -0
  34. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +0 -1
  35. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
  36. package/dist/lib/resource-wrappers/artifact-resource.component.js +20 -23
  37. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  38. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +0 -1
  39. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
  40. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +36 -45
  41. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
  42. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +0 -1
  43. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  44. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +98 -100
  45. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  46. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +0 -1
  47. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
  48. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +21 -24
  49. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  50. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +0 -1
  51. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  52. package/dist/lib/resource-wrappers/dashboard-resource.component.js +11 -10
  53. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  54. package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts +0 -1
  55. package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts.map +1 -1
  56. package/dist/lib/resource-wrappers/list-detail-resource.component.js +3 -5
  57. package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
  58. package/dist/lib/resource-wrappers/notifications-resource.component.d.ts +0 -1
  59. package/dist/lib/resource-wrappers/notifications-resource.component.d.ts.map +1 -1
  60. package/dist/lib/resource-wrappers/notifications-resource.component.js +3 -5
  61. package/dist/lib/resource-wrappers/notifications-resource.component.js.map +1 -1
  62. package/dist/lib/resource-wrappers/query-resource.component.d.ts +0 -1
  63. package/dist/lib/resource-wrappers/query-resource.component.d.ts.map +1 -1
  64. package/dist/lib/resource-wrappers/query-resource.component.js +3 -5
  65. package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
  66. package/dist/lib/resource-wrappers/record-resource.component.d.ts +0 -1
  67. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  68. package/dist/lib/resource-wrappers/record-resource.component.js +14 -34
  69. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  70. package/dist/lib/resource-wrappers/resource-wrappers-loader.d.ts +0 -1
  71. package/dist/lib/resource-wrappers/resource-wrappers-loader.d.ts.map +1 -1
  72. package/dist/lib/resource-wrappers/resource-wrappers-loader.js +3 -33
  73. package/dist/lib/resource-wrappers/resource-wrappers-loader.js.map +1 -1
  74. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +0 -1
  75. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
  76. package/dist/lib/resource-wrappers/search-results-resource.component.js +3 -5
  77. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  78. package/dist/lib/resource-wrappers/view-resource.component.d.ts +0 -1
  79. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  80. package/dist/lib/resource-wrappers/view-resource.component.js +8 -13
  81. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  82. package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts +6 -0
  83. package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts.map +1 -1
  84. package/dist/lib/shell/components/dialogs/app-access-dialog.component.js +62 -34
  85. package/dist/lib/shell/components/dialogs/app-access-dialog.component.js.map +1 -1
  86. package/dist/lib/shell/components/header/app-nav.component.d.ts +71 -14
  87. package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
  88. package/dist/lib/shell/components/header/app-nav.component.js +205 -65
  89. package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
  90. package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
  91. package/dist/lib/shell/components/header/app-switcher.component.js +36 -35
  92. package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
  93. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  94. package/dist/lib/shell/components/tabs/component-cache-manager.js +0 -6
  95. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  96. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  97. package/dist/lib/shell/components/tabs/tab-container.component.js +14 -15
  98. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  99. package/dist/lib/shell/shell.component.d.ts +18 -2
  100. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  101. package/dist/lib/shell/shell.component.js +266 -203
  102. package/dist/lib/shell/shell.component.js.map +1 -1
  103. package/dist/lib/shell/shell.module.d.ts +8 -7
  104. package/dist/lib/shell/shell.module.d.ts.map +1 -1
  105. package/dist/lib/shell/shell.module.js +12 -3
  106. package/dist/lib/shell/shell.module.js.map +1 -1
  107. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
  108. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +56 -61
  109. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  110. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts.map +1 -1
  111. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +3 -3
  112. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js.map +1 -1
  113. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts.map +1 -1
  114. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +21 -22
  115. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js.map +1 -1
  116. package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
  117. package/dist/lib/single-dashboard/single-dashboard.component.js +84 -83
  118. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  119. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  120. package/dist/lib/single-list-detail/single-list-detail.component.js +75 -72
  121. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  122. package/dist/lib/single-query/single-query.component.d.ts.map +1 -1
  123. package/dist/lib/single-query/single-query.component.js +4 -4
  124. package/dist/lib/single-query/single-query.component.js.map +1 -1
  125. package/dist/lib/single-record/single-record.component.d.ts +9 -0
  126. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  127. package/dist/lib/single-record/single-record.component.js +54 -13
  128. package/dist/lib/single-record/single-record.component.js.map +1 -1
  129. package/dist/lib/single-search-result/single-search-result.component.d.ts.map +1 -1
  130. package/dist/lib/single-search-result/single-search-result.component.js +4 -4
  131. package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
  132. package/dist/lib/system-validation/system-validation-banner.component.d.ts.map +1 -1
  133. package/dist/lib/system-validation/system-validation-banner.component.js +85 -65
  134. package/dist/lib/system-validation/system-validation-banner.component.js.map +1 -1
  135. package/dist/lib/user-menu/base-user-menu.d.ts +0 -1
  136. package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
  137. package/dist/lib/user-menu/base-user-menu.js +1 -16
  138. package/dist/lib/user-menu/base-user-menu.js.map +1 -1
  139. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  140. package/dist/lib/user-notifications/user-notifications.component.js +14 -15
  141. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  142. package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
  143. package/dist/lib/user-profile/user-profile.component.js +56 -54
  144. package/dist/lib/user-profile/user-profile.component.js.map +1 -1
  145. package/dist/module.d.ts +32 -32
  146. package/dist/module.js +4 -5
  147. package/dist/module.js.map +1 -1
  148. package/dist/public-api.d.ts +6 -1
  149. package/dist/public-api.d.ts.map +1 -1
  150. package/dist/public-api.js +10 -1
  151. package/dist/public-api.js.map +1 -1
  152. package/package.json +60 -60
package/README.md CHANGED
@@ -1,25 +1,72 @@
1
1
  # @memberjunction/ng-explorer-core
2
2
 
3
- The `@memberjunction/ng-explorer-core` package provides the core components and infrastructure for the MemberJunction Explorer application. It serves as the foundation for building a complete data exploration and management interface based on MemberJunction entities.
3
+ Core components and infrastructure for the MemberJunction Explorer application. Provides the shell, routing, resource wrappers, command palette, user menu system, authentication guards, and single-entity/record/dashboard view components.
4
4
 
5
5
  ## Overview
6
6
 
7
- Explorer Core is a comprehensive Angular library that implements the MemberJunction Explorer application's core functionality. It provides a dynamic resource-based architecture for managing entities, records, reports, dashboards, queries, and other data resources within the MemberJunction ecosystem.
7
+ Explorer Core is the central package that implements the Explorer application's runtime. It provides the `ShellComponent` (the main application frame with header, app switcher, navigation, and tab container), resource wrapper components for each resource type, route guards, validation services, and an extensible user menu plugin system.
8
+
9
+ ```mermaid
10
+ graph TD
11
+ SHELL["ShellComponent\n(<mj-shell>)"] --> HEAD["AppNavComponent\n(Header + Nav)"]
12
+ SHELL --> TABS["TabContainerComponent\n(Golden Layout)"]
13
+ SHELL --> AS["AppSwitcherComponent"]
14
+ SHELL --> CMD["CommandPaletteComponent"]
15
+ SHELL --> UM["User Menu Plugin System"]
16
+
17
+ TABS --> RW["Resource Wrappers"]
18
+
19
+ subgraph "Resource Wrappers"
20
+ RR["RecordResource"]
21
+ DR["DashboardResource"]
22
+ VR["ViewResource"]
23
+ QR["QueryResource"]
24
+ CR["ChatResource"]
25
+ AR["ArtifactResource"]
26
+ end
27
+
28
+ subgraph "Route Guards"
29
+ AG["AuthGuardService"]
30
+ EG["EntitiesGuard"]
31
+ end
32
+
33
+ subgraph "Validation"
34
+ SVS["SystemValidationService"]
35
+ STVS["StartupValidationService"]
36
+ SVB["ValidationBannerComponent"]
37
+ end
38
+
39
+ style SHELL fill:#7c5295,stroke:#563a6b,color:#fff
40
+ style HEAD fill:#2d6a9f,stroke:#1a4971,color:#fff
41
+ style TABS fill:#2d6a9f,stroke:#1a4971,color:#fff
42
+ style AS fill:#2d8659,stroke:#1a5c3a,color:#fff
43
+ style CMD fill:#2d8659,stroke:#1a5c3a,color:#fff
44
+ style UM fill:#2d8659,stroke:#1a5c3a,color:#fff
45
+ style RR fill:#b8762f,stroke:#8a5722,color:#fff
46
+ style DR fill:#b8762f,stroke:#8a5722,color:#fff
47
+ style VR fill:#b8762f,stroke:#8a5722,color:#fff
48
+ style QR fill:#b8762f,stroke:#8a5722,color:#fff
49
+ style CR fill:#b8762f,stroke:#8a5722,color:#fff
50
+ style AR fill:#b8762f,stroke:#8a5722,color:#fff
51
+ style AG fill:#2d6a9f,stroke:#1a4971,color:#fff
52
+ style EG fill:#2d6a9f,stroke:#1a4971,color:#fff
53
+ style SVS fill:#2d8659,stroke:#1a5c3a,color:#fff
54
+ style STVS fill:#2d8659,stroke:#1a5c3a,color:#fff
55
+ style SVB fill:#2d8659,stroke:#1a5c3a,color:#fff
56
+ ```
8
57
 
9
58
  ## Features
10
59
 
11
- - **Dynamic Resource Container Architecture**: Loads components at runtime based on resource type
12
- - **Complete Navigation System**: Drawer-based navigation with workspace and tab management
13
- - **Entity Management**: Browse, view, create, edit, and delete entity records
14
- - **Dashboard System**: Create, edit, and view interactive dashboards
15
- - **Report Integration**: Display and manage reports
16
- - **Query Support**: Execute and display query results
17
- - **Search Integration**: Unified search results display
18
- - **User Views**: Support for custom user-defined views
19
- - **Authentication**: Built-in authentication components and guards
20
- - **Responsive Design**: Mobile-friendly UI that adapts to different screen sizes
21
- - **Workspace Management**: Persistent workspace with saved tabs and state
22
- - **Event-Driven Architecture**: Comprehensive event system for component communication
60
+ - **Shell Component**: App-centric header with app switcher, nav items, Golden Layout tab container, loading animations, and notification badges
61
+ - **Resource Wrappers**: Specialized components for Records, Dashboards, Views, Queries, Lists, Search Results, Conversations, and Artifacts
62
+ - **Command Palette**: Global keyboard-driven command search (Ctrl+K / Cmd+K)
63
+ - **User Menu Plugin System**: Extensible via `BaseUserMenu` with `@RegisterClass` overrides
64
+ - **Route Guards**: `AuthGuardService` for authentication, `EntitiesGuard` for entity route validation
65
+ - **System Validation**: Startup validation services with visual banner for configuration issues
66
+ - **OAuth Module**: OAuth callback handling for external service integrations
67
+ - **Single-entity views**: `SingleRecordComponent`, `SingleDashboardComponent`, `SingleQueryComponent`, `SingleListDetailComponent`, `SingleSearchResultComponent`
68
+ - **Dashboard management**: Add/edit/delete dashboard items, preferences dialog
69
+ - **User profile**: Profile viewing and notification components
23
70
 
24
71
  ## Installation
25
72
 
@@ -27,771 +74,115 @@ Explorer Core is a comprehensive Angular library that implements the MemberJunct
27
74
  npm install @memberjunction/ng-explorer-core
28
75
  ```
29
76
 
30
- ## Requirements
77
+ ## Key Dependencies
31
78
 
32
- - Angular 18.0.2 or higher
33
- - MemberJunction core libraries:
34
- - `@memberjunction/core` v2.43.0+
35
- - `@memberjunction/core-entities` v2.43.0+
36
- - `@memberjunction/global` v2.43.0+
37
- - Kendo UI for Angular v16.2.0+
38
- - TypeScript 4.9+
79
+ | Dependency | Purpose |
80
+ |---|---|
81
+ | `@memberjunction/ng-base-application` | ApplicationManager, WorkspaceStateManager, GoldenLayoutManager |
82
+ | `@memberjunction/ng-auth-services` | MJAuthBase for authentication |
83
+ | `@memberjunction/ng-shared`, `@memberjunction/ng-shared-generic` | Shared services, NavigationService |
84
+ | `@memberjunction/ng-dashboards` | Dashboard components |
85
+ | `@memberjunction/ng-entity-form-dialog` | Entity form dialogs |
86
+ | `@memberjunction/ng-conversations` | Chat conversation components |
87
+ | `@memberjunction/ng-artifacts` | Artifact viewer |
88
+ | `golden-layout` | Tab container layout engine |
89
+ | `@progress/kendo-angular-*` | Kendo UI components |
39
90
 
40
- ## Basic Setup
91
+ ## Usage
41
92
 
42
93
  ### Module Import
43
94
 
44
- Import the `ExplorerCoreModule` in your application module:
45
-
46
95
  ```typescript
47
- import { NgModule } from '@angular/core';
48
- import { BrowserModule } from '@angular/platform-browser';
49
- import { ExplorerCoreModule } from '@memberjunction/ng-explorer-core';
96
+ import { ExplorerCoreModule, ShellModule } from '@memberjunction/ng-explorer-core';
50
97
 
51
98
  @NgModule({
52
- declarations: [AppComponent],
53
- imports: [
54
- BrowserModule,
55
- ExplorerCoreModule
56
- ],
57
- bootstrap: [AppComponent]
99
+ imports: [ExplorerCoreModule, ShellModule]
58
100
  })
59
- export class AppModule { }
101
+ export class AppModule {}
60
102
  ```
61
103
 
62
- ### Routing Configuration
104
+ ### Shell Component
63
105
 
64
- The Explorer Core module includes its own routing configuration. You can integrate it with your application's routing:
65
-
66
- ```typescript
67
- import { Routes } from '@angular/router';
68
- import { AuthGuardService } from '@memberjunction/ng-explorer-core';
69
-
70
- const routes: Routes = [
71
- {
72
- path: '',
73
- canActivate: [AuthGuardService],
74
- loadChildren: () => import('@memberjunction/ng-explorer-core').then(m => m.ExplorerCoreModule)
75
- }
76
- ];
106
+ ```html
107
+ <mj-shell></mj-shell>
77
108
  ```
78
109
 
79
- ## Core Components
80
-
81
- ### Resource Container Component
82
-
83
- The heart of the Explorer architecture, dynamically loading components based on resource type:
84
-
85
- ```typescript
86
- import { Component } from '@angular/core';
87
- import { ResourceData } from '@memberjunction/core-entities';
88
-
89
- @Component({
90
- template: `
91
- <mj-resource
92
- [Data]="resourceData"
93
- [isVisible]="isActive"
94
- (ResourceRecordSaved)="onResourceSaved($event)"
95
- (ContentLoadingStarted)="onLoadingStarted($event)"
96
- (ContentLoadingComplete)="onLoadingComplete($event)">
97
- </mj-resource>
98
- `
99
- })
100
- export class MyComponent {
101
- resourceData: ResourceData = {
102
- ID: 'unique-id',
103
- Name: 'My Resource',
104
- ResourceType: 'Records',
105
- ResourceRecordID: '123',
106
- Configuration: {
107
- Entity: 'Contacts'
108
- }
109
- };
110
-
111
- isActive = true;
112
-
113
- onResourceSaved(entity: BaseEntity) {
114
- console.log('Resource saved:', entity);
115
- }
116
-
117
- onLoadingStarted(container: ResourceContainerComponent) {
118
- console.log('Loading started');
119
- }
120
-
121
- onLoadingComplete(container: ResourceContainerComponent) {
122
- console.log('Loading complete');
123
- }
124
- }
125
- ```
126
-
127
- ### Navigation Component
128
-
129
- Provides the main application navigation with workspace and tab management:
130
-
131
- ```typescript
132
- @Component({
133
- template: `
134
- <mj-navigation
135
- [applicationName]="'My Application'">
136
- </mj-navigation>
137
- `
138
- })
139
- export class AppComponent { }
140
- ```
141
-
142
- ### Home Component
143
-
144
- Displays navigation items configured to show on the home screen:
145
-
146
- ```typescript
147
- @Component({
148
- template: `<mj-home></mj-home>`
149
- })
150
- export class HomePageComponent { }
151
- ```
110
+ The shell handles everything: header navigation, app switching, tab management, workspace state persistence, loading animations, and user menu.
152
111
 
153
- ### Entity Management Components
112
+ ### Custom Resource Types
154
113
 
155
- #### Entity Browser
156
114
  ```typescript
157
- @Component({
158
- template: `
159
- <mj-single-entity
160
- [entityName]="'Contacts'"
161
- [viewID]="viewId">
162
- </mj-single-entity>
163
- `
164
- })
165
- export class EntityBrowserComponent {
166
- viewId?: string; // Optional view ID
167
- }
168
- ```
169
-
170
- #### Record Editor
171
- ```typescript
172
- @Component({
173
- template: `
174
- <mj-single-record
175
- [entityName]="'Contacts'"
176
- [PrimaryKey]="recordKey"
177
- [newRecordValues]="defaultValues"
178
- (recordSaved)="onRecordSaved($event)"
179
- (loadComplete)="onLoadComplete()">
180
- </mj-single-record>
181
- `
182
- })
183
- export class RecordEditorComponent {
184
- recordKey = new CompositeKey([{ FieldName: 'ID', Value: '123' }]);
185
- defaultValues = { CompanyID: 1 }; // For new records
186
-
187
- onRecordSaved(entity: BaseEntity) {
188
- console.log('Record saved:', entity);
189
- }
190
-
191
- onLoadComplete() {
192
- console.log('Record loaded');
193
- }
194
- }
195
- ```
196
-
197
- ### Dashboard Components
198
-
199
- ```typescript
200
- @Component({
201
- template: `
202
- <mj-single-dashboard
203
- [dashboardId]="dashboardId"
204
- [editMode]="false">
205
- </mj-single-dashboard>
206
- `
207
- })
208
- export class DashboardViewerComponent {
209
- dashboardId = '456';
210
- }
211
- ```
212
-
213
- ### Form Toolbar
214
-
215
- Provides consistent form actions across the application:
216
-
217
- ```typescript
218
- @Component({
219
- template: `
220
- <mj-form-toolbar
221
- [record]="entity"
222
- [EditMode]="true"
223
- (SaveRecord)="save()"
224
- (DeleteRecord)="delete()"
225
- (CancelEdit)="cancel()">
226
- </mj-form-toolbar>
227
- `
228
- })
229
- export class FormComponent {
230
- entity: BaseEntity;
231
-
232
- save() { /* Save logic */ }
233
- delete() { /* Delete logic */ }
234
- cancel() { /* Cancel logic */ }
235
- }
236
- ```
237
-
238
- ## Resource Types and Wrappers
239
-
240
- The Explorer supports multiple resource types through specialized wrapper components:
241
-
242
- ### Creating Custom Resource Types
243
-
244
- ```typescript
245
- import { Component } from '@angular/core';
246
115
  import { RegisterClass } from '@memberjunction/global';
247
116
  import { BaseResourceComponent } from '@memberjunction/ng-shared';
248
117
 
249
- @RegisterClass(BaseResourceComponent, 'CustomResource')
250
- @Component({
251
- selector: 'mj-custom-resource',
252
- template: `
253
- <div class="custom-resource">
254
- <h2>{{ Data.Name }}</h2>
255
- <!-- Custom resource implementation -->
256
- </div>
257
- `
258
- })
118
+ @RegisterClass(BaseResourceComponent, 'MyCustomResource')
119
+ @Component({ selector: 'mj-custom-resource', template: '...' })
259
120
  export class CustomResource extends BaseResourceComponent {
260
121
  async GetResourceDisplayName(data: ResourceData): Promise<string> {
261
122
  return `Custom: ${data.Name}`;
262
123
  }
263
-
264
124
  async GetResourceIconClass(data: ResourceData): Promise<string> {
265
125
  return 'fa-solid fa-star';
266
126
  }
267
127
  }
268
128
  ```
269
129
 
270
- ### Built-in Resource Types
271
-
272
- - **Records**: Entity record viewing and editing
273
- - **Reports**: Report display and execution
274
- - **Dashboards**: Interactive dashboard display
275
- - **Queries**: Query execution and results
276
- - **UserViews**: Custom user-defined views
277
- - **SearchResults**: Unified search results
278
- - **ListDetail**: Master-detail layouts
279
-
280
- ## Event System
281
-
282
- The Explorer uses a comprehensive event system for component communication:
283
-
284
- ```typescript
285
- import { MJGlobal, MJEventType } from '@memberjunction/global';
286
- import { EventCodes } from '@memberjunction/ng-shared';
287
-
288
- // Subscribe to events
289
- const subscription = MJGlobal.Instance.GetEventListener(false)
290
- .subscribe((event) => {
291
- if (event.eventCode === EventCodes.ComponentEvent) {
292
- console.log('Component event:', event.args);
293
- }
294
- });
295
-
296
- // Emit events
297
- MJGlobal.Instance.RaiseEvent({
298
- eventCode: EventCodes.ComponentEvent,
299
- eventType: MJEventType.ComponentEvent,
300
- sourceComponent: this,
301
- args: { action: 'save', entityName: 'Contacts' }
302
- });
303
- ```
304
-
305
- ## Authentication and Guards
306
-
307
- ### Auth Guard Service
308
-
309
- ```typescript
310
- import { Routes } from '@angular/router';
311
- import { AuthGuardService } from '@memberjunction/ng-explorer-core';
312
-
313
- const routes: Routes = [
314
- {
315
- path: 'secure',
316
- canActivate: [AuthGuardService],
317
- component: SecureComponent
318
- }
319
- ];
320
- ```
321
-
322
- ### Entities Guard
323
-
324
- ```typescript
325
- import { EntitiesGuard } from '@memberjunction/ng-explorer-core';
326
-
327
- const routes: Routes = [
328
- {
329
- path: 'entities/:entityName',
330
- canActivate: [EntitiesGuard],
331
- component: EntityComponent
332
- }
333
- ];
334
- ```
335
-
336
- ## Advanced Features
337
-
338
- ### Workspace Management
339
-
340
- The Explorer automatically manages workspace state, including:
341
- - Open tabs and their state
342
- - Navigation history
343
- - User preferences
344
- - Resource configurations
345
-
346
- ### Tab Management
347
-
348
- ```typescript
349
- // Access tab management through the navigation component
350
- @ViewChild(NavigationComponent) navigation: NavigationComponent;
351
-
352
- // Open a new tab
353
- this.navigation.openTab({
354
- label: 'New Contact',
355
- icon: 'fa-user',
356
- data: {
357
- resourceType: 'Records',
358
- entityName: 'Contacts',
359
- recordId: 'new'
360
- }
361
- });
362
- ```
363
-
364
- ### Custom Expansion Panels
365
-
366
- ```typescript
367
- @Component({
368
- template: `
369
- <mj-expansion-panel
370
- [title]="'Advanced Options'"
371
- [expanded]="false"
372
- (expandedChange)="onExpandedChange($event)">
373
- <!-- Panel content -->
374
- </mj-expansion-panel>
375
- `
376
- })
377
- export class MyPanelComponent { }
378
- ```
379
-
380
- ## User Menu Plugin System
381
-
382
- The Explorer shell includes a fully extensible user menu system that appears when clicking the user avatar in the header. This plugin architecture allows you to customize, add, or replace menu items without modifying core Explorer code.
383
-
384
- ### Architecture Overview
385
-
386
- The user menu system consists of several components:
387
-
388
- - **`BaseUserMenu`**: The base class with default menu implementation, registered via `@RegisterClass`
389
- - **`UserMenuItem`**: Interface defining menu item properties (id, label, icon, group, etc.)
390
- - **`UserMenuContext`**: Context passed to menu handlers with user info, shell reference, and services
391
- - **`DeveloperModeService`**: Service managing developer mode state, persisted via MJ: User Settings entity
392
-
393
- ### Default Menu Items
394
-
395
- The default `BaseUserMenu` implementation provides these menu items:
396
-
397
- | ID | Label | Group | Developer Only |
398
- |----|-------|-------|----------------|
399
- | `profile` | Profile | primary | No |
400
- | `toggle-dev-mode` | Toggle Developer Mode | developer | Yes |
401
- | `log-layout` | Log Layout to Console | developer | Yes |
402
- | `inspect-state` | Inspect Workspace State | developer | Yes |
403
- | `reset-layout` | Reset Layout | system | No |
404
- | `logout` | Logout | danger | No |
405
-
406
- Menu items are organized into groups with dividers automatically inserted between groups.
407
-
408
- ### Creating a Custom User Menu
409
-
410
- To customize the user menu, create a subclass of `BaseUserMenu` and register it with `@RegisterClass`. Because your subclass is compiled after the base class (due to the import dependency), it automatically gets higher priority in the ClassFactory.
130
+ ### User Menu Customization
411
131
 
412
132
  ```typescript
413
133
  import { RegisterClass } from '@memberjunction/global';
414
- import {
415
- BaseUserMenu,
416
- UserMenuItem,
417
- UserMenuActionResult,
418
- UserMenuContext
419
- } from '@memberjunction/ng-explorer-core';
134
+ import { BaseUserMenu, UserMenuItem } from '@memberjunction/ng-explorer-core';
420
135
 
421
136
  @RegisterClass(BaseUserMenu)
422
137
  export class CustomUserMenu extends BaseUserMenu {
423
-
424
- /**
425
- * Override to customize menu items.
426
- * Call super.GetMenuItems() to include default items, or return entirely new items.
427
- */
428
138
  public GetMenuItems(): UserMenuItem[] {
429
- // Get default items
430
139
  const items = super.GetMenuItems();
431
-
432
- // Add a custom item
433
140
  items.push({
434
- id: 'my-custom-action',
435
- label: 'My Custom Action',
436
- icon: 'fa-solid fa-star',
437
- group: 'primary',
438
- order: 50,
439
- developerOnly: false,
440
- visible: true,
441
- enabled: true,
442
- tooltip: 'Perform my custom action',
443
- shortcut: '⌘K'
141
+ id: 'my-action', label: 'My Action', icon: 'fa-solid fa-star',
142
+ group: 'primary', order: 50, developerOnly: false,
143
+ visible: true, enabled: true
444
144
  });
445
-
446
- // Remove an item by filtering
447
- const filteredItems = items.filter(item => item.id !== 'reset-layout');
448
-
449
- return filteredItems;
450
- }
451
-
452
- /**
453
- * Handle custom menu item clicks.
454
- * Method naming convention: Handle_<item-id-with-hyphens-replaced-by-underscores>
455
- */
456
- protected async Handle_my_custom_action(): Promise<UserMenuActionResult> {
457
- // Access context for user info, shell, services, etc.
458
- const user = this._context?.user;
459
- console.log(`Custom action triggered by user: ${user?.Name}`);
460
-
461
- // Perform your custom logic here
462
- // ...
463
-
464
- return {
465
- success: true,
466
- closeMenu: true, // Close the menu after action
467
- message: 'Action completed!'
468
- };
469
- }
470
- }
471
- ```
472
-
473
- ### UserMenuItem Interface
474
-
475
- Each menu item has the following properties:
476
-
477
- ```typescript
478
- interface UserMenuItem {
479
- /** Unique identifier for the menu item */
480
- id: string;
481
-
482
- /** Display text for the menu item */
483
- label: string;
484
-
485
- /** Font Awesome icon class (e.g., 'fa-solid fa-gear') */
486
- icon: string;
487
-
488
- /** Optional icon/text color (CSS color value) */
489
- color?: string;
490
-
491
- /** Optional CSS class for custom styling (e.g., 'danger' for red styling) */
492
- cssClass?: string;
493
-
494
- /** Group ID for organizing items. Items with same group are grouped together. */
495
- group: 'primary' | 'developer' | 'system' | 'danger' | string;
496
-
497
- /** Sort order within group (lower = higher in menu) */
498
- order: number;
499
-
500
- /** Whether item requires Developer role to be visible */
501
- developerOnly: boolean;
502
-
503
- /** Whether the item is currently visible (dynamic control) */
504
- visible: boolean;
505
-
506
- /** Whether the item is currently enabled/clickable */
507
- enabled: boolean;
508
-
509
- /** Optional tooltip text */
510
- tooltip?: string;
511
-
512
- /** Optional keyboard shortcut hint displayed on the right */
513
- shortcut?: string;
514
- }
515
- ```
516
-
517
- ### UserMenuContext
518
-
519
- The context provides access to user information and shell services:
520
-
521
- ```typescript
522
- interface UserMenuContext {
523
- /** Current authenticated user info */
524
- user: UserInfo;
525
-
526
- /** Full user entity with all fields */
527
- userEntity: UserEntity;
528
-
529
- /** Reference to shell component for advanced operations */
530
- shell: Record<string, unknown>;
531
-
532
- /** View container for opening dialogs/modals */
533
- viewContainerRef: ViewContainerRef;
534
-
535
- /** Whether user has Developer role */
536
- isDeveloper: boolean;
537
-
538
- /** Whether developer mode is currently enabled */
539
- developerModeEnabled: boolean;
540
-
541
- /** Current application context */
542
- currentApplication: ApplicationInfoRef | null;
543
-
544
- /** Workspace manager for layout operations */
545
- workspaceManager: WorkspaceManagerRef;
546
-
547
- /** Auth service for logout operations */
548
- authService: AuthServiceRef;
549
-
550
- /** Function to open settings dialog */
551
- openSettings: () => void;
552
- }
553
- ```
554
-
555
- ### Menu Options
556
-
557
- Customize menu display options by overriding `GetOptions()`:
558
-
559
- ```typescript
560
- @RegisterClass(BaseUserMenu)
561
- export class CustomUserMenu extends BaseUserMenu {
562
-
563
- public GetOptions(): UserMenuOptions {
564
- return {
565
- showUserName: true, // Show user name in menu header
566
- showUserEmail: true, // Show user email below name
567
- menuPosition: 'below-left', // Position relative to avatar
568
- animationStyle: 'fade' // 'fade', 'slide', or 'none'
569
- };
570
- }
571
- }
572
- ```
573
-
574
- ### Developer Mode
575
-
576
- The Developer Mode feature allows users with developer privileges to toggle additional debugging tools in the UI.
577
-
578
- #### Checking Developer Status
579
-
580
- ```typescript
581
- import { DeveloperModeService } from '@memberjunction/ng-shared';
582
-
583
- @Component({...})
584
- export class MyComponent implements OnInit {
585
-
586
- constructor(private devMode: DeveloperModeService) {}
587
-
588
- ngOnInit() {
589
- // Subscribe to developer mode changes
590
- this.devMode.IsEnabled$.subscribe(enabled => {
591
- this.showDevTools = enabled;
592
- });
593
-
594
- // Check if user has developer role (can enable dev mode)
595
- if (this.devMode.IsDeveloper) {
596
- console.log('User can toggle developer mode');
597
- }
598
-
599
- // Check current state synchronously
600
- if (this.devMode.IsEnabled) {
601
- console.log('Developer mode is currently ON');
602
- }
603
- }
604
- }
605
- ```
606
-
607
- #### Developer Roles
608
-
609
- Users with any of these roles can toggle developer mode:
610
- - Developer
611
- - Admin
612
- - System Administrator
613
- - Integration
614
-
615
- The setting is persisted per-user in the `MJ: User Settings` entity with the key `Explorer.DeveloperMode`.
616
-
617
- ### Example: Adding Organization-Specific Menu Items
618
-
619
- ```typescript
620
- import { RegisterClass } from '@memberjunction/global';
621
- import { BaseUserMenu, UserMenuItem, UserMenuActionResult } from '@memberjunction/ng-explorer-core';
622
- import { WindowService } from '@progress/kendo-angular-dialog';
623
-
624
- @RegisterClass(BaseUserMenu)
625
- export class AcmeUserMenu extends BaseUserMenu {
626
-
627
- public GetMenuItems(): UserMenuItem[] {
628
- const items = super.GetMenuItems();
629
-
630
- // Add company-specific items
631
- items.push(
632
- {
633
- id: 'help-center',
634
- label: 'ACME Help Center',
635
- icon: 'fa-solid fa-circle-question',
636
- group: 'primary',
637
- order: 25,
638
- developerOnly: false,
639
- visible: true,
640
- enabled: true
641
- },
642
- {
643
- id: 'submit-feedback',
644
- label: 'Submit Feedback',
645
- icon: 'fa-solid fa-comment',
646
- group: 'primary',
647
- order: 30,
648
- developerOnly: false,
649
- visible: true,
650
- enabled: true
651
- },
652
- {
653
- id: 'admin-console',
654
- label: 'Admin Console',
655
- icon: 'fa-solid fa-screwdriver-wrench',
656
- color: '#6366f1',
657
- group: 'system',
658
- order: 10,
659
- developerOnly: true, // Only visible to developers
660
- visible: true,
661
- enabled: this._context?.isDeveloper ?? false
662
- }
663
- );
664
-
665
145
  return items;
666
146
  }
667
-
668
- protected async Handle_help_center(): Promise<UserMenuActionResult> {
669
- window.open('https://help.acme.com', '_blank');
670
- return { success: true, closeMenu: true };
671
- }
672
-
673
- protected async Handle_submit_feedback(): Promise<UserMenuActionResult> {
674
- // Open feedback dialog
675
- // You could inject WindowService and open a Kendo dialog here
676
- return { success: true, closeMenu: true };
677
- }
678
-
679
- protected async Handle_admin_console(): Promise<UserMenuActionResult> {
680
- // Navigate to admin console
681
- window.location.href = '/admin';
682
- return { success: true, closeMenu: false };
683
- }
684
147
  }
685
148
  ```
686
149
 
687
- ### Ensuring Your Custom Menu is Loaded
150
+ ### Command Palette
688
151
 
689
- To ensure your custom menu class is included in the bundle and not tree-shaken:
152
+ The command palette is available globally via Ctrl+K (Cmd+K on Mac). Custom commands can be registered via `CommandPaletteService`.
690
153
 
691
- 1. **Create a loader function** in your module:
154
+ ## Exported API
692
155
 
693
- ```typescript
694
- // custom-user-menu.ts
695
- export function LoadCustomUserMenu() {
696
- // This function exists to prevent tree-shaking
697
- }
698
- ```
699
-
700
- 2. **Call the loader** from your module's public API or app initialization:
701
-
702
- ```typescript
703
- // In your app.module.ts or public-api.ts
704
- import { LoadCustomUserMenu } from './custom-user-menu';
705
- LoadCustomUserMenu();
706
- ```
707
-
708
- This pattern ensures the `@RegisterClass` decorator executes and registers your custom implementation.
709
-
710
- ## Build Scripts
711
-
712
- ```json
713
- {
714
- "scripts": {
715
- "build": "ngc",
716
- "watch": "ngc -w",
717
- "test": "echo \"Error: no test specified\" && exit 1"
718
- }
719
- }
720
- ```
156
+ Key exports include:
721
157
 
722
- ## Development
158
+ | Export | Type | Description |
159
+ |---|---|---|
160
+ | `ShellComponent` | Component | Main application shell |
161
+ | `ShellModule` | NgModule | Shell module with all shell-related components |
162
+ | `ExplorerCoreModule` | NgModule | Core module with routes and common components |
163
+ | `ResourceContainerComponent` | Component | Dynamic resource loading container |
164
+ | `CommandPaletteComponent` | Component | Global command search |
165
+ | `CommandPaletteService` | Service | Programmatic command palette control |
166
+ | `AuthGuardService` | Guard | Authentication route guard |
167
+ | `EntitiesGuard` | Guard | Entity route validation guard |
168
+ | `SystemValidationService` | Service | System configuration validation |
169
+ | `StartupValidationService` | Service | Startup validation checks |
170
+ | `SystemValidationBannerComponent` | Component | Validation issue banner |
171
+ | `BaseUserMenu` | Class | Extensible user menu base class |
172
+ | `UserMenuItem`, `UserMenuContext` | Interfaces | User menu type definitions |
173
+ | `DashboardPreferencesDialogComponent` | Component | Dashboard preferences editor |
174
+ | `SingleRecordComponent` | Component | Single record viewer/editor |
175
+ | `SingleDashboardComponent` | Component | Single dashboard viewer |
176
+ | `SingleQueryComponent` | Component | Single query viewer |
177
+ | `OAuthModule` | NgModule | OAuth callback handling |
178
+ | `AppRoutingModule` | NgModule | Application routing configuration |
723
179
 
724
- ### Building the Package
180
+ ## Build
725
181
 
726
182
  ```bash
727
- # Build the package
728
- npm run build
729
-
730
- # Watch mode for development
731
- npm run watch
732
- ```
733
-
734
- ### Package Structure
735
-
183
+ cd packages/Angular/Explorer/explorer-core && npm run build
736
184
  ```
737
- explorer-core/
738
- ├── src/
739
- │ ├── lib/
740
- │ │ ├── auth-button/
741
- │ │ ├── dashboard-browser-component/
742
- │ │ ├── generic/
743
- │ │ ├── guards/
744
- │ │ ├── header/
745
- │ │ ├── home-component/
746
- │ │ ├── navigation/
747
- │ │ ├── resource-wrappers/
748
- │ │ ├── shell/ # Main shell component
749
- │ │ ├── single-dashboard/
750
- │ │ ├── single-entity/
751
- │ │ ├── single-record/
752
- │ │ ├── user-menu/ # User menu plugin system
753
- │ │ │ ├── base-user-menu.ts # Base class with default implementation
754
- │ │ │ ├── user-menu.types.ts # Type definitions
755
- │ │ │ └── index.ts # Module exports
756
- │ │ └── ...
757
- │ ├── generic/
758
- │ ├── shared/
759
- │ ├── module.ts
760
- │ └── public-api.ts
761
- ├── package.json
762
- └── tsconfig.json
763
- ```
764
-
765
- ## Integration with Other MJ Packages
766
-
767
- The Explorer Core integrates seamlessly with:
768
-
769
- - **@memberjunction/ng-auth-services**: Authentication and authorization
770
- - **@memberjunction/ng-container-directives**: Layout management
771
- - **@memberjunction/ng-entity-permissions**: Entity-level permissions
772
- - **@memberjunction/ng-file-storage**: File upload and management
773
- - **@memberjunction/ng-record-changes**: Audit trail functionality
774
- - **@memberjunction/ng-user-view-grid**: Data grid components
775
- - **@memberjunction/ng-dashboards**: Dashboard creation and management
776
- - **@memberjunction/ng-resource-permissions**: Resource-level permissions
777
-
778
- ## Best Practices
779
-
780
- 1. **Resource Loading**: Always check `isVisible` before loading heavy resources
781
- 2. **Event Handling**: Unsubscribe from events in `ngOnDestroy`
782
- 3. **Tab Management**: Limit concurrent tabs to maintain performance
783
- 4. **Entity Access**: Use metadata to check entity permissions before operations
784
- 5. **Error Handling**: Implement proper error handling for all async operations
785
-
786
- ## Troubleshooting
787
-
788
- ### Common Issues
789
-
790
- 1. **Resource not loading**: Ensure the resource type is properly registered
791
- 2. **Navigation errors**: Check route configuration and guards
792
- 3. **Missing icons**: Verify Font Awesome is properly loaded
793
- 4. **Performance issues**: Review tab count and resource loading strategies
794
185
 
795
186
  ## License
796
187
 
797
- ISC License - see LICENSE file for details
188
+ ISC