@memberjunction/ng-record-changes 5.27.1 → 5.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -0
- package/dist/__tests__/restore-version.test.js +102 -152
- package/dist/__tests__/restore-version.test.js.map +1 -1
- package/dist/lib/__tests__/record-changes.test.js +21 -12
- package/dist/lib/__tests__/record-changes.test.js.map +1 -1
- package/dist/lib/ng-record-changes.component.d.ts +171 -49
- package/dist/lib/ng-record-changes.component.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.component.js +645 -416
- package/dist/lib/ng-record-changes.component.js.map +1 -1
- package/dist/lib/ng-record-changes.module.d.ts +6 -5
- package/dist/lib/ng-record-changes.module.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.module.js +9 -4
- package/dist/lib/ng-record-changes.module.js.map +1 -1
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts +267 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts.map +1 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js +748 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js.map +1 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-preview-panel.component.js","sourceRoot":"","sources":["../../../src/lib/restore-preview-panel/restore-preview-panel.component.ts","../../../src/lib/restore-preview-panel/restore-preview-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n EventEmitter,\n Input,\n Output,\n OnInit,\n ViewEncapsulation,\n} from '@angular/core';\nimport {\n BaseEntity,\n EntityFieldInfo,\n EntityFieldTSType,\n EntityInfo,\n Metadata,\n} from '@memberjunction/core';\nimport { MJRecordChangeEntity } from '@memberjunction/core-entities';\n\n/**\n * Mode controls how the preview is rendered and how the restore is interpreted.\n *\n * - `'live'`: target record exists; the preview shows a current-vs-restore\n * diff per field. Confirming applies the snapshot to the live record and\n * triggers an UPDATE.\n * - `'undelete'`: target record was hard-deleted. The preview shows the\n * snapshot fields that will be inserted; confirming triggers an INSERT.\n */\nexport type RestorePreviewMode = 'live' | 'undelete';\n\n/**\n * One row in the restore preview table.\n *\n * Renders as a checkbox + field name + (current / restore) values. The\n * `IsChanged` flag drives the default-checked state and the row's visual\n * treatment. `IsMissingInSchema` and `IsFKMissing` surface drift warnings.\n */\nexport interface RestoreFieldRow {\n /** Raw field name (matches EntityField.Name). */\n FieldName: string;\n /** Friendly label (EntityField.DisplayNameOrName). */\n DisplayName: string;\n /** Formatted current value of the live record (empty in undelete mode). */\n CurrentValue: string;\n /** Formatted snapshot value that would be applied. */\n RestoreValue: string;\n /** Raw snapshot value (the value passed to BaseEntity.Set). */\n RawRestoreValue: unknown;\n /** True when CurrentValue and RestoreValue differ. Drives default checked. */\n IsChanged: boolean;\n /** User's selection — when true, this field will be applied on restore. */\n Selected: boolean;\n /** True when the snapshot references a field that no longer exists on the entity. */\n IsMissingInSchema: boolean;\n /** True when the field is a FK whose target row no longer exists (best-effort). */\n IsFKMissing: boolean;\n /** True when the field is read-only / system / PK and cannot be restored. */\n IsImmutable: boolean;\n}\n\n/**\n * Cancelable event fired immediately after the user clicks Restore but\n * before {@link RestorePreviewPanelComponent.RestoreConfirmed} emits.\n *\n * Consumers can set `cancel = true` (and optionally `cancelReason`) to abort\n * the restore — useful for custom approval workflows, audit logging hooks,\n * or for a consumer that wants to take over the actual save itself.\n */\nexport interface BeforeRestoreCommitEvent {\n /** Set to true to abort. RestoreConfirmed will not fire. */\n cancel: boolean;\n /** Optional explanation surfaced by the consumer. */\n cancelReason?: string;\n /** Selected field names (only fields the user kept checked). */\n SelectedFieldNames: string[];\n /** The full set of rows in the preview, including unselected. */\n AllRows: RestoreFieldRow[];\n /** ID of the source RecordChange row whose state is being restored. */\n SourceChangeID: string;\n /** Optional reason text the user entered. */\n Reason: string | null;\n /** The mode — 'live' (UPDATE) or 'undelete' (INSERT). */\n Mode: RestorePreviewMode;\n}\n\n/**\n * Event payload emitted after the user has confirmed a restore.\n *\n * The host component is responsible for applying the snapshot to a\n * BaseEntity instance, calling {@link BaseEntity.SetRestoreContext}, and\n * invoking Save(). This component never touches the database directly so\n * it remains usable in any consumer context.\n */\nexport interface RestoreCommitEvent {\n /** ID of the source RecordChange row whose state is being restored. */\n SourceChangeID: string;\n /** Optional user-entered reason; persisted to RecordChange.RestoreReason. */\n Reason: string | null;\n /** Selected fields with their snapshot values, ready for BaseEntity.Set. */\n FieldValues: Array<{ FieldName: string; Value: unknown }>;\n /** The full preview rows (including unselected) for audit/logging. */\n AllRows: RestoreFieldRow[];\n /** Mode indicates UPDATE (live) vs INSERT (undelete). */\n Mode: RestorePreviewMode;\n}\n\n/**\n * Reusable slide-in panel that previews a restore operation against a\n * historical {@link MJRecordChangeEntity} and lets the user confirm with\n * field-level granularity.\n *\n * This component is rendered by both:\n * - The Record Changes timeline (for restoring a live record from any past\n * change row)\n * - The Recycle Bin (for re-creating a hard-deleted record from its delete\n * snapshot)\n *\n * It does NOT perform the save itself — the host component receives a\n * {@link RestoreCommitEvent} with the selected field values and is\n * responsible for applying them to a BaseEntity, setting the restore\n * context, and calling Save(). This keeps the component purely\n * presentational and reusable in any context.\n *\n * ### Semantic correctness\n *\n * The preview compares the **full snapshot** captured in the source\n * change's `FullRecordJSON` to the current live record (or to nothing in\n * un-delete mode). It does NOT roll back a single delta — restoring `v2`\n * means \"make the record look like it did at v2\", not \"undo v3's changes\".\n *\n * @example Live restore from the timeline\n * <mj-restore-preview-panel\n * [Visible]=\"showPreview\"\n * [Mode]=\"'live'\"\n * [RecordChange]=\"selectedChange\"\n * [LiveRecord]=\"record\"\n * (RestoreConfirmed)=\"onRestoreConfirmed($event)\"\n * (RestoreCancelled)=\"showPreview = false\">\n * </mj-restore-preview-panel>\n *\n * @example Un-delete from the Recycle Bin\n * <mj-restore-preview-panel\n * [Visible]=\"showPreview\"\n * [Mode]=\"'undelete'\"\n * [RecordChange]=\"deletedChange\"\n * [EntityName]=\"'Customers'\"\n * (RestoreConfirmed)=\"onRecreate($event)\"\n * (RestoreCancelled)=\"showPreview = false\">\n * </mj-restore-preview-panel>\n */\n@Component({\n standalone: false,\n selector: 'mj-restore-preview-panel',\n templateUrl: './restore-preview-panel.component.html',\n styleUrls: ['./restore-preview-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class RestorePreviewPanelComponent implements OnInit {\n // ─── Inputs ─────────────────────────────────────────────────────\n\n /**\n * Controls panel visibility. Setting to true opens the slide-in;\n * setting to false closes it.\n */\n @Input() Visible = false;\n\n /**\n * Operating mode — `'live'` for restoring an existing record from a\n * snapshot, `'undelete'` for re-creating a hard-deleted record.\n */\n @Input() Mode: RestorePreviewMode = 'live';\n\n /**\n * The historical RecordChange row whose state will be restored. Required.\n * The component reads `FullRecordJSON` from this entity to determine the\n * target state. The change's `Type` does not matter — `Create`,\n * `Update`, `Snapshot`, and `Delete` are all valid restore sources.\n */\n private _recordChange: MJRecordChangeEntity | null = null;\n @Input()\n set RecordChange(value: MJRecordChangeEntity | null) {\n this._recordChange = value;\n if (this.isInitialized) this.rebuildRows();\n }\n get RecordChange(): MJRecordChangeEntity | null {\n return this._recordChange;\n }\n\n /**\n * The current live record to diff against. Required in `'live'` mode,\n * ignored in `'undelete'` mode (since the live record no longer exists).\n */\n private _liveRecord: BaseEntity | null = null;\n @Input()\n set LiveRecord(value: BaseEntity | null) {\n this._liveRecord = value;\n if (this.isInitialized) this.rebuildRows();\n }\n get LiveRecord(): BaseEntity | null {\n return this._liveRecord;\n }\n\n /**\n * The entity name. Required in `'undelete'` mode (since there's no live\n * record to read it from). In `'live'` mode it can be omitted and is\n * inferred from the LiveRecord.\n */\n @Input() EntityName: string | null = null;\n\n /**\n * When true, the Restore button is disabled until the user enters a\n * non-empty reason. Useful for regulated environments where every\n * reversal needs justification. Default: false.\n */\n @Input() RequireReason = false;\n\n /**\n * When true, hides the optional reason text area entirely. Default: false.\n */\n @Input() HideReason = false;\n\n // ─── Outputs ────────────────────────────────────────────────────\n\n /**\n * Cancelable event fired when the user clicks Restore but before\n * {@link RestoreConfirmed} emits. Consumers can set `cancel = true` on\n * the event arg to abort the operation — useful for custom approval\n * workflows or for taking over the save themselves.\n */\n @Output() BeforeRestoreCommit = new EventEmitter<BeforeRestoreCommitEvent>();\n\n /**\n * Emitted after the user confirms the restore (and BeforeRestoreCommit\n * was not cancelled). The host is responsible for applying the field\n * values to a BaseEntity, calling SetRestoreContext, and invoking Save().\n */\n @Output() RestoreConfirmed = new EventEmitter<RestoreCommitEvent>();\n\n /**\n * Emitted when the user cancels the preview without restoring.\n */\n @Output() RestoreCancelled = new EventEmitter<void>();\n\n // ─── Public state (read by template) ────────────────────────────\n\n public Rows: RestoreFieldRow[] = [];\n public Reason = '';\n public IsRestoring = false;\n public ShowUnchanged = false;\n\n /** Number of rows where the current value differs from the snapshot. */\n public ChangedCount = 0;\n /** Number of rows that are checked (will be applied on restore). */\n public SelectedCount = 0;\n /** Number of rows the schema has dropped or renamed since the snapshot. */\n public DriftCount = 0;\n\n private isInitialized = false;\n private resolvedEntityInfo: EntityInfo | null = null;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n this.isInitialized = true;\n this.rebuildRows();\n }\n\n // ─── Public methods ─────────────────────────────────────────────\n\n /**\n * Toggles whether unchanged rows are visible in the table. When false\n * (default), only rows where current ≠ snapshot are shown.\n */\n public ToggleUnchanged(): void {\n this.ShowUnchanged = !this.ShowUnchanged;\n this.cdr.markForCheck();\n }\n\n /**\n * Toggles whether a single row is selected for restore. Updates the\n * SelectedCount in real time so the primary button label reflects it.\n */\n public ToggleRow(row: RestoreFieldRow): void {\n if (row.IsImmutable || row.IsMissingInSchema) return;\n row.Selected = !row.Selected;\n this.recountSelected();\n this.cdr.markForCheck();\n }\n\n /**\n * Selects every row that can be selected (skips immutable / drifted).\n */\n public SelectAll(): void {\n for (const row of this.Rows) {\n if (!row.IsImmutable && !row.IsMissingInSchema) row.Selected = true;\n }\n this.recountSelected();\n this.cdr.markForCheck();\n }\n\n /**\n * Deselects every row in the preview.\n */\n public DeselectAll(): void {\n for (const row of this.Rows) row.Selected = false;\n this.recountSelected();\n this.cdr.markForCheck();\n }\n\n /**\n * User clicked Restore — fire BeforeRestoreCommit (cancelable), then\n * RestoreConfirmed if not cancelled.\n */\n public ConfirmRestore(): void {\n if (!this._recordChange) return;\n if (this.IsRestoreDisabled) return;\n\n const selected = this.Rows.filter(r => r.Selected && !r.IsMissingInSchema && !r.IsImmutable);\n const reason = this.Reason.trim() ? this.Reason.trim() : null;\n\n const beforeEvent: BeforeRestoreCommitEvent = {\n cancel: false,\n SelectedFieldNames: selected.map(r => r.FieldName),\n AllRows: this.Rows.slice(),\n SourceChangeID: this._recordChange.ID,\n Reason: reason,\n Mode: this.Mode,\n };\n this.BeforeRestoreCommit.emit(beforeEvent);\n if (beforeEvent.cancel) return;\n\n this.IsRestoring = true;\n this.cdr.markForCheck();\n\n const commitEvent: RestoreCommitEvent = {\n SourceChangeID: this._recordChange.ID,\n Reason: reason,\n FieldValues: selected.map(r => ({ FieldName: r.FieldName, Value: r.RawRestoreValue })),\n AllRows: this.Rows.slice(),\n Mode: this.Mode,\n };\n this.RestoreConfirmed.emit(commitEvent);\n }\n\n /**\n * User cancelled the preview. Resets state and emits RestoreCancelled.\n */\n public Cancel(): void {\n this.RestoreCancelled.emit();\n }\n\n /**\n * Resets internal state — useful after a save completes so the panel\n * can be reopened cleanly. Called by the host component when needed.\n */\n public Reset(): void {\n this.Reason = '';\n this.IsRestoring = false;\n this.ShowUnchanged = false;\n this.rebuildRows();\n }\n\n // ─── Computed getters (template) ────────────────────────────────\n\n public get IsRestoreDisabled(): boolean {\n if (this.IsRestoring) return true;\n if (this.SelectedCount === 0) return true;\n if (this.RequireReason && this.Reason.trim().length === 0) return true;\n return false;\n }\n\n public get RestoreButtonLabel(): string {\n if (this.IsRestoring) return 'Restoring…';\n if (this.Mode === 'undelete') {\n return this.SelectedCount > 0 ? `Re-create (${this.SelectedCount} field${this.SelectedCount === 1 ? '' : 's'})` : 'Re-create';\n }\n return this.SelectedCount > 0 ? `Restore (${this.SelectedCount} field${this.SelectedCount === 1 ? '' : 's'})` : 'Restore';\n }\n\n public get HeaderTitle(): string {\n return this.Mode === 'undelete' ? 'Re-create from snapshot' : 'Restore record to this version';\n }\n\n public get VersionTimestamp(): Date | null {\n return this._recordChange?.ChangedAt ?? null;\n }\n\n public get VersionUser(): string {\n return this._recordChange?.User ?? '';\n }\n\n public get UnchangedCount(): number {\n return this.Rows.length - this.ChangedCount;\n }\n\n // ─── Internal: row building ─────────────────────────────────────\n\n /**\n * Rebuilds the Rows array from the current RecordChange + LiveRecord.\n * Idempotent and cheap — safe to call from input setters.\n */\n private rebuildRows(): void {\n this.Rows = [];\n this.ChangedCount = 0;\n this.SelectedCount = 0;\n this.DriftCount = 0;\n\n if (!this._recordChange) {\n this.cdr.markForCheck();\n return;\n }\n\n const snapshot = this.parseSnapshot(this._recordChange.FullRecordJSON);\n if (!snapshot) {\n this.cdr.markForCheck();\n return;\n }\n\n const entityInfo = this.resolveEntityInfo();\n if (!entityInfo) {\n this.cdr.markForCheck();\n return;\n }\n\n // Build a row for every field in the snapshot. We iterate the snapshot\n // (not EntityInfo.Fields) so fields that exist in the snapshot but no\n // longer in the schema surface as drift warnings.\n const seen = new Set<string>();\n for (const fieldName of Object.keys(snapshot)) {\n seen.add(fieldName.toLowerCase());\n const row = this.buildRowFromSnapshot(fieldName, snapshot[fieldName], entityInfo);\n if (row) this.Rows.push(row);\n }\n\n // Sort: changed rows first, then unchanged. Within each group, by display name.\n this.Rows.sort((a, b) => {\n if (a.IsChanged !== b.IsChanged) return a.IsChanged ? -1 : 1;\n return a.DisplayName.localeCompare(b.DisplayName);\n });\n\n this.ChangedCount = this.Rows.filter(r => r.IsChanged).length;\n this.DriftCount = this.Rows.filter(r => r.IsMissingInSchema).length;\n this.recountSelected();\n this.cdr.markForCheck();\n }\n\n private buildRowFromSnapshot(\n fieldName: string,\n snapshotValue: unknown,\n entityInfo: EntityInfo,\n ): RestoreFieldRow | null {\n const field = entityInfo.Fields.find(\n (f: EntityFieldInfo) => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase(),\n );\n\n // Skip system / timestamp fields that the platform manages.\n if (fieldName.startsWith('__mj_')) return null;\n\n const isImmutable = !!field && (field.ReadOnly || field.IsPrimaryKey);\n const isMissingInSchema = !field;\n const isDateField = field?.TSType === EntityFieldTSType.Date;\n\n const formattedRestore = this.formatValue(snapshotValue, isDateField);\n const formattedCurrent = this.Mode === 'undelete'\n ? ''\n : this.getCurrentFieldValue(fieldName, isDateField);\n\n const isChanged = this.Mode === 'undelete'\n ? snapshotValue != null && snapshotValue !== ''\n : formattedCurrent !== formattedRestore;\n\n // Default selection: pre-check changed rows that we can actually apply.\n const selected = isChanged && !isImmutable && !isMissingInSchema;\n\n return {\n FieldName: fieldName,\n DisplayName: field?.DisplayNameOrName ?? fieldName,\n CurrentValue: formattedCurrent,\n RestoreValue: formattedRestore,\n RawRestoreValue: snapshotValue,\n IsChanged: isChanged,\n Selected: selected,\n IsMissingInSchema: isMissingInSchema,\n IsFKMissing: false, // Reserved for future FK-existence check\n IsImmutable: isImmutable,\n };\n }\n\n private getCurrentFieldValue(fieldName: string, isDateField: boolean): string {\n if (!this._liveRecord) return '';\n const field = this._liveRecord.Fields.find(\n f => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase(),\n );\n if (!field) return '';\n return this.formatValue(field.Value, isDateField);\n }\n\n private parseSnapshot(json: string | null | undefined): Record<string, unknown> | null {\n if (!json) return null;\n try {\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n\n /**\n * Resolves the entity metadata. Prefers LiveRecord.EntityInfo (always\n * accurate). Falls back to looking up by EntityName. Memoized.\n */\n private resolveEntityInfo(): EntityInfo | null {\n if (this.resolvedEntityInfo) return this.resolvedEntityInfo;\n if (this._liveRecord?.EntityInfo) {\n this.resolvedEntityInfo = this._liveRecord.EntityInfo;\n return this.resolvedEntityInfo;\n }\n if (this.EntityName) {\n const md = new Metadata();\n const ei = md.Entities.find(\n e => e.Name.trim().toLowerCase() === this.EntityName!.trim().toLowerCase(),\n );\n this.resolvedEntityInfo = ei ?? null;\n return this.resolvedEntityInfo;\n }\n return null;\n }\n\n private formatValue(value: unknown, isDateField: boolean): string {\n if (value == null) return '';\n if (typeof value === 'object') {\n const keys = Object.keys(value as Record<string, unknown>);\n if (keys.length === 0) return '';\n return JSON.stringify(value);\n }\n if (isDateField && typeof value === 'string') {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(date);\n }\n }\n return String(value);\n }\n\n private recountSelected(): void {\n this.SelectedCount = this.Rows.filter(r => r.Selected).length;\n }\n\n // ─── Display helpers (template) ─────────────────────────────────\n\n public formatTimestamp(date: Date | null): string {\n if (!date) return '';\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(new Date(date));\n }\n}\n","<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"HeaderTitle\"\n [Visible]=\"Visible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"500\"\n [MaxWidthRatio]=\"0.7\"\n (Closed)=\"Cancel()\">\n\n @if (RecordChange) {\n <div class=\"rpp-container\">\n\n <!-- Header summary block -->\n <div class=\"rpp-header\">\n <div class=\"rpp-header-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"rpp-header-text\">\n <div class=\"rpp-header-title\">{{ HeaderTitle }}</div>\n <div class=\"rpp-header-meta\">\n <span><strong>Version:</strong> {{ formatTimestamp(VersionTimestamp) }}</span>\n @if (VersionUser) {\n <span><strong>By:</strong> {{ VersionUser }}</span>\n }\n </div>\n </div>\n </div>\n\n <!-- Drift warning -->\n @if (DriftCount > 0) {\n <div class=\"rpp-banner rpp-banner-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n <span>{{ DriftCount }} field{{ DriftCount === 1 ? '' : 's' }} from this snapshot no longer exist on the entity and will be skipped.</span>\n </div>\n }\n\n <!-- Empty state -->\n @if (Rows.length === 0) {\n <div class=\"rpp-empty\">\n <i class=\"fa-solid fa-circle-info\" aria-hidden=\"true\"></i>\n <p>No fields could be parsed from this snapshot.</p>\n </div>\n }\n\n <!-- Action bar (select all / deselect all) -->\n @if (Rows.length > 0 && Mode !== 'undelete') {\n <div class=\"rpp-action-bar\">\n <span class=\"rpp-action-bar-label\">{{ ChangedCount }} field{{ ChangedCount === 1 ? '' : 's' }} differ from current</span>\n <div class=\"rpp-action-bar-buttons\">\n <button class=\"rpp-link-btn\" type=\"button\" (click)=\"SelectAll()\" [disabled]=\"IsRestoring\">Select all changed</button>\n <span class=\"rpp-action-bar-sep\">·</span>\n <button class=\"rpp-link-btn\" type=\"button\" (click)=\"DeselectAll()\" [disabled]=\"IsRestoring\">Deselect all</button>\n </div>\n </div>\n }\n\n <!-- Diff table -->\n @if (Rows.length > 0) {\n <div class=\"rpp-table-wrap\">\n <table class=\"rpp-table\">\n <thead>\n <tr>\n <th class=\"rpp-col-check\"></th>\n <th class=\"rpp-col-field\">Field</th>\n @if (Mode === 'live') {\n <th class=\"rpp-col-current\">Current Value</th>\n <th class=\"rpp-col-restore\">Restore To</th>\n } @else {\n <th class=\"rpp-col-restore\" colspan=\"2\">Will be created with</th>\n }\n <th class=\"rpp-col-flag\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of Rows; track row.FieldName) {\n @if (row.IsChanged || ShowUnchanged) {\n <tr [class.rpp-row-changed]=\"row.IsChanged\"\n [class.rpp-row-unchanged]=\"!row.IsChanged\"\n [class.rpp-row-immutable]=\"row.IsImmutable\"\n [class.rpp-row-drift]=\"row.IsMissingInSchema\">\n <td class=\"rpp-col-check\">\n <button type=\"button\"\n class=\"rpp-checkbox\"\n [class.checked]=\"row.Selected\"\n [class.disabled]=\"row.IsImmutable || row.IsMissingInSchema\"\n [disabled]=\"row.IsImmutable || row.IsMissingInSchema || IsRestoring\"\n [attr.aria-label]=\"'Toggle ' + row.DisplayName\"\n (click)=\"ToggleRow(row)\">\n @if (row.Selected) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n }\n </button>\n </td>\n <td class=\"rpp-col-field\">\n <div class=\"rpp-field-display\">{{ row.DisplayName }}</div>\n <div class=\"rpp-field-name\">{{ row.FieldName }}</div>\n </td>\n @if (Mode === 'live') {\n <td class=\"rpp-col-current\" [class.rpp-empty-cell]=\"!row.CurrentValue\">\n {{ row.CurrentValue || '(empty)' }}\n </td>\n <td class=\"rpp-col-restore\" [class.rpp-empty-cell]=\"!row.RestoreValue\">\n {{ row.RestoreValue || '(empty)' }}\n </td>\n } @else {\n <td class=\"rpp-col-restore\" colspan=\"2\" [class.rpp-empty-cell]=\"!row.RestoreValue\">\n {{ row.RestoreValue || '(empty)' }}\n </td>\n }\n <td class=\"rpp-col-flag\">\n @if (row.IsMissingInSchema) {\n <i class=\"fa-solid fa-triangle-exclamation rpp-flag-drift\"\n title=\"This field no longer exists on the entity and will be skipped\"\n aria-hidden=\"true\"></i>\n } @else if (row.IsImmutable) {\n <i class=\"fa-solid fa-lock rpp-flag-immutable\"\n title=\"Read-only or system field — cannot be modified\"\n aria-hidden=\"true\"></i>\n } @else if (row.IsChanged) {\n <i class=\"fa-solid fa-circle-exclamation rpp-flag-changed\"\n title=\"Will be changed\"\n aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-check rpp-flag-ok\"\n title=\"Already matches\"\n aria-hidden=\"true\"></i>\n }\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n <!-- Unchanged disclosure -->\n @if (UnchangedCount > 0 && Mode === 'live') {\n <button class=\"rpp-disclosure\" type=\"button\" (click)=\"ToggleUnchanged()\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!ShowUnchanged\"\n [class.fa-chevron-down]=\"ShowUnchanged\"\n aria-hidden=\"true\"></i>\n <span>{{ ShowUnchanged ? 'Hide' : 'Show' }} {{ UnchangedCount }} unchanged field{{ UnchangedCount === 1 ? '' : 's' }}</span>\n </button>\n }\n }\n\n <!-- Reason text area -->\n @if (!HideReason && Rows.length > 0) {\n <div class=\"rpp-reason-section\">\n <label for=\"rpp-reason-input\">\n Reason for restore\n @if (RequireReason) {\n <span class=\"rpp-required\">*</span>\n } @else {\n <span class=\"rpp-optional\">(optional)</span>\n }\n </label>\n <textarea id=\"rpp-reason-input\"\n [(ngModel)]=\"Reason\"\n [disabled]=\"IsRestoring\"\n placeholder=\"e.g., Reverting incorrect Q2 entries\"\n class=\"rpp-reason-textarea\"\n rows=\"2\"></textarea>\n </div>\n }\n </div>\n\n <!-- Footer actions -->\n <div class=\"rpp-footer\">\n <div class=\"rpp-footer-info\">\n <i class=\"fa-solid fa-shield-halved\" aria-hidden=\"true\"></i>\n @if (Mode === 'live') {\n <span>A snapshot of the current state is saved automatically before the restore.</span>\n } @else {\n <span>A new \"Created\" entry will be added to this record's history, linked back to the original deletion.</span>\n }\n </div>\n <div class=\"rpp-footer-actions\">\n <button type=\"button\"\n class=\"rpp-btn rpp-btn-primary\"\n [disabled]=\"IsRestoreDisabled\"\n (click)=\"ConfirmRestore()\">\n @if (IsRestoring) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-rotate-left\" aria-hidden=\"true\"></i>\n }\n {{ RestoreButtonLabel }}\n </button>\n <button type=\"button\"\n class=\"rpp-btn rpp-btn-secondary\"\n [disabled]=\"IsRestoring\"\n (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n }\n</mj-slide-panel>\n"]}
|
package/dist/public-api.d.ts
CHANGED
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6DAA6D,CAAC"}
|
package/dist/public-api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Public API Surface of ng-
|
|
2
|
+
* Public API Surface of @memberjunction/ng-record-changes
|
|
3
3
|
*/
|
|
4
4
|
export * from './lib/ng-record-changes.component';
|
|
5
5
|
export * from './lib/ng-record-changes.module';
|
|
6
|
+
export * from './lib/restore-preview-panel/restore-preview-panel.component';
|
|
6
7
|
//# sourceMappingURL=public-api.js.map
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC","sourcesContent":["/*\n * Public API Surface of ng-
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6DAA6D,CAAC","sourcesContent":["/*\n * Public API Surface of @memberjunction/ng-record-changes\n */\n\nexport * from './lib/ng-record-changes.component';\nexport * from './lib/ng-record-changes.module';\nexport * from './lib/restore-preview-panel/restore-preview-panel.component';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-record-changes",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.29.0",
|
|
4
4
|
"description": "MemberJunction: Angular dialog to show changes made to a specific individual record",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -26,13 +26,14 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@angular/platform-browser": "21.1.3",
|
|
29
|
-
"@memberjunction/core": "5.
|
|
30
|
-
"@memberjunction/core-entities": "5.
|
|
31
|
-
"@memberjunction/global": "5.
|
|
32
|
-
"@memberjunction/ng-notifications": "5.
|
|
33
|
-
"@memberjunction/ng-shared-generic": "5.
|
|
34
|
-
"@memberjunction/ng-versions": "5.
|
|
29
|
+
"@memberjunction/core": "5.29.0",
|
|
30
|
+
"@memberjunction/core-entities": "5.29.0",
|
|
31
|
+
"@memberjunction/global": "5.29.0",
|
|
32
|
+
"@memberjunction/ng-notifications": "5.29.0",
|
|
33
|
+
"@memberjunction/ng-shared-generic": "5.29.0",
|
|
34
|
+
"@memberjunction/ng-versions": "5.29.0",
|
|
35
35
|
"diff": "8.0.3",
|
|
36
|
+
"rxjs": "^7.8.2",
|
|
36
37
|
"tslib": "^2.8.1"
|
|
37
38
|
},
|
|
38
39
|
"sideEffects": false,
|