pict-section-recordset 1.1.0 → 1.3.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.
Files changed (67) hide show
  1. package/package.json +5 -1
  2. package/source/views/RecordSet-Filters.js +196 -72
  3. package/source/views/filters/RecordSet-Filter-Base.js +86 -8
  4. package/source/views/read/RecordSet-Read.js +308 -2
  5. package/types/providers/Filter-Data-Provider.d.ts +1 -1
  6. package/types/providers/Filter-Data-Provider.d.ts.map +1 -1
  7. package/types/views/Filter-PersistenceView.d.ts +23 -2
  8. package/types/views/Filter-PersistenceView.d.ts.map +1 -1
  9. package/types/views/RecordSet-Filters.d.ts +54 -2
  10. package/types/views/RecordSet-Filters.d.ts.map +1 -1
  11. package/types/views/filters/RecordSet-Filter-Base.d.ts +14 -0
  12. package/types/views/filters/RecordSet-Filter-Base.d.ts.map +1 -1
  13. package/types/views/list/RecordSet-List.d.ts.map +1 -1
  14. package/types/views/read/RecordSet-Read.d.ts +51 -0
  15. package/types/views/read/RecordSet-Read.d.ts.map +1 -1
  16. package/.vscode/launch.json +0 -46
  17. package/CONTRIBUTING.md +0 -50
  18. package/debug/Harness.js +0 -0
  19. package/docs/.nojekyll +0 -0
  20. package/docs/README.md +0 -76
  21. package/docs/_brand.json +0 -18
  22. package/docs/_cover.md +0 -11
  23. package/docs/_sidebar.md +0 -19
  24. package/docs/_version.json +0 -7
  25. package/docs/api-reference.md +0 -233
  26. package/docs/filters.md +0 -151
  27. package/docs/index.html +0 -38
  28. package/docs/record-providers.md +0 -155
  29. package/docs/retold-catalog.json +0 -87
  30. package/docs/retold-keyword-index.json +0 -5227
  31. package/docs/views/create/README.md +0 -181
  32. package/docs/views/dashboard/README.md +0 -308
  33. package/docs/views/list/README.md +0 -260
  34. package/docs/views/read/README.md +0 -216
  35. package/eslint.config.mjs +0 -10
  36. package/example_applications/README.md +0 -39
  37. package/example_applications/ServeExamples.js +0 -82
  38. package/example_applications/bookstore/.quackage.json +0 -9
  39. package/example_applications/bookstore/Bookstore-Application-Configuration.json +0 -4
  40. package/example_applications/bookstore/Bookstore-Application.js +0 -671
  41. package/example_applications/bookstore/css/bookstore.css +0 -729
  42. package/example_applications/bookstore/css/pure.min.css +0 -11
  43. package/example_applications/bookstore/html/index.html +0 -46
  44. package/example_applications/bookstore/package.json +0 -34
  45. package/example_applications/bookstore/providers/PictRouter-Bookstore.json +0 -32
  46. package/example_applications/bookstore/views/PictView-Bookstore-Content-About.json +0 -21
  47. package/example_applications/bookstore/views/PictView-Bookstore-Content-Legal.json +0 -21
  48. package/example_applications/bookstore/views/PictView-Bookstore-Dashboard.js +0 -147
  49. package/example_applications/bookstore/views/PictView-Bookstore-Layout.js +0 -85
  50. package/example_applications/bookstore/views/PictView-Bookstore-Login.js +0 -58
  51. package/example_applications/bookstore/views/PictView-Bookstore-Navigation.js +0 -228
  52. package/example_applications/index.html +0 -50
  53. package/example_applications/mocks/book-edit-view.html +0 -173
  54. package/example_applications/mocks/book-read-view.html +0 -166
  55. package/example_applications/mocks/list-view.html +0 -185
  56. package/example_applications/package.json +0 -16
  57. package/example_applications/simple_entity/.quackage.json +0 -9
  58. package/example_applications/simple_entity/README-Simple-RecordSet.md +0 -8
  59. package/example_applications/simple_entity/Simple-RecordSet-Application.js +0 -887
  60. package/example_applications/simple_entity/html/index.html +0 -207
  61. package/example_applications/simple_entity/package.json +0 -27
  62. package/test/PictSectionRecordSet-Basic_tests.js +0 -205
  63. package/test/PictSectionRecordSet-Filter-Data-Provider_tests.js +0 -263
  64. package/test/PictSectionRecordSet-Filter-InstanceViews-Render_tests.js +0 -328
  65. package/test/PictSectionRecordSet-RecordProvider-Meadow_tests.js +0 -216
  66. package/tsconfig.build.json +0 -16
  67. package/tsconfig.json +0 -16
@@ -1,5 +1,11 @@
1
1
  const libPictRecordSetRecordView = require('../RecordSet-RecordBaseView.js');
2
2
 
3
+ // Identity + audit field names stamped on (virtually) every Meadow entity. These are
4
+ // surfaced through the record audit header (the first-class activity line + the Details
5
+ // modal), not inline in the record body. The entity's own ID/GUID field names are added
6
+ // at suppression time via the provider's getIDField()/getGUIDField().
7
+ const _AUDIT_FIELD_NAMES = ['CreatingIDUser', 'UpdatingIDUser', 'DeletingIDUser', 'Deleted', 'CreateDate', 'UpdateDate', 'DeleteDate'];
8
+
3
9
  /** @type {Record<string, any>} */
4
10
  const _DEFAULT_CONFIGURATION__Read = (
5
11
  {
@@ -22,7 +28,32 @@ const _DEFAULT_CONFIGURATION__Read = (
22
28
  AutoSolveWithApp: false,
23
29
  AutoSolveOrdinal: 0,
24
30
 
25
- CSS: false,
31
+ CSS: /*css*/`
32
+ .prsp-audit-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin: 0 0 1rem; }
33
+ .prsp-audit-line { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--theme-color-text-muted, #6b7686); font-size: 0.85rem; }
34
+ .prsp-audit-line .pict-icon { font-size: 0.8rem; }
35
+ .prsp-audit-line strong { color: var(--theme-color-text-secondary, #45505f); font-weight: 600; }
36
+ .prsp-audit-button { display: inline-flex; align-items: center; gap: 0.4rem; border: 1px solid var(--theme-color-border-default, #d7dce3); background: var(--theme-color-background-primary, #fff); color: var(--theme-color-text-muted, #6b7686); border-radius: 8px; padding: 0.35rem 0.65rem; font: inherit; font-size: 0.82rem; cursor: pointer; transition: all 0.15s ease; }
37
+ .prsp-audit-button:hover { border-color: var(--theme-color-brand-primary, #156dd1); color: var(--theme-color-brand-primary, #156dd1); }
38
+ .prsp-record-related:empty { display: none; }
39
+ .prsp-audit-anchor { position: relative; }
40
+ .prsp-audit-popover { position: absolute; top: calc(100% + 8px); right: 0; min-width: 320px; max-width: 90vw; background: var(--theme-color-background-panel, #fff); border: 1px solid var(--theme-color-border-default, #d7dce3); border-radius: 10px; box-shadow: 0 14px 36px rgba(15, 23, 42, 0.18); padding: 1rem 1.1rem; z-index: 40; display: none; }
41
+ .prsp-audit-popover.is-open { display: block; }
42
+ .prsp-audit-dl { display: grid; grid-template-columns: auto 1fr; gap: 0.6rem 1rem; align-items: baseline; margin: 0; }
43
+ .prsp-audit-dl dt { color: var(--theme-color-text-muted, #6b7686); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.03em; white-space: nowrap; }
44
+ .prsp-audit-dl dd { margin: 0; color: var(--theme-color-text-primary, #1f2733); font-size: 0.9rem; }
45
+ .prsp-audit-dl dd small { color: var(--theme-color-text-muted, #6b7686); }
46
+ .prsp-audit-dl dd.is-deleted { color: var(--theme-color-status-error, #b62828); }
47
+ .prsp-audit-guid { display: inline-flex; align-items: center; gap: 0.4rem; }
48
+ .prsp-audit-guid code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8rem; color: var(--theme-color-text-secondary, #45505f); background: var(--theme-color-background-secondary, #f5f6f8); padding: 0.1rem 0.4rem; border-radius: 5px; }
49
+ .prsp-audit-copy { border: 0; background: transparent; color: var(--theme-color-text-muted, #6b7686); cursor: pointer; padding: 0.1rem 0.3rem; border-radius: 4px; font-size: 0.85rem; }
50
+ .prsp-audit-copy:hover { color: var(--theme-color-brand-primary, #156dd1); }
51
+ /* Tufte: in view mode the record VALUES are the foreground. Read-only fields render as
52
+ text (not boxed inputs), so the data outweighs its labels and section chrome. */
53
+ .prsp-record-read input.input[readonly], .prsp-record-read input.input[disabled], .prsp-record-read textarea[readonly], .prsp-record-read textarea[disabled], .prsp-record-read select[disabled] { background: transparent !important; border-color: transparent !important; box-shadow: none !important; padding-left: 0 !important; padding-right: 0 !important; height: auto !important; min-height: 0 !important; opacity: 1 !important; cursor: default !important; color: var(--theme-color-text-primary, #1f2733) !important; -webkit-text-fill-color: var(--theme-color-text-primary, #1f2733) !important; font-weight: 600 !important; font-size: 1.1rem !important; }
54
+ .prsp-record-read .label { font-size: 0.68rem !important; font-weight: 600 !important; text-transform: uppercase !important; letter-spacing: 0.05em !important; color: var(--theme-color-text-muted, #6b7686) !important; margin-bottom: 0.05rem !important; }
55
+ .prsp-record-read .section-header { background: var(--theme-color-background-selected, #e3edfb) !important; color: var(--theme-color-brand-primary, #156dd1) !important; font-size: 0.74rem !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.06em !important; padding: 0.4rem 0.8rem !important; border-radius: 6px !important; border-bottom: 0 !important; margin: 1.1rem 0 0.7rem !important; }
56
+ `,
26
57
  CSSPriority: 500,
27
58
 
28
59
  Templates:
@@ -227,6 +258,47 @@ const _DEFAULT_CONFIGURATION__Read = (
227
258
  // TODO: Double payload pattern...
228
259
  Template: `#/PSRS/{~D:Record.Payload.Payload.RecordSet~}/View/{~DVBK:Record.Payload.Data:Record.Payload.Payload.GUIDAddress~}`
229
260
  },
261
+ // --- Record audit header (themeable; apps brand via --theme-color-* tokens) ---
262
+ {
263
+ Hash: 'PRSP-Read-RecordAuditHeader-Template',
264
+ Template: /*html*/`
265
+ <div class="prsp-audit-header">
266
+ <div class="prsp-audit-activity">{~TS:PRSP-Read-RecordAudit-Line-Template:AppData.PRSP_RecordAudit.ActivitySlot~}</div>
267
+ <div class="prsp-audit-anchor">
268
+ <button type="button" class="prsp-audit-button" title="Identity and audit detail" onclick="_Pict.views['RSP-RecordSet-Read'].toggleRecordAudit()">{~I:Info~}<span>Details</span></button>
269
+ <div class="prsp-audit-popover" id="PRSP-Read-AuditPopover">
270
+ <dl class="prsp-audit-dl">
271
+ <dt>{~D:AppData.PRSP_RecordAudit.IDFieldName~}</dt><dd><span class="prsp-audit-guid"><code>{~D:AppData.PRSP_RecordAudit.IDValue~}</code><button type="button" class="prsp-audit-copy" title="Copy" onclick="_Pict.views['RSP-RecordSet-Read'].copyValue('{~D:AppData.PRSP_RecordAudit.IDValue~}')">{~I:Copy~}</button></span></dd>
272
+ <dt>{~D:AppData.PRSP_RecordAudit.GUIDFieldName~}</dt><dd><span class="prsp-audit-guid"><code>{~D:AppData.PRSP_RecordAudit.GUIDValue~}</code><button type="button" class="prsp-audit-copy" title="Copy" onclick="_Pict.views['RSP-RecordSet-Read'].copyValue('{~D:AppData.PRSP_RecordAudit.GUIDValue~}')">{~I:Copy~}</button></span></dd>
273
+ {~TS:PRSP-Read-RecordAudit-Created-Template:AppData.PRSP_RecordAudit.CreatedSlot~}
274
+ {~TS:PRSP-Read-RecordAudit-Updated-Template:AppData.PRSP_RecordAudit.UpdatedSlot~}
275
+ {~TS:PRSP-Read-RecordAudit-Deleted-Template:AppData.PRSP_RecordAudit.DeletedSlot~}
276
+ </dl>
277
+ </div>
278
+ </div>
279
+ </div>
280
+ `
281
+ },
282
+ {
283
+ Hash: 'PRSP-Read-RecordAudit-Line-Template',
284
+ Template: /*html*/`<span class="prsp-audit-line">{~I:Refresh~} {~D:Record.Label~} by <strong>{~E:User^Record.UserID^PRSP-Read-RecordAudit-UserName-Template~}</strong> &middot; {~DateFormat:Record.Date^MMM D, YYYY - h:mm A~}</span>`
285
+ },
286
+ {
287
+ Hash: 'PRSP-Read-RecordAudit-UserName-Template',
288
+ Template: /*html*/`{~D:Record.NameFirst~} {~D:Record.NameLast~}`
289
+ },
290
+ {
291
+ Hash: 'PRSP-Read-RecordAudit-Created-Template',
292
+ Template: /*html*/`<dt>Created</dt><dd>{~DateFormat:Record.Date^MMM D, YYYY - h:mm A~} <small>by {~E:User^Record.UserID^PRSP-Read-RecordAudit-UserName-Template~}</small></dd>`
293
+ },
294
+ {
295
+ Hash: 'PRSP-Read-RecordAudit-Updated-Template',
296
+ Template: /*html*/`<dt>Last updated</dt><dd>{~DateFormat:Record.Date^MMM D, YYYY - h:mm A~} <small>by {~E:User^Record.UserID^PRSP-Read-RecordAudit-UserName-Template~}</small></dd>`
297
+ },
298
+ {
299
+ Hash: 'PRSP-Read-RecordAudit-Deleted-Template',
300
+ Template: /*html*/`<dt>Deleted</dt><dd class="is-deleted">{~DateFormat:Record.Date^MMM D, YYYY - h:mm A~} <small>by {~E:User^Record.UserID^PRSP-Read-RecordAudit-UserName-Template~}</small></dd>`
301
+ },
230
302
  ],
231
303
 
232
304
  Renderables:
@@ -319,6 +391,8 @@ class viewRecordSetRead extends libPictRecordSetRecordView
319
391
  this.initializeDragListener();
320
392
  }
321
393
 
394
+ this.pict.CSSMap.injectCSS();
395
+ this._bindAuditDismiss();
322
396
  return super.onAfterRender(pRenderable);
323
397
  }
324
398
 
@@ -387,6 +461,222 @@ class viewRecordSetRead extends libPictRecordSetRecordView
387
461
  this.fable.providers.RecordSetRouter.pictRouter.navigate(`/PSRS/${ this.RecordSet }/Edit/${ this.GUID }`);
388
462
  }
389
463
 
464
+ /**
465
+ * Build the record audit header state — the first-class activity line plus the data the
466
+ * Details modal renders. Identity (ID/GUID) and the create/update/delete stamps are read
467
+ * straight off the fetched record; the acting-user names resolve lazily via {~E:User^…~}
468
+ * in the templates (cachetrax-cached), so nothing is pre-resolved here. Stored at
469
+ * AppData.PRSP_RecordAudit for the templates to consume.
470
+ *
471
+ * @param {Record<string, any>} pRecord - The fetched record.
472
+ */
473
+ _prepareRecordAuditState(pRecord)
474
+ {
475
+ if (!pRecord || typeof pRecord !== 'object')
476
+ {
477
+ this.pict.AppData.PRSP_RecordAudit = false;
478
+ return;
479
+ }
480
+ const tmpProvider = this.pict.providers[this.providerHash];
481
+ const tmpIDField = tmpProvider ? tmpProvider.getIDField() : 'ID';
482
+ const tmpGUIDField = tmpProvider ? tmpProvider.getGUIDField() : 'GUID';
483
+
484
+ const tmpHasCreate = this._validAuditDate(pRecord.CreateDate);
485
+ const tmpHasUpdate = this._validAuditDate(pRecord.UpdateDate) && (pRecord.UpdateDate !== pRecord.CreateDate);
486
+ const tmpDeleted = !!pRecord.Deleted && this._validAuditDate(pRecord.DeleteDate);
487
+
488
+ let tmpActivitySlot = [];
489
+ if (tmpHasUpdate)
490
+ {
491
+ tmpActivitySlot = [{ Label: 'Updated', Date: pRecord.UpdateDate, UserID: pRecord.UpdatingIDUser }];
492
+ }
493
+ else if (tmpHasCreate)
494
+ {
495
+ tmpActivitySlot = [{ Label: 'Created', Date: pRecord.CreateDate, UserID: pRecord.CreatingIDUser }];
496
+ }
497
+
498
+ const tmpIDValue = (pRecord[tmpIDField] != null) ? pRecord[tmpIDField] : '';
499
+ this.pict.AppData.PRSP_RecordAudit =
500
+ {
501
+ RecordSet: this.RecordSet,
502
+ DisplayName: this._computeDisplayName(pRecord),
503
+ IDFieldName: tmpIDField,
504
+ GUIDFieldName: tmpGUIDField,
505
+ IDValue: tmpIDValue,
506
+ GUIDValue: (pRecord[tmpGUIDField] != null) ? pRecord[tmpGUIDField] : '',
507
+ ActivitySlot: tmpActivitySlot,
508
+ CreatedSlot: tmpHasCreate ? [{ Date: pRecord.CreateDate, UserID: pRecord.CreatingIDUser }] : [],
509
+ UpdatedSlot: tmpHasUpdate ? [{ Date: pRecord.UpdateDate, UserID: pRecord.UpdatingIDUser }] : [],
510
+ DeletedSlot: tmpDeleted ? [{ Date: pRecord.DeleteDate, UserID: pRecord.DeletingIDUser }] : []
511
+ };
512
+ }
513
+
514
+ /**
515
+ * Compute a human-friendly display name for a record using an opinionated heuristic: first +
516
+ * last name, then a single descriptive field (FullName, Name, Title, …), else ''. Callers fall
517
+ * back to the GUID. Lets the page title read "Krishna Pavia Tester" instead of a raw GUID.
518
+ * @param {Record<string, any>} pRecord
519
+ * @return {string}
520
+ */
521
+ _computeDisplayName(pRecord)
522
+ {
523
+ if (!pRecord || typeof pRecord !== 'object')
524
+ {
525
+ return '';
526
+ }
527
+ const tmpFirst = pRecord.NameFirst || pRecord.FirstName;
528
+ const tmpLast = pRecord.NameLast || pRecord.LastName;
529
+ if (tmpFirst || tmpLast)
530
+ {
531
+ return [tmpFirst, tmpLast].filter(Boolean).join(' ').trim();
532
+ }
533
+ const tmpCandidateFields = ['FullName', 'Name', 'Title', 'DisplayName', 'Label', 'Subject', 'Description', 'Code', 'Hash'];
534
+ for (const tmpField of tmpCandidateFields)
535
+ {
536
+ if (pRecord[tmpField] != null && String(pRecord[tmpField]).trim() !== '')
537
+ {
538
+ return String(pRecord[tmpField]).trim();
539
+ }
540
+ }
541
+ return '';
542
+ }
543
+
544
+ /**
545
+ * Whether an audit date value is present and meaningful (guards null/empty and the Meadow
546
+ * "0000-00-00" zero-date sentinel).
547
+ * @param {any} pValue
548
+ * @return {boolean}
549
+ */
550
+ _validAuditDate(pValue)
551
+ {
552
+ if (!pValue)
553
+ {
554
+ return false;
555
+ }
556
+ return String(pValue).indexOf('0000-00-00') !== 0;
557
+ }
558
+
559
+ /**
560
+ * Toggle the anchored identity + audit popover open or closed. The content is rendered inline
561
+ * with the record (so the {~E:User^…~} names resolve during the read render); this just flips
562
+ * its visibility — no overlay.
563
+ */
564
+ toggleRecordAudit()
565
+ {
566
+ const tmpPopover = document.getElementById('PRSP-Read-AuditPopover');
567
+ if (tmpPopover)
568
+ {
569
+ tmpPopover.classList.toggle('is-open');
570
+ }
571
+ }
572
+
573
+ /**
574
+ * Bind the one-time document handlers that dismiss the audit popover on an outside click or
575
+ * Escape. Browser-level events with no inline-handler equivalent — bound once and guarded so
576
+ * re-renders don't stack listeners.
577
+ */
578
+ _bindAuditDismiss()
579
+ {
580
+ if (this._auditDismissBound || typeof document === 'undefined')
581
+ {
582
+ return;
583
+ }
584
+ this._auditDismissBound = true;
585
+ document.addEventListener('click', (pEvent) =>
586
+ {
587
+ const tmpPopover = document.getElementById('PRSP-Read-AuditPopover');
588
+ if (!tmpPopover || !tmpPopover.classList.contains('is-open'))
589
+ {
590
+ return;
591
+ }
592
+ if (tmpPopover.contains(pEvent.target) || (pEvent.target.closest && pEvent.target.closest('.prsp-audit-button')))
593
+ {
594
+ return;
595
+ }
596
+ tmpPopover.classList.remove('is-open');
597
+ });
598
+ document.addEventListener('keydown', (pEvent) =>
599
+ {
600
+ if (pEvent.key === 'Escape')
601
+ {
602
+ const tmpPopover = document.getElementById('PRSP-Read-AuditPopover');
603
+ if (tmpPopover)
604
+ {
605
+ tmpPopover.classList.remove('is-open');
606
+ }
607
+ }
608
+ });
609
+ }
610
+
611
+ /**
612
+ * Copy a record value (ID or GUID) to the clipboard from the audit popover, with a toast.
613
+ * @param {string} pValue
614
+ */
615
+ copyValue(pValue)
616
+ {
617
+ const tmpModal = this.pict.views['Pict-Section-Modal'];
618
+ const fToast = (pMessage, pType) =>
619
+ {
620
+ if (tmpModal && typeof tmpModal.toast === 'function')
621
+ {
622
+ tmpModal.toast(pMessage, { type: pType || 'success' });
623
+ }
624
+ };
625
+ if (typeof navigator !== 'undefined' && navigator.clipboard && navigator.clipboard.writeText)
626
+ {
627
+ navigator.clipboard.writeText(pValue).then(() => fToast('GUID copied to clipboard')).catch(() => fToast('Could not copy GUID', 'error'));
628
+ }
629
+ else
630
+ {
631
+ fToast('Could not copy GUID', 'error');
632
+ }
633
+ }
634
+
635
+ /**
636
+ * Remove identity + audit descriptors from a (cloned) manifest so they don't render inline
637
+ * in the record body — they live behind the audit header's Details modal instead. Also
638
+ * prunes any section left with no descriptors (e.g. an emptied "Audit Trail" section). The
639
+ * entity's own ID/GUID field names are suppressed alongside the shared audit fields.
640
+ * @param {Record<string, any>} pManifest - The cloned manifest to mutate.
641
+ */
642
+ _suppressAuditDescriptors(pManifest)
643
+ {
644
+ if (!pManifest || !pManifest.Descriptors)
645
+ {
646
+ return;
647
+ }
648
+ const tmpProvider = this.pict.providers[this.providerHash];
649
+ const tmpSuppress = _AUDIT_FIELD_NAMES.slice();
650
+ if (tmpProvider)
651
+ {
652
+ tmpSuppress.push(tmpProvider.getIDField());
653
+ tmpSuppress.push(tmpProvider.getGUIDField());
654
+ }
655
+ for (const tmpKey of Object.keys(pManifest.Descriptors))
656
+ {
657
+ const tmpFieldName = tmpKey.split('.').pop();
658
+ if (tmpSuppress.indexOf(tmpFieldName) >= 0)
659
+ {
660
+ delete pManifest.Descriptors[tmpKey];
661
+ }
662
+ }
663
+ // Drop sections that no longer have any descriptors (so an emptied titled section like
664
+ // "Audit Trail" doesn't render as a bare heading).
665
+ if (Array.isArray(pManifest.Sections))
666
+ {
667
+ const tmpUsedSections = {};
668
+ for (const tmpKey of Object.keys(pManifest.Descriptors))
669
+ {
670
+ const tmpSectionHash = pManifest.Descriptors[tmpKey] && pManifest.Descriptors[tmpKey].PictForm && pManifest.Descriptors[tmpKey].PictForm.Section;
671
+ if (tmpSectionHash)
672
+ {
673
+ tmpUsedSections[tmpSectionHash] = true;
674
+ }
675
+ }
676
+ pManifest.Sections = pManifest.Sections.filter((pSection) => tmpUsedSections[pSection.Hash]);
677
+ }
678
+ }
679
+
390
680
  onBeforeRenderRead(pRecordReadData)
391
681
  {
392
682
  this.formatDisplayData(pRecordReadData);
@@ -467,12 +757,19 @@ class viewRecordSetRead extends libPictRecordSetRecordView
467
757
  tmpRecordReadData.RecordSchema = await this.pict.providers[pProviderHash].getRecordSchema();
468
758
  this.pict.AppData[`${ tmpRecordReadData.RecordSet }Details`] = tmpRecordReadData.Record;
469
759
 
760
+ // Build the audit header state (first-class activity line + the Details modal) for this record.
761
+ this._prepareRecordAuditState(tmpRecordReadData.Record);
762
+
470
763
  if (pRecordConfiguration.RecordSetReadManifestOnly)
471
764
  {
472
765
  this.pict.TemplateProvider.addTemplate(`PRSP-Read-RecordRead-Template`, /*html*/`
473
766
  <!-- Manifest dynamic pict template: [PRSP-Read-RecordRead-Template] -->
767
+ <div class="prsp-record-read">
768
+ {~T:PRSP-Read-RecordAuditHeader-Template~}
474
769
  <div>${ this._generateManifestTemplate(pRecordConfiguration, 'RecordRead', null, true) }</div>
475
770
  {~T:PRSP-Read-RecordButtonBar-Template~}
771
+ <div class="prsp-record-related" id="PRSP-Read-Related"></div>
772
+ </div>
476
773
  <!-- Manifest dynamic pict end template: [PRSP-Read-RecordRead-Template] -->
477
774
  `);
478
775
  }
@@ -482,8 +779,12 @@ class viewRecordSetRead extends libPictRecordSetRecordView
482
779
  this.defaultManifest = await this._buildDefaultManifest(tmpRecordReadData.RecordSet);
483
780
  this.pict.TemplateProvider.addTemplate(`PRSP-Read-RecordRead-Template`, /*html*/`
484
781
  <!-- Manifest dynamic pict template: [PRSP-Read-RecordRead-Template] -->
782
+ <div class="prsp-record-read">
783
+ {~T:PRSP-Read-RecordAuditHeader-Template~}
485
784
  <div>${ this._generateManifestTemplate(pRecordConfiguration, 'RecordRead', null, true, this.action, this.defaultManifest) }</div>
486
785
  {~T:PRSP-Read-RecordButtonBar-Template~}
786
+ <div class="prsp-record-related" id="PRSP-Read-Related"></div>
787
+ </div>
487
788
  <!-- Manifest dynamic pict end template: [PRSP-Read-RecordRead-Template] -->
488
789
  `);
489
790
  }
@@ -616,7 +917,7 @@ class viewRecordSetRead extends libPictRecordSetRecordView
616
917
  const schema = await this.pict.providers[providerHash].getRecordSchema();
617
918
  for (const p of Object.keys(schema.properties))
618
919
  {
619
- const exclusionSet = [this.pict.providers[this.providerHash].getIDField(), this.pict.providers[this.providerHash].getGUIDField(), 'CreatingIDUser', 'UpdatingIDUser', 'DeletingIDUser', 'Deleted', 'CreateDate', 'UpdateDate', 'DeleteDate', 'Deleted'];
920
+ const exclusionSet = [this.pict.providers[this.providerHash].getIDField(), this.pict.providers[this.providerHash].getGUIDField()].concat(_AUDIT_FIELD_NAMES);
620
921
  if (exclusionSet.includes(p))
621
922
  {
622
923
  continue;
@@ -695,6 +996,11 @@ class viewRecordSetRead extends libPictRecordSetRecordView
695
996
  tmpManifest.Descriptors[x].PictForm.InputType = 'ReadOnly';
696
997
  }
697
998
  }
999
+ // Suppress identity + audit fields from the body; they surface via the audit header's Details modal.
1000
+ if (config.RecordSetReadSuppressAuditFields !== false)
1001
+ {
1002
+ this._suppressAuditDescriptors(tmpManifest);
1003
+ }
698
1004
  if (setBaseManifest)
699
1005
  {
700
1006
  this.manifest = tmpManifest;
@@ -146,7 +146,7 @@ declare class FilterDataProvider extends libPictProvider {
146
146
  * @param {string} pViewContext - The current view context
147
147
  * @return {boolean} - Returns true when the settings have been saved.
148
148
  */
149
- saveFilterMeta(pRecordSet: string, pViewContext: string): boolean;
149
+ saveFilterMeta(pRecordSet: string, pViewContext: string, pSilent: any, pDisplayNameOverride: any): boolean;
150
150
  /** ===== LAST USED Filter Experience ============= */
151
151
  /**
152
152
  * Save the application metadata as the last used filter experience (continually updated).
@@ -1 +1 @@
1
- {"version":3,"file":"Filter-Data-Provider.d.ts","sourceRoot":"","sources":["../../source/providers/Filter-Data-Provider.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Filter-Data-Provider.d.ts","sourceRoot":"","sources":["../../source/providers/Filter-Data-Provider.js"],"names":[],"mappings":"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"}
@@ -75,7 +75,28 @@ declare class viewFilterPersistenceView extends libPictView {
75
75
  * @param {function} [pCallback] - A callback function to be executed after saving the settings.
76
76
  * @returns {boolean} - Returns true when the settings have been saved.
77
77
  */
78
- saveFilterPersistenceSettings(event: Event, pCallback?: Function): boolean;
78
+ /** HTML-escape a value for safe display in the modal. */
79
+ _escapeHTML(pValue: any): string;
80
+ /** Describe a single active filter clause in plain English (e.g. "Date Created between A and B"). */
81
+ _describeFilterClause(pClause: any): string;
82
+ /**
83
+ * @returns {{ summary: string, count: string }} A plain-English summary of the current
84
+ * search + filter clauses, and the matched record count (from the rendered list total).
85
+ */
86
+ _describeCurrentFilter(): {
87
+ summary: string;
88
+ count: string;
89
+ };
90
+ /**
91
+ * Prompt for a name (via pict-section-modal when available) and save the current search +
92
+ * filters as a named experience. The modal previews the filter in plain English and the
93
+ * number of records it matches. Falls back to the generated name with no prompt if the
94
+ * modal section is not registered in the host app.
95
+ *
96
+ * @param {Event} pEvent
97
+ */
98
+ promptSaveFilterExperience(pEvent: Event): boolean;
99
+ saveFilterPersistenceSettings(event: any, pCallback: any): boolean;
79
100
  /**
80
101
  * Sets the filter experience as the default for the current record set and view context.
81
102
  * @param {Event} event - The event object.
@@ -112,7 +133,7 @@ declare namespace _DEFAULT_CONFIGURATION_FilterPersistenceView {
112
133
  let AutoRenderOrdinal: number;
113
134
  let AutoSolveWithApp: boolean;
114
135
  let AutoSolveOrdinal: number;
115
- let CSS: boolean;
136
+ let CSS: string;
116
137
  let CSSPriority: number;
117
138
  let Templates: {
118
139
  Hash: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Filter-PersistenceView.d.ts","sourceRoot":"","sources":["../../source/views/Filter-PersistenceView.js"],"names":[],"mappings":";AAuFA;IAEC,2DASC;IAJA,yBAA4B;IAC5B,2BAA8B;IAC9B,+BAAqC;IACrC,qCAAwC;IAIzC;;;;;;OAMG;IACH,8CALW,MAAM,gBACN,MAAM,wBAEJ,OAAO,CAqCnB;IAED;;;;;OAKG;IACH,8DAJW,MAAM,gBACN,MAAM,qCACN,OAAO,QA0BjB;IAED;;;;;;OAMG;IACH,oCALW,MAAM,gBACN,MAAM,wBAEJ,OAAO,CAYnB;IAED;;;OAGG;IACH,mCA2BC;IAED;;;;;;OAMG;IACH,2CALW,MAAM,gBACN,MAAM,aACN,MAAM,GACJ,OAAO,CAenB;IAED;;;;OAIG;IACH,sCAHW,KAAK,GACH,OAAO,CA6BnB;IAED;;;OAGG;IACH,4BAFa,OAAO,CAmBnB;IAED;;;OAGG;IACH,mDAFa,OAAO,CA+CnB;IAED;;;;OAIG;IACH,8CAHW,KAAK,GACH,OAAO,CAcnB;IAED;;;;OAIG;IACH,qCAHW,KAAK,mBACH,OAAO,CAqBnB;IAED;;;;;OAKG;IACH,qCAJW,KAAK,yBAEH,OAAO,CA4BnB;IAED;;;;;;OAMG;IACH,0CALW,KAAK,aACL,OAAO,yBAEL,OAAO,CAyBnB;IAED;;;OAGG;IACH,uCAFW,OAAO,QA4BjB;IAED;;;;;OAKG;IACH,uCAJW,KAAK,yBAEH,OAAO,CAsBnB;CACD"}
1
+ {"version":3,"file":"Filter-PersistenceView.d.ts","sourceRoot":"","sources":["../../source/views/Filter-PersistenceView.js"],"names":[],"mappings":";AA4EA;IAEC,2DASC;IAJA,yBAA4B;IAC5B,2BAA8B;IAC9B,+BAAqC;IACrC,qCAAwC;IAsBzC;;;;;;OAMG;IACH,8CALW,MAAM,gBACN,MAAM,wBAEJ,OAAO,CAqCnB;IAED;;;;;OAKG;IACH,8DAJW,MAAM,gBACN,MAAM,qCACN,OAAO,QA0BjB;IAED;;;;;;OAMG;IACH,oCALW,MAAM,gBACN,MAAM,wBAEJ,OAAO,CAYnB;IAED;;;OAGG;IACH,mCA2BC;IAED;;;;;;OAMG;IACH,2CALW,MAAM,gBACN,MAAM,aACN,MAAM,GACJ,OAAO,CAenB;IAED;;;;OAIG;IACH,sCAHW,KAAK,GACH,OAAO,CA6BnB;IAED;;;OAGG;IACH,4BAFa,OAAO,CAmBnB;IAED;;;OAGG;IACH,mDAFa,OAAO,CA+CnB;IAED;;;;OAIG;IACH,8CAHW,KAAK,GACH,OAAO,CAcnB;IAED;;;;OAIG;IACH,qCAHW,KAAK,mBACH,OAAO,CAqBnB;IAED;;;;;OAKG;IACH,yDAAyD;IACzD,iCAGC;IAED,qGAAqG;IACrG,4CAoBC;IAED;;;OAGG;IACH,0BAHa;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAqB9C;IAED;;;;;;;OAOG;IACH,mCAFW,KAAK,WA+Cf;IAED,mEA0BC;IAED;;;;;;OAMG;IACH,0CALW,KAAK,aACL,OAAO,yBAEL,OAAO,CAyBnB;IAED;;;OAGG;IACH,uCAFW,OAAO,QA4BjB;IAED;;;;;OAKG;IACH,uCAJW,KAAK,yBAEH,OAAO,CAsBnB;CACD"}
@@ -18,7 +18,15 @@ declare class ViewRecordSetSUBSETFilters extends libPictView {
18
18
  newFilterSearchApplied: boolean;
19
19
  addFilterCallback: Function;
20
20
  removeFilterCallback: Function;
21
+ _drawerOpen: boolean;
22
+ _searchString: {};
21
23
  _renderEpoch: number;
24
+ _addFilterOpen: boolean;
25
+ _addFilterRecordSet: string;
26
+ _addFilterViewContext: string;
27
+ _addFilterSearch: string;
28
+ _addFilterExpandedKey: any;
29
+ filterFieldBlacklist: any[];
22
30
  /**
23
31
  * Bump the render epoch. Call this whenever the active filter clauses are
24
32
  * about to change in a way that would invalidate in-flight filter renders.
@@ -64,6 +72,27 @@ declare class ViewRecordSetSUBSETFilters extends libPictView {
64
72
  * @returns {any} The result of the super.onMarshalToView() method.
65
73
  */
66
74
  onMarshalToView(): any;
75
+ /** Toggle the slide-out filter drawer beneath the search bar. */
76
+ toggleFilterDrawer(): boolean;
77
+ /**
78
+ * The current search term, read back from the active route URL (the source of truth) so
79
+ * the search box stays populated across re-renders and reflects bookmarked/filtered URLs.
80
+ * performSearch builds `.../FilteredTo/FBVOR~<field>~LK~<encoded %term%>~...` from the
81
+ * SearchFields, so the term is the first LK value in the FilteredTo segment.
82
+ *
83
+ * @return {string}
84
+ */
85
+ _searchTermFromURL(): string;
86
+ /** The number of active (structured) filter clauses for a record set. */
87
+ getActiveFilterCount(pRecordSet: any): number;
88
+ /**
89
+ * Repaint the filter-bar chrome after a (re)render: the filters icon (outline vs filled
90
+ * + count badge), the active-filter highlight, the persisted drawer-open state, and the
91
+ * search input value (so applying a search no longer clears the search box).
92
+ *
93
+ * @param {string} pRecordSet
94
+ */
95
+ _paintFilterControls(pRecordSet: string): void;
67
96
  /**
68
97
  * @param {Event} pEvent - The DOM event that triggered the search
69
98
  * @param {string} pRecordSet - The record set being filtered
@@ -102,7 +131,28 @@ declare class ViewRecordSetSUBSETFilters extends libPictView {
102
131
  * @param {string} pRecordSet - The record set being filtered
103
132
  * @param {string} pViewContext - The view context for the filter (ex. List, Dashboard)
104
133
  */
105
- selectFilterToAdd(pEvent: Event, pRecordSet: string, pViewContext: string): void;
134
+ toggleAddFilterPopover(pEvent: Event, pRecordSet: string, pViewContext: string): void;
135
+ /** Close the add-filter popover. */
136
+ closeAddFilterPopover(): void;
137
+ /**
138
+ * Filter the add-filter field list by a search term, re-rendering only the list so the
139
+ * search input keeps focus.
140
+ * @param {string} pValue - The search term.
141
+ */
142
+ searchAddFilter(pValue: string): void;
143
+ /**
144
+ * Expand or collapse a field's available clauses in the add-filter popover.
145
+ * @param {string} pFilterKey - The field whose clauses to toggle.
146
+ */
147
+ toggleAddFilterField(pFilterKey: string): void;
148
+ /**
149
+ * (Re)build the add-filter popover's field list into AppData from the record set's filter
150
+ * schema, honouring the current search term and the expanded field.
151
+ * @param {string} pRecordSet - The record set whose filter schema to read.
152
+ */
153
+ _buildAddFilterFields(pRecordSet: string): void;
154
+ /** Reflect the add-filter popover's open/closed state on its container element. */
155
+ _paintAddFilterOpenState(): void;
106
156
  /**
107
157
  * @param {Event} pEvent - The DOM event that triggered the search
108
158
  * @param {string} pRecordSet - The record set being filtered
@@ -159,9 +209,11 @@ declare class ViewRecordSetSUBSETFilters extends libPictView {
159
209
  decode(base64: string): ArrayBuffer;
160
210
  }
161
211
  declare namespace ViewRecordSetSUBSETFilters {
162
- export { _DEFAULT_CONFIGURATION_SUBSET_Filter as default_configuration };
212
+ export { FilterIconOutline, FilterIconFilled, _DEFAULT_CONFIGURATION_SUBSET_Filter as default_configuration };
163
213
  }
164
214
  import libPictView = require("pict-view");
215
+ declare var FilterIconOutline: string;
216
+ declare var FilterIconFilled: string;
165
217
  /** @type {Record<string, any>} */
166
218
  declare const _DEFAULT_CONFIGURATION_SUBSET_Filter: Record<string, any>;
167
219
  //# sourceMappingURL=RecordSet-Filters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RecordSet-Filters.d.ts","sourceRoot":"","sources":["../../source/views/RecordSet-Filters.js"],"names":[],"mappings":";AA6MA;IAEC,2DAuCC;IAnCA,kHAAkH;IAClH,MADW,GAAe,GAAG,OAAO,MAAM,CAAC,GAAG;QAAE,oBAAoB,EAAE;;;;;;;;SAAsC,CAAA;KAAE,CACrG;IAeT,cAA+E;IAG/E,wCAA0E;IAK1E,gCAAmC;IACnC,4BAA6B;IAC7B,+BAAgC;IAQhC,qBAAqB;IAGtB;;;;;OAKG;IACH,mBAFY,MAAM,CAMjB;IAED;;;OAGG;IACH,gDAGC;IAED;;;OAGG;IACH,mDAGC;IAED;;OAEG;IACH,gCAGC;IAED;;OAEG;IACH,mCAGC;IAED;;OAEG;IACH,6BAFY,MAAM,CAKjB;IAED;;;;OAIG;IACH,kCAJW,MAAM,GAEL,GAAG,CAMd;IAKD;;;OAGG;IACH,qBAFa,GAAG,CAaf;IAED;;;OAGG;IACH,mBAFa,GAAG,CAaf;IAED;;;;OAIG;IACH,qBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAUhB;IAED;;;;OAIG;IACH,0BAJW,MAAM,gBACN,MAAM,kBACN,MAAM,QAsDhB;IAED;;;;;OAKG;IACH,oBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAUhB;IAGD;;;;;OAKG;IACH,oBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAoBhB;IAED;;;;;MAKE;IACF,qBALW,KAAK,cACL,MAAM,gBACN,MAAM,GACJ,OAAO,CAQnB;IAED;;;;OAIG;IACH,0BAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAQhB;IAED;;;;;;OAMG;IACH,kBANW,KAAK,cACL,MAAM,gBACN,MAAM,cACN,MAAM,cACN,MAAM,QAWhB;IAED;;;;;OAKG;IACH,qBALW,KAAK,cACL,MAAM,gBACN,MAAM,sBACN,MAAM,QAWhB;IAED;;;;OAIG;IACH,4BAHW,MAAM,GACL,KAAK,CAAC,GAAG,CAAC,CAMrB;IAmDD;;;;OAIG;IACH,uCAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,OAAO,CAAC,MAAM,CAAC,CAiB1B;IAED;;;;OAIG;IACH,yCAHW,MAAM,GACL,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAUvC;IAED;;;;OAIG;IACH,iBAJW,MAAM,aACN,iBAAiB,GAChB,OAAO,CAAC,WAAW,CAAC,CAU/B;IAED;;;OAGG;IACH,sBAHW,UAAU,aACV,iBAAiB,mBAa3B;IAED;;;OAGG;IACH,oBAHW,WAAW,GACV,MAAM,CA2BjB;IAED;;;OAGG;IACH,eAHW,MAAM,GACL,WAAW,CAsCtB;CACD;;;;;AAxtBD,kCAAkC;AAClC,oDADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA6J5B"}
1
+ {"version":3,"file":"RecordSet-Filters.d.ts","sourceRoot":"","sources":["../../source/views/RecordSet-Filters.js"],"names":[],"mappings":";AAgTA;IAEC,2DAoDC;IAhDA,kHAAkH;IAClH,MADW,GAAe,GAAG,OAAO,MAAM,CAAC,GAAG;QAAE,oBAAoB,EAAE;;;;;;;;SAAsC,CAAA;KAAE,CACrG;IAeT,cAA+E;IAG/E,wCAA0E;IAK1E,gCAAmC;IACnC,4BAA6B;IAC7B,+BAAgC;IAGhC,qBAAwB;IACxB,kBAAuB;IAQvB,qBAAqB;IAErB,wBAA2B;IAC3B,4BAA+B;IAC/B,8BAAiC;IACjC,yBAA0B;IAC1B,2BAAiC;IAGjC,4BAA8B;IAG/B;;;;;OAKG;IACH,mBAFY,MAAM,CAMjB;IAED;;;OAGG;IACH,gDAGC;IAED;;;OAGG;IACH,mDAGC;IAED;;OAEG;IACH,gCAGC;IAED;;OAEG;IACH,mCAGC;IAED;;OAEG;IACH,6BAFY,MAAM,CAKjB;IAED;;;;OAIG;IACH,kCAJW,MAAM,GAEL,GAAG,CAMd;IAKD;;;OAGG;IACH,qBAFa,GAAG,CAaf;IAED;;;OAGG;IACH,mBAFa,GAAG,CAaf;IAED,iEAAiE;IACjE,8BAMC;IAED;;;;;;;OAOG;IACH,sBAFY,MAAM,CAcjB;IAED,yEAAyE;IACzE,8CAKC;IAED;;;;;;OAMG;IACH,iCAFW,MAAM,QAehB;IAED;;;;OAIG;IACH,qBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAUhB;IAED;;;;OAIG;IACH,0BAJW,MAAM,gBACN,MAAM,kBACN,MAAM,QAsDhB;IAED;;;;;OAKG;IACH,oBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAWhB;IAGD;;;;;OAKG;IACH,oBAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAoBhB;IAED;;;;;MAKE;IACF,qBALW,KAAK,cACL,MAAM,gBACN,MAAM,GACJ,OAAO,CAQnB;IAED;;;;OAIG;IACH,+BAJW,KAAK,cACL,MAAM,gBACN,MAAM,QAiBhB;IAED,oCAAoC;IACpC,8BAKC;IAED;;;;OAIG;IACH,wBAFW,MAAM,QAOhB;IAED;;;OAGG;IACH,iCAFW,MAAM,QAOhB;IAED;;;;OAIG;IACH,kCAFW,MAAM,QAgChB;IAED,mFAAmF;IACnF,iCAIC;IAED;;;;;;OAMG;IACH,kBANW,KAAK,cACL,MAAM,gBACN,MAAM,cACN,MAAM,cACN,MAAM,QAWhB;IAED;;;;;OAKG;IACH,qBALW,KAAK,cACL,MAAM,gBACN,MAAM,sBACN,MAAM,QAWhB;IAED;;;;OAIG;IACH,4BAHW,MAAM,GACL,KAAK,CAAC,GAAG,CAAC,CAMrB;IAgGD;;;;OAIG;IACH,uCAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,OAAO,CAAC,MAAM,CAAC,CAiB1B;IAED;;;;OAIG;IACH,yCAHW,MAAM,GACL,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAUvC;IAED;;;;OAIG;IACH,iBAJW,MAAM,aACN,iBAAiB,GAChB,OAAO,CAAC,WAAW,CAAC,CAU/B;IAED;;;OAGG;IACH,sBAHW,UAAU,aACV,iBAAiB,mBAa3B;IAED;;;OAGG;IACH,oBAHW,WAAW,GACV,MAAM,CA2BjB;IAED;;;OAGG;IACH,eAHW,MAAM,GACL,WAAW,CAsCtB;CACD;;;;;;;AAvgCD,kCAAkC;AAClC,oDADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAgQ5B"}
@@ -8,6 +8,20 @@ declare class ViewRecordSetSUBSETFilterBase extends libPictView {
8
8
  */
9
9
  prepareRecord(pRecord: Record<string, any>): void;
10
10
  getFilterFormTemplate(): string;
11
+ /**
12
+ * Remove this filter clause from its record set and re-render the filter control.
13
+ *
14
+ * Lives on the base view so every filter type inherits a single, themeable remove
15
+ * affordance and no host application has to re-implement one. Delegates to the
16
+ * consolidated control view (the canonical re-render path) and falls back to the
17
+ * record-set provider directly if that view is somehow unavailable.
18
+ *
19
+ * @param {Event} pEvent - The DOM event that triggered the removal.
20
+ * @param {string} pRecordSet - The record set being filtered.
21
+ * @param {string} pViewContext - The view context for the filter (e.g. List, Dashboard).
22
+ * @param {string} pHash - The hash of the specific filter clause to remove.
23
+ */
24
+ removeClause(pEvent: Event, pRecordSet: string, pViewContext: string, pHash: string): any;
11
25
  /**
12
26
  * @return {string} - The prefix for the informary address.
13
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"RecordSet-Filter-Base.d.ts","sourceRoot":"","sources":["../../../source/views/filters/RecordSet-Filter-Base.js"],"names":[],"mappings":";AAmEA;IAEC,2DAIC;IAED;;;;OAIG;IACH,uBAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAgB7B;IAED,gCAGC;IAED;;OAEG;IACH,6BAFY,MAAM,CAKjB;IAED;;;;OAIG;IACH,2CAJW,MAAM,GAEL,GAAG,CAKd;CACD;;;;;AApHD,kCAAkC;AAClC,oDADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA+D5B"}
1
+ {"version":3,"file":"RecordSet-Filter-Base.d.ts","sourceRoot":"","sources":["../../../source/views/filters/RecordSet-Filter-Base.js"],"names":[],"mappings":";AAkHA;IAEC,2DAIC;IAED;;;;OAIG;IACH,uBAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAgB7B;IAED,gCAGC;IAED;;;;;;;;;;;;OAYG;IACH,qBALW,KAAK,cACL,MAAM,gBACN,MAAM,SACN,MAAM,OAmBhB;IAED;;OAEG;IACH,6BAFY,MAAM,CAKjB;IAED;;;;OAIG;IACH,2CAJW,MAAM,GAEL,GAAG,CAKd;CACD;;;;;AAnMD,kCAAkC;AAClC,oDADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA8G5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"RecordSet-List.d.ts","sourceRoot":"","sources":["../../../source/views/list/RecordSet-List.js"],"names":[],"mappings":";AA4EA;IAOE;;;;;;;;MAQC;IAGF,4DAwBC;IAiBD,8CAGC;IAED,sDAqCC;IAjCA,iCAUC;IAyBF;;;;;;;;;OASG;IACH,oCATW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,iBACnB,MAAM,iBACN,MAAM,+BACN,MAAM,WACN,MAAM,aACN,MAAM,GAEL,OAAO,CAAC,IAAI,CAAC,CAwPxB;IAED;;;;;;;;;;OAUG;IACH,kCAVW,MAAM,2BACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,iBACnB,MAAM,iBACN,MAAM,+BACN,MAAM,WACN,MAAM,aACN,MAAM,GAEL,OAAO,CAAC,IAAI,CAAC,CAoPxB;CAwBD;;;;;AA/rBD,kCAAkC;AAClC,4CADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA+D1B"}
1
+ {"version":3,"file":"RecordSet-List.d.ts","sourceRoot":"","sources":["../../../source/views/list/RecordSet-List.js"],"names":[],"mappings":";AA4EA;IAOE;;;;;;;;MAQC;IAGF,4DAwBC;IAiBD,8CAGC;IAED,sDAqCC;IAjCA,iCAUC;IAyBF;;;;;;;;;OASG;IACH,oCATW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,iBACnB,MAAM,iBACN,MAAM,+BACN,MAAM,WACN,MAAM,aACN,MAAM,GAEL,OAAO,CAAC,IAAI,CAAC,CAgQxB;IAED;;;;;;;;;;OAUG;IACH,kCAVW,MAAM,2BACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,iBACnB,MAAM,iBACN,MAAM,+BACN,MAAM,WACN,MAAM,aACN,MAAM,GAEL,OAAO,CAAC,IAAI,CAAC,CA4PxB;CAwBD;;;;;AA/sBD,kCAAkC;AAClC,4CADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA+D1B"}
@@ -34,6 +34,57 @@ declare class viewRecordSetRead extends libPictRecordSetRecordView {
34
34
  cancel(): Promise<void>;
35
35
  save(): Promise<void>;
36
36
  edit(): Promise<void>;
37
+ /**
38
+ * Build the record audit header state — the first-class activity line plus the data the
39
+ * Details modal renders. Identity (ID/GUID) and the create/update/delete stamps are read
40
+ * straight off the fetched record; the acting-user names resolve lazily via {~E:User^…~}
41
+ * in the templates (cachetrax-cached), so nothing is pre-resolved here. Stored at
42
+ * AppData.PRSP_RecordAudit for the templates to consume.
43
+ *
44
+ * @param {Record<string, any>} pRecord - The fetched record.
45
+ */
46
+ _prepareRecordAuditState(pRecord: Record<string, any>): void;
47
+ /**
48
+ * Compute a human-friendly display name for a record using an opinionated heuristic: first +
49
+ * last name, then a single descriptive field (FullName, Name, Title, …), else ''. Callers fall
50
+ * back to the GUID. Lets the page title read "Krishna Pavia Tester" instead of a raw GUID.
51
+ * @param {Record<string, any>} pRecord
52
+ * @return {string}
53
+ */
54
+ _computeDisplayName(pRecord: Record<string, any>): string;
55
+ /**
56
+ * Whether an audit date value is present and meaningful (guards null/empty and the Meadow
57
+ * "0000-00-00" zero-date sentinel).
58
+ * @param {any} pValue
59
+ * @return {boolean}
60
+ */
61
+ _validAuditDate(pValue: any): boolean;
62
+ /**
63
+ * Toggle the anchored identity + audit popover open or closed. The content is rendered inline
64
+ * with the record (so the {~E:User^…~} names resolve during the read render); this just flips
65
+ * its visibility — no overlay.
66
+ */
67
+ toggleRecordAudit(): void;
68
+ /**
69
+ * Bind the one-time document handlers that dismiss the audit popover on an outside click or
70
+ * Escape. Browser-level events with no inline-handler equivalent — bound once and guarded so
71
+ * re-renders don't stack listeners.
72
+ */
73
+ _bindAuditDismiss(): void;
74
+ _auditDismissBound: boolean;
75
+ /**
76
+ * Copy a record value (ID or GUID) to the clipboard from the audit popover, with a toast.
77
+ * @param {string} pValue
78
+ */
79
+ copyValue(pValue: string): void;
80
+ /**
81
+ * Remove identity + audit descriptors from a (cloned) manifest so they don't render inline
82
+ * in the record body — they live behind the audit header's Details modal instead. Also
83
+ * prunes any section left with no descriptors (e.g. an emptied "Audit Trail" section). The
84
+ * entity's own ID/GUID field names are suppressed alongside the shared audit fields.
85
+ * @param {Record<string, any>} pManifest - The cloned manifest to mutate.
86
+ */
87
+ _suppressAuditDescriptors(pManifest: Record<string, any>): void;
37
88
  onBeforeRenderRead(pRecordReadData: any): any;
38
89
  formatDisplayData(pRecordListData: any): any;
39
90
  onBeforeEdit(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"RecordSet-Read.d.ts","sourceRoot":"","sources":["../../../source/views/read/RecordSet-Read.js"],"names":[],"mappings":";AAgQA;IAOE,mBAAyB;IACzB,eAAoB;IACpB,YAAc;IACd,eAAqB;IACrB,kBAAwB;IACxB,eAAqB;IACrB,mCAAwB;IACxB,cAAoB;IACpB;;;;;;;;;;;;;;;;;MAA2B;IAC3B,UAAgB;IAGjB,+BAqCC;IAED,yCAQC;IAED,+DAiBC;IAED,+DAiBC;IASD,wBAIC;IAED,sBAMC;IAED,sBAIC;IAED,8CAIC;IAED,6CAcC;IAED,8BAGC;IAED,8BAGC;IAED,8BAGC;IAED,mCAGC;IAED,8FA8HC;IAED,8BAyBC;IAED;;;;;;;;;;;;;;;;;OAiFC;IAED,gJAsDC;IAED;;;;;;;;SAqLC;CAUD;;;;;AAl5BD,kCAAkC;AAClC,4CADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA4P1B"}
1
+ {"version":3,"file":"RecordSet-Read.d.ts","sourceRoot":"","sources":["../../../source/views/read/RecordSet-Read.js"],"names":[],"mappings":";AAwUA;IAOE,mBAAyB;IACzB,eAAoB;IACpB,YAAc;IACd,eAAqB;IACrB,kBAAwB;IACxB,eAAqB;IACrB,mCAAwB;IACxB,cAAoB;IACpB;;;;;;;;;;;;;;;;;MAA2B;IAC3B,UAAgB;IAGjB,+BAqCC;IAED,yCAUC;IAED,+DAiBC;IAED,+DAiBC;IASD,wBAIC;IAED,sBAMC;IAED,sBAIC;IAED;;;;;;;;OAQG;IACH,kCAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAyC7B;IAED;;;;;;OAMG;IACH,6BAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,MAAM,CAuBjB;IAED;;;;;OAKG;IACH,wBAHW,GAAG,GACF,OAAO,CASlB;IAED;;;;OAIG;IACH,0BAOC;IAED;;;;OAIG;IACH,0BA+BC;IAzBA,4BAA8B;IA2B/B;;;OAGG;IACH,kBAFW,MAAM,QAoBhB;IAED;;;;;;OAMG;IACH,qCAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAsC7B;IAED,8CAIC;IAED,6CAcC;IAED,8BAGC;IAED,8BAGC;IAED,8BAGC;IAED,mCAGC;IAED,8FAyIC;IAED,8BAyBC;IAED;;;;;;;;;;;;;;;;;OAiFC;IAED,gJA2DC;IAED;;;;;;;;SAqLC;CAUD;;;;;AA9rCD,kCAAkC;AAClC,4CADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA8T1B"}