@memberjunction/ng-record-changes 4.3.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.
- package/dist/lib/__tests__/record-changes.test.js +67 -37
- package/dist/lib/__tests__/record-changes.test.js.map +1 -1
- package/dist/lib/ng-record-changes.component.d.ts +31 -12
- package/dist/lib/ng-record-changes.component.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.component.js +430 -360
- package/dist/lib/ng-record-changes.component.js.map +1 -1
- package/package.json +9 -9
|
@@ -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.
|
|
13
|
-
const _forTrack2 = ($index, $item) => $item.
|
|
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
|
|
88
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
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
|
|
97
|
-
const
|
|
98
|
-
i0.ɵɵelementStart(0, "div",
|
|
99
|
-
i0.ɵɵelement(1, "i",
|
|
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",
|
|
104
|
-
i0.ɵɵlistener("click", function
|
|
105
|
-
i0.ɵɵelement(5, "i",
|
|
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
|
|
110
|
-
i0.ɵɵ
|
|
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(
|
|
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
|
|
122
|
+
const field_r9 = ctx.$implicit;
|
|
140
123
|
i0.ɵɵadvance(2);
|
|
141
|
-
i0.ɵɵtextInterpolate(
|
|
142
|
-
i0.ɵɵadvance(
|
|
143
|
-
i0.ɵɵtextInterpolate(
|
|
124
|
+
i0.ɵɵtextInterpolate(field_r9.displayName);
|
|
125
|
+
i0.ɵɵadvance(3);
|
|
126
|
+
i0.ɵɵtextInterpolate(field_r9.value);
|
|
144
127
|
} }
|
|
145
|
-
function
|
|
146
|
-
i0.ɵɵ
|
|
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
|
|
151
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
152
|
-
i0.ɵɵ
|
|
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
|
|
156
|
-
i0.ɵɵ
|
|
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
|
|
164
|
-
i0.ɵɵ
|
|
165
|
-
|
|
138
|
+
const change_r8 = i0.ɵɵnextContext(2).$implicit;
|
|
139
|
+
i0.ɵɵconditional(change_r8.FullRecordJSON ? 0 : -1);
|
|
140
|
+
} }
|
|
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. ");
|
|
145
|
+
i0.ɵɵelementEnd();
|
|
166
146
|
} }
|
|
167
|
-
function
|
|
168
|
-
i0.ɵɵelementStart(0, "div",
|
|
169
|
-
i0.ɵɵelement(
|
|
170
|
-
i0.ɵɵ
|
|
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);
|
|
171
152
|
i0.ɵɵelementEnd();
|
|
172
|
-
i0.ɵɵ
|
|
173
|
-
i0.ɵɵ
|
|
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
|
|
177
|
-
i0.ɵɵelementStart(0, "div",
|
|
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
|
|
179
|
+
const fc_r10 = i0.ɵɵnextContext().$implicit;
|
|
182
180
|
i0.ɵɵadvance(2);
|
|
183
|
-
i0.ɵɵtextInterpolate(
|
|
181
|
+
i0.ɵɵtextInterpolate(fc_r10.oldValue || "(empty)");
|
|
182
|
+
i0.ɵɵadvance(3);
|
|
183
|
+
i0.ɵɵtextInterpolate(fc_r10.newValue || "(empty)");
|
|
184
184
|
} }
|
|
185
|
-
function
|
|
186
|
-
i0.ɵɵ
|
|
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
|
|
191
|
-
i0.ɵɵ
|
|
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
|
|
195
|
-
i0.ɵɵelementStart(0, "div",
|
|
196
|
-
i0.ɵɵtext(
|
|
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.ɵɵ
|
|
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
|
|
212
|
-
i0.ɵɵadvance(
|
|
213
|
-
i0.ɵɵtextInterpolate(
|
|
214
|
-
i0.ɵɵadvance(
|
|
215
|
-
i0.ɵɵtextInterpolate(
|
|
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
|
|
218
|
-
i0.ɵɵelementStart(0, "div",
|
|
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.ɵɵ
|
|
222
|
-
i0.ɵɵ
|
|
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
|
|
214
|
+
const fc_r10 = ctx.$implicit;
|
|
225
215
|
i0.ɵɵadvance(2);
|
|
226
|
-
i0.ɵɵtextInterpolate(
|
|
227
|
-
i0.ɵɵadvance();
|
|
228
|
-
i0.ɵɵconditional(
|
|
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
|
|
231
|
-
i0.ɵɵ
|
|
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
|
|
240
|
-
const ctx_r1 = i0.ɵɵnextContext(
|
|
241
|
-
i0.ɵɵ
|
|
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
|
|
245
|
-
i0.ɵɵelementStart(0, "div", 68)
|
|
246
|
-
i0.ɵɵelement(
|
|
247
|
-
i0.ɵɵtext(
|
|
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
|
|
254
|
-
i0.ɵɵadvance(
|
|
255
|
-
i0.ɵɵ
|
|
233
|
+
const change_r8 = i0.ɵɵnextContext(2).$implicit;
|
|
234
|
+
i0.ɵɵadvance(2);
|
|
235
|
+
i0.ɵɵtextInterpolate1(" ", change_r8.Comments, " ");
|
|
256
236
|
} }
|
|
257
|
-
function
|
|
258
|
-
i0.ɵɵelementStart(0, "div", 69)
|
|
259
|
-
i0.ɵɵelement(
|
|
260
|
-
i0.ɵɵ
|
|
261
|
-
i0.ɵɵ
|
|
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
|
|
267
|
-
i0.ɵɵadvance(
|
|
268
|
-
i0.ɵɵtextInterpolate(
|
|
244
|
+
const change_r8 = i0.ɵɵnextContext(2).$implicit;
|
|
245
|
+
i0.ɵɵadvance(3);
|
|
246
|
+
i0.ɵɵtextInterpolate(change_r8.ErrorLog);
|
|
269
247
|
} }
|
|
270
|
-
function
|
|
271
|
-
i0.ɵɵelementStart(0, "div",
|
|
272
|
-
i0.ɵɵ
|
|
273
|
-
i0.ɵɵ
|
|
274
|
-
i0.ɵɵ
|
|
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
|
|
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(
|
|
257
|
+
i0.ɵɵconditional(change_r8.Type === "Create" ? 1 : change_r8.Type === "Delete" ? 2 : 3);
|
|
287
258
|
i0.ɵɵadvance(3);
|
|
288
|
-
i0.ɵɵconditional(
|
|
259
|
+
i0.ɵɵconditional(change_r8.Comments ? 4 : -1);
|
|
289
260
|
i0.ɵɵadvance();
|
|
290
|
-
i0.ɵɵconditional(
|
|
261
|
+
i0.ɵɵconditional(change_r8.ErrorLog ? 5 : -1);
|
|
291
262
|
} }
|
|
292
|
-
function
|
|
293
|
-
const
|
|
294
|
-
i0.ɵɵelementStart(0, "div",
|
|
295
|
-
i0.ɵɵlistener("
|
|
296
|
-
i0.ɵɵelementStart(1, "div",
|
|
297
|
-
i0.ɵɵ
|
|
298
|
-
i0.ɵɵ
|
|
299
|
-
i0.ɵɵ
|
|
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, "
|
|
302
|
-
i0.ɵɵtext(
|
|
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",
|
|
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(
|
|
314
|
-
i0.ɵɵtext(
|
|
283
|
+
i0.ɵɵelementStart(14, "span", 63);
|
|
284
|
+
i0.ɵɵtext(15);
|
|
315
285
|
i0.ɵɵelementEnd();
|
|
316
|
-
i0.ɵɵ
|
|
317
|
-
i0.ɵɵ
|
|
318
|
-
i0.ɵɵ
|
|
319
|
-
i0.ɵɵ
|
|
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
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
i0.ɵɵclassProp("expanded", ctx_r1.expandedItems.has(
|
|
326
|
-
i0.ɵɵattribute("tabindex", 0)("aria-expanded", ctx_r1.expandedItems.has(
|
|
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.ɵɵ
|
|
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(
|
|
340
|
-
i0.ɵɵadvance();
|
|
341
|
-
i0.ɵɵ
|
|
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(" ",
|
|
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.ɵɵ
|
|
308
|
+
i0.ɵɵproperty("title", ctx_r1.formatFullDateTime(change_r8.ChangedAt));
|
|
348
309
|
i0.ɵɵadvance();
|
|
349
|
-
i0.ɵɵ
|
|
310
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatTime(change_r8.ChangedAt));
|
|
350
311
|
i0.ɵɵadvance();
|
|
351
|
-
i0.ɵɵ
|
|
312
|
+
i0.ɵɵclassMap(ctx_r1.getSourceClass(change_r8.Source));
|
|
352
313
|
i0.ɵɵadvance();
|
|
353
|
-
i0.ɵɵ
|
|
314
|
+
i0.ɵɵtextInterpolate(change_r8.Source);
|
|
354
315
|
i0.ɵɵadvance();
|
|
355
|
-
i0.ɵɵ
|
|
316
|
+
i0.ɵɵclassMap(ctx_r1.getStatusClass(change_r8.Status));
|
|
356
317
|
i0.ɵɵadvance();
|
|
357
|
-
i0.ɵɵ
|
|
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
|
|
360
|
-
i0.ɵɵelementStart(0, "div",
|
|
361
|
-
i0.ɵɵ
|
|
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
|
|
329
|
+
const group_r11 = ctx.$implicit;
|
|
330
|
+
i0.ɵɵadvance(2);
|
|
331
|
+
i0.ɵɵtextInterpolate(group_r11.label);
|
|
365
332
|
i0.ɵɵadvance();
|
|
366
|
-
i0.ɵɵrepeater(
|
|
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"
|
|
371
|
-
i0.ɵɵ
|
|
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(
|
|
384
|
-
i0.ɵɵtext(
|
|
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(
|
|
390
|
-
i0.ɵɵ
|
|
391
|
-
i0.ɵɵ
|
|
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(
|
|
399
|
-
i0.ɵɵtext(
|
|
353
|
+
i0.ɵɵelementStart(10, "div", 34);
|
|
354
|
+
i0.ɵɵtext(11);
|
|
400
355
|
i0.ɵɵelementEnd()()();
|
|
401
|
-
i0.ɵɵ
|
|
402
|
-
i0.ɵɵ
|
|
403
|
-
i0.ɵɵelementStart(
|
|
404
|
-
i0.ɵɵ
|
|
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.ɵɵ
|
|
412
|
-
i0.ɵɵadvance(
|
|
413
|
-
i0.ɵɵ
|
|
414
|
-
i0.ɵɵadvance(
|
|
415
|
-
i0.ɵɵ
|
|
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 ?
|
|
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,
|
|
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
|
|
450
|
-
i0.ɵɵelementStart(0, "div",
|
|
451
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_0_listener() { i0.ɵɵrestoreView(
|
|
452
|
-
i0.ɵɵelementStart(1, "div",
|
|
453
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(
|
|
454
|
-
i0.ɵɵelementStart(2, "mj-label-create",
|
|
455
|
-
i0.ɵɵlistener("Created", function RecordChangesComponent_Conditional_3_Template_mj_label_create_Created_2_listener($event) { i0.ɵɵrestoreView(
|
|
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();
|
|
@@ -470,6 +460,7 @@ export class RecordChangesComponent {
|
|
|
470
460
|
record;
|
|
471
461
|
viewData = [];
|
|
472
462
|
filteredData = [];
|
|
463
|
+
dateGroups = [];
|
|
473
464
|
expandedItems = new Set();
|
|
474
465
|
// Version label state
|
|
475
466
|
RecordLabels = [];
|
|
@@ -508,6 +499,7 @@ export class RecordChangesComponent {
|
|
|
508
499
|
if (changes) {
|
|
509
500
|
this.viewData = changes.sort((a, b) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime());
|
|
510
501
|
this.filteredData = [...this.viewData];
|
|
502
|
+
this.dateGroups = this.buildDateGroups(this.filteredData);
|
|
511
503
|
this.IsLoading = false;
|
|
512
504
|
}
|
|
513
505
|
else {
|
|
@@ -518,20 +510,42 @@ export class RecordChangesComponent {
|
|
|
518
510
|
});
|
|
519
511
|
}
|
|
520
512
|
}
|
|
521
|
-
// Filter
|
|
513
|
+
// ─── Filter & Search ────────────────────────────────────────────
|
|
522
514
|
onSearchChange() {
|
|
523
515
|
this.applyFilters();
|
|
524
516
|
}
|
|
525
517
|
onFilterChange() {
|
|
526
518
|
this.applyFilters();
|
|
527
519
|
}
|
|
520
|
+
SetTypeFilter(type) {
|
|
521
|
+
this.selectedType = this.selectedType === type ? '' : type;
|
|
522
|
+
this.applyFilters();
|
|
523
|
+
}
|
|
528
524
|
ClearFilters() {
|
|
529
525
|
this.searchTerm = '';
|
|
530
526
|
this.selectedType = '';
|
|
531
527
|
this.selectedSource = '';
|
|
532
528
|
this.applyFilters();
|
|
533
529
|
}
|
|
534
|
-
|
|
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 ─────────────────────────────────────────────
|
|
535
549
|
async LoadRecordLabels() {
|
|
536
550
|
if (!this.record)
|
|
537
551
|
return;
|
|
@@ -541,7 +555,6 @@ export class RecordChangesComponent {
|
|
|
541
555
|
const entityId = this.record.EntityInfo.ID;
|
|
542
556
|
const recordId = this.record.PrimaryKey.ToConcatenatedString();
|
|
543
557
|
const rv = new RunView();
|
|
544
|
-
// Find all label items that reference this specific record
|
|
545
558
|
const itemsResult = await rv.RunView({
|
|
546
559
|
EntityName: 'MJ: Version Label Items',
|
|
547
560
|
Fields: ['VersionLabelID'],
|
|
@@ -610,24 +623,7 @@ export class RecordChangesComponent {
|
|
|
610
623
|
default: return '';
|
|
611
624
|
}
|
|
612
625
|
}
|
|
613
|
-
|
|
614
|
-
let filtered = [...this.viewData];
|
|
615
|
-
if (this.searchTerm.trim()) {
|
|
616
|
-
const search = this.searchTerm.toLowerCase();
|
|
617
|
-
filtered = filtered.filter(change => change.ChangesDescription?.toLowerCase().includes(search) ||
|
|
618
|
-
change.User?.toLowerCase().includes(search) ||
|
|
619
|
-
change.Comments?.toLowerCase().includes(search));
|
|
620
|
-
}
|
|
621
|
-
if (this.selectedType) {
|
|
622
|
-
filtered = filtered.filter(change => change.Type === this.selectedType);
|
|
623
|
-
}
|
|
624
|
-
if (this.selectedSource) {
|
|
625
|
-
filtered = filtered.filter(change => change.Source === this.selectedSource);
|
|
626
|
-
}
|
|
627
|
-
this.filteredData = filtered;
|
|
628
|
-
this.cdr.markForCheck();
|
|
629
|
-
}
|
|
630
|
-
// Timeline interaction methods
|
|
626
|
+
// ─── Timeline Interaction ───────────────────────────────────────
|
|
631
627
|
toggleExpansion(changeId) {
|
|
632
628
|
if (this.expandedItems.has(changeId)) {
|
|
633
629
|
this.expandedItems.delete(changeId);
|
|
@@ -643,29 +639,44 @@ export class RecordChangesComponent {
|
|
|
643
639
|
this.toggleExpansion(changeId);
|
|
644
640
|
}
|
|
645
641
|
}
|
|
646
|
-
//
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
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);
|
|
653
651
|
}
|
|
652
|
+
return Array.from(groups.entries()).map(([label, items]) => ({ label, changes: items }));
|
|
653
|
+
}
|
|
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;
|
|
654
665
|
}
|
|
655
|
-
|
|
666
|
+
// ─── Display Helpers ────────────────────────────────────────────
|
|
667
|
+
getChangeTypeCardClass(type) {
|
|
656
668
|
switch (type) {
|
|
657
|
-
case 'Create': return '
|
|
658
|
-
case 'Update': return '
|
|
659
|
-
case 'Delete': return '
|
|
660
|
-
default: return '
|
|
669
|
+
case 'Create': return 'type-create';
|
|
670
|
+
case 'Update': return 'type-update';
|
|
671
|
+
case 'Delete': return 'type-delete';
|
|
672
|
+
default: return 'type-update';
|
|
661
673
|
}
|
|
662
674
|
}
|
|
663
|
-
|
|
675
|
+
getChangeTypeBadgeText(type) {
|
|
664
676
|
switch (type) {
|
|
665
|
-
case 'Create': return '
|
|
666
|
-
case '
|
|
667
|
-
|
|
668
|
-
default: return 'badge-unknown';
|
|
677
|
+
case 'Create': return 'Created';
|
|
678
|
+
case 'Delete': return 'Deleted';
|
|
679
|
+
default: return type;
|
|
669
680
|
}
|
|
670
681
|
}
|
|
671
682
|
getSourceClass(source) {
|
|
@@ -682,6 +693,39 @@ export class RecordChangesComponent {
|
|
|
682
693
|
getTimelineItemLabel(change) {
|
|
683
694
|
return `${change.Type} by ${change.User || 'Unknown User'} on ${this.formatFullDateTime(change.ChangedAt)}`;
|
|
684
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
|
+
}
|
|
685
729
|
formatRelativeTime(date) {
|
|
686
730
|
const now = new Date();
|
|
687
731
|
const diffMs = now.getTime() - new Date(date).getTime();
|
|
@@ -713,70 +757,95 @@ export class RecordChangesComponent {
|
|
|
713
757
|
timeZoneName: 'short'
|
|
714
758
|
}).format(new Date(date));
|
|
715
759
|
}
|
|
760
|
+
// ─── Change Summary ─────────────────────────────────────────────
|
|
716
761
|
getChangeSummary(change) {
|
|
717
|
-
if (change.Type === 'Create')
|
|
718
|
-
return 'Record
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return 'Record was deleted';
|
|
722
|
-
}
|
|
762
|
+
if (change.Type === 'Create')
|
|
763
|
+
return 'Record created';
|
|
764
|
+
if (change.Type === 'Delete')
|
|
765
|
+
return 'Record deleted';
|
|
723
766
|
try {
|
|
724
767
|
const changesJson = JSON.parse(change.ChangesJSON || '{}');
|
|
725
|
-
const
|
|
726
|
-
if (
|
|
768
|
+
const fieldNames = this.extractFieldDisplayNames(changesJson);
|
|
769
|
+
if (fieldNames.length === 0)
|
|
727
770
|
return 'No field changes detected';
|
|
728
|
-
|
|
729
|
-
const changeInfo = changesJson[fieldKey];
|
|
730
|
-
const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
|
|
731
|
-
return field?.DisplayNameOrName || changeInfo.field;
|
|
732
|
-
});
|
|
733
|
-
if (fieldNames.length === 1) {
|
|
734
|
-
return `${fieldNames[0]} changed`;
|
|
735
|
-
}
|
|
736
|
-
if (fieldNames.length === 2) {
|
|
737
|
-
return `${fieldNames[0]} and ${fieldNames[1]} changed`;
|
|
738
|
-
}
|
|
739
|
-
if (fieldNames.length <= 4) {
|
|
740
|
-
const lastField = fieldNames.pop();
|
|
741
|
-
return `${fieldNames.join(', ')}, and ${lastField} changed`;
|
|
742
|
-
}
|
|
743
|
-
return `${fieldNames.slice(0, 3).join(', ')}, and ${fieldNames.length - 3} other field${fieldNames.length - 3 > 1 ? 's' : ''} changed`;
|
|
771
|
+
return this.buildFieldListSummary(fieldNames);
|
|
744
772
|
}
|
|
745
773
|
catch {
|
|
746
774
|
return change.ChangesDescription || 'Changes made';
|
|
747
775
|
}
|
|
748
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) ────────────────────────────────
|
|
749
810
|
getFieldChanges(change) {
|
|
750
811
|
try {
|
|
751
812
|
const changesJson = JSON.parse(change.ChangesJSON || '{}');
|
|
752
|
-
|
|
753
|
-
return fields.map(fieldKey => {
|
|
754
|
-
const changeInfo = changesJson[fieldKey];
|
|
755
|
-
const field = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase());
|
|
756
|
-
const isBooleanField = field?.TSType === EntityFieldTSType.Boolean;
|
|
757
|
-
const isDateField = field?.TSType === EntityFieldTSType.Date;
|
|
758
|
-
let diffHtml;
|
|
759
|
-
const formattedOld = this.formatChangeValue(changeInfo.oldValue, isDateField);
|
|
760
|
-
const formattedNew = this.formatChangeValue(changeInfo.newValue, isDateField);
|
|
761
|
-
if (!isBooleanField) {
|
|
762
|
-
if (formattedOld !== formattedNew) {
|
|
763
|
-
diffHtml = this.generateDiffHtml(formattedOld, formattedNew);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
return {
|
|
767
|
-
field: changeInfo.field,
|
|
768
|
-
displayName: field?.DisplayNameOrName || changeInfo.field,
|
|
769
|
-
oldValue: formattedOld,
|
|
770
|
-
newValue: formattedNew,
|
|
771
|
-
isBooleanField,
|
|
772
|
-
diffHtml
|
|
773
|
-
};
|
|
774
|
-
});
|
|
813
|
+
return Object.keys(changesJson).map(fieldKey => this.buildFieldChangeInfo(changesJson[fieldKey]));
|
|
775
814
|
}
|
|
776
815
|
catch {
|
|
777
816
|
return [];
|
|
778
817
|
}
|
|
779
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
|
+
}
|
|
780
849
|
getCreatedFields(change) {
|
|
781
850
|
try {
|
|
782
851
|
if (!change.FullRecordJSON)
|
|
@@ -795,6 +864,7 @@ export class RecordChangesComponent {
|
|
|
795
864
|
return [];
|
|
796
865
|
}
|
|
797
866
|
}
|
|
867
|
+
// ─── Value Formatting ───────────────────────────────────────────
|
|
798
868
|
/**
|
|
799
869
|
* Formats a change value for display. Handles corrupted date values (stored as empty objects)
|
|
800
870
|
* and formats ISO date strings into a human-readable format.
|
|
@@ -802,48 +872,48 @@ export class RecordChangesComponent {
|
|
|
802
872
|
formatChangeValue(value, isDateField) {
|
|
803
873
|
if (value == null)
|
|
804
874
|
return '';
|
|
805
|
-
// Handle object values (e.g., Date objects that were incorrectly serialized as {})
|
|
806
875
|
if (typeof value === 'object') {
|
|
807
876
|
const keys = Object.keys(value);
|
|
808
877
|
if (keys.length === 0)
|
|
809
|
-
return '';
|
|
878
|
+
return '';
|
|
810
879
|
return JSON.stringify(value);
|
|
811
880
|
}
|
|
812
|
-
// Format ISO date strings into a readable format
|
|
813
881
|
if (isDateField && typeof value === 'string') {
|
|
814
882
|
const date = new Date(value);
|
|
815
883
|
if (!isNaN(date.getTime())) {
|
|
816
|
-
return
|
|
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);
|
|
817
892
|
}
|
|
818
893
|
}
|
|
819
894
|
return String(value);
|
|
820
895
|
}
|
|
896
|
+
// ─── Diff Generation (text fields only) ─────────────────────────
|
|
821
897
|
generateDiffHtml(oldValue, newValue) {
|
|
822
898
|
if (!oldValue && !newValue) {
|
|
823
|
-
return this.sanitizer.bypassSecurityTrustHtml('<
|
|
899
|
+
return this.sanitizer.bypassSecurityTrustHtml('<span class="rc-diff-unchanged">(no change)</span>');
|
|
824
900
|
}
|
|
825
901
|
if (!oldValue) {
|
|
826
|
-
return this.sanitizer.bypassSecurityTrustHtml(`<
|
|
902
|
+
return this.sanitizer.bypassSecurityTrustHtml(`<span class="rc-diff-added">${this.escapeHtml(newValue)}</span>`);
|
|
827
903
|
}
|
|
828
904
|
if (!newValue) {
|
|
829
|
-
return this.sanitizer.bypassSecurityTrustHtml(`<
|
|
905
|
+
return this.sanitizer.bypassSecurityTrustHtml(`<span class="rc-diff-removed">${this.escapeHtml(oldValue)}</span>`);
|
|
830
906
|
}
|
|
831
907
|
const useWordDiff = this.shouldUseWordDiff(oldValue, newValue);
|
|
832
908
|
const diffs = useWordDiff ? diffWords(oldValue, newValue) : diffChars(oldValue, newValue);
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
842
|
-
else {
|
|
843
|
-
html += `<span class="diff-unchanged">${escapedValue}</span>`;
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
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('');
|
|
847
917
|
return this.sanitizer.bypassSecurityTrustHtml(html);
|
|
848
918
|
}
|
|
849
919
|
shouldUseWordDiff(oldValue, newValue) {
|
|
@@ -858,7 +928,7 @@ export class RecordChangesComponent {
|
|
|
858
928
|
return div.innerHTML;
|
|
859
929
|
}
|
|
860
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)); };
|
|
861
|
-
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, "
|
|
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) {
|
|
862
932
|
i0.ɵɵelementStart(0, "mj-slide-panel", 0);
|
|
863
933
|
i0.ɵɵlistener("Closed", function RecordChangesComponent_Template_mj_slide_panel_Closed_0_listener() { return ctx.OnClose(); });
|
|
864
934
|
i0.ɵɵconditionalCreate(1, RecordChangesComponent_Conditional_1_Template, 1, 0, "mj-loading", 1);
|
|
@@ -873,15 +943,15 @@ export class RecordChangesComponent {
|
|
|
873
943
|
i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
|
|
874
944
|
i0.ɵɵadvance();
|
|
875
945
|
i0.ɵɵconditional(ctx.ShowCreateWizard ? 3 : -1);
|
|
876
|
-
} }, 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 });
|
|
877
947
|
}
|
|
878
948
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesComponent, [{
|
|
879
949
|
type: Component,
|
|
880
|
-
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"] }]
|
|
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' : '' }} · {{ 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"] }]
|
|
881
951
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1.MJNotificationService }, { type: i2.DomSanitizer }], { dialogClosed: [{
|
|
882
952
|
type: Output
|
|
883
953
|
}], record: [{
|
|
884
954
|
type: Input
|
|
885
955
|
}] }); })();
|
|
886
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber:
|
|
956
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber: 43 }); })();
|
|
887
957
|
//# sourceMappingURL=ng-record-changes.component.js.map
|