@memberjunction/ng-record-clone 0.0.0 → 6.2.0-edge.2

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.
Files changed (55) hide show
  1. package/LICENSE +183 -0
  2. package/README.md +225 -28
  3. package/dist/lib/clone-lineage-chip.component.d.ts +50 -0
  4. package/dist/lib/clone-lineage-chip.component.d.ts.map +1 -0
  5. package/dist/lib/clone-lineage-chip.component.js +448 -0
  6. package/dist/lib/clone-lineage-chip.component.js.map +1 -0
  7. package/dist/lib/clone-plan-tree.component.d.ts +51 -0
  8. package/dist/lib/clone-plan-tree.component.d.ts.map +1 -0
  9. package/dist/lib/clone-plan-tree.component.js +634 -0
  10. package/dist/lib/clone-plan-tree.component.js.map +1 -0
  11. package/dist/lib/clone-progress.component.d.ts +12 -0
  12. package/dist/lib/clone-progress.component.d.ts.map +1 -0
  13. package/dist/lib/clone-progress.component.js +151 -0
  14. package/dist/lib/clone-progress.component.js.map +1 -0
  15. package/dist/lib/clone-result.component.d.ts +40 -0
  16. package/dist/lib/clone-result.component.d.ts.map +1 -0
  17. package/dist/lib/clone-result.component.js +357 -0
  18. package/dist/lib/clone-result.component.js.map +1 -0
  19. package/dist/lib/clone-review.component.d.ts +58 -0
  20. package/dist/lib/clone-review.component.d.ts.map +1 -0
  21. package/dist/lib/clone-review.component.js +581 -0
  22. package/dist/lib/clone-review.component.js.map +1 -0
  23. package/dist/lib/clone-scope-controls.component.d.ts +81 -0
  24. package/dist/lib/clone-scope-controls.component.d.ts.map +1 -0
  25. package/dist/lib/clone-scope-controls.component.js +394 -0
  26. package/dist/lib/clone-scope-controls.component.js.map +1 -0
  27. package/dist/lib/clone-values.component.d.ts +55 -0
  28. package/dist/lib/clone-values.component.d.ts.map +1 -0
  29. package/dist/lib/clone-values.component.js +493 -0
  30. package/dist/lib/clone-values.component.js.map +1 -0
  31. package/dist/lib/record-clone-panel.component.d.ts +247 -0
  32. package/dist/lib/record-clone-panel.component.d.ts.map +1 -0
  33. package/dist/lib/record-clone-panel.component.js +1252 -0
  34. package/dist/lib/record-clone-panel.component.js.map +1 -0
  35. package/dist/lib/record-clone-slide-in.component.d.ts +83 -0
  36. package/dist/lib/record-clone-slide-in.component.d.ts.map +1 -0
  37. package/dist/lib/record-clone-slide-in.component.js +206 -0
  38. package/dist/lib/record-clone-slide-in.component.js.map +1 -0
  39. package/dist/lib/record-clone-types.d.ts +89 -0
  40. package/dist/lib/record-clone-types.d.ts.map +1 -0
  41. package/dist/lib/record-clone-types.js +29 -0
  42. package/dist/lib/record-clone-types.js.map +1 -0
  43. package/dist/lib/record-clone.module.d.ts +16 -0
  44. package/dist/lib/record-clone.module.d.ts.map +1 -0
  45. package/dist/lib/record-clone.module.js +69 -0
  46. package/dist/lib/record-clone.module.js.map +1 -0
  47. package/dist/lib/record-clone.service.d.ts +42 -0
  48. package/dist/lib/record-clone.service.d.ts.map +1 -0
  49. package/dist/lib/record-clone.service.js +123 -0
  50. package/dist/lib/record-clone.service.js.map +1 -0
  51. package/dist/public-api.d.ts +16 -0
  52. package/dist/public-api.d.ts.map +1 -0
  53. package/dist/public-api.js +16 -0
  54. package/dist/public-api.js.map +1 -0
  55. package/package.json +49 -7
@@ -0,0 +1,357 @@
1
+ /**
2
+ * @fileoverview Result display component following clone execution.
3
+ *
4
+ * Implements §12.3 of the Record Cloning architectural blueprint. Displays success
5
+ * state, execution summary (records created/referenced/skipped and execution duration),
6
+ * warnings review, and navigation CTAs ("Open Cloned Record", "Clone Another", "Close").
7
+ */
8
+ import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, } from '@angular/core';
9
+ import { CommonModule } from '@angular/common';
10
+ import { MJButtonDirective, MJStatBadgeComponent, } from '@memberjunction/ng-ui-components';
11
+ import * as i0 from "@angular/core";
12
+ const _forTrack0 = ($index, $item) => $item.Code + ($item.NodeKey || "") + $index;
13
+ function CloneResultComponent_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
14
+ i0.ɵɵelementStart(0, "strong");
15
+ i0.ɵɵtext(1);
16
+ i0.ɵɵelementEnd();
17
+ i0.ɵɵtext(2, " has been created. ");
18
+ } if (rf & 2) {
19
+ const ctx_r1 = i0.ɵɵnextContext(2);
20
+ i0.ɵɵadvance();
21
+ i0.ɵɵtextInterpolate(ctx_r1.RootRecordName);
22
+ } }
23
+ function CloneResultComponent_Conditional_1_Conditional_6_Template(rf, ctx) { if (rf & 1) {
24
+ i0.ɵɵtext(0);
25
+ } if (rf & 2) {
26
+ const ctx_r1 = i0.ɵɵnextContext(2);
27
+ i0.ɵɵtextInterpolate1(" New ", ctx_r1.EntityName, " record and its hierarchy have been created. ");
28
+ } }
29
+ function CloneResultComponent_Conditional_1_Conditional_9_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelement(0, "mj-stat-badge", 7);
31
+ } if (rf & 2) {
32
+ const ctx_r1 = i0.ɵɵnextContext(2);
33
+ i0.ɵɵproperty("Count", ctx_r1.ReferencedCount);
34
+ } }
35
+ function CloneResultComponent_Conditional_1_Conditional_10_For_6_Template(rf, ctx) { if (rf & 1) {
36
+ i0.ɵɵelementStart(0, "li");
37
+ i0.ɵɵtext(1);
38
+ i0.ɵɵelementEnd();
39
+ } if (rf & 2) {
40
+ const warn_r3 = ctx.$implicit;
41
+ i0.ɵɵadvance();
42
+ i0.ɵɵtextInterpolate(warn_r3.Message);
43
+ } }
44
+ function CloneResultComponent_Conditional_1_Conditional_10_Template(rf, ctx) { if (rf & 1) {
45
+ i0.ɵɵelementStart(0, "div", 8)(1, "span", 16);
46
+ i0.ɵɵelement(2, "i", 17);
47
+ i0.ɵɵtext(3);
48
+ i0.ɵɵelementEnd();
49
+ i0.ɵɵelementStart(4, "ul", 18);
50
+ i0.ɵɵrepeaterCreate(5, CloneResultComponent_Conditional_1_Conditional_10_For_6_Template, 2, 1, "li", null, _forTrack0);
51
+ i0.ɵɵelementEnd()();
52
+ } if (rf & 2) {
53
+ const ctx_r1 = i0.ɵɵnextContext(2);
54
+ i0.ɵɵadvance(3);
55
+ i0.ɵɵtextInterpolate1(" Execution Warnings (", ctx_r1.Result.Warnings.length, ") ");
56
+ i0.ɵɵadvance(2);
57
+ i0.ɵɵrepeater(ctx_r1.Result.Warnings);
58
+ } }
59
+ function CloneResultComponent_Conditional_1_Conditional_20_Template(rf, ctx) { if (rf & 1) {
60
+ const _r4 = i0.ɵɵgetCurrentView();
61
+ i0.ɵɵelementStart(0, "div", 15)(1, "button", 19);
62
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_1_Conditional_20_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenCloneLog()); });
63
+ i0.ɵɵelement(2, "i", 20);
64
+ i0.ɵɵtext(3);
65
+ i0.ɵɵelementEnd()();
66
+ } if (rf & 2) {
67
+ const ctx_r1 = i0.ɵɵnextContext(2);
68
+ i0.ɵɵadvance(3);
69
+ i0.ɵɵtextInterpolate1(" View Clone Log [", ctx_r1.Result == null ? null : ctx_r1.Result.CloneLogID, "] ");
70
+ } }
71
+ function CloneResultComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
72
+ const _r1 = i0.ɵɵgetCurrentView();
73
+ i0.ɵɵelementStart(0, "div", 1);
74
+ i0.ɵɵelement(1, "i", 2);
75
+ i0.ɵɵelementEnd();
76
+ i0.ɵɵelementStart(2, "h3", 3);
77
+ i0.ɵɵtext(3, "Record Cloned Successfully");
78
+ i0.ɵɵelementEnd();
79
+ i0.ɵɵelementStart(4, "p", 4);
80
+ i0.ɵɵconditionalCreate(5, CloneResultComponent_Conditional_1_Conditional_5_Template, 3, 1)(6, CloneResultComponent_Conditional_1_Conditional_6_Template, 1, 1);
81
+ i0.ɵɵelementEnd();
82
+ i0.ɵɵelementStart(7, "div", 5);
83
+ i0.ɵɵelement(8, "mj-stat-badge", 6);
84
+ i0.ɵɵconditionalCreate(9, CloneResultComponent_Conditional_1_Conditional_9_Template, 1, 1, "mj-stat-badge", 7);
85
+ i0.ɵɵelementEnd();
86
+ i0.ɵɵconditionalCreate(10, CloneResultComponent_Conditional_1_Conditional_10_Template, 7, 1, "div", 8);
87
+ i0.ɵɵelementStart(11, "div", 9)(12, "button", 10);
88
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_1_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnOpenClone()); });
89
+ i0.ɵɵelement(13, "i", 11);
90
+ i0.ɵɵtext(14, " Open Cloned Record ");
91
+ i0.ɵɵelementEnd();
92
+ i0.ɵɵelementStart(15, "button", 12);
93
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_1_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnCloneAnother()); });
94
+ i0.ɵɵelement(16, "i", 13);
95
+ i0.ɵɵtext(17, " Clone Another ");
96
+ i0.ɵɵelementEnd();
97
+ i0.ɵɵelementStart(18, "button", 14);
98
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_1_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnClose()); });
99
+ i0.ɵɵtext(19, " Close ");
100
+ i0.ɵɵelementEnd()();
101
+ i0.ɵɵconditionalCreate(20, CloneResultComponent_Conditional_1_Conditional_20_Template, 4, 1, "div", 15);
102
+ } if (rf & 2) {
103
+ const ctx_r1 = i0.ɵɵnextContext();
104
+ i0.ɵɵadvance(5);
105
+ i0.ɵɵconditional(ctx_r1.RootRecordName ? 5 : 6);
106
+ i0.ɵɵadvance(3);
107
+ i0.ɵɵproperty("Count", ctx_r1.CreatedCount);
108
+ i0.ɵɵadvance();
109
+ i0.ɵɵconditional(ctx_r1.ReferencedCount > 0 ? 9 : -1);
110
+ i0.ɵɵadvance();
111
+ i0.ɵɵconditional((ctx_r1.Result == null ? null : ctx_r1.Result.Warnings) && ctx_r1.Result.Warnings.length > 0 ? 10 : -1);
112
+ i0.ɵɵadvance(10);
113
+ i0.ɵɵconditional((ctx_r1.Result == null ? null : ctx_r1.Result.CloneLogID) ? 20 : -1);
114
+ } }
115
+ function CloneResultComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
116
+ const _r5 = i0.ɵɵgetCurrentView();
117
+ i0.ɵɵelementStart(0, "div", 21);
118
+ i0.ɵɵelement(1, "i", 22);
119
+ i0.ɵɵelementEnd();
120
+ i0.ɵɵelementStart(2, "h3", 23);
121
+ i0.ɵɵtext(3, "Cloning Failed");
122
+ i0.ɵɵelementEnd();
123
+ i0.ɵɵelementStart(4, "p", 24);
124
+ i0.ɵɵtext(5);
125
+ i0.ɵɵelementEnd();
126
+ i0.ɵɵelementStart(6, "div", 9)(7, "button", 10);
127
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_2_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnCloneAnother()); });
128
+ i0.ɵɵelement(8, "i", 13);
129
+ i0.ɵɵtext(9, " Try Again ");
130
+ i0.ɵɵelementEnd();
131
+ i0.ɵɵelementStart(10, "button", 14);
132
+ i0.ɵɵlistener("click", function CloneResultComponent_Conditional_2_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnClose()); });
133
+ i0.ɵɵtext(11, " Close ");
134
+ i0.ɵɵelementEnd()();
135
+ } if (rf & 2) {
136
+ const ctx_r1 = i0.ɵɵnextContext();
137
+ i0.ɵɵadvance(5);
138
+ i0.ɵɵtextInterpolate1(" ", (ctx_r1.Result == null ? null : ctx_r1.Result.ErrorMessage) || "An error occurred during execution. No records were modified.", " ");
139
+ } }
140
+ export class CloneResultComponent {
141
+ /** Execute output to summarize. */
142
+ Result = null;
143
+ /** Entity of the root clone. */
144
+ EntityName = 'Record';
145
+ /** Record-id string of the root clone; falls back to `Result.Roots[0].TargetKey`. */
146
+ TargetKey = null;
147
+ /** Display name of the new root record. */
148
+ RootRecordName;
149
+ /** Fires with the root clone's key when the user opens it. `NavigateToRecord` fires too. */
150
+ OpenClone = new EventEmitter();
151
+ /** The user wants to clone the source again. */
152
+ CloneAnother = new EventEmitter();
153
+ /** The user closed the result. */
154
+ Close = new EventEmitter();
155
+ /** Fires with the clone log ID when the user opens the log. `NavigateToRecord` fires too. */
156
+ OpenCloneLog = new EventEmitter();
157
+ /** Asks the host to open the clone or the clone log record. */
158
+ NavigateToRecord = new EventEmitter();
159
+ get CreatedCount() {
160
+ return this.Result?.Created?.length ?? this.Result?.Counts?.Create ?? 1;
161
+ }
162
+ get ReferencedCount() {
163
+ if (!this.Result?.Counts?.ByEntity)
164
+ return 0;
165
+ return Object.values(this.Result.Counts.ByEntity).reduce((acc, c) => acc + (c.Reference || 0), 0);
166
+ }
167
+ OnOpenClone() {
168
+ const raw = this.TargetKey || this.Result?.Roots?.[0]?.TargetKey;
169
+ if (raw) {
170
+ const key = typeof raw === 'string'
171
+ ? raw
172
+ : raw?.ToURLSegment?.() ?? raw?.ToConcatenatedString?.() ?? String(raw);
173
+ this.OpenClone.emit(key);
174
+ this.NavigateToRecord.emit({
175
+ Kind: 'record',
176
+ EntityName: this.EntityName,
177
+ RecordKey: key,
178
+ });
179
+ }
180
+ }
181
+ OnCloneAnother() {
182
+ this.CloneAnother.emit();
183
+ }
184
+ OnClose() {
185
+ this.Close.emit();
186
+ }
187
+ OnOpenCloneLog() {
188
+ if (this.Result?.CloneLogID) {
189
+ this.OpenCloneLog.emit(this.Result.CloneLogID);
190
+ this.NavigateToRecord.emit({
191
+ Kind: 'record',
192
+ EntityName: 'MJ: Record Clone Logs',
193
+ RecordKey: this.Result.CloneLogID,
194
+ });
195
+ }
196
+ }
197
+ static ɵfac = function CloneResultComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CloneResultComponent)(); };
198
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CloneResultComponent, selectors: [["mj-clone-result"]], inputs: { Result: "Result", EntityName: "EntityName", TargetKey: "TargetKey", RootRecordName: "RootRecordName" }, outputs: { OpenClone: "OpenClone", CloneAnother: "CloneAnother", Close: "Close", OpenCloneLog: "OpenCloneLog", NavigateToRecord: "NavigateToRecord" }, decls: 3, vars: 1, consts: [[1, "clone-result-container"], [1, "result-icon-wrapper", "success"], [1, "fa-solid", "fa-circle-check", "result-icon"], [1, "result-title"], [1, "result-subtitle"], [1, "result-stats"], ["Label", "created", "Variant", "success", "Icon", "fa-solid fa-plus", 3, "Count"], ["Label", "referenced", "Variant", "info", "Icon", "fa-solid fa-link", 3, "Count"], [1, "result-warnings-box"], [1, "result-actions"], ["type", "button", "mjButton", "", "variant", "primary", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], ["type", "button", "mjButton", "", "variant", "secondary", 3, "click"], [1, "fa-solid", "fa-rotate-right"], ["type", "button", "mjButton", "", "variant", "outline", 3, "click"], [1, "audit-log-footer"], [1, "warnings-title"], [1, "fa-solid", "fa-triangle-exclamation"], [1, "warnings-list"], ["type", "button", 1, "audit-link-btn", 3, "click"], [1, "fa-solid", "fa-file-lines"], [1, "result-icon-wrapper", "failure"], [1, "fa-solid", "fa-circle-xmark", "result-icon"], [1, "result-title", "failure-text"], [1, "result-subtitle", "failure-message"]], template: function CloneResultComponent_Template(rf, ctx) { if (rf & 1) {
199
+ i0.ɵɵelementStart(0, "div", 0);
200
+ i0.ɵɵconditionalCreate(1, CloneResultComponent_Conditional_1_Template, 21, 5)(2, CloneResultComponent_Conditional_2_Template, 12, 1);
201
+ i0.ɵɵelementEnd();
202
+ } if (rf & 2) {
203
+ i0.ɵɵadvance();
204
+ i0.ɵɵconditional((ctx.Result == null ? null : ctx.Result.Success) ? 1 : 2);
205
+ } }, dependencies: [CommonModule,
206
+ MJButtonDirective,
207
+ MJStatBadgeComponent], styles: [".clone-result-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n padding: var(--mj-space-8) var(--mj-space-4);\n gap: var(--mj-space-4);\n }\n\n .result-icon-wrapper[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .result-icon-wrapper.success[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n }\n\n .result-icon-wrapper.failure[_ngcontent-%COMP%] {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n }\n\n .result-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n }\n\n .result-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .failure-text[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n }\n\n .result-subtitle[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n max-width: 440px;\n }\n\n .failure-message[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n }\n\n .result-stats[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: var(--mj-space-1) 0;\n }\n\n .result-warnings-box[_ngcontent-%COMP%] {\n text-align: left;\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-2) var(--mj-space-3);\n max-width: 440px;\n width: 100%;\n }\n\n .warnings-title[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .warnings-list[_ngcontent-%COMP%] {\n margin: 4px 0 0;\n padding-left: 18px;\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n }\n\n .result-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-2);\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .audit-log-footer[_ngcontent-%COMP%] {\n margin-top: var(--mj-space-2);\n }\n\n .audit-link-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: var(--mj-text-xs);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n text-decoration: underline;\n }\n\n .audit-link-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary-hover);\n }"], changeDetection: 0 });
208
+ }
209
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CloneResultComponent, [{
210
+ type: Component,
211
+ args: [{ standalone: true, selector: 'mj-clone-result', template: `
212
+ <div class="clone-result-container">
213
+ @if (Result?.Success) {
214
+ <!-- Success State -->
215
+ <div class="result-icon-wrapper success">
216
+ <i class="fa-solid fa-circle-check result-icon"></i>
217
+ </div>
218
+ <h3 class="result-title">Record Cloned Successfully</h3>
219
+ <p class="result-subtitle">
220
+ @if (RootRecordName) {
221
+ <strong>{{RootRecordName}}</strong> has been created.
222
+ } @else {
223
+ New {{EntityName}} record and its hierarchy have been created.
224
+ }
225
+ </p>
226
+
227
+ <!-- Summary Badges -->
228
+ <div class="result-stats">
229
+ <mj-stat-badge
230
+ [Count]="CreatedCount"
231
+ Label="created"
232
+ Variant="success"
233
+ Icon="fa-solid fa-plus">
234
+ </mj-stat-badge>
235
+
236
+ @if (ReferencedCount > 0) {
237
+ <mj-stat-badge
238
+ [Count]="ReferencedCount"
239
+ Label="referenced"
240
+ Variant="info"
241
+ Icon="fa-solid fa-link">
242
+ </mj-stat-badge>
243
+ }
244
+ </div>
245
+
246
+ <!-- Warnings if any -->
247
+ @if (Result?.Warnings && Result!.Warnings!.length > 0) {
248
+ <div class="result-warnings-box">
249
+ <span class="warnings-title">
250
+ <i class="fa-solid fa-triangle-exclamation"></i>
251
+ Execution Warnings ({{Result!.Warnings!.length}})
252
+ </span>
253
+ <ul class="warnings-list">
254
+ @for (warn of Result!.Warnings; track warn.Code + (warn.NodeKey || '') + $index) {
255
+ <li>{{warn.Message}}</li>
256
+ }
257
+ </ul>
258
+ </div>
259
+ }
260
+
261
+ <!-- Primary CTAs -->
262
+ <div class="result-actions">
263
+ <button
264
+ type="button"
265
+ mjButton
266
+ variant="primary"
267
+ (click)="OnOpenClone()">
268
+ <i class="fa-solid fa-arrow-up-right-from-square"></i>
269
+ Open Cloned Record
270
+ </button>
271
+
272
+ <button
273
+ type="button"
274
+ mjButton
275
+ variant="secondary"
276
+ (click)="OnCloneAnother()">
277
+ <i class="fa-solid fa-rotate-right"></i>
278
+ Clone Another
279
+ </button>
280
+
281
+ <button
282
+ type="button"
283
+ mjButton
284
+ variant="outline"
285
+ (click)="OnClose()">
286
+ Close
287
+ </button>
288
+ </div>
289
+
290
+ <!-- Audit Log Link -->
291
+ @if (Result?.CloneLogID) {
292
+ <div class="audit-log-footer">
293
+ <button
294
+ type="button"
295
+ class="audit-link-btn"
296
+ (click)="OnOpenCloneLog()">
297
+ <i class="fa-solid fa-file-lines"></i>
298
+ View Clone Log [{{Result?.CloneLogID}}]
299
+ </button>
300
+ </div>
301
+ }
302
+ } @else {
303
+ <!-- Failure State -->
304
+ <div class="result-icon-wrapper failure">
305
+ <i class="fa-solid fa-circle-xmark result-icon"></i>
306
+ </div>
307
+ <h3 class="result-title failure-text">Cloning Failed</h3>
308
+ <p class="result-subtitle failure-message">
309
+ {{Result?.ErrorMessage || 'An error occurred during execution. No records were modified.'}}
310
+ </p>
311
+
312
+ <div class="result-actions">
313
+ <button
314
+ type="button"
315
+ mjButton
316
+ variant="primary"
317
+ (click)="OnCloneAnother()">
318
+ <i class="fa-solid fa-rotate-right"></i>
319
+ Try Again
320
+ </button>
321
+
322
+ <button
323
+ type="button"
324
+ mjButton
325
+ variant="outline"
326
+ (click)="OnClose()">
327
+ Close
328
+ </button>
329
+ </div>
330
+ }
331
+ </div>
332
+ `, imports: [
333
+ CommonModule,
334
+ MJButtonDirective,
335
+ MJStatBadgeComponent,
336
+ ], changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n .clone-result-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n padding: var(--mj-space-8) var(--mj-space-4);\n gap: var(--mj-space-4);\n }\n\n .result-icon-wrapper {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .result-icon-wrapper.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n }\n\n .result-icon-wrapper.failure {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n }\n\n .result-icon {\n font-size: 32px;\n }\n\n .result-title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .failure-text {\n color: var(--mj-status-error-text);\n }\n\n .result-subtitle {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n max-width: 440px;\n }\n\n .failure-message {\n color: var(--mj-status-error-text);\n }\n\n .result-stats {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: var(--mj-space-1) 0;\n }\n\n .result-warnings-box {\n text-align: left;\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-2) var(--mj-space-3);\n max-width: 440px;\n width: 100%;\n }\n\n .warnings-title {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .warnings-list {\n margin: 4px 0 0;\n padding-left: 18px;\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n }\n\n .result-actions {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-2);\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .audit-log-footer {\n margin-top: var(--mj-space-2);\n }\n\n .audit-link-btn {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: var(--mj-text-xs);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n text-decoration: underline;\n }\n\n .audit-link-btn:hover {\n color: var(--mj-brand-primary-hover);\n }\n "] }]
337
+ }], null, { Result: [{
338
+ type: Input
339
+ }], EntityName: [{
340
+ type: Input
341
+ }], TargetKey: [{
342
+ type: Input
343
+ }], RootRecordName: [{
344
+ type: Input
345
+ }], OpenClone: [{
346
+ type: Output
347
+ }], CloneAnother: [{
348
+ type: Output
349
+ }], Close: [{
350
+ type: Output
351
+ }], OpenCloneLog: [{
352
+ type: Output
353
+ }], NavigateToRecord: [{
354
+ type: Output
355
+ }] }); })();
356
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CloneResultComponent, { className: "CloneResultComponent", filePath: "src/lib/clone-result.component.ts", lineNumber: 277 }); })();
357
+ //# sourceMappingURL=clone-result.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-result.component.js","sourceRoot":"","sources":["../../src/lib/clone-result.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Result display component following clone execution.\n *\n * Implements §12.3 of the Record Cloning architectural blueprint. Displays success\n * state, execution summary (records created/referenced/skipped and execution duration),\n * warnings review, and navigation CTAs (\"Open Cloned Record\", \"Clone Another\", \"Close\").\n */\n\nimport {\n Component,\n ChangeDetectionStrategy,\n Input,\n Output,\n EventEmitter,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n MJButtonDirective,\n MJStatBadgeComponent,\n} from '@memberjunction/ng-ui-components';\nimport type {\n RecordCloneExecuteOutput,\n RecordCloneKey,\n} from '@memberjunction/core-entities';\nimport { CompositeKey } from '@memberjunction/core';\nimport type { CloneNavigationEvent } from './record-clone-types';\n\n@Component({\n standalone: true,\n selector: 'mj-clone-result',\n template: `\n <div class=\"clone-result-container\">\n @if (Result?.Success) {\n <!-- Success State -->\n <div class=\"result-icon-wrapper success\">\n <i class=\"fa-solid fa-circle-check result-icon\"></i>\n </div>\n <h3 class=\"result-title\">Record Cloned Successfully</h3>\n <p class=\"result-subtitle\">\n @if (RootRecordName) {\n <strong>{{RootRecordName}}</strong> has been created.\n } @else {\n New {{EntityName}} record and its hierarchy have been created.\n }\n </p>\n\n <!-- Summary Badges -->\n <div class=\"result-stats\">\n <mj-stat-badge\n [Count]=\"CreatedCount\"\n Label=\"created\"\n Variant=\"success\"\n Icon=\"fa-solid fa-plus\">\n </mj-stat-badge>\n\n @if (ReferencedCount > 0) {\n <mj-stat-badge\n [Count]=\"ReferencedCount\"\n Label=\"referenced\"\n Variant=\"info\"\n Icon=\"fa-solid fa-link\">\n </mj-stat-badge>\n }\n </div>\n\n <!-- Warnings if any -->\n @if (Result?.Warnings && Result!.Warnings!.length > 0) {\n <div class=\"result-warnings-box\">\n <span class=\"warnings-title\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n Execution Warnings ({{Result!.Warnings!.length}})\n </span>\n <ul class=\"warnings-list\">\n @for (warn of Result!.Warnings; track warn.Code + (warn.NodeKey || '') + $index) {\n <li>{{warn.Message}}</li>\n }\n </ul>\n </div>\n }\n\n <!-- Primary CTAs -->\n <div class=\"result-actions\">\n <button\n type=\"button\"\n mjButton\n variant=\"primary\"\n (click)=\"OnOpenClone()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i>\n Open Cloned Record\n </button>\n\n <button\n type=\"button\"\n mjButton\n variant=\"secondary\"\n (click)=\"OnCloneAnother()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n Clone Another\n </button>\n\n <button\n type=\"button\"\n mjButton\n variant=\"outline\"\n (click)=\"OnClose()\">\n Close\n </button>\n </div>\n\n <!-- Audit Log Link -->\n @if (Result?.CloneLogID) {\n <div class=\"audit-log-footer\">\n <button\n type=\"button\"\n class=\"audit-link-btn\"\n (click)=\"OnOpenCloneLog()\">\n <i class=\"fa-solid fa-file-lines\"></i>\n View Clone Log [{{Result?.CloneLogID}}]\n </button>\n </div>\n }\n } @else {\n <!-- Failure State -->\n <div class=\"result-icon-wrapper failure\">\n <i class=\"fa-solid fa-circle-xmark result-icon\"></i>\n </div>\n <h3 class=\"result-title failure-text\">Cloning Failed</h3>\n <p class=\"result-subtitle failure-message\">\n {{Result?.ErrorMessage || 'An error occurred during execution. No records were modified.'}}\n </p>\n\n <div class=\"result-actions\">\n <button\n type=\"button\"\n mjButton\n variant=\"primary\"\n (click)=\"OnCloneAnother()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n Try Again\n </button>\n\n <button\n type=\"button\"\n mjButton\n variant=\"outline\"\n (click)=\"OnClose()\">\n Close\n </button>\n </div>\n }\n </div>\n `,\n styles: [`\n .clone-result-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n padding: var(--mj-space-8) var(--mj-space-4);\n gap: var(--mj-space-4);\n }\n\n .result-icon-wrapper {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .result-icon-wrapper.success {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n }\n\n .result-icon-wrapper.failure {\n background: var(--mj-status-error-bg);\n color: var(--mj-status-error-text);\n }\n\n .result-icon {\n font-size: 32px;\n }\n\n .result-title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n color: var(--mj-text-primary);\n }\n\n .failure-text {\n color: var(--mj-status-error-text);\n }\n\n .result-subtitle {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n max-width: 440px;\n }\n\n .failure-message {\n color: var(--mj-status-error-text);\n }\n\n .result-stats {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: var(--mj-space-1) 0;\n }\n\n .result-warnings-box {\n text-align: left;\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-2) var(--mj-space-3);\n max-width: 440px;\n width: 100%;\n }\n\n .warnings-title {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-status-warning-text);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .warnings-list {\n margin: 4px 0 0;\n padding-left: 18px;\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n }\n\n .result-actions {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-2);\n flex-wrap: wrap;\n justify-content: center;\n }\n\n .audit-log-footer {\n margin-top: var(--mj-space-2);\n }\n\n .audit-link-btn {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: var(--mj-text-xs);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n text-decoration: underline;\n }\n\n .audit-link-btn:hover {\n color: var(--mj-brand-primary-hover);\n }\n `],\n imports: [\n CommonModule,\n MJButtonDirective,\n MJStatBadgeComponent,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CloneResultComponent {\n /** Execute output to summarize. */\n @Input() Result: RecordCloneExecuteOutput | null = null;\n /** Entity of the root clone. */\n @Input() EntityName = 'Record';\n /** Record-id string of the root clone; falls back to `Result.Roots[0].TargetKey`. */\n @Input() TargetKey: string | null = null;\n /** Display name of the new root record. */\n @Input() RootRecordName?: string;\n\n /** Fires with the root clone's key when the user opens it. `NavigateToRecord` fires too. */\n @Output() OpenClone = new EventEmitter<string>();\n /** The user wants to clone the source again. */\n @Output() CloneAnother = new EventEmitter<void>();\n /** The user closed the result. */\n @Output() Close = new EventEmitter<void>();\n /** Fires with the clone log ID when the user opens the log. `NavigateToRecord` fires too. */\n @Output() OpenCloneLog = new EventEmitter<string>();\n /** Asks the host to open the clone or the clone log record. */\n @Output() NavigateToRecord = new EventEmitter<CloneNavigationEvent>();\n\n public get CreatedCount(): number {\n return this.Result?.Created?.length ?? this.Result?.Counts?.Create ?? 1;\n }\n\n public get ReferencedCount(): number {\n if (!this.Result?.Counts?.ByEntity) return 0;\n return Object.values(this.Result.Counts.ByEntity).reduce((acc, c) => acc + (c.Reference || 0), 0);\n }\n\n public OnOpenClone(): void {\n const raw = this.TargetKey || this.Result?.Roots?.[0]?.TargetKey;\n if (raw) {\n const key = typeof raw === 'string'\n ? raw\n : (raw as CompositeKey)?.ToURLSegment?.() ?? (raw as CompositeKey)?.ToConcatenatedString?.() ?? String(raw);\n this.OpenClone.emit(key);\n this.NavigateToRecord.emit({\n Kind: 'record',\n EntityName: this.EntityName,\n RecordKey: key,\n });\n }\n }\n\n public OnCloneAnother(): void {\n this.CloneAnother.emit();\n }\n\n public OnClose(): void {\n this.Close.emit();\n }\n\n public OnOpenCloneLog(): void {\n if (this.Result?.CloneLogID) {\n this.OpenCloneLog.emit(this.Result.CloneLogID);\n this.NavigateToRecord.emit({\n Kind: 'record',\n EntityName: 'MJ: Record Clone Logs',\n RecordKey: this.Result.CloneLogID,\n });\n }\n }\n}\n"]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @fileoverview Review and preflight execution component for record cloning.
3
+ *
4
+ * Implements §12.3 & §12.4 of the Record Cloning architectural blueprint. Displays
5
+ * stat badges (Create / Reference / Skip / Warnings), blocked alert banner with reasons,
6
+ * warnings grouped by severity linking to nodes, field-change diffs, and confirmation actions.
7
+ */
8
+ import { EventEmitter } from '@angular/core';
9
+ import type { RecordClonePlanDetails, RecordClonePlanNode, RecordClonePlanWarning, RecordClonePlanFieldChange } from '@memberjunction/core-entities';
10
+ import * as i0 from "@angular/core";
11
+ interface NodeFieldChangesSummary {
12
+ Node: RecordClonePlanNode;
13
+ Changes: RecordClonePlanFieldChange[];
14
+ }
15
+ export declare class CloneReviewComponent {
16
+ /** The plan to review: counts, warnings, blocked reasons and per-node field changes. */
17
+ Plan: RecordClonePlanDetails | null;
18
+ /** Name the root clone will get. */
19
+ RootName: string;
20
+ /** Reason the user entered, shown for confirmation. */
21
+ Reason: string;
22
+ /** Disables Confirm while the clone runs. */
23
+ IsExecuting: boolean;
24
+ /** Disables Confirm while the plan is being recomputed, so the user never confirms a plan they haven't seen. */
25
+ IsPlanning: boolean;
26
+ /** The user confirmed; the host executes the plan. */
27
+ Confirm: EventEmitter<void>;
28
+ /** The user backed out of the clone. */
29
+ Cancel: EventEmitter<void>;
30
+ /** Fires with a node key when the user clicks a warning or node to inspect it. */
31
+ NodeClicked: EventEmitter<string>;
32
+ get IsBlocked(): boolean;
33
+ get CreateCount(): number;
34
+ get ReferenceCount(): number;
35
+ get SkipCount(): number;
36
+ get AllWarnings(): RecordClonePlanWarning[];
37
+ get BlockingErrors(): RecordClonePlanWarning[];
38
+ get NonBlockingWarnings(): RecordClonePlanWarning[];
39
+ get TotalWarningsCount(): number;
40
+ /**
41
+ * The field changes a reviewer needs: every rule the clone applies (reset, ownership, rename,
42
+ * remap, derived rule, override, prompt), configured exclusions and FLS denials. Plain copies,
43
+ * columns that can't be written, and the automatic key and __mj_ timestamp exclusions are left out:
44
+ * they are the same for every clone and would bury the rest.
45
+ */
46
+ get NodesWithFieldChanges(): NodeFieldChangesSummary[];
47
+ private static isReviewable;
48
+ get TotalFieldChangesCount(): number;
49
+ FormatChangeKind(kind: string): string;
50
+ FormatDiffValue(val: unknown): string;
51
+ OnNodeClick(nodeKey: string): void;
52
+ OnConfirm(): void;
53
+ OnCancel(): void;
54
+ static ɵfac: i0.ɵɵFactoryDeclaration<CloneReviewComponent, never>;
55
+ static ɵcmp: i0.ɵɵComponentDeclaration<CloneReviewComponent, "mj-clone-review", never, { "Plan": { "alias": "Plan"; "required": false; }; "RootName": { "alias": "RootName"; "required": false; }; "Reason": { "alias": "Reason"; "required": false; }; "IsExecuting": { "alias": "IsExecuting"; "required": false; }; "IsPlanning": { "alias": "IsPlanning"; "required": false; }; }, { "Confirm": "Confirm"; "Cancel": "Cancel"; "NodeClicked": "NodeClicked"; }, never, never, true, never>;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=clone-review.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-review.component.d.ts","sourceRoot":"","sources":["../../src/lib/clone-review.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAKH,YAAY,EACf,MAAM,eAAe,CAAC;AAMvB,OAAO,KAAK,EACR,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC7B,MAAM,+BAA+B,CAAC;;AAEvC,UAAU,uBAAuB;IAC7B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACzC;AAED,qBAmba,oBAAoB;IAC7B,wFAAwF;IAC/E,IAAI,EAAE,sBAAsB,GAAG,IAAI,CAAQ;IACpD,oCAAoC;IAC3B,QAAQ,SAAM;IACvB,uDAAuD;IAC9C,MAAM,SAAM;IACrB,6CAA6C;IACpC,WAAW,UAAS;IAC7B,gHAAgH;IACvG,UAAU,UAAS;IAE5B,sDAAsD;IAC5C,OAAO,qBAA4B;IAC7C,wCAAwC;IAC9B,MAAM,qBAA4B;IAC5C,kFAAkF;IACxE,WAAW,uBAA8B;IAEnD,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,IAAW,cAAc,IAAI,MAAM,CAGlC;IAED,IAAW,SAAS,IAAI,MAAM,CAG7B;IAED,IAAW,WAAW,IAAI,sBAAsB,EAAE,CAejD;IAED,IAAW,cAAc,IAAI,sBAAsB,EAAE,CAEpD;IAED,IAAW,mBAAmB,IAAI,sBAAsB,EAAE,CAEzD;IAED,IAAW,kBAAkB,IAAI,MAAM,CAEtC;IAED;;;;;OAKG;IACH,IAAW,qBAAqB,IAAI,uBAAuB,EAAE,CAU5D;IAED,OAAO,CAAC,MAAM,CAAC,YAAY;IAS3B,IAAW,sBAAsB,IAAI,MAAM,CAE1C;IAEM,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAItC,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAMrC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,IAAI;yCArHd,oBAAoB;2CAApB,oBAAoB;CA0HhC"}