@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.
- package/README.md +117 -726
- package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/record-resource.component.js +11 -29
- package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.d.ts +71 -14
- package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
- package/dist/lib/shell/components/header/app-nav.component.js +195 -54
- package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/component-cache-manager.js +0 -6
- package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +5 -1
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +28 -17
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +1 -1
- package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +1 -1
- package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +1 -1
- package/dist/lib/single-record/single-record.component.d.ts +9 -0
- package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
- package/dist/lib/single-record/single-record.component.js +43 -2
- package/dist/lib/single-record/single-record.component.js.map +1 -1
- package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
- package/dist/lib/user-menu/base-user-menu.js +2 -13
- package/dist/lib/user-menu/base-user-menu.js.map +1 -1
- package/package.json +35 -35
- package/dist/generic/Events.types.d.ts +0 -174
- package/dist/generic/Events.types.d.ts.map +0 -1
- package/dist/generic/Events.types.js +0 -220
- package/dist/generic/Events.types.js.map +0 -1
- package/dist/lib/app-view/application-view.component.d.ts +0 -65
- package/dist/lib/app-view/application-view.component.d.ts.map +0 -1
- package/dist/lib/app-view/application-view.component.js +0 -611
- package/dist/lib/app-view/application-view.component.js.map +0 -1
- package/dist/lib/auth-button/auth-button.component.d.ts +0 -13
- package/dist/lib/auth-button/auth-button.component.d.ts.map +0 -1
- package/dist/lib/auth-button/auth-button.component.js +0 -36
- package/dist/lib/auth-button/auth-button.component.js.map +0 -1
- package/dist/lib/base-browser-component/base-browser-component.d.ts +0 -44
- package/dist/lib/base-browser-component/base-browser-component.d.ts.map +0 -1
- package/dist/lib/base-browser-component/base-browser-component.js +0 -195
- package/dist/lib/base-browser-component/base-browser-component.js.map +0 -1
- package/dist/lib/chat-wrapper/chat-wrapper.component.d.ts +0 -54
- package/dist/lib/chat-wrapper/chat-wrapper.component.d.ts.map +0 -1
- package/dist/lib/chat-wrapper/chat-wrapper.component.js +0 -257
- package/dist/lib/chat-wrapper/chat-wrapper.component.js.map +0 -1
- package/dist/lib/dashboard-browser-component/dashboard-browser.component.d.ts +0 -32
- package/dist/lib/dashboard-browser-component/dashboard-browser.component.d.ts.map +0 -1
- package/dist/lib/dashboard-browser-component/dashboard-browser.component.js +0 -244
- package/dist/lib/dashboard-browser-component/dashboard-browser.component.js.map +0 -1
- package/dist/lib/data-browser-component/data-browser.component.d.ts +0 -23
- package/dist/lib/data-browser-component/data-browser.component.d.ts.map +0 -1
- package/dist/lib/data-browser-component/data-browser.component.js +0 -267
- package/dist/lib/data-browser-component/data-browser.component.js.map +0 -1
- package/dist/lib/expansion-panel-component/expansion-panel-component.d.ts +0 -21
- package/dist/lib/expansion-panel-component/expansion-panel-component.d.ts.map +0 -1
- package/dist/lib/expansion-panel-component/expansion-panel-component.js +0 -158
- package/dist/lib/expansion-panel-component/expansion-panel-component.js.map +0 -1
- package/dist/lib/favorites/favorites.component.d.ts +0 -15
- package/dist/lib/favorites/favorites.component.d.ts.map +0 -1
- package/dist/lib/favorites/favorites.component.js +0 -135
- package/dist/lib/favorites/favorites.component.js.map +0 -1
- package/dist/lib/files/files.component.d.ts +0 -10
- package/dist/lib/files/files.component.d.ts.map +0 -1
- package/dist/lib/files/files.component.js +0 -41
- package/dist/lib/files/files.component.js.map +0 -1
- package/dist/lib/generic-browse-list/generic-browse-list.component.d.ts +0 -30
- package/dist/lib/generic-browse-list/generic-browse-list.component.d.ts.map +0 -1
- package/dist/lib/generic-browse-list/generic-browse-list.component.js +0 -171
- package/dist/lib/generic-browse-list/generic-browse-list.component.js.map +0 -1
- package/dist/lib/generic-browser-list/generic-browser-list.component.d.ts +0 -120
- package/dist/lib/generic-browser-list/generic-browser-list.component.d.ts.map +0 -1
- package/dist/lib/generic-browser-list/generic-browser-list.component.js +0 -1093
- package/dist/lib/generic-browser-list/generic-browser-list.component.js.map +0 -1
- package/dist/lib/header/MSFT_UserImageService.d.ts +0 -12
- package/dist/lib/header/MSFT_UserImageService.d.ts.map +0 -1
- package/dist/lib/header/MSFT_UserImageService.js +0 -25
- package/dist/lib/header/MSFT_UserImageService.js.map +0 -1
- package/dist/lib/header/header.component.d.ts +0 -69
- package/dist/lib/header/header.component.d.ts.map +0 -1
- package/dist/lib/header/header.component.js +0 -342
- package/dist/lib/header/header.component.js.map +0 -1
- package/dist/lib/home-component/home.component.d.ts +0 -22
- package/dist/lib/home-component/home.component.d.ts.map +0 -1
- package/dist/lib/home-component/home.component.js +0 -194
- package/dist/lib/home-component/home.component.js.map +0 -1
- package/dist/lib/home-wrapper/home-wrapper.component.d.ts +0 -7
- package/dist/lib/home-wrapper/home-wrapper.component.d.ts.map +0 -1
- package/dist/lib/home-wrapper/home-wrapper.component.js +0 -30
- package/dist/lib/home-wrapper/home-wrapper.component.js.map +0 -1
- package/dist/lib/list-view/list-view.component.d.ts +0 -45
- package/dist/lib/list-view/list-view.component.d.ts.map +0 -1
- package/dist/lib/list-view/list-view.component.js +0 -329
- package/dist/lib/list-view/list-view.component.js.map +0 -1
- package/dist/lib/navigation/navigation.component.d.ts +0 -142
- package/dist/lib/navigation/navigation.component.d.ts.map +0 -1
- package/dist/lib/navigation/navigation.component.js +0 -1212
- package/dist/lib/navigation/navigation.component.js.map +0 -1
- package/dist/lib/query-browser-component/query-browser.component.d.ts +0 -75
- package/dist/lib/query-browser-component/query-browser.component.d.ts.map +0 -1
- package/dist/lib/query-browser-component/query-browser.component.js +0 -908
- package/dist/lib/query-browser-component/query-browser.component.js.map +0 -1
- package/dist/lib/report-browser-component/report-browser.component.d.ts +0 -22
- package/dist/lib/report-browser-component/report-browser.component.d.ts.map +0 -1
- package/dist/lib/report-browser-component/report-browser.component.js +0 -80
- package/dist/lib/report-browser-component/report-browser.component.js.map +0 -1
- package/dist/lib/resource-browser/resource-browser.component.d.ts +0 -178
- package/dist/lib/resource-browser/resource-browser.component.d.ts.map +0 -1
- package/dist/lib/resource-browser/resource-browser.component.js +0 -1012
- package/dist/lib/resource-browser/resource-browser.component.js.map +0 -1
- package/dist/lib/resource-wrappers/report-resource.component.d.ts +0 -13
- package/dist/lib/resource-wrappers/report-resource.component.d.ts.map +0 -1
- package/dist/lib/resource-wrappers/report-resource.component.js +0 -49
- package/dist/lib/resource-wrappers/report-resource.component.js.map +0 -1
- package/dist/lib/shared/custom-icon/custom-icon.component.d.ts +0 -11
- package/dist/lib/shared/custom-icon/custom-icon.component.d.ts.map +0 -1
- package/dist/lib/shared/custom-icon/custom-icon.component.js +0 -44
- package/dist/lib/shared/custom-icon/custom-icon.component.js.map +0 -1
- package/dist/lib/single-application/single-application.component.d.ts +0 -24
- package/dist/lib/single-application/single-application.component.d.ts.map +0 -1
- package/dist/lib/single-application/single-application.component.js +0 -122
- package/dist/lib/single-application/single-application.component.js.map +0 -1
- package/dist/lib/single-entity/single-entity.component.d.ts +0 -34
- package/dist/lib/single-entity/single-entity.component.d.ts.map +0 -1
- package/dist/lib/single-entity/single-entity.component.js +0 -245
- package/dist/lib/single-entity/single-entity.component.js.map +0 -1
- package/dist/lib/single-report/single-report.component.d.ts +0 -17
- package/dist/lib/single-report/single-report.component.d.ts.map +0 -1
- package/dist/lib/single-report/single-report.component.js +0 -55
- package/dist/lib/single-report/single-report.component.js.map +0 -1
- package/dist/lib/single-view/single-view.component.d.ts +0 -43
- package/dist/lib/single-view/single-view.component.d.ts.map +0 -1
- package/dist/lib/single-view/single-view.component.js +0 -207
- package/dist/lib/single-view/single-view.component.js.map +0 -1
- package/dist/lib/style-guide-test/style-guide-test.component.d.ts +0 -70
- package/dist/lib/style-guide-test/style-guide-test.component.d.ts.map +0 -1
- package/dist/lib/style-guide-test/style-guide-test.component.js +0 -1024
- package/dist/lib/style-guide-test/style-guide-test.component.js.map +0 -1
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts +0 -46
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts.map +0 -1
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js +0 -547
- 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
|