@memberjunction/ng-dashboards 5.41.0 → 5.43.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 (47) hide show
  1. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  2. package/dist/AI/components/analytics/ai-analytics-resource.component.js +16 -5
  3. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  4. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts +59 -0
  5. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.d.ts.map +1 -0
  6. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js +150 -0
  7. package/dist/AI/components/analytics/realtime/realtime-transcripts-data.js.map +1 -0
  8. package/dist/AI/components/analytics/realtime/realtime-transcripts.component.d.ts +28 -0
  9. package/dist/AI/components/analytics/realtime/realtime-transcripts.component.d.ts.map +1 -0
  10. package/dist/AI/components/analytics/realtime/realtime-transcripts.component.js +235 -0
  11. package/dist/AI/components/analytics/realtime/realtime-transcripts.component.js.map +1 -0
  12. package/dist/AI/index.d.ts +2 -0
  13. package/dist/AI/index.d.ts.map +1 -1
  14. package/dist/AI/index.js +3 -0
  15. package/dist/AI/index.js.map +1 -1
  16. package/dist/BulkOperations/bulk-operations-container.component.d.ts +17 -0
  17. package/dist/BulkOperations/bulk-operations-container.component.d.ts.map +1 -0
  18. package/dist/BulkOperations/bulk-operations-container.component.js +70 -0
  19. package/dist/BulkOperations/bulk-operations-container.component.js.map +1 -0
  20. package/dist/BulkOperations/bulk-operations-operations.component.d.ts +16 -0
  21. package/dist/BulkOperations/bulk-operations-operations.component.d.ts.map +1 -0
  22. package/dist/BulkOperations/bulk-operations-operations.component.js +42 -0
  23. package/dist/BulkOperations/bulk-operations-operations.component.js.map +1 -0
  24. package/dist/BulkOperations/bulk-operations-run-history.component.d.ts +16 -0
  25. package/dist/BulkOperations/bulk-operations-run-history.component.d.ts.map +1 -0
  26. package/dist/BulkOperations/bulk-operations-run-history.component.js +42 -0
  27. package/dist/BulkOperations/bulk-operations-run-history.component.js.map +1 -0
  28. package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
  29. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  30. package/dist/Home/home-dashboard.component.js +12 -8
  31. package/dist/Home/home-dashboard.component.js.map +1 -1
  32. package/dist/Integration/components/connections/connections.component.d.ts +12 -0
  33. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  34. package/dist/Integration/components/connections/connections.component.js +419 -333
  35. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  36. package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
  37. package/dist/MCP/mcp-dashboard.component.js +4 -1
  38. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  39. package/dist/ai-dashboards.module.d.ts +20 -19
  40. package/dist/ai-dashboards.module.d.ts.map +1 -1
  41. package/dist/ai-dashboards.module.js +6 -0
  42. package/dist/ai-dashboards.module.js.map +1 -1
  43. package/dist/core-dashboards.module.d.ts +54 -50
  44. package/dist/core-dashboards.module.d.ts.map +1 -1
  45. package/dist/core-dashboards.module.js +27 -3
  46. package/dist/core-dashboards.module.js.map +1 -1
  47. package/package.json +56 -55
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-transcripts-data.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/realtime/realtime-transcripts-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAqB,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAE9D,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAChD,MAAM,0BAA0B,GAAG,0BAA0B,CAAC;AAC9D,MAAM,aAAa,GAAG,8BAA8B,CAAC;AACrD,MAAM,kBAAkB,GAAG,0CAA0C,CAAC;AAuBtE,MAAM,SAAS,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/D,MAAM,MAAM,GAAG,CAAC,CAAU,EAAQ,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAA2B,EAAE,OAAO,GAAG,GAAG;IAC7E,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAC3B;QACI,UAAU,EAAE,mBAAmB;QAC/B,WAAW,EAAE,qBAAqB;QAClC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;QACxE,OAAO,EAAE,qBAAqB;QAC9B,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;KACvB,EACD,QAAQ,CAAC,WAAW,CACvB,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACtC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;QACtC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;KAC5C,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACpC,QAA2B,EAC3B,cAAsB,EACtB,OAAe;IAEf,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;QACnD;YACI,UAAU,EAAE,0BAA0B;YACtC,WAAW,EAAE,mBAAmB,SAAS,CAAC,cAAc,CAAC,GAAG;YAC5D,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,CAAC;YACrF,OAAO,EAAE,oBAAoB;YAC7B,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,QAAQ;SACvB;QACD;YACI,UAAU,EAAE,aAAa;YACzB,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;YAC7E,MAAM,EAAE,CAAC,IAAI,CAAC;YACd,OAAO,EAAE,GAAG;YACZ,UAAU,EAAE,QAAQ;SACvB;KACJ,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEzB,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,YAAY,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7H,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;IAEzC,MAAM,OAAO,GAAG,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,wGAAwG;AACxG,KAAK,UAAU,oBAAoB,CAC/B,QAA2B,EAC3B,EAAW,EACX,SAAmB;IAEnB,MAAM,GAAG,GAAG,IAAI,GAAG,EAA8C,CAAC;IAClE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAC3B;QACI,UAAU,EAAE,kBAAkB;QAC9B,WAAW,EAAE,uBAAuB,QAAQ,GAAG;QAC/C,MAAM,EAAE,CAAC,uBAAuB,EAAE,aAAa,EAAE,SAAS,CAAC;QAC3D,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,QAAQ;KACvB,EACD,QAAQ,CAAC,WAAW,CACvB,CAAC;IACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAClE,IAAI,CAAC,EAAE,EAAE,CAAC;gBACN,SAAS;YACb,CAAC;YACD,mGAAmG;YACnG,mGAAmG;YACnG,qFAAqF;YACrF,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE;gBACR,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,aAAa;gBACzC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC,IAAI,OAAO;aAC/C,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,wGAAwG;AACxG,SAAS,oBAAoB;IACzB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACjD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CACzB,CAA0B,EAC1B,gBAAiE,EACjE,SAA8B;IAE9B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG;QACT,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACjD,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;KAClC,CAAC;IACF,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACnB,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACzD,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;IAClF,CAAC;IACD,yGAAyG;IACzG,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,IAAI,WAAW,EAAE,CAAC;QACd,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;IACjG,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * @fileoverview Pure data layer for the Realtime \"Voice Transcripts\" view. Loads the unified per-room\n * meeting transcripts the bridge writes (one `MJ: Conversations` of `Type='Meeting Room'` per room +\n * `MJ: Conversation Details` per utterance), and resolves each line's speaker — agent lines via `AgentID`,\n * heard ('User') lines via the diarized `ExternalID` → the room's `AIAgentSessionBridgeParticipant` roster\n * (DisplayName + IsAgent). No Angular imports — RunView(s) + client-side aggregation only.\n *\n * @module @memberjunction/ng-dashboards\n */\nimport { IMetadataProvider, RunView } from '@memberjunction/core';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\n\nconst CONVERSATION_ENTITY = 'MJ: Conversations';\nconst CONVERSATION_DETAIL_ENTITY = 'MJ: Conversation Details';\nconst BRIDGE_ENTITY = 'MJ: AI Agent Session Bridges';\nconst PARTICIPANT_ENTITY = 'MJ: AI Agent Session Bridge Participants';\n\n/** One meeting-room transcript in the list view. */\nexport interface MeetingRoomSummary {\n ConversationID: string;\n Name: string;\n /** The room's external connection id (`ExternalID`) — the join key to the bridge/participant rows. */\n RoomKey: string;\n CreatedAt: Date;\n LastActivity: Date;\n}\n\n/** A speaker-attributed transcript line for the drill-in view. */\nexport interface TranscriptLine {\n ID: string;\n /** `'agent'` = an agent spoke; `'human'` = a human/participant spoke; `'error'` = an error row. */\n Kind: 'agent' | 'human' | 'error';\n /** Resolved display name of the speaker (agent name, participant name, or a sensible fallback). */\n Speaker: string;\n Message: string;\n At: Date;\n}\n\nconst escapeSql = (v: string): string => v.replace(/'/g, \"''\");\nconst toDate = (v: unknown): Date => (v instanceof Date ? v : new Date(String(v ?? '')));\n\n/**\n * Loads the meeting-room transcript LIST (light — no per-room detail load). Newest activity first.\n *\n * @param provider The request-scoped metadata provider.\n * @param maxRows Cap on rooms returned (default 500).\n */\nexport async function LoadMeetingRooms(provider: IMetadataProvider, maxRows = 500): Promise<MeetingRoomSummary[]> {\n const rv = RunView.FromMetadataProvider(provider);\n const result = await rv.RunView<Record<string, unknown>>(\n {\n EntityName: CONVERSATION_ENTITY,\n ExtraFilter: `Type='Meeting Room'`,\n Fields: ['ID', 'Name', 'ExternalID', '__mj_CreatedAt', '__mj_UpdatedAt'],\n OrderBy: '__mj_UpdatedAt DESC',\n MaxRows: maxRows,\n ResultType: 'simple',\n },\n provider.CurrentUser,\n );\n if (!result.Success) {\n return [];\n }\n return result.Results.map((r) => ({\n ConversationID: String(r['ID']),\n Name: String(r['Name'] ?? 'Meeting Room'),\n RoomKey: String(r['ExternalID'] ?? ''),\n CreatedAt: toDate(r['__mj_CreatedAt']),\n LastActivity: toDate(r['__mj_UpdatedAt']),\n }));\n}\n\n/**\n * Loads + speaker-attributes one room's transcript. Resolves agent lines via `AgentID` (AIEngine cache) and\n * heard lines via the diarized `ExternalID` against the room's participant roster (so a `User` line reads as\n * the actual person, and another agent heard in the room reads as that agent — not a generic \"User\").\n *\n * @param provider The request-scoped metadata provider.\n * @param conversationID The room conversation id.\n * @param roomKey The room's external id (to load its bridge participants for attribution).\n */\nexport async function LoadRoomTranscript(\n provider: IMetadataProvider,\n conversationID: string,\n roomKey: string,\n): Promise<TranscriptLine[]> {\n const rv = RunView.FromMetadataProvider(provider);\n const [detailResult, bridgeResult] = await rv.RunViews([\n {\n EntityName: CONVERSATION_DETAIL_ENTITY,\n ExtraFilter: `ConversationID='${escapeSql(conversationID)}'`,\n Fields: ['ID', 'Role', 'Message', 'AgentID', 'ExternalID', 'Error', '__mj_CreatedAt'],\n OrderBy: '__mj_CreatedAt ASC',\n MaxRows: 5000,\n ResultType: 'simple',\n },\n {\n EntityName: BRIDGE_ENTITY,\n ExtraFilter: roomKey ? `ExternalConnectionID='${escapeSql(roomKey)}'` : `1=0`,\n Fields: ['ID'],\n MaxRows: 100,\n ResultType: 'simple',\n },\n ], provider.CurrentUser);\n\n const participantNames = await loadParticipantNames(provider, rv, (bridgeResult?.Results ?? []).map((b) => String(b['ID'])));\n const agentName = buildAgentNameLookup();\n\n const details = detailResult?.Success ? detailResult.Results : [];\n return details.map((d) => attributeLine(d, participantNames, agentName));\n}\n\n/** roomBridges → a map of `ExternalParticipantID → { name, isAgent }` for diarized-line attribution. */\nasync function loadParticipantNames(\n provider: IMetadataProvider,\n rv: RunView,\n bridgeIds: string[],\n): Promise<Map<string, { name: string; isAgent: boolean }>> {\n const map = new Map<string, { name: string; isAgent: boolean }>();\n if (bridgeIds.length === 0) {\n return map;\n }\n const inClause = bridgeIds.map((id) => `'${escapeSql(id)}'`).join(',');\n const result = await rv.RunView<Record<string, unknown>>(\n {\n EntityName: PARTICIPANT_ENTITY,\n ExtraFilter: `SessionBridgeID IN (${inClause})`,\n Fields: ['ExternalParticipantID', 'DisplayName', 'IsAgent'],\n MaxRows: 1000,\n ResultType: 'simple',\n },\n provider.CurrentUser,\n );\n if (result.Success) {\n for (const p of result.Results) {\n const id = String(p['ExternalParticipantID'] ?? '').toLowerCase();\n if (!id) {\n continue;\n }\n // Each agent appears on multiple bridges' rosters — `IsAgent=1` only on its OWN bridge (where it's\n // the bot), `IsAgent=0` where another agent merely heard it. OR-reduce so it resolves to an agent,\n // and keep the most specific (non-fallback) DisplayName we've seen for the identity.\n const isAgent = p['IsAgent'] === true;\n const name = String(p['DisplayName'] ?? '');\n const prev = map.get(id);\n map.set(id, {\n name: name || prev?.name || 'Participant',\n isAgent: (prev?.isAgent ?? false) || isAgent,\n });\n }\n }\n return map;\n}\n\n/** AgentID → agent name, from the AIEngine cache (agents are always loaded for the analytics shell). */\nfunction buildAgentNameLookup(): Map<string, string> {\n const map = new Map<string, string>();\n for (const a of AIEngineBase.Instance.Agents ?? []) {\n map.set(a.ID.toLowerCase(), a.Name ?? 'Agent');\n }\n return map;\n}\n\n/**\n * Resolves one raw detail row into a display-ready, speaker-attributed line — the diarization-attribution\n * core. Exported for unit testing (the maps are easy to construct directly, no RunView mocking needed).\n *\n * @param d The raw `MJ: Conversation Details` row.\n * @param participantNames `ExternalParticipantID(lower) → { name, isAgent }` from the room roster.\n * @param agentName `AgentID(lower) → agent name`.\n */\nexport function attributeLine(\n d: Record<string, unknown>,\n participantNames: Map<string, { name: string; isAgent: boolean }>,\n agentName: Map<string, string>,\n): TranscriptLine {\n const role = String(d['Role'] ?? 'User');\n const externalId = String(d['ExternalID'] ?? '').toLowerCase();\n const base = {\n ID: String(d['ID']),\n Message: String(d['Message'] ?? d['Error'] ?? ''),\n At: toDate(d['__mj_CreatedAt']),\n };\n if (role === 'Error') {\n return { ...base, Kind: 'error', Speaker: 'Error' };\n }\n if (role === 'AI') {\n const agentId = String(d['AgentID'] ?? '').toLowerCase();\n return { ...base, Kind: 'agent', Speaker: agentName.get(agentId) ?? 'Agent' };\n }\n // 'User' — diarized to a participant when we have the speaker label; another agent heard reads as agent.\n const participant = externalId ? participantNames.get(externalId) : undefined;\n if (participant) {\n return { ...base, Kind: participant.isAgent ? 'agent' : 'human', Speaker: participant.name };\n }\n return { ...base, Kind: 'human', Speaker: 'Participant' };\n}\n"]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview `app-analytics-realtime-transcripts` — the "Voice Transcripts" view in the AI Analytics
3
+ * shell. A master-detail browser over the unified per-room meeting transcripts the realtime bridge records:
4
+ * a list of meeting rooms on the left, the speaker-attributed (diarized) transcript on the right. Read-only;
5
+ * a child view of the analytics shell (extends {@link BaseAngularComponent}, threads `ProviderToUse`).
6
+ *
7
+ * @module @memberjunction/ng-dashboards
8
+ */
9
+ import { OnInit } from '@angular/core';
10
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
11
+ import { type MeetingRoomSummary, type TranscriptLine } from './realtime-transcripts-data';
12
+ import * as i0 from "@angular/core";
13
+ export declare class AnalyticsRealtimeTranscriptsComponent extends BaseAngularComponent implements OnInit {
14
+ private cdr;
15
+ IsLoading: boolean;
16
+ IsLoadingTranscript: boolean;
17
+ Rooms: MeetingRoomSummary[];
18
+ SelectedRoom: MeetingRoomSummary | null;
19
+ Lines: TranscriptLine[];
20
+ ngOnInit(): Promise<void>;
21
+ reload(): Promise<void>;
22
+ selectRoom(room: MeetingRoomSummary): Promise<void>;
23
+ static ɵfac: i0.ɵɵFactoryDeclaration<AnalyticsRealtimeTranscriptsComponent, never>;
24
+ static ɵcmp: i0.ɵɵComponentDeclaration<AnalyticsRealtimeTranscriptsComponent, "app-analytics-realtime-transcripts", never, {}, {}, never, never, false, never>;
25
+ }
26
+ /** Tree-shaking prevention — called from the module constructor so the component class isn't elided. */
27
+ export declare function LoadAnalyticsRealtimeTranscripts(): void;
28
+ //# sourceMappingURL=realtime-transcripts.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-transcripts.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/realtime/realtime-transcripts.component.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAa,MAAM,EAA6B,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAGH,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACtB,MAAM,6BAA6B,CAAC;;AAErC,qBA4Fa,qCAAsC,SAAQ,oBAAqB,YAAW,MAAM;IAC7F,OAAO,CAAC,GAAG,CAA6B;IAEjC,SAAS,UAAQ;IACjB,mBAAmB,UAAS;IAC5B,KAAK,EAAE,kBAAkB,EAAE,CAAM;IACjC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAQ;IAC/C,KAAK,EAAE,cAAc,EAAE,CAAM;IAE9B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IASvB,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;yCAtBvD,qCAAqC;2CAArC,qCAAqC;CA+BjD;AAED,wGAAwG;AACxG,wBAAgB,gCAAgC,IAAI,IAAI,CAAgB"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * @fileoverview `app-analytics-realtime-transcripts` — the "Voice Transcripts" view in the AI Analytics
3
+ * shell. A master-detail browser over the unified per-room meeting transcripts the realtime bridge records:
4
+ * a list of meeting rooms on the left, the speaker-attributed (diarized) transcript on the right. Read-only;
5
+ * a child view of the analytics shell (extends {@link BaseAngularComponent}, threads `ProviderToUse`).
6
+ *
7
+ * @module @memberjunction/ng-dashboards
8
+ */
9
+ import { Component, ChangeDetectorRef, inject } from '@angular/core';
10
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
11
+ import { AIEngineBase } from '@memberjunction/ai-engine-base';
12
+ import { LoadMeetingRooms, LoadRoomTranscript, } from './realtime-transcripts-data';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@memberjunction/ng-shared-generic";
15
+ import * as i2 from "@angular/common";
16
+ const _forTrack0 = ($index, $item) => $item.ConversationID;
17
+ const _forTrack1 = ($index, $item) => $item.ID;
18
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "div", 0);
20
+ i0.ɵɵelement(1, "mj-loading", 2);
21
+ i0.ɵɵelementEnd();
22
+ } }
23
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
24
+ i0.ɵɵelementStart(0, "div", 7);
25
+ i0.ɵɵelement(1, "i", 10);
26
+ i0.ɵɵelementStart(2, "p");
27
+ i0.ɵɵtext(3, "No meeting transcripts yet.");
28
+ i0.ɵɵelementEnd()();
29
+ } }
30
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_8_For_1_Template(rf, ctx) { if (rf & 1) {
31
+ const _r3 = i0.ɵɵgetCurrentView();
32
+ i0.ɵɵelementStart(0, "button", 12);
33
+ i0.ɵɵlistener("click", function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_8_For_1_Template_button_click_0_listener() { const room_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectRoom(room_r4)); });
34
+ i0.ɵɵelement(1, "i", 13);
35
+ i0.ɵɵelementStart(2, "span", 14);
36
+ i0.ɵɵtext(3);
37
+ i0.ɵɵelementEnd();
38
+ i0.ɵɵelementStart(4, "span", 15);
39
+ i0.ɵɵtext(5);
40
+ i0.ɵɵpipe(6, "date");
41
+ i0.ɵɵelementEnd()();
42
+ } if (rf & 2) {
43
+ const room_r4 = ctx.$implicit;
44
+ const ctx_r1 = i0.ɵɵnextContext(3);
45
+ i0.ɵɵclassProp("room--active", room_r4.ConversationID === (ctx_r1.SelectedRoom == null ? null : ctx_r1.SelectedRoom.ConversationID));
46
+ i0.ɵɵadvance(3);
47
+ i0.ɵɵtextInterpolate(room_r4.Name);
48
+ i0.ɵɵadvance(2);
49
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(6, 4, room_r4.LastActivity, "MMM d, h:mm a"));
50
+ } }
51
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
52
+ i0.ɵɵrepeaterCreate(0, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_8_For_1_Template, 7, 7, "button", 11, _forTrack0);
53
+ } if (rf & 2) {
54
+ const ctx_r1 = i0.ɵɵnextContext(2);
55
+ i0.ɵɵrepeater(ctx_r1.Rooms);
56
+ } }
57
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_10_Template(rf, ctx) { if (rf & 1) {
58
+ i0.ɵɵelementStart(0, "div", 9);
59
+ i0.ɵɵelement(1, "i", 16);
60
+ i0.ɵɵelementStart(2, "p");
61
+ i0.ɵɵtext(3, "Select a meeting to view its transcript.");
62
+ i0.ɵɵelementEnd()();
63
+ } }
64
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) {
65
+ i0.ɵɵelementStart(0, "div", 0);
66
+ i0.ɵɵelement(1, "mj-loading", 17);
67
+ i0.ɵɵelementEnd();
68
+ } }
69
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_Conditional_7_Template(rf, ctx) { if (rf & 1) {
70
+ i0.ɵɵelementStart(0, "div", 7)(1, "p");
71
+ i0.ɵɵtext(2, "This meeting has no recorded utterances.");
72
+ i0.ɵɵelementEnd()();
73
+ } }
74
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_For_9_Template(rf, ctx) { if (rf & 1) {
75
+ i0.ɵɵelementStart(0, "div")(1, "div", 22)(2, "span", 23);
76
+ i0.ɵɵtext(3);
77
+ i0.ɵɵelementEnd();
78
+ i0.ɵɵelementStart(4, "span", 24);
79
+ i0.ɵɵtext(5);
80
+ i0.ɵɵpipe(6, "date");
81
+ i0.ɵɵelementEnd()();
82
+ i0.ɵɵelementStart(7, "div", 25);
83
+ i0.ɵɵtext(8);
84
+ i0.ɵɵelementEnd()();
85
+ } if (rf & 2) {
86
+ const line_r5 = ctx.$implicit;
87
+ i0.ɵɵclassMap(i0.ɵɵinterpolate1("line line--", line_r5.Kind));
88
+ i0.ɵɵadvance(3);
89
+ i0.ɵɵtextInterpolate(line_r5.Speaker);
90
+ i0.ɵɵadvance(2);
91
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(6, 6, line_r5.At, "h:mm:ss a"));
92
+ i0.ɵɵadvance(3);
93
+ i0.ɵɵtextInterpolate(line_r5.Message);
94
+ } }
95
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
96
+ i0.ɵɵelementStart(0, "div", 18)(1, "h3");
97
+ i0.ɵɵtext(2);
98
+ i0.ɵɵelementEnd();
99
+ i0.ɵɵelementStart(3, "span", 19);
100
+ i0.ɵɵtext(4);
101
+ i0.ɵɵpipe(5, "date");
102
+ i0.ɵɵelementEnd()();
103
+ i0.ɵɵelementStart(6, "div", 20);
104
+ i0.ɵɵconditionalCreate(7, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_Conditional_7_Template, 3, 0, "div", 7);
105
+ i0.ɵɵrepeaterCreate(8, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_For_9_Template, 9, 9, "div", 21, _forTrack1);
106
+ i0.ɵɵelementEnd();
107
+ } if (rf & 2) {
108
+ const ctx_r1 = i0.ɵɵnextContext(2);
109
+ i0.ɵɵadvance(2);
110
+ i0.ɵɵtextInterpolate(ctx_r1.SelectedRoom.Name);
111
+ i0.ɵɵadvance(2);
112
+ i0.ɵɵtextInterpolate3("", ctx_r1.Lines.length, " utterance", ctx_r1.Lines.length === 1 ? "" : "s", " \u00B7 ", i0.ɵɵpipeBind2(5, 5, ctx_r1.SelectedRoom.CreatedAt, "medium"));
113
+ i0.ɵɵadvance(3);
114
+ i0.ɵɵconditional(ctx_r1.Lines.length === 0 ? 7 : -1);
115
+ i0.ɵɵadvance();
116
+ i0.ɵɵrepeater(ctx_r1.Lines);
117
+ } }
118
+ function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
119
+ const _r1 = i0.ɵɵgetCurrentView();
120
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 3)(2, "div", 4)(3, "span");
121
+ i0.ɵɵtext(4);
122
+ i0.ɵɵelementEnd();
123
+ i0.ɵɵelementStart(5, "button", 5);
124
+ i0.ɵɵlistener("click", function AnalyticsRealtimeTranscriptsComponent_Conditional_1_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.reload()); });
125
+ i0.ɵɵelement(6, "i", 6);
126
+ i0.ɵɵelementEnd()();
127
+ i0.ɵɵconditionalCreate(7, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_7_Template, 4, 0, "div", 7)(8, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_8_Template, 2, 0);
128
+ i0.ɵɵelementEnd();
129
+ i0.ɵɵelementStart(9, "div", 8);
130
+ i0.ɵɵconditionalCreate(10, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_10_Template, 4, 0, "div", 9)(11, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_11_Template, 2, 0, "div", 0)(12, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Conditional_12_Template, 10, 8);
131
+ i0.ɵɵelementEnd()();
132
+ } if (rf & 2) {
133
+ const ctx_r1 = i0.ɵɵnextContext();
134
+ i0.ɵɵadvance(4);
135
+ i0.ɵɵtextInterpolate2("", ctx_r1.Rooms.length, " meeting", ctx_r1.Rooms.length === 1 ? "" : "s");
136
+ i0.ɵɵadvance(3);
137
+ i0.ɵɵconditional(ctx_r1.Rooms.length === 0 ? 7 : 8);
138
+ i0.ɵɵadvance(3);
139
+ i0.ɵɵconditional(!ctx_r1.SelectedRoom ? 10 : ctx_r1.IsLoadingTranscript ? 11 : 12);
140
+ } }
141
+ export class AnalyticsRealtimeTranscriptsComponent extends BaseAngularComponent {
142
+ cdr = inject(ChangeDetectorRef);
143
+ IsLoading = true;
144
+ IsLoadingTranscript = false;
145
+ Rooms = [];
146
+ SelectedRoom = null;
147
+ Lines = [];
148
+ async ngOnInit() {
149
+ await this.reload();
150
+ }
151
+ async reload() {
152
+ this.IsLoading = true;
153
+ this.cdr.detectChanges();
154
+ await AIEngineBase.Instance.EnsureLoaded(); // agents cache, for AI-line attribution
155
+ this.Rooms = await LoadMeetingRooms(this.ProviderToUse);
156
+ this.IsLoading = false;
157
+ this.cdr.detectChanges();
158
+ }
159
+ async selectRoom(room) {
160
+ this.SelectedRoom = room;
161
+ this.Lines = [];
162
+ this.IsLoadingTranscript = true;
163
+ this.cdr.detectChanges();
164
+ this.Lines = await LoadRoomTranscript(this.ProviderToUse, room.ConversationID, room.RoomKey);
165
+ this.IsLoadingTranscript = false;
166
+ this.cdr.detectChanges();
167
+ }
168
+ static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsRealtimeTranscriptsComponent_BaseFactory; return function AnalyticsRealtimeTranscriptsComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsRealtimeTranscriptsComponent_BaseFactory || (ɵAnalyticsRealtimeTranscriptsComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsRealtimeTranscriptsComponent)))(__ngFactoryType__ || AnalyticsRealtimeTranscriptsComponent); }; })();
169
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsRealtimeTranscriptsComponent, selectors: [["app-analytics-realtime-transcripts"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], [1, "transcripts"], ["text", "Loading meeting transcripts..."], [1, "room-list"], [1, "room-list__head"], ["title", "Refresh", 1, "rt-refresh", 3, "click"], [1, "fa-solid", "fa-rotate"], [1, "empty"], [1, "transcript-pane"], [1, "empty", "empty--center"], [1, "fa-solid", "fa-comment-slash"], [1, "room", 3, "room--active"], [1, "room", 3, "click"], [1, "fa-solid", "fa-tower-broadcast", "room__icon"], [1, "room__name"], [1, "room__when"], [1, "fa-solid", "fa-arrow-left"], ["text", "Loading transcript..."], [1, "transcript-pane__head"], [1, "muted"], [1, "lines"], [3, "class"], [1, "line__meta"], [1, "line__speaker"], [1, "line__time"], [1, "line__bubble"]], template: function AnalyticsRealtimeTranscriptsComponent_Template(rf, ctx) { if (rf & 1) {
170
+ i0.ɵɵconditionalCreate(0, AnalyticsRealtimeTranscriptsComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsRealtimeTranscriptsComponent_Conditional_1_Template, 13, 4, "div", 1);
171
+ } if (rf & 2) {
172
+ i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
173
+ } }, dependencies: [i1.LoadingComponent, i2.DatePipe], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n .loading-container[_ngcontent-%COMP%] { display: flex; align-items: center; justify-content: center; padding: 48px; }\n .transcripts[_ngcontent-%COMP%] { display: grid; grid-template-columns: 300px 1fr; gap: 16px; height: 100%; min-height: 420px; }\n .room-list[_ngcontent-%COMP%] { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); overflow-y: auto; }\n .room-list__head[_ngcontent-%COMP%] { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; font-size: 12px; color: var(--mj-text-muted); border-bottom: 1px solid var(--mj-border-subtle); position: sticky; top: 0; background: var(--mj-bg-surface); }\n .rt-refresh[_ngcontent-%COMP%] { background: none; border: none; color: var(--mj-text-muted); cursor: pointer; padding: 4px; }\n .rt-refresh[_ngcontent-%COMP%]:hover { color: var(--mj-brand-primary); }\n .room[_ngcontent-%COMP%] { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 8px; width: 100%; text-align: left; padding: 10px 12px; border: none; border-bottom: 1px solid var(--mj-border-subtle); background: none; cursor: pointer; }\n .room[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n .room--active[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n .room__icon[_ngcontent-%COMP%] { grid-row: 1 / 3; align-self: center; color: var(--mj-brand-primary); }\n .room__name[_ngcontent-%COMP%] { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n .room__when[_ngcontent-%COMP%] { color: var(--mj-text-muted); font-size: 11px; }\n .transcript-pane[_ngcontent-%COMP%] { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); display: flex; flex-direction: column; overflow: hidden; }\n .transcript-pane__head[_ngcontent-%COMP%] { padding: 12px 16px; border-bottom: 1px solid var(--mj-border-subtle); }\n .transcript-pane__head[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { margin: 0; font-size: 15px; color: var(--mj-text-primary); }\n .muted[_ngcontent-%COMP%] { color: var(--mj-text-muted); font-size: 12px; }\n .lines[_ngcontent-%COMP%] { padding: 12px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }\n .line[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 3px; max-width: 80%; }\n .line--agent[_ngcontent-%COMP%] { align-self: flex-start; }\n .line--human[_ngcontent-%COMP%] { align-self: flex-end; align-items: flex-end; }\n .line--error[_ngcontent-%COMP%] { align-self: center; max-width: 90%; }\n .line__meta[_ngcontent-%COMP%] { display: flex; gap: 8px; font-size: 11px; }\n .line__speaker[_ngcontent-%COMP%] { font-weight: 600; color: var(--mj-text-secondary); }\n .line__time[_ngcontent-%COMP%] { color: var(--mj-text-disabled); }\n .line__bubble[_ngcontent-%COMP%] { padding: 8px 12px; border-radius: 10px; font-size: 13px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }\n .line--agent[_ngcontent-%COMP%] .line__bubble[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-text-primary); }\n .line--human[_ngcontent-%COMP%] .line__bubble[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--mj-text-primary); }\n .line--error[_ngcontent-%COMP%] .line__bubble[_ngcontent-%COMP%] { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border: 1px solid var(--mj-status-error-border); }\n .empty[_ngcontent-%COMP%] { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px; color: var(--mj-text-muted); }\n .empty--center[_ngcontent-%COMP%] { margin: auto; }\n .empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 28px; opacity: 0.5; }"] });
174
+ }
175
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AnalyticsRealtimeTranscriptsComponent, [{
176
+ type: Component,
177
+ args: [{ standalone: false, selector: 'app-analytics-realtime-transcripts', template: `
178
+ @if (IsLoading) {
179
+ <div class="loading-container"><mj-loading text="Loading meeting transcripts..."></mj-loading></div>
180
+ } @else {
181
+ <div class="transcripts">
182
+ <!-- Room list -->
183
+ <div class="room-list">
184
+ <div class="room-list__head">
185
+ <span>{{ Rooms.length }} meeting{{ Rooms.length === 1 ? '' : 's' }}</span>
186
+ <button class="rt-refresh" title="Refresh" (click)="reload()"><i class="fa-solid fa-rotate"></i></button>
187
+ </div>
188
+ @if (Rooms.length === 0) {
189
+ <div class="empty"><i class="fa-solid fa-comment-slash"></i><p>No meeting transcripts yet.</p></div>
190
+ } @else {
191
+ @for (room of Rooms; track room.ConversationID) {
192
+ <button class="room" [class.room--active]="room.ConversationID === SelectedRoom?.ConversationID" (click)="selectRoom(room)">
193
+ <i class="fa-solid fa-tower-broadcast room__icon"></i>
194
+ <span class="room__name">{{ room.Name }}</span>
195
+ <span class="room__when">{{ room.LastActivity | date: 'MMM d, h:mm a' }}</span>
196
+ </button>
197
+ }
198
+ }
199
+ </div>
200
+
201
+ <!-- Transcript pane -->
202
+ <div class="transcript-pane">
203
+ @if (!SelectedRoom) {
204
+ <div class="empty empty--center"><i class="fa-solid fa-arrow-left"></i><p>Select a meeting to view its transcript.</p></div>
205
+ } @else if (IsLoadingTranscript) {
206
+ <div class="loading-container"><mj-loading text="Loading transcript..."></mj-loading></div>
207
+ } @else {
208
+ <div class="transcript-pane__head">
209
+ <h3>{{ SelectedRoom.Name }}</h3>
210
+ <span class="muted">{{ Lines.length }} utterance{{ Lines.length === 1 ? '' : 's' }} · {{ SelectedRoom.CreatedAt | date: 'medium' }}</span>
211
+ </div>
212
+ <div class="lines">
213
+ @if (Lines.length === 0) {
214
+ <div class="empty"><p>This meeting has no recorded utterances.</p></div>
215
+ }
216
+ @for (line of Lines; track line.ID) {
217
+ <div class="line line--{{ line.Kind }}">
218
+ <div class="line__meta">
219
+ <span class="line__speaker">{{ line.Speaker }}</span>
220
+ <span class="line__time">{{ line.At | date: 'h:mm:ss a' }}</span>
221
+ </div>
222
+ <div class="line__bubble">{{ line.Message }}</div>
223
+ </div>
224
+ }
225
+ </div>
226
+ }
227
+ </div>
228
+ </div>
229
+ }
230
+ `, styles: ["\n :host { display: block; height: 100%; }\n .loading-container { display: flex; align-items: center; justify-content: center; padding: 48px; }\n .transcripts { display: grid; grid-template-columns: 300px 1fr; gap: 16px; height: 100%; min-height: 420px; }\n .room-list { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); overflow-y: auto; }\n .room-list__head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; font-size: 12px; color: var(--mj-text-muted); border-bottom: 1px solid var(--mj-border-subtle); position: sticky; top: 0; background: var(--mj-bg-surface); }\n .rt-refresh { background: none; border: none; color: var(--mj-text-muted); cursor: pointer; padding: 4px; }\n .rt-refresh:hover { color: var(--mj-brand-primary); }\n .room { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 8px; width: 100%; text-align: left; padding: 10px 12px; border: none; border-bottom: 1px solid var(--mj-border-subtle); background: none; cursor: pointer; }\n .room:hover { background: var(--mj-bg-surface-hover); }\n .room--active { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n .room__icon { grid-row: 1 / 3; align-self: center; color: var(--mj-brand-primary); }\n .room__name { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n .room__when { color: var(--mj-text-muted); font-size: 11px; }\n .transcript-pane { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); display: flex; flex-direction: column; overflow: hidden; }\n .transcript-pane__head { padding: 12px 16px; border-bottom: 1px solid var(--mj-border-subtle); }\n .transcript-pane__head h3 { margin: 0; font-size: 15px; color: var(--mj-text-primary); }\n .muted { color: var(--mj-text-muted); font-size: 12px; }\n .lines { padding: 12px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }\n .line { display: flex; flex-direction: column; gap: 3px; max-width: 80%; }\n .line--agent { align-self: flex-start; }\n .line--human { align-self: flex-end; align-items: flex-end; }\n .line--error { align-self: center; max-width: 90%; }\n .line__meta { display: flex; gap: 8px; font-size: 11px; }\n .line__speaker { font-weight: 600; color: var(--mj-text-secondary); }\n .line__time { color: var(--mj-text-disabled); }\n .line__bubble { padding: 8px 12px; border-radius: 10px; font-size: 13px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }\n .line--agent .line__bubble { background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-text-primary); }\n .line--human .line__bubble { background: var(--mj-bg-surface-sunken); color: var(--mj-text-primary); }\n .line--error .line__bubble { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border: 1px solid var(--mj-status-error-border); }\n .empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px; color: var(--mj-text-muted); }\n .empty--center { margin: auto; }\n .empty i { font-size: 28px; opacity: 0.5; }\n "] }]
231
+ }], null, null); })();
232
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsRealtimeTranscriptsComponent, { className: "AnalyticsRealtimeTranscriptsComponent", filePath: "src/AI/components/analytics/realtime/realtime-transcripts.component.ts", lineNumber: 111 }); })();
233
+ /** Tree-shaking prevention — called from the module constructor so the component class isn't elided. */
234
+ export function LoadAnalyticsRealtimeTranscripts() { }
235
+ //# sourceMappingURL=realtime-transcripts.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-transcripts.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/realtime/realtime-transcripts.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview `app-analytics-realtime-transcripts` — the \"Voice Transcripts\" view in the AI Analytics\n * shell. A master-detail browser over the unified per-room meeting transcripts the realtime bridge records:\n * a list of meeting rooms on the left, the speaker-attributed (diarized) transcript on the right. Read-only;\n * a child view of the analytics shell (extends {@link BaseAngularComponent}, threads `ProviderToUse`).\n *\n * @module @memberjunction/ng-dashboards\n */\nimport { Component, OnInit, ChangeDetectorRef, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport {\n LoadMeetingRooms,\n LoadRoomTranscript,\n type MeetingRoomSummary,\n type TranscriptLine,\n} from './realtime-transcripts-data';\n\n@Component({\n standalone: false,\n selector: 'app-analytics-realtime-transcripts',\n template: `\n @if (IsLoading) {\n <div class=\"loading-container\"><mj-loading text=\"Loading meeting transcripts...\"></mj-loading></div>\n } @else {\n <div class=\"transcripts\">\n <!-- Room list -->\n <div class=\"room-list\">\n <div class=\"room-list__head\">\n <span>{{ Rooms.length }} meeting{{ Rooms.length === 1 ? '' : 's' }}</span>\n <button class=\"rt-refresh\" title=\"Refresh\" (click)=\"reload()\"><i class=\"fa-solid fa-rotate\"></i></button>\n </div>\n @if (Rooms.length === 0) {\n <div class=\"empty\"><i class=\"fa-solid fa-comment-slash\"></i><p>No meeting transcripts yet.</p></div>\n } @else {\n @for (room of Rooms; track room.ConversationID) {\n <button class=\"room\" [class.room--active]=\"room.ConversationID === SelectedRoom?.ConversationID\" (click)=\"selectRoom(room)\">\n <i class=\"fa-solid fa-tower-broadcast room__icon\"></i>\n <span class=\"room__name\">{{ room.Name }}</span>\n <span class=\"room__when\">{{ room.LastActivity | date: 'MMM d, h:mm a' }}</span>\n </button>\n }\n }\n </div>\n\n <!-- Transcript pane -->\n <div class=\"transcript-pane\">\n @if (!SelectedRoom) {\n <div class=\"empty empty--center\"><i class=\"fa-solid fa-arrow-left\"></i><p>Select a meeting to view its transcript.</p></div>\n } @else if (IsLoadingTranscript) {\n <div class=\"loading-container\"><mj-loading text=\"Loading transcript...\"></mj-loading></div>\n } @else {\n <div class=\"transcript-pane__head\">\n <h3>{{ SelectedRoom.Name }}</h3>\n <span class=\"muted\">{{ Lines.length }} utterance{{ Lines.length === 1 ? '' : 's' }} · {{ SelectedRoom.CreatedAt | date: 'medium' }}</span>\n </div>\n <div class=\"lines\">\n @if (Lines.length === 0) {\n <div class=\"empty\"><p>This meeting has no recorded utterances.</p></div>\n }\n @for (line of Lines; track line.ID) {\n <div class=\"line line--{{ line.Kind }}\">\n <div class=\"line__meta\">\n <span class=\"line__speaker\">{{ line.Speaker }}</span>\n <span class=\"line__time\">{{ line.At | date: 'h:mm:ss a' }}</span>\n </div>\n <div class=\"line__bubble\">{{ line.Message }}</div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n `,\n styles: [`\n :host { display: block; height: 100%; }\n .loading-container { display: flex; align-items: center; justify-content: center; padding: 48px; }\n .transcripts { display: grid; grid-template-columns: 300px 1fr; gap: 16px; height: 100%; min-height: 420px; }\n .room-list { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); overflow-y: auto; }\n .room-list__head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; font-size: 12px; color: var(--mj-text-muted); border-bottom: 1px solid var(--mj-border-subtle); position: sticky; top: 0; background: var(--mj-bg-surface); }\n .rt-refresh { background: none; border: none; color: var(--mj-text-muted); cursor: pointer; padding: 4px; }\n .rt-refresh:hover { color: var(--mj-brand-primary); }\n .room { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 8px; width: 100%; text-align: left; padding: 10px 12px; border: none; border-bottom: 1px solid var(--mj-border-subtle); background: none; cursor: pointer; }\n .room:hover { background: var(--mj-bg-surface-hover); }\n .room--active { background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); }\n .room__icon { grid-row: 1 / 3; align-self: center; color: var(--mj-brand-primary); }\n .room__name { font-weight: 600; color: var(--mj-text-primary); font-size: 13px; }\n .room__when { color: var(--mj-text-muted); font-size: 11px; }\n .transcript-pane { border: 1px solid var(--mj-border-default); border-radius: 8px; background: var(--mj-bg-surface); display: flex; flex-direction: column; overflow: hidden; }\n .transcript-pane__head { padding: 12px 16px; border-bottom: 1px solid var(--mj-border-subtle); }\n .transcript-pane__head h3 { margin: 0; font-size: 15px; color: var(--mj-text-primary); }\n .muted { color: var(--mj-text-muted); font-size: 12px; }\n .lines { padding: 12px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }\n .line { display: flex; flex-direction: column; gap: 3px; max-width: 80%; }\n .line--agent { align-self: flex-start; }\n .line--human { align-self: flex-end; align-items: flex-end; }\n .line--error { align-self: center; max-width: 90%; }\n .line__meta { display: flex; gap: 8px; font-size: 11px; }\n .line__speaker { font-weight: 600; color: var(--mj-text-secondary); }\n .line__time { color: var(--mj-text-disabled); }\n .line__bubble { padding: 8px 12px; border-radius: 10px; font-size: 13px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }\n .line--agent .line__bubble { background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface)); color: var(--mj-text-primary); }\n .line--human .line__bubble { background: var(--mj-bg-surface-sunken); color: var(--mj-text-primary); }\n .line--error .line__bubble { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border: 1px solid var(--mj-status-error-border); }\n .empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px; color: var(--mj-text-muted); }\n .empty--center { margin: auto; }\n .empty i { font-size: 28px; opacity: 0.5; }\n `],\n})\nexport class AnalyticsRealtimeTranscriptsComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n public IsLoading = true;\n public IsLoadingTranscript = false;\n public Rooms: MeetingRoomSummary[] = [];\n public SelectedRoom: MeetingRoomSummary | null = null;\n public Lines: TranscriptLine[] = [];\n\n async ngOnInit(): Promise<void> {\n await this.reload();\n }\n\n public async reload(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n await AIEngineBase.Instance.EnsureLoaded(); // agents cache, for AI-line attribution\n this.Rooms = await LoadMeetingRooms(this.ProviderToUse);\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n\n public async selectRoom(room: MeetingRoomSummary): Promise<void> {\n this.SelectedRoom = room;\n this.Lines = [];\n this.IsLoadingTranscript = true;\n this.cdr.detectChanges();\n this.Lines = await LoadRoomTranscript(this.ProviderToUse, room.ConversationID, room.RoomKey);\n this.IsLoadingTranscript = false;\n this.cdr.detectChanges();\n }\n}\n\n/** Tree-shaking prevention — called from the module constructor so the component class isn't elided. */\nexport function LoadAnalyticsRealtimeTranscripts(): void { /* no-op */ }\n"]}
@@ -28,5 +28,7 @@ export * from './components/analytics/realtime/realtime-overview.component';
28
28
  export * from './components/analytics/realtime/realtime-sessions.component';
29
29
  export * from './components/analytics/realtime/realtime-management-data';
30
30
  export * from './components/analytics/realtime/realtime-management.component';
31
+ export * from './components/analytics/realtime/realtime-transcripts-data';
32
+ export * from './components/analytics/realtime/realtime-transcripts.component';
31
33
  export * from './components/overview/ai-overview-hub.component';
32
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AI/index.ts"],"names":[],"mappings":"AACA,cAAc,uCAAuC,CAAC;AAGtD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,kDAAkD,CAAC;AACjE,cAAc,mDAAmD,CAAC;AAClE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AAGnE,cAAc,yCAAyC,CAAC;AACxD,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,cAAc,mDAAmD,CAAC;AAGlE,cAAc,yDAAyD,CAAC;AAGxE,cAAc,kEAAkE,CAAC;AAMjF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGpG,cAAc,2DAA2D,CAAC;AAG1E,cAAc,gEAAgE,CAAC;AAG/E,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uDAAuD,CAAC;AACtE,cAAc,wDAAwD,CAAC;AACvE,cAAc,sEAAsE,CAAC;AACrF,cAAc,kEAAkE,CAAC;AACjF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,sEAAsE,CAAC;AACrF,cAAc,0DAA0D,CAAC;AACzE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,gEAAgE,CAAC;AAG/E,cAAc,uDAAuD,CAAC;AACtE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAG5E,cAAc,0DAA0D,CAAC;AACzE,cAAc,+DAA+D,CAAC;AAG9E,cAAc,iDAAiD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AI/index.ts"],"names":[],"mappings":"AACA,cAAc,uCAAuC,CAAC;AAGtD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,kDAAkD,CAAC;AACjE,cAAc,mDAAmD,CAAC;AAClE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AAGnE,cAAc,yCAAyC,CAAC;AACxD,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,cAAc,mDAAmD,CAAC;AAGlE,cAAc,yDAAyD,CAAC;AAGxE,cAAc,kEAAkE,CAAC;AAMjF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGpG,cAAc,2DAA2D,CAAC;AAG1E,cAAc,gEAAgE,CAAC;AAG/E,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uDAAuD,CAAC;AACtE,cAAc,wDAAwD,CAAC;AACvE,cAAc,sEAAsE,CAAC;AACrF,cAAc,kEAAkE,CAAC;AACjF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,sEAAsE,CAAC;AACrF,cAAc,0DAA0D,CAAC;AACzE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,gEAAgE,CAAC;AAG/E,cAAc,uDAAuD,CAAC;AACtE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAG5E,cAAc,0DAA0D,CAAC;AACzE,cAAc,+DAA+D,CAAC;AAG9E,cAAc,2DAA2D,CAAC;AAC1E,cAAc,gEAAgE,CAAC;AAG/E,cAAc,iDAAiD,CAAC"}
package/dist/AI/index.js CHANGED
@@ -42,6 +42,9 @@ export * from './components/analytics/realtime/realtime-sessions.component';
42
42
  // Realtime management (bridges, providers, identities, channels, co-agents)
43
43
  export * from './components/analytics/realtime/realtime-management-data';
44
44
  export * from './components/analytics/realtime/realtime-management.component';
45
+ // Realtime voice transcripts (diarized per-room meeting transcript browser)
46
+ export * from './components/analytics/realtime/realtime-transcripts-data';
47
+ export * from './components/analytics/realtime/realtime-transcripts.component';
45
48
  // Overview Hub
46
49
  export * from './components/overview/ai-overview-hub.component';
47
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/AI/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,cAAc,uCAAuC,CAAC;AAEtD,kBAAkB;AAClB,cAAc,6CAA6C,CAAC;AAC5D,cAAc,kDAAkD,CAAC;AACjE,cAAc,mDAAmD,CAAC;AAClE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AAEnE,oBAAoB;AACpB,cAAc,yCAAyC,CAAC;AACxD,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,cAAc,mDAAmD,CAAC;AAElE,iBAAiB;AACjB,cAAc,yDAAyD,CAAC;AAExE,uBAAuB;AACvB,cAAc,kEAAkE,CAAC;AAEjF,sEAAsE;AACtE,uEAAuE;AACvE,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,oBAAoB;AACpB,cAAc,2DAA2D,CAAC;AAE1E,sBAAsB;AACtB,cAAc,gEAAgE,CAAC;AAE/E,eAAe;AACf,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uDAAuD,CAAC;AACtE,cAAc,wDAAwD,CAAC;AACvE,cAAc,sEAAsE,CAAC;AACrF,cAAc,kEAAkE,CAAC;AACjF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,sEAAsE,CAAC;AACrF,cAAc,0DAA0D,CAAC;AACzE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,gEAAgE,CAAC;AAE/E,kCAAkC;AAClC,cAAc,uDAAuD,CAAC;AACtE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAE5E,4EAA4E;AAC5E,cAAc,0DAA0D,CAAC;AACzE,cAAc,+DAA+D,CAAC;AAE9E,eAAe;AACf,cAAc,iDAAiD,CAAC","sourcesContent":["// Services\nexport * from './services/ai-instrumentation.service';\n\n// Main Components\nexport * from './components/execution-monitoring.component';\nexport * from './components/prompts/prompt-management.component';\nexport * from './components/agents/agent-configuration.component';\nexport * from './components/models/model-management.component';\nexport * from './components/system/system-configuration.component';\n\n// Widget Components\nexport * from './components/widgets/kpi-card.component';\nexport * from './components/widgets/live-execution-widget.component';\nexport * from './components/charts/time-series-chart.component';\nexport * from './components/charts/performance-heatmap.component';\n\n// Agent Requests\nexport * from './components/requests/agent-requests-resource.component';\n\n// Autotagging Pipeline\nexport * from './components/autotagging/autotagging-pipeline-resource.component';\n\n// Tags — canonical Knowledge Hub dashboard for everything tag-related\n// (Library + Taxonomy moved from Classify, plus Suggestions + Health).\n// Re-exported explicitly because the file is a clone of the autotag pipeline\n// and shares cron-helper module-level exports we don't want to re-export twice.\nexport { TagsResourceComponent, LoadTagsResource } from './components/tags/tags-resource.component';\n\n// Vector Management\nexport * from './components/vectors/vector-management-resource.component';\n\n// Duplicate Detection\nexport * from './components/duplicates/duplicate-detection-resource.component';\n\n// AI Analytics\nexport * from './interfaces/analytics-preferences.interface';\nexport * from './components/analytics/analytics-filter-bar.component';\nexport * from './components/analytics/ai-analytics-resource.component';\nexport * from './components/analytics/executive-summary/executive-summary.component';\nexport * from './components/analytics/prompt-runs/prompt-run-analysis.component';\nexport * from './components/analytics/agent-runs/agent-run-analysis.component';\nexport * from './components/analytics/model-performance/model-performance.component';\nexport * from './components/analytics/cost-budget/cost-budget.component';\nexport * from './components/analytics/error-analysis/error-analysis.component';\nexport * from './components/analytics/usage-patterns/usage-patterns.component';\n\n// Realtime Voice (agent sessions)\nexport * from './components/analytics/realtime/realtime-session-data';\nexport * from './components/analytics/realtime/realtime-overview.component';\nexport * from './components/analytics/realtime/realtime-sessions.component';\n\n// Realtime management (bridges, providers, identities, channels, co-agents)\nexport * from './components/analytics/realtime/realtime-management-data';\nexport * from './components/analytics/realtime/realtime-management.component';\n\n// Overview Hub\nexport * from './components/overview/ai-overview-hub.component';"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/AI/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,cAAc,uCAAuC,CAAC;AAEtD,kBAAkB;AAClB,cAAc,6CAA6C,CAAC;AAC5D,cAAc,kDAAkD,CAAC;AACjE,cAAc,mDAAmD,CAAC;AAClE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,oDAAoD,CAAC;AAEnE,oBAAoB;AACpB,cAAc,yCAAyC,CAAC;AACxD,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,cAAc,mDAAmD,CAAC;AAElE,iBAAiB;AACjB,cAAc,yDAAyD,CAAC;AAExE,uBAAuB;AACvB,cAAc,kEAAkE,CAAC;AAEjF,sEAAsE;AACtE,uEAAuE;AACvE,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,oBAAoB;AACpB,cAAc,2DAA2D,CAAC;AAE1E,sBAAsB;AACtB,cAAc,gEAAgE,CAAC;AAE/E,eAAe;AACf,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uDAAuD,CAAC;AACtE,cAAc,wDAAwD,CAAC;AACvE,cAAc,sEAAsE,CAAC;AACrF,cAAc,kEAAkE,CAAC;AACjF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,sEAAsE,CAAC;AACrF,cAAc,0DAA0D,CAAC;AACzE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,gEAAgE,CAAC;AAE/E,kCAAkC;AAClC,cAAc,uDAAuD,CAAC;AACtE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,6DAA6D,CAAC;AAE5E,4EAA4E;AAC5E,cAAc,0DAA0D,CAAC;AACzE,cAAc,+DAA+D,CAAC;AAE9E,4EAA4E;AAC5E,cAAc,2DAA2D,CAAC;AAC1E,cAAc,gEAAgE,CAAC;AAE/E,eAAe;AACf,cAAc,iDAAiD,CAAC","sourcesContent":["// Services\nexport * from './services/ai-instrumentation.service';\n\n// Main Components\nexport * from './components/execution-monitoring.component';\nexport * from './components/prompts/prompt-management.component';\nexport * from './components/agents/agent-configuration.component';\nexport * from './components/models/model-management.component';\nexport * from './components/system/system-configuration.component';\n\n// Widget Components\nexport * from './components/widgets/kpi-card.component';\nexport * from './components/widgets/live-execution-widget.component';\nexport * from './components/charts/time-series-chart.component';\nexport * from './components/charts/performance-heatmap.component';\n\n// Agent Requests\nexport * from './components/requests/agent-requests-resource.component';\n\n// Autotagging Pipeline\nexport * from './components/autotagging/autotagging-pipeline-resource.component';\n\n// Tags — canonical Knowledge Hub dashboard for everything tag-related\n// (Library + Taxonomy moved from Classify, plus Suggestions + Health).\n// Re-exported explicitly because the file is a clone of the autotag pipeline\n// and shares cron-helper module-level exports we don't want to re-export twice.\nexport { TagsResourceComponent, LoadTagsResource } from './components/tags/tags-resource.component';\n\n// Vector Management\nexport * from './components/vectors/vector-management-resource.component';\n\n// Duplicate Detection\nexport * from './components/duplicates/duplicate-detection-resource.component';\n\n// AI Analytics\nexport * from './interfaces/analytics-preferences.interface';\nexport * from './components/analytics/analytics-filter-bar.component';\nexport * from './components/analytics/ai-analytics-resource.component';\nexport * from './components/analytics/executive-summary/executive-summary.component';\nexport * from './components/analytics/prompt-runs/prompt-run-analysis.component';\nexport * from './components/analytics/agent-runs/agent-run-analysis.component';\nexport * from './components/analytics/model-performance/model-performance.component';\nexport * from './components/analytics/cost-budget/cost-budget.component';\nexport * from './components/analytics/error-analysis/error-analysis.component';\nexport * from './components/analytics/usage-patterns/usage-patterns.component';\n\n// Realtime Voice (agent sessions)\nexport * from './components/analytics/realtime/realtime-session-data';\nexport * from './components/analytics/realtime/realtime-overview.component';\nexport * from './components/analytics/realtime/realtime-sessions.component';\n\n// Realtime management (bridges, providers, identities, channels, co-agents)\nexport * from './components/analytics/realtime/realtime-management-data';\nexport * from './components/analytics/realtime/realtime-management.component';\n\n// Realtime voice transcripts (diarized per-room meeting transcript browser)\nexport * from './components/analytics/realtime/realtime-transcripts-data';\nexport * from './components/analytics/realtime/realtime-transcripts.component';\n\n// Overview Hub\nexport * from './components/overview/ai-overview-hub.component';"]}
@@ -0,0 +1,17 @@
1
+ import { AdminSection, BaseAdminContainerComponent } from '../Admin/base-admin-container.component';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Bulk Operations dashboard container — the left-nav shell for the Bulk Operations app. Reuses the proven
5
+ * Admin container shell (template + base) and contributes two sections: Operations (author + run) and Run
6
+ * History (audit). Each section hosts a thin resource component that renders the generic
7
+ * `@memberjunction/ng-record-process-studio` UI.
8
+ */
9
+ export declare class BulkOperationsContainerComponent extends BaseAdminContainerComponent {
10
+ readonly ContainerTitle = "Bulk Operations";
11
+ readonly ContainerIcon = "fa-solid fa-layer-group";
12
+ readonly ContainerSubtitle = "Define and run rules-driven bulk operations across your data";
13
+ readonly Sections: AdminSection[];
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<BulkOperationsContainerComponent, never>;
15
+ static ɵcmp: i0.ɵɵComponentDeclaration<BulkOperationsContainerComponent, "mj-bulk-operations-container", never, {}, {}, never, never, false, never>;
16
+ }
17
+ //# sourceMappingURL=bulk-operations-container.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-operations-container.component.d.ts","sourceRoot":"","sources":["../../src/BulkOperations/bulk-operations-container.component.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;;AAEpG;;;;;GAKG;AACH,qBAOa,gCAAiC,SAAQ,2BAA2B;IAC7E,SAAgB,cAAc,qBAAqB;IACnD,SAAgB,aAAa,6BAA6B;IAC1D,SAAgB,iBAAiB,kEAAkE;IAEnG,SAAgB,QAAQ,EAAE,YAAY,EAAE,CAetC;yCApBO,gCAAgC;2CAAhC,gCAAgC;CAqB5C"}
@@ -0,0 +1,70 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { RegisterClass } from '@memberjunction/global';
9
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
10
+ import { BaseAdminContainerComponent } from '../Admin/base-admin-container.component';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@memberjunction/ng-ui-components";
13
+ /**
14
+ * Bulk Operations dashboard container — the left-nav shell for the Bulk Operations app. Reuses the proven
15
+ * Admin container shell (template + base) and contributes two sections: Operations (author + run) and Run
16
+ * History (audit). Each section hosts a thin resource component that renders the generic
17
+ * `@memberjunction/ng-record-process-studio` UI.
18
+ */
19
+ let BulkOperationsContainerComponent = class BulkOperationsContainerComponent extends BaseAdminContainerComponent {
20
+ ContainerTitle = 'Bulk Operations';
21
+ ContainerIcon = 'fa-solid fa-layer-group';
22
+ ContainerSubtitle = 'Define and run rules-driven bulk operations across your data';
23
+ Sections = [
24
+ {
25
+ id: 'operations',
26
+ label: 'Operations',
27
+ icon: 'fa-solid fa-wand-magic-sparkles',
28
+ description: 'Create, edit, and run bulk operations',
29
+ source: { kind: 'resource', driverClass: 'BulkOperationsOperations' },
30
+ },
31
+ {
32
+ id: 'run-history',
33
+ label: 'Run History',
34
+ icon: 'fa-solid fa-clock-rotate-left',
35
+ description: 'Past runs and their per-record results',
36
+ source: { kind: 'resource', driverClass: 'BulkOperationsRunHistory' },
37
+ },
38
+ ];
39
+ static ɵfac = /*@__PURE__*/ (() => { let ɵBulkOperationsContainerComponent_BaseFactory; return function BulkOperationsContainerComponent_Factory(__ngFactoryType__) { return (ɵBulkOperationsContainerComponent_BaseFactory || (ɵBulkOperationsContainerComponent_BaseFactory = i0.ɵɵgetInheritedFactory(BulkOperationsContainerComponent)))(__ngFactoryType__ || BulkOperationsContainerComponent); }; })();
40
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: BulkOperationsContainerComponent, selectors: [["mj-bulk-operations-container"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 7, vars: 9, consts: [["contentHost", ""], [3, "Title", "Icon", "Subtitle"], ["Direction", "row", 3, "Flex", "Padding"], ["MobileTitle", "Administration", 3, "ItemClicked", "Sections", "ActiveId"], [3, "Loading", "Error"]], template: function BulkOperationsContainerComponent_Template(rf, ctx) { if (rf & 1) {
41
+ const _r1 = i0.ɵɵgetCurrentView();
42
+ i0.ɵɵelementStart(0, "mj-page-layout");
43
+ i0.ɵɵelement(1, "mj-page-header", 1);
44
+ i0.ɵɵelementStart(2, "mj-page-body", 2)(3, "mj-left-nav", 3);
45
+ i0.ɵɵlistener("ItemClicked", function BulkOperationsContainerComponent_Template_mj_left_nav_ItemClicked_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnNavItemClicked($event)); });
46
+ i0.ɵɵelementEnd();
47
+ i0.ɵɵelementStart(4, "mj-left-nav-content", 4);
48
+ i0.ɵɵelementContainer(5, null, 0);
49
+ i0.ɵɵelementEnd()()();
50
+ } if (rf & 2) {
51
+ i0.ɵɵadvance();
52
+ i0.ɵɵproperty("Title", ctx.ContainerTitle)("Icon", ctx.ContainerIcon)("Subtitle", ctx.ContainerSubtitle);
53
+ i0.ɵɵadvance();
54
+ i0.ɵɵproperty("Flex", true)("Padding", false);
55
+ i0.ɵɵadvance();
56
+ i0.ɵɵproperty("Sections", ctx.NavSections)("ActiveId", ctx.ActiveSection);
57
+ i0.ɵɵadvance();
58
+ i0.ɵɵproperty("Loading", ctx.IsLoading)("Error", ctx.LoadError);
59
+ } }, dependencies: [i1.MJPageHeaderComponent, i1.MJPageLayoutComponent, i1.MJPageBodyComponent, i1.MJLeftNavComponent, i1.MJLeftNavContentComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n\n\n\n@media (max-width: 700px) {\n [_nghost-%COMP%] mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}"] });
60
+ };
61
+ BulkOperationsContainerComponent = __decorate([
62
+ RegisterClass(BaseResourceComponent, 'BulkOperationsContainer')
63
+ ], BulkOperationsContainerComponent);
64
+ export { BulkOperationsContainerComponent };
65
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BulkOperationsContainerComponent, [{
66
+ type: Component,
67
+ args: [{ standalone: false, selector: 'mj-bulk-operations-container', template: "<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n MobileTitle=\"Administration\"\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n", styles: [":host { display: block; height: 100%; }\n\n/* Layout, rail styling, and content-area chrome all live in the shared\n <mj-page-body> / <mj-left-nav> / <mj-left-nav-content> components. The\n only thing this file owns is the responsive collapse of the parent flex\n direction at narrow viewports. See Section 10 of explorer-chrome-conventions. */\n@media (max-width: 700px) {\n :host ::ng-deep mj-page-body.mj-page-body--row {\n flex-direction: column;\n }\n}\n"] }]
68
+ }], null, null); })();
69
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(BulkOperationsContainerComponent, { className: "BulkOperationsContainerComponent", filePath: "src/BulkOperations/bulk-operations-container.component.ts", lineNumber: 19 }); })();
70
+ //# sourceMappingURL=bulk-operations-container.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-operations-container.component.js","sourceRoot":"","sources":["../../src/BulkOperations/bulk-operations-container.component.ts","../../src/Admin/admin-container.component.html"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAgB,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;;;AAEpG;;;;;GAKG;AAQI,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,2BAA2B;IAC7D,cAAc,GAAG,iBAAiB,CAAC;IACnC,aAAa,GAAG,yBAAyB,CAAC;IAC1C,iBAAiB,GAAG,8DAA8D,CAAC;IAEnF,QAAQ,GAAmB;QACvC;YACI,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,iCAAiC;YACvC,WAAW,EAAE,uCAAuC;YACpD,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,0BAA0B,EAAE;SACxE;QACD;YACI,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,+BAA+B;YACrC,WAAW,EAAE,wCAAwC;YACrD,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,0BAA0B,EAAE;SACxE;KACJ,CAAC;6SApBO,gCAAgC,yBAAhC,gCAAgC;6DAAhC,gCAAgC;;YClB7C,sCAAgB;YACZ,oCAIiB;YAGb,AADJ,uCAA8D,qBAKb;YAAzC,0KAAe,4BAAwB,KAAC;YAC5C,iBAAc;YACd,8CAA+D;YAC3D,iCAA0C;YAGtD,AADI,AADI,iBAAsB,EACX,EACF;;YAhBT,cAAwB;YAExB,AADA,AADA,0CAAwB,2BACF,mCACQ;YAGpB,cAAa;YAAC,AAAd,2BAAa,kBAAkB;YAGrC,cAAwB;YACxB,AADA,0CAAwB,+BACE;YAGT,cAAqB;YAAC,AAAtB,uCAAqB,wBAAoB;;;ADIzD,gCAAgC;IAP5C,aAAa,CAAC,qBAAqB,EAAE,yBAAyB,CAAC;GAOnD,gCAAgC,CAqB5C;;iFArBY,gCAAgC;cAN5C,SAAS;6BACM,KAAK,YACP,8BAA8B;;kFAI/B,gCAAgC","sourcesContent":["import { Component } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { AdminSection, BaseAdminContainerComponent } from '../Admin/base-admin-container.component';\n\n/**\n * Bulk Operations dashboard container — the left-nav shell for the Bulk Operations app. Reuses the proven\n * Admin container shell (template + base) and contributes two sections: Operations (author + run) and Run\n * History (audit). Each section hosts a thin resource component that renders the generic\n * `@memberjunction/ng-record-process-studio` UI.\n */\n@RegisterClass(BaseResourceComponent, 'BulkOperationsContainer')\n@Component({\n standalone: false,\n selector: 'mj-bulk-operations-container',\n templateUrl: '../Admin/admin-container.component.html',\n styleUrls: ['../Admin/admin-container.component.css'],\n})\nexport class BulkOperationsContainerComponent extends BaseAdminContainerComponent {\n public readonly ContainerTitle = 'Bulk Operations';\n public readonly ContainerIcon = 'fa-solid fa-layer-group';\n public readonly ContainerSubtitle = 'Define and run rules-driven bulk operations across your data';\n\n public readonly Sections: AdminSection[] = [\n {\n id: 'operations',\n label: 'Operations',\n icon: 'fa-solid fa-wand-magic-sparkles',\n description: 'Create, edit, and run bulk operations',\n source: { kind: 'resource', driverClass: 'BulkOperationsOperations' },\n },\n {\n id: 'run-history',\n label: 'Run History',\n icon: 'fa-solid fa-clock-rotate-left',\n description: 'Past runs and their per-record results',\n source: { kind: 'resource', driverClass: 'BulkOperationsRunHistory' },\n },\n ];\n}\n","<mj-page-layout>\n <mj-page-header\n [Title]=\"ContainerTitle\"\n [Icon]=\"ContainerIcon\"\n [Subtitle]=\"ContainerSubtitle\">\n </mj-page-header>\n\n <mj-page-body [Flex]=\"true\" [Padding]=\"false\" Direction=\"row\">\n <mj-left-nav\n MobileTitle=\"Administration\"\n [Sections]=\"NavSections\"\n [ActiveId]=\"ActiveSection\"\n (ItemClicked)=\"OnNavItemClicked($event)\">\n </mj-left-nav>\n <mj-left-nav-content [Loading]=\"IsLoading\" [Error]=\"LoadError\">\n <ng-container #contentHost></ng-container>\n </mj-left-nav-content>\n </mj-page-body>\n</mj-page-layout>\n"]}
@@ -0,0 +1,16 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
3
+ import { ResourceData } from '@memberjunction/core-entities';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * "Operations" sub-page of the Bulk Operations shell. A thin host that renders the generic, self-contained
7
+ * `<mj-record-process-studio>` (list / create / edit / run) scoped to the current provider.
8
+ */
9
+ export declare class BulkOperationsOperationsComponent extends BaseResourceComponent implements OnInit {
10
+ ngOnInit(): Promise<void>;
11
+ GetResourceDisplayName(_data: ResourceData): Promise<string>;
12
+ GetResourceIconClass(_data: ResourceData): Promise<string>;
13
+ static ɵfac: i0.ɵɵFactoryDeclaration<BulkOperationsOperationsComponent, never>;
14
+ static ɵcmp: i0.ɵɵComponentDeclaration<BulkOperationsOperationsComponent, "mj-bulk-operations-operations", never, {}, {}, never, never, false, never>;
15
+ }
16
+ //# sourceMappingURL=bulk-operations-operations.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-operations-operations.component.d.ts","sourceRoot":"","sources":["../../src/BulkOperations/bulk-operations-operations.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;;AAE7D;;;GAGG;AACH,qBAOa,iCAAkC,SAAQ,qBAAsB,YAAW,MAAM;IAC3E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,sBAAsB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAC5D,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCANhE,iCAAiC;2CAAjC,iCAAiC;CAO7C"}
@@ -0,0 +1,42 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component } from '@angular/core';
8
+ import { RegisterClass } from '@memberjunction/global';
9
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "@memberjunction/ng-record-process-studio";
12
+ /**
13
+ * "Operations" sub-page of the Bulk Operations shell. A thin host that renders the generic, self-contained
14
+ * `<mj-record-process-studio>` (list / create / edit / run) scoped to the current provider.
15
+ */
16
+ let BulkOperationsOperationsComponent = class BulkOperationsOperationsComponent extends BaseResourceComponent {
17
+ async ngOnInit() {
18
+ super.ngOnInit();
19
+ this.NotifyLoadComplete();
20
+ }
21
+ async GetResourceDisplayName(_data) { return 'Operations'; }
22
+ async GetResourceIconClass(_data) { return 'fa-solid fa-wand-magic-sparkles'; }
23
+ static ɵfac = /*@__PURE__*/ (() => { let ɵBulkOperationsOperationsComponent_BaseFactory; return function BulkOperationsOperationsComponent_Factory(__ngFactoryType__) { return (ɵBulkOperationsOperationsComponent_BaseFactory || (ɵBulkOperationsOperationsComponent_BaseFactory = i0.ɵɵgetInheritedFactory(BulkOperationsOperationsComponent)))(__ngFactoryType__ || BulkOperationsOperationsComponent); }; })();
24
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: BulkOperationsOperationsComponent, selectors: [["mj-bulk-operations-operations"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "bo-host"], [3, "Provider"]], template: function BulkOperationsOperationsComponent_Template(rf, ctx) { if (rf & 1) {
25
+ i0.ɵɵelementStart(0, "div", 0);
26
+ i0.ɵɵelement(1, "mj-record-process-studio", 1);
27
+ i0.ɵɵelementEnd();
28
+ } if (rf & 2) {
29
+ i0.ɵɵadvance();
30
+ i0.ɵɵproperty("Provider", ctx.ProviderToUse);
31
+ } }, dependencies: [i1.RecordProcessStudioComponent], styles: [".bo-host[_ngcontent-%COMP%]{padding:20px;height:100%;overflow:auto;box-sizing:border-box}"] });
32
+ };
33
+ BulkOperationsOperationsComponent = __decorate([
34
+ RegisterClass(BaseResourceComponent, 'BulkOperationsOperations')
35
+ ], BulkOperationsOperationsComponent);
36
+ export { BulkOperationsOperationsComponent };
37
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BulkOperationsOperationsComponent, [{
38
+ type: Component,
39
+ args: [{ standalone: false, selector: 'mj-bulk-operations-operations', template: `<div class="bo-host"><mj-record-process-studio [Provider]="ProviderToUse"></mj-record-process-studio></div>`, styles: [".bo-host{padding:20px;height:100%;overflow:auto;box-sizing:border-box}"] }]
40
+ }], null, null); })();
41
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(BulkOperationsOperationsComponent, { className: "BulkOperationsOperationsComponent", filePath: "src/BulkOperations/bulk-operations-operations.component.ts", lineNumber: 17 }); })();
42
+ //# sourceMappingURL=bulk-operations-operations.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-operations-operations.component.js","sourceRoot":"","sources":["../../src/BulkOperations/bulk-operations-operations.component.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAU,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;;AAGlE;;;GAGG;AAQI,IAAM,iCAAiC,GAAvC,MAAM,iCAAkC,SAAQ,qBAAqB;IAC/D,KAAK,CAAC,QAAQ;QACnB,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IACQ,KAAK,CAAC,sBAAsB,CAAC,KAAmB,IAAqB,OAAO,YAAY,CAAC,CAAC,CAAC;IAC3F,KAAK,CAAC,oBAAoB,CAAC,KAAmB,IAAqB,OAAO,iCAAiC,CAAC,CAAC,CAAC;iTAN9G,iCAAiC,yBAAjC,iCAAiC;6DAAjC,iCAAiC;YAH/B,8BAAqB;YAAA,8CAAgF;YAAA,iBAAM;;YAA5D,cAA0B;YAA1B,4CAA0B;;;AAG3E,iCAAiC;IAP7C,aAAa,CAAC,qBAAqB,EAAE,0BAA0B,CAAC;GAOpD,iCAAiC,CAO7C;;iFAPY,iCAAiC;cAN7C,SAAS;6BACM,KAAK,YACP,+BAA+B,YAC/B,6GAA6G;;kFAG9G,iCAAiC","sourcesContent":["import { Component, OnInit } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { ResourceData } from '@memberjunction/core-entities';\n\n/**\n * \"Operations\" sub-page of the Bulk Operations shell. A thin host that renders the generic, self-contained\n * `<mj-record-process-studio>` (list / create / edit / run) scoped to the current provider.\n */\n@RegisterClass(BaseResourceComponent, 'BulkOperationsOperations')\n@Component({\n standalone: false,\n selector: 'mj-bulk-operations-operations',\n template: `<div class=\"bo-host\"><mj-record-process-studio [Provider]=\"ProviderToUse\"></mj-record-process-studio></div>`,\n styles: [`.bo-host{padding:20px;height:100%;overflow:auto;box-sizing:border-box}`],\n})\nexport class BulkOperationsOperationsComponent extends BaseResourceComponent implements OnInit {\n override async ngOnInit(): Promise<void> {\n super.ngOnInit();\n this.NotifyLoadComplete();\n }\n override async GetResourceDisplayName(_data: ResourceData): Promise<string> { return 'Operations'; }\n override async GetResourceIconClass(_data: ResourceData): Promise<string> { return 'fa-solid fa-wand-magic-sparkles'; }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
3
+ import { ResourceData } from '@memberjunction/core-entities';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * "Run History" sub-page of the Bulk Operations shell. A thin host that renders the generic, self-contained
7
+ * `<mj-record-process-history>` (run list + per-record drill-in) scoped to the current provider.
8
+ */
9
+ export declare class BulkOperationsRunHistoryComponent extends BaseResourceComponent implements OnInit {
10
+ ngOnInit(): Promise<void>;
11
+ GetResourceDisplayName(_data: ResourceData): Promise<string>;
12
+ GetResourceIconClass(_data: ResourceData): Promise<string>;
13
+ static ɵfac: i0.ɵɵFactoryDeclaration<BulkOperationsRunHistoryComponent, never>;
14
+ static ɵcmp: i0.ɵɵComponentDeclaration<BulkOperationsRunHistoryComponent, "mj-bulk-operations-run-history", never, {}, {}, never, never, false, never>;
15
+ }
16
+ //# sourceMappingURL=bulk-operations-run-history.component.d.ts.map