@memberjunction/ng-record-changes 5.27.1 → 5.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -0
- package/dist/__tests__/restore-version.test.js +102 -152
- package/dist/__tests__/restore-version.test.js.map +1 -1
- package/dist/lib/__tests__/record-changes.test.js +21 -12
- package/dist/lib/__tests__/record-changes.test.js.map +1 -1
- package/dist/lib/ng-record-changes.component.d.ts +171 -49
- package/dist/lib/ng-record-changes.component.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.component.js +645 -416
- package/dist/lib/ng-record-changes.component.js.map +1 -1
- package/dist/lib/ng-record-changes.module.d.ts +6 -5
- package/dist/lib/ng-record-changes.module.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.module.js +9 -4
- package/dist/lib/ng-record-changes.module.js.map +1 -1
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts +267 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts.map +1 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js +748 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js.map +1 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +8 -7
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
|
|
2
|
-
import { EntityFieldTSType, Metadata, RunView } from '@memberjunction/core';
|
|
1
|
+
import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy, ViewEncapsulation, } from '@angular/core';
|
|
2
|
+
import { EntityFieldTSType, Metadata, RunView, } from '@memberjunction/core';
|
|
3
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
3
4
|
import { diffChars, diffWords } from 'diff';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
import * as i1 from "@memberjunction/ng-notifications";
|
|
@@ -7,12 +8,14 @@ import * as i2 from "@angular/platform-browser";
|
|
|
7
8
|
import * as i3 from "@angular/forms";
|
|
8
9
|
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
9
10
|
import * as i5 from "@memberjunction/ng-versions";
|
|
11
|
+
import * as i6 from "./restore-preview-panel/restore-preview-panel.component";
|
|
12
|
+
import * as i7 from "@angular/common";
|
|
10
13
|
const _c0 = a0 => [a0];
|
|
11
14
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
12
|
-
const _forTrack1 = ($index, $item) => $item.
|
|
13
|
-
const _forTrack2 = ($index, $item) => $item.
|
|
14
|
-
const _forTrack3 = ($index, $item) => $item.
|
|
15
|
-
const _forTrack4 = ($index, $item) => $item.
|
|
15
|
+
const _forTrack1 = ($index, $item) => $item.Key;
|
|
16
|
+
const _forTrack2 = ($index, $item) => $item.label;
|
|
17
|
+
const _forTrack3 = ($index, $item) => $item.name;
|
|
18
|
+
const _forTrack4 = ($index, $item) => $item.field;
|
|
16
19
|
function RecordChangesComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
17
20
|
i0.ɵɵelement(0, "mj-loading", 1);
|
|
18
21
|
} }
|
|
@@ -86,12 +89,120 @@ function RecordChangesComponent_Conditional_2_Conditional_14_Template(rf, ctx) {
|
|
|
86
89
|
i0.ɵɵtext(10, "Record change tracking is managed at the entity level");
|
|
87
90
|
i0.ɵɵelementEnd()()();
|
|
88
91
|
} }
|
|
89
|
-
function
|
|
92
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_0_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
90
93
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
91
|
-
i0.ɵɵelementStart(0, "
|
|
94
|
+
i0.ɵɵelementStart(0, "button", 40);
|
|
95
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_0_For_1_Template_button_click_0_listener() { const pill_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.TogglePill(pill_r6.Key)); });
|
|
96
|
+
i0.ɵɵelement(1, "i", 47);
|
|
97
|
+
i0.ɵɵtext(2);
|
|
98
|
+
i0.ɵɵelementStart(3, "span", 48);
|
|
99
|
+
i0.ɵɵtext(4);
|
|
100
|
+
i0.ɵɵelementEnd()();
|
|
101
|
+
} if (rf & 2) {
|
|
102
|
+
const pill_r6 = ctx.$implicit;
|
|
103
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
104
|
+
i0.ɵɵclassProp("active", ctx_r1.ChipSelections[pill_r6.Key])("rc-filter-pill-restore", pill_r6.Variant === "restore");
|
|
105
|
+
i0.ɵɵadvance();
|
|
106
|
+
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", pill_r6.Icon));
|
|
107
|
+
i0.ɵɵadvance();
|
|
108
|
+
i0.ɵɵtextInterpolate1(" ", pill_r6.Label, " ");
|
|
109
|
+
i0.ɵɵadvance(2);
|
|
110
|
+
i0.ɵɵtextInterpolate(pill_r6.Count);
|
|
111
|
+
} }
|
|
112
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
+
i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_0_For_1_Template, 5, 9, "button", 46, _forTrack1);
|
|
114
|
+
} if (rf & 2) {
|
|
115
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
116
|
+
i0.ɵɵrepeater(ctx_r1.ConditionalPills);
|
|
117
|
+
} }
|
|
118
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
119
|
+
i0.ɵɵelementStart(0, "span", 48);
|
|
92
120
|
i0.ɵɵtext(1);
|
|
93
|
-
i0.ɵɵ
|
|
94
|
-
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
} if (rf & 2) {
|
|
123
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
124
|
+
i0.ɵɵadvance();
|
|
125
|
+
i0.ɵɵtextInterpolate(ctx_r1.SelectedConditionalCount);
|
|
126
|
+
} }
|
|
127
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
128
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
129
|
+
i0.ɵɵelementStart(0, "label", 59)(1, "input", 60);
|
|
130
|
+
i0.ɵɵlistener("change", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_For_5_Template_input_change_1_listener() { const pill_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r1.TogglePill(pill_r10.Key)); });
|
|
131
|
+
i0.ɵɵelementEnd();
|
|
132
|
+
i0.ɵɵelement(2, "i", 47);
|
|
133
|
+
i0.ɵɵelementStart(3, "span", 61);
|
|
134
|
+
i0.ɵɵtext(4);
|
|
135
|
+
i0.ɵɵelementEnd();
|
|
136
|
+
i0.ɵɵelementStart(5, "span", 62);
|
|
137
|
+
i0.ɵɵtext(6);
|
|
138
|
+
i0.ɵɵelementEnd()();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
const pill_r10 = ctx.$implicit;
|
|
141
|
+
const ctx_r1 = i0.ɵɵnextContext(6);
|
|
142
|
+
i0.ɵɵclassProp("rc-filter-overflow-row-restore", pill_r10.Variant === "restore");
|
|
143
|
+
i0.ɵɵadvance();
|
|
144
|
+
i0.ɵɵproperty("checked", ctx_r1.ChipSelections[pill_r10.Key]);
|
|
145
|
+
i0.ɵɵadvance();
|
|
146
|
+
i0.ɵɵclassMap(i0.ɵɵinterpolate1("fa-solid ", pill_r10.Icon));
|
|
147
|
+
i0.ɵɵadvance(2);
|
|
148
|
+
i0.ɵɵtextInterpolate(pill_r10.Label);
|
|
149
|
+
i0.ɵɵadvance(2);
|
|
150
|
+
i0.ɵɵtextInterpolate(pill_r10.Count);
|
|
151
|
+
} }
|
|
152
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
153
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
154
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
155
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.CloseFilterOverflow()); });
|
|
156
|
+
i0.ɵɵelementEnd();
|
|
157
|
+
i0.ɵɵelementStart(1, "div", 53)(2, "div", 54);
|
|
158
|
+
i0.ɵɵtext(3, "Filter by");
|
|
159
|
+
i0.ɵɵelementEnd();
|
|
160
|
+
i0.ɵɵrepeaterCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_For_5_Template, 7, 8, "label", 55, _forTrack1);
|
|
161
|
+
i0.ɵɵelementStart(6, "div", 56)(7, "button", 57);
|
|
162
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(5); ctx_r1.SelectAllPill(); return i0.ɵɵresetView(ctx_r1.CloseFilterOverflow()); });
|
|
163
|
+
i0.ɵɵtext(8, " Clear all ");
|
|
164
|
+
i0.ɵɵelementEnd();
|
|
165
|
+
i0.ɵɵelementStart(9, "button", 58);
|
|
166
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.CloseFilterOverflow()); });
|
|
167
|
+
i0.ɵɵtext(10, " Done ");
|
|
168
|
+
i0.ɵɵelementEnd()()();
|
|
169
|
+
} if (rf & 2) {
|
|
170
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
171
|
+
i0.ɵɵadvance(4);
|
|
172
|
+
i0.ɵɵrepeater(ctx_r1.ConditionalPills);
|
|
173
|
+
} }
|
|
174
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
175
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
176
|
+
i0.ɵɵelementStart(0, "div", 45)(1, "button", 49);
|
|
177
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.ToggleFilterOverflow()); });
|
|
178
|
+
i0.ɵɵelement(2, "i", 50);
|
|
179
|
+
i0.ɵɵtext(3, " More filters ");
|
|
180
|
+
i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_4_Template, 2, 1, "span", 48);
|
|
181
|
+
i0.ɵɵelement(5, "i", 51);
|
|
182
|
+
i0.ɵɵelementEnd();
|
|
183
|
+
i0.ɵɵconditionalCreate(6, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Conditional_6_Template, 11, 0);
|
|
184
|
+
i0.ɵɵelementEnd();
|
|
185
|
+
} if (rf & 2) {
|
|
186
|
+
const ctx_r1 = i0.ɵɵnextContext(4);
|
|
187
|
+
i0.ɵɵadvance();
|
|
188
|
+
i0.ɵɵclassProp("active", ctx_r1.SelectedConditionalCount > 0);
|
|
189
|
+
i0.ɵɵadvance(3);
|
|
190
|
+
i0.ɵɵconditional(ctx_r1.SelectedConditionalCount > 0 ? 4 : -1);
|
|
191
|
+
i0.ɵɵadvance(2);
|
|
192
|
+
i0.ɵɵconditional(ctx_r1.ShowFilterOverflow ? 6 : -1);
|
|
193
|
+
} }
|
|
194
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
195
|
+
i0.ɵɵconditionalCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_0_Template, 2, 0)(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Conditional_1_Template, 7, 4, "div", 45);
|
|
196
|
+
} if (rf & 2) {
|
|
197
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
198
|
+
i0.ɵɵconditional(!ctx_r1.UseOverflowPopover ? 0 : 1);
|
|
199
|
+
} }
|
|
200
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
201
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
202
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
203
|
+
i0.ɵɵtext(1);
|
|
204
|
+
i0.ɵɵelementStart(2, "button", 63);
|
|
205
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_20_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ClearFilters()); });
|
|
95
206
|
i0.ɵɵtext(3, "Clear filters");
|
|
96
207
|
i0.ɵɵelementEnd()();
|
|
97
208
|
} if (rf & 2) {
|
|
@@ -99,254 +210,314 @@ function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_28_Temp
|
|
|
99
210
|
i0.ɵɵadvance();
|
|
100
211
|
i0.ɵɵtextInterpolate2(" Showing ", ctx_r1.filteredData.length, " of ", ctx_r1.viewData.length, " changes ");
|
|
101
212
|
} }
|
|
102
|
-
function
|
|
103
|
-
const
|
|
104
|
-
i0.ɵɵelementStart(0, "div",
|
|
105
|
-
i0.ɵɵelement(1, "i",
|
|
213
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
214
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
215
|
+
i0.ɵɵelementStart(0, "div", 44);
|
|
216
|
+
i0.ɵɵelement(1, "i", 64);
|
|
106
217
|
i0.ɵɵelementStart(2, "p");
|
|
107
218
|
i0.ɵɵtext(3, "No changes match your current filters.");
|
|
108
219
|
i0.ɵɵelementEnd();
|
|
109
|
-
i0.ɵɵelementStart(4, "button",
|
|
110
|
-
i0.ɵɵlistener("click", function
|
|
111
|
-
i0.ɵɵelement(5, "i",
|
|
220
|
+
i0.ɵɵelementStart(4, "button", 65);
|
|
221
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ClearFilters()); });
|
|
222
|
+
i0.ɵɵelement(5, "i", 66);
|
|
112
223
|
i0.ɵɵtext(6, " Clear Filters ");
|
|
113
224
|
i0.ɵɵelementEnd()();
|
|
114
225
|
} }
|
|
115
|
-
function
|
|
116
|
-
i0.ɵɵ
|
|
226
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_0_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
i0.ɵɵtext(0);
|
|
228
|
+
} if (rf & 2) {
|
|
229
|
+
const srcChange_r16 = i0.ɵɵnextContext();
|
|
230
|
+
const ctx_r1 = i0.ɵɵnextContext(7);
|
|
231
|
+
i0.ɵɵtextInterpolate1(" by ", ctx_r1.getUserDisplayName(srcChange_r16.User), " ");
|
|
232
|
+
} }
|
|
233
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
234
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
235
|
+
i0.ɵɵelementStart(0, "a", 85);
|
|
236
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_0_Template_a_click_0_listener($event) { const srcChange_r16 = i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(7); return i0.ɵɵresetView(ctx_r1.JumpToSourceChange(srcChange_r16, $event)); });
|
|
237
|
+
i0.ɵɵelement(1, "i", 86);
|
|
238
|
+
i0.ɵɵtext(2);
|
|
239
|
+
i0.ɵɵpipe(3, "date");
|
|
240
|
+
i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_0_Conditional_4_Template, 1, 1);
|
|
241
|
+
i0.ɵɵelementEnd();
|
|
242
|
+
} if (rf & 2) {
|
|
243
|
+
const srcChange_r16 = ctx;
|
|
244
|
+
const ctx_r1 = i0.ɵɵnextContext(7);
|
|
245
|
+
i0.ɵɵproperty("title", "Jump to source version (" + ctx_r1.formatFullDateTime(srcChange_r16.ChangedAt) + ")");
|
|
246
|
+
i0.ɵɵadvance(2);
|
|
247
|
+
i0.ɵɵtextInterpolate2(" Restored from ", ctx_r1.formatTime(srcChange_r16.ChangedAt), " ", srcChange_r16.ChangedAt ? "on " + i0.ɵɵpipeBind2(3, 4, srcChange_r16.ChangedAt, "mediumDate") : "", " ");
|
|
248
|
+
i0.ɵɵadvance(2);
|
|
249
|
+
i0.ɵɵconditional(srcChange_r16.User ? 4 : -1);
|
|
250
|
+
} }
|
|
251
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
252
|
+
i0.ɵɵelementStart(0, "span", 84);
|
|
253
|
+
i0.ɵɵelement(1, "i", 87);
|
|
254
|
+
i0.ɵɵtext(2, " Restored from earlier version ");
|
|
255
|
+
i0.ɵɵelementEnd();
|
|
256
|
+
} }
|
|
257
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
258
|
+
i0.ɵɵconditionalCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_0_Template, 5, 7, "a", 83)(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Conditional_1_Template, 3, 0, "span", 84);
|
|
259
|
+
} if (rf & 2) {
|
|
260
|
+
let tmp_24_0;
|
|
261
|
+
const change_r14 = i0.ɵɵnextContext().$implicit;
|
|
262
|
+
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
263
|
+
i0.ɵɵconditional((tmp_24_0 = ctx_r1.getRestoredFromSourceChange(change_r14)) ? 0 : 1, tmp_24_0);
|
|
264
|
+
} }
|
|
265
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
266
|
+
i0.ɵɵelementStart(0, "blockquote", 88)(1, "span", 93);
|
|
267
|
+
i0.ɵɵtext(2, "Reason");
|
|
268
|
+
i0.ɵɵelementEnd();
|
|
269
|
+
i0.ɵɵelementStart(3, "span", 94);
|
|
270
|
+
i0.ɵɵtext(4);
|
|
271
|
+
i0.ɵɵelementEnd()();
|
|
272
|
+
} if (rf & 2) {
|
|
273
|
+
i0.ɵɵadvance(4);
|
|
274
|
+
i0.ɵɵtextInterpolate(ctx);
|
|
275
|
+
} }
|
|
276
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Conditional_0_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
i0.ɵɵelementStart(0, "div", 95)(1, "div", 96);
|
|
117
278
|
i0.ɵɵtext(2);
|
|
118
279
|
i0.ɵɵelementEnd();
|
|
119
|
-
i0.ɵɵelementStart(3, "div",
|
|
280
|
+
i0.ɵɵelementStart(3, "div", 97)(4, "span", 98);
|
|
120
281
|
i0.ɵɵtext(5);
|
|
121
282
|
i0.ɵɵelementEnd()()();
|
|
122
283
|
} if (rf & 2) {
|
|
123
|
-
const
|
|
284
|
+
const field_r17 = ctx.$implicit;
|
|
124
285
|
i0.ɵɵadvance(2);
|
|
125
|
-
i0.ɵɵtextInterpolate(
|
|
286
|
+
i0.ɵɵtextInterpolate(field_r17.displayName);
|
|
126
287
|
i0.ɵɵadvance(3);
|
|
127
|
-
i0.ɵɵtextInterpolate(
|
|
288
|
+
i0.ɵɵtextInterpolate(field_r17.value);
|
|
128
289
|
} }
|
|
129
|
-
function
|
|
130
|
-
i0.ɵɵrepeaterCreate(0,
|
|
290
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
291
|
+
i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Conditional_0_For_1_Template, 6, 2, "div", 95, _forTrack3);
|
|
131
292
|
} if (rf & 2) {
|
|
132
|
-
const
|
|
293
|
+
const change_r14 = i0.ɵɵnextContext(3).$implicit;
|
|
133
294
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
134
|
-
i0.ɵɵrepeater(ctx_r1.getCreatedFields(
|
|
295
|
+
i0.ɵɵrepeater(ctx_r1.getCreatedFields(change_r14));
|
|
135
296
|
} }
|
|
136
|
-
function
|
|
137
|
-
i0.ɵɵconditionalCreate(0,
|
|
297
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
298
|
+
i0.ɵɵconditionalCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Conditional_0_Template, 2, 0);
|
|
138
299
|
} if (rf & 2) {
|
|
139
|
-
const
|
|
140
|
-
i0.ɵɵconditional(
|
|
300
|
+
const change_r14 = i0.ɵɵnextContext(2).$implicit;
|
|
301
|
+
i0.ɵɵconditional(change_r14.FullRecordJSON ? 0 : -1);
|
|
141
302
|
} }
|
|
142
|
-
function
|
|
143
|
-
i0.ɵɵelementStart(0, "div",
|
|
144
|
-
i0.ɵɵelement(1, "i",
|
|
303
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
304
|
+
i0.ɵɵelementStart(0, "div", 89);
|
|
305
|
+
i0.ɵɵelement(1, "i", 99);
|
|
145
306
|
i0.ɵɵtext(2, " This record was permanently removed from the system. ");
|
|
146
307
|
i0.ɵɵelementEnd();
|
|
147
308
|
} }
|
|
148
|
-
function
|
|
149
|
-
i0.ɵɵelementStart(0, "div",
|
|
150
|
-
i0.ɵɵelement(1, "span",
|
|
151
|
-
i0.ɵɵelementStart(2, "span",
|
|
309
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
310
|
+
i0.ɵɵelementStart(0, "div", 100);
|
|
311
|
+
i0.ɵɵelement(1, "span", 103);
|
|
312
|
+
i0.ɵɵelementStart(2, "span", 104);
|
|
152
313
|
i0.ɵɵtext(3);
|
|
153
314
|
i0.ɵɵelementEnd();
|
|
154
|
-
i0.ɵɵelement(4, "i",
|
|
155
|
-
i0.ɵɵelementStart(6, "span",
|
|
315
|
+
i0.ɵɵelement(4, "i", 105)(5, "span", 103);
|
|
316
|
+
i0.ɵɵelementStart(6, "span", 106);
|
|
156
317
|
i0.ɵɵtext(7);
|
|
157
318
|
i0.ɵɵelementEnd()();
|
|
158
319
|
} if (rf & 2) {
|
|
159
|
-
const
|
|
320
|
+
const fc_r18 = i0.ɵɵnextContext().$implicit;
|
|
160
321
|
i0.ɵɵadvance();
|
|
161
|
-
i0.ɵɵclassProp("on",
|
|
322
|
+
i0.ɵɵclassProp("on", fc_r18.oldValue === "true" || fc_r18.oldValue === "1")("off", fc_r18.oldValue !== "true" && fc_r18.oldValue !== "1");
|
|
162
323
|
i0.ɵɵadvance(2);
|
|
163
|
-
i0.ɵɵtextInterpolate(
|
|
324
|
+
i0.ɵɵtextInterpolate(fc_r18.oldValue === "true" || fc_r18.oldValue === "1" ? "Yes" : "No");
|
|
164
325
|
i0.ɵɵadvance(2);
|
|
165
|
-
i0.ɵɵclassProp("on",
|
|
326
|
+
i0.ɵɵclassProp("on", fc_r18.newValue === "true" || fc_r18.newValue === "1")("off", fc_r18.newValue !== "true" && fc_r18.newValue !== "1");
|
|
166
327
|
i0.ɵɵadvance();
|
|
167
|
-
i0.ɵɵclassProp("active",
|
|
328
|
+
i0.ɵɵclassProp("active", fc_r18.newValue === "true" || fc_r18.newValue === "1")("inactive", fc_r18.newValue !== "true" && fc_r18.newValue !== "1");
|
|
168
329
|
i0.ɵɵadvance();
|
|
169
|
-
i0.ɵɵtextInterpolate(
|
|
330
|
+
i0.ɵɵtextInterpolate(fc_r18.newValue === "true" || fc_r18.newValue === "1" ? "Yes" : "No");
|
|
170
331
|
} }
|
|
171
|
-
function
|
|
172
|
-
i0.ɵɵelementStart(0, "div",
|
|
332
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
333
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "span", 107);
|
|
173
334
|
i0.ɵɵtext(2);
|
|
174
335
|
i0.ɵɵelementEnd();
|
|
175
|
-
i0.ɵɵelement(3, "i",
|
|
176
|
-
i0.ɵɵelementStart(4, "span",
|
|
336
|
+
i0.ɵɵelement(3, "i", 105);
|
|
337
|
+
i0.ɵɵelementStart(4, "span", 98);
|
|
177
338
|
i0.ɵɵtext(5);
|
|
178
339
|
i0.ɵɵelementEnd()();
|
|
179
340
|
} if (rf & 2) {
|
|
180
|
-
const
|
|
341
|
+
const fc_r18 = i0.ɵɵnextContext().$implicit;
|
|
181
342
|
i0.ɵɵadvance(2);
|
|
182
|
-
i0.ɵɵtextInterpolate(
|
|
343
|
+
i0.ɵɵtextInterpolate(fc_r18.oldValue || "(empty)");
|
|
183
344
|
i0.ɵɵadvance(3);
|
|
184
|
-
i0.ɵɵtextInterpolate(
|
|
345
|
+
i0.ɵɵtextInterpolate(fc_r18.newValue || "(empty)");
|
|
185
346
|
} }
|
|
186
|
-
function
|
|
187
|
-
i0.ɵɵelement(0, "div",
|
|
347
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
348
|
+
i0.ɵɵelement(0, "div", 102);
|
|
188
349
|
} if (rf & 2) {
|
|
189
|
-
const
|
|
190
|
-
i0.ɵɵproperty("innerHTML",
|
|
350
|
+
const fc_r18 = i0.ɵɵnextContext().$implicit;
|
|
351
|
+
i0.ɵɵproperty("innerHTML", fc_r18.diffHtml, i0.ɵɵsanitizeHtml);
|
|
191
352
|
} }
|
|
192
|
-
function
|
|
193
|
-
i0.ɵɵelementStart(0, "div",
|
|
353
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
354
|
+
i0.ɵɵelementStart(0, "div", 101)(1, "span", 107);
|
|
194
355
|
i0.ɵɵtext(2);
|
|
195
356
|
i0.ɵɵelementEnd();
|
|
196
|
-
i0.ɵɵelement(3, "i",
|
|
197
|
-
i0.ɵɵelementStart(4, "span",
|
|
357
|
+
i0.ɵɵelement(3, "i", 105);
|
|
358
|
+
i0.ɵɵelementStart(4, "span", 98);
|
|
198
359
|
i0.ɵɵtext(5);
|
|
199
360
|
i0.ɵɵelementEnd()();
|
|
200
361
|
} if (rf & 2) {
|
|
201
|
-
const
|
|
362
|
+
const fc_r18 = i0.ɵɵnextContext().$implicit;
|
|
202
363
|
i0.ɵɵadvance(2);
|
|
203
|
-
i0.ɵɵtextInterpolate(
|
|
364
|
+
i0.ɵɵtextInterpolate(fc_r18.oldValue || "(empty)");
|
|
204
365
|
i0.ɵɵadvance(3);
|
|
205
|
-
i0.ɵɵtextInterpolate(
|
|
366
|
+
i0.ɵɵtextInterpolate(fc_r18.newValue || "(empty)");
|
|
206
367
|
} }
|
|
207
|
-
function
|
|
208
|
-
i0.ɵɵelementStart(0, "div",
|
|
368
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
369
|
+
i0.ɵɵelementStart(0, "div", 95)(1, "div", 96);
|
|
209
370
|
i0.ɵɵtext(2);
|
|
210
371
|
i0.ɵɵelementEnd();
|
|
211
|
-
i0.ɵɵelementStart(3, "div",
|
|
212
|
-
i0.ɵɵconditionalCreate(4,
|
|
372
|
+
i0.ɵɵelementStart(3, "div", 97);
|
|
373
|
+
i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_4_Template, 8, 14, "div", 100)(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_5_Template, 6, 2, "div", 101)(6, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_6_Template, 1, 1, "div", 102)(7, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Conditional_7_Template, 6, 2, "div", 101);
|
|
213
374
|
i0.ɵɵelementEnd()();
|
|
214
375
|
} if (rf & 2) {
|
|
215
|
-
const
|
|
376
|
+
const fc_r18 = ctx.$implicit;
|
|
216
377
|
i0.ɵɵadvance(2);
|
|
217
|
-
i0.ɵɵtextInterpolate(
|
|
378
|
+
i0.ɵɵtextInterpolate(fc_r18.displayName);
|
|
218
379
|
i0.ɵɵadvance(2);
|
|
219
|
-
i0.ɵɵconditional(
|
|
380
|
+
i0.ɵɵconditional(fc_r18.fieldType === "boolean" ? 4 : fc_r18.fieldType === "date" || fc_r18.fieldType === "number" ? 5 : fc_r18.diffHtml ? 6 : 7);
|
|
220
381
|
} }
|
|
221
|
-
function
|
|
222
|
-
i0.ɵɵrepeaterCreate(0,
|
|
382
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
383
|
+
i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_For_1_Template, 8, 2, "div", 95, _forTrack4);
|
|
223
384
|
} if (rf & 2) {
|
|
224
|
-
const
|
|
385
|
+
const change_r14 = i0.ɵɵnextContext(2).$implicit;
|
|
225
386
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
226
|
-
i0.ɵɵrepeater(ctx_r1.getFieldChanges(
|
|
387
|
+
i0.ɵɵrepeater(ctx_r1.getFieldChanges(change_r14));
|
|
227
388
|
} }
|
|
228
|
-
function
|
|
229
|
-
i0.ɵɵelementStart(0, "div",
|
|
230
|
-
i0.ɵɵelement(1, "i",
|
|
389
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
390
|
+
i0.ɵɵelementStart(0, "div", 90);
|
|
391
|
+
i0.ɵɵelement(1, "i", 108);
|
|
231
392
|
i0.ɵɵtext(2);
|
|
232
393
|
i0.ɵɵelementEnd();
|
|
233
394
|
} if (rf & 2) {
|
|
234
|
-
const
|
|
395
|
+
const change_r14 = i0.ɵɵnextContext(2).$implicit;
|
|
235
396
|
i0.ɵɵadvance(2);
|
|
236
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
397
|
+
i0.ɵɵtextInterpolate1(" ", change_r14.Comments, " ");
|
|
237
398
|
} }
|
|
238
|
-
function
|
|
239
|
-
i0.ɵɵelementStart(0, "div",
|
|
240
|
-
i0.ɵɵelement(1, "i",
|
|
241
|
-
i0.ɵɵelementStart(2, "pre",
|
|
399
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
400
|
+
i0.ɵɵelementStart(0, "div", 91);
|
|
401
|
+
i0.ɵɵelement(1, "i", 109);
|
|
402
|
+
i0.ɵɵelementStart(2, "pre", 110);
|
|
242
403
|
i0.ɵɵtext(3);
|
|
243
404
|
i0.ɵɵelementEnd()();
|
|
244
405
|
} if (rf & 2) {
|
|
245
|
-
const
|
|
406
|
+
const change_r14 = i0.ɵɵnextContext(2).$implicit;
|
|
246
407
|
i0.ɵɵadvance(3);
|
|
247
|
-
i0.ɵɵtextInterpolate(
|
|
408
|
+
i0.ɵɵtextInterpolate(change_r14.ErrorLog);
|
|
248
409
|
} }
|
|
249
|
-
function
|
|
250
|
-
const
|
|
251
|
-
i0.ɵɵelementStart(0, "div",
|
|
252
|
-
i0.ɵɵlistener("click", function
|
|
253
|
-
i0.ɵɵelement(2, "i",
|
|
254
|
-
i0.ɵɵtext(3, " Restore
|
|
410
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
411
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
412
|
+
i0.ɵɵelementStart(0, "div", 92)(1, "button", 111);
|
|
413
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_7_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r19); const change_r14 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.OnRestoreVersion(change_r14, $event)); });
|
|
414
|
+
i0.ɵɵelement(2, "i", 87);
|
|
415
|
+
i0.ɵɵtext(3, " Restore record to this version ");
|
|
255
416
|
i0.ɵɵelementEnd()();
|
|
256
417
|
} }
|
|
257
|
-
function
|
|
258
|
-
i0.ɵɵelementStart(0, "div",
|
|
259
|
-
i0.ɵɵconditionalCreate(1,
|
|
260
|
-
i0.ɵɵconditionalCreate(
|
|
261
|
-
i0.ɵɵconditionalCreate(5,
|
|
262
|
-
i0.ɵɵconditionalCreate(6,
|
|
418
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
419
|
+
i0.ɵɵelementStart(0, "div", 82);
|
|
420
|
+
i0.ɵɵconditionalCreate(1, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_1_Template, 5, 1, "blockquote", 88);
|
|
421
|
+
i0.ɵɵconditionalCreate(2, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_2_Template, 1, 1)(3, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_3_Template, 3, 0, "div", 89)(4, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_4_Template, 2, 0);
|
|
422
|
+
i0.ɵɵconditionalCreate(5, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_5_Template, 3, 1, "div", 90);
|
|
423
|
+
i0.ɵɵconditionalCreate(6, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_6_Template, 4, 1, "div", 91);
|
|
424
|
+
i0.ɵɵconditionalCreate(7, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Conditional_7_Template, 4, 0, "div", 92);
|
|
263
425
|
i0.ɵɵelementEnd();
|
|
264
426
|
} if (rf & 2) {
|
|
265
|
-
|
|
427
|
+
let tmp_24_0;
|
|
428
|
+
const change_r14 = i0.ɵɵnextContext().$implicit;
|
|
266
429
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
267
430
|
i0.ɵɵadvance();
|
|
268
|
-
i0.ɵɵconditional(
|
|
431
|
+
i0.ɵɵconditional((tmp_24_0 = ctx_r1.getRestoreReason(change_r14)) ? 1 : -1, tmp_24_0);
|
|
432
|
+
i0.ɵɵadvance();
|
|
433
|
+
i0.ɵɵconditional(change_r14.Type === "Create" ? 2 : change_r14.Type === "Delete" ? 3 : 4);
|
|
269
434
|
i0.ɵɵadvance(3);
|
|
270
|
-
i0.ɵɵconditional(
|
|
435
|
+
i0.ɵɵconditional(change_r14.Comments ? 5 : -1);
|
|
271
436
|
i0.ɵɵadvance();
|
|
272
|
-
i0.ɵɵconditional(
|
|
437
|
+
i0.ɵɵconditional(change_r14.ErrorLog ? 6 : -1);
|
|
273
438
|
i0.ɵɵadvance();
|
|
274
|
-
i0.ɵɵconditional(ctx_r1.AllowRestore &&
|
|
439
|
+
i0.ɵɵconditional(ctx_r1.AllowRestore && change_r14.Type !== "Delete" && !ctx_r1.isMostRecentChange(change_r14) ? 7 : -1);
|
|
275
440
|
} }
|
|
276
|
-
function
|
|
277
|
-
const
|
|
278
|
-
i0.ɵɵelementStart(0, "div",
|
|
279
|
-
i0.ɵɵlistener("keydown", function
|
|
280
|
-
i0.ɵɵelementStart(1, "div",
|
|
281
|
-
i0.ɵɵlistener("click", function
|
|
282
|
-
i0.ɵɵelementStart(2, "div",
|
|
441
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
442
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
443
|
+
i0.ɵɵelementStart(0, "div", 70);
|
|
444
|
+
i0.ɵɵlistener("keydown", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Template_div_keydown_0_listener($event) { const change_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onTimelineItemKeydown($event, change_r14.ID)); });
|
|
445
|
+
i0.ɵɵelementStart(1, "div", 71);
|
|
446
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Template_div_click_1_listener() { const change_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.toggleExpansion(change_r14.ID)); });
|
|
447
|
+
i0.ɵɵelementStart(2, "div", 72)(3, "span", 73);
|
|
283
448
|
i0.ɵɵtext(4);
|
|
284
449
|
i0.ɵɵelementEnd();
|
|
285
|
-
i0.ɵɵelementStart(5, "span",
|
|
450
|
+
i0.ɵɵelementStart(5, "span", 74);
|
|
286
451
|
i0.ɵɵtext(6);
|
|
287
|
-
i0.ɵɵelementEnd()();
|
|
288
|
-
i0.ɵɵelementStart(7, "div", 60)(8, "div", 61)(9, "div", 62);
|
|
289
|
-
i0.ɵɵtext(10);
|
|
290
452
|
i0.ɵɵelementEnd();
|
|
453
|
+
i0.ɵɵconditionalCreate(7, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_7_Template, 2, 1);
|
|
454
|
+
i0.ɵɵelementEnd();
|
|
455
|
+
i0.ɵɵelementStart(8, "div", 75)(9, "div", 76)(10, "div", 77);
|
|
291
456
|
i0.ɵɵtext(11);
|
|
292
457
|
i0.ɵɵelementEnd();
|
|
293
|
-
i0.ɵɵ
|
|
294
|
-
i0.ɵɵ
|
|
458
|
+
i0.ɵɵtext(12);
|
|
459
|
+
i0.ɵɵelementEnd();
|
|
460
|
+
i0.ɵɵelementStart(13, "span", 78);
|
|
461
|
+
i0.ɵɵtext(14);
|
|
295
462
|
i0.ɵɵelementEnd();
|
|
296
|
-
i0.ɵɵelementStart(
|
|
297
|
-
i0.ɵɵtext(
|
|
463
|
+
i0.ɵɵelementStart(15, "span", 79);
|
|
464
|
+
i0.ɵɵtext(16);
|
|
298
465
|
i0.ɵɵelementEnd();
|
|
299
|
-
i0.ɵɵelementStart(
|
|
300
|
-
i0.ɵɵtext(
|
|
466
|
+
i0.ɵɵelementStart(17, "span", 80);
|
|
467
|
+
i0.ɵɵtext(18);
|
|
301
468
|
i0.ɵɵelementEnd();
|
|
302
|
-
i0.ɵɵelement(
|
|
469
|
+
i0.ɵɵelement(19, "i", 81);
|
|
303
470
|
i0.ɵɵelementEnd()();
|
|
304
|
-
i0.ɵɵconditionalCreate(
|
|
471
|
+
i0.ɵɵconditionalCreate(20, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Conditional_20_Template, 8, 5, "div", 82);
|
|
305
472
|
i0.ɵɵelementEnd();
|
|
306
473
|
} if (rf & 2) {
|
|
307
|
-
const
|
|
474
|
+
const change_r14 = ctx.$implicit;
|
|
308
475
|
const ctx_r1 = i0.ɵɵnextContext(5);
|
|
309
|
-
i0.ɵɵclassMap(ctx_r1.getChangeTypeCardClass(
|
|
310
|
-
i0.ɵɵclassProp("expanded", ctx_r1.expandedItems.has(
|
|
311
|
-
i0.ɵɵattribute("tabindex", 0)("aria-expanded", ctx_r1.expandedItems.has(
|
|
312
|
-
i0.ɵɵadvance(
|
|
313
|
-
i0.ɵɵ
|
|
476
|
+
i0.ɵɵclassMap(ctx_r1.getChangeTypeCardClass(change_r14.Type));
|
|
477
|
+
i0.ɵɵclassProp("expanded", ctx_r1.expandedItems.has(change_r14.ID))("rc-card-restore", ctx_r1.isRestoreRow(change_r14))("rc-card-highlight", ctx_r1.HighlightedChangeID === change_r14.ID);
|
|
478
|
+
i0.ɵɵattribute("data-change-id", change_r14.ID)("tabindex", 0)("aria-expanded", ctx_r1.expandedItems.has(change_r14.ID))("aria-label", ctx_r1.getTimelineItemLabel(change_r14));
|
|
479
|
+
i0.ɵɵadvance(3);
|
|
480
|
+
i0.ɵɵclassProp("rc-card-type-badge-restore", ctx_r1.isRestoreRow(change_r14));
|
|
481
|
+
i0.ɵɵadvance();
|
|
482
|
+
i0.ɵɵtextInterpolate(ctx_r1.getEffectiveBadgeText(change_r14));
|
|
314
483
|
i0.ɵɵadvance(2);
|
|
315
|
-
i0.ɵɵtextInterpolate(ctx_r1.getChangeSummary(
|
|
484
|
+
i0.ɵɵtextInterpolate(ctx_r1.getChangeSummary(change_r14));
|
|
485
|
+
i0.ɵɵadvance();
|
|
486
|
+
i0.ɵɵconditional(ctx_r1.isRestoreRow(change_r14) ? 7 : -1);
|
|
316
487
|
i0.ɵɵadvance(4);
|
|
317
|
-
i0.ɵɵtextInterpolate(ctx_r1.getUserInitials(
|
|
488
|
+
i0.ɵɵtextInterpolate(ctx_r1.getUserInitials(change_r14.User));
|
|
318
489
|
i0.ɵɵadvance();
|
|
319
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.getUserDisplayName(
|
|
490
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getUserDisplayName(change_r14.User), " ");
|
|
320
491
|
i0.ɵɵadvance();
|
|
321
|
-
i0.ɵɵproperty("title", ctx_r1.formatFullDateTime(
|
|
492
|
+
i0.ɵɵproperty("title", ctx_r1.formatFullDateTime(change_r14.ChangedAt));
|
|
322
493
|
i0.ɵɵadvance();
|
|
323
|
-
i0.ɵɵtextInterpolate(ctx_r1.formatTime(
|
|
494
|
+
i0.ɵɵtextInterpolate(ctx_r1.formatTime(change_r14.ChangedAt));
|
|
324
495
|
i0.ɵɵadvance();
|
|
325
|
-
i0.ɵɵclassMap(ctx_r1.getSourceClass(
|
|
496
|
+
i0.ɵɵclassMap(ctx_r1.getSourceClass(change_r14.Source));
|
|
326
497
|
i0.ɵɵadvance();
|
|
327
|
-
i0.ɵɵtextInterpolate(
|
|
498
|
+
i0.ɵɵtextInterpolate(change_r14.Source);
|
|
328
499
|
i0.ɵɵadvance();
|
|
329
|
-
i0.ɵɵclassMap(ctx_r1.getStatusClass(
|
|
500
|
+
i0.ɵɵclassMap(ctx_r1.getStatusClass(change_r14.Status));
|
|
330
501
|
i0.ɵɵadvance();
|
|
331
|
-
i0.ɵɵtextInterpolate(
|
|
502
|
+
i0.ɵɵtextInterpolate(change_r14.Status);
|
|
332
503
|
i0.ɵɵadvance(2);
|
|
333
|
-
i0.ɵɵconditional(ctx_r1.expandedItems.has(
|
|
504
|
+
i0.ɵɵconditional(ctx_r1.expandedItems.has(change_r14.ID) ? 20 : -1);
|
|
334
505
|
} }
|
|
335
|
-
function
|
|
336
|
-
i0.ɵɵelementStart(0, "div",
|
|
506
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
507
|
+
i0.ɵɵelementStart(0, "div", 67)(1, "div", 68);
|
|
337
508
|
i0.ɵɵtext(2);
|
|
338
509
|
i0.ɵɵelementEnd();
|
|
339
|
-
i0.ɵɵrepeaterCreate(3,
|
|
510
|
+
i0.ɵɵrepeaterCreate(3, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_For_4_Template, 21, 28, "div", 69, _forTrack0);
|
|
340
511
|
i0.ɵɵelementEnd();
|
|
341
512
|
} if (rf & 2) {
|
|
342
|
-
const
|
|
513
|
+
const group_r20 = ctx.$implicit;
|
|
343
514
|
i0.ɵɵadvance(2);
|
|
344
|
-
i0.ɵɵtextInterpolate(
|
|
515
|
+
i0.ɵɵtextInterpolate(group_r20.label);
|
|
345
516
|
i0.ɵɵadvance();
|
|
346
|
-
i0.ɵɵrepeater(
|
|
517
|
+
i0.ɵɵrepeater(group_r20.changes);
|
|
347
518
|
} }
|
|
348
|
-
function
|
|
349
|
-
i0.ɵɵrepeaterCreate(0,
|
|
519
|
+
function RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
520
|
+
i0.ɵɵrepeaterCreate(0, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_For_1_Template, 5, 1, "div", 67, _forTrack2);
|
|
350
521
|
} if (rf & 2) {
|
|
351
522
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
352
523
|
i0.ɵɵrepeater(ctx_r1.dateGroups);
|
|
@@ -373,28 +544,15 @@ function RecordChangesComponent_Conditional_2_Conditional_15_Template(rf, ctx) {
|
|
|
373
544
|
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()); });
|
|
374
545
|
i0.ɵɵelementEnd()();
|
|
375
546
|
i0.ɵɵelementStart(16, "button", 40);
|
|
376
|
-
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.
|
|
547
|
+
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.SelectAllPill()); });
|
|
377
548
|
i0.ɵɵelement(17, "i", 41);
|
|
378
549
|
i0.ɵɵtext(18, " All ");
|
|
379
550
|
i0.ɵɵelementEnd();
|
|
380
|
-
i0.ɵɵ
|
|
381
|
-
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")); });
|
|
382
|
-
i0.ɵɵelement(20, "i", 42);
|
|
383
|
-
i0.ɵɵtext(21, " Updates ");
|
|
551
|
+
i0.ɵɵconditionalCreate(19, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_19_Template, 2, 1);
|
|
384
552
|
i0.ɵɵelementEnd();
|
|
385
|
-
i0.ɵɵ
|
|
386
|
-
i0.ɵɵ
|
|
387
|
-
i0.ɵɵ
|
|
388
|
-
i0.ɵɵtext(24, " Creates ");
|
|
389
|
-
i0.ɵɵelementEnd();
|
|
390
|
-
i0.ɵɵelementStart(25, "button", 40);
|
|
391
|
-
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")); });
|
|
392
|
-
i0.ɵɵelement(26, "i", 44);
|
|
393
|
-
i0.ɵɵtext(27, " Deletes ");
|
|
394
|
-
i0.ɵɵelementEnd()();
|
|
395
|
-
i0.ɵɵconditionalCreate(28, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_28_Template, 4, 2, "div", 45);
|
|
396
|
-
i0.ɵɵelementStart(29, "div", 46);
|
|
397
|
-
i0.ɵɵconditionalCreate(30, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_30_Template, 7, 0, "div", 47)(31, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_31_Template, 2, 0);
|
|
553
|
+
i0.ɵɵconditionalCreate(20, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_20_Template, 4, 2, "div", 42);
|
|
554
|
+
i0.ɵɵelementStart(21, "div", 43);
|
|
555
|
+
i0.ɵɵconditionalCreate(22, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_22_Template, 7, 0, "div", 44)(23, RecordChangesComponent_Conditional_2_Conditional_15_Conditional_23_Template, 2, 0);
|
|
398
556
|
i0.ɵɵelementEnd();
|
|
399
557
|
} if (rf & 2) {
|
|
400
558
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -407,19 +565,15 @@ function RecordChangesComponent_Conditional_2_Conditional_15_Template(rf, ctx) {
|
|
|
407
565
|
i0.ɵɵadvance(4);
|
|
408
566
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.searchTerm);
|
|
409
567
|
i0.ɵɵadvance();
|
|
410
|
-
i0.ɵɵclassProp("active",
|
|
411
|
-
i0.ɵɵadvance(3);
|
|
412
|
-
i0.ɵɵclassProp("active", ctx_r1.selectedType === "Update");
|
|
413
|
-
i0.ɵɵadvance(3);
|
|
414
|
-
i0.ɵɵclassProp("active", ctx_r1.selectedType === "Create");
|
|
568
|
+
i0.ɵɵclassProp("active", ctx_r1.IsAllSelected);
|
|
415
569
|
i0.ɵɵadvance(3);
|
|
416
|
-
i0.ɵɵ
|
|
417
|
-
i0.ɵɵadvance(
|
|
418
|
-
i0.ɵɵconditional(ctx_r1.filteredData.length !== ctx_r1.viewData.length ?
|
|
570
|
+
i0.ɵɵconditional(ctx_r1.HasConditionalPills ? 19 : -1);
|
|
571
|
+
i0.ɵɵadvance();
|
|
572
|
+
i0.ɵɵconditional(ctx_r1.filteredData.length !== ctx_r1.viewData.length ? 20 : -1);
|
|
419
573
|
i0.ɵɵadvance();
|
|
420
574
|
i0.ɵɵattribute("aria-label", "Timeline of changes for " + ctx_r1.record.EntityInfo.Name + " record");
|
|
421
575
|
i0.ɵɵadvance();
|
|
422
|
-
i0.ɵɵconditional(ctx_r1.filteredData.length === 0 ?
|
|
576
|
+
i0.ɵɵconditional(ctx_r1.filteredData.length === 0 ? 22 : 23);
|
|
423
577
|
} }
|
|
424
578
|
function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
425
579
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -437,7 +591,7 @@ function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
437
591
|
i0.ɵɵelementEnd()();
|
|
438
592
|
i0.ɵɵconditionalCreate(11, RecordChangesComponent_Conditional_2_Conditional_11_Template, 3, 0, "div", 12)(12, RecordChangesComponent_Conditional_2_Conditional_12_Template, 2, 0, "div", 13)(13, RecordChangesComponent_Conditional_2_Conditional_13_Template, 3, 0, "div", 14);
|
|
439
593
|
i0.ɵɵelementEnd();
|
|
440
|
-
i0.ɵɵconditionalCreate(14, RecordChangesComponent_Conditional_2_Conditional_14_Template, 11, 0, "div", 15)(15, RecordChangesComponent_Conditional_2_Conditional_15_Template,
|
|
594
|
+
i0.ɵɵconditionalCreate(14, RecordChangesComponent_Conditional_2_Conditional_14_Template, 11, 0, "div", 15)(15, RecordChangesComponent_Conditional_2_Conditional_15_Template, 24, 13);
|
|
441
595
|
i0.ɵɵelementEnd();
|
|
442
596
|
} if (rf & 2) {
|
|
443
597
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -448,133 +602,34 @@ function RecordChangesComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
448
602
|
i0.ɵɵadvance(3);
|
|
449
603
|
i0.ɵɵconditional(ctx_r1.viewData.length === 0 ? 14 : 15);
|
|
450
604
|
} }
|
|
451
|
-
function RecordChangesComponent_Conditional_3_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
452
|
-
i0.ɵɵelementStart(0, "div", 96);
|
|
453
|
-
i0.ɵɵelement(1, "i", 101);
|
|
454
|
-
i0.ɵɵtext(2, " No field changes could be parsed from this version. ");
|
|
455
|
-
i0.ɵɵelementEnd();
|
|
456
|
-
} }
|
|
457
|
-
function RecordChangesComponent_Conditional_3_Conditional_18_For_12_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
458
|
-
i0.ɵɵelement(0, "i", 107);
|
|
459
|
-
} }
|
|
460
|
-
function RecordChangesComponent_Conditional_3_Conditional_18_For_12_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
461
|
-
i0.ɵɵelement(0, "i", 108);
|
|
462
|
-
} }
|
|
463
|
-
function RecordChangesComponent_Conditional_3_Conditional_18_For_12_Template(rf, ctx) { if (rf & 1) {
|
|
464
|
-
i0.ɵɵelementStart(0, "tr")(1, "td", 103);
|
|
465
|
-
i0.ɵɵtext(2);
|
|
466
|
-
i0.ɵɵelementEnd();
|
|
467
|
-
i0.ɵɵelementStart(3, "td", 104);
|
|
468
|
-
i0.ɵɵtext(4);
|
|
469
|
-
i0.ɵɵelementEnd();
|
|
470
|
-
i0.ɵɵelementStart(5, "td", 105);
|
|
471
|
-
i0.ɵɵtext(6);
|
|
472
|
-
i0.ɵɵelementEnd();
|
|
473
|
-
i0.ɵɵelementStart(7, "td", 106);
|
|
474
|
-
i0.ɵɵconditionalCreate(8, RecordChangesComponent_Conditional_3_Conditional_18_For_12_Conditional_8_Template, 1, 0, "i", 107)(9, RecordChangesComponent_Conditional_3_Conditional_18_For_12_Conditional_9_Template, 1, 0, "i", 108);
|
|
475
|
-
i0.ɵɵelementEnd()();
|
|
476
|
-
} if (rf & 2) {
|
|
477
|
-
const diff_r14 = ctx.$implicit;
|
|
478
|
-
i0.ɵɵclassProp("rc-diff-changed", diff_r14.IsChanged)("rc-diff-unchanged", !diff_r14.IsChanged);
|
|
479
|
-
i0.ɵɵadvance(2);
|
|
480
|
-
i0.ɵɵtextInterpolate(diff_r14.DisplayName);
|
|
481
|
-
i0.ɵɵadvance(2);
|
|
482
|
-
i0.ɵɵtextInterpolate(diff_r14.CurrentValue || "(empty)");
|
|
483
|
-
i0.ɵɵadvance(2);
|
|
484
|
-
i0.ɵɵtextInterpolate(diff_r14.VersionValue || "(empty)");
|
|
485
|
-
i0.ɵɵadvance(2);
|
|
486
|
-
i0.ɵɵconditional(diff_r14.IsChanged ? 8 : 9);
|
|
487
|
-
} }
|
|
488
|
-
function RecordChangesComponent_Conditional_3_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
489
|
-
i0.ɵɵelementStart(0, "table", 97)(1, "thead")(2, "tr")(3, "th");
|
|
490
|
-
i0.ɵɵtext(4, "Field");
|
|
491
|
-
i0.ɵɵelementEnd();
|
|
492
|
-
i0.ɵɵelementStart(5, "th");
|
|
493
|
-
i0.ɵɵtext(6, "Current Value");
|
|
494
|
-
i0.ɵɵelementEnd();
|
|
495
|
-
i0.ɵɵelementStart(7, "th");
|
|
496
|
-
i0.ɵɵtext(8, "Restore To");
|
|
497
|
-
i0.ɵɵelementEnd();
|
|
498
|
-
i0.ɵɵelement(9, "th");
|
|
499
|
-
i0.ɵɵelementEnd()();
|
|
500
|
-
i0.ɵɵelementStart(10, "tbody");
|
|
501
|
-
i0.ɵɵrepeaterCreate(11, RecordChangesComponent_Conditional_3_Conditional_18_For_12_Template, 10, 8, "tr", 102, _forTrack4);
|
|
502
|
-
i0.ɵɵelementEnd()();
|
|
503
|
-
} if (rf & 2) {
|
|
504
|
-
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
505
|
-
i0.ɵɵadvance(11);
|
|
506
|
-
i0.ɵɵrepeater(ctx_r1.RestorePreviewFields);
|
|
507
|
-
} }
|
|
508
|
-
function RecordChangesComponent_Conditional_3_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
509
|
-
i0.ɵɵelement(0, "i", 109);
|
|
510
|
-
i0.ɵɵtext(1, " Restoring... ");
|
|
511
|
-
} }
|
|
512
|
-
function RecordChangesComponent_Conditional_3_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
513
|
-
i0.ɵɵelement(0, "i", 110);
|
|
514
|
-
i0.ɵɵtext(1, " Apply Restore ");
|
|
515
|
-
} }
|
|
516
|
-
function RecordChangesComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
517
|
-
const _r13 = i0.ɵɵgetCurrentView();
|
|
518
|
-
i0.ɵɵelementStart(0, "div", 89);
|
|
519
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelRestorePreview()); });
|
|
520
|
-
i0.ɵɵelementStart(1, "div", 90);
|
|
521
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r13); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
522
|
-
i0.ɵɵelementStart(2, "div", 91)(3, "div", 92);
|
|
523
|
-
i0.ɵɵelement(4, "i", 88);
|
|
524
|
-
i0.ɵɵtext(5, " Restore Preview ");
|
|
525
|
-
i0.ɵɵelementEnd();
|
|
526
|
-
i0.ɵɵelementStart(6, "button", 93);
|
|
527
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelRestorePreview()); });
|
|
528
|
-
i0.ɵɵelement(7, "i", 94);
|
|
529
|
-
i0.ɵɵelementEnd()();
|
|
530
|
-
i0.ɵɵelementStart(8, "div", 95)(9, "span")(10, "strong");
|
|
531
|
-
i0.ɵɵtext(11, "Version:");
|
|
532
|
-
i0.ɵɵelementEnd();
|
|
533
|
-
i0.ɵɵtext(12);
|
|
534
|
-
i0.ɵɵelementEnd();
|
|
535
|
-
i0.ɵɵelementStart(13, "span")(14, "strong");
|
|
536
|
-
i0.ɵɵtext(15, "By:");
|
|
537
|
-
i0.ɵɵelementEnd();
|
|
538
|
-
i0.ɵɵtext(16);
|
|
539
|
-
i0.ɵɵelementEnd()();
|
|
540
|
-
i0.ɵɵconditionalCreate(17, RecordChangesComponent_Conditional_3_Conditional_17_Template, 3, 0, "div", 96)(18, RecordChangesComponent_Conditional_3_Conditional_18_Template, 13, 0, "table", 97);
|
|
541
|
-
i0.ɵɵelementStart(19, "div", 98)(20, "button", 99);
|
|
542
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmRestore()); });
|
|
543
|
-
i0.ɵɵconditionalCreate(21, RecordChangesComponent_Conditional_3_Conditional_21_Template, 2, 0)(22, RecordChangesComponent_Conditional_3_Conditional_22_Template, 2, 0);
|
|
544
|
-
i0.ɵɵelementEnd();
|
|
545
|
-
i0.ɵɵelementStart(23, "button", 100);
|
|
546
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_3_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelRestorePreview()); });
|
|
547
|
-
i0.ɵɵtext(24, " Cancel ");
|
|
548
|
-
i0.ɵɵelementEnd()()()();
|
|
549
|
-
} if (rf & 2) {
|
|
550
|
-
const ctx_r1 = i0.ɵɵnextContext();
|
|
551
|
-
i0.ɵɵadvance(12);
|
|
552
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatFullDateTime(ctx_r1.RestorePreview.ChangedAt));
|
|
553
|
-
i0.ɵɵadvance(4);
|
|
554
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.getUserDisplayName(ctx_r1.RestorePreview.User));
|
|
555
|
-
i0.ɵɵadvance();
|
|
556
|
-
i0.ɵɵconditional(ctx_r1.RestorePreviewFields.length === 0 ? 17 : 18);
|
|
557
|
-
i0.ɵɵadvance(3);
|
|
558
|
-
i0.ɵɵproperty("disabled", ctx_r1.IsRestoring || ctx_r1.RestorePreviewFields.length === 0);
|
|
559
|
-
i0.ɵɵadvance();
|
|
560
|
-
i0.ɵɵconditional(ctx_r1.IsRestoring ? 21 : 22);
|
|
561
|
-
i0.ɵɵadvance(2);
|
|
562
|
-
i0.ɵɵproperty("disabled", ctx_r1.IsRestoring);
|
|
563
|
-
} }
|
|
564
605
|
function RecordChangesComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
565
|
-
const
|
|
566
|
-
i0.ɵɵelementStart(0, "div",
|
|
567
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_4_Template_div_click_0_listener() { i0.ɵɵrestoreView(
|
|
568
|
-
i0.ɵɵelementStart(1, "div",
|
|
569
|
-
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_4_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(
|
|
570
|
-
i0.ɵɵelementStart(2, "mj-label-create",
|
|
571
|
-
i0.ɵɵlistener("Created", function RecordChangesComponent_Conditional_4_Template_mj_label_create_Created_2_listener($event) { i0.ɵɵrestoreView(
|
|
606
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
607
|
+
i0.ɵɵelementStart(0, "div", 112);
|
|
608
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_4_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
|
|
609
|
+
i0.ɵɵelementStart(1, "div", 113);
|
|
610
|
+
i0.ɵɵlistener("click", function RecordChangesComponent_Conditional_4_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r21); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
611
|
+
i0.ɵɵelementStart(2, "mj-label-create", 114);
|
|
612
|
+
i0.ɵɵlistener("Created", function RecordChangesComponent_Conditional_4_Template_mj_label_create_Created_2_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreated($event)); })("Cancel", function RecordChangesComponent_Conditional_4_Template_mj_label_create_Cancel_2_listener() { i0.ɵɵrestoreView(_r21); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnLabelCreateCancelled()); });
|
|
572
613
|
i0.ɵɵelementEnd()()();
|
|
573
614
|
} if (rf & 2) {
|
|
574
615
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
575
616
|
i0.ɵɵadvance(2);
|
|
576
617
|
i0.ɵɵproperty("PreselectedEntity", ctx_r1.record.EntityInfo)("PreselectedRecordIds", i0.ɵɵpureFunction1(2, _c0, ctx_r1.record.PrimaryKey.KeyValuePairs[0].Value));
|
|
577
618
|
} }
|
|
619
|
+
/**
|
|
620
|
+
* Slide-out timeline of all changes to a single record. Hosts the reusable
|
|
621
|
+
* {@link RestorePreviewPanelComponent} for the actual restore confirmation
|
|
622
|
+
* flow, and exposes a `RestoreRequested` event the host can act on to
|
|
623
|
+
* persist the restore.
|
|
624
|
+
*
|
|
625
|
+
* @example
|
|
626
|
+
* <mj-record-changes
|
|
627
|
+
* [record]="myEntity"
|
|
628
|
+
* [AllowRestore]="true"
|
|
629
|
+
* (dialogClosed)="showHistory = false"
|
|
630
|
+
* (RestoreRequested)="onRestoreRequested($event)">
|
|
631
|
+
* </mj-record-changes>
|
|
632
|
+
*/
|
|
578
633
|
export class RecordChangesComponent {
|
|
579
634
|
cdr;
|
|
580
635
|
ngZone;
|
|
@@ -587,19 +642,20 @@ export class RecordChangesComponent {
|
|
|
587
642
|
/** Whether to show a "Restore" button on each historical version row. Default false. */
|
|
588
643
|
AllowRestore = false;
|
|
589
644
|
/**
|
|
590
|
-
* Emitted when the user
|
|
591
|
-
* The
|
|
645
|
+
* Emitted when the user confirms a restore in the preview panel.
|
|
646
|
+
* The host is responsible for applying the snapshot to the record and
|
|
647
|
+
* saving with `record.SetRestoreContext()` set first.
|
|
592
648
|
*/
|
|
593
649
|
RestoreRequested = new EventEmitter();
|
|
594
650
|
viewData = [];
|
|
595
651
|
filteredData = [];
|
|
596
652
|
dateGroups = [];
|
|
597
653
|
expandedItems = new Set();
|
|
598
|
-
/** The change record
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
|
|
602
|
-
/** Whether the restore
|
|
654
|
+
/** The change record currently selected for restore preview, or null. */
|
|
655
|
+
RestorePreviewChange = null;
|
|
656
|
+
/** Visibility of the embedded restore preview slide-in. */
|
|
657
|
+
RestorePreviewVisible = false;
|
|
658
|
+
/** Whether the restore commit is in progress (between confirmation and host response). */
|
|
603
659
|
IsRestoring = false;
|
|
604
660
|
// Version label state
|
|
605
661
|
RecordLabels = [];
|
|
@@ -607,8 +663,30 @@ export class RecordChangesComponent {
|
|
|
607
663
|
ShowCreateWizard = false;
|
|
608
664
|
// Filter properties
|
|
609
665
|
searchTerm = '';
|
|
666
|
+
/** Single selected type filter (legacy, kept for backwards compat). */
|
|
610
667
|
selectedType = '';
|
|
611
668
|
selectedSource = '';
|
|
669
|
+
/** Map of Key → selected, used by the conditional chip system. */
|
|
670
|
+
ChipSelections = {};
|
|
671
|
+
/** Whether the overflow popover is open. */
|
|
672
|
+
ShowFilterOverflow = false;
|
|
673
|
+
/** Highlighted change ID for the lineage-jump indicator (transient). */
|
|
674
|
+
HighlightedChangeID = null;
|
|
675
|
+
/**
|
|
676
|
+
* Conditional filter pills derived from loaded data. Always includes 'All'
|
|
677
|
+
* implicitly. Other pills only render when at least one matching change
|
|
678
|
+
* exists. Overflows into a popover when the count exceeds 2.
|
|
679
|
+
*/
|
|
680
|
+
ConditionalPills = [];
|
|
681
|
+
/** Threshold above which conditional chips collapse into the overflow popover. */
|
|
682
|
+
OVERFLOW_THRESHOLD = 2;
|
|
683
|
+
/**
|
|
684
|
+
* Subscription to the record's BaseEntity event stream. We listen for
|
|
685
|
+
* 'save' events and auto-refresh the timeline so the user immediately
|
|
686
|
+
* sees the new RecordChange row produced by either a normal save or a
|
|
687
|
+
* restore. Cleaned up in ngOnDestroy.
|
|
688
|
+
*/
|
|
689
|
+
_entitySaveSub = null;
|
|
612
690
|
constructor(cdr, ngZone, mjNotificationService, sanitizer) {
|
|
613
691
|
this.cdr = cdr;
|
|
614
692
|
this.ngZone = ngZone;
|
|
@@ -622,8 +700,30 @@ export class RecordChangesComponent {
|
|
|
622
700
|
this.cdr.markForCheck();
|
|
623
701
|
this.LoadRecordChanges(this.record.PrimaryKey, '', this.record.EntityInfo.Name);
|
|
624
702
|
this.LoadRecordLabels();
|
|
703
|
+
this.subscribeToRecordSaves();
|
|
625
704
|
}
|
|
626
705
|
}
|
|
706
|
+
ngOnDestroy() {
|
|
707
|
+
this._entitySaveSub?.unsubscribe();
|
|
708
|
+
this._entitySaveSub = null;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Wires up an event handler on the live record so the timeline auto-
|
|
712
|
+
* refreshes immediately after any save lands — including the one
|
|
713
|
+
* produced by the restore flow. Without this the user sees their record
|
|
714
|
+
* update in the form but the panel above still shows the pre-restore
|
|
715
|
+
* change list, which is confusing.
|
|
716
|
+
*/
|
|
717
|
+
subscribeToRecordSaves() {
|
|
718
|
+
if (!this.record)
|
|
719
|
+
return;
|
|
720
|
+
this._entitySaveSub?.unsubscribe();
|
|
721
|
+
this._entitySaveSub = this.record.RegisterEventHandler((event) => {
|
|
722
|
+
if (event?.type === 'save') {
|
|
723
|
+
this.ngZone.run(() => this.Refresh());
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
627
727
|
/**
|
|
628
728
|
* Reloads the record changes list from the database.
|
|
629
729
|
* Called by the parent container after a save completes while the drawer is open.
|
|
@@ -648,8 +748,8 @@ export class RecordChangesComponent {
|
|
|
648
748
|
this.ngZone.run(() => {
|
|
649
749
|
if (changes) {
|
|
650
750
|
this.viewData = changes.sort((a, b) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime());
|
|
651
|
-
this.
|
|
652
|
-
this.
|
|
751
|
+
this.rebuildConditionalPills();
|
|
752
|
+
this.applyFilters();
|
|
653
753
|
this.IsLoading = false;
|
|
654
754
|
}
|
|
655
755
|
else {
|
|
@@ -667,16 +767,102 @@ export class RecordChangesComponent {
|
|
|
667
767
|
onFilterChange() {
|
|
668
768
|
this.applyFilters();
|
|
669
769
|
}
|
|
670
|
-
|
|
671
|
-
|
|
770
|
+
/**
|
|
771
|
+
* Toggles the "All" pill — clears every conditional selection.
|
|
772
|
+
*/
|
|
773
|
+
SelectAllPill() {
|
|
774
|
+
for (const k of Object.keys(this.ChipSelections))
|
|
775
|
+
this.ChipSelections[k] = false;
|
|
776
|
+
this.applyFilters();
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Toggles a conditional pill on/off.
|
|
780
|
+
*/
|
|
781
|
+
TogglePill(key) {
|
|
782
|
+
this.ChipSelections[key] = !this.ChipSelections[key];
|
|
672
783
|
this.applyFilters();
|
|
673
784
|
}
|
|
785
|
+
/**
|
|
786
|
+
* Returns true when no conditional pills are selected (i.e. "All" mode).
|
|
787
|
+
*/
|
|
788
|
+
get IsAllSelected() {
|
|
789
|
+
return !Object.values(this.ChipSelections).some(v => v);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Whether any conditional pills are actually visible at all.
|
|
793
|
+
*/
|
|
794
|
+
get HasConditionalPills() {
|
|
795
|
+
return this.ConditionalPills.length > 0;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* True when the conditional chips should collapse into an overflow popover
|
|
799
|
+
* because there are more than the threshold.
|
|
800
|
+
*/
|
|
801
|
+
get UseOverflowPopover() {
|
|
802
|
+
return this.ConditionalPills.length > this.OVERFLOW_THRESHOLD;
|
|
803
|
+
}
|
|
804
|
+
/** Number of currently selected conditional pills (for the popover trigger label). */
|
|
805
|
+
get SelectedConditionalCount() {
|
|
806
|
+
return Object.values(this.ChipSelections).filter(v => v).length;
|
|
807
|
+
}
|
|
808
|
+
ToggleFilterOverflow() {
|
|
809
|
+
this.ShowFilterOverflow = !this.ShowFilterOverflow;
|
|
810
|
+
this.cdr.markForCheck();
|
|
811
|
+
}
|
|
812
|
+
CloseFilterOverflow() {
|
|
813
|
+
this.ShowFilterOverflow = false;
|
|
814
|
+
this.cdr.markForCheck();
|
|
815
|
+
}
|
|
674
816
|
ClearFilters() {
|
|
675
817
|
this.searchTerm = '';
|
|
676
|
-
this.
|
|
677
|
-
|
|
818
|
+
for (const k of Object.keys(this.ChipSelections))
|
|
819
|
+
this.ChipSelections[k] = false;
|
|
678
820
|
this.applyFilters();
|
|
679
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* Builds the list of conditional pills from currently loaded data —
|
|
824
|
+
* a pill only appears for change types/sources that actually exist.
|
|
825
|
+
*/
|
|
826
|
+
rebuildConditionalPills() {
|
|
827
|
+
const counts = {};
|
|
828
|
+
let restoreCount = 0;
|
|
829
|
+
for (const c of this.viewData) {
|
|
830
|
+
const type = c.Type ?? 'Update';
|
|
831
|
+
counts[type] = (counts[type] ?? 0) + 1;
|
|
832
|
+
if (this.isRestoreChange(c))
|
|
833
|
+
restoreCount++;
|
|
834
|
+
}
|
|
835
|
+
const pills = [];
|
|
836
|
+
if ((counts['Update'] ?? 0) > 0) {
|
|
837
|
+
pills.push({ Key: 'Update', Label: 'Updates', Icon: 'fa-pen', Count: counts['Update'], Variant: 'type' });
|
|
838
|
+
}
|
|
839
|
+
if ((counts['Create'] ?? 0) > 0) {
|
|
840
|
+
pills.push({ Key: 'Create', Label: 'Creates', Icon: 'fa-plus', Count: counts['Create'], Variant: 'type' });
|
|
841
|
+
}
|
|
842
|
+
if ((counts['Delete'] ?? 0) > 0) {
|
|
843
|
+
pills.push({ Key: 'Delete', Label: 'Deletes', Icon: 'fa-trash', Count: counts['Delete'], Variant: 'type' });
|
|
844
|
+
}
|
|
845
|
+
if ((counts['Snapshot'] ?? 0) > 0) {
|
|
846
|
+
pills.push({ Key: 'Snapshot', Label: 'Snapshots', Icon: 'fa-camera', Count: counts['Snapshot'], Variant: 'type' });
|
|
847
|
+
}
|
|
848
|
+
if (restoreCount > 0) {
|
|
849
|
+
pills.push({ Key: 'Restore', Label: 'Restored', Icon: 'fa-clock-rotate-left', Count: restoreCount, Variant: 'restore' });
|
|
850
|
+
}
|
|
851
|
+
// Initialize/prune selection state
|
|
852
|
+
const validKeys = new Set(pills.map(p => p.Key));
|
|
853
|
+
for (const k of Object.keys(this.ChipSelections)) {
|
|
854
|
+
if (!validKeys.has(k))
|
|
855
|
+
delete this.ChipSelections[k];
|
|
856
|
+
}
|
|
857
|
+
for (const p of pills) {
|
|
858
|
+
if (this.ChipSelections[p.Key] === undefined)
|
|
859
|
+
this.ChipSelections[p.Key] = false;
|
|
860
|
+
}
|
|
861
|
+
this.ConditionalPills = pills;
|
|
862
|
+
}
|
|
863
|
+
isRestoreChange(c) {
|
|
864
|
+
return c.Source === 'Restore' || c.RestoredFromID != null;
|
|
865
|
+
}
|
|
680
866
|
applyFilters() {
|
|
681
867
|
let filtered = [...this.viewData];
|
|
682
868
|
if (this.searchTerm.trim()) {
|
|
@@ -685,11 +871,22 @@ export class RecordChangesComponent {
|
|
|
685
871
|
change.User?.toLowerCase().includes(search) ||
|
|
686
872
|
change.Comments?.toLowerCase().includes(search));
|
|
687
873
|
}
|
|
688
|
-
if (
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
874
|
+
// Apply conditional pill filters — if any are selected, only show changes matching ANY of them (OR semantics).
|
|
875
|
+
const selectedKeys = Object.keys(this.ChipSelections).filter(k => this.ChipSelections[k]);
|
|
876
|
+
if (selectedKeys.length > 0) {
|
|
877
|
+
filtered = filtered.filter(change => {
|
|
878
|
+
for (const key of selectedKeys) {
|
|
879
|
+
if (key === 'Restore') {
|
|
880
|
+
if (this.isRestoreChange(change))
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
else {
|
|
884
|
+
if (change.Type === key)
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return false;
|
|
889
|
+
});
|
|
693
890
|
}
|
|
694
891
|
this.filteredData = filtered;
|
|
695
892
|
this.dateGroups = this.buildDateGroups(this.filteredData);
|
|
@@ -709,7 +906,7 @@ export class RecordChangesComponent {
|
|
|
709
906
|
EntityName: 'MJ: Version Label Items',
|
|
710
907
|
Fields: ['VersionLabelID'],
|
|
711
908
|
ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,
|
|
712
|
-
ResultType: 'simple'
|
|
909
|
+
ResultType: 'simple',
|
|
713
910
|
});
|
|
714
911
|
if (!itemsResult.Success || itemsResult.Results.length === 0) {
|
|
715
912
|
this.ngZone.run(() => {
|
|
@@ -726,7 +923,7 @@ export class RecordChangesComponent {
|
|
|
726
923
|
Fields: ['ID', 'Name', 'Description', 'Scope', 'Status', 'ItemCount', '__mj_CreatedAt'],
|
|
727
924
|
ExtraFilter: `ID IN (${labelIdFilter})`,
|
|
728
925
|
OrderBy: '__mj_CreatedAt DESC',
|
|
729
|
-
ResultType: 'simple'
|
|
926
|
+
ResultType: 'simple',
|
|
730
927
|
});
|
|
731
928
|
if (labelsResult.Success) {
|
|
732
929
|
this.RecordLabels = labelsResult.Results.map(l => ({
|
|
@@ -736,7 +933,7 @@ export class RecordChangesComponent {
|
|
|
736
933
|
Scope: l.Scope,
|
|
737
934
|
Status: l.Status,
|
|
738
935
|
CreatedAt: l.__mj_CreatedAt,
|
|
739
|
-
ItemCount: l.ItemCount
|
|
936
|
+
ItemCount: l.ItemCount,
|
|
740
937
|
}));
|
|
741
938
|
}
|
|
742
939
|
}
|
|
@@ -790,104 +987,101 @@ export class RecordChangesComponent {
|
|
|
790
987
|
}
|
|
791
988
|
}
|
|
792
989
|
/**
|
|
793
|
-
* Opens the
|
|
794
|
-
*
|
|
990
|
+
* Opens the embedded restore preview panel for a given change record.
|
|
991
|
+
* The panel computes a full-record diff (current vs the change's
|
|
992
|
+
* FullRecordJSON snapshot) — this is the semantic-correctness fix:
|
|
993
|
+
* we restore TO the state at that point in time, not just undo the
|
|
994
|
+
* one delta the user clicked.
|
|
795
995
|
*/
|
|
796
996
|
OnRestoreVersion(change, event) {
|
|
797
|
-
event.stopPropagation();
|
|
798
|
-
this.
|
|
799
|
-
this.
|
|
800
|
-
this.IsRestoring = false;
|
|
801
|
-
this.cdr.markForCheck();
|
|
802
|
-
}
|
|
803
|
-
/** Closes the restore preview panel without applying changes. */
|
|
804
|
-
CancelRestorePreview() {
|
|
805
|
-
this.RestorePreview = null;
|
|
806
|
-
this.RestorePreviewFields = [];
|
|
997
|
+
event.stopPropagation();
|
|
998
|
+
this.RestorePreviewChange = change;
|
|
999
|
+
this.RestorePreviewVisible = true;
|
|
807
1000
|
this.cdr.markForCheck();
|
|
808
1001
|
}
|
|
809
1002
|
/**
|
|
810
|
-
*
|
|
811
|
-
*
|
|
1003
|
+
* Called when the user confirms the restore in the embedded panel.
|
|
1004
|
+
* Translates the panel's RestoreCommitEvent into the broader-shape
|
|
1005
|
+
* RestoreVersionEvent the host is wired to handle.
|
|
812
1006
|
*/
|
|
813
|
-
|
|
814
|
-
if (!this.
|
|
1007
|
+
OnRestorePanelConfirmed(commit) {
|
|
1008
|
+
if (!this.RestorePreviewChange)
|
|
815
1009
|
return;
|
|
816
|
-
const change = this.
|
|
817
|
-
const fieldChanges = this.parseFieldChanges(change);
|
|
1010
|
+
const change = this.RestorePreviewChange;
|
|
818
1011
|
this.IsRestoring = true;
|
|
819
1012
|
this.cdr.markForCheck();
|
|
820
1013
|
this.RestoreRequested.emit({
|
|
821
|
-
|
|
1014
|
+
SourceChangeID: commit.SourceChangeID,
|
|
822
1015
|
ChangedAt: change.ChangedAt,
|
|
823
1016
|
ChangedByUser: change.User || '',
|
|
824
|
-
|
|
1017
|
+
Reason: commit.Reason,
|
|
1018
|
+
FieldValues: commit.FieldValues,
|
|
825
1019
|
});
|
|
826
|
-
//
|
|
827
|
-
// A brief delay allows the parent to process, then we reset.
|
|
1020
|
+
// Close the panel after a brief delay so the host has a moment to react.
|
|
828
1021
|
setTimeout(() => {
|
|
829
|
-
this.
|
|
830
|
-
this.
|
|
1022
|
+
this.RestorePreviewVisible = false;
|
|
1023
|
+
this.RestorePreviewChange = null;
|
|
831
1024
|
this.IsRestoring = false;
|
|
832
1025
|
this.cdr.markForCheck();
|
|
833
1026
|
}, 500);
|
|
834
1027
|
}
|
|
835
1028
|
/**
|
|
836
|
-
*
|
|
1029
|
+
* Called when the user dismisses the restore preview without confirming.
|
|
837
1030
|
*/
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const diffs = [];
|
|
843
|
-
for (const key of Object.keys(changesJson)) {
|
|
844
|
-
const entry = changesJson[key];
|
|
845
|
-
const fieldName = entry.field || key;
|
|
846
|
-
const entityField = this.record.EntityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());
|
|
847
|
-
const isDateField = entityField?.TSType === EntityFieldTSType.Date;
|
|
848
|
-
const versionValue = this.formatChangeValue(entry.oldValue, isDateField);
|
|
849
|
-
const currentValue = this.getCurrentFieldValue(fieldName, isDateField);
|
|
850
|
-
diffs.push({
|
|
851
|
-
FieldName: fieldName,
|
|
852
|
-
DisplayName: entityField?.DisplayNameOrName || fieldName,
|
|
853
|
-
VersionValue: versionValue,
|
|
854
|
-
CurrentValue: currentValue,
|
|
855
|
-
IsChanged: versionValue !== currentValue
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
return diffs;
|
|
859
|
-
}
|
|
860
|
-
/** Gets the current value of a field from the live record, formatted for display. */
|
|
861
|
-
getCurrentFieldValue(fieldName, isDateField) {
|
|
862
|
-
const field = this.record.Fields.find(f => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());
|
|
863
|
-
if (!field)
|
|
864
|
-
return '';
|
|
865
|
-
return this.formatChangeValue(field.Value, isDateField);
|
|
1031
|
+
OnRestorePanelCancelled() {
|
|
1032
|
+
this.RestorePreviewVisible = false;
|
|
1033
|
+
this.RestorePreviewChange = null;
|
|
1034
|
+
this.cdr.markForCheck();
|
|
866
1035
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1036
|
+
// ─── Lineage chip ───────────────────────────────────────────────
|
|
1037
|
+
/**
|
|
1038
|
+
* Returns the source change for a given restored row, if found in the
|
|
1039
|
+
* currently loaded changes. Returns null when the source isn't loaded
|
|
1040
|
+
* (e.g., it's been pruned from history) or when this row isn't a restore.
|
|
1041
|
+
*/
|
|
1042
|
+
getRestoredFromSourceChange(change) {
|
|
1043
|
+
const sourceId = change.RestoredFromID;
|
|
1044
|
+
if (!sourceId)
|
|
873
1045
|
return null;
|
|
874
|
-
|
|
1046
|
+
return this.viewData.find(c => UUIDsEqual(c.ID, sourceId)) ?? null;
|
|
875
1047
|
}
|
|
876
|
-
/**
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
return
|
|
1048
|
+
/**
|
|
1049
|
+
* True when the row was produced by a restore operation (either the
|
|
1050
|
+
* `Source` is `'Restore'` OR `RestoredFromID` is populated).
|
|
1051
|
+
*/
|
|
1052
|
+
isRestoreRow(change) {
|
|
1053
|
+
return this.isRestoreChange(change);
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* True when this change is the most recent in the loaded history.
|
|
1057
|
+
* `viewData` is sorted DESC by `ChangedAt`, so the most recent is index 0.
|
|
1058
|
+
* Restoring to the most recent version is a no-op, so the timeline hides
|
|
1059
|
+
* the Restore button on this row.
|
|
1060
|
+
*/
|
|
1061
|
+
isMostRecentChange(change) {
|
|
1062
|
+
return this.viewData.length > 0 && this.viewData[0] === change;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Click handler for the lineage chip — scrolls/highlights the source
|
|
1066
|
+
* change row in the timeline. Auto-clears after a few seconds.
|
|
1067
|
+
*/
|
|
1068
|
+
JumpToSourceChange(sourceChange, event) {
|
|
1069
|
+
event.stopPropagation();
|
|
1070
|
+
this.HighlightedChangeID = sourceChange.ID;
|
|
1071
|
+
this.expandedItems.add(sourceChange.ID);
|
|
1072
|
+
this.cdr.markForCheck();
|
|
1073
|
+
// Auto-clear the highlight after 3s
|
|
1074
|
+
setTimeout(() => {
|
|
1075
|
+
if (this.HighlightedChangeID && UUIDsEqual(this.HighlightedChangeID, sourceChange.ID)) {
|
|
1076
|
+
this.HighlightedChangeID = null;
|
|
1077
|
+
this.cdr.markForCheck();
|
|
1078
|
+
}
|
|
1079
|
+
}, 3000);
|
|
1080
|
+
// Scroll into view
|
|
1081
|
+
setTimeout(() => {
|
|
1082
|
+
const el = document.querySelector(`[data-change-id="${sourceChange.ID}"]`);
|
|
1083
|
+
el?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
1084
|
+
}, 50);
|
|
891
1085
|
}
|
|
892
1086
|
// ─── Date Grouping ─────────────────────────────────────────────
|
|
893
1087
|
buildDateGroups(changes) {
|
|
@@ -919,6 +1113,7 @@ export class RecordChangesComponent {
|
|
|
919
1113
|
case 'Create': return 'type-create';
|
|
920
1114
|
case 'Update': return 'type-update';
|
|
921
1115
|
case 'Delete': return 'type-delete';
|
|
1116
|
+
case 'Snapshot': return 'type-snapshot';
|
|
922
1117
|
default: return 'type-update';
|
|
923
1118
|
}
|
|
924
1119
|
}
|
|
@@ -926,11 +1121,38 @@ export class RecordChangesComponent {
|
|
|
926
1121
|
switch (type) {
|
|
927
1122
|
case 'Create': return 'Created';
|
|
928
1123
|
case 'Delete': return 'Deleted';
|
|
1124
|
+
case 'Snapshot': return 'Snapshot';
|
|
929
1125
|
default: return type;
|
|
930
1126
|
}
|
|
931
1127
|
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Badge text for the row's primary type tag. For restore rows we override
|
|
1130
|
+
* the underlying `Type='Update'` and show "Restore" instead — matches the
|
|
1131
|
+
* mockup's intent of treating restore as a first-class operation in the
|
|
1132
|
+
* timeline rather than a flavor of update.
|
|
1133
|
+
*/
|
|
1134
|
+
getEffectiveBadgeText(change) {
|
|
1135
|
+
if (this.isRestoreRow(change))
|
|
1136
|
+
return 'Restore';
|
|
1137
|
+
return this.getChangeTypeBadgeText(change.Type);
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Optional restore reason — pulled from the dynamic `RestoreReason`
|
|
1141
|
+
* column added by the lineage migration. Returns null when not present
|
|
1142
|
+
* or not a restore row.
|
|
1143
|
+
*/
|
|
1144
|
+
getRestoreReason(change) {
|
|
1145
|
+
if (!this.isRestoreRow(change))
|
|
1146
|
+
return null;
|
|
1147
|
+
const reason = change.RestoreReason;
|
|
1148
|
+
return reason && reason.trim().length > 0 ? reason : null;
|
|
1149
|
+
}
|
|
932
1150
|
getSourceClass(source) {
|
|
933
|
-
|
|
1151
|
+
if (source === 'Restore')
|
|
1152
|
+
return 'source-restore';
|
|
1153
|
+
if (source === 'Internal')
|
|
1154
|
+
return 'source-internal';
|
|
1155
|
+
return 'source-external';
|
|
934
1156
|
}
|
|
935
1157
|
getStatusClass(status) {
|
|
936
1158
|
switch (status) {
|
|
@@ -946,12 +1168,10 @@ export class RecordChangesComponent {
|
|
|
946
1168
|
getUserInitials(user) {
|
|
947
1169
|
if (!user)
|
|
948
1170
|
return '?';
|
|
949
|
-
// Handle email addresses: take first char of local part + first char of domain
|
|
950
1171
|
if (user.includes('@')) {
|
|
951
1172
|
const local = user.split('@')[0];
|
|
952
1173
|
return local.substring(0, 2).toUpperCase();
|
|
953
1174
|
}
|
|
954
|
-
// Handle names: first char of each word
|
|
955
1175
|
const parts = user.trim().split(/\s+/);
|
|
956
1176
|
if (parts.length >= 2) {
|
|
957
1177
|
return (parts[0][0] + parts[1][0]).toUpperCase();
|
|
@@ -973,7 +1193,7 @@ export class RecordChangesComponent {
|
|
|
973
1193
|
return new Intl.DateTimeFormat('en-US', {
|
|
974
1194
|
hour: 'numeric',
|
|
975
1195
|
minute: '2-digit',
|
|
976
|
-
hour12: true
|
|
1196
|
+
hour12: true,
|
|
977
1197
|
}).format(new Date(date));
|
|
978
1198
|
}
|
|
979
1199
|
formatRelativeTime(date) {
|
|
@@ -993,7 +1213,7 @@ export class RecordChangesComponent {
|
|
|
993
1213
|
return new Intl.DateTimeFormat('en-US', {
|
|
994
1214
|
month: 'short',
|
|
995
1215
|
day: 'numeric',
|
|
996
|
-
year: diffDays > 365 ? 'numeric' : undefined
|
|
1216
|
+
year: diffDays > 365 ? 'numeric' : undefined,
|
|
997
1217
|
}).format(new Date(date));
|
|
998
1218
|
}
|
|
999
1219
|
formatFullDateTime(date) {
|
|
@@ -1004,15 +1224,27 @@ export class RecordChangesComponent {
|
|
|
1004
1224
|
hour: 'numeric',
|
|
1005
1225
|
minute: 'numeric',
|
|
1006
1226
|
hour12: true,
|
|
1007
|
-
timeZoneName: 'short'
|
|
1227
|
+
timeZoneName: 'short',
|
|
1008
1228
|
}).format(new Date(date));
|
|
1009
1229
|
}
|
|
1010
1230
|
// ─── Change Summary ─────────────────────────────────────────────
|
|
1011
1231
|
getChangeSummary(change) {
|
|
1232
|
+
// Restore rows get a distinctive summary so the timeline reads like a
|
|
1233
|
+
// sentence — "Restored to 5:56 PM version" rather than yet another
|
|
1234
|
+
// "Name and Description changed". The lineage chip carries the full
|
|
1235
|
+
// source-version detail.
|
|
1236
|
+
if (this.isRestoreRow(change)) {
|
|
1237
|
+
const src = this.getRestoredFromSourceChange(change);
|
|
1238
|
+
if (src)
|
|
1239
|
+
return `Restored to ${this.formatTime(src.ChangedAt)} version`;
|
|
1240
|
+
return 'Restored from earlier version';
|
|
1241
|
+
}
|
|
1012
1242
|
if (change.Type === 'Create')
|
|
1013
1243
|
return 'Record created';
|
|
1014
1244
|
if (change.Type === 'Delete')
|
|
1015
1245
|
return 'Record deleted';
|
|
1246
|
+
if (change.Type === 'Snapshot')
|
|
1247
|
+
return change.ChangesDescription || 'Snapshot captured';
|
|
1016
1248
|
try {
|
|
1017
1249
|
const changesJson = JSON.parse(change.ChangesJSON || '{}');
|
|
1018
1250
|
const fieldNames = this.extractFieldDisplayNames(changesJson);
|
|
@@ -1029,9 +1261,7 @@ export class RecordChangesComponent {
|
|
|
1029
1261
|
if (!change.FullRecordJSON)
|
|
1030
1262
|
return 0;
|
|
1031
1263
|
const record = JSON.parse(change.FullRecordJSON);
|
|
1032
|
-
return this.record.EntityInfo.Fields
|
|
1033
|
-
.filter((f) => record[f.Name] != null && record[f.Name] !== '')
|
|
1034
|
-
.length;
|
|
1264
|
+
return this.record.EntityInfo.Fields.filter((f) => record[f.Name] != null && record[f.Name] !== '').length;
|
|
1035
1265
|
}
|
|
1036
1266
|
catch {
|
|
1037
1267
|
return 0;
|
|
@@ -1082,7 +1312,7 @@ export class RecordChangesComponent {
|
|
|
1082
1312
|
oldValue: formattedOld,
|
|
1083
1313
|
newValue: formattedNew,
|
|
1084
1314
|
fieldType,
|
|
1085
|
-
diffHtml
|
|
1315
|
+
diffHtml,
|
|
1086
1316
|
};
|
|
1087
1317
|
}
|
|
1088
1318
|
classifyFieldType(field) {
|
|
@@ -1107,7 +1337,7 @@ export class RecordChangesComponent {
|
|
|
1107
1337
|
.map((field) => ({
|
|
1108
1338
|
name: field.Name,
|
|
1109
1339
|
displayName: field.DisplayNameOrName,
|
|
1110
|
-
value: this.formatChangeValue(record[field.Name], field.TSType === EntityFieldTSType.Date)
|
|
1340
|
+
value: this.formatChangeValue(record[field.Name], field.TSType === EntityFieldTSType.Date),
|
|
1111
1341
|
}));
|
|
1112
1342
|
}
|
|
1113
1343
|
catch {
|
|
@@ -1115,10 +1345,6 @@ export class RecordChangesComponent {
|
|
|
1115
1345
|
}
|
|
1116
1346
|
}
|
|
1117
1347
|
// ─── Value Formatting ───────────────────────────────────────────
|
|
1118
|
-
/**
|
|
1119
|
-
* Formats a change value for display. Handles corrupted date values (stored as empty objects)
|
|
1120
|
-
* and formats ISO date strings into a human-readable format.
|
|
1121
|
-
*/
|
|
1122
1348
|
formatChangeValue(value, isDateField) {
|
|
1123
1349
|
if (value == null)
|
|
1124
1350
|
return '';
|
|
@@ -1137,7 +1363,7 @@ export class RecordChangesComponent {
|
|
|
1137
1363
|
year: 'numeric',
|
|
1138
1364
|
hour: 'numeric',
|
|
1139
1365
|
minute: '2-digit',
|
|
1140
|
-
hour12: true
|
|
1366
|
+
hour12: true,
|
|
1141
1367
|
}).format(date);
|
|
1142
1368
|
}
|
|
1143
1369
|
}
|
|
@@ -1156,21 +1382,22 @@ export class RecordChangesComponent {
|
|
|
1156
1382
|
}
|
|
1157
1383
|
const useWordDiff = this.shouldUseWordDiff(oldValue, newValue);
|
|
1158
1384
|
const diffs = useWordDiff ? diffWords(oldValue, newValue) : diffChars(oldValue, newValue);
|
|
1159
|
-
const html = diffs
|
|
1385
|
+
const html = diffs
|
|
1386
|
+
.map((part) => {
|
|
1160
1387
|
const escaped = this.escapeHtml(part.value);
|
|
1161
1388
|
if (part.added)
|
|
1162
1389
|
return `<span class="rc-diff-added">${escaped}</span>`;
|
|
1163
1390
|
if (part.removed)
|
|
1164
1391
|
return `<span class="rc-diff-removed">${escaped}</span>`;
|
|
1165
1392
|
return `<span class="rc-diff-unchanged">${escaped}</span>`;
|
|
1166
|
-
})
|
|
1393
|
+
})
|
|
1394
|
+
.join('');
|
|
1167
1395
|
return this.sanitizer.bypassSecurityTrustHtml(html);
|
|
1168
1396
|
}
|
|
1169
1397
|
shouldUseWordDiff(oldValue, newValue) {
|
|
1170
1398
|
const hasMultipleWords = (text) => text.includes(' ') && text.split(' ').length > 3;
|
|
1171
1399
|
const isLongText = (text) => text.length > 50;
|
|
1172
|
-
return (hasMultipleWords(oldValue) || hasMultipleWords(newValue)) &&
|
|
1173
|
-
(isLongText(oldValue) || isLongText(newValue));
|
|
1400
|
+
return (hasMultipleWords(oldValue) || hasMultipleWords(newValue)) && (isLongText(oldValue) || isLongText(newValue));
|
|
1174
1401
|
}
|
|
1175
1402
|
escapeHtml(text) {
|
|
1176
1403
|
const div = document.createElement('div');
|
|
@@ -1178,12 +1405,14 @@ export class RecordChangesComponent {
|
|
|
1178
1405
|
return div.innerHTML;
|
|
1179
1406
|
}
|
|
1180
1407
|
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)); };
|
|
1181
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordChangesComponent, selectors: [["mj-record-changes"]], inputs: { record: "record", AllowRestore: "AllowRestore" }, outputs: { dialogClosed: "dialogClosed", RestoreRequested: "RestoreRequested" }, standalone: false, decls: 5, vars:
|
|
1408
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordChangesComponent, selectors: [["mj-record-changes"]], inputs: { record: "record", AllowRestore: "AllowRestore" }, outputs: { dialogClosed: "dialogClosed", RestoreRequested: "RestoreRequested" }, standalone: false, decls: 5, vars: 13, consts: [[3, "Closed", "Mode", "Title", "Visible", "Resizable", "MinWidthPx", "MaxWidthRatio"], ["text", "Loading history...", "size", "medium"], [1, "rc-container"], [3, "RestoreConfirmed", "RestoreCancelled", "Visible", "Mode", "RecordChange", "LiveRecord"], [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"], ["type", "button", 1, "rc-filter-pill", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], [1, "rc-filter-results"], [1, "rc-timeline"], [1, "rc-no-results"], [1, "rc-filter-overflow-wrap"], ["type", "button", 1, "rc-filter-pill", 3, "active", "rc-filter-pill-restore"], ["aria-hidden", "true"], [1, "rc-filter-pill-count"], ["type", "button", 1, "rc-filter-pill", "rc-filter-pill-overflow", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-sliders"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "rc-filter-overflow-caret"], [1, "rc-filter-overflow-backdrop", 3, "click"], ["role", "menu", 1, "rc-filter-overflow-popover"], [1, "rc-filter-overflow-header"], [1, "rc-filter-overflow-row", 3, "rc-filter-overflow-row-restore"], [1, "rc-filter-overflow-actions"], ["type", "button", 1, "rc-filter-overflow-clear", 3, "click"], ["type", "button", 1, "rc-filter-overflow-done", 3, "click"], [1, "rc-filter-overflow-row"], ["type", "checkbox", 3, "change", "checked"], [1, "rc-filter-overflow-label"], [1, "rc-filter-overflow-count"], [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", "rc-card-restore", "rc-card-highlight"], [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-restored-chip", 3, "title"], ["title", "Source version was not loaded into this view", 1, "rc-restored-chip", "rc-restored-chip-orphan"], [1, "rc-restored-chip", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-link"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], [1, "rc-restore-reason"], [1, "rc-deletion-note"], [1, "rc-comments"], [1, "rc-errors"], [1, "rc-restore-action"], [1, "rc-restore-reason-label"], [1, "rc-restore-reason-text"], [1, "rc-field-row"], [1, "rc-field-label"], [1, "rc-field-values"], [1, "rc-val-new"], ["aria-hidden", "true", 1, "fa-solid", "fa-trash"], [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"], ["title", "Restore the entire record to its state at this version", 1, "rc-restore-btn", 3, "click"], [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) {
|
|
1182
1409
|
i0.ɵɵelementStart(0, "mj-slide-panel", 0);
|
|
1183
1410
|
i0.ɵɵlistener("Closed", function RecordChangesComponent_Template_mj_slide_panel_Closed_0_listener() { return ctx.OnClose(); });
|
|
1184
1411
|
i0.ɵɵconditionalCreate(1, RecordChangesComponent_Conditional_1_Template, 1, 0, "mj-loading", 1);
|
|
1185
1412
|
i0.ɵɵconditionalCreate(2, RecordChangesComponent_Conditional_2_Template, 16, 3, "div", 2);
|
|
1186
|
-
i0.ɵɵ
|
|
1413
|
+
i0.ɵɵelementStart(3, "mj-restore-preview-panel", 3);
|
|
1414
|
+
i0.ɵɵlistener("RestoreConfirmed", function RecordChangesComponent_Template_mj_restore_preview_panel_RestoreConfirmed_3_listener($event) { return ctx.OnRestorePanelConfirmed($event); })("RestoreCancelled", function RecordChangesComponent_Template_mj_restore_preview_panel_RestoreCancelled_3_listener() { return ctx.OnRestorePanelCancelled(); });
|
|
1415
|
+
i0.ɵɵelementEnd();
|
|
1187
1416
|
i0.ɵɵconditionalCreate(4, RecordChangesComponent_Conditional_4_Template, 3, 4, "div", 4);
|
|
1188
1417
|
i0.ɵɵelementEnd();
|
|
1189
1418
|
} if (rf & 2) {
|
|
@@ -1193,14 +1422,14 @@ export class RecordChangesComponent {
|
|
|
1193
1422
|
i0.ɵɵadvance();
|
|
1194
1423
|
i0.ɵɵconditional(!ctx.IsLoading ? 2 : -1);
|
|
1195
1424
|
i0.ɵɵadvance();
|
|
1196
|
-
i0.ɵɵ
|
|
1425
|
+
i0.ɵɵproperty("Visible", ctx.RestorePreviewVisible)("Mode", "live")("RecordChange", ctx.RestorePreviewChange)("LiveRecord", ctx.record);
|
|
1197
1426
|
i0.ɵɵadvance();
|
|
1198
1427
|
i0.ɵɵconditional(ctx.ShowCreateWizard ? 4 : -1);
|
|
1199
|
-
} }, 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: var(--mj-bg-surface-card);\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: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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 var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); 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: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\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: var(--mj-bg-surface-sunken);\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: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\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: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\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: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-brand-primary);\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: var(--mj-brand-primary-hover); }\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: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\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: var(--mj-border-default);\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: var(--mj-text-disabled);\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: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\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: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\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: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\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: var(--mj-text-disabled);\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: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\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 var(--mj-border-default);\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: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\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: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\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: var(--mj-text-primary);\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: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\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: var(--mj-bg-overlay);\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: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\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 var(--mj-border-default);\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\n/* \u2500\u2500\u2500 Restore Action \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\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-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n"], encapsulation: 2, changeDetection: 0 });
|
|
1428
|
+
} }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent, i5.MjSlidePanelComponent, i5.MjLabelCreateComponent, i6.RestorePreviewPanelComponent, i7.DatePipe], 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: var(--mj-bg-surface-card);\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: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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 var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); 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: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\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: var(--mj-bg-surface-sunken);\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: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\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: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\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: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-brand-primary);\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: var(--mj-brand-primary-hover); }\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: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\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: var(--mj-border-default);\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: var(--mj-text-disabled);\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: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\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: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\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: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\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 /* Allow the lineage chip to wrap to a second line on narrow panel widths\n instead of squeezing the title text into a \"Name and Description c...\"\n truncation. The badge stays on the first line; chip wraps gracefully. */\n flex-wrap: wrap;\n row-gap: 6px;\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\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: var(--mj-text-disabled);\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: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\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 var(--mj-border-default);\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: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\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: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\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: var(--mj-text-primary);\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: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\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: var(--mj-bg-overlay);\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: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\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 var(--mj-border-default);\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\n/* \u2500\u2500\u2500 Restore Action \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n /* Breathing room from the card's bottom and right edges so the button\n doesn't sit flush against the border. */\n padding-right: 10px;\n padding-bottom: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\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-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Restore lineage + conditional filter chips + overflow popover\n * (added with the Restore Prior Version feature)\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\n/* \u2500\u2500\u2500 Filter pill enhancements \u2500\u2500\u2500 */\n\n.rc-filter-pill-count {\n margin-left: 4px;\n background: color-mix(in srgb, currentColor 12%, transparent);\n padding: 1px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-filter-pill.active .rc-filter-pill-count {\n background: color-mix(in srgb, var(--mj-text-inverse, #fff) 22%, transparent);\n}\n\n/* Restore-variant pill: violet treatment to set it apart from type pills */\n.rc-filter-pill-restore {\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border-color: color-mix(in srgb, var(--mj-status-info) 30%, var(--mj-border-default));\n}\n.rc-filter-pill-restore:hover {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n.rc-filter-pill-restore.active {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Overflow filter popover \u2500\u2500\u2500 */\n\n.rc-filter-overflow-wrap {\n position: relative;\n display: inline-block;\n}\n\n.rc-filter-pill-overflow {\n /* Overflow trigger inherits the standard filter pill look */\n}\n\n.rc-filter-overflow-caret {\n font-size: 9px;\n margin-left: 2px;\n}\n\n.rc-filter-overflow-backdrop {\n position: fixed;\n inset: 0;\n z-index: 10;\n}\n\n.rc-filter-overflow-popover {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 11;\n min-width: 240px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 14px 40px rgba(15, 23, 42, 0.18);\n padding: 8px;\n}\n\n.rc-filter-overflow-header {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n padding: 6px 8px 8px;\n}\n\n.rc-filter-overflow-row {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 7px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.rc-filter-overflow-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-filter-overflow-row input[type=\"checkbox\"] {\n margin: 0;\n accent-color: var(--mj-brand-primary);\n}\n\n.rc-filter-overflow-row i {\n color: var(--mj-text-muted);\n font-size: 12px;\n width: 14px;\n text-align: center;\n}\n\n.rc-filter-overflow-row-restore i {\n color: var(--mj-status-info);\n}\n\n.rc-filter-overflow-label {\n flex: 1;\n}\n\n.rc-filter-overflow-count {\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.rc-filter-overflow-actions {\n display: flex;\n justify-content: space-between;\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: 8px;\n margin-top: 6px;\n}\n\n.rc-filter-overflow-clear,\n.rc-filter-overflow-done {\n background: none;\n border: none;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 4px 10px;\n border-radius: 5px;\n}\n\n.rc-filter-overflow-clear {\n color: var(--mj-text-muted);\n}\n.rc-filter-overflow-clear:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rc-filter-overflow-done {\n color: var(--mj-brand-primary);\n}\n.rc-filter-overflow-done:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n/* \u2500\u2500\u2500 Snapshot type badge + card accent \u2500\u2500\u2500 */\n\n.type-snapshot .rc-card-type-badge {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Restore Source pill (in card meta) \u2500\u2500\u2500 */\n\n.source-restore {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Restore card variant: violet left accent \u2500\u2500\u2500 */\n\n.rc-card.rc-card-restore {\n border-left: 3px solid var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Lineage chip \u2500\u2500\u2500 */\n\n/* Lineage chip \u2014 outline-only \"interactive link\" treatment so it reads as\n distinct from the filled RESTORE badge sitting next to it. The badge says\n \"this row IS a restore\" (filled, static); the chip says \"click here to\n see the source version\" (outline, hoverable). */\n.rc-restored-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n margin-left: 8px;\n padding: 2px 9px;\n border-radius: 11px;\n font-size: 11px;\n font-weight: 500;\n background: transparent;\n color: color-mix(in srgb, var(--mj-status-info) 90%, var(--mj-text-primary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 40%, var(--mj-border-default));\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n transition: background-color 0.12s, border-color 0.12s, color 0.12s;\n}\n\n.rc-restored-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 12%, transparent);\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.rc-restored-chip i {\n font-size: 10px;\n}\n\n.rc-restored-chip-orphan {\n cursor: default;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n border-color: var(--mj-border-default);\n}\n\n.rc-restored-chip-orphan:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Card highlight (when jumped-to via lineage chip) \u2500\u2500\u2500 */\n\n.rc-card.rc-card-highlight {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n animation: rc-card-pulse 1.4s ease-in-out;\n}\n\n@keyframes rc-card-pulse {\n 0%, 100% { background: var(--mj-bg-surface); }\n 50% { background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)); }\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Restore-row badge override + Restore Reason block\n * (mockup-aligned treatment for restore rows in the timeline)\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\n/* The base type-update badge styling would otherwise paint a restore row's\n badge blue with \"Update\" text. Override to violet + \"Restore\" text so it\n matches the source pill, lineage chip, and card border. */\n.rc-card-type-badge.rc-card-type-badge-restore {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* Restore reason \u2014 minimal blockquote treatment.\n A thin violet left bar + italic text reads like a margin note rather than\n a heavy callout. Visually connected to the restore family (left bar uses\n the same violet as the badge / source pill / card border) without\n competing with the field-diff rows that follow. */\n.rc-restore-reason {\n /* Indented in from the card body edge so it visually nests one level\n deeper than the field-diff rows that follow, and given generous\n vertical breathing room so it doesn't crowd the lineage chip above\n or the first field row below. */\n margin: 14px 8px 18px 18px;\n padding: 0 0 0 12px;\n border-left: 2px solid color-mix(in srgb, var(--mj-status-info) 55%, var(--mj-border-default));\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-size: 13px;\n line-height: 1.5;\n}\n\n.rc-restore-reason-label {\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--mj-status-info) 75%, var(--mj-text-muted));\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.rc-restore-reason-text {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n"], encapsulation: 2, changeDetection: 0 });
|
|
1200
1429
|
}
|
|
1201
1430
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesComponent, [{
|
|
1202
1431
|
type: Component,
|
|
1203
|
-
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\n @if (AllowRestore && change.Type === 'Update') {\n <div class=\"rc-restore-action\">\n <button class=\"rc-restore-btn\"\n (click)=\"OnRestoreVersion(change, $event)\"\n title=\"Restore field values from before this change\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restore Previous Values\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\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\n RESTORE PREVIEW PANEL (inline diff before applying)\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 -->\n @if (RestorePreview) {\n <div class=\"rc-restore-preview-backdrop\" (click)=\"CancelRestorePreview()\">\n <div class=\"rc-restore-preview-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"rc-restore-preview-header\">\n <div class=\"rc-restore-preview-title\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restore Preview\n </div>\n <button class=\"rc-restore-preview-close\" (click)=\"CancelRestorePreview()\" title=\"Close preview\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <div class=\"rc-restore-preview-meta\">\n <span><strong>Version:</strong> {{ formatFullDateTime(RestorePreview.ChangedAt) }}</span>\n <span><strong>By:</strong> {{ getUserDisplayName(RestorePreview.User) }}</span>\n </div>\n\n @if (RestorePreviewFields.length === 0) {\n <div class=\"rc-restore-preview-empty\">\n <i class=\"fa-solid fa-circle-info\" aria-hidden=\"true\"></i>\n No field changes could be parsed from this version.\n </div>\n } @else {\n <table class=\"rc-restore-preview-table\">\n <thead>\n <tr>\n <th>Field</th>\n <th>Current Value</th>\n <th>Restore To</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (diff of RestorePreviewFields; track diff.FieldName) {\n <tr [class.rc-diff-changed]=\"diff.IsChanged\" [class.rc-diff-unchanged]=\"!diff.IsChanged\">\n <td class=\"rc-restore-field-name\">{{ diff.DisplayName }}</td>\n <td class=\"rc-restore-current\">{{ diff.CurrentValue || '(empty)' }}</td>\n <td class=\"rc-restore-version\">{{ diff.VersionValue || '(empty)' }}</td>\n <td class=\"rc-restore-indicator\">\n @if (diff.IsChanged) {\n <i class=\"fa-solid fa-circle-exclamation\" title=\"Will be changed\"></i>\n } @else {\n <i class=\"fa-solid fa-check\" title=\"Already matches\"></i>\n }\n </td>\n </tr>\n }\n </tbody>\n </table>\n }\n\n <div class=\"rc-restore-preview-actions\">\n <button class=\"rc-restore-confirm-btn\"\n [disabled]=\"IsRestoring || RestorePreviewFields.length === 0\"\n (click)=\"ConfirmRestore()\">\n @if (IsRestoring) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Restoring...\n } @else {\n <i class=\"fa-solid fa-rotate-left\" aria-hidden=\"true\"></i>\n Apply Restore\n }\n </button>\n <button class=\"rc-restore-cancel-btn\" (click)=\"CancelRestorePreview()\" [disabled]=\"IsRestoring\">\n Cancel\n </button>\n </div>\n </div>\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: var(--mj-bg-surface-card);\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: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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 var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); 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: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\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: var(--mj-bg-surface-sunken);\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: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\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: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\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: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-brand-primary);\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: var(--mj-brand-primary-hover); }\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: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\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: var(--mj-border-default);\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: var(--mj-text-disabled);\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: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\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: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\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: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\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: var(--mj-text-disabled);\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: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\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 var(--mj-border-default);\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: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\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: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\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: var(--mj-text-primary);\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: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\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: var(--mj-bg-overlay);\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: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\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 var(--mj-border-default);\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\n/* \u2500\u2500\u2500 Restore Action \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\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-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n"] }]
|
|
1432
|
+
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 \u2014 chips render only for change types/sources actually present in loaded data.\n When more than 2 conditional chips would render, they collapse into a \"More filters\" popover. -->\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\n <button class=\"rc-filter-pill\" [class.active]=\"IsAllSelected\" (click)=\"SelectAllPill()\" type=\"button\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i> All\n </button>\n\n @if (HasConditionalPills) {\n @if (!UseOverflowPopover) {\n <!-- 1-2 conditional pills: render inline -->\n @for (pill of ConditionalPills; track pill.Key) {\n <button class=\"rc-filter-pill\"\n [class.active]=\"ChipSelections[pill.Key]\"\n [class.rc-filter-pill-restore]=\"pill.Variant === 'restore'\"\n (click)=\"TogglePill(pill.Key)\"\n type=\"button\">\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n {{ pill.Label }}\n <span class=\"rc-filter-pill-count\">{{ pill.Count }}</span>\n </button>\n }\n } @else {\n <!-- 3+ conditional pills: overflow popover -->\n <div class=\"rc-filter-overflow-wrap\">\n <button class=\"rc-filter-pill rc-filter-pill-overflow\"\n [class.active]=\"SelectedConditionalCount > 0\"\n (click)=\"ToggleFilterOverflow()\"\n type=\"button\">\n <i class=\"fa-solid fa-sliders\" aria-hidden=\"true\"></i>\n More filters\n @if (SelectedConditionalCount > 0) {\n <span class=\"rc-filter-pill-count\">{{ SelectedConditionalCount }}</span>\n }\n <i class=\"fa-solid fa-chevron-down rc-filter-overflow-caret\" aria-hidden=\"true\"></i>\n </button>\n\n @if (ShowFilterOverflow) {\n <!-- Backdrop: clicks close the popover -->\n <div class=\"rc-filter-overflow-backdrop\" (click)=\"CloseFilterOverflow()\"></div>\n <div class=\"rc-filter-overflow-popover\" role=\"menu\">\n <div class=\"rc-filter-overflow-header\">Filter by</div>\n @for (pill of ConditionalPills; track pill.Key) {\n <label class=\"rc-filter-overflow-row\" [class.rc-filter-overflow-row-restore]=\"pill.Variant === 'restore'\">\n <input type=\"checkbox\"\n [checked]=\"ChipSelections[pill.Key]\"\n (change)=\"TogglePill(pill.Key)\" />\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n <span class=\"rc-filter-overflow-label\">{{ pill.Label }}</span>\n <span class=\"rc-filter-overflow-count\">{{ pill.Count }}</span>\n </label>\n }\n <div class=\"rc-filter-overflow-actions\">\n <button class=\"rc-filter-overflow-clear\" (click)=\"SelectAllPill(); CloseFilterOverflow()\" type=\"button\">\n Clear all\n </button>\n <button class=\"rc-filter-overflow-done\" (click)=\"CloseFilterOverflow()\" type=\"button\">\n Done\n </button>\n </div>\n </div>\n }\n </div>\n }\n }\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 [attr.data-change-id]=\"change.ID\"\n [class]=\"getChangeTypeCardClass(change.Type)\"\n [class.expanded]=\"expandedItems.has(change.ID)\"\n [class.rc-card-restore]=\"isRestoreRow(change)\"\n [class.rc-card-highlight]=\"HighlightedChangeID === 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\"\n [class.rc-card-type-badge-restore]=\"isRestoreRow(change)\">{{ getEffectiveBadgeText(change) }}</span>\n <span class=\"rc-card-summary\">{{ getChangeSummary(change) }}</span>\n\n <!-- Lineage chip \u2014 visible when this row was produced by a restore -->\n @if (isRestoreRow(change)) {\n @if (getRestoredFromSourceChange(change); as srcChange) {\n <a class=\"rc-restored-chip\"\n (click)=\"JumpToSourceChange(srcChange, $event)\"\n [title]=\"'Jump to source version (' + formatFullDateTime(srcChange.ChangedAt) + ')'\">\n <i class=\"fa-solid fa-link\" aria-hidden=\"true\"></i>\n Restored from {{ formatTime(srcChange.ChangedAt) }} {{ srcChange.ChangedAt ? 'on ' + (srcChange.ChangedAt | date:'mediumDate') : '' }}\n @if (srcChange.User) {\n by {{ getUserDisplayName(srcChange.User) }}\n }\n </a>\n } @else {\n <span class=\"rc-restored-chip rc-restored-chip-orphan\"\n title=\"Source version was not loaded into this view\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restored from earlier version\n </span>\n }\n }\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 <!-- Restore reason (when present) \u2014 Notion/Linear-style\n blockquote: a thin violet left bar + italic text,\n with a tiny \"Reason\" prefix. No box, no header,\n no large vertical footprint. Reads as a\n justification note rather than a callout. -->\n @if (getRestoreReason(change); as reason) {\n <blockquote class=\"rc-restore-reason\">\n <span class=\"rc-restore-reason-label\">Reason</span>\n <span class=\"rc-restore-reason-text\">{{ reason }}</span>\n </blockquote>\n }\n\n @if (change.Type === 'Create') {\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 / Snapshot / Restore: 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 <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 <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 <div class=\"rc-text-diff\" [innerHTML]=\"fc.diffHtml\"></div>\n } @else {\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\n <!-- Restore action: shown for Update, Create, and Snapshot rows.\n Hidden on Delete rows (handled via the Recycle Bin path)\n and on the most recent change (restoring to current state is a no-op). -->\n @if (AllowRestore && change.Type !== 'Delete' && !isMostRecentChange(change)) {\n <div class=\"rc-restore-action\">\n <button class=\"rc-restore-btn\"\n (click)=\"OnRestoreVersion(change, $event)\"\n title=\"Restore the entire record to its state at this version\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restore record to this version\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\n <!-- Restore preview slide-in (reusable component) -->\n <mj-restore-preview-panel\n [Visible]=\"RestorePreviewVisible\"\n [Mode]=\"'live'\"\n [RecordChange]=\"RestorePreviewChange\"\n [LiveRecord]=\"record\"\n (RestoreConfirmed)=\"OnRestorePanelConfirmed($event)\"\n (RestoreCancelled)=\"OnRestorePanelCancelled()\">\n </mj-restore-preview-panel>\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: var(--mj-bg-surface-card);\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: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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 var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\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: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); 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: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\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: var(--mj-bg-surface-sunken);\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: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\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: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\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: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\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 var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\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: var(--mj-brand-primary);\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: var(--mj-brand-primary-hover); }\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: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\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: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\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: var(--mj-border-default);\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: var(--mj-text-disabled);\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: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\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: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\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: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\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 /* Allow the lineage chip to wrap to a second line on narrow panel widths\n instead of squeezing the title text into a \"Name and Description c...\"\n truncation. The badge stays on the first line; chip wraps gracefully. */\n flex-wrap: wrap;\n row-gap: 6px;\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\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: var(--mj-text-disabled);\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: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\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 var(--mj-border-default);\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 var(--mj-border-default);\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: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\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: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\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: var(--mj-text-primary);\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: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\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: var(--mj-bg-overlay);\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: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\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 var(--mj-border-default);\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\n/* \u2500\u2500\u2500 Restore Action \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n /* Breathing room from the card's bottom and right edges so the button\n doesn't sit flush against the border. */\n padding-right: 10px;\n padding-bottom: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\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-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Restore lineage + conditional filter chips + overflow popover\n * (added with the Restore Prior Version feature)\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\n/* \u2500\u2500\u2500 Filter pill enhancements \u2500\u2500\u2500 */\n\n.rc-filter-pill-count {\n margin-left: 4px;\n background: color-mix(in srgb, currentColor 12%, transparent);\n padding: 1px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-filter-pill.active .rc-filter-pill-count {\n background: color-mix(in srgb, var(--mj-text-inverse, #fff) 22%, transparent);\n}\n\n/* Restore-variant pill: violet treatment to set it apart from type pills */\n.rc-filter-pill-restore {\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border-color: color-mix(in srgb, var(--mj-status-info) 30%, var(--mj-border-default));\n}\n.rc-filter-pill-restore:hover {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n.rc-filter-pill-restore.active {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Overflow filter popover \u2500\u2500\u2500 */\n\n.rc-filter-overflow-wrap {\n position: relative;\n display: inline-block;\n}\n\n.rc-filter-pill-overflow {\n /* Overflow trigger inherits the standard filter pill look */\n}\n\n.rc-filter-overflow-caret {\n font-size: 9px;\n margin-left: 2px;\n}\n\n.rc-filter-overflow-backdrop {\n position: fixed;\n inset: 0;\n z-index: 10;\n}\n\n.rc-filter-overflow-popover {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 11;\n min-width: 240px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 14px 40px rgba(15, 23, 42, 0.18);\n padding: 8px;\n}\n\n.rc-filter-overflow-header {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n padding: 6px 8px 8px;\n}\n\n.rc-filter-overflow-row {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 7px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.rc-filter-overflow-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-filter-overflow-row input[type=\"checkbox\"] {\n margin: 0;\n accent-color: var(--mj-brand-primary);\n}\n\n.rc-filter-overflow-row i {\n color: var(--mj-text-muted);\n font-size: 12px;\n width: 14px;\n text-align: center;\n}\n\n.rc-filter-overflow-row-restore i {\n color: var(--mj-status-info);\n}\n\n.rc-filter-overflow-label {\n flex: 1;\n}\n\n.rc-filter-overflow-count {\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.rc-filter-overflow-actions {\n display: flex;\n justify-content: space-between;\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: 8px;\n margin-top: 6px;\n}\n\n.rc-filter-overflow-clear,\n.rc-filter-overflow-done {\n background: none;\n border: none;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 4px 10px;\n border-radius: 5px;\n}\n\n.rc-filter-overflow-clear {\n color: var(--mj-text-muted);\n}\n.rc-filter-overflow-clear:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rc-filter-overflow-done {\n color: var(--mj-brand-primary);\n}\n.rc-filter-overflow-done:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n/* \u2500\u2500\u2500 Snapshot type badge + card accent \u2500\u2500\u2500 */\n\n.type-snapshot .rc-card-type-badge {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Restore Source pill (in card meta) \u2500\u2500\u2500 */\n\n.source-restore {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Restore card variant: violet left accent \u2500\u2500\u2500 */\n\n.rc-card.rc-card-restore {\n border-left: 3px solid var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Lineage chip \u2500\u2500\u2500 */\n\n/* Lineage chip \u2014 outline-only \"interactive link\" treatment so it reads as\n distinct from the filled RESTORE badge sitting next to it. The badge says\n \"this row IS a restore\" (filled, static); the chip says \"click here to\n see the source version\" (outline, hoverable). */\n.rc-restored-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n margin-left: 8px;\n padding: 2px 9px;\n border-radius: 11px;\n font-size: 11px;\n font-weight: 500;\n background: transparent;\n color: color-mix(in srgb, var(--mj-status-info) 90%, var(--mj-text-primary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 40%, var(--mj-border-default));\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n transition: background-color 0.12s, border-color 0.12s, color 0.12s;\n}\n\n.rc-restored-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 12%, transparent);\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.rc-restored-chip i {\n font-size: 10px;\n}\n\n.rc-restored-chip-orphan {\n cursor: default;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n border-color: var(--mj-border-default);\n}\n\n.rc-restored-chip-orphan:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Card highlight (when jumped-to via lineage chip) \u2500\u2500\u2500 */\n\n.rc-card.rc-card-highlight {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n animation: rc-card-pulse 1.4s ease-in-out;\n}\n\n@keyframes rc-card-pulse {\n 0%, 100% { background: var(--mj-bg-surface); }\n 50% { background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)); }\n}\n\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Restore-row badge override + Restore Reason block\n * (mockup-aligned treatment for restore rows in the timeline)\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\n/* The base type-update badge styling would otherwise paint a restore row's\n badge blue with \"Update\" text. Override to violet + \"Restore\" text so it\n matches the source pill, lineage chip, and card border. */\n.rc-card-type-badge.rc-card-type-badge-restore {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* Restore reason \u2014 minimal blockquote treatment.\n A thin violet left bar + italic text reads like a margin note rather than\n a heavy callout. Visually connected to the restore family (left bar uses\n the same violet as the badge / source pill / card border) without\n competing with the field-diff rows that follow. */\n.rc-restore-reason {\n /* Indented in from the card body edge so it visually nests one level\n deeper than the field-diff rows that follow, and given generous\n vertical breathing room so it doesn't crowd the lineage chip above\n or the first field row below. */\n margin: 14px 8px 18px 18px;\n padding: 0 0 0 12px;\n border-left: 2px solid color-mix(in srgb, var(--mj-status-info) 55%, var(--mj-border-default));\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-size: 13px;\n line-height: 1.5;\n}\n\n.rc-restore-reason-label {\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--mj-status-info) 75%, var(--mj-text-muted));\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.rc-restore-reason-text {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n"] }]
|
|
1204
1433
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1.MJNotificationService }, { type: i2.DomSanitizer }], { dialogClosed: [{
|
|
1205
1434
|
type: Output
|
|
1206
1435
|
}], record: [{
|
|
@@ -1210,5 +1439,5 @@ export class RecordChangesComponent {
|
|
|
1210
1439
|
}], RestoreRequested: [{
|
|
1211
1440
|
type: Output
|
|
1212
1441
|
}] }); })();
|
|
1213
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber:
|
|
1442
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecordChangesComponent, { className: "RecordChangesComponent", filePath: "src/lib/ng-record-changes.component.ts", lineNumber: 120 }); })();
|
|
1214
1443
|
//# sourceMappingURL=ng-record-changes.component.js.map
|