@memberjunction/ng-explorer-settings 5.3.0 → 5.4.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/__tests__/explorer-settings.test.js.map +1 -1
- package/dist/lib/account-info/account-info.component.js.map +1 -1
- package/dist/lib/appearance-settings/appearance-settings.component.js.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.js +2 -2
- package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
- package/dist/lib/application-management/application-management.component.js +2 -2
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/application-settings/application-settings.component.js.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +2 -2
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +2 -2
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
- package/dist/lib/general-settings/general-settings.component.js.map +1 -1
- package/dist/lib/module.js.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.js +2 -2
- package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
- package/dist/lib/role-management/role-management.component.js +2 -2
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/settings/settings.component.js.map +1 -1
- package/dist/lib/shared/settings-card.component.js.map +1 -1
- package/dist/lib/shared/shared-settings.module.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +2 -2
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.d.ts +60 -68
- package/dist/lib/user-app-config/user-app-config.component.d.ts.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.js +441 -302
- package/dist/lib/user-app-config/user-app-config.component.js.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.js +2 -2
- package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
- package/dist/lib/user-management/user-management.component.js +2 -2
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +17 -17
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, NgZone, ElementRef, inject } from '@angular/core';
|
|
2
2
|
import { Metadata, RunView, LogError, LogStatus } from '@memberjunction/core';
|
|
3
|
+
import { ApplicationManager } from '@memberjunction/ng-base-application';
|
|
4
|
+
import { SharedService } from '@memberjunction/ng-shared';
|
|
3
5
|
import * as i0 from "@angular/core";
|
|
4
|
-
import * as i1 from "@memberjunction/ng-
|
|
5
|
-
import * as i2 from "@memberjunction/ng-shared";
|
|
6
|
-
import * as i3 from "@memberjunction/ng-shared-generic";
|
|
6
|
+
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
7
7
|
const _forTrack0 = ($index, $item) => $item.app.ID;
|
|
8
8
|
function UserAppConfigComponent_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
9
9
|
i0.ɵɵelementStart(0, "div", 8);
|
|
@@ -19,17 +19,17 @@ function UserAppConfigComponent_Conditional_0_Conditional_10_Template(rf, ctx) {
|
|
|
19
19
|
} if (rf & 2) {
|
|
20
20
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
21
21
|
i0.ɵɵadvance(3);
|
|
22
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
22
|
+
i0.ɵɵtextInterpolate(ctx_r1.ErrorMessage);
|
|
23
23
|
} }
|
|
24
24
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
25
25
|
i0.ɵɵelementStart(0, "div", 27);
|
|
26
|
-
i0.ɵɵelement(1, "i",
|
|
26
|
+
i0.ɵɵelement(1, "i", 34);
|
|
27
27
|
i0.ɵɵelementStart(2, "p");
|
|
28
28
|
i0.ɵɵtext(3, "All applications added!");
|
|
29
29
|
i0.ɵɵelementEnd()();
|
|
30
30
|
} }
|
|
31
31
|
function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
-
i0.ɵɵelementStart(0, "span",
|
|
32
|
+
i0.ɵɵelementStart(0, "span", 40);
|
|
33
33
|
i0.ɵɵtext(1);
|
|
34
34
|
i0.ɵɵelementEnd();
|
|
35
35
|
} if (rf & 2) {
|
|
@@ -39,19 +39,19 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Conditional_
|
|
|
39
39
|
} }
|
|
40
40
|
function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template(rf, ctx) { if (rf & 1) {
|
|
41
41
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
42
|
-
i0.ɵɵelementStart(0, "div",
|
|
43
|
-
i0.ɵɵlistener("dblclick", function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template_div_dblclick_0_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.
|
|
44
|
-
i0.ɵɵelementStart(1, "div",
|
|
45
|
-
i0.ɵɵelement(2, "i",
|
|
42
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
43
|
+
i0.ɵɵlistener("dblclick", function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template_div_dblclick_0_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.AddApp(item_r5)); });
|
|
44
|
+
i0.ɵɵelementStart(1, "div", 36);
|
|
45
|
+
i0.ɵɵelement(2, "i", 37);
|
|
46
46
|
i0.ɵɵelementEnd();
|
|
47
|
-
i0.ɵɵelementStart(3, "div",
|
|
47
|
+
i0.ɵɵelementStart(3, "div", 38)(4, "span", 39);
|
|
48
48
|
i0.ɵɵtext(5);
|
|
49
49
|
i0.ɵɵelementEnd();
|
|
50
|
-
i0.ɵɵconditionalCreate(6, UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Conditional_6_Template, 2, 1, "span",
|
|
50
|
+
i0.ɵɵconditionalCreate(6, UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Conditional_6_Template, 2, 1, "span", 40);
|
|
51
51
|
i0.ɵɵelementEnd();
|
|
52
|
-
i0.ɵɵelementStart(7, "button",
|
|
53
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template_button_click_7_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.
|
|
54
|
-
i0.ɵɵelement(8, "i",
|
|
52
|
+
i0.ɵɵelementStart(7, "button", 41);
|
|
53
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template_button_click_7_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.AddApp(item_r5)); });
|
|
54
|
+
i0.ɵɵelement(8, "i", 42);
|
|
55
55
|
i0.ɵɵtext(9, " Add ");
|
|
56
56
|
i0.ɵɵelementEnd()();
|
|
57
57
|
} if (rf & 2) {
|
|
@@ -67,16 +67,16 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template(rf,
|
|
|
67
67
|
} }
|
|
68
68
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
69
69
|
i0.ɵɵelementStart(0, "div", 27);
|
|
70
|
-
i0.ɵɵelement(1, "i",
|
|
70
|
+
i0.ɵɵelement(1, "i", 43);
|
|
71
71
|
i0.ɵɵelementStart(2, "p");
|
|
72
72
|
i0.ɵɵtext(3, "No applications selected");
|
|
73
73
|
i0.ɵɵelementEnd();
|
|
74
|
-
i0.ɵɵelementStart(4, "p",
|
|
74
|
+
i0.ɵɵelementStart(4, "p", 44);
|
|
75
75
|
i0.ɵɵtext(5, "Add apps from the available list");
|
|
76
76
|
i0.ɵɵelementEnd()();
|
|
77
77
|
} }
|
|
78
78
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
79
|
-
i0.ɵɵelementStart(0, "span",
|
|
79
|
+
i0.ɵɵelementStart(0, "span", 40);
|
|
80
80
|
i0.ɵɵtext(1);
|
|
81
81
|
i0.ɵɵelementEnd();
|
|
82
82
|
} if (rf & 2) {
|
|
@@ -86,36 +86,36 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_
|
|
|
86
86
|
} }
|
|
87
87
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
88
88
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
89
|
-
i0.ɵɵelementStart(0, "div",
|
|
90
|
-
i0.ɵɵlistener("dragstart", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_div_dragstart_0_listener($event) { const ctx_r7 = i0.ɵɵrestoreView(_r7); const item_r9 = ctx_r7.$implicit; const ɵ$index_115_r10 = ctx_r7.$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.
|
|
91
|
-
i0.ɵɵelementStart(1, "div",
|
|
92
|
-
i0.ɵɵelement(3, "i",
|
|
89
|
+
i0.ɵɵelementStart(0, "div", 47);
|
|
90
|
+
i0.ɵɵlistener("dragstart", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_div_dragstart_0_listener($event) { const ctx_r7 = i0.ɵɵrestoreView(_r7); const item_r9 = ctx_r7.$implicit; const ɵ$index_115_r10 = ctx_r7.$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnDragStart($event, item_r9, ɵ$index_115_r10)); })("dragend", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_div_dragend_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnDragEnd()); })("dragenter", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_div_dragenter_0_listener($event) { const ɵ$index_115_r10 = i0.ɵɵrestoreView(_r7).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnDragEnter($event, ɵ$index_115_r10)); })("dblclick", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_div_dblclick_0_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.RemoveApp(item_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
91
|
+
i0.ɵɵelementStart(1, "div", 48)(2, "div", 49);
|
|
92
|
+
i0.ɵɵelement(3, "i", 50);
|
|
93
93
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵelementStart(4, "div",
|
|
95
|
-
i0.ɵɵelement(5, "i",
|
|
94
|
+
i0.ɵɵelementStart(4, "div", 36);
|
|
95
|
+
i0.ɵɵelement(5, "i", 37);
|
|
96
96
|
i0.ɵɵelementEnd();
|
|
97
|
-
i0.ɵɵelementStart(6, "div",
|
|
97
|
+
i0.ɵɵelementStart(6, "div", 38)(7, "span", 39);
|
|
98
98
|
i0.ɵɵtext(8);
|
|
99
99
|
i0.ɵɵelementEnd();
|
|
100
|
-
i0.ɵɵconditionalCreate(9, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Conditional_9_Template, 2, 1, "span",
|
|
100
|
+
i0.ɵɵconditionalCreate(9, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Conditional_9_Template, 2, 1, "span", 40);
|
|
101
101
|
i0.ɵɵelementEnd();
|
|
102
|
-
i0.ɵɵelementStart(10, "div",
|
|
103
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_11_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.
|
|
104
|
-
i0.ɵɵelement(12, "i",
|
|
102
|
+
i0.ɵɵelementStart(10, "div", 51)(11, "button", 52);
|
|
103
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_11_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.MoveUp(item_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
104
|
+
i0.ɵɵelement(12, "i", 53);
|
|
105
105
|
i0.ɵɵelementEnd();
|
|
106
|
-
i0.ɵɵelementStart(13, "button",
|
|
107
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_13_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.
|
|
108
|
-
i0.ɵɵelement(14, "i",
|
|
106
|
+
i0.ɵɵelementStart(13, "button", 54);
|
|
107
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_13_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.MoveDown(item_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
108
|
+
i0.ɵɵelement(14, "i", 55);
|
|
109
109
|
i0.ɵɵelementEnd();
|
|
110
|
-
i0.ɵɵelementStart(15, "button",
|
|
111
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_15_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.
|
|
110
|
+
i0.ɵɵelementStart(15, "button", 56);
|
|
111
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template_button_click_15_listener($event) { const item_r9 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); ctx_r1.RemoveApp(item_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
112
112
|
i0.ɵɵelement(16, "i", 6);
|
|
113
113
|
i0.ɵɵelementEnd()()()();
|
|
114
114
|
} if (rf & 2) {
|
|
115
115
|
const item_r9 = ctx.$implicit;
|
|
116
116
|
const ɵ$index_115_r10 = ctx.$index;
|
|
117
117
|
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
118
|
-
i0.ɵɵclassProp("dragging", ctx_r1.
|
|
118
|
+
i0.ɵɵclassProp("dragging", ctx_r1.DraggedItem === item_r9);
|
|
119
119
|
i0.ɵɵadvance();
|
|
120
120
|
i0.ɵɵstyleProp("border-left-color", item_r9.app.GetColor());
|
|
121
121
|
i0.ɵɵadvance(3);
|
|
@@ -129,18 +129,109 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_
|
|
|
129
129
|
i0.ɵɵadvance(2);
|
|
130
130
|
i0.ɵɵproperty("disabled", ɵ$index_115_r10 === 0);
|
|
131
131
|
i0.ɵɵadvance(2);
|
|
132
|
-
i0.ɵɵproperty("disabled", ɵ$index_115_r10 === ctx_r1.
|
|
132
|
+
i0.ɵɵproperty("disabled", ɵ$index_115_r10 === ctx_r1.ActiveApps.length - 1);
|
|
133
133
|
} }
|
|
134
134
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
135
135
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
136
|
-
i0.ɵɵelementStart(0, "div",
|
|
137
|
-
i0.ɵɵlistener("dragover", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_Template_div_dragover_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.
|
|
138
|
-
i0.ɵɵrepeaterCreate(1, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template, 17, 12, "div",
|
|
136
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
137
|
+
i0.ɵɵlistener("dragover", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_Template_div_dragover_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnDragOver($event)); })("drop", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_Template_div_drop_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnDrop($event)); });
|
|
138
|
+
i0.ɵɵrepeaterCreate(1, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_For_2_Template, 17, 12, "div", 46, _forTrack0);
|
|
139
|
+
i0.ɵɵelementEnd();
|
|
140
|
+
} if (rf & 2) {
|
|
141
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
142
|
+
i0.ɵɵadvance();
|
|
143
|
+
i0.ɵɵrepeater(ctx_r1.ActiveApps);
|
|
144
|
+
} }
|
|
145
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
146
|
+
i0.ɵɵelement(0, "div", 58);
|
|
147
|
+
} }
|
|
148
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
149
|
+
i0.ɵɵelement(0, "div", 58);
|
|
150
|
+
} }
|
|
151
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
152
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
153
|
+
i0.ɵɵconditionalCreate(0, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Conditional_0_Template, 1, 0, "div", 58);
|
|
154
|
+
i0.ɵɵelementStart(1, "div", 59)(2, "div", 60);
|
|
155
|
+
i0.ɵɵlistener("touchstart", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Template_div_touchstart_2_listener($event) { const ɵ$index_159_r12 = i0.ɵɵrestoreView(_r11).$index; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnTouchDragStart($event, ɵ$index_159_r12)); });
|
|
156
|
+
i0.ɵɵelement(3, "i", 50);
|
|
157
|
+
i0.ɵɵelementEnd();
|
|
158
|
+
i0.ɵɵelementStart(4, "div", 36);
|
|
159
|
+
i0.ɵɵelement(5, "i", 37);
|
|
160
|
+
i0.ɵɵelementEnd();
|
|
161
|
+
i0.ɵɵelementStart(6, "span", 61);
|
|
162
|
+
i0.ɵɵtext(7);
|
|
163
|
+
i0.ɵɵelementEnd();
|
|
164
|
+
i0.ɵɵelementStart(8, "button", 62);
|
|
165
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Template_button_click_8_listener() { const item_r13 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ToggleApp(item_r13)); });
|
|
166
|
+
i0.ɵɵelement(9, "i", 63);
|
|
167
|
+
i0.ɵɵelementEnd()();
|
|
168
|
+
i0.ɵɵconditionalCreate(10, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Conditional_10_Template, 1, 0, "div", 58);
|
|
169
|
+
} if (rf & 2) {
|
|
170
|
+
const item_r13 = ctx.$implicit;
|
|
171
|
+
const ɵ$index_159_r12 = ctx.$index;
|
|
172
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
173
|
+
i0.ɵɵconditional(ctx_r1.TouchDragActive && ctx_r1.TouchDropIndex === ɵ$index_159_r12 && ctx_r1.TouchDragIndex > ɵ$index_159_r12 ? 0 : -1);
|
|
174
|
+
i0.ɵɵadvance();
|
|
175
|
+
i0.ɵɵclassProp("touch-ghost", ctx_r1.TouchDragActive && ctx_r1.TouchDragIndex === ɵ$index_159_r12);
|
|
176
|
+
i0.ɵɵadvance(3);
|
|
177
|
+
i0.ɵɵstyleProp("background-color", item_r13.app.GetColor());
|
|
178
|
+
i0.ɵɵadvance();
|
|
179
|
+
i0.ɵɵclassMap(item_r13.app.Icon || "fa-solid fa-cube");
|
|
180
|
+
i0.ɵɵadvance(2);
|
|
181
|
+
i0.ɵɵtextInterpolate(item_r13.app.Name);
|
|
182
|
+
i0.ɵɵadvance();
|
|
183
|
+
i0.ɵɵariaProperty("aria-label", i0.ɵɵinterpolate1("Remove ", item_r13.app.Name));
|
|
184
|
+
i0.ɵɵadvance(2);
|
|
185
|
+
i0.ɵɵconditional(ctx_r1.TouchDragActive && ctx_r1.TouchDropIndex === ɵ$index_159_r12 && ctx_r1.TouchDragIndex < ɵ$index_159_r12 ? 10 : -1);
|
|
186
|
+
} }
|
|
187
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
188
|
+
i0.ɵɵelement(0, "div", 58);
|
|
189
|
+
} }
|
|
190
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
191
|
+
i0.ɵɵelementStart(0, "div", 57);
|
|
192
|
+
i0.ɵɵtext(1, "Your Apps");
|
|
139
193
|
i0.ɵɵelementEnd();
|
|
194
|
+
i0.ɵɵrepeaterCreate(2, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_For_3_Template, 11, 11, null, null, _forTrack0);
|
|
195
|
+
i0.ɵɵconditionalCreate(4, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_Conditional_4_Template, 1, 0, "div", 58);
|
|
140
196
|
} if (rf & 2) {
|
|
141
197
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
198
|
+
i0.ɵɵadvance(2);
|
|
199
|
+
i0.ɵɵrepeater(ctx_r1.ActiveApps);
|
|
200
|
+
i0.ɵɵadvance(2);
|
|
201
|
+
i0.ɵɵconditional(ctx_r1.TouchDragActive && ctx_r1.TouchDropIndex === ctx_r1.ActiveApps.length - 1 && ctx_r1.TouchDragIndex < ctx_r1.TouchDropIndex ? 4 : -1);
|
|
202
|
+
} }
|
|
203
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_30_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
204
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
205
|
+
i0.ɵɵelementStart(0, "div", 64)(1, "div", 36);
|
|
206
|
+
i0.ɵɵelement(2, "i", 37);
|
|
207
|
+
i0.ɵɵelementEnd();
|
|
208
|
+
i0.ɵɵelementStart(3, "span", 61);
|
|
209
|
+
i0.ɵɵtext(4);
|
|
210
|
+
i0.ɵɵelementEnd();
|
|
211
|
+
i0.ɵɵelementStart(5, "button", 65);
|
|
212
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_30_For_3_Template_button_click_5_listener() { const item_r15 = i0.ɵɵrestoreView(_r14).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ToggleApp(item_r15)); });
|
|
213
|
+
i0.ɵɵelement(6, "i", 66);
|
|
214
|
+
i0.ɵɵelementEnd()();
|
|
215
|
+
} if (rf & 2) {
|
|
216
|
+
const item_r15 = ctx.$implicit;
|
|
217
|
+
i0.ɵɵadvance();
|
|
218
|
+
i0.ɵɵstyleProp("background-color", item_r15.app.GetColor());
|
|
142
219
|
i0.ɵɵadvance();
|
|
143
|
-
i0.ɵɵ
|
|
220
|
+
i0.ɵɵclassMap(item_r15.app.Icon || "fa-solid fa-cube");
|
|
221
|
+
i0.ɵɵadvance(2);
|
|
222
|
+
i0.ɵɵtextInterpolate(item_r15.app.Name);
|
|
223
|
+
i0.ɵɵadvance();
|
|
224
|
+
i0.ɵɵariaProperty("aria-label", i0.ɵɵinterpolate1("Add ", item_r15.app.Name));
|
|
225
|
+
} }
|
|
226
|
+
function UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_30_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
i0.ɵɵelementStart(0, "div", 57);
|
|
228
|
+
i0.ɵɵtext(1, "Available");
|
|
229
|
+
i0.ɵɵelementEnd();
|
|
230
|
+
i0.ɵɵrepeaterCreate(2, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_30_For_3_Template, 7, 7, "div", 64, _forTrack0);
|
|
231
|
+
} if (rf & 2) {
|
|
232
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
233
|
+
i0.ɵɵadvance(2);
|
|
234
|
+
i0.ɵɵrepeater(ctx_r1.AvailableApps);
|
|
144
235
|
} }
|
|
145
236
|
function UserAppConfigComponent_Conditional_0_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
146
237
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
@@ -148,7 +239,7 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_Template(rf, ctx) {
|
|
|
148
239
|
i0.ɵɵtext(2, " Select which applications appear in your app switcher and arrange them in your preferred order. Double-click to quickly add or remove. Drag and drop to reorder, or use the arrow buttons. ");
|
|
149
240
|
i0.ɵɵelementEnd();
|
|
150
241
|
i0.ɵɵelementStart(3, "div", 20)(4, "div", 21)(5, "div", 22);
|
|
151
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_click_5_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.
|
|
242
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_click_5_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.AvailablePanelCollapsed = !ctx_r1.AvailablePanelCollapsed); });
|
|
152
243
|
i0.ɵɵelement(6, "i", 23);
|
|
153
244
|
i0.ɵɵelementStart(7, "h3");
|
|
154
245
|
i0.ɵɵtext(8, "Available Applications");
|
|
@@ -163,7 +254,7 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_Template(rf, ctx) {
|
|
|
163
254
|
i0.ɵɵrepeaterCreate(14, UserAppConfigComponent_Conditional_0_Conditional_11_For_15_Template, 10, 6, "div", 28, _forTrack0);
|
|
164
255
|
i0.ɵɵelementEnd()();
|
|
165
256
|
i0.ɵɵelementStart(16, "div", 29)(17, "div", 22);
|
|
166
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_click_17_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.
|
|
257
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_click_17_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectedPanelCollapsed = !ctx_r1.SelectedPanelCollapsed); });
|
|
167
258
|
i0.ɵɵelement(18, "i", 30);
|
|
168
259
|
i0.ɵɵelementStart(19, "h3");
|
|
169
260
|
i0.ɵɵtext(20, "Your Applications");
|
|
@@ -176,43 +267,53 @@ function UserAppConfigComponent_Conditional_0_Conditional_11_Template(rf, ctx) {
|
|
|
176
267
|
i0.ɵɵelementStart(24, "div", 26);
|
|
177
268
|
i0.ɵɵconditionalCreate(25, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_25_Template, 6, 0, "div", 27);
|
|
178
269
|
i0.ɵɵconditionalCreate(26, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_26_Template, 3, 0, "div", 31);
|
|
179
|
-
i0.ɵɵelementEnd()()()
|
|
270
|
+
i0.ɵɵelementEnd()()();
|
|
271
|
+
i0.ɵɵelementStart(27, "div", 32);
|
|
272
|
+
i0.ɵɵlistener("touchmove", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_touchmove_27_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTouchDragMove($event)); })("touchend", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_touchend_27_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTouchDragEnd()); })("touchcancel", function UserAppConfigComponent_Conditional_0_Conditional_11_Template_div_touchcancel_27_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTouchDragEnd()); });
|
|
273
|
+
i0.ɵɵelementStart(28, "div", 33);
|
|
274
|
+
i0.ɵɵconditionalCreate(29, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_29_Template, 5, 1);
|
|
275
|
+
i0.ɵɵconditionalCreate(30, UserAppConfigComponent_Conditional_0_Conditional_11_Conditional_30_Template, 4, 0);
|
|
276
|
+
i0.ɵɵelementEnd()()();
|
|
180
277
|
} if (rf & 2) {
|
|
181
278
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
182
279
|
i0.ɵɵadvance(4);
|
|
183
|
-
i0.ɵɵclassProp("collapsed", ctx_r1.
|
|
280
|
+
i0.ɵɵclassProp("collapsed", ctx_r1.AvailablePanelCollapsed);
|
|
184
281
|
i0.ɵɵadvance(6);
|
|
185
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
282
|
+
i0.ɵɵtextInterpolate(ctx_r1.AvailableApps.length);
|
|
186
283
|
i0.ɵɵadvance();
|
|
187
|
-
i0.ɵɵclassProp("fa-chevron-down", ctx_r1.
|
|
284
|
+
i0.ɵɵclassProp("fa-chevron-down", ctx_r1.AvailablePanelCollapsed)("fa-chevron-up", !ctx_r1.AvailablePanelCollapsed);
|
|
188
285
|
i0.ɵɵadvance(2);
|
|
189
|
-
i0.ɵɵconditional(ctx_r1.
|
|
286
|
+
i0.ɵɵconditional(ctx_r1.AvailableApps.length === 0 ? 13 : -1);
|
|
190
287
|
i0.ɵɵadvance();
|
|
191
|
-
i0.ɵɵrepeater(ctx_r1.
|
|
288
|
+
i0.ɵɵrepeater(ctx_r1.AvailableApps);
|
|
192
289
|
i0.ɵɵadvance(2);
|
|
193
|
-
i0.ɵɵclassProp("collapsed", ctx_r1.
|
|
290
|
+
i0.ɵɵclassProp("collapsed", ctx_r1.SelectedPanelCollapsed);
|
|
194
291
|
i0.ɵɵadvance(6);
|
|
195
|
-
i0.ɵɵtextInterpolate(ctx_r1.
|
|
292
|
+
i0.ɵɵtextInterpolate(ctx_r1.ActiveApps.length);
|
|
196
293
|
i0.ɵɵadvance();
|
|
197
|
-
i0.ɵɵclassProp("fa-chevron-down", ctx_r1.
|
|
294
|
+
i0.ɵɵclassProp("fa-chevron-down", ctx_r1.SelectedPanelCollapsed)("fa-chevron-up", !ctx_r1.SelectedPanelCollapsed);
|
|
198
295
|
i0.ɵɵadvance(2);
|
|
199
|
-
i0.ɵɵconditional(ctx_r1.
|
|
296
|
+
i0.ɵɵconditional(ctx_r1.ActiveApps.length === 0 ? 25 : -1);
|
|
297
|
+
i0.ɵɵadvance();
|
|
298
|
+
i0.ɵɵconditional(ctx_r1.ActiveApps.length > 0 ? 26 : -1);
|
|
299
|
+
i0.ɵɵadvance(3);
|
|
300
|
+
i0.ɵɵconditional(ctx_r1.ActiveApps.length > 0 ? 29 : -1);
|
|
200
301
|
i0.ɵɵadvance();
|
|
201
|
-
i0.ɵɵconditional(ctx_r1.
|
|
302
|
+
i0.ɵɵconditional(ctx_r1.AvailableApps.length > 0 ? 30 : -1);
|
|
202
303
|
} }
|
|
203
304
|
function UserAppConfigComponent_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
204
|
-
const
|
|
305
|
+
const _r16 = i0.ɵɵgetCurrentView();
|
|
205
306
|
i0.ɵɵelementStart(0, "button", 16);
|
|
206
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
207
|
-
i0.ɵɵelement(1, "i",
|
|
307
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.Reset()); });
|
|
308
|
+
i0.ɵɵelement(1, "i", 67);
|
|
208
309
|
i0.ɵɵtext(2, " Reset Changes ");
|
|
209
310
|
i0.ɵɵelementEnd();
|
|
210
311
|
} if (rf & 2) {
|
|
211
312
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
212
|
-
i0.ɵɵproperty("disabled", ctx_r1.
|
|
313
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsLoading || ctx_r1.IsSaving);
|
|
213
314
|
} }
|
|
214
315
|
function UserAppConfigComponent_Conditional_0_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
215
|
-
i0.ɵɵelement(0, "mj-loading",
|
|
316
|
+
i0.ɵɵelement(0, "mj-loading", 68);
|
|
216
317
|
i0.ɵɵelementStart(1, "span");
|
|
217
318
|
i0.ɵɵtext(2, "Saving...");
|
|
218
319
|
i0.ɵɵelementEnd();
|
|
@@ -220,7 +321,7 @@ function UserAppConfigComponent_Conditional_0_Conditional_17_Template(rf, ctx) {
|
|
|
220
321
|
i0.ɵɵproperty("showText", false);
|
|
221
322
|
} }
|
|
222
323
|
function UserAppConfigComponent_Conditional_0_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
223
|
-
i0.ɵɵelement(0, "i",
|
|
324
|
+
i0.ɵɵelement(0, "i", 69);
|
|
224
325
|
i0.ɵɵelementStart(1, "span");
|
|
225
326
|
i0.ɵɵtext(2, "Save Changes");
|
|
226
327
|
i0.ɵɵelementEnd();
|
|
@@ -228,337 +329,384 @@ function UserAppConfigComponent_Conditional_0_Conditional_18_Template(rf, ctx) {
|
|
|
228
329
|
function UserAppConfigComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
229
330
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
230
331
|
i0.ɵɵelementStart(0, "div", 0);
|
|
231
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.
|
|
332
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Close()); });
|
|
232
333
|
i0.ɵɵelementEnd();
|
|
233
334
|
i0.ɵɵelementStart(1, "div", 1)(2, "div", 2)(3, "h2", 3);
|
|
234
335
|
i0.ɵɵelement(4, "i", 4);
|
|
235
336
|
i0.ɵɵtext(5, " Configure Apps ");
|
|
236
337
|
i0.ɵɵelementEnd();
|
|
237
338
|
i0.ɵɵelementStart(6, "button", 5);
|
|
238
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.
|
|
339
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Close()); });
|
|
239
340
|
i0.ɵɵelement(7, "i", 6);
|
|
240
341
|
i0.ɵɵelementEnd()();
|
|
241
342
|
i0.ɵɵelementStart(8, "div", 7);
|
|
242
343
|
i0.ɵɵconditionalCreate(9, UserAppConfigComponent_Conditional_0_Conditional_9_Template, 2, 0, "div", 8);
|
|
243
344
|
i0.ɵɵconditionalCreate(10, UserAppConfigComponent_Conditional_0_Conditional_10_Template, 4, 1, "div", 9);
|
|
244
|
-
i0.ɵɵconditionalCreate(11, UserAppConfigComponent_Conditional_0_Conditional_11_Template,
|
|
345
|
+
i0.ɵɵconditionalCreate(11, UserAppConfigComponent_Conditional_0_Conditional_11_Template, 31, 19, "div", 10);
|
|
245
346
|
i0.ɵɵelementStart(12, "div", 11)(13, "div", 12);
|
|
246
347
|
i0.ɵɵconditionalCreate(14, UserAppConfigComponent_Conditional_0_Conditional_14_Template, 3, 1, "button", 13);
|
|
247
348
|
i0.ɵɵelementEnd();
|
|
248
349
|
i0.ɵɵelementStart(15, "div", 14)(16, "button", 15);
|
|
249
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.
|
|
350
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Save()); });
|
|
250
351
|
i0.ɵɵconditionalCreate(17, UserAppConfigComponent_Conditional_0_Conditional_17_Template, 3, 1)(18, UserAppConfigComponent_Conditional_0_Conditional_18_Template, 3, 0);
|
|
251
352
|
i0.ɵɵelementEnd();
|
|
252
353
|
i0.ɵɵelementStart(19, "button", 16);
|
|
253
|
-
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.
|
|
354
|
+
i0.ɵɵlistener("click", function UserAppConfigComponent_Conditional_0_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Close()); });
|
|
254
355
|
i0.ɵɵtext(20, " Cancel ");
|
|
255
356
|
i0.ɵɵelementEnd()()()()();
|
|
256
357
|
} if (rf & 2) {
|
|
257
358
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
258
359
|
i0.ɵɵadvance(9);
|
|
259
|
-
i0.ɵɵconditional(ctx_r1.
|
|
360
|
+
i0.ɵɵconditional(ctx_r1.IsLoading ? 9 : -1);
|
|
260
361
|
i0.ɵɵadvance();
|
|
261
|
-
i0.ɵɵconditional(ctx_r1.
|
|
362
|
+
i0.ɵɵconditional(ctx_r1.ErrorMessage ? 10 : -1);
|
|
262
363
|
i0.ɵɵadvance();
|
|
263
|
-
i0.ɵɵconditional(!ctx_r1.
|
|
364
|
+
i0.ɵɵconditional(!ctx_r1.IsLoading ? 11 : -1);
|
|
264
365
|
i0.ɵɵadvance(3);
|
|
265
|
-
i0.ɵɵconditional(ctx_r1.
|
|
366
|
+
i0.ɵɵconditional(ctx_r1.HasChanges() ? 14 : -1);
|
|
266
367
|
i0.ɵɵadvance(2);
|
|
267
|
-
i0.ɵɵproperty("disabled", ctx_r1.
|
|
368
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsLoading || ctx_r1.IsSaving || !ctx_r1.HasChanges());
|
|
268
369
|
i0.ɵɵadvance();
|
|
269
|
-
i0.ɵɵconditional(ctx_r1.
|
|
370
|
+
i0.ɵɵconditional(ctx_r1.IsSaving ? 17 : 18);
|
|
270
371
|
i0.ɵɵadvance(2);
|
|
271
|
-
i0.ɵɵproperty("disabled", ctx_r1.
|
|
372
|
+
i0.ɵɵproperty("disabled", ctx_r1.IsSaving);
|
|
272
373
|
} }
|
|
273
374
|
/**
|
|
274
375
|
* Full-screen modal dialog for configuring user's application visibility and order.
|
|
275
376
|
* Allows users to:
|
|
276
377
|
* - Select which applications to show in the app switcher
|
|
277
|
-
* - Reorder applications via drag-and-drop
|
|
378
|
+
* - Reorder applications via drag-and-drop (desktop)
|
|
379
|
+
* - Toggle apps on/off in a single list (mobile)
|
|
278
380
|
*/
|
|
279
381
|
export class UserAppConfigComponent {
|
|
280
|
-
appManager;
|
|
281
|
-
sharedService;
|
|
282
|
-
cdr;
|
|
283
|
-
ngZone;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
isLoading = false;
|
|
294
|
-
isSaving = false;
|
|
295
|
-
errorMessage = '';
|
|
296
|
-
// Panel collapse state (for mobile)
|
|
297
|
-
availablePanelCollapsed = false;
|
|
298
|
-
selectedPanelCollapsed = false;
|
|
299
|
-
// Native drag-and-drop state
|
|
300
|
-
draggedItem = null;
|
|
301
|
-
draggedIndex = -1;
|
|
302
|
-
dropTargetIndex = -1;
|
|
303
|
-
constructor(appManager, sharedService, cdr, ngZone) {
|
|
304
|
-
this.appManager = appManager;
|
|
305
|
-
this.sharedService = sharedService;
|
|
306
|
-
this.cdr = cdr;
|
|
307
|
-
this.ngZone = ngZone;
|
|
382
|
+
appManager = inject(ApplicationManager);
|
|
383
|
+
sharedService = inject(SharedService);
|
|
384
|
+
cdr = inject(ChangeDetectorRef);
|
|
385
|
+
ngZone = inject(NgZone);
|
|
386
|
+
el = inject(ElementRef);
|
|
387
|
+
_showDialog = false;
|
|
388
|
+
set ShowDialog(value) {
|
|
389
|
+
if (value !== this._showDialog) {
|
|
390
|
+
this._showDialog = value;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
get ShowDialog() {
|
|
394
|
+
return this._showDialog;
|
|
308
395
|
}
|
|
396
|
+
ShowDialogChange = new EventEmitter();
|
|
397
|
+
ConfigSaved = new EventEmitter();
|
|
398
|
+
AllApps = [];
|
|
399
|
+
ActiveApps = [];
|
|
400
|
+
AvailableApps = [];
|
|
401
|
+
IsLoading = false;
|
|
402
|
+
IsSaving = false;
|
|
403
|
+
ErrorMessage = '';
|
|
404
|
+
AvailablePanelCollapsed = false;
|
|
405
|
+
SelectedPanelCollapsed = false;
|
|
406
|
+
DraggedItem = null;
|
|
407
|
+
DraggedIndex = -1;
|
|
408
|
+
DropTargetIndex = -1;
|
|
309
409
|
/**
|
|
310
410
|
* Opens the dialog and loads user's app configuration
|
|
311
411
|
*/
|
|
312
|
-
async
|
|
313
|
-
this.
|
|
314
|
-
this.
|
|
315
|
-
this.
|
|
412
|
+
async Open() {
|
|
413
|
+
this._showDialog = true;
|
|
414
|
+
this.ShowDialogChange.emit(true);
|
|
415
|
+
this.ErrorMessage = '';
|
|
316
416
|
await this.loadConfiguration();
|
|
317
417
|
}
|
|
318
418
|
/**
|
|
319
419
|
* Closes the dialog without saving
|
|
320
420
|
*/
|
|
321
|
-
|
|
322
|
-
this.
|
|
323
|
-
this.
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Loads the user's current app configuration
|
|
327
|
-
*/
|
|
328
|
-
async loadConfiguration() {
|
|
329
|
-
this.isLoading = true;
|
|
330
|
-
this.errorMessage = '';
|
|
331
|
-
try {
|
|
332
|
-
const md = new Metadata();
|
|
333
|
-
const rv = new RunView();
|
|
334
|
-
// Load all system apps from ApplicationManager
|
|
335
|
-
const systemApps = this.appManager.GetAllSystemApps();
|
|
336
|
-
// Load user's UserApplication records
|
|
337
|
-
const userAppsResult = await rv.RunView({
|
|
338
|
-
EntityName: 'MJ: User Applications',
|
|
339
|
-
ExtraFilter: `UserID = '${md.CurrentUser.ID}'`,
|
|
340
|
-
OrderBy: 'Sequence, Application',
|
|
341
|
-
ResultType: 'entity_object'
|
|
342
|
-
});
|
|
343
|
-
const userApps = userAppsResult.Success ? userAppsResult.Results : [];
|
|
344
|
-
// Build app config items
|
|
345
|
-
this.allApps = this.buildAppConfigItems(systemApps, userApps);
|
|
346
|
-
// Separate into active (selected) and available (unselected)
|
|
347
|
-
this.refreshAppLists();
|
|
348
|
-
}
|
|
349
|
-
catch (error) {
|
|
350
|
-
this.errorMessage = 'Failed to load app configuration. Please try again.';
|
|
351
|
-
LogError('Error loading app configuration:', undefined, error instanceof Error ? error.message : String(error));
|
|
352
|
-
}
|
|
353
|
-
finally {
|
|
354
|
-
this.ngZone.run(() => {
|
|
355
|
-
this.isLoading = false;
|
|
356
|
-
this.cdr.detectChanges();
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Builds app config items by matching system apps with user's UserApplication records
|
|
362
|
-
*/
|
|
363
|
-
buildAppConfigItems(systemApps, userApps) {
|
|
364
|
-
const items = [];
|
|
365
|
-
for (const app of systemApps) {
|
|
366
|
-
const userApp = userApps.find(ua => ua.ApplicationID === app.ID);
|
|
367
|
-
items.push({
|
|
368
|
-
app,
|
|
369
|
-
userAppId: userApp?.ID || null,
|
|
370
|
-
sequence: userApp?.Sequence ?? 999, // Default high sequence for unselected
|
|
371
|
-
isActive: userApp?.IsActive ?? false,
|
|
372
|
-
isDirty: false
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
return items;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Separates apps into active and available lists based on isActive state
|
|
379
|
-
*/
|
|
380
|
-
refreshAppLists() {
|
|
381
|
-
this.activeApps = this.allApps
|
|
382
|
-
.filter(item => item.isActive)
|
|
383
|
-
.sort((a, b) => a.sequence - b.sequence);
|
|
384
|
-
this.availableApps = this.allApps
|
|
385
|
-
.filter(item => !item.isActive)
|
|
386
|
-
.sort((a, b) => a.app.Name.localeCompare(b.app.Name));
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Native drag start handler
|
|
390
|
-
*/
|
|
391
|
-
onDragStart(event, item, index) {
|
|
392
|
-
this.draggedItem = item;
|
|
393
|
-
this.draggedIndex = index;
|
|
394
|
-
if (event.dataTransfer) {
|
|
395
|
-
event.dataTransfer.effectAllowed = 'move';
|
|
396
|
-
event.dataTransfer.setData('text/plain', index.toString());
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Native drag over handler - allows drop
|
|
401
|
-
*/
|
|
402
|
-
onDragOver(event) {
|
|
403
|
-
event.preventDefault();
|
|
404
|
-
if (event.dataTransfer) {
|
|
405
|
-
event.dataTransfer.dropEffect = 'move';
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Native drag enter handler - tracks drop target
|
|
410
|
-
*/
|
|
411
|
-
onDragEnter(event, index) {
|
|
412
|
-
event.preventDefault();
|
|
413
|
-
this.dropTargetIndex = index;
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Native drag end handler - cleanup
|
|
417
|
-
*/
|
|
418
|
-
onDragEnd(event) {
|
|
419
|
-
this.draggedItem = null;
|
|
420
|
-
this.draggedIndex = -1;
|
|
421
|
-
this.dropTargetIndex = -1;
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Native drop handler - reorder items
|
|
425
|
-
*/
|
|
426
|
-
onDrop(event) {
|
|
427
|
-
event.preventDefault();
|
|
428
|
-
if (this.draggedIndex >= 0 && this.dropTargetIndex >= 0 && this.draggedIndex !== this.dropTargetIndex) {
|
|
429
|
-
// Remove item from old position
|
|
430
|
-
const [movedItem] = this.activeApps.splice(this.draggedIndex, 1);
|
|
431
|
-
// Insert at new position
|
|
432
|
-
this.activeApps.splice(this.dropTargetIndex, 0, movedItem);
|
|
433
|
-
// Update sequences based on new order
|
|
434
|
-
this.activeApps.forEach((item, idx) => {
|
|
435
|
-
if (item.sequence !== idx) {
|
|
436
|
-
item.sequence = idx;
|
|
437
|
-
item.isDirty = true;
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
this.cdr.detectChanges();
|
|
441
|
-
}
|
|
442
|
-
// Reset drag state
|
|
443
|
-
this.draggedItem = null;
|
|
444
|
-
this.draggedIndex = -1;
|
|
445
|
-
this.dropTargetIndex = -1;
|
|
421
|
+
Close() {
|
|
422
|
+
this._showDialog = false;
|
|
423
|
+
this.ShowDialogChange.emit(false);
|
|
446
424
|
}
|
|
447
425
|
/**
|
|
448
426
|
* Adds an app to the user's active list
|
|
449
427
|
*/
|
|
450
|
-
|
|
428
|
+
AddApp(item) {
|
|
451
429
|
item.isActive = true;
|
|
452
|
-
item.sequence = this.
|
|
430
|
+
item.sequence = this.ActiveApps.length;
|
|
453
431
|
item.isDirty = true;
|
|
454
432
|
this.refreshAppLists();
|
|
455
433
|
}
|
|
456
434
|
/**
|
|
457
435
|
* Removes an app from the user's active list
|
|
458
436
|
*/
|
|
459
|
-
|
|
437
|
+
RemoveApp(item) {
|
|
460
438
|
item.isActive = false;
|
|
461
439
|
item.sequence = 999;
|
|
462
440
|
item.isDirty = true;
|
|
463
441
|
this.refreshAppLists();
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
442
|
+
this.resequenceActiveApps();
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Toggles an app between active and inactive
|
|
446
|
+
*/
|
|
447
|
+
ToggleApp(item) {
|
|
448
|
+
if (item.isActive) {
|
|
449
|
+
this.RemoveApp(item);
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
this.AddApp(item);
|
|
453
|
+
}
|
|
471
454
|
}
|
|
472
455
|
/**
|
|
473
456
|
* Moves an app up in the order
|
|
474
457
|
*/
|
|
475
|
-
|
|
476
|
-
const index = this.
|
|
458
|
+
MoveUp(item) {
|
|
459
|
+
const index = this.ActiveApps.indexOf(item);
|
|
477
460
|
if (index > 0) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
// Swap sequences
|
|
481
|
-
const tempSeq = item.sequence;
|
|
482
|
-
item.sequence = prevItem.sequence;
|
|
483
|
-
prevItem.sequence = tempSeq;
|
|
484
|
-
item.isDirty = true;
|
|
485
|
-
prevItem.isDirty = true;
|
|
486
|
-
// Re-sort and create new array reference to trigger change detection
|
|
487
|
-
this.activeApps = [...this.activeApps].sort((a, b) => a.sequence - b.sequence);
|
|
461
|
+
this.swapSequences(item, this.ActiveApps[index - 1]);
|
|
462
|
+
this.ActiveApps = [...this.ActiveApps].sort((a, b) => a.sequence - b.sequence);
|
|
488
463
|
}
|
|
489
464
|
}
|
|
490
465
|
/**
|
|
491
466
|
* Moves an app down in the order
|
|
492
467
|
*/
|
|
493
|
-
|
|
494
|
-
const index = this.
|
|
495
|
-
if (index < this.
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
// Swap sequences
|
|
499
|
-
const tempSeq = item.sequence;
|
|
500
|
-
item.sequence = nextItem.sequence;
|
|
501
|
-
nextItem.sequence = tempSeq;
|
|
502
|
-
item.isDirty = true;
|
|
503
|
-
nextItem.isDirty = true;
|
|
504
|
-
// Re-sort and create new array reference to trigger change detection
|
|
505
|
-
this.activeApps = [...this.activeApps].sort((a, b) => a.sequence - b.sequence);
|
|
468
|
+
MoveDown(item) {
|
|
469
|
+
const index = this.ActiveApps.indexOf(item);
|
|
470
|
+
if (index < this.ActiveApps.length - 1) {
|
|
471
|
+
this.swapSequences(item, this.ActiveApps[index + 1]);
|
|
472
|
+
this.ActiveApps = [...this.ActiveApps].sort((a, b) => a.sequence - b.sequence);
|
|
506
473
|
}
|
|
507
474
|
}
|
|
508
475
|
/**
|
|
509
476
|
* Checks if there are any unsaved changes
|
|
510
477
|
*/
|
|
511
|
-
|
|
512
|
-
return this.
|
|
478
|
+
HasChanges() {
|
|
479
|
+
return this.AllApps.some(item => item.isDirty);
|
|
513
480
|
}
|
|
514
481
|
/**
|
|
515
482
|
* Saves the user's app configuration
|
|
516
483
|
*/
|
|
517
|
-
async
|
|
518
|
-
if (!this.
|
|
519
|
-
this.
|
|
484
|
+
async Save() {
|
|
485
|
+
if (!this.HasChanges()) {
|
|
486
|
+
this.Close();
|
|
520
487
|
return;
|
|
521
488
|
}
|
|
522
|
-
this.
|
|
523
|
-
this.
|
|
489
|
+
this.IsSaving = true;
|
|
490
|
+
this.ErrorMessage = '';
|
|
524
491
|
try {
|
|
525
492
|
const md = new Metadata();
|
|
526
|
-
const
|
|
527
|
-
// Process each app config item
|
|
528
|
-
for (const item of this.allApps) {
|
|
493
|
+
for (const item of this.AllApps) {
|
|
529
494
|
if (!item.isDirty)
|
|
530
495
|
continue;
|
|
531
496
|
if (item.userAppId) {
|
|
532
|
-
// Update existing UserApplication record
|
|
533
497
|
await this.updateUserApplication(md, item);
|
|
534
498
|
}
|
|
535
499
|
else if (item.isActive) {
|
|
536
|
-
// Create new UserApplication record (only if active)
|
|
537
500
|
await this.createUserApplication(md, item);
|
|
538
501
|
}
|
|
539
|
-
// If not active and no existing record, nothing to do
|
|
540
502
|
}
|
|
541
|
-
// Reload the ApplicationManager to reflect changes
|
|
542
503
|
LogStatus('User app configuration saved, reloading ApplicationManager...');
|
|
543
504
|
await this.appManager.ReloadUserApplications();
|
|
544
505
|
this.sharedService.CreateSimpleNotification('App configuration saved successfully!', 'success', 3000);
|
|
545
|
-
this.
|
|
546
|
-
this.
|
|
506
|
+
this.ConfigSaved.emit();
|
|
507
|
+
this.Close();
|
|
547
508
|
}
|
|
548
509
|
catch (error) {
|
|
549
|
-
this.
|
|
510
|
+
this.ErrorMessage = 'Failed to save configuration. Please try again.';
|
|
550
511
|
LogError('Error saving app configuration:', undefined, error instanceof Error ? error.message : String(error));
|
|
551
512
|
}
|
|
552
513
|
finally {
|
|
553
514
|
this.ngZone.run(() => {
|
|
554
|
-
this.
|
|
515
|
+
this.IsSaving = false;
|
|
555
516
|
this.cdr.detectChanges();
|
|
556
517
|
});
|
|
557
518
|
}
|
|
558
519
|
}
|
|
559
520
|
/**
|
|
560
|
-
*
|
|
521
|
+
* Resets all changes and reloads the configuration
|
|
561
522
|
*/
|
|
523
|
+
async Reset() {
|
|
524
|
+
await this.loadConfiguration();
|
|
525
|
+
}
|
|
526
|
+
// ---------------------------------------------------------------------------
|
|
527
|
+
// Drag-and-drop handlers (desktop only)
|
|
528
|
+
// ---------------------------------------------------------------------------
|
|
529
|
+
OnDragStart(event, item, index) {
|
|
530
|
+
this.DraggedItem = item;
|
|
531
|
+
this.DraggedIndex = index;
|
|
532
|
+
if (event.dataTransfer) {
|
|
533
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
534
|
+
event.dataTransfer.setData('text/plain', index.toString());
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
OnDragOver(event) {
|
|
538
|
+
event.preventDefault();
|
|
539
|
+
if (event.dataTransfer) {
|
|
540
|
+
event.dataTransfer.dropEffect = 'move';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
OnDragEnter(event, index) {
|
|
544
|
+
event.preventDefault();
|
|
545
|
+
this.DropTargetIndex = index;
|
|
546
|
+
}
|
|
547
|
+
OnDragEnd() {
|
|
548
|
+
this.DraggedItem = null;
|
|
549
|
+
this.DraggedIndex = -1;
|
|
550
|
+
this.DropTargetIndex = -1;
|
|
551
|
+
}
|
|
552
|
+
OnDrop(event) {
|
|
553
|
+
event.preventDefault();
|
|
554
|
+
if (this.DraggedIndex >= 0 && this.DropTargetIndex >= 0 && this.DraggedIndex !== this.DropTargetIndex) {
|
|
555
|
+
const [movedItem] = this.ActiveApps.splice(this.DraggedIndex, 1);
|
|
556
|
+
this.ActiveApps.splice(this.DropTargetIndex, 0, movedItem);
|
|
557
|
+
this.resequenceActiveApps();
|
|
558
|
+
this.cdr.detectChanges();
|
|
559
|
+
}
|
|
560
|
+
this.OnDragEnd();
|
|
561
|
+
}
|
|
562
|
+
// ---------------------------------------------------------------------------
|
|
563
|
+
// Touch drag-and-drop handlers (mobile)
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
TouchDragIndex = -1;
|
|
566
|
+
TouchDropIndex = -1;
|
|
567
|
+
TouchDragActive = false;
|
|
568
|
+
touchStartY = 0;
|
|
569
|
+
touchCurrentY = 0;
|
|
570
|
+
touchRowHeight = 0;
|
|
571
|
+
touchDragElement = null;
|
|
572
|
+
touchScrollContainer = null;
|
|
573
|
+
OnTouchDragStart(event, index) {
|
|
574
|
+
const touch = event.touches[0];
|
|
575
|
+
const row = event.target.closest('.mobile-app-row');
|
|
576
|
+
if (!row)
|
|
577
|
+
return;
|
|
578
|
+
event.preventDefault();
|
|
579
|
+
this.TouchDragIndex = index;
|
|
580
|
+
this.TouchDropIndex = index;
|
|
581
|
+
this.TouchDragActive = true;
|
|
582
|
+
this.touchStartY = touch.clientY;
|
|
583
|
+
this.touchCurrentY = touch.clientY;
|
|
584
|
+
this.touchDragElement = row;
|
|
585
|
+
this.touchRowHeight = row.offsetHeight;
|
|
586
|
+
this.touchScrollContainer = this.el.nativeElement.querySelector('.mobile-list');
|
|
587
|
+
row.classList.add('touch-dragging');
|
|
588
|
+
}
|
|
589
|
+
OnTouchDragMove(event) {
|
|
590
|
+
if (!this.TouchDragActive || !this.touchDragElement)
|
|
591
|
+
return;
|
|
592
|
+
event.preventDefault();
|
|
593
|
+
const touch = event.touches[0];
|
|
594
|
+
this.touchCurrentY = touch.clientY;
|
|
595
|
+
const deltaY = this.touchCurrentY - this.touchStartY;
|
|
596
|
+
this.touchDragElement.style.transform = `translateY(${deltaY}px)`;
|
|
597
|
+
this.touchDragElement.style.zIndex = '100';
|
|
598
|
+
this.updateTouchDropTarget(deltaY);
|
|
599
|
+
this.autoScrollIfNeeded();
|
|
600
|
+
}
|
|
601
|
+
OnTouchDragEnd() {
|
|
602
|
+
if (!this.TouchDragActive)
|
|
603
|
+
return;
|
|
604
|
+
if (this.touchDragElement) {
|
|
605
|
+
this.touchDragElement.style.transform = '';
|
|
606
|
+
this.touchDragElement.style.zIndex = '';
|
|
607
|
+
this.touchDragElement.classList.remove('touch-dragging');
|
|
608
|
+
}
|
|
609
|
+
if (this.TouchDragIndex >= 0 && this.TouchDropIndex >= 0 && this.TouchDragIndex !== this.TouchDropIndex) {
|
|
610
|
+
const [movedItem] = this.ActiveApps.splice(this.TouchDragIndex, 1);
|
|
611
|
+
this.ActiveApps.splice(this.TouchDropIndex, 0, movedItem);
|
|
612
|
+
this.resequenceActiveApps();
|
|
613
|
+
}
|
|
614
|
+
this.resetTouchDragState();
|
|
615
|
+
this.cdr.detectChanges();
|
|
616
|
+
}
|
|
617
|
+
updateTouchDropTarget(deltaY) {
|
|
618
|
+
const rowsToMove = Math.round(deltaY / this.touchRowHeight);
|
|
619
|
+
const newIndex = Math.max(0, Math.min(this.ActiveApps.length - 1, this.TouchDragIndex + rowsToMove));
|
|
620
|
+
this.TouchDropIndex = newIndex;
|
|
621
|
+
}
|
|
622
|
+
autoScrollIfNeeded() {
|
|
623
|
+
if (!this.touchScrollContainer)
|
|
624
|
+
return;
|
|
625
|
+
const rect = this.touchScrollContainer.getBoundingClientRect();
|
|
626
|
+
const edgeZone = 40;
|
|
627
|
+
if (this.touchCurrentY < rect.top + edgeZone) {
|
|
628
|
+
this.touchScrollContainer.scrollTop -= 8;
|
|
629
|
+
}
|
|
630
|
+
else if (this.touchCurrentY > rect.bottom - edgeZone) {
|
|
631
|
+
this.touchScrollContainer.scrollTop += 8;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
resetTouchDragState() {
|
|
635
|
+
this.TouchDragIndex = -1;
|
|
636
|
+
this.TouchDropIndex = -1;
|
|
637
|
+
this.TouchDragActive = false;
|
|
638
|
+
this.touchDragElement = null;
|
|
639
|
+
this.touchScrollContainer = null;
|
|
640
|
+
}
|
|
641
|
+
// ---------------------------------------------------------------------------
|
|
642
|
+
// Private helpers
|
|
643
|
+
// ---------------------------------------------------------------------------
|
|
644
|
+
async loadConfiguration() {
|
|
645
|
+
this.IsLoading = true;
|
|
646
|
+
this.ErrorMessage = '';
|
|
647
|
+
try {
|
|
648
|
+
const md = new Metadata();
|
|
649
|
+
const rv = new RunView();
|
|
650
|
+
const systemApps = this.appManager.GetAllSystemApps();
|
|
651
|
+
const userAppsResult = await rv.RunView({
|
|
652
|
+
EntityName: 'MJ: User Applications',
|
|
653
|
+
Fields: ['ID', 'ApplicationID', 'Sequence', 'IsActive'],
|
|
654
|
+
ExtraFilter: `UserID = '${md.CurrentUser.ID}'`,
|
|
655
|
+
OrderBy: 'Sequence, Application',
|
|
656
|
+
ResultType: 'simple'
|
|
657
|
+
});
|
|
658
|
+
if (!userAppsResult.Success) {
|
|
659
|
+
throw new Error(userAppsResult.ErrorMessage);
|
|
660
|
+
}
|
|
661
|
+
this.AllApps = this.buildAppConfigItems(systemApps, userAppsResult.Results);
|
|
662
|
+
this.refreshAppLists();
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
this.ErrorMessage = 'Failed to load app configuration. Please try again.';
|
|
666
|
+
LogError('Error loading app configuration:', undefined, error instanceof Error ? error.message : String(error));
|
|
667
|
+
}
|
|
668
|
+
finally {
|
|
669
|
+
this.ngZone.run(() => {
|
|
670
|
+
this.IsLoading = false;
|
|
671
|
+
this.cdr.detectChanges();
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
buildAppConfigItems(systemApps, userApps) {
|
|
676
|
+
return systemApps.map(app => {
|
|
677
|
+
const userApp = userApps.find(ua => ua.ApplicationID === app.ID);
|
|
678
|
+
return {
|
|
679
|
+
app,
|
|
680
|
+
userAppId: userApp?.ID ?? null,
|
|
681
|
+
sequence: userApp?.Sequence ?? 999,
|
|
682
|
+
isActive: userApp?.IsActive ?? false,
|
|
683
|
+
isDirty: false
|
|
684
|
+
};
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
refreshAppLists() {
|
|
688
|
+
this.ActiveApps = this.AllApps
|
|
689
|
+
.filter(item => item.isActive)
|
|
690
|
+
.sort((a, b) => a.sequence - b.sequence);
|
|
691
|
+
this.AvailableApps = this.AllApps
|
|
692
|
+
.filter(item => !item.isActive)
|
|
693
|
+
.sort((a, b) => a.app.Name.localeCompare(b.app.Name));
|
|
694
|
+
}
|
|
695
|
+
resequenceActiveApps() {
|
|
696
|
+
this.ActiveApps.forEach((item, index) => {
|
|
697
|
+
if (item.sequence !== index) {
|
|
698
|
+
item.sequence = index;
|
|
699
|
+
item.isDirty = true;
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
swapSequences(a, b) {
|
|
704
|
+
const tempSeq = a.sequence;
|
|
705
|
+
a.sequence = b.sequence;
|
|
706
|
+
b.sequence = tempSeq;
|
|
707
|
+
a.isDirty = true;
|
|
708
|
+
b.isDirty = true;
|
|
709
|
+
}
|
|
562
710
|
async updateUserApplication(md, item) {
|
|
563
711
|
const userApp = await md.GetEntityObject('MJ: User Applications');
|
|
564
712
|
await userApp.Load(item.userAppId);
|
|
@@ -571,9 +719,6 @@ export class UserAppConfigComponent {
|
|
|
571
719
|
item.isDirty = false;
|
|
572
720
|
LogStatus(`Updated UserApplication for ${item.app.Name}: sequence=${item.sequence}, isActive=${item.isActive}`);
|
|
573
721
|
}
|
|
574
|
-
/**
|
|
575
|
-
* Creates a new UserApplication record
|
|
576
|
-
*/
|
|
577
722
|
async createUserApplication(md, item) {
|
|
578
723
|
const userApp = await md.GetEntityObject('MJ: User Applications');
|
|
579
724
|
userApp.NewRecord();
|
|
@@ -589,28 +734,22 @@ export class UserAppConfigComponent {
|
|
|
589
734
|
item.isDirty = false;
|
|
590
735
|
LogStatus(`Created UserApplication for ${item.app.Name}: sequence=${item.sequence}`);
|
|
591
736
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
*/
|
|
595
|
-
async reset() {
|
|
596
|
-
await this.loadConfiguration();
|
|
597
|
-
}
|
|
598
|
-
static ɵfac = function UserAppConfigComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserAppConfigComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i2.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
|
|
599
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserAppConfigComponent, selectors: [["mj-user-app-config"]], inputs: { showDialog: "showDialog" }, outputs: { showDialogChange: "showDialogChange", configSaved: "configSaved" }, standalone: false, decls: 1, vars: 1, consts: [["role", "presentation", 1, "modal-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "app-config-title", 1, "modal-dialog", "full-screen-dialog"], [1, "modal-header"], ["id", "app-config-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-grid-2"], ["aria-label", "Close dialog", 1, "modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], [1, "app-config-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-message"], [1, "config-content"], [1, "dialog-footer"], [1, "footer-left"], [1, "mj-btn", "mj-btn-secondary", 3, "disabled"], [1, "footer-right"], [1, "mj-btn", "mj-btn-primary", 3, "click", "disabled"], [1, "mj-btn", "mj-btn-secondary", 3, "click", "disabled"], ["text", "Loading your app configuration...", "size", "medium"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-exclamation"], [1, "config-description"], [1, "panels-container"], [1, "panel", "available-apps-panel"], [1, "panel-header", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], [1, "badge"], ["aria-hidden", "true", 1, "collapse-toggle", "fa-solid"], [1, "panel-content"], [1, "empty-state"], [1, "available-app-item"], [1, "panel", "selected-apps-panel"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-circle"], [1, "sortable-list"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "available-app-item", 3, "dblclick"], [1, "app-icon"], ["aria-hidden", "true"], [1, "app-info"], [1, "app-name"], [1, "app-description"], ["title", "Add to your apps", 1, "mj-btn", "mj-btn-primary", "mj-btn-outline", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["aria-hidden", "true", 1, "fa-solid", "fa-inbox"], [1, "hint"], [1, "sortable-list", 3, "dragover", "drop"], ["draggable", "true", 1, "app-item", 3, "dragging"], ["draggable", "true", 1, "app-item", 3, "dragstart", "dragend", "dragenter", "dblclick"], [1, "app-item-content"], [1, "drag-handle"], ["aria-hidden", "true", 1, "fa-solid", "fa-grip-vertical"], [1, "app-actions"], ["title", "Move up", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-up"], ["title", "Move down", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down"], ["title", "Remove from your apps", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "mj-btn-danger", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-rotate-left"], ["size", "small", 3, "showText"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"]], template: function UserAppConfigComponent_Template(rf, ctx) { if (rf & 1) {
|
|
737
|
+
static ɵfac = function UserAppConfigComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserAppConfigComponent)(); };
|
|
738
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserAppConfigComponent, selectors: [["mj-user-app-config"]], inputs: { ShowDialog: "ShowDialog" }, outputs: { ShowDialogChange: "ShowDialogChange", ConfigSaved: "ConfigSaved" }, standalone: false, decls: 1, vars: 1, consts: [["role", "presentation", 1, "modal-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "app-config-title", 1, "modal-dialog", "full-screen-dialog"], [1, "modal-header"], ["id", "app-config-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-grid-2"], ["aria-label", "Close dialog", 1, "modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], [1, "app-config-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-message"], [1, "config-content"], [1, "dialog-footer"], [1, "footer-left"], [1, "mj-btn", "mj-btn-secondary", 3, "disabled"], [1, "footer-right"], [1, "mj-btn", "mj-btn-primary", 3, "click", "disabled"], [1, "mj-btn", "mj-btn-secondary", 3, "click", "disabled"], ["text", "Loading your app configuration...", "size", "medium"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-exclamation"], [1, "config-description"], [1, "panels-container", "desktop-only"], [1, "panel", "available-apps-panel"], [1, "panel-header", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], [1, "badge"], ["aria-hidden", "true", 1, "collapse-toggle", "fa-solid"], [1, "panel-content"], [1, "empty-state"], [1, "available-app-item"], [1, "panel", "selected-apps-panel"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-circle"], [1, "sortable-list"], [1, "mobile-view", 3, "touchmove", "touchend", "touchcancel"], [1, "mobile-list"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-double"], [1, "available-app-item", 3, "dblclick"], [1, "app-icon"], ["aria-hidden", "true"], [1, "app-info"], [1, "app-name"], [1, "app-description"], ["title", "Add to your apps", 1, "mj-btn", "mj-btn-primary", "mj-btn-outline", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["aria-hidden", "true", 1, "fa-solid", "fa-inbox"], [1, "hint"], [1, "sortable-list", 3, "dragover", "drop"], ["draggable", "true", 1, "app-item", 3, "dragging"], ["draggable", "true", 1, "app-item", 3, "dragstart", "dragend", "dragenter", "dblclick"], [1, "app-item-content"], [1, "drag-handle"], ["aria-hidden", "true", 1, "fa-solid", "fa-grip-vertical"], [1, "app-actions"], ["title", "Move up", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-up"], ["title", "Move down", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down"], ["title", "Remove from your apps", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "mj-btn-danger", 3, "click"], [1, "mobile-section-label"], [1, "mobile-drop-indicator"], [1, "mobile-app-row"], ["aria-label", "Drag to reorder", 1, "mobile-drag-handle", 3, "touchstart"], [1, "mobile-app-name"], [1, "mobile-toggle", "on", 3, "click", "aria-label"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-on"], [1, "mobile-app-row", "inactive"], [1, "mobile-toggle", "off", 3, "click", "aria-label"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-off"], ["aria-hidden", "true", 1, "fa-solid", "fa-rotate-left"], ["size", "small", 3, "showText"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"]], template: function UserAppConfigComponent_Template(rf, ctx) { if (rf & 1) {
|
|
600
739
|
i0.ɵɵconditionalCreate(0, UserAppConfigComponent_Conditional_0_Template, 21, 7);
|
|
601
740
|
} if (rf & 2) {
|
|
602
|
-
i0.ɵɵconditional(ctx.
|
|
603
|
-
} }, dependencies: [i3.LoadingComponent], styles: ["\n\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n}\n\n\n\n.full-screen-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: var(--mat-sys-surface);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 0;\n font: var(--mat-sys-title-large);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mat-sys-primary);\n}\n\n.modal-close[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n border: none;\n border-radius: var(--mat-sys-corner-full);\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-close[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mat-sys-primary);\n outline-offset: 2px;\n}\n\n\n\n.app-config-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mat-sys-surface-container-lowest);\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n color: var(--mat-sys-on-surface-variant);\n}\n\n\n\n.error-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--mat-sys-error-container);\n color: var(--mat-sys-on-error-container);\n border-bottom: 1px solid var(--mat-sys-error);\n}\n\n.error-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n}\n\n\n\n.config-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 1.5rem;\n overflow: hidden;\n}\n\n.config-description[_ngcontent-%COMP%] {\n margin: 0 0 1.5rem 0;\n color: var(--mat-sys-on-surface-variant);\n font: var(--mat-sys-body-large);\n line-height: 1.5;\n}\n\n\n\n.panels-container[_ngcontent-%COMP%] {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n overflow: hidden;\n}\n\n@media (max-width: 900px) {\n .panels-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: auto;\n }\n\n \n\n .panel-header[_ngcontent-%COMP%] .collapse-toggle[_ngcontent-%COMP%] {\n display: inline-block !important;\n color: var(--mat-sys-on-surface-variant) !important;\n }\n\n \n\n .panel-header[_ngcontent-%COMP%] {\n cursor: pointer;\n user-select: none;\n }\n\n .panel-header[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container);\n }\n\n \n\n .panel.collapsed[_ngcontent-%COMP%] {\n flex: 0 0 auto !important;\n }\n\n .panel.collapsed[_ngcontent-%COMP%] .panel-content[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .panel.collapsed[_ngcontent-%COMP%] .panel-header[_ngcontent-%COMP%] {\n border-bottom: none;\n }\n\n \n\n .panel[_ngcontent-%COMP%]:not(.collapsed) {\n flex: 1 1 auto;\n min-height: 150px;\n }\n}\n\n\n\n.panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium);\n overflow: hidden;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 1rem 1.25rem;\n background: var(--mat-sys-surface-container);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.panel-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.1rem;\n color: var(--mat-sys-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font: var(--mat-sys-title-medium);\n color: var(--mat-sys-on-surface);\n flex: 1;\n}\n\n.panel-header[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary);\n padding: 0.125rem 0.625rem;\n border-radius: var(--mat-sys-corner-full);\n font: var(--mat-sys-label-medium);\n font-weight: 500;\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] .collapse-toggle[_ngcontent-%COMP%] {\n display: none;\n color: var(--mat-sys-on-surface-variant);\n font-size: 0.9rem;\n margin-left: 0.5rem;\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0.75rem;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 1.5rem;\n color: var(--mat-sys-on-surface-variant);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font: var(--mat-sys-body-large);\n}\n\n.empty-state[_ngcontent-%COMP%] .hint[_ngcontent-%COMP%] {\n margin-top: 0.25rem;\n font: var(--mat-sys-body-medium);\n opacity: 0.7;\n}\n\n\n\n.sortable-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n\n\n.app-item[_ngcontent-%COMP%] {\n cursor: grab;\n transition: transform 0.2s, opacity 0.2s;\n}\n\n.app-item[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.app-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.5;\n transform: scale(0.98);\n}\n\n.app-item-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-left-width: 4px;\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.app-item-content[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-primary);\n box-shadow: var(--mat-sys-elevation-1);\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n color: var(--mat-sys-on-surface-variant);\n cursor: grab;\n padding: 0.25rem;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.app-icon[_ngcontent-%COMP%] {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: var(--mat-sys-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 1.1rem;\n flex-shrink: 0;\n}\n\n.app-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n min-width: 0;\n}\n\n.app-name[_ngcontent-%COMP%] {\n font: var(--mat-sys-body-large);\n font-weight: 500;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-description[_ngcontent-%COMP%] {\n font: var(--mat-sys-body-small);\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n\n\n.available-app-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n margin-bottom: 0.5rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.available-app-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-surface-container);\n}\n\n.available-app-item[_ngcontent-%COMP%] .app-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.dialog-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.footer-left[_ngcontent-%COMP%], \n.footer-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n}\n\n.dialog-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n\n\n@media (max-width: 600px) {\n .config-content[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .panels-container[_ngcontent-%COMP%] {\n gap: 1rem;\n }\n\n .app-item-content[_ngcontent-%COMP%], \n .available-app-item[_ngcontent-%COMP%] {\n padding: 0.625rem 0.75rem;\n }\n\n .app-icon[_ngcontent-%COMP%] {\n width: 2.25rem;\n height: 2.25rem;\n font-size: 1rem;\n }\n\n .dialog-footer[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 0.75rem;\n }\n\n .footer-left[_ngcontent-%COMP%], \n .footer-right[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n\n\n@media (prefers-reduced-motion: reduce) {\n .app-item[_ngcontent-%COMP%], \n .app-item-content[_ngcontent-%COMP%], \n .available-app-item[_ngcontent-%COMP%], \n .modal-close[_ngcontent-%COMP%] {\n transition: none;\n }\n}"] });
|
|
741
|
+
i0.ɵɵconditional(ctx.ShowDialog ? 0 : -1);
|
|
742
|
+
} }, dependencies: [i1.LoadingComponent], styles: ["\n\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n}\n\n\n\n.full-screen-dialog[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: var(--mat-sys-surface);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 0;\n font: var(--mat-sys-title-large);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mat-sys-primary);\n}\n\n.modal-close[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n border: none;\n border-radius: var(--mat-sys-corner-full);\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-close[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mat-sys-primary);\n outline-offset: 2px;\n}\n\n\n\n.app-config-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mat-sys-surface-container-lowest);\n}\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n color: var(--mat-sys-on-surface-variant);\n}\n\n\n\n.error-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--mat-sys-error-container);\n color: var(--mat-sys-on-error-container);\n border-bottom: 1px solid var(--mat-sys-error);\n}\n\n.error-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n}\n\n\n\n.config-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 1.5rem;\n overflow: hidden;\n}\n\n.config-description[_ngcontent-%COMP%] {\n margin: 0 0 1.5rem 0;\n color: var(--mat-sys-on-surface-variant);\n font: var(--mat-sys-body-large);\n line-height: 1.5;\n}\n\n\n\n.panels-container[_ngcontent-%COMP%] {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n overflow: hidden;\n}\n\n@media (max-width: 900px) {\n .panels-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: auto;\n }\n\n \n\n .panel-header[_ngcontent-%COMP%] .collapse-toggle[_ngcontent-%COMP%] {\n display: inline-block !important;\n color: var(--mat-sys-on-surface-variant) !important;\n }\n\n \n\n .panel-header[_ngcontent-%COMP%] {\n cursor: pointer;\n user-select: none;\n }\n\n .panel-header[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container);\n }\n\n \n\n .panel.collapsed[_ngcontent-%COMP%] {\n flex: 0 0 auto !important;\n }\n\n .panel.collapsed[_ngcontent-%COMP%] .panel-content[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .panel.collapsed[_ngcontent-%COMP%] .panel-header[_ngcontent-%COMP%] {\n border-bottom: none;\n }\n\n \n\n .panel[_ngcontent-%COMP%]:not(.collapsed) {\n flex: 1 1 auto;\n min-height: 150px;\n }\n}\n\n\n\n.panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium);\n overflow: hidden;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 1rem 1.25rem;\n background: var(--mat-sys-surface-container);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.panel-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:first-child {\n font-size: 1.1rem;\n color: var(--mat-sys-primary);\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font: var(--mat-sys-title-medium);\n color: var(--mat-sys-on-surface);\n flex: 1;\n}\n\n.panel-header[_ngcontent-%COMP%] .badge[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary);\n padding: 0.125rem 0.625rem;\n border-radius: var(--mat-sys-corner-full);\n font: var(--mat-sys-label-medium);\n font-weight: 500;\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] .collapse-toggle[_ngcontent-%COMP%] {\n display: none;\n color: var(--mat-sys-on-surface-variant);\n font-size: 0.9rem;\n margin-left: 0.5rem;\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0.75rem;\n}\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 1.5rem;\n color: var(--mat-sys-on-surface-variant);\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font: var(--mat-sys-body-large);\n}\n\n.empty-state[_ngcontent-%COMP%] .hint[_ngcontent-%COMP%] {\n margin-top: 0.25rem;\n font: var(--mat-sys-body-medium);\n opacity: 0.7;\n}\n\n\n\n.sortable-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n\n\n.app-item[_ngcontent-%COMP%] {\n cursor: grab;\n transition: transform 0.2s, opacity 0.2s;\n}\n\n.app-item[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.app-item.dragging[_ngcontent-%COMP%] {\n opacity: 0.5;\n transform: scale(0.98);\n}\n\n.app-item-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-left-width: 4px;\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.app-item-content[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-primary);\n box-shadow: var(--mat-sys-elevation-1);\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n color: var(--mat-sys-on-surface-variant);\n cursor: grab;\n padding: 0.25rem;\n}\n\n.drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n}\n\n.app-icon[_ngcontent-%COMP%] {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: var(--mat-sys-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 1.1rem;\n flex-shrink: 0;\n}\n\n.app-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n min-width: 0;\n}\n\n.app-name[_ngcontent-%COMP%] {\n font: var(--mat-sys-body-large);\n font-weight: 500;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-description[_ngcontent-%COMP%] {\n font: var(--mat-sys-body-small);\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-text-secondary);\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn-ghost[_ngcontent-%COMP%]:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn-sm[_ngcontent-%COMP%] {\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n font-size: 0.8rem;\n}\n\n.app-actions[_ngcontent-%COMP%] .mj-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n\n\n.available-app-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n margin-bottom: 0.5rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.available-app-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-surface-container);\n}\n\n.available-app-item[_ngcontent-%COMP%] .app-info[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.dialog-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.footer-left[_ngcontent-%COMP%], \n.footer-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n}\n\n.dialog-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n\n\n\n\n\n\n\n.mobile-view[_ngcontent-%COMP%] {\n display: none;\n}\n\n@media (max-width: 600px) {\n \n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .config-description[_ngcontent-%COMP%] {\n display: none;\n }\n\n .mobile-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n }\n\n .mobile-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n }\n\n \n\n .mobile-section-label[_ngcontent-%COMP%] {\n padding: 0.5rem 0.625rem 0.25rem;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--mj-text-secondary);\n }\n\n \n\n .mobile-app-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.625rem;\n border-radius: var(--mj-radius-md);\n transition: background-color 0.15s ease;\n }\n\n .mobile-app-row.inactive[_ngcontent-%COMP%] {\n opacity: 0.7;\n }\n\n .mobile-app-row[_ngcontent-%COMP%] .app-icon[_ngcontent-%COMP%] {\n width: 2rem;\n height: 2rem;\n font-size: 0.875rem;\n flex-shrink: 0;\n }\n\n .mobile-app-name[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n \n\n .mobile-drag-handle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n flex-shrink: 0;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n touch-action: none;\n cursor: grab;\n padding: 0.5rem 0;\n }\n\n .mobile-drag-handle[_ngcontent-%COMP%]:active {\n cursor: grabbing;\n color: var(--mj-text-primary);\n }\n\n \n\n .mobile-app-row.touch-dragging[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-hover);\n box-shadow: var(--mj-shadow-lg);\n border-radius: var(--mj-radius-md);\n position: relative;\n z-index: 100;\n opacity: 0.95;\n }\n\n \n\n .mobile-app-row.touch-ghost[_ngcontent-%COMP%] {\n opacity: 0.3;\n }\n\n \n\n .mobile-drop-indicator[_ngcontent-%COMP%] {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 0.625rem;\n }\n\n \n\n .mobile-toggle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n padding: 0.25rem;\n cursor: pointer;\n font-size: 1.5rem;\n flex-shrink: 0;\n transition: color 0.15s ease;\n min-width: 44px;\n min-height: 44px;\n }\n\n .mobile-toggle.on[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n }\n\n .mobile-toggle.off[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n }\n\n \n\n .modal-header[_ngcontent-%COMP%] {\n padding: 0.75rem 1rem;\n }\n\n .modal-title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n\n \n\n .config-content[_ngcontent-%COMP%] {\n padding: 0;\n }\n\n \n\n .dialog-footer[_ngcontent-%COMP%] {\n padding: 0.75rem;\n gap: 0.5rem;\n }\n\n .footer-left[_ngcontent-%COMP%], \n .footer-right[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n }\n\n .dialog-footer[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 38px;\n }\n}\n\n\n\n@media (prefers-reduced-motion: reduce) {\n .app-item[_ngcontent-%COMP%], \n .app-item-content[_ngcontent-%COMP%], \n .available-app-item[_ngcontent-%COMP%], \n .modal-close[_ngcontent-%COMP%] {\n transition: none;\n }\n}"] });
|
|
604
743
|
}
|
|
605
744
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserAppConfigComponent, [{
|
|
606
745
|
type: Component,
|
|
607
|
-
args: [{ standalone: false, selector: 'mj-user-app-config', template: "<!-- Modal Backdrop -->\n@if (showDialog) {\n <div class=\"modal-backdrop\" (click)=\"close()\" role=\"presentation\"></div>\n <div\n class=\"modal-dialog full-screen-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"app-config-title\"\n >\n <!-- Dialog Header -->\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" id=\"app-config-title\">\n <i class=\"fa-solid fa-grid-2\" aria-hidden=\"true\"></i>\n Configure Apps\n </h2>\n <button\n class=\"modal-close\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"app-config-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\">\n <mj-loading text=\"Loading your app configuration...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Error Message -->\n @if (errorMessage) {\n <div class=\"error-message\" role=\"alert\">\n <i class=\"fa-solid fa-circle-exclamation\" aria-hidden=\"true\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n }\n\n <!-- Main Content -->\n @if (!isLoading) {\n <div class=\"config-content\">\n <p class=\"config-description\">\n Select which applications appear in your app switcher and arrange them in your preferred order.\n Double-click to quickly add or remove. Drag and drop to reorder, or use the arrow buttons.\n </p>\n\n <div class=\"panels-container\">\n <!-- Available Apps Panel -->\n <div class=\"panel available-apps-panel\" [class.collapsed]=\"availablePanelCollapsed\">\n <div class=\"panel-header\" (click)=\"availablePanelCollapsed = !availablePanelCollapsed\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i>\n <h3>Available Applications</h3>\n <span class=\"badge\">{{ availableApps.length }}</span>\n <i\n class=\"collapse-toggle fa-solid\"\n [class.fa-chevron-down]=\"availablePanelCollapsed\"\n [class.fa-chevron-up]=\"!availablePanelCollapsed\"\n aria-hidden=\"true\"\n ></i>\n </div>\n\n <div class=\"panel-content\">\n @if (availableApps.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <p>All applications added!</p>\n </div>\n }\n\n @for (item of availableApps; track item.app.ID) {\n <div class=\"available-app-item\" (dblclick)=\"addApp(item)\">\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-info\">\n <span class=\"app-name\">{{ item.app.Name }}</span>\n @if (item.app.Description) {\n <span class=\"app-description\">{{ item.app.Description }}</span>\n }\n </div>\n\n <button\n class=\"mj-btn mj-btn-primary mj-btn-outline mj-btn-sm\"\n (click)=\"addApp(item)\"\n title=\"Add to your apps\"\n >\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n Add\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Selected Apps Panel -->\n <div class=\"panel selected-apps-panel\" [class.collapsed]=\"selectedPanelCollapsed\">\n <div class=\"panel-header\" (click)=\"selectedPanelCollapsed = !selectedPanelCollapsed\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <h3>Your Applications</h3>\n <span class=\"badge\">{{ activeApps.length }}</span>\n <i\n class=\"collapse-toggle fa-solid\"\n [class.fa-chevron-down]=\"selectedPanelCollapsed\"\n [class.fa-chevron-up]=\"!selectedPanelCollapsed\"\n aria-hidden=\"true\"\n ></i>\n </div>\n\n <div class=\"panel-content\">\n @if (activeApps.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\" aria-hidden=\"true\"></i>\n <p>No applications selected</p>\n <p class=\"hint\">Add apps from the available list</p>\n </div>\n }\n\n @if (activeApps.length > 0) {\n <div\n class=\"sortable-list\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event)\"\n >\n @for (item of activeApps; track item.app.ID; let i = $index) {\n <div\n class=\"app-item\"\n [class.dragging]=\"draggedItem === item\"\n draggable=\"true\"\n (dragstart)=\"onDragStart($event, item, i)\"\n (dragend)=\"onDragEnd($event)\"\n (dragenter)=\"onDragEnter($event, i)\"\n (dblclick)=\"removeApp(item); $event.stopPropagation()\"\n >\n <div class=\"app-item-content\" [style.border-left-color]=\"item.app.GetColor()\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-info\">\n <span class=\"app-name\">{{ item.app.Name }}</span>\n @if (item.app.Description) {\n <span class=\"app-description\">{{ item.app.Description }}</span>\n }\n </div>\n\n <div class=\"app-actions\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n [disabled]=\"i === 0\"\n (click)=\"moveUp(item); $event.stopPropagation()\"\n title=\"Move up\"\n >\n <i class=\"fa-solid fa-chevron-up\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n [disabled]=\"i === activeApps.length - 1\"\n (click)=\"moveDown(item); $event.stopPropagation()\"\n title=\"Move down\"\n >\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm mj-btn-danger\"\n (click)=\"removeApp(item); $event.stopPropagation()\"\n title=\"Remove from your apps\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Footer Actions - Primary on LEFT per MD3 -->\n <div class=\"dialog-footer\">\n <div class=\"footer-left\">\n @if (hasChanges()) {\n <button\n class=\"mj-btn mj-btn-secondary\"\n (click)=\"reset()\"\n [disabled]=\"isLoading || isSaving\"\n >\n <i class=\"fa-solid fa-rotate-left\" aria-hidden=\"true\"></i>\n Reset Changes\n </button>\n }\n </div>\n <div class=\"footer-right\">\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"save()\"\n [disabled]=\"isLoading || isSaving || !hasChanges()\"\n >\n @if (isSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span>Saving...</span>\n } @else {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span>Save Changes</span>\n }\n </button>\n <button\n class=\"mj-btn mj-btn-secondary\"\n (click)=\"close()\"\n [disabled]=\"isSaving\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ============================================\n User App Config - MD3 Design System\n ============================================ */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n}\n\n/* Full-screen dialog */\n.full-screen-dialog {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: var(--mat-sys-surface);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n}\n\n/* Modal Header */\n.modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 0;\n font: var(--mat-sys-title-large);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-title i {\n color: var(--mat-sys-primary);\n}\n\n.modal-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n border: none;\n border-radius: var(--mat-sys-corner-full);\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.modal-close:hover {\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-close:focus-visible {\n outline: 2px solid var(--mat-sys-primary);\n outline-offset: 2px;\n}\n\n/* Main container */\n.app-config-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mat-sys-surface-container-lowest);\n}\n\n/* Loading state */\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n color: var(--mat-sys-on-surface-variant);\n}\n\n/* Error message */\n.error-message {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--mat-sys-error-container);\n color: var(--mat-sys-on-error-container);\n border-bottom: 1px solid var(--mat-sys-error);\n}\n\n.error-message i {\n font-size: 1.1rem;\n}\n\n/* Config content */\n.config-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 1.5rem;\n overflow: hidden;\n}\n\n.config-description {\n margin: 0 0 1.5rem 0;\n color: var(--mat-sys-on-surface-variant);\n font: var(--mat-sys-body-large);\n line-height: 1.5;\n}\n\n/* Panels container */\n.panels-container {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n overflow: hidden;\n}\n\n@media (max-width: 900px) {\n .panels-container {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: auto;\n }\n\n /* Show collapse toggle on mobile */\n .panel-header .collapse-toggle {\n display: inline-block !important;\n color: var(--mat-sys-on-surface-variant) !important;\n }\n\n /* Make header clickable on mobile */\n .panel-header {\n cursor: pointer;\n user-select: none;\n }\n\n .panel-header:hover {\n background: var(--mat-sys-surface-container);\n }\n\n /* Collapsed panel - just show header */\n .panel.collapsed {\n flex: 0 0 auto !important;\n }\n\n .panel.collapsed .panel-content {\n display: none !important;\n }\n\n .panel.collapsed .panel-header {\n border-bottom: none;\n }\n\n /* Non-collapsed panel takes available space */\n .panel:not(.collapsed) {\n flex: 1 1 auto;\n min-height: 150px;\n }\n}\n\n/* Panel styles */\n.panel {\n display: flex;\n flex-direction: column;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium);\n overflow: hidden;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 1rem 1.25rem;\n background: var(--mat-sys-surface-container);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.panel-header i:first-child {\n font-size: 1.1rem;\n color: var(--mat-sys-primary);\n}\n\n.panel-header h3 {\n margin: 0;\n font: var(--mat-sys-title-medium);\n color: var(--mat-sys-on-surface);\n flex: 1;\n}\n\n.panel-header .badge {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary);\n padding: 0.125rem 0.625rem;\n border-radius: var(--mat-sys-corner-full);\n font: var(--mat-sys-label-medium);\n font-weight: 500;\n}\n\n/* Collapse toggle - hidden by default, shown on mobile */\n.panel-header .collapse-toggle {\n display: none;\n color: var(--mat-sys-on-surface-variant);\n font-size: 0.9rem;\n margin-left: 0.5rem;\n}\n\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 0.75rem;\n}\n\n/* Empty state */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 1.5rem;\n color: var(--mat-sys-on-surface-variant);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n}\n\n.empty-state p {\n margin: 0;\n font: var(--mat-sys-body-large);\n}\n\n.empty-state .hint {\n margin-top: 0.25rem;\n font: var(--mat-sys-body-medium);\n opacity: 0.7;\n}\n\n/* Sortable list container */\n.sortable-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n/* App items */\n.app-item {\n cursor: grab;\n transition: transform 0.2s, opacity 0.2s;\n}\n\n.app-item:active {\n cursor: grabbing;\n}\n\n.app-item.dragging {\n opacity: 0.5;\n transform: scale(0.98);\n}\n\n.app-item-content {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-left-width: 4px;\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.app-item-content:hover {\n border-color: var(--mat-sys-primary);\n box-shadow: var(--mat-sys-elevation-1);\n}\n\n.drag-handle {\n color: var(--mat-sys-on-surface-variant);\n cursor: grab;\n padding: 0.25rem;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.app-icon {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: var(--mat-sys-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 1.1rem;\n flex-shrink: 0;\n}\n\n.app-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n min-width: 0;\n}\n\n.app-name {\n font: var(--mat-sys-body-large);\n font-weight: 500;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-description {\n font: var(--mat-sys-body-small);\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-actions {\n display: flex;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n/* Available app items */\n.available-app-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n margin-bottom: 0.5rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.available-app-item:hover {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-surface-container);\n}\n\n.available-app-item .app-info {\n flex: 1;\n}\n\n/* Dialog footer */\n.dialog-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.footer-left,\n.footer-right {\n display: flex;\n gap: 0.75rem;\n}\n\n.dialog-footer button {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n/* Responsive adjustments */\n@media (max-width: 600px) {\n .config-content {\n padding: 1rem;\n }\n\n .panels-container {\n gap: 1rem;\n }\n\n .app-item-content,\n .available-app-item {\n padding: 0.625rem 0.75rem;\n }\n\n .app-icon {\n width: 2.25rem;\n height: 2.25rem;\n font-size: 1rem;\n }\n\n .dialog-footer {\n flex-direction: column;\n gap: 0.75rem;\n }\n\n .footer-left,\n .footer-right {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* Accessibility - Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n .app-item,\n .app-item-content,\n .available-app-item,\n .modal-close {\n transition: none;\n }\n}\n"] }]
|
|
608
|
-
}],
|
|
746
|
+
args: [{ standalone: false, selector: 'mj-user-app-config', template: "<!-- Modal Backdrop -->\n@if (ShowDialog) {\n <div class=\"modal-backdrop\" (click)=\"Close()\" role=\"presentation\"></div>\n <div\n class=\"modal-dialog full-screen-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"app-config-title\"\n >\n <!-- Dialog Header -->\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" id=\"app-config-title\">\n <i class=\"fa-solid fa-grid-2\" aria-hidden=\"true\"></i>\n Configure Apps\n </h2>\n <button\n class=\"modal-close\"\n (click)=\"Close()\"\n aria-label=\"Close dialog\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"app-config-container\">\n <!-- Loading State -->\n @if (IsLoading) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\">\n <mj-loading text=\"Loading your app configuration...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Error Message -->\n @if (ErrorMessage) {\n <div class=\"error-message\" role=\"alert\">\n <i class=\"fa-solid fa-circle-exclamation\" aria-hidden=\"true\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n\n <!-- Main Content -->\n @if (!IsLoading) {\n <div class=\"config-content\">\n <p class=\"config-description\">\n Select which applications appear in your app switcher and arrange them in your preferred order.\n Double-click to quickly add or remove. Drag and drop to reorder, or use the arrow buttons.\n </p>\n\n <!-- Desktop: two-panel layout with drag-and-drop -->\n <div class=\"panels-container desktop-only\">\n <!-- Available Apps Panel -->\n <div class=\"panel available-apps-panel\" [class.collapsed]=\"AvailablePanelCollapsed\">\n <div class=\"panel-header\" (click)=\"AvailablePanelCollapsed = !AvailablePanelCollapsed\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i>\n <h3>Available Applications</h3>\n <span class=\"badge\">{{ AvailableApps.length }}</span>\n <i\n class=\"collapse-toggle fa-solid\"\n [class.fa-chevron-down]=\"AvailablePanelCollapsed\"\n [class.fa-chevron-up]=\"!AvailablePanelCollapsed\"\n aria-hidden=\"true\"\n ></i>\n </div>\n\n <div class=\"panel-content\">\n @if (AvailableApps.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-check-double\" aria-hidden=\"true\"></i>\n <p>All applications added!</p>\n </div>\n }\n\n @for (item of AvailableApps; track item.app.ID) {\n <div class=\"available-app-item\" (dblclick)=\"AddApp(item)\">\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-info\">\n <span class=\"app-name\">{{ item.app.Name }}</span>\n @if (item.app.Description) {\n <span class=\"app-description\">{{ item.app.Description }}</span>\n }\n </div>\n\n <button\n class=\"mj-btn mj-btn-primary mj-btn-outline mj-btn-sm\"\n (click)=\"AddApp(item)\"\n title=\"Add to your apps\"\n >\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n Add\n </button>\n </div>\n }\n </div>\n </div>\n\n <!-- Selected Apps Panel -->\n <div class=\"panel selected-apps-panel\" [class.collapsed]=\"SelectedPanelCollapsed\">\n <div class=\"panel-header\" (click)=\"SelectedPanelCollapsed = !SelectedPanelCollapsed\">\n <i class=\"fa-solid fa-check-circle\" aria-hidden=\"true\"></i>\n <h3>Your Applications</h3>\n <span class=\"badge\">{{ ActiveApps.length }}</span>\n <i\n class=\"collapse-toggle fa-solid\"\n [class.fa-chevron-down]=\"SelectedPanelCollapsed\"\n [class.fa-chevron-up]=\"!SelectedPanelCollapsed\"\n aria-hidden=\"true\"\n ></i>\n </div>\n\n <div class=\"panel-content\">\n @if (ActiveApps.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-inbox\" aria-hidden=\"true\"></i>\n <p>No applications selected</p>\n <p class=\"hint\">Add apps from the available list</p>\n </div>\n }\n\n @if (ActiveApps.length > 0) {\n <div\n class=\"sortable-list\"\n (dragover)=\"OnDragOver($event)\"\n (drop)=\"OnDrop($event)\"\n >\n @for (item of ActiveApps; track item.app.ID; let i = $index) {\n <div\n class=\"app-item\"\n [class.dragging]=\"DraggedItem === item\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event, item, i)\"\n (dragend)=\"OnDragEnd()\"\n (dragenter)=\"OnDragEnter($event, i)\"\n (dblclick)=\"RemoveApp(item); $event.stopPropagation()\"\n >\n <div class=\"app-item-content\" [style.border-left-color]=\"item.app.GetColor()\">\n <div class=\"drag-handle\">\n <i class=\"fa-solid fa-grip-vertical\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n\n <div class=\"app-info\">\n <span class=\"app-name\">{{ item.app.Name }}</span>\n @if (item.app.Description) {\n <span class=\"app-description\">{{ item.app.Description }}</span>\n }\n </div>\n\n <div class=\"app-actions\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n [disabled]=\"i === 0\"\n (click)=\"MoveUp(item); $event.stopPropagation()\"\n title=\"Move up\"\n >\n <i class=\"fa-solid fa-chevron-up\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n [disabled]=\"i === ActiveApps.length - 1\"\n (click)=\"MoveDown(item); $event.stopPropagation()\"\n title=\"Move down\"\n >\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm mj-btn-danger\"\n (click)=\"RemoveApp(item); $event.stopPropagation()\"\n title=\"Remove from your apps\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Mobile: single list with toggles + touch drag reorder -->\n <div\n class=\"mobile-view\"\n (touchmove)=\"OnTouchDragMove($event)\"\n (touchend)=\"OnTouchDragEnd()\"\n (touchcancel)=\"OnTouchDragEnd()\"\n >\n <div class=\"mobile-list\">\n @if (ActiveApps.length > 0) {\n <div class=\"mobile-section-label\">Your Apps</div>\n @for (item of ActiveApps; track item.app.ID; let i = $index) {\n @if (TouchDragActive && TouchDropIndex === i && TouchDragIndex > i) {\n <div class=\"mobile-drop-indicator\"></div>\n }\n <div\n class=\"mobile-app-row\"\n [class.touch-ghost]=\"TouchDragActive && TouchDragIndex === i\"\n >\n <div\n class=\"mobile-drag-handle\"\n (touchstart)=\"OnTouchDragStart($event, i)\"\n aria-label=\"Drag to reorder\"\n >\n <i class=\"fa-solid fa-grip-vertical\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"mobile-app-name\">{{ item.app.Name }}</span>\n <button\n class=\"mobile-toggle on\"\n (click)=\"ToggleApp(item)\"\n aria-label=\"Remove {{ item.app.Name }}\"\n >\n <i class=\"fa-solid fa-toggle-on\" aria-hidden=\"true\"></i>\n </button>\n </div>\n @if (TouchDragActive && TouchDropIndex === i && TouchDragIndex < i) {\n <div class=\"mobile-drop-indicator\"></div>\n }\n }\n @if (TouchDragActive && TouchDropIndex === ActiveApps.length - 1 && TouchDragIndex < TouchDropIndex) {\n <div class=\"mobile-drop-indicator\"></div>\n }\n }\n\n @if (AvailableApps.length > 0) {\n <div class=\"mobile-section-label\">Available</div>\n @for (item of AvailableApps; track item.app.ID) {\n <div class=\"mobile-app-row inactive\">\n <div class=\"app-icon\" [style.background-color]=\"item.app.GetColor()\">\n <i [class]=\"item.app.Icon || 'fa-solid fa-cube'\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"mobile-app-name\">{{ item.app.Name }}</span>\n <button\n class=\"mobile-toggle off\"\n (click)=\"ToggleApp(item)\"\n aria-label=\"Add {{ item.app.Name }}\"\n >\n <i class=\"fa-solid fa-toggle-off\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Footer Actions -->\n <div class=\"dialog-footer\">\n <div class=\"footer-left\">\n @if (HasChanges()) {\n <button\n class=\"mj-btn mj-btn-secondary\"\n (click)=\"Reset()\"\n [disabled]=\"IsLoading || IsSaving\"\n >\n <i class=\"fa-solid fa-rotate-left\" aria-hidden=\"true\"></i>\n Reset Changes\n </button>\n }\n </div>\n <div class=\"footer-right\">\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"Save()\"\n [disabled]=\"IsLoading || IsSaving || !HasChanges()\"\n >\n @if (IsSaving) {\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span>Saving...</span>\n } @else {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n <span>Save Changes</span>\n }\n </button>\n <button\n class=\"mj-btn mj-btn-secondary\"\n (click)=\"Close()\"\n [disabled]=\"IsSaving\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["/* ============================================\n User App Config - MD3 Design System\n ============================================ */\n\n/* Modal Backdrop */\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n}\n\n/* Full-screen dialog */\n.full-screen-dialog {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: var(--mat-sys-surface);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n}\n\n/* Modal Header */\n.modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin: 0;\n font: var(--mat-sys-title-large);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-title i {\n color: var(--mat-sys-primary);\n}\n\n.modal-close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n border: none;\n border-radius: var(--mat-sys-corner-full);\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.modal-close:hover {\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface);\n}\n\n.modal-close:focus-visible {\n outline: 2px solid var(--mat-sys-primary);\n outline-offset: 2px;\n}\n\n/* Main container */\n.app-config-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n background: var(--mat-sys-surface-container-lowest);\n}\n\n/* Loading state */\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 1rem;\n color: var(--mat-sys-on-surface-variant);\n}\n\n/* Error message */\n.error-message {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--mat-sys-error-container);\n color: var(--mat-sys-on-error-container);\n border-bottom: 1px solid var(--mat-sys-error);\n}\n\n.error-message i {\n font-size: 1.1rem;\n}\n\n/* Config content */\n.config-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n padding: 1.5rem;\n overflow: hidden;\n}\n\n.config-description {\n margin: 0 0 1.5rem 0;\n color: var(--mat-sys-on-surface-variant);\n font: var(--mat-sys-body-large);\n line-height: 1.5;\n}\n\n/* Panels container */\n.panels-container {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n overflow: hidden;\n}\n\n@media (max-width: 900px) {\n .panels-container {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: auto;\n }\n\n /* Show collapse toggle on mobile */\n .panel-header .collapse-toggle {\n display: inline-block !important;\n color: var(--mat-sys-on-surface-variant) !important;\n }\n\n /* Make header clickable on mobile */\n .panel-header {\n cursor: pointer;\n user-select: none;\n }\n\n .panel-header:hover {\n background: var(--mat-sys-surface-container);\n }\n\n /* Collapsed panel - just show header */\n .panel.collapsed {\n flex: 0 0 auto !important;\n }\n\n .panel.collapsed .panel-content {\n display: none !important;\n }\n\n .panel.collapsed .panel-header {\n border-bottom: none;\n }\n\n /* Non-collapsed panel takes available space */\n .panel:not(.collapsed) {\n flex: 1 1 auto;\n min-height: 150px;\n }\n}\n\n/* Panel styles */\n.panel {\n display: flex;\n flex-direction: column;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium);\n overflow: hidden;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 1rem 1.25rem;\n background: var(--mat-sys-surface-container);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.panel-header i:first-child {\n font-size: 1.1rem;\n color: var(--mat-sys-primary);\n}\n\n.panel-header h3 {\n margin: 0;\n font: var(--mat-sys-title-medium);\n color: var(--mat-sys-on-surface);\n flex: 1;\n}\n\n.panel-header .badge {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary);\n padding: 0.125rem 0.625rem;\n border-radius: var(--mat-sys-corner-full);\n font: var(--mat-sys-label-medium);\n font-weight: 500;\n}\n\n/* Collapse toggle - hidden by default, shown on mobile */\n.panel-header .collapse-toggle {\n display: none;\n color: var(--mat-sys-on-surface-variant);\n font-size: 0.9rem;\n margin-left: 0.5rem;\n}\n\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 0.75rem;\n}\n\n/* Empty state */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 1.5rem;\n color: var(--mat-sys-on-surface-variant);\n text-align: center;\n}\n\n.empty-state i {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n}\n\n.empty-state p {\n margin: 0;\n font: var(--mat-sys-body-large);\n}\n\n.empty-state .hint {\n margin-top: 0.25rem;\n font: var(--mat-sys-body-medium);\n opacity: 0.7;\n}\n\n/* Sortable list container */\n.sortable-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n/* App items */\n.app-item {\n cursor: grab;\n transition: transform 0.2s, opacity 0.2s;\n}\n\n.app-item:active {\n cursor: grabbing;\n}\n\n.app-item.dragging {\n opacity: 0.5;\n transform: scale(0.98);\n}\n\n.app-item-content {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-left-width: 4px;\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.app-item-content:hover {\n border-color: var(--mat-sys-primary);\n box-shadow: var(--mat-sys-elevation-1);\n}\n\n.drag-handle {\n color: var(--mat-sys-on-surface-variant);\n cursor: grab;\n padding: 0.25rem;\n}\n\n.drag-handle:active {\n cursor: grabbing;\n}\n\n.app-icon {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: var(--mat-sys-corner-small);\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 1.1rem;\n flex-shrink: 0;\n}\n\n.app-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n min-width: 0;\n}\n\n.app-name {\n font: var(--mat-sys-body-large);\n font-weight: 500;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-description {\n font: var(--mat-sys-body-small);\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.app-actions {\n display: flex;\n gap: 0.25rem;\n flex-shrink: 0;\n}\n\n.app-actions .mj-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.app-actions .mj-btn-ghost {\n background: transparent;\n color: var(--mj-text-secondary);\n}\n\n.app-actions .mj-btn-ghost:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.app-actions .mj-btn-ghost:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.app-actions .mj-btn-sm {\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n font-size: 0.8rem;\n}\n\n.app-actions .mj-btn-danger:hover:not(:disabled) {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error);\n}\n\n/* Available app items */\n.available-app-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n margin-bottom: 0.5rem;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small);\n transition: all 0.2s ease;\n}\n\n.available-app-item:hover {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-surface-container);\n}\n\n.available-app-item .app-info {\n flex: 1;\n}\n\n/* Dialog footer */\n.dialog-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n background: var(--mat-sys-surface);\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.footer-left,\n.footer-right {\n display: flex;\n gap: 0.75rem;\n}\n\n.dialog-footer button {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n/* ==============================================\n Mobile: single list with toggles\n ============================================== */\n\n/* Hidden by default on desktop */\n.mobile-view {\n display: none;\n}\n\n@media (max-width: 600px) {\n /* Swap layouts */\n .desktop-only {\n display: none !important;\n }\n\n .config-description {\n display: none;\n }\n\n .mobile-view {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n }\n\n .mobile-list {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n }\n\n /* Section labels */\n .mobile-section-label {\n padding: 0.5rem 0.625rem 0.25rem;\n font-size: 0.6875rem;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--mj-text-secondary);\n }\n\n /* App rows */\n .mobile-app-row {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n padding: 0.625rem;\n border-radius: var(--mj-radius-md);\n transition: background-color 0.15s ease;\n }\n\n .mobile-app-row.inactive {\n opacity: 0.7;\n }\n\n .mobile-app-row .app-icon {\n width: 2rem;\n height: 2rem;\n font-size: 0.875rem;\n flex-shrink: 0;\n }\n\n .mobile-app-name {\n flex: 1;\n min-width: 0;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* Drag handle */\n .mobile-drag-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n flex-shrink: 0;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n touch-action: none;\n cursor: grab;\n padding: 0.5rem 0;\n }\n\n .mobile-drag-handle:active {\n cursor: grabbing;\n color: var(--mj-text-primary);\n }\n\n /* Dragging row */\n .mobile-app-row.touch-dragging {\n background: var(--mj-bg-surface-hover);\n box-shadow: var(--mj-shadow-lg);\n border-radius: var(--mj-radius-md);\n position: relative;\n z-index: 100;\n opacity: 0.95;\n }\n\n /* Ghost placeholder for the original position */\n .mobile-app-row.touch-ghost {\n opacity: 0.3;\n }\n\n /* Drop indicator line */\n .mobile-drop-indicator {\n height: 2px;\n background: var(--mj-brand-primary);\n border-radius: 1px;\n margin: 0 0.625rem;\n }\n\n /* Toggle button */\n .mobile-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n padding: 0.25rem;\n cursor: pointer;\n font-size: 1.5rem;\n flex-shrink: 0;\n transition: color 0.15s ease;\n min-width: 44px;\n min-height: 44px;\n }\n\n .mobile-toggle.on {\n color: var(--mj-brand-primary);\n }\n\n .mobile-toggle.off {\n color: var(--mj-text-muted);\n }\n\n /* Header compact */\n .modal-header {\n padding: 0.75rem 1rem;\n }\n\n .modal-title {\n font-size: 1.125rem;\n }\n\n /* Content compact */\n .config-content {\n padding: 0;\n }\n\n /* Footer compact */\n .dialog-footer {\n padding: 0.75rem;\n gap: 0.5rem;\n }\n\n .footer-left,\n .footer-right {\n display: flex;\n gap: 0.5rem;\n }\n\n .dialog-footer .mj-btn {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 38px;\n }\n}\n\n/* Accessibility - Reduced Motion */\n@media (prefers-reduced-motion: reduce) {\n .app-item,\n .app-item-content,\n .available-app-item,\n .modal-close {\n transition: none;\n }\n}\n"] }]
|
|
747
|
+
}], null, { ShowDialog: [{
|
|
609
748
|
type: Input
|
|
610
|
-
}],
|
|
749
|
+
}], ShowDialogChange: [{
|
|
611
750
|
type: Output
|
|
612
|
-
}],
|
|
751
|
+
}], ConfigSaved: [{
|
|
613
752
|
type: Output
|
|
614
753
|
}] }); })();
|
|
615
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserAppConfigComponent, { className: "UserAppConfigComponent", filePath: "src/lib/user-app-config/user-app-config.component.ts", lineNumber:
|
|
754
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserAppConfigComponent, { className: "UserAppConfigComponent", filePath: "src/lib/user-app-config/user-app-config.component.ts", lineNumber: 41 }); })();
|
|
616
755
|
//# sourceMappingURL=user-app-config.component.js.map
|