@memberjunction/ng-dashboards 5.35.0 → 5.36.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/dist/AI/components/agents/agent-configuration.component.js +3 -3
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts +22 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +157 -137
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +28 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +2075 -2068
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +4 -4
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +15 -0
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +1411 -1424
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.d.ts +12 -8
- package/dist/APIKeys/api-keys-resource.component.d.ts.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +329 -371
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +137 -142
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +111 -116
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +13 -65
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +13 -65
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +13 -65
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +13 -65
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/Admin/base-admin-container.component.d.ts +9 -7
- package/dist/Admin/base-admin-container.component.d.ts.map +1 -1
- package/dist/Admin/base-admin-container.component.js +26 -17
- package/dist/Admin/base-admin-container.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +74 -67
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-new-message-resource.component.d.ts +93 -0
- package/dist/Communication/communication-new-message-resource.component.d.ts.map +1 -0
- package/dist/Communication/communication-new-message-resource.component.js +661 -0
- package/dist/Communication/communication-new-message-resource.component.js.map +1 -0
- package/dist/Credentials/components/credentials-categories-resource.component.js +152 -159
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +151 -155
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +20 -21
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.d.ts +2 -0
- package/dist/DatabaseDesigner/components/entity-list.component.d.ts.map +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +131 -125
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +7 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.d.ts +5 -0
- package/dist/DevTools/app-state-inspector.component.d.ts.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +46 -72
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.js +88 -100
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.js +158 -168
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +257 -264
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.d.ts +5 -0
- package/dist/DevTools/layout-inspector.component.d.ts.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +46 -64
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/DevTools/lazy-module-status.component.js +75 -84
- package/dist/DevTools/lazy-module-status.component.js.map +1 -1
- package/dist/DevTools/settings-explorer.component.js +76 -85
- package/dist/DevTools/settings-explorer.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts +2 -0
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +7 -3
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +97 -99
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +842 -855
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +502 -517
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +78 -89
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts +5 -0
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +1120 -1128
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts +11 -0
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.d.ts.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +606 -661
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +102 -0
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +1179 -504
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.d.ts +133 -3
- package/dist/Lists/components/lists-operations-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +1527 -327
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts +29 -0
- package/dist/Lists/components/lists-shared-with-me-resource.component.d.ts.map +1 -0
- package/dist/Lists/components/lists-shared-with-me-resource.component.js +77 -0
- package/dist/Lists/components/lists-shared-with-me-resource.component.js.map +1 -0
- package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts +6 -0
- package/dist/Lists/components/venn-diagram/venn-diagram.component.d.ts.map +1 -1
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js +35 -7
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
- package/dist/Lists/index.d.ts +1 -0
- package/dist/Lists/index.d.ts.map +1 -1
- package/dist/Lists/index.js +1 -0
- package/dist/Lists/index.js.map +1 -1
- package/dist/Lists/services/list-set-operations.service.d.ts +93 -2
- package/dist/Lists/services/list-set-operations.service.d.ts.map +1 -1
- package/dist/Lists/services/list-set-operations.service.js +236 -10
- package/dist/Lists/services/list-set-operations.service.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +19 -19
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +58 -60
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts +13 -3
- package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
- package/dist/SystemDiagnostics/system-diagnostics.component.js +1007 -1252
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +31 -6
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +543 -629
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +50 -49
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +1 -1
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +16 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +9 -7
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +13 -4
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/core-dashboards.module.d.ts +1 -1
- package/dist/core-dashboards.module.d.ts.map +1 -1
- package/dist/core-dashboards.module.js +16 -1
- package/dist/core-dashboards.module.js.map +1 -1
- package/dist/lists-dashboards.module.d.ts +10 -9
- package/dist/lists-dashboards.module.d.ts.map +1 -1
- package/dist/lists-dashboards.module.js +13 -2
- package/dist/lists-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +1 -1
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +13 -1
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +53 -52
|
@@ -10,55 +10,6 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
10
10
|
import { BaseAdminContainerComponent } from './base-admin-container.component';
|
|
11
11
|
import * as i0 from "@angular/core";
|
|
12
12
|
import * as i1 from "@memberjunction/ng-ui-components";
|
|
13
|
-
const _forTrack0 = ($index, $item) => $item.id;
|
|
14
|
-
function AdminIdentityAccessComponent_For_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
15
|
-
i0.ɵɵelementStart(0, "div", 14);
|
|
16
|
-
i0.ɵɵtext(1);
|
|
17
|
-
i0.ɵɵelementEnd();
|
|
18
|
-
} if (rf & 2) {
|
|
19
|
-
const section_r2 = i0.ɵɵnextContext().$implicit;
|
|
20
|
-
i0.ɵɵadvance();
|
|
21
|
-
i0.ɵɵtextInterpolate(section_r2.description);
|
|
22
|
-
} }
|
|
23
|
-
function AdminIdentityAccessComponent_For_6_Template(rf, ctx) { if (rf & 1) {
|
|
24
|
-
const _r1 = i0.ɵɵgetCurrentView();
|
|
25
|
-
i0.ɵɵelementStart(0, "button", 10);
|
|
26
|
-
i0.ɵɵlistener("click", function AdminIdentityAccessComponent_For_6_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)); });
|
|
27
|
-
i0.ɵɵelement(1, "i", 11);
|
|
28
|
-
i0.ɵɵelementStart(2, "div", 12)(3, "div", 13);
|
|
29
|
-
i0.ɵɵtext(4);
|
|
30
|
-
i0.ɵɵelementEnd();
|
|
31
|
-
i0.ɵɵconditionalCreate(5, AdminIdentityAccessComponent_For_6_Conditional_5_Template, 2, 1, "div", 14);
|
|
32
|
-
i0.ɵɵelementEnd()();
|
|
33
|
-
} if (rf & 2) {
|
|
34
|
-
const section_r2 = ctx.$implicit;
|
|
35
|
-
const ctx_r2 = i0.ɵɵnextContext();
|
|
36
|
-
i0.ɵɵclassProp("admin-container__nav-item--active", ctx_r2.ActiveSection === section_r2.id);
|
|
37
|
-
i0.ɵɵadvance();
|
|
38
|
-
i0.ɵɵclassMap(section_r2.icon);
|
|
39
|
-
i0.ɵɵadvance(3);
|
|
40
|
-
i0.ɵɵtextInterpolate(section_r2.label);
|
|
41
|
-
i0.ɵɵadvance();
|
|
42
|
-
i0.ɵɵconditional(section_r2.description ? 5 : -1);
|
|
43
|
-
} }
|
|
44
|
-
function AdminIdentityAccessComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
-
i0.ɵɵelementStart(0, "div", 7);
|
|
46
|
-
i0.ɵɵelement(1, "i", 15);
|
|
47
|
-
i0.ɵɵelementStart(2, "span");
|
|
48
|
-
i0.ɵɵtext(3);
|
|
49
|
-
i0.ɵɵelementEnd()();
|
|
50
|
-
} if (rf & 2) {
|
|
51
|
-
const ctx_r2 = i0.ɵɵnextContext();
|
|
52
|
-
i0.ɵɵadvance(3);
|
|
53
|
-
i0.ɵɵtextInterpolate(ctx_r2.LoadError);
|
|
54
|
-
} }
|
|
55
|
-
function AdminIdentityAccessComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
-
i0.ɵɵelementStart(0, "div", 8);
|
|
57
|
-
i0.ɵɵelement(1, "i", 16);
|
|
58
|
-
i0.ɵɵelementStart(2, "span");
|
|
59
|
-
i0.ɵɵtext(3, "Loading\u2026");
|
|
60
|
-
i0.ɵɵelementEnd()();
|
|
61
|
-
} }
|
|
62
13
|
/**
|
|
63
14
|
* Admin → Identity & Access. Users, roles, app-role assignments,
|
|
64
15
|
* entity permissions, and API keys.
|
|
@@ -112,29 +63,26 @@ let AdminIdentityAccessComponent = class AdminIdentityAccessComponent extends Ba
|
|
|
112
63
|
}
|
|
113
64
|
];
|
|
114
65
|
static ɵfac = /*@__PURE__*/ (() => { let ɵAdminIdentityAccessComponent_BaseFactory; return function AdminIdentityAccessComponent_Factory(__ngFactoryType__) { return (ɵAdminIdentityAccessComponent_BaseFactory || (ɵAdminIdentityAccessComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AdminIdentityAccessComponent)))(__ngFactoryType__ || AdminIdentityAccessComponent); }; })();
|
|
115
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AdminIdentityAccessComponent, selectors: [["mj-admin-identity-access"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
66
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AdminIdentityAccessComponent, selectors: [["mj-admin-identity-access"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 7, vars: 9, consts: [["contentHost", ""], [3, "Title", "Icon", "Subtitle"], ["Direction", "row", 3, "Flex", "Padding"], [3, "ItemClicked", "Sections", "ActiveId"], [3, "Loading", "Error"]], template: function AdminIdentityAccessComponent_Template(rf, ctx) { if (rf & 1) {
|
|
67
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
116
68
|
i0.ɵɵelementStart(0, "mj-page-layout");
|
|
117
69
|
i0.ɵɵelement(1, "mj-page-header", 1);
|
|
118
|
-
i0.ɵɵelementStart(2, "mj-page-body", 2)(3, "
|
|
119
|
-
i0.ɵɵ
|
|
70
|
+
i0.ɵɵelementStart(2, "mj-page-body", 2)(3, "mj-left-nav", 3);
|
|
71
|
+
i0.ɵɵlistener("ItemClicked", function AdminIdentityAccessComponent_Template_mj_left_nav_ItemClicked_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnNavItemClicked($event)); });
|
|
120
72
|
i0.ɵɵelementEnd();
|
|
121
|
-
i0.ɵɵelementStart(
|
|
122
|
-
i0.ɵɵ
|
|
123
|
-
i0.ɵɵ
|
|
124
|
-
i0.ɵɵelementContainer(11, null, 0);
|
|
125
|
-
i0.ɵɵelementEnd()()()()();
|
|
73
|
+
i0.ɵɵelementStart(4, "mj-left-nav-content", 4);
|
|
74
|
+
i0.ɵɵelementContainer(5, null, 0);
|
|
75
|
+
i0.ɵɵelementEnd()()();
|
|
126
76
|
} if (rf & 2) {
|
|
127
77
|
i0.ɵɵadvance();
|
|
128
78
|
i0.ɵɵproperty("Title", ctx.ContainerTitle)("Icon", ctx.ContainerIcon)("Subtitle", ctx.ContainerSubtitle);
|
|
129
79
|
i0.ɵɵadvance();
|
|
130
80
|
i0.ɵɵproperty("Flex", true)("Padding", false);
|
|
131
|
-
i0.ɵɵadvance(
|
|
132
|
-
i0.ɵɵ
|
|
133
|
-
i0.ɵɵadvance(
|
|
134
|
-
i0.ɵɵ
|
|
135
|
-
|
|
136
|
-
i0.ɵɵclassProp("admin-container__host--hidden", ctx.LoadError || ctx.IsLoading);
|
|
137
|
-
} }, dependencies: [i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n.admin-container__body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n.admin-container__nav[_ngcontent-%COMP%] {\n width: 240px;\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.admin-container__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.admin-container__nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.admin-container__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.admin-container__nav-item--active[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, transparent);\n}\n.admin-container__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.admin-container__nav-text[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n.admin-container__nav-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n}\n.admin-container__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.admin-container__nav-item--active[_ngcontent-%COMP%] .admin-container__nav-desc[_ngcontent-%COMP%] {\n color: color-mix(in srgb, var(--mj-brand-primary) 70%, var(--mj-text-muted));\n}\n\n\n\n.admin-container__content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n\n\n.admin-container__host[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.admin-container__host--hidden[_ngcontent-%COMP%] { display: none; }\n.admin-container__host[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: block;\n}\n\n\n\n.admin-container__empty[_ngcontent-%COMP%], \n.admin-container__error[_ngcontent-%COMP%], \n.admin-container__loading[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n color: var(--mj-text-muted);\n font-size: 13px;\n padding: 32px;\n text-align: center;\n}\n.admin-container__error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n.admin-container__error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 20px; }\n.admin-container__loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 16px; color: var(--mj-brand-primary); }\n\n@media (max-width: 700px) {\n .admin-container__body[_ngcontent-%COMP%] { flex-direction: column; }\n .admin-container__nav[_ngcontent-%COMP%] {\n width: 100%;\n height: auto;\n max-height: 220px;\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 .admin-container__nav-item[_ngcontent-%COMP%] { flex: 1 1 calc(50% - 8px); margin-bottom: 0; }\n .admin-container__nav-desc[_ngcontent-%COMP%] { display: none; }\n}"] });
|
|
81
|
+
i0.ɵɵadvance();
|
|
82
|
+
i0.ɵɵproperty("Sections", ctx.NavSections)("ActiveId", ctx.ActiveSection);
|
|
83
|
+
i0.ɵɵadvance();
|
|
84
|
+
i0.ɵɵproperty("Loading", ctx.IsLoading)("Error", ctx.LoadError);
|
|
85
|
+
} }, dependencies: [i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent, i1.MJLeftNavComponent, i1.MJLeftNavContentComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n\n\n\n@media (max-width: 700px) {\n [_nghost-%COMP%] mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}"] });
|
|
138
86
|
};
|
|
139
87
|
AdminIdentityAccessComponent = __decorate([
|
|
140
88
|
RegisterClass(BaseResourceComponent, 'AdminIdentityAccess')
|
|
@@ -142,7 +90,7 @@ AdminIdentityAccessComponent = __decorate([
|
|
|
142
90
|
export { AdminIdentityAccessComponent };
|
|
143
91
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AdminIdentityAccessComponent, [{
|
|
144
92
|
type: Component,
|
|
145
|
-
args: [{ standalone: false, selector: 'mj-admin-identity-access', template: "<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\"
|
|
93
|
+
args: [{ standalone: false, selector: 'mj-admin-identity-access', template: "<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n", styles: [":host { display: block; height: 100%; }\n\n/* Layout, rail styling, and content-area chrome all live in the shared\n <mj-page-body> / <mj-left-nav> / <mj-left-nav-content> components. The\n only thing this file owns is the responsive collapse of the parent flex\n direction at narrow viewports. See Section 10 of explorer-chrome-conventions. */\n@media (max-width: 700px) {\n :host ::ng-deep mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}\n"] }]
|
|
146
94
|
}], null, null); })();
|
|
147
95
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AdminIdentityAccessComponent, { className: "AdminIdentityAccessComponent", filePath: "src/Admin/admin-identity-access.component.ts", lineNumber: 17 }); })();
|
|
148
96
|
//# sourceMappingURL=admin-identity-access.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-identity-access.component.js","sourceRoot":"","sources":["../../src/Admin/admin-identity-access.component.ts","../../src/Admin/admin-container.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAgB,2BAA2B,EAAE,MAAM,kCAAkC,CAAC
|
|
1
|
+
{"version":3,"file":"admin-identity-access.component.js","sourceRoot":"","sources":["../../src/Admin/admin-identity-access.component.ts","../../src/Admin/admin-container.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAgB,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;;;AAE7F;;;GAGG;AAQI,IAAM,4BAA4B,GAAlC,MAAM,4BAA6B,SAAQ,2BAA2B;IACzD,cAAc,GAAG,mBAAmB,CAAC;IACrC,aAAa,GAAG,2BAA2B,CAAC;IAC5C,iBAAiB,GAAG,yCAAyC,CAAC;IAE9D,QAAQ,GAAmB;QACvC;YACI,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,sBAAsB;YACnC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE;SAClE;QACD;YACI,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,8BAA8B;YAC3C,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE;SAClE;QACD;YACI,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,sBAAsB;YAC5B,WAAW,EAAE,2BAA2B;YACxC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,wBAAwB,EAAE;SACzE;QACD;YACI,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,kCAAkC;YAC/C,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,0BAA0B,EAAE;SACxE;QACD;YACI,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,kBAAkB;YACxB,WAAW,EAAE,+BAA+B;YAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE;SACrE;QACD;YACI,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,iBAAiB;YACvB,WAAW,EAAE,+BAA+B;YAC5C,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE;SAC/D;KACJ,CAAC;6RAhDO,4BAA4B,yBAA5B,4BAA4B;6DAA5B,4BAA4B;;YChBzC,sCAAgB;YACZ,oCAIiB;YAGb,AADJ,uCAA8D,qBAIb;YAAzC,sKAAe,4BAAwB,KAAC;YAC5C,iBAAc;YACd,8CAA+D;YAC3D,iCAA0C;YAGtD,AADI,AADI,iBAAsB,EACX,EACF;;YAfT,cAAwB;YAExB,AADA,AADA,0CAAwB,2BACF,mCACQ;YAGpB,cAAa;YAAC,AAAd,2BAAa,kBAAkB;YAErC,cAAwB;YACxB,AADA,0CAAwB,+BACE;YAGT,cAAqB;YAAC,AAAtB,uCAAqB,wBAAoB;;;ADGzD,4BAA4B;IAPxC,aAAa,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;GAO/C,4BAA4B,CAiDxC;;iFAjDY,4BAA4B;cANxC,SAAS;6BACM,KAAK,YACP,0BAA0B;;kFAI3B,4BAA4B","sourcesContent":["import { Component } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass } from '@memberjunction/global';\nimport { AdminSection, BaseAdminContainerComponent } from './base-admin-container.component';\n\n/**\n * Admin → Identity & Access. Users, roles, app-role assignments,\n * entity permissions, and API keys.\n */\n@RegisterClass(BaseResourceComponent, 'AdminIdentityAccess')\n@Component({\n standalone: false,\n selector: 'mj-admin-identity-access',\n templateUrl: './admin-container.component.html',\n styleUrls: ['./admin-container.component.css']\n})\nexport class AdminIdentityAccessComponent extends BaseAdminContainerComponent {\n public readonly ContainerTitle = 'Identity & Access';\n public readonly ContainerIcon = 'fa-solid fa-shield-halved';\n public readonly ContainerSubtitle = 'Users, roles, permissions, and API keys';\n\n public readonly Sections: AdminSection[] = [\n {\n id: 'users',\n label: 'Users',\n icon: 'fa-solid fa-users',\n description: 'Manage user accounts',\n source: { kind: 'dashboard', dashboardName: 'User Management' }\n },\n {\n id: 'roles',\n label: 'Roles',\n icon: 'fa-solid fa-user-shield',\n description: 'Define roles and assignments',\n source: { kind: 'dashboard', dashboardName: 'Role Management' }\n },\n {\n id: 'apps',\n label: 'Apps',\n icon: 'fa-solid fa-th-large',\n description: 'Application configuration',\n source: { kind: 'dashboard', dashboardName: 'Application Management' }\n },\n {\n id: 'app-roles',\n label: 'App Roles',\n icon: 'fa-solid fa-people-roof',\n description: 'Role assignments per application',\n source: { kind: 'resource', driverClass: 'ApplicationRolesResource' }\n },\n {\n id: 'permissions',\n label: 'Permissions',\n icon: 'fa-solid fa-lock',\n description: 'Entity-level access and audit',\n source: { kind: 'dashboard', dashboardName: 'Entity Permissions' }\n },\n {\n id: 'api-keys',\n label: 'API Keys',\n icon: 'fa-solid fa-key',\n description: 'API authentication and scopes',\n source: { kind: 'resource', driverClass: 'APIKeysResource' }\n }\n ];\n}\n","<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n"]}
|
|
@@ -10,55 +10,6 @@ import { RegisterClass } from '@memberjunction/global';
|
|
|
10
10
|
import { BaseAdminContainerComponent } from './base-admin-container.component';
|
|
11
11
|
import * as i0 from "@angular/core";
|
|
12
12
|
import * as i1 from "@memberjunction/ng-ui-components";
|
|
13
|
-
const _forTrack0 = ($index, $item) => $item.id;
|
|
14
|
-
function AdminMonitoringComponent_For_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
15
|
-
i0.ɵɵelementStart(0, "div", 14);
|
|
16
|
-
i0.ɵɵtext(1);
|
|
17
|
-
i0.ɵɵelementEnd();
|
|
18
|
-
} if (rf & 2) {
|
|
19
|
-
const section_r2 = i0.ɵɵnextContext().$implicit;
|
|
20
|
-
i0.ɵɵadvance();
|
|
21
|
-
i0.ɵɵtextInterpolate(section_r2.description);
|
|
22
|
-
} }
|
|
23
|
-
function AdminMonitoringComponent_For_6_Template(rf, ctx) { if (rf & 1) {
|
|
24
|
-
const _r1 = i0.ɵɵgetCurrentView();
|
|
25
|
-
i0.ɵɵelementStart(0, "button", 10);
|
|
26
|
-
i0.ɵɵlistener("click", function AdminMonitoringComponent_For_6_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)); });
|
|
27
|
-
i0.ɵɵelement(1, "i", 11);
|
|
28
|
-
i0.ɵɵelementStart(2, "div", 12)(3, "div", 13);
|
|
29
|
-
i0.ɵɵtext(4);
|
|
30
|
-
i0.ɵɵelementEnd();
|
|
31
|
-
i0.ɵɵconditionalCreate(5, AdminMonitoringComponent_For_6_Conditional_5_Template, 2, 1, "div", 14);
|
|
32
|
-
i0.ɵɵelementEnd()();
|
|
33
|
-
} if (rf & 2) {
|
|
34
|
-
const section_r2 = ctx.$implicit;
|
|
35
|
-
const ctx_r2 = i0.ɵɵnextContext();
|
|
36
|
-
i0.ɵɵclassProp("admin-container__nav-item--active", ctx_r2.ActiveSection === section_r2.id);
|
|
37
|
-
i0.ɵɵadvance();
|
|
38
|
-
i0.ɵɵclassMap(section_r2.icon);
|
|
39
|
-
i0.ɵɵadvance(3);
|
|
40
|
-
i0.ɵɵtextInterpolate(section_r2.label);
|
|
41
|
-
i0.ɵɵadvance();
|
|
42
|
-
i0.ɵɵconditional(section_r2.description ? 5 : -1);
|
|
43
|
-
} }
|
|
44
|
-
function AdminMonitoringComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
-
i0.ɵɵelementStart(0, "div", 7);
|
|
46
|
-
i0.ɵɵelement(1, "i", 15);
|
|
47
|
-
i0.ɵɵelementStart(2, "span");
|
|
48
|
-
i0.ɵɵtext(3);
|
|
49
|
-
i0.ɵɵelementEnd()();
|
|
50
|
-
} if (rf & 2) {
|
|
51
|
-
const ctx_r2 = i0.ɵɵnextContext();
|
|
52
|
-
i0.ɵɵadvance(3);
|
|
53
|
-
i0.ɵɵtextInterpolate(ctx_r2.LoadError);
|
|
54
|
-
} }
|
|
55
|
-
function AdminMonitoringComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
-
i0.ɵɵelementStart(0, "div", 8);
|
|
57
|
-
i0.ɵɵelement(1, "i", 16);
|
|
58
|
-
i0.ɵɵelementStart(2, "span");
|
|
59
|
-
i0.ɵɵtext(3, "Loading\u2026");
|
|
60
|
-
i0.ɵɵelementEnd()();
|
|
61
|
-
} }
|
|
62
13
|
/**
|
|
63
14
|
* Admin → Monitoring. System health, SQL execution logs, and outbound
|
|
64
15
|
* communication delivery monitoring.
|
|
@@ -86,29 +37,26 @@ let AdminMonitoringComponent = class AdminMonitoringComponent extends BaseAdminC
|
|
|
86
37
|
}
|
|
87
38
|
];
|
|
88
39
|
static ɵfac = /*@__PURE__*/ (() => { let ɵAdminMonitoringComponent_BaseFactory; return function AdminMonitoringComponent_Factory(__ngFactoryType__) { return (ɵAdminMonitoringComponent_BaseFactory || (ɵAdminMonitoringComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AdminMonitoringComponent)))(__ngFactoryType__ || AdminMonitoringComponent); }; })();
|
|
89
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AdminMonitoringComponent, selectors: [["mj-admin-monitoring"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
40
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AdminMonitoringComponent, selectors: [["mj-admin-monitoring"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 7, vars: 9, consts: [["contentHost", ""], [3, "Title", "Icon", "Subtitle"], ["Direction", "row", 3, "Flex", "Padding"], [3, "ItemClicked", "Sections", "ActiveId"], [3, "Loading", "Error"]], template: function AdminMonitoringComponent_Template(rf, ctx) { if (rf & 1) {
|
|
41
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
90
42
|
i0.ɵɵelementStart(0, "mj-page-layout");
|
|
91
43
|
i0.ɵɵelement(1, "mj-page-header", 1);
|
|
92
|
-
i0.ɵɵelementStart(2, "mj-page-body", 2)(3, "
|
|
93
|
-
i0.ɵɵ
|
|
44
|
+
i0.ɵɵelementStart(2, "mj-page-body", 2)(3, "mj-left-nav", 3);
|
|
45
|
+
i0.ɵɵlistener("ItemClicked", function AdminMonitoringComponent_Template_mj_left_nav_ItemClicked_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnNavItemClicked($event)); });
|
|
94
46
|
i0.ɵɵelementEnd();
|
|
95
|
-
i0.ɵɵelementStart(
|
|
96
|
-
i0.ɵɵ
|
|
97
|
-
i0.ɵɵ
|
|
98
|
-
i0.ɵɵelementContainer(11, null, 0);
|
|
99
|
-
i0.ɵɵelementEnd()()()()();
|
|
47
|
+
i0.ɵɵelementStart(4, "mj-left-nav-content", 4);
|
|
48
|
+
i0.ɵɵelementContainer(5, null, 0);
|
|
49
|
+
i0.ɵɵelementEnd()()();
|
|
100
50
|
} if (rf & 2) {
|
|
101
51
|
i0.ɵɵadvance();
|
|
102
52
|
i0.ɵɵproperty("Title", ctx.ContainerTitle)("Icon", ctx.ContainerIcon)("Subtitle", ctx.ContainerSubtitle);
|
|
103
53
|
i0.ɵɵadvance();
|
|
104
54
|
i0.ɵɵproperty("Flex", true)("Padding", false);
|
|
105
|
-
i0.ɵɵadvance(
|
|
106
|
-
i0.ɵɵ
|
|
107
|
-
i0.ɵɵadvance(
|
|
108
|
-
i0.ɵɵ
|
|
109
|
-
|
|
110
|
-
i0.ɵɵclassProp("admin-container__host--hidden", ctx.LoadError || ctx.IsLoading);
|
|
111
|
-
} }, dependencies: [i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n.admin-container__body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n.admin-container__nav[_ngcontent-%COMP%] {\n width: 240px;\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.admin-container__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.admin-container__nav-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n.admin-container__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.admin-container__nav-item--active[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, transparent);\n}\n.admin-container__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.admin-container__nav-text[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n.admin-container__nav-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n}\n.admin-container__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.admin-container__nav-item--active[_ngcontent-%COMP%] .admin-container__nav-desc[_ngcontent-%COMP%] {\n color: color-mix(in srgb, var(--mj-brand-primary) 70%, var(--mj-text-muted));\n}\n\n\n\n.admin-container__content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n\n\n.admin-container__host[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.admin-container__host--hidden[_ngcontent-%COMP%] { display: none; }\n.admin-container__host[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n display: block;\n}\n\n\n\n.admin-container__empty[_ngcontent-%COMP%], \n.admin-container__error[_ngcontent-%COMP%], \n.admin-container__loading[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n color: var(--mj-text-muted);\n font-size: 13px;\n padding: 32px;\n text-align: center;\n}\n.admin-container__error[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n.admin-container__error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 20px; }\n.admin-container__loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 16px; color: var(--mj-brand-primary); }\n\n@media (max-width: 700px) {\n .admin-container__body[_ngcontent-%COMP%] { flex-direction: column; }\n .admin-container__nav[_ngcontent-%COMP%] {\n width: 100%;\n height: auto;\n max-height: 220px;\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 .admin-container__nav-item[_ngcontent-%COMP%] { flex: 1 1 calc(50% - 8px); margin-bottom: 0; }\n .admin-container__nav-desc[_ngcontent-%COMP%] { display: none; }\n}"] });
|
|
55
|
+
i0.ɵɵadvance();
|
|
56
|
+
i0.ɵɵproperty("Sections", ctx.NavSections)("ActiveId", ctx.ActiveSection);
|
|
57
|
+
i0.ɵɵadvance();
|
|
58
|
+
i0.ɵɵproperty("Loading", ctx.IsLoading)("Error", ctx.LoadError);
|
|
59
|
+
} }, dependencies: [i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent, i1.MJLeftNavComponent, i1.MJLeftNavContentComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n\n\n\n@media (max-width: 700px) {\n [_nghost-%COMP%] mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}"] });
|
|
112
60
|
};
|
|
113
61
|
AdminMonitoringComponent = __decorate([
|
|
114
62
|
RegisterClass(BaseResourceComponent, 'AdminMonitoring')
|
|
@@ -116,7 +64,7 @@ AdminMonitoringComponent = __decorate([
|
|
|
116
64
|
export { AdminMonitoringComponent };
|
|
117
65
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AdminMonitoringComponent, [{
|
|
118
66
|
type: Component,
|
|
119
|
-
args: [{ standalone: false, selector: 'mj-admin-monitoring', template: "<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\"
|
|
67
|
+
args: [{ standalone: false, selector: 'mj-admin-monitoring', template: "<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n", styles: [":host { display: block; height: 100%; }\n\n/* Layout, rail styling, and content-area chrome all live in the shared\n <mj-page-body> / <mj-left-nav> / <mj-left-nav-content> components. The\n only thing this file owns is the responsive collapse of the parent flex\n direction at narrow viewports. See Section 10 of explorer-chrome-conventions. */\n@media (max-width: 700px) {\n :host ::ng-deep mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}\n"] }]
|
|
120
68
|
}], null, null); })();
|
|
121
69
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AdminMonitoringComponent, { className: "AdminMonitoringComponent", filePath: "src/Admin/admin-monitoring.component.ts", lineNumber: 17 }); })();
|
|
122
70
|
//# sourceMappingURL=admin-monitoring.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-monitoring.component.js","sourceRoot":"","sources":["../../src/Admin/admin-monitoring.component.ts","../../src/Admin/admin-container.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAgB,2BAA2B,EAAE,MAAM,kCAAkC,CAAC
|
|
1
|
+
{"version":3,"file":"admin-monitoring.component.js","sourceRoot":"","sources":["../../src/Admin/admin-monitoring.component.ts","../../src/Admin/admin-container.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAgB,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;;;AAE7F;;;GAGG;AAQI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,2BAA2B;IACrD,cAAc,GAAG,YAAY,CAAC;IAC9B,aAAa,GAAG,yBAAyB,CAAC;IAC1C,iBAAiB,GAAG,wCAAwC,CAAC;IAE7E,4EAA4E;IAC5E,sEAAsE;IACtD,QAAQ,GAAmB;QACvC;YACI,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,iCAAiC;YAC9C,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,2BAA2B,EAAE;SACzE;QACD;YACI,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,uBAAuB;YAC7B,WAAW,EAAE,6BAA6B;YAC1C,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE;SAC9D;KACJ,CAAC;6QAtBO,wBAAwB,yBAAxB,wBAAwB;6DAAxB,wBAAwB;;YChBrC,sCAAgB;YACZ,oCAIiB;YAGb,AADJ,uCAA8D,qBAIb;YAAzC,kKAAe,4BAAwB,KAAC;YAC5C,iBAAc;YACd,8CAA+D;YAC3D,iCAA0C;YAGtD,AADI,AADI,iBAAsB,EACX,EACF;;YAfT,cAAwB;YAExB,AADA,AADA,0CAAwB,2BACF,mCACQ;YAGpB,cAAa;YAAC,AAAd,2BAAa,kBAAkB;YAErC,cAAwB;YACxB,AADA,0CAAwB,+BACE;YAGT,cAAqB;YAAC,AAAtB,uCAAqB,wBAAoB;;;ADGzD,wBAAwB;IAPpC,aAAa,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;GAO3C,wBAAwB,CAuBpC;;iFAvBY,wBAAwB;cANpC,SAAS;6BACM,KAAK,YACP,qBAAqB;;kFAItB,wBAAwB","sourcesContent":["import { Component } from '@angular/core';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RegisterClass } from '@memberjunction/global';\nimport { AdminSection, BaseAdminContainerComponent } from './base-admin-container.component';\n\n/**\n * Admin → Monitoring. System health, SQL execution logs, and outbound\n * communication delivery monitoring.\n */\n@RegisterClass(BaseResourceComponent, 'AdminMonitoring')\n@Component({\n standalone: false,\n selector: 'mj-admin-monitoring',\n templateUrl: './admin-container.component.html',\n styleUrls: ['./admin-container.component.css']\n})\nexport class AdminMonitoringComponent extends BaseAdminContainerComponent {\n public readonly ContainerTitle = 'Monitoring';\n public readonly ContainerIcon = 'fa-solid fa-stethoscope';\n public readonly ContainerSubtitle = 'System health and query execution logs';\n\n // Communication Monitor intentionally NOT included here — outbound delivery\n // monitoring belongs in the Communications app, not in the Admin app.\n public readonly Sections: AdminSection[] = [\n {\n id: 'diagnostics',\n label: 'Diagnostics',\n icon: 'fa-solid fa-stethoscope',\n description: 'Runtime health and connectivity',\n source: { kind: 'resource', driverClass: 'SystemDiagnosticsResource' }\n },\n {\n id: 'sql-logging',\n label: 'SQL Logging',\n icon: 'fa-solid fa-file-code',\n description: 'Captured SQL execution logs',\n source: { kind: 'dashboard', dashboardName: 'SQL Logging' }\n }\n ];\n}\n","<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OnInit, OnDestroy, ChangeDetectorRef, ViewContainerRef, ComponentRef } from '@angular/core';
|
|
2
2
|
import { BaseResourceComponent } from '@memberjunction/ng-shared';
|
|
3
|
+
import { MJLeftNavItem, MJLeftNavSection } from '@memberjunction/ng-ui-components';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
/** A single sub-section inside an admin container's left-nav. */
|
|
5
6
|
export interface AdminSection {
|
|
@@ -58,6 +59,14 @@ export declare abstract class BaseAdminContainerComponent extends BaseResourceCo
|
|
|
58
59
|
ngOnDestroy(): void;
|
|
59
60
|
GetResourceDisplayName(): Promise<string>;
|
|
60
61
|
GetResourceIconClass(): Promise<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Single-section view of `Sections` shaped for `<mj-left-nav>`. AdminSection
|
|
64
|
+
* already has the required id / label / icon / description fields, so it's
|
|
65
|
+
* structurally compatible with MJLeftNavItem.
|
|
66
|
+
*/
|
|
67
|
+
get NavSections(): MJLeftNavSection[];
|
|
68
|
+
/** Adapter from `<mj-left-nav>`'s ItemClicked event back to `selectSection`. */
|
|
69
|
+
OnNavItemClicked(item: MJLeftNavItem): void;
|
|
61
70
|
/** Called by the framework on browser back/forward + deep-link entry. */
|
|
62
71
|
protected OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void;
|
|
63
72
|
OnSectionClick(section: AdminSection): Promise<void>;
|
|
@@ -66,13 +75,6 @@ export declare abstract class BaseAdminContainerComponent extends BaseResourceCo
|
|
|
66
75
|
private detachCurrent;
|
|
67
76
|
private createResourceRef;
|
|
68
77
|
private createDashboardRef;
|
|
69
|
-
/**
|
|
70
|
-
* Force the rendered sub-component's host element to fill the container
|
|
71
|
-
* cell. Mirrors what `tab-container` does for top-level resources — many
|
|
72
|
-
* dashboards rely on inline `height: 100%` to bound their internal layout
|
|
73
|
-
* (so their own `overflow-y: auto` regions actually scroll).
|
|
74
|
-
*/
|
|
75
|
-
private applyHostSizing;
|
|
76
78
|
private findSection;
|
|
77
79
|
static ɵfac: i0.ɵɵFactoryDeclaration<BaseAdminContainerComponent, never>;
|
|
78
80
|
static ɵdir: i0.ɵɵDirectiveDeclaration<BaseAdminContainerComponent, never, never, {}, {}, never, never, true, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-admin-container.component.d.ts","sourceRoot":"","sources":["../../src/Admin/base-admin-container.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,MAAM,EACN,SAAS,EACT,iBAAiB,EAEjB,gBAAgB,EAChB,YAAY,EAGf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAiB,MAAM,2BAA2B,CAAC;;
|
|
1
|
+
{"version":3,"file":"base-admin-container.component.d.ts","sourceRoot":"","sources":["../../src/Admin/base-admin-container.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,MAAM,EACN,SAAS,EACT,iBAAiB,EAEjB,gBAAgB,EAChB,YAAY,EAGf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAiB,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;;AAEnF,iEAAiE;AACjE,MAAM,WAAW,YAAY;IACzB,iEAAiE;IACjE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GACxB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD;;;;;;;;;GASG;AACH,8BACsB,2BAA4B,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IACxG,kBAAyB,cAAc,EAAE,MAAM,CAAC;IAChD,kBAAyB,aAAa,EAAE,MAAM,CAAC;IAC/C,kBAAyB,iBAAiB,EAAE,MAAM,CAAC;IACnD,kBAAyB,QAAQ,EAAE,YAAY,EAAE,CAAC;IAGlD,SAAS,CAAC,WAAW,EAAG,gBAAgB,CAAC;IAElC,aAAa,SAAM;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,SAAS,UAAS;IAEzB;;;;;;OAMG;IACH,SAAS,CAAC,KAAK,qCAA4C;IAC3D,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjD,SAAS,CAAC,QAAQ,CAAC,GAAG,oBAA6B;IAE7B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB/B,WAAW,IAAI,IAAI;IASb,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IACzC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAE7D;;;;OAIG;IACH,IAAW,WAAW,IAAI,gBAAgB,EAAE,CAE3C;IAED,gFAAgF;IACzE,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAOlD,yEAAyE;cACtD,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI;IASlG,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YAOnD,aAAa;YA+Bb,aAAa;IAwB3B,OAAO,CAAC,aAAa;YAQP,iBAAiB;YAYjB,kBAAkB;IA2BhC,OAAO,CAAC,WAAW;yCA/LD,2BAA2B;2CAA3B,2BAA2B;CAmMhD"}
|
|
@@ -56,6 +56,21 @@ export class BaseAdminContainerComponent extends BaseResourceComponent {
|
|
|
56
56
|
}
|
|
57
57
|
async GetResourceDisplayName() { return this.ContainerTitle; }
|
|
58
58
|
async GetResourceIconClass() { return this.ContainerIcon; }
|
|
59
|
+
/**
|
|
60
|
+
* Single-section view of `Sections` shaped for `<mj-left-nav>`. AdminSection
|
|
61
|
+
* already has the required id / label / icon / description fields, so it's
|
|
62
|
+
* structurally compatible with MJLeftNavItem.
|
|
63
|
+
*/
|
|
64
|
+
get NavSections() {
|
|
65
|
+
return [{ items: this.Sections }];
|
|
66
|
+
}
|
|
67
|
+
/** Adapter from `<mj-left-nav>`'s ItemClicked event back to `selectSection`. */
|
|
68
|
+
OnNavItemClicked(item) {
|
|
69
|
+
const section = this.Sections.find(s => s.id === item.id);
|
|
70
|
+
if (section) {
|
|
71
|
+
void this.OnSectionClick(section);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
59
74
|
/** Called by the framework on browser back/forward + deep-link entry. */
|
|
60
75
|
OnQueryParamsChanged(params, _source) {
|
|
61
76
|
const section = params['section'];
|
|
@@ -73,6 +88,17 @@ export class BaseAdminContainerComponent extends BaseResourceComponent {
|
|
|
73
88
|
}
|
|
74
89
|
// ---------- protected ----------
|
|
75
90
|
async selectSection(section, syncUrl) {
|
|
91
|
+
// Guard against duplicate calls for the same section. Without this,
|
|
92
|
+
// ngOnInit's own GetQueryParams read races with the workspace stream's
|
|
93
|
+
// synchronous replay through OnQueryParamsChanged on first mount —
|
|
94
|
+
// both call selectSection with the same target, both reach
|
|
95
|
+
// createComponent, and two instances of the sub-page end up mounted
|
|
96
|
+
// in the contentHost. OnSectionClick + OnQueryParamsChanged each
|
|
97
|
+
// guard their own call site, but defense-in-depth here covers any
|
|
98
|
+
// future caller (and the ngOnInit ↔ stream-replay race specifically).
|
|
99
|
+
if (section.id === this.ActiveSection) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
76
102
|
this.ActiveSection = section.id;
|
|
77
103
|
this.IsLoading = true;
|
|
78
104
|
this.LoadError = null;
|
|
@@ -107,7 +133,6 @@ export class BaseAdminContainerComponent extends BaseResourceComponent {
|
|
|
107
133
|
? await this.createResourceRef(section.source.driverClass)
|
|
108
134
|
: await this.createDashboardRef(section.source.dashboardName);
|
|
109
135
|
if (ref) {
|
|
110
|
-
this.applyHostSizing(ref);
|
|
111
136
|
this.cache.set(section.id, ref);
|
|
112
137
|
this.currentSectionId = section.id;
|
|
113
138
|
}
|
|
@@ -160,22 +185,6 @@ export class BaseAdminContainerComponent extends BaseResourceComponent {
|
|
|
160
185
|
instance.Refresh();
|
|
161
186
|
return ref;
|
|
162
187
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Force the rendered sub-component's host element to fill the container
|
|
165
|
-
* cell. Mirrors what `tab-container` does for top-level resources — many
|
|
166
|
-
* dashboards rely on inline `height: 100%` to bound their internal layout
|
|
167
|
-
* (so their own `overflow-y: auto` regions actually scroll).
|
|
168
|
-
*/
|
|
169
|
-
applyHostSizing(ref) {
|
|
170
|
-
const hostEl = ref.hostView.rootNodes[0];
|
|
171
|
-
if (!hostEl || !(hostEl instanceof HTMLElement))
|
|
172
|
-
return;
|
|
173
|
-
hostEl.style.height = '100%';
|
|
174
|
-
hostEl.style.minHeight = '0';
|
|
175
|
-
hostEl.style.display = 'flex';
|
|
176
|
-
hostEl.style.flexDirection = 'column';
|
|
177
|
-
hostEl.style.flex = '1 1 auto';
|
|
178
|
-
}
|
|
179
188
|
findSection(id) {
|
|
180
189
|
if (!id)
|
|
181
190
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-admin-container.component.js","sourceRoot":"","sources":["../../src/Admin/base-admin-container.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ViewChild,\n ViewContainerRef,\n ComponentRef,\n Type,\n inject\n} from '@angular/core';\nimport { BaseResourceComponent, BaseDashboard } from '@memberjunction/ng-shared';\nimport { MJGlobal } from '@memberjunction/global';\nimport { DashboardEngine } from '@memberjunction/core-entities';\n\n/** A single sub-section inside an admin container's left-nav. */\nexport interface AdminSection {\n /** Stable identifier — used in the URL `?section=` deep-link. */\n id: string;\n label: string;\n icon: string;\n description: string;\n source: AdminSectionSource;\n}\n\n/**\n * How to resolve and instantiate the component for this sub-section.\n *\n * - `resource`: looks up `@RegisterClass(BaseResourceComponent, driverClass)` and renders it directly.\n * - `dashboard`: looks up the MJ Dashboard record by name, then renders its `DriverClass` via the\n * BaseDashboard registry with a synthetic `{ dashboard }` config (mirrors the shell's flow for\n * `ResourceType: \"Dashboards\"` nav items).\n */\nexport type AdminSectionSource =\n | { kind: 'resource'; driverClass: string }\n | { kind: 'dashboard'; dashboardName: string };\n\n/**\n * Shared base for all Admin app container resources. Subclasses declare:\n * - ContainerTitle / ContainerIcon / ContainerSubtitle\n * - Sections[]\n * - @RegisterClass(BaseResourceComponent, '...')\n *\n * The base handles: left-nav state, URL deep-linking via NavigationService,\n * dynamic component instantiation for both resource and dashboard sections,\n * teardown on switch.\n */\n@Directive()\nexport abstract class BaseAdminContainerComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public abstract readonly ContainerTitle: string;\n public abstract readonly ContainerIcon: string;\n public abstract readonly ContainerSubtitle: string;\n public abstract readonly Sections: AdminSection[];\n\n @ViewChild('contentHost', { read: ViewContainerRef, static: true })\n protected contentHost!: ViewContainerRef;\n\n public ActiveSection = '';\n public LoadError: string | null = null;\n public IsLoading = false;\n\n /**\n * Cache of section.id → ComponentRef. Once a sub-section is rendered we\n * keep its component alive across switches by detaching + reattaching the\n * view (instead of destroying + recreating). This preserves state — Event\n * Monitor's captured events, GraphQL Console's history, query inputs,\n * scroll position, etc. — and avoids expensive re-init.\n */\n protected cache = new Map<string, ComponentRef<unknown>>();\n protected currentSectionId: string | null = null;\n\n protected readonly cdr = inject(ChangeDetectorRef);\n\n public override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n\n const params = this.GetQueryParams();\n const requested = params['section'];\n const initial = this.findSection(requested)?.id ?? this.Sections[0]?.id ?? '';\n const target = this.findSection(initial);\n if (target) {\n await this.selectSection(target, /*syncUrl*/ false);\n }\n\n if (!requested && this.ActiveSection) {\n this.UpdateQueryParams({ section: this.ActiveSection });\n }\n\n this.NotifyLoadComplete();\n }\n\n public override ngOnDestroy(): void {\n for (const ref of this.cache.values()) {\n try { ref.destroy(); } catch { /* ignore */ }\n }\n this.cache.clear();\n this.currentSectionId = null;\n super.ngOnDestroy();\n }\n\n public override async GetResourceDisplayName(): Promise<string> { return this.ContainerTitle; }\n public override async GetResourceIconClass(): Promise<string> { return this.ContainerIcon; }\n\n /** Called by the framework on browser back/forward + deep-link entry. */\n protected override OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void {\n const section = params['section'];\n if (!section || section === this.ActiveSection) return;\n const target = this.findSection(section);\n if (target) {\n void this.selectSection(target, /*syncUrl*/ false);\n }\n }\n\n public async OnSectionClick(section: AdminSection): Promise<void> {\n if (section.id === this.ActiveSection) return;\n await this.selectSection(section, /*syncUrl*/ true);\n }\n\n // ---------- protected ----------\n\n private async selectSection(section: AdminSection, syncUrl: boolean): Promise<void> {\n this.ActiveSection = section.id;\n this.IsLoading = true;\n this.LoadError = null;\n this.cdr.markForCheck();\n\n if (syncUrl) {\n this.UpdateQueryParams({ section: section.id });\n }\n\n try {\n await this.renderSection(section);\n } catch (err) {\n this.LoadError = err instanceof Error ? err.message : String(err);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n private async renderSection(section: AdminSection): Promise<void> {\n // Detach (don't destroy) the currently visible sub-component so it\n // stays alive in memory with its state intact.\n this.detachCurrent();\n\n // Reattach if cached\n const cached = this.cache.get(section.id);\n if (cached) {\n this.contentHost.insert(cached.hostView);\n this.currentSectionId = section.id;\n return;\n }\n\n // Otherwise, create fresh\n const ref = section.source.kind === 'resource'\n ? await this.createResourceRef(section.source.driverClass)\n : await this.createDashboardRef(section.source.dashboardName);\n\n if (ref) {\n this.applyHostSizing(ref);\n this.cache.set(section.id, ref);\n this.currentSectionId = section.id;\n }\n }\n\n private detachCurrent(): void {\n if (!this.currentSectionId) return;\n const cur = this.cache.get(this.currentSectionId);\n if (!cur) return;\n const idx = this.contentHost.indexOf(cur.hostView);\n if (idx >= 0) this.contentHost.detach(idx);\n }\n\n private async createResourceRef(driverClass: string): Promise<ComponentRef<unknown> | null> {\n const reg = await MJGlobal.Instance.ClassFactory.GetRegistrationAsync(BaseResourceComponent, driverClass);\n if (!reg) {\n this.LoadError = `Component \"${driverClass}\" is not registered. Make sure its module is imported.`;\n return null;\n }\n const ref = this.contentHost.createComponent(reg.SubClass as Type<BaseResourceComponent>);\n const instance = ref.instance as BaseResourceComponent;\n if (this.Data) instance.Data = this.Data;\n return ref;\n }\n\n private async createDashboardRef(dashboardName: string): Promise<ComponentRef<unknown> | null> {\n await DashboardEngine.Instance.Config(false);\n const dashboard = DashboardEngine.Instance.Dashboards.find(d => d.Name === dashboardName);\n if (!dashboard) {\n this.LoadError = `Dashboard \"${dashboardName}\" was not found in metadata.`;\n return null;\n }\n if (dashboard.Type !== 'Code') {\n this.LoadError = `Dashboard \"${dashboardName}\" has type \"${dashboard.Type}\" — only Code dashboards can be embedded here.`;\n return null;\n }\n if (!dashboard.DriverClass) {\n this.LoadError = `Dashboard \"${dashboardName}\" has no DriverClass set.`;\n return null;\n }\n const reg = await MJGlobal.Instance.ClassFactory.GetRegistrationAsync(BaseDashboard, dashboard.DriverClass);\n if (!reg) {\n this.LoadError = `Driver class \"${dashboard.DriverClass}\" is not registered against BaseDashboard.`;\n return null;\n }\n const ref = this.contentHost.createComponent(reg.SubClass as Type<BaseDashboard>);\n const instance = ref.instance as BaseDashboard;\n instance.Config = { dashboard, userState: undefined };\n instance.Refresh();\n return ref;\n }\n\n /**\n * Force the rendered sub-component's host element to fill the container\n * cell. Mirrors what `tab-container` does for top-level resources — many\n * dashboards rely on inline `height: 100%` to bound their internal layout\n * (so their own `overflow-y: auto` regions actually scroll).\n */\n private applyHostSizing(ref: ComponentRef<unknown>): void {\n const hostEl = (ref.hostView as unknown as { rootNodes: HTMLElement[] }).rootNodes[0];\n if (!hostEl || !(hostEl instanceof HTMLElement)) return;\n hostEl.style.height = '100%';\n hostEl.style.minHeight = '0';\n hostEl.style.display = 'flex';\n hostEl.style.flexDirection = 'column';\n hostEl.style.flex = '1 1 auto';\n }\n\n private findSection(id: string | undefined | null): AdminSection | undefined {\n if (!id) return undefined;\n return this.Sections.find(s => s.id === id);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-admin-container.component.js","sourceRoot":"","sources":["../../src/Admin/base-admin-container.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ViewChild,\n ViewContainerRef,\n ComponentRef,\n Type,\n inject\n} from '@angular/core';\nimport { BaseResourceComponent, BaseDashboard } from '@memberjunction/ng-shared';\nimport { MJGlobal } from '@memberjunction/global';\nimport { DashboardEngine } from '@memberjunction/core-entities';\nimport { MJLeftNavItem, MJLeftNavSection } from '@memberjunction/ng-ui-components';\n\n/** A single sub-section inside an admin container's left-nav. */\nexport interface AdminSection {\n /** Stable identifier — used in the URL `?section=` deep-link. */\n id: string;\n label: string;\n icon: string;\n description: string;\n source: AdminSectionSource;\n}\n\n/**\n * How to resolve and instantiate the component for this sub-section.\n *\n * - `resource`: looks up `@RegisterClass(BaseResourceComponent, driverClass)` and renders it directly.\n * - `dashboard`: looks up the MJ Dashboard record by name, then renders its `DriverClass` via the\n * BaseDashboard registry with a synthetic `{ dashboard }` config (mirrors the shell's flow for\n * `ResourceType: \"Dashboards\"` nav items).\n */\nexport type AdminSectionSource =\n | { kind: 'resource'; driverClass: string }\n | { kind: 'dashboard'; dashboardName: string };\n\n/**\n * Shared base for all Admin app container resources. Subclasses declare:\n * - ContainerTitle / ContainerIcon / ContainerSubtitle\n * - Sections[]\n * - @RegisterClass(BaseResourceComponent, '...')\n *\n * The base handles: left-nav state, URL deep-linking via NavigationService,\n * dynamic component instantiation for both resource and dashboard sections,\n * teardown on switch.\n */\n@Directive()\nexport abstract class BaseAdminContainerComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public abstract readonly ContainerTitle: string;\n public abstract readonly ContainerIcon: string;\n public abstract readonly ContainerSubtitle: string;\n public abstract readonly Sections: AdminSection[];\n\n @ViewChild('contentHost', { read: ViewContainerRef, static: true })\n protected contentHost!: ViewContainerRef;\n\n public ActiveSection = '';\n public LoadError: string | null = null;\n public IsLoading = false;\n\n /**\n * Cache of section.id → ComponentRef. Once a sub-section is rendered we\n * keep its component alive across switches by detaching + reattaching the\n * view (instead of destroying + recreating). This preserves state — Event\n * Monitor's captured events, GraphQL Console's history, query inputs,\n * scroll position, etc. — and avoids expensive re-init.\n */\n protected cache = new Map<string, ComponentRef<unknown>>();\n protected currentSectionId: string | null = null;\n\n protected readonly cdr = inject(ChangeDetectorRef);\n\n public override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n\n const params = this.GetQueryParams();\n const requested = params['section'];\n const initial = this.findSection(requested)?.id ?? this.Sections[0]?.id ?? '';\n const target = this.findSection(initial);\n if (target) {\n await this.selectSection(target, /*syncUrl*/ false);\n }\n\n if (!requested && this.ActiveSection) {\n this.UpdateQueryParams({ section: this.ActiveSection });\n }\n\n this.NotifyLoadComplete();\n }\n\n public override ngOnDestroy(): void {\n for (const ref of this.cache.values()) {\n try { ref.destroy(); } catch { /* ignore */ }\n }\n this.cache.clear();\n this.currentSectionId = null;\n super.ngOnDestroy();\n }\n\n public override async GetResourceDisplayName(): Promise<string> { return this.ContainerTitle; }\n public override async GetResourceIconClass(): Promise<string> { return this.ContainerIcon; }\n\n /**\n * Single-section view of `Sections` shaped for `<mj-left-nav>`. AdminSection\n * already has the required id / label / icon / description fields, so it's\n * structurally compatible with MJLeftNavItem.\n */\n public get NavSections(): MJLeftNavSection[] {\n return [{ items: this.Sections }];\n }\n\n /** Adapter from `<mj-left-nav>`'s ItemClicked event back to `selectSection`. */\n public OnNavItemClicked(item: MJLeftNavItem): void {\n const section = this.Sections.find(s => s.id === item.id);\n if (section) {\n void this.OnSectionClick(section);\n }\n }\n\n /** Called by the framework on browser back/forward + deep-link entry. */\n protected override OnQueryParamsChanged(params: Record<string, string>, _source: 'popstate' | 'deeplink'): void {\n const section = params['section'];\n if (!section || section === this.ActiveSection) return;\n const target = this.findSection(section);\n if (target) {\n void this.selectSection(target, /*syncUrl*/ false);\n }\n }\n\n public async OnSectionClick(section: AdminSection): Promise<void> {\n if (section.id === this.ActiveSection) return;\n await this.selectSection(section, /*syncUrl*/ true);\n }\n\n // ---------- protected ----------\n\n private async selectSection(section: AdminSection, syncUrl: boolean): Promise<void> {\n // Guard against duplicate calls for the same section. Without this,\n // ngOnInit's own GetQueryParams read races with the workspace stream's\n // synchronous replay through OnQueryParamsChanged on first mount —\n // both call selectSection with the same target, both reach\n // createComponent, and two instances of the sub-page end up mounted\n // in the contentHost. OnSectionClick + OnQueryParamsChanged each\n // guard their own call site, but defense-in-depth here covers any\n // future caller (and the ngOnInit ↔ stream-replay race specifically).\n if (section.id === this.ActiveSection) {\n return;\n }\n this.ActiveSection = section.id;\n this.IsLoading = true;\n this.LoadError = null;\n this.cdr.markForCheck();\n\n if (syncUrl) {\n this.UpdateQueryParams({ section: section.id });\n }\n\n try {\n await this.renderSection(section);\n } catch (err) {\n this.LoadError = err instanceof Error ? err.message : String(err);\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n private async renderSection(section: AdminSection): Promise<void> {\n // Detach (don't destroy) the currently visible sub-component so it\n // stays alive in memory with its state intact.\n this.detachCurrent();\n\n // Reattach if cached\n const cached = this.cache.get(section.id);\n if (cached) {\n this.contentHost.insert(cached.hostView);\n this.currentSectionId = section.id;\n return;\n }\n\n // Otherwise, create fresh\n const ref = section.source.kind === 'resource'\n ? await this.createResourceRef(section.source.driverClass)\n : await this.createDashboardRef(section.source.dashboardName);\n\n if (ref) {\n this.cache.set(section.id, ref);\n this.currentSectionId = section.id;\n }\n }\n\n private detachCurrent(): void {\n if (!this.currentSectionId) return;\n const cur = this.cache.get(this.currentSectionId);\n if (!cur) return;\n const idx = this.contentHost.indexOf(cur.hostView);\n if (idx >= 0) this.contentHost.detach(idx);\n }\n\n private async createResourceRef(driverClass: string): Promise<ComponentRef<unknown> | null> {\n const reg = await MJGlobal.Instance.ClassFactory.GetRegistrationAsync(BaseResourceComponent, driverClass);\n if (!reg) {\n this.LoadError = `Component \"${driverClass}\" is not registered. Make sure its module is imported.`;\n return null;\n }\n const ref = this.contentHost.createComponent(reg.SubClass as Type<BaseResourceComponent>);\n const instance = ref.instance as BaseResourceComponent;\n if (this.Data) instance.Data = this.Data;\n return ref;\n }\n\n private async createDashboardRef(dashboardName: string): Promise<ComponentRef<unknown> | null> {\n await DashboardEngine.Instance.Config(false);\n const dashboard = DashboardEngine.Instance.Dashboards.find(d => d.Name === dashboardName);\n if (!dashboard) {\n this.LoadError = `Dashboard \"${dashboardName}\" was not found in metadata.`;\n return null;\n }\n if (dashboard.Type !== 'Code') {\n this.LoadError = `Dashboard \"${dashboardName}\" has type \"${dashboard.Type}\" — only Code dashboards can be embedded here.`;\n return null;\n }\n if (!dashboard.DriverClass) {\n this.LoadError = `Dashboard \"${dashboardName}\" has no DriverClass set.`;\n return null;\n }\n const reg = await MJGlobal.Instance.ClassFactory.GetRegistrationAsync(BaseDashboard, dashboard.DriverClass);\n if (!reg) {\n this.LoadError = `Driver class \"${dashboard.DriverClass}\" is not registered against BaseDashboard.`;\n return null;\n }\n const ref = this.contentHost.createComponent(reg.SubClass as Type<BaseDashboard>);\n const instance = ref.instance as BaseDashboard;\n instance.Config = { dashboard, userState: undefined };\n instance.Refresh();\n return ref;\n }\n\n private findSection(id: string | undefined | null): AdminSection | undefined {\n if (!id) return undefined;\n return this.Sections.find(s => s.id === id);\n }\n}\n"]}
|