@memberjunction/ng-explorer-core 5.35.0 → 5.37.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.
Files changed (32) hide show
  1. package/dist/generated/lazy-feature-config.d.ts +1 -1
  2. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  3. package/dist/generated/lazy-feature-config.js +5 -3
  4. package/dist/generated/lazy-feature-config.js.map +1 -1
  5. package/dist/lib/conversation-feedback/conversation-feedback.d.ts +108 -0
  6. package/dist/lib/conversation-feedback/conversation-feedback.d.ts.map +1 -0
  7. package/dist/lib/conversation-feedback/conversation-feedback.js +809 -0
  8. package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -0
  9. package/dist/lib/conversation-feedback/index.d.ts +2 -0
  10. package/dist/lib/conversation-feedback/index.d.ts.map +1 -0
  11. package/dist/lib/conversation-feedback/index.js +2 -0
  12. package/dist/lib/conversation-feedback/index.js.map +1 -0
  13. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  14. package/dist/lib/resource-wrappers/dashboard-resource.component.js +23 -1
  15. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  16. package/dist/lib/resource-wrappers/view-resource.component.d.ts +12 -0
  17. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  18. package/dist/lib/resource-wrappers/view-resource.component.js +107 -15
  19. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  20. package/dist/lib/single-list-detail/single-list-detail.component.d.ts +153 -3
  21. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  22. package/dist/lib/single-list-detail/single-list-detail.component.js +1479 -271
  23. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  24. package/dist/module.d.ts +32 -29
  25. package/dist/module.d.ts.map +1 -1
  26. package/dist/module.js +19 -6
  27. package/dist/module.js.map +1 -1
  28. package/dist/public-api.d.ts +1 -0
  29. package/dist/public-api.d.ts.map +1 -1
  30. package/dist/public-api.js +1 -0
  31. package/dist/public-api.js.map +1 -1
  32. package/package.json +45 -42
@@ -1,129 +1,448 @@
1
1
  import { Component, Input, ViewChild, HostListener } from '@angular/core';
2
2
  import { CompositeKey, LogError, LogErrorEx, LogStatus, RunView } from '@memberjunction/core';
3
+ import { GraphQLListsClient } from '@memberjunction/graphql-dataprovider';
4
+ import { CapabilitiesForLevel } from '@memberjunction/lists-base';
3
5
  import { Subject, debounceTime } from 'rxjs';
4
6
  import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
5
7
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
8
  import * as i0 from "@angular/core";
7
9
  import * as i1 from "@memberjunction/ng-shared";
8
- import * as i2 from "@memberjunction/ng-ui-components";
9
- import * as i3 from "@memberjunction/ng-shared-generic";
10
- import * as i4 from "@memberjunction/ng-list-detail-grid";
10
+ import * as i2 from "@memberjunction/ng-export-service";
11
+ import * as i3 from "@memberjunction/ng-list-management";
12
+ import * as i4 from "@angular/forms";
13
+ import * as i5 from "@memberjunction/ng-ui-components";
14
+ import * as i6 from "@memberjunction/ng-shared-generic";
15
+ import * as i7 from "@memberjunction/ng-list-detail-grid";
16
+ import * as i8 from "@angular/common";
11
17
  const _c0 = ["listDetailGrid"];
12
18
  const _forTrack0 = ($index, $item) => $item.Text;
13
19
  const _forTrack1 = ($index, $item) => $item.ID;
14
- function SingleListDetailComponent_Conditional_9_For_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
15
- i0.ɵɵelementStart(0, "span", 17);
20
+ const _forTrack2 = ($index, $item) => $item.Name;
21
+ function SingleListDetailComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
22
+ i0.ɵɵelementStart(0, "h1");
16
23
  i0.ɵɵtext(1);
17
24
  i0.ɵɵelementEnd();
18
25
  } if (rf & 2) {
19
- const option_r2 = i0.ɵɵnextContext().$implicit;
26
+ const ctx_r0 = i0.ɵɵnextContext();
20
27
  i0.ɵɵadvance();
21
- i0.ɵɵtextInterpolate(option_r2.Description);
28
+ i0.ɵɵtextInterpolate(ctx_r0.listRecord.Name);
22
29
  } }
23
- function SingleListDetailComponent_Conditional_9_For_2_Template(rf, ctx) { if (rf & 1) {
24
- const _r1 = i0.ɵɵgetCurrentView();
25
- i0.ɵɵelementStart(0, "div", 15);
26
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_For_2_Template_div_click_0_listener() { const option_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onDropdownItemClick(option_r2)); });
27
- i0.ɵɵelementStart(1, "span", 16);
30
+ function SingleListDetailComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
31
+ i0.ɵɵelementStart(0, "h1");
32
+ i0.ɵɵtext(1, "List");
33
+ i0.ɵɵelementEnd();
34
+ } }
35
+ function SingleListDetailComponent_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
36
+ i0.ɵɵtext(0, " Snapshot of: ");
37
+ i0.ɵɵelementStart(1, "strong");
28
38
  i0.ɵɵtext(2);
29
39
  i0.ɵɵelementEnd();
30
- i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_9_For_2_Conditional_3_Template, 2, 1, "span", 17);
40
+ } if (rf & 2) {
41
+ const ctx_r0 = i0.ɵɵnextContext(2);
42
+ i0.ɵɵadvance(2);
43
+ i0.ɵɵtextInterpolate(ctx_r0.sourceViewName ?? "(unknown view)");
44
+ } }
45
+ function SingleListDetailComponent_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
46
+ i0.ɵɵtext(0, " Live view: ");
47
+ i0.ɵɵelementStart(1, "strong");
48
+ i0.ɵɵtext(2);
31
49
  i0.ɵɵelementEnd();
32
50
  } if (rf & 2) {
33
- const option_r2 = ctx.$implicit;
51
+ const ctx_r0 = i0.ɵɵnextContext(2);
34
52
  i0.ɵɵadvance(2);
35
- i0.ɵɵtextInterpolate(option_r2.Text);
53
+ i0.ɵɵtextInterpolate(ctx_r0.sourceViewName ?? "(unknown view)");
54
+ } }
55
+ function SingleListDetailComponent_Conditional_5_Conditional_5_Template(rf, ctx) { if (rf & 1) {
56
+ i0.ɵɵelementStart(0, "span", 16);
57
+ i0.ɵɵtext(1);
58
+ i0.ɵɵpipe(2, "date");
59
+ i0.ɵɵelementEnd();
60
+ } if (rf & 2) {
61
+ const ctx_r0 = i0.ɵɵnextContext(2);
36
62
  i0.ɵɵadvance();
37
- i0.ɵɵconditional(option_r2.Description ? 3 : -1);
63
+ i0.ɵɵtextInterpolate1(" \u00B7 last refreshed ", i0.ɵɵpipeBind2(2, 1, ctx_r0.listRecord.LastRefreshedAt, "medium"), " ");
38
64
  } }
39
- function SingleListDetailComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
40
- i0.ɵɵelementStart(0, "div", 7);
41
- i0.ɵɵrepeaterCreate(1, SingleListDetailComponent_Conditional_9_For_2_Template, 4, 2, "div", 14, _forTrack0);
65
+ function SingleListDetailComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
66
+ i0.ɵɵelementStart(0, "div", 4);
67
+ i0.ɵɵelement(1, "i", 15);
68
+ i0.ɵɵelementStart(2, "span");
69
+ i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_5_Conditional_3_Template, 3, 1)(4, SingleListDetailComponent_Conditional_5_Conditional_4_Template, 3, 1);
70
+ i0.ɵɵelementEnd();
71
+ i0.ɵɵconditionalCreate(5, SingleListDetailComponent_Conditional_5_Conditional_5_Template, 3, 4, "span", 16);
42
72
  i0.ɵɵelementEnd();
43
73
  } if (rf & 2) {
44
- const ctx_r2 = i0.ɵɵnextContext();
74
+ const ctx_r0 = i0.ɵɵnextContext();
75
+ i0.ɵɵproperty("title", "Source view: " + (ctx_r0.sourceViewName ?? "unknown"));
76
+ i0.ɵɵadvance(3);
77
+ i0.ɵɵconditional((ctx_r0.listRecord == null ? null : ctx_r0.listRecord.UseSnapshot) ? 3 : 4);
78
+ i0.ɵɵadvance(2);
79
+ i0.ɵɵconditional((ctx_r0.listRecord == null ? null : ctx_r0.listRecord.LastRefreshedAt) ? 5 : -1);
80
+ } }
81
+ function SingleListDetailComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
82
+ i0.ɵɵelementStart(0, "div", 5);
83
+ i0.ɵɵelement(1, "mj-tag-chips", 17);
84
+ i0.ɵɵelementEnd();
85
+ } if (rf & 2) {
86
+ const ctx_r0 = i0.ɵɵnextContext();
45
87
  i0.ɵɵadvance();
46
- i0.ɵɵrepeater(ctx_r2.addOptions);
88
+ i0.ɵɵproperty("Provider", ctx_r0.Provider)("RecordID", ctx_r0.listRecord.ID)("Editable", ctx_r0.capabilities.CanEdit)("MaxDisplay", 20);
47
89
  } }
48
- function SingleListDetailComponent_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
49
- i0.ɵɵelementStart(0, "span", 20);
90
+ function SingleListDetailComponent_Conditional_7_Conditional_5_For_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
91
+ i0.ɵɵelementStart(0, "span", 25);
50
92
  i0.ɵɵtext(1);
51
93
  i0.ɵɵelementEnd();
52
94
  } if (rf & 2) {
53
- const ctx_r2 = i0.ɵɵnextContext(2);
95
+ const option_r4 = i0.ɵɵnextContext().$implicit;
54
96
  i0.ɵɵadvance();
55
- i0.ɵɵtextInterpolate1("(", ctx_r2.selectedKeys.length, " selected)");
97
+ i0.ɵɵtextInterpolate(option_r4.Description);
56
98
  } }
57
- function SingleListDetailComponent_Conditional_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
58
- const _r5 = i0.ɵɵgetCurrentView();
59
- i0.ɵɵelementStart(0, "button", 26);
60
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_10_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.openRemoveDialog()); });
61
- i0.ɵɵelement(1, "span", 27);
62
- i0.ɵɵtext(2, " Remove from List ");
99
+ function SingleListDetailComponent_Conditional_7_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
100
+ const _r3 = i0.ɵɵgetCurrentView();
101
+ i0.ɵɵelementStart(0, "div", 23);
102
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_7_Conditional_5_For_2_Template_div_click_0_listener() { const option_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.onDropdownItemClick(option_r4)); });
103
+ i0.ɵɵelementStart(1, "span", 24);
104
+ i0.ɵɵtext(2);
63
105
  i0.ɵɵelementEnd();
106
+ i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_7_Conditional_5_For_2_Conditional_3_Template, 2, 1, "span", 25);
107
+ i0.ɵɵelementEnd();
108
+ } if (rf & 2) {
109
+ const option_r4 = ctx.$implicit;
110
+ i0.ɵɵadvance(2);
111
+ i0.ɵɵtextInterpolate(option_r4.Text);
112
+ i0.ɵɵadvance();
113
+ i0.ɵɵconditional(option_r4.Description ? 3 : -1);
64
114
  } }
65
- function SingleListDetailComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
66
- const _r4 = i0.ɵɵgetCurrentView();
67
- i0.ɵɵelementStart(0, "div", 8)(1, "div", 18)(2, "span", 19);
115
+ function SingleListDetailComponent_Conditional_7_Conditional_5_Template(rf, ctx) { if (rf & 1) {
116
+ i0.ɵɵelementStart(0, "div", 21);
117
+ i0.ɵɵrepeaterCreate(1, SingleListDetailComponent_Conditional_7_Conditional_5_For_2_Template, 4, 2, "div", 22, _forTrack0);
118
+ i0.ɵɵelementEnd();
119
+ } if (rf & 2) {
120
+ const ctx_r0 = i0.ɵɵnextContext(2);
121
+ i0.ɵɵadvance();
122
+ i0.ɵɵrepeater(ctx_r0.addOptions);
123
+ } }
124
+ function SingleListDetailComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
125
+ const _r2 = i0.ɵɵgetCurrentView();
126
+ i0.ɵɵelementStart(0, "div", 6)(1, "button", 18);
127
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_7_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleAddDropdown()); });
128
+ i0.ɵɵelement(2, "span", 19);
129
+ i0.ɵɵtext(3, " Add to List ");
130
+ i0.ɵɵelement(4, "span", 20);
131
+ i0.ɵɵelementEnd();
132
+ i0.ɵɵconditionalCreate(5, SingleListDetailComponent_Conditional_7_Conditional_5_Template, 3, 0, "div", 21);
133
+ i0.ɵɵelementEnd();
134
+ } if (rf & 2) {
135
+ const ctx_r0 = i0.ɵɵnextContext();
136
+ i0.ɵɵadvance(5);
137
+ i0.ɵɵconditional(ctx_r0.showAddDropdown ? 5 : -1);
138
+ } }
139
+ function SingleListDetailComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
140
+ i0.ɵɵelementStart(0, "span", 7);
141
+ i0.ɵɵelement(1, "i", 26);
142
+ i0.ɵɵtext(2, " Viewer access ");
143
+ i0.ɵɵelementEnd();
144
+ } }
145
+ function SingleListDetailComponent_Conditional_9_Conditional_4_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵelementStart(0, "span", 29);
147
+ i0.ɵɵtext(1);
148
+ i0.ɵɵelementEnd();
149
+ } if (rf & 2) {
150
+ const ctx_r0 = i0.ɵɵnextContext(2);
151
+ i0.ɵɵadvance();
152
+ i0.ɵɵtextInterpolate1("(", ctx_r0.selectedKeys.length, " selected)");
153
+ } }
154
+ function SingleListDetailComponent_Conditional_9_Conditional_6_Conditional_20_Template(rf, ctx) { if (rf & 1) {
155
+ i0.ɵɵelement(0, "span", 48);
156
+ i0.ɵɵtext(1, " Applying\u2026 ");
157
+ } }
158
+ function SingleListDetailComponent_Conditional_9_Conditional_6_Conditional_21_Template(rf, ctx) { if (rf & 1) {
159
+ i0.ɵɵelement(0, "span", 49);
160
+ i0.ɵɵtext(1, " Apply Status ");
161
+ } }
162
+ function SingleListDetailComponent_Conditional_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
163
+ const _r6 = i0.ɵɵgetCurrentView();
164
+ i0.ɵɵelementStart(0, "button", 34);
165
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openMoveDialog()); });
166
+ i0.ɵɵelement(1, "span", 35);
167
+ i0.ɵɵtext(2, " Move\u2026 ");
168
+ i0.ɵɵelementEnd();
169
+ i0.ɵɵelementStart(3, "button", 36);
170
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openCopyDialog()); });
171
+ i0.ɵɵelement(4, "span", 37);
172
+ i0.ɵɵtext(5, " Copy\u2026 ");
173
+ i0.ɵɵelementEnd();
174
+ i0.ɵɵelementStart(6, "select", 38);
175
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_9_Conditional_6_Template_select_ngModelChange_6_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.bulkStatus, $event) || (ctx_r0.bulkStatus = $event); return i0.ɵɵresetView($event); });
176
+ i0.ɵɵelementStart(7, "option", 39);
177
+ i0.ɵɵtext(8, "Set status\u2026");
178
+ i0.ɵɵelementEnd();
179
+ i0.ɵɵelementStart(9, "option", 40);
180
+ i0.ɵɵtext(10, "Active");
181
+ i0.ɵɵelementEnd();
182
+ i0.ɵɵelementStart(11, "option", 41);
183
+ i0.ɵɵtext(12, "Complete");
184
+ i0.ɵɵelementEnd();
185
+ i0.ɵɵelementStart(13, "option", 42);
186
+ i0.ɵɵtext(14, "Pending");
187
+ i0.ɵɵelementEnd();
188
+ i0.ɵɵelementStart(15, "option", 43);
189
+ i0.ɵɵtext(16, "Disabled");
190
+ i0.ɵɵelementEnd();
191
+ i0.ɵɵelementStart(17, "option", 44);
192
+ i0.ɵɵtext(18, "Rejected");
193
+ i0.ɵɵelementEnd()();
194
+ i0.ɵɵelementStart(19, "button", 45);
195
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Conditional_6_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.applyBulkStatus()); });
196
+ i0.ɵɵconditionalCreate(20, SingleListDetailComponent_Conditional_9_Conditional_6_Conditional_20_Template, 2, 0)(21, SingleListDetailComponent_Conditional_9_Conditional_6_Conditional_21_Template, 2, 0);
197
+ i0.ɵɵelementEnd();
198
+ i0.ɵɵelementStart(22, "button", 46);
199
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Conditional_6_Template_button_click_22_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openRemoveDialog()); });
200
+ i0.ɵɵelement(23, "span", 47);
201
+ i0.ɵɵtext(24, " Remove from List ");
202
+ i0.ɵɵelementEnd();
203
+ } if (rf & 2) {
204
+ const ctx_r0 = i0.ɵɵnextContext(2);
205
+ i0.ɵɵadvance(6);
206
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.bulkStatus);
207
+ i0.ɵɵproperty("disabled", ctx_r0.isApplyingBulkStatus);
208
+ i0.ɵɵadvance(13);
209
+ i0.ɵɵproperty("disabled", !ctx_r0.bulkStatus || ctx_r0.isApplyingBulkStatus);
210
+ i0.ɵɵadvance();
211
+ i0.ɵɵconditional(ctx_r0.isApplyingBulkStatus ? 20 : 21);
212
+ } }
213
+ function SingleListDetailComponent_Conditional_9_Conditional_7_Conditional_6_Template(rf, ctx) { if (rf & 1) {
214
+ i0.ɵɵelement(0, "span", 48);
215
+ i0.ɵɵtext(1, " Previewing... ");
216
+ } }
217
+ function SingleListDetailComponent_Conditional_9_Conditional_7_Conditional_7_Template(rf, ctx) { if (rf & 1) {
218
+ i0.ɵɵelement(0, "span", 53);
219
+ i0.ɵɵtext(1, " Refresh from Source ");
220
+ } }
221
+ function SingleListDetailComponent_Conditional_9_Conditional_7_Template(rf, ctx) { if (rf & 1) {
222
+ const _r7 = i0.ɵɵgetCurrentView();
223
+ i0.ɵɵelementStart(0, "select", 50);
224
+ i0.ɵɵlistener("ngModelChange", function SingleListDetailComponent_Conditional_9_Conditional_7_Template_select_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onRefreshModeChange($event)); });
225
+ i0.ɵɵelementStart(1, "option", 51);
226
+ i0.ɵɵtext(2, "Additive");
227
+ i0.ɵɵelementEnd();
228
+ i0.ɵɵelementStart(3, "option", 52);
229
+ i0.ɵɵtext(4, "Sync");
230
+ i0.ɵɵelementEnd()();
231
+ i0.ɵɵelementStart(5, "button", 45);
232
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Conditional_7_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onRefreshFromSource()); });
233
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_9_Conditional_7_Conditional_6_Template, 2, 0)(7, SingleListDetailComponent_Conditional_9_Conditional_7_Conditional_7_Template, 2, 0);
234
+ i0.ɵɵelementEnd();
235
+ } if (rf & 2) {
236
+ const ctx_r0 = i0.ɵɵnextContext(2);
237
+ i0.ɵɵproperty("ngModel", ctx_r0.refreshMode)("disabled", ctx_r0.isPreviewingRefresh || ctx_r0.isApplyingRefresh);
238
+ i0.ɵɵadvance(5);
239
+ i0.ɵɵproperty("disabled", ctx_r0.isPreviewingRefresh || ctx_r0.isApplyingRefresh);
240
+ i0.ɵɵadvance();
241
+ i0.ɵɵconditional(ctx_r0.isPreviewingRefresh ? 6 : 7);
242
+ } }
243
+ function SingleListDetailComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
244
+ const _r5 = i0.ɵɵgetCurrentView();
245
+ i0.ɵɵelementStart(0, "div", 8)(1, "div", 27)(2, "span", 28);
68
246
  i0.ɵɵtext(3);
69
247
  i0.ɵɵelementEnd();
70
- i0.ɵɵconditionalCreate(4, SingleListDetailComponent_Conditional_10_Conditional_4_Template, 2, 1, "span", 20);
248
+ i0.ɵɵconditionalCreate(4, SingleListDetailComponent_Conditional_9_Conditional_4_Template, 2, 1, "span", 29);
71
249
  i0.ɵɵelementEnd();
72
- i0.ɵɵelementStart(5, "div", 21);
73
- i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_10_Conditional_6_Template, 3, 0, "button", 22);
74
- i0.ɵɵelementStart(7, "button", 23);
75
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onRefreshClick()); });
76
- i0.ɵɵelement(8, "span", 24);
77
- i0.ɵɵtext(9, " Refresh ");
250
+ i0.ɵɵelementStart(5, "div", 30);
251
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_9_Conditional_6_Template, 25, 4);
252
+ i0.ɵɵconditionalCreate(7, SingleListDetailComponent_Conditional_9_Conditional_7_Template, 8, 4);
253
+ i0.ɵɵelementStart(8, "button", 31);
254
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onRefreshClick()); });
255
+ i0.ɵɵelement(9, "span", 32);
256
+ i0.ɵɵtext(10, " Refresh ");
78
257
  i0.ɵɵelementEnd();
79
- i0.ɵɵelementStart(10, "button", 23);
80
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_10_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onExportClick()); });
81
- i0.ɵɵelement(11, "span", 25);
82
- i0.ɵɵtext(12, " Export ");
258
+ i0.ɵɵelementStart(11, "button", 31);
259
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_9_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onExportClick()); });
260
+ i0.ɵɵelement(12, "span", 33);
261
+ i0.ɵɵtext(13, " Export ");
83
262
  i0.ɵɵelementEnd()()();
84
263
  } if (rf & 2) {
85
- const ctx_r2 = i0.ɵɵnextContext();
264
+ const ctx_r0 = i0.ɵɵnextContext();
86
265
  i0.ɵɵadvance(3);
87
- i0.ɵɵtextInterpolate2("", ctx_r2.rowCount, " row", ctx_r2.rowCount !== 1 ? "s" : "");
266
+ i0.ɵɵtextInterpolate2("", ctx_r0.rowCount, " row", ctx_r0.rowCount !== 1 ? "s" : "");
88
267
  i0.ɵɵadvance();
89
- i0.ɵɵconditional(ctx_r2.selectedKeys.length > 0 ? 4 : -1);
268
+ i0.ɵɵconditional(ctx_r0.selectedKeys.length > 0 ? 4 : -1);
90
269
  i0.ɵɵadvance(2);
91
- i0.ɵɵconditional(ctx_r2.selectedKeys.length > 0 ? 6 : -1);
270
+ i0.ɵɵconditional(ctx_r0.selectedKeys.length > 0 && ctx_r0.capabilities.CanEdit ? 6 : -1);
271
+ i0.ɵɵadvance();
272
+ i0.ɵɵconditional(ctx_r0.hasLineage && ctx_r0.capabilities.CanRefresh ? 7 : -1);
92
273
  } }
93
- function SingleListDetailComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
274
+ function SingleListDetailComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
94
275
  i0.ɵɵelementStart(0, "div", 9);
95
- i0.ɵɵelement(1, "mj-loading", 28);
276
+ i0.ɵɵelement(1, "mj-loading", 54);
96
277
  i0.ɵɵelementEnd();
97
278
  } }
98
- function SingleListDetailComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
99
- const _r6 = i0.ɵɵgetCurrentView();
100
- i0.ɵɵelementStart(0, "div", 10)(1, "mj-list-detail-grid", 29, 0);
101
- i0.ɵɵlistener("rowClicked", function SingleListDetailComponent_Conditional_12_Template_mj_list_detail_grid_rowClicked_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onRowClicked($event)); })("rowDoubleClicked", function SingleListDetailComponent_Conditional_12_Template_mj_list_detail_grid_rowDoubleClicked_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onRowDoubleClicked($event)); })("selectionChange", function SingleListDetailComponent_Conditional_12_Template_mj_list_detail_grid_selectionChange_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onSelectionChange($event)); })("dataLoaded", function SingleListDetailComponent_Conditional_12_Template_mj_list_detail_grid_dataLoaded_1_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDataLoaded($event)); });
279
+ function SingleListDetailComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
280
+ const _r8 = i0.ɵɵgetCurrentView();
281
+ i0.ɵɵelementStart(0, "div", 10)(1, "div", 55)(2, "mj-list-detail-grid", 56, 0);
282
+ i0.ɵɵlistener("rowClicked", function SingleListDetailComponent_Conditional_11_Template_mj_list_detail_grid_rowClicked_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onRowClicked($event)); })("rowDoubleClicked", function SingleListDetailComponent_Conditional_11_Template_mj_list_detail_grid_rowDoubleClicked_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onRowDoubleClicked($event)); })("selectionChange", function SingleListDetailComponent_Conditional_11_Template_mj_list_detail_grid_selectionChange_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onSelectionChange($event)); })("dataLoaded", function SingleListDetailComponent_Conditional_11_Template_mj_list_detail_grid_dataLoaded_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDataLoaded($event)); });
283
+ i0.ɵɵelementEnd()();
284
+ i0.ɵɵelementStart(4, "aside", 57);
285
+ i0.ɵɵelement(5, "mj-list-stats", 58);
286
+ i0.ɵɵelementEnd()();
287
+ } if (rf & 2) {
288
+ const ctx_r0 = i0.ɵɵnextContext();
289
+ i0.ɵɵadvance(2);
290
+ i0.ɵɵproperty("listId", ctx_r0.ListID)("listEntity", ctx_r0.listRecord)("autoNavigate", true)("height", "auto")("showToolbar", false)("toolbarConfig", ctx_r0.gridToolbarConfig)("selectionMode", "checkbox");
291
+ i0.ɵɵadvance(3);
292
+ i0.ɵɵproperty("Provider", ctx_r0.Provider)("ListID", ctx_r0.listRecord.ID)("RefreshTrigger", ctx_r0.statsRefreshTrigger);
293
+ } }
294
+ function SingleListDetailComponent_Conditional_14_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
295
+ i0.ɵɵelement(0, "mj-progress-bar", 65);
296
+ } if (rf & 2) {
297
+ const ctx_r0 = i0.ɵɵnextContext(3);
298
+ i0.ɵɵproperty("Value", ctx_r0.moveCopyProgressPercent);
299
+ } }
300
+ function SingleListDetailComponent_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
301
+ i0.ɵɵelementStart(0, "div", 61);
302
+ i0.ɵɵelement(1, "mj-loading", 64);
303
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_14_Conditional_2_Conditional_2_Template, 1, 1, "mj-progress-bar", 65);
304
+ i0.ɵɵelementEnd();
305
+ } if (rf & 2) {
306
+ const ctx_r0 = i0.ɵɵnextContext(2);
307
+ i0.ɵɵadvance();
308
+ i0.ɵɵproperty("text", (ctx_r0.moveCopyMode === "move" ? "Moving" : "Copying") + " records...");
309
+ i0.ɵɵadvance();
310
+ i0.ɵɵconditional(ctx_r0.moveCopyTotal > 0 ? 2 : -1);
311
+ } }
312
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
313
+ i0.ɵɵelementStart(0, "div", 71);
314
+ i0.ɵɵelement(1, "mj-loading", 74);
315
+ i0.ɵɵelementEnd();
316
+ } }
317
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
318
+ i0.ɵɵelementStart(0, "div", 72);
319
+ i0.ɵɵelement(1, "span", 75);
320
+ i0.ɵɵelementStart(2, "p");
321
+ i0.ɵɵtext(3, "No other lists found for this entity.");
322
+ i0.ɵɵelementEnd();
323
+ i0.ɵɵelementStart(4, "p", 76);
324
+ i0.ɵɵtext(5, "Create a new list first if you need a new target.");
325
+ i0.ɵɵelementEnd()();
326
+ } }
327
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
328
+ i0.ɵɵelementStart(0, "span", 82);
329
+ i0.ɵɵtext(1);
330
+ i0.ɵɵelementEnd();
331
+ } if (rf & 2) {
332
+ const target_r12 = i0.ɵɵnextContext().$implicit;
333
+ i0.ɵɵadvance();
334
+ i0.ɵɵtextInterpolate1(" \u2014 ", target_r12.Description);
335
+ } }
336
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Template(rf, ctx) { if (rf & 1) {
337
+ const _r11 = i0.ɵɵgetCurrentView();
338
+ i0.ɵɵelementStart(0, "div", 78);
339
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Template_div_click_0_listener() { const target_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.selectMoveCopyTarget(target_r12)); });
340
+ i0.ɵɵelementStart(1, "div", 79)(2, "input", 80);
341
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Template_input_click_2_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); })("change", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Template_input_change_2_listener() { const target_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.selectMoveCopyTarget(target_r12)); });
102
342
  i0.ɵɵelementEnd()();
343
+ i0.ɵɵelementStart(3, "div", 81)(4, "strong");
344
+ i0.ɵɵtext(5);
345
+ i0.ɵɵelementEnd();
346
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Conditional_6_Template, 2, 1, "span", 82);
347
+ i0.ɵɵelementEnd()();
348
+ } if (rf & 2) {
349
+ const target_r12 = ctx.$implicit;
350
+ const ctx_r0 = i0.ɵɵnextContext(4);
351
+ i0.ɵɵclassProp("selected", (ctx_r0.moveCopySelectedTarget == null ? null : ctx_r0.moveCopySelectedTarget.ID) === target_r12.ID);
352
+ i0.ɵɵadvance(2);
353
+ i0.ɵɵproperty("checked", (ctx_r0.moveCopySelectedTarget == null ? null : ctx_r0.moveCopySelectedTarget.ID) === target_r12.ID);
354
+ i0.ɵɵadvance(3);
355
+ i0.ɵɵtextInterpolate(target_r12.Name);
356
+ i0.ɵɵadvance();
357
+ i0.ɵɵconditional(target_r12.Description ? 6 : -1);
358
+ } }
359
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
360
+ i0.ɵɵelementStart(0, "div", 73);
361
+ i0.ɵɵrepeaterCreate(1, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_For_2_Template, 7, 5, "div", 77, _forTrack1);
362
+ i0.ɵɵelementEnd();
363
+ } if (rf & 2) {
364
+ const ctx_r0 = i0.ɵɵnextContext(3);
365
+ i0.ɵɵadvance();
366
+ i0.ɵɵrepeater(ctx_r0.filteredMoveCopyTargets);
367
+ } }
368
+ function SingleListDetailComponent_Conditional_14_Conditional_3_Template(rf, ctx) { if (rf & 1) {
369
+ const _r10 = i0.ɵɵgetCurrentView();
370
+ i0.ɵɵelementStart(0, "p", 66);
371
+ i0.ɵɵtext(1);
372
+ i0.ɵɵelementEnd();
373
+ i0.ɵɵelementStart(2, "div", 67)(3, "div", 68);
374
+ i0.ɵɵelement(4, "span", 69);
375
+ i0.ɵɵelementStart(5, "input", 70);
376
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_14_Conditional_3_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r0.moveCopyTargetSearch, $event) || (ctx_r0.moveCopyTargetSearch = $event); return i0.ɵɵresetView($event); });
377
+ i0.ɵɵelementEnd()()();
378
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_6_Template, 2, 0, "div", 71)(7, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_7_Template, 6, 0, "div", 72)(8, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_Template, 3, 0, "div", 73);
379
+ } if (rf & 2) {
380
+ const ctx_r0 = i0.ɵɵnextContext(2);
381
+ i0.ɵɵadvance();
382
+ i0.ɵɵtextInterpolate1(" Choose the target list. Both lists must hold the same entity (", (ctx_r0.listRecord == null ? null : ctx_r0.listRecord.Entity) ?? "records", "). ");
383
+ i0.ɵɵadvance(4);
384
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.moveCopyTargetSearch);
385
+ i0.ɵɵadvance();
386
+ i0.ɵɵconditional(ctx_r0.moveCopyTargetCandidatesLoading ? 6 : ctx_r0.filteredMoveCopyTargets.length === 0 ? 7 : 8);
387
+ } }
388
+ function SingleListDetailComponent_Conditional_14_Conditional_6_Template(rf, ctx) { if (rf & 1) {
389
+ i0.ɵɵelement(0, "span", 35);
390
+ i0.ɵɵtext(1, " Continue ");
391
+ } }
392
+ function SingleListDetailComponent_Conditional_14_Conditional_7_Template(rf, ctx) { if (rf & 1) {
393
+ i0.ɵɵelement(0, "span", 37);
394
+ i0.ɵɵtext(1);
103
395
  } if (rf & 2) {
104
- const ctx_r2 = i0.ɵɵnextContext();
396
+ const ctx_r0 = i0.ɵɵnextContext(2);
105
397
  i0.ɵɵadvance();
106
- i0.ɵɵproperty("listId", ctx_r2.ListID)("listEntity", ctx_r2.listRecord)("autoNavigate", true)("height", "auto")("showToolbar", false)("toolbarConfig", ctx_r2.gridToolbarConfig)("selectionMode", "checkbox");
398
+ i0.ɵɵtextInterpolate1(" Copy ", ctx_r0.selectedKeys.length, " ");
107
399
  } }
108
- function SingleListDetailComponent_Conditional_13_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
109
- i0.ɵɵelement(0, "mj-progress-bar", 37);
400
+ function SingleListDetailComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
401
+ const _r9 = i0.ɵɵgetCurrentView();
402
+ i0.ɵɵelementStart(0, "mj-dialog", 59);
403
+ i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_14_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeMoveCopyDialog()); });
404
+ i0.ɵɵelementStart(1, "div", 60);
405
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_14_Conditional_2_Template, 3, 2, "div", 61)(3, SingleListDetailComponent_Conditional_14_Conditional_3_Template, 9, 3);
406
+ i0.ɵɵelementEnd();
407
+ i0.ɵɵelementStart(4, "mj-dialog-actions")(5, "button", 62);
408
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmMoveCopy()); });
409
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_14_Conditional_6_Template, 2, 0)(7, SingleListDetailComponent_Conditional_14_Conditional_7_Template, 2, 1);
410
+ i0.ɵɵelementEnd();
411
+ i0.ɵɵelementStart(8, "button", 63);
412
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeMoveCopyDialog()); });
413
+ i0.ɵɵtext(9, " Cancel ");
414
+ i0.ɵɵelementEnd()()();
110
415
  } if (rf & 2) {
111
- const ctx_r2 = i0.ɵɵnextContext(3);
112
- i0.ɵɵproperty("Value", ctx_r2.removeProgressPercent);
416
+ const ctx_r0 = i0.ɵɵnextContext();
417
+ i0.ɵɵproperty("Visible", true)("Title", (ctx_r0.moveCopyMode === "move" ? "Move " : "Copy ") + ctx_r0.selectedKeys.length + " record" + (ctx_r0.selectedKeys.length === 1 ? "" : "s") + " to\u2026")("MinWidth", 480)("Width", 640)("Height", 560);
418
+ i0.ɵɵadvance(2);
419
+ i0.ɵɵconditional(ctx_r0.isApplyingMoveCopy ? 2 : 3);
420
+ i0.ɵɵadvance(3);
421
+ i0.ɵɵproperty("disabled", !ctx_r0.moveCopySelectedTarget || ctx_r0.isApplyingMoveCopy);
422
+ i0.ɵɵadvance();
423
+ i0.ɵɵconditional(ctx_r0.moveCopyMode === "move" ? 6 : 7);
424
+ i0.ɵɵadvance(2);
425
+ i0.ɵɵproperty("disabled", ctx_r0.isApplyingMoveCopy);
113
426
  } }
114
- function SingleListDetailComponent_Conditional_13_Conditional_2_Template(rf, ctx) { if (rf & 1) {
115
- i0.ɵɵelementStart(0, "div", 32);
116
- i0.ɵɵelement(1, "mj-loading", 36);
117
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_13_Conditional_2_Conditional_2_Template, 1, 1, "mj-progress-bar", 37);
427
+ function SingleListDetailComponent_Conditional_15_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
428
+ i0.ɵɵelement(0, "mj-progress-bar", 65);
429
+ } if (rf & 2) {
430
+ const ctx_r0 = i0.ɵɵnextContext(3);
431
+ i0.ɵɵproperty("Value", ctx_r0.removeProgressPercent);
432
+ } }
433
+ function SingleListDetailComponent_Conditional_15_Conditional_2_Template(rf, ctx) { if (rf & 1) {
434
+ i0.ɵɵelementStart(0, "div", 61);
435
+ i0.ɵɵelement(1, "mj-loading", 87);
436
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_15_Conditional_2_Conditional_2_Template, 1, 1, "mj-progress-bar", 65);
118
437
  i0.ɵɵelementEnd();
119
438
  } if (rf & 2) {
120
- const ctx_r2 = i0.ɵɵnextContext(2);
439
+ const ctx_r0 = i0.ɵɵnextContext(2);
121
440
  i0.ɵɵadvance(2);
122
- i0.ɵɵconditional(ctx_r2.removeTotal > 0 ? 2 : -1);
441
+ i0.ɵɵconditional(ctx_r0.removeTotal > 0 ? 2 : -1);
123
442
  } }
124
- function SingleListDetailComponent_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
125
- i0.ɵɵelementStart(0, "div", 33);
126
- i0.ɵɵelement(1, "span", 38);
443
+ function SingleListDetailComponent_Conditional_15_Conditional_3_Template(rf, ctx) { if (rf & 1) {
444
+ i0.ɵɵelementStart(0, "div", 85);
445
+ i0.ɵɵelement(1, "span", 88);
127
446
  i0.ɵɵelementStart(2, "p");
128
447
  i0.ɵɵtext(3, "Are you sure you want to remove ");
129
448
  i0.ɵɵelementStart(4, "strong");
@@ -131,292 +450,462 @@ function SingleListDetailComponent_Conditional_13_Conditional_3_Template(rf, ctx
131
450
  i0.ɵɵelementEnd();
132
451
  i0.ɵɵtext(6);
133
452
  i0.ɵɵelementEnd();
134
- i0.ɵɵelementStart(7, "p", 39);
453
+ i0.ɵɵelementStart(7, "p", 76);
135
454
  i0.ɵɵtext(8, "This will not delete the records, only remove them from this list.");
136
455
  i0.ɵɵelementEnd()();
137
456
  } if (rf & 2) {
138
- const ctx_r2 = i0.ɵɵnextContext(2);
457
+ const ctx_r0 = i0.ɵɵnextContext(2);
139
458
  i0.ɵɵadvance(5);
140
- i0.ɵɵtextInterpolate(ctx_r2.selectedKeys.length);
459
+ i0.ɵɵtextInterpolate(ctx_r0.selectedKeys.length);
141
460
  i0.ɵɵadvance();
142
- i0.ɵɵtextInterpolate1(" record", ctx_r2.selectedKeys.length !== 1 ? "s" : "", " from this list?");
461
+ i0.ɵɵtextInterpolate1(" record", ctx_r0.selectedKeys.length !== 1 ? "s" : "", " from this list?");
143
462
  } }
144
- function SingleListDetailComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
145
- const _r7 = i0.ɵɵgetCurrentView();
146
- i0.ɵɵelementStart(0, "mj-dialog", 30);
147
- i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_13_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeRemoveDialog()); });
148
- i0.ɵɵelementStart(1, "div", 31);
149
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_13_Conditional_2_Template, 3, 1, "div", 32)(3, SingleListDetailComponent_Conditional_13_Conditional_3_Template, 9, 2, "div", 33);
463
+ function SingleListDetailComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
464
+ const _r13 = i0.ɵɵgetCurrentView();
465
+ i0.ɵɵelementStart(0, "mj-dialog", 83);
466
+ i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_15_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeRemoveDialog()); });
467
+ i0.ɵɵelementStart(1, "div", 84);
468
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_15_Conditional_2_Template, 3, 1, "div", 61)(3, SingleListDetailComponent_Conditional_15_Conditional_3_Template, 9, 2, "div", 85);
150
469
  i0.ɵɵelementEnd();
151
- i0.ɵɵelementStart(4, "mj-dialog-actions")(5, "button", 34);
152
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_13_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.confirmRemoveFromList()); });
470
+ i0.ɵɵelementStart(4, "mj-dialog-actions")(5, "button", 86);
471
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r13); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmRemoveFromList()); });
153
472
  i0.ɵɵtext(6, " Remove ");
154
473
  i0.ɵɵelementEnd();
155
- i0.ɵɵelementStart(7, "button", 35);
156
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_13_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeRemoveDialog()); });
474
+ i0.ɵɵelementStart(7, "button", 63);
475
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r13); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeRemoveDialog()); });
157
476
  i0.ɵɵtext(8, " Cancel ");
158
477
  i0.ɵɵelementEnd()()();
159
478
  } if (rf & 2) {
160
- const ctx_r2 = i0.ɵɵnextContext();
479
+ const ctx_r0 = i0.ɵɵnextContext();
161
480
  i0.ɵɵproperty("Visible", true)("MinWidth", 350)("Width", 450);
162
481
  i0.ɵɵadvance(2);
163
- i0.ɵɵconditional(ctx_r2.isRemoving ? 2 : 3);
482
+ i0.ɵɵconditional(ctx_r0.isRemoving ? 2 : 3);
164
483
  i0.ɵɵadvance(3);
165
- i0.ɵɵproperty("disabled", ctx_r2.isRemoving);
484
+ i0.ɵɵproperty("disabled", ctx_r0.isRemoving);
166
485
  i0.ɵɵadvance(2);
167
- i0.ɵɵproperty("disabled", ctx_r2.isRemoving);
486
+ i0.ɵɵproperty("disabled", ctx_r0.isRemoving);
168
487
  } }
169
- function SingleListDetailComponent_Conditional_14_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
170
- i0.ɵɵelement(0, "mj-progress-bar", 37);
488
+ function SingleListDetailComponent_Conditional_16_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
489
+ i0.ɵɵelement(0, "mj-progress-bar", 65);
171
490
  } if (rf & 2) {
172
- const ctx_r2 = i0.ɵɵnextContext(3);
173
- i0.ɵɵproperty("Value", ctx_r2.addProgressPercent);
491
+ const ctx_r0 = i0.ɵɵnextContext(3);
492
+ i0.ɵɵproperty("Value", ctx_r0.addProgressPercent);
174
493
  } }
175
- function SingleListDetailComponent_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
176
- i0.ɵɵelementStart(0, "div", 32);
177
- i0.ɵɵelement(1, "mj-loading", 43);
178
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_14_Conditional_2_Conditional_2_Template, 1, 1, "mj-progress-bar", 37);
494
+ function SingleListDetailComponent_Conditional_16_Conditional_2_Template(rf, ctx) { if (rf & 1) {
495
+ i0.ɵɵelementStart(0, "div", 61);
496
+ i0.ɵɵelement(1, "mj-loading", 90);
497
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_16_Conditional_2_Conditional_2_Template, 1, 1, "mj-progress-bar", 65);
179
498
  i0.ɵɵelementEnd();
180
499
  } if (rf & 2) {
181
- const ctx_r2 = i0.ɵɵnextContext(2);
500
+ const ctx_r0 = i0.ɵɵnextContext(2);
182
501
  i0.ɵɵadvance(2);
183
- i0.ɵɵconditional(ctx_r2.addTotal > 0 ? 2 : -1);
502
+ i0.ɵɵconditional(ctx_r0.addTotal > 0 ? 2 : -1);
184
503
  } }
185
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
186
- i0.ɵɵelementStart(0, "div", 50);
187
- i0.ɵɵelement(1, "mj-loading", 52);
504
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
505
+ i0.ɵɵelementStart(0, "div", 71);
506
+ i0.ɵɵelement(1, "mj-loading", 94);
188
507
  i0.ɵɵelementEnd();
189
508
  } if (rf & 2) {
190
509
  i0.ɵɵadvance();
191
510
  i0.ɵɵproperty("showText", false);
192
511
  } }
193
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
194
- i0.ɵɵelementStart(0, "div", 51);
195
- i0.ɵɵelement(1, "span", 53);
512
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
513
+ i0.ɵɵelementStart(0, "div", 72);
514
+ i0.ɵɵelement(1, "span", 95);
196
515
  i0.ɵɵelementStart(2, "p");
197
516
  i0.ɵɵtext(3);
198
517
  i0.ɵɵelementEnd()();
199
518
  } if (rf & 2) {
200
- const ctx_r2 = i0.ɵɵnextContext(3);
519
+ const ctx_r0 = i0.ɵɵnextContext(3);
201
520
  i0.ɵɵadvance(3);
202
- i0.ɵɵtextInterpolate1("No records found matching \"", ctx_r2.addRecordsSearchFilter, "\"");
521
+ i0.ɵɵtextInterpolate1("No records found matching \"", ctx_r0.addRecordsSearchFilter, "\"");
203
522
  } }
204
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_9_Template(rf, ctx) { if (rf & 1) {
205
- i0.ɵɵelementStart(0, "div", 51);
206
- i0.ɵɵelement(1, "span", 54);
523
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_9_Template(rf, ctx) { if (rf & 1) {
524
+ i0.ɵɵelementStart(0, "div", 72);
525
+ i0.ɵɵelement(1, "span", 75);
207
526
  i0.ɵɵelementStart(2, "p");
208
527
  i0.ɵɵtext(3, "Search for records to add to this list");
209
528
  i0.ɵɵelementEnd()();
210
529
  } }
211
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
212
- i0.ɵɵelement(0, "span", 62);
530
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
531
+ i0.ɵɵelement(0, "span", 101);
213
532
  } }
214
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_3_Template(rf, ctx) { if (rf & 1) {
215
- const _r13 = i0.ɵɵgetCurrentView();
216
- i0.ɵɵelementStart(0, "input", 66);
217
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_3_Template_input_click_0_listener($event) { i0.ɵɵrestoreView(_r13); return i0.ɵɵresetView($event.stopPropagation()); })("change", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_3_Template_input_change_0_listener() { i0.ɵɵrestoreView(_r13); const record_r12 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.toggleRecordSelection(record_r12)); });
533
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_3_Template(rf, ctx) { if (rf & 1) {
534
+ const _r19 = i0.ɵɵgetCurrentView();
535
+ i0.ɵɵelementStart(0, "input", 104);
536
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_3_Template_input_click_0_listener($event) { i0.ɵɵrestoreView(_r19); return i0.ɵɵresetView($event.stopPropagation()); })("change", function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_3_Template_input_change_0_listener() { i0.ɵɵrestoreView(_r19); const record_r18 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleRecordSelection(record_r18)); });
218
537
  i0.ɵɵelementEnd();
219
538
  } if (rf & 2) {
220
- const record_r12 = i0.ɵɵnextContext().$implicit;
221
- i0.ɵɵproperty("checked", record_r12.isSelected);
539
+ const record_r18 = i0.ɵɵnextContext().$implicit;
540
+ i0.ɵɵproperty("checked", record_r18.isSelected);
222
541
  } }
223
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
224
- i0.ɵɵelementStart(0, "span", 65);
542
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
543
+ i0.ɵɵelementStart(0, "span", 103);
225
544
  i0.ɵɵtext(1, "In List");
226
545
  i0.ɵɵelementEnd();
227
546
  } }
228
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Template(rf, ctx) { if (rf & 1) {
229
- const _r11 = i0.ɵɵgetCurrentView();
230
- i0.ɵɵelementStart(0, "div", 60);
231
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Template_div_click_0_listener() { const record_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.toggleRecordSelection(record_r12)); });
232
- i0.ɵɵelementStart(1, "div", 61);
233
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_2_Template, 1, 0, "span", 62)(3, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_3_Template, 1, 1, "input", 63);
547
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Template(rf, ctx) { if (rf & 1) {
548
+ const _r17 = i0.ɵɵgetCurrentView();
549
+ i0.ɵɵelementStart(0, "div", 78);
550
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Template_div_click_0_listener() { const record_r18 = i0.ɵɵrestoreView(_r17).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleRecordSelection(record_r18)); });
551
+ i0.ɵɵelementStart(1, "div", 79);
552
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_2_Template, 1, 0, "span", 101)(3, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_3_Template, 1, 1, "input", 102);
234
553
  i0.ɵɵelementEnd();
235
- i0.ɵɵelementStart(4, "div", 64);
554
+ i0.ɵɵelementStart(4, "div", 81);
236
555
  i0.ɵɵtext(5);
237
556
  i0.ɵɵelementEnd();
238
- i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Conditional_6_Template, 2, 0, "span", 65);
557
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Conditional_6_Template, 2, 0, "span", 103);
239
558
  i0.ɵɵelementEnd();
240
559
  } if (rf & 2) {
241
- const record_r12 = ctx.$implicit;
242
- i0.ɵɵclassProp("in-list", record_r12.isInList)("selected", record_r12.isSelected);
560
+ const record_r18 = ctx.$implicit;
561
+ i0.ɵɵclassProp("in-list", record_r18.isInList)("selected", record_r18.isSelected);
243
562
  i0.ɵɵadvance(2);
244
- i0.ɵɵconditional(record_r12.isInList ? 2 : 3);
563
+ i0.ɵɵconditional(record_r18.isInList ? 2 : 3);
245
564
  i0.ɵɵadvance(3);
246
- i0.ɵɵtextInterpolate(record_r12.Name);
565
+ i0.ɵɵtextInterpolate(record_r18.Name);
247
566
  i0.ɵɵadvance();
248
- i0.ɵɵconditional(record_r12.isInList ? 6 : -1);
567
+ i0.ɵɵconditional(record_r18.isInList ? 6 : -1);
249
568
  } }
250
- function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
251
- const _r10 = i0.ɵɵgetCurrentView();
252
- i0.ɵɵelementStart(0, "div", 55)(1, "button", 56);
253
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.selectAllAddable()); });
569
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
570
+ const _r16 = i0.ɵɵgetCurrentView();
571
+ i0.ɵɵelementStart(0, "div", 96)(1, "button", 97);
572
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r16); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.selectAllAddable()); });
254
573
  i0.ɵɵtext(2, "Select All");
255
574
  i0.ɵɵelementEnd();
256
- i0.ɵɵelementStart(3, "button", 56);
257
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.deselectAllAddable()); });
575
+ i0.ɵɵelementStart(3, "button", 97);
576
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r16); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.deselectAllAddable()); });
258
577
  i0.ɵɵtext(4, "Deselect All");
259
578
  i0.ɵɵelementEnd();
260
- i0.ɵɵelementStart(5, "span", 57);
579
+ i0.ɵɵelementStart(5, "span", 98);
261
580
  i0.ɵɵtext(6);
262
581
  i0.ɵɵelementEnd()();
263
- i0.ɵɵelementStart(7, "div", 58);
264
- i0.ɵɵrepeaterCreate(8, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_For_9_Template, 7, 7, "div", 59, _forTrack1);
582
+ i0.ɵɵelementStart(7, "div", 99);
583
+ i0.ɵɵrepeaterCreate(8, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_For_9_Template, 7, 7, "div", 100, _forTrack1);
265
584
  i0.ɵɵelementEnd();
266
585
  } if (rf & 2) {
267
- const ctx_r2 = i0.ɵɵnextContext(3);
586
+ const ctx_r0 = i0.ɵɵnextContext(3);
268
587
  i0.ɵɵadvance(6);
269
- i0.ɵɵtextInterpolate1("", ctx_r2.selectedAddableRecords.length, " selected");
588
+ i0.ɵɵtextInterpolate1("", ctx_r0.selectedAddableRecords.length, " selected");
270
589
  i0.ɵɵadvance(2);
271
- i0.ɵɵrepeater(ctx_r2.addableRecords);
590
+ i0.ɵɵrepeater(ctx_r0.addableRecords);
272
591
  } }
273
- function SingleListDetailComponent_Conditional_14_Conditional_3_Template(rf, ctx) { if (rf & 1) {
274
- const _r9 = i0.ɵɵgetCurrentView();
275
- i0.ɵɵelementStart(0, "div", 44)(1, "div", 45);
276
- i0.ɵɵelement(2, "span", 46);
277
- i0.ɵɵelementStart(3, "input", 47);
278
- i0.ɵɵlistener("input", function SingleListDetailComponent_Conditional_14_Conditional_3_Template_input_input_3_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onAddRecordsSearchInputEvent($event)); });
592
+ function SingleListDetailComponent_Conditional_16_Conditional_3_Template(rf, ctx) { if (rf & 1) {
593
+ const _r15 = i0.ɵɵgetCurrentView();
594
+ i0.ɵɵelementStart(0, "div", 67)(1, "div", 68);
595
+ i0.ɵɵelement(2, "span", 69);
596
+ i0.ɵɵelementStart(3, "input", 91);
597
+ i0.ɵɵlistener("input", function SingleListDetailComponent_Conditional_16_Conditional_3_Template_input_input_3_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onAddRecordsSearchInputEvent($event)); });
279
598
  i0.ɵɵelementEnd()();
280
- i0.ɵɵelementStart(4, "span", 48);
599
+ i0.ɵɵelementStart(4, "span", 92);
281
600
  i0.ɵɵtext(5, "Type at least 2 characters to search");
282
601
  i0.ɵɵelementEnd()();
283
- i0.ɵɵelementStart(6, "div", 49);
284
- i0.ɵɵconditionalCreate(7, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_7_Template, 2, 1, "div", 50)(8, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_8_Template, 4, 1, "div", 51)(9, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_9_Template, 4, 0, "div", 51)(10, SingleListDetailComponent_Conditional_14_Conditional_3_Conditional_10_Template, 10, 1);
602
+ i0.ɵɵelementStart(6, "div", 93);
603
+ i0.ɵɵconditionalCreate(7, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_7_Template, 2, 1, "div", 71)(8, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_8_Template, 4, 1, "div", 72)(9, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_9_Template, 4, 0, "div", 72)(10, SingleListDetailComponent_Conditional_16_Conditional_3_Conditional_10_Template, 10, 1);
285
604
  i0.ɵɵelementEnd();
286
605
  } if (rf & 2) {
287
- const ctx_r2 = i0.ɵɵnextContext(2);
606
+ const ctx_r0 = i0.ɵɵnextContext(2);
288
607
  i0.ɵɵadvance(3);
289
- i0.ɵɵproperty("placeholder", "Search " + ((ctx_r2.listRecord == null ? null : ctx_r2.listRecord.Entity) || "records") + "...")("value", ctx_r2.addRecordsSearchFilter);
608
+ i0.ɵɵproperty("placeholder", "Search " + ((ctx_r0.listRecord == null ? null : ctx_r0.listRecord.Entity) || "records") + "...")("value", ctx_r0.addRecordsSearchFilter);
290
609
  i0.ɵɵadvance(4);
291
- i0.ɵɵconditional(ctx_r2.addDialogLoading ? 7 : ctx_r2.addableRecords.length === 0 && ctx_r2.addRecordsSearchFilter.length >= 2 ? 8 : ctx_r2.addableRecords.length === 0 ? 9 : 10);
610
+ i0.ɵɵconditional(ctx_r0.addDialogLoading ? 7 : ctx_r0.addableRecords.length === 0 && ctx_r0.addRecordsSearchFilter.length >= 2 ? 8 : ctx_r0.addableRecords.length === 0 ? 9 : 10);
292
611
  } }
293
- function SingleListDetailComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
294
- const _r8 = i0.ɵɵgetCurrentView();
295
- i0.ɵɵelementStart(0, "mj-dialog", 40);
296
- i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_14_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeAddRecordsDialog()); });
297
- i0.ɵɵelementStart(1, "div", 41);
298
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_14_Conditional_2_Template, 3, 1, "div", 32)(3, SingleListDetailComponent_Conditional_14_Conditional_3_Template, 11, 3);
612
+ function SingleListDetailComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
613
+ const _r14 = i0.ɵɵgetCurrentView();
614
+ i0.ɵɵelementStart(0, "mj-dialog", 59);
615
+ i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_16_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddRecordsDialog()); });
616
+ i0.ɵɵelementStart(1, "div", 89);
617
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_16_Conditional_2_Template, 3, 1, "div", 61)(3, SingleListDetailComponent_Conditional_16_Conditional_3_Template, 11, 3);
299
618
  i0.ɵɵelementEnd();
300
- i0.ɵɵelementStart(4, "mj-dialog-actions")(5, "button", 42);
301
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.confirmAddRecords()); });
619
+ i0.ɵɵelementStart(4, "mj-dialog-actions")(5, "button", 62);
620
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r14); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmAddRecords()); });
302
621
  i0.ɵɵtext(6);
303
622
  i0.ɵɵelementEnd();
304
- i0.ɵɵelementStart(7, "button", 35);
305
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_14_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeAddRecordsDialog()); });
623
+ i0.ɵɵelementStart(7, "button", 63);
624
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_16_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r14); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddRecordsDialog()); });
306
625
  i0.ɵɵtext(8, " Cancel ");
307
626
  i0.ɵɵelementEnd()()();
308
627
  } if (rf & 2) {
309
- const ctx_r2 = i0.ɵɵnextContext();
310
- i0.ɵɵproperty("Visible", true)("Title", "Add " + ((ctx_r2.listRecord == null ? null : ctx_r2.listRecord.Entity) || "Records") + " to List")("MinWidth", 500)("Width", 700)("Height", 650);
628
+ const ctx_r0 = i0.ɵɵnextContext();
629
+ i0.ɵɵproperty("Visible", true)("Title", "Add " + ((ctx_r0.listRecord == null ? null : ctx_r0.listRecord.Entity) || "Records") + " to List")("MinWidth", 500)("Width", 700)("Height", 650);
311
630
  i0.ɵɵadvance(2);
312
- i0.ɵɵconditional(ctx_r2.addDialogSaving ? 2 : 3);
631
+ i0.ɵɵconditional(ctx_r0.addDialogSaving ? 2 : 3);
313
632
  i0.ɵɵadvance(3);
314
- i0.ɵɵproperty("disabled", ctx_r2.addDialogSaving || ctx_r2.selectedAddableRecords.length === 0);
633
+ i0.ɵɵproperty("disabled", ctx_r0.addDialogSaving || ctx_r0.selectedAddableRecords.length === 0);
315
634
  i0.ɵɵadvance();
316
- i0.ɵɵtextInterpolate2(" Add ", ctx_r2.selectedAddableRecords.length > 0 ? ctx_r2.selectedAddableRecords.length : "", " Record", ctx_r2.selectedAddableRecords.length !== 1 ? "s" : "", " ");
635
+ i0.ɵɵtextInterpolate2(" Add ", ctx_r0.selectedAddableRecords.length > 0 ? ctx_r0.selectedAddableRecords.length : "", " Record", ctx_r0.selectedAddableRecords.length !== 1 ? "s" : "", " ");
317
636
  i0.ɵɵadvance();
318
- i0.ɵɵproperty("disabled", ctx_r2.addDialogSaving);
637
+ i0.ɵɵproperty("disabled", ctx_r0.addDialogSaving);
319
638
  } }
320
- function SingleListDetailComponent_Conditional_15_Conditional_2_Template(rf, ctx) { if (rf & 1) {
321
- i0.ɵɵelementStart(0, "div", 32);
322
- i0.ɵɵelement(1, "mj-loading", 68);
639
+ function SingleListDetailComponent_Conditional_17_For_25_Template(rf, ctx) { if (rf & 1) {
640
+ const _r21 = i0.ɵɵgetCurrentView();
641
+ i0.ɵɵelementStart(0, "label", 117)(1, "input", 121);
642
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_17_For_25_Template_input_ngModelChange_1_listener($event) { const f_r22 = i0.ɵɵrestoreView(_r21).$implicit; i0.ɵɵtwoWayBindingSet(f_r22.Selected, $event) || (f_r22.Selected = $event); return i0.ɵɵresetView($event); });
323
643
  i0.ɵɵelementEnd();
644
+ i0.ɵɵelementStart(2, "span");
645
+ i0.ɵɵtext(3);
646
+ i0.ɵɵelementEnd()();
647
+ } if (rf & 2) {
648
+ const f_r22 = ctx.$implicit;
649
+ i0.ɵɵadvance();
650
+ i0.ɵɵtwoWayProperty("ngModel", f_r22.Selected);
651
+ i0.ɵɵadvance(2);
652
+ i0.ɵɵtextInterpolate(f_r22.DisplayName);
324
653
  } }
325
- function SingleListDetailComponent_Conditional_15_Conditional_3_Template(rf, ctx) { if (rf & 1) {
326
- i0.ɵɵelementStart(0, "div", 32);
327
- i0.ɵɵelement(1, "mj-loading", 43)(2, "mj-progress-bar", 37);
654
+ function SingleListDetailComponent_Conditional_17_Conditional_35_Template(rf, ctx) { if (rf & 1) {
655
+ i0.ɵɵelement(0, "i", 48);
656
+ i0.ɵɵtext(1, " Exporting\u2026 ");
657
+ } }
658
+ function SingleListDetailComponent_Conditional_17_Conditional_36_Template(rf, ctx) { if (rf & 1) {
659
+ i0.ɵɵelement(0, "i", 122);
660
+ i0.ɵɵtext(1);
661
+ } if (rf & 2) {
662
+ const ctx_r0 = i0.ɵɵnextContext(2);
663
+ i0.ɵɵadvance();
664
+ i0.ɵɵtextInterpolate2(" Export ", ctx_r0.exportRecordCount, " Record", ctx_r0.exportRecordCount === 1 ? "" : "s", " ");
665
+ } }
666
+ function SingleListDetailComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
667
+ const _r20 = i0.ɵɵgetCurrentView();
668
+ i0.ɵɵelementStart(0, "mj-dialog", 59);
669
+ i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_17_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeExportDialog()); });
670
+ i0.ɵɵelementStart(1, "div", 105)(2, "label", 106);
671
+ i0.ɵɵtext(3, "Format");
672
+ i0.ɵɵelementEnd();
673
+ i0.ɵɵelementStart(4, "div", 107)(5, "label", 108);
674
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_label_click_5_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.exportFormat = "excel"); });
675
+ i0.ɵɵelementStart(6, "input", 109);
676
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_17_Template_input_ngModelChange_6_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.exportFormat, $event) || (ctx_r0.exportFormat = $event); return i0.ɵɵresetView($event); });
677
+ i0.ɵɵelementEnd();
678
+ i0.ɵɵelement(7, "i", 110);
679
+ i0.ɵɵelementStart(8, "span");
680
+ i0.ɵɵtext(9, "Excel (.xlsx)");
681
+ i0.ɵɵelementEnd()();
682
+ i0.ɵɵelementStart(10, "label", 108);
683
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_label_click_10_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.exportFormat = "csv"); });
684
+ i0.ɵɵelementStart(11, "input", 111);
685
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_17_Template_input_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.exportFormat, $event) || (ctx_r0.exportFormat = $event); return i0.ɵɵresetView($event); });
686
+ i0.ɵɵelementEnd();
687
+ i0.ɵɵelement(12, "i", 112);
688
+ i0.ɵɵelementStart(13, "span");
689
+ i0.ɵɵtext(14, "CSV");
690
+ i0.ɵɵelementEnd()();
691
+ i0.ɵɵelementStart(15, "label", 108);
692
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_label_click_15_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.exportFormat = "json"); });
693
+ i0.ɵɵelementStart(16, "input", 113);
694
+ i0.ɵɵtwoWayListener("ngModelChange", function SingleListDetailComponent_Conditional_17_Template_input_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.exportFormat, $event) || (ctx_r0.exportFormat = $event); return i0.ɵɵresetView($event); });
695
+ i0.ɵɵelementEnd();
696
+ i0.ɵɵelement(17, "i", 114);
697
+ i0.ɵɵelementStart(18, "span");
698
+ i0.ɵɵtext(19, "JSON");
699
+ i0.ɵɵelementEnd()()();
700
+ i0.ɵɵelement(20, "div", 115);
701
+ i0.ɵɵelementStart(21, "label", 106);
702
+ i0.ɵɵtext(22, "Columns to include");
703
+ i0.ɵɵelementEnd();
704
+ i0.ɵɵelementStart(23, "div", 116);
705
+ i0.ɵɵrepeaterCreate(24, SingleListDetailComponent_Conditional_17_For_25_Template, 4, 2, "label", 117, _forTrack2);
706
+ i0.ɵɵelementEnd();
707
+ i0.ɵɵelementStart(26, "div", 118)(27, "a", 119);
708
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_a_click_27_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); ctx_r0.selectAllExportFields(); return i0.ɵɵresetView($event.preventDefault()); });
709
+ i0.ɵɵtext(28, "Select All");
710
+ i0.ɵɵelementEnd();
711
+ i0.ɵɵelementStart(29, "a", 119);
712
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_a_click_29_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); ctx_r0.selectNoneExportFields(); return i0.ɵɵresetView($event.preventDefault()); });
713
+ i0.ɵɵtext(30, "Select None");
328
714
  i0.ɵɵelementEnd();
715
+ i0.ɵɵelementStart(31, "span", 120);
716
+ i0.ɵɵtext(32);
717
+ i0.ɵɵelementEnd()()();
718
+ i0.ɵɵelementStart(33, "mj-dialog-actions")(34, "button", 62);
719
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_button_click_34_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.executeExport()); });
720
+ i0.ɵɵconditionalCreate(35, SingleListDetailComponent_Conditional_17_Conditional_35_Template, 2, 0)(36, SingleListDetailComponent_Conditional_17_Conditional_36_Template, 2, 2);
721
+ i0.ɵɵelementEnd();
722
+ i0.ɵɵelementStart(37, "button", 63);
723
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_17_Template_button_click_37_listener() { i0.ɵɵrestoreView(_r20); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeExportDialog()); });
724
+ i0.ɵɵtext(38, "Cancel");
725
+ i0.ɵɵelementEnd()()();
329
726
  } if (rf & 2) {
330
- const ctx_r2 = i0.ɵɵnextContext(2);
727
+ const ctx_r0 = i0.ɵɵnextContext();
728
+ i0.ɵɵproperty("Visible", true)("Title", "Export " + ctx_r0.exportRecordCount + " Record" + (ctx_r0.exportRecordCount === 1 ? "" : "s"))("MinWidth", 520)("Width", 640)("Height", 640);
729
+ i0.ɵɵadvance(5);
730
+ i0.ɵɵclassProp("export-format-option--selected", ctx_r0.exportFormat === "excel");
731
+ i0.ɵɵadvance();
732
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.exportFormat);
733
+ i0.ɵɵadvance(4);
734
+ i0.ɵɵclassProp("export-format-option--selected", ctx_r0.exportFormat === "csv");
735
+ i0.ɵɵadvance();
736
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.exportFormat);
737
+ i0.ɵɵadvance(4);
738
+ i0.ɵɵclassProp("export-format-option--selected", ctx_r0.exportFormat === "json");
739
+ i0.ɵɵadvance();
740
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.exportFormat);
741
+ i0.ɵɵadvance(8);
742
+ i0.ɵɵrepeater(ctx_r0.exportFields);
743
+ i0.ɵɵadvance(8);
744
+ i0.ɵɵtextInterpolate2("", ctx_r0.selectedExportFieldCount, " of ", ctx_r0.exportFields.length, " selected");
331
745
  i0.ɵɵadvance(2);
332
- i0.ɵɵproperty("Value", ctx_r2.addFromViewProgressPercent);
746
+ i0.ɵɵproperty("disabled", ctx_r0.selectedExportFieldCount === 0 || ctx_r0.isExporting);
747
+ i0.ɵɵadvance();
748
+ i0.ɵɵconditional(ctx_r0.isExporting ? 35 : 36);
749
+ i0.ɵɵadvance(2);
750
+ i0.ɵɵproperty("disabled", ctx_r0.isExporting);
751
+ } }
752
+ function SingleListDetailComponent_Conditional_18_Conditional_2_Template(rf, ctx) { if (rf & 1) {
753
+ i0.ɵɵelementStart(0, "div", 61);
754
+ i0.ɵɵelement(1, "mj-loading", 124);
755
+ i0.ɵɵelementEnd();
756
+ } }
757
+ function SingleListDetailComponent_Conditional_18_Conditional_3_Template(rf, ctx) { if (rf & 1) {
758
+ i0.ɵɵelementStart(0, "div", 61);
759
+ i0.ɵɵelement(1, "mj-loading", 90)(2, "mj-progress-bar", 65);
760
+ i0.ɵɵelementEnd();
761
+ } if (rf & 2) {
762
+ const ctx_r0 = i0.ɵɵnextContext(2);
763
+ i0.ɵɵadvance(2);
764
+ i0.ɵɵproperty("Value", ctx_r0.addFromViewProgressPercent);
333
765
  } }
334
- function SingleListDetailComponent_Conditional_15_Conditional_4_Template(rf, ctx) { if (rf & 1) {
335
- i0.ɵɵelementStart(0, "div", 32);
336
- i0.ɵɵelement(1, "mj-loading", 69);
766
+ function SingleListDetailComponent_Conditional_18_Conditional_4_Template(rf, ctx) { if (rf & 1) {
767
+ i0.ɵɵelementStart(0, "div", 61);
768
+ i0.ɵɵelement(1, "mj-loading", 125);
337
769
  i0.ɵɵelementEnd();
338
770
  } }
339
- function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
340
- i0.ɵɵelementStart(0, "div", 51);
341
- i0.ɵɵelement(1, "span", 72);
771
+ function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
772
+ i0.ɵɵelementStart(0, "div", 72);
773
+ i0.ɵɵelement(1, "span", 127);
342
774
  i0.ɵɵelementStart(2, "p");
343
775
  i0.ɵɵtext(3, "No saved views found for this entity");
344
776
  i0.ɵɵelementEnd()();
345
777
  } }
346
- function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_For_1_Template(rf, ctx) { if (rf & 1) {
347
- const _r15 = i0.ɵɵgetCurrentView();
348
- i0.ɵɵelementStart(0, "div", 74);
349
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_For_1_Template_div_click_0_listener() { const view_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.toggleViewSelection(view_r16)); });
350
- i0.ɵɵelementStart(1, "input", 66);
351
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_For_1_Template_input_click_1_listener($event) { i0.ɵɵrestoreView(_r15); return i0.ɵɵresetView($event.stopPropagation()); })("change", function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_For_1_Template_input_change_1_listener() { const view_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.toggleViewSelection(view_r16)); });
778
+ function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_For_1_Template(rf, ctx) { if (rf & 1) {
779
+ const _r24 = i0.ɵɵgetCurrentView();
780
+ i0.ɵɵelementStart(0, "div", 129);
781
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_For_1_Template_div_click_0_listener() { const view_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleViewSelection(view_r25)); });
782
+ i0.ɵɵelementStart(1, "input", 104);
783
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_For_1_Template_input_click_1_listener($event) { i0.ɵɵrestoreView(_r24); return i0.ɵɵresetView($event.stopPropagation()); })("change", function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_For_1_Template_input_change_1_listener() { const view_r25 = i0.ɵɵrestoreView(_r24).$implicit; const ctx_r0 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r0.toggleViewSelection(view_r25)); });
352
784
  i0.ɵɵelementEnd();
353
- i0.ɵɵelement(2, "span", 75);
354
- i0.ɵɵelementStart(3, "span", 76);
785
+ i0.ɵɵelement(2, "span", 130);
786
+ i0.ɵɵelementStart(3, "span", 131);
355
787
  i0.ɵɵtext(4);
356
788
  i0.ɵɵelementEnd()();
357
789
  } if (rf & 2) {
358
- const view_r16 = ctx.$implicit;
359
- const ctx_r2 = i0.ɵɵnextContext(4);
360
- i0.ɵɵclassProp("selected", ctx_r2.isViewSelected(view_r16));
790
+ const view_r25 = ctx.$implicit;
791
+ const ctx_r0 = i0.ɵɵnextContext(4);
792
+ i0.ɵɵclassProp("selected", ctx_r0.isViewSelected(view_r25));
361
793
  i0.ɵɵadvance();
362
- i0.ɵɵproperty("checked", ctx_r2.isViewSelected(view_r16));
794
+ i0.ɵɵproperty("checked", ctx_r0.isViewSelected(view_r25));
363
795
  i0.ɵɵadvance(3);
364
- i0.ɵɵtextInterpolate(view_r16.Name);
796
+ i0.ɵɵtextInterpolate(view_r25.Name);
365
797
  } }
366
- function SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
367
- i0.ɵɵrepeaterCreate(0, SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_For_1_Template, 5, 4, "div", 73, _forTrack1);
798
+ function SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
799
+ i0.ɵɵrepeaterCreate(0, SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_For_1_Template, 5, 4, "div", 128, _forTrack1);
368
800
  } if (rf & 2) {
369
- const ctx_r2 = i0.ɵɵnextContext(3);
370
- i0.ɵɵrepeater(ctx_r2.userViews);
801
+ const ctx_r0 = i0.ɵɵnextContext(3);
802
+ i0.ɵɵrepeater(ctx_r0.userViews);
371
803
  } }
372
- function SingleListDetailComponent_Conditional_15_Conditional_5_Template(rf, ctx) { if (rf & 1) {
373
- i0.ɵɵelementStart(0, "p", 70);
804
+ function SingleListDetailComponent_Conditional_18_Conditional_5_Template(rf, ctx) { if (rf & 1) {
805
+ i0.ɵɵelementStart(0, "p", 66);
374
806
  i0.ɵɵtext(1, "Select views to add their records to this list:");
375
807
  i0.ɵɵelementEnd();
376
- i0.ɵɵelementStart(2, "div", 71);
377
- i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_3_Template, 4, 0, "div", 51)(4, SingleListDetailComponent_Conditional_15_Conditional_5_Conditional_4_Template, 2, 0);
808
+ i0.ɵɵelementStart(2, "div", 126);
809
+ i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_3_Template, 4, 0, "div", 72)(4, SingleListDetailComponent_Conditional_18_Conditional_5_Conditional_4_Template, 2, 0);
378
810
  i0.ɵɵelementEnd();
379
811
  } if (rf & 2) {
380
- const ctx_r2 = i0.ɵɵnextContext(2);
812
+ const ctx_r0 = i0.ɵɵnextContext(2);
381
813
  i0.ɵɵadvance(3);
382
- i0.ɵɵconditional(!ctx_r2.userViews || ctx_r2.userViews.length === 0 ? 3 : 4);
814
+ i0.ɵɵconditional(!ctx_r0.userViews || ctx_r0.userViews.length === 0 ? 3 : 4);
383
815
  } }
384
- function SingleListDetailComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
385
- const _r14 = i0.ɵɵgetCurrentView();
386
- i0.ɵɵelementStart(0, "mj-dialog", 67);
387
- i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_15_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeAddFromViewDialog()); });
388
- i0.ɵɵelementStart(1, "div", 31);
389
- i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_15_Conditional_2_Template, 2, 0, "div", 32)(3, SingleListDetailComponent_Conditional_15_Conditional_3_Template, 3, 1, "div", 32)(4, SingleListDetailComponent_Conditional_15_Conditional_4_Template, 2, 0, "div", 32)(5, SingleListDetailComponent_Conditional_15_Conditional_5_Template, 5, 1);
816
+ function SingleListDetailComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
817
+ const _r23 = i0.ɵɵgetCurrentView();
818
+ i0.ɵɵelementStart(0, "mj-dialog", 123);
819
+ i0.ɵɵlistener("Close", function SingleListDetailComponent_Conditional_18_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddFromViewDialog()); });
820
+ i0.ɵɵelementStart(1, "div", 84);
821
+ i0.ɵɵconditionalCreate(2, SingleListDetailComponent_Conditional_18_Conditional_2_Template, 2, 0, "div", 61)(3, SingleListDetailComponent_Conditional_18_Conditional_3_Template, 3, 1, "div", 61)(4, SingleListDetailComponent_Conditional_18_Conditional_4_Template, 2, 0, "div", 61)(5, SingleListDetailComponent_Conditional_18_Conditional_5_Template, 5, 1);
390
822
  i0.ɵɵelementEnd();
391
- i0.ɵɵelementStart(6, "mj-dialog-actions")(7, "button", 42);
392
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.confirmAddFromView()); });
823
+ i0.ɵɵelementStart(6, "mj-dialog-actions")(7, "button", 62);
824
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_18_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r23); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.confirmAddFromView()); });
393
825
  i0.ɵɵtext(8);
394
826
  i0.ɵɵelementEnd();
395
- i0.ɵɵelementStart(9, "button", 35);
396
- i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_15_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeAddFromViewDialog()); });
827
+ i0.ɵɵelementStart(9, "button", 63);
828
+ i0.ɵɵlistener("click", function SingleListDetailComponent_Conditional_18_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r23); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.closeAddFromViewDialog()); });
397
829
  i0.ɵɵtext(10, " Cancel ");
398
830
  i0.ɵɵelementEnd()()();
399
831
  } if (rf & 2) {
400
- const ctx_r2 = i0.ɵɵnextContext();
832
+ const ctx_r0 = i0.ɵɵnextContext();
401
833
  i0.ɵɵproperty("Visible", true)("MinWidth", 400)("Width", 600)("Height", 500);
402
834
  i0.ɵɵadvance(2);
403
- i0.ɵɵconditional(ctx_r2.showAddFromViewLoader && ctx_r2.fetchingRecordsToSave ? 2 : ctx_r2.showAddFromViewLoader && ctx_r2.addFromViewTotal > 0 ? 3 : ctx_r2.showAddFromViewLoader ? 4 : 5);
835
+ i0.ɵɵconditional(ctx_r0.showAddFromViewLoader && ctx_r0.fetchingRecordsToSave ? 2 : ctx_r0.showAddFromViewLoader && ctx_r0.addFromViewTotal > 0 ? 3 : ctx_r0.showAddFromViewLoader ? 4 : 5);
404
836
  i0.ɵɵadvance(5);
405
- i0.ɵɵproperty("disabled", ctx_r2.showAddFromViewLoader || ctx_r2.userViewsToAdd.length === 0);
837
+ i0.ɵɵproperty("disabled", ctx_r0.showAddFromViewLoader || ctx_r0.userViewsToAdd.length === 0);
406
838
  i0.ɵɵadvance();
407
- i0.ɵɵtextInterpolate2(" Add from ", ctx_r2.userViewsToAdd.length, " View", ctx_r2.userViewsToAdd.length !== 1 ? "s" : "", " ");
839
+ i0.ɵɵtextInterpolate2(" Add from ", ctx_r0.userViewsToAdd.length, " View", ctx_r0.userViewsToAdd.length !== 1 ? "s" : "", " ");
408
840
  i0.ɵɵadvance();
409
- i0.ɵɵproperty("disabled", ctx_r2.showAddFromViewLoader);
841
+ i0.ɵɵproperty("disabled", ctx_r0.showAddFromViewLoader);
410
842
  } }
411
843
  export class SingleListDetailComponent extends BaseAngularComponent {
412
844
  sharedService;
413
845
  cdr;
414
846
  elementRef;
847
+ exportService;
848
+ listSharingService;
415
849
  ListID = "";
850
+ /**
851
+ * Bumped on every list-membership mutation so the Usage stats sidebar
852
+ * re-queries member count / growth / last-activity. Without this nudge,
853
+ * those numbers drift from reality until a full page reload because the
854
+ * stats component otherwise only loads on init.
855
+ */
856
+ statsRefreshTrigger = 0;
857
+ bumpStatsRefresh() { this.statsRefreshTrigger++; }
416
858
  listDetailGrid;
417
859
  // List record
418
860
  listRecord = null;
419
861
  showLoader = false;
862
+ // Permission-level gating (Phase 2.8). Resolved lazily after the list
863
+ // loads. Capabilities is exposed to the template for `@if` gating; the
864
+ // server-side enforcement remains the source of truth — these flags
865
+ // are a UX convenience so users don't see buttons they'll be rejected on.
866
+ capabilities = CapabilitiesForLevel(null);
867
+ currentLevel = null;
868
+ // Lineage / refresh-from-source state. `sourceViewName` is loaded after
869
+ // listRecord so the lineage badge can show a friendly view name; the
870
+ // refresh-mode default falls back to the list's RefreshMode field but
871
+ // can be overridden per-user via localStorage (see `loadLastUsedMode`).
872
+ sourceViewName = null;
873
+ // Bulk-edit (Phase 5.2). Status, Move, Copy, Remove. Move flows through
874
+ // the delta-confirm dialog because it produces drops on the source list.
875
+ bulkStatus = '';
876
+ isApplyingBulkStatus = false;
877
+ // Move / Copy state (mockups 23, 24). The picker dialog lists candidate
878
+ // target lists scoped to the same entity. We load it lazily on first
879
+ // open and cache for the session — opening the picker twice in a row
880
+ // doesn't re-fetch unless the user explicitly hits "Refresh".
881
+ showMoveCopyDialog = false;
882
+ moveCopyMode = 'move';
883
+ moveCopyTargetSearch = '';
884
+ moveCopyTargetCandidates = [];
885
+ moveCopyTargetCandidatesLoading = false;
886
+ moveCopySelectedTarget = null;
887
+ isApplyingMoveCopy = false;
888
+ moveCopyProgress = 0;
889
+ moveCopyTotal = 0;
890
+ // Move delta-confirm. Built locally from the in-hand RecordIDs — no
891
+ // server round-trip needed since we already know exactly what will be
892
+ // added to the target and removed from the source. The drop-guard is
893
+ // enforced at confirm time (mode='move' + ack checkbox).
894
+ moveDeltaConfirmVisible = false;
895
+ moveDelta = null;
896
+ // Export picker (Phase 5.1, mockup 26). Opens before any export; lets
897
+ // the user pick format + which entity fields to include. Fields are
898
+ // resolved from EntityInfo on the loaded provider — no separate fetch.
899
+ showExportDialog = false;
900
+ exportFormat = 'excel';
901
+ exportFields = [];
902
+ exportRecordCount = 0;
903
+ isExporting = false;
904
+ refreshMode = 'Additive';
905
+ isPreviewingRefresh = false;
906
+ isApplyingRefresh = false;
907
+ refreshDelta = null;
908
+ refreshConfirmVisible = false;
420
909
  // Grid state
421
910
  selectedKeys = [];
422
911
  rowCount = 0;
@@ -452,6 +941,15 @@ export class SingleListDetailComponent extends BaseAngularComponent {
452
941
  userViewsToAdd = [];
453
942
  addFromViewProgress = 0;
454
943
  addFromViewTotal = 0;
944
+ /**
945
+ * Stored percent (0–100) for the progress bar. Backed instead of computed
946
+ * via getter because the original getter recomputed on every Angular CD
947
+ * read and the async save loop mutated addFromViewProgress between the
948
+ * initial check and dev-mode re-check — producing NG0100
949
+ * ExpressionChangedAfterItHasBeenCheckedError floods in the console.
950
+ * Updated via setAddFromViewProgress(...) at controlled points.
951
+ */
952
+ addFromViewProgressPercent = 0;
455
953
  fetchingRecordsToSave = false;
456
954
  // Dropdown button toggle state
457
955
  showAddDropdown = false;
@@ -478,19 +976,26 @@ export class SingleListDetailComponent extends BaseAngularComponent {
478
976
  }
479
977
  }
480
978
  }
481
- constructor(sharedService, cdr, elementRef) {
979
+ constructor(sharedService, cdr, elementRef, exportService, listSharingService) {
482
980
  super();
483
981
  this.sharedService = sharedService;
484
982
  this.cdr = cdr;
485
983
  this.elementRef = elementRef;
984
+ this.exportService = exportService;
985
+ this.listSharingService = listSharingService;
486
986
  // Debounce search input
487
987
  this.searchSubject
488
988
  .pipe(debounceTime(300))
489
989
  .subscribe((searchText) => this.searchRecords(searchText));
490
990
  }
491
- async ngOnInit() {
991
+ ngOnInit() {
492
992
  if (this.ListID) {
493
- await this.loadListRecord();
993
+ // Defer the load to a macrotask so the initial assignment of
994
+ // `listRecord` cannot land during Angular's dev-mode verify pass
995
+ // (NG0100). The first CD cycle renders with listRecord=null
996
+ // ("List"); the macrotask then loads, assigns, and fires its own
997
+ // detectChanges in a fresh cycle.
998
+ setTimeout(() => { void this.loadListRecord(); }, 0);
494
999
  }
495
1000
  }
496
1001
  /**
@@ -502,12 +1007,22 @@ export class SingleListDetailComponent extends BaseAngularComponent {
502
1007
  this.showLoader = true;
503
1008
  try {
504
1009
  const md = this.ProviderToUse;
505
- this.listRecord = await md.GetEntityObject("MJ: Lists");
506
- const loadResult = await this.listRecord.Load(this.ListID);
1010
+ // Build + load against a LOCAL handle. Only assign to
1011
+ // this.listRecord after Load() succeeds — otherwise Angular's
1012
+ // change detector sees a transiently-populated half-loaded
1013
+ // entity (Name=null) before Load fills it in, and the title
1014
+ // binding throws ExpressionChangedAfterItHasBeenCheckedError.
1015
+ const list = await md.GetEntityObject("MJ: Lists");
1016
+ const loadResult = await list.Load(this.ListID);
507
1017
  if (!loadResult) {
508
- LogError("Error loading list with ID " + this.ListID, undefined, this.listRecord.LatestResult);
1018
+ LogError("Error loading list with ID " + this.ListID, undefined, list.LatestResult);
509
1019
  this.listRecord = null;
510
1020
  }
1021
+ else {
1022
+ this.listRecord = list;
1023
+ await this.loadLineageContext();
1024
+ await this.loadCapabilities();
1025
+ }
511
1026
  }
512
1027
  catch (error) {
513
1028
  LogError("Error loading list", undefined, error);
@@ -518,6 +1033,167 @@ export class SingleListDetailComponent extends BaseAngularComponent {
518
1033
  this.cdr.detectChanges();
519
1034
  }
520
1035
  }
1036
+ /**
1037
+ * Load lineage context for the refresh-from-source UI:
1038
+ * - Resolve the source view's display name for the lineage badge.
1039
+ * - Initialize the refresh-mode dropdown from per-user last-used
1040
+ * preference, falling back to the list's RefreshMode field.
1041
+ * Silent on failure — the badge / refresh button just won't render
1042
+ * rather than blocking the rest of the detail view.
1043
+ */
1044
+ async loadLineageContext() {
1045
+ if (!this.listRecord?.SourceViewID) {
1046
+ this.sourceViewName = null;
1047
+ return;
1048
+ }
1049
+ this.refreshMode = this.loadLastUsedMode() ?? this.listRecord.RefreshMode;
1050
+ try {
1051
+ const view = await this.ProviderToUse.GetEntityObject('MJ: User Views');
1052
+ const loaded = await view.Load(this.listRecord.SourceViewID);
1053
+ this.sourceViewName = loaded ? view.Name : null;
1054
+ }
1055
+ catch (e) {
1056
+ LogError(`Failed to load source view name for list ${this.ListID}: ${e}`);
1057
+ this.sourceViewName = null;
1058
+ }
1059
+ }
1060
+ /**
1061
+ * Resolve the caller's permission level for this list (Owner / Edit /
1062
+ * View / null) and derive UI capability flags. Best-effort — if the
1063
+ * resolve fails we conservatively default to no-mutation (Viewer-like)
1064
+ * so we don't accidentally surface buttons the server will reject.
1065
+ */
1066
+ async loadCapabilities() {
1067
+ if (!this.listRecord) {
1068
+ this.capabilities = CapabilitiesForLevel(null);
1069
+ this.currentLevel = null;
1070
+ return;
1071
+ }
1072
+ try {
1073
+ const currentUserId = this.ProviderToUse.CurrentUser?.ID;
1074
+ if (!currentUserId) {
1075
+ this.capabilities = CapabilitiesForLevel('View');
1076
+ this.currentLevel = 'View';
1077
+ return;
1078
+ }
1079
+ // Fast path: the list's UserID is its owner. Owners always have full
1080
+ // capabilities and don't carry a Resource Permission row (ownership
1081
+ // is implicit), so the permission-row lookup below would return null
1082
+ // and incorrectly hide all edit/share/delete buttons. Mirrors the
1083
+ // owner short-circuit in the server-side ListSharing.ResolveEffectivePermission.
1084
+ if (UUIDsEqual(this.listRecord.UserID, currentUserId)) {
1085
+ this.currentLevel = 'Owner';
1086
+ this.capabilities = CapabilitiesForLevel('Owner');
1087
+ return;
1088
+ }
1089
+ // Non-owner: resolve via ListSharingService (GraphQL). Never instantiate
1090
+ // the server-side `ListSharing` class from a browser bundle.
1091
+ const level = (await this.listSharingService.getUserPermissionLevel(this.listRecord.ID, currentUserId));
1092
+ this.currentLevel = level;
1093
+ this.capabilities = CapabilitiesForLevel(level);
1094
+ }
1095
+ catch (e) {
1096
+ LogError(`loadCapabilities failed: ${e instanceof Error ? e.message : String(e)}`);
1097
+ this.capabilities = CapabilitiesForLevel('View');
1098
+ this.currentLevel = 'View';
1099
+ }
1100
+ }
1101
+ get hasLineage() {
1102
+ return !!this.listRecord?.SourceViewID;
1103
+ }
1104
+ loadLastUsedMode() {
1105
+ try {
1106
+ const stored = localStorage.getItem(`mj.lists.refreshMode.${this.ListID}`);
1107
+ if (stored === 'Additive' || stored === 'Sync')
1108
+ return stored;
1109
+ }
1110
+ catch {
1111
+ // localStorage may not be available (SSR, private mode) — fall through.
1112
+ }
1113
+ return null;
1114
+ }
1115
+ saveLastUsedMode(mode) {
1116
+ try {
1117
+ localStorage.setItem(`mj.lists.refreshMode.${this.ListID}`, mode);
1118
+ }
1119
+ catch {
1120
+ // ignore
1121
+ }
1122
+ }
1123
+ /**
1124
+ * Kick off a refresh-from-source preview. Builds the delta server-side
1125
+ * and opens the confirm dialog when it returns. The dialog enforces the
1126
+ * acknowledgement UX; the server enforces the actual drop guard.
1127
+ */
1128
+ async onRefreshFromSource() {
1129
+ if (!this.hasLineage || this.isPreviewingRefresh)
1130
+ return;
1131
+ this.isPreviewingRefresh = true;
1132
+ this.refreshDelta = null;
1133
+ this.cdr.detectChanges();
1134
+ try {
1135
+ const provider = this.ProviderToUse;
1136
+ const client = new GraphQLListsClient(provider);
1137
+ const delta = await client.PreviewListDelta({
1138
+ Target: this.ListID,
1139
+ Source: { kind: 'view', viewId: this.listRecord.SourceViewID },
1140
+ Mode: this.refreshMode,
1141
+ });
1142
+ this.refreshDelta = delta;
1143
+ this.refreshConfirmVisible = true;
1144
+ }
1145
+ catch (e) {
1146
+ const message = e instanceof Error ? e.message : String(e);
1147
+ this.sharedService.CreateSimpleNotification(`Refresh preview failed: ${message}`, 'error', 5000);
1148
+ }
1149
+ finally {
1150
+ this.isPreviewingRefresh = false;
1151
+ this.cdr.detectChanges();
1152
+ }
1153
+ }
1154
+ onRefreshConfirmCancel() {
1155
+ this.refreshConfirmVisible = false;
1156
+ this.refreshDelta = null;
1157
+ this.cdr.detectChanges();
1158
+ }
1159
+ async onRefreshConfirmCommit(deltaToken) {
1160
+ if (!this.refreshDelta)
1161
+ return;
1162
+ this.isApplyingRefresh = true;
1163
+ this.cdr.detectChanges();
1164
+ try {
1165
+ const provider = this.ProviderToUse;
1166
+ const client = new GraphQLListsClient(provider);
1167
+ const result = await client.ApplyListDelta({
1168
+ Delta: { ...this.refreshDelta, DeltaToken: deltaToken },
1169
+ ConfirmDrops: (this.refreshDelta.Counts.Remove ?? 0) > 0,
1170
+ });
1171
+ if (result.Success) {
1172
+ this.saveLastUsedMode(this.refreshMode);
1173
+ this.refreshConfirmVisible = false;
1174
+ this.refreshDelta = null;
1175
+ this.sharedService.CreateSimpleNotification(`Refresh applied: +${result.Counts?.Added ?? 0} / -${result.Counts?.Removed ?? 0}`, 'success', 3000);
1176
+ // Reload list (for LastRefreshedAt) + grid in parallel.
1177
+ await this.loadListRecord();
1178
+ this.refreshGrid();
1179
+ this.bumpStatsRefresh();
1180
+ }
1181
+ else {
1182
+ this.sharedService.CreateSimpleNotification(`Refresh failed: ${result.Message}`, 'error', 5000);
1183
+ }
1184
+ }
1185
+ catch (e) {
1186
+ const message = e instanceof Error ? e.message : String(e);
1187
+ this.sharedService.CreateSimpleNotification(`Refresh failed: ${message}`, 'error', 5000);
1188
+ }
1189
+ finally {
1190
+ this.isApplyingRefresh = false;
1191
+ this.cdr.detectChanges();
1192
+ }
1193
+ }
1194
+ onRefreshModeChange(mode) {
1195
+ this.refreshMode = mode;
1196
+ }
521
1197
  // ==========================================
522
1198
  // Grid Event Handlers
523
1199
  // ==========================================
@@ -550,16 +1226,154 @@ export class SingleListDetailComponent extends BaseAngularComponent {
550
1226
  get addProgressPercent() {
551
1227
  return this.addTotal > 0 ? Math.round((this.addProgress / this.addTotal) * 100) : 0;
552
1228
  }
553
- get addFromViewProgressPercent() {
554
- return this.addFromViewTotal > 0 ? Math.round((this.addFromViewProgress / this.addFromViewTotal) * 100) : 0;
1229
+ /** Update progress + recompute the stored percent atomically. Call this
1230
+ * from inside the save loop so the bound value is set in lockstep with
1231
+ * the underlying counter (avoids NG0100). */
1232
+ setAddFromViewProgress(progress) {
1233
+ this.addFromViewProgress = progress;
1234
+ this.addFromViewProgressPercent = this.addFromViewTotal > 0
1235
+ ? Math.round((progress / this.addFromViewTotal) * 100)
1236
+ : 0;
555
1237
  }
556
1238
  onRefreshClick() {
557
1239
  this.refreshGrid();
558
1240
  }
559
1241
  onExportClick() {
560
- // Trigger export on the underlying grid
561
- if (this.listDetailGrid) {
562
- this.listDetailGrid.export();
1242
+ this.openExportDialog();
1243
+ }
1244
+ /**
1245
+ * Open the format + column picker (mockup 26). Resolves the candidate
1246
+ * field list from EntityInfo on the loaded provider — no extra
1247
+ * RunView. Default selection is every non-virtual entity field, which
1248
+ * matches what the underlying grid's "export all" path produced.
1249
+ */
1250
+ openExportDialog() {
1251
+ if (!this.listRecord) {
1252
+ this.sharedService.CreateSimpleNotification('Load a list first before exporting.', 'info', 3000);
1253
+ return;
1254
+ }
1255
+ const md = this.ProviderToUse;
1256
+ const entityInfo = md.EntityByID(this.listRecord.EntityID);
1257
+ if (!entityInfo) {
1258
+ this.sharedService.CreateSimpleNotification(`Entity for this list not found in metadata.`, 'error', 4000);
1259
+ return;
1260
+ }
1261
+ if (entityInfo.PrimaryKeys.length !== 1) {
1262
+ this.sharedService.CreateSimpleNotification(`Composite-PK entities ('${entityInfo.Name}') aren't yet supported for List export.`, 'warning', 5000);
1263
+ return;
1264
+ }
1265
+ this.exportFields = entityInfo.Fields
1266
+ .filter((f) => f.IsVirtual !== true)
1267
+ .map((f) => ({
1268
+ Name: f.Name,
1269
+ DisplayName: f.DisplayName || f.Name,
1270
+ Selected: true,
1271
+ }));
1272
+ this.exportRecordCount = this.rowCount;
1273
+ this.exportFormat = 'excel';
1274
+ this.showExportDialog = true;
1275
+ this.cdr.detectChanges();
1276
+ }
1277
+ closeExportDialog() {
1278
+ this.showExportDialog = false;
1279
+ this.cdr.detectChanges();
1280
+ }
1281
+ selectAllExportFields() {
1282
+ for (const f of this.exportFields)
1283
+ f.Selected = true;
1284
+ }
1285
+ selectNoneExportFields() {
1286
+ for (const f of this.exportFields)
1287
+ f.Selected = false;
1288
+ }
1289
+ get selectedExportFieldCount() {
1290
+ return this.exportFields.filter((f) => f.Selected).length;
1291
+ }
1292
+ /**
1293
+ * Run the export with the user's chosen format + columns. Resolves
1294
+ * the list's member RecordIDs from the in-memory grid when possible
1295
+ * (avoids an extra RunView), then bulk-loads the underlying entity
1296
+ * rows restricted to the chosen Fields. Output is projected to
1297
+ * exactly the user's selected columns + ordering.
1298
+ */
1299
+ async executeExport() {
1300
+ if (!this.listRecord)
1301
+ return;
1302
+ const selectedFields = this.exportFields.filter((f) => f.Selected).map((f) => f.Name);
1303
+ if (selectedFields.length === 0)
1304
+ return;
1305
+ this.isExporting = true;
1306
+ this.cdr.detectChanges();
1307
+ try {
1308
+ const md = this.ProviderToUse;
1309
+ const entityInfo = md.EntityByID(this.listRecord.EntityID);
1310
+ const pk = entityInfo.PrimaryKeys[0].Name;
1311
+ // Fetch the list's member record IDs. The grid only holds the
1312
+ // current page, so we hit MJ: List Details directly to get the
1313
+ // full set — same single-PK assumption guarded at dialog open.
1314
+ const rv = RunView.FromMetadataProvider(md);
1315
+ const memberResult = await rv.RunView({
1316
+ EntityName: 'MJ: List Details',
1317
+ ExtraFilter: `ListID='${this.listRecord.ID}'`,
1318
+ Fields: ['RecordID'],
1319
+ ResultType: 'simple',
1320
+ });
1321
+ if (!memberResult.Success) {
1322
+ this.sharedService.CreateSimpleNotification(`Export failed loading members: ${memberResult.ErrorMessage}`, 'error', 5000);
1323
+ return;
1324
+ }
1325
+ const recordIds = (memberResult.Results ?? []).map((r) => String(r.RecordID));
1326
+ if (recordIds.length === 0) {
1327
+ this.sharedService.CreateSimpleNotification('List is empty — nothing to export.', 'info', 3000);
1328
+ this.showExportDialog = false;
1329
+ return;
1330
+ }
1331
+ // Pull underlying entity rows restricted to the chosen fields.
1332
+ // Always include the PK so the projection round-trips cleanly.
1333
+ const fieldsForQuery = Array.from(new Set([pk, ...selectedFields]));
1334
+ const escaped = recordIds.map((id) => `'${id.replace(/'/g, "''")}'`).join(',');
1335
+ const rowResult = await rv.RunView({
1336
+ EntityName: entityInfo.Name,
1337
+ ExtraFilter: `${pk} IN (${escaped})`,
1338
+ Fields: fieldsForQuery,
1339
+ ResultType: 'simple',
1340
+ });
1341
+ if (!rowResult.Success) {
1342
+ this.sharedService.CreateSimpleNotification(`Export failed loading rows: ${rowResult.ErrorMessage}`, 'error', 5000);
1343
+ return;
1344
+ }
1345
+ // Project rows to exactly the columns + ordering the user picked.
1346
+ const rows = (rowResult.Results ?? []).map((row) => {
1347
+ const projected = {};
1348
+ for (const f of selectedFields)
1349
+ projected[f] = row[f];
1350
+ return projected;
1351
+ });
1352
+ const dateStamp = new Date().toISOString().slice(0, 10);
1353
+ const safeName = (this.listRecord.Name || 'list').replace(/[^a-z0-9_-]+/gi, '_');
1354
+ const ext = this.exportFormat === 'excel' ? 'xlsx' : this.exportFormat;
1355
+ const fileName = `${safeName}-${dateStamp}.${ext}`;
1356
+ const exportResult = this.exportFormat === 'excel'
1357
+ ? await this.exportService.toExcel(rows, { fileName, includeHeaders: true })
1358
+ : this.exportFormat === 'csv'
1359
+ ? await this.exportService.toCSV(rows, { fileName, includeHeaders: true })
1360
+ : await this.exportService.toJSON(rows, { fileName });
1361
+ if (exportResult.success) {
1362
+ this.exportService.downloadResult(exportResult);
1363
+ this.sharedService.CreateSimpleNotification(`Exported ${rows.length} record(s)`, 'success', 3000);
1364
+ this.showExportDialog = false;
1365
+ }
1366
+ else {
1367
+ this.sharedService.CreateSimpleNotification('Export failed', 'error', 5000);
1368
+ }
1369
+ }
1370
+ catch (e) {
1371
+ const message = e instanceof Error ? e.message : String(e);
1372
+ this.sharedService.CreateSimpleNotification(`Export error: ${message}`, 'error', 5000);
1373
+ }
1374
+ finally {
1375
+ this.isExporting = false;
1376
+ this.cdr.detectChanges();
563
1377
  }
564
1378
  }
565
1379
  toggleAddDropdown() {
@@ -572,6 +1386,360 @@ export class SingleListDetailComponent extends BaseAngularComponent {
572
1386
  }
573
1387
  }
574
1388
  // ==========================================
1389
+ /**
1390
+ * Apply the chosen status to all selected list-detail rows. Re-uses
1391
+ * the existing extract-record-id-from-composite-key logic to map
1392
+ * `selectedKeys` to the actual `MJ: List Detail.RecordID` values.
1393
+ */
1394
+ async applyBulkStatus() {
1395
+ if (!this.listRecord || this.selectedKeys.length === 0 || !this.bulkStatus)
1396
+ return;
1397
+ this.isApplyingBulkStatus = true;
1398
+ this.cdr.detectChanges();
1399
+ try {
1400
+ const md = this.ProviderToUse;
1401
+ const rv = RunView.FromMetadataProvider(md);
1402
+ const entityInfo = md.EntityByID(this.listRecord.EntityID);
1403
+ const recordIds = this.selectedKeys.map((key) => {
1404
+ if (entityInfo && entityInfo.PrimaryKeys.length === 1) {
1405
+ const ck = new CompositeKey();
1406
+ ck.LoadFromConcatenatedString(key);
1407
+ return ck.KeyValuePairs[0]?.Value || key;
1408
+ }
1409
+ return key;
1410
+ });
1411
+ const filter = `ListID='${this.listRecord.ID}' AND RecordID IN (${recordIds.map((id) => `'${String(id).replace(/'/g, "''")}'`).join(',')})`;
1412
+ // Two-step: fetch just the IDs via a 'simple' RunView, then load each
1413
+ // entity through GetEntityObject(..., CurrentUser) so the entity is
1414
+ // born with the user context that Save() requires. RunView with
1415
+ // 'entity_object' returns entities WITHOUT a CurrentUser bound — fine
1416
+ // for read-only use, broken for Save (`ContextCurrentUser cannot be
1417
+ // null`).
1418
+ const idResult = await rv.RunView({
1419
+ EntityName: 'MJ: List Details',
1420
+ ExtraFilter: filter,
1421
+ Fields: ['ID'],
1422
+ ResultType: 'simple',
1423
+ });
1424
+ if (!idResult.Success) {
1425
+ this.sharedService.CreateSimpleNotification(`Failed to load list details: ${idResult.ErrorMessage}`, 'error', 4000);
1426
+ return;
1427
+ }
1428
+ let updated = 0;
1429
+ let failed = 0;
1430
+ const failureMessages = [];
1431
+ for (const row of idResult.Results ?? []) {
1432
+ const detail = await md.GetEntityObject('MJ: List Details', md.CurrentUser);
1433
+ const loaded = await detail.Load(row.ID);
1434
+ if (!loaded) {
1435
+ failed++;
1436
+ const reason = detail.LatestResult?.CompleteMessage ?? 'load failed';
1437
+ if (failureMessages.length < 3)
1438
+ failureMessages.push(reason);
1439
+ continue;
1440
+ }
1441
+ detail.Status = this.bulkStatus;
1442
+ const ok = await detail.Save();
1443
+ if (ok) {
1444
+ updated++;
1445
+ }
1446
+ else {
1447
+ failed++;
1448
+ const reason = detail.LatestResult?.CompleteMessage ?? 'unknown error';
1449
+ if (failureMessages.length < 3)
1450
+ failureMessages.push(reason);
1451
+ LogError(`Bulk status update failed for List Detail ${row.ID}: ${reason}`);
1452
+ }
1453
+ }
1454
+ this.sharedService.CreateSimpleNotification(failed === 0
1455
+ ? `Updated ${updated} item(s) to '${this.bulkStatus}'`
1456
+ : `Updated ${updated}, ${failed} failed: ${failureMessages.join(' | ')}`, failed === 0 ? 'success' : 'warning', failed === 0 ? 3000 : 8000);
1457
+ this.bulkStatus = '';
1458
+ // Defer the grid refresh to the next microtask — see comment in
1459
+ // confirmRemoveFromList for why running it synchronously here
1460
+ // triggers NG0100 and silently breaks the UI refresh.
1461
+ await Promise.resolve();
1462
+ this.refreshGrid();
1463
+ this.bumpStatsRefresh();
1464
+ }
1465
+ catch (e) {
1466
+ const message = e instanceof Error ? e.message : String(e);
1467
+ this.sharedService.CreateSimpleNotification(`Bulk update failed: ${message}`, 'error', 5000);
1468
+ }
1469
+ finally {
1470
+ this.isApplyingBulkStatus = false;
1471
+ this.cdr.detectChanges();
1472
+ }
1473
+ }
1474
+ // ==========================================
1475
+ // Bulk Move / Copy (mockups 23, 24)
1476
+ //
1477
+ // Move = insert into target + delete from source (drops on source).
1478
+ // Copy = insert into target only (additive — no drops).
1479
+ //
1480
+ // The drop-guard for Move is enforced by routing through the local
1481
+ // delta-confirm dialog: the user must ack the removal before the
1482
+ // mutation runs. We build a synthetic ListDelta locally because we
1483
+ // already know the exact ToAdd / ToRemove sets — no server round-trip
1484
+ // needed for the preview. Apply step uses direct entity Save/Delete
1485
+ // inside a single TransactionGroup (same pattern as Remove).
1486
+ // ==========================================
1487
+ openMoveDialog() { this.openMoveCopyDialog('move'); }
1488
+ openCopyDialog() { this.openMoveCopyDialog('copy'); }
1489
+ openMoveCopyDialog(mode) {
1490
+ if (!this.listRecord || this.selectedKeys.length === 0) {
1491
+ this.sharedService.CreateSimpleNotification('Please select records first', 'warning', 2500);
1492
+ return;
1493
+ }
1494
+ this.moveCopyMode = mode;
1495
+ this.moveCopySelectedTarget = null;
1496
+ this.moveCopyTargetSearch = '';
1497
+ this.showMoveCopyDialog = true;
1498
+ // Load candidates once per dialog open. We don't keep them in
1499
+ // permanent component state because the user could create/delete
1500
+ // lists between opens, and the target picker isn't visible often
1501
+ // enough to justify long-lived caching.
1502
+ void this.loadMoveCopyTargets();
1503
+ this.cdr.detectChanges();
1504
+ }
1505
+ closeMoveCopyDialog() {
1506
+ this.showMoveCopyDialog = false;
1507
+ this.moveCopyTargetCandidates = [];
1508
+ this.moveCopySelectedTarget = null;
1509
+ this.cdr.detectChanges();
1510
+ }
1511
+ selectMoveCopyTarget(target) {
1512
+ this.moveCopySelectedTarget = target;
1513
+ }
1514
+ get filteredMoveCopyTargets() {
1515
+ const term = this.moveCopyTargetSearch.trim().toLowerCase();
1516
+ if (!term)
1517
+ return this.moveCopyTargetCandidates;
1518
+ return this.moveCopyTargetCandidates.filter((l) => l.Name.toLowerCase().includes(term) ||
1519
+ (l.Description?.toLowerCase().includes(term) ?? false));
1520
+ }
1521
+ get moveCopyProgressPercent() {
1522
+ return this.moveCopyTotal > 0 ? Math.round((this.moveCopyProgress / this.moveCopyTotal) * 100) : 0;
1523
+ }
1524
+ /** Load candidate target lists — same Entity, owned by or shared with
1525
+ * the current user, excluding the list we're standing on. One RunView
1526
+ * on open; results stay in memory until the dialog closes. */
1527
+ async loadMoveCopyTargets() {
1528
+ if (!this.listRecord)
1529
+ return;
1530
+ this.moveCopyTargetCandidatesLoading = true;
1531
+ this.cdr.detectChanges();
1532
+ try {
1533
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
1534
+ // Filter to same EntityID + exclude the current list. UserID filter
1535
+ // would over-restrict (Shared-With-Me lists should be valid targets
1536
+ // when the user has Edit there); the server enforces the real
1537
+ // permission on the per-row Save, so listing extra entries is fine.
1538
+ const filter = `EntityID='${this.listRecord.EntityID}' AND ID<>'${this.listRecord.ID}'`;
1539
+ const result = await rv.RunView({
1540
+ EntityName: 'MJ: Lists',
1541
+ ExtraFilter: filter,
1542
+ OrderBy: 'Name',
1543
+ ResultType: 'simple',
1544
+ MaxRows: 500,
1545
+ });
1546
+ if (result.Success) {
1547
+ this.moveCopyTargetCandidates = (result.Results ?? []);
1548
+ }
1549
+ else {
1550
+ this.moveCopyTargetCandidates = [];
1551
+ this.sharedService.CreateSimpleNotification(`Failed to load target lists: ${result.ErrorMessage}`, 'error', 4000);
1552
+ }
1553
+ }
1554
+ catch (e) {
1555
+ this.moveCopyTargetCandidates = [];
1556
+ const message = e instanceof Error ? e.message : String(e);
1557
+ this.sharedService.CreateSimpleNotification(`Failed to load target lists: ${message}`, 'error', 4000);
1558
+ }
1559
+ finally {
1560
+ this.moveCopyTargetCandidatesLoading = false;
1561
+ this.cdr.detectChanges();
1562
+ }
1563
+ }
1564
+ /**
1565
+ * "Continue" / "Copy" click in the target picker. For Copy we apply
1566
+ * immediately. For Move we build a local Delta and show the confirm
1567
+ * dialog — the actual mutation fires from onMoveConfirmCommit().
1568
+ */
1569
+ async confirmMoveCopy() {
1570
+ if (!this.listRecord || !this.moveCopySelectedTarget || this.selectedKeys.length === 0)
1571
+ return;
1572
+ if (this.moveCopyMode === 'copy') {
1573
+ await this.applyMoveCopy(false);
1574
+ return;
1575
+ }
1576
+ // Move: show delta-confirm so the user explicitly acks the source-side drop.
1577
+ const recordIds = this.extractSelectedRecordIds();
1578
+ this.moveDelta = this.buildMoveDelta(recordIds);
1579
+ this.showMoveCopyDialog = false;
1580
+ this.moveDeltaConfirmVisible = true;
1581
+ this.cdr.detectChanges();
1582
+ }
1583
+ onMoveConfirmCancel() {
1584
+ this.moveDeltaConfirmVisible = false;
1585
+ this.moveDelta = null;
1586
+ // Re-open the target picker so the user can change their mind without
1587
+ // losing their selection.
1588
+ this.showMoveCopyDialog = true;
1589
+ this.cdr.detectChanges();
1590
+ }
1591
+ async onMoveConfirmCommit(_deltaToken) {
1592
+ this.moveDeltaConfirmVisible = false;
1593
+ this.cdr.detectChanges();
1594
+ await this.applyMoveCopy(true);
1595
+ }
1596
+ /**
1597
+ * Pull RecordIDs out of selectedKeys. selectedKeys arrive from the
1598
+ * grid in concatenated-key format ("ID|<value>"). For single-PK entities
1599
+ * MJ: List Details stores the raw value; for composite-PK entities it
1600
+ * stores the full concatenated string. We normalize based on entity
1601
+ * metadata — same logic as confirmRemoveFromList.
1602
+ */
1603
+ extractSelectedRecordIds() {
1604
+ const md = this.ProviderToUse;
1605
+ const entityInfo = this.listRecord ? md.EntityByID(this.listRecord.EntityID) : null;
1606
+ return this.selectedKeys.map((key) => {
1607
+ if (entityInfo && entityInfo.PrimaryKeys.length === 1) {
1608
+ const ck = new CompositeKey();
1609
+ ck.LoadFromConcatenatedString(key);
1610
+ return String(ck.KeyValuePairs[0]?.Value ?? key);
1611
+ }
1612
+ return key;
1613
+ });
1614
+ }
1615
+ /**
1616
+ * Build a synthetic ListDelta for the Move-confirm dialog. Token is
1617
+ * a sentinel — we never call server-side ApplyDelta for this flow,
1618
+ * the mutations run client-side inside a transaction group. The
1619
+ * delta-confirm component only reads counts + ToAdd/ToRemove + Warnings;
1620
+ * the token round-trips through the (Confirm) emit but is unused.
1621
+ */
1622
+ buildMoveDelta(recordIds) {
1623
+ const removeCount = recordIds.length;
1624
+ return {
1625
+ TargetListId: this.listRecord.ID,
1626
+ EntityName: this.listRecord.Entity ?? '',
1627
+ ToAdd: [],
1628
+ ToRemove: recordIds,
1629
+ Unchanged: [],
1630
+ Counts: {
1631
+ Add: 0,
1632
+ Remove: removeCount,
1633
+ Unchanged: 0,
1634
+ SourceTotal: 0,
1635
+ TargetTotal: this.rowCount,
1636
+ },
1637
+ Warnings: [{
1638
+ Code: 'WILL_REMOVE_RECORDS',
1639
+ Message: `${removeCount} record(s) will be removed from "${this.listRecord.Name}" as part of the move`,
1640
+ Details: { Count: removeCount },
1641
+ }],
1642
+ // Sentinel — client-side flow doesn't round-trip this.
1643
+ DeltaToken: 'client-move-delta',
1644
+ };
1645
+ }
1646
+ /**
1647
+ * Execute the move/copy. Insert all records into the target, and for
1648
+ * Move also delete the matching MJ: List Details from the source. All
1649
+ * mutations run in a single TransactionGroup so partial failures don't
1650
+ * leave records duplicated in both lists.
1651
+ */
1652
+ async applyMoveCopy(isMove) {
1653
+ if (!this.listRecord || !this.moveCopySelectedTarget)
1654
+ return;
1655
+ const source = this.listRecord;
1656
+ const target = this.moveCopySelectedTarget;
1657
+ const recordIds = this.extractSelectedRecordIds();
1658
+ if (recordIds.length === 0)
1659
+ return;
1660
+ this.isApplyingMoveCopy = true;
1661
+ this.moveCopyTotal = recordIds.length;
1662
+ this.moveCopyProgress = 0;
1663
+ this.cdr.detectChanges();
1664
+ const md = this.ProviderToUse;
1665
+ const rv = RunView.FromMetadataProvider(md);
1666
+ try {
1667
+ // Dedupe against the target: skip records already present so a
1668
+ // partially-completed previous run can be re-tried cleanly.
1669
+ const filterIds = recordIds.map((id) => `'${String(id).replace(/'/g, "''")}'`).join(',');
1670
+ const existingTarget = await rv.RunView({
1671
+ EntityName: 'MJ: List Details',
1672
+ ExtraFilter: `ListID='${target.ID}' AND RecordID IN (${filterIds})`,
1673
+ Fields: ['RecordID'],
1674
+ ResultType: 'simple',
1675
+ });
1676
+ const alreadyInTarget = new Set((existingTarget.Results ?? []).map((r) => String(r.RecordID)));
1677
+ const toAdd = recordIds.filter((id) => !alreadyInTarget.has(id));
1678
+ // For Move, look up the source-side ListDetail rows to delete.
1679
+ let sourceRows = [];
1680
+ if (isMove) {
1681
+ const lookup = await rv.RunView({
1682
+ EntityName: 'MJ: List Details',
1683
+ ExtraFilter: `ListID='${source.ID}' AND RecordID IN (${filterIds})`,
1684
+ ResultType: 'entity_object',
1685
+ });
1686
+ if (!lookup.Success) {
1687
+ throw new Error(`Failed to load source rows: ${lookup.ErrorMessage}`);
1688
+ }
1689
+ sourceRows = lookup.Results ?? [];
1690
+ }
1691
+ const tg = await md.CreateTransactionGroup();
1692
+ // Queue inserts into target.
1693
+ for (const recordId of toAdd) {
1694
+ const newDetail = await md.GetEntityObject('MJ: List Details', md.CurrentUser);
1695
+ newDetail.NewRecord();
1696
+ newDetail.ListID = target.ID;
1697
+ newDetail.RecordID = recordId;
1698
+ newDetail.Sequence = 0;
1699
+ newDetail.TransactionGroup = tg;
1700
+ await newDetail.Save();
1701
+ }
1702
+ // Queue source-side deletes for Move only.
1703
+ if (isMove) {
1704
+ for (const row of sourceRows) {
1705
+ row.TransactionGroup = tg;
1706
+ await row.Delete();
1707
+ }
1708
+ }
1709
+ const ok = await tg.Submit();
1710
+ this.moveCopyProgress = this.moveCopyTotal;
1711
+ if (!ok) {
1712
+ this.sharedService.CreateSimpleNotification(`${isMove ? 'Move' : 'Copy'} partially failed — some changes may not have applied`, 'error', 5000);
1713
+ return;
1714
+ }
1715
+ const skippedNote = alreadyInTarget.size > 0
1716
+ ? ` (${alreadyInTarget.size} already in target — skipped)`
1717
+ : '';
1718
+ this.sharedService.CreateSimpleNotification(`${isMove ? 'Moved' : 'Copied'} ${toAdd.length} record(s) to "${target.Name}"${skippedNote}`, 'success', 3000);
1719
+ // Same NG0100 pattern as confirmRemoveFromList — defer cleanup +
1720
+ // refresh by a microtask so the dialog/visibility flips happen in
1721
+ // a fresh change-detection cycle.
1722
+ await Promise.resolve();
1723
+ this.closeMoveCopyDialog();
1724
+ this.moveDelta = null;
1725
+ if (isMove) {
1726
+ this.listDetailGrid?.clearSelection();
1727
+ this.refreshGrid();
1728
+ this.bumpStatsRefresh();
1729
+ }
1730
+ this.cdr.detectChanges();
1731
+ }
1732
+ catch (e) {
1733
+ const message = e instanceof Error ? e.message : String(e);
1734
+ LogError(`Move/Copy failed: ${message}`);
1735
+ this.sharedService.CreateSimpleNotification(`${isMove ? 'Move' : 'Copy'} failed: ${message}`, 'error', 5000);
1736
+ }
1737
+ finally {
1738
+ this.isApplyingMoveCopy = false;
1739
+ this.cdr.detectChanges();
1740
+ }
1741
+ }
1742
+ // ==========================================
575
1743
  // Remove from List Dialog
576
1744
  // ==========================================
577
1745
  openRemoveDialog() {
@@ -635,9 +1803,18 @@ export class SingleListDetailComponent extends BaseAngularComponent {
635
1803
  if (success) {
636
1804
  this.removeProgress = this.removeTotal;
637
1805
  this.sharedService.CreateSimpleNotification(`Removed ${listDetails.length} record${listDetails.length !== 1 ? 's' : ''} from list`, 'success', 2500);
1806
+ // Defer cleanup + refresh to the next microtask. Running these
1807
+ // synchronously inside the current change-detection cycle
1808
+ // triggers NG0100 (`@if (showRemoveDialog)` flips false while
1809
+ // children are still being checked), which leaves the grid in a
1810
+ // stale state — the deletion succeeds server-side but the UI
1811
+ // doesn't re-fetch until the user navigates away and back.
1812
+ await Promise.resolve();
638
1813
  this.closeRemoveDialog();
639
1814
  this.listDetailGrid?.clearSelection();
640
1815
  this.refreshGrid();
1816
+ this.bumpStatsRefresh();
1817
+ this.cdr.detectChanges();
641
1818
  }
642
1819
  else {
643
1820
  LogError("Error removing records from list");
@@ -779,8 +1956,13 @@ export class SingleListDetailComponent extends BaseAngularComponent {
779
1956
  if (success) {
780
1957
  this.addProgress = this.addTotal;
781
1958
  this.sharedService.CreateSimpleNotification(`Added ${recordsToAdd.length} record${recordsToAdd.length !== 1 ? 's' : ''} to list`, 'success', 2500);
1959
+ // Defer dialog close + grid refresh to the next microtask. See
1960
+ // confirmRemoveFromList for the NG0100 background.
1961
+ await Promise.resolve();
782
1962
  this.closeAddRecordsDialog();
783
1963
  this.refreshGrid();
1964
+ this.bumpStatsRefresh();
1965
+ this.cdr.detectChanges();
784
1966
  }
785
1967
  else {
786
1968
  LogError("Error adding records to list");
@@ -802,8 +1984,8 @@ export class SingleListDetailComponent extends BaseAngularComponent {
802
1984
  this.showAddFromViewDialog = false;
803
1985
  this.userViewsToAdd = [];
804
1986
  this.showAddFromViewLoader = false;
805
- this.addFromViewProgress = 0;
806
1987
  this.addFromViewTotal = 0;
1988
+ this.setAddFromViewProgress(0);
807
1989
  }
808
1990
  async loadEntityViews() {
809
1991
  if (!this.listRecord || !this.listRecord.Entity)
@@ -862,7 +2044,7 @@ export class SingleListDetailComponent extends BaseAngularComponent {
862
2044
  await this.loadExistingListDetailIds();
863
2045
  const recordsToAdd = [...recordIdSet].filter(id => !this.existingListDetailIds.has(id));
864
2046
  this.addFromViewTotal = recordsToAdd.length;
865
- this.addFromViewProgress = 0;
2047
+ this.setAddFromViewProgress(0);
866
2048
  this.fetchingRecordsToSave = false;
867
2049
  this.cdr.detectChanges();
868
2050
  const progressPerRecord = 0.8 / Math.max(recordsToAdd.length, 1); // 80% for individual saves
@@ -887,17 +2069,28 @@ export class SingleListDetailComponent extends BaseAngularComponent {
887
2069
  message: listDetail.LatestResult?.CompleteMessage
888
2070
  });
889
2071
  }
890
- // Update progress (0-80%)
891
- this.addFromViewProgress = Math.round((i + 1) * progressPerRecord * this.addFromViewTotal);
2072
+ // Update progress (0-80%) via the helper so both the counter and the
2073
+ // bound percent move in lockstep, then detectChanges() to close the
2074
+ // CD cycle on this iteration. Without detectChanges() the next await
2075
+ // can yield in the middle of a cycle and Angular's dev-mode re-check
2076
+ // catches the percent changing → NG0100 flood.
2077
+ this.setAddFromViewProgress(Math.round((i + 1) * progressPerRecord * this.addFromViewTotal));
2078
+ this.cdr.detectChanges();
892
2079
  }
893
2080
  // Show 80% complete before submit
894
- this.addFromViewProgress = Math.round(this.addFromViewTotal * 0.8);
2081
+ this.setAddFromViewProgress(Math.round(this.addFromViewTotal * 0.8));
2082
+ this.cdr.detectChanges();
895
2083
  const success = await tg.Submit();
896
2084
  if (success) {
897
- this.addFromViewProgress = this.addFromViewTotal;
2085
+ this.setAddFromViewProgress(this.addFromViewTotal);
898
2086
  this.sharedService.CreateSimpleNotification(`Added ${recordsToAdd.length} record${recordsToAdd.length !== 1 ? 's' : ''} to list`, 'success', 2500);
2087
+ // Defer dialog close + grid refresh to the next microtask. See
2088
+ // confirmRemoveFromList for the NG0100 background.
2089
+ await Promise.resolve();
899
2090
  this.closeAddFromViewDialog();
900
2091
  this.refreshGrid();
2092
+ this.bumpStatsRefresh();
2093
+ this.cdr.detectChanges();
901
2094
  }
902
2095
  else {
903
2096
  LogError("Error adding records from view to list");
@@ -905,7 +2098,7 @@ export class SingleListDetailComponent extends BaseAngularComponent {
905
2098
  this.showAddFromViewLoader = false;
906
2099
  }
907
2100
  }
908
- static ɵfac = function SingleListDetailComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SingleListDetailComponent)(i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef)); };
2101
+ static ɵfac = function SingleListDetailComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SingleListDetailComponent)(i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i2.ExportService), i0.ɵɵdirectiveInject(i3.ListSharingService)); };
909
2102
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SingleListDetailComponent, selectors: [["mj-list-detail"]], viewQuery: function SingleListDetailComponent_Query(rf, ctx) { if (rf & 1) {
910
2103
  i0.ɵɵviewQuery(_c0, 5);
911
2104
  } if (rf & 2) {
@@ -913,48 +2106,63 @@ export class SingleListDetailComponent extends BaseAngularComponent {
913
2106
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.listDetailGrid = _t.first);
914
2107
  } }, hostBindings: function SingleListDetailComponent_HostBindings(rf, ctx) { if (rf & 1) {
915
2108
  i0.ɵɵlistener("click", function SingleListDetailComponent_click_HostBindingHandler($event) { return ctx.onDocumentClick($event); }, i0.ɵɵresolveDocument);
916
- } }, inputs: { ListID: "ListID" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 16, vars: 8, consts: [["listDetailGrid", ""], [1, "list-detail-container"], [1, "list-header"], [1, "add-dropdown-wrapper"], ["mjButton", "", "variant", "primary", 1, "add-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-chevron-down", "add-dropdown-arrow"], [1, "add-dropdown-panel"], [1, "custom-toolbar"], [1, "loading-container"], [1, "grid-container"], ["Title", "Remove from List", 3, "Visible", "MinWidth", "Width"], [3, "Visible", "Title", "MinWidth", "Width", "Height"], ["Title", "Add Records from Views", 3, "Visible", "MinWidth", "Width", "Height"], [1, "add-dropdown-item"], [1, "add-dropdown-item", 3, "click"], [1, "add-dropdown-item-text"], [1, "add-dropdown-item-desc"], [1, "toolbar-left"], [1, "row-count"], [1, "selection-count"], [1, "toolbar-right"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", "remove-btn"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", 3, "click"], [1, "fa-solid", "fa-rotate"], [1, "fa-solid", "fa-file-export"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", "remove-btn", 3, "click"], [1, "fa-solid", "fa-trash"], ["text", "Loading list...", "size", "medium"], [3, "rowClicked", "rowDoubleClicked", "selectionChange", "dataLoaded", "listId", "listEntity", "autoNavigate", "height", "showToolbar", "toolbarConfig", "selectionMode"], ["Title", "Remove from List", 3, "Close", "Visible", "MinWidth", "Width"], [1, "dialog-content"], [1, "dialog-loading"], [1, "dialog-message"], ["mjButton", "", "variant", "danger", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", 3, "click", "disabled"], ["text", "Removing records...", "size", "small"], [1, "progress-bar", 3, "Value"], [1, "fa-solid", "fa-triangle-exclamation", "warning-icon"], [1, "dialog-note"], [3, "Close", "Visible", "Title", "MinWidth", "Width", "Height"], [1, "dialog-content", "add-records-dialog"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["text", "Adding records to list...", "size", "small"], [1, "search-section"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", 1, "mj-input", "search-input", 3, "input", "placeholder", "value"], [1, "search-hint"], [1, "records-list"], [1, "list-loading"], [1, "empty-results"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-search", "empty-icon"], [1, "fa-solid", "fa-list", "empty-icon"], [1, "selection-controls"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], [1, "selection-info"], [1, "records-scroll"], [1, "record-item", 3, "in-list", "selected"], [1, "record-item", 3, "click"], [1, "record-checkbox"], ["title", "Already in list", 1, "fa-solid", "fa-check", "in-list-icon"], ["type", "checkbox", 3, "checked"], [1, "record-name"], [1, "in-list-badge"], ["type", "checkbox", 3, "click", "change", "checked"], ["Title", "Add Records from Views", 3, "Close", "Visible", "MinWidth", "Width", "Height"], ["text", "Loading records from views...", "size", "small"], ["text", "Loading views...", "size", "small"], [1, "dialog-instruction"], [1, "views-list"], [1, "fa-solid", "fa-folder-open", "empty-icon"], [1, "view-item", 3, "selected"], [1, "view-item", 3, "click"], [1, "fa-solid", "fa-table-list", "view-icon"], [1, "view-name"]], template: function SingleListDetailComponent_Template(rf, ctx) { if (rf & 1) {
917
- i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "h1");
918
- i0.ɵɵtext(3);
2109
+ } }, inputs: { ListID: "ListID" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 19, vars: 20, consts: [["listDetailGrid", ""], [1, "list-detail-container"], [1, "list-header"], [1, "list-header__titleblock"], [1, "lineage-badge", 3, "title"], [1, "list-detail__tags"], [1, "add-dropdown-wrapper"], [1, "permission-badge", "permission-badge--viewer"], [1, "custom-toolbar"], [1, "loading-container"], [1, "grid-with-stats"], [3, "Confirm", "Cancel", "Visible", "Delta", "TargetListName", "SourceLabel"], [3, "Visible", "Title", "MinWidth", "Width", "Height"], ["Title", "Remove from List", 3, "Visible", "MinWidth", "Width"], ["Title", "Add Records from Views", 3, "Visible", "MinWidth", "Width", "Height"], [1, "fa-solid", "fa-link"], [1, "lineage-badge__refreshed"], ["EntityName", "MJ: Lists", 3, "Provider", "RecordID", "Editable", "MaxDisplay"], ["mjButton", "", "variant", "primary", 1, "add-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-chevron-down", "add-dropdown-arrow"], [1, "add-dropdown-panel"], [1, "add-dropdown-item"], [1, "add-dropdown-item", 3, "click"], [1, "add-dropdown-item-text"], [1, "add-dropdown-item-desc"], [1, "fa-solid", "fa-eye"], [1, "toolbar-left"], [1, "row-count"], [1, "selection-count"], [1, "toolbar-right"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", 3, "click"], [1, "fa-solid", "fa-rotate"], [1, "fa-solid", "fa-file-export"], ["mjButton", "", "variant", "flat", "title", "Move selected records to another list", 1, "toolbar-button", 3, "click"], [1, "fa-solid", "fa-arrow-right-arrow-left"], ["mjButton", "", "variant", "flat", "title", "Copy selected records to another list (keeps them here too)", 1, "toolbar-button", 3, "click"], [1, "fa-solid", "fa-copy"], ["title", "Set status on selected items", 1, "mj-input", "mj-select", "bulk-status-select", 3, "ngModelChange", "ngModel", "disabled"], ["value", ""], ["value", "Active"], ["value", "Complete"], ["value", "Pending"], ["value", "Disabled"], ["value", "Rejected"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", 3, "click", "disabled"], ["mjButton", "", "variant", "flat", 1, "toolbar-button", "remove-btn", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-pen-to-square"], ["title", "Refresh mode", 1, "mj-input", "mj-select", "refresh-mode-select", 3, "ngModelChange", "ngModel", "disabled"], ["value", "Additive"], ["value", "Sync"], [1, "fa-solid", "fa-cloud-arrow-down"], ["text", "Loading list...", "size", "medium"], [1, "grid-container"], [3, "rowClicked", "rowDoubleClicked", "selectionChange", "dataLoaded", "listId", "listEntity", "autoNavigate", "height", "showToolbar", "toolbarConfig", "selectionMode"], [1, "list-detail__stats"], [3, "Provider", "ListID", "RefreshTrigger"], [3, "Close", "Visible", "Title", "MinWidth", "Width", "Height"], [1, "dialog-content", "move-copy-dialog"], [1, "dialog-loading"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["mjButton", "", "variant", "outline", 3, "click", "disabled"], ["size", "small", 3, "text"], [1, "progress-bar", 3, "Value"], [1, "dialog-instruction"], [1, "search-section"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Filter lists by name\u2026", 1, "mj-input", "search-input", 3, "ngModelChange", "ngModel"], [1, "list-loading"], [1, "empty-results"], [1, "records-scroll", "move-copy-targets"], ["text", "Loading lists...", "size", "small"], [1, "fa-solid", "fa-list", "empty-icon"], [1, "dialog-note"], [1, "record-item", 3, "selected"], [1, "record-item", 3, "click"], [1, "record-checkbox"], ["type", "radio", "name", "moveCopyTarget", 3, "click", "change", "checked"], [1, "record-name"], [1, "target-desc"], ["Title", "Remove from List", 3, "Close", "Visible", "MinWidth", "Width"], [1, "dialog-content"], [1, "dialog-message"], ["mjButton", "", "variant", "danger", 3, "click", "disabled"], ["text", "Removing records...", "size", "small"], [1, "fa-solid", "fa-triangle-exclamation", "warning-icon"], [1, "dialog-content", "add-records-dialog"], ["text", "Adding records to list...", "size", "small"], ["type", "text", 1, "mj-input", "search-input", 3, "input", "placeholder", "value"], [1, "search-hint"], [1, "records-list"], ["size", "small", 3, "showText"], [1, "fa-solid", "fa-search", "empty-icon"], [1, "selection-controls"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], [1, "selection-info"], [1, "records-scroll"], [1, "record-item", 3, "in-list", "selected"], ["title", "Already in list", 1, "fa-solid", "fa-check", "in-list-icon"], ["type", "checkbox", 3, "checked"], [1, "in-list-badge"], ["type", "checkbox", 3, "click", "change", "checked"], [1, "dialog-content", "export-dialog"], [1, "export-section-label"], [1, "export-format-row"], [1, "export-format-option", 3, "click"], ["type", "radio", "name", "exportFormat", "value", "excel", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-file-excel", 2, "color", "var(--mj-status-success)"], ["type", "radio", "name", "exportFormat", "value", "csv", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-file-csv", 2, "color", "var(--mj-text-secondary)"], ["type", "radio", "name", "exportFormat", "value", "json", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-file-code", 2, "color", "var(--mj-brand-primary)"], [1, "export-section-divider"], [1, "export-fields-list"], [1, "export-field-row"], [1, "export-field-actions"], ["href", "#", 3, "click"], [1, "muted"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-download"], ["Title", "Add Records from Views", 3, "Close", "Visible", "MinWidth", "Width", "Height"], ["text", "Loading records from views...", "size", "small"], ["text", "Loading views...", "size", "small"], [1, "views-list"], [1, "fa-solid", "fa-folder-open", "empty-icon"], [1, "view-item", 3, "selected"], [1, "view-item", 3, "click"], [1, "fa-solid", "fa-table-list", "view-icon"], [1, "view-name"]], template: function SingleListDetailComponent_Template(rf, ctx) { if (rf & 1) {
2110
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
2111
+ i0.ɵɵconditionalCreate(3, SingleListDetailComponent_Conditional_3_Template, 2, 1, "h1")(4, SingleListDetailComponent_Conditional_4_Template, 2, 0, "h1");
2112
+ i0.ɵɵconditionalCreate(5, SingleListDetailComponent_Conditional_5_Template, 6, 3, "div", 4);
2113
+ i0.ɵɵconditionalCreate(6, SingleListDetailComponent_Conditional_6_Template, 2, 4, "div", 5);
919
2114
  i0.ɵɵelementEnd();
920
- i0.ɵɵelementStart(4, "div", 3)(5, "button", 4);
921
- i0.ɵɵlistener("click", function SingleListDetailComponent_Template_button_click_5_listener() { return ctx.toggleAddDropdown(); });
922
- i0.ɵɵelement(6, "span", 5);
923
- i0.ɵɵtext(7, " Add to List ");
924
- i0.ɵɵelement(8, "span", 6);
2115
+ i0.ɵɵconditionalCreate(7, SingleListDetailComponent_Conditional_7_Template, 6, 1, "div", 6)(8, SingleListDetailComponent_Conditional_8_Template, 3, 0, "span", 7);
925
2116
  i0.ɵɵelementEnd();
926
- i0.ɵɵconditionalCreate(9, SingleListDetailComponent_Conditional_9_Template, 3, 0, "div", 7);
927
- i0.ɵɵelementEnd()();
928
- i0.ɵɵconditionalCreate(10, SingleListDetailComponent_Conditional_10_Template, 13, 4, "div", 8);
929
- i0.ɵɵconditionalCreate(11, SingleListDetailComponent_Conditional_11_Template, 2, 0, "div", 9);
930
- i0.ɵɵconditionalCreate(12, SingleListDetailComponent_Conditional_12_Template, 3, 7, "div", 10);
2117
+ i0.ɵɵconditionalCreate(9, SingleListDetailComponent_Conditional_9_Template, 14, 5, "div", 8);
2118
+ i0.ɵɵconditionalCreate(10, SingleListDetailComponent_Conditional_10_Template, 2, 0, "div", 9);
2119
+ i0.ɵɵconditionalCreate(11, SingleListDetailComponent_Conditional_11_Template, 6, 10, "div", 10);
2120
+ i0.ɵɵelementStart(12, "mj-list-delta-confirm", 11);
2121
+ i0.ɵɵlistener("Confirm", function SingleListDetailComponent_Template_mj_list_delta_confirm_Confirm_12_listener($event) { return ctx.onRefreshConfirmCommit($event); })("Cancel", function SingleListDetailComponent_Template_mj_list_delta_confirm_Cancel_12_listener() { return ctx.onRefreshConfirmCancel(); });
931
2122
  i0.ɵɵelementEnd();
932
- i0.ɵɵconditionalCreate(13, SingleListDetailComponent_Conditional_13_Template, 9, 6, "mj-dialog", 11);
933
- i0.ɵɵconditionalCreate(14, SingleListDetailComponent_Conditional_14_Template, 9, 10, "mj-dialog", 12);
934
- i0.ɵɵconditionalCreate(15, SingleListDetailComponent_Conditional_15_Template, 11, 9, "mj-dialog", 13);
2123
+ i0.ɵɵelementStart(13, "mj-list-delta-confirm", 11);
2124
+ i0.ɵɵlistener("Confirm", function SingleListDetailComponent_Template_mj_list_delta_confirm_Confirm_13_listener($event) { return ctx.onMoveConfirmCommit($event); })("Cancel", function SingleListDetailComponent_Template_mj_list_delta_confirm_Cancel_13_listener() { return ctx.onMoveConfirmCancel(); });
2125
+ i0.ɵɵelementEnd()();
2126
+ i0.ɵɵconditionalCreate(14, SingleListDetailComponent_Conditional_14_Template, 10, 9, "mj-dialog", 12);
2127
+ i0.ɵɵconditionalCreate(15, SingleListDetailComponent_Conditional_15_Template, 9, 6, "mj-dialog", 13);
2128
+ i0.ɵɵconditionalCreate(16, SingleListDetailComponent_Conditional_16_Template, 9, 10, "mj-dialog", 12);
2129
+ i0.ɵɵconditionalCreate(17, SingleListDetailComponent_Conditional_17_Template, 39, 19, "mj-dialog", 12);
2130
+ i0.ɵɵconditionalCreate(18, SingleListDetailComponent_Conditional_18_Template, 11, 9, "mj-dialog", 14);
935
2131
  } if (rf & 2) {
936
2132
  i0.ɵɵadvance(3);
937
- i0.ɵɵtextInterpolate(ctx.listRecord ? ctx.listRecord.Name : "List");
938
- i0.ɵɵadvance(6);
939
- i0.ɵɵconditional(ctx.showAddDropdown ? 9 : -1);
2133
+ i0.ɵɵconditional(ctx.listRecord ? 3 : 4);
2134
+ i0.ɵɵadvance(2);
2135
+ i0.ɵɵconditional(ctx.hasLineage ? 5 : -1);
2136
+ i0.ɵɵadvance();
2137
+ i0.ɵɵconditional(ctx.listRecord ? 6 : -1);
2138
+ i0.ɵɵadvance();
2139
+ i0.ɵɵconditional(ctx.capabilities.CanEdit ? 7 : ctx.currentLevel ? 8 : -1);
2140
+ i0.ɵɵadvance(2);
2141
+ i0.ɵɵconditional(!ctx.showLoader && ctx.listRecord ? 9 : -1);
2142
+ i0.ɵɵadvance();
2143
+ i0.ɵɵconditional(ctx.showLoader ? 10 : -1);
2144
+ i0.ɵɵadvance();
2145
+ i0.ɵɵconditional(!ctx.showLoader && ctx.listRecord ? 11 : -1);
2146
+ i0.ɵɵadvance();
2147
+ i0.ɵɵproperty("Visible", ctx.refreshConfirmVisible && !!ctx.refreshDelta)("Delta", ctx.refreshDelta)("TargetListName", (ctx.listRecord == null ? null : ctx.listRecord.Name) ?? null)("SourceLabel", ctx.sourceViewName);
940
2148
  i0.ɵɵadvance();
941
- i0.ɵɵconditional(!ctx.showLoader && ctx.listRecord ? 10 : -1);
2149
+ i0.ɵɵproperty("Visible", ctx.moveDeltaConfirmVisible && !!ctx.moveDelta)("Delta", ctx.moveDelta)("TargetListName", (ctx.listRecord == null ? null : ctx.listRecord.Name) ?? null)("SourceLabel", "Move to " + ((ctx.moveCopySelectedTarget == null ? null : ctx.moveCopySelectedTarget.Name) ?? "target list"));
942
2150
  i0.ɵɵadvance();
943
- i0.ɵɵconditional(ctx.showLoader ? 11 : -1);
2151
+ i0.ɵɵconditional(ctx.showMoveCopyDialog ? 14 : -1);
944
2152
  i0.ɵɵadvance();
945
- i0.ɵɵconditional(!ctx.showLoader && ctx.listRecord ? 12 : -1);
2153
+ i0.ɵɵconditional(ctx.showRemoveDialog ? 15 : -1);
946
2154
  i0.ɵɵadvance();
947
- i0.ɵɵconditional(ctx.showRemoveDialog ? 13 : -1);
2155
+ i0.ɵɵconditional(ctx.showAddRecordsDialog ? 16 : -1);
948
2156
  i0.ɵɵadvance();
949
- i0.ɵɵconditional(ctx.showAddRecordsDialog ? 14 : -1);
2157
+ i0.ɵɵconditional(ctx.showExportDialog && ctx.listRecord ? 17 : -1);
950
2158
  i0.ɵɵadvance();
951
- i0.ɵɵconditional(ctx.showAddFromViewDialog ? 15 : -1);
952
- } }, dependencies: [i2.MJProgressBarComponent, i3.LoadingComponent, i4.ListDetailGridComponent, i2.MJButtonDirective, i2.MJDialogComponent, i2.MJDialogActionsComponent], styles: [".list-detail-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n}\n\n.list-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 16px;\n flex-shrink: 0;\n}\n\n.list-header[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n\n\n.custom-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-bottom: none;\n border-radius: 8px 8px 0 0;\n flex-shrink: 0;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.row-count[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.selection-count[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.toolbar-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n}\n\n.toolbar-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.remove-btn[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.grid-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 0 0 8px 8px;\n overflow: hidden;\n}\n\n\n\n.add-dropdown-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.add-btn[_ngcontent-%COMP%] {\n font-size: 16px;\n padding: 8px 25px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.add-dropdown-arrow[_ngcontent-%COMP%] {\n font-size: 12px;\n margin-left: 4px;\n}\n\n.add-dropdown-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 240px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 100;\n overflow: hidden;\n}\n\n.add-dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding: 10px 16px;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.add-dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.add-dropdown-item-text[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.add-dropdown-item-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n\n\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.dialog-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n gap: 20px;\n}\n\n.dialog-message[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n}\n\n.warning-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--mj-status-warning);\n margin-bottom: 16px;\n display: block;\n}\n\n.dialog-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 8px 0;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.dialog-note[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary) !important;\n font-size: 13px !important;\n}\n\n.progress-bar[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 300px;\n}\n\n\n\n\n\n\n.add-records-dialog[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.search-section[_ngcontent-%COMP%] {\n padding-bottom: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] .search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 10px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n pointer-events: none;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] .search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding-left: 32px;\n}\n\n.search-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n.records-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.list-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 40px;\n}\n\n.empty-results[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: var(--mj-text-disabled);\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n color: var(--mj-border-strong);\n}\n\n.empty-results[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n.selection-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 8px;\n}\n\n.selection-info[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.records-scroll[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n max-height: 280px;\n}\n\n.record-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.record-item[_ngcontent-%COMP%]:hover:not(.in-list) {\n background: var(--mj-bg-surface-card);\n}\n\n.record-item.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.record-item.in-list[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n cursor: default;\n opacity: 0.7;\n}\n\n.record-checkbox[_ngcontent-%COMP%] {\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.record-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.in-list-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 14px;\n}\n\n.record-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.in-list-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-radius: 10px;\n font-weight: 500;\n}\n\n\n\n\n\n\n.dialog-instruction[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.views-list[_ngcontent-%COMP%] {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.view-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.view-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.view-item.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.view-item[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.view-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 16px;\n}\n\n.view-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}"] });
2159
+ i0.ɵɵconditional(ctx.showAddFromViewDialog ? 18 : -1);
2160
+ } }, dependencies: [i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.CheckboxControlValueAccessor, i4.SelectControlValueAccessor, i4.RadioControlValueAccessor, i4.NgControlStatus, i4.NgModel, i5.MJProgressBarComponent, i6.LoadingComponent, i7.ListDetailGridComponent, i3.ListDeltaConfirmComponent, i3.ListStatsComponent, i3.TagChipsComponent, i5.MJButtonDirective, i5.MJDialogComponent, i5.MJDialogActionsComponent, i8.DatePipe], styles: [".list-detail-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n}\n\n.list-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 16px;\n flex-shrink: 0;\n gap: 16px;\n}\n\n.list-header__titleblock[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.list-header[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.lineage-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n color: var(--mj-text-secondary);\n font-size: 12px;\n width: fit-content;\n}\n\n.lineage-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.lineage-badge__refreshed[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.refresh-mode-select[_ngcontent-%COMP%] {\n min-width: 100px;\n font-size: 13px;\n}\n\n.bulk-status-select[_ngcontent-%COMP%] {\n min-width: 130px;\n font-size: 13px;\n}\n\n\n\n\n\n.permission-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.permission-badge--viewer[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n\n\n.list-detail__tags[_ngcontent-%COMP%] {\n margin-top: 8px;\n}\n\n\n\n\n.grid-with-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 280px;\n gap: 16px;\n flex: 1;\n min-height: 0;\n}\n\n.list-detail__stats[_ngcontent-%COMP%] {\n min-width: 0;\n overflow-y: auto;\n}\n\n@media (max-width: 900px) {\n .grid-with-stats[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n .list-detail__stats[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n.custom-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-bottom: none;\n border-radius: 8px 8px 0 0;\n flex-shrink: 0;\n}\n\n.toolbar-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.toolbar-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.row-count[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.selection-count[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.toolbar-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n}\n\n.toolbar-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.remove-btn[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.grid-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 0 0 8px 8px;\n overflow: hidden;\n}\n\n\n\n.add-dropdown-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.add-btn[_ngcontent-%COMP%] {\n font-size: 16px;\n padding: 8px 25px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.add-dropdown-arrow[_ngcontent-%COMP%] {\n font-size: 12px;\n margin-left: 4px;\n}\n\n.add-dropdown-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 240px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 100;\n overflow: hidden;\n}\n\n.add-dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n padding: 10px 16px;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.add-dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.add-dropdown-item-text[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.add-dropdown-item-desc[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n\n\n\n\n\n.dialog-content[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.dialog-loading[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n gap: 20px;\n}\n\n.dialog-message[_ngcontent-%COMP%] {\n text-align: center;\n padding: 20px;\n}\n\n.warning-icon[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--mj-status-warning);\n margin-bottom: 16px;\n display: block;\n}\n\n.dialog-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 8px 0;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.dialog-note[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary) !important;\n font-size: 13px !important;\n}\n\n.progress-bar[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 300px;\n}\n\n\n\n\n\n\n.add-records-dialog[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.search-section[_ngcontent-%COMP%] {\n padding-bottom: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] .search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 10px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n pointer-events: none;\n}\n\n.search-input-wrapper[_ngcontent-%COMP%] .search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding-left: 32px;\n}\n\n.search-hint[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n.records-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.list-loading[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n padding: 40px;\n}\n\n.empty-results[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: var(--mj-text-disabled);\n}\n\n.empty-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n color: var(--mj-border-strong);\n}\n\n.empty-results[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n.selection-controls[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 8px;\n}\n\n.selection-info[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.records-scroll[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n max-height: 280px;\n}\n\n.record-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.record-item[_ngcontent-%COMP%]:hover:not(.in-list) {\n background: var(--mj-bg-surface-card);\n}\n\n.record-item.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.record-item.in-list[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n cursor: default;\n opacity: 0.7;\n}\n\n.record-checkbox[_ngcontent-%COMP%] {\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.record-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.in-list-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n font-size: 14px;\n}\n\n.record-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.in-list-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-radius: 10px;\n font-weight: 500;\n}\n\n\n\n\n\n\n.dialog-instruction[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.views-list[_ngcontent-%COMP%] {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.view-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.view-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.view-item.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.view-item[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.view-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 16px;\n}\n\n.view-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n\n\n.export-dialog[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 8px; }\n.export-section-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n margin-bottom: 8px;\n}\n.export-format-row[_ngcontent-%COMP%] { display: flex; gap: 8px; }\n.export-format-option[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 13px;\n background: var(--mj-bg-surface);\n}\n.export-format-option--selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, transparent);\n}\n.export-format-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] { margin: 0; }\n.export-section-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 16px 0;\n}\n.export-fields-list[_ngcontent-%COMP%] {\n max-height: 280px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n.export-field-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n cursor: pointer;\n}\n.export-field-row[_ngcontent-%COMP%]:last-child { border-bottom: none; }\n.export-field-row[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n.export-field-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n align-items: center;\n font-size: 11.5px;\n}\n.export-field-actions[_ngcontent-%COMP%] a[_ngcontent-%COMP%] { color: var(--mj-text-link); }\n.export-field-actions[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%] {\n margin-left: auto;\n color: var(--mj-text-muted);\n}"] });
953
2161
  }
954
2162
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SingleListDetailComponent, [{
955
2163
  type: Component,
956
- args: [{ standalone: false, selector: 'mj-list-detail', template: "<div class=\"list-detail-container\">\n <!-- Header with title and Add button -->\n <div class=\"list-header\">\n <h1>{{ listRecord ? listRecord.Name : \"List\" }}</h1>\n <div class=\"add-dropdown-wrapper\">\n <button mjButton variant=\"primary\" class=\"add-btn\" (click)=\"toggleAddDropdown()\">\n <span class=\"fa-solid fa-plus\"></span>\n Add to List\n <span class=\"fa-solid fa-chevron-down add-dropdown-arrow\"></span>\n </button>\n @if (showAddDropdown) {\n <div class=\"add-dropdown-panel\">\n @for (option of addOptions; track option.Text) {\n <div class=\"add-dropdown-item\" (click)=\"onDropdownItemClick(option)\">\n <span class=\"add-dropdown-item-text\">{{ option.Text }}</span>\n @if (option.Description) {\n <span class=\"add-dropdown-item-desc\">{{ option.Description }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Custom Toolbar -->\n @if (!showLoader && listRecord) {\n <div class=\"custom-toolbar\">\n <div class=\"toolbar-left\">\n <span class=\"row-count\">{{ rowCount }} row{{ rowCount !== 1 ? 's' : '' }}</span>\n @if (selectedKeys.length > 0) {\n <span class=\"selection-count\">({{ selectedKeys.length }} selected)</span>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedKeys.length > 0) {\n <button mjButton\n (click)=\"openRemoveDialog()\"\n variant=\"flat\"\n class=\"toolbar-button remove-btn\">\n <span class=\"fa-solid fa-trash\"></span>\n Remove from List\n </button>\n }\n <button mjButton\n (click)=\"onRefreshClick()\"\n variant=\"flat\"\n class=\"toolbar-button\">\n <span class=\"fa-solid fa-rotate\"></span>\n Refresh\n </button>\n <button mjButton\n (click)=\"onExportClick()\"\n variant=\"flat\"\n class=\"toolbar-button\">\n <span class=\"fa-solid fa-file-export\"></span>\n Export\n </button>\n </div>\n </div>\n }\n\n <!-- Loading State -->\n @if (showLoader) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading list...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Grid -->\n @if (!showLoader && listRecord) {\n <div class=\"grid-container\">\n <mj-list-detail-grid\n #listDetailGrid\n [listId]=\"ListID\"\n [listEntity]=\"listRecord\"\n [autoNavigate]=\"true\"\n [height]=\"'auto'\"\n [showToolbar]=\"false\"\n [toolbarConfig]=\"gridToolbarConfig\"\n [selectionMode]=\"'checkbox'\"\n (rowClicked)=\"onRowClicked($event)\"\n (rowDoubleClicked)=\"onRowDoubleClicked($event)\"\n (selectionChange)=\"onSelectionChange($event)\"\n (dataLoaded)=\"onDataLoaded($event)\">\n </mj-list-detail-grid>\n </div>\n }\n</div>\n\n<!-- Remove from List Confirmation Dialog -->\n@if (showRemoveDialog) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Remove from List\"\n (Close)=\"closeRemoveDialog()\"\n [MinWidth]=\"350\"\n [Width]=\"450\">\n <div class=\"dialog-content\">\n @if (isRemoving) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Removing records...\" size=\"small\"></mj-loading>\n @if (removeTotal > 0) {\n <mj-progress-bar\n [Value]=\"removeProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n }\n </div>\n } @else {\n <div class=\"dialog-message\">\n <span class=\"fa-solid fa-triangle-exclamation warning-icon\"></span>\n <p>Are you sure you want to remove <strong>{{ selectedKeys.length }}</strong> record{{ selectedKeys.length !== 1 ? 's' : '' }} from this list?</p>\n <p class=\"dialog-note\">This will not delete the records, only remove them from this list.</p>\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmRemoveFromList()\"\n [disabled]=\"isRemoving\"\n variant=\"danger\">\n Remove\n </button>\n <button mjButton\n (click)=\"closeRemoveDialog()\"\n [disabled]=\"isRemoving\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Add Records Dialog -->\n@if (showAddRecordsDialog) {\n <mj-dialog\n [Visible]=\"true\"\n [Title]=\"'Add ' + (listRecord?.Entity || 'Records') + ' to List'\"\n (Close)=\"closeAddRecordsDialog()\"\n [MinWidth]=\"500\"\n [Width]=\"700\"\n [Height]=\"650\">\n <div class=\"dialog-content add-records-dialog\">\n @if (addDialogSaving) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Adding records to list...\" size=\"small\"></mj-loading>\n @if (addTotal > 0) {\n <mj-progress-bar\n [Value]=\"addProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n }\n </div>\n } @else {\n <!-- Search Input -->\n <div class=\"search-section\">\n <div class=\"search-input-wrapper\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n class=\"mj-input search-input\"\n type=\"text\"\n [placeholder]=\"'Search ' + (listRecord?.Entity || 'records') + '...'\"\n [value]=\"addRecordsSearchFilter\"\n (input)=\"onAddRecordsSearchInputEvent($event)\" />\n </div>\n <span class=\"search-hint\">Type at least 2 characters to search</span>\n </div>\n <!-- Records List -->\n <div class=\"records-list\">\n @if (addDialogLoading) {\n <div class=\"list-loading\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n </div>\n } @else if (addableRecords.length === 0 && addRecordsSearchFilter.length >= 2) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-search empty-icon\"></span>\n <p>No records found matching \"{{ addRecordsSearchFilter }}\"</p>\n </div>\n } @else if (addableRecords.length === 0) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-list empty-icon\"></span>\n <p>Search for records to add to this list</p>\n </div>\n } @else {\n <!-- Selection controls -->\n <div class=\"selection-controls\">\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"selectAllAddable()\">Select All</button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"deselectAllAddable()\">Deselect All</button>\n <span class=\"selection-info\">{{ selectedAddableRecords.length }} selected</span>\n </div>\n <!-- Records -->\n <div class=\"records-scroll\">\n @for (record of addableRecords; track record.ID) {\n <div class=\"record-item\"\n [class.in-list]=\"record.isInList\"\n [class.selected]=\"record.isSelected\"\n (click)=\"toggleRecordSelection(record)\">\n <div class=\"record-checkbox\">\n @if (record.isInList) {\n <span class=\"fa-solid fa-check in-list-icon\" title=\"Already in list\"></span>\n } @else {\n <input type=\"checkbox\"\n [checked]=\"record.isSelected\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRecordSelection(record)\">\n }\n </div>\n <div class=\"record-name\">{{ record.Name }}</div>\n @if (record.isInList) {\n <span class=\"in-list-badge\">In List</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmAddRecords()\"\n [disabled]=\"addDialogSaving || selectedAddableRecords.length === 0\"\n variant=\"primary\">\n Add {{ selectedAddableRecords.length > 0 ? selectedAddableRecords.length : '' }} Record{{ selectedAddableRecords.length !== 1 ? 's' : '' }}\n </button>\n <button mjButton\n (click)=\"closeAddRecordsDialog()\"\n [disabled]=\"addDialogSaving\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Add From View Dialog -->\n@if (showAddFromViewDialog) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Add Records from Views\"\n (Close)=\"closeAddFromViewDialog()\"\n [MinWidth]=\"400\"\n [Width]=\"600\"\n [Height]=\"500\">\n <div class=\"dialog-content\">\n @if (showAddFromViewLoader && fetchingRecordsToSave) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Loading records from views...\" size=\"small\"></mj-loading>\n </div>\n } @else if (showAddFromViewLoader && addFromViewTotal > 0) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Adding records to list...\" size=\"small\"></mj-loading>\n <mj-progress-bar\n [Value]=\"addFromViewProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n </div>\n } @else if (showAddFromViewLoader) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Loading views...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n <p class=\"dialog-instruction\">Select views to add their records to this list:</p>\n <div class=\"views-list\">\n @if (!userViews || userViews.length === 0) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-folder-open empty-icon\"></span>\n <p>No saved views found for this entity</p>\n </div>\n } @else {\n @for (view of userViews; track view.ID) {\n <div class=\"view-item\"\n [class.selected]=\"isViewSelected(view)\"\n (click)=\"toggleViewSelection(view)\">\n <input type=\"checkbox\"\n [checked]=\"isViewSelected(view)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleViewSelection(view)\">\n <span class=\"fa-solid fa-table-list view-icon\"></span>\n <span class=\"view-name\">{{ view.Name }}</span>\n </div>\n }\n }\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmAddFromView()\"\n [disabled]=\"showAddFromViewLoader || userViewsToAdd.length === 0\"\n variant=\"primary\">\n Add from {{ userViewsToAdd.length }} View{{ userViewsToAdd.length !== 1 ? 's' : '' }}\n </button>\n <button mjButton\n (click)=\"closeAddFromViewDialog()\"\n [disabled]=\"showAddFromViewLoader\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n", styles: [".list-detail-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n}\n\n.list-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 16px;\n flex-shrink: 0;\n}\n\n.list-header h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* Custom Toolbar */\n.custom-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-bottom: none;\n border-radius: 8px 8px 0 0;\n flex-shrink: 0;\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.row-count {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.selection-count {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.toolbar-button {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n}\n\n.toolbar-button span {\n font-size: 14px;\n}\n\n.remove-btn {\n color: var(--mj-status-error);\n}\n\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.grid-container {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 0 0 8px 8px;\n overflow: hidden;\n}\n\n/* Add Dropdown Button */\n.add-dropdown-wrapper {\n position: relative;\n}\n\n.add-btn {\n font-size: 16px;\n padding: 8px 25px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.add-dropdown-arrow {\n font-size: 12px;\n margin-left: 4px;\n}\n\n.add-dropdown-panel {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 240px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 100;\n overflow: hidden;\n}\n\n.add-dropdown-item {\n display: flex;\n flex-direction: column;\n padding: 10px 16px;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.add-dropdown-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.add-dropdown-item-text {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.add-dropdown-item-desc {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n/* ==========================================\n Dialog Styles\n ========================================== */\n\n.dialog-content {\n padding: 8px 0;\n}\n\n.dialog-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n gap: 20px;\n}\n\n.dialog-message {\n text-align: center;\n padding: 20px;\n}\n\n.warning-icon {\n font-size: 48px;\n color: var(--mj-status-warning);\n margin-bottom: 16px;\n display: block;\n}\n\n.dialog-message p {\n margin: 8px 0;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.dialog-note {\n color: var(--mj-text-secondary) !important;\n font-size: 13px !important;\n}\n\n.progress-bar {\n width: 100%;\n max-width: 300px;\n}\n\n/* ==========================================\n Add Records Dialog\n ========================================== */\n\n.add-records-dialog {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.search-section {\n padding-bottom: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.search-input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-input-wrapper .search-icon {\n position: absolute;\n left: 10px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n pointer-events: none;\n}\n\n.search-input-wrapper .search-input {\n width: 100%;\n padding-left: 32px;\n}\n\n.search-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n.records-list {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.list-loading {\n display: flex;\n justify-content: center;\n padding: 40px;\n}\n\n.empty-results {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: var(--mj-text-disabled);\n}\n\n.empty-icon {\n font-size: 32px;\n margin-bottom: 12px;\n color: var(--mj-border-strong);\n}\n\n.empty-results p {\n margin: 0;\n font-size: 14px;\n}\n\n.selection-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 8px;\n}\n\n.selection-info {\n margin-left: auto;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.records-scroll {\n flex: 1;\n overflow-y: auto;\n max-height: 280px;\n}\n\n.record-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.record-item:hover:not(.in-list) {\n background: var(--mj-bg-surface-card);\n}\n\n.record-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.record-item.in-list {\n background: var(--mj-bg-surface-card);\n cursor: default;\n opacity: 0.7;\n}\n\n.record-checkbox {\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.record-checkbox input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.in-list-icon {\n color: var(--mj-status-success);\n font-size: 14px;\n}\n\n.record-name {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.in-list-badge {\n font-size: 11px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-radius: 10px;\n font-weight: 500;\n}\n\n/* ==========================================\n Add From View Dialog\n ========================================== */\n\n.dialog-instruction {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.views-list {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.view-item {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.view-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.view-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.view-item input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.view-icon {\n color: var(--mj-text-secondary);\n font-size: 16px;\n}\n\n.view-name {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n"] }]
957
- }], () => [{ type: i1.SharedService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], { ListID: [{
2164
+ args: [{ standalone: false, selector: 'mj-list-detail', template: "<div class=\"list-detail-container\">\n <!-- Header with title and Add button -->\n <div class=\"list-header\">\n <div class=\"list-header__titleblock\">\n @if (listRecord) {\n <h1>{{ listRecord.Name }}</h1>\n } @else {\n <h1>List</h1>\n }\n @if (hasLineage) {\n <div class=\"lineage-badge\" [title]=\"'Source view: ' + (sourceViewName ?? 'unknown')\">\n <i class=\"fa-solid fa-link\"></i>\n <span>\n @if (listRecord?.UseSnapshot) {\n Snapshot of: <strong>{{ sourceViewName ?? '(unknown view)' }}</strong>\n } @else {\n Live view: <strong>{{ sourceViewName ?? '(unknown view)' }}</strong>\n }\n </span>\n @if (listRecord?.LastRefreshedAt) {\n <span class=\"lineage-badge__refreshed\">\n \u00B7 last refreshed {{ listRecord!.LastRefreshedAt | date:'medium' }}\n </span>\n }\n </div>\n }\n @if (listRecord) {\n <!-- Tags section (Phase 4.2). Editable on the detail view. -->\n <div class=\"list-detail__tags\">\n <mj-tag-chips\n [Provider]=\"Provider\"\n EntityName=\"MJ: Lists\"\n [RecordID]=\"listRecord.ID\"\n [Editable]=\"capabilities.CanEdit\"\n [MaxDisplay]=\"20\">\n </mj-tag-chips>\n </div>\n }\n </div>\n @if (capabilities.CanEdit) {\n <div class=\"add-dropdown-wrapper\">\n <button mjButton variant=\"primary\" class=\"add-btn\" (click)=\"toggleAddDropdown()\">\n <span class=\"fa-solid fa-plus\"></span>\n Add to List\n <span class=\"fa-solid fa-chevron-down add-dropdown-arrow\"></span>\n </button>\n @if (showAddDropdown) {\n <div class=\"add-dropdown-panel\">\n @for (option of addOptions; track option.Text) {\n <div class=\"add-dropdown-item\" (click)=\"onDropdownItemClick(option)\">\n <span class=\"add-dropdown-item-text\">{{ option.Text }}</span>\n @if (option.Description) {\n <span class=\"add-dropdown-item-desc\">{{ option.Description }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else if (currentLevel) {\n <!-- Viewer-perspective badge so users understand why mutation\n controls are absent. Mirrors mockup 19. -->\n <span class=\"permission-badge permission-badge--viewer\">\n <i class=\"fa-solid fa-eye\"></i>\n Viewer access\n </span>\n }\n </div>\n\n <!-- Custom Toolbar -->\n @if (!showLoader && listRecord) {\n <div class=\"custom-toolbar\">\n <div class=\"toolbar-left\">\n <span class=\"row-count\">{{ rowCount }} row{{ rowCount !== 1 ? 's' : '' }}</span>\n @if (selectedKeys.length > 0) {\n <span class=\"selection-count\">({{ selectedKeys.length }} selected)</span>\n }\n </div>\n <div class=\"toolbar-right\">\n @if (selectedKeys.length > 0 && capabilities.CanEdit) {\n <!-- Bulk-edit toolbar (Phase 5.2, mockups 23/24).\n Move/Copy open the target-list picker. Move then routes\n through the delta-confirm dialog because the source side\n drops; Copy is additive and applies directly. -->\n <button mjButton\n (click)=\"openMoveDialog()\"\n variant=\"flat\"\n class=\"toolbar-button\"\n title=\"Move selected records to another list\">\n <span class=\"fa-solid fa-arrow-right-arrow-left\"></span>\n Move\u2026\n </button>\n <button mjButton\n (click)=\"openCopyDialog()\"\n variant=\"flat\"\n class=\"toolbar-button\"\n title=\"Copy selected records to another list (keeps them here too)\">\n <span class=\"fa-solid fa-copy\"></span>\n Copy\u2026\n </button>\n <select\n class=\"mj-input mj-select bulk-status-select\"\n [(ngModel)]=\"bulkStatus\"\n [disabled]=\"isApplyingBulkStatus\"\n title=\"Set status on selected items\">\n <option value=\"\">Set status\u2026</option>\n <option value=\"Active\">Active</option>\n <option value=\"Complete\">Complete</option>\n <option value=\"Pending\">Pending</option>\n <option value=\"Disabled\">Disabled</option>\n <option value=\"Rejected\">Rejected</option>\n </select>\n <button mjButton\n (click)=\"applyBulkStatus()\"\n [disabled]=\"!bulkStatus || isApplyingBulkStatus\"\n variant=\"flat\"\n class=\"toolbar-button\">\n @if (isApplyingBulkStatus) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n Applying\u2026\n } @else {\n <span class=\"fa-solid fa-pen-to-square\"></span>\n Apply Status\n }\n </button>\n <button mjButton\n (click)=\"openRemoveDialog()\"\n variant=\"flat\"\n class=\"toolbar-button remove-btn\">\n <span class=\"fa-solid fa-trash\"></span>\n Remove from List\n </button>\n }\n @if (hasLineage && capabilities.CanRefresh) {\n <select\n class=\"mj-input mj-select refresh-mode-select\"\n [ngModel]=\"refreshMode\"\n (ngModelChange)=\"onRefreshModeChange($event)\"\n [disabled]=\"isPreviewingRefresh || isApplyingRefresh\"\n title=\"Refresh mode\">\n <option value=\"Additive\">Additive</option>\n <option value=\"Sync\">Sync</option>\n </select>\n <button mjButton\n (click)=\"onRefreshFromSource()\"\n [disabled]=\"isPreviewingRefresh || isApplyingRefresh\"\n variant=\"flat\"\n class=\"toolbar-button\">\n @if (isPreviewingRefresh) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n Previewing...\n } @else {\n <span class=\"fa-solid fa-cloud-arrow-down\"></span>\n Refresh from Source\n }\n </button>\n }\n <button mjButton\n (click)=\"onRefreshClick()\"\n variant=\"flat\"\n class=\"toolbar-button\">\n <span class=\"fa-solid fa-rotate\"></span>\n Refresh\n </button>\n <button mjButton\n (click)=\"onExportClick()\"\n variant=\"flat\"\n class=\"toolbar-button\">\n <span class=\"fa-solid fa-file-export\"></span>\n Export\n </button>\n </div>\n </div>\n }\n\n <!-- Loading State -->\n @if (showLoader) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading list...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Grid + side stats panel (Phase 5.4). -->\n @if (!showLoader && listRecord) {\n <div class=\"grid-with-stats\">\n <div class=\"grid-container\">\n <mj-list-detail-grid\n #listDetailGrid\n [listId]=\"ListID\"\n [listEntity]=\"listRecord\"\n [autoNavigate]=\"true\"\n [height]=\"'auto'\"\n [showToolbar]=\"false\"\n [toolbarConfig]=\"gridToolbarConfig\"\n [selectionMode]=\"'checkbox'\"\n (rowClicked)=\"onRowClicked($event)\"\n (rowDoubleClicked)=\"onRowDoubleClicked($event)\"\n (selectionChange)=\"onSelectionChange($event)\"\n (dataLoaded)=\"onDataLoaded($event)\">\n </mj-list-detail-grid>\n </div>\n <aside class=\"list-detail__stats\">\n <mj-list-stats [Provider]=\"Provider\" [ListID]=\"listRecord.ID\" [RefreshTrigger]=\"statsRefreshTrigger\"></mj-list-stats>\n </aside>\n </div>\n }\n\n <!-- Refresh-from-source delta-confirm dialog -->\n <mj-list-delta-confirm\n [Visible]=\"refreshConfirmVisible && !!refreshDelta\"\n [Delta]=\"refreshDelta\"\n [TargetListName]=\"listRecord?.Name ?? null\"\n [SourceLabel]=\"sourceViewName\"\n (Confirm)=\"onRefreshConfirmCommit($event)\"\n (Cancel)=\"onRefreshConfirmCancel()\">\n </mj-list-delta-confirm>\n\n <!-- Move delta-confirm dialog (mockup 24). Shown only for Move,\n never for Copy. Drops on the source side require the user to\n acknowledge before Confirm enables. -->\n <mj-list-delta-confirm\n [Visible]=\"moveDeltaConfirmVisible && !!moveDelta\"\n [Delta]=\"moveDelta\"\n [TargetListName]=\"listRecord?.Name ?? null\"\n [SourceLabel]=\"'Move to ' + (moveCopySelectedTarget?.Name ?? 'target list')\"\n (Confirm)=\"onMoveConfirmCommit($event)\"\n (Cancel)=\"onMoveConfirmCancel()\">\n </mj-list-delta-confirm>\n</div>\n\n<!-- Move/Copy target picker (mockup 23). Lists every list owned by /\n shared with the current user that targets the same entity. -->\n@if (showMoveCopyDialog) {\n <mj-dialog\n [Visible]=\"true\"\n [Title]=\"(moveCopyMode === 'move' ? 'Move ' : 'Copy ') + selectedKeys.length + ' record' + (selectedKeys.length === 1 ? '' : 's') + ' to\u2026'\"\n (Close)=\"closeMoveCopyDialog()\"\n [MinWidth]=\"480\"\n [Width]=\"640\"\n [Height]=\"560\">\n <div class=\"dialog-content move-copy-dialog\">\n @if (isApplyingMoveCopy) {\n <div class=\"dialog-loading\">\n <mj-loading [text]=\"(moveCopyMode === 'move' ? 'Moving' : 'Copying') + ' records...'\" size=\"small\"></mj-loading>\n @if (moveCopyTotal > 0) {\n <mj-progress-bar\n [Value]=\"moveCopyProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n }\n </div>\n } @else {\n <p class=\"dialog-instruction\">\n Choose the target list. Both lists must hold the same entity ({{ listRecord?.Entity ?? 'records' }}).\n </p>\n <div class=\"search-section\">\n <div class=\"search-input-wrapper\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n class=\"mj-input search-input\"\n type=\"text\"\n placeholder=\"Filter lists by name\u2026\"\n [(ngModel)]=\"moveCopyTargetSearch\" />\n </div>\n </div>\n @if (moveCopyTargetCandidatesLoading) {\n <div class=\"list-loading\">\n <mj-loading text=\"Loading lists...\" size=\"small\"></mj-loading>\n </div>\n } @else if (filteredMoveCopyTargets.length === 0) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-list empty-icon\"></span>\n <p>No other lists found for this entity.</p>\n <p class=\"dialog-note\">Create a new list first if you need a new target.</p>\n </div>\n } @else {\n <div class=\"records-scroll move-copy-targets\">\n @for (target of filteredMoveCopyTargets; track target.ID) {\n <div class=\"record-item\"\n [class.selected]=\"moveCopySelectedTarget?.ID === target.ID\"\n (click)=\"selectMoveCopyTarget(target)\">\n <div class=\"record-checkbox\">\n <input type=\"radio\"\n name=\"moveCopyTarget\"\n [checked]=\"moveCopySelectedTarget?.ID === target.ID\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"selectMoveCopyTarget(target)\">\n </div>\n <div class=\"record-name\">\n <strong>{{ target.Name }}</strong>\n @if (target.Description) {\n <span class=\"target-desc\"> \u2014 {{ target.Description }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmMoveCopy()\"\n [disabled]=\"!moveCopySelectedTarget || isApplyingMoveCopy\"\n variant=\"primary\">\n @if (moveCopyMode === 'move') {\n <span class=\"fa-solid fa-arrow-right-arrow-left\"></span>\n Continue\n } @else {\n <span class=\"fa-solid fa-copy\"></span>\n Copy {{ selectedKeys.length }}\n }\n </button>\n <button mjButton\n (click)=\"closeMoveCopyDialog()\"\n [disabled]=\"isApplyingMoveCopy\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Remove from List Confirmation Dialog -->\n@if (showRemoveDialog) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Remove from List\"\n (Close)=\"closeRemoveDialog()\"\n [MinWidth]=\"350\"\n [Width]=\"450\">\n <div class=\"dialog-content\">\n @if (isRemoving) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Removing records...\" size=\"small\"></mj-loading>\n @if (removeTotal > 0) {\n <mj-progress-bar\n [Value]=\"removeProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n }\n </div>\n } @else {\n <div class=\"dialog-message\">\n <span class=\"fa-solid fa-triangle-exclamation warning-icon\"></span>\n <p>Are you sure you want to remove <strong>{{ selectedKeys.length }}</strong> record{{ selectedKeys.length !== 1 ? 's' : '' }} from this list?</p>\n <p class=\"dialog-note\">This will not delete the records, only remove them from this list.</p>\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmRemoveFromList()\"\n [disabled]=\"isRemoving\"\n variant=\"danger\">\n Remove\n </button>\n <button mjButton\n (click)=\"closeRemoveDialog()\"\n [disabled]=\"isRemoving\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Add Records Dialog -->\n@if (showAddRecordsDialog) {\n <mj-dialog\n [Visible]=\"true\"\n [Title]=\"'Add ' + (listRecord?.Entity || 'Records') + ' to List'\"\n (Close)=\"closeAddRecordsDialog()\"\n [MinWidth]=\"500\"\n [Width]=\"700\"\n [Height]=\"650\">\n <div class=\"dialog-content add-records-dialog\">\n @if (addDialogSaving) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Adding records to list...\" size=\"small\"></mj-loading>\n @if (addTotal > 0) {\n <mj-progress-bar\n [Value]=\"addProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n }\n </div>\n } @else {\n <!-- Search Input -->\n <div class=\"search-section\">\n <div class=\"search-input-wrapper\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n class=\"mj-input search-input\"\n type=\"text\"\n [placeholder]=\"'Search ' + (listRecord?.Entity || 'records') + '...'\"\n [value]=\"addRecordsSearchFilter\"\n (input)=\"onAddRecordsSearchInputEvent($event)\" />\n </div>\n <span class=\"search-hint\">Type at least 2 characters to search</span>\n </div>\n <!-- Records List -->\n <div class=\"records-list\">\n @if (addDialogLoading) {\n <div class=\"list-loading\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n </div>\n } @else if (addableRecords.length === 0 && addRecordsSearchFilter.length >= 2) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-search empty-icon\"></span>\n <p>No records found matching \"{{ addRecordsSearchFilter }}\"</p>\n </div>\n } @else if (addableRecords.length === 0) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-list empty-icon\"></span>\n <p>Search for records to add to this list</p>\n </div>\n } @else {\n <!-- Selection controls -->\n <div class=\"selection-controls\">\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"selectAllAddable()\">Select All</button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"deselectAllAddable()\">Deselect All</button>\n <span class=\"selection-info\">{{ selectedAddableRecords.length }} selected</span>\n </div>\n <!-- Records -->\n <div class=\"records-scroll\">\n @for (record of addableRecords; track record.ID) {\n <div class=\"record-item\"\n [class.in-list]=\"record.isInList\"\n [class.selected]=\"record.isSelected\"\n (click)=\"toggleRecordSelection(record)\">\n <div class=\"record-checkbox\">\n @if (record.isInList) {\n <span class=\"fa-solid fa-check in-list-icon\" title=\"Already in list\"></span>\n } @else {\n <input type=\"checkbox\"\n [checked]=\"record.isSelected\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRecordSelection(record)\">\n }\n </div>\n <div class=\"record-name\">{{ record.Name }}</div>\n @if (record.isInList) {\n <span class=\"in-list-badge\">In List</span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmAddRecords()\"\n [disabled]=\"addDialogSaving || selectedAddableRecords.length === 0\"\n variant=\"primary\">\n Add {{ selectedAddableRecords.length > 0 ? selectedAddableRecords.length : '' }} Record{{ selectedAddableRecords.length !== 1 ? 's' : '' }}\n </button>\n <button mjButton\n (click)=\"closeAddRecordsDialog()\"\n [disabled]=\"addDialogSaving\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Export Dialog (mockup 26) \u2014 format + column picker -->\n@if (showExportDialog && listRecord) {\n <mj-dialog\n [Visible]=\"true\"\n [Title]=\"'Export ' + exportRecordCount + ' Record' + (exportRecordCount === 1 ? '' : 's')\"\n (Close)=\"closeExportDialog()\"\n [MinWidth]=\"520\"\n [Width]=\"640\"\n [Height]=\"640\">\n <div class=\"dialog-content export-dialog\">\n <label class=\"export-section-label\">Format</label>\n <div class=\"export-format-row\">\n <label class=\"export-format-option\"\n [class.export-format-option--selected]=\"exportFormat === 'excel'\"\n (click)=\"exportFormat = 'excel'\">\n <input type=\"radio\" name=\"exportFormat\" value=\"excel\" [(ngModel)]=\"exportFormat\">\n <i class=\"fa-solid fa-file-excel\" style=\"color: var(--mj-status-success);\"></i>\n <span>Excel (.xlsx)</span>\n </label>\n <label class=\"export-format-option\"\n [class.export-format-option--selected]=\"exportFormat === 'csv'\"\n (click)=\"exportFormat = 'csv'\">\n <input type=\"radio\" name=\"exportFormat\" value=\"csv\" [(ngModel)]=\"exportFormat\">\n <i class=\"fa-solid fa-file-csv\" style=\"color: var(--mj-text-secondary);\"></i>\n <span>CSV</span>\n </label>\n <label class=\"export-format-option\"\n [class.export-format-option--selected]=\"exportFormat === 'json'\"\n (click)=\"exportFormat = 'json'\">\n <input type=\"radio\" name=\"exportFormat\" value=\"json\" [(ngModel)]=\"exportFormat\">\n <i class=\"fa-solid fa-file-code\" style=\"color: var(--mj-brand-primary);\"></i>\n <span>JSON</span>\n </label>\n </div>\n\n <div class=\"export-section-divider\"></div>\n\n <label class=\"export-section-label\">Columns to include</label>\n <div class=\"export-fields-list\">\n @for (f of exportFields; track f.Name) {\n <label class=\"export-field-row\">\n <input type=\"checkbox\" [(ngModel)]=\"f.Selected\">\n <span>{{ f.DisplayName }}</span>\n </label>\n }\n </div>\n <div class=\"export-field-actions\">\n <a href=\"#\" (click)=\"selectAllExportFields(); $event.preventDefault()\">Select All</a>\n <a href=\"#\" (click)=\"selectNoneExportFields(); $event.preventDefault()\">Select None</a>\n <span class=\"muted\">{{ selectedExportFieldCount }} of {{ exportFields.length }} selected</span>\n </div>\n </div>\n <mj-dialog-actions>\n <button mjButton variant=\"primary\"\n [disabled]=\"selectedExportFieldCount === 0 || isExporting\"\n (click)=\"executeExport()\">\n @if (isExporting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Exporting\u2026\n } @else {\n <i class=\"fa-solid fa-download\"></i>\n Export {{ exportRecordCount }} Record{{ exportRecordCount === 1 ? '' : 's' }}\n }\n </button>\n <button mjButton variant=\"outline\" [disabled]=\"isExporting\" (click)=\"closeExportDialog()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n\n<!-- Add From View Dialog -->\n@if (showAddFromViewDialog) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Add Records from Views\"\n (Close)=\"closeAddFromViewDialog()\"\n [MinWidth]=\"400\"\n [Width]=\"600\"\n [Height]=\"500\">\n <div class=\"dialog-content\">\n @if (showAddFromViewLoader && fetchingRecordsToSave) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Loading records from views...\" size=\"small\"></mj-loading>\n </div>\n } @else if (showAddFromViewLoader && addFromViewTotal > 0) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Adding records to list...\" size=\"small\"></mj-loading>\n <mj-progress-bar\n [Value]=\"addFromViewProgressPercent\"\n class=\"progress-bar\">\n </mj-progress-bar>\n </div>\n } @else if (showAddFromViewLoader) {\n <div class=\"dialog-loading\">\n <mj-loading text=\"Loading views...\" size=\"small\"></mj-loading>\n </div>\n } @else {\n <p class=\"dialog-instruction\">Select views to add their records to this list:</p>\n <div class=\"views-list\">\n @if (!userViews || userViews.length === 0) {\n <div class=\"empty-results\">\n <span class=\"fa-solid fa-folder-open empty-icon\"></span>\n <p>No saved views found for this entity</p>\n </div>\n } @else {\n @for (view of userViews; track view.ID) {\n <div class=\"view-item\"\n [class.selected]=\"isViewSelected(view)\"\n (click)=\"toggleViewSelection(view)\">\n <input type=\"checkbox\"\n [checked]=\"isViewSelected(view)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleViewSelection(view)\">\n <span class=\"fa-solid fa-table-list view-icon\"></span>\n <span class=\"view-name\">{{ view.Name }}</span>\n </div>\n }\n }\n </div>\n }\n </div>\n <mj-dialog-actions>\n <button mjButton\n (click)=\"confirmAddFromView()\"\n [disabled]=\"showAddFromViewLoader || userViewsToAdd.length === 0\"\n variant=\"primary\">\n Add from {{ userViewsToAdd.length }} View{{ userViewsToAdd.length !== 1 ? 's' : '' }}\n </button>\n <button mjButton\n (click)=\"closeAddFromViewDialog()\"\n [disabled]=\"showAddFromViewLoader\"\n variant=\"outline\">\n Cancel\n </button>\n </mj-dialog-actions>\n </mj-dialog>\n}\n", styles: [".list-detail-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px;\n background: var(--mj-bg-surface-card);\n}\n\n.list-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 16px;\n flex-shrink: 0;\n gap: 16px;\n}\n\n.list-header__titleblock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.list-header h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.lineage-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\n color: var(--mj-text-secondary);\n font-size: 12px;\n width: fit-content;\n}\n\n.lineage-badge i {\n color: var(--mj-brand-primary);\n}\n\n.lineage-badge__refreshed {\n color: var(--mj-text-muted);\n}\n\n.refresh-mode-select {\n min-width: 100px;\n font-size: 13px;\n}\n\n.bulk-status-select {\n min-width: 130px;\n font-size: 13px;\n}\n\n/* Viewer-perspective badge (mockup 19) \u2014 surfaced in the header when the\n user has read-only access so the missing mutation controls don't feel\n broken. */\n.permission-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 999px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.permission-badge--viewer {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n/* Tags section on the list detail header (Phase 4.2). */\n.list-detail__tags {\n margin-top: 8px;\n}\n\n/* Grid + side stats two-column layout (Phase 5.4). Stats hides on\n narrow screens so the grid keeps its breathing room. */\n.grid-with-stats {\n display: grid;\n grid-template-columns: 1fr 280px;\n gap: 16px;\n flex: 1;\n min-height: 0;\n}\n\n.list-detail__stats {\n min-width: 0;\n overflow-y: auto;\n}\n\n@media (max-width: 900px) {\n .grid-with-stats {\n grid-template-columns: 1fr;\n }\n .list-detail__stats {\n display: none;\n }\n}\n\n/* Custom Toolbar */\n.custom-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-bottom: none;\n border-radius: 8px 8px 0 0;\n flex-shrink: 0;\n}\n\n.toolbar-left {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.toolbar-right {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.row-count {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.selection-count {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.toolbar-button {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n}\n\n.toolbar-button span {\n font-size: 14px;\n}\n\n.remove-btn {\n color: var(--mj-status-error);\n}\n\n.loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.grid-container {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 0 0 8px 8px;\n overflow: hidden;\n}\n\n/* Add Dropdown Button */\n.add-dropdown-wrapper {\n position: relative;\n}\n\n.add-btn {\n font-size: 16px;\n padding: 8px 25px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.add-dropdown-arrow {\n font-size: 12px;\n margin-left: 4px;\n}\n\n.add-dropdown-panel {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 240px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n z-index: 100;\n overflow: hidden;\n}\n\n.add-dropdown-item {\n display: flex;\n flex-direction: column;\n padding: 10px 16px;\n cursor: pointer;\n transition: background-color 0.15s;\n}\n\n.add-dropdown-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.add-dropdown-item-text {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.add-dropdown-item-desc {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n}\n\n/* ==========================================\n Dialog Styles\n ========================================== */\n\n.dialog-content {\n padding: 8px 0;\n}\n\n.dialog-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n gap: 20px;\n}\n\n.dialog-message {\n text-align: center;\n padding: 20px;\n}\n\n.warning-icon {\n font-size: 48px;\n color: var(--mj-status-warning);\n margin-bottom: 16px;\n display: block;\n}\n\n.dialog-message p {\n margin: 8px 0;\n font-size: 15px;\n color: var(--mj-text-primary);\n}\n\n.dialog-note {\n color: var(--mj-text-secondary) !important;\n font-size: 13px !important;\n}\n\n.progress-bar {\n width: 100%;\n max-width: 300px;\n}\n\n/* ==========================================\n Add Records Dialog\n ========================================== */\n\n.add-records-dialog {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.search-section {\n padding-bottom: 12px;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.search-input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.search-input-wrapper .search-icon {\n position: absolute;\n left: 10px;\n color: var(--mj-text-disabled);\n font-size: 14px;\n pointer-events: none;\n}\n\n.search-input-wrapper .search-input {\n width: 100%;\n padding-left: 32px;\n}\n\n.search-hint {\n display: block;\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n.records-list {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.list-loading {\n display: flex;\n justify-content: center;\n padding: 40px;\n}\n\n.empty-results {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: var(--mj-text-disabled);\n}\n\n.empty-icon {\n font-size: 32px;\n margin-bottom: 12px;\n color: var(--mj-border-strong);\n}\n\n.empty-results p {\n margin: 0;\n font-size: 14px;\n}\n\n.selection-controls {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n margin-bottom: 8px;\n}\n\n.selection-info {\n margin-left: auto;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.records-scroll {\n flex: 1;\n overflow-y: auto;\n max-height: 280px;\n}\n\n.record-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.record-item:hover:not(.in-list) {\n background: var(--mj-bg-surface-card);\n}\n\n.record-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.record-item.in-list {\n background: var(--mj-bg-surface-card);\n cursor: default;\n opacity: 0.7;\n}\n\n.record-checkbox {\n width: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.record-checkbox input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.in-list-icon {\n color: var(--mj-status-success);\n font-size: 14px;\n}\n\n.record-name {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.in-list-badge {\n font-size: 11px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-radius: 10px;\n font-weight: 500;\n}\n\n/* ==========================================\n Add From View Dialog\n ========================================== */\n\n.dialog-instruction {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.views-list {\n max-height: 320px;\n overflow-y: auto;\n}\n\n.view-item {\n display: flex;\n align-items: center;\n padding: 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.15s;\n gap: 12px;\n}\n\n.view-item:hover {\n background: var(--mj-bg-surface-card);\n}\n\n.view-item.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.view-item input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n\n.view-icon {\n color: var(--mj-text-secondary);\n font-size: 16px;\n}\n\n.view-name {\n flex: 1;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n/* Export dialog (Phase 5.1, mockup 26) */\n.export-dialog { display: flex; flex-direction: column; gap: 8px; }\n.export-section-label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n margin-bottom: 8px;\n}\n.export-format-row { display: flex; gap: 8px; }\n.export-format-option {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n font-size: 13px;\n background: var(--mj-bg-surface);\n}\n.export-format-option--selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 6%, transparent);\n}\n.export-format-option input[type=\"radio\"] { margin: 0; }\n.export-section-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 16px 0;\n}\n.export-fields-list {\n max-height: 280px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n.export-field-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 13px;\n cursor: pointer;\n}\n.export-field-row:last-child { border-bottom: none; }\n.export-field-row:hover { background: var(--mj-bg-surface-hover); }\n.export-field-actions {\n display: flex;\n gap: 12px;\n margin-top: 8px;\n align-items: center;\n font-size: 11.5px;\n}\n.export-field-actions a { color: var(--mj-text-link); }\n.export-field-actions .muted {\n margin-left: auto;\n color: var(--mj-text-muted);\n}\n"] }]
2165
+ }], () => [{ type: i1.SharedService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i2.ExportService }, { type: i3.ListSharingService }], { ListID: [{
958
2166
  type: Input
959
2167
  }], listDetailGrid: [{
960
2168
  type: ViewChild,
@@ -963,5 +2171,5 @@ export class SingleListDetailComponent extends BaseAngularComponent {
963
2171
  type: HostListener,
964
2172
  args: ['document:click', ['$event']]
965
2173
  }] }); })();
966
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SingleListDetailComponent, { className: "SingleListDetailComponent", filePath: "src/lib/single-list-detail/single-list-detail.component.ts", lineNumber: 28 }); })();
2174
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SingleListDetailComponent, { className: "SingleListDetailComponent", filePath: "src/lib/single-list-detail/single-list-detail.component.ts", lineNumber: 32 }); })();
967
2175
  //# sourceMappingURL=single-list-detail.component.js.map