@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.
- package/README.md +117 -726
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +11 -0
- package/dist/app-routing.module.js.map +1 -1
- package/dist/lib/command-palette/command-palette.component.d.ts +79 -0
- package/dist/lib/command-palette/command-palette.component.d.ts.map +1 -0
- package/dist/lib/command-palette/command-palette.component.js +326 -0
- package/dist/lib/command-palette/command-palette.component.js.map +1 -0
- package/dist/lib/command-palette/command-palette.service.d.ts +49 -0
- package/dist/lib/command-palette/command-palette.service.d.ts.map +1 -0
- package/dist/lib/command-palette/command-palette.service.js +101 -0
- package/dist/lib/command-palette/command-palette.service.js.map +1 -0
- package/dist/lib/command-palette/index.d.ts +3 -0
- package/dist/lib/command-palette/index.d.ts.map +1 -0
- package/dist/lib/command-palette/index.js +3 -0
- package/dist/lib/command-palette/index.js.map +1 -0
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +14 -12
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
- package/dist/lib/generic/form-toolbar.d.ts.map +1 -1
- package/dist/lib/generic/form-toolbar.js +56 -38
- package/dist/lib/generic/form-toolbar.js.map +1 -1
- package/dist/lib/generic/resource-container-component.d.ts.map +1 -1
- package/dist/lib/generic/resource-container-component.js +3 -2
- package/dist/lib/generic/resource-container-component.js.map +1 -1
- package/dist/lib/oauth/oauth-callback.component.d.ts +97 -0
- package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -0
- package/dist/lib/oauth/oauth-callback.component.js +408 -0
- package/dist/lib/oauth/oauth-callback.component.js.map +1 -0
- package/dist/lib/oauth/oauth.module.d.ts +14 -0
- package/dist/lib/oauth/oauth.module.d.ts.map +1 -0
- package/dist/lib/oauth/oauth.module.js +43 -0
- package/dist/lib/oauth/oauth.module.js.map +1 -0
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.js +20 -23
- package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js +36 -45
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +98 -100
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +21 -24
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +11 -10
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/list-detail-resource.component.js +3 -5
- package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/notifications-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/notifications-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/notifications-resource.component.js +3 -5
- package/dist/lib/resource-wrappers/notifications-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/query-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/query-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/query-resource.component.js +3 -5
- package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/record-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/record-resource.component.js +14 -34
- package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/resource-wrappers-loader.d.ts +0 -1
- package/dist/lib/resource-wrappers/resource-wrappers-loader.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/resource-wrappers-loader.js +3 -33
- package/dist/lib/resource-wrappers/resource-wrappers-loader.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +3 -5
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts +0 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +8 -13
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts +6 -0
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts.map +1 -1
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.js +62 -34
- package/dist/lib/shell/components/dialogs/app-access-dialog.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts +71 -14
- package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.js +205 -65
- package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-switcher.component.js +36 -35
- package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +0 -6
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +14 -15
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +18 -2
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +266 -203
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +8 -7
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +12 -3
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +56 -61
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +3 -3
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +21 -22
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +84 -83
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +75 -72
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/lib/single-query/single-query.component.d.ts.map +1 -1
- package/dist/lib/single-query/single-query.component.js +4 -4
- package/dist/lib/single-query/single-query.component.js.map +1 -1
- package/dist/lib/single-record/single-record.component.d.ts +9 -0
- package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
- package/dist/lib/single-record/single-record.component.js +54 -13
- package/dist/lib/single-record/single-record.component.js.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.d.ts.map +1 -1
- package/dist/lib/single-search-result/single-search-result.component.js +4 -4
- package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
- package/dist/lib/system-validation/system-validation-banner.component.d.ts.map +1 -1
- package/dist/lib/system-validation/system-validation-banner.component.js +85 -65
- package/dist/lib/system-validation/system-validation-banner.component.js.map +1 -1
- package/dist/lib/user-menu/base-user-menu.d.ts +0 -1
- package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
- package/dist/lib/user-menu/base-user-menu.js +1 -16
- package/dist/lib/user-menu/base-user-menu.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +14 -15
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
- package/dist/lib/user-profile/user-profile.component.js +56 -54
- package/dist/lib/user-profile/user-profile.component.js.map +1 -1
- package/dist/module.d.ts +32 -32
- package/dist/module.js +4 -5
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +6 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +10 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +60 -60
package/README.md
CHANGED
|
@@ -1,25 +1,72 @@
|
|
|
1
1
|
# @memberjunction/ng-explorer-core
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
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
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
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
|
-
##
|
|
77
|
+
## Key Dependencies
|
|
31
78
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
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
|
-
##
|
|
91
|
+
## Usage
|
|
41
92
|
|
|
42
93
|
### Module Import
|
|
43
94
|
|
|
44
|
-
Import the `ExplorerCoreModule` in your application module:
|
|
45
|
-
|
|
46
95
|
```typescript
|
|
47
|
-
import {
|
|
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
|
-
|
|
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
|
-
###
|
|
104
|
+
### Shell Component
|
|
63
105
|
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
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, '
|
|
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
|
-
###
|
|
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-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
-
###
|
|
150
|
+
### Command Palette
|
|
688
151
|
|
|
689
|
-
|
|
152
|
+
The command palette is available globally via Ctrl+K (Cmd+K on Mac). Custom commands can be registered via `CommandPaletteService`.
|
|
690
153
|
|
|
691
|
-
|
|
154
|
+
## Exported API
|
|
692
155
|
|
|
693
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
+
## Build
|
|
725
181
|
|
|
726
182
|
```bash
|
|
727
|
-
|
|
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
|
|
188
|
+
ISC
|