@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.
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +5 -3
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/conversation-feedback/conversation-feedback.d.ts +108 -0
- package/dist/lib/conversation-feedback/conversation-feedback.d.ts.map +1 -0
- package/dist/lib/conversation-feedback/conversation-feedback.js +809 -0
- package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -0
- package/dist/lib/conversation-feedback/index.d.ts +2 -0
- package/dist/lib/conversation-feedback/index.d.ts.map +1 -0
- package/dist/lib/conversation-feedback/index.js +2 -0
- package/dist/lib/conversation-feedback/index.js.map +1 -0
- package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js +23 -1
- package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts +12 -0
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +107 -15
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts +153 -3
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +1479 -271
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/module.d.ts +32 -29
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +19 -6
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +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-
|
|
9
|
-
import * as i3 from "@memberjunction/ng-
|
|
10
|
-
import * as i4 from "@
|
|
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
|
-
|
|
15
|
-
|
|
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
|
|
26
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
20
27
|
i0.ɵɵadvance();
|
|
21
|
-
i0.ɵɵtextInterpolate(
|
|
28
|
+
i0.ɵɵtextInterpolate(ctx_r0.listRecord.Name);
|
|
22
29
|
} }
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
i0.ɵɵ
|
|
26
|
-
i0.ɵɵ
|
|
27
|
-
|
|
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
|
-
|
|
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
|
|
51
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
34
52
|
i0.ɵɵadvance(2);
|
|
35
|
-
i0.ɵɵtextInterpolate(
|
|
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.ɵɵ
|
|
63
|
+
i0.ɵɵtextInterpolate1(" \u00B7 last refreshed ", i0.ɵɵpipeBind2(2, 1, ctx_r0.listRecord.LastRefreshedAt, "medium"), " ");
|
|
38
64
|
} }
|
|
39
|
-
function
|
|
40
|
-
i0.ɵɵelementStart(0, "div",
|
|
41
|
-
i0.ɵɵ
|
|
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
|
|
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.ɵɵ
|
|
88
|
+
i0.ɵɵproperty("Provider", ctx_r0.Provider)("RecordID", ctx_r0.listRecord.ID)("Editable", ctx_r0.capabilities.CanEdit)("MaxDisplay", 20);
|
|
47
89
|
} }
|
|
48
|
-
function
|
|
49
|
-
i0.ɵɵelementStart(0, "span",
|
|
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
|
|
95
|
+
const option_r4 = i0.ɵɵnextContext().$implicit;
|
|
54
96
|
i0.ɵɵadvance();
|
|
55
|
-
i0.ɵɵ
|
|
97
|
+
i0.ɵɵtextInterpolate(option_r4.Description);
|
|
56
98
|
} }
|
|
57
|
-
function
|
|
58
|
-
const
|
|
59
|
-
i0.ɵɵelementStart(0, "
|
|
60
|
-
i0.ɵɵlistener("click", function
|
|
61
|
-
i0.ɵɵ
|
|
62
|
-
i0.ɵɵtext(2
|
|
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
|
|
66
|
-
|
|
67
|
-
i0.ɵɵ
|
|
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,
|
|
248
|
+
i0.ɵɵconditionalCreate(4, SingleListDetailComponent_Conditional_9_Conditional_4_Template, 2, 1, "span", 29);
|
|
71
249
|
i0.ɵɵelementEnd();
|
|
72
|
-
i0.ɵɵelementStart(5, "div",
|
|
73
|
-
i0.ɵɵconditionalCreate(6,
|
|
74
|
-
i0.ɵɵ
|
|
75
|
-
i0.ɵɵ
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
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(
|
|
80
|
-
i0.ɵɵlistener("click", function
|
|
81
|
-
i0.ɵɵelement(
|
|
82
|
-
i0.ɵɵtext(
|
|
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
|
|
264
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
86
265
|
i0.ɵɵadvance(3);
|
|
87
|
-
i0.ɵɵtextInterpolate2("",
|
|
266
|
+
i0.ɵɵtextInterpolate2("", ctx_r0.rowCount, " row", ctx_r0.rowCount !== 1 ? "s" : "");
|
|
88
267
|
i0.ɵɵadvance();
|
|
89
|
-
i0.ɵɵconditional(
|
|
268
|
+
i0.ɵɵconditional(ctx_r0.selectedKeys.length > 0 ? 4 : -1);
|
|
90
269
|
i0.ɵɵadvance(2);
|
|
91
|
-
i0.ɵɵconditional(
|
|
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
|
|
274
|
+
function SingleListDetailComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
94
275
|
i0.ɵɵelementStart(0, "div", 9);
|
|
95
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
276
|
+
i0.ɵɵelement(1, "mj-loading", 54);
|
|
96
277
|
i0.ɵɵelementEnd();
|
|
97
278
|
} }
|
|
98
|
-
function
|
|
99
|
-
const
|
|
100
|
-
i0.ɵɵelementStart(0, "div", 10)(1, "mj-list-detail-grid",
|
|
101
|
-
i0.ɵɵlistener("rowClicked", function
|
|
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
|
|
396
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
105
397
|
i0.ɵɵadvance();
|
|
106
|
-
i0.ɵɵ
|
|
398
|
+
i0.ɵɵtextInterpolate1(" Copy ", ctx_r0.selectedKeys.length, " ");
|
|
107
399
|
} }
|
|
108
|
-
function
|
|
109
|
-
i0.ɵɵ
|
|
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
|
|
112
|
-
i0.ɵɵproperty("
|
|
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
|
|
115
|
-
i0.ɵɵ
|
|
116
|
-
|
|
117
|
-
i0.ɵɵ
|
|
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
|
|
439
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
121
440
|
i0.ɵɵadvance(2);
|
|
122
|
-
i0.ɵɵconditional(
|
|
441
|
+
i0.ɵɵconditional(ctx_r0.removeTotal > 0 ? 2 : -1);
|
|
123
442
|
} }
|
|
124
|
-
function
|
|
125
|
-
i0.ɵɵelementStart(0, "div",
|
|
126
|
-
i0.ɵɵelement(1, "span",
|
|
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",
|
|
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
|
|
457
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
139
458
|
i0.ɵɵadvance(5);
|
|
140
|
-
i0.ɵɵtextInterpolate(
|
|
459
|
+
i0.ɵɵtextInterpolate(ctx_r0.selectedKeys.length);
|
|
141
460
|
i0.ɵɵadvance();
|
|
142
|
-
i0.ɵɵtextInterpolate1(" record",
|
|
461
|
+
i0.ɵɵtextInterpolate1(" record", ctx_r0.selectedKeys.length !== 1 ? "s" : "", " from this list?");
|
|
143
462
|
} }
|
|
144
|
-
function
|
|
145
|
-
const
|
|
146
|
-
i0.ɵɵelementStart(0, "mj-dialog",
|
|
147
|
-
i0.ɵɵlistener("Close", function
|
|
148
|
-
i0.ɵɵelementStart(1, "div",
|
|
149
|
-
i0.ɵɵconditionalCreate(2,
|
|
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",
|
|
152
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
156
|
-
i0.ɵɵlistener("click", function
|
|
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
|
|
479
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
161
480
|
i0.ɵɵproperty("Visible", true)("MinWidth", 350)("Width", 450);
|
|
162
481
|
i0.ɵɵadvance(2);
|
|
163
|
-
i0.ɵɵconditional(
|
|
482
|
+
i0.ɵɵconditional(ctx_r0.isRemoving ? 2 : 3);
|
|
164
483
|
i0.ɵɵadvance(3);
|
|
165
|
-
i0.ɵɵproperty("disabled",
|
|
484
|
+
i0.ɵɵproperty("disabled", ctx_r0.isRemoving);
|
|
166
485
|
i0.ɵɵadvance(2);
|
|
167
|
-
i0.ɵɵproperty("disabled",
|
|
486
|
+
i0.ɵɵproperty("disabled", ctx_r0.isRemoving);
|
|
168
487
|
} }
|
|
169
|
-
function
|
|
170
|
-
i0.ɵɵelement(0, "mj-progress-bar",
|
|
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
|
|
173
|
-
i0.ɵɵproperty("Value",
|
|
491
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
492
|
+
i0.ɵɵproperty("Value", ctx_r0.addProgressPercent);
|
|
174
493
|
} }
|
|
175
|
-
function
|
|
176
|
-
i0.ɵɵelementStart(0, "div",
|
|
177
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
178
|
-
i0.ɵɵconditionalCreate(2,
|
|
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
|
|
500
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
182
501
|
i0.ɵɵadvance(2);
|
|
183
|
-
i0.ɵɵconditional(
|
|
502
|
+
i0.ɵɵconditional(ctx_r0.addTotal > 0 ? 2 : -1);
|
|
184
503
|
} }
|
|
185
|
-
function
|
|
186
|
-
i0.ɵɵelementStart(0, "div",
|
|
187
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
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
|
|
194
|
-
i0.ɵɵelementStart(0, "div",
|
|
195
|
-
i0.ɵɵelement(1, "span",
|
|
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
|
|
519
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
201
520
|
i0.ɵɵadvance(3);
|
|
202
|
-
i0.ɵɵtextInterpolate1("No records found matching \"",
|
|
521
|
+
i0.ɵɵtextInterpolate1("No records found matching \"", ctx_r0.addRecordsSearchFilter, "\"");
|
|
203
522
|
} }
|
|
204
|
-
function
|
|
205
|
-
i0.ɵɵelementStart(0, "div",
|
|
206
|
-
i0.ɵɵelement(1, "span",
|
|
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
|
|
212
|
-
i0.ɵɵelement(0, "span",
|
|
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
|
|
215
|
-
const
|
|
216
|
-
i0.ɵɵelementStart(0, "input",
|
|
217
|
-
i0.ɵɵlistener("click", function
|
|
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
|
|
221
|
-
i0.ɵɵproperty("checked",
|
|
539
|
+
const record_r18 = i0.ɵɵnextContext().$implicit;
|
|
540
|
+
i0.ɵɵproperty("checked", record_r18.isSelected);
|
|
222
541
|
} }
|
|
223
|
-
function
|
|
224
|
-
i0.ɵɵelementStart(0, "span",
|
|
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
|
|
229
|
-
const
|
|
230
|
-
i0.ɵɵelementStart(0, "div",
|
|
231
|
-
i0.ɵɵlistener("click", function
|
|
232
|
-
i0.ɵɵelementStart(1, "div",
|
|
233
|
-
i0.ɵɵconditionalCreate(2,
|
|
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",
|
|
554
|
+
i0.ɵɵelementStart(4, "div", 81);
|
|
236
555
|
i0.ɵɵtext(5);
|
|
237
556
|
i0.ɵɵelementEnd();
|
|
238
|
-
i0.ɵɵconditionalCreate(6,
|
|
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
|
|
242
|
-
i0.ɵɵclassProp("in-list",
|
|
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(
|
|
563
|
+
i0.ɵɵconditional(record_r18.isInList ? 2 : 3);
|
|
245
564
|
i0.ɵɵadvance(3);
|
|
246
|
-
i0.ɵɵtextInterpolate(
|
|
565
|
+
i0.ɵɵtextInterpolate(record_r18.Name);
|
|
247
566
|
i0.ɵɵadvance();
|
|
248
|
-
i0.ɵɵconditional(
|
|
567
|
+
i0.ɵɵconditional(record_r18.isInList ? 6 : -1);
|
|
249
568
|
} }
|
|
250
|
-
function
|
|
251
|
-
const
|
|
252
|
-
i0.ɵɵelementStart(0, "div",
|
|
253
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
257
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
579
|
+
i0.ɵɵelementStart(5, "span", 98);
|
|
261
580
|
i0.ɵɵtext(6);
|
|
262
581
|
i0.ɵɵelementEnd()();
|
|
263
|
-
i0.ɵɵelementStart(7, "div",
|
|
264
|
-
i0.ɵɵrepeaterCreate(8,
|
|
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
|
|
586
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
268
587
|
i0.ɵɵadvance(6);
|
|
269
|
-
i0.ɵɵtextInterpolate1("",
|
|
588
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.selectedAddableRecords.length, " selected");
|
|
270
589
|
i0.ɵɵadvance(2);
|
|
271
|
-
i0.ɵɵrepeater(
|
|
590
|
+
i0.ɵɵrepeater(ctx_r0.addableRecords);
|
|
272
591
|
} }
|
|
273
|
-
function
|
|
274
|
-
const
|
|
275
|
-
i0.ɵɵelementStart(0, "div",
|
|
276
|
-
i0.ɵɵelement(2, "span",
|
|
277
|
-
i0.ɵɵelementStart(3, "input",
|
|
278
|
-
i0.ɵɵlistener("input", function
|
|
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",
|
|
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",
|
|
284
|
-
i0.ɵɵconditionalCreate(7,
|
|
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
|
|
606
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
288
607
|
i0.ɵɵadvance(3);
|
|
289
|
-
i0.ɵɵproperty("placeholder", "Search " + ((
|
|
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(
|
|
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
|
|
294
|
-
const
|
|
295
|
-
i0.ɵɵelementStart(0, "mj-dialog",
|
|
296
|
-
i0.ɵɵlistener("Close", function
|
|
297
|
-
i0.ɵɵelementStart(1, "div",
|
|
298
|
-
i0.ɵɵconditionalCreate(2,
|
|
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",
|
|
301
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
305
|
-
i0.ɵɵlistener("click", function
|
|
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
|
|
310
|
-
i0.ɵɵproperty("Visible", true)("Title", "Add " + ((
|
|
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(
|
|
631
|
+
i0.ɵɵconditional(ctx_r0.addDialogSaving ? 2 : 3);
|
|
313
632
|
i0.ɵɵadvance(3);
|
|
314
|
-
i0.ɵɵproperty("disabled",
|
|
633
|
+
i0.ɵɵproperty("disabled", ctx_r0.addDialogSaving || ctx_r0.selectedAddableRecords.length === 0);
|
|
315
634
|
i0.ɵɵadvance();
|
|
316
|
-
i0.ɵɵtextInterpolate2(" Add ",
|
|
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",
|
|
637
|
+
i0.ɵɵproperty("disabled", ctx_r0.addDialogSaving);
|
|
319
638
|
} }
|
|
320
|
-
function
|
|
321
|
-
i0.ɵɵ
|
|
322
|
-
i0.ɵɵ
|
|
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
|
|
326
|
-
i0.ɵɵ
|
|
327
|
-
i0.ɵɵ
|
|
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
|
|
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("
|
|
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
|
|
335
|
-
i0.ɵɵelementStart(0, "div",
|
|
336
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
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
|
|
340
|
-
i0.ɵɵelementStart(0, "div",
|
|
341
|
-
i0.ɵɵelement(1, "span",
|
|
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
|
|
347
|
-
const
|
|
348
|
-
i0.ɵɵelementStart(0, "div",
|
|
349
|
-
i0.ɵɵlistener("click", function
|
|
350
|
-
i0.ɵɵelementStart(1, "input",
|
|
351
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
354
|
-
i0.ɵɵelementStart(3, "span",
|
|
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
|
|
359
|
-
const
|
|
360
|
-
i0.ɵɵclassProp("selected",
|
|
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",
|
|
794
|
+
i0.ɵɵproperty("checked", ctx_r0.isViewSelected(view_r25));
|
|
363
795
|
i0.ɵɵadvance(3);
|
|
364
|
-
i0.ɵɵtextInterpolate(
|
|
796
|
+
i0.ɵɵtextInterpolate(view_r25.Name);
|
|
365
797
|
} }
|
|
366
|
-
function
|
|
367
|
-
i0.ɵɵrepeaterCreate(0,
|
|
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
|
|
370
|
-
i0.ɵɵrepeater(
|
|
801
|
+
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
802
|
+
i0.ɵɵrepeater(ctx_r0.userViews);
|
|
371
803
|
} }
|
|
372
|
-
function
|
|
373
|
-
i0.ɵɵelementStart(0, "p",
|
|
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",
|
|
377
|
-
i0.ɵɵconditionalCreate(3,
|
|
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
|
|
812
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
381
813
|
i0.ɵɵadvance(3);
|
|
382
|
-
i0.ɵɵconditional(!
|
|
814
|
+
i0.ɵɵconditional(!ctx_r0.userViews || ctx_r0.userViews.length === 0 ? 3 : 4);
|
|
383
815
|
} }
|
|
384
|
-
function
|
|
385
|
-
const
|
|
386
|
-
i0.ɵɵelementStart(0, "mj-dialog",
|
|
387
|
-
i0.ɵɵlistener("Close", function
|
|
388
|
-
i0.ɵɵelementStart(1, "div",
|
|
389
|
-
i0.ɵɵconditionalCreate(2,
|
|
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",
|
|
392
|
-
i0.ɵɵlistener("click", function
|
|
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",
|
|
396
|
-
i0.ɵɵlistener("click", function
|
|
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
|
|
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(
|
|
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",
|
|
837
|
+
i0.ɵɵproperty("disabled", ctx_r0.showAddFromViewLoader || ctx_r0.userViewsToAdd.length === 0);
|
|
406
838
|
i0.ɵɵadvance();
|
|
407
|
-
i0.ɵɵtextInterpolate2(" Add from ",
|
|
839
|
+
i0.ɵɵtextInterpolate2(" Add from ", ctx_r0.userViewsToAdd.length, " View", ctx_r0.userViewsToAdd.length !== 1 ? "s" : "", " ");
|
|
408
840
|
i0.ɵɵadvance();
|
|
409
|
-
i0.ɵɵproperty("disabled",
|
|
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
|
-
|
|
991
|
+
ngOnInit() {
|
|
492
992
|
if (this.ListID) {
|
|
493
|
-
|
|
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
|
-
|
|
506
|
-
|
|
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,
|
|
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
|
-
|
|
554
|
-
|
|
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
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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:
|
|
917
|
-
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "
|
|
918
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
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,
|
|
927
|
-
i0.ɵɵ
|
|
928
|
-
i0.ɵɵconditionalCreate(
|
|
929
|
-
i0.ɵɵ
|
|
930
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
933
|
-
i0.ɵɵ
|
|
934
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
938
|
-
i0.ɵɵadvance(
|
|
939
|
-
i0.ɵɵconditional(ctx.
|
|
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.ɵɵ
|
|
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.
|
|
2151
|
+
i0.ɵɵconditional(ctx.showMoveCopyDialog ? 14 : -1);
|
|
944
2152
|
i0.ɵɵadvance();
|
|
945
|
-
i0.ɵɵconditional(
|
|
2153
|
+
i0.ɵɵconditional(ctx.showRemoveDialog ? 15 : -1);
|
|
946
2154
|
i0.ɵɵadvance();
|
|
947
|
-
i0.ɵɵconditional(ctx.
|
|
2155
|
+
i0.ɵɵconditional(ctx.showAddRecordsDialog ? 16 : -1);
|
|
948
2156
|
i0.ɵɵadvance();
|
|
949
|
-
i0.ɵɵconditional(ctx.
|
|
2157
|
+
i0.ɵɵconditional(ctx.showExportDialog && ctx.listRecord ? 17 : -1);
|
|
950
2158
|
i0.ɵɵadvance();
|
|
951
|
-
i0.ɵɵconditional(ctx.showAddFromViewDialog ?
|
|
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:
|
|
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
|