@memberjunction/ng-dashboards 6.2.0-edge.2 → 6.2.0-edge.4

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 (229) hide show
  1. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts +4 -3
  2. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts.map +1 -1
  3. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js +8 -5
  4. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js.map +1 -1
  5. package/dist/AI/components/duplicates/compare-value.component.d.ts +67 -0
  6. package/dist/AI/components/duplicates/compare-value.component.d.ts.map +1 -0
  7. package/dist/AI/components/duplicates/compare-value.component.js +168 -0
  8. package/dist/AI/components/duplicates/compare-value.component.js.map +1 -0
  9. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +49 -3
  10. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  11. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +287 -169
  12. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  13. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +77 -0
  14. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -0
  15. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +116 -0
  16. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -0
  17. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
  18. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
  19. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +16 -4
  20. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
  21. package/dist/AI/components/tags/tags-resource.component.d.ts +2 -0
  22. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  23. package/dist/AI/components/tags/tags-resource.component.js +12 -6
  24. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  25. package/dist/AI/components/vectors/vector-index-auto.d.ts +29 -0
  26. package/dist/AI/components/vectors/vector-index-auto.d.ts.map +1 -0
  27. package/dist/AI/components/vectors/vector-index-auto.js +59 -0
  28. package/dist/AI/components/vectors/vector-index-auto.js.map +1 -0
  29. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +9 -0
  30. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  31. package/dist/AI/components/vectors/vector-management-resource.component.js +65 -20
  32. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  33. package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
  34. package/dist/Actions/components/actions-overview.component.js +7 -3
  35. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  36. package/dist/Actions/components/categories-list-view.component.d.ts.map +1 -1
  37. package/dist/Actions/components/categories-list-view.component.js +3 -2
  38. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  39. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  40. package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
  41. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  42. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts +0 -3
  43. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.d.ts.map +1 -1
  44. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +5 -14
  45. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js.map +1 -1
  46. package/dist/ComponentStudio/components/artifact-load-dialog.component.d.ts.map +1 -1
  47. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +1 -0
  48. package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
  49. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  50. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +1 -0
  51. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  52. package/dist/ComponentStudio/components/form-override-dialog.component.d.ts +12 -1
  53. package/dist/ComponentStudio/components/form-override-dialog.component.d.ts.map +1 -1
  54. package/dist/ComponentStudio/components/form-override-dialog.component.js +128 -81
  55. package/dist/ComponentStudio/components/form-override-dialog.component.js.map +1 -1
  56. package/dist/Credentials/components/credentials-list-resource.component.d.ts +2 -0
  57. package/dist/Credentials/components/credentials-list-resource.component.d.ts.map +1 -1
  58. package/dist/Credentials/components/credentials-list-resource.component.js +12 -10
  59. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  60. package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts +14 -43
  61. package/dist/DashboardBrowser/dashboard-browser-agent-context.d.ts.map +1 -1
  62. package/dist/DashboardBrowser/dashboard-browser-agent-context.js +6 -29
  63. package/dist/DashboardBrowser/dashboard-browser-agent-context.js.map +1 -1
  64. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts +174 -321
  65. package/dist/DashboardBrowser/dashboard-browser-resource.component.d.ts.map +1 -1
  66. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +522 -1195
  67. package/dist/DashboardBrowser/dashboard-browser-resource.component.js.map +1 -1
  68. package/dist/DashboardBrowser/dashboard-library-filter.d.ts +116 -0
  69. package/dist/DashboardBrowser/dashboard-library-filter.d.ts.map +1 -0
  70. package/dist/DashboardBrowser/dashboard-library-filter.js +277 -0
  71. package/dist/DashboardBrowser/dashboard-library-filter.js.map +1 -0
  72. package/dist/DashboardBrowser/dashboard-share-dialog.component.d.ts +1 -1
  73. package/dist/DashboardBrowser/dashboard-share-dialog.component.js.map +1 -1
  74. package/dist/DashboardBrowser/dashboards-agent-tools.d.ts +26 -0
  75. package/dist/DashboardBrowser/dashboards-agent-tools.d.ts.map +1 -0
  76. package/dist/DashboardBrowser/dashboards-agent-tools.js +32 -0
  77. package/dist/DashboardBrowser/dashboards-agent-tools.js.map +1 -0
  78. package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts +58 -0
  79. package/dist/DashboardBrowser/dashboards-categories-resource.component.d.ts.map +1 -0
  80. package/dist/DashboardBrowser/dashboards-categories-resource.component.js +391 -0
  81. package/dist/DashboardBrowser/dashboards-categories-resource.component.js.map +1 -0
  82. package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts +37 -0
  83. package/dist/DashboardBrowser/dashboards-categories.helpers.d.ts.map +1 -0
  84. package/dist/DashboardBrowser/dashboards-categories.helpers.js +68 -0
  85. package/dist/DashboardBrowser/dashboards-categories.helpers.js.map +1 -0
  86. package/dist/DashboardEditor/dashboard-editor.component.d.ts +295 -0
  87. package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -0
  88. package/dist/DashboardEditor/dashboard-editor.component.js +1022 -0
  89. package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -0
  90. package/dist/DashboardEditor/dashboard-editor.types.d.ts +23 -0
  91. package/dist/DashboardEditor/dashboard-editor.types.d.ts.map +1 -0
  92. package/dist/DashboardEditor/dashboard-editor.types.js +3 -0
  93. package/dist/DashboardEditor/dashboard-editor.types.js.map +1 -0
  94. package/dist/DashboardEditor/dashboard-viewer-factory.d.ts +11 -0
  95. package/dist/DashboardEditor/dashboard-viewer-factory.d.ts.map +1 -0
  96. package/dist/DashboardEditor/dashboard-viewer-factory.js +17 -0
  97. package/dist/DashboardEditor/dashboard-viewer-factory.js.map +1 -0
  98. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +30 -0
  99. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  100. package/dist/DataExplorer/data-explorer-dashboard.component.js +349 -232
  101. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  102. package/dist/DataExplorer/services/explorer-state.service.d.ts +1 -1
  103. package/dist/DataExplorer/services/explorer-state.service.js +2 -5
  104. package/dist/DataExplorer/services/explorer-state.service.js.map +1 -1
  105. package/dist/FormBuilder/form-builder-resource.component.d.ts +0 -14
  106. package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
  107. package/dist/FormBuilder/form-builder-resource.component.js +7 -29
  108. package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
  109. package/dist/Home/home-agent-context.d.ts +29 -10
  110. package/dist/Home/home-agent-context.d.ts.map +1 -1
  111. package/dist/Home/home-agent-context.js +50 -24
  112. package/dist/Home/home-agent-context.js.map +1 -1
  113. package/dist/Home/home-dashboard-switcher.component.d.ts +95 -0
  114. package/dist/Home/home-dashboard-switcher.component.d.ts.map +1 -0
  115. package/dist/Home/home-dashboard-switcher.component.js +442 -0
  116. package/dist/Home/home-dashboard-switcher.component.js.map +1 -0
  117. package/dist/Home/home-dashboard.component.d.ts +330 -17
  118. package/dist/Home/home-dashboard.component.d.ts.map +1 -1
  119. package/dist/Home/home-dashboard.component.js +1702 -1014
  120. package/dist/Home/home-dashboard.component.js.map +1 -1
  121. package/dist/Home/home-menus.d.ts +38 -0
  122. package/dist/Home/home-menus.d.ts.map +1 -0
  123. package/dist/Home/home-menus.js +53 -0
  124. package/dist/Home/home-menus.js.map +1 -0
  125. package/dist/Home/home-pinned-dashboards.d.ts +33 -0
  126. package/dist/Home/home-pinned-dashboards.d.ts.map +1 -0
  127. package/dist/Home/home-pinned-dashboards.js +76 -0
  128. package/dist/Home/home-pinned-dashboards.js.map +1 -0
  129. package/dist/PredictiveStudio/components/ps-production.component.d.ts +5 -1
  130. package/dist/PredictiveStudio/components/ps-production.component.d.ts.map +1 -1
  131. package/dist/PredictiveStudio/components/ps-production.component.js +64 -41
  132. package/dist/PredictiveStudio/components/ps-production.component.js.map +1 -1
  133. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  134. package/dist/QueryBrowser/query-browser-resource.component.js +3 -2
  135. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  136. package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js +2 -2
  137. package/dist/RealtimeRecordings/realtime-recordings-dashboard.component.js.map +1 -1
  138. package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts +107 -0
  139. package/dist/TelephonyOperations/telephony-operations-agent-context.d.ts.map +1 -0
  140. package/dist/TelephonyOperations/telephony-operations-agent-context.js +216 -0
  141. package/dist/TelephonyOperations/telephony-operations-agent-context.js.map +1 -0
  142. package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts +58 -0
  143. package/dist/TelephonyOperations/telephony-operations-dashboard.component.d.ts.map +1 -0
  144. package/dist/TelephonyOperations/telephony-operations-dashboard.component.js +812 -0
  145. package/dist/TelephonyOperations/telephony-operations-dashboard.component.js.map +1 -0
  146. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  147. package/dist/Testing/components/testing-explorer.component.js +7 -7
  148. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  149. package/dist/WorkQueue/components/work-queue-bindings.component.d.ts +37 -0
  150. package/dist/WorkQueue/components/work-queue-bindings.component.d.ts.map +1 -0
  151. package/dist/WorkQueue/components/work-queue-bindings.component.js +210 -0
  152. package/dist/WorkQueue/components/work-queue-bindings.component.js.map +1 -0
  153. package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts +70 -0
  154. package/dist/WorkQueue/components/work-queue-dead-letters.component.d.ts.map +1 -0
  155. package/dist/WorkQueue/components/work-queue-dead-letters.component.js +496 -0
  156. package/dist/WorkQueue/components/work-queue-dead-letters.component.js.map +1 -0
  157. package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts +22 -0
  158. package/dist/WorkQueue/components/work-queue-discard-dialog.component.d.ts.map +1 -0
  159. package/dist/WorkQueue/components/work-queue-discard-dialog.component.js +99 -0
  160. package/dist/WorkQueue/components/work-queue-discard-dialog.component.js.map +1 -0
  161. package/dist/WorkQueue/components/work-queue-overview.component.d.ts +29 -0
  162. package/dist/WorkQueue/components/work-queue-overview.component.d.ts.map +1 -0
  163. package/dist/WorkQueue/components/work-queue-overview.component.js +278 -0
  164. package/dist/WorkQueue/components/work-queue-overview.component.js.map +1 -0
  165. package/dist/WorkQueue/components/work-queue-partitions.component.d.ts +59 -0
  166. package/dist/WorkQueue/components/work-queue-partitions.component.d.ts.map +1 -0
  167. package/dist/WorkQueue/components/work-queue-partitions.component.js +359 -0
  168. package/dist/WorkQueue/components/work-queue-partitions.component.js.map +1 -0
  169. package/dist/WorkQueue/services/work-queue-operator.service.d.ts +22 -0
  170. package/dist/WorkQueue/services/work-queue-operator.service.d.ts.map +1 -0
  171. package/dist/WorkQueue/services/work-queue-operator.service.js +44 -0
  172. package/dist/WorkQueue/services/work-queue-operator.service.js.map +1 -0
  173. package/dist/WorkQueue/work-queue-agent-context.d.ts +67 -0
  174. package/dist/WorkQueue/work-queue-agent-context.d.ts.map +1 -0
  175. package/dist/WorkQueue/work-queue-agent-context.js +119 -0
  176. package/dist/WorkQueue/work-queue-agent-context.js.map +1 -0
  177. package/dist/WorkQueue/work-queue-dashboard.component.d.ts +94 -0
  178. package/dist/WorkQueue/work-queue-dashboard.component.d.ts.map +1 -0
  179. package/dist/WorkQueue/work-queue-dashboard.component.js +545 -0
  180. package/dist/WorkQueue/work-queue-dashboard.component.js.map +1 -0
  181. package/dist/WorkQueue/work-queue-types.d.ts +40 -0
  182. package/dist/WorkQueue/work-queue-types.d.ts.map +1 -0
  183. package/dist/WorkQueue/work-queue-types.js +2 -0
  184. package/dist/WorkQueue/work-queue-types.js.map +1 -0
  185. package/dist/ai-dashboards.module.d.ts +21 -20
  186. package/dist/ai-dashboards.module.d.ts.map +1 -1
  187. package/dist/ai-dashboards.module.js +4 -1
  188. package/dist/ai-dashboards.module.js.map +1 -1
  189. package/dist/core-dashboards.module.d.ts +69 -61
  190. package/dist/core-dashboards.module.d.ts.map +1 -1
  191. package/dist/core-dashboards.module.js +29 -2
  192. package/dist/core-dashboards.module.js.map +1 -1
  193. package/dist/data-explorer-dashboards.module.d.ts +1 -1
  194. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  195. package/dist/data-explorer-dashboards.module.js +3 -1
  196. package/dist/data-explorer-dashboards.module.js.map +1 -1
  197. package/dist/module.d.ts +14 -13
  198. package/dist/module.d.ts.map +1 -1
  199. package/dist/module.js +7 -0
  200. package/dist/module.js.map +1 -1
  201. package/dist/public-api.d.ts +6 -0
  202. package/dist/public-api.d.ts.map +1 -1
  203. package/dist/public-api.js +9 -0
  204. package/dist/public-api.js.map +1 -1
  205. package/dist/shared/dashboard-library-changes.d.ts +23 -0
  206. package/dist/shared/dashboard-library-changes.d.ts.map +1 -0
  207. package/dist/shared/dashboard-library-changes.js +26 -0
  208. package/dist/shared/dashboard-library-changes.js.map +1 -0
  209. package/dist/shared/dashboard-owner-names.d.ts +17 -0
  210. package/dist/shared/dashboard-owner-names.d.ts.map +1 -0
  211. package/dist/shared/dashboard-owner-names.js +65 -0
  212. package/dist/shared/dashboard-owner-names.js.map +1 -0
  213. package/dist/shared/dashboard-recents.d.ts +34 -0
  214. package/dist/shared/dashboard-recents.d.ts.map +1 -0
  215. package/dist/shared/dashboard-recents.js +87 -0
  216. package/dist/shared/dashboard-recents.js.map +1 -0
  217. package/dist/shared/dashboards-app-install.d.ts +59 -0
  218. package/dist/shared/dashboards-app-install.d.ts.map +1 -0
  219. package/dist/shared/dashboards-app-install.js +97 -0
  220. package/dist/shared/dashboards-app-install.js.map +1 -0
  221. package/dist/shared/dashboards-app.helpers.d.ts +42 -0
  222. package/dist/shared/dashboards-app.helpers.d.ts.map +1 -0
  223. package/dist/shared/dashboards-app.helpers.js +143 -0
  224. package/dist/shared/dashboards-app.helpers.js.map +1 -0
  225. package/dist/work-queue-dashboards.module.d.ts +23 -0
  226. package/dist/work-queue-dashboards.module.d.ts.map +1 -0
  227. package/dist/work-queue-dashboards.module.js +92 -0
  228. package/dist/work-queue-dashboards.module.js.map +1 -0
  229. package/package.json +73 -66
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Pure helpers that scope the Record Duplicates board to ONE duplicate run.
3
+ *
4
+ * The board joins `MJ: Duplicate Run Details` to `MJ: Duplicate Run Detail Matches` by
5
+ * DuplicateRunDetailID. Loading those two entities unscoped pulls every review row ever produced,
6
+ * for every entity and every run (hundreds of thousands of rows on a busy tenant), and the load
7
+ * grows with each run anyone performs. Restricting both sides to the run being viewed bounds the
8
+ * load to that run's rows, which is what the board actually renders.
9
+ *
10
+ * The scoping is done in two steps, details first and then matches by the detail IDs just loaded,
11
+ * on purpose. Matches carry no DuplicateRunID of their own, and the only single-query alternative is
12
+ * a subquery against the details view, which means naming a schema and a view from the client. The
13
+ * Angular client has no dialect knowledge (`QuoteSchemaAndView` lives on the server-side database
14
+ * providers, not on the GraphQL provider); the server does rewrite bracketed identifiers for
15
+ * PostgreSQL, but a view name chosen here is still a guess about the database behind the API. An
16
+ * `IN (...)` list of IDs is plain SQL everywhere, names nothing, and the join it produces is exact
17
+ * rather than re-derived. Cost: one extra round trip.
18
+ *
19
+ * Why both queries still carry `IgnoreMaxRows`: details truncate to the newest N by date while
20
+ * matches truncate to the top N by probability. Those two subsets diverge as soon as a run exceeds
21
+ * UserViewMaxRows (1000), leaving details with no loaded matches; buildGroups() then drops every
22
+ * such detail and the board is empty with a full run behind it. Scoping bounds the volume, and the
23
+ * flag keeps the join complete inside that bound. Dropping the flag would bring the empty board back
24
+ * for any single run larger than 1000 rows.
25
+ */
26
+ import { RunViewParams } from '@memberjunction/core';
27
+ /** The slice of an `MJ: Duplicate Runs` row the board needs to choose which run it shows. */
28
+ export interface DuplicateRunCandidate {
29
+ ID: string;
30
+ EntityID: string;
31
+ ProcessingStatus: string;
32
+ StartedAt: Date | string | null;
33
+ /** Set when the run covered one list's records rather than the whole entity. */
34
+ SourceListID: string | null;
35
+ }
36
+ /** How many detail IDs go into one matches query; keeps each `IN (...)` list a sane size. */
37
+ export declare const MATCH_QUERY_DETAIL_CHUNK_SIZE = 500;
38
+ /** The slice of an entity-document picker option needed to choose a default. */
39
+ export interface EntityDocumentCandidate {
40
+ ID: string;
41
+ EntityID: string;
42
+ }
43
+ /**
44
+ * Pick the run the board should display for an entity: the newest run that did not fail and covered
45
+ * the whole entity, or, when there is none, the newest run of any kind.
46
+ *
47
+ * Not "most recent Complete run": a run the user cancels keeps `ProcessingStatus = 'In Progress'`
48
+ * (the detector marks it for resumption), and the board's own idle timer can finish a detection
49
+ * before the server does; both end with a reload while a newer run exists, and preferring an older
50
+ * Complete run there would hide the rows the user just watched being produced. Not plain "newest"
51
+ * either: a Failed run usually has no details, and a list-scoped run holds a small subset, so each
52
+ * would hide a good entity-wide run behind an empty or partial board. Runs for other entities are
53
+ * never candidates. Returns null when there is no entity or no run for it.
54
+ */
55
+ export declare function SelectCurrentRunForEntity<T extends DuplicateRunCandidate>(runs: readonly T[], entityID: string | null | undefined): T | null;
56
+ /**
57
+ * The entity document the board should show before the user picks one: the document for the entity
58
+ * of the newest run worth showing (see {@link SelectCurrentRunForEntity}), so a first visit lands on
59
+ * results that exist. Falls back to the first document when no run matches any document, and to
60
+ * null when there are no documents at all.
61
+ */
62
+ export declare function PickDefaultEntityDocument<D extends EntityDocumentCandidate>(documents: readonly D[], runs: readonly DuplicateRunCandidate[]): D | null;
63
+ /** The completed details of ONE run, newest first. Bounded by the run; `IgnoreMaxRows` per the file comment. */
64
+ export declare function BuildRunScopedDetailsQuery(runID: string): RunViewParams;
65
+ /**
66
+ * The matches whose parent detail is one of `detailIDs`, as one query per chunk of
67
+ * {@link MATCH_QUERY_DETAIL_CHUNK_SIZE} IDs. No IDs, no queries. Plain `IN (...)` so it runs on any
68
+ * database behind the API; `IgnoreMaxRows` per the file comment.
69
+ */
70
+ export declare function BuildMatchQueriesForDetailIDs(detailIDs: readonly string[], chunkSize?: number): RunViewParams[];
71
+ /** The detail IDs a matches query built by {@link BuildMatchQueriesForDetailIDs} covers. */
72
+ export declare function DetailIDsCoveredByMatchQuery(query: RunViewParams): string[];
73
+ /** Index matches by their parent detail; the join buildGroups() performs. */
74
+ export declare function GroupMatchesByDetail<M extends {
75
+ DuplicateRunDetailID: string;
76
+ }>(matches: readonly M[]): Map<string, M[]>;
77
+ //# sourceMappingURL=duplicate-detection-run-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-detection-run-scope.d.ts","sourceRoot":"","sources":["../../../../src/AI/components/duplicates/duplicate-detection-run-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,6FAA6F;AAC7F,MAAM,WAAW,qBAAqB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,gFAAgF;IAChF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAaD,6FAA6F;AAC7F,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAIjD,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,qBAAqB,EACrE,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC,CAAC,GAAG,IAAI,CAMV;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,uBAAuB,EACvE,SAAS,EAAE,SAAS,CAAC,EAAE,EACvB,IAAI,EAAE,SAAS,qBAAqB,EAAE,GACvC,CAAC,GAAG,IAAI,CAcV;AAMD,gHAAgH;AAChH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAQvE;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CACzC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,SAAS,GAAE,MAAsC,GAClD,aAAa,EAAE,CAajB;AAED,4FAA4F;AAC5F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAO3E;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,oBAAoB,EAAE,MAAM,CAAA;CAAE,EAC3E,OAAO,EAAE,SAAS,CAAC,EAAE,GACtB,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAWlB"}
@@ -0,0 +1,116 @@
1
+ import { EscapeSQLString, IndexByUUID, UUIDsEqual } from '@memberjunction/global';
2
+ const RUN_FAILED = 'Failed';
3
+ /**
4
+ * A run worth putting on the board ahead of others: it did not fail (a run is marked Failed on any
5
+ * exception in detection, usually before a single detail is written) and it covered the whole
6
+ * entity rather than one list (a list run is a small subset that would hide the entity-wide results).
7
+ */
8
+ function isPreferredRun(run) {
9
+ return run.ProcessingStatus !== RUN_FAILED && !run.SourceListID;
10
+ }
11
+ /** How many detail IDs go into one matches query; keeps each `IN (...)` list a sane size. */
12
+ export const MATCH_QUERY_DETAIL_CHUNK_SIZE = 500;
13
+ const DETAIL_COMPLETE = 'Complete';
14
+ /**
15
+ * Pick the run the board should display for an entity: the newest run that did not fail and covered
16
+ * the whole entity, or, when there is none, the newest run of any kind.
17
+ *
18
+ * Not "most recent Complete run": a run the user cancels keeps `ProcessingStatus = 'In Progress'`
19
+ * (the detector marks it for resumption), and the board's own idle timer can finish a detection
20
+ * before the server does; both end with a reload while a newer run exists, and preferring an older
21
+ * Complete run there would hide the rows the user just watched being produced. Not plain "newest"
22
+ * either: a Failed run usually has no details, and a list-scoped run holds a small subset, so each
23
+ * would hide a good entity-wide run behind an empty or partial board. Runs for other entities are
24
+ * never candidates. Returns null when there is no entity or no run for it.
25
+ */
26
+ export function SelectCurrentRunForEntity(runs, entityID) {
27
+ if (!entityID) {
28
+ return null;
29
+ }
30
+ const forEntity = newestFirst(runs.filter(r => UUIDsEqual(r.EntityID, entityID)));
31
+ return forEntity.find(isPreferredRun) ?? forEntity[0] ?? null;
32
+ }
33
+ /**
34
+ * The entity document the board should show before the user picks one: the document for the entity
35
+ * of the newest run worth showing (see {@link SelectCurrentRunForEntity}), so a first visit lands on
36
+ * results that exist. Falls back to the first document when no run matches any document, and to
37
+ * null when there are no documents at all.
38
+ */
39
+ export function PickDefaultEntityDocument(documents, runs) {
40
+ if (documents.length === 0) {
41
+ return null;
42
+ }
43
+ // First document per entity wins, as documents.find() would.
44
+ const documentsByEntity = IndexByUUID(documents, d => d.EntityID);
45
+ const ordered = [...newestFirst(runs.filter(isPreferredRun)), ...newestFirst(runs)];
46
+ for (const run of ordered) {
47
+ const match = documentsByEntity.Get(run.EntityID);
48
+ if (match) {
49
+ return match;
50
+ }
51
+ }
52
+ return documents[0];
53
+ }
54
+ function newestFirst(runs) {
55
+ return [...runs].sort((a, b) => toTime(b.StartedAt) - toTime(a.StartedAt));
56
+ }
57
+ /** The completed details of ONE run, newest first. Bounded by the run; `IgnoreMaxRows` per the file comment. */
58
+ export function BuildRunScopedDetailsQuery(runID) {
59
+ return {
60
+ EntityName: 'MJ: Duplicate Run Details',
61
+ ExtraFilter: `DuplicateRunID='${EscapeSQLString(runID)}' AND MatchStatus='${DETAIL_COMPLETE}'`,
62
+ OrderBy: '__mj_CreatedAt DESC',
63
+ IgnoreMaxRows: true,
64
+ ResultType: 'entity_object'
65
+ };
66
+ }
67
+ /**
68
+ * The matches whose parent detail is one of `detailIDs`, as one query per chunk of
69
+ * {@link MATCH_QUERY_DETAIL_CHUNK_SIZE} IDs. No IDs, no queries. Plain `IN (...)` so it runs on any
70
+ * database behind the API; `IgnoreMaxRows` per the file comment.
71
+ */
72
+ export function BuildMatchQueriesForDetailIDs(detailIDs, chunkSize = MATCH_QUERY_DETAIL_CHUNK_SIZE) {
73
+ const queries = [];
74
+ for (let start = 0; start < detailIDs.length; start += chunkSize) {
75
+ const literals = detailIDs.slice(start, start + chunkSize).map(id => `'${EscapeSQLString(id)}'`);
76
+ queries.push({
77
+ EntityName: 'MJ: Duplicate Run Detail Matches',
78
+ ExtraFilter: `DuplicateRunDetailID IN (${literals.join(',')})`,
79
+ OrderBy: 'MatchProbability DESC',
80
+ IgnoreMaxRows: true,
81
+ ResultType: 'entity_object'
82
+ });
83
+ }
84
+ return queries;
85
+ }
86
+ /** The detail IDs a matches query built by {@link BuildMatchQueriesForDetailIDs} covers. */
87
+ export function DetailIDsCoveredByMatchQuery(query) {
88
+ const filter = typeof query.ExtraFilter === 'string' ? query.ExtraFilter : '';
89
+ const list = /DuplicateRunDetailID IN \((.*)\)/s.exec(filter)?.[1] ?? '';
90
+ return list
91
+ .split(/','/)
92
+ .map(part => part.replace(/^'|'$/g, '').replace(/''/g, "'"))
93
+ .filter(part => part.length > 0);
94
+ }
95
+ /** Index matches by their parent detail; the join buildGroups() performs. */
96
+ export function GroupMatchesByDetail(matches) {
97
+ const byDetail = new Map();
98
+ for (const match of matches) {
99
+ const existing = byDetail.get(match.DuplicateRunDetailID);
100
+ if (existing) {
101
+ existing.push(match);
102
+ }
103
+ else {
104
+ byDetail.set(match.DuplicateRunDetailID, [match]);
105
+ }
106
+ }
107
+ return byDetail;
108
+ }
109
+ function toTime(value) {
110
+ if (!value) {
111
+ return 0;
112
+ }
113
+ const time = new Date(value).getTime();
114
+ return isNaN(time) ? 0 : time;
115
+ }
116
+ //# sourceMappingURL=duplicate-detection-run-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-detection-run-scope.js","sourceRoot":"","sources":["../../../../src/AI/components/duplicates/duplicate-detection-run-scope.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure helpers that scope the Record Duplicates board to ONE duplicate run.\n *\n * The board joins `MJ: Duplicate Run Details` to `MJ: Duplicate Run Detail Matches` by\n * DuplicateRunDetailID. Loading those two entities unscoped pulls every review row ever produced,\n * for every entity and every run (hundreds of thousands of rows on a busy tenant), and the load\n * grows with each run anyone performs. Restricting both sides to the run being viewed bounds the\n * load to that run's rows, which is what the board actually renders.\n *\n * The scoping is done in two steps, details first and then matches by the detail IDs just loaded,\n * on purpose. Matches carry no DuplicateRunID of their own, and the only single-query alternative is\n * a subquery against the details view, which means naming a schema and a view from the client. The\n * Angular client has no dialect knowledge (`QuoteSchemaAndView` lives on the server-side database\n * providers, not on the GraphQL provider); the server does rewrite bracketed identifiers for\n * PostgreSQL, but a view name chosen here is still a guess about the database behind the API. An\n * `IN (...)` list of IDs is plain SQL everywhere, names nothing, and the join it produces is exact\n * rather than re-derived. Cost: one extra round trip.\n *\n * Why both queries still carry `IgnoreMaxRows`: details truncate to the newest N by date while\n * matches truncate to the top N by probability. Those two subsets diverge as soon as a run exceeds\n * UserViewMaxRows (1000), leaving details with no loaded matches; buildGroups() then drops every\n * such detail and the board is empty with a full run behind it. Scoping bounds the volume, and the\n * flag keeps the join complete inside that bound. Dropping the flag would bring the empty board back\n * for any single run larger than 1000 rows.\n */\nimport { RunViewParams } from '@memberjunction/core';\nimport { EscapeSQLString, IndexByUUID, UUIDsEqual } from '@memberjunction/global';\n\n/** The slice of an `MJ: Duplicate Runs` row the board needs to choose which run it shows. */\nexport interface DuplicateRunCandidate {\n ID: string;\n EntityID: string;\n ProcessingStatus: string;\n StartedAt: Date | string | null;\n /** Set when the run covered one list's records rather than the whole entity. */\n SourceListID: string | null;\n}\n\nconst RUN_FAILED = 'Failed';\n\n/**\n * A run worth putting on the board ahead of others: it did not fail (a run is marked Failed on any\n * exception in detection, usually before a single detail is written) and it covered the whole\n * entity rather than one list (a list run is a small subset that would hide the entity-wide results).\n */\nfunction isPreferredRun(run: DuplicateRunCandidate): boolean {\n return run.ProcessingStatus !== RUN_FAILED && !run.SourceListID;\n}\n\n/** How many detail IDs go into one matches query; keeps each `IN (...)` list a sane size. */\nexport const MATCH_QUERY_DETAIL_CHUNK_SIZE = 500;\n\nconst DETAIL_COMPLETE = 'Complete';\n\n/** The slice of an entity-document picker option needed to choose a default. */\nexport interface EntityDocumentCandidate {\n ID: string;\n EntityID: string;\n}\n\n/**\n * Pick the run the board should display for an entity: the newest run that did not fail and covered\n * the whole entity, or, when there is none, the newest run of any kind.\n *\n * Not \"most recent Complete run\": a run the user cancels keeps `ProcessingStatus = 'In Progress'`\n * (the detector marks it for resumption), and the board's own idle timer can finish a detection\n * before the server does; both end with a reload while a newer run exists, and preferring an older\n * Complete run there would hide the rows the user just watched being produced. Not plain \"newest\"\n * either: a Failed run usually has no details, and a list-scoped run holds a small subset, so each\n * would hide a good entity-wide run behind an empty or partial board. Runs for other entities are\n * never candidates. Returns null when there is no entity or no run for it.\n */\nexport function SelectCurrentRunForEntity<T extends DuplicateRunCandidate>(\n runs: readonly T[],\n entityID: string | null | undefined\n): T | null {\n if (!entityID) {\n return null;\n }\n const forEntity = newestFirst(runs.filter(r => UUIDsEqual(r.EntityID, entityID)));\n return forEntity.find(isPreferredRun) ?? forEntity[0] ?? null;\n}\n\n/**\n * The entity document the board should show before the user picks one: the document for the entity\n * of the newest run worth showing (see {@link SelectCurrentRunForEntity}), so a first visit lands on\n * results that exist. Falls back to the first document when no run matches any document, and to\n * null when there are no documents at all.\n */\nexport function PickDefaultEntityDocument<D extends EntityDocumentCandidate>(\n documents: readonly D[],\n runs: readonly DuplicateRunCandidate[]\n): D | null {\n if (documents.length === 0) {\n return null;\n }\n // First document per entity wins, as documents.find() would.\n const documentsByEntity = IndexByUUID(documents, d => d.EntityID);\n const ordered = [...newestFirst(runs.filter(isPreferredRun)), ...newestFirst(runs)];\n for (const run of ordered) {\n const match = documentsByEntity.Get(run.EntityID);\n if (match) {\n return match;\n }\n }\n return documents[0];\n}\n\nfunction newestFirst<T extends DuplicateRunCandidate>(runs: readonly T[]): T[] {\n return [...runs].sort((a, b) => toTime(b.StartedAt) - toTime(a.StartedAt));\n}\n\n/** The completed details of ONE run, newest first. Bounded by the run; `IgnoreMaxRows` per the file comment. */\nexport function BuildRunScopedDetailsQuery(runID: string): RunViewParams {\n return {\n EntityName: 'MJ: Duplicate Run Details',\n ExtraFilter: `DuplicateRunID='${EscapeSQLString(runID)}' AND MatchStatus='${DETAIL_COMPLETE}'`,\n OrderBy: '__mj_CreatedAt DESC',\n IgnoreMaxRows: true,\n ResultType: 'entity_object'\n };\n}\n\n/**\n * The matches whose parent detail is one of `detailIDs`, as one query per chunk of\n * {@link MATCH_QUERY_DETAIL_CHUNK_SIZE} IDs. No IDs, no queries. Plain `IN (...)` so it runs on any\n * database behind the API; `IgnoreMaxRows` per the file comment.\n */\nexport function BuildMatchQueriesForDetailIDs(\n detailIDs: readonly string[],\n chunkSize: number = MATCH_QUERY_DETAIL_CHUNK_SIZE\n): RunViewParams[] {\n const queries: RunViewParams[] = [];\n for (let start = 0; start < detailIDs.length; start += chunkSize) {\n const literals = detailIDs.slice(start, start + chunkSize).map(id => `'${EscapeSQLString(id)}'`);\n queries.push({\n EntityName: 'MJ: Duplicate Run Detail Matches',\n ExtraFilter: `DuplicateRunDetailID IN (${literals.join(',')})`,\n OrderBy: 'MatchProbability DESC',\n IgnoreMaxRows: true,\n ResultType: 'entity_object'\n });\n }\n return queries;\n}\n\n/** The detail IDs a matches query built by {@link BuildMatchQueriesForDetailIDs} covers. */\nexport function DetailIDsCoveredByMatchQuery(query: RunViewParams): string[] {\n const filter = typeof query.ExtraFilter === 'string' ? query.ExtraFilter : '';\n const list = /DuplicateRunDetailID IN \\((.*)\\)/s.exec(filter)?.[1] ?? '';\n return list\n .split(/','/)\n .map(part => part.replace(/^'|'$/g, '').replace(/''/g, \"'\"))\n .filter(part => part.length > 0);\n}\n\n/** Index matches by their parent detail; the join buildGroups() performs. */\nexport function GroupMatchesByDetail<M extends { DuplicateRunDetailID: string }>(\n matches: readonly M[]\n): Map<string, M[]> {\n const byDetail = new Map<string, M[]>();\n for (const match of matches) {\n const existing = byDetail.get(match.DuplicateRunDetailID);\n if (existing) {\n existing.push(match);\n } else {\n byDetail.set(match.DuplicateRunDetailID, [match]);\n }\n }\n return byDetail;\n}\n\nfunction toTime(value: Date | string | null): number {\n if (!value) {\n return 0;\n }\n const time = new Date(value).getTime();\n return isNaN(time) ? 0 : time;\n}\n"]}
@@ -177,6 +177,7 @@ export declare class ModelPromptPriorityMatrixComponent extends BaseAngularCompo
177
177
  private loadAssociations;
178
178
  private buildAssociations;
179
179
  private buildMatrix;
180
+ private pairKey;
180
181
  private canAssignModelToPrompt;
181
182
  GetCellKey(promptIndex: number, modelIndex: number): string;
182
183
  /** @deprecated Use {@link GetCellKey}. */
@@ -1 +1 @@
1
- {"version":3,"file":"model-prompt-priority-matrix.component.d.ts","sourceRoot":"","sources":["../../../../src/AI/components/prompts/model-prompt-priority-matrix.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model-prompt-priority-matrix.component.d.ts","sourceRoot":"","sources":["../../../../src/AI/components/prompts/model-prompt-priority-matrix.component.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { Component, Input, Output, EventEmitter } from '@angular/core';
2
2
  import { RunView, LogError, LogStatus } from '@memberjunction/core';
3
3
  import { Subject, BehaviorSubject } from 'rxjs';
4
- import { UUIDsEqual } from '@memberjunction/global';
4
+ import { IndexByUUID, NormalizeUUID, UUIDsEqual } from '@memberjunction/global';
5
5
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "@memberjunction/ng-notifications";
@@ -710,10 +710,12 @@ export class ModelPromptPriorityMatrixComponent extends BaseAngularComponent {
710
710
  }
711
711
  buildAssociations(dbAssociations) {
712
712
  this.Associations = [];
713
+ const promptsByID = IndexByUUID(this.Prompts);
714
+ const modelsByID = IndexByUUID(this.Models);
713
715
  // Create associations for existing database records
714
716
  dbAssociations.forEach(dbAssoc => {
715
- const prompt = this.Prompts.find(p => UUIDsEqual(p.ID, dbAssoc.PromptID));
716
- const model = this.Models.find(m => UUIDsEqual(m.ID, dbAssoc.ModelID));
717
+ const prompt = promptsByID.Get(dbAssoc.PromptID);
718
+ const model = modelsByID.Get(dbAssoc.ModelID);
717
719
  if (prompt && model) {
718
720
  this.Associations.push({
719
721
  promptId: prompt.ID,
@@ -731,10 +733,17 @@ export class ModelPromptPriorityMatrixComponent extends BaseAngularComponent {
731
733
  }
732
734
  buildMatrix() {
733
735
  this.Matrix = [];
736
+ // One lookup per cell instead of a scan of every association per cell; the first association for a pair wins, as find() did.
737
+ const associationsByPair = new Map();
738
+ for (const a of this.Associations) {
739
+ const key = this.pairKey(a.promptId, a.modelId);
740
+ if (!associationsByPair.has(key))
741
+ associationsByPair.set(key, a);
742
+ }
734
743
  this.Prompts.forEach((prompt, promptIndex) => {
735
744
  this.Matrix[promptIndex] = [];
736
745
  this.Models.forEach((model, modelIndex) => {
737
- const association = this.Associations.find(a => UUIDsEqual(a.promptId, prompt.ID) && UUIDsEqual(a.modelId, model.ID));
746
+ const association = associationsByPair.get(this.pairKey(prompt.ID, model.ID));
738
747
  this.Matrix[promptIndex][modelIndex] = {
739
748
  promptId: prompt.ID,
740
749
  modelId: model.ID,
@@ -744,6 +753,9 @@ export class ModelPromptPriorityMatrixComponent extends BaseAngularComponent {
744
753
  });
745
754
  });
746
755
  }
756
+ pairKey(promptId, modelId) {
757
+ return `${NormalizeUUID(promptId)}|${NormalizeUUID(modelId)}`;
758
+ }
747
759
  canAssignModelToPrompt(prompt, model) {
748
760
  // Check model type compatibility
749
761
  if (prompt.OutputType && model.AIModelTypeID) {