@memberjunction/ng-explorer-core 2.42.0 → 2.43.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/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts +40 -0
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -0
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +592 -0
- package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -0
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts +4 -1
- package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
- package/dist/lib/single-dashboard/single-dashboard.component.js +9 -3
- package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts +2 -0
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts.map +1 -1
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js +167 -79
- package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js.map +1 -1
- package/dist/module.d.ts +41 -39
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +16 -7
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +25 -25
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
11
|
+
import { moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
|
|
12
|
+
import { LogError, Metadata, RunView } from '@memberjunction/core';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
import * as i1 from "@angular/forms";
|
|
15
|
+
import * as i2 from "@progress/kendo-angular-dialog";
|
|
16
|
+
import * as i3 from "@progress/kendo-angular-indicators";
|
|
17
|
+
import * as i4 from "@angular/cdk/drag-drop";
|
|
18
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
19
|
+
const _c0 = a0 => [a0];
|
|
20
|
+
function DashboardPreferencesDialogComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
21
|
+
i0.ɵɵelement(0, "i", 16);
|
|
22
|
+
i0.ɵɵtext(1, " Global Scope ");
|
|
23
|
+
} }
|
|
24
|
+
function DashboardPreferencesDialogComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
25
|
+
i0.ɵɵelement(0, "i", 17);
|
|
26
|
+
i0.ɵɵtext(1);
|
|
27
|
+
} if (rf & 2) {
|
|
28
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
29
|
+
i0.ɵɵadvance();
|
|
30
|
+
i0.ɵɵtextInterpolate1(" Application: ", ctx_r0.applicationName, " ");
|
|
31
|
+
} }
|
|
32
|
+
function DashboardPreferencesDialogComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
33
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
34
|
+
i0.ɵɵelementStart(0, "div", 7)(1, "label")(2, "input", 18);
|
|
35
|
+
i0.ɵɵtwoWayListener("ngModelChange", function DashboardPreferencesDialogComponent_Conditional_9_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.preferenceMode, $event) || (ctx_r0.preferenceMode = $event); return i0.ɵɵresetView($event); });
|
|
36
|
+
i0.ɵɵlistener("change", function DashboardPreferencesDialogComponent_Conditional_9_Template_input_change_2_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onPreferenceModeChange()); });
|
|
37
|
+
i0.ɵɵelementEnd();
|
|
38
|
+
i0.ɵɵtext(3, " Personal Preferences ");
|
|
39
|
+
i0.ɵɵelementEnd();
|
|
40
|
+
i0.ɵɵelementStart(4, "label")(5, "input", 19);
|
|
41
|
+
i0.ɵɵtwoWayListener("ngModelChange", function DashboardPreferencesDialogComponent_Conditional_9_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.preferenceMode, $event) || (ctx_r0.preferenceMode = $event); return i0.ɵɵresetView($event); });
|
|
42
|
+
i0.ɵɵlistener("change", function DashboardPreferencesDialogComponent_Conditional_9_Template_input_change_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onPreferenceModeChange()); });
|
|
43
|
+
i0.ɵɵelementEnd();
|
|
44
|
+
i0.ɵɵtext(6, " System Defaults ");
|
|
45
|
+
i0.ɵɵelementEnd()();
|
|
46
|
+
} if (rf & 2) {
|
|
47
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
48
|
+
i0.ɵɵadvance(2);
|
|
49
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.preferenceMode);
|
|
50
|
+
i0.ɵɵadvance(3);
|
|
51
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.preferenceMode);
|
|
52
|
+
} }
|
|
53
|
+
function DashboardPreferencesDialogComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
i0.ɵɵelementStart(0, "div", 9);
|
|
55
|
+
i0.ɵɵelement(1, "kendo-loader");
|
|
56
|
+
i0.ɵɵtext(2, " Loading dashboards... ");
|
|
57
|
+
i0.ɵɵelementEnd();
|
|
58
|
+
} }
|
|
59
|
+
function DashboardPreferencesDialogComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
i0.ɵɵelementStart(0, "div", 10);
|
|
61
|
+
i0.ɵɵelement(1, "i", 20);
|
|
62
|
+
i0.ɵɵtext(2);
|
|
63
|
+
i0.ɵɵelementEnd();
|
|
64
|
+
} if (rf & 2) {
|
|
65
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
66
|
+
i0.ɵɵadvance(2);
|
|
67
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.error, " ");
|
|
68
|
+
} }
|
|
69
|
+
function DashboardPreferencesDialogComponent_Conditional_13_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
70
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
71
|
+
i0.ɵɵelement(1, "i", 29);
|
|
72
|
+
i0.ɵɵtext(2, " All dashboards are configured ");
|
|
73
|
+
i0.ɵɵelementEnd();
|
|
74
|
+
} }
|
|
75
|
+
function DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
76
|
+
i0.ɵɵelementStart(0, "span", 34);
|
|
77
|
+
i0.ɵɵtext(1);
|
|
78
|
+
i0.ɵɵelementEnd();
|
|
79
|
+
} if (rf & 2) {
|
|
80
|
+
const dashboard_r5 = i0.ɵɵnextContext().$implicit;
|
|
81
|
+
i0.ɵɵadvance();
|
|
82
|
+
i0.ɵɵtextInterpolate(dashboard_r5.Description);
|
|
83
|
+
} }
|
|
84
|
+
function DashboardPreferencesDialogComponent_Conditional_13_For_9_Template(rf, ctx) { if (rf & 1) {
|
|
85
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
86
|
+
i0.ɵɵelementStart(0, "div", 25)(1, "div", 30);
|
|
87
|
+
i0.ɵɵelement(2, "i", 31);
|
|
88
|
+
i0.ɵɵelementStart(3, "div", 32)(4, "span", 33);
|
|
89
|
+
i0.ɵɵtext(5);
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
91
|
+
i0.ɵɵtemplate(6, DashboardPreferencesDialogComponent_Conditional_13_For_9_Conditional_6_Template, 2, 1, "span", 34);
|
|
92
|
+
i0.ɵɵelementEnd();
|
|
93
|
+
i0.ɵɵelementStart(7, "button", 35);
|
|
94
|
+
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Conditional_13_For_9_Template_button_click_7_listener() { const dashboard_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.addDashboard(dashboard_r5)); });
|
|
95
|
+
i0.ɵɵelement(8, "i", 36);
|
|
96
|
+
i0.ɵɵelementEnd()()();
|
|
97
|
+
} if (rf & 2) {
|
|
98
|
+
const dashboard_r5 = ctx.$implicit;
|
|
99
|
+
i0.ɵɵproperty("cdkDragData", dashboard_r5);
|
|
100
|
+
i0.ɵɵadvance(5);
|
|
101
|
+
i0.ɵɵtextInterpolate(dashboard_r5.Name);
|
|
102
|
+
i0.ɵɵadvance();
|
|
103
|
+
i0.ɵɵconditional(dashboard_r5.Description ? 6 : -1);
|
|
104
|
+
} }
|
|
105
|
+
function DashboardPreferencesDialogComponent_Conditional_13_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
106
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
107
|
+
i0.ɵɵelement(1, "i", 29);
|
|
108
|
+
i0.ɵɵtext(2, " No dashboards configured ");
|
|
109
|
+
i0.ɵɵelementEnd();
|
|
110
|
+
} }
|
|
111
|
+
function DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
112
|
+
i0.ɵɵelementStart(0, "span", 34);
|
|
113
|
+
i0.ɵɵtext(1);
|
|
114
|
+
i0.ɵɵelementEnd();
|
|
115
|
+
} if (rf & 2) {
|
|
116
|
+
const dashboard_r7 = i0.ɵɵnextContext().$implicit;
|
|
117
|
+
i0.ɵɵadvance();
|
|
118
|
+
i0.ɵɵtextInterpolate(dashboard_r7.Description);
|
|
119
|
+
} }
|
|
120
|
+
function DashboardPreferencesDialogComponent_Conditional_13_For_18_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
122
|
+
i0.ɵɵelementStart(0, "div", 28)(1, "div", 30);
|
|
123
|
+
i0.ɵɵelement(2, "i", 31);
|
|
124
|
+
i0.ɵɵelementStart(3, "span", 37);
|
|
125
|
+
i0.ɵɵtext(4);
|
|
126
|
+
i0.ɵɵelementEnd();
|
|
127
|
+
i0.ɵɵelementStart(5, "div", 32)(6, "span", 33);
|
|
128
|
+
i0.ɵɵtext(7);
|
|
129
|
+
i0.ɵɵelementEnd();
|
|
130
|
+
i0.ɵɵtemplate(8, DashboardPreferencesDialogComponent_Conditional_13_For_18_Conditional_8_Template, 2, 1, "span", 34);
|
|
131
|
+
i0.ɵɵelementEnd();
|
|
132
|
+
i0.ɵɵelementStart(9, "button", 38);
|
|
133
|
+
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Conditional_13_For_18_Template_button_click_9_listener() { const dashboard_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.removeDashboard(dashboard_r7)); });
|
|
134
|
+
i0.ɵɵelement(10, "i", 14);
|
|
135
|
+
i0.ɵɵelementEnd()()();
|
|
136
|
+
} if (rf & 2) {
|
|
137
|
+
const dashboard_r7 = ctx.$implicit;
|
|
138
|
+
const ɵ$index_102_r8 = ctx.$index;
|
|
139
|
+
i0.ɵɵproperty("cdkDragData", dashboard_r7);
|
|
140
|
+
i0.ɵɵadvance(4);
|
|
141
|
+
i0.ɵɵtextInterpolate(ɵ$index_102_r8 + 1);
|
|
142
|
+
i0.ɵɵadvance(3);
|
|
143
|
+
i0.ɵɵtextInterpolate(dashboard_r7.Name);
|
|
144
|
+
i0.ɵɵadvance();
|
|
145
|
+
i0.ɵɵconditional(dashboard_r7.Description ? 8 : -1);
|
|
146
|
+
} }
|
|
147
|
+
function DashboardPreferencesDialogComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
148
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
149
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "div", 21)(2, "h4");
|
|
150
|
+
i0.ɵɵelement(3, "i", 22);
|
|
151
|
+
i0.ɵɵtext(4, " Available Dashboards");
|
|
152
|
+
i0.ɵɵelementEnd();
|
|
153
|
+
i0.ɵɵelementStart(5, "div", 23, 0);
|
|
154
|
+
i0.ɵɵlistener("cdkDropListDropped", function DashboardPreferencesDialogComponent_Conditional_13_Template_div_cdkDropListDropped_5_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDrop($event)); });
|
|
155
|
+
i0.ɵɵtemplate(7, DashboardPreferencesDialogComponent_Conditional_13_Conditional_7_Template, 3, 0, "div", 24);
|
|
156
|
+
i0.ɵɵrepeaterCreate(8, DashboardPreferencesDialogComponent_Conditional_13_For_9_Template, 9, 3, "div", 25, _forTrack0);
|
|
157
|
+
i0.ɵɵelementEnd()();
|
|
158
|
+
i0.ɵɵelementStart(10, "div", 26)(11, "h4");
|
|
159
|
+
i0.ɵɵelement(12, "i", 27);
|
|
160
|
+
i0.ɵɵtext(13, " Configured Dashboards");
|
|
161
|
+
i0.ɵɵelementEnd();
|
|
162
|
+
i0.ɵɵelementStart(14, "div", 23, 1);
|
|
163
|
+
i0.ɵɵlistener("cdkDropListDropped", function DashboardPreferencesDialogComponent_Conditional_13_Template_div_cdkDropListDropped_14_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDrop($event)); });
|
|
164
|
+
i0.ɵɵtemplate(16, DashboardPreferencesDialogComponent_Conditional_13_Conditional_16_Template, 3, 0, "div", 24);
|
|
165
|
+
i0.ɵɵrepeaterCreate(17, DashboardPreferencesDialogComponent_Conditional_13_For_18_Template, 11, 4, "div", 28, _forTrack0);
|
|
166
|
+
i0.ɵɵelementEnd()()();
|
|
167
|
+
} if (rf & 2) {
|
|
168
|
+
const availableList_r9 = i0.ɵɵreference(6);
|
|
169
|
+
const configuredList_r10 = i0.ɵɵreference(15);
|
|
170
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
171
|
+
i0.ɵɵadvance(5);
|
|
172
|
+
i0.ɵɵproperty("cdkDropListData", ctx_r0.availableDashboards)("cdkDropListConnectedTo", i0.ɵɵpureFunction1(6, _c0, configuredList_r10));
|
|
173
|
+
i0.ɵɵadvance(2);
|
|
174
|
+
i0.ɵɵconditional(ctx_r0.availableDashboards.length === 0 ? 7 : -1);
|
|
175
|
+
i0.ɵɵadvance();
|
|
176
|
+
i0.ɵɵrepeater(ctx_r0.availableDashboards);
|
|
177
|
+
i0.ɵɵadvance(6);
|
|
178
|
+
i0.ɵɵproperty("cdkDropListData", ctx_r0.configuredDashboards)("cdkDropListConnectedTo", i0.ɵɵpureFunction1(8, _c0, availableList_r9));
|
|
179
|
+
i0.ɵɵadvance(2);
|
|
180
|
+
i0.ɵɵconditional(ctx_r0.configuredDashboards.length === 0 ? 16 : -1);
|
|
181
|
+
i0.ɵɵadvance();
|
|
182
|
+
i0.ɵɵrepeater(ctx_r0.configuredDashboards);
|
|
183
|
+
} }
|
|
184
|
+
function DashboardPreferencesDialogComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
185
|
+
i0.ɵɵelement(0, "kendo-loader", 39);
|
|
186
|
+
i0.ɵɵtext(1, " Saving... ");
|
|
187
|
+
} }
|
|
188
|
+
function DashboardPreferencesDialogComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
189
|
+
i0.ɵɵelement(0, "i", 40);
|
|
190
|
+
i0.ɵɵtext(1, " Save Changes ");
|
|
191
|
+
} }
|
|
192
|
+
export class DashboardPreferencesDialogComponent {
|
|
193
|
+
constructor() {
|
|
194
|
+
this.applicationId = null;
|
|
195
|
+
this.scope = 'Global';
|
|
196
|
+
this.result = new EventEmitter();
|
|
197
|
+
this.availableDashboards = [];
|
|
198
|
+
this.configuredDashboards = [];
|
|
199
|
+
this.applicationName = '';
|
|
200
|
+
this.loading = true;
|
|
201
|
+
this.saving = false;
|
|
202
|
+
this.error = null;
|
|
203
|
+
this.hasChanges = false;
|
|
204
|
+
this.isSysAdmin = false;
|
|
205
|
+
this.preferenceMode = 'personal';
|
|
206
|
+
this.originalConfiguredIds = [];
|
|
207
|
+
this.currentUserPreferences = [];
|
|
208
|
+
this.allAvailableDashboards = [];
|
|
209
|
+
}
|
|
210
|
+
ngOnInit() {
|
|
211
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
212
|
+
try {
|
|
213
|
+
yield this.loadData();
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
LogError('Error initializing dashboard preferences dialog', null, error);
|
|
217
|
+
this.error = 'Failed to load dashboard preferences';
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
this.loading = false;
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
loadData() {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
const md = new Metadata();
|
|
227
|
+
// Check if current user is sysadmin
|
|
228
|
+
this.isSysAdmin = md.CurrentUser.Type.trim().toLowerCase() === 'owner';
|
|
229
|
+
console.log('User is sysadmin:', this.isSysAdmin);
|
|
230
|
+
// Default to personal preferences for all users (including sysadmin)
|
|
231
|
+
this.preferenceMode = 'personal';
|
|
232
|
+
// Load application name if we're in app scope
|
|
233
|
+
if (this.scope === 'App' && this.applicationId) {
|
|
234
|
+
yield this.loadApplicationName();
|
|
235
|
+
}
|
|
236
|
+
// Get cached dashboards from MJ_Metadata dataset
|
|
237
|
+
const ds = yield md.GetAndCacheDatasetByName("MJ_Metadata");
|
|
238
|
+
if (!ds || !ds.Success) {
|
|
239
|
+
throw new Error((ds === null || ds === void 0 ? void 0 : ds.Status) || 'Failed to load metadata dataset');
|
|
240
|
+
}
|
|
241
|
+
const dashList = ds.Results.find(r => r.Code === 'Dashboards');
|
|
242
|
+
if (!dashList) {
|
|
243
|
+
throw new Error('Dashboards dataset not found');
|
|
244
|
+
}
|
|
245
|
+
// Filter dashboards by scope
|
|
246
|
+
const appFilter = this.applicationId ? ` AND ApplicationID='${this.applicationId}'` : ' AND ApplicationID IS NULL';
|
|
247
|
+
this.allAvailableDashboards = dashList.Results.filter((d) => {
|
|
248
|
+
if (this.scope === 'Global') {
|
|
249
|
+
return d.Scope === 'Global' && !d.ApplicationID;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
return d.ApplicationID === this.applicationId; // ignore scope for dashboards that match app id, sometimes they have a global scope as they can be shown globally as well as app specific
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
// Load current user preferences
|
|
256
|
+
yield this.loadCurrentPreferences();
|
|
257
|
+
// Split dashboards into available and configured
|
|
258
|
+
this.splitDashboards();
|
|
259
|
+
// Store original state to detect changes
|
|
260
|
+
this.originalConfiguredIds = this.configuredDashboards.map(d => d.ID);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
loadApplicationName() {
|
|
264
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
if (!this.applicationId)
|
|
266
|
+
return;
|
|
267
|
+
try {
|
|
268
|
+
const md = new Metadata();
|
|
269
|
+
const ds = yield md.GetAndCacheDatasetByName("MJ_Metadata");
|
|
270
|
+
const appList = ds.Results.find(r => r.Code === 'Applications');
|
|
271
|
+
if (appList) {
|
|
272
|
+
const app = appList.Results.find((a) => a.ID === this.applicationId);
|
|
273
|
+
this.applicationName = (app === null || app === void 0 ? void 0 : app.Name) || 'Unknown Application';
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
LogError('Error loading application name', null, error);
|
|
278
|
+
this.applicationName = 'Unknown Application';
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
loadCurrentPreferences() {
|
|
283
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
284
|
+
const rv = new RunView();
|
|
285
|
+
const md = new Metadata();
|
|
286
|
+
const appFilter = this.applicationId ? ` AND ApplicationID='${this.applicationId}'` : '';
|
|
287
|
+
const baseCondition = `Scope='${this.scope}'${appFilter}`;
|
|
288
|
+
let filter;
|
|
289
|
+
if (this.isSysAdmin && this.scope === 'Global' && this.preferenceMode === 'system') {
|
|
290
|
+
// Load system defaults only (UserID IS NULL)
|
|
291
|
+
filter = `UserID IS NULL AND ${baseCondition}`;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// Load personal user preferences (including for sysadmin when in personal mode)
|
|
295
|
+
// For personal mode, we ONLY load the user's specific preferences, no fallback to system defaults
|
|
296
|
+
// This allows sysadmin to see their actual personal preferences vs system defaults
|
|
297
|
+
filter = `UserID='${md.CurrentUser.ID}' AND ${baseCondition}`;
|
|
298
|
+
}
|
|
299
|
+
console.log('Loading preferences with filter:', filter);
|
|
300
|
+
const prefsResult = yield rv.RunView({
|
|
301
|
+
EntityName: 'MJ: Dashboard User Preferences',
|
|
302
|
+
ExtraFilter: filter,
|
|
303
|
+
ResultType: 'entity_object',
|
|
304
|
+
OrderBy: 'DisplayOrder',
|
|
305
|
+
});
|
|
306
|
+
this.currentUserPreferences = (prefsResult === null || prefsResult === void 0 ? void 0 : prefsResult.Results) || [];
|
|
307
|
+
console.log('Loaded preferences:', this.currentUserPreferences.length);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
splitDashboards() {
|
|
311
|
+
const configuredIds = new Set(this.currentUserPreferences.map(p => p.DashboardID));
|
|
312
|
+
// Get configured dashboards in the right order
|
|
313
|
+
this.configuredDashboards = this.currentUserPreferences
|
|
314
|
+
.map(pref => this.allAvailableDashboards.find(d => d.ID === pref.DashboardID))
|
|
315
|
+
.filter((d) => d !== undefined);
|
|
316
|
+
// Get available dashboards (not configured)
|
|
317
|
+
this.availableDashboards = this.allAvailableDashboards
|
|
318
|
+
.filter(d => !configuredIds.has(d.ID))
|
|
319
|
+
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
320
|
+
}
|
|
321
|
+
onDrop(event) {
|
|
322
|
+
try {
|
|
323
|
+
if (event.previousContainer === event.container) {
|
|
324
|
+
// Reordering within the same list
|
|
325
|
+
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
// Moving between lists
|
|
329
|
+
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
|
|
330
|
+
// If moving to configured dashboards, sort the available list
|
|
331
|
+
if (event.container.data === this.configuredDashboards) {
|
|
332
|
+
this.availableDashboards.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
this.checkForChanges();
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
LogError('Error in drag drop operation', null, error);
|
|
339
|
+
this.error = 'Error reordering dashboards. Please try again.';
|
|
340
|
+
// Clear error after 3 seconds
|
|
341
|
+
setTimeout(() => {
|
|
342
|
+
this.error = null;
|
|
343
|
+
}, 3000);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
addDashboard(dashboard) {
|
|
347
|
+
try {
|
|
348
|
+
const index = this.availableDashboards.findIndex(d => d.ID === dashboard.ID);
|
|
349
|
+
if (index !== -1) {
|
|
350
|
+
this.availableDashboards.splice(index, 1);
|
|
351
|
+
this.configuredDashboards.push(dashboard);
|
|
352
|
+
this.checkForChanges();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
LogError('Error adding dashboard', null, error);
|
|
357
|
+
this.error = 'Error adding dashboard. Please try again.';
|
|
358
|
+
// Clear error after 3 seconds
|
|
359
|
+
setTimeout(() => {
|
|
360
|
+
this.error = null;
|
|
361
|
+
}, 3000);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
removeDashboard(dashboard) {
|
|
365
|
+
try {
|
|
366
|
+
const index = this.configuredDashboards.findIndex(d => d.ID === dashboard.ID);
|
|
367
|
+
if (index !== -1) {
|
|
368
|
+
this.configuredDashboards.splice(index, 1);
|
|
369
|
+
this.availableDashboards.push(dashboard);
|
|
370
|
+
this.availableDashboards.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
371
|
+
this.checkForChanges();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
LogError('Error removing dashboard', null, error);
|
|
376
|
+
this.error = 'Error removing dashboard. Please try again.';
|
|
377
|
+
// Clear error after 3 seconds
|
|
378
|
+
setTimeout(() => {
|
|
379
|
+
this.error = null;
|
|
380
|
+
}, 3000);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
onPreferenceModeChange() {
|
|
384
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
385
|
+
try {
|
|
386
|
+
this.loading = true;
|
|
387
|
+
this.error = null;
|
|
388
|
+
// Reload preferences with new mode
|
|
389
|
+
yield this.loadCurrentPreferences();
|
|
390
|
+
this.splitDashboards();
|
|
391
|
+
this.originalConfiguredIds = this.configuredDashboards.map(d => d.ID);
|
|
392
|
+
this.hasChanges = false;
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
LogError('Error changing preference mode', null, error);
|
|
396
|
+
this.error = 'Error loading preferences. Please try again.';
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
this.loading = false;
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
checkForChanges() {
|
|
404
|
+
try {
|
|
405
|
+
const currentConfiguredIds = this.configuredDashboards.map(d => d.ID);
|
|
406
|
+
// Check if the order or selection has changed
|
|
407
|
+
this.hasChanges = currentConfiguredIds.length !== this.originalConfiguredIds.length ||
|
|
408
|
+
currentConfiguredIds.some((id, index) => id !== this.originalConfiguredIds[index]);
|
|
409
|
+
// Debug logging
|
|
410
|
+
console.log('Dashboard preferences change check:', {
|
|
411
|
+
original: this.originalConfiguredIds,
|
|
412
|
+
current: currentConfiguredIds,
|
|
413
|
+
hasChanges: this.hasChanges
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
LogError('Error checking for changes', null, error);
|
|
418
|
+
this.hasChanges = false;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
onSave() {
|
|
422
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
423
|
+
var _a, _b, _c, _d, _e, _f;
|
|
424
|
+
if (this.saving || !this.hasChanges) {
|
|
425
|
+
console.log('Save cancelled:', { saving: this.saving, hasChanges: this.hasChanges });
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
try {
|
|
429
|
+
this.saving = true;
|
|
430
|
+
console.log('Starting save process with configured dashboards:', this.configuredDashboards.map(d => ({ id: d.ID, name: d.Name })));
|
|
431
|
+
const md = new Metadata();
|
|
432
|
+
const rv = new RunView();
|
|
433
|
+
// Get existing preferences for this scope
|
|
434
|
+
const baseCondition = this.scope === 'Global'
|
|
435
|
+
? `Scope='Global' AND ApplicationID IS NULL`
|
|
436
|
+
: `Scope='App' AND ApplicationID='${this.applicationId}'`;
|
|
437
|
+
let userFilter;
|
|
438
|
+
if (this.isSysAdmin && this.scope === 'Global' && this.preferenceMode === 'system') {
|
|
439
|
+
// Managing system defaults
|
|
440
|
+
userFilter = `UserID IS NULL AND ${baseCondition}`;
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
// Managing personal preferences
|
|
444
|
+
userFilter = `UserID='${md.CurrentUser.ID}' AND ${baseCondition}`;
|
|
445
|
+
}
|
|
446
|
+
console.log('Loading existing preferences with filter:', userFilter);
|
|
447
|
+
const existingPrefs = yield rv.RunView({
|
|
448
|
+
EntityName: 'MJ: Dashboard User Preferences',
|
|
449
|
+
ExtraFilter: userFilter,
|
|
450
|
+
ResultType: 'entity_object',
|
|
451
|
+
});
|
|
452
|
+
const existingPreferences = (existingPrefs === null || existingPrefs === void 0 ? void 0 : existingPrefs.Results) || [];
|
|
453
|
+
console.log('Found existing preferences:', existingPreferences.length);
|
|
454
|
+
// Create maps for efficient lookups
|
|
455
|
+
const existingByDashboardId = new Map();
|
|
456
|
+
existingPreferences.forEach(pref => {
|
|
457
|
+
existingByDashboardId.set(pref.DashboardID, pref);
|
|
458
|
+
});
|
|
459
|
+
const configuredDashboardIds = new Set(this.configuredDashboards.map(d => d.ID));
|
|
460
|
+
// Step 1: Delete preferences that are no longer configured
|
|
461
|
+
const prefsToDelete = existingPreferences.filter(pref => !configuredDashboardIds.has(pref.DashboardID));
|
|
462
|
+
console.log('Preferences to delete:', prefsToDelete.length);
|
|
463
|
+
for (const pref of prefsToDelete) {
|
|
464
|
+
console.log('Deleting preference for dashboard:', pref.DashboardID);
|
|
465
|
+
if (!(yield pref.Delete())) {
|
|
466
|
+
const errorMsg = ((_a = pref.LatestResult) === null || _a === void 0 ? void 0 : _a.Error) || ((_b = pref.LatestResult) === null || _b === void 0 ? void 0 : _b.Message) || 'Unknown error';
|
|
467
|
+
throw new Error(`Failed to delete preference: ${errorMsg}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// Step 2: Update existing preferences or create new ones
|
|
471
|
+
const newPreferences = [];
|
|
472
|
+
for (let i = 0; i < this.configuredDashboards.length; i++) {
|
|
473
|
+
const dashboard = this.configuredDashboards[i];
|
|
474
|
+
const newDisplayOrder = i + 1;
|
|
475
|
+
let prefEntity = existingByDashboardId.get(dashboard.ID);
|
|
476
|
+
if (prefEntity) {
|
|
477
|
+
// Update existing preference
|
|
478
|
+
console.log(`Updating existing preference for dashboard ${dashboard.Name}, new order: ${newDisplayOrder}`);
|
|
479
|
+
prefEntity.DisplayOrder = newDisplayOrder;
|
|
480
|
+
if (!(yield prefEntity.Save())) {
|
|
481
|
+
const errorMsg = ((_c = prefEntity.LatestResult) === null || _c === void 0 ? void 0 : _c.Error) || ((_d = prefEntity.LatestResult) === null || _d === void 0 ? void 0 : _d.Message) || 'Unknown error';
|
|
482
|
+
throw new Error(`Failed to update preference for dashboard ${dashboard.Name}: ${errorMsg}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
// Create new preference
|
|
487
|
+
console.log(`Creating new preference for dashboard ${dashboard.Name}, order: ${newDisplayOrder}`);
|
|
488
|
+
prefEntity = yield md.GetEntityObject('MJ: Dashboard User Preferences');
|
|
489
|
+
// Set UserID based on preference mode
|
|
490
|
+
if (this.isSysAdmin && this.scope === 'Global' && this.preferenceMode === 'system') {
|
|
491
|
+
prefEntity.UserID = null; // System default
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
prefEntity.UserID = md.CurrentUser.ID; // Personal preference
|
|
495
|
+
}
|
|
496
|
+
prefEntity.DashboardID = dashboard.ID;
|
|
497
|
+
prefEntity.DisplayOrder = newDisplayOrder;
|
|
498
|
+
prefEntity.Scope = this.scope;
|
|
499
|
+
prefEntity.ApplicationID = this.applicationId;
|
|
500
|
+
console.log('Creating preference entity:', {
|
|
501
|
+
UserID: prefEntity.UserID,
|
|
502
|
+
DashboardID: prefEntity.DashboardID,
|
|
503
|
+
DisplayOrder: prefEntity.DisplayOrder,
|
|
504
|
+
Scope: prefEntity.Scope,
|
|
505
|
+
ApplicationID: prefEntity.ApplicationID
|
|
506
|
+
});
|
|
507
|
+
if (!(yield prefEntity.Save())) {
|
|
508
|
+
const errorMsg = ((_e = prefEntity.LatestResult) === null || _e === void 0 ? void 0 : _e.Error) || ((_f = prefEntity.LatestResult) === null || _f === void 0 ? void 0 : _f.Message) || 'Unknown error';
|
|
509
|
+
throw new Error(`Failed to create preference for dashboard ${dashboard.Name}: ${errorMsg}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
newPreferences.push(prefEntity);
|
|
513
|
+
}
|
|
514
|
+
console.log('Successfully processed', newPreferences.length, 'preferences');
|
|
515
|
+
// Emit success result
|
|
516
|
+
this.result.emit({
|
|
517
|
+
saved: true,
|
|
518
|
+
preferences: newPreferences
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
console.error('Save error:', error);
|
|
523
|
+
LogError('Error saving dashboard preferences', null, error);
|
|
524
|
+
this.error = `Failed to save preferences: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
|
525
|
+
// Clear error after 5 seconds
|
|
526
|
+
setTimeout(() => {
|
|
527
|
+
this.error = null;
|
|
528
|
+
}, 5000);
|
|
529
|
+
}
|
|
530
|
+
finally {
|
|
531
|
+
this.saving = false;
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
onCancel() {
|
|
536
|
+
this.result.emit({ saved: false });
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
DashboardPreferencesDialogComponent.ɵfac = function DashboardPreferencesDialogComponent_Factory(t) { return new (t || DashboardPreferencesDialogComponent)(); };
|
|
540
|
+
DashboardPreferencesDialogComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardPreferencesDialogComponent, selectors: [["mj-dashboard-preferences-dialog"]], inputs: { applicationId: "applicationId", scope: "scope" }, outputs: { result: "result" }, decls: 21, vars: 11, consts: [["availableList", "cdkDropList"], ["configuredList", "cdkDropList"], ["title", "Dashboard Preferences", 3, "close", "width", "height", "minWidth", "minHeight"], [1, "dashboard-preferences-dialog"], [1, "dialog-header"], [1, "fa-solid", "fa-sliders"], [1, "scope-indicator"], [1, "preference-mode-selector"], [1, "dialog-content"], [1, "loading-container"], [1, "error-container"], [1, "preferences-panels"], [1, "dialog-footer"], ["type", "button", 1, "btn", "btn-secondary", 3, "click"], [1, "fa-solid", "fa-times"], ["type", "button", 1, "btn", "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-globe"], [1, "fa-solid", "fa-layer-group"], ["type", "radio", "name", "preferenceMode", "value", "personal", 3, "ngModelChange", "change", "ngModel"], ["type", "radio", "name", "preferenceMode", "value", "system", 3, "ngModelChange", "change", "ngModel"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "panel", "available-panel"], [1, "fa-solid", "fa-list"], ["cdkDropList", "", 1, "dashboard-list", 3, "cdkDropListDropped", "cdkDropListData", "cdkDropListConnectedTo"], [1, "empty-state"], ["cdkDrag", "", 1, "dashboard-item", "available-item", 3, "cdkDragData"], [1, "panel", "configured-panel"], [1, "fa-solid", "fa-list-ol"], ["cdkDrag", "", 1, "dashboard-item", "configured-item", 3, "cdkDragData"], [1, "fa-solid", "fa-info-circle"], [1, "dashboard-item-content"], [1, "fa-solid", "fa-grip-vertical", "drag-handle"], [1, "dashboard-info"], [1, "dashboard-name"], [1, "dashboard-description"], ["type", "button", "title", "Add to configured dashboards", 1, "add-button", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "order-number"], ["type", "button", "title", "Remove from configured dashboards", 1, "remove-button", 3, "click"], ["size", "small"], [1, "fa-solid", "fa-check"]], template: function DashboardPreferencesDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
541
|
+
i0.ɵɵelementStart(0, "kendo-dialog", 2);
|
|
542
|
+
i0.ɵɵlistener("close", function DashboardPreferencesDialogComponent_Template_kendo_dialog_close_0_listener() { return ctx.onCancel(); });
|
|
543
|
+
i0.ɵɵelementStart(1, "div", 3)(2, "div", 4)(3, "h3");
|
|
544
|
+
i0.ɵɵelement(4, "i", 5);
|
|
545
|
+
i0.ɵɵtext(5, " Dashboard Preferences");
|
|
546
|
+
i0.ɵɵelementEnd();
|
|
547
|
+
i0.ɵɵelementStart(6, "p", 6);
|
|
548
|
+
i0.ɵɵtemplate(7, DashboardPreferencesDialogComponent_Conditional_7_Template, 2, 0)(8, DashboardPreferencesDialogComponent_Conditional_8_Template, 2, 1);
|
|
549
|
+
i0.ɵɵelementEnd();
|
|
550
|
+
i0.ɵɵtemplate(9, DashboardPreferencesDialogComponent_Conditional_9_Template, 7, 2, "div", 7);
|
|
551
|
+
i0.ɵɵelementEnd();
|
|
552
|
+
i0.ɵɵelementStart(10, "div", 8);
|
|
553
|
+
i0.ɵɵtemplate(11, DashboardPreferencesDialogComponent_Conditional_11_Template, 3, 0, "div", 9)(12, DashboardPreferencesDialogComponent_Conditional_12_Template, 3, 1, "div", 10)(13, DashboardPreferencesDialogComponent_Conditional_13_Template, 19, 10, "div", 11);
|
|
554
|
+
i0.ɵɵelementEnd();
|
|
555
|
+
i0.ɵɵelementStart(14, "div", 12)(15, "button", 13);
|
|
556
|
+
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Template_button_click_15_listener() { return ctx.onCancel(); });
|
|
557
|
+
i0.ɵɵelement(16, "i", 14);
|
|
558
|
+
i0.ɵɵtext(17, " Cancel ");
|
|
559
|
+
i0.ɵɵelementEnd();
|
|
560
|
+
i0.ɵɵelementStart(18, "button", 15);
|
|
561
|
+
i0.ɵɵlistener("click", function DashboardPreferencesDialogComponent_Template_button_click_18_listener() { return ctx.onSave(); });
|
|
562
|
+
i0.ɵɵtemplate(19, DashboardPreferencesDialogComponent_Conditional_19_Template, 2, 0)(20, DashboardPreferencesDialogComponent_Conditional_20_Template, 2, 0);
|
|
563
|
+
i0.ɵɵelementEnd()()()();
|
|
564
|
+
} if (rf & 2) {
|
|
565
|
+
i0.ɵɵproperty("width", 800)("height", 600)("minWidth", 600)("minHeight", 400);
|
|
566
|
+
i0.ɵɵadvance(7);
|
|
567
|
+
i0.ɵɵconditional(ctx.scope === "Global" ? 7 : 8);
|
|
568
|
+
i0.ɵɵadvance(2);
|
|
569
|
+
i0.ɵɵconditional(ctx.isSysAdmin && ctx.scope === "Global" ? 9 : -1);
|
|
570
|
+
i0.ɵɵadvance(2);
|
|
571
|
+
i0.ɵɵconditional(ctx.loading ? 11 : -1);
|
|
572
|
+
i0.ɵɵadvance();
|
|
573
|
+
i0.ɵɵconditional(ctx.error ? 12 : -1);
|
|
574
|
+
i0.ɵɵadvance();
|
|
575
|
+
i0.ɵɵconditional(!ctx.loading && !ctx.error ? 13 : -1);
|
|
576
|
+
i0.ɵɵadvance(5);
|
|
577
|
+
i0.ɵɵproperty("disabled", !ctx.hasChanges || ctx.saving);
|
|
578
|
+
i0.ɵɵadvance();
|
|
579
|
+
i0.ɵɵconditional(ctx.saving ? 19 : 20);
|
|
580
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.RadioControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.DialogComponent, i3.LoaderComponent, i4.CdkDropList, i4.CdkDrag], styles: [".dashboard-preferences-dialog[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header[_ngcontent-%COMP%] {\n padding: 20px 24px 16px;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.dialog-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n color: #666;\n}\n\n.scope-indicator[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.scope-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 6px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: #495057;\n}\n\n.preference-mode-selector[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n margin: 0;\n}\n\n.dialog-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container[_ngcontent-%COMP%], .error-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n flex-direction: column;\n gap: 12px;\n}\n\n.error-container[_ngcontent-%COMP%] {\n color: #dc3545;\n}\n\n.error-container[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n margin-bottom: 8px;\n}\n\n.preferences-panels[_ngcontent-%COMP%] {\n display: flex;\n gap: 20px;\n height: 100%;\n}\n\n.panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.panel[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n}\n\n.panel[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n color: #6c757d;\n}\n\n.dashboard-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n min-height: 300px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100px;\n color: #6c757d;\n font-style: italic;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n opacity: 0.5;\n}\n\n.dashboard-item[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n background: white;\n transition: all 0.2s ease;\n cursor: move;\n}\n\n.dashboard-item[_ngcontent-%COMP%]:hover {\n border-color: #007bff;\n box-shadow: 0 2px 4px rgba(0, 123, 255, 0.1);\n}\n\n.dashboard-item.cdk-drag-preview[_ngcontent-%COMP%] {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform: rotate(2deg);\n}\n\n.dashboard-item.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0.3;\n border-style: dashed;\n}\n\n.dashboard-item-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n gap: 12px;\n}\n\n.drag-handle[_ngcontent-%COMP%] {\n color: #adb5bd;\n cursor: move;\n font-size: 14px;\n}\n\n.order-number[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: #007bff;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.dashboard-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.dashboard-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: #333;\n font-size: 14px;\n}\n\n.dashboard-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6c757d;\n line-height: 1.3;\n}\n\n.add-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #28a745;\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0.7;\n}\n\n.add-button[_ngcontent-%COMP%]:hover {\n background-color: rgba(40, 167, 69, 0.1);\n opacity: 1;\n}\n\n.remove-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #dc3545;\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n}\n\n.remove-button[_ngcontent-%COMP%]:hover {\n background-color: rgba(220, 53, 69, 0.1);\n}\n\n.cdk-drop-list-dragging[_ngcontent-%COMP%] .dashboard-item[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.dialog-footer[_ngcontent-%COMP%] {\n padding: 16px 24px;\n border-top: 1px solid #e0e0e0;\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n background: #f8f9fa;\n}\n\n.btn[_ngcontent-%COMP%] {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: white;\n border-color: #6c757d;\n color: #6c757d;\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #6c757d;\n color: white;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: #007bff;\n color: white;\n border-color: #007bff;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #0056b3;\n border-color: #0056b3;\n}\n\n\n\n@media (max-width: 768px) {\n .dashboard-preferences-dialog[_ngcontent-%COMP%] {\n width: 95vw;\n max-height: 90vh;\n }\n \n .preferences-panels[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 16px;\n }\n \n .panel[_ngcontent-%COMP%] {\n min-height: 200px;\n }\n \n .dashboard-list[_ngcontent-%COMP%] {\n min-height: 150px;\n }\n}"] });
|
|
581
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DashboardPreferencesDialogComponent, [{
|
|
582
|
+
type: Component,
|
|
583
|
+
args: [{ selector: 'mj-dashboard-preferences-dialog', template: "<kendo-dialog title=\"Dashboard Preferences\" \n [width]=\"800\" \n [height]=\"600\"\n [minWidth]=\"600\"\n [minHeight]=\"400\"\n (close)=\"onCancel()\">\n<div class=\"dashboard-preferences-dialog\">\n <div class=\"dialog-header\">\n <h3><i class=\"fa-solid fa-sliders\"></i> Dashboard Preferences</h3>\n <p class=\"scope-indicator\">\n @if (scope === 'Global') {\n <i class=\"fa-solid fa-globe\"></i> Global Scope\n } @else {\n <i class=\"fa-solid fa-layer-group\"></i> Application: {{ applicationName }}\n }\n </p>\n @if (isSysAdmin && scope === 'Global') {\n <div class=\"preference-mode-selector\">\n <label>\n <input type=\"radio\" \n name=\"preferenceMode\" \n value=\"personal\" \n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n Personal Preferences\n </label>\n <label>\n <input type=\"radio\" \n name=\"preferenceMode\" \n value=\"system\" \n [(ngModel)]=\"preferenceMode\"\n (change)=\"onPreferenceModeChange()\">\n System Defaults\n </label>\n </div>\n }\n </div>\n\n <div class=\"dialog-content\">\n @if (loading) {\n <div class=\"loading-container\">\n <kendo-loader></kendo-loader>\n Loading dashboards...\n </div>\n }\n\n @if (error) {\n <div class=\"error-container\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ error }}\n </div>\n }\n\n @if (!loading && !error) {\n <div class=\"preferences-panels\">\n <!-- Available Dashboards Panel -->\n <div class=\"panel available-panel\">\n <h4><i class=\"fa-solid fa-list\"></i> Available Dashboards</h4>\n <div class=\"dashboard-list\" \n cdkDropList \n #availableList=\"cdkDropList\"\n [cdkDropListData]=\"availableDashboards\"\n [cdkDropListConnectedTo]=\"[configuredList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n \n @if (availableDashboards.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n All dashboards are configured\n </div>\n }\n\n @for (dashboard of availableDashboards; track dashboard.ID) {\n <div class=\"dashboard-item available-item\" \n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\" \n class=\"add-button\"\n (click)=\"addDashboard(dashboard)\"\n title=\"Add to configured dashboards\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Configured Dashboards Panel -->\n <div class=\"panel configured-panel\">\n <h4><i class=\"fa-solid fa-list-ol\"></i> Configured Dashboards</h4>\n <div class=\"dashboard-list\" \n cdkDropList \n #configuredList=\"cdkDropList\"\n [cdkDropListData]=\"configuredDashboards\"\n [cdkDropListConnectedTo]=\"[availableList]\"\n (cdkDropListDropped)=\"onDrop($event)\">\n \n @if (configuredDashboards.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n No dashboards configured\n </div>\n }\n\n @for (dashboard of configuredDashboards; track dashboard.ID; let i = $index) {\n <div class=\"dashboard-item configured-item\" \n cdkDrag\n [cdkDragData]=\"dashboard\">\n <div class=\"dashboard-item-content\">\n <i class=\"fa-solid fa-grip-vertical drag-handle\"></i>\n <span class=\"order-number\">{{ i + 1 }}</span>\n <div class=\"dashboard-info\">\n <span class=\"dashboard-name\">{{ dashboard.Name }}</span>\n @if (dashboard.Description) {\n <span class=\"dashboard-description\">{{ dashboard.Description }}</span>\n }\n </div>\n <button type=\"button\" \n class=\"remove-button\"\n (click)=\"removeDashboard(dashboard)\"\n title=\"Remove from configured dashboards\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n\n <div class=\"dialog-footer\">\n <button type=\"button\" \n class=\"btn btn-secondary\" \n (click)=\"onCancel()\">\n <i class=\"fa-solid fa-times\"></i> Cancel\n </button>\n <button type=\"button\" \n class=\"btn btn-primary\" \n [disabled]=\"!hasChanges || saving\"\n (click)=\"onSave()\">\n @if (saving) {\n <kendo-loader size=\"small\"></kendo-loader>\n Saving...\n } @else {\n <i class=\"fa-solid fa-check\"></i> Save Changes\n }\n </button>\n </div>\n</div>\n</kendo-dialog>", styles: [".dashboard-preferences-dialog {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dialog-header {\n padding: 20px 24px 16px;\n border-bottom: 1px solid #e0e0e0;\n}\n\n.dialog-header h3 {\n margin: 0 0 8px 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n}\n\n.dialog-header h3 i {\n margin-right: 8px;\n color: #666;\n}\n\n.scope-indicator {\n margin: 0;\n font-size: 14px;\n color: #666;\n}\n\n.scope-indicator i {\n margin-right: 6px;\n}\n\n.preference-mode-selector {\n margin-top: 12px;\n display: flex;\n gap: 20px;\n}\n\n.preference-mode-selector label {\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n font-size: 14px;\n color: #495057;\n}\n\n.preference-mode-selector input[type=\"radio\"] {\n margin: 0;\n}\n\n.dialog-content {\n flex: 1;\n overflow: hidden;\n padding: 20px 24px;\n}\n\n.loading-container, .error-container {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n flex-direction: column;\n gap: 12px;\n}\n\n.error-container {\n color: #dc3545;\n}\n\n.error-container i {\n font-size: 24px;\n margin-bottom: 8px;\n}\n\n.preferences-panels {\n display: flex;\n gap: 20px;\n height: 100%;\n}\n\n.panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.panel h4 {\n margin: 0;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n}\n\n.panel h4 i {\n margin-right: 8px;\n color: #6c757d;\n}\n\n.dashboard-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n min-height: 300px;\n}\n\n.empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100px;\n color: #6c757d;\n font-style: italic;\n flex-direction: column;\n gap: 8px;\n}\n\n.empty-state i {\n font-size: 24px;\n opacity: 0.5;\n}\n\n.dashboard-item {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n background: white;\n transition: all 0.2s ease;\n cursor: move;\n}\n\n.dashboard-item:hover {\n border-color: #007bff;\n box-shadow: 0 2px 4px rgba(0, 123, 255, 0.1);\n}\n\n.dashboard-item.cdk-drag-preview {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transform: rotate(2deg);\n}\n\n.dashboard-item.cdk-drag-placeholder {\n opacity: 0.3;\n border-style: dashed;\n}\n\n.dashboard-item-content {\n display: flex;\n align-items: center;\n padding: 12px;\n gap: 12px;\n}\n\n.drag-handle {\n color: #adb5bd;\n cursor: move;\n font-size: 14px;\n}\n\n.order-number {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: #007bff;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.dashboard-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.dashboard-name {\n font-weight: 500;\n color: #333;\n font-size: 14px;\n}\n\n.dashboard-description {\n font-size: 12px;\n color: #6c757d;\n line-height: 1.3;\n}\n\n.add-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #28a745;\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n opacity: 0.7;\n}\n\n.add-button:hover {\n background-color: rgba(40, 167, 69, 0.1);\n opacity: 1;\n}\n\n.remove-button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #dc3545;\n border-radius: 4px;\n transition: background-color 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n}\n\n.remove-button:hover {\n background-color: rgba(220, 53, 69, 0.1);\n}\n\n.cdk-drop-list-dragging .dashboard-item:not(.cdk-drag-placeholder) {\n transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);\n}\n\n.dialog-footer {\n padding: 16px 24px;\n border-top: 1px solid #e0e0e0;\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n background: #f8f9fa;\n}\n\n.btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n border: 1px solid transparent;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-secondary {\n background: white;\n border-color: #6c757d;\n color: #6c757d;\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: #6c757d;\n color: white;\n}\n\n.btn-primary {\n background: #007bff;\n color: white;\n border-color: #007bff;\n}\n\n.btn-primary:hover:not(:disabled) {\n background: #0056b3;\n border-color: #0056b3;\n}\n\n/* Responsive design */\n@media (max-width: 768px) {\n .dashboard-preferences-dialog {\n width: 95vw;\n max-height: 90vh;\n }\n \n .preferences-panels {\n flex-direction: column;\n gap: 16px;\n }\n \n .panel {\n min-height: 200px;\n }\n \n .dashboard-list {\n min-height: 150px;\n }\n}"] }]
|
|
584
|
+
}], null, { applicationId: [{
|
|
585
|
+
type: Input
|
|
586
|
+
}], scope: [{
|
|
587
|
+
type: Input
|
|
588
|
+
}], result: [{
|
|
589
|
+
type: Output
|
|
590
|
+
}] }); })();
|
|
591
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DashboardPreferencesDialogComponent, { className: "DashboardPreferencesDialogComponent", filePath: "src/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.ts", lineNumber: 16 }); })();
|
|
592
|
+
//# sourceMappingURL=dashboard-preferences-dialog.component.js.map
|