@memberjunction/ng-explorer-core 5.24.0 → 5.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-routing.module.d.ts.map +1 -1
- package/dist/app-routing.module.js +14 -19
- package/dist/app-routing.module.js.map +1 -1
- package/dist/generated/lazy-feature-config.js +3 -3
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/artifact-resource.component.js +1 -0
- package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +16 -17
- package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js +56 -62
- package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +2 -4
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +9 -13
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +2 -15
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +18 -52
- package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +2 -3
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +7 -9
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/list-detail-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/list-detail-resource.component.js +1 -0
- package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/notifications-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/notifications-resource.component.js +1 -0
- package/dist/lib/resource-wrappers/notifications-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/query-resource.component.js +1 -0
- package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +74 -4
- package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/search-results-resource.component.js +786 -25
- package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts +7 -4
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +30 -14
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +10 -3
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +28 -8
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +416 -218
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +2 -1
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +7 -3
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +6 -0
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +63 -38
- package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +1 -0
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/user-menu/base-user-menu.d.ts +7 -7
- package/dist/lib/user-menu/base-user-menu.d.ts.map +1 -1
- package/dist/lib/user-menu/base-user-menu.js +8 -1
- package/dist/lib/user-menu/base-user-menu.js.map +1 -1
- package/dist/lib/user-menu/user-menu.types.d.ts +15 -0
- package/dist/lib/user-menu/user-menu.types.d.ts.map +1 -1
- package/dist/lib/user-menu/user-menu.types.js.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.d.ts +6 -3
- package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
- package/dist/lib/user-notifications/user-notifications.component.js +46 -19
- package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
- package/dist/module.d.ts +3 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +8 -0
- package/dist/module.js.map +1 -1
- package/package.json +40 -38
|
@@ -9,6 +9,7 @@ import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
|
9
9
|
import { getActiveTheme } from './loading-themes';
|
|
10
10
|
import { TabContainerComponent } from './components/tabs/tab-container.component';
|
|
11
11
|
import { BaseUserMenu, isUserMenuDivider } from '../user-menu';
|
|
12
|
+
import { InstanceConfigEngine } from '@memberjunction/core-entities';
|
|
12
13
|
import * as i0 from "@angular/core";
|
|
13
14
|
import * as i1 from "@memberjunction/ng-base-application";
|
|
14
15
|
import * as i2 from "@memberjunction/ng-shared";
|
|
@@ -17,19 +18,22 @@ import * as i4 from "@memberjunction/ng-auth-services";
|
|
|
17
18
|
import * as i5 from "@memberjunction/ng-user-avatar";
|
|
18
19
|
import * as i6 from "./services/settings-dialog.service";
|
|
19
20
|
import * as i7 from "../command-palette/command-palette.service";
|
|
20
|
-
import * as i8 from "@
|
|
21
|
-
import * as i9 from "@
|
|
22
|
-
import * as i10 from "@memberjunction/ng-
|
|
23
|
-
import * as i11 from "
|
|
24
|
-
import * as i12 from "
|
|
25
|
-
import * as i13 from "./components/
|
|
26
|
-
import * as i14 from "./components/
|
|
27
|
-
import * as i15 from "
|
|
21
|
+
import * as i8 from "@memberjunction/ng-file-storage";
|
|
22
|
+
import * as i9 from "@angular/forms";
|
|
23
|
+
import * as i10 from "@memberjunction/ng-ui-components";
|
|
24
|
+
import * as i11 from "@memberjunction/ng-shared-generic";
|
|
25
|
+
import * as i12 from "@memberjunction/ng-search";
|
|
26
|
+
import * as i13 from "./components/header/app-switcher.component";
|
|
27
|
+
import * as i14 from "./components/header/app-nav.component";
|
|
28
|
+
import * as i15 from "./components/tabs/tab-container.component";
|
|
29
|
+
import * as i16 from "./components/dialogs/app-access-dialog.component";
|
|
30
|
+
import * as i17 from "../command-palette/command-palette.component";
|
|
28
31
|
const _c0 = ["searchInput"];
|
|
29
|
-
const _c1 = ["
|
|
32
|
+
const _c1 = ["shellSearchComposite"];
|
|
33
|
+
const _c2 = ["appAccessDialog"];
|
|
30
34
|
function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
31
35
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
32
|
-
i0.ɵɵelementStart(0, "button",
|
|
36
|
+
i0.ɵɵelementStart(0, "button", 46);
|
|
33
37
|
i0.ɵɵlistener("click", function ShellComponent_Conditional_5_For_2_Template_button_click_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r3, $event)); })("dblclick", function ShellComponent_Conditional_5_For_2_Template_button_dblclick_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r3, $event)); });
|
|
34
38
|
i0.ɵɵelement(1, "i");
|
|
35
39
|
i0.ɵɵelementEnd();
|
|
@@ -43,8 +47,8 @@ function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
43
47
|
i0.ɵɵclassMap(app_r3.Icon);
|
|
44
48
|
} }
|
|
45
49
|
function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
46
|
-
i0.ɵɵelementStart(0, "div",
|
|
47
|
-
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button",
|
|
50
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
51
|
+
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
|
|
48
52
|
i0.ɵɵelementEnd();
|
|
49
53
|
} if (rf & 2) {
|
|
50
54
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -53,14 +57,24 @@ function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
|
53
57
|
} }
|
|
54
58
|
function ShellComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
55
59
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
56
|
-
i0.ɵɵelementStart(0, "mj-app-nav",
|
|
60
|
+
i0.ɵɵelementStart(0, "mj-app-nav", 47);
|
|
57
61
|
i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemClick_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemDismiss_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
|
|
58
62
|
i0.ɵɵelementEnd();
|
|
59
63
|
} if (rf & 2) {
|
|
60
64
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
61
65
|
i0.ɵɵproperty("app", ctx_r3.activeApp);
|
|
62
66
|
} }
|
|
63
|
-
function
|
|
67
|
+
function ShellComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
68
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
69
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "mj-search-composite", 48, 2);
|
|
70
|
+
i0.ɵɵlistener("ResultSelected", function ShellComponent_Conditional_8_Template_mj_search_composite_ResultSelected_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSearchResultSelected($event)); })("SearchSubmitted", function ShellComponent_Conditional_8_Template_mj_search_composite_SearchSubmitted_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSearchSubmitted($event)); })("SeeAllRequested", function ShellComponent_Conditional_8_Template_mj_search_composite_SeeAllRequested_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnSeeAllSearch($event)); });
|
|
71
|
+
i0.ɵɵelementEnd()();
|
|
72
|
+
} if (rf & 2) {
|
|
73
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
74
|
+
i0.ɵɵadvance();
|
|
75
|
+
i0.ɵɵproperty("ShowShortcutHint", true)("EnablePreview", ctx_r3.ShowSearchPreview)("EnableRecent", true)("MaxPreviewResults", 8);
|
|
76
|
+
} }
|
|
77
|
+
function ShellComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
64
78
|
i0.ɵɵelementStart(0, "span", 16);
|
|
65
79
|
i0.ɵɵtext(1);
|
|
66
80
|
i0.ɵɵelementEnd();
|
|
@@ -69,37 +83,37 @@ function ShellComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
|
69
83
|
i0.ɵɵadvance();
|
|
70
84
|
i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
|
|
71
85
|
} }
|
|
72
|
-
function
|
|
73
|
-
const
|
|
74
|
-
i0.ɵɵelementStart(0, "button",
|
|
75
|
-
i0.ɵɵlistener("click", function
|
|
86
|
+
function ShellComponent_Conditional_14_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
88
|
+
i0.ɵɵelementStart(0, "button", 46);
|
|
89
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_14_For_2_Template_button_click_0_listener($event) { const app_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r8, $event)); })("dblclick", function ShellComponent_Conditional_14_For_2_Template_button_dblclick_0_listener($event) { const app_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r8, $event)); });
|
|
76
90
|
i0.ɵɵelement(1, "i");
|
|
77
91
|
i0.ɵɵelementEnd();
|
|
78
92
|
} if (rf & 2) {
|
|
79
|
-
const
|
|
93
|
+
const app_r8 = ctx.$implicit;
|
|
80
94
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
81
|
-
i0.ɵɵstyleProp("--app-color",
|
|
82
|
-
i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(
|
|
83
|
-
i0.ɵɵproperty("title",
|
|
95
|
+
i0.ɵɵstyleProp("--app-color", app_r8.GetColor());
|
|
96
|
+
i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(app_r8));
|
|
97
|
+
i0.ɵɵproperty("title", app_r8.Name);
|
|
84
98
|
i0.ɵɵadvance();
|
|
85
|
-
i0.ɵɵclassMap(
|
|
99
|
+
i0.ɵɵclassMap(app_r8.Icon);
|
|
86
100
|
} }
|
|
87
|
-
function
|
|
101
|
+
function ShellComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
88
102
|
i0.ɵɵelementStart(0, "div", 17);
|
|
89
|
-
i0.ɵɵrepeaterCreate(1,
|
|
103
|
+
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_14_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
|
|
90
104
|
i0.ɵɵelementEnd();
|
|
91
105
|
} if (rf & 2) {
|
|
92
106
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
93
107
|
i0.ɵɵadvance();
|
|
94
108
|
i0.ɵɵrepeater(ctx_r3.leftOfUserMenuApps);
|
|
95
109
|
} }
|
|
96
|
-
function
|
|
110
|
+
function ShellComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
97
111
|
i0.ɵɵelement(0, "img", 20);
|
|
98
112
|
} if (rf & 2) {
|
|
99
113
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
100
114
|
i0.ɵɵproperty("src", ctx_r3.userImageURL, i0.ɵɵsanitizeUrl);
|
|
101
115
|
} }
|
|
102
|
-
function
|
|
116
|
+
function ShellComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
103
117
|
i0.ɵɵelementStart(0, "div", 21);
|
|
104
118
|
i0.ɵɵelement(1, "i");
|
|
105
119
|
i0.ɵɵelementEnd();
|
|
@@ -108,8 +122,8 @@ function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
|
108
122
|
i0.ɵɵadvance();
|
|
109
123
|
i0.ɵɵclassMap(ctx_r3.userIconClass || "fa-solid fa-user");
|
|
110
124
|
} }
|
|
111
|
-
function
|
|
112
|
-
i0.ɵɵelementStart(0, "span",
|
|
125
|
+
function ShellComponent_Conditional_19_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
126
|
+
i0.ɵɵelementStart(0, "span", 53);
|
|
113
127
|
i0.ɵɵtext(1);
|
|
114
128
|
i0.ɵɵelementEnd();
|
|
115
129
|
} if (rf & 2) {
|
|
@@ -118,107 +132,121 @@ function ShellComponent_Conditional_20_Conditional_1_Conditional_4_Template(rf,
|
|
|
118
132
|
i0.ɵɵadvance();
|
|
119
133
|
i0.ɵɵtextInterpolate1(" ", (tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.email, " ");
|
|
120
134
|
} }
|
|
121
|
-
function
|
|
122
|
-
i0.ɵɵelementStart(0, "
|
|
135
|
+
function ShellComponent_Conditional_19_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
136
|
+
i0.ɵɵelementStart(0, "span", 54);
|
|
137
|
+
i0.ɵɵtext(1);
|
|
138
|
+
i0.ɵɵelementEnd();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
let tmp_5_0;
|
|
141
|
+
const ctx_r3 = i0.ɵɵnextContext(3);
|
|
142
|
+
i0.ɵɵadvance();
|
|
143
|
+
i0.ɵɵtextInterpolate((tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.subtitle);
|
|
144
|
+
} }
|
|
145
|
+
function ShellComponent_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
146
|
+
i0.ɵɵelementStart(0, "div", 50)(1, "div", 51)(2, "span", 52);
|
|
123
147
|
i0.ɵɵtext(3);
|
|
124
148
|
i0.ɵɵelementEnd();
|
|
125
|
-
i0.ɵɵconditionalCreate(4,
|
|
149
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_19_Conditional_1_Conditional_4_Template, 2, 1, "span", 53);
|
|
150
|
+
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_19_Conditional_1_Conditional_5_Template, 2, 1, "span", 54);
|
|
126
151
|
i0.ɵɵelementEnd()();
|
|
127
|
-
i0.ɵɵelement(
|
|
152
|
+
i0.ɵɵelement(6, "div", 55);
|
|
128
153
|
} if (rf & 2) {
|
|
129
154
|
let tmp_4_0;
|
|
130
155
|
let tmp_5_0;
|
|
156
|
+
let tmp_6_0;
|
|
131
157
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
132
158
|
i0.ɵɵadvance(3);
|
|
133
159
|
i0.ɵɵtextInterpolate(((tmp_4_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_4_0.name) || ctx_r3.userName);
|
|
134
160
|
i0.ɵɵadvance();
|
|
135
161
|
i0.ɵɵconditional(((tmp_5_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_5_0.showUserEmail) && ((tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.email) ? 4 : -1);
|
|
162
|
+
i0.ɵɵadvance();
|
|
163
|
+
i0.ɵɵconditional(((tmp_6_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_6_0.subtitle) ? 5 : -1);
|
|
136
164
|
} }
|
|
137
|
-
function
|
|
138
|
-
i0.ɵɵelement(0, "div",
|
|
165
|
+
function ShellComponent_Conditional_19_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
166
|
+
i0.ɵɵelement(0, "div", 55);
|
|
139
167
|
} }
|
|
140
|
-
function
|
|
141
|
-
const
|
|
142
|
-
i0.ɵɵelementStart(0, "div",
|
|
143
|
-
i0.ɵɵlistener("click", function
|
|
168
|
+
function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
169
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
170
|
+
i0.ɵɵelementStart(0, "div", 58);
|
|
171
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r9); const item_r10 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onUserMenuItemClick(item_r10.id)); });
|
|
144
172
|
i0.ɵɵelement(1, "i");
|
|
145
|
-
i0.ɵɵelementStart(2, "span",
|
|
173
|
+
i0.ɵɵelementStart(2, "span", 59);
|
|
146
174
|
i0.ɵɵtext(3);
|
|
147
175
|
i0.ɵɵelementEnd();
|
|
148
|
-
i0.ɵɵelementStart(4, "div",
|
|
149
|
-
i0.ɵɵelement(6, "i",
|
|
176
|
+
i0.ɵɵelementStart(4, "div", 60)(5, "div", 61);
|
|
177
|
+
i0.ɵɵelement(6, "i", 62);
|
|
150
178
|
i0.ɵɵelementEnd()()();
|
|
151
179
|
} if (rf & 2) {
|
|
152
|
-
const
|
|
180
|
+
const item_r10 = i0.ɵɵnextContext();
|
|
153
181
|
const ctx_r3 = i0.ɵɵnextContext(4);
|
|
154
|
-
i0.ɵɵproperty("title",
|
|
182
|
+
i0.ɵɵproperty("title", item_r10.tooltip || "");
|
|
155
183
|
i0.ɵɵadvance();
|
|
156
|
-
i0.ɵɵclassMap(
|
|
184
|
+
i0.ɵɵclassMap(item_r10.icon);
|
|
157
185
|
i0.ɵɵadvance(2);
|
|
158
|
-
i0.ɵɵtextInterpolate(
|
|
186
|
+
i0.ɵɵtextInterpolate(item_r10.label);
|
|
159
187
|
i0.ɵɵadvance();
|
|
160
188
|
i0.ɵɵclassProp("dark", ctx_r3.IsDarkMode);
|
|
161
189
|
i0.ɵɵadvance(2);
|
|
162
190
|
i0.ɵɵclassMap(ctx_r3.IsDarkMode ? "fa-solid fa-moon" : "fa-solid fa-sun");
|
|
163
191
|
} }
|
|
164
|
-
function
|
|
165
|
-
i0.ɵɵelementStart(0, "span",
|
|
192
|
+
function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
193
|
+
i0.ɵɵelementStart(0, "span", 64);
|
|
166
194
|
i0.ɵɵtext(1);
|
|
167
195
|
i0.ɵɵelementEnd();
|
|
168
196
|
} if (rf & 2) {
|
|
169
|
-
const
|
|
197
|
+
const item_r10 = i0.ɵɵnextContext(2);
|
|
170
198
|
i0.ɵɵadvance();
|
|
171
|
-
i0.ɵɵtextInterpolate(
|
|
199
|
+
i0.ɵɵtextInterpolate(item_r10.shortcut);
|
|
172
200
|
} }
|
|
173
|
-
function
|
|
174
|
-
const
|
|
175
|
-
i0.ɵɵelementStart(0, "div",
|
|
176
|
-
i0.ɵɵlistener("click", function
|
|
201
|
+
function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
202
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
203
|
+
i0.ɵɵelementStart(0, "div", 63);
|
|
204
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const item_r10 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(item_r10.enabled && ctx_r3.onUserMenuItemClick(item_r10.id)); });
|
|
177
205
|
i0.ɵɵelement(1, "i");
|
|
178
|
-
i0.ɵɵelementStart(2, "span",
|
|
206
|
+
i0.ɵɵelementStart(2, "span", 59);
|
|
179
207
|
i0.ɵɵtext(3);
|
|
180
208
|
i0.ɵɵelementEnd();
|
|
181
|
-
i0.ɵɵconditionalCreate(4,
|
|
209
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template, 2, 1, "span", 64);
|
|
182
210
|
i0.ɵɵelementEnd();
|
|
183
211
|
} if (rf & 2) {
|
|
184
|
-
const
|
|
185
|
-
i0.ɵɵstyleProp("color",
|
|
186
|
-
i0.ɵɵclassProp("disabled", !
|
|
187
|
-
i0.ɵɵproperty("title",
|
|
212
|
+
const item_r10 = i0.ɵɵnextContext();
|
|
213
|
+
i0.ɵɵstyleProp("color", item_r10.color || null);
|
|
214
|
+
i0.ɵɵclassProp("disabled", !item_r10.enabled)("danger", item_r10.cssClass === "danger");
|
|
215
|
+
i0.ɵɵproperty("title", item_r10.tooltip || "");
|
|
188
216
|
i0.ɵɵadvance();
|
|
189
|
-
i0.ɵɵclassMap(
|
|
217
|
+
i0.ɵɵclassMap(item_r10.icon);
|
|
190
218
|
i0.ɵɵadvance(2);
|
|
191
|
-
i0.ɵɵtextInterpolate(
|
|
219
|
+
i0.ɵɵtextInterpolate(item_r10.label);
|
|
192
220
|
i0.ɵɵadvance();
|
|
193
|
-
i0.ɵɵconditional(
|
|
221
|
+
i0.ɵɵconditional(item_r10.shortcut ? 4 : -1);
|
|
194
222
|
} }
|
|
195
|
-
function
|
|
196
|
-
i0.ɵɵconditionalCreate(0,
|
|
223
|
+
function ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
224
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_0_Template, 7, 8, "div", 56)(1, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Conditional_1_Template, 5, 11, "div", 57);
|
|
197
225
|
} if (rf & 2) {
|
|
198
226
|
i0.ɵɵconditional(ctx.id === "toggle-theme" ? 0 : 1);
|
|
199
227
|
} }
|
|
200
|
-
function
|
|
201
|
-
i0.ɵɵconditionalCreate(0,
|
|
228
|
+
function ShellComponent_Conditional_19_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
229
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_1_Conditional_0_Template, 2, 1);
|
|
202
230
|
} if (rf & 2) {
|
|
203
231
|
let tmp_14_0;
|
|
204
|
-
const
|
|
232
|
+
const element_r12 = i0.ɵɵnextContext().$implicit;
|
|
205
233
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
206
|
-
i0.ɵɵconditional((tmp_14_0 = ctx_r3.asMenuItem(
|
|
234
|
+
i0.ɵɵconditional((tmp_14_0 = ctx_r3.asMenuItem(element_r12)) ? 0 : -1, tmp_14_0);
|
|
207
235
|
} }
|
|
208
|
-
function
|
|
209
|
-
i0.ɵɵconditionalCreate(0,
|
|
210
|
-
i0.ɵɵconditionalCreate(1,
|
|
236
|
+
function ShellComponent_Conditional_19_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
237
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_19_For_3_Conditional_0_Template, 1, 0, "div", 55);
|
|
238
|
+
i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_19_For_3_Conditional_1_Template, 1, 1);
|
|
211
239
|
} if (rf & 2) {
|
|
212
|
-
const
|
|
240
|
+
const element_r12 = ctx.$implicit;
|
|
213
241
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
214
|
-
i0.ɵɵconditional(ctx_r3.isMenuDivider(
|
|
242
|
+
i0.ɵɵconditional(ctx_r3.isMenuDivider(element_r12) ? 0 : -1);
|
|
215
243
|
i0.ɵɵadvance();
|
|
216
|
-
i0.ɵɵconditional(!ctx_r3.isMenuDivider(
|
|
244
|
+
i0.ɵɵconditional(!ctx_r3.isMenuDivider(element_r12) ? 1 : -1);
|
|
217
245
|
} }
|
|
218
|
-
function
|
|
219
|
-
i0.ɵɵelementStart(0, "div",
|
|
220
|
-
i0.ɵɵconditionalCreate(1,
|
|
221
|
-
i0.ɵɵrepeaterCreate(2,
|
|
246
|
+
function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
247
|
+
i0.ɵɵelementStart(0, "div", 49);
|
|
248
|
+
i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_19_Conditional_1_Template, 7, 3);
|
|
249
|
+
i0.ɵɵrepeaterCreate(2, ShellComponent_Conditional_19_For_3_Template, 2, 2, null, null, i0.ɵɵrepeaterTrackByIdentity);
|
|
222
250
|
i0.ɵɵelementEnd();
|
|
223
251
|
} if (rf & 2) {
|
|
224
252
|
let tmp_3_0;
|
|
@@ -231,25 +259,25 @@ function ShellComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
|
231
259
|
i0.ɵɵadvance();
|
|
232
260
|
i0.ɵɵrepeater(ctx_r3.userMenuElements);
|
|
233
261
|
} }
|
|
234
|
-
function
|
|
235
|
-
const _r12 = i0.ɵɵgetCurrentView();
|
|
236
|
-
i0.ɵɵelementStart(0, "div", 62);
|
|
237
|
-
i0.ɵɵlistener("click", function ShellComponent_Conditional_21_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeSearch()); });
|
|
238
|
-
i0.ɵɵelementEnd();
|
|
239
|
-
} }
|
|
240
|
-
function ShellComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
262
|
+
function ShellComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
241
263
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
242
|
-
i0.ɵɵelementStart(0, "div",
|
|
243
|
-
i0.ɵɵlistener("click", function
|
|
264
|
+
i0.ɵɵelementStart(0, "div", 65);
|
|
265
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_20_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeSearch()); });
|
|
244
266
|
i0.ɵɵelementEnd();
|
|
245
267
|
} }
|
|
246
|
-
function
|
|
268
|
+
function ShellComponent_Conditional_28_Template(rf, ctx) { if (rf & 1) {
|
|
247
269
|
const _r14 = i0.ɵɵgetCurrentView();
|
|
248
|
-
i0.ɵɵelementStart(0, "div",
|
|
270
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
271
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_28_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeMobileNav()); });
|
|
272
|
+
i0.ɵɵelementEnd();
|
|
273
|
+
} }
|
|
274
|
+
function ShellComponent_Conditional_35_Template(rf, ctx) { if (rf & 1) {
|
|
275
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
276
|
+
i0.ɵɵelementStart(0, "div", 35)(1, "div", 67);
|
|
249
277
|
i0.ɵɵtext(2);
|
|
250
278
|
i0.ɵɵelementEnd();
|
|
251
|
-
i0.ɵɵelementStart(3, "mj-app-nav",
|
|
252
|
-
i0.ɵɵlistener("navItemClick", function
|
|
279
|
+
i0.ɵɵelementStart(3, "mj-app-nav", 68);
|
|
280
|
+
i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_35_Template_mj_app_nav_navItemClick_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_35_Template_mj_app_nav_navItemDismiss_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
|
|
253
281
|
i0.ɵɵelementEnd()();
|
|
254
282
|
} if (rf & 2) {
|
|
255
283
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -258,8 +286,8 @@ function ShellComponent_Conditional_36_Template(rf, ctx) { if (rf & 1) {
|
|
|
258
286
|
i0.ɵɵadvance();
|
|
259
287
|
i0.ɵɵproperty("app", ctx_r3.activeApp);
|
|
260
288
|
} }
|
|
261
|
-
function
|
|
262
|
-
i0.ɵɵelementStart(0, "span",
|
|
289
|
+
function ShellComponent_Conditional_45_Template(rf, ctx) { if (rf & 1) {
|
|
290
|
+
i0.ɵɵelementStart(0, "span", 39);
|
|
263
291
|
i0.ɵɵtext(1);
|
|
264
292
|
i0.ɵɵelementEnd();
|
|
265
293
|
} if (rf & 2) {
|
|
@@ -267,25 +295,25 @@ function ShellComponent_Conditional_46_Template(rf, ctx) { if (rf & 1) {
|
|
|
267
295
|
i0.ɵɵadvance();
|
|
268
296
|
i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
|
|
269
297
|
} }
|
|
270
|
-
function
|
|
271
|
-
const
|
|
272
|
-
i0.ɵɵelementStart(0, "div",
|
|
273
|
-
i0.ɵɵelement(2, "i",
|
|
298
|
+
function ShellComponent_Conditional_47_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
299
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
300
|
+
i0.ɵɵelementStart(0, "div", 70)(1, "p", 71);
|
|
301
|
+
i0.ɵɵelement(2, "i", 72);
|
|
274
302
|
i0.ɵɵtext(3, " Taking longer than expected ");
|
|
275
303
|
i0.ɵɵelementEnd();
|
|
276
|
-
i0.ɵɵelementStart(4, "p",
|
|
304
|
+
i0.ɵɵelementStart(4, "p", 73);
|
|
277
305
|
i0.ɵɵtext(5, " This can happen after updates or due to cached data issues. ");
|
|
278
306
|
i0.ɵɵelementEnd();
|
|
279
|
-
i0.ɵɵelementStart(6, "button",
|
|
280
|
-
i0.ɵɵlistener("click", function
|
|
281
|
-
i0.ɵɵelement(7, "i",
|
|
307
|
+
i0.ɵɵelementStart(6, "button", 74);
|
|
308
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_47_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r16); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.ResetApplication()); });
|
|
309
|
+
i0.ɵɵelement(7, "i", 75);
|
|
282
310
|
i0.ɵɵtext(8, " Reset ");
|
|
283
311
|
i0.ɵɵelementEnd()();
|
|
284
312
|
} }
|
|
285
|
-
function
|
|
286
|
-
i0.ɵɵelementStart(0, "div",
|
|
287
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
288
|
-
i0.ɵɵconditionalCreate(2,
|
|
313
|
+
function ShellComponent_Conditional_47_Template(rf, ctx) { if (rf & 1) {
|
|
314
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
315
|
+
i0.ɵɵelement(1, "mj-loading", 69);
|
|
316
|
+
i0.ɵɵconditionalCreate(2, ShellComponent_Conditional_47_Conditional_2_Template, 9, 0, "div", 70);
|
|
289
317
|
i0.ɵɵelementEnd();
|
|
290
318
|
} if (rf & 2) {
|
|
291
319
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -294,10 +322,10 @@ function ShellComponent_Conditional_48_Template(rf, ctx) { if (rf & 1) {
|
|
|
294
322
|
i0.ɵɵadvance();
|
|
295
323
|
i0.ɵɵconditional(ctx_r3.ShowResetOption ? 2 : -1);
|
|
296
324
|
} }
|
|
297
|
-
function
|
|
298
|
-
i0.ɵɵelementStart(0, "div",
|
|
299
|
-
i0.ɵɵelement(2, "mj-loading",
|
|
300
|
-
i0.ɵɵelementStart(3, "span",
|
|
325
|
+
function ShellComponent_Conditional_51_Template(rf, ctx) { if (rf & 1) {
|
|
326
|
+
i0.ɵɵelementStart(0, "div", 44)(1, "div", 76);
|
|
327
|
+
i0.ɵɵelement(2, "mj-loading", 77);
|
|
328
|
+
i0.ɵɵelementStart(3, "span", 78);
|
|
301
329
|
i0.ɵɵtext(4);
|
|
302
330
|
i0.ɵɵelementEnd()()();
|
|
303
331
|
} if (rf & 2) {
|
|
@@ -333,10 +361,10 @@ export class ShellComponent {
|
|
|
333
361
|
commandPaletteService;
|
|
334
362
|
themeService;
|
|
335
363
|
homePinService;
|
|
364
|
+
fileOpenService;
|
|
336
365
|
subscriptions = [];
|
|
337
366
|
urlBasedNavigation = false; // Track if we're loading from a URL
|
|
338
367
|
initialNavigationComplete = false; // Track if initial navigation has completed
|
|
339
|
-
firstUrlSync = true; // Track if this is the first URL sync (for replaceUrl behavior)
|
|
340
368
|
activeApp = null;
|
|
341
369
|
loading = true;
|
|
342
370
|
initialized = false;
|
|
@@ -389,6 +417,15 @@ export class ShellComponent {
|
|
|
389
417
|
searchableEntities = [];
|
|
390
418
|
selectedEntity = null;
|
|
391
419
|
searchInput;
|
|
420
|
+
// Universal search bar
|
|
421
|
+
shellSearchComposite;
|
|
422
|
+
// Instance configuration feature flags
|
|
423
|
+
get ShowSearchBar() {
|
|
424
|
+
return InstanceConfigEngine.Instance.GetBoolean('Shell.SearchBar.Enabled', true);
|
|
425
|
+
}
|
|
426
|
+
get ShowSearchPreview() {
|
|
427
|
+
return InstanceConfigEngine.Instance.GetBoolean('Shell.SearchBar.EnablePreview', true);
|
|
428
|
+
}
|
|
392
429
|
// Tab container reference for thumbnail capture
|
|
393
430
|
tabContainerRef;
|
|
394
431
|
// App access dialog
|
|
@@ -410,7 +447,7 @@ export class ShellComponent {
|
|
|
410
447
|
return this.appManager.GetNavBarApps('Left of User Menu')
|
|
411
448
|
.filter(app => !(app.HideNavBarIconWhenActive && UUIDsEqual(app.ID, this.activeApp?.ID)));
|
|
412
449
|
}
|
|
413
|
-
constructor(appManager, workspaceManager, layoutManager, tabService, navigationService, route, router, authBase, cdr, userAvatarService, settingsDialogService, viewContainerRef, titleService, developerModeService, commandPaletteService, themeService, homePinService) {
|
|
450
|
+
constructor(appManager, workspaceManager, layoutManager, tabService, navigationService, route, router, authBase, cdr, userAvatarService, settingsDialogService, viewContainerRef, titleService, developerModeService, commandPaletteService, themeService, homePinService, fileOpenService) {
|
|
414
451
|
this.appManager = appManager;
|
|
415
452
|
this.workspaceManager = workspaceManager;
|
|
416
453
|
this.layoutManager = layoutManager;
|
|
@@ -428,6 +465,7 @@ export class ShellComponent {
|
|
|
428
465
|
this.commandPaletteService = commandPaletteService;
|
|
429
466
|
this.themeService = themeService;
|
|
430
467
|
this.homePinService = homePinService;
|
|
468
|
+
this.fileOpenService = fileOpenService;
|
|
431
469
|
// Initialize theme immediately so loading UI shows correct colors from the start
|
|
432
470
|
this.activeTheme = getActiveTheme();
|
|
433
471
|
// Initialize animation based on theme configuration
|
|
@@ -481,6 +519,10 @@ export class ShellComponent {
|
|
|
481
519
|
// Initialize application manager (subscribes to LoggedIn event)
|
|
482
520
|
this.appManager.Initialize();
|
|
483
521
|
await StartupManager.Instance.Startup();
|
|
522
|
+
// Initialize instance configuration for feature flags
|
|
523
|
+
await InstanceConfigEngine.Instance.Config(false).catch(() => {
|
|
524
|
+
LogStatus('InstanceConfigEngine initialization skipped (not critical)');
|
|
525
|
+
});
|
|
484
526
|
// Get current user
|
|
485
527
|
const md = new Metadata();
|
|
486
528
|
const user = md.CurrentUser;
|
|
@@ -627,12 +669,21 @@ export class ShellComponent {
|
|
|
627
669
|
await this.loadSearchableEntities();
|
|
628
670
|
this.initialized = true;
|
|
629
671
|
this.waitingForFirstResource = true;
|
|
630
|
-
//
|
|
631
|
-
//
|
|
632
|
-
//
|
|
633
|
-
//
|
|
672
|
+
// Decide whether to restore workspace state or honor the current URL.
|
|
673
|
+
// If the user navigated to a specific path (deep link, bookmark, typed URL),
|
|
674
|
+
// that URL takes priority — the ResourceResolver will handle tab creation.
|
|
675
|
+
// Only restore workspace state when the URL is bare root (/) or empty.
|
|
676
|
+
const initialUrl = this.router.url.split('?')[0]; // ignore query params for this check
|
|
677
|
+
const isDeepLink = initialUrl.length > 1 && initialUrl !== '/';
|
|
634
678
|
const initConfig = this.workspaceManager.GetConfiguration();
|
|
635
|
-
if (
|
|
679
|
+
if (isDeepLink) {
|
|
680
|
+
// User navigated to a specific URL — sync workspace to match the URL,
|
|
681
|
+
// not the other way around. The ResourceResolver will have created a tab
|
|
682
|
+
// for this URL; we just need to activate it.
|
|
683
|
+
await this.syncWorkspaceWithUrl(this.router.url);
|
|
684
|
+
}
|
|
685
|
+
else if (initConfig && initConfig.activeTabId) {
|
|
686
|
+
// Bare root URL — restore last workspace state
|
|
636
687
|
await this.syncActiveAppWithTab(initConfig);
|
|
637
688
|
this.syncUrlWithWorkspace(initConfig);
|
|
638
689
|
}
|
|
@@ -759,10 +810,7 @@ export class ShellComponent {
|
|
|
759
810
|
// Suppress ResourceResolver for this navigation - we're just syncing the URL
|
|
760
811
|
// to reflect the current active tab, not requesting a new tab to be opened
|
|
761
812
|
this.tabService.SuppressNextResolve();
|
|
762
|
-
|
|
763
|
-
const replaceUrl = this.firstUrlSync;
|
|
764
|
-
this.firstUrlSync = false;
|
|
765
|
-
this.router.navigateByUrl(resourceUrl, { replaceUrl });
|
|
813
|
+
this.router.navigateByUrl(resourceUrl);
|
|
766
814
|
}
|
|
767
815
|
}
|
|
768
816
|
}
|
|
@@ -781,12 +829,54 @@ export class ShellComponent {
|
|
|
781
829
|
// Activate the matching tab
|
|
782
830
|
this.workspaceManager.SetActiveTab(matchingTab.id);
|
|
783
831
|
}
|
|
832
|
+
else if (matchingTab && matchingTab.id === config.activeTabId) {
|
|
833
|
+
// Same tab is already active, but query params may have changed (back/forward within nav item)
|
|
834
|
+
const urlParams = this.extractQueryParamsFromUrl(url);
|
|
835
|
+
const tabParams = (matchingTab.configuration?.['queryParams'] || {});
|
|
836
|
+
if (!this.queryParamsEqual(urlParams, tabParams)) {
|
|
837
|
+
// URL is source of truth during back/forward — update tab config to match.
|
|
838
|
+
this.urlBasedNavigation = true;
|
|
839
|
+
try {
|
|
840
|
+
this.workspaceManager.UpdateTabConfiguration(matchingTab.id, {
|
|
841
|
+
queryParams: Object.keys(urlParams).length > 0 ? urlParams : undefined
|
|
842
|
+
});
|
|
843
|
+
this.navigationService.NotifyQueryParamsChanged(matchingTab.id, urlParams);
|
|
844
|
+
}
|
|
845
|
+
finally {
|
|
846
|
+
this.urlBasedNavigation = false;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
784
850
|
else if (!matchingTab) {
|
|
785
|
-
// No matching tab found - check if this is an app-only URL for an app with zero nav items
|
|
786
|
-
// If so, we need to create a new tab for it (the old one was replaced when navigating away)
|
|
787
851
|
await this.handleMissingTabForUrl(url);
|
|
788
852
|
}
|
|
789
853
|
}
|
|
854
|
+
/**
|
|
855
|
+
* Extract query params from a URL string, stripping any fragment (#hash).
|
|
856
|
+
*/
|
|
857
|
+
extractQueryParamsFromUrl(url) {
|
|
858
|
+
const fragmentIndex = url.indexOf('#');
|
|
859
|
+
const cleanUrl = fragmentIndex !== -1 ? url.substring(0, fragmentIndex) : url;
|
|
860
|
+
const queryIndex = cleanUrl.indexOf('?');
|
|
861
|
+
if (queryIndex === -1)
|
|
862
|
+
return {};
|
|
863
|
+
const params = new URLSearchParams(cleanUrl.substring(queryIndex + 1));
|
|
864
|
+
const result = {};
|
|
865
|
+
params.forEach((value, key) => { result[key] = value; });
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Compare two query param records for equality, normalizing encoding differences
|
|
870
|
+
* (URLSearchParams encodes spaces as +, Angular Router uses %20).
|
|
871
|
+
*/
|
|
872
|
+
queryParamsEqual(a, b) {
|
|
873
|
+
const keysA = Object.keys(a);
|
|
874
|
+
const keysB = Object.keys(b);
|
|
875
|
+
if (keysA.length !== keysB.length)
|
|
876
|
+
return false;
|
|
877
|
+
return keysA.every(key => decodeURIComponent(a[key]?.replace(/\+/g, ' ') || '') ===
|
|
878
|
+
decodeURIComponent(b[key]?.replace(/\+/g, ' ') || ''));
|
|
879
|
+
}
|
|
790
880
|
/**
|
|
791
881
|
* Handle the case where no tab matches the URL during back/forward navigation.
|
|
792
882
|
* Creates new tabs for resources when the original tab was replaced.
|
|
@@ -851,6 +941,36 @@ export class ShellComponent {
|
|
|
851
941
|
this.navigationService.OpenReport(reportId, 'Report');
|
|
852
942
|
return;
|
|
853
943
|
}
|
|
944
|
+
// Check for app-scoped search URL: /app/:appName/search/:searchInput
|
|
945
|
+
const appSearchMatch = urlPath.match(/^\/app\/([^\/]+)\/search\/(.+)$/);
|
|
946
|
+
if (appSearchMatch) {
|
|
947
|
+
const searchInput = decodeURIComponent(appSearchMatch[2]);
|
|
948
|
+
this.navigationService.OpenSearch(searchInput);
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
// Check for app nav item URL: /app/:appName/:navItemName
|
|
952
|
+
const appNavItemMatch = urlPath.match(/^\/app\/([^\/]+)\/([^\/]+)$/);
|
|
953
|
+
if (appNavItemMatch) {
|
|
954
|
+
const appPath = decodeURIComponent(appNavItemMatch[1]);
|
|
955
|
+
const navItemName = decodeURIComponent(appNavItemMatch[2]);
|
|
956
|
+
const app = this.appManager.GetAppByPath(appPath) || this.appManager.GetAppByName(appPath);
|
|
957
|
+
if (app) {
|
|
958
|
+
// Activate the app and open the nav item
|
|
959
|
+
await this.appManager.SetActiveApp(app.ID);
|
|
960
|
+
const navItems = await app.GetNavItems();
|
|
961
|
+
const navItem = navItems.find(item => item.Label === navItemName);
|
|
962
|
+
if (navItem) {
|
|
963
|
+
// Parse query params to pass as configuration
|
|
964
|
+
const qpObj = {};
|
|
965
|
+
queryParams.forEach((value, key) => { qpObj[key] = value; });
|
|
966
|
+
this.navigationService.OpenNavItem(app.ID, navItem, app.GetColor(), Object.keys(qpObj).length > 0 ? { queryParams: qpObj } : undefined);
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
console.warn('handleMissingTabForUrl: nav item not found:', navItemName, 'in app:', appPath);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
854
974
|
// Check for app-only URL: /app/:appName
|
|
855
975
|
const appOnlyMatch = urlPath.match(/^\/app\/([^\/]+)$/);
|
|
856
976
|
if (appOnlyMatch) {
|
|
@@ -868,6 +988,14 @@ export class ShellComponent {
|
|
|
868
988
|
this.workspaceManager.OpenTab(defaultTab, app.GetColor());
|
|
869
989
|
}
|
|
870
990
|
}
|
|
991
|
+
else {
|
|
992
|
+
// App has nav items — activate the app and its default nav item
|
|
993
|
+
await this.appManager.SetActiveApp(app.ID);
|
|
994
|
+
const defaultNavItem = navItems.find(item => item.isDefault) || navItems[0];
|
|
995
|
+
if (defaultNavItem) {
|
|
996
|
+
this.navigationService.OpenNavItem(app.ID, defaultNavItem, app.GetColor());
|
|
997
|
+
}
|
|
998
|
+
}
|
|
871
999
|
}
|
|
872
1000
|
return;
|
|
873
1001
|
}
|
|
@@ -1122,6 +1250,14 @@ export class ShellComponent {
|
|
|
1122
1250
|
const queryParams = config['queryParams'];
|
|
1123
1251
|
const isAppDefault = config['isAppDefault'];
|
|
1124
1252
|
const tabAppId = tab.applicationId;
|
|
1253
|
+
// Helper to append query params to a URL, preserving any existing params
|
|
1254
|
+
const appendQP = (url) => {
|
|
1255
|
+
if (!queryParams || Object.keys(queryParams).length === 0)
|
|
1256
|
+
return url;
|
|
1257
|
+
const separator = url.includes('?') ? '&' : '?';
|
|
1258
|
+
const params = new URLSearchParams(queryParams);
|
|
1259
|
+
return `${url}${separator}${params.toString()}`;
|
|
1260
|
+
};
|
|
1125
1261
|
// Helper function to get app path for URL
|
|
1126
1262
|
const getAppPath = (appIdOrName) => {
|
|
1127
1263
|
// First try by ID
|
|
@@ -1223,7 +1359,7 @@ export class ShellComponent {
|
|
|
1223
1359
|
case 'records':
|
|
1224
1360
|
// /app/:appName/record/:entityName/:recordId
|
|
1225
1361
|
if (entityName && recordId) {
|
|
1226
|
-
return `/app/${encodeURIComponent(appPath)}/record/${encodeURIComponent(entityName)}/${recordId}
|
|
1362
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/record/${encodeURIComponent(entityName)}/${recordId}`);
|
|
1227
1363
|
}
|
|
1228
1364
|
break;
|
|
1229
1365
|
case 'user views':
|
|
@@ -1235,56 +1371,67 @@ export class ShellComponent {
|
|
|
1235
1371
|
if (extraFilter) {
|
|
1236
1372
|
url += `?ExtraFilter=${encodeURIComponent(extraFilter)}`;
|
|
1237
1373
|
}
|
|
1238
|
-
return url;
|
|
1374
|
+
return appendQP(url);
|
|
1239
1375
|
}
|
|
1240
1376
|
}
|
|
1241
1377
|
else if (recordId) {
|
|
1242
1378
|
// /app/:appName/view/:viewId (saved view)
|
|
1243
|
-
return `/app/${encodeURIComponent(appPath)}/view/${recordId}
|
|
1379
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/view/${recordId}`);
|
|
1244
1380
|
}
|
|
1245
1381
|
break;
|
|
1246
1382
|
case 'dashboards':
|
|
1247
1383
|
// /app/:appName/dashboard/:dashboardId
|
|
1248
1384
|
if (recordId) {
|
|
1249
|
-
return `/app/${encodeURIComponent(appPath)}/dashboard/${recordId}
|
|
1385
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/dashboard/${recordId}`);
|
|
1250
1386
|
}
|
|
1251
1387
|
break;
|
|
1252
1388
|
case 'artifacts':
|
|
1253
1389
|
// /app/:appName/artifact/:artifactId
|
|
1254
1390
|
if (recordId) {
|
|
1255
|
-
return `/app/${encodeURIComponent(appPath)}/artifact/${recordId}
|
|
1391
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/artifact/${recordId}`);
|
|
1256
1392
|
}
|
|
1257
1393
|
break;
|
|
1258
1394
|
case 'queries':
|
|
1259
1395
|
// /app/:appName/query/:queryId
|
|
1260
1396
|
if (recordId) {
|
|
1261
|
-
return `/app/${encodeURIComponent(appPath)}/query/${recordId}
|
|
1397
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/query/${recordId}`);
|
|
1262
1398
|
}
|
|
1263
1399
|
break;
|
|
1264
1400
|
case 'reports':
|
|
1265
1401
|
// /app/:appName/report/:reportId
|
|
1266
1402
|
if (recordId) {
|
|
1267
|
-
return `/app/${encodeURIComponent(appPath)}/report/${recordId}
|
|
1403
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/report/${recordId}`);
|
|
1268
1404
|
}
|
|
1269
1405
|
break;
|
|
1270
|
-
case 'search results':
|
|
1271
|
-
// /app/:appName/search/:searchInput?Entity=...
|
|
1406
|
+
case 'search results': {
|
|
1407
|
+
// /app/:appName/search/:searchInput?minRelevance=...&Entity=...
|
|
1272
1408
|
const searchInput = config['SearchInput'];
|
|
1273
1409
|
if (searchInput) {
|
|
1274
1410
|
let url = `/app/${encodeURIComponent(appPath)}/search/${encodeURIComponent(searchInput)}`;
|
|
1411
|
+
const searchParams = new URLSearchParams();
|
|
1275
1412
|
if (entityName) {
|
|
1276
|
-
|
|
1413
|
+
searchParams.set('Entity', entityName);
|
|
1414
|
+
}
|
|
1415
|
+
if (queryParams) {
|
|
1416
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
1417
|
+
if (value != null)
|
|
1418
|
+
searchParams.set(key, value);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
if (searchParams.toString()) {
|
|
1422
|
+
url += `?${searchParams.toString()}`;
|
|
1277
1423
|
}
|
|
1278
1424
|
return url;
|
|
1279
1425
|
}
|
|
1280
1426
|
break;
|
|
1427
|
+
}
|
|
1281
1428
|
}
|
|
1282
1429
|
}
|
|
1283
1430
|
// Fallback to legacy routes (for backward compatibility during transition)
|
|
1284
1431
|
switch (resourceType) {
|
|
1285
1432
|
case 'records':
|
|
1286
1433
|
if (entityName && recordId) {
|
|
1287
|
-
return `/resource/record/${encodeURIComponent(entityName)}/${recordId}
|
|
1434
|
+
return appendQP(`/resource/record/${encodeURIComponent(entityName)}/${recordId}`);
|
|
1288
1435
|
}
|
|
1289
1436
|
break;
|
|
1290
1437
|
case 'user views':
|
|
@@ -1294,26 +1441,26 @@ export class ShellComponent {
|
|
|
1294
1441
|
if (extraFilter) {
|
|
1295
1442
|
url += `?ExtraFilter=${encodeURIComponent(extraFilter)}`;
|
|
1296
1443
|
}
|
|
1297
|
-
return url;
|
|
1444
|
+
return appendQP(url);
|
|
1298
1445
|
}
|
|
1299
1446
|
}
|
|
1300
1447
|
else if (recordId) {
|
|
1301
|
-
return `/resource/view/${recordId}
|
|
1448
|
+
return appendQP(`/resource/view/${recordId}`);
|
|
1302
1449
|
}
|
|
1303
1450
|
break;
|
|
1304
1451
|
case 'dashboards':
|
|
1305
1452
|
if (recordId) {
|
|
1306
|
-
return `/resource/dashboard/${recordId}
|
|
1453
|
+
return appendQP(`/resource/dashboard/${recordId}`);
|
|
1307
1454
|
}
|
|
1308
1455
|
break;
|
|
1309
1456
|
case 'artifacts':
|
|
1310
1457
|
if (recordId) {
|
|
1311
|
-
return `/resource/artifact/${recordId}
|
|
1458
|
+
return appendQP(`/resource/artifact/${recordId}`);
|
|
1312
1459
|
}
|
|
1313
1460
|
break;
|
|
1314
1461
|
case 'queries':
|
|
1315
1462
|
if (recordId) {
|
|
1316
|
-
return `/resource/query/${recordId}
|
|
1463
|
+
return appendQP(`/resource/query/${recordId}`);
|
|
1317
1464
|
}
|
|
1318
1465
|
break;
|
|
1319
1466
|
}
|
|
@@ -1661,7 +1808,7 @@ export class ShellComponent {
|
|
|
1661
1808
|
this.workspaceManager.SetActiveTab(defaultNavItemTab.id);
|
|
1662
1809
|
const resourceUrl = await this.buildResourceUrl(defaultNavItemTab);
|
|
1663
1810
|
if (resourceUrl) {
|
|
1664
|
-
this.router.navigateByUrl(resourceUrl
|
|
1811
|
+
this.router.navigateByUrl(resourceUrl);
|
|
1665
1812
|
}
|
|
1666
1813
|
}
|
|
1667
1814
|
else {
|
|
@@ -1677,7 +1824,7 @@ export class ShellComponent {
|
|
|
1677
1824
|
// but we can also manually trigger it here to ensure immediate update
|
|
1678
1825
|
const resourceUrl = await this.buildResourceUrl(firstTab);
|
|
1679
1826
|
if (resourceUrl) {
|
|
1680
|
-
this.router.navigateByUrl(resourceUrl
|
|
1827
|
+
this.router.navigateByUrl(resourceUrl);
|
|
1681
1828
|
}
|
|
1682
1829
|
}
|
|
1683
1830
|
}
|
|
@@ -2330,6 +2477,45 @@ export class ShellComponent {
|
|
|
2330
2477
|
}
|
|
2331
2478
|
}
|
|
2332
2479
|
// ========================================
|
|
2480
|
+
// UNIVERSAL SEARCH EVENT HANDLERS
|
|
2481
|
+
// ========================================
|
|
2482
|
+
OnGlobalKeydown(event) {
|
|
2483
|
+
const target = event.target;
|
|
2484
|
+
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)
|
|
2485
|
+
return;
|
|
2486
|
+
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
|
2487
|
+
const isCtrlOrCmd = isMac ? event.metaKey : event.ctrlKey;
|
|
2488
|
+
if (isCtrlOrCmd && event.key === 'k') {
|
|
2489
|
+
event.preventDefault();
|
|
2490
|
+
event.stopPropagation();
|
|
2491
|
+
if (this.shellSearchComposite?.Focus) {
|
|
2492
|
+
this.shellSearchComposite.Focus();
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
OnSearchResultSelected(result) {
|
|
2497
|
+
if (result.ResultType === 'storage-file') {
|
|
2498
|
+
if (!this.fileOpenService.OpenPreviewFromSearchResult(result.RawMetadata)) {
|
|
2499
|
+
this.fileOpenService.OpenFileFromSearchResult(result.RawMetadata);
|
|
2500
|
+
}
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
if (!result.EntityName || !result.RecordID)
|
|
2504
|
+
return;
|
|
2505
|
+
// Entity records — open via NavigationService
|
|
2506
|
+
const pkey = new CompositeKey([{ FieldName: 'ID', Value: result.RecordID }]);
|
|
2507
|
+
this.navigationService.OpenEntityRecord(result.EntityName, pkey);
|
|
2508
|
+
}
|
|
2509
|
+
OnSearchSubmitted(query) {
|
|
2510
|
+
if (query && query.trim().length >= 2) {
|
|
2511
|
+
const minRelevance = this.shellSearchComposite?.MinRelevancePercent;
|
|
2512
|
+
this.navigationService.OpenSearch(query, minRelevance ? { minRelevance } : undefined);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
OnSeeAllSearch(query) {
|
|
2516
|
+
this.OnSearchSubmitted(query);
|
|
2517
|
+
}
|
|
2518
|
+
// ========================================
|
|
2333
2519
|
// NOTIFICATION FUNCTIONALITY
|
|
2334
2520
|
// ========================================
|
|
2335
2521
|
/**
|
|
@@ -2419,6 +2605,12 @@ export class ShellComponent {
|
|
|
2419
2605
|
appName: accessResult.appName,
|
|
2420
2606
|
appId: accessResult.appId
|
|
2421
2607
|
};
|
|
2608
|
+
case 'not_authorized':
|
|
2609
|
+
return {
|
|
2610
|
+
type: 'no_access',
|
|
2611
|
+
appName: accessResult.appName,
|
|
2612
|
+
appId: accessResult.appId
|
|
2613
|
+
};
|
|
2422
2614
|
default:
|
|
2423
2615
|
// 'accessible' shouldn't reach here, but handle it as a generic error
|
|
2424
2616
|
return {
|
|
@@ -2574,7 +2766,7 @@ export class ShellComponent {
|
|
|
2574
2766
|
}
|
|
2575
2767
|
// Update URL to reflect the new app
|
|
2576
2768
|
const appPath = app.Path || app.Name;
|
|
2577
|
-
this.router.navigateByUrl(`/app/${encodeURIComponent(appPath)}
|
|
2769
|
+
this.router.navigateByUrl(`/app/${encodeURIComponent(appPath)}`);
|
|
2578
2770
|
}
|
|
2579
2771
|
/**
|
|
2580
2772
|
* Redirect to the first available app (fallback)
|
|
@@ -2594,93 +2786,91 @@ export class ShellComponent {
|
|
|
2594
2786
|
this.cdr.detectChanges();
|
|
2595
2787
|
}
|
|
2596
2788
|
}
|
|
2597
|
-
static ɵfac = function ShellComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShellComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i1.GoldenLayoutManager), i0.ɵɵdirectiveInject(i1.TabService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i3.ActivatedRoute), i0.ɵɵdirectiveInject(i3.Router), i0.ɵɵdirectiveInject(i4.MJAuthBase), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.UserAvatarService), i0.ɵɵdirectiveInject(i6.SettingsDialogService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i2.TitleService), i0.ɵɵdirectiveInject(i2.DeveloperModeService), i0.ɵɵdirectiveInject(i7.CommandPaletteService), i0.ɵɵdirectiveInject(i2.ThemeService), i0.ɵɵdirectiveInject(i2.HomeAppPinService)); };
|
|
2789
|
+
static ɵfac = function ShellComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShellComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i1.GoldenLayoutManager), i0.ɵɵdirectiveInject(i1.TabService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i3.ActivatedRoute), i0.ɵɵdirectiveInject(i3.Router), i0.ɵɵdirectiveInject(i4.MJAuthBase), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.UserAvatarService), i0.ɵɵdirectiveInject(i6.SettingsDialogService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i2.TitleService), i0.ɵɵdirectiveInject(i2.DeveloperModeService), i0.ɵɵdirectiveInject(i7.CommandPaletteService), i0.ɵɵdirectiveInject(i2.ThemeService), i0.ɵɵdirectiveInject(i2.HomeAppPinService), i0.ɵɵdirectiveInject(i8.FileOpenService)); };
|
|
2598
2790
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShellComponent, selectors: [["mj-shell"]], viewQuery: function ShellComponent_Query(rf, ctx) { if (rf & 1) {
|
|
2599
|
-
i0.ɵɵviewQuery(_c0, 5)(TabContainerComponent, 5)(
|
|
2791
|
+
i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(TabContainerComponent, 5)(_c2, 5);
|
|
2600
2792
|
} if (rf & 2) {
|
|
2601
2793
|
let _t;
|
|
2602
2794
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInput = _t.first);
|
|
2795
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.shellSearchComposite = _t.first);
|
|
2603
2796
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.tabContainerRef = _t.first);
|
|
2604
2797
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.appAccessDialog = _t.first);
|
|
2605
2798
|
} }, hostBindings: function ShellComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
2606
|
-
i0.ɵɵlistener("keydown", function ShellComponent_keydown_HostBindingHandler($event) { return ctx.
|
|
2607
|
-
} }, standalone: false, decls:
|
|
2799
|
+
i0.ɵɵlistener("keydown", function ShellComponent_keydown_HostBindingHandler($event) { return ctx.OnGlobalKeydown($event); }, i0.ɵɵresolveDocument);
|
|
2800
|
+
} }, standalone: false, decls: 52, vars: 28, consts: [["searchInput", ""], ["appAccessDialog", ""], ["shellSearchComposite", ""], [1, "shell-container"], [1, "shell-header"], ["title", "MemberJunction", 1, "mj-logo"], ["title", "Menu", 1, "hamburger-btn", 3, "click"], [1, "fa-solid", "fa-bars"], [1, "nav-bar-apps", "left-of-switcher"], [3, "appSelected", "activeApp", "isViewingSystemTab", "loadingAppId"], [1, "desktop-nav", 3, "app"], [1, "shell-search-bar", "desktop-only"], [1, "spacer"], [1, "header-actions"], ["title", "Notifications", 1, "icon-btn", "desktop-only", "notification-btn", 3, "click"], [1, "fa-solid", "fa-bell"], [1, "notification-badge"], [1, "nav-bar-apps", "left-of-user-menu"], [1, "user-menu"], [1, "avatar-btn", 3, "click"], ["alt", "User avatar", 1, "avatar-img", 3, "src"], [1, "icon-fallback"], [1, "user-context-menu", 3, "menu-fade", "menu-slide"], [1, "search-popup-overlay"], [1, "search-popup"], [1, "search-popup-content", 3, "click"], ["TextField", "Name", "ValueField", "ID", 1, "search-entity-dropdown", 3, "ngModelChange", "Data", "ngModel"], ["type", "text", "placeholder", "Search...", 1, "mj-input", "search-input", 3, "keydown.enter"], ["title", "Search", 1, "search-submit-btn", 3, "click"], [1, "fa-solid", "fa-search"], [1, "mobile-nav-overlay"], [1, "mobile-nav-drawer"], [1, "mobile-nav-header"], [1, "close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "mobile-nav-content"], [1, "mobile-nav-footer"], ["title", "Search", 1, "mobile-nav-action", 3, "click"], ["title", "Notifications", 1, "mobile-nav-action", 3, "click"], [1, "notification-badge-mobile"], [3, "firstResourceLoadComplete", "layoutInitError"], [1, "shell-loading"], [3, "result"], [3, "AppSelected"], [1, "pin-progress-backdrop"], [1, "nav-bar-app-btn", 3, "active", "title", "--app-color"], [1, "nav-bar-app-btn", 3, "click", "dblclick", "title"], [1, "desktop-nav", 3, "navItemClick", "navItemDismiss", "app"], ["Placeholder", "Search everything...", 3, "ResultSelected", "SearchSubmitted", "SeeAllRequested", "ShowShortcutHint", "EnablePreview", "EnableRecent", "MaxPreviewResults"], [1, "user-context-menu"], [1, "user-menu-header"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "user-subtitle"], [1, "user-menu-divider"], [1, "user-menu-item", "theme-toggle-item", 3, "title"], [1, "user-menu-item", 3, "disabled", "danger", "color", "title"], [1, "user-menu-item", "theme-toggle-item", 3, "click", "title"], [1, "menu-label"], [1, "theme-toggle-track"], [1, "theme-toggle-thumb"], [1, "theme-toggle-icon"], [1, "user-menu-item", 3, "click", "title"], [1, "menu-shortcut"], [1, "search-popup-overlay", 3, "click"], [1, "mobile-nav-overlay", 3, "click"], [1, "mobile-nav-section-title"], [3, "navItemClick", "navItemDismiss", "app"], ["size", "large", 3, "text", "textColor", "logoColor", "logoGradient", "animation"], [1, "loading-reset-panel"], [1, "loading-reset-message"], [1, "fa-regular", "fa-clock"], [1, "loading-reset-hint"], [1, "loading-reset-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "pin-progress-modal"], ["size", "small", 3, "showText"], [1, "pin-progress-text"]], template: function ShellComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2608
2801
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
2609
|
-
i0.ɵɵelementStart(0, "div",
|
|
2610
|
-
i0.ɵɵelement(2, "div",
|
|
2611
|
-
i0.ɵɵelementStart(3, "button",
|
|
2802
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "header", 4);
|
|
2803
|
+
i0.ɵɵelement(2, "div", 5);
|
|
2804
|
+
i0.ɵɵelementStart(3, "button", 6);
|
|
2612
2805
|
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleMobileNav()); });
|
|
2613
|
-
i0.ɵɵelement(4, "i",
|
|
2806
|
+
i0.ɵɵelement(4, "i", 7);
|
|
2614
2807
|
i0.ɵɵelementEnd();
|
|
2615
|
-
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div",
|
|
2616
|
-
i0.ɵɵelementStart(6, "mj-app-switcher",
|
|
2808
|
+
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div", 8);
|
|
2809
|
+
i0.ɵɵelementStart(6, "mj-app-switcher", 9);
|
|
2617
2810
|
i0.ɵɵlistener("appSelected", function ShellComponent_Template_mj_app_switcher_appSelected_6_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
|
|
2618
2811
|
i0.ɵɵelementEnd();
|
|
2619
|
-
i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav",
|
|
2620
|
-
i0.ɵɵ
|
|
2621
|
-
i0.ɵɵ
|
|
2622
|
-
i0.ɵɵ
|
|
2623
|
-
i0.ɵɵ
|
|
2812
|
+
i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav", 10);
|
|
2813
|
+
i0.ɵɵconditionalCreate(8, ShellComponent_Conditional_8_Template, 3, 4, "div", 11);
|
|
2814
|
+
i0.ɵɵelement(9, "div", 12);
|
|
2815
|
+
i0.ɵɵelementStart(10, "div", 13)(11, "button", 14);
|
|
2816
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.showNotifications()); });
|
|
2817
|
+
i0.ɵɵelement(12, "i", 15);
|
|
2818
|
+
i0.ɵɵconditionalCreate(13, ShellComponent_Conditional_13_Template, 2, 1, "span", 16);
|
|
2624
2819
|
i0.ɵɵelementEnd();
|
|
2625
|
-
i0.ɵɵ
|
|
2626
|
-
i0.ɵɵ
|
|
2627
|
-
i0.ɵɵ
|
|
2628
|
-
i0.ɵɵconditionalCreate(
|
|
2820
|
+
i0.ɵɵconditionalCreate(14, ShellComponent_Conditional_14_Template, 3, 0, "div", 17);
|
|
2821
|
+
i0.ɵɵelementStart(15, "div", 18)(16, "button", 19);
|
|
2822
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_16_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
|
|
2823
|
+
i0.ɵɵconditionalCreate(17, ShellComponent_Conditional_17_Template, 1, 1, "img", 20)(18, ShellComponent_Conditional_18_Template, 2, 2, "div", 21);
|
|
2629
2824
|
i0.ɵɵelementEnd();
|
|
2630
|
-
i0.ɵɵconditionalCreate(
|
|
2631
|
-
i0.ɵɵelementStart(16, "div", 18)(17, "button", 19);
|
|
2632
|
-
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_17_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
|
|
2633
|
-
i0.ɵɵconditionalCreate(18, ShellComponent_Conditional_18_Template, 1, 1, "img", 20)(19, ShellComponent_Conditional_19_Template, 2, 2, "div", 21);
|
|
2634
|
-
i0.ɵɵelementEnd();
|
|
2635
|
-
i0.ɵɵconditionalCreate(20, ShellComponent_Conditional_20_Template, 4, 5, "div", 22);
|
|
2825
|
+
i0.ɵɵconditionalCreate(19, ShellComponent_Conditional_19_Template, 4, 5, "div", 22);
|
|
2636
2826
|
i0.ɵɵelementEnd()()();
|
|
2637
|
-
i0.ɵɵconditionalCreate(
|
|
2638
|
-
i0.ɵɵelementStart(
|
|
2639
|
-
i0.ɵɵlistener("click", function
|
|
2640
|
-
i0.ɵɵelementStart(
|
|
2641
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
2827
|
+
i0.ɵɵconditionalCreate(20, ShellComponent_Conditional_20_Template, 1, 0, "div", 23);
|
|
2828
|
+
i0.ɵɵelementStart(21, "div", 24)(22, "div", 25);
|
|
2829
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_div_click_22_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
2830
|
+
i0.ɵɵelementStart(23, "mj-dropdown", 26);
|
|
2831
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ShellComponent_Template_mj_dropdown_ngModelChange_23_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.selectedEntity, $event) || (ctx.selectedEntity = $event); return i0.ɵɵresetView($event); });
|
|
2642
2832
|
i0.ɵɵelementEnd();
|
|
2643
|
-
i0.ɵɵelementStart(
|
|
2644
|
-
i0.ɵɵlistener("keydown.enter", function
|
|
2833
|
+
i0.ɵɵelementStart(24, "input", 27, 0);
|
|
2834
|
+
i0.ɵɵlistener("keydown.enter", function ShellComponent_Template_input_keydown_enter_24_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
|
|
2645
2835
|
i0.ɵɵelementEnd();
|
|
2646
|
-
i0.ɵɵelementStart(
|
|
2647
|
-
i0.ɵɵlistener("click", function
|
|
2648
|
-
i0.ɵɵelement(
|
|
2836
|
+
i0.ɵɵelementStart(26, "button", 28);
|
|
2837
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_26_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
|
|
2838
|
+
i0.ɵɵelement(27, "i", 29);
|
|
2649
2839
|
i0.ɵɵelementEnd()()();
|
|
2650
|
-
i0.ɵɵconditionalCreate(
|
|
2651
|
-
i0.ɵɵelementStart(
|
|
2652
|
-
i0.ɵɵtext(
|
|
2840
|
+
i0.ɵɵconditionalCreate(28, ShellComponent_Conditional_28_Template, 1, 0, "div", 30);
|
|
2841
|
+
i0.ɵɵelementStart(29, "div", 31)(30, "div", 32)(31, "span");
|
|
2842
|
+
i0.ɵɵtext(32, "Navigation");
|
|
2653
2843
|
i0.ɵɵelementEnd();
|
|
2654
|
-
i0.ɵɵelementStart(
|
|
2655
|
-
i0.ɵɵlistener("click", function
|
|
2656
|
-
i0.ɵɵelement(
|
|
2844
|
+
i0.ɵɵelementStart(33, "button", 33);
|
|
2845
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_33_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
2846
|
+
i0.ɵɵelement(34, "i", 34);
|
|
2657
2847
|
i0.ɵɵelementEnd()();
|
|
2658
|
-
i0.ɵɵconditionalCreate(
|
|
2659
|
-
i0.ɵɵelementStart(
|
|
2660
|
-
i0.ɵɵlistener("click", function
|
|
2661
|
-
i0.ɵɵelement(
|
|
2662
|
-
i0.ɵɵelementStart(
|
|
2663
|
-
i0.ɵɵtext(
|
|
2848
|
+
i0.ɵɵconditionalCreate(35, ShellComponent_Conditional_35_Template, 4, 2, "div", 35);
|
|
2849
|
+
i0.ɵɵelementStart(36, "div", 36)(37, "button", 37);
|
|
2850
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_37_listener() { i0.ɵɵrestoreView(_r1); ctx.toggleSearch(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
2851
|
+
i0.ɵɵelement(38, "i", 29);
|
|
2852
|
+
i0.ɵɵelementStart(39, "span");
|
|
2853
|
+
i0.ɵɵtext(40, "Search");
|
|
2664
2854
|
i0.ɵɵelementEnd()();
|
|
2665
|
-
i0.ɵɵelementStart(
|
|
2666
|
-
i0.ɵɵlistener("click", function
|
|
2667
|
-
i0.ɵɵelement(
|
|
2668
|
-
i0.ɵɵelementStart(
|
|
2669
|
-
i0.ɵɵtext(
|
|
2855
|
+
i0.ɵɵelementStart(41, "button", 38);
|
|
2856
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_41_listener() { i0.ɵɵrestoreView(_r1); ctx.showNotifications(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
2857
|
+
i0.ɵɵelement(42, "i", 15);
|
|
2858
|
+
i0.ɵɵelementStart(43, "span");
|
|
2859
|
+
i0.ɵɵtext(44, "Notifications");
|
|
2670
2860
|
i0.ɵɵelementEnd();
|
|
2671
|
-
i0.ɵɵconditionalCreate(
|
|
2861
|
+
i0.ɵɵconditionalCreate(45, ShellComponent_Conditional_45_Template, 2, 1, "span", 39);
|
|
2672
2862
|
i0.ɵɵelementEnd()()();
|
|
2673
|
-
i0.ɵɵelementStart(
|
|
2674
|
-
i0.ɵɵlistener("firstResourceLoadComplete", function
|
|
2863
|
+
i0.ɵɵelementStart(46, "mj-tab-container", 40);
|
|
2864
|
+
i0.ɵɵlistener("firstResourceLoadComplete", function ShellComponent_Template_mj_tab_container_firstResourceLoadComplete_46_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFirstResourceLoadComplete()); })("layoutInitError", function ShellComponent_Template_mj_tab_container_layoutInitError_46_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleLayoutError()); });
|
|
2675
2865
|
i0.ɵɵelementEnd()();
|
|
2676
|
-
i0.ɵɵconditionalCreate(
|
|
2677
|
-
i0.ɵɵelementStart(
|
|
2678
|
-
i0.ɵɵlistener("result", function
|
|
2866
|
+
i0.ɵɵconditionalCreate(47, ShellComponent_Conditional_47_Template, 3, 6, "div", 41);
|
|
2867
|
+
i0.ɵɵelementStart(48, "mj-app-access-dialog", 42, 1);
|
|
2868
|
+
i0.ɵɵlistener("result", function ShellComponent_Template_mj_app_access_dialog_result_48_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppAccessDialogResult($event)); });
|
|
2679
2869
|
i0.ɵɵelementEnd();
|
|
2680
|
-
i0.ɵɵelementStart(
|
|
2681
|
-
i0.ɵɵlistener("AppSelected", function
|
|
2870
|
+
i0.ɵɵelementStart(50, "mj-command-palette", 43);
|
|
2871
|
+
i0.ɵɵlistener("AppSelected", function ShellComponent_Template_mj_command_palette_AppSelected_50_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
|
|
2682
2872
|
i0.ɵɵelementEnd();
|
|
2683
|
-
i0.ɵɵconditionalCreate(
|
|
2873
|
+
i0.ɵɵconditionalCreate(51, ShellComponent_Conditional_51_Template, 5, 2, "div", 44);
|
|
2684
2874
|
} if (rf & 2) {
|
|
2685
2875
|
i0.ɵɵclassProp("hidden", ctx.loading)("tabs-visible", ctx.tabBarVisible);
|
|
2686
2876
|
i0.ɵɵadvance(5);
|
|
@@ -2689,43 +2879,48 @@ export class ShellComponent {
|
|
|
2689
2879
|
i0.ɵɵproperty("activeApp", ctx.activeApp)("isViewingSystemTab", ctx.isViewingSystemTab)("loadingAppId", ctx.loadingAppId);
|
|
2690
2880
|
i0.ɵɵadvance();
|
|
2691
2881
|
i0.ɵɵconditional(ctx.activeApp ? 7 : -1);
|
|
2692
|
-
i0.ɵɵadvance(7);
|
|
2693
|
-
i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 14 : -1);
|
|
2694
2882
|
i0.ɵɵadvance();
|
|
2695
|
-
i0.ɵɵconditional(ctx.
|
|
2883
|
+
i0.ɵɵconditional(ctx.ShowSearchBar ? 8 : -1);
|
|
2884
|
+
i0.ɵɵadvance(5);
|
|
2885
|
+
i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 13 : -1);
|
|
2886
|
+
i0.ɵɵadvance();
|
|
2887
|
+
i0.ɵɵconditional(ctx.leftOfUserMenuApps.length > 0 ? 14 : -1);
|
|
2696
2888
|
i0.ɵɵadvance(3);
|
|
2697
|
-
i0.ɵɵconditional(ctx.userImageURL ?
|
|
2889
|
+
i0.ɵɵconditional(ctx.userImageURL ? 17 : 18);
|
|
2698
2890
|
i0.ɵɵadvance(2);
|
|
2699
|
-
i0.ɵɵconditional(ctx.userMenuVisible ?
|
|
2891
|
+
i0.ɵɵconditional(ctx.userMenuVisible ? 19 : -1);
|
|
2700
2892
|
i0.ɵɵadvance();
|
|
2701
|
-
i0.ɵɵconditional(ctx.isSearchOpen ?
|
|
2893
|
+
i0.ɵɵconditional(ctx.isSearchOpen ? 20 : -1);
|
|
2702
2894
|
i0.ɵɵadvance();
|
|
2703
2895
|
i0.ɵɵclassProp("open", ctx.isSearchOpen);
|
|
2704
2896
|
i0.ɵɵadvance(2);
|
|
2705
2897
|
i0.ɵɵproperty("Data", ctx.searchableEntities);
|
|
2706
2898
|
i0.ɵɵtwoWayProperty("ngModel", ctx.selectedEntity);
|
|
2707
2899
|
i0.ɵɵadvance(5);
|
|
2708
|
-
i0.ɵɵconditional(ctx.mobileNavOpen ?
|
|
2900
|
+
i0.ɵɵconditional(ctx.mobileNavOpen ? 28 : -1);
|
|
2709
2901
|
i0.ɵɵadvance();
|
|
2710
2902
|
i0.ɵɵclassProp("open", ctx.mobileNavOpen);
|
|
2711
2903
|
i0.ɵɵadvance(6);
|
|
2712
|
-
i0.ɵɵconditional(ctx.activeApp ?
|
|
2904
|
+
i0.ɵɵconditional(ctx.activeApp ? 35 : -1);
|
|
2713
2905
|
i0.ɵɵadvance(10);
|
|
2714
|
-
i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ?
|
|
2906
|
+
i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 45 : -1);
|
|
2715
2907
|
i0.ɵɵadvance();
|
|
2716
2908
|
i0.ɵɵclassProp("hide-tab-bar", !ctx.tabBarVisible);
|
|
2717
2909
|
i0.ɵɵadvance();
|
|
2718
|
-
i0.ɵɵconditional(ctx.loading ?
|
|
2910
|
+
i0.ɵɵconditional(ctx.loading ? 47 : -1);
|
|
2719
2911
|
i0.ɵɵadvance(4);
|
|
2720
|
-
i0.ɵɵconditional(ctx.PinProgressVisible ?
|
|
2721
|
-
} }, dependencies: [i8.NgControlStatus, i8.NgModel, i9.MJDropdownComponent, i10.LoadingComponent, i11.AppSwitcherComponent, i12.AppNavComponent, i13.TabContainerComponent, i14.AppAccessDialogComponent, i15.CommandPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] });
|
|
2912
|
+
i0.ɵɵconditional(ctx.PinProgressVisible ? 51 : -1);
|
|
2913
|
+
} }, dependencies: [i9.NgControlStatus, i9.NgModel, i10.MJDropdownComponent, i11.LoadingComponent, i12.SearchCompositeComponent, i13.AppSwitcherComponent, i14.AppNavComponent, i15.TabContainerComponent, i16.AppAccessDialogComponent, i17.CommandPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n \n\n\n position: relative;\n z-index: 500;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n.shell-search-bar[_ngcontent-%COMP%] {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar[_ngcontent-%COMP%] { display: none; }\n}\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] });
|
|
2722
2914
|
}
|
|
2723
2915
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ShellComponent, [{
|
|
2724
2916
|
type: Component,
|
|
2725
|
-
args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher -->\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n\n <!-- App Navigation (desktop only) -->\n @if (activeApp) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n\n <!-- Actions (search, notifications, user menu) -->\n <div class=\"header-actions\">\n <button class=\"icon-btn desktop-only search-toggle-btn\" title=\"Search\" (click)=\"toggleSearch()\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design token for theme switching & white-labeling */\n.mj-logo {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: fixed;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] }]
|
|
2726
|
-
}], () => [{ type: i1.ApplicationManager }, { type: i1.WorkspaceStateManager }, { type: i1.GoldenLayoutManager }, { type: i1.TabService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: i3.Router }, { type: i4.MJAuthBase }, { type: i0.ChangeDetectorRef }, { type: i5.UserAvatarService }, { type: i6.SettingsDialogService }, { type: i0.ViewContainerRef }, { type: i2.TitleService }, { type: i2.DeveloperModeService }, { type: i7.CommandPaletteService }, { type: i2.ThemeService }, { type: i2.HomeAppPinService }], { searchInput: [{
|
|
2917
|
+
args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher -->\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n\n <!-- App Navigation (desktop only) -->\n @if (activeApp) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Universal Search Bar -->\n @if (ShowSearchBar) {\n <div class=\"shell-search-bar desktop-only\">\n <mj-search-composite\n #shellSearchComposite\n Placeholder=\"Search everything...\"\n [ShowShortcutHint]=\"true\"\n [EnablePreview]=\"ShowSearchPreview\"\n [EnableRecent]=\"true\"\n [MaxPreviewResults]=\"8\"\n (ResultSelected)=\"OnSearchResultSelected($event)\"\n (SearchSubmitted)=\"OnSearchSubmitted($event)\"\n (SeeAllRequested)=\"OnSeeAllSearch($event)\">\n </mj-search-composite>\n </div>\n }\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n <!-- Actions (notifications, user menu) -->\n <div class=\"header-actions\">\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n @if (getUserDisplayInfo()?.subtitle) {\n <span class=\"user-subtitle\">{{ getUserDisplayInfo()?.subtitle }}</span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design token for theme switching & white-labeling */\n.mj-logo {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100vh;\n width: 100%;\n overflow: hidden;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n /* Creates a stacking context so children (search bar z-index: 99999, dropdown)\n are contained within this level. Modal overlays (z-index: 1000+) sit above. */\n position: relative;\n z-index: 500;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header .user-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100vh;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* ========================================\n UNIVERSAL SEARCH BAR\n ======================================== */\n.shell-search-bar {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar { display: none; }\n}\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: fixed;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}"] }]
|
|
2918
|
+
}], () => [{ type: i1.ApplicationManager }, { type: i1.WorkspaceStateManager }, { type: i1.GoldenLayoutManager }, { type: i1.TabService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: i3.Router }, { type: i4.MJAuthBase }, { type: i0.ChangeDetectorRef }, { type: i5.UserAvatarService }, { type: i6.SettingsDialogService }, { type: i0.ViewContainerRef }, { type: i2.TitleService }, { type: i2.DeveloperModeService }, { type: i7.CommandPaletteService }, { type: i2.ThemeService }, { type: i2.HomeAppPinService }, { type: i8.FileOpenService }], { searchInput: [{
|
|
2727
2919
|
type: ViewChild,
|
|
2728
2920
|
args: ['searchInput']
|
|
2921
|
+
}], shellSearchComposite: [{
|
|
2922
|
+
type: ViewChild,
|
|
2923
|
+
args: ['shellSearchComposite']
|
|
2729
2924
|
}], tabContainerRef: [{
|
|
2730
2925
|
type: ViewChild,
|
|
2731
2926
|
args: [TabContainerComponent]
|
|
@@ -2735,6 +2930,9 @@ export class ShellComponent {
|
|
|
2735
2930
|
}], handleGlobalKeyboardShortcuts: [{
|
|
2736
2931
|
type: HostListener,
|
|
2737
2932
|
args: ['document:keydown', ['$event']]
|
|
2933
|
+
}], OnGlobalKeydown: [{
|
|
2934
|
+
type: HostListener,
|
|
2935
|
+
args: ['document:keydown', ['$event']]
|
|
2738
2936
|
}] }); })();
|
|
2739
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber:
|
|
2937
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber: 47 }); })();
|
|
2740
2938
|
//# sourceMappingURL=shell.component.js.map
|