@memberjunction/ng-entity-viewer 5.43.0 → 5.44.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/aggregate-panel/aggregate-panel.component.d.ts +5 -0
- package/dist/lib/aggregate-panel/aggregate-panel.component.d.ts.map +1 -1
- package/dist/lib/aggregate-panel/aggregate-panel.component.js +45 -47
- package/dist/lib/aggregate-panel/aggregate-panel.component.js.map +1 -1
- package/dist/lib/entity-cards/entity-cards.component.js +7 -10
- package/dist/lib/entity-cards/entity-cards.component.js.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts +10 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.js +35 -34
- package/dist/lib/entity-data-grid/entity-data-grid.component.js.map +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts +0 -4
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.d.ts.map +1 -1
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js +166 -207
- package/dist/lib/entity-record-detail-panel/entity-record-detail-panel.component.js.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts +109 -5
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.js +287 -42
- package/dist/lib/entity-viewer/entity-viewer.component.js.map +1 -1
- package/dist/lib/recycle-bin/recycle-bin.component.js +21 -44
- package/dist/lib/recycle-bin/recycle-bin.component.js.map +1 -1
- package/dist/lib/shared-view-warning-dialog/shared-view-warning-dialog.component.js +19 -20
- package/dist/lib/shared-view-warning-dialog/shared-view-warning-dialog.component.js.map +1 -1
- package/dist/lib/view-config-panel/view-config-panel.component.js +268 -301
- package/dist/lib/view-config-panel/view-config-panel.component.js.map +1 -1
- package/dist/lib/view-selector/view-selector.component.d.ts +26 -1
- package/dist/lib/view-selector/view-selector.component.d.ts.map +1 -1
- package/dist/lib/view-selector/view-selector.component.js +118 -76
- package/dist/lib/view-selector/view-selector.component.js.map +1 -1
- package/dist/lib/view-types/descriptors/grid-view-type.d.ts +7 -0
- package/dist/lib/view-types/descriptors/grid-view-type.d.ts.map +1 -1
- package/dist/lib/view-types/descriptors/grid-view-type.js +7 -0
- package/dist/lib/view-types/descriptors/grid-view-type.js.map +1 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.d.ts +18 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/grid-view-renderer.component.js +29 -3
- package/dist/lib/view-types/renderers/grid-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/renderers/map-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/map-view-renderer.component.js +11 -14
- package/dist/lib/view-types/renderers/map-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.d.ts.map +1 -1
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.js +12 -14
- package/dist/lib/view-types/renderers/timeline-view-renderer.component.js.map +1 -1
- package/dist/lib/view-types/view-type.contracts.d.ts +44 -0
- package/dist/lib/view-types/view-type.contracts.d.ts.map +1 -1
- package/dist/lib/view-types/view-type.contracts.js +6 -0
- package/dist/lib/view-types/view-type.contracts.js.map +1 -1
- package/dist/lib/view-workspace/view-workspace.component.d.ts +32 -1
- package/dist/lib/view-workspace/view-workspace.component.d.ts.map +1 -1
- package/dist/lib/view-workspace/view-workspace.component.js +68 -7
- package/dist/lib/view-workspace/view-workspace.component.js.map +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +10 -1
- package/dist/module.js.map +1 -1
- package/package.json +18 -17
- package/dist/__tests__/entity-cards-selection.test.d.ts +0 -2
- package/dist/__tests__/entity-cards-selection.test.d.ts.map +0 -1
- package/dist/__tests__/entity-cards-selection.test.js +0 -149
- package/dist/__tests__/entity-cards-selection.test.js.map +0 -1
- package/dist/__tests__/entity-cards-viewmodel.test.d.ts +0 -2
- package/dist/__tests__/entity-cards-viewmodel.test.d.ts.map +0 -1
- package/dist/__tests__/entity-cards-viewmodel.test.js +0 -208
- package/dist/__tests__/entity-cards-viewmodel.test.js.map +0 -1
- package/dist/__tests__/highlight.test.d.ts +0 -2
- package/dist/__tests__/highlight.test.d.ts.map +0 -1
- package/dist/__tests__/highlight.test.js +0 -67
- package/dist/__tests__/highlight.test.js.map +0 -1
- package/dist/__tests__/index.test.d.ts +0 -2
- package/dist/__tests__/index.test.d.ts.map +0 -1
- package/dist/__tests__/index.test.js +0 -7
- package/dist/__tests__/index.test.js.map +0 -1
- package/dist/__tests__/view-types.test.d.ts +0 -2
- package/dist/__tests__/view-types.test.d.ts.map +0 -1
- package/dist/__tests__/view-types.test.js +0 -102
- package/dist/__tests__/view-types.test.js.map +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
|
|
2
2
|
import { UserViewEngine } from '@memberjunction/core-entities';
|
|
3
3
|
import { Subject } from 'rxjs';
|
|
4
|
+
import { takeUntil } from 'rxjs/operators';
|
|
4
5
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
5
6
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
7
8
|
import * as i1 from "@angular/forms";
|
|
9
|
+
import * as i2 from "@memberjunction/ng-ui-components";
|
|
8
10
|
const _forTrack0 = ($index, $item) => $item.id;
|
|
9
11
|
function ViewSelectorComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
10
12
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -30,12 +32,12 @@ function ViewSelectorComponent_Conditional_9_Conditional_18_Template(rf, ctx) {
|
|
|
30
32
|
i0.ɵɵelement(0, "i", 32);
|
|
31
33
|
} }
|
|
32
34
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
33
|
-
i0.ɵɵelementStart(0, "span",
|
|
35
|
+
i0.ɵɵelementStart(0, "span", 45);
|
|
34
36
|
i0.ɵɵtext(1, "Default");
|
|
35
37
|
i0.ɵɵelementEnd();
|
|
36
38
|
} }
|
|
37
39
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
38
|
-
i0.ɵɵelementStart(0, "div",
|
|
40
|
+
i0.ɵɵelementStart(0, "div", 46);
|
|
39
41
|
i0.ɵɵtext(1);
|
|
40
42
|
i0.ɵɵelementEnd();
|
|
41
43
|
} if (rf & 2) {
|
|
@@ -45,7 +47,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_7_
|
|
|
45
47
|
} }
|
|
46
48
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
47
49
|
i0.ɵɵelementStart(0, "span");
|
|
48
|
-
i0.ɵɵelement(1, "i",
|
|
50
|
+
i0.ɵɵelement(1, "i", 55);
|
|
49
51
|
i0.ɵɵtext(2);
|
|
50
52
|
i0.ɵɵelementEnd();
|
|
51
53
|
} if (rf & 2) {
|
|
@@ -56,7 +58,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_
|
|
|
56
58
|
} }
|
|
57
59
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
58
60
|
i0.ɵɵelementStart(0, "span");
|
|
59
|
-
i0.ɵɵelement(1, "i",
|
|
61
|
+
i0.ɵɵelement(1, "i", 56);
|
|
60
62
|
i0.ɵɵtext(2);
|
|
61
63
|
i0.ɵɵelementEnd();
|
|
62
64
|
} if (rf & 2) {
|
|
@@ -67,7 +69,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_
|
|
|
67
69
|
} }
|
|
68
70
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
69
71
|
i0.ɵɵelementStart(0, "span");
|
|
70
|
-
i0.ɵɵelement(1, "i",
|
|
72
|
+
i0.ɵɵelement(1, "i", 57);
|
|
71
73
|
i0.ɵɵtext(2);
|
|
72
74
|
i0.ɵɵelementEnd();
|
|
73
75
|
} if (rf & 2) {
|
|
@@ -77,7 +79,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_
|
|
|
77
79
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.GetViewSortInfo(view_r5));
|
|
78
80
|
} }
|
|
79
81
|
function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
-
i0.ɵɵelementStart(0, "div",
|
|
82
|
+
i0.ɵɵelementStart(0, "div", 47);
|
|
81
83
|
i0.ɵɵconditionalCreate(1, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_1_Template, 3, 2, "span");
|
|
82
84
|
i0.ɵɵconditionalCreate(2, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_2_Template, 3, 2, "span");
|
|
83
85
|
i0.ɵɵconditionalCreate(3, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Conditional_3_Template, 3, 1, "span");
|
|
@@ -100,26 +102,26 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template(rf, c
|
|
|
100
102
|
i0.ɵɵelementStart(0, "div", 27);
|
|
101
103
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template_div_click_0_listener() { const view_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SelectView(view_r5)); });
|
|
102
104
|
i0.ɵɵelementStart(1, "div", 28);
|
|
103
|
-
i0.ɵɵelement(2, "i",
|
|
105
|
+
i0.ɵɵelement(2, "i", 44);
|
|
104
106
|
i0.ɵɵelementEnd();
|
|
105
107
|
i0.ɵɵelementStart(3, "div", 30)(4, "div", 31);
|
|
106
108
|
i0.ɵɵtext(5);
|
|
107
|
-
i0.ɵɵconditionalCreate(6, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_6_Template, 2, 0, "span",
|
|
109
|
+
i0.ɵɵconditionalCreate(6, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_6_Template, 2, 0, "span", 45);
|
|
108
110
|
i0.ɵɵelementEnd();
|
|
109
|
-
i0.ɵɵconditionalCreate(7, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_7_Template, 2, 1, "div",
|
|
110
|
-
i0.ɵɵconditionalCreate(8, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Template, 4, 3, "div",
|
|
111
|
+
i0.ɵɵconditionalCreate(7, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_7_Template, 2, 1, "div", 46);
|
|
112
|
+
i0.ɵɵconditionalCreate(8, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_8_Template, 4, 3, "div", 47);
|
|
111
113
|
i0.ɵɵelementEnd();
|
|
112
|
-
i0.ɵɵelementStart(9, "div",
|
|
114
|
+
i0.ɵɵelementStart(9, "div", 48)(10, "button", 49);
|
|
113
115
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template_button_click_10_listener($event) { const view_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnDuplicateView(view_r5.id, $event)); });
|
|
114
|
-
i0.ɵɵelement(11, "i",
|
|
116
|
+
i0.ɵɵelement(11, "i", 50);
|
|
115
117
|
i0.ɵɵelementEnd();
|
|
116
|
-
i0.ɵɵelementStart(12, "button",
|
|
118
|
+
i0.ɵɵelementStart(12, "button", 51);
|
|
117
119
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template_button_click_12_listener($event) { const view_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnConfigureViewById(view_r5.id, $event)); });
|
|
118
|
-
i0.ɵɵelement(13, "i",
|
|
120
|
+
i0.ɵɵelement(13, "i", 52);
|
|
119
121
|
i0.ɵɵelementEnd();
|
|
120
|
-
i0.ɵɵelementStart(14, "button",
|
|
122
|
+
i0.ɵɵelementStart(14, "button", 53);
|
|
121
123
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template_button_click_14_listener($event) { const view_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnOpenViewInTab(view_r5.id, $event)); });
|
|
122
|
-
i0.ɵɵelement(15, "i",
|
|
124
|
+
i0.ɵɵelement(15, "i", 54);
|
|
123
125
|
i0.ɵɵelementEnd()();
|
|
124
126
|
i0.ɵɵconditionalCreate(16, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Conditional_16_Template, 1, 0, "i", 32);
|
|
125
127
|
i0.ɵɵelementEnd();
|
|
@@ -141,15 +143,15 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template(rf, c
|
|
|
141
143
|
i0.ɵɵconditional(ctx_r1.SelectedViewID === view_r5.id ? 16 : -1);
|
|
142
144
|
} }
|
|
143
145
|
function ViewSelectorComponent_Conditional_9_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
144
|
-
i0.ɵɵelementStart(0, "div", 26)(1, "div",
|
|
145
|
-
i0.ɵɵelement(2, "i",
|
|
146
|
+
i0.ɵɵelementStart(0, "div", 26)(1, "div", 40);
|
|
147
|
+
i0.ɵɵelement(2, "i", 41);
|
|
146
148
|
i0.ɵɵelementStart(3, "span");
|
|
147
149
|
i0.ɵɵtext(4, "My Views");
|
|
148
150
|
i0.ɵɵelementEnd();
|
|
149
|
-
i0.ɵɵelementStart(5, "span",
|
|
151
|
+
i0.ɵɵelementStart(5, "span", 42);
|
|
150
152
|
i0.ɵɵtext(6);
|
|
151
153
|
i0.ɵɵelementEnd()();
|
|
152
|
-
i0.ɵɵrepeaterCreate(7, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template, 17, 9, "div",
|
|
154
|
+
i0.ɵɵrepeaterCreate(7, ViewSelectorComponent_Conditional_9_Conditional_19_For_8_Template, 17, 9, "div", 43, _forTrack0);
|
|
153
155
|
i0.ɵɵelementEnd();
|
|
154
156
|
} if (rf & 2) {
|
|
155
157
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -159,17 +161,17 @@ function ViewSelectorComponent_Conditional_9_Conditional_19_Template(rf, ctx) {
|
|
|
159
161
|
i0.ɵɵrepeater(ctx_r1.FilteredMyViews);
|
|
160
162
|
} }
|
|
161
163
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
162
|
-
i0.ɵɵelementStart(0, "span",
|
|
164
|
+
i0.ɵɵelementStart(0, "span", 61);
|
|
163
165
|
i0.ɵɵtext(1, "View Only");
|
|
164
166
|
i0.ɵɵelementEnd();
|
|
165
167
|
} }
|
|
166
168
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
167
|
-
i0.ɵɵelementStart(0, "span",
|
|
169
|
+
i0.ɵɵelementStart(0, "span", 62);
|
|
168
170
|
i0.ɵɵtext(1, "Can Edit");
|
|
169
171
|
i0.ɵɵelementEnd();
|
|
170
172
|
} }
|
|
171
173
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
172
|
-
i0.ɵɵelementStart(0, "div",
|
|
174
|
+
i0.ɵɵelementStart(0, "div", 46);
|
|
173
175
|
i0.ɵɵtext(1);
|
|
174
176
|
i0.ɵɵelementEnd();
|
|
175
177
|
} if (rf & 2) {
|
|
@@ -179,7 +181,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_8_
|
|
|
179
181
|
} }
|
|
180
182
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
181
183
|
i0.ɵɵelementStart(0, "span");
|
|
182
|
-
i0.ɵɵelement(1, "i",
|
|
184
|
+
i0.ɵɵelement(1, "i", 55);
|
|
183
185
|
i0.ɵɵtext(2);
|
|
184
186
|
i0.ɵɵelementEnd();
|
|
185
187
|
} if (rf & 2) {
|
|
@@ -190,7 +192,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_
|
|
|
190
192
|
} }
|
|
191
193
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
192
194
|
i0.ɵɵelementStart(0, "span");
|
|
193
|
-
i0.ɵɵelement(1, "i",
|
|
195
|
+
i0.ɵɵelement(1, "i", 56);
|
|
194
196
|
i0.ɵɵtext(2);
|
|
195
197
|
i0.ɵɵelementEnd();
|
|
196
198
|
} if (rf & 2) {
|
|
@@ -200,7 +202,7 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_
|
|
|
200
202
|
i0.ɵɵtextInterpolate2(" ", ctx_r1.GetViewColumnCount(view_r7), " col", ctx_r1.GetViewColumnCount(view_r7) !== 1 ? "s" : "");
|
|
201
203
|
} }
|
|
202
204
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
203
|
-
i0.ɵɵelementStart(0, "div",
|
|
205
|
+
i0.ɵɵelementStart(0, "div", 47);
|
|
204
206
|
i0.ɵɵconditionalCreate(1, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Conditional_1_Template, 3, 2, "span");
|
|
205
207
|
i0.ɵɵconditionalCreate(2, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Conditional_2_Template, 3, 2, "span");
|
|
206
208
|
i0.ɵɵelementEnd();
|
|
@@ -214,9 +216,9 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_
|
|
|
214
216
|
} }
|
|
215
217
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
216
218
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
217
|
-
i0.ɵɵelementStart(0, "button",
|
|
219
|
+
i0.ɵɵelementStart(0, "button", 51);
|
|
218
220
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_13_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r8); const view_r7 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnConfigureViewById(view_r7.id, $event)); });
|
|
219
|
-
i0.ɵɵelement(1, "i",
|
|
221
|
+
i0.ɵɵelement(1, "i", 52);
|
|
220
222
|
i0.ɵɵelementEnd();
|
|
221
223
|
} }
|
|
222
224
|
function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -226,21 +228,21 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template(rf, c
|
|
|
226
228
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
227
229
|
i0.ɵɵelementStart(0, "div", 27);
|
|
228
230
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template_div_click_0_listener() { const view_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SelectView(view_r7)); });
|
|
229
|
-
i0.ɵɵelementStart(1, "div",
|
|
230
|
-
i0.ɵɵelement(2, "i",
|
|
231
|
+
i0.ɵɵelementStart(1, "div", 59);
|
|
232
|
+
i0.ɵɵelement(2, "i", 60);
|
|
231
233
|
i0.ɵɵelementEnd();
|
|
232
234
|
i0.ɵɵelementStart(3, "div", 30)(4, "div", 31);
|
|
233
235
|
i0.ɵɵtext(5);
|
|
234
|
-
i0.ɵɵconditionalCreate(6, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_6_Template, 2, 0, "span",
|
|
236
|
+
i0.ɵɵconditionalCreate(6, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_6_Template, 2, 0, "span", 61)(7, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_7_Template, 2, 0, "span", 62);
|
|
235
237
|
i0.ɵɵelementEnd();
|
|
236
|
-
i0.ɵɵconditionalCreate(8, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_8_Template, 2, 1, "div",
|
|
237
|
-
i0.ɵɵconditionalCreate(9, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Template, 3, 2, "div",
|
|
238
|
+
i0.ɵɵconditionalCreate(8, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_8_Template, 2, 1, "div", 46);
|
|
239
|
+
i0.ɵɵconditionalCreate(9, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_9_Template, 3, 2, "div", 47);
|
|
238
240
|
i0.ɵɵelementEnd();
|
|
239
|
-
i0.ɵɵelementStart(10, "div",
|
|
241
|
+
i0.ɵɵelementStart(10, "div", 48)(11, "button", 63);
|
|
240
242
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template_button_click_11_listener($event) { const view_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnDuplicateView(view_r7.id, $event)); });
|
|
241
|
-
i0.ɵɵelement(12, "i",
|
|
243
|
+
i0.ɵɵelement(12, "i", 50);
|
|
242
244
|
i0.ɵɵelementEnd();
|
|
243
|
-
i0.ɵɵconditionalCreate(13, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_13_Template, 2, 0, "button",
|
|
245
|
+
i0.ɵɵconditionalCreate(13, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_13_Template, 2, 0, "button", 64);
|
|
244
246
|
i0.ɵɵelementEnd();
|
|
245
247
|
i0.ɵɵconditionalCreate(14, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Conditional_14_Template, 1, 0, "i", 32);
|
|
246
248
|
i0.ɵɵelementEnd();
|
|
@@ -262,15 +264,15 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template(rf, c
|
|
|
262
264
|
i0.ɵɵconditional(ctx_r1.SelectedViewID === view_r7.id ? 14 : -1);
|
|
263
265
|
} }
|
|
264
266
|
function ViewSelectorComponent_Conditional_9_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
265
|
-
i0.ɵɵelementStart(0, "div", 26)(1, "div",
|
|
266
|
-
i0.ɵɵelement(2, "i",
|
|
267
|
+
i0.ɵɵelementStart(0, "div", 26)(1, "div", 40);
|
|
268
|
+
i0.ɵɵelement(2, "i", 58);
|
|
267
269
|
i0.ɵɵelementStart(3, "span");
|
|
268
270
|
i0.ɵɵtext(4, "Shared With Me");
|
|
269
271
|
i0.ɵɵelementEnd();
|
|
270
|
-
i0.ɵɵelementStart(5, "span",
|
|
272
|
+
i0.ɵɵelementStart(5, "span", 42);
|
|
271
273
|
i0.ɵɵtext(6);
|
|
272
274
|
i0.ɵɵelementEnd()();
|
|
273
|
-
i0.ɵɵrepeaterCreate(7, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template, 15, 8, "div",
|
|
275
|
+
i0.ɵɵrepeaterCreate(7, ViewSelectorComponent_Conditional_9_Conditional_20_For_8_Template, 15, 8, "div", 43, _forTrack0);
|
|
274
276
|
i0.ɵɵelementEnd();
|
|
275
277
|
} if (rf & 2) {
|
|
276
278
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -280,29 +282,17 @@ function ViewSelectorComponent_Conditional_9_Conditional_20_Template(rf, ctx) {
|
|
|
280
282
|
i0.ɵɵrepeater(ctx_r1.FilteredSharedViews);
|
|
281
283
|
} }
|
|
282
284
|
function ViewSelectorComponent_Conditional_9_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
283
|
-
i0.ɵɵ
|
|
284
|
-
i0.ɵɵelement(1, "i", 64);
|
|
285
|
-
i0.ɵɵelementStart(2, "div", 65)(3, "strong");
|
|
286
|
-
i0.ɵɵtext(4, "No saved views yet");
|
|
287
|
-
i0.ɵɵelementEnd();
|
|
288
|
-
i0.ɵɵelementStart(5, "span");
|
|
289
|
-
i0.ɵɵtext(6, "Save your current configuration as a view");
|
|
290
|
-
i0.ɵɵelementEnd()()();
|
|
285
|
+
i0.ɵɵelement(0, "mj-empty-state", 33);
|
|
291
286
|
} }
|
|
292
287
|
function ViewSelectorComponent_Conditional_9_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
293
|
-
i0.ɵɵ
|
|
294
|
-
i0.ɵɵelement(1, "i", 66);
|
|
295
|
-
i0.ɵɵelementStart(2, "span");
|
|
296
|
-
i0.ɵɵtext(3);
|
|
297
|
-
i0.ɵɵelementEnd()();
|
|
288
|
+
i0.ɵɵelement(0, "mj-empty-state", 34);
|
|
298
289
|
} if (rf & 2) {
|
|
299
290
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
300
|
-
i0.ɵɵ
|
|
301
|
-
i0.ɵɵtextInterpolate1("No views match \"", ctx_r1.SearchText, "\"");
|
|
291
|
+
i0.ɵɵproperty("Title", ctx_r1.NoViewsMatchMessage);
|
|
302
292
|
} }
|
|
303
293
|
function ViewSelectorComponent_Conditional_9_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
304
|
-
i0.ɵɵelementStart(0, "div",
|
|
305
|
-
i0.ɵɵelement(1, "i",
|
|
294
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
295
|
+
i0.ɵɵelement(1, "i", 65);
|
|
306
296
|
i0.ɵɵelementStart(2, "span");
|
|
307
297
|
i0.ɵɵtext(3, "Loading views...");
|
|
308
298
|
i0.ɵɵelementEnd()();
|
|
@@ -335,19 +325,19 @@ function ViewSelectorComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
|
335
325
|
i0.ɵɵelementEnd()();
|
|
336
326
|
i0.ɵɵconditionalCreate(19, ViewSelectorComponent_Conditional_9_Conditional_19_Template, 9, 1, "div", 26);
|
|
337
327
|
i0.ɵɵconditionalCreate(20, ViewSelectorComponent_Conditional_9_Conditional_20_Template, 9, 1, "div", 26);
|
|
338
|
-
i0.ɵɵconditionalCreate(21, ViewSelectorComponent_Conditional_9_Conditional_21_Template,
|
|
339
|
-
i0.ɵɵconditionalCreate(22, ViewSelectorComponent_Conditional_9_Conditional_22_Template,
|
|
340
|
-
i0.ɵɵconditionalCreate(23, ViewSelectorComponent_Conditional_9_Conditional_23_Template, 4, 0, "div",
|
|
328
|
+
i0.ɵɵconditionalCreate(21, ViewSelectorComponent_Conditional_9_Conditional_21_Template, 1, 0, "mj-empty-state", 33);
|
|
329
|
+
i0.ɵɵconditionalCreate(22, ViewSelectorComponent_Conditional_9_Conditional_22_Template, 1, 1, "mj-empty-state", 34);
|
|
330
|
+
i0.ɵɵconditionalCreate(23, ViewSelectorComponent_Conditional_9_Conditional_23_Template, 4, 0, "div", 35);
|
|
341
331
|
i0.ɵɵelementEnd();
|
|
342
|
-
i0.ɵɵelementStart(24, "div",
|
|
332
|
+
i0.ɵɵelementStart(24, "div", 36)(25, "button", 37);
|
|
343
333
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnQuickSave()); });
|
|
344
334
|
i0.ɵɵelement(26, "i", 13);
|
|
345
335
|
i0.ɵɵelementStart(27, "span");
|
|
346
336
|
i0.ɵɵtext(28, "New View");
|
|
347
337
|
i0.ɵɵelementEnd()();
|
|
348
|
-
i0.ɵɵelementStart(29, "button",
|
|
338
|
+
i0.ɵɵelementStart(29, "button", 38);
|
|
349
339
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_9_Template_button_click_29_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnResetToDefault()); });
|
|
350
|
-
i0.ɵɵelement(30, "i",
|
|
340
|
+
i0.ɵɵelement(30, "i", 39);
|
|
351
341
|
i0.ɵɵelementStart(31, "span");
|
|
352
342
|
i0.ɵɵtext(32, "Reset to Default");
|
|
353
343
|
i0.ɵɵelementEnd()()()();
|
|
@@ -376,9 +366,9 @@ function ViewSelectorComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
|
376
366
|
} }
|
|
377
367
|
function ViewSelectorComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
378
368
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
379
|
-
i0.ɵɵelementStart(0, "button",
|
|
369
|
+
i0.ɵɵelementStart(0, "button", 66);
|
|
380
370
|
i0.ɵɵlistener("click", function ViewSelectorComponent_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnOpenInTab()); });
|
|
381
|
-
i0.ɵɵelement(1, "i",
|
|
371
|
+
i0.ɵɵelement(1, "i", 67);
|
|
382
372
|
i0.ɵɵelementEnd();
|
|
383
373
|
} }
|
|
384
374
|
/**
|
|
@@ -453,6 +443,8 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
453
443
|
SelectedView = null;
|
|
454
444
|
SearchText = '';
|
|
455
445
|
destroy$ = new Subject();
|
|
446
|
+
/** Guards the one-time reactive subscription to UserViewEngine set up in {@link ensureEngineSubscription}. */
|
|
447
|
+
subscribedToEngine = false;
|
|
456
448
|
get metadata() { return this.ProviderToUse; }
|
|
457
449
|
constructor(cdr) {
|
|
458
450
|
super();
|
|
@@ -461,7 +453,7 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
461
453
|
ngOnChanges(changes) {
|
|
462
454
|
if (changes['Entity']) {
|
|
463
455
|
if (this.Entity) {
|
|
464
|
-
this.LoadViews();
|
|
456
|
+
void this.LoadViews();
|
|
465
457
|
}
|
|
466
458
|
else {
|
|
467
459
|
this.MyViews = [];
|
|
@@ -479,7 +471,14 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
479
471
|
this.destroy$.complete();
|
|
480
472
|
}
|
|
481
473
|
/**
|
|
482
|
-
*
|
|
474
|
+
* Ensure the {@link UserViewEngine} cache is loaded, establish a one-time reactive
|
|
475
|
+
* subscription to it, and (re)derive the view lists for the current entity.
|
|
476
|
+
*
|
|
477
|
+
* The subscription is what keeps this dropdown correct: BaseEntity `.Save()`/`.Delete()`
|
|
478
|
+
* on a User View auto-invalidates the engine cache (an in-place array mutation), which
|
|
479
|
+
* emits on `ObserveProperty('_views')`. So when the workspace creates, updates, duplicates,
|
|
480
|
+
* or deletes a view, the list here re-derives automatically — no manual reload required,
|
|
481
|
+
* and no stale-cache race between a fire-and-forget reload and the async cache update.
|
|
483
482
|
*/
|
|
484
483
|
async LoadViews() {
|
|
485
484
|
if (!this.Entity) {
|
|
@@ -488,11 +487,49 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
488
487
|
this.IsLoading = true;
|
|
489
488
|
this.cdr.detectChanges();
|
|
490
489
|
try {
|
|
491
|
-
|
|
492
|
-
//
|
|
493
|
-
// The engine is initialized once and caches all views; GetAccessibleViewsForEntity()
|
|
494
|
-
// already filters by owned + shared and checks UserCanView.
|
|
490
|
+
// Load once; subsequent calls are cheap no-ops. We never force a refresh here — the
|
|
491
|
+
// reactive subscription below keeps the lists fresh once data has changed.
|
|
495
492
|
await UserViewEngine.Instance.Config(false);
|
|
493
|
+
}
|
|
494
|
+
catch (error) {
|
|
495
|
+
console.error('Failed to load views:', error);
|
|
496
|
+
}
|
|
497
|
+
finally {
|
|
498
|
+
this.IsLoading = false;
|
|
499
|
+
}
|
|
500
|
+
this.ensureEngineSubscription();
|
|
501
|
+
this.recomputeViews();
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Subscribe (once for the component's lifetime) to the engine's cached `_views` array.
|
|
505
|
+
* The BehaviorSubject replays the current array on subscribe and re-emits on every
|
|
506
|
+
* subsequent create/update/delete/refresh, so {@link recomputeViews} runs whenever the
|
|
507
|
+
* underlying data actually changes.
|
|
508
|
+
*/
|
|
509
|
+
ensureEngineSubscription() {
|
|
510
|
+
if (this.subscribedToEngine) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
this.subscribedToEngine = true;
|
|
514
|
+
UserViewEngine.Instance
|
|
515
|
+
.ObserveProperty('_views')
|
|
516
|
+
.pipe(takeUntil(this.destroy$))
|
|
517
|
+
.subscribe(() => this.recomputeViews());
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Re-derive the owned/shared view lists for the current entity from the engine cache.
|
|
521
|
+
* `GetAccessibleViewsForEntity()` already filters by owned + shared and checks UserCanView.
|
|
522
|
+
*/
|
|
523
|
+
recomputeViews() {
|
|
524
|
+
if (!this.Entity) {
|
|
525
|
+
this.MyViews = [];
|
|
526
|
+
this.SharedViews = [];
|
|
527
|
+
this.SelectedView = null;
|
|
528
|
+
this.cdr.detectChanges();
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
try {
|
|
532
|
+
const userId = this.metadata.CurrentUser?.ID;
|
|
496
533
|
const accessibleViews = UserViewEngine.Instance.GetAccessibleViewsForEntity(this.Entity.ID);
|
|
497
534
|
// Separate into owned and shared
|
|
498
535
|
this.MyViews = accessibleViews
|
|
@@ -505,10 +542,9 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
505
542
|
this.updateSelectedViewFromId();
|
|
506
543
|
}
|
|
507
544
|
catch (error) {
|
|
508
|
-
console.error('Failed to
|
|
545
|
+
console.error('Failed to derive views:', error);
|
|
509
546
|
}
|
|
510
547
|
finally {
|
|
511
|
-
this.IsLoading = false;
|
|
512
548
|
this.cdr.detectChanges();
|
|
513
549
|
}
|
|
514
550
|
}
|
|
@@ -662,6 +698,12 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
662
698
|
get HasViews() {
|
|
663
699
|
return this.MyViews.length > 0 || this.SharedViews.length > 0;
|
|
664
700
|
}
|
|
701
|
+
/**
|
|
702
|
+
* Title for the "no search results" empty state — echoes the current search term.
|
|
703
|
+
*/
|
|
704
|
+
get NoViewsMatchMessage() {
|
|
705
|
+
return `No views match "${this.SearchText}"`;
|
|
706
|
+
}
|
|
665
707
|
/**
|
|
666
708
|
* Check if the current user can edit the selected view
|
|
667
709
|
*/
|
|
@@ -782,7 +824,7 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
782
824
|
this.SelectDefault();
|
|
783
825
|
}
|
|
784
826
|
static ɵfac = function ViewSelectorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewSelectorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
785
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewSelectorComponent, selectors: [["mj-view-selector"]], inputs: { Entity: "Entity", SelectedViewID: "SelectedViewID", ViewModified: "ViewModified" }, outputs: { ViewSelected: "ViewSelected", SaveViewRequested: "SaveViewRequested", ManageViewsRequested: "ManageViewsRequested", OpenInTabRequested: "OpenInTabRequested", ConfigureViewRequested: "ConfigureViewRequested", CreateNewRecordRequested: "CreateNewRecordRequested", ExportRequested: "ExportRequested", DuplicateViewRequested: "DuplicateViewRequested", QuickSaveRequested: "QuickSaveRequested", RevertRequested: "RevertRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 17, vars: 12, consts: [[1, "vs-container"], [1, "vs-backdrop"], [1, "vs-wrapper"], ["title", "Select a saved view", 1, "vs-button", 3, "click", "disabled"], [1, "fa-solid", "fa-layer-group", "vs-btn-icon"], [1, "vs-btn-name"], ["title", "View has unsaved changes", 1, "vs-modified-dot"], [1, "fa-solid", "fa-chevron-down", "vs-arrow"], [1, "vs-panel"], ["title", "Open this view in a new tab", 1, "vs-icon-btn"], ["title", "Configure view settings (columns, filters, sorting)", 1, "vs-icon-btn", 3, "click"], [1, "fa-solid", "fa-sliders-h"], ["title", "Create new record", 1, "vs-icon-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Export to Excel", 1, "vs-icon-btn", "vs-export-btn", 3, "click"], [1, "fa-solid", "fa-file-excel"], [1, "vs-backdrop", 3, "click"], [1, "vs-panel-header"], [1, "fa-solid", "fa-table-list", "vs-header-icon"], [1, "vs-panel-title"], [1, "vs-Entity-badge"], ["title", "Close", 1, "vs-close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "vs-panel-search"], ["type", "text", "placeholder", "Search views...", 1, "vs-search-input", 3, "ngModelChange", "keydown.escape", "ngModel"], [1, "vs-panel-body"], [1, "vs-section"], [1, "vs-card", 3, "click"], [1, "vs-card-icon"], [1, "fa-solid", "fa-table"], [1, "vs-card-content"], [1, "vs-card-name"], [1, "fa-solid", "fa-check", "vs-card-check"], [
|
|
827
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewSelectorComponent, selectors: [["mj-view-selector"]], inputs: { Entity: "Entity", SelectedViewID: "SelectedViewID", ViewModified: "ViewModified" }, outputs: { ViewSelected: "ViewSelected", SaveViewRequested: "SaveViewRequested", ManageViewsRequested: "ManageViewsRequested", OpenInTabRequested: "OpenInTabRequested", ConfigureViewRequested: "ConfigureViewRequested", CreateNewRecordRequested: "CreateNewRecordRequested", ExportRequested: "ExportRequested", DuplicateViewRequested: "DuplicateViewRequested", QuickSaveRequested: "QuickSaveRequested", RevertRequested: "RevertRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 17, vars: 12, consts: [[1, "vs-container"], [1, "vs-backdrop"], [1, "vs-wrapper"], ["title", "Select a saved view", 1, "vs-button", 3, "click", "disabled"], [1, "fa-solid", "fa-layer-group", "vs-btn-icon"], [1, "vs-btn-name"], ["title", "View has unsaved changes", 1, "vs-modified-dot"], [1, "fa-solid", "fa-chevron-down", "vs-arrow"], [1, "vs-panel"], ["title", "Open this view in a new tab", 1, "vs-icon-btn"], ["title", "Configure view settings (columns, filters, sorting)", 1, "vs-icon-btn", 3, "click"], [1, "fa-solid", "fa-sliders-h"], ["title", "Create new record", 1, "vs-icon-btn", 3, "click"], [1, "fa-solid", "fa-plus"], ["title", "Export to Excel", 1, "vs-icon-btn", "vs-export-btn", 3, "click"], [1, "fa-solid", "fa-file-excel"], [1, "vs-backdrop", 3, "click"], [1, "vs-panel-header"], [1, "fa-solid", "fa-table-list", "vs-header-icon"], [1, "vs-panel-title"], [1, "vs-Entity-badge"], ["title", "Close", 1, "vs-close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "vs-panel-search"], ["type", "text", "placeholder", "Search views...", 1, "vs-search-input", 3, "ngModelChange", "keydown.escape", "ngModel"], [1, "vs-panel-body"], [1, "vs-section"], [1, "vs-card", 3, "click"], [1, "vs-card-icon"], [1, "fa-solid", "fa-table"], [1, "vs-card-content"], [1, "vs-card-name"], [1, "fa-solid", "fa-check", "vs-card-check"], ["Size", "compact", "Icon", "fa-solid fa-bookmark", "Title", "No saved views yet", "Message", "Save your current configuration as a view"], ["Size", "compact", "Variant", "no-results", 3, "Title"], [1, "vs-loading"], [1, "vs-panel-footer"], ["title", "Save current view configuration", 1, "vs-panel-btn", "primary", 3, "click"], ["title", "Reset to default view", 1, "vs-panel-btn", 3, "click"], [1, "fa-solid", "fa-arrow-rotate-left"], [1, "vs-section-header"], [1, "fa-solid", "fa-user"], [1, "vs-section-count"], [1, "vs-card", 3, "active"], [1, "fa-solid", "fa-table-list"], [1, "vs-default-badge"], [1, "vs-card-desc"], [1, "vs-card-meta"], [1, "vs-card-actions"], ["title", "Duplicate", 1, "vs-action-btn", 3, "click"], [1, "fa-regular", "fa-copy"], ["title", "Configure", 1, "vs-action-btn", 3, "click"], [1, "fa-solid", "fa-sliders"], ["title", "Open in Tab", 1, "vs-action-btn", 3, "click"], [1, "fa-solid", "fa-up-right-from-square"], [1, "fa-solid", "fa-filter"], [1, "fa-solid", "fa-table-columns"], [1, "fa-solid", "fa-arrow-down-short-wide"], [1, "fa-solid", "fa-share-nodes"], [1, "vs-card-icon", "shared"], [1, "fa-solid", "fa-users"], [1, "vs-shared-badge"], [1, "vs-shared-badge", "editable"], ["title", "Duplicate as My View", 1, "vs-action-btn", 3, "click"], ["title", "Configure", 1, "vs-action-btn"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["title", "Open this view in a new tab", 1, "vs-icon-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"]], template: function ViewSelectorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
786
828
|
i0.ɵɵelementStart(0, "div", 0);
|
|
787
829
|
i0.ɵɵconditionalCreate(1, ViewSelectorComponent_Conditional_1_Template, 1, 0, "div", 1);
|
|
788
830
|
i0.ɵɵelementStart(2, "div", 2)(3, "button", 3);
|
|
@@ -825,11 +867,11 @@ export class ViewSelectorComponent extends BaseAngularComponent {
|
|
|
825
867
|
i0.ɵɵconditional(ctx.IsDropdownOpen ? 9 : -1);
|
|
826
868
|
i0.ɵɵadvance();
|
|
827
869
|
i0.ɵɵconditional(ctx.SelectedViewID ? 10 : -1);
|
|
828
|
-
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["/* ========================================\n VIEW SELECTOR - All classes prefixed vs-\n to avoid conflicts (ViewEncapsulation.None)\n ======================================== */\n\n/* Container */\n.vs-container {\n display: flex;\n align-items: center;\n gap: 4px;\n position: relative;\n}\n\n/* Backdrop for closing panel */\n.vs-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.vs-wrapper {\n position: relative;\n}\n\n/* Main Button */\n.vs-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 140px;\n max-width: 280px;\n}\n\n.vs-button:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.vs-button.open {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button.modified {\n border-color: var(--mj-status-warning);\n}\n\n.vs-btn-icon {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.vs-btn-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.vs-modified-dot {\n color: var(--mj-status-warning);\n font-weight: bold;\n font-size: 18px;\n line-height: 1;\n}\n\n.vs-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.vs-arrow.rotated {\n transform: rotate(180deg);\n}\n\n/* ========================================\n RICH VIEW PANEL\n Styles ported directly from prototype\n ======================================== */\n\n/* Reset inherited styles inside panel */\n.vs-panel,\n.vs-panel * {\n box-sizing: border-box;\n line-height: 1.5;\n text-align: left;\n}\n\n.vs-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 400px;\n max-width: calc(100vw - 40px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n z-index: 1000;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n/* Panel Header */\n.vs-panel-header {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-header-icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.vs-panel-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.vs-entity-badge {\n font-size: 11px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.vs-close-btn {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-close-btn:hover {\n color: var(--mj-text-primary);\n}\n\n/* Panel Search */\n.vs-panel-search {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-search-input {\n width: 100%;\n padding: 6px 12px 6px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface-card) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' fill='%23999'%3E%3Cpath d='M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208z'/%3E%3C/svg%3E\") no-repeat 10px center;\n background-size: 14px;\n box-sizing: border-box;\n font-family: inherit;\n}\n\n.vs-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.vs-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n/* Panel Body */\n.vs-panel-body {\n max-height: 400px;\n overflow-y: auto;\n}\n\n/* View Section */\n.vs-section {\n padding: 8px 0;\n}\n\n.vs-section-header {\n padding: 6px 20px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-section-header i {\n font-size: 10px;\n}\n\n.vs-section-count {\n background: var(--mj-border-default);\n padding: 0 6px;\n border-radius: 8px;\n font-size: 10px;\n}\n\n/* View Card */\n.vs-card {\n padding: 10px 20px;\n cursor: pointer;\n transition: background 0.1s;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.vs-card:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-card.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n padding-left: 17px;\n}\n\n/* View Card Icon */\n.vs-card-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card-icon.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.vs-card-icon.shared {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n}\n\n/* View Card Content */\n.vs-card-content {\n flex: 1;\n min-width: 0;\n padding-top: 4px;\n}\n\n.vs-card-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-card.active .vs-card-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.vs-default-badge {\n font-size: 9px;\n font-weight: 600;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n padding: 1px 5px;\n border-radius: 6px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.vs-shared-badge {\n font-size: 9px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 1px 5px;\n border-radius: 6px;\n}\n\n.vs-shared-badge.editable {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.vs-card-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.vs-card-meta {\n display: flex;\n gap: 10px;\n margin-top: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.vs-card-meta span {\n display: flex;\n align-items: center;\n gap: 3px;\n}\n\n.vs-card-meta i {\n font-size: 10px;\n}\n\n/* View Card Check */\n.vs-card-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* View Card Actions (hover reveal) */\n.vs-card-actions {\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card:hover .vs-card-actions {\n opacity: 1;\n}\n\n.vs-action-btn {\n width: 26px;\n height: 26px;\n border-radius: 4px;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-action-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n}\n\n/* Empty State */\n.vs-empty-message {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.vs-empty-message i {\n font-size: 16px;\n opacity: 0.5;\n}\n\n.vs-empty-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.vs-empty-text strong {\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.vs-empty-text span {\n font-size: 12px;\n}\n\n/* Loading */\n.vs-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n/* Panel Footer */\n.vs-panel-footer {\n padding: 12px 20px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n gap: 8px;\n}\n\n.vs-panel-btn {\n flex: 1;\n padding: 8px 12px;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.15s;\n font-family: inherit;\n text-align: center;\n}\n\n.vs-panel-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.vs-panel-btn i {\n font-size: 11px;\n}\n\n/* ========================================\n ICON BUTTONS (outside panel)\n ======================================== */\n\n.vs-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.vs-icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-brand-primary);\n}\n\n.vs-icon-btn i {\n font-size: 12px;\n}\n\n.vs-export-btn:hover {\n color: var(--mj-status-success);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .vs-button {\n min-width: 100px;\n max-width: 180px;\n padding: 6px 10px;\n }\n\n .vs-panel {\n width: calc(100vw - 32px);\n max-width: 400px;\n }\n}\n"], encapsulation: 2 });
|
|
870
|
+
} }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJEmptyStateComponent], styles: ["/* ========================================\n VIEW SELECTOR - All classes prefixed vs-\n to avoid conflicts (ViewEncapsulation.None)\n ======================================== */\n\n/* Container */\n.vs-container {\n display: flex;\n align-items: center;\n gap: 4px;\n position: relative;\n}\n\n/* Backdrop for closing panel */\n.vs-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.vs-wrapper {\n position: relative;\n}\n\n/* Main Button */\n.vs-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 140px;\n max-width: 280px;\n}\n\n.vs-button:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.vs-button.open {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button.modified {\n border-color: var(--mj-status-warning);\n}\n\n.vs-btn-icon {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.vs-btn-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.vs-modified-dot {\n color: var(--mj-status-warning);\n font-weight: bold;\n font-size: 18px;\n line-height: 1;\n}\n\n.vs-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.vs-arrow.rotated {\n transform: rotate(180deg);\n}\n\n/* ========================================\n RICH VIEW PANEL\n Styles ported directly from prototype\n ======================================== */\n\n/* Reset inherited styles inside panel */\n.vs-panel,\n.vs-panel * {\n box-sizing: border-box;\n line-height: 1.5;\n text-align: left;\n}\n\n.vs-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 400px;\n max-width: calc(100vw - 40px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n z-index: 1000;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n/* Panel Header */\n.vs-panel-header {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-header-icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.vs-panel-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.vs-entity-badge {\n font-size: 11px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.vs-close-btn {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-close-btn:hover {\n color: var(--mj-text-primary);\n}\n\n/* Panel Search */\n.vs-panel-search {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-search-input {\n width: 100%;\n padding: 6px 12px 6px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface-card) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' fill='%23999'%3E%3Cpath d='M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208z'/%3E%3C/svg%3E\") no-repeat 10px center;\n background-size: 14px;\n box-sizing: border-box;\n font-family: inherit;\n}\n\n.vs-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.vs-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n/* Panel Body */\n.vs-panel-body {\n max-height: 400px;\n overflow-y: auto;\n}\n\n/* View Section */\n.vs-section {\n padding: 8px 0;\n}\n\n.vs-section-header {\n padding: 6px 20px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-section-header i {\n font-size: 10px;\n}\n\n.vs-section-count {\n background: var(--mj-border-default);\n padding: 0 6px;\n border-radius: 8px;\n font-size: 10px;\n}\n\n/* View Card */\n.vs-card {\n padding: 10px 20px;\n cursor: pointer;\n transition: background 0.1s;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.vs-card:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-card.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n padding-left: 17px;\n}\n\n/* View Card Icon */\n.vs-card-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card-icon.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.vs-card-icon.shared {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n}\n\n/* View Card Content */\n.vs-card-content {\n flex: 1;\n min-width: 0;\n padding-top: 4px;\n}\n\n.vs-card-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-card.active .vs-card-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.vs-default-badge {\n font-size: 9px;\n font-weight: 600;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n padding: 1px 5px;\n border-radius: 6px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.vs-shared-badge {\n font-size: 9px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 1px 5px;\n border-radius: 6px;\n}\n\n.vs-shared-badge.editable {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.vs-card-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.vs-card-meta {\n display: flex;\n gap: 10px;\n margin-top: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.vs-card-meta span {\n display: flex;\n align-items: center;\n gap: 3px;\n}\n\n.vs-card-meta i {\n font-size: 10px;\n}\n\n/* View Card Check */\n.vs-card-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* View Card Actions (hover reveal) */\n.vs-card-actions {\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card:hover .vs-card-actions {\n opacity: 1;\n}\n\n.vs-action-btn {\n width: 26px;\n height: 26px;\n border-radius: 4px;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-action-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n}\n\n/* Loading */\n.vs-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n/* Panel Footer */\n.vs-panel-footer {\n padding: 12px 20px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n gap: 8px;\n}\n\n.vs-panel-btn {\n flex: 1;\n padding: 8px 12px;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.15s;\n font-family: inherit;\n text-align: center;\n}\n\n.vs-panel-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.vs-panel-btn i {\n font-size: 11px;\n}\n\n/* ========================================\n ICON BUTTONS (outside panel)\n ======================================== */\n\n.vs-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.vs-icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-brand-primary);\n}\n\n.vs-icon-btn i {\n font-size: 12px;\n}\n\n.vs-export-btn:hover {\n color: var(--mj-status-success);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .vs-button {\n min-width: 100px;\n max-width: 180px;\n padding: 6px 10px;\n }\n\n .vs-panel {\n width: calc(100vw - 32px);\n max-width: 400px;\n }\n}\n"], encapsulation: 2 });
|
|
829
871
|
}
|
|
830
872
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ViewSelectorComponent, [{
|
|
831
873
|
type: Component,
|
|
832
|
-
args: [{ standalone: false, selector: 'mj-view-selector', encapsulation: ViewEncapsulation.None, template: "<div class=\"vs-container\">\n <!-- Backdrop for closing panel -->\n @if (IsDropdownOpen) {\n <div class=\"vs-backdrop\" (click)=\"CloseDropdown()\"></div>\n }\n\n <!-- Main View Selector Button -->\n <div class=\"vs-wrapper\">\n <button\n class=\"vs-button\"\n [class.modified]=\"ViewModified\"\n [class.open]=\"IsDropdownOpen\"\n (click)=\"ToggleDropdown()\"\n [disabled]=\"IsLoading\"\n title=\"Select a saved view\">\n <i class=\"fa-solid fa-layer-group vs-btn-icon\"></i>\n <span class=\"vs-btn-name\">{{ DisplayName }}</span>\n @if (ViewModified) {\n <span class=\"vs-modified-dot\" title=\"View has unsaved changes\">\u2022</span>\n }\n <i class=\"fa-solid fa-chevron-down vs-arrow\" [class.rotated]=\"IsDropdownOpen\"></i>\n </button>\n\n <!-- Rich View Panel -->\n @if (IsDropdownOpen) {\n <div class=\"vs-panel\">\n <!-- Panel Header -->\n <div class=\"vs-panel-header\">\n <i class=\"fa-solid fa-table-list vs-header-icon\"></i>\n <span class=\"vs-panel-title\">Views</span>\n @if (Entity) {\n <span class=\"vs-Entity-badge\">{{ Entity.DisplayNameOrName }}</span>\n }\n <button class=\"vs-close-btn\" (click)=\"CloseDropdown()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Search -->\n <div class=\"vs-panel-search\">\n <input\n type=\"text\"\n class=\"vs-search-input\"\n placeholder=\"Search views...\"\n [(ngModel)]=\"SearchText\"\n (keydown.escape)=\"SearchText = ''\"\n />\n </div>\n\n <!-- Panel Body -->\n <div class=\"vs-panel-body\">\n <!-- Default Option -->\n <div class=\"vs-section\">\n <div\n class=\"vs-card\"\n [class.active]=\"!SelectedViewID\"\n (click)=\"SelectDefault()\">\n <div class=\"vs-card-icon\" [class.active]=\"!SelectedViewID\">\n <i class=\"fa-solid fa-table\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">(Default)</div>\n </div>\n @if (!SelectedViewID) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n </div>\n\n <!-- My Views Section -->\n @if (FilteredMyViews.length > 0) {\n <div class=\"vs-section\">\n <div class=\"vs-section-header\">\n <i class=\"fa-solid fa-user\"></i>\n <span>My Views</span>\n <span class=\"vs-section-count\">{{ FilteredMyViews.length }}</span>\n </div>\n @for (view of FilteredMyViews; track view.id) {\n <div\n class=\"vs-card\"\n [class.active]=\"SelectedViewID === view.id\"\n (click)=\"SelectView(view)\">\n <div class=\"vs-card-icon\" [class.active]=\"SelectedViewID === view.id\">\n <i class=\"fa-solid fa-table-list\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">\n {{ view.name }}\n @if (view.isDefault) {\n <span class=\"vs-default-badge\">Default</span>\n }\n </div>\n @if (view.entity.Description) {\n <div class=\"vs-card-desc\">{{ view.entity.Description }}</div>\n }\n @if (GetViewFilterCount(view) > 0 || GetViewColumnCount(view) > 0 || GetViewSortInfo(view)) {\n <div class=\"vs-card-meta\">\n @if (GetViewFilterCount(view) > 0) {\n <span><i class=\"fa-solid fa-filter\"></i> {{ GetViewFilterCount(view) }} filter{{ GetViewFilterCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewColumnCount(view) > 0) {\n <span><i class=\"fa-solid fa-table-columns\"></i> {{ GetViewColumnCount(view) }} col{{ GetViewColumnCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewSortInfo(view)) {\n <span><i class=\"fa-solid fa-arrow-down-short-wide\"></i> {{ GetViewSortInfo(view) }}</span>\n }\n </div>\n }\n </div>\n <div class=\"vs-card-actions\">\n <button\n class=\"vs-action-btn\"\n (click)=\"OnDuplicateView(view.id, $event)\"\n title=\"Duplicate\">\n <i class=\"fa-regular fa-copy\"></i>\n </button>\n <button\n class=\"vs-action-btn\"\n (click)=\"OnConfigureViewById(view.id, $event)\"\n title=\"Configure\">\n <i class=\"fa-solid fa-sliders\"></i>\n </button>\n <button\n class=\"vs-action-btn\"\n (click)=\"OnOpenViewInTab(view.id, $event)\"\n title=\"Open in Tab\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n </div>\n @if (SelectedViewID === view.id) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n }\n </div>\n }\n\n <!-- Shared Views Section -->\n @if (FilteredSharedViews.length > 0) {\n <div class=\"vs-section\">\n <div class=\"vs-section-header\">\n <i class=\"fa-solid fa-share-nodes\"></i>\n <span>Shared With Me</span>\n <span class=\"vs-section-count\">{{ FilteredSharedViews.length }}</span>\n </div>\n @for (view of FilteredSharedViews; track view.id) {\n <div\n class=\"vs-card\"\n [class.active]=\"SelectedViewID === view.id\"\n (click)=\"SelectView(view)\">\n <div class=\"vs-card-icon shared\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">\n {{ view.name }}\n @if (!view.userCanEdit) {\n <span class=\"vs-shared-badge\">View Only</span>\n } @else {\n <span class=\"vs-shared-badge editable\">Can Edit</span>\n }\n </div>\n @if (view.entity.Description) {\n <div class=\"vs-card-desc\">{{ view.entity.Description }}</div>\n }\n @if (GetViewFilterCount(view) > 0 || GetViewColumnCount(view) > 0) {\n <div class=\"vs-card-meta\">\n @if (GetViewFilterCount(view) > 0) {\n <span><i class=\"fa-solid fa-filter\"></i> {{ GetViewFilterCount(view) }} filter{{ GetViewFilterCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewColumnCount(view) > 0) {\n <span><i class=\"fa-solid fa-table-columns\"></i> {{ GetViewColumnCount(view) }} col{{ GetViewColumnCount(view) !== 1 ? 's' : '' }}</span>\n }\n </div>\n }\n </div>\n <div class=\"vs-card-actions\">\n <button\n class=\"vs-action-btn\"\n (click)=\"OnDuplicateView(view.id, $event)\"\n title=\"Duplicate as My View\">\n <i class=\"fa-regular fa-copy\"></i>\n </button>\n @if (view.userCanEdit) {\n <button\n class=\"vs-action-btn\"\n (click)=\"OnConfigureViewById(view.id, $event)\"\n title=\"Configure\">\n <i class=\"fa-solid fa-sliders\"></i>\n </button>\n }\n </div>\n @if (SelectedViewID === view.id) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n }\n </div>\n }\n\n <!-- No Views Message -->\n @if (!HasViews && !IsLoading) {\n <div class=\"vs-empty-message\">\n <i class=\"fa-solid fa-bookmark\"></i>\n <div class=\"vs-empty-text\">\n <strong>No saved views yet</strong>\n <span>Save your current configuration as a view</span>\n </div>\n </div>\n }\n\n <!-- No Search Results -->\n @if (HasViews && FilteredMyViews.length === 0 && FilteredSharedViews.length === 0 && SearchText) {\n <div class=\"vs-empty-message\">\n <i class=\"fa-solid fa-search\"></i>\n <span>No views match \"{{ SearchText }}\"</span>\n </div>\n }\n\n <!-- Loading Indicator -->\n @if (IsLoading) {\n <div class=\"vs-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading views...</span>\n </div>\n }\n </div>\n\n <!-- Panel Footer -->\n <div class=\"vs-panel-footer\">\n <button\n class=\"vs-panel-btn primary\"\n (click)=\"OnQuickSave()\"\n title=\"Save current view configuration\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New View</span>\n </button>\n <button\n class=\"vs-panel-btn\"\n (click)=\"OnResetToDefault()\"\n title=\"Reset to default view\">\n <i class=\"fa-solid fa-arrow-rotate-left\"></i>\n <span>Reset to Default</span>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Open in Tab Button (only visible when a view is selected) -->\n @if (SelectedViewID) {\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnOpenInTab()\"\n title=\"Open this view in a new tab\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n\n <!-- Configure View Button -->\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnConfigureView()\"\n title=\"Configure view settings (columns, filters, sorting)\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n </button>\n\n <!-- Create New Record Button -->\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnCreateNewRecord()\"\n title=\"Create new record\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n\n <!-- Export Button -->\n <button\n class=\"vs-icon-btn vs-export-btn\"\n (click)=\"OnExport()\"\n title=\"Export to Excel\">\n <i class=\"fa-solid fa-file-excel\"></i>\n </button>\n</div>\n", styles: ["/* ========================================\n VIEW SELECTOR - All classes prefixed vs-\n to avoid conflicts (ViewEncapsulation.None)\n ======================================== */\n\n/* Container */\n.vs-container {\n display: flex;\n align-items: center;\n gap: 4px;\n position: relative;\n}\n\n/* Backdrop for closing panel */\n.vs-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.vs-wrapper {\n position: relative;\n}\n\n/* Main Button */\n.vs-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 140px;\n max-width: 280px;\n}\n\n.vs-button:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.vs-button.open {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button.modified {\n border-color: var(--mj-status-warning);\n}\n\n.vs-btn-icon {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.vs-btn-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.vs-modified-dot {\n color: var(--mj-status-warning);\n font-weight: bold;\n font-size: 18px;\n line-height: 1;\n}\n\n.vs-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.vs-arrow.rotated {\n transform: rotate(180deg);\n}\n\n/* ========================================\n RICH VIEW PANEL\n Styles ported directly from prototype\n ======================================== */\n\n/* Reset inherited styles inside panel */\n.vs-panel,\n.vs-panel * {\n box-sizing: border-box;\n line-height: 1.5;\n text-align: left;\n}\n\n.vs-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 400px;\n max-width: calc(100vw - 40px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n z-index: 1000;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n/* Panel Header */\n.vs-panel-header {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-header-icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.vs-panel-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.vs-entity-badge {\n font-size: 11px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.vs-close-btn {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-close-btn:hover {\n color: var(--mj-text-primary);\n}\n\n/* Panel Search */\n.vs-panel-search {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-search-input {\n width: 100%;\n padding: 6px 12px 6px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface-card) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' fill='%23999'%3E%3Cpath d='M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208z'/%3E%3C/svg%3E\") no-repeat 10px center;\n background-size: 14px;\n box-sizing: border-box;\n font-family: inherit;\n}\n\n.vs-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.vs-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n/* Panel Body */\n.vs-panel-body {\n max-height: 400px;\n overflow-y: auto;\n}\n\n/* View Section */\n.vs-section {\n padding: 8px 0;\n}\n\n.vs-section-header {\n padding: 6px 20px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-section-header i {\n font-size: 10px;\n}\n\n.vs-section-count {\n background: var(--mj-border-default);\n padding: 0 6px;\n border-radius: 8px;\n font-size: 10px;\n}\n\n/* View Card */\n.vs-card {\n padding: 10px 20px;\n cursor: pointer;\n transition: background 0.1s;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.vs-card:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-card.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n padding-left: 17px;\n}\n\n/* View Card Icon */\n.vs-card-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card-icon.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.vs-card-icon.shared {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n}\n\n/* View Card Content */\n.vs-card-content {\n flex: 1;\n min-width: 0;\n padding-top: 4px;\n}\n\n.vs-card-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-card.active .vs-card-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.vs-default-badge {\n font-size: 9px;\n font-weight: 600;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n padding: 1px 5px;\n border-radius: 6px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.vs-shared-badge {\n font-size: 9px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 1px 5px;\n border-radius: 6px;\n}\n\n.vs-shared-badge.editable {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.vs-card-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.vs-card-meta {\n display: flex;\n gap: 10px;\n margin-top: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.vs-card-meta span {\n display: flex;\n align-items: center;\n gap: 3px;\n}\n\n.vs-card-meta i {\n font-size: 10px;\n}\n\n/* View Card Check */\n.vs-card-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* View Card Actions (hover reveal) */\n.vs-card-actions {\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card:hover .vs-card-actions {\n opacity: 1;\n}\n\n.vs-action-btn {\n width: 26px;\n height: 26px;\n border-radius: 4px;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-action-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n}\n\n/* Empty State */\n.vs-empty-message {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n}\n\n.vs-empty-message i {\n font-size: 16px;\n opacity: 0.5;\n}\n\n.vs-empty-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.vs-empty-text strong {\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.vs-empty-text span {\n font-size: 12px;\n}\n\n/* Loading */\n.vs-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n/* Panel Footer */\n.vs-panel-footer {\n padding: 12px 20px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n gap: 8px;\n}\n\n.vs-panel-btn {\n flex: 1;\n padding: 8px 12px;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.15s;\n font-family: inherit;\n text-align: center;\n}\n\n.vs-panel-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.vs-panel-btn i {\n font-size: 11px;\n}\n\n/* ========================================\n ICON BUTTONS (outside panel)\n ======================================== */\n\n.vs-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.vs-icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-brand-primary);\n}\n\n.vs-icon-btn i {\n font-size: 12px;\n}\n\n.vs-export-btn:hover {\n color: var(--mj-status-success);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .vs-button {\n min-width: 100px;\n max-width: 180px;\n padding: 6px 10px;\n }\n\n .vs-panel {\n width: calc(100vw - 32px);\n max-width: 400px;\n }\n}\n"] }]
|
|
874
|
+
args: [{ standalone: false, selector: 'mj-view-selector', encapsulation: ViewEncapsulation.None, template: "<div class=\"vs-container\">\n <!-- Backdrop for closing panel -->\n @if (IsDropdownOpen) {\n <div class=\"vs-backdrop\" (click)=\"CloseDropdown()\"></div>\n }\n\n <!-- Main View Selector Button -->\n <div class=\"vs-wrapper\">\n <button\n class=\"vs-button\"\n [class.modified]=\"ViewModified\"\n [class.open]=\"IsDropdownOpen\"\n (click)=\"ToggleDropdown()\"\n [disabled]=\"IsLoading\"\n title=\"Select a saved view\">\n <i class=\"fa-solid fa-layer-group vs-btn-icon\"></i>\n <span class=\"vs-btn-name\">{{ DisplayName }}</span>\n @if (ViewModified) {\n <span class=\"vs-modified-dot\" title=\"View has unsaved changes\">\u2022</span>\n }\n <i class=\"fa-solid fa-chevron-down vs-arrow\" [class.rotated]=\"IsDropdownOpen\"></i>\n </button>\n\n <!-- Rich View Panel -->\n @if (IsDropdownOpen) {\n <div class=\"vs-panel\">\n <!-- Panel Header -->\n <div class=\"vs-panel-header\">\n <i class=\"fa-solid fa-table-list vs-header-icon\"></i>\n <span class=\"vs-panel-title\">Views</span>\n @if (Entity) {\n <span class=\"vs-Entity-badge\">{{ Entity.DisplayNameOrName }}</span>\n }\n <button class=\"vs-close-btn\" (click)=\"CloseDropdown()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Search -->\n <div class=\"vs-panel-search\">\n <input\n type=\"text\"\n class=\"vs-search-input\"\n placeholder=\"Search views...\"\n [(ngModel)]=\"SearchText\"\n (keydown.escape)=\"SearchText = ''\"\n />\n </div>\n\n <!-- Panel Body -->\n <div class=\"vs-panel-body\">\n <!-- Default Option -->\n <div class=\"vs-section\">\n <div\n class=\"vs-card\"\n [class.active]=\"!SelectedViewID\"\n (click)=\"SelectDefault()\">\n <div class=\"vs-card-icon\" [class.active]=\"!SelectedViewID\">\n <i class=\"fa-solid fa-table\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">(Default)</div>\n </div>\n @if (!SelectedViewID) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n </div>\n\n <!-- My Views Section -->\n @if (FilteredMyViews.length > 0) {\n <div class=\"vs-section\">\n <div class=\"vs-section-header\">\n <i class=\"fa-solid fa-user\"></i>\n <span>My Views</span>\n <span class=\"vs-section-count\">{{ FilteredMyViews.length }}</span>\n </div>\n @for (view of FilteredMyViews; track view.id) {\n <div\n class=\"vs-card\"\n [class.active]=\"SelectedViewID === view.id\"\n (click)=\"SelectView(view)\">\n <div class=\"vs-card-icon\" [class.active]=\"SelectedViewID === view.id\">\n <i class=\"fa-solid fa-table-list\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">\n {{ view.name }}\n @if (view.isDefault) {\n <span class=\"vs-default-badge\">Default</span>\n }\n </div>\n @if (view.entity.Description) {\n <div class=\"vs-card-desc\">{{ view.entity.Description }}</div>\n }\n @if (GetViewFilterCount(view) > 0 || GetViewColumnCount(view) > 0 || GetViewSortInfo(view)) {\n <div class=\"vs-card-meta\">\n @if (GetViewFilterCount(view) > 0) {\n <span><i class=\"fa-solid fa-filter\"></i> {{ GetViewFilterCount(view) }} filter{{ GetViewFilterCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewColumnCount(view) > 0) {\n <span><i class=\"fa-solid fa-table-columns\"></i> {{ GetViewColumnCount(view) }} col{{ GetViewColumnCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewSortInfo(view)) {\n <span><i class=\"fa-solid fa-arrow-down-short-wide\"></i> {{ GetViewSortInfo(view) }}</span>\n }\n </div>\n }\n </div>\n <div class=\"vs-card-actions\">\n <button\n class=\"vs-action-btn\"\n (click)=\"OnDuplicateView(view.id, $event)\"\n title=\"Duplicate\">\n <i class=\"fa-regular fa-copy\"></i>\n </button>\n <button\n class=\"vs-action-btn\"\n (click)=\"OnConfigureViewById(view.id, $event)\"\n title=\"Configure\">\n <i class=\"fa-solid fa-sliders\"></i>\n </button>\n <button\n class=\"vs-action-btn\"\n (click)=\"OnOpenViewInTab(view.id, $event)\"\n title=\"Open in Tab\">\n <i class=\"fa-solid fa-up-right-from-square\"></i>\n </button>\n </div>\n @if (SelectedViewID === view.id) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n }\n </div>\n }\n\n <!-- Shared Views Section -->\n @if (FilteredSharedViews.length > 0) {\n <div class=\"vs-section\">\n <div class=\"vs-section-header\">\n <i class=\"fa-solid fa-share-nodes\"></i>\n <span>Shared With Me</span>\n <span class=\"vs-section-count\">{{ FilteredSharedViews.length }}</span>\n </div>\n @for (view of FilteredSharedViews; track view.id) {\n <div\n class=\"vs-card\"\n [class.active]=\"SelectedViewID === view.id\"\n (click)=\"SelectView(view)\">\n <div class=\"vs-card-icon shared\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"vs-card-content\">\n <div class=\"vs-card-name\">\n {{ view.name }}\n @if (!view.userCanEdit) {\n <span class=\"vs-shared-badge\">View Only</span>\n } @else {\n <span class=\"vs-shared-badge editable\">Can Edit</span>\n }\n </div>\n @if (view.entity.Description) {\n <div class=\"vs-card-desc\">{{ view.entity.Description }}</div>\n }\n @if (GetViewFilterCount(view) > 0 || GetViewColumnCount(view) > 0) {\n <div class=\"vs-card-meta\">\n @if (GetViewFilterCount(view) > 0) {\n <span><i class=\"fa-solid fa-filter\"></i> {{ GetViewFilterCount(view) }} filter{{ GetViewFilterCount(view) !== 1 ? 's' : '' }}</span>\n }\n @if (GetViewColumnCount(view) > 0) {\n <span><i class=\"fa-solid fa-table-columns\"></i> {{ GetViewColumnCount(view) }} col{{ GetViewColumnCount(view) !== 1 ? 's' : '' }}</span>\n }\n </div>\n }\n </div>\n <div class=\"vs-card-actions\">\n <button\n class=\"vs-action-btn\"\n (click)=\"OnDuplicateView(view.id, $event)\"\n title=\"Duplicate as My View\">\n <i class=\"fa-regular fa-copy\"></i>\n </button>\n @if (view.userCanEdit) {\n <button\n class=\"vs-action-btn\"\n (click)=\"OnConfigureViewById(view.id, $event)\"\n title=\"Configure\">\n <i class=\"fa-solid fa-sliders\"></i>\n </button>\n }\n </div>\n @if (SelectedViewID === view.id) {\n <i class=\"fa-solid fa-check vs-card-check\"></i>\n }\n </div>\n }\n </div>\n }\n\n <!-- No Views Message -->\n @if (!HasViews && !IsLoading) {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-bookmark\"\n Title=\"No saved views yet\"\n Message=\"Save your current configuration as a view\" />\n }\n\n <!-- No Search Results -->\n @if (HasViews && FilteredMyViews.length === 0 && FilteredSharedViews.length === 0 && SearchText) {\n <mj-empty-state\n Size=\"compact\"\n Variant=\"no-results\"\n [Title]=\"NoViewsMatchMessage\" />\n }\n\n <!-- Loading Indicator -->\n @if (IsLoading) {\n <div class=\"vs-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading views...</span>\n </div>\n }\n </div>\n\n <!-- Panel Footer -->\n <div class=\"vs-panel-footer\">\n <button\n class=\"vs-panel-btn primary\"\n (click)=\"OnQuickSave()\"\n title=\"Save current view configuration\">\n <i class=\"fa-solid fa-plus\"></i>\n <span>New View</span>\n </button>\n <button\n class=\"vs-panel-btn\"\n (click)=\"OnResetToDefault()\"\n title=\"Reset to default view\">\n <i class=\"fa-solid fa-arrow-rotate-left\"></i>\n <span>Reset to Default</span>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Open in Tab Button (only visible when a view is selected) -->\n @if (SelectedViewID) {\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnOpenInTab()\"\n title=\"Open this view in a new tab\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n }\n\n <!-- Configure View Button -->\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnConfigureView()\"\n title=\"Configure view settings (columns, filters, sorting)\">\n <i class=\"fa-solid fa-sliders-h\"></i>\n </button>\n\n <!-- Create New Record Button -->\n <button\n class=\"vs-icon-btn\"\n (click)=\"OnCreateNewRecord()\"\n title=\"Create new record\">\n <i class=\"fa-solid fa-plus\"></i>\n </button>\n\n <!-- Export Button -->\n <button\n class=\"vs-icon-btn vs-export-btn\"\n (click)=\"OnExport()\"\n title=\"Export to Excel\">\n <i class=\"fa-solid fa-file-excel\"></i>\n </button>\n</div>\n", styles: ["/* ========================================\n VIEW SELECTOR - All classes prefixed vs-\n to avoid conflicts (ViewEncapsulation.None)\n ======================================== */\n\n/* Container */\n.vs-container {\n display: flex;\n align-items: center;\n gap: 4px;\n position: relative;\n}\n\n/* Backdrop for closing panel */\n.vs-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n background: transparent;\n}\n\n.vs-wrapper {\n position: relative;\n}\n\n/* Main Button */\n.vs-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n transition: all 0.15s ease;\n min-width: 140px;\n max-width: 280px;\n}\n\n.vs-button:hover {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.vs-button.open {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-button.modified {\n border-color: var(--mj-status-warning);\n}\n\n.vs-btn-icon {\n color: var(--mj-brand-primary);\n font-size: 12px;\n}\n\n.vs-btn-name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: left;\n}\n\n.vs-modified-dot {\n color: var(--mj-status-warning);\n font-weight: bold;\n font-size: 18px;\n line-height: 1;\n}\n\n.vs-arrow {\n color: var(--mj-text-muted);\n font-size: 10px;\n transition: transform 0.2s ease;\n}\n\n.vs-arrow.rotated {\n transform: rotate(180deg);\n}\n\n/* ========================================\n RICH VIEW PANEL\n Styles ported directly from prototype\n ======================================== */\n\n/* Reset inherited styles inside panel */\n.vs-panel,\n.vs-panel * {\n box-sizing: border-box;\n line-height: 1.5;\n text-align: left;\n}\n\n.vs-panel {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 400px;\n max-width: calc(100vw - 40px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);\n z-index: 1000;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n/* Panel Header */\n.vs-panel-header {\n padding: 16px 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-header-icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n}\n\n.vs-panel-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.vs-entity-badge {\n font-size: 11px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.vs-close-btn {\n margin-left: auto;\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 16px;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-close-btn:hover {\n color: var(--mj-text-primary);\n}\n\n/* Panel Search */\n.vs-panel-search {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.vs-search-input {\n width: 100%;\n padding: 6px 12px 6px 32px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n font-size: 13px;\n background: var(--mj-bg-surface-card) url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' fill='%23999'%3E%3Cpath d='M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208z'/%3E%3C/svg%3E\") no-repeat 10px center;\n background-size: 14px;\n box-sizing: border-box;\n font-family: inherit;\n}\n\n.vs-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n}\n\n.vs-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n/* Panel Body */\n.vs-panel-body {\n max-height: 400px;\n overflow-y: auto;\n}\n\n/* View Section */\n.vs-section {\n padding: 8px 0;\n}\n\n.vs-section-header {\n padding: 6px 20px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-section-header i {\n font-size: 10px;\n}\n\n.vs-section-count {\n background: var(--mj-border-default);\n padding: 0 6px;\n border-radius: 8px;\n font-size: 10px;\n}\n\n/* View Card */\n.vs-card {\n padding: 10px 20px;\n cursor: pointer;\n transition: background 0.1s;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.vs-card:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n}\n\n.vs-card.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n padding-left: 17px;\n}\n\n/* View Card Icon */\n.vs-card-icon {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card-icon.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.vs-card-icon.shared {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n}\n\n/* View Card Content */\n.vs-card-content {\n flex: 1;\n min-width: 0;\n padding-top: 4px;\n}\n\n.vs-card-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.vs-card.active .vs-card-name {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.vs-default-badge {\n font-size: 9px;\n font-weight: 600;\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n padding: 1px 5px;\n border-radius: 6px;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.vs-shared-badge {\n font-size: 9px;\n font-weight: 600;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n padding: 1px 5px;\n border-radius: 6px;\n}\n\n.vs-shared-badge.editable {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n}\n\n.vs-card-desc {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.vs-card-meta {\n display: flex;\n gap: 10px;\n margin-top: 4px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.vs-card-meta span {\n display: flex;\n align-items: center;\n gap: 3px;\n}\n\n.vs-card-meta i {\n font-size: 10px;\n}\n\n/* View Card Check */\n.vs-card-check {\n color: var(--mj-brand-primary);\n font-size: 12px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* View Card Actions (hover reveal) */\n.vs-card-actions {\n display: flex;\n gap: 2px;\n opacity: 0;\n transition: opacity 0.15s;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.vs-card:hover .vs-card-actions {\n opacity: 1;\n}\n\n.vs-action-btn {\n width: 26px;\n height: 26px;\n border-radius: 4px;\n border: none;\n background: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-action-btn:hover {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-primary);\n}\n\n/* Loading */\n.vs-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-muted);\n font-size: 13px;\n text-align: center;\n}\n\n/* Panel Footer */\n.vs-panel-footer {\n padding: 12px 20px;\n border-top: 1px solid var(--mj-border-default);\n display: flex;\n gap: 8px;\n}\n\n.vs-panel-btn {\n flex: 1;\n padding: 8px 12px;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.15s;\n font-family: inherit;\n text-align: center;\n}\n\n.vs-panel-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.vs-panel-btn.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.vs-panel-btn i {\n font-size: 11px;\n}\n\n/* ========================================\n ICON BUTTONS (outside panel)\n ======================================== */\n\n.vs-icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n}\n\n.vs-icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n color: var(--mj-brand-primary);\n}\n\n.vs-icon-btn i {\n font-size: 12px;\n}\n\n.vs-export-btn:hover {\n color: var(--mj-status-success);\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .vs-button {\n min-width: 100px;\n max-width: 180px;\n padding: 6px 10px;\n }\n\n .vs-panel {\n width: calc(100vw - 32px);\n max-width: 400px;\n }\n}\n"] }]
|
|
833
875
|
}], () => [{ type: i0.ChangeDetectorRef }], { Entity: [{
|
|
834
876
|
type: Input
|
|
835
877
|
}], SelectedViewID: [{
|