@memberjunction/ng-record-changes 5.23.0 → 5.24.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=restore-version.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore-version.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/restore-version.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Tests for restore version logic extracted from RecordChangesComponent.
3
+ *
4
+ * We test pure logic functions directly to avoid Angular TestBed complexity.
5
+ * These mirror the component's parseFieldChanges, buildRestorePreviewFields, etc.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ // ── Extracted pure logic mirrors from RecordChangesComponent ──
9
+ /** Mirrors RecordChangesComponent.parseFieldChanges */
10
+ function parseFieldChanges(changesJSON) {
11
+ const fieldChanges = {};
12
+ try {
13
+ const changesJson = JSON.parse(changesJSON || '{}');
14
+ for (const key of Object.keys(changesJson)) {
15
+ const entry = changesJson[key];
16
+ const fieldName = entry.field || key;
17
+ fieldChanges[fieldName] = {
18
+ OldValue: entry.oldValue,
19
+ NewValue: entry.newValue,
20
+ };
21
+ }
22
+ }
23
+ catch {
24
+ // Return empty on parse failure
25
+ }
26
+ return fieldChanges;
27
+ }
28
+ /** Mirrors RecordChangesComponent.buildRestorePreviewFields (simplified without EntityInfo) */
29
+ function buildRestorePreviewFields(changesJSON, currentValues) {
30
+ let changesJson;
31
+ try {
32
+ changesJson = JSON.parse(changesJSON || '{}');
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ const diffs = [];
38
+ for (const key of Object.keys(changesJson)) {
39
+ const entry = changesJson[key];
40
+ const fieldName = entry.field || key;
41
+ const versionValue = String(entry.oldValue ?? '');
42
+ const currentValue = currentValues[fieldName] ?? '';
43
+ diffs.push({
44
+ FieldName: fieldName,
45
+ DisplayName: fieldName,
46
+ VersionValue: versionValue,
47
+ CurrentValue: currentValue,
48
+ IsChanged: versionValue !== currentValue,
49
+ });
50
+ }
51
+ return diffs;
52
+ }
53
+ // ═══════════════════════════════════════════
54
+ // RestoreVersionEvent emission logic
55
+ // ═══════════════════════════════════════════
56
+ describe('parseFieldChanges', () => {
57
+ it('should parse ChangesJSON into field change map', () => {
58
+ const json = JSON.stringify({
59
+ '0': { field: 'FirstName', oldValue: 'John', newValue: 'Jonathan' },
60
+ '1': { field: 'Email', oldValue: 'old@example.com', newValue: 'new@example.com' },
61
+ });
62
+ const result = parseFieldChanges(json);
63
+ expect(Object.keys(result)).toHaveLength(2);
64
+ expect(result['FirstName']).toEqual({ OldValue: 'John', NewValue: 'Jonathan' });
65
+ expect(result['Email']).toEqual({
66
+ OldValue: 'old@example.com',
67
+ NewValue: 'new@example.com',
68
+ });
69
+ });
70
+ it('should use key as field name when field property is missing', () => {
71
+ const json = JSON.stringify({
72
+ Status: { oldValue: 'Active', newValue: 'Inactive' },
73
+ });
74
+ const result = parseFieldChanges(json);
75
+ expect(result['Status']).toEqual({ OldValue: 'Active', NewValue: 'Inactive' });
76
+ });
77
+ it('should return empty object for invalid JSON', () => {
78
+ const result = parseFieldChanges('not valid json');
79
+ expect(Object.keys(result)).toHaveLength(0);
80
+ });
81
+ it('should return empty object for empty string', () => {
82
+ const result = parseFieldChanges('');
83
+ expect(Object.keys(result)).toHaveLength(0);
84
+ });
85
+ it('should handle null/undefined old and new values', () => {
86
+ const json = JSON.stringify({
87
+ '0': { field: 'Description', oldValue: null, newValue: 'New description' },
88
+ });
89
+ const result = parseFieldChanges(json);
90
+ expect(result['Description']).toEqual({
91
+ OldValue: null,
92
+ NewValue: 'New description',
93
+ });
94
+ });
95
+ });
96
+ // ═══════════════════════════════════════════
97
+ // Diff computation between version and current
98
+ // ═══════════════════════════════════════════
99
+ describe('buildRestorePreviewFields', () => {
100
+ it('should mark fields as changed when version differs from current', () => {
101
+ const json = JSON.stringify({
102
+ '0': { field: 'Name', oldValue: 'Old Name', newValue: 'Current Name' },
103
+ '1': { field: 'Status', oldValue: 'Active', newValue: 'Inactive' },
104
+ });
105
+ const currentValues = {
106
+ Name: 'Current Name',
107
+ Status: 'Inactive',
108
+ };
109
+ const diffs = buildRestorePreviewFields(json, currentValues);
110
+ expect(diffs).toHaveLength(2);
111
+ const nameDiff = diffs.find((d) => d.FieldName === 'Name');
112
+ expect(nameDiff.VersionValue).toBe('Old Name');
113
+ expect(nameDiff.CurrentValue).toBe('Current Name');
114
+ expect(nameDiff.IsChanged).toBe(true);
115
+ const statusDiff = diffs.find((d) => d.FieldName === 'Status');
116
+ expect(statusDiff.VersionValue).toBe('Active');
117
+ expect(statusDiff.CurrentValue).toBe('Inactive');
118
+ expect(statusDiff.IsChanged).toBe(true);
119
+ });
120
+ it('should mark fields as unchanged when version matches current', () => {
121
+ const json = JSON.stringify({
122
+ '0': { field: 'Name', oldValue: 'Same Value', newValue: 'Different' },
123
+ });
124
+ const currentValues = {
125
+ Name: 'Same Value',
126
+ };
127
+ const diffs = buildRestorePreviewFields(json, currentValues);
128
+ expect(diffs[0].IsChanged).toBe(false);
129
+ });
130
+ it('should return empty array for invalid JSON', () => {
131
+ const diffs = buildRestorePreviewFields('bad json', {});
132
+ expect(diffs).toHaveLength(0);
133
+ });
134
+ it('should handle missing current values (treats as empty string)', () => {
135
+ const json = JSON.stringify({
136
+ '0': { field: 'NewField', oldValue: 'some value', newValue: '' },
137
+ });
138
+ const diffs = buildRestorePreviewFields(json, {});
139
+ expect(diffs[0].CurrentValue).toBe('');
140
+ expect(diffs[0].VersionValue).toBe('some value');
141
+ expect(diffs[0].IsChanged).toBe(true);
142
+ });
143
+ it('should treat null oldValue as empty string for comparison', () => {
144
+ const json = JSON.stringify({
145
+ '0': { field: 'Notes', oldValue: null, newValue: 'Added notes' },
146
+ });
147
+ const diffs = buildRestorePreviewFields(json, { Notes: '' });
148
+ expect(diffs[0].VersionValue).toBe('');
149
+ expect(diffs[0].CurrentValue).toBe('');
150
+ expect(diffs[0].IsChanged).toBe(false);
151
+ });
152
+ });
153
+ // ═══════════════════════════════════════════
154
+ // RestoreVersionEvent interface shape
155
+ // ═══════════════════════════════════════════
156
+ describe('RestoreVersionEvent', () => {
157
+ it('should have the correct shape', () => {
158
+ const event = {
159
+ VersionID: 'abc-123',
160
+ ChangedAt: new Date('2025-01-15T10:00:00Z'),
161
+ ChangedByUser: 'user@example.com',
162
+ FieldChanges: {
163
+ Name: { OldValue: 'Old', NewValue: 'New' },
164
+ Status: { OldValue: 'Active', NewValue: 'Inactive' },
165
+ },
166
+ };
167
+ expect(event.VersionID).toBe('abc-123');
168
+ expect(event.ChangedByUser).toBe('user@example.com');
169
+ expect(Object.keys(event.FieldChanges)).toHaveLength(2);
170
+ expect(event.FieldChanges['Name'].OldValue).toBe('Old');
171
+ });
172
+ });
173
+ //# sourceMappingURL=restore-version.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore-version.test.js","sourceRoot":"","sources":["../../src/__tests__/restore-version.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for restore version logic extracted from RecordChangesComponent.\n *\n * We test pure logic functions directly to avoid Angular TestBed complexity.\n * These mirror the component's parseFieldChanges, buildRestorePreviewFields, etc.\n */\nimport { describe, it, expect } from 'vitest';\nimport { RestoreFieldDiff, RestoreVersionEvent } from '../lib/ng-record-changes.component';\n\n// ── Extracted pure logic mirrors from RecordChangesComponent ──\n\n/** Mirrors RecordChangesComponent.parseFieldChanges */\nfunction parseFieldChanges(\n changesJSON: string\n): Record<string, { OldValue: unknown; NewValue: unknown }> {\n const fieldChanges: Record<string, { OldValue: unknown; NewValue: unknown }> = {};\n try {\n const changesJson = JSON.parse(changesJSON || '{}') as Record<\n string,\n { field?: string; oldValue?: unknown; newValue?: unknown }\n >;\n for (const key of Object.keys(changesJson)) {\n const entry = changesJson[key];\n const fieldName = entry.field || key;\n fieldChanges[fieldName] = {\n OldValue: entry.oldValue,\n NewValue: entry.newValue,\n };\n }\n } catch {\n // Return empty on parse failure\n }\n return fieldChanges;\n}\n\n/** Mirrors RecordChangesComponent.buildRestorePreviewFields (simplified without EntityInfo) */\nfunction buildRestorePreviewFields(\n changesJSON: string,\n currentValues: Record<string, string>\n): RestoreFieldDiff[] {\n let changesJson: Record<string, { field?: string; oldValue?: unknown; newValue?: unknown }>;\n try {\n changesJson = JSON.parse(changesJSON || '{}');\n } catch {\n return [];\n }\n\n const diffs: RestoreFieldDiff[] = [];\n for (const key of Object.keys(changesJson)) {\n const entry = changesJson[key];\n const fieldName = entry.field || key;\n const versionValue = String(entry.oldValue ?? '');\n const currentValue = currentValues[fieldName] ?? '';\n\n diffs.push({\n FieldName: fieldName,\n DisplayName: fieldName,\n VersionValue: versionValue,\n CurrentValue: currentValue,\n IsChanged: versionValue !== currentValue,\n });\n }\n return diffs;\n}\n\n// ═══════════════════════════════════════════\n// RestoreVersionEvent emission logic\n// ═══════════════════════════════════════════\ndescribe('parseFieldChanges', () => {\n it('should parse ChangesJSON into field change map', () => {\n const json = JSON.stringify({\n '0': { field: 'FirstName', oldValue: 'John', newValue: 'Jonathan' },\n '1': { field: 'Email', oldValue: 'old@example.com', newValue: 'new@example.com' },\n });\n\n const result = parseFieldChanges(json);\n expect(Object.keys(result)).toHaveLength(2);\n expect(result['FirstName']).toEqual({ OldValue: 'John', NewValue: 'Jonathan' });\n expect(result['Email']).toEqual({\n OldValue: 'old@example.com',\n NewValue: 'new@example.com',\n });\n });\n\n it('should use key as field name when field property is missing', () => {\n const json = JSON.stringify({\n Status: { oldValue: 'Active', newValue: 'Inactive' },\n });\n\n const result = parseFieldChanges(json);\n expect(result['Status']).toEqual({ OldValue: 'Active', NewValue: 'Inactive' });\n });\n\n it('should return empty object for invalid JSON', () => {\n const result = parseFieldChanges('not valid json');\n expect(Object.keys(result)).toHaveLength(0);\n });\n\n it('should return empty object for empty string', () => {\n const result = parseFieldChanges('');\n expect(Object.keys(result)).toHaveLength(0);\n });\n\n it('should handle null/undefined old and new values', () => {\n const json = JSON.stringify({\n '0': { field: 'Description', oldValue: null, newValue: 'New description' },\n });\n\n const result = parseFieldChanges(json);\n expect(result['Description']).toEqual({\n OldValue: null,\n NewValue: 'New description',\n });\n });\n});\n\n// ═══════════════════════════════════════════\n// Diff computation between version and current\n// ═══════════════════════════════════════════\ndescribe('buildRestorePreviewFields', () => {\n it('should mark fields as changed when version differs from current', () => {\n const json = JSON.stringify({\n '0': { field: 'Name', oldValue: 'Old Name', newValue: 'Current Name' },\n '1': { field: 'Status', oldValue: 'Active', newValue: 'Inactive' },\n });\n const currentValues: Record<string, string> = {\n Name: 'Current Name',\n Status: 'Inactive',\n };\n\n const diffs = buildRestorePreviewFields(json, currentValues);\n expect(diffs).toHaveLength(2);\n\n const nameDiff = diffs.find((d) => d.FieldName === 'Name');\n expect(nameDiff!.VersionValue).toBe('Old Name');\n expect(nameDiff!.CurrentValue).toBe('Current Name');\n expect(nameDiff!.IsChanged).toBe(true);\n\n const statusDiff = diffs.find((d) => d.FieldName === 'Status');\n expect(statusDiff!.VersionValue).toBe('Active');\n expect(statusDiff!.CurrentValue).toBe('Inactive');\n expect(statusDiff!.IsChanged).toBe(true);\n });\n\n it('should mark fields as unchanged when version matches current', () => {\n const json = JSON.stringify({\n '0': { field: 'Name', oldValue: 'Same Value', newValue: 'Different' },\n });\n const currentValues: Record<string, string> = {\n Name: 'Same Value',\n };\n\n const diffs = buildRestorePreviewFields(json, currentValues);\n expect(diffs[0].IsChanged).toBe(false);\n });\n\n it('should return empty array for invalid JSON', () => {\n const diffs = buildRestorePreviewFields('bad json', {});\n expect(diffs).toHaveLength(0);\n });\n\n it('should handle missing current values (treats as empty string)', () => {\n const json = JSON.stringify({\n '0': { field: 'NewField', oldValue: 'some value', newValue: '' },\n });\n\n const diffs = buildRestorePreviewFields(json, {});\n expect(diffs[0].CurrentValue).toBe('');\n expect(diffs[0].VersionValue).toBe('some value');\n expect(diffs[0].IsChanged).toBe(true);\n });\n\n it('should treat null oldValue as empty string for comparison', () => {\n const json = JSON.stringify({\n '0': { field: 'Notes', oldValue: null, newValue: 'Added notes' },\n });\n\n const diffs = buildRestorePreviewFields(json, { Notes: '' });\n expect(diffs[0].VersionValue).toBe('');\n expect(diffs[0].CurrentValue).toBe('');\n expect(diffs[0].IsChanged).toBe(false);\n });\n});\n\n// ═══════════════════════════════════════════\n// RestoreVersionEvent interface shape\n// ═══════════════════════════════════════════\ndescribe('RestoreVersionEvent', () => {\n it('should have the correct shape', () => {\n const event: RestoreVersionEvent = {\n VersionID: 'abc-123',\n ChangedAt: new Date('2025-01-15T10:00:00Z'),\n ChangedByUser: 'user@example.com',\n FieldChanges: {\n Name: { OldValue: 'Old', NewValue: 'New' },\n Status: { OldValue: 'Active', NewValue: 'Inactive' },\n },\n };\n\n expect(event.VersionID).toBe('abc-123');\n expect(event.ChangedByUser).toBe('user@example.com');\n expect(Object.keys(event.FieldChanges)).toHaveLength(2);\n expect(event.FieldChanges['Name'].OldValue).toBe('Old');\n });\n});\n"]}
@@ -14,6 +14,23 @@ interface RecordLabel {
14
14
  CreatedAt: Date;
15
15
  ItemCount: number;
16
16
  }
17
+ /**
18
+ * Event payload emitted when the user requests to restore a previous version.
19
+ * The parent component is responsible for applying the old field values and saving.
20
+ */
21
+ export interface RestoreVersionEvent {
22
+ /** The ID of the MJ: Record Changes record being restored */
23
+ VersionID: string;
24
+ /** When the version was created */
25
+ ChangedAt: Date;
26
+ /** User who made the change */
27
+ ChangedByUser: string;
28
+ /** Map of field name to old/new values from this change */
29
+ FieldChanges: Record<string, {
30
+ OldValue: unknown;
31
+ NewValue: unknown;
32
+ }>;
33
+ }
17
34
  /** A single field change with type-aware rendering info */
18
35
  export interface FieldChangeInfo {
19
36
  field: string;
@@ -23,6 +40,14 @@ export interface FieldChangeInfo {
23
40
  fieldType: 'boolean' | 'date' | 'number' | 'text';
24
41
  diffHtml?: SafeHtml;
25
42
  }
43
+ /** A single field in the restore preview, comparing version value vs current record value */
44
+ export interface RestoreFieldDiff {
45
+ FieldName: string;
46
+ DisplayName: string;
47
+ VersionValue: string;
48
+ CurrentValue: string;
49
+ IsChanged: boolean;
50
+ }
26
51
  /** A group of changes that share the same date */
27
52
  export interface DateGroup {
28
53
  label: string;
@@ -37,10 +62,23 @@ export declare class RecordChangesComponent implements OnInit {
37
62
  IsVisible: boolean;
38
63
  dialogClosed: EventEmitter<any>;
39
64
  record: BaseEntity;
65
+ /** Whether to show a "Restore" button on each historical version row. Default false. */
66
+ AllowRestore: boolean;
67
+ /**
68
+ * Emitted when the user clicks Restore on a historical version.
69
+ * The parent is responsible for loading old values into the record and saving.
70
+ */
71
+ RestoreRequested: EventEmitter<RestoreVersionEvent>;
40
72
  viewData: MJRecordChangeEntity[];
41
73
  filteredData: MJRecordChangeEntity[];
42
74
  dateGroups: DateGroup[];
43
75
  expandedItems: Set<string>;
76
+ /** The change record being previewed for restore, or null if no preview is active */
77
+ RestorePreview: MJRecordChangeEntity | null;
78
+ /** Parsed field-level diff for the restore preview */
79
+ RestorePreviewFields: RestoreFieldDiff[];
80
+ /** Whether the restore operation is in progress */
81
+ IsRestoring: boolean;
44
82
  RecordLabels: RecordLabel[];
45
83
  IsLoadingLabels: boolean;
46
84
  ShowCreateWizard: boolean;
@@ -66,6 +104,28 @@ export declare class RecordChangesComponent implements OnInit {
66
104
  getLabelStatusClass(status: string): string;
67
105
  toggleExpansion(changeId: string): void;
68
106
  onTimelineItemKeydown(event: KeyboardEvent, changeId: string): void;
107
+ /**
108
+ * Opens the inline restore preview panel for a given change record.
109
+ * Computes a field-by-field diff between the version's old values and the current record.
110
+ */
111
+ OnRestoreVersion(change: MJRecordChangeEntity, event: MouseEvent): void;
112
+ /** Closes the restore preview panel without applying changes. */
113
+ CancelRestorePreview(): void;
114
+ /**
115
+ * Confirms the restore: emits a RestoreVersionEvent with the old field values
116
+ * so the parent (record-form-container) can apply them and save.
117
+ */
118
+ ConfirmRestore(): void;
119
+ /**
120
+ * Builds the diff list comparing version old values vs the current record.
121
+ */
122
+ private buildRestorePreviewFields;
123
+ /** Gets the current value of a field from the live record, formatted for display. */
124
+ private getCurrentFieldValue;
125
+ /** Parses ChangesJSON into a structured map, returning null on failure. */
126
+ private parseChangesJson;
127
+ /** Parses field changes into the RestoreVersionEvent format. */
128
+ private parseFieldChanges;
69
129
  private buildDateGroups;
70
130
  private formatDateGroupLabel;
71
131
  getChangeTypeCardClass(type: string): string;
@@ -100,7 +160,7 @@ export declare class RecordChangesComponent implements OnInit {
100
160
  private shouldUseWordDiff;
101
161
  private escapeHtml;
102
162
  static ɵfac: i0.ɵɵFactoryDeclaration<RecordChangesComponent, never>;
103
- static ɵcmp: i0.ɵɵComponentDeclaration<RecordChangesComponent, "mj-record-changes", never, { "record": { "alias": "record"; "required": false; }; }, { "dialogClosed": "dialogClosed"; }, never, never, false, never>;
163
+ static ɵcmp: i0.ɵɵComponentDeclaration<RecordChangesComponent, "mj-record-changes", never, { "record": { "alias": "record"; "required": false; }; "AllowRestore": { "alias": "AllowRestore"; "required": false; }; }, { "dialogClosed": "dialogClosed"; "RestoreRequested": "RestoreRequested"; }, never, never, false, never>;
104
164
  }
105
165
  export {};
106
166
  //# sourceMappingURL=ng-record-changes.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-record-changes.component.d.ts","sourceRoot":"","sources":["../../src/lib/ng-record-changes.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-record-changes.component.d.ts","sourceRoot":"","sources":["../../src/lib/ng-record-changes.component.ts"],"names":[],"mappings":"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"}