@memberjunction/ng-dashboards 5.32.0 → 5.34.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 (95) hide show
  1. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  2. package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
  3. package/dist/Admin/admin-data-schema.component.d.ts +16 -0
  4. package/dist/Admin/admin-data-schema.component.d.ts.map +1 -0
  5. package/dist/Admin/admin-data-schema.component.js +136 -0
  6. package/dist/Admin/admin-data-schema.component.js.map +1 -0
  7. package/dist/Admin/admin-dev-tools-resource.component.d.ts +14 -0
  8. package/dist/Admin/admin-dev-tools-resource.component.d.ts.map +1 -0
  9. package/dist/Admin/admin-dev-tools-resource.component.js +162 -0
  10. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -0
  11. package/dist/Admin/admin-identity-access.component.d.ts +15 -0
  12. package/dist/Admin/admin-identity-access.component.d.ts.map +1 -0
  13. package/dist/Admin/admin-identity-access.component.js +156 -0
  14. package/dist/Admin/admin-identity-access.component.js.map +1 -0
  15. package/dist/Admin/admin-monitoring.component.d.ts +15 -0
  16. package/dist/Admin/admin-monitoring.component.d.ts.map +1 -0
  17. package/dist/Admin/admin-monitoring.component.js +130 -0
  18. package/dist/Admin/admin-monitoring.component.js.map +1 -0
  19. package/dist/Admin/base-admin-container.component.d.ts +80 -0
  20. package/dist/Admin/base-admin-container.component.d.ts.map +1 -0
  21. package/dist/Admin/base-admin-container.component.js +198 -0
  22. package/dist/Admin/base-admin-container.component.js.map +1 -0
  23. package/dist/Admin/index.d.ts +6 -0
  24. package/dist/Admin/index.d.ts.map +1 -0
  25. package/dist/Admin/index.js +6 -0
  26. package/dist/Admin/index.js.map +1 -0
  27. package/dist/ComponentStudio/components/workspace/component-preview.component.js +1 -1
  28. package/dist/ComponentStudio/components/workspace/component-preview.component.js.map +1 -1
  29. package/dist/ComponentStudio/services/component-studio-state.service.d.ts +28 -8
  30. package/dist/ComponentStudio/services/component-studio-state.service.d.ts.map +1 -1
  31. package/dist/ComponentStudio/services/component-studio-state.service.js +45 -27
  32. package/dist/ComponentStudio/services/component-studio-state.service.js.map +1 -1
  33. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +18 -3
  34. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -1
  35. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +51 -11
  36. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -1
  37. package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
  38. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  39. package/dist/DevTools/app-state-inspector.component.d.ts +53 -0
  40. package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -0
  41. package/dist/DevTools/app-state-inspector.component.js +301 -0
  42. package/dist/DevTools/app-state-inspector.component.js.map +1 -0
  43. package/dist/DevTools/class-registry.component.d.ts +64 -0
  44. package/dist/DevTools/class-registry.component.d.ts.map +1 -0
  45. package/dist/DevTools/class-registry.component.js +423 -0
  46. package/dist/DevTools/class-registry.component.js.map +1 -0
  47. package/dist/DevTools/dev-tools-prefs.d.ts +21 -0
  48. package/dist/DevTools/dev-tools-prefs.d.ts.map +1 -0
  49. package/dist/DevTools/dev-tools-prefs.js +48 -0
  50. package/dist/DevTools/dev-tools-prefs.js.map +1 -0
  51. package/dist/DevTools/event-monitor.component.d.ts +78 -0
  52. package/dist/DevTools/event-monitor.component.d.ts.map +1 -0
  53. package/dist/DevTools/event-monitor.component.js +659 -0
  54. package/dist/DevTools/event-monitor.component.js.map +1 -0
  55. package/dist/DevTools/graphql-console.component.d.ts +153 -0
  56. package/dist/DevTools/graphql-console.component.d.ts.map +1 -0
  57. package/dist/DevTools/graphql-console.component.js +1463 -0
  58. package/dist/DevTools/graphql-console.component.js.map +1 -0
  59. package/dist/DevTools/index.d.ts +8 -0
  60. package/dist/DevTools/index.d.ts.map +1 -0
  61. package/dist/DevTools/index.js +8 -0
  62. package/dist/DevTools/index.js.map +1 -0
  63. package/dist/DevTools/layout-inspector.component.d.ts +42 -0
  64. package/dist/DevTools/layout-inspector.component.d.ts.map +1 -0
  65. package/dist/DevTools/layout-inspector.component.js +208 -0
  66. package/dist/DevTools/layout-inspector.component.js.map +1 -0
  67. package/dist/DevTools/lazy-module-status.component.d.ts +65 -0
  68. package/dist/DevTools/lazy-module-status.component.d.ts.map +1 -0
  69. package/dist/DevTools/lazy-module-status.component.js +388 -0
  70. package/dist/DevTools/lazy-module-status.component.js.map +1 -0
  71. package/dist/DevTools/settings-explorer.component.d.ts +55 -0
  72. package/dist/DevTools/settings-explorer.component.d.ts.map +1 -0
  73. package/dist/DevTools/settings-explorer.component.js +394 -0
  74. package/dist/DevTools/settings-explorer.component.js.map +1 -0
  75. package/dist/Integration/components/widgets/integration-card.component.js +2 -2
  76. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  77. package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
  78. package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
  79. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +134 -1
  80. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
  81. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +1227 -24
  82. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  83. package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
  84. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  85. package/dist/Testing/components/testing-runs.component.js +3 -3
  86. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  87. package/dist/core-dashboards.module.d.ts +45 -34
  88. package/dist/core-dashboards.module.d.ts.map +1 -1
  89. package/dist/core-dashboards.module.js +57 -0
  90. package/dist/core-dashboards.module.js.map +1 -1
  91. package/dist/public-api.d.ts +2 -0
  92. package/dist/public-api.d.ts.map +1 -1
  93. package/dist/public-api.js +2 -0
  94. package/dist/public-api.js.map +1 -1
  95. package/package.json +52 -52
@@ -0,0 +1,53 @@
1
+ import { OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
3
+ import { WorkspaceStateManager } from '@memberjunction/ng-base-application';
4
+ import { DeveloperModeService } from '@memberjunction/ng-shared';
5
+ import * as i0 from "@angular/core";
6
+ interface InspectorSection {
7
+ id: string;
8
+ label: string;
9
+ icon: string;
10
+ enabled: boolean;
11
+ description?: string;
12
+ }
13
+ /**
14
+ * App State Inspector — read-only structured view of the Explorer's runtime
15
+ * state. Replaces the legacy "Inspect App State" user-menu item which only
16
+ * dumped to console. Lives in the Admin app's dev tools area.
17
+ */
18
+ export declare class AppStateInspectorComponent extends BaseResourceComponent implements OnInit, OnDestroy {
19
+ private cdr;
20
+ private workspace;
21
+ private devMode;
22
+ Sections: InspectorSection[];
23
+ ActiveSection: string;
24
+ StateJson: string;
25
+ SearchQuery: string;
26
+ CopyConfirmed: boolean;
27
+ LastRefreshed: Date;
28
+ constructor(cdr: ChangeDetectorRef, workspace: WorkspaceStateManager, devMode: DeveloperModeService);
29
+ ngOnInit(): void;
30
+ ngOnDestroy(): void;
31
+ GetResourceDisplayName(): Promise<string>;
32
+ GetResourceIconClass(): Promise<string>;
33
+ OnSectionClick(section: InspectorSection): void;
34
+ refresh(): void;
35
+ OnCopy(): Promise<void>;
36
+ OnDownload(): void;
37
+ get LastRefreshedLabel(): string;
38
+ get SectionLabel(): string;
39
+ private computeSectionData;
40
+ private userData;
41
+ private providerData;
42
+ private workspaceData;
43
+ private appData;
44
+ private devData;
45
+ private browserData;
46
+ private jsonReplacer;
47
+ private readMemory;
48
+ private timestampSlug;
49
+ static ɵfac: i0.ɵɵFactoryDeclaration<AppStateInspectorComponent, never>;
50
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppStateInspectorComponent, "mj-app-state-inspector", never, {}, {}, never, never, false, never>;
51
+ }
52
+ export {};
53
+ //# sourceMappingURL=app-state-inspector.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-state-inspector.component.d.ts","sourceRoot":"","sources":["../../src/DevTools/app-state-inspector.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIlE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;;AAEjE,UAAU,gBAAgB;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAOa,0BAA2B,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAkB1F,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,OAAO;IAlBZ,QAAQ,EAAE,gBAAgB,EAAE,CAOjC;IAEK,aAAa,SAAU;IACvB,SAAS,SAAQ;IACjB,WAAW,SAAM;IACjB,aAAa,UAAS;IACtB,aAAa,OAAc;gBAGtB,GAAG,EAAE,iBAAiB,EACtB,SAAS,EAAE,qBAAqB,EAChC,OAAO,EAAE,oBAAoB;IAKlC,QAAQ,IAAI,IAAI;IASP,WAAW,IAAI,IAAI;IAKb,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IACzC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAEtD,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAO/C,OAAO,IAAI,IAAI;IAMT,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B,UAAU,IAAI,IAAI;IAUzB,IAAW,kBAAkB,IAAI,MAAM,CAEtC;IAED,IAAW,YAAY,IAAI,MAAM,CAEhC;IAID,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,aAAa;yCA9LZ,0BAA0B;2CAA1B,0BAA0B;CAoMtC"}
@@ -0,0 +1,301 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
9
+ import { RegisterClass } from '@memberjunction/global';
10
+ import { DevToolsPrefs } from './dev-tools-prefs';
11
+ import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "@memberjunction/ng-base-application";
14
+ import * as i2 from "@memberjunction/ng-shared";
15
+ import * as i3 from "@angular/forms";
16
+ import * as i4 from "@memberjunction/ng-code-editor";
17
+ const _forTrack0 = ($index, $item) => $item.id;
18
+ function AppStateInspectorComponent_For_22_Conditional_5_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "div", 27);
20
+ i0.ɵɵtext(1);
21
+ i0.ɵɵelementEnd();
22
+ } if (rf & 2) {
23
+ const section_r2 = i0.ɵɵnextContext().$implicit;
24
+ i0.ɵɵadvance();
25
+ i0.ɵɵtextInterpolate(section_r2.description);
26
+ } }
27
+ function AppStateInspectorComponent_For_22_Template(rf, ctx) { if (rf & 1) {
28
+ const _r1 = i0.ɵɵgetCurrentView();
29
+ i0.ɵɵelementStart(0, "button", 23);
30
+ i0.ɵɵlistener("click", function AppStateInspectorComponent_For_22_Template_button_click_0_listener() { const section_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.OnSectionClick(section_r2)); });
31
+ i0.ɵɵelement(1, "i", 24);
32
+ i0.ɵɵelementStart(2, "div", 25)(3, "div", 26);
33
+ i0.ɵɵtext(4);
34
+ i0.ɵɵelementEnd();
35
+ i0.ɵɵconditionalCreate(5, AppStateInspectorComponent_For_22_Conditional_5_Template, 2, 1, "div", 27);
36
+ i0.ɵɵelementEnd()();
37
+ } if (rf & 2) {
38
+ const section_r2 = ctx.$implicit;
39
+ const ctx_r2 = i0.ɵɵnextContext();
40
+ i0.ɵɵclassProp("mj-inspector__nav-item--active", ctx_r2.ActiveSection === section_r2.id);
41
+ i0.ɵɵadvance();
42
+ i0.ɵɵclassMap(section_r2.icon);
43
+ i0.ɵɵadvance(3);
44
+ i0.ɵɵtextInterpolate(section_r2.label);
45
+ i0.ɵɵadvance();
46
+ i0.ɵɵconditional(section_r2.description ? 5 : -1);
47
+ } }
48
+ /**
49
+ * App State Inspector — read-only structured view of the Explorer's runtime
50
+ * state. Replaces the legacy "Inspect App State" user-menu item which only
51
+ * dumped to console. Lives in the Admin app's dev tools area.
52
+ */
53
+ let AppStateInspectorComponent = class AppStateInspectorComponent extends BaseResourceComponent {
54
+ cdr;
55
+ workspace;
56
+ devMode;
57
+ Sections = [
58
+ { id: 'user', label: 'Current User', icon: 'fa-solid fa-user', enabled: true, description: 'Identity, roles, email' },
59
+ { id: 'provider', label: 'Provider', icon: 'fa-solid fa-plug', enabled: true, description: 'API URL, entities loaded' },
60
+ { id: 'workspace', label: 'Workspace', icon: 'fa-solid fa-table-columns', enabled: true, description: 'Tabs, layout, active state' },
61
+ { id: 'app', label: 'Active Application', icon: 'fa-solid fa-th-large', enabled: true, description: 'Current app + nav items' },
62
+ { id: 'dev', label: 'Developer Mode', icon: 'fa-solid fa-code', enabled: true, description: 'Dev mode flag, eligibility' },
63
+ { id: 'browser', label: 'Browser & Session', icon: 'fa-solid fa-window-maximize', enabled: true, description: 'User agent, viewport, URL' }
64
+ ];
65
+ ActiveSection = 'user';
66
+ StateJson = '{}';
67
+ SearchQuery = '';
68
+ CopyConfirmed = false;
69
+ LastRefreshed = new Date();
70
+ constructor(cdr, workspace, devMode) {
71
+ super();
72
+ this.cdr = cdr;
73
+ this.workspace = workspace;
74
+ this.devMode = devMode;
75
+ }
76
+ ngOnInit() {
77
+ const p = DevToolsPrefs.Get('appStateInspector');
78
+ if (p?.activeSection && this.Sections.some(s => s.id === p.activeSection)) {
79
+ this.ActiveSection = p.activeSection;
80
+ }
81
+ this.refresh();
82
+ this.NotifyLoadComplete();
83
+ }
84
+ ngOnDestroy() {
85
+ DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });
86
+ super.ngOnDestroy();
87
+ }
88
+ async GetResourceDisplayName() { return 'App State Inspector'; }
89
+ async GetResourceIconClass() { return 'fa-solid fa-magnifying-glass-chart'; }
90
+ OnSectionClick(section) {
91
+ if (this.ActiveSection === section.id)
92
+ return;
93
+ this.ActiveSection = section.id;
94
+ DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });
95
+ this.refresh();
96
+ }
97
+ refresh() {
98
+ this.StateJson = JSON.stringify(this.computeSectionData(this.ActiveSection), this.jsonReplacer, 2);
99
+ this.LastRefreshed = new Date();
100
+ this.cdr.markForCheck();
101
+ }
102
+ async OnCopy() {
103
+ try {
104
+ await navigator.clipboard.writeText(this.StateJson);
105
+ this.CopyConfirmed = true;
106
+ this.cdr.markForCheck();
107
+ setTimeout(() => {
108
+ this.CopyConfirmed = false;
109
+ this.cdr.markForCheck();
110
+ }, 1800);
111
+ }
112
+ catch {
113
+ // clipboard unavailable
114
+ }
115
+ }
116
+ OnDownload() {
117
+ const blob = new Blob([this.StateJson], { type: 'application/json' });
118
+ const url = URL.createObjectURL(blob);
119
+ const a = document.createElement('a');
120
+ a.href = url;
121
+ a.download = `mj-app-state-${this.ActiveSection}-${this.timestampSlug()}.json`;
122
+ a.click();
123
+ URL.revokeObjectURL(url);
124
+ }
125
+ get LastRefreshedLabel() {
126
+ return this.LastRefreshed.toLocaleTimeString();
127
+ }
128
+ get SectionLabel() {
129
+ return this.Sections.find(s => s.id === this.ActiveSection)?.label ?? '';
130
+ }
131
+ // ---------- private ----------
132
+ computeSectionData(section) {
133
+ switch (section) {
134
+ case 'user': return this.userData();
135
+ case 'provider': return this.providerData();
136
+ case 'workspace': return this.workspaceData();
137
+ case 'app': return this.appData();
138
+ case 'dev': return this.devData();
139
+ case 'browser': return this.browserData();
140
+ default: return {};
141
+ }
142
+ }
143
+ userData() {
144
+ const user = this.ProviderToUse?.CurrentUser;
145
+ if (!user)
146
+ return { error: 'No current user' };
147
+ return {
148
+ ID: user.ID,
149
+ Name: user.Name,
150
+ FirstName: user.FirstName,
151
+ LastName: user.LastName,
152
+ Email: user.Email,
153
+ Type: user.Type,
154
+ IsActive: user.IsActive,
155
+ LinkedRecordType: user.LinkedRecordType,
156
+ CreatedAt: user.__mj_CreatedAt,
157
+ Roles: (user.UserRoles ?? []).map(r => ({ Role: r.Role, RoleID: r.RoleID }))
158
+ };
159
+ }
160
+ providerData() {
161
+ const provider = this.ProviderToUse;
162
+ if (!provider)
163
+ return { error: 'No provider' };
164
+ const data = {
165
+ type: provider.constructor.name,
166
+ EntitiesCount: provider.Entities?.length ?? 0,
167
+ ApplicationsCount: provider.Applications?.length ?? 0,
168
+ QueriesCount: provider.Queries?.length ?? 0,
169
+ RolesCount: provider.Roles?.length ?? 0
170
+ };
171
+ if (provider instanceof GraphQLDataProvider) {
172
+ data.URL = provider.ConfigData?.URL;
173
+ data.WSURL = provider.ConfigData?.WSURL;
174
+ }
175
+ return data;
176
+ }
177
+ workspaceData() {
178
+ const config = this.workspace.GetConfiguration();
179
+ return config;
180
+ }
181
+ appData() {
182
+ const config = this.workspace.GetConfiguration();
183
+ if (!config)
184
+ return { error: 'No workspace configuration' };
185
+ const activeTab = config.tabs?.find(t => t.id === config.activeTabId);
186
+ return {
187
+ ActiveTabId: config.activeTabId,
188
+ ActiveTab: activeTab,
189
+ TabCount: config.tabs?.length ?? 0
190
+ };
191
+ }
192
+ devData() {
193
+ return {
194
+ IsEnabled: this.devMode.IsEnabled,
195
+ IsDeveloper: this.devMode.IsDeveloper,
196
+ EligibleRoles: ['Developer', 'Admin', 'System Administrator', 'Integration']
197
+ };
198
+ }
199
+ browserData() {
200
+ return {
201
+ UserAgent: navigator.userAgent,
202
+ Language: navigator.language,
203
+ Languages: navigator.languages,
204
+ Platform: navigator.platform,
205
+ Online: navigator.onLine,
206
+ Viewport: { width: window.innerWidth, height: window.innerHeight, devicePixelRatio: window.devicePixelRatio },
207
+ URL: window.location.href,
208
+ Origin: window.location.origin,
209
+ Path: window.location.pathname + window.location.search,
210
+ Memory: this.readMemory()
211
+ };
212
+ }
213
+ jsonReplacer(_key, value) {
214
+ if (value instanceof Date)
215
+ return value.toISOString();
216
+ if (value instanceof Map)
217
+ return Object.fromEntries(value.entries());
218
+ if (value instanceof Set)
219
+ return Array.from(value);
220
+ if (typeof value === 'function')
221
+ return `[Function ${value.name || 'anonymous'}]`;
222
+ return value;
223
+ }
224
+ readMemory() {
225
+ const memory = performance.memory;
226
+ if (!memory)
227
+ return undefined;
228
+ return { usedJSHeapSize: memory.usedJSHeapSize, totalJSHeapSize: memory.totalJSHeapSize };
229
+ }
230
+ timestampSlug() {
231
+ const d = new Date();
232
+ const pad = (n) => n.toString().padStart(2, '0');
233
+ return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
234
+ }
235
+ static ɵfac = function AppStateInspectorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AppStateInspectorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i2.DeveloperModeService)); };
236
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AppStateInspectorComponent, selectors: [["mj-app-state-inspector"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 31, vars: 14, consts: [[1, "mj-inspector"], [1, "mj-inspector__header"], [1, "mj-inspector__header-icon"], [1, "fa-solid", "fa-magnifying-glass-chart"], [1, "mj-inspector__header-title"], [1, "mj-inspector__header-sub"], [1, "mj-inspector__header-spacer"], [1, "mj-inspector__header-actions"], ["type", "button", "title", "Refresh", 1, "mj-inspector__btn", 3, "click"], [1, "fa-solid", "fa-rotate"], ["type", "button", 1, "mj-inspector__btn", 3, "click", "title"], [1, "fa-solid"], ["type", "button", "title", "Download as JSON", 1, "mj-inspector__btn", 3, "click"], [1, "fa-solid", "fa-download"], [1, "mj-inspector__body"], [1, "mj-inspector__sidebar"], ["type", "button", 1, "mj-inspector__nav-item", 3, "mj-inspector__nav-item--active"], [1, "mj-inspector__content"], [1, "mj-inspector__content-head"], [1, "mj-inspector__content-title"], [1, "mj-inspector__content-meta"], [1, "mj-inspector__editor"], [3, "ngModelChange", "ngModel", "language", "readonly", "lineWrapping"], ["type", "button", 1, "mj-inspector__nav-item", 3, "click"], [1, "mj-inspector__nav-icon"], [1, "mj-inspector__nav-text"], [1, "mj-inspector__nav-label"], [1, "mj-inspector__nav-desc"]], template: function AppStateInspectorComponent_Template(rf, ctx) { if (rf & 1) {
237
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
238
+ i0.ɵɵelement(3, "i", 3);
239
+ i0.ɵɵelementEnd();
240
+ i0.ɵɵelementStart(4, "div")(5, "h3", 4);
241
+ i0.ɵɵtext(6, "App State Inspector");
242
+ i0.ɵɵelementEnd();
243
+ i0.ɵɵelementStart(7, "div", 5);
244
+ i0.ɵɵtext(8, "Read-only snapshot of Explorer runtime state");
245
+ i0.ɵɵelementEnd()();
246
+ i0.ɵɵelement(9, "span", 6);
247
+ i0.ɵɵelementStart(10, "div", 7)(11, "button", 8);
248
+ i0.ɵɵlistener("click", function AppStateInspectorComponent_Template_button_click_11_listener() { return ctx.refresh(); });
249
+ i0.ɵɵelement(12, "i", 9);
250
+ i0.ɵɵtext(13, " Refresh ");
251
+ i0.ɵɵelementEnd();
252
+ i0.ɵɵelementStart(14, "button", 10);
253
+ i0.ɵɵlistener("click", function AppStateInspectorComponent_Template_button_click_14_listener() { return ctx.OnCopy(); });
254
+ i0.ɵɵelement(15, "i", 11);
255
+ i0.ɵɵtext(16);
256
+ i0.ɵɵelementEnd();
257
+ i0.ɵɵelementStart(17, "button", 12);
258
+ i0.ɵɵlistener("click", function AppStateInspectorComponent_Template_button_click_17_listener() { return ctx.OnDownload(); });
259
+ i0.ɵɵelement(18, "i", 13);
260
+ i0.ɵɵelementEnd()()();
261
+ i0.ɵɵelementStart(19, "div", 14)(20, "aside", 15);
262
+ i0.ɵɵrepeaterCreate(21, AppStateInspectorComponent_For_22_Template, 6, 6, "button", 16, _forTrack0);
263
+ i0.ɵɵelementEnd();
264
+ i0.ɵɵelementStart(23, "div", 17)(24, "div", 18)(25, "h4", 19);
265
+ i0.ɵɵtext(26);
266
+ i0.ɵɵelementEnd();
267
+ i0.ɵɵelementStart(27, "span", 20);
268
+ i0.ɵɵtext(28);
269
+ i0.ɵɵelementEnd()();
270
+ i0.ɵɵelementStart(29, "div", 21)(30, "mj-code-editor", 22);
271
+ i0.ɵɵtwoWayListener("ngModelChange", function AppStateInspectorComponent_Template_mj_code_editor_ngModelChange_30_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.StateJson, $event) || (ctx.StateJson = $event); return $event; });
272
+ i0.ɵɵelementEnd()()()()();
273
+ } if (rf & 2) {
274
+ i0.ɵɵadvance(14);
275
+ i0.ɵɵclassProp("mj-inspector__btn--success", ctx.CopyConfirmed);
276
+ i0.ɵɵproperty("title", ctx.CopyConfirmed ? "Copied" : "Copy JSON");
277
+ i0.ɵɵadvance();
278
+ i0.ɵɵclassProp("fa-clipboard", !ctx.CopyConfirmed)("fa-check", ctx.CopyConfirmed);
279
+ i0.ɵɵadvance();
280
+ i0.ɵɵtextInterpolate1(" ", ctx.CopyConfirmed ? "Copied" : "Copy", " ");
281
+ i0.ɵɵadvance(5);
282
+ i0.ɵɵrepeater(ctx.Sections);
283
+ i0.ɵɵadvance(5);
284
+ i0.ɵɵtextInterpolate(ctx.SectionLabel);
285
+ i0.ɵɵadvance(2);
286
+ i0.ɵɵtextInterpolate1("Refreshed ", ctx.LastRefreshedLabel);
287
+ i0.ɵɵadvance(2);
288
+ i0.ɵɵtwoWayProperty("ngModel", ctx.StateJson);
289
+ i0.ɵɵproperty("language", "json")("readonly", true)("lineWrapping", true);
290
+ } }, dependencies: [i3.NgControlStatus, i3.NgModel, i4.CodeEditorComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n.mj-inspector[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n font-family: inherit;\n}\n\n\n\n.mj-inspector__header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n.mj-inspector__header-icon[_ngcontent-%COMP%] {\n width: 36px; height: 36px;\n border-radius: 9px;\n background: linear-gradient(135deg, #264FAF 0%, #0076b6 100%);\n color: white;\n display: flex; align-items: center; justify-content: center;\n font-size: 15px;\n flex-shrink: 0;\n}\n.mj-inspector__header-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n letter-spacing: -0.2px;\n}\n.mj-inspector__header-sub[_ngcontent-%COMP%] {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n.mj-inspector__header-spacer[_ngcontent-%COMP%] { flex: 1; }\n.mj-inspector__header-actions[_ngcontent-%COMP%] {\n display: flex; gap: 6px;\n}\n.mj-inspector__btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border-radius: 7px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: all 0.15s;\n}\n.mj-inspector__btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n.mj-inspector__btn--success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-border-default));\n}\n\n\n\n.mj-inspector__body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n.mj-inspector__sidebar[_ngcontent-%COMP%] {\n width: 220px;\n border-right: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n overflow-y: auto;\n flex-shrink: 0;\n padding: 8px;\n}\n.mj-inspector__nav-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.12s;\n margin-bottom: 2px;\n font-family: inherit;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n text-align: left;\n width: 100%;\n}\n.mj-inspector__nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.mj-inspector__nav-item--active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n.mj-inspector__nav-item--active[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, transparent);\n}\n.mj-inspector__nav-icon[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n font-size: 13px;\n margin-top: 1px;\n flex-shrink: 0;\n color: inherit;\n}\n.mj-inspector__nav-text[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n.mj-inspector__nav-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n}\n.mj-inspector__nav-desc[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 3px;\n line-height: 1.3;\n}\n.mj-inspector__nav-item--active[_ngcontent-%COMP%] .mj-inspector__nav-desc[_ngcontent-%COMP%] {\n color: color-mix(in srgb, var(--mj-brand-primary) 70%, var(--mj-text-muted));\n}\n\n\n\n.mj-inspector__content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n}\n.mj-inspector__content-head[_ngcontent-%COMP%] {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: var(--mj-bg-surface-card);\n}\n.mj-inspector__content-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.mj-inspector__content-meta[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n.mj-inspector__editor[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.mj-inspector__editor[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: block;\n}\n\n\n\n.mj-inspector__empty[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n@media (max-width: 700px) {\n .mj-inspector__body[_ngcontent-%COMP%] { flex-direction: column; }\n .mj-inspector__sidebar[_ngcontent-%COMP%] {\n width: 100%;\n height: auto;\n max-height: 200px;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n .mj-inspector__nav-item[_ngcontent-%COMP%] { flex: 1 1 calc(50% - 8px); margin-bottom: 0; }\n .mj-inspector__nav-desc[_ngcontent-%COMP%] { display: none; }\n .mj-inspector__header[_ngcontent-%COMP%] { padding: 12px 14px; gap: 10px; }\n}"] });
291
+ };
292
+ AppStateInspectorComponent = __decorate([
293
+ RegisterClass(BaseResourceComponent, 'AppStateInspector')
294
+ ], AppStateInspectorComponent);
295
+ export { AppStateInspectorComponent };
296
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AppStateInspectorComponent, [{
297
+ type: Component,
298
+ args: [{ standalone: false, selector: 'mj-app-state-inspector', template: "<div class=\"mj-inspector\">\n <div class=\"mj-inspector__header\">\n <div class=\"mj-inspector__header-icon\"><i class=\"fa-solid fa-magnifying-glass-chart\"></i></div>\n <div>\n <h3 class=\"mj-inspector__header-title\">App State Inspector</h3>\n <div class=\"mj-inspector__header-sub\">Read-only snapshot of Explorer runtime state</div>\n </div>\n <span class=\"mj-inspector__header-spacer\"></span>\n <div class=\"mj-inspector__header-actions\">\n <button class=\"mj-inspector__btn\" type=\"button\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-rotate\"></i> Refresh\n </button>\n <button class=\"mj-inspector__btn\"\n [class.mj-inspector__btn--success]=\"CopyConfirmed\"\n type=\"button\" (click)=\"OnCopy()\"\n [title]=\"CopyConfirmed ? 'Copied' : 'Copy JSON'\">\n <i class=\"fa-solid\" [class.fa-clipboard]=\"!CopyConfirmed\" [class.fa-check]=\"CopyConfirmed\"></i>\n {{ CopyConfirmed ? 'Copied' : 'Copy' }}\n </button>\n <button class=\"mj-inspector__btn\" type=\"button\" (click)=\"OnDownload()\" title=\"Download as JSON\">\n <i class=\"fa-solid fa-download\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"mj-inspector__body\">\n <aside class=\"mj-inspector__sidebar\">\n @for (section of Sections; track section.id) {\n <button type=\"button\"\n class=\"mj-inspector__nav-item\"\n [class.mj-inspector__nav-item--active]=\"ActiveSection === section.id\"\n (click)=\"OnSectionClick(section)\">\n <i class=\"mj-inspector__nav-icon\" [class]=\"section.icon\"></i>\n <div class=\"mj-inspector__nav-text\">\n <div class=\"mj-inspector__nav-label\">{{ section.label }}</div>\n @if (section.description) {\n <div class=\"mj-inspector__nav-desc\">{{ section.description }}</div>\n }\n </div>\n </button>\n }\n </aside>\n\n <div class=\"mj-inspector__content\">\n <div class=\"mj-inspector__content-head\">\n <h4 class=\"mj-inspector__content-title\">{{ SectionLabel }}</h4>\n <span class=\"mj-inspector__content-meta\">Refreshed {{ LastRefreshedLabel }}</span>\n </div>\n <div class=\"mj-inspector__editor\">\n <mj-code-editor\n [(ngModel)]=\"StateJson\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n</div>\n", styles: [":host { display: block; height: 100%; }\n\n.mj-inspector {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n font-family: inherit;\n}\n\n/* Header */\n.mj-inspector__header {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n.mj-inspector__header-icon {\n width: 36px; height: 36px;\n border-radius: 9px;\n background: linear-gradient(135deg, #264FAF 0%, #0076b6 100%);\n color: white;\n display: flex; align-items: center; justify-content: center;\n font-size: 15px;\n flex-shrink: 0;\n}\n.mj-inspector__header-title {\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n letter-spacing: -0.2px;\n}\n.mj-inspector__header-sub {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n.mj-inspector__header-spacer { flex: 1; }\n.mj-inspector__header-actions {\n display: flex; gap: 6px;\n}\n.mj-inspector__btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border-radius: 7px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: all 0.15s;\n}\n.mj-inspector__btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n.mj-inspector__btn--success {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-border-default));\n}\n\n/* Layout: sidebar + content */\n.mj-inspector__body {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n.mj-inspector__sidebar {\n width: 220px;\n border-right: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n overflow-y: auto;\n flex-shrink: 0;\n padding: 8px;\n}\n.mj-inspector__nav-item {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.12s;\n margin-bottom: 2px;\n font-family: inherit;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n text-align: left;\n width: 100%;\n}\n.mj-inspector__nav-item:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.mj-inspector__nav-item--active {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-brand-primary);\n}\n.mj-inspector__nav-item--active:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, transparent);\n}\n.mj-inspector__nav-icon {\n width: 18px;\n text-align: center;\n font-size: 13px;\n margin-top: 1px;\n flex-shrink: 0;\n color: inherit;\n}\n.mj-inspector__nav-text { flex: 1; min-width: 0; }\n.mj-inspector__nav-label {\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n}\n.mj-inspector__nav-desc {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 3px;\n line-height: 1.3;\n}\n.mj-inspector__nav-item--active .mj-inspector__nav-desc {\n color: color-mix(in srgb, var(--mj-brand-primary) 70%, var(--mj-text-muted));\n}\n\n/* Content area */\n.mj-inspector__content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n}\n.mj-inspector__content-head {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: var(--mj-bg-surface-card);\n}\n.mj-inspector__content-title {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n.mj-inspector__content-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n.mj-inspector__editor {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.mj-inspector__editor mj-code-editor {\n flex: 1;\n min-height: 0;\n display: block;\n}\n\n/* Empty state */\n.mj-inspector__empty {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n@media (max-width: 700px) {\n .mj-inspector__body { flex-direction: column; }\n .mj-inspector__sidebar {\n width: 100%;\n height: auto;\n max-height: 200px;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n .mj-inspector__nav-item { flex: 1 1 calc(50% - 8px); margin-bottom: 0; }\n .mj-inspector__nav-desc { display: none; }\n .mj-inspector__header { padding: 12px 14px; gap: 10px; }\n}\n"] }]
299
+ }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.WorkspaceStateManager }, { type: i2.DeveloperModeService }], null); })();
300
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AppStateInspectorComponent, { className: "AppStateInspectorComponent", filePath: "src/DevTools/app-state-inspector.component.ts", lineNumber: 29 }); })();
301
+ //# sourceMappingURL=app-state-inspector.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-state-inspector.component.js","sourceRoot":"","sources":["../../src/DevTools/app-state-inspector.component.ts","../../src/DevTools/app-state-inspector.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass } from '@memberjunction/global';\nimport { DevToolsPrefs } from './dev-tools-prefs';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\nimport { WorkspaceStateManager } from '@memberjunction/ng-base-application';\nimport { DeveloperModeService } from '@memberjunction/ng-shared';\n\ninterface InspectorSection {\n id: string;\n label: string;\n icon: string;\n enabled: boolean;\n description?: string;\n}\n\n/**\n * App State Inspector — read-only structured view of the Explorer's runtime\n * state. Replaces the legacy \"Inspect App State\" user-menu item which only\n * dumped to console. Lives in the Admin app's dev tools area.\n */\n@RegisterClass(BaseResourceComponent, 'AppStateInspector')\n@Component({\n standalone: false,\n selector: 'mj-app-state-inspector',\n templateUrl: './app-state-inspector.component.html',\n styleUrls: ['./inspector-shared.css']\n})\nexport class AppStateInspectorComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n\n public Sections: InspectorSection[] = [\n { id: 'user', label: 'Current User', icon: 'fa-solid fa-user', enabled: true, description: 'Identity, roles, email' },\n { id: 'provider', label: 'Provider', icon: 'fa-solid fa-plug', enabled: true, description: 'API URL, entities loaded' },\n { id: 'workspace',label: 'Workspace', icon: 'fa-solid fa-table-columns', enabled: true, description: 'Tabs, layout, active state' },\n { id: 'app', label: 'Active Application', icon: 'fa-solid fa-th-large', enabled: true, description: 'Current app + nav items' },\n { id: 'dev', label: 'Developer Mode', icon: 'fa-solid fa-code', enabled: true, description: 'Dev mode flag, eligibility' },\n { id: 'browser', label: 'Browser & Session', icon: 'fa-solid fa-window-maximize',enabled: true, description: 'User agent, viewport, URL' }\n ];\n\n public ActiveSection = 'user';\n public StateJson = '{}';\n public SearchQuery = '';\n public CopyConfirmed = false;\n public LastRefreshed = new Date();\n\n constructor(\n private cdr: ChangeDetectorRef,\n private workspace: WorkspaceStateManager,\n private devMode: DeveloperModeService\n ) {\n super();\n }\n\n public ngOnInit(): void {\n const p = DevToolsPrefs.Get<{ activeSection?: string }>('appStateInspector');\n if (p?.activeSection && this.Sections.some(s => s.id === p.activeSection)) {\n this.ActiveSection = p.activeSection;\n }\n this.refresh();\n this.NotifyLoadComplete();\n }\n\n public override ngOnDestroy(): void {\n DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });\n super.ngOnDestroy();\n }\n\n public override async GetResourceDisplayName(): Promise<string> { return 'App State Inspector'; }\n public override async GetResourceIconClass(): Promise<string> { return 'fa-solid fa-magnifying-glass-chart'; }\n\n public OnSectionClick(section: InspectorSection): void {\n if (this.ActiveSection === section.id) return;\n this.ActiveSection = section.id;\n DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });\n this.refresh();\n }\n\n public refresh(): void {\n this.StateJson = JSON.stringify(this.computeSectionData(this.ActiveSection), this.jsonReplacer, 2);\n this.LastRefreshed = new Date();\n this.cdr.markForCheck();\n }\n\n public async OnCopy(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.StateJson);\n this.CopyConfirmed = true;\n this.cdr.markForCheck();\n setTimeout(() => {\n this.CopyConfirmed = false;\n this.cdr.markForCheck();\n }, 1800);\n } catch {\n // clipboard unavailable\n }\n }\n\n public OnDownload(): void {\n const blob = new Blob([this.StateJson], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `mj-app-state-${this.ActiveSection}-${this.timestampSlug()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n public get LastRefreshedLabel(): string {\n return this.LastRefreshed.toLocaleTimeString();\n }\n\n public get SectionLabel(): string {\n return this.Sections.find(s => s.id === this.ActiveSection)?.label ?? '';\n }\n\n // ---------- private ----------\n\n private computeSectionData(section: string): unknown {\n switch (section) {\n case 'user': return this.userData();\n case 'provider': return this.providerData();\n case 'workspace': return this.workspaceData();\n case 'app': return this.appData();\n case 'dev': return this.devData();\n case 'browser': return this.browserData();\n default: return {};\n }\n }\n\n private userData(): unknown {\n const user = this.ProviderToUse?.CurrentUser;\n if (!user) return { error: 'No current user' };\n return {\n ID: user.ID,\n Name: user.Name,\n FirstName: user.FirstName,\n LastName: user.LastName,\n Email: user.Email,\n Type: user.Type,\n IsActive: user.IsActive,\n LinkedRecordType: user.LinkedRecordType,\n CreatedAt: user.__mj_CreatedAt,\n Roles: (user.UserRoles ?? []).map(r => ({ Role: r.Role, RoleID: r.RoleID }))\n };\n }\n\n private providerData(): unknown {\n const provider = this.ProviderToUse;\n if (!provider) return { error: 'No provider' };\n const data: Record<string, unknown> = {\n type: provider.constructor.name,\n EntitiesCount: provider.Entities?.length ?? 0,\n ApplicationsCount: provider.Applications?.length ?? 0,\n QueriesCount: provider.Queries?.length ?? 0,\n RolesCount: provider.Roles?.length ?? 0\n };\n if (provider instanceof GraphQLDataProvider) {\n data.URL = provider.ConfigData?.URL;\n data.WSURL = provider.ConfigData?.WSURL;\n }\n return data;\n }\n\n private workspaceData(): unknown {\n const config = this.workspace.GetConfiguration();\n return config;\n }\n\n private appData(): unknown {\n const config = this.workspace.GetConfiguration();\n if (!config) return { error: 'No workspace configuration' };\n const activeTab = config.tabs?.find(t => t.id === config.activeTabId);\n return {\n ActiveTabId: config.activeTabId,\n ActiveTab: activeTab,\n TabCount: config.tabs?.length ?? 0\n };\n }\n\n private devData(): unknown {\n return {\n IsEnabled: this.devMode.IsEnabled,\n IsDeveloper: this.devMode.IsDeveloper,\n EligibleRoles: ['Developer', 'Admin', 'System Administrator', 'Integration']\n };\n }\n\n private browserData(): unknown {\n return {\n UserAgent: navigator.userAgent,\n Language: navigator.language,\n Languages: navigator.languages,\n Platform: navigator.platform,\n Online: navigator.onLine,\n Viewport: { width: window.innerWidth, height: window.innerHeight, devicePixelRatio: window.devicePixelRatio },\n URL: window.location.href,\n Origin: window.location.origin,\n Path: window.location.pathname + window.location.search,\n Memory: this.readMemory()\n };\n }\n\n private jsonReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n if (value instanceof Map) return Object.fromEntries(value.entries());\n if (value instanceof Set) return Array.from(value);\n if (typeof value === 'function') return `[Function ${(value as { name: string }).name || 'anonymous'}]`;\n return value;\n }\n\n private readMemory(): { usedJSHeapSize: number; totalJSHeapSize: number } | undefined {\n const memory = (performance as Performance & {\n memory?: { usedJSHeapSize: number; totalJSHeapSize: number };\n }).memory;\n if (!memory) return undefined;\n return { usedJSHeapSize: memory.usedJSHeapSize, totalJSHeapSize: memory.totalJSHeapSize };\n }\n\n private timestampSlug(): string {\n const d = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;\n }\n\n}\n","<div class=\"mj-inspector\">\n <div class=\"mj-inspector__header\">\n <div class=\"mj-inspector__header-icon\"><i class=\"fa-solid fa-magnifying-glass-chart\"></i></div>\n <div>\n <h3 class=\"mj-inspector__header-title\">App State Inspector</h3>\n <div class=\"mj-inspector__header-sub\">Read-only snapshot of Explorer runtime state</div>\n </div>\n <span class=\"mj-inspector__header-spacer\"></span>\n <div class=\"mj-inspector__header-actions\">\n <button class=\"mj-inspector__btn\" type=\"button\" (click)=\"refresh()\" title=\"Refresh\">\n <i class=\"fa-solid fa-rotate\"></i> Refresh\n </button>\n <button class=\"mj-inspector__btn\"\n [class.mj-inspector__btn--success]=\"CopyConfirmed\"\n type=\"button\" (click)=\"OnCopy()\"\n [title]=\"CopyConfirmed ? 'Copied' : 'Copy JSON'\">\n <i class=\"fa-solid\" [class.fa-clipboard]=\"!CopyConfirmed\" [class.fa-check]=\"CopyConfirmed\"></i>\n {{ CopyConfirmed ? 'Copied' : 'Copy' }}\n </button>\n <button class=\"mj-inspector__btn\" type=\"button\" (click)=\"OnDownload()\" title=\"Download as JSON\">\n <i class=\"fa-solid fa-download\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"mj-inspector__body\">\n <aside class=\"mj-inspector__sidebar\">\n @for (section of Sections; track section.id) {\n <button type=\"button\"\n class=\"mj-inspector__nav-item\"\n [class.mj-inspector__nav-item--active]=\"ActiveSection === section.id\"\n (click)=\"OnSectionClick(section)\">\n <i class=\"mj-inspector__nav-icon\" [class]=\"section.icon\"></i>\n <div class=\"mj-inspector__nav-text\">\n <div class=\"mj-inspector__nav-label\">{{ section.label }}</div>\n @if (section.description) {\n <div class=\"mj-inspector__nav-desc\">{{ section.description }}</div>\n }\n </div>\n </button>\n }\n </aside>\n\n <div class=\"mj-inspector__content\">\n <div class=\"mj-inspector__content-head\">\n <h4 class=\"mj-inspector__content-title\">{{ SectionLabel }}</h4>\n <span class=\"mj-inspector__content-meta\">Refreshed {{ LastRefreshedLabel }}</span>\n </div>\n <div class=\"mj-inspector__editor\">\n <mj-code-editor\n [(ngModel)]=\"StateJson\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n</div>\n"]}
@@ -0,0 +1,64 @@
1
+ import { OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
3
+ import * as i0 from "@angular/core";
4
+ /** Local mirror of MJGlobal's ClassRegistration shape (avoids importing the type). */
5
+ interface ClassRegistration {
6
+ BaseClass: {
7
+ name?: string;
8
+ };
9
+ SubClass: {
10
+ name?: string;
11
+ };
12
+ Key: string | null;
13
+ Priority: number;
14
+ }
15
+ interface RegistrationGroup {
16
+ baseClassName: string;
17
+ count: number;
18
+ registrations: ClassRegistration[];
19
+ expanded: boolean;
20
+ /** Number of distinct keys (some keys can have multiple registrations at different priorities). */
21
+ uniqueKeys: number;
22
+ /** True when at least one key in this group has multiple registrations (priority resolution applies). */
23
+ hasOverrides: boolean;
24
+ }
25
+ /**
26
+ * Class Registry Browser — read-only inspector of every `@RegisterClass`
27
+ * registration tracked by `MJGlobal.Instance.ClassFactory`. Groups by base
28
+ * class, surfaces priority/override conflicts, supports search + copy.
29
+ */
30
+ export declare class ClassRegistryInspectorComponent extends BaseResourceComponent implements OnInit, OnDestroy {
31
+ private cdr;
32
+ Groups: RegistrationGroup[];
33
+ Stats: {
34
+ total: number;
35
+ baseClasses: number;
36
+ withOverrides: number;
37
+ };
38
+ SearchQuery: string;
39
+ CopyConfirmed: boolean;
40
+ LastRefreshed: Date;
41
+ constructor(cdr: ChangeDetectorRef);
42
+ ngOnInit(): void;
43
+ ngOnDestroy(): void;
44
+ PersistPrefs(): void;
45
+ private savePrefs;
46
+ GetResourceDisplayName(): Promise<string>;
47
+ GetResourceIconClass(): Promise<string>;
48
+ refresh(): void;
49
+ ToggleGroup(group: RegistrationGroup): void;
50
+ ExpandAll(): void;
51
+ CollapseAll(): void;
52
+ OnSearchChange(value: string): void;
53
+ get FilteredGroups(): RegistrationGroup[];
54
+ IsConflictRow(group: RegistrationGroup, reg: ClassRegistration): boolean;
55
+ IsWinningRow(group: RegistrationGroup, reg: ClassRegistration): boolean;
56
+ OnCopy(): Promise<void>;
57
+ get LastRefreshedLabel(): string;
58
+ TrackByBase: (_i: number, g: RegistrationGroup) => string;
59
+ TrackByReg: (_i: number, r: ClassRegistration) => string;
60
+ static ɵfac: i0.ɵɵFactoryDeclaration<ClassRegistryInspectorComponent, never>;
61
+ static ɵcmp: i0.ɵɵComponentDeclaration<ClassRegistryInspectorComponent, "mj-class-registry-inspector", never, {}, {}, never, never, false, never>;
62
+ }
63
+ export {};
64
+ //# sourceMappingURL=class-registry.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-registry.component.d.ts","sourceRoot":"","sources":["../../src/DevTools/class-registry.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAIlE,sFAAsF;AACtF,UAAU,iBAAiB;IACvB,SAAS,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,QAAQ,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,iBAAiB;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,mGAAmG;IACnG,UAAU,EAAE,MAAM,CAAC;IACnB,yGAAyG;IACzG,YAAY,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAOa,+BAAgC,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAQvF,OAAO,CAAC,GAAG;IANhB,MAAM,EAAE,iBAAiB,EAAE,CAAM;IACjC,KAAK;;;;MAAkD;IACvD,WAAW,SAAM;IACjB,aAAa,UAAS;IACtB,aAAa,OAAc;gBAEd,GAAG,EAAE,iBAAiB;IAInC,QAAQ,IAAI,IAAI;IAaP,WAAW,IAAI,IAAI;IAK5B,YAAY,IAAI,IAAI;IAI3B,OAAO,CAAC,SAAS;IAOK,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IACzC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAEtD,OAAO,IAAI,IAAI;IAoDf,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAK3C,SAAS,IAAI,IAAI;IAKjB,WAAW,IAAI,IAAI;IAKnB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1C,IAAW,cAAc,IAAI,iBAAiB,EAAE,CAc/C;IAEM,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO;IAMxE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO;IASjE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBpC,IAAW,kBAAkB,IAAI,MAAM,CAEtC;IAEM,WAAW,GAAI,IAAI,MAAM,EAAE,GAAG,iBAAiB,YAAqB;IACpE,UAAU,GAAI,IAAI,MAAM,EAAE,GAAG,iBAAiB,YAA8D;yCA/K1G,+BAA+B;2CAA/B,+BAA+B;CAgL3C"}