@memberjunction/ng-record-changes 4.2.0 → 4.3.1

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.
@@ -9,8 +9,9 @@ import * as i4 from "@memberjunction/ng-shared-generic";
9
9
  import * as i5 from "@memberjunction/ng-versions";
10
10
  const _c0 = a0 => [a0];
11
11
  const _forTrack0 = ($index, $item) => $item.ID;
12
- const _forTrack1 = ($index, $item) => $item.name;
13
- const _forTrack2 = ($index, $item) => $item.field;
12
+ const _forTrack1 = ($index, $item) => $item.label;
13
+ const _forTrack2 = ($index, $item) => $item.name;
14
+ const _forTrack3 = ($index, $item) => $item.field;
14
15
  function RecordChangesComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
15
16
  i0.ɵɵelement(0, "mj-loading", 1);
16
17
  } }
@@ -84,339 +85,328 @@ function RecordChangesComponent_Conditional_2_Conditional_14_Template(rf, ctx) {
84
85
  i0.ɵɵtext(10, "Record change tracking is managed at the entity level");
85
86
  i0.ɵɵelementEnd()()();
86
87
  } }
87
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Template(rf, ctx) { if (rf & 1) {
88
- i0.ɵɵelementStart(0, "div", 39);
88
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_28_Template(rf, ctx) { if (rf & 1) {
89
+ const _r5 = i0.ɵɵgetCurrentView();
90
+ i0.ɵɵelementStart(0, "div", 44);
89
91
  i0.ɵɵtext(1);
90
- i0.ɵɵelementEnd();
92
+ i0.ɵɵelementStart(2, "button", 47);
93
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_28_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ClearFilters()); });
94
+ i0.ɵɵtext(3, "Clear filters");
95
+ i0.ɵɵelementEnd()();
91
96
  } if (rf & 2) {
92
97
  const ctx_r1 = i0.ɵɵnextContext(3);
93
98
  i0.ɵɵadvance();
94
99
  i0.ɵɵtextInterpolate2(" Showing ", ctx_r1.filteredData.length, " of ", ctx_r1.viewData.length, " changes ");
95
100
  } }
96
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_21_Template(rf, ctx) { if (rf & 1) {
97
- const _r5 = i0.ɵɵgetCurrentView();
98
- i0.ɵɵelementStart(0, "div", 41);
99
- i0.ɵɵelement(1, "i", 43);
101
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_30_Template(rf, ctx) { if (rf & 1) {
102
+ const _r6 = i0.ɵɵgetCurrentView();
103
+ i0.ɵɵelementStart(0, "div", 46);
104
+ i0.ɵɵelement(1, "i", 48);
100
105
  i0.ɵɵelementStart(2, "p");
101
106
  i0.ɵɵtext(3, "No changes match your current filters.");
102
107
  i0.ɵɵelementEnd();
103
- i0.ɵɵelementStart(4, "button", 44);
104
- i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_21_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ClearFilters()); });
105
- i0.ɵɵelement(5, "i", 45);
108
+ i0.ɵɵelementStart(4, "button", 49);
109
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_30_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ClearFilters()); });
110
+ i0.ɵɵelement(5, "i", 50);
106
111
  i0.ɵɵtext(6, " Clear Filters ");
107
112
  i0.ɵɵelementEnd()();
108
113
  } }
109
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
110
- i0.ɵɵelement(0, "div", 50);
111
- } }
112
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
113
- i0.ɵɵelementStart(0, "span", 60);
114
- i0.ɵɵtext(1);
115
- i0.ɵɵelementEnd();
116
- } if (rf & 2) {
117
- const change_r7 = i0.ɵɵnextContext().$implicit;
118
- i0.ɵɵadvance();
119
- i0.ɵɵtextInterpolate1(" via ", change_r7.Integration, " ");
120
- } }
121
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_20_Template(rf, ctx) { if (rf & 1) {
122
- i0.ɵɵelementStart(0, "div", 61);
123
- i0.ɵɵtext(1);
124
- i0.ɵɵelementEnd();
125
- } if (rf & 2) {
126
- const change_r7 = i0.ɵɵnextContext().$implicit;
127
- const ctx_r1 = i0.ɵɵnextContext(4);
128
- i0.ɵɵadvance();
129
- i0.ɵɵtextInterpolate1(" ", ctx_r1.getChangeSummary(change_r7), " ");
130
- } }
131
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
132
- i0.ɵɵelementStart(0, "div", 71)(1, "span", 72);
114
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Conditional_0_For_1_Template(rf, ctx) { if (rf & 1) {
115
+ i0.ɵɵelementStart(0, "div", 70)(1, "div", 71);
133
116
  i0.ɵɵtext(2);
134
117
  i0.ɵɵelementEnd();
135
- i0.ɵɵelementStart(3, "span", 73);
136
- i0.ɵɵtext(4);
137
- i0.ɵɵelementEnd()();
118
+ i0.ɵɵelementStart(3, "div", 72)(4, "span", 73);
119
+ i0.ɵɵtext(5);
120
+ i0.ɵɵelementEnd()()();
138
121
  } if (rf & 2) {
139
- const field_r8 = ctx.$implicit;
140
- i0.ɵɵadvance(2);
141
- i0.ɵɵtextInterpolate(field_r8.displayName);
122
+ const field_r9 = ctx.$implicit;
142
123
  i0.ɵɵadvance(2);
143
- i0.ɵɵtextInterpolate(field_r8.value);
124
+ i0.ɵɵtextInterpolate(field_r9.displayName);
125
+ i0.ɵɵadvance(3);
126
+ i0.ɵɵtextInterpolate(field_r9.value);
144
127
  } }
145
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
146
- i0.ɵɵelementStart(0, "div", 70);
147
- i0.ɵɵrepeaterCreate(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Conditional_4_For_2_Template, 5, 2, "div", 71, _forTrack1);
148
- i0.ɵɵelementEnd();
128
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
129
+ i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Conditional_0_For_1_Template, 6, 2, "div", 70, _forTrack2);
149
130
  } if (rf & 2) {
150
- const change_r7 = i0.ɵɵnextContext(3).$implicit;
151
- const ctx_r1 = i0.ɵɵnextContext(4);
152
- i0.ɵɵadvance();
153
- i0.ɵɵrepeater(ctx_r1.getCreatedFields(change_r7));
131
+ const change_r8 = i0.ɵɵnextContext(3).$implicit;
132
+ const ctx_r1 = i0.ɵɵnextContext(5);
133
+ i0.ɵɵrepeater(ctx_r1.getCreatedFields(change_r8));
154
134
  } }
155
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Template(rf, ctx) { if (rf & 1) {
156
- i0.ɵɵelementStart(0, "div", 65)(1, "h4");
157
- i0.ɵɵelement(2, "i", 10);
158
- i0.ɵɵtext(3, " Record Created");
159
- i0.ɵɵelementEnd();
160
- i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Conditional_4_Template, 3, 0, "div", 70);
161
- i0.ɵɵelementEnd();
135
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
136
+ i0.ɵɵconditionalCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Conditional_0_Template, 2, 0);
162
137
  } if (rf & 2) {
163
- const change_r7 = i0.ɵɵnextContext(2).$implicit;
164
- i0.ɵɵadvance(4);
165
- i0.ɵɵconditional(change_r7.FullRecordJSON ? 4 : -1);
138
+ const change_r8 = i0.ɵɵnextContext(2).$implicit;
139
+ i0.ɵɵconditional(change_r8.FullRecordJSON ? 0 : -1);
166
140
  } }
167
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_6_Template(rf, ctx) { if (rf & 1) {
168
- i0.ɵɵelementStart(0, "div", 66)(1, "h4");
169
- i0.ɵɵelement(2, "i", 74);
170
- i0.ɵɵtext(3, " Record Deleted");
141
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_2_Template(rf, ctx) { if (rf & 1) {
142
+ i0.ɵɵelementStart(0, "div", 67);
143
+ i0.ɵɵelement(1, "i", 43);
144
+ i0.ɵɵtext(2, " This record was permanently removed from the system. ");
171
145
  i0.ɵɵelementEnd();
172
- i0.ɵɵelementStart(4, "p", 75);
173
- i0.ɵɵtext(5, "This record was permanently removed from the system.");
146
+ } }
147
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
148
+ i0.ɵɵelementStart(0, "div", 74);
149
+ i0.ɵɵelement(1, "span", 77);
150
+ i0.ɵɵelementStart(2, "span", 78);
151
+ i0.ɵɵtext(3);
152
+ i0.ɵɵelementEnd();
153
+ i0.ɵɵelement(4, "i", 79)(5, "span", 77);
154
+ i0.ɵɵelementStart(6, "span", 80);
155
+ i0.ɵɵtext(7);
174
156
  i0.ɵɵelementEnd()();
157
+ } if (rf & 2) {
158
+ const fc_r10 = i0.ɵɵnextContext().$implicit;
159
+ i0.ɵɵadvance();
160
+ i0.ɵɵclassProp("on", fc_r10.oldValue === "true" || fc_r10.oldValue === "1")("off", fc_r10.oldValue !== "true" && fc_r10.oldValue !== "1");
161
+ i0.ɵɵadvance(2);
162
+ i0.ɵɵtextInterpolate(fc_r10.oldValue === "true" || fc_r10.oldValue === "1" ? "Yes" : "No");
163
+ i0.ɵɵadvance(2);
164
+ i0.ɵɵclassProp("on", fc_r10.newValue === "true" || fc_r10.newValue === "1")("off", fc_r10.newValue !== "true" && fc_r10.newValue !== "1");
165
+ i0.ɵɵadvance();
166
+ i0.ɵɵclassProp("active", fc_r10.newValue === "true" || fc_r10.newValue === "1")("inactive", fc_r10.newValue !== "true" && fc_r10.newValue !== "1");
167
+ i0.ɵɵadvance();
168
+ i0.ɵɵtextInterpolate(fc_r10.newValue === "true" || fc_r10.newValue === "1" ? "Yes" : "No");
175
169
  } }
176
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_3_Template(rf, ctx) { if (rf & 1) {
177
- i0.ɵɵelementStart(0, "div", 78)(1, "span", 81);
170
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
171
+ i0.ɵɵelementStart(0, "div", 75)(1, "span", 81);
178
172
  i0.ɵɵtext(2);
173
+ i0.ɵɵelementEnd();
174
+ i0.ɵɵelement(3, "i", 79);
175
+ i0.ɵɵelementStart(4, "span", 73);
176
+ i0.ɵɵtext(5);
179
177
  i0.ɵɵelementEnd()();
180
178
  } if (rf & 2) {
181
- const fieldChange_r9 = i0.ɵɵnextContext().$implicit;
179
+ const fc_r10 = i0.ɵɵnextContext().$implicit;
182
180
  i0.ɵɵadvance(2);
183
- i0.ɵɵtextInterpolate(fieldChange_r9.newValue);
181
+ i0.ɵɵtextInterpolate(fc_r10.oldValue || "(empty)");
182
+ i0.ɵɵadvance(3);
183
+ i0.ɵɵtextInterpolate(fc_r10.newValue || "(empty)");
184
184
  } }
185
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_4_Template(rf, ctx) { if (rf & 1) {
186
- i0.ɵɵelementStart(0, "div", 79);
187
- i0.ɵɵelement(1, "div", 82);
188
- i0.ɵɵelementEnd();
185
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
186
+ i0.ɵɵelement(0, "div", 76);
189
187
  } if (rf & 2) {
190
- const fieldChange_r9 = i0.ɵɵnextContext().$implicit;
191
- i0.ɵɵadvance();
192
- i0.ɵɵproperty("innerHTML", fieldChange_r9.diffHtml, i0.ɵɵsanitizeHtml);
188
+ const fc_r10 = i0.ɵɵnextContext().$implicit;
189
+ i0.ɵɵproperty("innerHTML", fc_r10.diffHtml, i0.ɵɵsanitizeHtml);
193
190
  } }
194
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
195
- i0.ɵɵelementStart(0, "div", 80)(1, "div", 83)(2, "span", 84);
196
- i0.ɵɵtext(3, "From:");
191
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
192
+ i0.ɵɵelementStart(0, "div", 75)(1, "span", 81);
193
+ i0.ɵɵtext(2);
197
194
  i0.ɵɵelementEnd();
198
- i0.ɵɵelementStart(4, "span", 85);
195
+ i0.ɵɵelement(3, "i", 79);
196
+ i0.ɵɵelementStart(4, "span", 73);
199
197
  i0.ɵɵtext(5);
200
198
  i0.ɵɵelementEnd()();
201
- i0.ɵɵelementStart(6, "div", 86);
202
- i0.ɵɵelement(7, "i", 87);
203
- i0.ɵɵelementEnd();
204
- i0.ɵɵelementStart(8, "div", 81)(9, "span", 84);
205
- i0.ɵɵtext(10, "To:");
206
- i0.ɵɵelementEnd();
207
- i0.ɵɵelementStart(11, "span", 85);
208
- i0.ɵɵtext(12);
209
- i0.ɵɵelementEnd()()();
210
199
  } if (rf & 2) {
211
- const fieldChange_r9 = i0.ɵɵnextContext().$implicit;
212
- i0.ɵɵadvance(5);
213
- i0.ɵɵtextInterpolate(fieldChange_r9.oldValue || "(empty)");
214
- i0.ɵɵadvance(7);
215
- i0.ɵɵtextInterpolate(fieldChange_r9.newValue || "(empty)");
200
+ const fc_r10 = i0.ɵɵnextContext().$implicit;
201
+ i0.ɵɵadvance(2);
202
+ i0.ɵɵtextInterpolate(fc_r10.oldValue || "(empty)");
203
+ i0.ɵɵadvance(3);
204
+ i0.ɵɵtextInterpolate(fc_r10.newValue || "(empty)");
216
205
  } }
217
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Template(rf, ctx) { if (rf & 1) {
218
- i0.ɵɵelementStart(0, "div", 77)(1, "div", 72);
206
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Template(rf, ctx) { if (rf & 1) {
207
+ i0.ɵɵelementStart(0, "div", 70)(1, "div", 71);
219
208
  i0.ɵɵtext(2);
220
209
  i0.ɵɵelementEnd();
221
- i0.ɵɵconditionalCreate(3, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_3_Template, 3, 1, "div", 78)(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_4_Template, 2, 1, "div", 79)(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Conditional_5_Template, 13, 2, "div", 80);
222
- i0.ɵɵelementEnd();
210
+ i0.ɵɵelementStart(3, "div", 72);
211
+ i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_4_Template, 8, 14, "div", 74)(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_5_Template, 6, 2, "div", 75)(6, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_6_Template, 1, 1, "div", 76)(7, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Conditional_7_Template, 6, 2, "div", 75);
212
+ i0.ɵɵelementEnd()();
223
213
  } if (rf & 2) {
224
- const fieldChange_r9 = ctx.$implicit;
214
+ const fc_r10 = ctx.$implicit;
225
215
  i0.ɵɵadvance(2);
226
- i0.ɵɵtextInterpolate(fieldChange_r9.displayName);
227
- i0.ɵɵadvance();
228
- i0.ɵɵconditional(fieldChange_r9.isBooleanField ? 3 : fieldChange_r9.diffHtml ? 4 : 5);
216
+ i0.ɵɵtextInterpolate(fc_r10.displayName);
217
+ i0.ɵɵadvance(2);
218
+ i0.ɵɵconditional(fc_r10.fieldType === "boolean" ? 4 : fc_r10.fieldType === "date" || fc_r10.fieldType === "number" ? 5 : fc_r10.diffHtml ? 6 : 7);
229
219
  } }
230
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_Template(rf, ctx) { if (rf & 1) {
231
- i0.ɵɵelementStart(0, "div", 67)(1, "h4");
232
- i0.ɵɵelement(2, "i", 76);
233
- i0.ɵɵtext(3, " Fields Changed");
234
- i0.ɵɵelementEnd();
235
- i0.ɵɵelementStart(4, "div", 70);
236
- i0.ɵɵrepeaterCreate(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_For_6_Template, 6, 2, "div", 77, _forTrack2);
237
- i0.ɵɵelementEnd()();
220
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_Template(rf, ctx) { if (rf & 1) {
221
+ i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_For_1_Template, 8, 2, "div", 70, _forTrack3);
238
222
  } if (rf & 2) {
239
- const change_r7 = i0.ɵɵnextContext(2).$implicit;
240
- const ctx_r1 = i0.ɵɵnextContext(4);
241
- i0.ɵɵadvance(5);
242
- i0.ɵɵrepeater(ctx_r1.getFieldChanges(change_r7));
223
+ const change_r8 = i0.ɵɵnextContext(2).$implicit;
224
+ const ctx_r1 = i0.ɵɵnextContext(5);
225
+ i0.ɵɵrepeater(ctx_r1.getFieldChanges(change_r8));
243
226
  } }
244
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_8_Template(rf, ctx) { if (rf & 1) {
245
- i0.ɵɵelementStart(0, "div", 68)(1, "h5");
246
- i0.ɵɵelement(2, "i", 88);
247
- i0.ɵɵtext(3, " Comments");
227
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_4_Template(rf, ctx) { if (rf & 1) {
228
+ i0.ɵɵelementStart(0, "div", 68);
229
+ i0.ɵɵelement(1, "i", 82);
230
+ i0.ɵɵtext(2);
248
231
  i0.ɵɵelementEnd();
249
- i0.ɵɵelementStart(4, "p");
250
- i0.ɵɵtext(5);
251
- i0.ɵɵelementEnd()();
252
232
  } if (rf & 2) {
253
- const change_r7 = i0.ɵɵnextContext(2).$implicit;
254
- i0.ɵɵadvance(5);
255
- i0.ɵɵtextInterpolate(change_r7.Comments);
233
+ const change_r8 = i0.ɵɵnextContext(2).$implicit;
234
+ i0.ɵɵadvance(2);
235
+ i0.ɵɵtextInterpolate1(" ", change_r8.Comments, " ");
256
236
  } }
257
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_9_Template(rf, ctx) { if (rf & 1) {
258
- i0.ɵɵelementStart(0, "div", 69)(1, "h5");
259
- i0.ɵɵelement(2, "i", 89);
260
- i0.ɵɵtext(3, " Errors");
261
- i0.ɵɵelementEnd();
262
- i0.ɵɵelementStart(4, "pre", 90);
263
- i0.ɵɵtext(5);
237
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_5_Template(rf, ctx) { if (rf & 1) {
238
+ i0.ɵɵelementStart(0, "div", 69);
239
+ i0.ɵɵelement(1, "i", 83);
240
+ i0.ɵɵelementStart(2, "pre", 84);
241
+ i0.ɵɵtext(3);
264
242
  i0.ɵɵelementEnd()();
265
243
  } if (rf & 2) {
266
- const change_r7 = i0.ɵɵnextContext(2).$implicit;
267
- i0.ɵɵadvance(5);
268
- i0.ɵɵtextInterpolate(change_r7.ErrorLog);
244
+ const change_r8 = i0.ɵɵnextContext(2).$implicit;
245
+ i0.ɵɵadvance(3);
246
+ i0.ɵɵtextInterpolate(change_r8.ErrorLog);
269
247
  } }
270
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Template(rf, ctx) { if (rf & 1) {
271
- i0.ɵɵelementStart(0, "div", 62)(1, "div", 63);
272
- i0.ɵɵelement(2, "i", 64);
273
- i0.ɵɵelementStart(3, "strong");
274
- i0.ɵɵtext(4);
275
- i0.ɵɵelementEnd()();
276
- i0.ɵɵconditionalCreate(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_5_Template, 5, 1, "div", 65)(6, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_6_Template, 6, 0, "div", 66)(7, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_7_Template, 7, 0, "div", 67);
277
- i0.ɵɵconditionalCreate(8, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_8_Template, 6, 1, "div", 68);
278
- i0.ɵɵconditionalCreate(9, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Conditional_9_Template, 6, 1, "div", 69);
248
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Template(rf, ctx) { if (rf & 1) {
249
+ i0.ɵɵelementStart(0, "div", 66);
250
+ i0.ɵɵconditionalCreate(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_1_Template, 1, 1)(2, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_2_Template, 3, 0, "div", 67)(3, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_3_Template, 2, 0);
251
+ i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_4_Template, 3, 1, "div", 68);
252
+ i0.ɵɵconditionalCreate(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Conditional_5_Template, 4, 1, "div", 69);
279
253
  i0.ɵɵelementEnd();
280
254
  } if (rf & 2) {
281
- const change_r7 = i0.ɵɵnextContext().$implicit;
282
- const ctx_r1 = i0.ɵɵnextContext(4);
283
- i0.ɵɵadvance(4);
284
- i0.ɵɵtextInterpolate(ctx_r1.formatFullDateTime(change_r7.ChangedAt));
255
+ const change_r8 = i0.ɵɵnextContext().$implicit;
285
256
  i0.ɵɵadvance();
286
- i0.ɵɵconditional(change_r7.Type === "Create" ? 5 : change_r7.Type === "Delete" ? 6 : 7);
257
+ i0.ɵɵconditional(change_r8.Type === "Create" ? 1 : change_r8.Type === "Delete" ? 2 : 3);
287
258
  i0.ɵɵadvance(3);
288
- i0.ɵɵconditional(change_r7.Comments ? 8 : -1);
259
+ i0.ɵɵconditional(change_r8.Comments ? 4 : -1);
289
260
  i0.ɵɵadvance();
290
- i0.ɵɵconditional(change_r7.ErrorLog ? 9 : -1);
261
+ i0.ɵɵconditional(change_r8.ErrorLog ? 5 : -1);
291
262
  } }
292
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Template(rf, ctx) { if (rf & 1) {
293
- const _r6 = i0.ɵɵgetCurrentView();
294
- i0.ɵɵelementStart(0, "div", 47);
295
- i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Template_div_click_0_listener() { const change_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.toggleExpansion(change_r7.ID)); })("keydown", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Template_div_keydown_0_listener($event) { const change_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.onTimelineItemKeydown($event, change_r7.ID)); });
296
- i0.ɵɵelementStart(1, "div", 48)(2, "div", 49);
297
- i0.ɵɵelement(3, "i");
298
- i0.ɵɵelementEnd();
299
- i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_4_Template, 1, 0, "div", 50);
263
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Template(rf, ctx) { if (rf & 1) {
264
+ const _r7 = i0.ɵɵgetCurrentView();
265
+ i0.ɵɵelementStart(0, "div", 54);
266
+ i0.ɵɵlistener("keydown", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Template_div_keydown_0_listener($event) { const change_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onTimelineItemKeydown($event, change_r8.ID)); });
267
+ i0.ɵɵelementStart(1, "div", 55);
268
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Template_div_click_1_listener() { const change_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.toggleExpansion(change_r8.ID)); });
269
+ i0.ɵɵelementStart(2, "div", 56)(3, "span", 57);
270
+ i0.ɵɵtext(4);
300
271
  i0.ɵɵelementEnd();
301
- i0.ɵɵelementStart(5, "div", 51)(6, "div", 52)(7, "div", 53)(8, "span", 54);
302
- i0.ɵɵtext(9);
272
+ i0.ɵɵelementStart(5, "span", 58);
273
+ i0.ɵɵtext(6);
274
+ i0.ɵɵelementEnd()();
275
+ i0.ɵɵelementStart(7, "div", 59)(8, "div", 60)(9, "div", 61);
276
+ i0.ɵɵtext(10);
303
277
  i0.ɵɵelementEnd();
304
- i0.ɵɵelementStart(10, "span", 55);
305
278
  i0.ɵɵtext(11);
306
279
  i0.ɵɵelementEnd();
307
- i0.ɵɵelementStart(12, "span", 56);
280
+ i0.ɵɵelementStart(12, "span", 62);
308
281
  i0.ɵɵtext(13);
309
- i0.ɵɵelementEnd()();
310
- i0.ɵɵelementStart(14, "div", 57)(15, "span", 58);
311
- i0.ɵɵtext(16);
312
282
  i0.ɵɵelementEnd();
313
- i0.ɵɵelementStart(17, "span", 59);
314
- i0.ɵɵtext(18);
283
+ i0.ɵɵelementStart(14, "span", 63);
284
+ i0.ɵɵtext(15);
315
285
  i0.ɵɵelementEnd();
316
- i0.ɵɵconditionalCreate(19, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_19_Template, 2, 1, "span", 60);
317
- i0.ɵɵelementEnd()();
318
- i0.ɵɵconditionalCreate(20, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_20_Template, 2, 1, "div", 61);
319
- i0.ɵɵconditionalCreate(21, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Conditional_21_Template, 10, 4, "div", 62);
286
+ i0.ɵɵelementStart(16, "span", 64);
287
+ i0.ɵɵtext(17);
288
+ i0.ɵɵelementEnd();
289
+ i0.ɵɵelement(18, "i", 65);
320
290
  i0.ɵɵelementEnd()();
291
+ i0.ɵɵconditionalCreate(19, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Conditional_19_Template, 6, 3, "div", 66);
292
+ i0.ɵɵelementEnd();
321
293
  } if (rf & 2) {
322
- const change_r7 = ctx.$implicit;
323
- const ɵ$index_132_r10 = ctx.$index;
324
- const ctx_r1 = i0.ɵɵnextContext(4);
325
- i0.ɵɵclassProp("expanded", ctx_r1.expandedItems.has(change_r7.ID));
326
- i0.ɵɵattribute("tabindex", 0)("aria-expanded", ctx_r1.expandedItems.has(change_r7.ID))("aria-label", ctx_r1.getTimelineItemLabel(change_r7));
327
- i0.ɵɵadvance(2);
328
- i0.ɵɵclassMap(ctx_r1.getChangeTypeClass(change_r7.Type));
329
- i0.ɵɵadvance();
330
- i0.ɵɵclassMap(ctx_r1.getChangeTypeIcon(change_r7.Type));
331
- i0.ɵɵattribute("aria-hidden", true);
332
- i0.ɵɵadvance();
333
- i0.ɵɵconditional(ɵ$index_132_r10 < ctx_r1.filteredData.length - 1 ? 4 : -1);
294
+ const change_r8 = ctx.$implicit;
295
+ const ctx_r1 = i0.ɵɵnextContext(5);
296
+ i0.ɵɵclassMap(ctx_r1.getChangeTypeCardClass(change_r8.Type));
297
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedItems.has(change_r8.ID));
298
+ i0.ɵɵattribute("tabindex", 0)("aria-expanded", ctx_r1.expandedItems.has(change_r8.ID))("aria-label", ctx_r1.getTimelineItemLabel(change_r8));
334
299
  i0.ɵɵadvance(4);
335
- i0.ɵɵclassMap(ctx_r1.getChangeTypeBadgeClass(change_r7.Type));
336
- i0.ɵɵadvance();
337
- i0.ɵɵtextInterpolate1(" ", change_r7.Type, " ");
300
+ i0.ɵɵtextInterpolate(ctx_r1.getChangeTypeBadgeText(change_r8.Type));
338
301
  i0.ɵɵadvance(2);
339
- i0.ɵɵtextInterpolate(change_r7.User || "Unknown User");
340
- i0.ɵɵadvance();
341
- i0.ɵɵclassMap(ctx_r1.getSourceClass(change_r7.Source));
302
+ i0.ɵɵtextInterpolate(ctx_r1.getChangeSummary(change_r8));
303
+ i0.ɵɵadvance(4);
304
+ i0.ɵɵtextInterpolate(ctx_r1.getUserInitials(change_r8.User));
342
305
  i0.ɵɵadvance();
343
- i0.ɵɵtextInterpolate1(" ", change_r7.Source, " ");
344
- i0.ɵɵadvance(2);
345
- i0.ɵɵproperty("title", ctx_r1.formatFullDateTime(change_r7.ChangedAt));
306
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.getUserDisplayName(change_r8.User), " ");
346
307
  i0.ɵɵadvance();
347
- i0.ɵɵtextInterpolate1(" ", ctx_r1.formatRelativeTime(change_r7.ChangedAt), " ");
308
+ i0.ɵɵproperty("title", ctx_r1.formatFullDateTime(change_r8.ChangedAt));
348
309
  i0.ɵɵadvance();
349
- i0.ɵɵclassMap(ctx_r1.getStatusClass(change_r7.Status));
310
+ i0.ɵɵtextInterpolate(ctx_r1.formatTime(change_r8.ChangedAt));
350
311
  i0.ɵɵadvance();
351
- i0.ɵɵtextInterpolate1(" ", change_r7.Status, " ");
312
+ i0.ɵɵclassMap(ctx_r1.getSourceClass(change_r8.Source));
352
313
  i0.ɵɵadvance();
353
- i0.ɵɵconditional(change_r7.Integration ? 19 : -1);
314
+ i0.ɵɵtextInterpolate(change_r8.Source);
354
315
  i0.ɵɵadvance();
355
- i0.ɵɵconditional(!ctx_r1.expandedItems.has(change_r7.ID) ? 20 : -1);
316
+ i0.ɵɵclassMap(ctx_r1.getStatusClass(change_r8.Status));
356
317
  i0.ɵɵadvance();
357
- i0.ɵɵconditional(ctx_r1.expandedItems.has(change_r7.ID) ? 21 : -1);
318
+ i0.ɵɵtextInterpolate(change_r8.Status);
319
+ i0.ɵɵadvance(2);
320
+ i0.ɵɵconditional(ctx_r1.expandedItems.has(change_r8.ID) ? 19 : -1);
358
321
  } }
359
- function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_Template(rf, ctx) { if (rf & 1) {
360
- i0.ɵɵelementStart(0, "div", 42);
361
- i0.ɵɵrepeaterCreate(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_For_2_Template, 22, 26, "div", 46, _forTrack0);
322
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_Template(rf, ctx) { if (rf & 1) {
323
+ i0.ɵɵelementStart(0, "div", 51)(1, "div", 52);
324
+ i0.ɵɵtext(2);
325
+ i0.ɵɵelementEnd();
326
+ i0.ɵɵrepeaterCreate(3, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_For_4_Template, 20, 20, "div", 53, _forTrack0);
362
327
  i0.ɵɵelementEnd();
363
328
  } if (rf & 2) {
364
- const ctx_r1 = i0.ɵɵnextContext(3);
329
+ const group_r11 = ctx.$implicit;
330
+ i0.ɵɵadvance(2);
331
+ i0.ɵɵtextInterpolate(group_r11.label);
365
332
  i0.ɵɵadvance();
366
- i0.ɵɵrepeater(ctx_r1.filteredData);
333
+ i0.ɵɵrepeater(group_r11.changes);
334
+ } }
335
+ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_Template(rf, ctx) { if (rf & 1) {
336
+ i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_For_1_Template, 5, 1, "div", 51, _forTrack1);
337
+ } if (rf & 2) {
338
+ const ctx_r1 = i0.ɵɵnextContext(3);
339
+ i0.ɵɵrepeater(ctx_r1.dateGroups);
367
340
  } }
368
341
  function RecordChangesComponent_Conditional_2_Conditional_15_Template(rf, ctx) { if (rf & 1) {
369
342
  const _r4 = i0.ɵɵgetCurrentView();
370
- i0.ɵɵelementStart(0, "div", 28)(1, "div", 29)(2, "input", 30);
371
- i0.ɵɵtwoWayListener("ngModelChange", function RecordChangesComponent_Conditional_2_Conditional_15_Template_input_ngModelChange_2_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.searchTerm, $event) || (ctx_r1.searchTerm = $event); return i0.ɵɵresetView($event); });
372
- i0.ɵɵlistener("input", function RecordChangesComponent_Conditional_2_Conditional_15_Template_input_input_2_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onSearchChange()); });
373
- i0.ɵɵelementEnd();
374
- i0.ɵɵelementStart(3, "select", 31);
375
- i0.ɵɵtwoWayListener("ngModelChange", function RecordChangesComponent_Conditional_2_Conditional_15_Template_select_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedType, $event) || (ctx_r1.selectedType = $event); return i0.ɵɵresetView($event); });
376
- i0.ɵɵlistener("change", function RecordChangesComponent_Conditional_2_Conditional_15_Template_select_change_3_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onFilterChange()); });
377
- i0.ɵɵelementStart(4, "option", 32);
378
- i0.ɵɵtext(5, "All Changes");
379
- i0.ɵɵelementEnd();
380
- i0.ɵɵelementStart(6, "option", 33);
381
- i0.ɵɵtext(7, "Created");
343
+ i0.ɵɵelementStart(0, "div", 28)(1, "div")(2, "h2", 29);
344
+ i0.ɵɵtext(3, "Change History");
382
345
  i0.ɵɵelementEnd();
383
- i0.ɵɵelementStart(8, "option", 34);
384
- i0.ɵɵtext(9, "Updated");
385
- i0.ɵɵelementEnd();
386
- i0.ɵɵelementStart(10, "option", 35);
387
- i0.ɵɵtext(11, "Deleted");
346
+ i0.ɵɵelementStart(4, "div", 30);
347
+ i0.ɵɵtext(5);
388
348
  i0.ɵɵelementEnd()();
389
- i0.ɵɵelementStart(12, "select", 36);
390
- i0.ɵɵtwoWayListener("ngModelChange", function RecordChangesComponent_Conditional_2_Conditional_15_Template_select_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.selectedSource, $event) || (ctx_r1.selectedSource = $event); return i0.ɵɵresetView($event); });
391
- i0.ɵɵlistener("change", function RecordChangesComponent_Conditional_2_Conditional_15_Template_select_change_12_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onFilterChange()); });
392
- i0.ɵɵelementStart(13, "option", 32);
393
- i0.ɵɵtext(14, "All Sources");
394
- i0.ɵɵelementEnd();
395
- i0.ɵɵelementStart(15, "option", 37);
396
- i0.ɵɵtext(16, "Internal");
349
+ i0.ɵɵelementStart(6, "div", 31)(7, "div", 32);
350
+ i0.ɵɵelement(8, "i", 33);
351
+ i0.ɵɵtext(9);
397
352
  i0.ɵɵelementEnd();
398
- i0.ɵɵelementStart(17, "option", 38);
399
- i0.ɵɵtext(18, "External");
353
+ i0.ɵɵelementStart(10, "div", 34);
354
+ i0.ɵɵtext(11);
400
355
  i0.ɵɵelementEnd()()();
401
- i0.ɵɵconditionalCreate(19, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Template, 2, 2, "div", 39);
402
- i0.ɵɵelementEnd();
403
- i0.ɵɵelementStart(20, "div", 40);
404
- i0.ɵɵconditionalCreate(21, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_21_Template, 7, 0, "div", 41)(22, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_Template, 3, 0, "div", 42);
356
+ i0.ɵɵelementStart(12, "div", 35)(13, "div", 36);
357
+ i0.ɵɵelement(14, "i", 37);
358
+ i0.ɵɵelementStart(15, "input", 38);
359
+ i0.ɵɵtwoWayListener("ngModelChange", function RecordChangesComponent_Conditional_2_Conditional_15_Template_input_ngModelChange_15_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.searchTerm, $event) || (ctx_r1.searchTerm = $event); return i0.ɵɵresetView($event); });
360
+ i0.ɵɵlistener("input", function RecordChangesComponent_Conditional_2_Conditional_15_Template_input_input_15_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onSearchChange()); });
361
+ i0.ɵɵelementEnd()();
362
+ i0.ɵɵelementStart(16, "button", 39);
363
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetTypeFilter("")); });
364
+ i0.ɵɵelement(17, "i", 40);
365
+ i0.ɵɵtext(18, " All ");
366
+ i0.ɵɵelementEnd();
367
+ i0.ɵɵelementStart(19, "button", 39);
368
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Template_button_click_19_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetTypeFilter("Update")); });
369
+ i0.ɵɵelement(20, "i", 41);
370
+ i0.ɵɵtext(21, " Updates ");
371
+ i0.ɵɵelementEnd();
372
+ i0.ɵɵelementStart(22, "button", 39);
373
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Template_button_click_22_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetTypeFilter("Create")); });
374
+ i0.ɵɵelement(23, "i", 42);
375
+ i0.ɵɵtext(24, " Creates ");
376
+ i0.ɵɵelementEnd();
377
+ i0.ɵɵelementStart(25, "button", 39);
378
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetTypeFilter("Delete")); });
379
+ i0.ɵɵelement(26, "i", 43);
380
+ i0.ɵɵtext(27, " Deletes ");
381
+ i0.ɵɵelementEnd()();
382
+ i0.ɵɵconditionalCreate(28, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_28_Template, 4, 2, "div", 44);
383
+ i0.ɵɵelementStart(29, "div", 45);
384
+ i0.ɵɵconditionalCreate(30, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_30_Template, 7, 0, "div", 46)(31, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_Template, 2, 0);
405
385
  i0.ɵɵelementEnd();
406
386
  } if (rf & 2) {
407
387
  const ctx_r1 = i0.ɵɵnextContext(2);
388
+ i0.ɵɵadvance(5);
389
+ i0.ɵɵtextInterpolate(ctx_r1.record.EntityInfo.Name);
390
+ i0.ɵɵadvance(4);
391
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.record.EntityInfo.Name, " ");
408
392
  i0.ɵɵadvance(2);
393
+ i0.ɵɵtextInterpolate4("", ctx_r1.viewData.length, " change", ctx_r1.viewData.length !== 1 ? "s" : "", " \u00B7 ", ctx_r1.getUniqueContributorCount(), " contributor", ctx_r1.getUniqueContributorCount() !== 1 ? "s" : "");
394
+ i0.ɵɵadvance(4);
409
395
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.searchTerm);
410
396
  i0.ɵɵadvance();
411
- i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedType);
412
- i0.ɵɵadvance(9);
413
- i0.ɵɵtwoWayProperty("ngModel", ctx_r1.selectedSource);
414
- i0.ɵɵadvance(7);
415
- i0.ɵɵconditional(ctx_r1.filteredData.length !== ctx_r1.viewData.length ? 19 : -1);
397
+ i0.ɵɵclassProp("active", !ctx_r1.selectedType);
398
+ i0.ɵɵadvance(3);
399
+ i0.ɵɵclassProp("active", ctx_r1.selectedType === "Update");
400
+ i0.ɵɵadvance(3);
401
+ i0.ɵɵclassProp("active", ctx_r1.selectedType === "Create");
402
+ i0.ɵɵadvance(3);
403
+ i0.ɵɵclassProp("active", ctx_r1.selectedType === "Delete");
404
+ i0.ɵɵadvance(3);
405
+ i0.ɵɵconditional(ctx_r1.filteredData.length !== ctx_r1.viewData.length ? 28 : -1);
416
406
  i0.ɵɵadvance();
417
407
  i0.ɵɵattribute("aria-label", "Timeline of changes for " + ctx_r1.record.EntityInfo.Name + " record");
418
408
  i0.ɵɵadvance();
419
- i0.ɵɵconditional(ctx_r1.filteredData.length === 0 ? 21 : 22);
409
+ i0.ɵɵconditional(ctx_r1.filteredData.length === 0 ? 30 : 31);
420
410
  } }
421
411
  function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
422
412
  const _r1 = i0.ɵɵgetCurrentView();
@@ -434,7 +424,7 @@ function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
434
424
  i0.ɵɵelementEnd()();
435
425
  i0.ɵɵconditionalCreate(11, RecordChangesComponent_Conditional_2_Conditional_11_Template, 3, 0, "div", 11)(12, RecordChangesComponent_Conditional_2_Conditional_12_Template, 2, 0, "div", 12)(13, RecordChangesComponent_Conditional_2_Conditional_13_Template, 3, 0, "div", 13);
436
426
  i0.ɵɵelementEnd();
437
- i0.ɵɵconditionalCreate(14, RecordChangesComponent_Conditional_2_Conditional_14_Template, 11, 0, "div", 14)(15, RecordChangesComponent_Conditional_2_Conditional_15_Template, 23, 6);
427
+ i0.ɵɵconditionalCreate(14, RecordChangesComponent_Conditional_2_Conditional_14_Template, 11, 0, "div", 14)(15, RecordChangesComponent_Conditional_2_Conditional_15_Template, 32, 18);
438
428
  i0.ɵɵelementEnd();
439
429
  } if (rf & 2) {
440
430
  const ctx_r1 = i0.ɵɵnextContext();
@@ -446,13 +436,13 @@ function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
446
436
  i0.ɵɵconditional(ctx_r1.viewData.length === 0 ? 14 : 15);
447
437
  } }
448
438
  function RecordChangesComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
449
- const _r11 = i0.ɵɵgetCurrentView();
450
- i0.ɵɵelementStart(0, "div", 91);
451
- i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
452
- i0.ɵɵelementStart(1, "div", 92);
453
- i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
454
- i0.ɵɵelementStart(2, "mj-label-create", 93);
455
- i0.ɵɵlistener("Created", function RecordChangesComponent_Conditional_3_Template_mj_label_create_Created_2_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreated($event)); })("Cancel", function RecordChangesComponent_Conditional_3_Template_mj_label_create_Cancel_2_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
439
+ const _r12 = i0.ɵɵgetCurrentView();
440
+ i0.ɵɵelementStart(0, "div", 85);
441
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
442
+ i0.ɵɵelementStart(1, "div", 86);
443
+ i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r12); return i0.ɵɵresetView($event.stopPropagation()); });
444
+ i0.ɵɵelementStart(2, "mj-label-create", 87);
445
+ i0.ɵɵlistener("Created", function RecordChangesComponent_Conditional_3_Template_mj_label_create_Created_2_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreated($event)); })("Cancel", function RecordChangesComponent_Conditional_3_Template_mj_label_create_Cancel_2_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
456
446
  i0.ɵɵelementEnd()()();
457
447
  } if (rf & 2) {
458
448
  const ctx_r1 = i0.ɵɵnextContext();
@@ -461,6 +451,7 @@ function RecordChangesComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
461
451
  } }
462
452
  export class RecordChangesComponent {
463
453
  cdr;
454
+ ngZone;
464
455
  mjNotificationService;
465
456
  sanitizer;
466
457
  IsLoading = false;
@@ -469,6 +460,7 @@ export class RecordChangesComponent {
469
460
  record;
470
461
  viewData = [];
471
462
  filteredData = [];
463
+ dateGroups = [];
472
464
  expandedItems = new Set();
473
465
  // Version label state
474
466
  RecordLabels = [];
@@ -478,8 +470,9 @@ export class RecordChangesComponent {
478
470
  searchTerm = '';
479
471
  selectedType = '';
480
472
  selectedSource = '';
481
- constructor(cdr, mjNotificationService, sanitizer) {
473
+ constructor(cdr, ngZone, mjNotificationService, sanitizer) {
482
474
  this.cdr = cdr;
475
+ this.ngZone = ngZone;
483
476
  this.mjNotificationService = mjNotificationService;
484
477
  this.sanitizer = sanitizer;
485
478
  }
@@ -502,32 +495,57 @@ export class RecordChangesComponent {
502
495
  if (pkey && entityName) {
503
496
  const md = new Metadata();
504
497
  const changes = await md.GetRecordChanges(entityName, pkey);
505
- if (changes) {
506
- this.viewData = changes.sort((a, b) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime());
507
- this.filteredData = [...this.viewData];
508
- this.IsLoading = false;
509
- }
510
- else {
511
- this.mjNotificationService.CreateSimpleNotification(`Error loading record changes for ${entityName} with primary key ${pkey.ToString()}.`, 'error');
512
- this.IsLoading = false;
513
- }
514
- this.cdr.markForCheck();
498
+ this.ngZone.run(() => {
499
+ if (changes) {
500
+ this.viewData = changes.sort((a, b) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime());
501
+ this.filteredData = [...this.viewData];
502
+ this.dateGroups = this.buildDateGroups(this.filteredData);
503
+ this.IsLoading = false;
504
+ }
505
+ else {
506
+ this.mjNotificationService.CreateSimpleNotification(`Error loading record changes for ${entityName} with primary key ${pkey.ToString()}.`, 'error');
507
+ this.IsLoading = false;
508
+ }
509
+ this.cdr.markForCheck();
510
+ });
515
511
  }
516
512
  }
517
- // Filter and search methods
513
+ // ─── Filter & Search ────────────────────────────────────────────
518
514
  onSearchChange() {
519
515
  this.applyFilters();
520
516
  }
521
517
  onFilterChange() {
522
518
  this.applyFilters();
523
519
  }
520
+ SetTypeFilter(type) {
521
+ this.selectedType = this.selectedType === type ? '' : type;
522
+ this.applyFilters();
523
+ }
524
524
  ClearFilters() {
525
525
  this.searchTerm = '';
526
526
  this.selectedType = '';
527
527
  this.selectedSource = '';
528
528
  this.applyFilters();
529
529
  }
530
- // Version label methods
530
+ applyFilters() {
531
+ let filtered = [...this.viewData];
532
+ if (this.searchTerm.trim()) {
533
+ const search = this.searchTerm.toLowerCase();
534
+ filtered = filtered.filter(change => change.ChangesDescription?.toLowerCase().includes(search) ||
535
+ change.User?.toLowerCase().includes(search) ||
536
+ change.Comments?.toLowerCase().includes(search));
537
+ }
538
+ if (this.selectedType) {
539
+ filtered = filtered.filter(change => change.Type === this.selectedType);
540
+ }
541
+ if (this.selectedSource) {
542
+ filtered = filtered.filter(change => change.Source === this.selectedSource);
543
+ }
544
+ this.filteredData = filtered;
545
+ this.dateGroups = this.buildDateGroups(this.filteredData);
546
+ this.cdr.markForCheck();
547
+ }
548
+ // ─── Version Labels ─────────────────────────────────────────────
531
549
  async LoadRecordLabels() {
532
550
  if (!this.record)
533
551
  return;
@@ -537,7 +555,6 @@ export class RecordChangesComponent {
537
555
  const entityId = this.record.EntityInfo.ID;
538
556
  const recordId = this.record.PrimaryKey.ToConcatenatedString();
539
557
  const rv = new RunView();
540
- // Find all label items that reference this specific record
541
558
  const itemsResult = await rv.RunView({
542
559
  EntityName: 'MJ: Version Label Items',
543
560
  Fields: ['VersionLabelID'],
@@ -545,9 +562,11 @@ export class RecordChangesComponent {
545
562
  ResultType: 'simple'
546
563
  });
547
564
  if (!itemsResult.Success || itemsResult.Results.length === 0) {
548
- this.RecordLabels = [];
549
- this.IsLoadingLabels = false;
550
- this.cdr.markForCheck();
565
+ this.ngZone.run(() => {
566
+ this.RecordLabels = [];
567
+ this.IsLoadingLabels = false;
568
+ this.cdr.markForCheck();
569
+ });
551
570
  return;
552
571
  }
553
572
  const labelIds = [...new Set(itemsResult.Results.map(i => i.VersionLabelID))];
@@ -576,8 +595,10 @@ export class RecordChangesComponent {
576
595
  this.RecordLabels = [];
577
596
  }
578
597
  finally {
579
- this.IsLoadingLabels = false;
580
- this.cdr.markForCheck();
598
+ this.ngZone.run(() => {
599
+ this.IsLoadingLabels = false;
600
+ this.cdr.markForCheck();
601
+ });
581
602
  }
582
603
  }
583
604
  OpenCreateWizard() {
@@ -602,24 +623,7 @@ export class RecordChangesComponent {
602
623
  default: return '';
603
624
  }
604
625
  }
605
- applyFilters() {
606
- let filtered = [...this.viewData];
607
- if (this.searchTerm.trim()) {
608
- const search = this.searchTerm.toLowerCase();
609
- filtered = filtered.filter(change => change.ChangesDescription?.toLowerCase().includes(search) ||
610
- change.User?.toLowerCase().includes(search) ||
611
- change.Comments?.toLowerCase().includes(search));
612
- }
613
- if (this.selectedType) {
614
- filtered = filtered.filter(change => change.Type === this.selectedType);
615
- }
616
- if (this.selectedSource) {
617
- filtered = filtered.filter(change => change.Source === this.selectedSource);
618
- }
619
- this.filteredData = filtered;
620
- this.cdr.markForCheck();
621
- }
622
- // Timeline interaction methods
626
+ // ─── Timeline Interaction ───────────────────────────────────────
623
627
  toggleExpansion(changeId) {
624
628
  if (this.expandedItems.has(changeId)) {
625
629
  this.expandedItems.delete(changeId);
@@ -635,29 +639,44 @@ export class RecordChangesComponent {
635
639
  this.toggleExpansion(changeId);
636
640
  }
637
641
  }
638
- // Utility methods for timeline display
639
- getChangeTypeClass(type) {
640
- switch (type) {
641
- case 'Create': return 'change-create';
642
- case 'Update': return 'change-update';
643
- case 'Delete': return 'change-delete';
644
- default: return 'change-unknown';
642
+ // ─── Date Grouping ─────────────────────────────────────────────
643
+ buildDateGroups(changes) {
644
+ const groups = new Map();
645
+ for (const change of changes) {
646
+ const label = this.formatDateGroupLabel(new Date(change.ChangedAt));
647
+ if (!groups.has(label)) {
648
+ groups.set(label, []);
649
+ }
650
+ groups.get(label).push(change);
645
651
  }
652
+ return Array.from(groups.entries()).map(([label, items]) => ({ label, changes: items }));
646
653
  }
647
- getChangeTypeIcon(type) {
654
+ formatDateGroupLabel(date) {
655
+ const now = new Date();
656
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
657
+ const target = new Date(date.getFullYear(), date.getMonth(), date.getDate());
658
+ const diffDays = Math.floor((today.getTime() - target.getTime()) / 86400000);
659
+ const formatted = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(date);
660
+ if (diffDays === 0)
661
+ return `Today \u2014 ${formatted}`;
662
+ if (diffDays === 1)
663
+ return `Yesterday \u2014 ${formatted}`;
664
+ return formatted;
665
+ }
666
+ // ─── Display Helpers ────────────────────────────────────────────
667
+ getChangeTypeCardClass(type) {
648
668
  switch (type) {
649
- case 'Create': return 'fa-solid fa-plus';
650
- case 'Update': return 'fa-solid fa-edit';
651
- case 'Delete': return 'fa-solid fa-trash';
652
- default: return 'fa-solid fa-question';
669
+ case 'Create': return 'type-create';
670
+ case 'Update': return 'type-update';
671
+ case 'Delete': return 'type-delete';
672
+ default: return 'type-update';
653
673
  }
654
674
  }
655
- getChangeTypeBadgeClass(type) {
675
+ getChangeTypeBadgeText(type) {
656
676
  switch (type) {
657
- case 'Create': return 'badge-create';
658
- case 'Update': return 'badge-update';
659
- case 'Delete': return 'badge-delete';
660
- default: return 'badge-unknown';
677
+ case 'Create': return 'Created';
678
+ case 'Delete': return 'Deleted';
679
+ default: return type;
661
680
  }
662
681
  }
663
682
  getSourceClass(source) {
@@ -674,6 +693,39 @@ export class RecordChangesComponent {
674
693
  getTimelineItemLabel(change) {
675
694
  return `${change.Type} by ${change.User || 'Unknown User'} on ${this.formatFullDateTime(change.ChangedAt)}`;
676
695
  }
696
+ getUserInitials(user) {
697
+ if (!user)
698
+ return '?';
699
+ // Handle email addresses: take first char of local part + first char of domain
700
+ if (user.includes('@')) {
701
+ const local = user.split('@')[0];
702
+ return local.substring(0, 2).toUpperCase();
703
+ }
704
+ // Handle names: first char of each word
705
+ const parts = user.trim().split(/\s+/);
706
+ if (parts.length >= 2) {
707
+ return (parts[0][0] + parts[1][0]).toUpperCase();
708
+ }
709
+ return user.substring(0, 2).toUpperCase();
710
+ }
711
+ getUserDisplayName(user) {
712
+ if (!user)
713
+ return 'Unknown';
714
+ if (user.includes('@'))
715
+ return user.split('@')[0];
716
+ return user;
717
+ }
718
+ getUniqueContributorCount() {
719
+ const users = new Set(this.viewData.map(c => c.User).filter(Boolean));
720
+ return users.size;
721
+ }
722
+ formatTime(date) {
723
+ return new Intl.DateTimeFormat('en-US', {
724
+ hour: 'numeric',
725
+ minute: '2-digit',
726
+ hour12: true
727
+ }).format(new Date(date));
728
+ }
677
729
  formatRelativeTime(date) {
678
730
  const now = new Date();
679
731
  const diffMs = now.getTime() - new Date(date).getTime();
@@ -705,70 +757,95 @@ export class RecordChangesComponent {
705
757
  timeZoneName: 'short'
706
758
  }).format(new Date(date));
707
759
  }
760
+ // ─── Change Summary ─────────────────────────────────────────────
708
761
  getChangeSummary(change) {
709
- if (change.Type === 'Create') {
710
- return 'Record was created';
711
- }
712
- if (change.Type === 'Delete') {
713
- return 'Record was deleted';
714
- }
762
+ if (change.Type === 'Create')
763
+ return 'Record created';
764
+ if (change.Type === 'Delete')
765
+ return 'Record deleted';
715
766
  try {
716
767
  const changesJson = JSON.parse(change.ChangesJSON || '{}');
717
- const fields = Object.keys(changesJson);
718
- if (fields.length === 0)
768
+ const fieldNames = this.extractFieldDisplayNames(changesJson);
769
+ if (fieldNames.length === 0)
719
770
  return 'No field changes detected';
720
- const fieldNames = fields.map(fieldKey => {
721
- const changeInfo = changesJson[fieldKey];
722
- const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
723
- return field?.DisplayNameOrName || changeInfo.field;
724
- });
725
- if (fieldNames.length === 1) {
726
- return `${fieldNames[0]} changed`;
727
- }
728
- if (fieldNames.length === 2) {
729
- return `${fieldNames[0]} and ${fieldNames[1]} changed`;
730
- }
731
- if (fieldNames.length <= 4) {
732
- const lastField = fieldNames.pop();
733
- return `${fieldNames.join(', ')}, and ${lastField} changed`;
734
- }
735
- return `${fieldNames.slice(0, 3).join(', ')}, and ${fieldNames.length - 3} other field${fieldNames.length - 3 > 1 ? 's' : ''} changed`;
771
+ return this.buildFieldListSummary(fieldNames);
736
772
  }
737
773
  catch {
738
774
  return change.ChangesDescription || 'Changes made';
739
775
  }
740
776
  }
777
+ getCreatedFieldCount(change) {
778
+ try {
779
+ if (!change.FullRecordJSON)
780
+ return 0;
781
+ const record = JSON.parse(change.FullRecordJSON);
782
+ return this.record.EntityInfo.Fields
783
+ .filter((f) => record[f.Name] != null && record[f.Name] !== '')
784
+ .length;
785
+ }
786
+ catch {
787
+ return 0;
788
+ }
789
+ }
790
+ extractFieldDisplayNames(changesJson) {
791
+ return Object.keys(changesJson).map(fieldKey => {
792
+ const changeInfo = changesJson[fieldKey];
793
+ const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
794
+ return field?.DisplayNameOrName || changeInfo.field || fieldKey;
795
+ });
796
+ }
797
+ buildFieldListSummary(fieldNames) {
798
+ if (fieldNames.length === 1)
799
+ return `${fieldNames[0]} changed`;
800
+ if (fieldNames.length === 2)
801
+ return `${fieldNames[0]} and ${fieldNames[1]} changed`;
802
+ if (fieldNames.length <= 4) {
803
+ const last = fieldNames[fieldNames.length - 1];
804
+ return `${fieldNames.slice(0, -1).join(', ')}, and ${last} changed`;
805
+ }
806
+ const remaining = fieldNames.length - 3;
807
+ return `${fieldNames.slice(0, 3).join(', ')}, and ${remaining} other field${remaining > 1 ? 's' : ''} changed`;
808
+ }
809
+ // ─── Field Changes (type-aware) ────────────────────────────────
741
810
  getFieldChanges(change) {
742
811
  try {
743
812
  const changesJson = JSON.parse(change.ChangesJSON || '{}');
744
- const fields = Object.keys(changesJson);
745
- return fields.map(fieldKey => {
746
- const changeInfo = changesJson[fieldKey];
747
- const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
748
- const isBooleanField = field?.TSType === EntityFieldTSType.Boolean;
749
- const isDateField = field?.TSType === EntityFieldTSType.Date;
750
- let diffHtml;
751
- const formattedOld = this.formatChangeValue(changeInfo.oldValue, isDateField);
752
- const formattedNew = this.formatChangeValue(changeInfo.newValue, isDateField);
753
- if (!isBooleanField) {
754
- if (formattedOld !== formattedNew) {
755
- diffHtml = this.generateDiffHtml(formattedOld, formattedNew);
756
- }
757
- }
758
- return {
759
- field: changeInfo.field,
760
- displayName: field?.DisplayNameOrName || changeInfo.field,
761
- oldValue: formattedOld,
762
- newValue: formattedNew,
763
- isBooleanField,
764
- diffHtml
765
- };
766
- });
813
+ return Object.keys(changesJson).map(fieldKey => this.buildFieldChangeInfo(changesJson[fieldKey]));
767
814
  }
768
815
  catch {
769
816
  return [];
770
817
  }
771
818
  }
819
+ buildFieldChangeInfo(changeInfo) {
820
+ const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
821
+ const fieldType = this.classifyFieldType(field);
822
+ const isDateField = fieldType === 'date';
823
+ const formattedOld = this.formatChangeValue(changeInfo.oldValue, isDateField);
824
+ const formattedNew = this.formatChangeValue(changeInfo.newValue, isDateField);
825
+ let diffHtml;
826
+ if (fieldType === 'text' && formattedOld !== formattedNew) {
827
+ diffHtml = this.generateDiffHtml(formattedOld, formattedNew);
828
+ }
829
+ return {
830
+ field: changeInfo.field || '',
831
+ displayName: field?.DisplayNameOrName || changeInfo.field || '',
832
+ oldValue: formattedOld,
833
+ newValue: formattedNew,
834
+ fieldType,
835
+ diffHtml
836
+ };
837
+ }
838
+ classifyFieldType(field) {
839
+ if (!field)
840
+ return 'text';
841
+ if (field.TSType === EntityFieldTSType.Boolean)
842
+ return 'boolean';
843
+ if (field.TSType === EntityFieldTSType.Date)
844
+ return 'date';
845
+ if (field.TSType === EntityFieldTSType.Number)
846
+ return 'number';
847
+ return 'text';
848
+ }
772
849
  getCreatedFields(change) {
773
850
  try {
774
851
  if (!change.FullRecordJSON)
@@ -787,6 +864,7 @@ export class RecordChangesComponent {
787
864
  return [];
788
865
  }
789
866
  }
867
+ // ─── Value Formatting ───────────────────────────────────────────
790
868
  /**
791
869
  * Formats a change value for display. Handles corrupted date values (stored as empty objects)
792
870
  * and formats ISO date strings into a human-readable format.
@@ -794,48 +872,48 @@ export class RecordChangesComponent {
794
872
  formatChangeValue(value, isDateField) {
795
873
  if (value == null)
796
874
  return '';
797
- // Handle object values (e.g., Date objects that were incorrectly serialized as {})
798
875
  if (typeof value === 'object') {
799
876
  const keys = Object.keys(value);
800
877
  if (keys.length === 0)
801
- return ''; // Empty object from corrupted date serialization
878
+ return '';
802
879
  return JSON.stringify(value);
803
880
  }
804
- // Format ISO date strings into a readable format
805
881
  if (isDateField && typeof value === 'string') {
806
882
  const date = new Date(value);
807
883
  if (!isNaN(date.getTime())) {
808
- return date.toLocaleString();
884
+ return new Intl.DateTimeFormat('en-US', {
885
+ month: 'short',
886
+ day: 'numeric',
887
+ year: 'numeric',
888
+ hour: 'numeric',
889
+ minute: '2-digit',
890
+ hour12: true
891
+ }).format(date);
809
892
  }
810
893
  }
811
894
  return String(value);
812
895
  }
896
+ // ─── Diff Generation (text fields only) ─────────────────────────
813
897
  generateDiffHtml(oldValue, newValue) {
814
898
  if (!oldValue && !newValue) {
815
- return this.sanitizer.bypassSecurityTrustHtml('<div class="diff-container"><span class="diff-unchanged">(no change)</span></div>');
899
+ return this.sanitizer.bypassSecurityTrustHtml('<span class="rc-diff-unchanged">(no change)</span>');
816
900
  }
817
901
  if (!oldValue) {
818
- return this.sanitizer.bypassSecurityTrustHtml(`<div class="diff-container"><span class="diff-added">${this.escapeHtml(newValue)}</span></div>`);
902
+ return this.sanitizer.bypassSecurityTrustHtml(`<span class="rc-diff-added">${this.escapeHtml(newValue)}</span>`);
819
903
  }
820
904
  if (!newValue) {
821
- return this.sanitizer.bypassSecurityTrustHtml(`<div class="diff-container"><span class="diff-removed">${this.escapeHtml(oldValue)}</span></div>`);
905
+ return this.sanitizer.bypassSecurityTrustHtml(`<span class="rc-diff-removed">${this.escapeHtml(oldValue)}</span>`);
822
906
  }
823
907
  const useWordDiff = this.shouldUseWordDiff(oldValue, newValue);
824
908
  const diffs = useWordDiff ? diffWords(oldValue, newValue) : diffChars(oldValue, newValue);
825
- let html = '<div class="diff-container">';
826
- diffs.forEach((part) => {
827
- const escapedValue = this.escapeHtml(part.value);
828
- if (part.added) {
829
- html += `<span class="diff-added">${escapedValue}</span>`;
830
- }
831
- else if (part.removed) {
832
- html += `<span class="diff-removed">${escapedValue}</span>`;
833
- }
834
- else {
835
- html += `<span class="diff-unchanged">${escapedValue}</span>`;
836
- }
837
- });
838
- html += '</div>';
909
+ const html = diffs.map((part) => {
910
+ const escaped = this.escapeHtml(part.value);
911
+ if (part.added)
912
+ return `<span class="rc-diff-added">${escaped}</span>`;
913
+ if (part.removed)
914
+ return `<span class="rc-diff-removed">${escaped}</span>`;
915
+ return `<span class="rc-diff-unchanged">${escaped}</span>`;
916
+ }).join('');
839
917
  return this.sanitizer.bypassSecurityTrustHtml(html);
840
918
  }
841
919
  shouldUseWordDiff(oldValue, newValue) {
@@ -849,8 +927,8 @@ export class RecordChangesComponent {
849
927
  div.textContent = text;
850
928
  return div.innerHTML;
851
929
  }
852
- static ɵfac = function RecordChangesComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RecordChangesComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MJNotificationService), i0.ɵɵdirectiveInject(i2.DomSanitizer)); };
853
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordChangesComponent, selectors: [["mj-record-changes"]], inputs: { record: "record" }, outputs: { dialogClosed: "dialogClosed" }, standalone: false, decls: 4, vars: 9, consts: [[3, "Closed", "Mode", "Title", "Visible", "Resizable", "MinWidthPx", "MaxWidthRatio"], ["text", "Loading history...", "size", "medium"], [1, "record-changes-container"], [1, "create-wizard-overlay"], [1, "labels-section"], [1, "labels-header"], [1, "labels-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-tags"], [1, "labels-count"], ["title", "Create a version label for this record", 1, "create-label-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "labels-loading"], [1, "labels-empty"], [1, "labels-list"], [1, "empty-state"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "label-chip", 3, "title"], [1, "fa-solid", "fa-tag", "label-chip-icon"], [1, "label-chip-name"], [1, "label-chip-meta"], [1, "label-chip-status"], [1, "label-chip-items"], [1, "empty-state-icon"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "empty-state-title"], [1, "empty-state-description"], [1, "empty-state-hint"], [1, "fa-solid", "fa-shield-halved"], [1, "filter-panel"], [1, "filter-controls"], ["type", "text", "placeholder", "Search changes...", "aria-label", "Search record changes", 1, "search-input", 3, "ngModelChange", "input", "ngModel"], ["aria-label", "Filter by change type", 1, "filter-select", 3, "ngModelChange", "change", "ngModel"], ["value", ""], ["value", "Create"], ["value", "Update"], ["value", "Delete"], ["aria-label", "Filter by change source", 1, "filter-select", 3, "ngModelChange", "change", "ngModel"], ["value", "Internal"], ["value", "External"], [1, "filter-results"], [1, "timeline-container"], [1, "no-changes-message"], [1, "timeline"], [1, "fa-solid", "fa-filter"], [1, "clear-filters-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "timeline-item", 3, "expanded"], [1, "timeline-item", 3, "click", "keydown"], [1, "timeline-marker"], [1, "timeline-icon"], [1, "timeline-line"], [1, "timeline-content"], [1, "change-header"], [1, "change-title"], [1, "change-type-badge"], [1, "change-user"], [1, "change-source"], [1, "change-meta"], [1, "change-time", 3, "title"], [1, "change-status"], [1, "change-integration"], [1, "change-summary"], [1, "change-details"], [1, "change-timestamp"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock"], [1, "creation-details"], [1, "deletion-details"], [1, "update-details"], [1, "change-comments"], [1, "change-errors"], [1, "field-changes"], [1, "field-change", "created"], [1, "field-name"], [1, "field-value", "new-value"], [1, "fa-solid", "fa-trash"], [1, "deletion-note"], [1, "fa-solid", "fa-edit"], [1, "field-change"], [1, "boolean-change"], [1, "diff-view"], [1, "value-diff"], [1, "new-value"], [1, "diff-content", 3, "innerHTML"], [1, "old-value"], [1, "value-label"], [1, "value"], [1, "diff-arrow"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-right"], [1, "fa-solid", "fa-comment"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "error-log"], [1, "create-wizard-overlay", 3, "click"], [1, "create-wizard-container", 3, "click"], [3, "Created", "Cancel", "PreselectedEntity", "PreselectedRecordIds"]], template: function RecordChangesComponent_Template(rf, ctx) { if (rf & 1) {
930
+ static ɵfac = function RecordChangesComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RecordChangesComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i1.MJNotificationService), i0.ɵɵdirectiveInject(i2.DomSanitizer)); };
931
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordChangesComponent, selectors: [["mj-record-changes"]], inputs: { record: "record" }, outputs: { dialogClosed: "dialogClosed" }, standalone: false, decls: 4, vars: 9, consts: [[3, "Closed", "Mode", "Title", "Visible", "Resizable", "MinWidthPx", "MaxWidthRatio"], ["text", "Loading history...", "size", "medium"], [1, "rc-container"], [1, "rc-wizard-overlay"], [1, "rc-labels-section"], [1, "rc-labels-header"], [1, "rc-labels-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-tags"], [1, "rc-labels-count"], ["title", "Create a version label for this record", 1, "rc-create-label-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "rc-labels-loading"], [1, "rc-labels-empty"], [1, "rc-labels-list"], [1, "rc-empty-state"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "rc-label-chip", 3, "title"], [1, "fa-solid", "fa-tag", "rc-label-chip-icon"], [1, "rc-label-chip-name"], [1, "rc-label-chip-meta"], [1, "rc-label-chip-status"], [1, "rc-label-chip-items"], [1, "rc-empty-state-icon"], [1, "fa-solid", "fa-clock-rotate-left"], [1, "rc-empty-state-title"], [1, "rc-empty-state-description"], [1, "rc-empty-state-hint"], [1, "fa-solid", "fa-shield-halved"], [1, "rc-page-header"], [1, "rc-page-title"], [1, "rc-page-subtitle"], [1, "rc-header-meta"], [1, "rc-entity-badge"], ["aria-hidden", "true", 1, "fa-solid", "fa-database"], [1, "rc-change-count"], [1, "rc-filter-bar"], [1, "rc-search-wrap"], ["aria-hidden", "true", 1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search changes...", "aria-label", "Search record changes", 1, "rc-search-box", 3, "ngModelChange", "input", "ngModel"], [1, "rc-filter-pill", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["aria-hidden", "true", 1, "fa-solid", "fa-trash"], [1, "rc-filter-results"], [1, "rc-timeline"], [1, "rc-no-results"], [1, "rc-clear-filters-link", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "rc-clear-filters-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "rc-date-group"], [1, "rc-date-label"], [1, "rc-card", 3, "class", "expanded"], [1, "rc-card", 3, "keydown"], [1, "rc-card-header", 3, "click"], [1, "rc-card-header-left"], [1, "rc-card-type-badge"], [1, "rc-card-summary"], [1, "rc-card-meta"], [1, "rc-card-user"], [1, "rc-avatar"], [1, "rc-card-time", 3, "title"], [1, "rc-card-source"], [1, "rc-card-status"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "rc-card-chevron"], [1, "rc-card-body"], [1, "rc-deletion-note"], [1, "rc-comments"], [1, "rc-errors"], [1, "rc-field-row"], [1, "rc-field-label"], [1, "rc-field-values"], [1, "rc-val-new"], [1, "rc-bool-change"], [1, "rc-atomic-change"], [1, "rc-text-diff", 3, "innerHTML"], [1, "rc-bool-dot"], [1, "rc-bool-label", "old"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-right", "rc-val-arrow"], [1, "rc-bool-label", "new"], [1, "rc-val-old"], ["aria-hidden", "true", 1, "fa-solid", "fa-comment"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle"], [1, "rc-error-log"], [1, "rc-wizard-overlay", 3, "click"], [1, "rc-wizard-container", 3, "click"], [3, "Created", "Cancel", "PreselectedEntity", "PreselectedRecordIds"]], template: function RecordChangesComponent_Template(rf, ctx) { if (rf & 1) {
854
932
  i0.ɵɵelementStart(0, "mj-slide-panel", 0);
855
933
  i0.ɵɵlistener("Closed", function RecordChangesComponent_Template_mj_slide_panel_Closed_0_listener() { return ctx.OnClose(); });
856
934
  i0.ɵɵconditionalCreate(1, RecordChangesComponent_Conditional_1_Template, 1, 0, "mj-loading", 1);
@@ -865,15 +943,15 @@ export class RecordChangesComponent {
865
943
  i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
866
944
  i0.ɵɵadvance();
867
945
  i0.ɵɵconditional(ctx.ShowCreateWizard ? 3 : -1);
868
- } }, dependencies: [i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent, i5.MjSlidePanelComponent, i5.MjLabelCreateComponent], styles: ["/* Record Changes Timeline Styles */\n.record-changes-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 1rem;\n}\n\n/* Version Labels Section */\n.labels-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n border: 1px solid #e9ecef;\n}\n\n.labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 0.5rem;\n}\n\n.labels-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: #495057;\n}\n\n.labels-title i {\n color: #6f42c1;\n}\n\n.labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n height: 1.25rem;\n padding: 0 0.35rem;\n border-radius: 10px;\n background: #6f42c1;\n color: white;\n font-size: 0.7rem;\n font-weight: 700;\n}\n\n.create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.35rem 0.75rem;\n border: 1px solid #6f42c1;\n border-radius: 6px;\n background: white;\n color: #6f42c1;\n font-size: 0.8rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.create-label-btn:hover {\n background: #6f42c1;\n color: white;\n}\n\n.labels-loading {\n font-size: 0.8rem;\n color: #6c757d;\n padding: 0.25rem 0;\n}\n\n.labels-loading i {\n margin-right: 0.25rem;\n}\n\n.labels-empty {\n font-size: 0.8rem;\n color: #94a3b8;\n font-style: italic;\n padding: 0.25rem 0;\n}\n\n.labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.label-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.3rem 0.6rem;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 16px;\n font-size: 0.8rem;\n color: #495057;\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.label-chip:hover {\n border-color: #6f42c1;\n box-shadow: 0 1px 3px rgba(111, 66, 193, 0.15);\n}\n\n.label-chip-icon {\n color: #6f42c1;\n font-size: 0.7rem;\n}\n\n.label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.label-chip-meta {\n display: flex;\n align-items: center;\n gap: 0.3rem;\n font-size: 0.7rem;\n color: #6c757d;\n}\n\n.label-chip-status {\n padding: 0.1rem 0.3rem;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 0.6rem;\n letter-spacing: 0.03em;\n}\n\n.label-status-active {\n background: #d4edda;\n color: #155724;\n}\n\n.label-status-archived {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.label-status-restored {\n background: #cce7ff;\n color: #004085;\n}\n\n.label-chip-items {\n white-space: nowrap;\n}\n\n/* Create Wizard Overlay */\n.create-wizard-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: fadeIn 0.15s ease;\n}\n\n.create-wizard-container {\n background: white;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 1.5rem;\n animation: slideUp 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* Filter Panel */\n.filter-panel {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 1rem;\n border: 1px solid #e9ecef;\n}\n\n.filter-controls {\n display: flex;\n gap: 1rem;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.search-input {\n flex: 1;\n min-width: 200px;\n padding: 0.5rem 1rem;\n border: 1px solid #ced4da;\n border-radius: 4px;\n font-size: 0.9rem;\n}\n\n.search-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.filter-select {\n padding: 0.5rem;\n border: 1px solid #ced4da;\n border-radius: 4px;\n background: white;\n font-size: 0.9rem;\n min-width: 120px;\n}\n\n.filter-select:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.filter-results {\n margin-top: 0.5rem;\n font-size: 0.85rem;\n color: #6c757d;\n font-style: italic;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n text-align: center;\n min-height: 400px;\n}\n\n.empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #e8edf2, #f0f4f8);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 1.5rem;\n}\n\n.empty-state-icon i {\n font-size: 2rem;\n color: #94a3b8;\n}\n\n.empty-state-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: #334155;\n margin: 0 0 0.75rem 0;\n}\n\n.empty-state-description {\n font-size: 0.95rem;\n color: #64748b;\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 1.5rem 0;\n}\n\n.empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: #f1f5f9;\n border-radius: 20px;\n font-size: 0.8rem;\n color: #64748b;\n}\n\n.empty-state-hint i {\n color: #94a3b8;\n}\n\n/* No filtered results */\n.no-changes-message {\n text-align: center;\n padding: 3rem 1rem;\n color: #6c757d;\n}\n\n.no-changes-message i {\n display: block;\n font-size: 2rem;\n margin-bottom: 1rem;\n color: #adb5bd;\n}\n\n.no-changes-message p {\n font-size: 1rem;\n margin: 0 0 1rem 0;\n}\n\n.clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 1rem;\n border: 1px solid #ced4da;\n border-radius: 6px;\n background: white;\n color: #495057;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.clear-filters-btn:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n}\n\n/* Timeline Container */\n.timeline-container {\n flex: 1;\n overflow-y: auto;\n padding-right: 0.5rem;\n}\n\n/* Timeline */\n.timeline {\n position: relative;\n padding-left: 2rem;\n}\n\n.timeline-item {\n position: relative;\n margin-bottom: 1.5rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.timeline-item:hover {\n transform: translateX(2px);\n}\n\n.timeline-item:focus {\n outline: 2px solid #007bff;\n outline-offset: 2px;\n border-radius: 4px;\n}\n\n.timeline-item.expanded {\n margin-bottom: 2rem;\n}\n\n/* Timeline Marker */\n.timeline-marker {\n position: absolute;\n left: -2rem;\n top: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.timeline-icon {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.9rem;\n color: white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n z-index: 2;\n}\n\n.timeline-icon.change-create {\n background: linear-gradient(135deg, #28a745, #20c997);\n}\n\n.timeline-icon.change-update {\n background: linear-gradient(135deg, #007bff, #6f42c1);\n}\n\n.timeline-icon.change-delete {\n background: linear-gradient(135deg, #dc3545, #fd7e14);\n}\n\n.timeline-icon.change-unknown {\n background: linear-gradient(135deg, #6c757d, #adb5bd);\n}\n\n.timeline-line {\n width: 2px;\n height: 2rem;\n background: #e9ecef;\n margin-top: 0.5rem;\n}\n\n/* Timeline Content */\n.timeline-content {\n background: white;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n padding: 1rem;\n box-shadow: 0 2px 4px rgba(0,0,0,0.05);\n transition: box-shadow 0.2s ease;\n}\n\n.timeline-item:hover .timeline-content {\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n}\n\n.timeline-item.expanded .timeline-content {\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n}\n\n/* Change Header */\n.change-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.change-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.change-type-badge {\n font-size: 0.75rem;\n font-weight: 600;\n padding: 0.25rem 0.5rem;\n border-radius: 12px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.badge-create {\n background: #d4edda;\n color: #155724;\n}\n\n.badge-update {\n background: #cce7ff;\n color: #004085;\n}\n\n.badge-delete {\n background: #f8d7da;\n color: #721c24;\n}\n\n.badge-unknown {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.change-user {\n font-weight: 600;\n color: #495057;\n}\n\n.change-source {\n font-size: 0.8rem;\n padding: 0.2rem 0.4rem;\n border-radius: 8px;\n font-weight: 500;\n}\n\n.source-internal {\n background: #e7f3ff;\n color: #0056b3;\n}\n\n.source-external {\n background: #fff3cd;\n color: #856404;\n}\n\n.change-meta {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.85rem;\n color: #6c757d;\n flex-wrap: wrap;\n}\n\n.change-time {\n font-weight: 500;\n}\n\n.change-status {\n padding: 0.2rem 0.4rem;\n border-radius: 8px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-complete {\n background: #d4edda;\n color: #155724;\n}\n\n.status-pending {\n background: #fff3cd;\n color: #856404;\n}\n\n.status-error {\n background: #f8d7da;\n color: #721c24;\n}\n\n.status-unknown {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.change-integration {\n font-style: italic;\n color: #495057;\n}\n\n/* Change Summary */\n.change-summary {\n color: #6c757d;\n font-size: 0.9rem;\n line-height: 1.4;\n}\n\n/* Change Details */\n.change-details {\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid #e9ecef;\n}\n\n.change-timestamp {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 1rem;\n padding: 0.5rem;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 4px solid #6c757d;\n font-size: 0.9rem;\n color: #495057;\n}\n\n.change-timestamp i {\n color: #6c757d;\n}\n\n.change-details h4 {\n font-size: 1rem;\n margin-bottom: 1rem;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.change-details h5 {\n font-size: 0.9rem;\n margin-bottom: 0.5rem;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n/* Field Changes */\n.field-changes {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.field-change {\n background: #f8f9fa;\n border-radius: 6px;\n padding: 0.75rem;\n border-left: 4px solid #007bff;\n}\n\n.field-change.created {\n border-left-color: #28a745;\n}\n\n.field-name {\n font-weight: 600;\n color: #495057;\n margin-bottom: 0.5rem;\n display: block;\n}\n\n.field-value {\n font-family: 'Courier New', monospace;\n font-size: 0.85rem;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n background: white;\n border: 1px solid #dee2e6;\n}\n\n.value-diff {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 1rem;\n align-items: center;\n}\n\n.old-value, .new-value {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.value-label {\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #6c757d;\n}\n\n.old-value .value {\n color: #6c757d;\n background: #f8f9fa;\n text-decoration: line-through;\n}\n\n.new-value .value {\n color: #155724;\n background: #d4edda;\n font-weight: 500;\n}\n\n.value {\n font-family: 'Courier New', monospace;\n font-size: 0.85rem;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n border: 1px solid #dee2e6;\n word-break: break-all;\n}\n\n.diff-arrow {\n color: #007bff;\n font-size: 1.2rem;\n}\n\n.boolean-change .new-value {\n font-weight: 600;\n color: #007bff;\n font-size: 0.9rem;\n}\n\n/* Creation Details */\n.creation-details .field-change {\n border-left-color: #28a745;\n}\n\n.creation-details .field-value {\n color: #155724;\n background: #d4edda;\n font-weight: 500;\n}\n\n/* Deletion Details */\n.deletion-details {\n text-align: center;\n padding: 1rem;\n}\n\n.deletion-note {\n color: #6c757d;\n font-style: italic;\n margin-bottom: 0;\n}\n\n/* Diff View Styles */\n.diff-view {\n margin-top: 0.5rem;\n border: 1px dashed #28a745;\n border-radius: 4px;\n padding: 0.25rem;\n}\n\n.diff-content {\n background: #ffffff;\n border: 2px solid #007bff;\n border-radius: 6px;\n padding: 0.75rem;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 0.85rem;\n line-height: 1.45;\n overflow-x: auto;\n min-height: 2rem;\n}\n\n.diff-container {\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.diff-added {\n background-color: #d1f5d3;\n color: #22863a;\n text-decoration: none;\n border-radius: 3px;\n padding: 2px 4px;\n font-weight: 600;\n display: inline;\n border: 1px solid #28a745;\n position: relative;\n margin: 0 1px;\n}\n\n.diff-removed {\n background-color: #ffeef0;\n color: #d73a49;\n text-decoration: line-through;\n border-radius: 3px;\n padding: 2px 4px;\n font-weight: 600;\n display: inline;\n border: 1px solid #dc3545;\n position: relative;\n margin: 0 1px;\n}\n\n.diff-unchanged {\n color: #24292e;\n display: inline;\n}\n\n/* Hover effects for diff elements */\n.diff-added:hover {\n background-color: #c3f0c5;\n box-shadow: 0 0 0 2px rgba(40, 167, 69, 0.15);\n}\n\n.diff-removed:hover {\n background-color: #ffd6dd;\n box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.15);\n}\n\n/* Comments and Errors */\n.change-comments, .change-errors {\n margin-top: 1rem;\n padding: 0.75rem;\n border-radius: 6px;\n}\n\n.change-comments {\n background: #e7f3ff;\n border-left: 4px solid #007bff;\n}\n\n.change-errors {\n background: #f8d7da;\n border-left: 4px solid #dc3545;\n}\n\n.error-log {\n background: #ffffff;\n padding: 0.5rem;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 0.8rem;\n color: #721c24;\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .filter-controls {\n flex-direction: column;\n align-items: stretch;\n }\n\n .search-input, .filter-select {\n width: 100%;\n }\n\n .change-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .change-meta {\n flex-direction: column;\n align-items: flex-start;\n gap: 0.25rem;\n }\n\n .value-diff {\n grid-template-columns: 1fr;\n gap: 0.5rem;\n }\n\n .diff-arrow {\n justify-self: center;\n transform: rotate(90deg);\n }\n\n .timeline {\n padding-left: 1.5rem;\n }\n\n .timeline-marker {\n left: -1.5rem;\n }\n\n .timeline-icon {\n width: 2rem;\n height: 2rem;\n font-size: 0.8rem;\n }\n\n .diff-content {\n font-size: 0.8rem;\n padding: 0.5rem;\n }\n\n .diff-added, .diff-removed {\n padding: 1px 2px;\n }\n}\n\n@media (max-width: 480px) {\n .record-changes-container {\n padding: 0.5rem;\n }\n\n .timeline-content {\n padding: 0.75rem;\n }\n\n .field-change {\n padding: 0.5rem;\n }\n}\n"], encapsulation: 2, changeDetection: 0 });
946
+ } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent, i5.MjSlidePanelComponent, i5.MjLabelCreateComponent], styles: ["/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Record Changes \u2014 Option A \"Clean Timeline\"\n Linear / Notion-inspired minimal timeline design\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500\u2500 Container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px 24px;\n background: #fafbfc;\n}\n\n/* \u2500\u2500\u2500 Version Labels Section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-labels-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid #e9ecef;\n}\n\n.rc-labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.rc-labels-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: #495057;\n}\n\n.rc-labels-title i { color: #6f42c1; }\n\n.rc-labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 10px;\n background: #6f42c1;\n color: #fff;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid #6f42c1;\n border-radius: 6px;\n background: #fff;\n color: #6f42c1;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-create-label-btn:hover {\n background: #6f42c1;\n color: #fff;\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: #6c757d;\n padding: 4px 0;\n}\n\n.rc-labels-loading i { margin-right: 4px; }\n\n.rc-labels-empty {\n font-size: 12px;\n color: #94a3b8;\n font-style: italic;\n padding: 4px 0;\n}\n\n.rc-labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.rc-label-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n background: #fff;\n border: 1px solid #dee2e6;\n border-radius: 16px;\n font-size: 12px;\n color: #495057;\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: #6f42c1;\n box-shadow: 0 1px 3px rgba(111, 66, 193, 0.15);\n}\n\n.rc-label-chip-icon { color: #6f42c1; font-size: 10px; }\n\n.rc-label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-label-chip-meta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n color: #6c757d;\n}\n\n.rc-label-chip-status {\n padding: 1px 5px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 9px;\n letter-spacing: 0.03em;\n}\n\n.label-status-active { background: #d4edda; color: #155724; }\n.label-status-archived { background: #e2e3e5; color: #383d41; }\n.label-status-restored { background: #cce7ff; color: #004085; }\n\n.rc-label-chip-items { white-space: nowrap; }\n\n/* \u2500\u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 32px;\n text-align: center;\n min-height: 400px;\n}\n\n.rc-empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #e8edf2, #f0f4f8);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.rc-empty-state-icon i { font-size: 32px; color: #94a3b8; }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: #334155;\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: #64748b;\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 24px 0;\n}\n\n.rc-empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f1f5f9;\n border-radius: 20px;\n font-size: 12px;\n color: #64748b;\n}\n\n.rc-empty-state-hint i { color: #94a3b8; }\n\n/* \u2500\u2500\u2500 Page Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n padding-bottom: 20px;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: #111827;\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: #6b7280;\n margin-top: 4px;\n}\n\n.rc-header-meta { text-align: right; }\n\n.rc-entity-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n background: #eff6ff;\n color: #3b82f6;\n border: 1px solid #dbeafe;\n}\n\n.rc-change-count {\n font-size: 12px;\n color: #9ca3af;\n margin-top: 6px;\n}\n\n/* \u2500\u2500\u2500 Filter Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-filter-bar {\n display: flex;\n gap: 8px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.rc-search-wrap {\n position: relative;\n flex: 1;\n min-width: 180px;\n}\n\n.rc-search-wrap i {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: #9ca3af;\n font-size: 13px;\n pointer-events: none;\n}\n\n.rc-search-box {\n width: 100%;\n padding: 8px 12px 8px 36px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 13px;\n background: #fff;\n outline: none;\n color: #111827;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.rc-search-box::placeholder { color: #9ca3af; }\n\n.rc-filter-pill {\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n border: 1px solid #e5e7eb;\n background: #fff;\n cursor: pointer;\n color: #374151;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n.rc-filter-pill:hover {\n border-color: #6366f1;\n color: #6366f1;\n}\n\n.rc-filter-pill.active {\n background: #6366f1;\n color: #fff;\n border-color: #6366f1;\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: #6b7280;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-clear-filters-link {\n background: none;\n border: none;\n color: #6366f1;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 0;\n text-decoration: underline;\n}\n\n.rc-clear-filters-link:hover { color: #4f46e5; }\n\n/* \u2500\u2500\u2500 No Results \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-no-results {\n text-align: center;\n padding: 48px 16px;\n color: #6c757d;\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: #adb5bd;\n}\n\n.rc-no-results p { font-size: 14px; margin: 0 0 16px 0; }\n\n.rc-clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-clear-filters-btn:hover {\n border-color: #6366f1;\n color: #6366f1;\n}\n\n/* \u2500\u2500\u2500 Timeline \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-timeline {\n position: relative;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Vertical line running through the timeline */\n.rc-timeline::before {\n content: '';\n position: absolute;\n left: 15px;\n top: 24px;\n bottom: 0;\n width: 2px;\n background: #e5e7eb;\n}\n\n/* \u2500\u2500\u2500 Date Group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-date-group { margin-bottom: 8px; }\n\n.rc-date-label {\n position: relative;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: #9ca3af;\n padding: 16px 0 12px 44px;\n}\n\n/* Date dot on the timeline line */\n.rc-date-label::before {\n content: '';\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #e5e7eb;\n border: 2px solid #fafbfc;\n}\n\n/* \u2500\u2500\u2500 Change Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card {\n position: relative;\n margin-left: 44px;\n margin-bottom: 12px;\n background: #fff;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: #d1d5db;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);\n}\n\n.rc-card:focus {\n outline: 2px solid #6366f1;\n outline-offset: 2px;\n}\n\n/* Colored dot on the timeline line for each card */\n.rc-card::before {\n content: '';\n position: absolute;\n left: -23px;\n top: 20px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n z-index: 1;\n}\n\n.rc-card.type-update::before {\n background: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);\n}\n\n.rc-card.type-create::before {\n background: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);\n}\n\n.rc-card.type-delete::before {\n background: #ef4444;\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);\n}\n\n/* \u2500\u2500\u2500 Card Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card-header {\n padding: 14px 18px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n user-select: none;\n gap: 12px;\n}\n\n.rc-card-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.rc-card-type-badge {\n padding: 3px 10px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.3px;\n text-transform: uppercase;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.type-update .rc-card-type-badge { background: #eef2ff; color: #6366f1; }\n.type-create .rc-card-type-badge { background: #ecfdf5; color: #059669; }\n.type-delete .rc-card-type-badge { background: #fef2f2; color: #dc2626; }\n\n.rc-card-summary {\n font-size: 13px;\n color: #374151;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-card-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 12px;\n color: #9ca3af;\n flex-shrink: 0;\n}\n\n.rc-card-user {\n display: flex;\n align-items: center;\n gap: 5px;\n white-space: nowrap;\n}\n\n.rc-avatar {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: linear-gradient(135deg, #6366f1, #8b5cf6);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: #fff;\n flex-shrink: 0;\n}\n\n.rc-card-time { white-space: nowrap; }\n\n.rc-card-source {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.source-internal { background: #eff6ff; color: #3b82f6; }\n.source-external { background: #fefce8; color: #a16207; }\n\n.rc-card-status {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-complete { background: #ecfdf5; color: #059669; }\n.status-pending { background: #fefce8; color: #a16207; }\n.status-error { background: #fef2f2; color: #dc2626; }\n.status-unknown { background: #f3f4f6; color: #6b7280; }\n\n.rc-card-chevron {\n color: #9ca3af;\n transition: transform 0.2s;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.rc-card.expanded .rc-card-chevron { transform: rotate(180deg); }\n\n/* \u2500\u2500\u2500 Card Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card-body {\n border-top: 1px solid #f3f4f6;\n}\n\n/* \u2500\u2500\u2500 Field Row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-field-row {\n display: flex;\n align-items: stretch;\n border-bottom: 1px solid #f9fafb;\n}\n\n.rc-field-row:last-child { border-bottom: none; }\n\n.rc-field-label {\n width: 140px;\n min-width: 140px;\n padding: 12px 16px;\n font-size: 12px;\n font-weight: 600;\n color: #6b7280;\n background: #f9fafb;\n display: flex;\n align-items: center;\n border-right: 1px solid #f3f4f6;\n}\n\n.rc-field-values {\n flex: 1;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* \u2500\u2500\u2500 Atomic Change (numbers, dates) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-atomic-change {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.rc-val-old {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: #9ca3af;\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: #d1d5db;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.rc-val-new {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: #111827;\n font-weight: 500;\n}\n\n/* \u2500\u2500\u2500 Boolean Change \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-bool-change {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-bool-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.rc-bool-dot.on { background: #10b981; }\n.rc-bool-dot.off { background: #d1d5db; }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: #9ca3af;\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: #059669; }\n.rc-bool-label.new.inactive { color: #9ca3af; }\n\n/* \u2500\u2500\u2500 Text Diff (strings only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-text-diff {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.rc-diff-added {\n background: #dcfce7;\n color: #166534;\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: #fee2e2;\n color: #991b1b;\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: #374151;\n}\n\n/* \u2500\u2500\u2500 Deletion Note \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-deletion-note {\n padding: 16px 18px;\n color: #6b7280;\n font-size: 13px;\n font-style: italic;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-deletion-note i {\n color: #ef4444;\n font-size: 14px;\n}\n\n/* \u2500\u2500\u2500 Comments & Errors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-comments {\n padding: 12px 18px;\n background: #eff6ff;\n font-size: 13px;\n color: #1e40af;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid #f3f4f6;\n}\n\n.rc-comments i {\n color: #3b82f6;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: #fef2f2;\n font-size: 13px;\n color: #991b1b;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid #f3f4f6;\n}\n\n.rc-errors i {\n color: #ef4444;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: #fff;\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: #991b1b;\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n flex: 1;\n}\n\n/* \u2500\u2500\u2500 Create Wizard Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-wizard-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-wizard-container {\n background: #fff;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 24px;\n animation: rc-slideUp 0.2s ease;\n}\n\n@keyframes rc-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes rc-slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* \u2500\u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (max-width: 768px) {\n .rc-card-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .rc-card-meta {\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .rc-field-row {\n flex-direction: column;\n }\n\n .rc-field-label {\n width: 100%;\n min-width: unset;\n border-right: none;\n border-bottom: 1px solid #f3f4f6;\n padding: 8px 16px;\n }\n\n .rc-field-values {\n padding: 8px 16px;\n }\n\n .rc-atomic-change {\n flex-wrap: wrap;\n }\n\n .rc-filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .rc-search-wrap { min-width: unset; }\n\n .rc-filter-pill { justify-content: center; }\n\n .rc-page-header {\n flex-direction: column;\n gap: 12px;\n }\n\n .rc-header-meta { text-align: left; }\n}\n\n@media (max-width: 480px) {\n .rc-container { padding: 12px 16px; }\n\n .rc-card { margin-left: 36px; }\n\n .rc-date-label { padding-left: 36px; }\n\n .rc-card::before { left: -19px; }\n\n .rc-timeline::before { left: 12px; }\n\n .rc-date-label::before { left: 7px; }\n}\n"], encapsulation: 2, changeDetection: 0 });
869
947
  }
870
948
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesComponent, [{
871
949
  type: Component,
872
- args: [{ standalone: false, selector: 'mj-record-changes', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"'Record Changes History'\"\n [Visible]=\"IsVisible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"400\"\n [MaxWidthRatio]=\"0.6\"\n (Closed)=\"OnClose()\">\n\n @if (IsLoading) {\n <mj-loading text=\"Loading history...\" size=\"medium\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <div class=\"record-changes-container\">\n <!-- Version Labels Section -->\n <div class=\"labels-section\">\n <div class=\"labels-header\">\n <div class=\"labels-title\">\n <i class=\"fa-solid fa-tags\" aria-hidden=\"true\"></i>\n <span>Version Labels</span>\n @if (RecordLabels.length > 0) {\n <span class=\"labels-count\">{{ RecordLabels.length }}</span>\n }\n </div>\n <button class=\"create-label-btn\" (click)=\"OpenCreateWizard()\" title=\"Create a version label for this record\">\n <i class=\"fa-solid fa-plus\"></i> Create Label\n </button>\n </div>\n @if (IsLoadingLabels) {\n <div class=\"labels-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading labels...\n </div>\n } @else if (RecordLabels.length === 0) {\n <div class=\"labels-empty\">\n No version labels for this record yet.\n </div>\n } @else {\n <div class=\"labels-list\">\n @for (label of RecordLabels; track label.ID) {\n <div class=\"label-chip\" [title]=\"label.Description || label.Name\">\n <i class=\"fa-solid fa-tag label-chip-icon\"></i>\n <span class=\"label-chip-name\">{{ label.Name }}</span>\n <span class=\"label-chip-meta\">\n <span class=\"label-chip-status\" [class]=\"getLabelStatusClass(label.Status)\">{{ label.Status }}</span>\n <span class=\"label-chip-items\">{{ label.ItemCount }} item{{ label.ItemCount !== 1 ? 's' : '' }}</span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (viewData.length === 0) {\n <!-- Empty state \u2014 no changes ever recorded -->\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <h3 class=\"empty-state-title\">No Change History</h3>\n <p class=\"empty-state-description\">\n This record doesn't have any tracked changes yet.\n Changes will appear here automatically as edits are made.\n </p>\n <div class=\"empty-state-hint\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Record change tracking is managed at the entity level</span>\n </div>\n </div>\n } @else {\n <!-- Filter Panel -->\n <div class=\"filter-panel\">\n <div class=\"filter-controls\">\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search changes...\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n aria-label=\"Search record changes\"\n />\n <select\n class=\"filter-select\"\n [(ngModel)]=\"selectedType\"\n (change)=\"onFilterChange()\"\n aria-label=\"Filter by change type\"\n >\n <option value=\"\">All Changes</option>\n <option value=\"Create\">Created</option>\n <option value=\"Update\">Updated</option>\n <option value=\"Delete\">Deleted</option>\n </select>\n <select\n class=\"filter-select\"\n [(ngModel)]=\"selectedSource\"\n (change)=\"onFilterChange()\"\n aria-label=\"Filter by change source\"\n >\n <option value=\"\">All Sources</option>\n <option value=\"Internal\">Internal</option>\n <option value=\"External\">External</option>\n </select>\n </div>\n @if (filteredData.length !== viewData.length) {\n <div class=\"filter-results\">\n Showing {{ filteredData.length }} of {{ viewData.length }} changes\n </div>\n }\n </div>\n\n <!-- Timeline Container -->\n <div class=\"timeline-container\" [attr.aria-label]=\"'Timeline of changes for ' + record.EntityInfo.Name + ' record'\">\n @if (filteredData.length === 0) {\n <div class=\"no-changes-message\">\n <i class=\"fa-solid fa-filter\"></i>\n <p>No changes match your current filters.</p>\n <button class=\"clear-filters-btn\" (click)=\"ClearFilters()\">\n <i class=\"fa-solid fa-xmark\"></i> Clear Filters\n </button>\n </div>\n } @else {\n <div class=\"timeline\">\n @for (change of filteredData; track change.ID; let i = $index) {\n <div\n class=\"timeline-item\"\n [class.expanded]=\"expandedItems.has(change.ID)\"\n [attr.tabindex]=\"0\"\n [attr.aria-expanded]=\"expandedItems.has(change.ID)\"\n [attr.aria-label]=\"getTimelineItemLabel(change)\"\n (click)=\"toggleExpansion(change.ID)\"\n (keydown)=\"onTimelineItemKeydown($event, change.ID)\"\n >\n <div class=\"timeline-marker\">\n <div class=\"timeline-icon\" [class]=\"getChangeTypeClass(change.Type)\">\n <i [class]=\"getChangeTypeIcon(change.Type)\" [attr.aria-hidden]=\"true\"></i>\n </div>\n @if (i < filteredData.length - 1) {\n <div class=\"timeline-line\"></div>\n }\n </div>\n\n <div class=\"timeline-content\">\n <div class=\"change-header\">\n <div class=\"change-title\">\n <span class=\"change-type-badge\" [class]=\"getChangeTypeBadgeClass(change.Type)\">\n {{ change.Type }}\n </span>\n <span class=\"change-user\">{{ change.User || 'Unknown User' }}</span>\n <span class=\"change-source\" [class]=\"getSourceClass(change.Source)\">\n {{ change.Source }}\n </span>\n </div>\n <div class=\"change-meta\">\n <span class=\"change-time\" [title]=\"formatFullDateTime(change.ChangedAt)\">\n {{ formatRelativeTime(change.ChangedAt) }}\n </span>\n <span class=\"change-status\" [class]=\"getStatusClass(change.Status)\">\n {{ change.Status }}\n </span>\n @if (change.Integration) {\n <span class=\"change-integration\">\n via {{ change.Integration }}\n </span>\n }\n </div>\n </div>\n\n @if (!expandedItems.has(change.ID)) {\n <div class=\"change-summary\">\n {{ getChangeSummary(change) }}\n </div>\n }\n\n @if (expandedItems.has(change.ID)) {\n <div class=\"change-details\">\n <div class=\"change-timestamp\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <strong>{{ formatFullDateTime(change.ChangedAt) }}</strong>\n </div>\n @if (change.Type === 'Create') {\n <div class=\"creation-details\">\n <h4><i class=\"fa-solid fa-plus\"></i> Record Created</h4>\n @if (change.FullRecordJSON) {\n <div class=\"field-changes\">\n @for (field of getCreatedFields(change); track field.name) {\n <div class=\"field-change created\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n <span class=\"field-value new-value\">{{ field.value }}</span>\n </div>\n }\n </div>\n }\n </div>\n } @else if (change.Type === 'Delete') {\n <div class=\"deletion-details\">\n <h4><i class=\"fa-solid fa-trash\"></i> Record Deleted</h4>\n <p class=\"deletion-note\">This record was permanently removed from the system.</p>\n </div>\n } @else {\n <div class=\"update-details\">\n <h4><i class=\"fa-solid fa-edit\"></i> Fields Changed</h4>\n <div class=\"field-changes\">\n @for (fieldChange of getFieldChanges(change); track fieldChange.field) {\n <div class=\"field-change\">\n <div class=\"field-name\">{{ fieldChange.displayName }}</div>\n @if (fieldChange.isBooleanField) {\n <div class=\"boolean-change\">\n <span class=\"new-value\">{{ fieldChange.newValue }}</span>\n </div>\n } @else if (fieldChange.diffHtml) {\n <div class=\"diff-view\">\n <div class=\"diff-content\" [innerHTML]=\"fieldChange.diffHtml\"></div>\n </div>\n } @else {\n <div class=\"value-diff\">\n <div class=\"old-value\">\n <span class=\"value-label\">From:</span>\n <span class=\"value\">{{ fieldChange.oldValue || '(empty)' }}</span>\n </div>\n <div class=\"diff-arrow\">\n <i class=\"fa-solid fa-arrow-right\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"new-value\">\n <span class=\"value-label\">To:</span>\n <span class=\"value\">{{ fieldChange.newValue || '(empty)' }}</span>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n @if (change.Comments) {\n <div class=\"change-comments\">\n <h5><i class=\"fa-solid fa-comment\"></i> Comments</h5>\n <p>{{ change.Comments }}</p>\n </div>\n }\n\n @if (change.ErrorLog) {\n <div class=\"change-errors\">\n <h5><i class=\"fa-solid fa-exclamation-triangle\"></i> Errors</h5>\n <pre class=\"error-log\">{{ change.ErrorLog }}</pre>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (ShowCreateWizard) {\n <div class=\"create-wizard-overlay\" (click)=\"OnLabelCreateCancelled()\">\n <div class=\"create-wizard-container\" (click)=\"$event.stopPropagation()\">\n <mj-label-create\n [PreselectedEntity]=\"record.EntityInfo\"\n [PreselectedRecordIds]=\"[record.PrimaryKey.KeyValuePairs[0].Value]\"\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnLabelCreateCancelled()\">\n </mj-label-create>\n </div>\n </div>\n }\n</mj-slide-panel>\n", styles: ["/* Record Changes Timeline Styles */\n.record-changes-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 1rem;\n}\n\n/* Version Labels Section */\n.labels-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n border: 1px solid #e9ecef;\n}\n\n.labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 0.5rem;\n}\n\n.labels-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-weight: 600;\n font-size: 0.9rem;\n color: #495057;\n}\n\n.labels-title i {\n color: #6f42c1;\n}\n\n.labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.25rem;\n height: 1.25rem;\n padding: 0 0.35rem;\n border-radius: 10px;\n background: #6f42c1;\n color: white;\n font-size: 0.7rem;\n font-weight: 700;\n}\n\n.create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.35rem 0.75rem;\n border: 1px solid #6f42c1;\n border-radius: 6px;\n background: white;\n color: #6f42c1;\n font-size: 0.8rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.create-label-btn:hover {\n background: #6f42c1;\n color: white;\n}\n\n.labels-loading {\n font-size: 0.8rem;\n color: #6c757d;\n padding: 0.25rem 0;\n}\n\n.labels-loading i {\n margin-right: 0.25rem;\n}\n\n.labels-empty {\n font-size: 0.8rem;\n color: #94a3b8;\n font-style: italic;\n padding: 0.25rem 0;\n}\n\n.labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.label-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.3rem 0.6rem;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 16px;\n font-size: 0.8rem;\n color: #495057;\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.label-chip:hover {\n border-color: #6f42c1;\n box-shadow: 0 1px 3px rgba(111, 66, 193, 0.15);\n}\n\n.label-chip-icon {\n color: #6f42c1;\n font-size: 0.7rem;\n}\n\n.label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.label-chip-meta {\n display: flex;\n align-items: center;\n gap: 0.3rem;\n font-size: 0.7rem;\n color: #6c757d;\n}\n\n.label-chip-status {\n padding: 0.1rem 0.3rem;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 0.6rem;\n letter-spacing: 0.03em;\n}\n\n.label-status-active {\n background: #d4edda;\n color: #155724;\n}\n\n.label-status-archived {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.label-status-restored {\n background: #cce7ff;\n color: #004085;\n}\n\n.label-chip-items {\n white-space: nowrap;\n}\n\n/* Create Wizard Overlay */\n.create-wizard-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: fadeIn 0.15s ease;\n}\n\n.create-wizard-container {\n background: white;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 1.5rem;\n animation: slideUp 0.2s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* Filter Panel */\n.filter-panel {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 1rem;\n border: 1px solid #e9ecef;\n}\n\n.filter-controls {\n display: flex;\n gap: 1rem;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.search-input {\n flex: 1;\n min-width: 200px;\n padding: 0.5rem 1rem;\n border: 1px solid #ced4da;\n border-radius: 4px;\n font-size: 0.9rem;\n}\n\n.search-input:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.filter-select {\n padding: 0.5rem;\n border: 1px solid #ced4da;\n border-radius: 4px;\n background: white;\n font-size: 0.9rem;\n min-width: 120px;\n}\n\n.filter-select:focus {\n outline: none;\n border-color: #007bff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.filter-results {\n margin-top: 0.5rem;\n font-size: 0.85rem;\n color: #6c757d;\n font-style: italic;\n}\n\n/* Empty State */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n text-align: center;\n min-height: 400px;\n}\n\n.empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #e8edf2, #f0f4f8);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 1.5rem;\n}\n\n.empty-state-icon i {\n font-size: 2rem;\n color: #94a3b8;\n}\n\n.empty-state-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: #334155;\n margin: 0 0 0.75rem 0;\n}\n\n.empty-state-description {\n font-size: 0.95rem;\n color: #64748b;\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 1.5rem 0;\n}\n\n.empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: #f1f5f9;\n border-radius: 20px;\n font-size: 0.8rem;\n color: #64748b;\n}\n\n.empty-state-hint i {\n color: #94a3b8;\n}\n\n/* No filtered results */\n.no-changes-message {\n text-align: center;\n padding: 3rem 1rem;\n color: #6c757d;\n}\n\n.no-changes-message i {\n display: block;\n font-size: 2rem;\n margin-bottom: 1rem;\n color: #adb5bd;\n}\n\n.no-changes-message p {\n font-size: 1rem;\n margin: 0 0 1rem 0;\n}\n\n.clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.4rem 1rem;\n border: 1px solid #ced4da;\n border-radius: 6px;\n background: white;\n color: #495057;\n font-size: 0.85rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.clear-filters-btn:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n}\n\n/* Timeline Container */\n.timeline-container {\n flex: 1;\n overflow-y: auto;\n padding-right: 0.5rem;\n}\n\n/* Timeline */\n.timeline {\n position: relative;\n padding-left: 2rem;\n}\n\n.timeline-item {\n position: relative;\n margin-bottom: 1.5rem;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.timeline-item:hover {\n transform: translateX(2px);\n}\n\n.timeline-item:focus {\n outline: 2px solid #007bff;\n outline-offset: 2px;\n border-radius: 4px;\n}\n\n.timeline-item.expanded {\n margin-bottom: 2rem;\n}\n\n/* Timeline Marker */\n.timeline-marker {\n position: absolute;\n left: -2rem;\n top: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.timeline-icon {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.9rem;\n color: white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n z-index: 2;\n}\n\n.timeline-icon.change-create {\n background: linear-gradient(135deg, #28a745, #20c997);\n}\n\n.timeline-icon.change-update {\n background: linear-gradient(135deg, #007bff, #6f42c1);\n}\n\n.timeline-icon.change-delete {\n background: linear-gradient(135deg, #dc3545, #fd7e14);\n}\n\n.timeline-icon.change-unknown {\n background: linear-gradient(135deg, #6c757d, #adb5bd);\n}\n\n.timeline-line {\n width: 2px;\n height: 2rem;\n background: #e9ecef;\n margin-top: 0.5rem;\n}\n\n/* Timeline Content */\n.timeline-content {\n background: white;\n border: 1px solid #e9ecef;\n border-radius: 8px;\n padding: 1rem;\n box-shadow: 0 2px 4px rgba(0,0,0,0.05);\n transition: box-shadow 0.2s ease;\n}\n\n.timeline-item:hover .timeline-content {\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n}\n\n.timeline-item.expanded .timeline-content {\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n}\n\n/* Change Header */\n.change-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.change-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.change-type-badge {\n font-size: 0.75rem;\n font-weight: 600;\n padding: 0.25rem 0.5rem;\n border-radius: 12px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.badge-create {\n background: #d4edda;\n color: #155724;\n}\n\n.badge-update {\n background: #cce7ff;\n color: #004085;\n}\n\n.badge-delete {\n background: #f8d7da;\n color: #721c24;\n}\n\n.badge-unknown {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.change-user {\n font-weight: 600;\n color: #495057;\n}\n\n.change-source {\n font-size: 0.8rem;\n padding: 0.2rem 0.4rem;\n border-radius: 8px;\n font-weight: 500;\n}\n\n.source-internal {\n background: #e7f3ff;\n color: #0056b3;\n}\n\n.source-external {\n background: #fff3cd;\n color: #856404;\n}\n\n.change-meta {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.85rem;\n color: #6c757d;\n flex-wrap: wrap;\n}\n\n.change-time {\n font-weight: 500;\n}\n\n.change-status {\n padding: 0.2rem 0.4rem;\n border-radius: 8px;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-complete {\n background: #d4edda;\n color: #155724;\n}\n\n.status-pending {\n background: #fff3cd;\n color: #856404;\n}\n\n.status-error {\n background: #f8d7da;\n color: #721c24;\n}\n\n.status-unknown {\n background: #e2e3e5;\n color: #383d41;\n}\n\n.change-integration {\n font-style: italic;\n color: #495057;\n}\n\n/* Change Summary */\n.change-summary {\n color: #6c757d;\n font-size: 0.9rem;\n line-height: 1.4;\n}\n\n/* Change Details */\n.change-details {\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid #e9ecef;\n}\n\n.change-timestamp {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 1rem;\n padding: 0.5rem;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 4px solid #6c757d;\n font-size: 0.9rem;\n color: #495057;\n}\n\n.change-timestamp i {\n color: #6c757d;\n}\n\n.change-details h4 {\n font-size: 1rem;\n margin-bottom: 1rem;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.change-details h5 {\n font-size: 0.9rem;\n margin-bottom: 0.5rem;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n/* Field Changes */\n.field-changes {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.field-change {\n background: #f8f9fa;\n border-radius: 6px;\n padding: 0.75rem;\n border-left: 4px solid #007bff;\n}\n\n.field-change.created {\n border-left-color: #28a745;\n}\n\n.field-name {\n font-weight: 600;\n color: #495057;\n margin-bottom: 0.5rem;\n display: block;\n}\n\n.field-value {\n font-family: 'Courier New', monospace;\n font-size: 0.85rem;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n background: white;\n border: 1px solid #dee2e6;\n}\n\n.value-diff {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 1rem;\n align-items: center;\n}\n\n.old-value, .new-value {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.value-label {\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #6c757d;\n}\n\n.old-value .value {\n color: #6c757d;\n background: #f8f9fa;\n text-decoration: line-through;\n}\n\n.new-value .value {\n color: #155724;\n background: #d4edda;\n font-weight: 500;\n}\n\n.value {\n font-family: 'Courier New', monospace;\n font-size: 0.85rem;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n border: 1px solid #dee2e6;\n word-break: break-all;\n}\n\n.diff-arrow {\n color: #007bff;\n font-size: 1.2rem;\n}\n\n.boolean-change .new-value {\n font-weight: 600;\n color: #007bff;\n font-size: 0.9rem;\n}\n\n/* Creation Details */\n.creation-details .field-change {\n border-left-color: #28a745;\n}\n\n.creation-details .field-value {\n color: #155724;\n background: #d4edda;\n font-weight: 500;\n}\n\n/* Deletion Details */\n.deletion-details {\n text-align: center;\n padding: 1rem;\n}\n\n.deletion-note {\n color: #6c757d;\n font-style: italic;\n margin-bottom: 0;\n}\n\n/* Diff View Styles */\n.diff-view {\n margin-top: 0.5rem;\n border: 1px dashed #28a745;\n border-radius: 4px;\n padding: 0.25rem;\n}\n\n.diff-content {\n background: #ffffff;\n border: 2px solid #007bff;\n border-radius: 6px;\n padding: 0.75rem;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 0.85rem;\n line-height: 1.45;\n overflow-x: auto;\n min-height: 2rem;\n}\n\n.diff-container {\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.diff-added {\n background-color: #d1f5d3;\n color: #22863a;\n text-decoration: none;\n border-radius: 3px;\n padding: 2px 4px;\n font-weight: 600;\n display: inline;\n border: 1px solid #28a745;\n position: relative;\n margin: 0 1px;\n}\n\n.diff-removed {\n background-color: #ffeef0;\n color: #d73a49;\n text-decoration: line-through;\n border-radius: 3px;\n padding: 2px 4px;\n font-weight: 600;\n display: inline;\n border: 1px solid #dc3545;\n position: relative;\n margin: 0 1px;\n}\n\n.diff-unchanged {\n color: #24292e;\n display: inline;\n}\n\n/* Hover effects for diff elements */\n.diff-added:hover {\n background-color: #c3f0c5;\n box-shadow: 0 0 0 2px rgba(40, 167, 69, 0.15);\n}\n\n.diff-removed:hover {\n background-color: #ffd6dd;\n box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.15);\n}\n\n/* Comments and Errors */\n.change-comments, .change-errors {\n margin-top: 1rem;\n padding: 0.75rem;\n border-radius: 6px;\n}\n\n.change-comments {\n background: #e7f3ff;\n border-left: 4px solid #007bff;\n}\n\n.change-errors {\n background: #f8d7da;\n border-left: 4px solid #dc3545;\n}\n\n.error-log {\n background: #ffffff;\n padding: 0.5rem;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 0.8rem;\n color: #721c24;\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .filter-controls {\n flex-direction: column;\n align-items: stretch;\n }\n\n .search-input, .filter-select {\n width: 100%;\n }\n\n .change-header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .change-meta {\n flex-direction: column;\n align-items: flex-start;\n gap: 0.25rem;\n }\n\n .value-diff {\n grid-template-columns: 1fr;\n gap: 0.5rem;\n }\n\n .diff-arrow {\n justify-self: center;\n transform: rotate(90deg);\n }\n\n .timeline {\n padding-left: 1.5rem;\n }\n\n .timeline-marker {\n left: -1.5rem;\n }\n\n .timeline-icon {\n width: 2rem;\n height: 2rem;\n font-size: 0.8rem;\n }\n\n .diff-content {\n font-size: 0.8rem;\n padding: 0.5rem;\n }\n\n .diff-added, .diff-removed {\n padding: 1px 2px;\n }\n}\n\n@media (max-width: 480px) {\n .record-changes-container {\n padding: 0.5rem;\n }\n\n .timeline-content {\n padding: 0.75rem;\n }\n\n .field-change {\n padding: 0.5rem;\n }\n}\n"] }]
873
- }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJNotificationService }, { type: i2.DomSanitizer }], { dialogClosed: [{
950
+ args: [{ standalone: false, selector: 'mj-record-changes', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"'Record Changes History'\"\n [Visible]=\"IsVisible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"400\"\n [MaxWidthRatio]=\"0.6\"\n (Closed)=\"OnClose()\">\n\n @if (IsLoading) {\n <mj-loading text=\"Loading history...\" size=\"medium\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <div class=\"rc-container\">\n <!-- Version Labels Section -->\n <div class=\"rc-labels-section\">\n <div class=\"rc-labels-header\">\n <div class=\"rc-labels-title\">\n <i class=\"fa-solid fa-tags\" aria-hidden=\"true\"></i>\n <span>Version Labels</span>\n @if (RecordLabels.length > 0) {\n <span class=\"rc-labels-count\">{{ RecordLabels.length }}</span>\n }\n </div>\n <button class=\"rc-create-label-btn\" (click)=\"OpenCreateWizard()\" title=\"Create a version label for this record\">\n <i class=\"fa-solid fa-plus\"></i> Create Label\n </button>\n </div>\n @if (IsLoadingLabels) {\n <div class=\"rc-labels-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading labels...\n </div>\n } @else if (RecordLabels.length === 0) {\n <div class=\"rc-labels-empty\">\n No version labels for this record yet.\n </div>\n } @else {\n <div class=\"rc-labels-list\">\n @for (label of RecordLabels; track label.ID) {\n <div class=\"rc-label-chip\" [title]=\"label.Description || label.Name\">\n <i class=\"fa-solid fa-tag rc-label-chip-icon\"></i>\n <span class=\"rc-label-chip-name\">{{ label.Name }}</span>\n <span class=\"rc-label-chip-meta\">\n <span class=\"rc-label-chip-status\" [class]=\"getLabelStatusClass(label.Status)\">{{ label.Status }}</span>\n <span class=\"rc-label-chip-items\">{{ label.ItemCount }} item{{ label.ItemCount !== 1 ? 's' : '' }}</span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (viewData.length === 0) {\n <!-- Empty state -->\n <div class=\"rc-empty-state\">\n <div class=\"rc-empty-state-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <h3 class=\"rc-empty-state-title\">No Change History</h3>\n <p class=\"rc-empty-state-description\">\n This record doesn't have any tracked changes yet.\n Changes will appear here automatically as edits are made.\n </p>\n <div class=\"rc-empty-state-hint\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Record change tracking is managed at the entity level</span>\n </div>\n </div>\n } @else {\n <!-- Page Header -->\n <div class=\"rc-page-header\">\n <div>\n <h2 class=\"rc-page-title\">Change History</h2>\n <div class=\"rc-page-subtitle\">{{ record.EntityInfo.Name }}</div>\n </div>\n <div class=\"rc-header-meta\">\n <div class=\"rc-entity-badge\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n {{ record.EntityInfo.Name }}\n </div>\n <div class=\"rc-change-count\">{{ viewData.length }} change{{ viewData.length !== 1 ? 's' : '' }} &middot; {{ getUniqueContributorCount() }} contributor{{ getUniqueContributorCount() !== 1 ? 's' : '' }}</div>\n </div>\n </div>\n\n <!-- Filter Bar -->\n <div class=\"rc-filter-bar\">\n <div class=\"rc-search-wrap\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <input\n class=\"rc-search-box\"\n type=\"text\"\n placeholder=\"Search changes...\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n aria-label=\"Search record changes\"\n />\n </div>\n <button class=\"rc-filter-pill\" [class.active]=\"!selectedType\" (click)=\"SetTypeFilter('')\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i> All\n </button>\n <button class=\"rc-filter-pill\" [class.active]=\"selectedType === 'Update'\" (click)=\"SetTypeFilter('Update')\">\n <i class=\"fa-solid fa-pen\" aria-hidden=\"true\"></i> Updates\n </button>\n <button class=\"rc-filter-pill\" [class.active]=\"selectedType === 'Create'\" (click)=\"SetTypeFilter('Create')\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i> Creates\n </button>\n <button class=\"rc-filter-pill\" [class.active]=\"selectedType === 'Delete'\" (click)=\"SetTypeFilter('Delete')\">\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i> Deletes\n </button>\n </div>\n\n @if (filteredData.length !== viewData.length) {\n <div class=\"rc-filter-results\">\n Showing {{ filteredData.length }} of {{ viewData.length }} changes\n <button class=\"rc-clear-filters-link\" (click)=\"ClearFilters()\">Clear filters</button>\n </div>\n }\n\n <!-- Timeline -->\n <div class=\"rc-timeline\" [attr.aria-label]=\"'Timeline of changes for ' + record.EntityInfo.Name + ' record'\">\n @if (filteredData.length === 0) {\n <div class=\"rc-no-results\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n <p>No changes match your current filters.</p>\n <button class=\"rc-clear-filters-btn\" (click)=\"ClearFilters()\">\n <i class=\"fa-solid fa-xmark\"></i> Clear Filters\n </button>\n </div>\n } @else {\n @for (group of dateGroups; track group.label) {\n <div class=\"rc-date-group\">\n <div class=\"rc-date-label\">{{ group.label }}</div>\n\n @for (change of group.changes; track change.ID) {\n <div\n class=\"rc-card\"\n [class]=\"getChangeTypeCardClass(change.Type)\"\n [class.expanded]=\"expandedItems.has(change.ID)\"\n [attr.tabindex]=\"0\"\n [attr.aria-expanded]=\"expandedItems.has(change.ID)\"\n [attr.aria-label]=\"getTimelineItemLabel(change)\"\n (keydown)=\"onTimelineItemKeydown($event, change.ID)\"\n >\n <!-- Card Header -->\n <div class=\"rc-card-header\" (click)=\"toggleExpansion(change.ID)\">\n <div class=\"rc-card-header-left\">\n <span class=\"rc-card-type-badge\">{{ getChangeTypeBadgeText(change.Type) }}</span>\n <span class=\"rc-card-summary\">{{ getChangeSummary(change) }}</span>\n </div>\n <div class=\"rc-card-meta\">\n <div class=\"rc-card-user\">\n <div class=\"rc-avatar\">{{ getUserInitials(change.User) }}</div>\n {{ getUserDisplayName(change.User) }}\n </div>\n <span class=\"rc-card-time\" [title]=\"formatFullDateTime(change.ChangedAt)\">{{ formatTime(change.ChangedAt) }}</span>\n <span class=\"rc-card-source\" [class]=\"getSourceClass(change.Source)\">{{ change.Source }}</span>\n <span class=\"rc-card-status\" [class]=\"getStatusClass(change.Status)\">{{ change.Status }}</span>\n <i class=\"fa-solid fa-chevron-down rc-card-chevron\" aria-hidden=\"true\"></i>\n </div>\n </div>\n\n <!-- Card Body (expanded) -->\n @if (expandedItems.has(change.ID)) {\n <div class=\"rc-card-body\">\n @if (change.Type === 'Create') {\n <!-- Created record fields -->\n @if (change.FullRecordJSON) {\n @for (field of getCreatedFields(change); track field.name) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ field.displayName }}</div>\n <div class=\"rc-field-values\">\n <span class=\"rc-val-new\">{{ field.value }}</span>\n </div>\n </div>\n }\n }\n } @else if (change.Type === 'Delete') {\n <div class=\"rc-deletion-note\">\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n This record was permanently removed from the system.\n </div>\n } @else {\n <!-- Update: type-aware field changes -->\n @for (fc of getFieldChanges(change); track fc.field) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ fc.displayName }}</div>\n <div class=\"rc-field-values\">\n @if (fc.fieldType === 'boolean') {\n <!-- Boolean: dot indicators -->\n <div class=\"rc-bool-change\">\n <span class=\"rc-bool-dot\" [class.on]=\"fc.oldValue === 'true' || fc.oldValue === '1'\" [class.off]=\"fc.oldValue !== 'true' && fc.oldValue !== '1'\"></span>\n <span class=\"rc-bool-label old\">{{ fc.oldValue === 'true' || fc.oldValue === '1' ? 'Yes' : 'No' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-bool-dot\" [class.on]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.off]=\"fc.newValue !== 'true' && fc.newValue !== '1'\"></span>\n <span class=\"rc-bool-label new\" [class.active]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.inactive]=\"fc.newValue !== 'true' && fc.newValue !== '1'\">{{ fc.newValue === 'true' || fc.newValue === '1' ? 'Yes' : 'No' }}</span>\n </div>\n } @else if (fc.fieldType === 'date' || fc.fieldType === 'number') {\n <!-- Atomic: old \u2192 new -->\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n } @else if (fc.diffHtml) {\n <!-- Text: word/char diff -->\n <div class=\"rc-text-diff\" [innerHTML]=\"fc.diffHtml\"></div>\n } @else {\n <!-- Fallback: old \u2192 new -->\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (change.Comments) {\n <div class=\"rc-comments\">\n <i class=\"fa-solid fa-comment\" aria-hidden=\"true\"></i>\n {{ change.Comments }}\n </div>\n }\n\n @if (change.ErrorLog) {\n <div class=\"rc-errors\">\n <i class=\"fa-solid fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n <pre class=\"rc-error-log\">{{ change.ErrorLog }}</pre>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\n @if (ShowCreateWizard) {\n <div class=\"rc-wizard-overlay\" (click)=\"OnLabelCreateCancelled()\">\n <div class=\"rc-wizard-container\" (click)=\"$event.stopPropagation()\">\n <mj-label-create\n [PreselectedEntity]=\"record.EntityInfo\"\n [PreselectedRecordIds]=\"[record.PrimaryKey.KeyValuePairs[0].Value]\"\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnLabelCreateCancelled()\">\n </mj-label-create>\n </div>\n </div>\n }\n</mj-slide-panel>\n", styles: ["/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Record Changes \u2014 Option A \"Clean Timeline\"\n Linear / Notion-inspired minimal timeline design\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500\u2500 Container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px 24px;\n background: #fafbfc;\n}\n\n/* \u2500\u2500\u2500 Version Labels Section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-labels-section {\n background: #f8f9fa;\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid #e9ecef;\n}\n\n.rc-labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.rc-labels-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: #495057;\n}\n\n.rc-labels-title i { color: #6f42c1; }\n\n.rc-labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 10px;\n background: #6f42c1;\n color: #fff;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid #6f42c1;\n border-radius: 6px;\n background: #fff;\n color: #6f42c1;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-create-label-btn:hover {\n background: #6f42c1;\n color: #fff;\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: #6c757d;\n padding: 4px 0;\n}\n\n.rc-labels-loading i { margin-right: 4px; }\n\n.rc-labels-empty {\n font-size: 12px;\n color: #94a3b8;\n font-style: italic;\n padding: 4px 0;\n}\n\n.rc-labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.rc-label-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n background: #fff;\n border: 1px solid #dee2e6;\n border-radius: 16px;\n font-size: 12px;\n color: #495057;\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: #6f42c1;\n box-shadow: 0 1px 3px rgba(111, 66, 193, 0.15);\n}\n\n.rc-label-chip-icon { color: #6f42c1; font-size: 10px; }\n\n.rc-label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-label-chip-meta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n color: #6c757d;\n}\n\n.rc-label-chip-status {\n padding: 1px 5px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 9px;\n letter-spacing: 0.03em;\n}\n\n.label-status-active { background: #d4edda; color: #155724; }\n.label-status-archived { background: #e2e3e5; color: #383d41; }\n.label-status-restored { background: #cce7ff; color: #004085; }\n\n.rc-label-chip-items { white-space: nowrap; }\n\n/* \u2500\u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 32px;\n text-align: center;\n min-height: 400px;\n}\n\n.rc-empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #e8edf2, #f0f4f8);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.rc-empty-state-icon i { font-size: 32px; color: #94a3b8; }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: #334155;\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: #64748b;\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 24px 0;\n}\n\n.rc-empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f1f5f9;\n border-radius: 20px;\n font-size: 12px;\n color: #64748b;\n}\n\n.rc-empty-state-hint i { color: #94a3b8; }\n\n/* \u2500\u2500\u2500 Page Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n padding-bottom: 20px;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: #111827;\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: #6b7280;\n margin-top: 4px;\n}\n\n.rc-header-meta { text-align: right; }\n\n.rc-entity-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n background: #eff6ff;\n color: #3b82f6;\n border: 1px solid #dbeafe;\n}\n\n.rc-change-count {\n font-size: 12px;\n color: #9ca3af;\n margin-top: 6px;\n}\n\n/* \u2500\u2500\u2500 Filter Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-filter-bar {\n display: flex;\n gap: 8px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.rc-search-wrap {\n position: relative;\n flex: 1;\n min-width: 180px;\n}\n\n.rc-search-wrap i {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: #9ca3af;\n font-size: 13px;\n pointer-events: none;\n}\n\n.rc-search-box {\n width: 100%;\n padding: 8px 12px 8px 36px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 13px;\n background: #fff;\n outline: none;\n color: #111827;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.rc-search-box::placeholder { color: #9ca3af; }\n\n.rc-filter-pill {\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n border: 1px solid #e5e7eb;\n background: #fff;\n cursor: pointer;\n color: #374151;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n.rc-filter-pill:hover {\n border-color: #6366f1;\n color: #6366f1;\n}\n\n.rc-filter-pill.active {\n background: #6366f1;\n color: #fff;\n border-color: #6366f1;\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: #6b7280;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-clear-filters-link {\n background: none;\n border: none;\n color: #6366f1;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 0;\n text-decoration: underline;\n}\n\n.rc-clear-filters-link:hover { color: #4f46e5; }\n\n/* \u2500\u2500\u2500 No Results \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-no-results {\n text-align: center;\n padding: 48px 16px;\n color: #6c757d;\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: #adb5bd;\n}\n\n.rc-no-results p { font-size: 14px; margin: 0 0 16px 0; }\n\n.rc-clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-clear-filters-btn:hover {\n border-color: #6366f1;\n color: #6366f1;\n}\n\n/* \u2500\u2500\u2500 Timeline \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-timeline {\n position: relative;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Vertical line running through the timeline */\n.rc-timeline::before {\n content: '';\n position: absolute;\n left: 15px;\n top: 24px;\n bottom: 0;\n width: 2px;\n background: #e5e7eb;\n}\n\n/* \u2500\u2500\u2500 Date Group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-date-group { margin-bottom: 8px; }\n\n.rc-date-label {\n position: relative;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: #9ca3af;\n padding: 16px 0 12px 44px;\n}\n\n/* Date dot on the timeline line */\n.rc-date-label::before {\n content: '';\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #e5e7eb;\n border: 2px solid #fafbfc;\n}\n\n/* \u2500\u2500\u2500 Change Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card {\n position: relative;\n margin-left: 44px;\n margin-bottom: 12px;\n background: #fff;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: #d1d5db;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);\n}\n\n.rc-card:focus {\n outline: 2px solid #6366f1;\n outline-offset: 2px;\n}\n\n/* Colored dot on the timeline line for each card */\n.rc-card::before {\n content: '';\n position: absolute;\n left: -23px;\n top: 20px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n z-index: 1;\n}\n\n.rc-card.type-update::before {\n background: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);\n}\n\n.rc-card.type-create::before {\n background: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);\n}\n\n.rc-card.type-delete::before {\n background: #ef4444;\n box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);\n}\n\n/* \u2500\u2500\u2500 Card Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card-header {\n padding: 14px 18px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n user-select: none;\n gap: 12px;\n}\n\n.rc-card-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.rc-card-type-badge {\n padding: 3px 10px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.3px;\n text-transform: uppercase;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.type-update .rc-card-type-badge { background: #eef2ff; color: #6366f1; }\n.type-create .rc-card-type-badge { background: #ecfdf5; color: #059669; }\n.type-delete .rc-card-type-badge { background: #fef2f2; color: #dc2626; }\n\n.rc-card-summary {\n font-size: 13px;\n color: #374151;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-card-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 12px;\n color: #9ca3af;\n flex-shrink: 0;\n}\n\n.rc-card-user {\n display: flex;\n align-items: center;\n gap: 5px;\n white-space: nowrap;\n}\n\n.rc-avatar {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: linear-gradient(135deg, #6366f1, #8b5cf6);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: #fff;\n flex-shrink: 0;\n}\n\n.rc-card-time { white-space: nowrap; }\n\n.rc-card-source {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.source-internal { background: #eff6ff; color: #3b82f6; }\n.source-external { background: #fefce8; color: #a16207; }\n\n.rc-card-status {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-complete { background: #ecfdf5; color: #059669; }\n.status-pending { background: #fefce8; color: #a16207; }\n.status-error { background: #fef2f2; color: #dc2626; }\n.status-unknown { background: #f3f4f6; color: #6b7280; }\n\n.rc-card-chevron {\n color: #9ca3af;\n transition: transform 0.2s;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.rc-card.expanded .rc-card-chevron { transform: rotate(180deg); }\n\n/* \u2500\u2500\u2500 Card Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-card-body {\n border-top: 1px solid #f3f4f6;\n}\n\n/* \u2500\u2500\u2500 Field Row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-field-row {\n display: flex;\n align-items: stretch;\n border-bottom: 1px solid #f9fafb;\n}\n\n.rc-field-row:last-child { border-bottom: none; }\n\n.rc-field-label {\n width: 140px;\n min-width: 140px;\n padding: 12px 16px;\n font-size: 12px;\n font-weight: 600;\n color: #6b7280;\n background: #f9fafb;\n display: flex;\n align-items: center;\n border-right: 1px solid #f3f4f6;\n}\n\n.rc-field-values {\n flex: 1;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* \u2500\u2500\u2500 Atomic Change (numbers, dates) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-atomic-change {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.rc-val-old {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: #9ca3af;\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: #d1d5db;\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.rc-val-new {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: #111827;\n font-weight: 500;\n}\n\n/* \u2500\u2500\u2500 Boolean Change \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-bool-change {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-bool-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.rc-bool-dot.on { background: #10b981; }\n.rc-bool-dot.off { background: #d1d5db; }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: #9ca3af;\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: #059669; }\n.rc-bool-label.new.inactive { color: #9ca3af; }\n\n/* \u2500\u2500\u2500 Text Diff (strings only) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-text-diff {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.rc-diff-added {\n background: #dcfce7;\n color: #166534;\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: #fee2e2;\n color: #991b1b;\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: #374151;\n}\n\n/* \u2500\u2500\u2500 Deletion Note \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-deletion-note {\n padding: 16px 18px;\n color: #6b7280;\n font-size: 13px;\n font-style: italic;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-deletion-note i {\n color: #ef4444;\n font-size: 14px;\n}\n\n/* \u2500\u2500\u2500 Comments & Errors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-comments {\n padding: 12px 18px;\n background: #eff6ff;\n font-size: 13px;\n color: #1e40af;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid #f3f4f6;\n}\n\n.rc-comments i {\n color: #3b82f6;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: #fef2f2;\n font-size: 13px;\n color: #991b1b;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid #f3f4f6;\n}\n\n.rc-errors i {\n color: #ef4444;\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: #fff;\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: #991b1b;\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n flex: 1;\n}\n\n/* \u2500\u2500\u2500 Create Wizard Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.rc-wizard-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-wizard-container {\n background: #fff;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 24px;\n animation: rc-slideUp 0.2s ease;\n}\n\n@keyframes rc-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes rc-slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* \u2500\u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (max-width: 768px) {\n .rc-card-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .rc-card-meta {\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .rc-field-row {\n flex-direction: column;\n }\n\n .rc-field-label {\n width: 100%;\n min-width: unset;\n border-right: none;\n border-bottom: 1px solid #f3f4f6;\n padding: 8px 16px;\n }\n\n .rc-field-values {\n padding: 8px 16px;\n }\n\n .rc-atomic-change {\n flex-wrap: wrap;\n }\n\n .rc-filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .rc-search-wrap { min-width: unset; }\n\n .rc-filter-pill { justify-content: center; }\n\n .rc-page-header {\n flex-direction: column;\n gap: 12px;\n }\n\n .rc-header-meta { text-align: left; }\n}\n\n@media (max-width: 480px) {\n .rc-container { padding: 12px 16px; }\n\n .rc-card { margin-left: 36px; }\n\n .rc-date-label { padding-left: 36px; }\n\n .rc-card::before { left: -19px; }\n\n .rc-timeline::before { left: 12px; }\n\n .rc-date-label::before { left: 7px; }\n}\n"] }]
951
+ }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1.MJNotificationService }, { type: i2.DomSanitizer }], { dialogClosed: [{
874
952
  type: Output
875
953
  }], record: [{
876
954
  type: Input
877
955
  }] }); })();
878
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber: 27 }); })();
956
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber: 43 }); })();
879
957
  //# sourceMappingURL=ng-record-changes.component.js.map