@memberjunction/ng-record-merge 6.1.0-edge.5 → 6.1.0-edge.6

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.
@@ -104,7 +104,7 @@ function RecordMergePanelComponent_Conditional_0_Conditional_30_Template(rf, ctx
104
104
  i0.ɵɵelementStart(0, "div", 34);
105
105
  i0.ɵɵlistener("click", function RecordMergePanelComponent_Conditional_0_Conditional_30_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ConfirmDialogVisible = false); });
106
106
  i0.ɵɵelementStart(1, "div", 35);
107
- i0.ɵɵlistener("click", function RecordMergePanelComponent_Conditional_0_Conditional_30_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r6); return i0.ɵɵresetView($event.stopPropagation()); });
107
+ i0.ɵɵlistener("click", function RecordMergePanelComponent_Conditional_0_Conditional_30_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
108
108
  i0.ɵɵelementStart(2, "div", 36);
109
109
  i0.ɵɵelement(3, "i", 37);
110
110
  i0.ɵɵelementStart(4, "h4");
@@ -319,7 +319,7 @@ export class RecordMergePanelComponent {
319
319
  i0.ɵɵconditionalCreate(0, RecordMergePanelComponent_Conditional_0_Template, 31, 8)(1, RecordMergePanelComponent_Conditional_1_Template, 1, 0, "mj-empty-state", 0);
320
320
  } if (rf & 2) {
321
321
  i0.ɵɵconditional(ctx.Config && ctx.Comparison ? 0 : 1);
322
- } }, dependencies: [i1.MJEmptyStateComponent], styles: ["\n\n\n.merge-panel[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.merge-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.merge-header-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.merge-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.merge-entity-name[_ngcontent-%COMP%] {\n font-size: 0.82rem;\n color: var(--mj-text-secondary);\n padding: 0.1rem 0.5rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n}\n\n.merge-conflict-badge[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-status-warning-text);\n background: var(--mj-status-warning-bg);\n padding: 0.15rem 0.5rem;\n border-radius: 9999px;\n}\n\n.merge-toggle-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.35rem 0.75rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.78rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.merge-toggle-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n\n.merge-columns[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.merge-col-label[_ngcontent-%COMP%] {\n padding: 0.5rem 0.75rem;\n font-weight: 600;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.merge-select-all-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n font-size: 0.72rem;\n cursor: pointer;\n padding: 0.2rem;\n border-radius: 3px;\n}\n\n.merge-select-all-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n\n\n.merge-fields[_ngcontent-%COMP%] {\n overflow-y: auto;\n max-height: 60vh;\n}\n\n.merge-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n border-bottom: 1px solid var(--mj-border-subtle);\n transition: background 0.1s ease;\n}\n\n.merge-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.merge-row-conflict[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.merge-row-readonly[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.merge-cell[_ngcontent-%COMP%] {\n padding: 0.5rem 0.75rem;\n font-size: 0.85rem;\n display: flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.5rem;\n}\n\n.merge-cell-field[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 500;\n border-right: 1px solid var(--mj-border-subtle);\n}\n\n.merge-field-name[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.merge-readonly-icon[_ngcontent-%COMP%] {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.merge-cell-value[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.merge-cell-selectable[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.merge-cell-selectable[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.merge-cell-selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.merge-value[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n flex: 1;\n word-break: break-word;\n}\n\n.merge-value-empty[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n.merge-check-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 0.75rem;\n flex-shrink: 0;\n}\n\n\n\n.merge-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.merge-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.5rem 1rem;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border: none;\n}\n\n.merge-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.merge-btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.merge-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.merge-btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.merge-btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.merge-dialog-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.merge-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n max-width: 420px;\n width: 100%;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n}\n\n.merge-dialog-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 0.75rem;\n}\n\n.merge-dialog-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1rem;\n color: var(--mj-text-primary);\n}\n\n.merge-dialog-warning-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 1.2rem;\n}\n\n.merge-dialog-text[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 0.9rem;\n line-height: 1.5;\n margin-bottom: 1.25rem;\n}\n\n.merge-dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n\n\n@media (max-width: 768px) {\n .merge-columns[_ngcontent-%COMP%], \n .merge-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .merge-cell-field[_ngcontent-%COMP%] {\n border-right: none;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n }\n\n .merge-col-left[_ngcontent-%COMP%], \n .merge-col-right[_ngcontent-%COMP%] {\n padding-left: 1.5rem;\n }\n}"] });
322
+ } }, dependencies: [i1.MJEmptyStateComponent], styles: ["\n\n.merge-panel[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n\n.merge-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.merge-header-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.merge-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.merge-entity-name[_ngcontent-%COMP%] {\n font-size: 0.82rem;\n color: var(--mj-text-secondary);\n padding: 0.1rem 0.5rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n}\n\n.merge-conflict-badge[_ngcontent-%COMP%] {\n font-size: 0.78rem;\n color: var(--mj-status-warning-text);\n background: var(--mj-status-warning-bg);\n padding: 0.15rem 0.5rem;\n border-radius: 9999px;\n}\n\n.merge-toggle-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.35rem 0.75rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.78rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.merge-toggle-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n\n.merge-columns[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n border-bottom: 2px solid var(--mj-border-default);\n}\n\n.merge-col-label[_ngcontent-%COMP%] {\n padding: 0.5rem 0.75rem;\n font-weight: 600;\n font-size: 0.78rem;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.merge-select-all-btn[_ngcontent-%COMP%] {\n border: none;\n background: none;\n color: var(--mj-text-muted);\n font-size: 0.72rem;\n cursor: pointer;\n padding: 0.2rem;\n border-radius: 3px;\n}\n\n.merge-select-all-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n\n.merge-fields[_ngcontent-%COMP%] {\n overflow-y: auto;\n max-height: 60vh;\n}\n\n.merge-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n border-bottom: 1px solid var(--mj-border-subtle);\n transition: background 0.1s ease;\n}\n\n.merge-row[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.merge-row-conflict[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.merge-row-readonly[_ngcontent-%COMP%] {\n opacity: 0.7;\n}\n\n.merge-cell[_ngcontent-%COMP%] {\n padding: 0.5rem 0.75rem;\n font-size: 0.85rem;\n display: flex;\n align-items: center;\n gap: 0.4rem;\n min-height: 2.5rem;\n}\n\n.merge-cell-field[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 500;\n border-right: 1px solid var(--mj-border-subtle);\n}\n\n.merge-field-name[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.merge-readonly-icon[_ngcontent-%COMP%] {\n font-size: 0.65rem;\n color: var(--mj-text-muted);\n}\n\n.merge-cell-value[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.merge-cell-selectable[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.merge-cell-selectable[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.merge-cell-selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.merge-value[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n flex: 1;\n word-break: break-word;\n}\n\n.merge-value-empty[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n.merge-check-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 0.75rem;\n flex-shrink: 0;\n}\n\n\n.merge-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.merge-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n padding: 0.5rem 1rem;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n border: none;\n}\n\n.merge-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.merge-btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.merge-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.merge-btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.merge-btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n}\n\n\n.merge-dialog-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.merge-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 1.5rem;\n max-width: 420px;\n width: 100%;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n}\n\n.merge-dialog-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 0.75rem;\n}\n\n.merge-dialog-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.1rem;\n color: var(--mj-text-primary);\n}\n\n.merge-dialog-warning-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 1.2rem;\n}\n\n.merge-dialog-text[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-size: 0.9rem;\n line-height: 1.5;\n margin-bottom: 1.25rem;\n}\n\n.merge-dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n\n@media (max-width: 768px) {\n .merge-columns[_ngcontent-%COMP%], \n .merge-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .merge-cell-field[_ngcontent-%COMP%] {\n border-right: none;\n border-bottom: 1px solid var(--mj-border-subtle);\n font-size: 0.78rem;\n }\n\n .merge-col-left[_ngcontent-%COMP%], \n .merge-col-right[_ngcontent-%COMP%] {\n padding-left: 1.5rem;\n }\n}"] });
323
323
  }
324
324
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordMergePanelComponent, [{
325
325
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"record-merge-panel.component.js","sourceRoot":"","sources":["../../src/lib/record-merge-panel.component.ts","../../src/lib/record-merge-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Record Merge Panel Component\n *\n * Side-by-side field comparison panel for entity records.\n * Highlights conflicting values and allows field-by-field selection\n * of which value to keep in the merge result.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n Output,\n OnInit,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport {\n FieldComparison,\n MergeConfig,\n MergeComparisonResult,\n MergeConfirmedEvent,\n FieldSelectionEvent\n} from './record-merge-types';\n\n@Component({\n standalone: false,\n selector: 'mj-record-merge-panel',\n templateUrl: './record-merge-panel.component.html',\n styleUrls: ['./record-merge-panel.component.css']\n})\nexport class RecordMergePanelComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n // --- Inputs ---\n\n /** Field comparisons to display */\n @Input() Fields: FieldComparison[] = [];\n\n /** Merge configuration */\n @Input() Config: MergeConfig | null = null;\n\n /** Whether to show only conflicting fields initially */\n @Input() ShowConflictsOnly = false;\n\n /** Whether the merge action is enabled */\n @Input() MergeEnabled = true;\n\n /** Whether a merge is in progress */\n @Input() IsMerging = false;\n\n // --- Outputs ---\n\n @Output() MergeConfirmed = new EventEmitter<MergeConfirmedEvent>();\n @Output() MergeCancelled = new EventEmitter<void>();\n @Output() FieldSelected = new EventEmitter<FieldSelectionEvent>();\n\n // --- Component State ---\n\n public ShowAllFields = true;\n public Comparison: MergeComparisonResult | null = null;\n public ConfirmDialogVisible = false;\n\n ngOnInit(): void {\n this.ShowAllFields = !this.ShowConflictsOnly;\n this.buildComparison();\n }\n\n /** Toggle between showing all fields and conflicts only */\n public ToggleShowAll(): void {\n this.ShowAllFields = !this.ShowAllFields;\n this.cdr.detectChanges();\n }\n\n /** Select the left value for a field */\n public SelectLeft(field: FieldComparison): void {\n if (field.IsReadOnly) return;\n field.SelectedSide = 'left';\n this.emitFieldSelection(field);\n }\n\n /** Select the right value for a field */\n public SelectRight(field: FieldComparison): void {\n if (field.IsReadOnly) return;\n field.SelectedSide = 'right';\n this.emitFieldSelection(field);\n }\n\n /** Select all fields from the left side */\n public SelectAllLeft(): void {\n for (const field of this.Fields) {\n if (!field.IsReadOnly) {\n field.SelectedSide = 'left';\n }\n }\n this.cdr.detectChanges();\n }\n\n /** Select all fields from the right side */\n public SelectAllRight(): void {\n for (const field of this.Fields) {\n if (!field.IsReadOnly) {\n field.SelectedSide = 'right';\n }\n }\n this.cdr.detectChanges();\n }\n\n /** Get fields to display based on current filter */\n public GetVisibleFields(): FieldComparison[] {\n if (this.ShowAllFields) {\n return this.Fields;\n }\n return this.Fields.filter(f => f.HasConflict);\n }\n\n /** Show the merge confirmation dialog */\n public ShowConfirmDialog(): void {\n this.ConfirmDialogVisible = true;\n this.cdr.detectChanges();\n }\n\n /** Confirm the merge */\n public ConfirmMerge(): void {\n if (!this.Config) return;\n this.ConfirmDialogVisible = false;\n this.MergeConfirmed.emit({\n Config: this.Config,\n ResolvedFields: this.Fields\n });\n }\n\n /** Cancel the merge */\n public CancelMerge(): void {\n this.ConfirmDialogVisible = false;\n this.MergeCancelled.emit();\n }\n\n /** Get the display value for a field value */\n public FormatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return '(empty)';\n }\n if (value instanceof Date) {\n return value.toLocaleString();\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No';\n }\n return String(value);\n }\n\n /** Check if all conflict fields have been resolved */\n public AllConflictsResolved(): boolean {\n if (!this.Comparison) return true;\n return this.Comparison.ConflictFields.every(f => f.SelectedSide === 'left' || f.SelectedSide === 'right');\n }\n\n // --- Private Methods ---\n\n private buildComparison(): void {\n const conflictFields = this.Fields.filter(f => f.HasConflict);\n const matchingFields = this.Fields.filter(f => !f.HasConflict);\n this.Comparison = {\n Fields: this.Fields,\n ConflictFields: conflictFields,\n MatchingFields: matchingFields,\n TotalFieldCount: this.Fields.length,\n ConflictCount: conflictFields.length\n };\n }\n\n private emitFieldSelection(field: FieldComparison): void {\n const value = field.SelectedSide === 'left' ? field.LeftValue :\n field.SelectedSide === 'right' ? field.RightValue :\n field.CustomValue;\n this.FieldSelected.emit({\n FieldName: field.FieldName,\n SelectedSide: field.SelectedSide,\n Value: value\n });\n this.cdr.detectChanges();\n }\n}\n","@if (Config && Comparison) {\n <div class=\"merge-panel\">\n <!-- Header -->\n <div class=\"merge-header\">\n <div class=\"merge-header-info\">\n <h3 class=\"merge-title\">Record Comparison</h3>\n <span class=\"merge-entity-name\">{{ Config.EntityName }}</span>\n <span class=\"merge-conflict-badge\">\n {{ Comparison.ConflictCount }} conflicts / {{ Comparison.TotalFieldCount }} fields\n </span>\n </div>\n <div class=\"merge-header-actions\">\n <button class=\"merge-toggle-btn\" (click)=\"ToggleShowAll()\">\n @if (ShowAllFields) {\n <i class=\"fa-solid fa-filter\"></i> Show Conflicts Only\n } @else {\n <i class=\"fa-solid fa-list\"></i> Show All Fields\n }\n </button>\n </div>\n </div>\n\n <!-- Column Headers -->\n <div class=\"merge-columns\">\n <div class=\"merge-col-label merge-col-field\">Field</div>\n <div class=\"merge-col-label merge-col-left\">\n <span>{{ Config.LeftLabel }}</span>\n <button class=\"merge-select-all-btn\" (click)=\"SelectAllLeft()\" title=\"Select all from left\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n <div class=\"merge-col-label merge-col-right\">\n <span>{{ Config.RightLabel }}</span>\n <button class=\"merge-select-all-btn\" (click)=\"SelectAllRight()\" title=\"Select all from right\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n </div>\n\n <!-- Field Rows -->\n <div class=\"merge-fields\">\n @for (field of GetVisibleFields(); track field.FieldName) {\n <div class=\"merge-row\" [class.merge-row-conflict]=\"field.HasConflict\" [class.merge-row-readonly]=\"field.IsReadOnly\">\n <div class=\"merge-cell merge-cell-field\">\n <span class=\"merge-field-name\">{{ field.DisplayLabel }}</span>\n @if (field.IsReadOnly) {\n <i class=\"fa-solid fa-lock merge-readonly-icon\" title=\"Read-only field\"></i>\n }\n </div>\n <div\n class=\"merge-cell merge-cell-value merge-cell-left\"\n [class.merge-cell-selected]=\"field.SelectedSide === 'left'\"\n [class.merge-cell-selectable]=\"!field.IsReadOnly\"\n (click)=\"SelectLeft(field)\"\n >\n <span class=\"merge-value\" [class.merge-value-empty]=\"field.LeftValue === null || field.LeftValue === undefined\">\n {{ FormatValue(field.LeftValue) }}\n </span>\n @if (field.SelectedSide === 'left' && !field.IsReadOnly) {\n <i class=\"fa-solid fa-check merge-check-icon\"></i>\n }\n </div>\n <div\n class=\"merge-cell merge-cell-value merge-cell-right\"\n [class.merge-cell-selected]=\"field.SelectedSide === 'right'\"\n [class.merge-cell-selectable]=\"!field.IsReadOnly\"\n (click)=\"SelectRight(field)\"\n >\n <span class=\"merge-value\" [class.merge-value-empty]=\"field.RightValue === null || field.RightValue === undefined\">\n {{ FormatValue(field.RightValue) }}\n </span>\n @if (field.SelectedSide === 'right' && !field.IsReadOnly) {\n <i class=\"fa-solid fa-check merge-check-icon\"></i>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Footer Actions -->\n @if (MergeEnabled) {\n <div class=\"merge-footer\">\n <button class=\"merge-btn merge-btn-primary\" (click)=\"ShowConfirmDialog()\" [disabled]=\"IsMerging\">\n @if (IsMerging) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging...\n } @else {\n <i class=\"fa-solid fa-code-merge\"></i> Merge Records\n }\n </button>\n <button class=\"merge-btn merge-btn-secondary\" (click)=\"CancelMerge()\" [disabled]=\"IsMerging\">\n Cancel\n </button>\n </div>\n }\n </div>\n\n <!-- Confirmation Dialog -->\n @if (ConfirmDialogVisible) {\n <div class=\"merge-dialog-backdrop\" (click)=\"ConfirmDialogVisible = false\">\n <div class=\"merge-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"merge-dialog-header\">\n <i class=\"fa-solid fa-exclamation-triangle merge-dialog-warning-icon\"></i>\n <h4>Confirm Merge</h4>\n </div>\n <p class=\"merge-dialog-text\">\n This will merge the selected field values and create a merge log.\n This action cannot be undone. Are you sure?\n </p>\n <div class=\"merge-dialog-actions\">\n <button class=\"merge-btn merge-btn-primary\" (click)=\"ConfirmMerge()\">\n <i class=\"fa-solid fa-code-merge\"></i> Confirm Merge\n </button>\n <button class=\"merge-btn merge-btn-secondary\" (click)=\"ConfirmDialogVisible = false\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n} @else {\n <mj-empty-state\n Icon=\"fa-solid fa-code-compare\"\n Title=\"Select two records to compare\" />\n}\n"]}
1
+ {"version":3,"file":"record-merge-panel.component.js","sourceRoot":"","sources":["../../src/lib/record-merge-panel.component.ts","../../src/lib/record-merge-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Record Merge Panel Component\n *\n * Side-by-side field comparison panel for entity records.\n * Highlights conflicting values and allows field-by-field selection\n * of which value to keep in the merge result.\n */\n\nimport {\n Component,\n EventEmitter,\n Input,\n Output,\n OnInit,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport {\n FieldComparison,\n MergeConfig,\n MergeComparisonResult,\n MergeConfirmedEvent,\n FieldSelectionEvent\n} from './record-merge-types';\n\n@Component({\n standalone: false,\n selector: 'mj-record-merge-panel',\n templateUrl: './record-merge-panel.component.html',\n styleUrls: ['./record-merge-panel.component.css']\n})\nexport class RecordMergePanelComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n // --- Inputs ---\n\n /** Field comparisons to display */\n @Input() Fields: FieldComparison[] = [];\n\n /** Merge configuration */\n @Input() Config: MergeConfig | null = null;\n\n /** Whether to show only conflicting fields initially */\n @Input() ShowConflictsOnly = false;\n\n /** Whether the merge action is enabled */\n @Input() MergeEnabled = true;\n\n /** Whether a merge is in progress */\n @Input() IsMerging = false;\n\n // --- Outputs ---\n\n @Output() MergeConfirmed = new EventEmitter<MergeConfirmedEvent>();\n @Output() MergeCancelled = new EventEmitter<void>();\n @Output() FieldSelected = new EventEmitter<FieldSelectionEvent>();\n\n // --- Component State ---\n\n public ShowAllFields = true;\n public Comparison: MergeComparisonResult | null = null;\n public ConfirmDialogVisible = false;\n\n ngOnInit(): void {\n this.ShowAllFields = !this.ShowConflictsOnly;\n this.buildComparison();\n }\n\n /** Toggle between showing all fields and conflicts only */\n public ToggleShowAll(): void {\n this.ShowAllFields = !this.ShowAllFields;\n this.cdr.detectChanges();\n }\n\n /** Select the left value for a field */\n public SelectLeft(field: FieldComparison): void {\n if (field.IsReadOnly) return;\n field.SelectedSide = 'left';\n this.emitFieldSelection(field);\n }\n\n /** Select the right value for a field */\n public SelectRight(field: FieldComparison): void {\n if (field.IsReadOnly) return;\n field.SelectedSide = 'right';\n this.emitFieldSelection(field);\n }\n\n /** Select all fields from the left side */\n public SelectAllLeft(): void {\n for (const field of this.Fields) {\n if (!field.IsReadOnly) {\n field.SelectedSide = 'left';\n }\n }\n this.cdr.detectChanges();\n }\n\n /** Select all fields from the right side */\n public SelectAllRight(): void {\n for (const field of this.Fields) {\n if (!field.IsReadOnly) {\n field.SelectedSide = 'right';\n }\n }\n this.cdr.detectChanges();\n }\n\n /** Get fields to display based on current filter */\n public GetVisibleFields(): FieldComparison[] {\n if (this.ShowAllFields) {\n return this.Fields;\n }\n return this.Fields.filter(f => f.HasConflict);\n }\n\n /** Show the merge confirmation dialog */\n public ShowConfirmDialog(): void {\n this.ConfirmDialogVisible = true;\n this.cdr.detectChanges();\n }\n\n /** Confirm the merge */\n public ConfirmMerge(): void {\n if (!this.Config) return;\n this.ConfirmDialogVisible = false;\n this.MergeConfirmed.emit({\n Config: this.Config,\n ResolvedFields: this.Fields\n });\n }\n\n /** Cancel the merge */\n public CancelMerge(): void {\n this.ConfirmDialogVisible = false;\n this.MergeCancelled.emit();\n }\n\n /** Get the display value for a field value */\n public FormatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return '(empty)';\n }\n if (value instanceof Date) {\n return value.toLocaleString();\n }\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No';\n }\n return String(value);\n }\n\n /** Check if all conflict fields have been resolved */\n public AllConflictsResolved(): boolean {\n if (!this.Comparison) return true;\n return this.Comparison.ConflictFields.every(f => f.SelectedSide === 'left' || f.SelectedSide === 'right');\n }\n\n // --- Private Methods ---\n\n private buildComparison(): void {\n const conflictFields = this.Fields.filter(f => f.HasConflict);\n const matchingFields = this.Fields.filter(f => !f.HasConflict);\n this.Comparison = {\n Fields: this.Fields,\n ConflictFields: conflictFields,\n MatchingFields: matchingFields,\n TotalFieldCount: this.Fields.length,\n ConflictCount: conflictFields.length\n };\n }\n\n private emitFieldSelection(field: FieldComparison): void {\n const value = field.SelectedSide === 'left' ? field.LeftValue :\n field.SelectedSide === 'right' ? field.RightValue :\n field.CustomValue;\n this.FieldSelected.emit({\n FieldName: field.FieldName,\n SelectedSide: field.SelectedSide,\n Value: value\n });\n this.cdr.detectChanges();\n }\n}\n","@if (Config && Comparison) {\n <div class=\"merge-panel\">\n <!-- Header -->\n <div class=\"merge-header\">\n <div class=\"merge-header-info\">\n <h3 class=\"merge-title\">Record Comparison</h3>\n <span class=\"merge-entity-name\">{{ Config.EntityName }}</span>\n <span class=\"merge-conflict-badge\">\n {{ Comparison.ConflictCount }} conflicts / {{ Comparison.TotalFieldCount }} fields\n </span>\n </div>\n <div class=\"merge-header-actions\">\n <button class=\"merge-toggle-btn\" (click)=\"ToggleShowAll()\">\n @if (ShowAllFields) {\n <i class=\"fa-solid fa-filter\"></i> Show Conflicts Only\n } @else {\n <i class=\"fa-solid fa-list\"></i> Show All Fields\n }\n </button>\n </div>\n </div>\n\n <!-- Column Headers -->\n <div class=\"merge-columns\">\n <div class=\"merge-col-label merge-col-field\">Field</div>\n <div class=\"merge-col-label merge-col-left\">\n <span>{{ Config.LeftLabel }}</span>\n <button class=\"merge-select-all-btn\" (click)=\"SelectAllLeft()\" title=\"Select all from left\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n <div class=\"merge-col-label merge-col-right\">\n <span>{{ Config.RightLabel }}</span>\n <button class=\"merge-select-all-btn\" (click)=\"SelectAllRight()\" title=\"Select all from right\">\n <i class=\"fa-solid fa-check-double\"></i>\n </button>\n </div>\n </div>\n\n <!-- Field Rows -->\n <div class=\"merge-fields\">\n @for (field of GetVisibleFields(); track field.FieldName) {\n <div class=\"merge-row\" [class.merge-row-conflict]=\"field.HasConflict\" [class.merge-row-readonly]=\"field.IsReadOnly\">\n <div class=\"merge-cell merge-cell-field\">\n <span class=\"merge-field-name\">{{ field.DisplayLabel }}</span>\n @if (field.IsReadOnly) {\n <i class=\"fa-solid fa-lock merge-readonly-icon\" title=\"Read-only field\"></i>\n }\n </div>\n <div\n class=\"merge-cell merge-cell-value merge-cell-left\"\n [class.merge-cell-selected]=\"field.SelectedSide === 'left'\"\n [class.merge-cell-selectable]=\"!field.IsReadOnly\"\n (click)=\"SelectLeft(field)\"\n >\n <span class=\"merge-value\" [class.merge-value-empty]=\"field.LeftValue === null || field.LeftValue === undefined\">\n {{ FormatValue(field.LeftValue) }}\n </span>\n @if (field.SelectedSide === 'left' && !field.IsReadOnly) {\n <i class=\"fa-solid fa-check merge-check-icon\"></i>\n }\n </div>\n <div\n class=\"merge-cell merge-cell-value merge-cell-right\"\n [class.merge-cell-selected]=\"field.SelectedSide === 'right'\"\n [class.merge-cell-selectable]=\"!field.IsReadOnly\"\n (click)=\"SelectRight(field)\"\n >\n <span class=\"merge-value\" [class.merge-value-empty]=\"field.RightValue === null || field.RightValue === undefined\">\n {{ FormatValue(field.RightValue) }}\n </span>\n @if (field.SelectedSide === 'right' && !field.IsReadOnly) {\n <i class=\"fa-solid fa-check merge-check-icon\"></i>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Footer Actions -->\n @if (MergeEnabled) {\n <div class=\"merge-footer\">\n <button class=\"merge-btn merge-btn-primary\" (click)=\"ShowConfirmDialog()\" [disabled]=\"IsMerging\">\n @if (IsMerging) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Merging...\n } @else {\n <i class=\"fa-solid fa-code-merge\"></i> Merge Records\n }\n </button>\n <button class=\"merge-btn merge-btn-secondary\" (click)=\"CancelMerge()\" [disabled]=\"IsMerging\">\n Cancel\n </button>\n </div>\n }\n </div>\n\n <!-- Confirmation Dialog -->\n @if (ConfirmDialogVisible) {\n <div class=\"merge-dialog-backdrop\" (click)=\"ConfirmDialogVisible = false\">\n <div class=\"merge-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"merge-dialog-header\">\n <i class=\"fa-solid fa-exclamation-triangle merge-dialog-warning-icon\"></i>\n <h4>Confirm Merge</h4>\n </div>\n <p class=\"merge-dialog-text\">\n This will merge the selected field values and create a merge log.\n This action cannot be undone. Are you sure?\n </p>\n <div class=\"merge-dialog-actions\">\n <button class=\"merge-btn merge-btn-primary\" (click)=\"ConfirmMerge()\">\n <i class=\"fa-solid fa-code-merge\"></i> Confirm Merge\n </button>\n <button class=\"merge-btn merge-btn-secondary\" (click)=\"ConfirmDialogVisible = false\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n} @else {\n <mj-empty-state\n Icon=\"fa-solid fa-code-compare\"\n Title=\"Select two records to compare\" />\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-record-merge",
3
- "version": "6.1.0-edge.5",
3
+ "version": "6.1.0-edge.6",
4
4
  "description": "MemberJunction: Reusable record merge/comparison panel for side-by-side entity record comparison and field-by-field merge selection",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -11,21 +11,21 @@
11
11
  "author": "MemberJunction.com",
12
12
  "license": "BUSL-1.1",
13
13
  "devDependencies": {
14
- "@angular/compiler": "21.1.3",
15
- "@angular/compiler-cli": "21.1.3",
16
- "@memberjunction/ng-test-utils": "6.1.0-edge.5",
14
+ "@angular/compiler": "21.2.22",
15
+ "@angular/compiler-cli": "21.2.22",
16
+ "@memberjunction/ng-test-utils": "6.1.0-edge.6",
17
17
  "vitest": "^4.0.18"
18
18
  },
19
19
  "peerDependencies": {
20
- "@angular/common": "^21.1.3",
21
- "@angular/core": "^21.1.3"
20
+ "@angular/common": "^21.2.22",
21
+ "@angular/core": "^21.2.22"
22
22
  },
23
23
  "dependencies": {
24
- "@memberjunction/ng-ui-components": "6.1.0-edge.5",
25
- "@memberjunction/core": "6.1.0-edge.5",
26
- "@memberjunction/core-entities": "6.1.0-edge.5",
27
- "@memberjunction/global": "6.1.0-edge.5",
28
- "@memberjunction/ng-shared-generic": "6.1.0-edge.5",
24
+ "@memberjunction/ng-ui-components": "6.1.0-edge.6",
25
+ "@memberjunction/core": "6.1.0-edge.6",
26
+ "@memberjunction/core-entities": "6.1.0-edge.6",
27
+ "@memberjunction/global": "6.1.0-edge.6",
28
+ "@memberjunction/ng-shared-generic": "6.1.0-edge.6",
29
29
  "rxjs": "^7.8.2",
30
30
  "tslib": "^2.8.1"
31
31
  },