@memberjunction/ng-record-process-studio 6.1.4 → 6.2.0-edge.1

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 (25) hide show
  1. package/dist/lib/feature-pipeline-builder/feature-pipeline-builder.component.d.ts +163 -0
  2. package/dist/lib/feature-pipeline-builder/feature-pipeline-builder.component.d.ts.map +1 -0
  3. package/dist/lib/feature-pipeline-builder/feature-pipeline-builder.component.js +1400 -0
  4. package/dist/lib/feature-pipeline-builder/feature-pipeline-builder.component.js.map +1 -0
  5. package/dist/lib/record-process-editor/record-process-editor.component.d.ts +19 -1
  6. package/dist/lib/record-process-editor/record-process-editor.component.d.ts.map +1 -1
  7. package/dist/lib/record-process-editor/record-process-editor.component.js +173 -53
  8. package/dist/lib/record-process-editor/record-process-editor.component.js.map +1 -1
  9. package/dist/lib/record-process-history/record-process-history.component.d.ts +10 -0
  10. package/dist/lib/record-process-history/record-process-history.component.d.ts.map +1 -1
  11. package/dist/lib/record-process-history/record-process-history.component.js +30 -10
  12. package/dist/lib/record-process-history/record-process-history.component.js.map +1 -1
  13. package/dist/lib/record-process-studio/record-process-studio.component.d.ts +12 -0
  14. package/dist/lib/record-process-studio/record-process-studio.component.d.ts.map +1 -1
  15. package/dist/lib/record-process-studio/record-process-studio.component.js +31 -7
  16. package/dist/lib/record-process-studio/record-process-studio.component.js.map +1 -1
  17. package/dist/lib/run-detail.d.ts +4 -0
  18. package/dist/lib/run-detail.d.ts.map +1 -1
  19. package/dist/lib/run-detail.js +10 -2
  20. package/dist/lib/run-detail.js.map +1 -1
  21. package/dist/public-api.d.ts +1 -0
  22. package/dist/public-api.d.ts.map +1 -1
  23. package/dist/public-api.js +3 -1
  24. package/dist/public-api.js.map +1 -1
  25. package/package.json +10 -9
@@ -9,7 +9,7 @@ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
9
9
  import { BaseEntity, RunView } from '@memberjunction/core';
10
10
  import { MJEventType, MJGlobal, NormalizeUUID } from '@memberjunction/global';
11
11
  import { MJButtonDirective } from '@memberjunction/ng-ui-components';
12
- import { parseAppliedRunDetailChanges, displayRunValue } from '../run-detail';
12
+ import { ParseAppliedRunDetailChanges, DisplayRunValue } from '../run-detail';
13
13
  import * as i0 from "@angular/core";
14
14
  const _forTrack0 = ($index, $item) => $item.ID;
15
15
  const _forTrack1 = ($index, $item) => $item.RecordID;
@@ -273,7 +273,7 @@ export class RecordProcessHistoryComponent extends BaseAngularComponent {
273
273
  pendingReload = false;
274
274
  reloadTimer = null;
275
275
  async ngOnInit() {
276
- await this.reload();
276
+ await this.Reload();
277
277
  this.subscribeToRunChanges();
278
278
  }
279
279
  ngOnDestroy() {
@@ -309,10 +309,10 @@ export class RecordProcessHistoryComponent extends BaseAngularComponent {
309
309
  }
310
310
  this.reloadTimer = setTimeout(() => {
311
311
  this.reloadTimer = null;
312
- void this.reload();
312
+ void this.Reload();
313
313
  }, 400);
314
314
  }
315
- async reload() {
315
+ async Reload() {
316
316
  this.Loading = true;
317
317
  this.cdr.detectChanges();
318
318
  const rv = RunView.FromMetadataProvider(this.ProviderToUse);
@@ -339,7 +339,11 @@ export class RecordProcessHistoryComponent extends BaseAngularComponent {
339
339
  this.Loading = false;
340
340
  this.cdr.detectChanges();
341
341
  }
342
- async openRun(run) {
342
+ /** @deprecated Use {@link Reload}. */
343
+ async reload() {
344
+ return this.Reload();
345
+ }
346
+ async OpenRun(run) {
343
347
  this.OpenRunRow = run;
344
348
  this.Mode = 'detail';
345
349
  this.DetailLoading = true;
@@ -352,27 +356,43 @@ export class RecordProcessHistoryComponent extends BaseAngularComponent {
352
356
  ExtraFilter: `ProcessRunID='${run.ID}'`, OrderBy: 'Status, RecordID', MaxRows: 1000, ResultType: 'simple',
353
357
  });
354
358
  this.Details = (result.Success ? (result.Results ?? []) : []).map((d) => ({
355
- RecordID: d.RecordID, Status: d.Status, Changes: parseAppliedRunDetailChanges(d.ResultPayload), ErrorMessage: d.ErrorMessage,
359
+ RecordID: d.RecordID, Status: d.Status, Changes: ParseAppliedRunDetailChanges(d.ResultPayload), ErrorMessage: d.ErrorMessage,
356
360
  }));
357
361
  this.DetailLoading = false;
358
362
  this.cdr.detectChanges();
359
363
  }
360
- backToList() {
364
+ /** @deprecated Use {@link OpenRun}. */
365
+ async openRun(run) {
366
+ return this.OpenRun(run);
367
+ }
368
+ BackToList() {
361
369
  this.Mode = 'list';
362
370
  this.OpenRunRow = null;
363
371
  this.cdr.detectChanges();
364
372
  if (this.pendingReload) {
365
373
  this.pendingReload = false;
366
- void this.reload(); // a run changed while we were drilled into a detail — refresh now
374
+ void this.Reload(); // a run changed while we were drilled into a detail — refresh now
367
375
  }
368
376
  }
369
- fmt(value) {
377
+ /** @deprecated Use {@link BackToList}. */
378
+ backToList() {
379
+ return this.BackToList();
380
+ }
381
+ Fmt(value) {
370
382
  if (!value)
371
383
  return '—';
372
384
  const d = value instanceof Date ? value : new Date(value);
373
385
  return isNaN(d.getTime()) ? String(value) : d.toLocaleString();
374
386
  }
375
- disp(value) { return displayRunValue(value); }
387
+ /** @deprecated Use {@link Fmt}. */
388
+ fmt(value) {
389
+ return this.Fmt(value);
390
+ }
391
+ Disp(value) { return DisplayRunValue(value); }
392
+ /** @deprecated Use {@link Disp}. */
393
+ disp(value) {
394
+ return this.Disp(value);
395
+ }
376
396
  static ɵfac = /*@__PURE__*/ (() => { let ɵRecordProcessHistoryComponent_BaseFactory; return function RecordProcessHistoryComponent_Factory(__ngFactoryType__) { return (ɵRecordProcessHistoryComponent_BaseFactory || (ɵRecordProcessHistoryComponent_BaseFactory = i0.ɵɵgetInheritedFactory(RecordProcessHistoryComponent)))(__ngFactoryType__ || RecordProcessHistoryComponent); }; })();
377
397
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordProcessHistoryComponent, selectors: [["mj-record-process-history"]], inputs: { RecordProcessID: "RecordProcessID" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "rph-bar"], [1, "rph-title"], [1, "rph-spacer"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], [1, "rph-msg"], [1, "rph-table"], [1, "fa-solid", "fa-circle-notch", "fa-spin"], [1, "rph-tr", "rph-head"], [1, "rph-tr"], [1, "rph-tr", 3, "click"], [1, "rph-sub"], [1, "rph-nm"], [1, "st"], [1, "dot"], ["title", "Compute-only preview \u2014 no changes were written", 1, "dryrun"], [1, "counts"], [1, "cbadge", "ok"], [1, "cbadge", "err"], [1, "cbadge"], [1, "fa-solid", "fa-arrow-left"], [1, "rph-details"], [1, "rph-detrec"], [1, "rph-detkey"], [1, "st", "sm"], [1, "rph-rk"], [1, "rph-changes"], [1, "rph-chg"], [1, "rph-chg", "err-msg"], [1, "f"], [1, "o"], [1, "fa-solid", "fa-arrow-right-long", "ar"], [1, "nw"]], template: function RecordProcessHistoryComponent_Template(rf, ctx) { if (rf & 1) {
378
398
  i0.ɵɵconditionalCreate(0, RecordProcessHistoryComponent_Conditional_0_Template, 10, 1)(1, RecordProcessHistoryComponent_Conditional_1_Template, 10, 4);
@@ -1 +1 @@
1
- {"version":3,"file":"record-process-history.component.js","sourceRoot":"","sources":["../../../src/lib/record-process-history/record-process-history.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Run history for Bulk Operations: every Record Process run (who/when/scope/status/counts),\n * drilling into the per-record outcome (the field diff persisted on each Process Run Detail). Read-only\n * audit surface. Generic + reusable.\n * @module @memberjunction/ng-record-process-studio\n */\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { BaseEntity, BaseEntityEvent, RunView } from '@memberjunction/core';\nimport { MJEvent, MJEventType, MJGlobal, NormalizeUUID } from '@memberjunction/global';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { parseAppliedRunDetailChanges, displayRunValue, type RunDetailChange } from '../run-detail';\n\ninterface RawRun {\n ID: string; RecordProcessID: string; EntityID: string; Status: string;\n StartTime?: string | Date; SuccessCount?: number; ErrorCount?: number; SkippedCount?: number;\n TotalItemCount?: number; TriggeredBy?: string; SourceType?: string; DryRun?: boolean;\n}\ninterface RunRow extends RawRun { ProcessName: string; EntityName: string; }\n\ninterface RawDetail { RecordID: string; Status: string; ResultPayload?: string; ErrorMessage?: string; }\ninterface DetailRow { RecordID: string; Status: string; Changes: RunDetailChange[]; ErrorMessage?: string; }\n\n@Component({\n selector: 'mj-record-process-history',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MJButtonDirective],\n template: `\n @if (Mode === 'list') {\n <div class=\"rph-bar\">\n <h3 class=\"rph-title\">Run history</h3><span class=\"rph-spacer\"></span>\n <button mjButton variant=\"flat\" (click)=\"reload()\"><i class=\"fa-solid fa-arrows-rotate\"></i> Refresh</button>\n </div>\n @if (Loading) {\n <div class=\"rph-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading…</div>\n } @else if (Runs.length === 0) {\n <div class=\"rph-msg\">No runs yet.</div>\n } @else {\n <div class=\"rph-table\">\n <div class=\"rph-tr rph-head\"><div>When</div><div>Operation</div><div>Entity</div><div>By</div><div>Status</div><div>Counts</div></div>\n @for (r of Runs; track r.ID) {\n <div class=\"rph-tr\" (click)=\"openRun(r)\">\n <div class=\"rph-sub\">{{ fmt(r.StartTime) }}</div>\n <div class=\"rph-nm\">{{ r.ProcessName }}</div>\n <div>{{ r.EntityName }}</div>\n <div class=\"rph-sub\">{{ r.TriggeredBy || '—' }}</div>\n <div><span class=\"st\" [class.ok]=\"r.Status==='Completed'\" [class.err]=\"r.Status==='Failed'\"><span class=\"dot\"></span> {{ r.Status }}</span>@if (r.DryRun) { <span class=\"dryrun\" title=\"Compute-only preview — no changes were written\">Dry Run</span> }</div>\n <div class=\"counts\">\n <span class=\"cbadge ok\">{{ r.SuccessCount || 0 }} ok</span>\n @if (r.ErrorCount) { <span class=\"cbadge err\">{{ r.ErrorCount }} err</span> }\n @if (r.SkippedCount) { <span class=\"cbadge\">{{ r.SkippedCount }} skip</span> }\n </div>\n </div>\n }\n </div>\n }\n } @else {\n <div class=\"rph-bar\">\n <button mjButton variant=\"flat\" (click)=\"backToList()\"><i class=\"fa-solid fa-arrow-left\"></i> Back</button>\n <h3 class=\"rph-title\">{{ OpenRunRow?.ProcessName }} · {{ fmt(OpenRunRow?.StartTime) }}</h3>\n @if (OpenRunRow?.DryRun) { <span class=\"dryrun\" title=\"Compute-only preview — no changes were written\">Dry Run</span> }\n </div>\n @if (DetailLoading) {\n <div class=\"rph-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading details…</div>\n } @else if (Details.length === 0) {\n <div class=\"rph-msg\">No per-record details recorded for this run.</div>\n } @else {\n <div class=\"rph-details\">\n @for (d of Details; track d.RecordID) {\n <div class=\"rph-detrec\">\n <div class=\"rph-detkey\">\n <span class=\"st sm\" [class.ok]=\"d.Status==='Succeeded'\" [class.err]=\"d.Status==='Failed'\" [class.muted]=\"d.Status==='Skipped'\"><span class=\"dot\"></span> {{ d.Status }}</span>\n <div class=\"rph-rk\">{{ d.RecordID }}</div>\n </div>\n <div class=\"rph-changes\">\n @for (c of d.Changes; track c.Field) {\n <div class=\"rph-chg\"><span class=\"f\">{{ c.Field }}</span>\n <span class=\"o\">{{ disp(c.OldValue) }}</span><i class=\"fa-solid fa-arrow-right-long ar\"></i><span class=\"nw\">{{ disp(c.NewValue) }}</span></div>\n }\n @if (d.ErrorMessage) { <div class=\"rph-chg err-msg\">{{ d.ErrorMessage }}</div> }\n @if (d.Changes.length === 0 && !d.ErrorMessage) { <span class=\"rph-sub\">no changes</span> }\n </div>\n </div>\n }\n </div>\n }\n }\n `,\n styles: [`\n :host{display:block;color:var(--mj-text-primary)}\n .rph-bar{display:flex;align-items:center;gap:14px;margin-bottom:16px}\n .rph-title{margin:0;font-size:16px;font-weight:700}\n .rph-spacer{flex:1}\n .rph-bar button i{margin-right:6px}\n .rph-msg{padding:36px;text-align:center;color:var(--mj-text-muted)}\n .rph-table{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden}\n .rph-tr{display:grid;grid-template-columns:1.3fr 1.6fr 1.2fr .9fr 1fr 1.4fr;gap:14px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--mj-border-subtle);font-size:13px;cursor:pointer}\n .rph-tr:last-child{border-bottom:none}\n .rph-tr:not(.rph-head):hover{background:var(--mj-bg-surface-hover)}\n .rph-head{background:var(--mj-bg-surface-sunken);font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--mj-text-muted);font-weight:700;cursor:default}\n .rph-nm{font-weight:600}\n .rph-sub{color:var(--mj-text-muted);font-size:12px}\n .st{display:inline-flex;align-items:center;gap:7px;font-weight:600;font-size:12.5px}\n .st .dot{width:8px;height:8px;border-radius:50%;background:var(--mj-text-disabled)}\n .st.ok .dot{background:var(--mj-status-success)} .st.ok{color:var(--mj-status-success-text)}\n .st.err .dot{background:var(--mj-status-error)} .st.err{color:var(--mj-status-error-text)}\n .st.muted{color:var(--mj-text-muted)}\n .st.sm{font-size:11.5px}\n .counts{display:flex;gap:6px;flex-wrap:wrap}\n .cbadge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px;background:var(--mj-bg-surface-sunken);color:var(--mj-text-secondary)}\n .dryrun{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:6px;margin-left:6px;background:var(--mj-status-info-bg);color:var(--mj-status-info-text);border:1px solid var(--mj-status-info-border)}\n .cbadge.ok{background:var(--mj-status-success-bg);color:var(--mj-status-success-text)}\n .cbadge.err{background:var(--mj-status-error-bg);color:var(--mj-status-error-text)}\n .rph-details{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden;max-height:560px;overflow-y:auto}\n .rph-detrec{display:grid;grid-template-columns:200px 1fr;gap:14px;padding:11px 16px;border-bottom:1px solid var(--mj-border-subtle)}\n .rph-detrec:last-child{border-bottom:none}\n .rph-detkey{display:flex;flex-direction:column;gap:5px}\n .rph-rk{font-family:var(--mj-font-mono,monospace);font-size:11px;color:var(--mj-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n .rph-chg{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px;padding:2px 0}\n .rph-chg .f{font-weight:700;min-width:120px}\n .rph-chg .o{color:var(--mj-text-muted);text-decoration:line-through}\n .rph-chg .nw{color:var(--mj-status-success-text);font-weight:600}\n .rph-chg .ar{color:var(--mj-text-disabled);font-size:11px}\n .rph-chg.err-msg{color:var(--mj-status-error-text)}\n `],\n})\nexport class RecordProcessHistoryComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n /** Optional: show runs for one Record Process only. */\n @Input() RecordProcessID: string | null = null;\n\n public Mode: 'list' | 'detail' = 'list';\n public Loading = true;\n public DetailLoading = false;\n public Runs: RunRow[] = [];\n public Details: DetailRow[] = [];\n public OpenRunRow: RunRow | null = null;\n\n /**\n * There is no RecordProcess BaseEngine to observe — Process Runs is an unbounded log table, so we don't\n * bulk-cache it. Instead we re-query on demand AND keep the list live by listening for BaseEntity save/\n * delete events on the run tables: a run started/finished anywhere (this view, the editor preview, a grid\n * runner, the scheduler) fires an event, and we debounce-reload so history never goes stale behind a run.\n */\n private eventSub?: Subscription;\n private pendingReload = false;\n private reloadTimer: ReturnType<typeof setTimeout> | null = null;\n\n async ngOnInit(): Promise<void> {\n await this.reload();\n this.subscribeToRunChanges();\n }\n\n ngOnDestroy(): void {\n this.eventSub?.unsubscribe();\n if (this.reloadTimer) {\n clearTimeout(this.reloadTimer);\n }\n }\n\n /** Subscribe to BaseEntity events and debounce-reload whenever a Process Run (or its details) changes. */\n private subscribeToRunChanges(): void {\n this.eventSub = MJGlobal.Instance.GetEventListener(false).subscribe((event: MJEvent) => {\n if (event.event !== MJEventType.ComponentEvent || event.eventCode !== BaseEntity.BaseEventCode) {\n return;\n }\n const e = event.args as BaseEntityEvent;\n if (e.type !== 'save' && e.type !== 'delete' && e.type !== 'remote-invalidate') {\n return;\n }\n const name = e.baseEntity?.EntityInfo?.Name ?? e.entityName;\n if (name === 'MJ: Process Runs' || name === 'MJ: Process Run Details') {\n this.scheduleReload();\n }\n });\n }\n\n /** Debounce a burst of run/detail/checkpoint saves into a single reload; defer if the user is drilled into a detail. */\n private scheduleReload(): void {\n if (this.Mode !== 'list') {\n this.pendingReload = true; // refresh when they return to the list — don't yank them out of a drill-in\n return;\n }\n if (this.reloadTimer) {\n clearTimeout(this.reloadTimer);\n }\n this.reloadTimer = setTimeout(() => {\n this.reloadTimer = null;\n void this.reload();\n }, 400);\n }\n\n async reload(): Promise<void> {\n this.Loading = true; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const filter = this.RecordProcessID ? `RecordProcessID='${this.RecordProcessID}'` : '';\n const [runs, procs] = await rv.RunViews([\n {\n EntityName: 'MJ: Process Runs',\n Fields: ['ID', 'RecordProcessID', 'EntityID', 'Status', 'StartTime', 'SuccessCount', 'ErrorCount', 'SkippedCount', 'TotalItemCount', 'TriggeredBy', 'SourceType', 'DryRun'],\n ExtraFilter: filter, OrderBy: 'StartTime DESC', MaxRows: 200, ResultType: 'simple',\n },\n { EntityName: 'MJ: Record Processes', Fields: ['ID', 'Name'], ResultType: 'simple' },\n ]);\n // Normalized-UUID keys → O(1), case-safe across SQL Server (upper) / PostgreSQL (lower).\n const nameByID = new Map<string, string>();\n if (procs.Success) for (const p of procs.Results as Array<{ ID: string; Name: string }>) nameByID.set(NormalizeUUID(p.ID), p.Name);\n const rawRuns = runs.Success ? (runs.Results as RawRun[]) : [];\n this.Runs = rawRuns.map((r) => ({\n ...r,\n ProcessName: nameByID.get(NormalizeUUID(r.RecordProcessID)) ?? '(deleted)',\n EntityName: this.ProviderToUse.EntityByID(r.EntityID)?.Name ?? r.EntityID,\n }));\n this.Loading = false;\n this.cdr.detectChanges();\n }\n\n async openRun(run: RunRow): Promise<void> {\n this.OpenRunRow = run; this.Mode = 'detail'; this.DetailLoading = true; this.Details = []; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<RawDetail>({\n EntityName: 'MJ: Process Run Details',\n Fields: ['RecordID', 'Status', 'ResultPayload', 'ErrorMessage'],\n ExtraFilter: `ProcessRunID='${run.ID}'`, OrderBy: 'Status, RecordID', MaxRows: 1000, ResultType: 'simple',\n });\n this.Details = (result.Success ? (result.Results ?? []) : []).map((d) => ({\n RecordID: d.RecordID, Status: d.Status, Changes: parseAppliedRunDetailChanges(d.ResultPayload), ErrorMessage: d.ErrorMessage,\n }));\n this.DetailLoading = false;\n this.cdr.detectChanges();\n }\n\n backToList(): void {\n this.Mode = 'list';\n this.OpenRunRow = null;\n this.cdr.detectChanges();\n if (this.pendingReload) {\n this.pendingReload = false;\n void this.reload(); // a run changed while we were drilled into a detail — refresh now\n }\n }\n\n fmt(value?: string | Date): string {\n if (!value) return '—';\n const d = value instanceof Date ? value : new Date(value);\n return isNaN(d.getTime()) ? String(value) : d.toLocaleString();\n }\n disp(value: unknown): string { return displayRunValue(value); }\n}\n"]}
1
+ {"version":3,"file":"record-process-history.component.js","sourceRoot":"","sources":["../../../src/lib/record-process-history/record-process-history.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Run history for Bulk Operations: every Record Process run (who/when/scope/status/counts),\n * drilling into the per-record outcome (the field diff persisted on each Process Run Detail). Read-only\n * audit surface. Generic + reusable.\n * @module @memberjunction/ng-record-process-studio\n */\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { BaseEntity, BaseEntityEvent, RunView } from '@memberjunction/core';\nimport { MJEvent, MJEventType, MJGlobal, NormalizeUUID } from '@memberjunction/global';\nimport { MJButtonDirective } from '@memberjunction/ng-ui-components';\nimport { ParseAppliedRunDetailChanges, DisplayRunValue, type RunDetailChange } from '../run-detail';\n\ninterface RawRun {\n ID: string; RecordProcessID: string; EntityID: string; Status: string;\n StartTime?: string | Date; SuccessCount?: number; ErrorCount?: number; SkippedCount?: number;\n TotalItemCount?: number; TriggeredBy?: string; SourceType?: string; DryRun?: boolean;\n}\ninterface RunRow extends RawRun { ProcessName: string; EntityName: string; }\n\ninterface RawDetail { RecordID: string; Status: string; ResultPayload?: string; ErrorMessage?: string; }\ninterface DetailRow { RecordID: string; Status: string; Changes: RunDetailChange[]; ErrorMessage?: string; }\n\n@Component({\n selector: 'mj-record-process-history',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MJButtonDirective],\n template: `\n @if (Mode === 'list') {\n <div class=\"rph-bar\">\n <h3 class=\"rph-title\">Run history</h3><span class=\"rph-spacer\"></span>\n <button mjButton variant=\"flat\" (click)=\"reload()\"><i class=\"fa-solid fa-arrows-rotate\"></i> Refresh</button>\n </div>\n @if (Loading) {\n <div class=\"rph-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading…</div>\n } @else if (Runs.length === 0) {\n <div class=\"rph-msg\">No runs yet.</div>\n } @else {\n <div class=\"rph-table\">\n <div class=\"rph-tr rph-head\"><div>When</div><div>Operation</div><div>Entity</div><div>By</div><div>Status</div><div>Counts</div></div>\n @for (r of Runs; track r.ID) {\n <div class=\"rph-tr\" (click)=\"openRun(r)\">\n <div class=\"rph-sub\">{{ fmt(r.StartTime) }}</div>\n <div class=\"rph-nm\">{{ r.ProcessName }}</div>\n <div>{{ r.EntityName }}</div>\n <div class=\"rph-sub\">{{ r.TriggeredBy || '—' }}</div>\n <div><span class=\"st\" [class.ok]=\"r.Status==='Completed'\" [class.err]=\"r.Status==='Failed'\"><span class=\"dot\"></span> {{ r.Status }}</span>@if (r.DryRun) { <span class=\"dryrun\" title=\"Compute-only preview — no changes were written\">Dry Run</span> }</div>\n <div class=\"counts\">\n <span class=\"cbadge ok\">{{ r.SuccessCount || 0 }} ok</span>\n @if (r.ErrorCount) { <span class=\"cbadge err\">{{ r.ErrorCount }} err</span> }\n @if (r.SkippedCount) { <span class=\"cbadge\">{{ r.SkippedCount }} skip</span> }\n </div>\n </div>\n }\n </div>\n }\n } @else {\n <div class=\"rph-bar\">\n <button mjButton variant=\"flat\" (click)=\"backToList()\"><i class=\"fa-solid fa-arrow-left\"></i> Back</button>\n <h3 class=\"rph-title\">{{ OpenRunRow?.ProcessName }} · {{ fmt(OpenRunRow?.StartTime) }}</h3>\n @if (OpenRunRow?.DryRun) { <span class=\"dryrun\" title=\"Compute-only preview — no changes were written\">Dry Run</span> }\n </div>\n @if (DetailLoading) {\n <div class=\"rph-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading details…</div>\n } @else if (Details.length === 0) {\n <div class=\"rph-msg\">No per-record details recorded for this run.</div>\n } @else {\n <div class=\"rph-details\">\n @for (d of Details; track d.RecordID) {\n <div class=\"rph-detrec\">\n <div class=\"rph-detkey\">\n <span class=\"st sm\" [class.ok]=\"d.Status==='Succeeded'\" [class.err]=\"d.Status==='Failed'\" [class.muted]=\"d.Status==='Skipped'\"><span class=\"dot\"></span> {{ d.Status }}</span>\n <div class=\"rph-rk\">{{ d.RecordID }}</div>\n </div>\n <div class=\"rph-changes\">\n @for (c of d.Changes; track c.Field) {\n <div class=\"rph-chg\"><span class=\"f\">{{ c.Field }}</span>\n <span class=\"o\">{{ disp(c.OldValue) }}</span><i class=\"fa-solid fa-arrow-right-long ar\"></i><span class=\"nw\">{{ disp(c.NewValue) }}</span></div>\n }\n @if (d.ErrorMessage) { <div class=\"rph-chg err-msg\">{{ d.ErrorMessage }}</div> }\n @if (d.Changes.length === 0 && !d.ErrorMessage) { <span class=\"rph-sub\">no changes</span> }\n </div>\n </div>\n }\n </div>\n }\n }\n `,\n styles: [`\n :host{display:block;color:var(--mj-text-primary)}\n .rph-bar{display:flex;align-items:center;gap:14px;margin-bottom:16px}\n .rph-title{margin:0;font-size:16px;font-weight:700}\n .rph-spacer{flex:1}\n .rph-bar button i{margin-right:6px}\n .rph-msg{padding:36px;text-align:center;color:var(--mj-text-muted)}\n .rph-table{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden}\n .rph-tr{display:grid;grid-template-columns:1.3fr 1.6fr 1.2fr .9fr 1fr 1.4fr;gap:14px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--mj-border-subtle);font-size:13px;cursor:pointer}\n .rph-tr:last-child{border-bottom:none}\n .rph-tr:not(.rph-head):hover{background:var(--mj-bg-surface-hover)}\n .rph-head{background:var(--mj-bg-surface-sunken);font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--mj-text-muted);font-weight:700;cursor:default}\n .rph-nm{font-weight:600}\n .rph-sub{color:var(--mj-text-muted);font-size:12px}\n .st{display:inline-flex;align-items:center;gap:7px;font-weight:600;font-size:12.5px}\n .st .dot{width:8px;height:8px;border-radius:50%;background:var(--mj-text-disabled)}\n .st.ok .dot{background:var(--mj-status-success)} .st.ok{color:var(--mj-status-success-text)}\n .st.err .dot{background:var(--mj-status-error)} .st.err{color:var(--mj-status-error-text)}\n .st.muted{color:var(--mj-text-muted)}\n .st.sm{font-size:11.5px}\n .counts{display:flex;gap:6px;flex-wrap:wrap}\n .cbadge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px;background:var(--mj-bg-surface-sunken);color:var(--mj-text-secondary)}\n .dryrun{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:6px;margin-left:6px;background:var(--mj-status-info-bg);color:var(--mj-status-info-text);border:1px solid var(--mj-status-info-border)}\n .cbadge.ok{background:var(--mj-status-success-bg);color:var(--mj-status-success-text)}\n .cbadge.err{background:var(--mj-status-error-bg);color:var(--mj-status-error-text)}\n .rph-details{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden;max-height:560px;overflow-y:auto}\n .rph-detrec{display:grid;grid-template-columns:200px 1fr;gap:14px;padding:11px 16px;border-bottom:1px solid var(--mj-border-subtle)}\n .rph-detrec:last-child{border-bottom:none}\n .rph-detkey{display:flex;flex-direction:column;gap:5px}\n .rph-rk{font-family:var(--mj-font-mono,monospace);font-size:11px;color:var(--mj-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n .rph-chg{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px;padding:2px 0}\n .rph-chg .f{font-weight:700;min-width:120px}\n .rph-chg .o{color:var(--mj-text-muted);text-decoration:line-through}\n .rph-chg .nw{color:var(--mj-status-success-text);font-weight:600}\n .rph-chg .ar{color:var(--mj-text-disabled);font-size:11px}\n .rph-chg.err-msg{color:var(--mj-status-error-text)}\n `],\n})\nexport class RecordProcessHistoryComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n\n /** Optional: show runs for one Record Process only. */\n @Input() RecordProcessID: string | null = null;\n\n public Mode: 'list' | 'detail' = 'list';\n public Loading = true;\n public DetailLoading = false;\n public Runs: RunRow[] = [];\n public Details: DetailRow[] = [];\n public OpenRunRow: RunRow | null = null;\n\n /**\n * There is no RecordProcess BaseEngine to observe — Process Runs is an unbounded log table, so we don't\n * bulk-cache it. Instead we re-query on demand AND keep the list live by listening for BaseEntity save/\n * delete events on the run tables: a run started/finished anywhere (this view, the editor preview, a grid\n * runner, the scheduler) fires an event, and we debounce-reload so history never goes stale behind a run.\n */\n private eventSub?: Subscription;\n private pendingReload = false;\n private reloadTimer: ReturnType<typeof setTimeout> | null = null;\n\n async ngOnInit(): Promise<void> {\n await this.Reload();\n this.subscribeToRunChanges();\n }\n\n ngOnDestroy(): void {\n this.eventSub?.unsubscribe();\n if (this.reloadTimer) {\n clearTimeout(this.reloadTimer);\n }\n }\n\n /** Subscribe to BaseEntity events and debounce-reload whenever a Process Run (or its details) changes. */\n private subscribeToRunChanges(): void {\n this.eventSub = MJGlobal.Instance.GetEventListener(false).subscribe((event: MJEvent) => {\n if (event.event !== MJEventType.ComponentEvent || event.eventCode !== BaseEntity.BaseEventCode) {\n return;\n }\n const e = event.args as BaseEntityEvent;\n if (e.type !== 'save' && e.type !== 'delete' && e.type !== 'remote-invalidate') {\n return;\n }\n const name = e.baseEntity?.EntityInfo?.Name ?? e.entityName;\n if (name === 'MJ: Process Runs' || name === 'MJ: Process Run Details') {\n this.scheduleReload();\n }\n });\n }\n\n /** Debounce a burst of run/detail/checkpoint saves into a single reload; defer if the user is drilled into a detail. */\n private scheduleReload(): void {\n if (this.Mode !== 'list') {\n this.pendingReload = true; // refresh when they return to the list — don't yank them out of a drill-in\n return;\n }\n if (this.reloadTimer) {\n clearTimeout(this.reloadTimer);\n }\n this.reloadTimer = setTimeout(() => {\n this.reloadTimer = null;\n void this.Reload();\n }, 400);\n }\n\n async Reload(): Promise<void> {\n this.Loading = true; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const filter = this.RecordProcessID ? `RecordProcessID='${this.RecordProcessID}'` : '';\n const [runs, procs] = await rv.RunViews([\n {\n EntityName: 'MJ: Process Runs',\n Fields: ['ID', 'RecordProcessID', 'EntityID', 'Status', 'StartTime', 'SuccessCount', 'ErrorCount', 'SkippedCount', 'TotalItemCount', 'TriggeredBy', 'SourceType', 'DryRun'],\n ExtraFilter: filter, OrderBy: 'StartTime DESC', MaxRows: 200, ResultType: 'simple',\n },\n { EntityName: 'MJ: Record Processes', Fields: ['ID', 'Name'], ResultType: 'simple' },\n ]);\n // Normalized-UUID keys → O(1), case-safe across SQL Server (upper) / PostgreSQL (lower).\n const nameByID = new Map<string, string>();\n if (procs.Success) for (const p of procs.Results as Array<{ ID: string; Name: string }>) nameByID.set(NormalizeUUID(p.ID), p.Name);\n const rawRuns = runs.Success ? (runs.Results as RawRun[]) : [];\n this.Runs = rawRuns.map((r) => ({\n ...r,\n ProcessName: nameByID.get(NormalizeUUID(r.RecordProcessID)) ?? '(deleted)',\n EntityName: this.ProviderToUse.EntityByID(r.EntityID)?.Name ?? r.EntityID,\n }));\n this.Loading = false;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link Reload}. */\n async reload(): Promise<void> {\n return this.Reload();\n }\n\n async OpenRun(run: RunRow): Promise<void> {\n this.OpenRunRow = run; this.Mode = 'detail'; this.DetailLoading = true; this.Details = []; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<RawDetail>({\n EntityName: 'MJ: Process Run Details',\n Fields: ['RecordID', 'Status', 'ResultPayload', 'ErrorMessage'],\n ExtraFilter: `ProcessRunID='${run.ID}'`, OrderBy: 'Status, RecordID', MaxRows: 1000, ResultType: 'simple',\n });\n this.Details = (result.Success ? (result.Results ?? []) : []).map((d) => ({\n RecordID: d.RecordID, Status: d.Status, Changes: ParseAppliedRunDetailChanges(d.ResultPayload), ErrorMessage: d.ErrorMessage,\n }));\n this.DetailLoading = false;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link OpenRun}. */\n async openRun(run: RunRow): Promise<void> {\n return this.OpenRun(run);\n }\n\n BackToList(): void {\n this.Mode = 'list';\n this.OpenRunRow = null;\n this.cdr.detectChanges();\n if (this.pendingReload) {\n this.pendingReload = false;\n void this.Reload(); // a run changed while we were drilled into a detail — refresh now\n }\n }\n\n /** @deprecated Use {@link BackToList}. */\n backToList(): void {\n return this.BackToList();\n }\n\n Fmt(value?: string | Date): string {\n if (!value) return '—';\n const d = value instanceof Date ? value : new Date(value);\n return isNaN(d.getTime()) ? String(value) : d.toLocaleString();\n }\n\n /** @deprecated Use {@link Fmt}. */\n fmt(value?: string | Date): string {\n return this.Fmt(value);\n }\n Disp(value: unknown): string { return DisplayRunValue(value); }\n\n /** @deprecated Use {@link Disp}. */\n disp(value: unknown): string {\n return this.Disp(value);\n }\n}\n"]}
@@ -38,15 +38,27 @@ export declare class RecordProcessStudioComponent extends BaseAngularComponent i
38
38
  } | null;
39
39
  ngOnInit(): Promise<void>;
40
40
  get Filtered(): ProcessRow[];
41
+ Reload(): Promise<void>;
42
+ /** @deprecated Use {@link Reload}. */
41
43
  reload(): Promise<void>;
44
+ OnSearch(event: Event): void;
45
+ /** @deprecated Use {@link OnSearch}. */
42
46
  onSearch(event: Event): void;
43
47
  New(): void;
44
48
  Edit(p: ProcessRow): void;
49
+ BackToList(): void;
50
+ /** @deprecated Use {@link BackToList}. */
45
51
  backToList(): void;
52
+ OnSaved(): Promise<void>;
53
+ /** @deprecated Use {@link OnSaved}. */
46
54
  onSaved(): Promise<void>;
47
55
  /** Runs a process on demand against its default scope, via the dry-run → confirm runner. */
48
56
  Run(p: ProcessRow): void;
57
+ OnRunDone(_r: EntityActionUXResult): void;
58
+ /** @deprecated Use {@link OnRunDone}. */
49
59
  onRunDone(_r: EntityActionUXResult): void;
60
+ WorkLabel(workType: string): string;
61
+ /** @deprecated Use {@link WorkLabel}. */
50
62
  workLabel(workType: string): string;
51
63
  static ɵfac: i0.ɵɵFactoryDeclaration<RecordProcessStudioComponent, never>;
52
64
  static ɵcmp: i0.ɵɵComponentDeclaration<RecordProcessStudioComponent, "mj-record-process-studio", never, { "EntityID": { "alias": "EntityID"; "required": false; }; }, {}, never, never, true, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"record-process-studio.component.d.ts","sourceRoot":"","sources":["../../../src/lib/record-process-studio/record-process-studio.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAgE,MAAM,EAAU,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAA+B,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;;AAIzI,wDAAwD;AACxD,UAAU,UAAU;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAgGa,4BAA6B,SAAQ,oBAAqB,YAAW,MAAM;IACpF,OAAO,CAAC,GAAG,CAA6B;IAExC,qGAAqG;IAC5F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAU;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,OAAO,UAAQ;IACf,MAAM,SAAM;IACZ,SAAS,EAAE,UAAU,EAAE,CAAM;IAC7B,SAAS,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,qBAAqB,CAAA;KAAE,GAAG,IAAI,CAAQ;IAElF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,IAAI,QAAQ,IAAI,UAAU,EAAE,CAI3B;IAEK,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB7B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5B,GAAG,IAAI,IAAI;IACX,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IACzB,UAAU,IAAI,IAAI;IACZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B,4FAA4F;IAC5F,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAmBxB,SAAS,CAAC,EAAE,EAAE,oBAAoB,GAAG,IAAI;IAEzC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;yCApE1B,4BAA4B;2CAA5B,4BAA4B;CAuExC"}
1
+ {"version":3,"file":"record-process-studio.component.d.ts","sourceRoot":"","sources":["../../../src/lib/record-process-studio/record-process-studio.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAgE,MAAM,EAAU,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAA+B,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;;AAIzI,wDAAwD;AACxD,UAAU,UAAU;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAgGa,4BAA6B,SAAQ,oBAAqB,YAAW,MAAM;IACpF,OAAO,CAAC,GAAG,CAA6B;IAExC,qGAAqG;IAC5F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAU;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,OAAO,UAAQ;IACf,MAAM,SAAM;IACZ,SAAS,EAAE,UAAU,EAAE,CAAM;IAC7B,SAAS,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,qBAAqB,CAAA;KAAE,GAAG,IAAI,CAAQ;IAElF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,IAAI,QAAQ,IAAI,UAAU,EAAE,CAI3B;IAEK,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB7B,sCAAsC;IAChC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5B,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI5B,GAAG,IAAI,IAAI;IACX,IAAI,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IACzB,UAAU,IAAI,IAAI;IAElB,0CAA0C;IAC1C,UAAU,IAAI,IAAI;IAGZ,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B,uCAAuC;IACjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,4FAA4F;IAC5F,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAmBxB,SAAS,CAAC,EAAE,EAAE,oBAAoB,GAAG,IAAI;IAEzC,yCAAyC;IACzC,SAAS,CAAC,EAAE,EAAE,oBAAoB,GAAG,IAAI;IAIzC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInC,yCAAyC;IACzC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;yCAlG1B,4BAA4B;2CAA5B,4BAA4B;CAqGxC"}
@@ -167,7 +167,7 @@ export class RecordProcessStudioComponent extends BaseAngularComponent {
167
167
  Processes = [];
168
168
  RunDriver = null;
169
169
  async ngOnInit() {
170
- await this.reload();
170
+ await this.Reload();
171
171
  }
172
172
  get Filtered() {
173
173
  const q = this.Search.trim().toLowerCase();
@@ -175,7 +175,7 @@ export class RecordProcessStudioComponent extends BaseAngularComponent {
175
175
  return this.Processes;
176
176
  return this.Processes.filter((p) => p.Name.toLowerCase().includes(q) || (p.Entity ?? '').toLowerCase().includes(q));
177
177
  }
178
- async reload() {
178
+ async Reload() {
179
179
  this.Loading = true;
180
180
  this.cdr.detectChanges();
181
181
  const rv = RunView.FromMetadataProvider(this.ProviderToUse);
@@ -191,11 +191,27 @@ export class RecordProcessStudioComponent extends BaseAngularComponent {
191
191
  this.Loading = false;
192
192
  this.cdr.detectChanges();
193
193
  }
194
- onSearch(event) { this.Search = event.target.value; this.cdr.detectChanges(); }
194
+ /** @deprecated Use {@link Reload}. */
195
+ async reload() {
196
+ return this.Reload();
197
+ }
198
+ OnSearch(event) { this.Search = event.target.value; this.cdr.detectChanges(); }
199
+ /** @deprecated Use {@link OnSearch}. */
200
+ onSearch(event) {
201
+ return this.OnSearch(event);
202
+ }
195
203
  New() { this.EditingID = null; this.Mode = 'edit'; this.cdr.detectChanges(); }
196
204
  Edit(p) { this.EditingID = p.ID; this.Mode = 'edit'; this.cdr.detectChanges(); }
197
- backToList() { this.Mode = 'list'; this.EditingID = null; this.cdr.detectChanges(); }
198
- async onSaved() { this.backToList(); await this.reload(); }
205
+ BackToList() { this.Mode = 'list'; this.EditingID = null; this.cdr.detectChanges(); }
206
+ /** @deprecated Use {@link BackToList}. */
207
+ backToList() {
208
+ return this.BackToList();
209
+ }
210
+ async OnSaved() { this.BackToList(); await this.Reload(); }
211
+ /** @deprecated Use {@link OnSaved}. */
212
+ async onSaved() {
213
+ return this.OnSaved();
214
+ }
199
215
  /** Runs a process on demand against its default scope, via the dry-run → confirm runner. */
200
216
  Run(p) {
201
217
  const entity = this.ProviderToUse.EntityByID(p.EntityID);
@@ -216,10 +232,18 @@ export class RecordProcessStudioComponent extends BaseAngularComponent {
216
232
  };
217
233
  this.cdr.detectChanges();
218
234
  }
219
- onRunDone(_r) { this.RunDriver = null; this.cdr.detectChanges(); }
220
- workLabel(workType) {
235
+ OnRunDone(_r) { this.RunDriver = null; this.cdr.detectChanges(); }
236
+ /** @deprecated Use {@link OnRunDone}. */
237
+ onRunDone(_r) {
238
+ return this.OnRunDone(_r);
239
+ }
240
+ WorkLabel(workType) {
221
241
  return workType === 'FieldRules' ? 'Field Rules' : workType;
222
242
  }
243
+ /** @deprecated Use {@link WorkLabel}. */
244
+ workLabel(workType) {
245
+ return this.WorkLabel(workType);
246
+ }
223
247
  static ɵfac = /*@__PURE__*/ (() => { let ɵRecordProcessStudioComponent_BaseFactory; return function RecordProcessStudioComponent_Factory(__ngFactoryType__) { return (ɵRecordProcessStudioComponent_BaseFactory || (ɵRecordProcessStudioComponent_BaseFactory = i0.ɵɵgetInheritedFactory(RecordProcessStudioComponent)))(__ngFactoryType__ || RecordProcessStudioComponent); }; })();
224
248
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordProcessStudioComponent, selectors: [["mj-record-process-studio"]], inputs: { EntityID: "EntityID" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 2, consts: [[3, "DriverClass", "Context"], [1, "rps-bar"], [1, "rps-search"], [1, "fa-solid", "fa-magnifying-glass"], ["placeholder", "Search bulk operations\u2026", 1, "mj-input", 3, "input", "value"], [1, "rps-spacer"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "rps-msg"], ["Icon", "fa-solid fa-list-check", "Title", "No bulk operations yet", "ActionText", "Create one", "ActionIcon", "fa-solid fa-plus", 1, "rps-empty"], [1, "rps-table"], [1, "fa-solid", "fa-circle-notch", "fa-spin"], ["Icon", "fa-solid fa-list-check", "Title", "No bulk operations yet", "ActionText", "Create one", "ActionIcon", "fa-solid fa-plus", 1, "rps-empty", 3, "Action"], [1, "rps-tr", "rps-head"], [1, "ta-r"], [1, "rps-tr"], [1, "rps-tr", 3, "click"], [1, "rps-nm"], [1, "rps-sub"], [1, "pill", "purple"], [1, "pill"], [1, "ta-r", "rps-acts", 3, "click"], ["title", "Run", 1, "iconbtn", "run", 3, "click"], [1, "fa-solid", "fa-play"], ["title", "Edit", 1, "iconbtn", 3, "click"], [1, "fa-solid", "fa-pen"], [1, "rps-editbar"], [1, "fa-solid", "fa-arrow-left"], [3, "Saved", "Cancelled", "RecordProcessID", "DefaultEntityID", "Provider"], [3, "Completed", "Cancelled", "DriverClass", "Context"]], template: function RecordProcessStudioComponent_Template(rf, ctx) { if (rf & 1) {
225
249
  i0.ɵɵconditionalCreate(0, RecordProcessStudioComponent_Conditional_0_Template, 14, 2)(1, RecordProcessStudioComponent_Conditional_1_Template, 7, 4);
@@ -1 +1 @@
1
- {"version":3,"file":"record-process-studio.component.js","sourceRoot":"","sources":["../../../src/lib/record-process-studio/record-process-studio.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview The Bulk Operations hub: lists the org's Record Processes, lets a user create / edit one\n * (via the embedded {@link RecordProcessEditorComponent}), and run any of them on demand (mounting the\n * same dry-run → confirm runner used from a grid). Generic + reusable — Explorer's Bulk Operations app\n * hosts it, but any MJ app can drop it in.\n * @module @memberjunction/ng-record-process-studio\n */\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { EntityActionUXHostComponent, type EntityActionUXContext, type EntityActionUXResult } from '@memberjunction/ng-entity-action-ux';\nimport { MJButtonDirective, MJEmptyStateComponent } from '@memberjunction/ng-ui-components';\nimport { RecordProcessEditorComponent } from '../record-process-editor/record-process-editor.component';\n\n/** A row of the process list (read-only projection). */\ninterface ProcessRow {\n ID: string;\n Name: string;\n Description?: string;\n Entity: string;\n EntityID: string;\n WorkType: string;\n Status: string;\n ScopeType: string;\n ScopeFilter?: string;\n ScopeViewID?: string;\n ScopeListID?: string;\n}\n\n@Component({\n selector: 'mj-record-process-studio',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [RecordProcessEditorComponent, EntityActionUXHostComponent, MJButtonDirective, MJEmptyStateComponent],\n template: `\n @if (Mode === 'list') {\n <div class=\"rps-bar\">\n <div class=\"rps-search\"><i class=\"fa-solid fa-magnifying-glass\"></i>\n <input class=\"mj-input\" placeholder=\"Search bulk operations…\" [value]=\"Search\" (input)=\"onSearch($event)\"></div>\n <span class=\"rps-spacer\"></span>\n <button mjButton variant=\"flat\" (click)=\"reload()\"><i class=\"fa-solid fa-arrows-rotate\"></i> Refresh</button>\n <button mjButton variant=\"primary\" (click)=\"New()\"><i class=\"fa-solid fa-plus\"></i> New operation</button>\n </div>\n\n @if (Loading) {\n <div class=\"rps-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading…</div>\n } @else if (Filtered.length === 0) {\n <mj-empty-state class=\"rps-empty\"\n Icon=\"fa-solid fa-list-check\"\n Title=\"No bulk operations yet\"\n ActionText=\"Create one\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"New()\" />\n } @else {\n <div class=\"rps-table\">\n <div class=\"rps-tr rps-head\">\n <div>Operation</div><div>Entity</div><div>Type</div><div>Status</div><div class=\"ta-r\">Actions</div>\n </div>\n @for (p of Filtered; track p.ID) {\n <div class=\"rps-tr\" (click)=\"Edit(p)\">\n <div><div class=\"rps-nm\">{{ p.Name }}</div>@if (p.Description) {<div class=\"rps-sub\">{{ p.Description }}</div>}</div>\n <div>{{ p.Entity }}</div>\n <div><span class=\"pill purple\">{{ workLabel(p.WorkType) }}</span></div>\n <div><span class=\"pill\" [class.ok]=\"p.Status==='Active'\" [class.warn]=\"p.Status==='Draft'\" [class.muted]=\"p.Status==='Disabled'\">{{ p.Status }}</span></div>\n <div class=\"ta-r rps-acts\" (click)=\"$event.stopPropagation()\">\n <button class=\"iconbtn run\" title=\"Run\" (click)=\"Run(p)\"><i class=\"fa-solid fa-play\"></i></button>\n <button class=\"iconbtn\" title=\"Edit\" (click)=\"Edit(p)\"><i class=\"fa-solid fa-pen\"></i></button>\n </div>\n </div>\n }\n </div>\n }\n } @else {\n <div class=\"rps-editbar\">\n <button mjButton variant=\"flat\" (click)=\"backToList()\"><i class=\"fa-solid fa-arrow-left\"></i> Back</button>\n <h2>{{ EditingID ? 'Edit operation' : 'New operation' }}</h2>\n </div>\n <mj-record-process-editor\n [RecordProcessID]=\"EditingID\"\n [DefaultEntityID]=\"EntityID\"\n [Provider]=\"Provider\"\n (Saved)=\"onSaved()\"\n (Cancelled)=\"backToList()\">\n </mj-record-process-editor>\n }\n\n @if (RunDriver) {\n <mj-entity-action-ux-host\n [DriverClass]=\"RunDriver.DriverClass\" [Context]=\"RunDriver.Context\"\n (Completed)=\"onRunDone($event)\" (Cancelled)=\"RunDriver = null\">\n </mj-entity-action-ux-host>\n }\n `,\n styles: [`\n :host{display:block;color:var(--mj-text-primary)}\n .rps-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px}\n .rps-search{position:relative;flex:0 0 360px;max-width:360px}\n .rps-search i{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--mj-text-muted);font-size:13px}\n .rps-search input{padding-left:34px}\n .rps-spacer{flex:1}\n .rps-bar button i,.rps-editbar button i{margin-right:6px}\n .rps-msg,.rps-empty{padding:40px;text-align:center;color:var(--mj-text-muted)}\n .rps-empty i{font-size:30px;display:block;margin-bottom:12px;color:var(--mj-text-disabled)}\n .rps-empty p{margin:0 0 16px}\n .rps-table{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden}\n .rps-tr{display:grid;grid-template-columns:2.2fr 1.2fr 1fr .8fr 1fr;gap:14px;align-items:center;padding:13px 16px;border-bottom:1px solid var(--mj-border-subtle);cursor:pointer;font-size:13.5px}\n .rps-tr:last-child{border-bottom:none}\n .rps-tr:not(.rps-head):hover{background:var(--mj-bg-surface-hover)}\n .rps-head{background:var(--mj-bg-surface-sunken);font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--mj-text-muted);font-weight:700;cursor:default}\n .rps-nm{font-weight:600}\n .rps-sub{color:var(--mj-text-muted);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:420px}\n .ta-r{text-align:right;justify-self:end}\n .rps-acts{display:flex;gap:6px}\n .iconbtn{width:30px;height:30px;border-radius:7px;border:1px solid var(--mj-border-default);background:var(--mj-bg-surface-card);color:var(--mj-text-secondary);cursor:pointer;font-size:12.5px}\n .iconbtn:hover{background:var(--mj-bg-surface-hover);color:var(--mj-text-primary)}\n .iconbtn.run:hover{color:var(--mj-status-success-text);border-color:var(--mj-status-success)}\n .pill{display:inline-flex;align-items:center;padding:3px 10px;border-radius:999px;font-size:11.5px;font-weight:700;background:var(--mj-bg-surface-sunken);color:var(--mj-text-secondary)}\n .pill.purple{background:color-mix(in srgb,var(--mj-brand-primary) 14%,transparent);color:var(--mj-brand-primary)}\n .pill.ok{background:var(--mj-status-success-bg);color:var(--mj-status-success-text)}\n .pill.warn{background:var(--mj-status-warning-bg);color:var(--mj-status-warning-text)}\n .pill.muted{background:var(--mj-bg-surface-sunken);color:var(--mj-text-muted)}\n .rps-editbar{display:flex;align-items:center;gap:14px;margin-bottom:18px}\n .rps-editbar h2{margin:0;font-size:18px;font-weight:700}\n `],\n})\nexport class RecordProcessStudioComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n /** Optional: restrict the hub to processes for one entity (e.g. when embedded on an entity page). */\n @Input() EntityID: string | null = null;\n\n public Mode: 'list' | 'edit' = 'list';\n public EditingID: string | null = null;\n public Loading = true;\n public Search = '';\n public Processes: ProcessRow[] = [];\n public RunDriver: { DriverClass: string; Context: EntityActionUXContext } | null = null;\n\n async ngOnInit(): Promise<void> {\n await this.reload();\n }\n\n get Filtered(): ProcessRow[] {\n const q = this.Search.trim().toLowerCase();\n if (!q) return this.Processes;\n return this.Processes.filter((p) => p.Name.toLowerCase().includes(q) || (p.Entity ?? '').toLowerCase().includes(q));\n }\n\n async reload(): Promise<void> {\n this.Loading = true; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const filter = this.EntityID ? `EntityID='${this.EntityID}'` : '';\n const result = await rv.RunView<ProcessRow>({\n EntityName: 'MJ: Record Processes',\n Fields: ['ID', 'Name', 'Description', 'Entity', 'EntityID', 'WorkType', 'Status', 'ScopeType', 'ScopeFilter', 'ScopeViewID', 'ScopeListID'],\n ExtraFilter: filter,\n OrderBy: 'Name',\n ResultType: 'simple',\n });\n this.Processes = result.Success ? (result.Results ?? []) : [];\n this.Loading = false;\n this.cdr.detectChanges();\n }\n\n onSearch(event: Event): void { this.Search = (event.target as HTMLInputElement).value; this.cdr.detectChanges(); }\n\n New(): void { this.EditingID = null; this.Mode = 'edit'; this.cdr.detectChanges(); }\n Edit(p: ProcessRow): void { this.EditingID = p.ID; this.Mode = 'edit'; this.cdr.detectChanges(); }\n backToList(): void { this.Mode = 'list'; this.EditingID = null; this.cdr.detectChanges(); }\n async onSaved(): Promise<void> { this.backToList(); await this.reload(); }\n\n /** Runs a process on demand against its default scope, via the dry-run → confirm runner. */\n Run(p: ProcessRow): void {\n const entity = this.ProviderToUse.EntityByID(p.EntityID);\n if (!entity) return;\n this.RunDriver = {\n DriverClass: 'RecordProcessRunnerUX',\n Context: {\n EntityInfo: entity,\n ScopeKind: (p.ScopeType?.toLowerCase() as EntityActionUXContext['ScopeKind']) || 'filter',\n Filter: p.ScopeFilter ?? undefined,\n ViewID: p.ScopeViewID ?? undefined,\n ListID: p.ScopeListID ?? undefined,\n Config: { RecordProcessID: p.ID },\n Provider: this.ProviderToUse,\n ActionLabel: p.Name,\n },\n };\n this.cdr.detectChanges();\n }\n\n onRunDone(_r: EntityActionUXResult): void { this.RunDriver = null; this.cdr.detectChanges(); }\n\n workLabel(workType: string): string {\n return workType === 'FieldRules' ? 'Field Rules' : workType;\n }\n}\n"]}
1
+ {"version":3,"file":"record-process-studio.component.js","sourceRoot":"","sources":["../../../src/lib/record-process-studio/record-process-studio.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview The Bulk Operations hub: lists the org's Record Processes, lets a user create / edit one\n * (via the embedded {@link RecordProcessEditorComponent}), and run any of them on demand (mounting the\n * same dry-run → confirm runner used from a grid). Generic + reusable — Explorer's Bulk Operations app\n * hosts it, but any MJ app can drop it in.\n * @module @memberjunction/ng-record-process-studio\n */\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { RunView } from '@memberjunction/core';\nimport { EntityActionUXHostComponent, type EntityActionUXContext, type EntityActionUXResult } from '@memberjunction/ng-entity-action-ux';\nimport { MJButtonDirective, MJEmptyStateComponent } from '@memberjunction/ng-ui-components';\nimport { RecordProcessEditorComponent } from '../record-process-editor/record-process-editor.component';\n\n/** A row of the process list (read-only projection). */\ninterface ProcessRow {\n ID: string;\n Name: string;\n Description?: string;\n Entity: string;\n EntityID: string;\n WorkType: string;\n Status: string;\n ScopeType: string;\n ScopeFilter?: string;\n ScopeViewID?: string;\n ScopeListID?: string;\n}\n\n@Component({\n selector: 'mj-record-process-studio',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [RecordProcessEditorComponent, EntityActionUXHostComponent, MJButtonDirective, MJEmptyStateComponent],\n template: `\n @if (Mode === 'list') {\n <div class=\"rps-bar\">\n <div class=\"rps-search\"><i class=\"fa-solid fa-magnifying-glass\"></i>\n <input class=\"mj-input\" placeholder=\"Search bulk operations…\" [value]=\"Search\" (input)=\"onSearch($event)\"></div>\n <span class=\"rps-spacer\"></span>\n <button mjButton variant=\"flat\" (click)=\"reload()\"><i class=\"fa-solid fa-arrows-rotate\"></i> Refresh</button>\n <button mjButton variant=\"primary\" (click)=\"New()\"><i class=\"fa-solid fa-plus\"></i> New operation</button>\n </div>\n\n @if (Loading) {\n <div class=\"rps-msg\"><i class=\"fa-solid fa-circle-notch fa-spin\"></i> Loading…</div>\n } @else if (Filtered.length === 0) {\n <mj-empty-state class=\"rps-empty\"\n Icon=\"fa-solid fa-list-check\"\n Title=\"No bulk operations yet\"\n ActionText=\"Create one\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"New()\" />\n } @else {\n <div class=\"rps-table\">\n <div class=\"rps-tr rps-head\">\n <div>Operation</div><div>Entity</div><div>Type</div><div>Status</div><div class=\"ta-r\">Actions</div>\n </div>\n @for (p of Filtered; track p.ID) {\n <div class=\"rps-tr\" (click)=\"Edit(p)\">\n <div><div class=\"rps-nm\">{{ p.Name }}</div>@if (p.Description) {<div class=\"rps-sub\">{{ p.Description }}</div>}</div>\n <div>{{ p.Entity }}</div>\n <div><span class=\"pill purple\">{{ workLabel(p.WorkType) }}</span></div>\n <div><span class=\"pill\" [class.ok]=\"p.Status==='Active'\" [class.warn]=\"p.Status==='Draft'\" [class.muted]=\"p.Status==='Disabled'\">{{ p.Status }}</span></div>\n <div class=\"ta-r rps-acts\" (click)=\"$event.stopPropagation()\">\n <button class=\"iconbtn run\" title=\"Run\" (click)=\"Run(p)\"><i class=\"fa-solid fa-play\"></i></button>\n <button class=\"iconbtn\" title=\"Edit\" (click)=\"Edit(p)\"><i class=\"fa-solid fa-pen\"></i></button>\n </div>\n </div>\n }\n </div>\n }\n } @else {\n <div class=\"rps-editbar\">\n <button mjButton variant=\"flat\" (click)=\"backToList()\"><i class=\"fa-solid fa-arrow-left\"></i> Back</button>\n <h2>{{ EditingID ? 'Edit operation' : 'New operation' }}</h2>\n </div>\n <mj-record-process-editor\n [RecordProcessID]=\"EditingID\"\n [DefaultEntityID]=\"EntityID\"\n [Provider]=\"Provider\"\n (Saved)=\"onSaved()\"\n (Cancelled)=\"backToList()\">\n </mj-record-process-editor>\n }\n\n @if (RunDriver) {\n <mj-entity-action-ux-host\n [DriverClass]=\"RunDriver.DriverClass\" [Context]=\"RunDriver.Context\"\n (Completed)=\"onRunDone($event)\" (Cancelled)=\"RunDriver = null\">\n </mj-entity-action-ux-host>\n }\n `,\n styles: [`\n :host{display:block;color:var(--mj-text-primary)}\n .rps-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px}\n .rps-search{position:relative;flex:0 0 360px;max-width:360px}\n .rps-search i{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--mj-text-muted);font-size:13px}\n .rps-search input{padding-left:34px}\n .rps-spacer{flex:1}\n .rps-bar button i,.rps-editbar button i{margin-right:6px}\n .rps-msg,.rps-empty{padding:40px;text-align:center;color:var(--mj-text-muted)}\n .rps-empty i{font-size:30px;display:block;margin-bottom:12px;color:var(--mj-text-disabled)}\n .rps-empty p{margin:0 0 16px}\n .rps-table{border:1px solid var(--mj-border-subtle);border-radius:var(--mj-radius-md,10px);overflow:hidden}\n .rps-tr{display:grid;grid-template-columns:2.2fr 1.2fr 1fr .8fr 1fr;gap:14px;align-items:center;padding:13px 16px;border-bottom:1px solid var(--mj-border-subtle);cursor:pointer;font-size:13.5px}\n .rps-tr:last-child{border-bottom:none}\n .rps-tr:not(.rps-head):hover{background:var(--mj-bg-surface-hover)}\n .rps-head{background:var(--mj-bg-surface-sunken);font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--mj-text-muted);font-weight:700;cursor:default}\n .rps-nm{font-weight:600}\n .rps-sub{color:var(--mj-text-muted);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:420px}\n .ta-r{text-align:right;justify-self:end}\n .rps-acts{display:flex;gap:6px}\n .iconbtn{width:30px;height:30px;border-radius:7px;border:1px solid var(--mj-border-default);background:var(--mj-bg-surface-card);color:var(--mj-text-secondary);cursor:pointer;font-size:12.5px}\n .iconbtn:hover{background:var(--mj-bg-surface-hover);color:var(--mj-text-primary)}\n .iconbtn.run:hover{color:var(--mj-status-success-text);border-color:var(--mj-status-success)}\n .pill{display:inline-flex;align-items:center;padding:3px 10px;border-radius:999px;font-size:11.5px;font-weight:700;background:var(--mj-bg-surface-sunken);color:var(--mj-text-secondary)}\n .pill.purple{background:color-mix(in srgb,var(--mj-brand-primary) 14%,transparent);color:var(--mj-brand-primary)}\n .pill.ok{background:var(--mj-status-success-bg);color:var(--mj-status-success-text)}\n .pill.warn{background:var(--mj-status-warning-bg);color:var(--mj-status-warning-text)}\n .pill.muted{background:var(--mj-bg-surface-sunken);color:var(--mj-text-muted)}\n .rps-editbar{display:flex;align-items:center;gap:14px;margin-bottom:18px}\n .rps-editbar h2{margin:0;font-size:18px;font-weight:700}\n `],\n})\nexport class RecordProcessStudioComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n /** Optional: restrict the hub to processes for one entity (e.g. when embedded on an entity page). */\n @Input() EntityID: string | null = null;\n\n public Mode: 'list' | 'edit' = 'list';\n public EditingID: string | null = null;\n public Loading = true;\n public Search = '';\n public Processes: ProcessRow[] = [];\n public RunDriver: { DriverClass: string; Context: EntityActionUXContext } | null = null;\n\n async ngOnInit(): Promise<void> {\n await this.Reload();\n }\n\n get Filtered(): ProcessRow[] {\n const q = this.Search.trim().toLowerCase();\n if (!q) return this.Processes;\n return this.Processes.filter((p) => p.Name.toLowerCase().includes(q) || (p.Entity ?? '').toLowerCase().includes(q));\n }\n\n async Reload(): Promise<void> {\n this.Loading = true; this.cdr.detectChanges();\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const filter = this.EntityID ? `EntityID='${this.EntityID}'` : '';\n const result = await rv.RunView<ProcessRow>({\n EntityName: 'MJ: Record Processes',\n Fields: ['ID', 'Name', 'Description', 'Entity', 'EntityID', 'WorkType', 'Status', 'ScopeType', 'ScopeFilter', 'ScopeViewID', 'ScopeListID'],\n ExtraFilter: filter,\n OrderBy: 'Name',\n ResultType: 'simple',\n });\n this.Processes = result.Success ? (result.Results ?? []) : [];\n this.Loading = false;\n this.cdr.detectChanges();\n }\n\n /** @deprecated Use {@link Reload}. */\n async reload(): Promise<void> {\n return this.Reload();\n }\n\n OnSearch(event: Event): void { this.Search = (event.target as HTMLInputElement).value; this.cdr.detectChanges(); }\n\n /** @deprecated Use {@link OnSearch}. */\n onSearch(event: Event): void {\n return this.OnSearch(event);\n }\n\n New(): void { this.EditingID = null; this.Mode = 'edit'; this.cdr.detectChanges(); }\n Edit(p: ProcessRow): void { this.EditingID = p.ID; this.Mode = 'edit'; this.cdr.detectChanges(); }\n BackToList(): void { this.Mode = 'list'; this.EditingID = null; this.cdr.detectChanges(); }\n\n /** @deprecated Use {@link BackToList}. */\n backToList(): void {\n return this.BackToList();\n }\n async OnSaved(): Promise<void> { this.BackToList(); await this.Reload(); }\n\n /** @deprecated Use {@link OnSaved}. */\n async onSaved(): Promise<void> {\n return this.OnSaved();\n }\n\n /** Runs a process on demand against its default scope, via the dry-run → confirm runner. */\n Run(p: ProcessRow): void {\n const entity = this.ProviderToUse.EntityByID(p.EntityID);\n if (!entity) return;\n this.RunDriver = {\n DriverClass: 'RecordProcessRunnerUX',\n Context: {\n EntityInfo: entity,\n ScopeKind: (p.ScopeType?.toLowerCase() as EntityActionUXContext['ScopeKind']) || 'filter',\n Filter: p.ScopeFilter ?? undefined,\n ViewID: p.ScopeViewID ?? undefined,\n ListID: p.ScopeListID ?? undefined,\n Config: { RecordProcessID: p.ID },\n Provider: this.ProviderToUse,\n ActionLabel: p.Name,\n },\n };\n this.cdr.detectChanges();\n }\n\n OnRunDone(_r: EntityActionUXResult): void { this.RunDriver = null; this.cdr.detectChanges(); }\n\n /** @deprecated Use {@link OnRunDone}. */\n onRunDone(_r: EntityActionUXResult): void {\n return this.OnRunDone(_r);\n }\n\n WorkLabel(workType: string): string {\n return workType === 'FieldRules' ? 'Field Rules' : workType;\n }\n\n /** @deprecated Use {@link WorkLabel}. */\n workLabel(workType: string): string {\n return this.WorkLabel(workType);\n }\n}\n"]}
@@ -17,7 +17,11 @@ export interface RunDetailChange {
17
17
  * Parses a Process Run Detail's `ResultPayload` and returns only the changes that were actually applied
18
18
  * (condition passed, value differed, no error). Safe on null/empty/invalid JSON — returns `[]`.
19
19
  */
20
+ export declare function ParseAppliedRunDetailChanges(resultPayload: string | null | undefined): RunDetailChange[];
21
+ /** @deprecated Use {@link ParseAppliedRunDetailChanges}. */
20
22
  export declare function parseAppliedRunDetailChanges(resultPayload: string | null | undefined): RunDetailChange[];
21
23
  /** Renders an arbitrary value for the audit diff table. */
24
+ export declare function DisplayRunValue(value: unknown): string;
25
+ /** @deprecated Use {@link DisplayRunValue}. */
22
26
  export declare function displayRunValue(value: unknown): string;
23
27
  //# sourceMappingURL=run-detail.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-detail.d.ts","sourceRoot":"","sources":["../../src/lib/run-detail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0FAA0F;AAC1F,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AASD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,EAAE,CAWxG;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD"}
1
+ {"version":3,"file":"run-detail.d.ts","sourceRoot":"","sources":["../../src/lib/run-detail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0FAA0F;AAC1F,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AASD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,EAAE,CAWxG;AAED,4DAA4D;AAC5D,wBAAgB,4BAA4B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,EAAE,CAExG;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
@@ -8,7 +8,7 @@
8
8
  * Parses a Process Run Detail's `ResultPayload` and returns only the changes that were actually applied
9
9
  * (condition passed, value differed, no error). Safe on null/empty/invalid JSON — returns `[]`.
10
10
  */
11
- export function parseAppliedRunDetailChanges(resultPayload) {
11
+ export function ParseAppliedRunDetailChanges(resultPayload) {
12
12
  if (!resultPayload) {
13
13
  return [];
14
14
  }
@@ -21,8 +21,12 @@ export function parseAppliedRunDetailChanges(resultPayload) {
21
21
  }
22
22
  return (payload?.Changes ?? []).filter((c) => c.Applied && c.Changed && !c.Error);
23
23
  }
24
+ /** @deprecated Use {@link ParseAppliedRunDetailChanges}. */
25
+ export function parseAppliedRunDetailChanges(resultPayload) {
26
+ return ParseAppliedRunDetailChanges(resultPayload);
27
+ }
24
28
  /** Renders an arbitrary value for the audit diff table. */
25
- export function displayRunValue(value) {
29
+ export function DisplayRunValue(value) {
26
30
  if (value === null || value === undefined || value === '') {
27
31
  return '(empty)';
28
32
  }
@@ -31,4 +35,8 @@ export function displayRunValue(value) {
31
35
  }
32
36
  return String(value);
33
37
  }
38
+ /** @deprecated Use {@link DisplayRunValue}. */
39
+ export function displayRunValue(value) {
40
+ return DisplayRunValue(value);
41
+ }
34
42
  //# sourceMappingURL=run-detail.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-detail.js","sourceRoot":"","sources":["../../src/lib/run-detail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,aAAwC;IACjF,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,OAAqC,CAAC;IAC1C,IAAI,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtF,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxD,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC","sourcesContent":["/**\n * @fileoverview Pure helpers for reading a Process Run Detail's persisted result payload (the per-record\n * field diff) and rendering values. Extracted from the history component so the audit-diff logic is\n * unit-testable without a TestBed.\n * @module @memberjunction/ng-record-process-studio\n */\n\n/** One computed field change, as persisted on `MJ: Process Run Details.ResultPayload`. */\nexport interface RunDetailChange {\n Field: string;\n OldValue: unknown;\n NewValue: unknown;\n Applied: boolean;\n Changed: boolean;\n Error?: string;\n}\n\n/** The JSON shape persisted for a FieldRules run detail. */\ninterface RunDetailPayload {\n DryRun: boolean;\n Changes: RunDetailChange[];\n ChangedFields: string[];\n}\n\n/**\n * Parses a Process Run Detail's `ResultPayload` and returns only the changes that were actually applied\n * (condition passed, value differed, no error). Safe on null/empty/invalid JSON — returns `[]`.\n */\nexport function parseAppliedRunDetailChanges(resultPayload: string | null | undefined): RunDetailChange[] {\n if (!resultPayload) {\n return [];\n }\n let payload: RunDetailPayload | undefined;\n try {\n payload = JSON.parse(resultPayload) as RunDetailPayload;\n } catch {\n return [];\n }\n return (payload?.Changes ?? []).filter((c) => c.Applied && c.Changed && !c.Error);\n}\n\n/** Renders an arbitrary value for the audit diff table. */\nexport function displayRunValue(value: unknown): string {\n if (value === null || value === undefined || value === '') {\n return '(empty)';\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return String(value);\n}\n"]}
1
+ {"version":3,"file":"run-detail.js","sourceRoot":"","sources":["../../src/lib/run-detail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,aAAwC;IACjF,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,OAAqC,CAAC;IAC1C,IAAI,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtF,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,4BAA4B,CAAC,aAAwC;IACjF,OAAO,4BAA4B,CAAC,aAAa,CAAC,CAAC;AACvD,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACxD,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,eAAe,CAAC,KAAc;IAC1C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC","sourcesContent":["/**\n * @fileoverview Pure helpers for reading a Process Run Detail's persisted result payload (the per-record\n * field diff) and rendering values. Extracted from the history component so the audit-diff logic is\n * unit-testable without a TestBed.\n * @module @memberjunction/ng-record-process-studio\n */\n\n/** One computed field change, as persisted on `MJ: Process Run Details.ResultPayload`. */\nexport interface RunDetailChange {\n Field: string;\n OldValue: unknown;\n NewValue: unknown;\n Applied: boolean;\n Changed: boolean;\n Error?: string;\n}\n\n/** The JSON shape persisted for a FieldRules run detail. */\ninterface RunDetailPayload {\n DryRun: boolean;\n Changes: RunDetailChange[];\n ChangedFields: string[];\n}\n\n/**\n * Parses a Process Run Detail's `ResultPayload` and returns only the changes that were actually applied\n * (condition passed, value differed, no error). Safe on null/empty/invalid JSON — returns `[]`.\n */\nexport function ParseAppliedRunDetailChanges(resultPayload: string | null | undefined): RunDetailChange[] {\n if (!resultPayload) {\n return [];\n }\n let payload: RunDetailPayload | undefined;\n try {\n payload = JSON.parse(resultPayload) as RunDetailPayload;\n } catch {\n return [];\n }\n return (payload?.Changes ?? []).filter((c) => c.Applied && c.Changed && !c.Error);\n}\n\n/** @deprecated Use {@link ParseAppliedRunDetailChanges}. */\nexport function parseAppliedRunDetailChanges(resultPayload: string | null | undefined): RunDetailChange[] {\n return ParseAppliedRunDetailChanges(resultPayload);\n}\n\n/** Renders an arbitrary value for the audit diff table. */\nexport function DisplayRunValue(value: unknown): string {\n if (value === null || value === undefined || value === '') {\n return '(empty)';\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\n/** @deprecated Use {@link DisplayRunValue}. */\nexport function displayRunValue(value: unknown): string {\n return DisplayRunValue(value);\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export * from './lib/record-process-editor/record-process-editor.component';
2
+ export * from './lib/feature-pipeline-builder/feature-pipeline-builder.component';
2
3
  export * from './lib/record-process-studio/record-process-studio.component';
3
4
  export * from './lib/record-process-history/record-process-history.component';
4
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,+DAA+D,CAAC;AAM9E;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
1
+ {"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,6DAA6D,CAAC;AAC5E,cAAc,mEAAmE,CAAC;AAClF,cAAc,6DAA6D,CAAC;AAC5E,cAAc,+DAA+D,CAAC;AAO9E;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
@@ -1,9 +1,11 @@
1
1
  // @memberjunction/ng-record-process-studio
2
2
  // Generic Bulk Operations studio — author, run, and audit Record Processes.
3
3
  export * from './lib/record-process-editor/record-process-editor.component';
4
+ export * from './lib/feature-pipeline-builder/feature-pipeline-builder.component';
4
5
  export * from './lib/record-process-studio/record-process-studio.component';
5
6
  export * from './lib/record-process-history/record-process-history.component';
6
7
  import { RecordProcessEditorComponent } from './lib/record-process-editor/record-process-editor.component';
8
+ import { FeaturePipelineBuilderComponent } from './lib/feature-pipeline-builder/feature-pipeline-builder.component';
7
9
  import { RecordProcessStudioComponent } from './lib/record-process-studio/record-process-studio.component';
8
10
  import { RecordProcessHistoryComponent } from './lib/record-process-history/record-process-history.component';
9
11
  /**
@@ -11,7 +13,7 @@ import { RecordProcessHistoryComponent } from './lib/record-process-history/reco
11
13
  * Call once from the consuming app's bootstrap.
12
14
  */
13
15
  export function LoadRecordProcessStudio() {
14
- const _keep = [RecordProcessEditorComponent, RecordProcessStudioComponent, RecordProcessHistoryComponent];
16
+ const _keep = [RecordProcessEditorComponent, FeaturePipelineBuilderComponent, RecordProcessStudioComponent, RecordProcessHistoryComponent];
15
17
  if (_keep.length === 0) {
16
18
  throw new Error('unreachable');
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,4EAA4E;AAE5E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,+DAA+D,CAAC;AAE9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,6BAA6B,EAAE,MAAM,+DAA+D,CAAC;AAE9G;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACnC,MAAM,KAAK,GAAG,CAAC,4BAA4B,EAAE,4BAA4B,EAAE,6BAA6B,CAAC,CAAC;IAC1G,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;AACL,CAAC","sourcesContent":["// @memberjunction/ng-record-process-studio\n// Generic Bulk Operations studio — author, run, and audit Record Processes.\n\nexport * from './lib/record-process-editor/record-process-editor.component';\nexport * from './lib/record-process-studio/record-process-studio.component';\nexport * from './lib/record-process-history/record-process-history.component';\n\nimport { RecordProcessEditorComponent } from './lib/record-process-editor/record-process-editor.component';\nimport { RecordProcessStudioComponent } from './lib/record-process-studio/record-process-studio.component';\nimport { RecordProcessHistoryComponent } from './lib/record-process-history/record-process-history.component';\n\n/**\n * Tree-shaking guard — reference the studio components so a consumer's bundler keeps them.\n * Call once from the consuming app's bootstrap.\n */\nexport function LoadRecordProcessStudio(): void {\n const _keep = [RecordProcessEditorComponent, RecordProcessStudioComponent, RecordProcessHistoryComponent];\n if (_keep.length === 0) {\n throw new Error('unreachable');\n }\n}\n"]}
1
+ {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,4EAA4E;AAE5E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,mEAAmE,CAAC;AAClF,cAAc,6DAA6D,CAAC;AAC5E,cAAc,+DAA+D,CAAC;AAE9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,+BAA+B,EAAE,MAAM,mEAAmE,CAAC;AACpH,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,6BAA6B,EAAE,MAAM,+DAA+D,CAAC;AAE9G;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACnC,MAAM,KAAK,GAAG,CAAC,4BAA4B,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,6BAA6B,CAAC,CAAC;IAC3I,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;AACL,CAAC","sourcesContent":["// @memberjunction/ng-record-process-studio\n// Generic Bulk Operations studio — author, run, and audit Record Processes.\n\nexport * from './lib/record-process-editor/record-process-editor.component';\nexport * from './lib/feature-pipeline-builder/feature-pipeline-builder.component';\nexport * from './lib/record-process-studio/record-process-studio.component';\nexport * from './lib/record-process-history/record-process-history.component';\n\nimport { RecordProcessEditorComponent } from './lib/record-process-editor/record-process-editor.component';\nimport { FeaturePipelineBuilderComponent } from './lib/feature-pipeline-builder/feature-pipeline-builder.component';\nimport { RecordProcessStudioComponent } from './lib/record-process-studio/record-process-studio.component';\nimport { RecordProcessHistoryComponent } from './lib/record-process-history/record-process-history.component';\n\n/**\n * Tree-shaking guard — reference the studio components so a consumer's bundler keeps them.\n * Call once from the consuming app's bootstrap.\n */\nexport function LoadRecordProcessStudio(): void {\n const _keep = [RecordProcessEditorComponent, FeaturePipelineBuilderComponent, RecordProcessStudioComponent, RecordProcessHistoryComponent];\n if (_keep.length === 0) {\n throw new Error('unreachable');\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-record-process-studio",
3
- "version": "6.1.4",
3
+ "version": "6.2.0-edge.1",
4
4
  "description": "MemberJunction: Bulk Operations studio — generic, reusable Angular UI for authoring, running, and auditing Record Processes (rules-driven bulk updates). Consumed by MJExplorer's Bulk Operations app or any MJ app.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -21,7 +21,7 @@
21
21
  "@angular/compiler-cli": "21.2.22",
22
22
  "rimraf": "^5.0.0",
23
23
  "vitest": "^4.0.18",
24
- "@memberjunction/ng-test-utils": "6.1.4"
24
+ "@memberjunction/ng-test-utils": "6.2.0-edge.1"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@angular/common": "^21.2.22",
@@ -30,13 +30,14 @@
30
30
  "rxjs": "^7.8.2"
31
31
  },
32
32
  "dependencies": {
33
- "@memberjunction/core": "6.1.4",
34
- "@memberjunction/core-entities": "6.1.4",
35
- "@memberjunction/global": "6.1.4",
36
- "@memberjunction/graphql-dataprovider": "6.1.4",
37
- "@memberjunction/ng-base-types": "6.1.4",
38
- "@memberjunction/ng-entity-action-ux": "6.1.4",
39
- "@memberjunction/ng-ui-components": "6.1.4",
33
+ "@memberjunction/core": "6.2.0-edge.1",
34
+ "@memberjunction/core-entities": "6.2.0-edge.1",
35
+ "@memberjunction/feature-pipelines": "6.2.0-edge.1",
36
+ "@memberjunction/global": "6.2.0-edge.1",
37
+ "@memberjunction/graphql-dataprovider": "6.2.0-edge.1",
38
+ "@memberjunction/ng-base-types": "6.2.0-edge.1",
39
+ "@memberjunction/ng-entity-action-ux": "6.2.0-edge.1",
40
+ "@memberjunction/ng-ui-components": "6.2.0-edge.1",
40
41
  "tslib": "^2.8.1"
41
42
  },
42
43
  "sideEffects": false,