@memberjunction/ng-explorer-core 4.0.0 → 4.2.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 (142) hide show
  1. package/README.md +117 -726
  2. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  3. package/dist/lib/resource-wrappers/record-resource.component.js +11 -29
  4. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  5. package/dist/lib/shell/components/header/app-nav.component.d.ts +71 -14
  6. package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
  7. package/dist/lib/shell/components/header/app-nav.component.js +195 -54
  8. package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
  9. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  10. package/dist/lib/shell/components/tabs/component-cache-manager.js +0 -6
  11. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  12. package/dist/lib/shell/shell.component.d.ts +5 -1
  13. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  14. package/dist/lib/shell/shell.component.js +28 -17
  15. package/dist/lib/shell/shell.component.js.map +1 -1
  16. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +1 -1
  17. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +1 -1
  18. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +1 -1
  19. package/dist/lib/single-record/single-record.component.d.ts +9 -0
  20. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  21. package/dist/lib/single-record/single-record.component.js +43 -2
  22. package/dist/lib/single-record/single-record.component.js.map +1 -1
  23. package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
  24. package/dist/lib/user-menu/base-user-menu.js +2 -13
  25. package/dist/lib/user-menu/base-user-menu.js.map +1 -1
  26. package/package.json +35 -35
  27. package/dist/generic/Events.types.d.ts +0 -174
  28. package/dist/generic/Events.types.d.ts.map +0 -1
  29. package/dist/generic/Events.types.js +0 -220
  30. package/dist/generic/Events.types.js.map +0 -1
  31. package/dist/lib/app-view/application-view.component.d.ts +0 -65
  32. package/dist/lib/app-view/application-view.component.d.ts.map +0 -1
  33. package/dist/lib/app-view/application-view.component.js +0 -611
  34. package/dist/lib/app-view/application-view.component.js.map +0 -1
  35. package/dist/lib/auth-button/auth-button.component.d.ts +0 -13
  36. package/dist/lib/auth-button/auth-button.component.d.ts.map +0 -1
  37. package/dist/lib/auth-button/auth-button.component.js +0 -36
  38. package/dist/lib/auth-button/auth-button.component.js.map +0 -1
  39. package/dist/lib/base-browser-component/base-browser-component.d.ts +0 -44
  40. package/dist/lib/base-browser-component/base-browser-component.d.ts.map +0 -1
  41. package/dist/lib/base-browser-component/base-browser-component.js +0 -195
  42. package/dist/lib/base-browser-component/base-browser-component.js.map +0 -1
  43. package/dist/lib/chat-wrapper/chat-wrapper.component.d.ts +0 -54
  44. package/dist/lib/chat-wrapper/chat-wrapper.component.d.ts.map +0 -1
  45. package/dist/lib/chat-wrapper/chat-wrapper.component.js +0 -257
  46. package/dist/lib/chat-wrapper/chat-wrapper.component.js.map +0 -1
  47. package/dist/lib/dashboard-browser-component/dashboard-browser.component.d.ts +0 -32
  48. package/dist/lib/dashboard-browser-component/dashboard-browser.component.d.ts.map +0 -1
  49. package/dist/lib/dashboard-browser-component/dashboard-browser.component.js +0 -244
  50. package/dist/lib/dashboard-browser-component/dashboard-browser.component.js.map +0 -1
  51. package/dist/lib/data-browser-component/data-browser.component.d.ts +0 -23
  52. package/dist/lib/data-browser-component/data-browser.component.d.ts.map +0 -1
  53. package/dist/lib/data-browser-component/data-browser.component.js +0 -267
  54. package/dist/lib/data-browser-component/data-browser.component.js.map +0 -1
  55. package/dist/lib/expansion-panel-component/expansion-panel-component.d.ts +0 -21
  56. package/dist/lib/expansion-panel-component/expansion-panel-component.d.ts.map +0 -1
  57. package/dist/lib/expansion-panel-component/expansion-panel-component.js +0 -158
  58. package/dist/lib/expansion-panel-component/expansion-panel-component.js.map +0 -1
  59. package/dist/lib/favorites/favorites.component.d.ts +0 -15
  60. package/dist/lib/favorites/favorites.component.d.ts.map +0 -1
  61. package/dist/lib/favorites/favorites.component.js +0 -135
  62. package/dist/lib/favorites/favorites.component.js.map +0 -1
  63. package/dist/lib/files/files.component.d.ts +0 -10
  64. package/dist/lib/files/files.component.d.ts.map +0 -1
  65. package/dist/lib/files/files.component.js +0 -41
  66. package/dist/lib/files/files.component.js.map +0 -1
  67. package/dist/lib/generic-browse-list/generic-browse-list.component.d.ts +0 -30
  68. package/dist/lib/generic-browse-list/generic-browse-list.component.d.ts.map +0 -1
  69. package/dist/lib/generic-browse-list/generic-browse-list.component.js +0 -171
  70. package/dist/lib/generic-browse-list/generic-browse-list.component.js.map +0 -1
  71. package/dist/lib/generic-browser-list/generic-browser-list.component.d.ts +0 -120
  72. package/dist/lib/generic-browser-list/generic-browser-list.component.d.ts.map +0 -1
  73. package/dist/lib/generic-browser-list/generic-browser-list.component.js +0 -1093
  74. package/dist/lib/generic-browser-list/generic-browser-list.component.js.map +0 -1
  75. package/dist/lib/header/MSFT_UserImageService.d.ts +0 -12
  76. package/dist/lib/header/MSFT_UserImageService.d.ts.map +0 -1
  77. package/dist/lib/header/MSFT_UserImageService.js +0 -25
  78. package/dist/lib/header/MSFT_UserImageService.js.map +0 -1
  79. package/dist/lib/header/header.component.d.ts +0 -69
  80. package/dist/lib/header/header.component.d.ts.map +0 -1
  81. package/dist/lib/header/header.component.js +0 -342
  82. package/dist/lib/header/header.component.js.map +0 -1
  83. package/dist/lib/home-component/home.component.d.ts +0 -22
  84. package/dist/lib/home-component/home.component.d.ts.map +0 -1
  85. package/dist/lib/home-component/home.component.js +0 -194
  86. package/dist/lib/home-component/home.component.js.map +0 -1
  87. package/dist/lib/home-wrapper/home-wrapper.component.d.ts +0 -7
  88. package/dist/lib/home-wrapper/home-wrapper.component.d.ts.map +0 -1
  89. package/dist/lib/home-wrapper/home-wrapper.component.js +0 -30
  90. package/dist/lib/home-wrapper/home-wrapper.component.js.map +0 -1
  91. package/dist/lib/list-view/list-view.component.d.ts +0 -45
  92. package/dist/lib/list-view/list-view.component.d.ts.map +0 -1
  93. package/dist/lib/list-view/list-view.component.js +0 -329
  94. package/dist/lib/list-view/list-view.component.js.map +0 -1
  95. package/dist/lib/navigation/navigation.component.d.ts +0 -142
  96. package/dist/lib/navigation/navigation.component.d.ts.map +0 -1
  97. package/dist/lib/navigation/navigation.component.js +0 -1212
  98. package/dist/lib/navigation/navigation.component.js.map +0 -1
  99. package/dist/lib/query-browser-component/query-browser.component.d.ts +0 -75
  100. package/dist/lib/query-browser-component/query-browser.component.d.ts.map +0 -1
  101. package/dist/lib/query-browser-component/query-browser.component.js +0 -908
  102. package/dist/lib/query-browser-component/query-browser.component.js.map +0 -1
  103. package/dist/lib/report-browser-component/report-browser.component.d.ts +0 -22
  104. package/dist/lib/report-browser-component/report-browser.component.d.ts.map +0 -1
  105. package/dist/lib/report-browser-component/report-browser.component.js +0 -80
  106. package/dist/lib/report-browser-component/report-browser.component.js.map +0 -1
  107. package/dist/lib/resource-browser/resource-browser.component.d.ts +0 -178
  108. package/dist/lib/resource-browser/resource-browser.component.d.ts.map +0 -1
  109. package/dist/lib/resource-browser/resource-browser.component.js +0 -1012
  110. package/dist/lib/resource-browser/resource-browser.component.js.map +0 -1
  111. package/dist/lib/resource-wrappers/report-resource.component.d.ts +0 -13
  112. package/dist/lib/resource-wrappers/report-resource.component.d.ts.map +0 -1
  113. package/dist/lib/resource-wrappers/report-resource.component.js +0 -49
  114. package/dist/lib/resource-wrappers/report-resource.component.js.map +0 -1
  115. package/dist/lib/shared/custom-icon/custom-icon.component.d.ts +0 -11
  116. package/dist/lib/shared/custom-icon/custom-icon.component.d.ts.map +0 -1
  117. package/dist/lib/shared/custom-icon/custom-icon.component.js +0 -44
  118. package/dist/lib/shared/custom-icon/custom-icon.component.js.map +0 -1
  119. package/dist/lib/single-application/single-application.component.d.ts +0 -24
  120. package/dist/lib/single-application/single-application.component.d.ts.map +0 -1
  121. package/dist/lib/single-application/single-application.component.js +0 -122
  122. package/dist/lib/single-application/single-application.component.js.map +0 -1
  123. package/dist/lib/single-entity/single-entity.component.d.ts +0 -34
  124. package/dist/lib/single-entity/single-entity.component.d.ts.map +0 -1
  125. package/dist/lib/single-entity/single-entity.component.js +0 -245
  126. package/dist/lib/single-entity/single-entity.component.js.map +0 -1
  127. package/dist/lib/single-report/single-report.component.d.ts +0 -17
  128. package/dist/lib/single-report/single-report.component.d.ts.map +0 -1
  129. package/dist/lib/single-report/single-report.component.js +0 -55
  130. package/dist/lib/single-report/single-report.component.js.map +0 -1
  131. package/dist/lib/single-view/single-view.component.d.ts +0 -43
  132. package/dist/lib/single-view/single-view.component.d.ts.map +0 -1
  133. package/dist/lib/single-view/single-view.component.js +0 -207
  134. package/dist/lib/single-view/single-view.component.js.map +0 -1
  135. package/dist/lib/style-guide-test/style-guide-test.component.d.ts +0 -70
  136. package/dist/lib/style-guide-test/style-guide-test.component.d.ts.map +0 -1
  137. package/dist/lib/style-guide-test/style-guide-test.component.js +0 -1024
  138. package/dist/lib/style-guide-test/style-guide-test.component.js.map +0 -1
  139. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts +0 -46
  140. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts.map +0 -1
  141. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js +0 -547
  142. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js.map +0 -1
@@ -1,1212 +0,0 @@
1
- import { Component, ElementRef, ViewChild, HostListener, HostBinding, Input } from '@angular/core';
2
- import { NavigationEnd, NavigationSkipped } from '@angular/router';
3
- import { DrawerComponent } from "@progress/kendo-angular-layout";
4
- import { Metadata, RunView, LogError, LogStatus } from '@memberjunction/core';
5
- import { MJEventType, MJGlobal } from '@memberjunction/global';
6
- import { EventCodes, SharedService } from '@memberjunction/ng-shared';
7
- import { BaseResourceComponent } from '@memberjunction/ng-shared';
8
- import { ResourceData } from '@memberjunction/core-entities';
9
- import { ItemType, TreeItem } from '../../generic/Item.types';
10
- import { TemplateEngineBase } from '@memberjunction/templates-base-types';
11
- import { CommunicationEngineBase } from '@memberjunction/communication-types';
12
- import { EntityCommunicationsEngineClient } from '@memberjunction/entity-communications-client';
13
- import { MJNotificationService } from '@memberjunction/ng-notifications';
14
- import { LoadEntityCommunicationsEngineClient } from '@memberjunction/entity-communications-client';
15
- import * as i0 from "@angular/core";
16
- import * as i1 from "@angular/router";
17
- import * as i2 from "@memberjunction/ng-shared";
18
- import * as i3 from "@angular/common";
19
- import * as i4 from "@angular/platform-browser";
20
- import * as i5 from "@progress/kendo-angular-dialog";
21
- import * as i6 from "@progress/kendo-angular-layout";
22
- import * as i7 from "@memberjunction/ng-tabstrip";
23
- import * as i8 from "@memberjunction/ng-shared-generic";
24
- import * as i9 from "../generic/resource-container-component";
25
- const _c0 = ["mjTabstrip"];
26
- const _c1 = ["drawerWrapper"];
27
- const _c2 = ["container"];
28
- const _forTrack0 = ($index, $item) => $item.id;
29
- const _c3 = a0 => ({ "waiting": a0 });
30
- function NavigationComponent_mj_loading_2_Template(rf, ctx) { if (rf & 1) {
31
- i0.ɵɵelement(0, "mj-loading", 7);
32
- } if (rf & 2) {
33
- i0.ɵɵproperty("showText", false);
34
- } }
35
- function NavigationComponent_kendo_drawer_container_3_ng_template_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
36
- i0.ɵɵelement(0, "span", 14);
37
- } }
38
- function NavigationComponent_kendo_drawer_container_3_ng_template_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
39
- i0.ɵɵelement(0, "span");
40
- } if (rf & 2) {
41
- const item_r3 = i0.ɵɵnextContext().$implicit;
42
- i0.ɵɵclassMap(item_r3.icon);
43
- } }
44
- function NavigationComponent_kendo_drawer_container_3_ng_template_3_Template(rf, ctx) { if (rf & 1) {
45
- i0.ɵɵelementStart(0, "div", 13);
46
- i0.ɵɵtemplate(1, NavigationComponent_kendo_drawer_container_3_ng_template_3_Conditional_1_Template, 1, 0, "span", 14)(2, NavigationComponent_kendo_drawer_container_3_ng_template_3_Conditional_2_Template, 1, 2, "span", 15);
47
- i0.ɵɵelementEnd();
48
- i0.ɵɵelementStart(3, "div", 16)(4, "div");
49
- i0.ɵɵtext(5);
50
- i0.ɵɵelementEnd();
51
- i0.ɵɵelementStart(6, "span", 17);
52
- i0.ɵɵtext(7);
53
- i0.ɵɵelementEnd()();
54
- } if (rf & 2) {
55
- const item_r3 = ctx.$implicit;
56
- i0.ɵɵadvance();
57
- i0.ɵɵconditional(item_r3.text === "Ask Skip" ? 1 : 2);
58
- i0.ɵɵadvance(4);
59
- i0.ɵɵtextInterpolate(item_r3.text);
60
- i0.ɵɵadvance(2);
61
- i0.ɵɵtextInterpolate(item_r3.description);
62
- } }
63
- function NavigationComponent_kendo_drawer_container_3_For_12_Conditional_1_Template(rf, ctx) { if (rf & 1) {
64
- i0.ɵɵelement(0, "span", 18);
65
- } }
66
- function NavigationComponent_kendo_drawer_container_3_For_12_Conditional_2_Template(rf, ctx) { if (rf & 1) {
67
- i0.ɵɵelement(0, "span");
68
- } if (rf & 2) {
69
- const tab_r4 = i0.ɵɵnextContext().$implicit;
70
- i0.ɵɵclassMap(tab_r4.icon + " tab-icon");
71
- } }
72
- function NavigationComponent_kendo_drawer_container_3_For_12_Template(rf, ctx) { if (rf & 1) {
73
- i0.ɵɵelementStart(0, "mj-tab", 12);
74
- i0.ɵɵtemplate(1, NavigationComponent_kendo_drawer_container_3_For_12_Conditional_1_Template, 1, 0, "span", 18)(2, NavigationComponent_kendo_drawer_container_3_For_12_Conditional_2_Template, 1, 2, "span", 15);
75
- i0.ɵɵtext(3);
76
- i0.ɵɵelementEnd();
77
- } if (rf & 2) {
78
- const tab_r4 = ctx.$implicit;
79
- i0.ɵɵproperty("TabCloseable", true);
80
- i0.ɵɵadvance();
81
- i0.ɵɵconditional((tab_r4 == null ? null : tab_r4.contentLoading) ? 1 : (tab_r4 == null ? null : tab_r4.icon) ? 2 : -1);
82
- i0.ɵɵadvance(2);
83
- i0.ɵɵtextInterpolate1(" ", tab_r4.labelLoading ? "Loading..." : tab_r4.label, " ");
84
- } }
85
- function NavigationComponent_kendo_drawer_container_3_For_14_Template(rf, ctx) { if (rf & 1) {
86
- const _r5 = i0.ɵɵgetCurrentView();
87
- i0.ɵɵelementStart(0, "mj-tab-body")(1, "mj-resource", 19);
88
- i0.ɵɵlistener("ResourceRecordSaved", function NavigationComponent_kendo_drawer_container_3_For_14_Template_mj_resource_ResourceRecordSaved_1_listener($event) { const tab_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.HandleResourceRecordSaved(tab_r6, $event)); })("ContentLoadingStarted", function NavigationComponent_kendo_drawer_container_3_For_14_Template_mj_resource_ContentLoadingStarted_1_listener() { const tab_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setTabContentLoadingStatus(tab_r6, true)); })("ContentLoadingComplete", function NavigationComponent_kendo_drawer_container_3_For_14_Template_mj_resource_ContentLoadingComplete_1_listener() { const tab_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setTabContentLoadingStatus(tab_r6, false)); });
89
- i0.ɵɵelementEnd()();
90
- } if (rf & 2) {
91
- const tab_r6 = ctx.$implicit;
92
- const ɵ$index_52_r7 = ctx.$index;
93
- const ctx_r1 = i0.ɵɵnextContext(2);
94
- i0.ɵɵadvance();
95
- i0.ɵɵproperty("Data", tab_r6.data)("isVisible", ctx_r1.activeTabIndex - 1 === ɵ$index_52_r7);
96
- } }
97
- function NavigationComponent_kendo_drawer_container_3_Template(rf, ctx) { if (rf & 1) {
98
- const _r1 = i0.ɵɵgetCurrentView();
99
- i0.ɵɵelementStart(0, "kendo-drawer-container")(1, "kendo-drawer", 8, 1);
100
- i0.ɵɵlistener("select", function NavigationComponent_kendo_drawer_container_3_Template_kendo_drawer_select_1_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDrawerSelect($event)); });
101
- i0.ɵɵtemplate(3, NavigationComponent_kendo_drawer_container_3_ng_template_3_Template, 8, 3, "ng-template", 9);
102
- i0.ɵɵelementEnd();
103
- i0.ɵɵelementStart(4, "kendo-drawer-content", 10)(5, "mj-tabstrip", 11, 2);
104
- i0.ɵɵlistener("TabClosed", function NavigationComponent_kendo_drawer_container_3_Template_mj_tabstrip_TabClosed_5_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleTabClosed($event)); })("TabSelected", function NavigationComponent_kendo_drawer_container_3_Template_mj_tabstrip_TabSelected_5_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleTabSelected($event)); })("TabContextMenu", function NavigationComponent_kendo_drawer_container_3_Template_mj_tabstrip_TabContextMenu_5_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleTabContextMenu($event)); })("ResizeContainer", function NavigationComponent_kendo_drawer_container_3_Template_mj_tabstrip_ResizeContainer_5_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.sharedService.InvokeManualResize()); });
105
- i0.ɵɵelementStart(7, "mj-tab", 12);
106
- i0.ɵɵtext(8, " Home ");
107
- i0.ɵɵelementEnd();
108
- i0.ɵɵelementStart(9, "mj-tab-body");
109
- i0.ɵɵelement(10, "router-outlet");
110
- i0.ɵɵelementEnd();
111
- i0.ɵɵrepeaterCreate(11, NavigationComponent_kendo_drawer_container_3_For_12_Template, 4, 3, "mj-tab", 12, _forTrack0);
112
- i0.ɵɵrepeaterCreate(13, NavigationComponent_kendo_drawer_container_3_For_14_Template, 2, 2, "mj-tab-body", null, _forTrack0);
113
- i0.ɵɵelementEnd()()();
114
- } if (rf & 2) {
115
- const ctx_r1 = i0.ɵɵnextContext();
116
- i0.ɵɵadvance();
117
- i0.ɵɵproperty("items", ctx_r1.drawerItems)("mini", true)("animation", false)("autoCollapse", true);
118
- i0.ɵɵadvance(6);
119
- i0.ɵɵproperty("TabCloseable", false);
120
- i0.ɵɵadvance(4);
121
- i0.ɵɵrepeater(ctx_r1.tabs);
122
- i0.ɵɵadvance(2);
123
- i0.ɵɵrepeater(ctx_r1.tabs);
124
- } }
125
- function NavigationComponent_div_4_Template(rf, ctx) { if (rf & 1) {
126
- const _r8 = i0.ɵɵgetCurrentView();
127
- i0.ɵɵelementStart(0, "div", 20)(1, "div", 21);
128
- i0.ɵɵlistener("click", function NavigationComponent_div_4_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleContextMenuOption(1)); });
129
- i0.ɵɵtext(2, "Close All");
130
- i0.ɵɵelementEnd();
131
- i0.ɵɵelementStart(3, "div", 21);
132
- i0.ɵɵlistener("click", function NavigationComponent_div_4_Template_div_click_3_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleContextMenuOption(2)); });
133
- i0.ɵɵtext(4, "Close Others");
134
- i0.ɵɵelementEnd();
135
- i0.ɵɵelementStart(5, "div", 21);
136
- i0.ɵɵlistener("click", function NavigationComponent_div_4_Template_div_click_5_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleContextMenuOption(3)); });
137
- i0.ɵɵtext(6, "Close Tabs to the Right");
138
- i0.ɵɵelementEnd()();
139
- } if (rf & 2) {
140
- const ctx_r1 = i0.ɵɵnextContext();
141
- i0.ɵɵproperty("ngStyle", ctx_r1.contextMenuStyle);
142
- } }
143
- // Prevent tree-shaking of EntityCommunicationsEngineClient
144
- LoadEntityCommunicationsEngineClient();
145
- export class NavigationComponent {
146
- router;
147
- route;
148
- sharedService;
149
- location;
150
- renderer;
151
- titleService;
152
- cdr;
153
- applicationName;
154
- drawerItems = [{
155
- text: 'Loading...',
156
- icon: 'k-i-apps',
157
- }];
158
- mode = 'push';
159
- mini = true;
160
- viewsList = [];
161
- selectedDrawerItem = null;
162
- selectedApp = null;
163
- selectedEntity = null;
164
- selectedView = null;
165
- loading = true;
166
- loader = false;
167
- tabs = [];
168
- closedTabs = []; // should always be empty after using it
169
- tabQueryParams = {};
170
- workSpace = undefined;
171
- workSpaceItems = [];
172
- panelItems = [];
173
- showExpansionPanel = false;
174
- routeSub = null;
175
- isMobileScreen = false;
176
- resizeTimeout;
177
- drawer;
178
- mjTabStrip;
179
- drawerWrapper;
180
- container;
181
- onWindowResize() {
182
- clearTimeout(this.resizeTimeout);
183
- this.resizeTimeout = setTimeout(() => {
184
- this.checkViewportSize();
185
- }, 200); // Adjust the debounce time as needed
186
- }
187
- onClick() {
188
- this.contextMenuVisible = false;
189
- }
190
- contextMenuStyle = {};
191
- contextMenuVisible = false;
192
- // Inject the authentication service into your component through the constructor
193
- constructor(router, route, sharedService, location, renderer, titleService, cdr) {
194
- this.router = router;
195
- this.route = route;
196
- this.sharedService = sharedService;
197
- this.location = location;
198
- this.renderer = renderer;
199
- this.titleService = titleService;
200
- this.cdr = cdr;
201
- this.tabs = [];
202
- }
203
- _contextMenuSelectedTabIndex = -1;
204
- handleTabContextMenu(event) {
205
- event.mouseEvent.preventDefault();
206
- this._contextMenuSelectedTabIndex = event.index;
207
- const mouseX = event.mouseEvent.clientX;
208
- const mouseY = event.mouseEvent.clientY;
209
- this.contextMenuStyle = {
210
- top: mouseY + 'px',
211
- left: mouseX + 'px'
212
- };
213
- this.contextMenuVisible = true;
214
- }
215
- async handleContextMenuOption(option) {
216
- this.closedTabs = [];
217
- switch (option) {
218
- case 1:
219
- // Close All
220
- this.closedTabs = this.closedTabs.concat(this.tabs);
221
- this.tabs = [];
222
- break;
223
- case 2:
224
- // Close Others
225
- // the _contextMenuSelectedTabIndex is the index of the tab that was right-clicked on and it INCLUDES the home tab so we have to adjust it
226
- // keep just that item
227
- if (this._contextMenuSelectedTabIndex > 0) {
228
- this.closedTabs = this.tabs.filter((tab, index) => index !== this._contextMenuSelectedTabIndex - 1);
229
- this.tabs = [this.tabs[this._contextMenuSelectedTabIndex - 1]];
230
- }
231
- break;
232
- case 3:
233
- // Close Tabs to the Right
234
- const currentTabIndex = this._contextMenuSelectedTabIndex - 1; // because the HOME tab is not in the array so we have to offset by 1 here for our data structure
235
- this.closedTabs = this.tabs.slice(currentTabIndex + 1); // close everything to right
236
- this.tabs = this.tabs.slice(0, currentTabIndex + 1);
237
- break;
238
- default:
239
- // Handle other options if needed
240
- break;
241
- }
242
- this.contextMenuVisible = false;
243
- // CRITICAL: Force immediate change detection after tab array modifications
244
- // This ensures Angular immediately processes component destruction for closed tabs
245
- await this.waitForDomUpdate();
246
- const md = new Metadata();
247
- const transGroup = await md.CreateTransactionGroup();
248
- for (let i = 0; i < this.closedTabs.length; ++i) {
249
- const tab = this.closedTabs[i];
250
- await this.removeWorkspaceItem(tab, transGroup);
251
- }
252
- transGroup.Submit(); // INTENTIONALLY NOT USING AWAIT here - let's let the database updates for workspace edits happen in the background, no need to wait
253
- await this.waitForDomUpdate(); // make sure the DOM is updated before we do anything else so that the tab control knows about the changes from our data structure changes ABOVE
254
- if (this.activeTabIndex > this.tabs.length) // DO NOT add 1 here because in this case, the array boundary is the max for the tab control
255
- this.activeTabIndex = this.tabs.length; // don't subtract 1 here because the activeTabIndex is relative to the full set of tabs and the this.tabs array doesn't include the HOME tab
256
- else
257
- this.activeTabIndex = this.activeTabIndex; // this is a hack to force the tab control to update the selected tab
258
- if (this.activeTabIndex === 0) {
259
- // in this situation we have the home tab showing, so we need to update the URL path based on what's selected in the drawer
260
- let url = this.selectedDrawerItem ? this.selectedDrawerItem.path : '/home';
261
- this.router.navigate([url]);
262
- //this.location.go(url); // update the browser URL if needed
263
- this._mostRecentURL = url;
264
- }
265
- }
266
- checkViewportSize() {
267
- this.isMobileScreen = window.innerWidth <= 840;
268
- }
269
- ngAfterViewInit() {
270
- MJGlobal.Instance.GetEventListener(true) // true gets us replay of past events so we can "catch up" as needed
271
- .subscribe(event => {
272
- this.handleEvent(event, event.args);
273
- });
274
- this.route.queryParams.subscribe(params => {
275
- // what we want to do here is CACHE the params for the CURRENT tab so we have them
276
- // to throw back in the URL whenever the tab gets clicked on again in the future
277
- this.tabQueryParams['tab_' + this.activeTabIndex] = params;
278
- });
279
- }
280
- _loggedIn = false;
281
- _earlyEvents = [];
282
- async handleEvent(event, args) {
283
- // event handler
284
- switch (event.event) {
285
- case MJEventType.LoggedIn:
286
- await this.loadApp();
287
- await this.loadWorkspace();
288
- this._loggedIn = true;
289
- // check for early events and replay them now that we're logged in
290
- for (let i = 0; i < this._earlyEvents.length; ++i) {
291
- const e = this._earlyEvents[i];
292
- this.handleEvent(e.event, e.args); // recursve call to handle the event
293
- }
294
- this._earlyEvents.length = 0; // clear the array
295
- // resize everything after a short delay
296
- setTimeout(() => {
297
- this.sharedService.InvokeManualResize();
298
- }, 100);
299
- this.checkForBaseURL();
300
- break;
301
- case MJEventType.ComponentEvent:
302
- if (!this._loggedIn) {
303
- // we're not logged in yet, so queue up the event to be handled later
304
- this._earlyEvents.push({ event, args });
305
- }
306
- else {
307
- // we're logged in so go ahead and handle normally
308
- switch (event.eventCode) {
309
- case EventCodes.ViewNotifications:
310
- this.setActiveTabToHome();
311
- break;
312
- case EventCodes.ViewCreated:
313
- case EventCodes.AddDashboard:
314
- case EventCodes.AddReport:
315
- case EventCodes.AddQuery:
316
- case EventCodes.EntityRecordClicked:
317
- case EventCodes.ViewClicked:
318
- case EventCodes.ViewClicked:
319
- case EventCodes.RunSearch:
320
- case EventCodes.ListCreated:
321
- case EventCodes.ListClicked:
322
- // another component requested that we add something to our tab structure
323
- this.AddOrSelectTab(event.args);
324
- break;
325
- case EventCodes.CloseCurrentTab:
326
- if (this.mjTabStrip && this.activeTabIndex > 0) {
327
- this.mjTabStrip.CloseTab(this.activeTabIndex);
328
- }
329
- else {
330
- LogError("no active tab to close or tabstrip not available");
331
- }
332
- break;
333
- default:
334
- break;
335
- }
336
- }
337
- break;
338
- default:
339
- break;
340
- }
341
- }
342
- gotFirstNav = false;
343
- ngOnInit() {
344
- this.checkViewportSize();
345
- // Subscribe to route changes
346
- this.routeSub = this.router.events.pipe().subscribe((args) => {
347
- if (args instanceof NavigationEnd || args instanceof PopStateEvent) {
348
- const trigger = args.navigationTrigger;
349
- switch (trigger) {
350
- case 'imperative':
351
- // this is a programmatic navigation, so we don't want to do anything here
352
- break;
353
- case 'popstate':
354
- // this is a browser back/forward navigation, so we want to do something here
355
- // when the route changes and it maps to one of our drawer items, select it
356
- this.NavigateFromUrl();
357
- break;
358
- default:
359
- // this is a click on a link, so we want to do something here
360
- // when the route changes and it maps to one of our drawer items, select it
361
- this.NavigateFromUrl();
362
- break;
363
- }
364
- }
365
- else if (args instanceof NavigationSkipped) {
366
- // check to see if the route in args is truly the same as the this.route
367
- // if so, then we're navigating to the same route and we don't want to do anything
368
- // if not, then we're navigating to a different route and we want to do something
369
- if (this._mostRecentURL.trim().toLowerCase() != args.url.trim().toLowerCase()) {
370
- this.NavigateFromUrl();
371
- }
372
- }
373
- });
374
- }
375
- _mostRecentURL = '';
376
- _mostRecentHomeURL = ''; // used only when we're on the home tab so we can remember the full URL for the HOME tab when we come back to it from another tab
377
- async NavigateFromUrl() {
378
- let url = this.router.url.trim().toLowerCase();
379
- if (url === '/') {
380
- this._mostRecentURL = '/home';
381
- this.router.navigate(['/home']); // redirect to /home
382
- this.gotFirstNav = true;
383
- }
384
- else {
385
- this._mostRecentURL = this.router.url;
386
- // see if this matches a drawer item or not
387
- const item = this.drawerItems.find(i => url.toLowerCase().trim().startsWith(i.path?.toLowerCase().trim()));
388
- if (item) {
389
- this.selectDrawerItem(this.drawerItems.indexOf(item));
390
- this.gotFirstNav = true;
391
- }
392
- }
393
- if (this.activeTabIndex > 0) {
394
- // check to see if there are query params on the url and if so, stash em in the tabQueryParams array so we can restore the full set of query params later if we
395
- // come back to this tab
396
- const urlParts = this.router.url.split('?');
397
- if (urlParts.length > 1) {
398
- // we have query params, so stash them
399
- const params = new URLSearchParams(urlParts[1]);
400
- const queryParams = {};
401
- for (const [key, value] of params.entries()) {
402
- queryParams[key] = value;
403
- }
404
- this.tabQueryParams['tab_' + this.activeTabIndex] = queryParams;
405
- }
406
- }
407
- if (url.toLowerCase().includes('/app') && this.activeTabIndex > 0) {
408
- this.setActiveTabToHome();
409
- }
410
- // finally, if we are on the home tab, update the _mostRecentHomeURL property to the current URL
411
- if (this.activeTabIndex === 0) {
412
- // only update the most recent home URL if we have a url that starts with something that is in the drawer
413
- // or /app
414
- if (!url.startsWith('/home') && (url.startsWith("/app") || this.drawerItems.find((item) => url.startsWith(item.path))))
415
- this._mostRecentHomeURL = url;
416
- }
417
- }
418
- selectDrawerItem(index) {
419
- this.selectedDrawerItem = this.drawerItems[index];
420
- this.showExpansionPanel = index === 2;
421
- // Get the <ul> element that contains the <li> elements
422
- const ulElement = this.drawerWrapper.nativeElement.querySelector('ul');
423
- if (ulElement) {
424
- // Get the <li> element at the specified index
425
- const liElement = ulElement.children[index];
426
- // add the k-selected class to the <li> element
427
- this.renderer.addClass(liElement, 'k-selected');
428
- // and remove k-selected from all other <li> within the <ul>
429
- for (let i = 0; i < ulElement.children.length; ++i) {
430
- if (i !== index)
431
- this.renderer.removeClass(ulElement.children[i], 'k-selected');
432
- }
433
- }
434
- // make sure that the first tab is selected since this is showing stuff in the Home/Nav tab
435
- this.setActiveTabToHome();
436
- }
437
- setActiveTabToHome() {
438
- this.innerSelectTab(null);
439
- }
440
- innerSelectTab(tab) {
441
- // get index from the tabs array
442
- const index = tab ? this.tabs.indexOf(tab) + 1 : 0; // add one because the HOME tab is not in the array so we have to offset by 1 here for our data structure
443
- this.sharedService.InvokeManualResize();
444
- if (index === 0) {
445
- // this means the HOME tab
446
- let url = this.selectedDrawerItem ? this.selectedDrawerItem.path : '/home';
447
- if (this.selectedDrawerItem !== null && this.selectedDrawerItem !== undefined)
448
- url = this.selectedDrawerItem.path;
449
- if (!this._mostRecentURL.startsWith(url)) {
450
- // we only do this IF the most recent URL does NOT start with the selectedDrawerItem path.
451
- // The reason is because there could be SUB-PATHS within the _mostRecentURL that are not part of the selectedDrawerItem path
452
- // plus this is redundant if we're already on the selectedDrawerItem path
453
- if (this._mostRecentHomeURL.startsWith(url) ||
454
- (url === '/data' && this._mostRecentHomeURL.startsWith('/app')) || // special case for the /data drawer item, it leads to resources that start with /app after the first level, so we compare that too
455
- (url === '/home' && this._mostRecentHomeURL.startsWith('/app')) // special case for the /data drawer item, it leads to resources that start with /app after the first level, so we compare that too
456
- ) {
457
- // we use the most recent HomeURL if it starts with the selectedDrawerItem path
458
- // this is because we want to preserve the query params that were on the URL when we first navigated to the home tab
459
- url = this._mostRecentHomeURL;
460
- }
461
- this.router.navigate([url]);
462
- this.setAppTitle();
463
- this._mostRecentURL = url;
464
- }
465
- }
466
- else {
467
- const tab = this.tabs[index - 1];
468
- if (tab) {
469
- this.setAppTitle(tab.label);
470
- const data = tab.data;
471
- this.updateBrowserURL(tab, data);
472
- }
473
- }
474
- }
475
- checkForBaseURL() {
476
- setTimeout(() => {
477
- // this is a hack to get the first navigation to work correctly when the route is to the / base URL that doesn't seem to trigger the rest of our code like all other routes
478
- if (!this.gotFirstNav) {
479
- this.gotFirstNav = true;
480
- this.NavigateFromUrl();
481
- }
482
- }, 10);
483
- }
484
- /**
485
- * This method will load the user's workspace and all the workspace items that are part of the workspace from the database.
486
- */
487
- async loadWorkspace() {
488
- const md = new Metadata();
489
- const rv = new RunView();
490
- const workspaceParams = {
491
- EntityName: "Workspaces",
492
- ExtraFilter: `UserID='${md.CurrentUser.ID}'`,
493
- OrderBy: "__mj_UpdatedAt DESC", // by default get the workspace that was most recently updated
494
- ResultType: "entity_object" /*we want entity objects back so that we can modify them as needed*/
495
- };
496
- const workspaces = await rv.RunView(workspaceParams);
497
- if (workspaces.Success) {
498
- if (workspaces.Results.length) {
499
- this.workSpace = workspaces.Results[0]; // by default get the first one, and since we are sorting by __mj_UpdatedAt DESC above, will be most recently modified one. Future feature for multi-workspace support we'll have to adjust this
500
- }
501
- else {
502
- // no matching record found, so create a new one
503
- this.workSpace = await md.GetEntityObject('Workspaces');
504
- this.workSpace.NewRecord();
505
- this.workSpace.Name = `${md.CurrentUser.Name || md.CurrentUser.ID}'s Workspace`;
506
- this.workSpace.UserID = md.CurrentUser.ID;
507
- await this.workSpace.Save();
508
- }
509
- if (!this.workSpace)
510
- throw new Error('Error loading workspace');
511
- if (this.workSpace.IsSaved) {
512
- const workspaceItemParams = {
513
- EntityName: "Workspace Items",
514
- ExtraFilter: `WorkspaceID='${this.workSpace.ID}'`,
515
- OrderBy: "Sequence ASC", // get them in order
516
- ResultType: "entity_object" /*we want entity objects back so that we can modify them as needed*/
517
- };
518
- const workspaceItems = await rv.RunView(workspaceItemParams);
519
- if (workspaceItems.Success) {
520
- this.workSpaceItems = workspaceItems.Results;
521
- await this.LoadWorkspaceItems();
522
- }
523
- }
524
- }
525
- else
526
- throw new Error('Error loading workspace');
527
- }
528
- /**
529
- * This method will load all the workspace items that are part of the workspace currently set in the workSpace member variable
530
- */
531
- async LoadWorkspaceItems() {
532
- const md = new Metadata();
533
- this.tabs = []; // first clear out the tabs - this is often already the state but in case this is a full refresh, make sure we do this.
534
- for (let item of this.workSpaceItems) {
535
- const itemData = item.Configuration ? JSON.parse(item.Configuration) : {};
536
- const resourceData = new ResourceData({
537
- ID: item.ID,
538
- Name: item.Name,
539
- ResourceTypeID: item.ResourceTypeID,
540
- ResourceRecordID: item.ResourceRecordID,
541
- Configuration: itemData,
542
- });
543
- const newTab = {
544
- id: item.ID,
545
- labelLoading: true,
546
- contentLoading: false,
547
- data: resourceData,
548
- workspaceItem: item, // provide the entity object here so we can modify it later if needed
549
- icon: resourceData.ResourceIcon
550
- };
551
- // now add to data structure
552
- await this.internalAddTab(newTab);
553
- setTimeout(async () => {
554
- // non-blocking, load the resource names dynamically as this requires additional DB lookups
555
- newTab.label = await this.GetWorkspaceItemDisplayName(resourceData);
556
- const resourceDynamicIcon = await this.GetWorkspaceItemIconClass(resourceData);
557
- newTab.icon = resourceDynamicIcon ? resourceDynamicIcon : newTab.icon;
558
- newTab.labelLoading = false;
559
- if (newTab === this.tabs[this.activeTabIndex - 1]) // subtract one since the activeTabIndex is relative to the full set of tabs and the this.tabs array doesn't include the HOME tab
560
- this.setAppTitle(newTab.label);
561
- }, 10);
562
- }
563
- this.mjTabStrip.SelectedTabIndex = 0;
564
- }
565
- setAppTitle(title = '') {
566
- if (title === '')
567
- this.titleService.setTitle(this.applicationName);
568
- else
569
- this.titleService.setTitle(title + ' (' + this.applicationName + ')');
570
- }
571
- /**
572
- * This method is responsible for searching for a matching tab in the existing tab structure of the loaded workspace. It returns either a Tab object or null if one isn't found that matches the ResourceData provided.
573
- * @param data
574
- * @returns
575
- */
576
- findExistingTab(data) {
577
- let existingTab;
578
- if (data.ResourceType.trim().toLowerCase() === 'search results') {
579
- // we have a different matching logic for search results because we want to match on the search input as well as the entity
580
- existingTab = this.tabs.find(t => t.data.ResourceTypeID === data.ResourceTypeID &&
581
- t.data.Configuration.Entity === data.Configuration.Entity &&
582
- t.data.Configuration.SearchInput === data.Configuration.SearchInput);
583
- }
584
- else if (data.ResourceType.trim().toLowerCase() === 'user views') {
585
- // a viwe can be either saved (where we have a view id) or dyanmic (where we have an entity name, and optionally, an extra filter)
586
- if (data.ResourceRecordID) {
587
- // saved view
588
- existingTab = this.tabs.find(t => t.data.ResourceTypeID === data.ResourceTypeID &&
589
- t.data.ResourceRecordID === data.ResourceRecordID &&
590
- data.ResourceRecordID !== null &&
591
- data.ResourceRecordID !== undefined // make sure that we don't match on null/undefined ResourceRecordID's - these should always be NEW tabs
592
- );
593
- }
594
- else {
595
- // dynamic view, compare entity name and if we have extra filter use that for comparison too
596
- existingTab = this.tabs.find(t => t.data.ResourceTypeID === data.ResourceTypeID &&
597
- t.data.Configuration.Entity === data.Configuration.Entity &&
598
- t.data.Configuration.ExtraFilter === data.Configuration.ExtraFilter);
599
- }
600
- }
601
- else {
602
- existingTab = this.tabs.find(t => {
603
- if (t.data.ResourceTypeID === data.ResourceTypeID &&
604
- t.data.ResourceRecordID === data.ResourceRecordID) {
605
- // we now have to do one more check, we have to make sure that all of the values within the Configuration object match as well
606
- let bMatch = true;
607
- // ignore keys that start with an underscore or are the NewRecordValues key
608
- const keys = Object.keys(data.Configuration).filter(k => !k.startsWith('_') && k.trim().toLowerCase() !== 'newrecordvalues');
609
- for (const key of keys) {
610
- if (data.Configuration[key] !== t.data.Configuration[key]) {
611
- bMatch = false;
612
- break;
613
- }
614
- }
615
- return bMatch;
616
- }
617
- else
618
- return false;
619
- });
620
- }
621
- return existingTab;
622
- }
623
- /**
624
- * This utility method is used to either Add a tab if a matching tab for the given data parameter isn't found, or to select the existing tab if it already exists.
625
- * @param data
626
- */
627
- async AddOrSelectTab(data) {
628
- const t = this.tabs;
629
- this.loader = true;
630
- const existingTab = this.findExistingTab(data);
631
- if (existingTab) {
632
- // merge the data that we are provided with in terms of its raw query params with the existing tab
633
- // override existing values in the data.Configuration.___rawQueryParams from keys in the data.Configuration.___rawQueryParams
634
- existingTab.data.Configuration.___rawQueryParams = { ...existingTab.data.Configuration.___rawQueryParams, ...data.Configuration.___rawQueryParams };
635
- const index = this.tabs.indexOf(existingTab);
636
- // next, before we set the active tab, we need to merge the query params that we have for this tab with the query params that we have for the tab that we're about to select
637
- // when the app first loads there won't be any query params for the tabs, but as we navigate around and the tabs get selected, we'll cache the query params for each tab
638
- const tqp = this.tabQueryParams['tab_' + (index + 1)];
639
- if (tqp)
640
- this.tabQueryParams['tab_' + (index + 1)] = { ...tqp, ...existingTab.data.Configuration.___rawQueryParams };
641
- else
642
- this.tabQueryParams['tab_' + (index + 1)] = existingTab.data.Configuration.___rawQueryParams;
643
- // add one because the HOME tab is not in the tabs array but it IS part of our tab structure
644
- this.activeTabIndex = index + 1;
645
- this.scrollIntoView();
646
- if (existingTab.label)
647
- this.setAppTitle(existingTab.label);
648
- else
649
- this.setAppTitle();
650
- this.loader = false;
651
- }
652
- else {
653
- const newTab = {
654
- id: "", // initially blank but will be changed to the WorkspaceItem ID once we save it
655
- data: data,
656
- labelLoading: true,
657
- contentLoading: false,
658
- workspaceItem: null,
659
- icon: data.ResourceIcon,
660
- };
661
- // save it before we push to the tabs colleciton because we want the WorkspaceItem ID to be populated in the tab.id before we initialize the new tab by adding it to the this.tabs array
662
- await this.SaveSingleWorkspaceItem(newTab);
663
- // now add to data structure
664
- await this.internalAddTab(newTab);
665
- // select the new tab
666
- this.activeTabIndex = this.tabs.length; // this is intentionally past array boundary because ActiveTabIndex includes the Home tab that is not part of the tabs array
667
- this.sharedService.InvokeManualResize();
668
- this.scrollIntoView();
669
- setTimeout(async () => {
670
- // non-blocking this way
671
- newTab.label = await this.GetWorkspaceItemDisplayName(data); // do this after we fire up the loading so that we don't block anything
672
- const resourceDynamicIcon = await this.GetWorkspaceItemIconClass(data);
673
- newTab.icon = resourceDynamicIcon ? resourceDynamicIcon : newTab.icon;
674
- this.setAppTitle(newTab.label);
675
- newTab.labelLoading = false;
676
- this.loader = false;
677
- }, 10);
678
- }
679
- }
680
- async internalAddTab(newTab) {
681
- // add the tab to the tabs collection
682
- this.tabs.push(newTab);
683
- // Manually trigger change detection and wait for DOM updates
684
- await this.waitForDomUpdate();
685
- }
686
- waitForDomUpdate() {
687
- return new Promise(resolve => {
688
- this.cdr.detectChanges(); // Manually trigger change detection
689
- setTimeout(() => { resolve(); }, 0); // Resolve on the next tick to ensure changes are reflected in the DOM
690
- });
691
- }
692
- updateBrowserURL(tab, data) {
693
- // update the URL to reflect the current tab
694
- // FIRST, construct the base URL based on the resource type
695
- const rt = this.sharedService.ResourceTypeByID(data.ResourceTypeID);
696
- let url = '/resource';
697
- switch (rt?.Name.toLowerCase().trim()) {
698
- case 'user views':
699
- if (data.ResourceRecordID) {
700
- url += `/view/${data.ResourceRecordID}`;
701
- }
702
- else if (data.Configuration?.Entity) {
703
- // we don't have a view id. This can occur when we're referring to a dyanmic view where our data.Configuration.Entity is set and data.Configuration.ExtraFilter is set
704
- // so we need to construct a URL that will load up the dynamic view
705
- url += `/view/0?Entity=${data.Configuration.Entity}&ExtraFilter=${data.Configuration.ExtraFilter}`;
706
- }
707
- else {
708
- // we don't have a view ID and we also don't have an entity name, so this is an error condition
709
- LogError(`Invalid view configuration. No view ID or entity name specified.`);
710
- this.sharedService.CreateSimpleNotification(`Invalid view configuration. No view ID or entity name specified.`, "error", 5000);
711
- return;
712
- }
713
- break;
714
- case 'dashboards':
715
- url += `/dashboard/${data.ResourceRecordID}`;
716
- break;
717
- case 'reports':
718
- url += `/report/${data.ResourceRecordID}`;
719
- break;
720
- case 'queries':
721
- url += `/query/${data.ResourceRecordID}`;
722
- break;
723
- case 'records':
724
- const recIDAsString = data.ResourceRecordID !== null && data.ResourceRecordID !== undefined ? (typeof data.ResourceRecordID === "string" ? data.ResourceRecordID : data.ResourceRecordID.toString()) : "";
725
- url += `/record/${recIDAsString.trim()}?Entity=${data.Configuration.Entity}`;
726
- if (data.Configuration.NewRecordValues) {
727
- url += `&NewRecordValues=${data.Configuration.NewRecordValues}`;
728
- }
729
- break;
730
- case 'search results':
731
- url += `/search/${data.Configuration.SearchInput}?Entity=${data.Configuration.Entity}`;
732
- break;
733
- case 'settings':
734
- url += `/settings`;
735
- break;
736
- case 'notifications':
737
- url += `/notifications`;
738
- break;
739
- case 'lists':
740
- url += `/list/${data.ResourceRecordID}`;
741
- break;
742
- }
743
- // SECOND, we need to, in some cases, append query params that the TAB had created, we don't know what those are, they could be anything. In the AfterViewInit() code above we cache
744
- // these whenever they change for each tab.
745
- // Split the URL into the path and existing query params
746
- let [path, existingQuery] = url.split('?');
747
- const currentURL = window.location.href;
748
- const urlObj = new URL(currentURL);
749
- //Remove Entity as existingQuery will have it
750
- urlObj.searchParams.delete('Entity');
751
- for (const [key, value] of urlObj.searchParams.entries()) {
752
- existingQuery = existingQuery ? existingQuery + `&${key}=${value}` : `${key}=${value}`;
753
- }
754
- // Create a URLSearchParams object from the existing query params
755
- const queryParams = new URLSearchParams(existingQuery);
756
- const tabIndex = this.tabs.indexOf(tab) + 1; // we add 1 Because the HOME tab is not in the array so we have to offset by 1 here for our data structure
757
- let cachedQueryParams = this.tabQueryParams['tab_' + tabIndex];
758
- if (!cachedQueryParams) {
759
- // there is a case when we are first loading and cached query params might have been stuffed into a 'tab_-1' key because at the time activeTabIndex wasn't yet known. So we need to check for that
760
- cachedQueryParams = this.tabQueryParams['tab_-1'];
761
- if (cachedQueryParams) {
762
- delete this.tabQueryParams['tab_-1']; // remove it from the -1 key
763
- const tqp = this.tabQueryParams['tab_' + tabIndex];
764
- if (tqp)
765
- this.tabQueryParams['tab_' + tabIndex] = { ...tqp, ...cachedQueryParams }; // merge it with the existing key if it exists
766
- else
767
- this.tabQueryParams['tab_' + tabIndex] = { ...cachedQueryParams }; // stuff it into the correct key
768
- }
769
- }
770
- if (cachedQueryParams) {
771
- // Merge cached query params if they don't already exist in the URL
772
- const keys = Object.keys(cachedQueryParams);
773
- for (const key of keys) {
774
- if (!queryParams.has(key)) {
775
- queryParams.append(key, cachedQueryParams[key]);
776
- }
777
- }
778
- }
779
- // Construct the new URL with merged query params
780
- const params = queryParams.toString();
781
- const newUrl = `${path}${params && params.length > 0 ? '?' + queryParams.toString() : ''}`;
782
- // Update the most recent URL
783
- this._mostRecentURL = newUrl;
784
- // Update the browser URL without triggering Angular navigation
785
- // this.location.go(newUrl);
786
- this.router.navigateByUrl(newUrl); //, { skipLocationChange: true });
787
- // Update the app title
788
- this.setAppTitle(tab.label);
789
- }
790
- scrollIntoView() {
791
- if (this.mjTabStrip)
792
- this.mjTabStrip.scrollIntoView(this.activeTabIndex);
793
- }
794
- async GetWorkspaceItemDisplayName(data) {
795
- const resourceReg = MJGlobal.Instance.ClassFactory.GetRegistration(BaseResourceComponent, data.ResourceType);
796
- if (resourceReg) {
797
- const resource = new resourceReg.SubClass();
798
- return await resource.GetResourceDisplayName(data);
799
- }
800
- else {
801
- return `Workspace Item ${data.ID}`;
802
- }
803
- }
804
- async GetWorkspaceItemIconClass(data) {
805
- const resourceReg = MJGlobal.Instance.ClassFactory.GetRegistration(BaseResourceComponent, data.ResourceType);
806
- if (resourceReg) {
807
- const resource = new resourceReg.SubClass();
808
- return await resource.GetResourceIconClass(data);
809
- }
810
- else {
811
- return '';
812
- }
813
- }
814
- /**
815
- * Saves the workspace to the database.
816
- * @returns
817
- */
818
- async SaveWorkspace() {
819
- let bSuccess = true;
820
- for (let i = 0; i < this.tabs.length; ++i) {
821
- const tab = this.tabs[i];
822
- bSuccess = await this.SaveSingleWorkspaceItem(tab) && bSuccess;
823
- }
824
- return bSuccess;
825
- }
826
- async HandleResourceRecordSaved(tab, resourceRecord) {
827
- const oldId = tab.data.ResourceRecordID;
828
- tab.data.ResourceRecordID = resourceRecord.PrimaryKey.ToURLSegment();
829
- // we need to update the label in case the "Name" of the record changed, or if it was new and no longer is new
830
- tab.label = await this.GetWorkspaceItemDisplayName(tab.data);
831
- const resourceDynamicIcon = await this.GetWorkspaceItemIconClass(tab.data);
832
- tab.icon = resourceDynamicIcon ? resourceDynamicIcon : tab.icon;
833
- // now check to see if the old id and the new ID are any different
834
- // check for tab names that start with New as well...
835
- // and if so we need to replace the state in the URL for Angular so that we don't have a New Record situation in the URL but have the actual ID now
836
- // if (oldId !== tab.data.ResourceRecordID || tab.label?.toLowerCase().trim().startsWith('new') ) {
837
- this.updateBrowserURL(tab, tab.data);
838
- // }
839
- return await this.SaveSingleWorkspaceItem(tab);
840
- }
841
- /**
842
- * Saves a single workspace item to the database.
843
- * @param tab
844
- * @returns
845
- */
846
- async SaveSingleWorkspaceItem(tab) {
847
- try {
848
- if (!this.workSpace)
849
- throw new Error('No workspace loaded');
850
- let index = this.tabs.indexOf(tab);
851
- if (index < 0)
852
- index = this.tabs.length; // this situation occurs when the tab hasn't yet been added to the tabs collection so the index will be = the length of the tabs collection
853
- const md = new Metadata();
854
- let wsItem;
855
- if (!tab.workspaceItem) {
856
- wsItem = await md.GetEntityObject('Workspace Items');
857
- if (tab.data.ID && tab.data.ID.length > 0)
858
- await wsItem.Load(tab.data.ID);
859
- else {
860
- wsItem.NewRecord();
861
- wsItem.Name = tab.data.Name ? tab.data.Name : tab.data.ResourceType + ' Record:' + tab.data.ResourceRecordID;
862
- wsItem.WorkspaceID = this.workSpace.ID;
863
- wsItem.ResourceTypeID = tab.data?.ResourceTypeID;
864
- }
865
- tab.workspaceItem = wsItem;
866
- }
867
- else {
868
- wsItem = tab.workspaceItem;
869
- }
870
- wsItem.ResourceRecordID = tab.data.ResourceRecordID.toString();
871
- wsItem.Sequence = index;
872
- wsItem.Configuration = JSON.stringify(tab.data.Configuration); // JSON.stringify({ Entity: tab.data.Entity });
873
- const result = await wsItem.Save();
874
- if (!result) {
875
- // do a console error and display a simple notification
876
- LogError(`Error saving workspace item ${wsItem.Name} to the database. ${wsItem.LatestResult.Message || wsItem.LatestResult.Error || wsItem.LatestResult.Errors?.join('\n')}`);
877
- MJNotificationService.Instance.CreateSimpleNotification(`Error saving workspace item ${wsItem.Name} to the database. ${wsItem.LatestResult.Message}`, 'error', 5000);
878
- return false;
879
- }
880
- tab.id = wsItem.ID;
881
- return result;
882
- }
883
- catch (err) {
884
- LogError(err);
885
- return false;
886
- }
887
- }
888
- setTabContentLoadingStatus(tab, bLoading) {
889
- tab.contentLoading = bLoading;
890
- this.cdr.detectChanges(); // Manually trigger change detection
891
- }
892
- async handleTabClosed(event) {
893
- // get our tab data structure item based on the index that we get in the event
894
- if (event.index !== null && event.index >= 0 && event.index <= this.tabs.length) {
895
- const tab = this.tabs[event.index - 1]; // subtract 1 because the event index includes the home tab and our data structure does not
896
- await this.closeTab(tab, event.newTabIndex);
897
- }
898
- event.done(); // let the tab control know that we're done handling the event
899
- }
900
- handleTabSelected(event) {
901
- if (event.index !== null && event.index >= 0 && event.index <= this.tabs.length) {
902
- if (event.index > 0) {
903
- const tab = this.tabs[event.index - 1]; // subtract 1 because the event index includes the home tab and our data structure does not
904
- this.innerSelectTab(tab);
905
- }
906
- else
907
- this.innerSelectTab(null); // home
908
- }
909
- }
910
- async closeTab(tab, newTabIndex) {
911
- const tabIndex = this.tabs.indexOf(tab);
912
- if (tabIndex >= 0) {
913
- // INTENTIONAL - do not use await here, we want to let the database updates happen in the background
914
- this.removeWorkspaceItem(this.tabs[tabIndex], null /*no transaction group*/);
915
- //await this.waitForDomUpdate(); // make sure dom is up to date
916
- // now, check to see how many tabs we have left and if we have none, then we need to select the HOME tab
917
- if (this.tabs.length > 0) {
918
- if (newTabIndex === 0) {
919
- // home tab
920
- this.innerSelectTab(null); // null param means home tab
921
- }
922
- else {
923
- // not home tab
924
- const tab = this.tabs[newTabIndex - 1]; // remove 1 because the newTabIndex includes the HOME tab and our data structure does not
925
- this.updateBrowserURL(tab, tab?.data);
926
- }
927
- }
928
- else {
929
- this.innerSelectTab(null); // null param means home tab
930
- }
931
- }
932
- }
933
- async removeWorkspaceItem(tab, transGroup) {
934
- // remove the tab from the tabs collection
935
- const index = this.tabs.indexOf(tab);
936
- if (index >= 0) {
937
- this.tabs.splice(index, 1);
938
- // CRITICAL: Force immediate change detection to trigger component destruction
939
- // This ensures Angular processes the @for removal and calls ngOnDestroy on child components
940
- await this.waitForDomUpdate();
941
- }
942
- if (!tab.workspaceItem && tab.id && tab.id.length > 0) {
943
- // we lazy load the workspaceItem entity objects, so we load it here so we can delete it below, but only when it wasn't already loaded
944
- const md = new Metadata();
945
- tab.workspaceItem = await md.GetEntityObject('Workspace Items');
946
- await tab.workspaceItem.Load(tab.id);
947
- }
948
- if (tab.workspaceItem) {
949
- const entity = tab.workspaceItem;
950
- if (!transGroup) {
951
- if (!await entity.Delete()) {
952
- // error deleting the workspace item, alert the user
953
- this.sharedService.CreateSimpleNotification('Error deleting workspace item ' + tab.workspaceItem.Name + ' from the database. Please contact your system administrator.', 'error', 5000);
954
- }
955
- }
956
- else {
957
- entity.TransactionGroup = transGroup;
958
- await entity.Delete();
959
- }
960
- }
961
- }
962
- getActiveTabId() {
963
- if (this.activeTabIndex === 0) {
964
- return null;
965
- }
966
- else // subtract 1 from the activeTabIndex if it is not the first tab since our data structure is for tabs 1 to n
967
- return this.tabs[this.activeTabIndex - 1]?.id;
968
- }
969
- isTabActive(tabId) {
970
- return this.getActiveTabId() === tabId;
971
- }
972
- ngOnDestroy() {
973
- // Clean up the subscription when the component is destroyed
974
- clearTimeout(this.resizeTimeout);
975
- if (this.routeSub)
976
- this.routeSub.unsubscribe();
977
- window.removeEventListener('resize', () => { });
978
- }
979
- onDrawerSelect(ev) {
980
- this.selectedDrawerItem = ev.item;
981
- this.router.navigate([ev.item.path]);
982
- this._mostRecentURL = ev.item.path;
983
- // make sure that the first tab is selected since this is showing stuff in the Home/Nav tab
984
- if (this.activeTabIndex !== 0) {
985
- this.activeTabIndex = 0;
986
- }
987
- this.setAppTitle(ev.item.text);
988
- }
989
- get activeTabIndex() {
990
- if (this.mjTabStrip)
991
- return this.mjTabStrip.SelectedTabIndex;
992
- else
993
- return -1;
994
- }
995
- set activeTabIndex(index) {
996
- if (this.mjTabStrip)
997
- this.mjTabStrip.SelectedTabIndex = index;
998
- }
999
- getEntityItemFromViewItem(viewItem) {
1000
- for (let item of this.drawerItems) {
1001
- if (item.id === viewItem.parentId) {
1002
- // got the parent, this is the entity
1003
- return item;
1004
- }
1005
- }
1006
- return null;
1007
- }
1008
- getAppItemFromViewItem(viewItem) {
1009
- let entityItem = this.getEntityItemFromViewItem(viewItem), appItem = null;
1010
- if (entityItem)
1011
- for (let item of this.drawerItems) {
1012
- if (item.id == entityItem.parentId) {
1013
- // got the parent, this is the app
1014
- appItem = item;
1015
- break;
1016
- }
1017
- }
1018
- return appItem;
1019
- }
1020
- async loadApp() {
1021
- //setting the panelItems here because by this point
1022
- //the provider class is set within the MetaData class
1023
- //and the applications property is populated
1024
- const md = new Metadata();
1025
- const applications = md.Applications;
1026
- this.panelItems = applications.map((app) => {
1027
- let item = new TreeItem(app, ItemType.Application);
1028
- item.ChildItems = app.ApplicationEntities.map((entity) => {
1029
- let childItem = new TreeItem(entity, ItemType.Entity);
1030
- childItem.Name = entity.Entity;
1031
- childItem.ChildItems.push(new TreeItem({ Name: 'Stub Node' }, ItemType.StubData));
1032
- return childItem;
1033
- });
1034
- return item;
1035
- });
1036
- await TemplateEngineBase.Instance.Config(false);
1037
- await CommunicationEngineBase.Instance.Config(false);
1038
- await EntityCommunicationsEngineClient.Instance.Config(false);
1039
- await this.LoadDrawer();
1040
- this.setDrawerConfig();
1041
- window.addEventListener('resize', () => {
1042
- this.setDrawerConfig();
1043
- });
1044
- }
1045
- async LoadDrawer() {
1046
- const md = new Metadata();
1047
- //make sure SharedService_resourceTypes is populated first
1048
- await SharedService.RefreshData(true);
1049
- this.drawerItems.length = 0; // clear the array
1050
- const items = md.VisibleExplorerNavigationItems.filter(item => item.ShowInNavigationDrawer);
1051
- items.forEach(item => {
1052
- const drawerItem = {
1053
- id: item.ID,
1054
- selected: false,
1055
- text: item.Name,
1056
- path: item.Route,
1057
- icon: item.IconCSSClass
1058
- };
1059
- this.drawerItems.push(drawerItem);
1060
- });
1061
- this.loading = false;
1062
- }
1063
- async loadHome(md) {
1064
- const drawerItem = {
1065
- id: 'Home',
1066
- selected: true,
1067
- text: 'Home',
1068
- path: '/home',
1069
- icon: "fa-solid fa-house"
1070
- };
1071
- this.drawerItems.push(drawerItem);
1072
- }
1073
- async loadSettings(md) {
1074
- const drawerItem = {
1075
- id: 'Settings',
1076
- selected: false,
1077
- text: 'Settings',
1078
- path: '/settings',
1079
- icon: "fa-solid fa-gear"
1080
- };
1081
- this.drawerItems.push(drawerItem);
1082
- }
1083
- async loadLists() {
1084
- const drawerItem = {
1085
- id: 'Lists',
1086
- selected: false,
1087
- text: 'Lists',
1088
- path: '/lists',
1089
- icon: "fa-solid fa-list"
1090
- };
1091
- this.drawerItems.push(drawerItem);
1092
- }
1093
- async loadFiles() {
1094
- const rv = new RunView();
1095
- const viewResults = await rv.RunView({
1096
- EntityName: 'File Storage Providers',
1097
- ExtraFilter: 'IsActive = 1',
1098
- });
1099
- const filesEnabled = viewResults.RowCount > 0;
1100
- if (filesEnabled) {
1101
- const drawerItem = {
1102
- id: 'Files',
1103
- selected: false,
1104
- text: 'Files',
1105
- path: '/files',
1106
- icon: "fa-regular fa-folder"
1107
- };
1108
- this.drawerItems.push(drawerItem);
1109
- }
1110
- }
1111
- async loadApplications(md) {
1112
- const drawerItem = {
1113
- id: 'Data',
1114
- selected: false,
1115
- text: 'Data',
1116
- path: '/data',
1117
- icon: "fa-solid fa-database"
1118
- };
1119
- this.drawerItems.push(drawerItem);
1120
- }
1121
- async loadResourceType(key, resourceType, path, currentUserID) {
1122
- const rt = this.sharedService.ResourceTypeByName(resourceType);
1123
- if (rt) {
1124
- const drawerItem = {
1125
- id: key,
1126
- selected: false,
1127
- text: resourceType,
1128
- path: path,
1129
- icon: rt.Icon ? rt.Icon : "fa-regular fa-file-alt"
1130
- };
1131
- this.drawerItems.push(drawerItem);
1132
- }
1133
- else {
1134
- LogStatus("no resource type found for " + resourceType);
1135
- }
1136
- }
1137
- setDrawerConfig() {
1138
- const pageWidth = window.innerWidth;
1139
- if (pageWidth <= 840) {
1140
- this.mode = 'overlay';
1141
- this.mini = false;
1142
- }
1143
- else {
1144
- this.mode = 'push';
1145
- this.mini = true;
1146
- }
1147
- }
1148
- toggle() {
1149
- this.drawer.toggle();
1150
- this.mini = !this.mini;
1151
- this.sharedService.InvokeManualResize();
1152
- }
1153
- static ɵfac = function NavigationComponent_Factory(t) { return new (t || NavigationComponent)(i0.ɵɵdirectiveInject(i1.Router), i0.ɵɵdirectiveInject(i1.ActivatedRoute), i0.ɵɵdirectiveInject(i2.SharedService), i0.ɵɵdirectiveInject(i3.Location), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i4.Title), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
1154
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NavigationComponent, selectors: [["mj-navigation"]], viewQuery: function NavigationComponent_Query(rf, ctx) { if (rf & 1) {
1155
- i0.ɵɵviewQuery(DrawerComponent, 5);
1156
- i0.ɵɵviewQuery(_c0, 5);
1157
- i0.ɵɵviewQuery(_c1, 5);
1158
- i0.ɵɵviewQuery(_c2, 7, ElementRef);
1159
- } if (rf & 2) {
1160
- let _t;
1161
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.drawer = _t.first);
1162
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.mjTabStrip = _t.first);
1163
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.drawerWrapper = _t.first);
1164
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.container = _t.first);
1165
- } }, hostVars: 2, hostBindings: function NavigationComponent_HostBindings(rf, ctx) { if (rf & 1) {
1166
- i0.ɵɵlistener("resize", function NavigationComponent_resize_HostBindingHandler() { return ctx.onWindowResize(); }, false, i0.ɵɵresolveWindow)("click", function NavigationComponent_click_HostBindingHandler() { return ctx.onClick(); }, false, i0.ɵɵresolveDocument);
1167
- } if (rf & 2) {
1168
- i0.ɵɵclassProp("mobile-screen", ctx.isMobileScreen);
1169
- } }, inputs: { applicationName: "applicationName" }, decls: 5, vars: 6, consts: [["drawerWrapper", ""], ["drawer", ""], ["mjTabstrip", ""], ["kendoDialogContainer", "", 1, "navigation-wrap", 3, "ngClass"], ["size", "large", 3, "showText", 4, "ngIf"], [4, "ngIf"], ["class", "context-menu", 3, "ngStyle", 4, "ngIf"], ["size", "large", 3, "showText"], ["mode", "push", 3, "select", "items", "mini", "animation", "autoCollapse"], ["kendoDrawerItemTemplate", ""], ["kendoDialogContainer", ""], [3, "TabClosed", "TabSelected", "TabContextMenu", "ResizeContainer"], [3, "TabCloseable"], [1, "drawer-item-icon"], [1, "skip-icon"], [3, "class"], [1, "item-descr-wrap"], [1, "item-descr"], [1, "fa-regular", "fa-clock", "tab-icon"], [1, "tab-resource", 3, "ResourceRecordSaved", "ContentLoadingStarted", "ContentLoadingComplete", "Data", "isVisible"], [1, "context-menu", 3, "ngStyle"], [1, "context-menu-item", 3, "click"]], template: function NavigationComponent_Template(rf, ctx) { if (rf & 1) {
1170
- i0.ɵɵelementStart(0, "div", 3, 0);
1171
- i0.ɵɵtemplate(2, NavigationComponent_mj_loading_2_Template, 1, 1, "mj-loading", 4)(3, NavigationComponent_kendo_drawer_container_3_Template, 15, 5, "kendo-drawer-container", 5);
1172
- i0.ɵɵelementEnd();
1173
- i0.ɵɵtemplate(4, NavigationComponent_div_4_Template, 7, 1, "div", 6);
1174
- } if (rf & 2) {
1175
- i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(4, _c3, ctx.loader));
1176
- i0.ɵɵadvance(2);
1177
- i0.ɵɵproperty("ngIf", ctx.loading);
1178
- i0.ɵɵadvance();
1179
- i0.ɵɵproperty("ngIf", !ctx.loading);
1180
- i0.ɵɵadvance();
1181
- i0.ɵɵproperty("ngIf", ctx.contextMenuVisible);
1182
- } }, dependencies: [i1.RouterOutlet, i3.NgClass, i3.NgIf, i3.NgStyle, i5.DialogContainerDirective, i6.DrawerComponent, i6.DrawerContainerComponent, i6.DrawerContentComponent, i6.DrawerItemTemplateDirective, i7.MJTabStripComponent, i7.MJTabBodyComponent, i7.MJTabComponent, i8.LoadingComponent, i9.ResourceContainerComponent], styles: [".navigation-wrap[_ngcontent-%COMP%] {\n height: calc(100vh - 80px);\n}\n\n.context-menu[_ngcontent-%COMP%] {\n position: fixed;\n z-index: 9999;\n background-color: #ffffff;\n border: 1px solid #ccc;\n padding: 3px 3px;\n box-shadow: var(--shadow);\n}\n\n.nav-tab-title[_ngcontent-%COMP%] {\n margin-left: 10px;\n}\n\n.context-menu[_ngcontent-%COMP%] {\n position: fixed;\n z-index: 9999;\n background-color: #ffffff;\n border: 1px solid var(--gray-600);\n padding: 3px 3px;\n box-shadow: var(--shadow);\n}\n\n.tab-icon[_ngcontent-%COMP%] {\n margin-right: 5px;\n}\n\n.context-menu-item[_ngcontent-%COMP%] {\n padding: 8px 16px;\n cursor: pointer;\n}\n\n.context-menu-item[_ngcontent-%COMP%]:hover {\n background-color: var(--gray-700);\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] {\n background: var(--gray-color);\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] .k-content[_ngcontent-%COMP%] {\n padding: 25px;\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] .k-tabstrip-items-wrapper[_ngcontent-%COMP%] {\n background: var(--med-gray);\n padding-left: 20px;\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] .k-tabstrip-items-wrapper[_ngcontent-%COMP%] .k-item.k-active[_ngcontent-%COMP%] {\n border: 1px solid var(--light-gray);\n background: var(--light-gray);\n border-radius: 8px 8px 0 0;\n color: var(--blue-text);\n\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] .k-tabstrip-items-wrapper[_ngcontent-%COMP%] .k-item[_ngcontent-%COMP%]:hover {\n color: var(--blue-text);\n}\n\n.navigation-wrap[_ngcontent-%COMP%] .drawer-container[_ngcontent-%COMP%] .k-tabstrip-items-wrapper[_ngcontent-%COMP%] .k-item[_ngcontent-%COMP%] {\n background: var(--med-gray);\n border-radius: 0;\n border-right: 1px solid #909090;\n}\n\n.tab-resource[_ngcontent-%COMP%] {\n display: block;\n}\n\n.k-drawer-container[_ngcontent-%COMP%] {\n flex: 1;\n position: relative;\n z-index: 1;\n height: calc(100vh - 80px);\n}\n\n.k-drawer-push[_ngcontent-%COMP%] .k-drawer[_ngcontent-%COMP%] {\n padding: 1.5rem 0;\n background-color: var(--gray-600);\n transition: var(--transition-time);\n}\n\n .k-drawer-mini .item-descr-wrap {\n display: none;\n}\n\n .k-drawer-item {\n padding: 1rem;\n color: var(--gray-800);\n white-space: nowrap;\n transition: var(--transition-time);\n}\n\n .k-drawer-item:hover {\n background-color: var(--gray-700);\n}\n\n .k-drawer-item.k-selected {\n background-color: var(--mj-blue);\n}\n\n@media (max-width: 768px) {\n .k-drawer-container.k-drawer-push[_ngcontent-%COMP%] .k-drawer[_ngcontent-%COMP%] {\n position: fixed;\n top: 80px;\n left: -50px;\n bottom: 0;\n padding: 16px 0;\n z-index: 9999;\n }\n\n .k-drawer-expanded.k-drawer-push[_ngcontent-%COMP%] .k-drawer[_ngcontent-%COMP%] {\n left: 0px;\n }\n\n .k-drawer-mini .item-descr-wrap {\n display: block;\n }\n\n}"] });
1183
- }
1184
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NavigationComponent, [{
1185
- type: Component,
1186
- args: [{ selector: 'mj-navigation', template: "<div class=\"navigation-wrap\" [ngClass]=\"{'waiting': loader}\" #drawerWrapper kendoDialogContainer>\n <mj-loading *ngIf=\"loading\" [showText]=\"false\" size=\"large\"></mj-loading>\n <kendo-drawer-container *ngIf=\"!loading\" >\n <kendo-drawer\n #drawer\n [items]=\"drawerItems\"\n mode=\"push\"\n [mini]=\"true\"\n [animation]=\"false\"\n (select)=\"onDrawerSelect($event)\"\n [autoCollapse]=\"true\"\n >\n <ng-template kendoDrawerItemTemplate let-item>\n <div class=\"drawer-item-icon\">\n @if (item.text === 'Ask Skip') {\n <span class=\"skip-icon\"></span>\n } @else {\n <span [class]=\"item.icon\"></span>\n }\n </div>\n <div class=\"item-descr-wrap\">\n <div>{{ item.text }}</div>\n <span class=\"item-descr\">{{ item.description }}</span>\n </div>\n </ng-template> \n </kendo-drawer>\n <kendo-drawer-content kendoDialogContainer>\n\n <mj-tabstrip #mjTabstrip (TabClosed)=\"handleTabClosed($event)\" (TabSelected)=\"handleTabSelected($event)\" (TabContextMenu)=\"handleTabContextMenu($event)\" (ResizeContainer)=\"sharedService.InvokeManualResize()\">\n <mj-tab [TabCloseable]=\"false\">\n Home\n </mj-tab>\n <mj-tab-body>\n <router-outlet></router-outlet>\n </mj-tab-body>\n\n @for(tab of tabs; track tab.id; let i = $index) {\n <mj-tab [TabCloseable]=\"true\">\n @if(tab?.contentLoading) {\n <span class=\"fa-regular fa-clock tab-icon\"></span>\n }\n @else if (tab?.icon) {\n <span [class]=\"tab.icon + ' tab-icon'\"></span>\n }\n {{ tab.labelLoading ? 'Loading...' : tab.label }}\n </mj-tab>\n }\n @for(tab of tabs; track tab.id; let i = $index) {\n <mj-tab-body>\n <mj-resource [Data]=\"tab.data\" [isVisible]=\"activeTabIndex - 1 === i\"\n (ResourceRecordSaved)=\"HandleResourceRecordSaved(tab, $event)\"\n (ContentLoadingStarted)=\"setTabContentLoadingStatus(tab, true)\"\n (ContentLoadingComplete)=\"setTabContentLoadingStatus(tab, false)\"\n class=\"tab-resource\"\n ></mj-resource>\n </mj-tab-body> \n }\n </mj-tabstrip>\n </kendo-drawer-content>\n </kendo-drawer-container>\n\n \n <!-- <mj-skip-button\n action=\"route\"\n ></mj-skip-button> -->\n <!-- Skip Button shows up through the above line of code -->\n</div>\n\n<div class=\"context-menu\" [ngStyle]=\"contextMenuStyle\" *ngIf=\"contextMenuVisible\">\n <div class=\"context-menu-item\" (click)=\"handleContextMenuOption(1)\">Close All</div>\n <div class=\"context-menu-item\" (click)=\"handleContextMenuOption(2)\">Close Others</div>\n <div class=\"context-menu-item\" (click)=\"handleContextMenuOption(3)\">Close Tabs to the Right</div>\n </div>", styles: [".navigation-wrap {\n height: calc(100vh - 80px);\n}\n\n.context-menu {\n position: fixed;\n z-index: 9999;\n background-color: #ffffff;\n border: 1px solid #ccc;\n padding: 3px 3px;\n box-shadow: var(--shadow);\n}\n\n.nav-tab-title {\n margin-left: 10px;\n}\n\n.context-menu {\n position: fixed;\n z-index: 9999;\n background-color: #ffffff;\n border: 1px solid var(--gray-600);\n padding: 3px 3px;\n box-shadow: var(--shadow);\n}\n\n.tab-icon {\n margin-right: 5px;\n}\n\n.context-menu-item {\n padding: 8px 16px;\n cursor: pointer;\n}\n\n.context-menu-item:hover {\n background-color: var(--gray-700);\n}\n\n.navigation-wrap .drawer-container {\n background: var(--gray-color);\n}\n\n.navigation-wrap .drawer-container .k-content {\n padding: 25px;\n}\n\n.navigation-wrap .drawer-container .k-tabstrip-items-wrapper {\n background: var(--med-gray);\n padding-left: 20px;\n}\n\n.navigation-wrap .drawer-container .k-tabstrip-items-wrapper .k-item.k-active {\n border: 1px solid var(--light-gray);\n background: var(--light-gray);\n border-radius: 8px 8px 0 0;\n color: var(--blue-text);\n\n}\n\n.navigation-wrap .drawer-container .k-tabstrip-items-wrapper .k-item:hover {\n color: var(--blue-text);\n}\n\n.navigation-wrap .drawer-container .k-tabstrip-items-wrapper .k-item {\n background: var(--med-gray);\n border-radius: 0;\n border-right: 1px solid #909090;\n}\n\n.tab-resource {\n display: block;\n}\n\n.k-drawer-container {\n flex: 1;\n position: relative;\n z-index: 1;\n height: calc(100vh - 80px);\n}\n\n.k-drawer-push .k-drawer {\n padding: 1.5rem 0;\n background-color: var(--gray-600);\n transition: var(--transition-time);\n}\n\n::ng-deep .k-drawer-mini .item-descr-wrap {\n display: none;\n}\n\n::ng-deep .k-drawer-item {\n padding: 1rem;\n color: var(--gray-800);\n white-space: nowrap;\n transition: var(--transition-time);\n}\n\n::ng-deep .k-drawer-item:hover {\n background-color: var(--gray-700);\n}\n\n::ng-deep .k-drawer-item.k-selected {\n background-color: var(--mj-blue);\n}\n\n@media (max-width: 768px) {\n .k-drawer-container.k-drawer-push .k-drawer {\n position: fixed;\n top: 80px;\n left: -50px;\n bottom: 0;\n padding: 16px 0;\n z-index: 9999;\n }\n\n .k-drawer-expanded.k-drawer-push .k-drawer {\n left: 0px;\n }\n\n ::ng-deep .k-drawer-mini .item-descr-wrap {\n display: block;\n }\n\n}"] }]
1187
- }], () => [{ type: i1.Router }, { type: i1.ActivatedRoute }, { type: i2.SharedService }, { type: i3.Location }, { type: i0.Renderer2 }, { type: i4.Title }, { type: i0.ChangeDetectorRef }], { applicationName: [{
1188
- type: Input
1189
- }], isMobileScreen: [{
1190
- type: HostBinding,
1191
- args: ['class.mobile-screen']
1192
- }], drawer: [{
1193
- type: ViewChild,
1194
- args: [DrawerComponent, { static: false }]
1195
- }], mjTabStrip: [{
1196
- type: ViewChild,
1197
- args: ['mjTabstrip', { static: false }]
1198
- }], drawerWrapper: [{
1199
- type: ViewChild,
1200
- args: ['drawerWrapper', { static: false }]
1201
- }], container: [{
1202
- type: ViewChild,
1203
- args: ['container', { static: true, read: ElementRef }]
1204
- }], onWindowResize: [{
1205
- type: HostListener,
1206
- args: ['window:resize']
1207
- }], onClick: [{
1208
- type: HostListener,
1209
- args: ['document:click']
1210
- }] }); })();
1211
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(NavigationComponent, { className: "NavigationComponent" }); })();
1212
- //# sourceMappingURL=navigation.component.js.map