@memberjunction/ng-explorer-core 6.2.0-edge.3 → 6.2.0-edge.5

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 (138) hide show
  1. package/README.md +10 -0
  2. package/dist/app-routing.module.d.ts.map +1 -1
  3. package/dist/app-routing.module.js +13 -6
  4. package/dist/app-routing.module.js.map +1 -1
  5. package/dist/generated/lazy-feature-config.d.ts +1 -1
  6. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  7. package/dist/generated/lazy-feature-config.js +4 -2
  8. package/dist/generated/lazy-feature-config.js.map +1 -1
  9. package/dist/lib/guards/moved-nav-item-redirect.d.ts +15 -0
  10. package/dist/lib/guards/moved-nav-item-redirect.d.ts.map +1 -0
  11. package/dist/lib/guards/moved-nav-item-redirect.js +37 -0
  12. package/dist/lib/guards/moved-nav-item-redirect.js.map +1 -0
  13. package/dist/lib/oauth/oauth-callback.component.d.ts +2 -0
  14. package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -1
  15. package/dist/lib/oauth/oauth-callback.component.js +10 -10
  16. package/dist/lib/oauth/oauth-callback.component.js.map +1 -1
  17. package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts +34 -0
  18. package/dist/lib/omnibar/omnibar-dashboard-matches.d.ts.map +1 -0
  19. package/dist/lib/omnibar/omnibar-dashboard-matches.js +70 -0
  20. package/dist/lib/omnibar/omnibar-dashboard-matches.js.map +1 -0
  21. package/dist/lib/omnibar/omnibar-palette.component.d.ts +27 -2
  22. package/dist/lib/omnibar/omnibar-palette.component.d.ts.map +1 -1
  23. package/dist/lib/omnibar/omnibar-palette.component.js +126 -65
  24. package/dist/lib/omnibar/omnibar-palette.component.js.map +1 -1
  25. package/dist/lib/omnibar/omnibar-provider.d.ts +4 -0
  26. package/dist/lib/omnibar/omnibar-provider.d.ts.map +1 -1
  27. package/dist/lib/omnibar/omnibar-provider.js.map +1 -1
  28. package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts +2 -2
  29. package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts.map +1 -1
  30. package/dist/lib/omnibar/providers/omnibar-record.provider.js +3 -7
  31. package/dist/lib/omnibar/providers/omnibar-record.provider.js.map +1 -1
  32. package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts +15 -2
  33. package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts.map +1 -1
  34. package/dist/lib/omnibar/providers/omnibar-search.provider.js +59 -7
  35. package/dist/lib/omnibar/providers/omnibar-search.provider.js.map +1 -1
  36. package/dist/lib/profile/forking-setting.d.ts +8 -0
  37. package/dist/lib/profile/forking-setting.d.ts.map +1 -0
  38. package/dist/lib/profile/forking-setting.js +18 -0
  39. package/dist/lib/profile/forking-setting.js.map +1 -0
  40. package/dist/lib/profile/profile-dialog.component.d.ts +8 -0
  41. package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
  42. package/dist/lib/profile/profile-dialog.component.js +182 -92
  43. package/dist/lib/profile/profile-dialog.component.js.map +1 -1
  44. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +16 -1
  45. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
  46. package/dist/lib/resource-wrappers/artifact-resource.component.js +27 -4
  47. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  48. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +24 -21
  49. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  50. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +231 -54
  51. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  52. package/dist/lib/resource-wrappers/chat-search-routing.d.ts +10 -3
  53. package/dist/lib/resource-wrappers/chat-search-routing.d.ts.map +1 -1
  54. package/dist/lib/resource-wrappers/chat-search-routing.js +11 -4
  55. package/dist/lib/resource-wrappers/chat-search-routing.js.map +1 -1
  56. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +12 -3
  57. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
  58. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +18 -3
  59. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  60. package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts +29 -0
  61. package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.d.ts.map +1 -0
  62. package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js +141 -0
  63. package/dist/lib/resource-wrappers/dashboard-add-to-menu.component.js.map +1 -0
  64. package/dist/lib/resource-wrappers/dashboard-part-config.d.ts +28 -0
  65. package/dist/lib/resource-wrappers/dashboard-part-config.d.ts.map +1 -0
  66. package/dist/lib/resource-wrappers/dashboard-part-config.js +150 -0
  67. package/dist/lib/resource-wrappers/dashboard-part-config.js.map +1 -0
  68. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +361 -56
  69. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  70. package/dist/lib/resource-wrappers/dashboard-resource.component.js +1312 -361
  71. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  72. package/dist/lib/resource-wrappers/dashboard-source-search.d.ts +86 -0
  73. package/dist/lib/resource-wrappers/dashboard-source-search.d.ts.map +1 -0
  74. package/dist/lib/resource-wrappers/dashboard-source-search.js +136 -0
  75. package/dist/lib/resource-wrappers/dashboard-source-search.js.map +1 -0
  76. package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts +30 -0
  77. package/dist/lib/resource-wrappers/dashboard-studio-pane.d.ts.map +1 -0
  78. package/dist/lib/resource-wrappers/dashboard-studio-pane.js +55 -0
  79. package/dist/lib/resource-wrappers/dashboard-studio-pane.js.map +1 -0
  80. package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts +135 -0
  81. package/dist/lib/resource-wrappers/dashboard-studio-tools.d.ts.map +1 -0
  82. package/dist/lib/resource-wrappers/dashboard-studio-tools.js +856 -0
  83. package/dist/lib/resource-wrappers/dashboard-studio-tools.js.map +1 -0
  84. package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts +87 -0
  85. package/dist/lib/resource-wrappers/dashboard-tab-agent.d.ts.map +1 -0
  86. package/dist/lib/resource-wrappers/dashboard-tab-agent.js +125 -0
  87. package/dist/lib/resource-wrappers/dashboard-tab-agent.js.map +1 -0
  88. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +28 -7
  89. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
  90. package/dist/lib/resource-wrappers/livekit-room-resource.component.js +174 -112
  91. package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
  92. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +3 -3
  93. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
  94. package/dist/lib/resource-wrappers/search-results-resource.component.js +10 -14
  95. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  96. package/dist/lib/server-connectivity/server-connectivity-banner.component.d.ts +16 -3
  97. package/dist/lib/server-connectivity/server-connectivity-banner.component.d.ts.map +1 -1
  98. package/dist/lib/server-connectivity/server-connectivity-banner.component.js +17 -3
  99. package/dist/lib/server-connectivity/server-connectivity-banner.component.js.map +1 -1
  100. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +41 -0
  101. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  102. package/dist/lib/shell/components/tabs/tab-container.component.js +170 -39
  103. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  104. package/dist/lib/shell/dashboard-tab-for-url.d.ts +35 -0
  105. package/dist/lib/shell/dashboard-tab-for-url.d.ts.map +1 -0
  106. package/dist/lib/shell/dashboard-tab-for-url.js +39 -0
  107. package/dist/lib/shell/dashboard-tab-for-url.js.map +1 -0
  108. package/dist/lib/shell/deep-link-workspace.d.ts +25 -0
  109. package/dist/lib/shell/deep-link-workspace.d.ts.map +1 -0
  110. package/dist/lib/shell/deep-link-workspace.js +49 -0
  111. package/dist/lib/shell/deep-link-workspace.js.map +1 -0
  112. package/dist/lib/shell/shell.component.d.ts +43 -2
  113. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  114. package/dist/lib/shell/shell.component.js +174 -42
  115. package/dist/lib/shell/shell.component.js.map +1 -1
  116. package/dist/lib/shell/shell.module.d.ts +2 -1
  117. package/dist/lib/shell/shell.module.d.ts.map +1 -1
  118. package/dist/lib/shell/shell.module.js +6 -2
  119. package/dist/lib/shell/shell.module.js.map +1 -1
  120. package/dist/lib/single-dashboard/single-dashboard.component.js +1 -1
  121. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  122. package/dist/lib/single-record/single-record.component.d.ts +12 -0
  123. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  124. package/dist/lib/single-record/single-record.component.js +49 -8
  125. package/dist/lib/single-record/single-record.component.js.map +1 -1
  126. package/dist/lib/template-user/template-user-banner.component.d.ts +20 -0
  127. package/dist/lib/template-user/template-user-banner.component.d.ts.map +1 -0
  128. package/dist/lib/template-user/template-user-banner.component.js +67 -0
  129. package/dist/lib/template-user/template-user-banner.component.js.map +1 -0
  130. package/dist/module.d.ts +61 -59
  131. package/dist/module.d.ts.map +1 -1
  132. package/dist/module.js +7 -0
  133. package/dist/module.js.map +1 -1
  134. package/dist/public-api.d.ts +1 -0
  135. package/dist/public-api.d.ts.map +1 -1
  136. package/dist/public-api.js +1 -0
  137. package/dist/public-api.js.map +1 -1
  138. package/package.json +58 -53
@@ -64,6 +64,8 @@ export declare class OAuthCallbackComponent extends BaseAngularComponent impleme
64
64
  * Process the OAuth callback by extracting params and exchanging the code
65
65
  */
66
66
  private processOAuthCallback;
67
+ /** Pre-#5674 exchange URL for hosts that have not configured MJAPI_URI: derived from the GraphQL URL. */
68
+ private legacyExchangeUrl;
67
69
  /**
68
70
  * Call the backend to exchange the authorization code for tokens
69
71
  */
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-callback.component.d.ts","sourceRoot":"","sources":["../../../src/lib/oauth/oauth-callback.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAIzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAiBrE;;;;;;;;;GASG;AACH,qBAMa,sBAAuB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IA0BrF,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,GAAG;IA3Bf,oDAAoD;IAC7C,SAAS,UAAQ;IAExB,kBAAkB;IACX,QAAQ,UAAS;IAExB,+BAA+B;IACxB,YAAY,SAAM;IAEzB,iDAAiD;IAC1C,SAAS,SAAM;IAEtB,qCAAqC;IAC9B,WAAW,UAAS;IAE3B,6CAA6C;IACtC,aAAa,SAA0B;IAE9C,2CAA2C;IAC3C,OAAO,CAAC,SAAS,CAA+C;IAEhE,wCAAwC;IACxC,OAAO,CAAC,YAAY,CAAS;gBAGjB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,iBAAiB;IAI5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B,WAAW,IAAI,IAAI;IAQnB;;;OAGG;YACW,yBAAyB;IAiDvC;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;YACW,mBAAmB;IAcjC;;OAEG;YACW,oBAAoB;IAgDlC;;OAEG;YACW,YAAY;IAqC1B;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACI,OAAO,IAAI,IAAI;IAOtB,uCAAuC;IAChC,OAAO,IAAI,IAAI;IAItB;;OAEG;IACI,OAAO,IAAI,IAAI;IAKtB,uCAAuC;IAChC,OAAO,IAAI,IAAI;yCAnVb,sBAAsB;2CAAtB,sBAAsB;CAsVlC"}
1
+ {"version":3,"file":"oauth-callback.component.d.ts","sourceRoot":"","sources":["../../../src/lib/oauth/oauth-callback.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAa,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAIzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAiBrE;;;;;;;;;GASG;AACH,qBAMa,sBAAuB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IA0BrF,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,GAAG;IA3Bf,oDAAoD;IAC7C,SAAS,UAAQ;IAExB,kBAAkB;IACX,QAAQ,UAAS;IAExB,+BAA+B;IACxB,YAAY,SAAM;IAEzB,iDAAiD;IAC1C,SAAS,SAAM;IAEtB,qCAAqC;IAC9B,WAAW,UAAS;IAE3B,6CAA6C;IACtC,aAAa,SAA0B;IAE9C,2CAA2C;IAC3C,OAAO,CAAC,SAAS,CAA+C;IAEhE,wCAAwC;IACxC,OAAO,CAAC,YAAY,CAAS;gBAGjB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,iBAAiB;IAI5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B,WAAW,IAAI,IAAI;IAQnB;;;OAGG;YACW,yBAAyB;IAiDvC;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;YACW,mBAAmB;IAcjC;;OAEG;YACW,oBAAoB;IAgDlC,yGAAyG;IACzG,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;YACW,YAAY;IA+B1B;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACI,OAAO,IAAI,IAAI;IAOtB,uCAAuC;IAChC,OAAO,IAAI,IAAI;IAItB;;OAEG;IACI,OAAO,IAAI,IAAI;IAKtB,uCAAuC;IAChC,OAAO,IAAI,IAAI;yCArVb,sBAAsB;2CAAtB,sBAAsB;CAwVlC"}
@@ -253,6 +253,13 @@ export class OAuthCallbackComponent extends BaseAngularComponent {
253
253
  this.showError('network_error', message, true);
254
254
  }
255
255
  }
256
+ /** Pre-#5674 exchange URL for hosts that have not configured MJAPI_URI: derived from the GraphQL URL. */
257
+ legacyExchangeUrl(graphqlUrl) {
258
+ if (graphqlUrl.includes('/graphql')) {
259
+ return graphqlUrl.replace('/graphql', '/oauth/exchange');
260
+ }
261
+ return graphqlUrl.replace(/\/$/, '') + '/oauth/exchange';
262
+ }
256
263
  /**
257
264
  * Call the backend to exchange the authorization code for tokens
258
265
  */
@@ -260,16 +267,9 @@ export class OAuthCallbackComponent extends BaseAngularComponent {
260
267
  // Get the GraphQL provider - we know it's ready at this point
261
268
  const gqlProvider = this.ProviderToUse;
262
269
  const configData = gqlProvider.ConfigData;
263
- // Build the exchange endpoint URL from the GraphQL URL
264
- // Handle both cases: URL with /graphql suffix and URL without
265
- let apiUrl = configData.URL;
266
- if (apiUrl.includes('/graphql')) {
267
- apiUrl = apiUrl.replace('/graphql', '/oauth/exchange');
268
- }
269
- else {
270
- // URL doesn't have /graphql, append /oauth/exchange
271
- apiUrl = apiUrl.replace(/\/$/, '') + '/oauth/exchange';
272
- }
270
+ // The exchange endpoint hangs off the configured MJAPI URL (MJAPI_URI, MJ #5674). Without one,
271
+ // keep the pre-#5674 derivation from the GraphQL URL.
272
+ const apiUrl = configData.MJAPIURL ? `${configData.MJAPIURL}/oauth/exchange` : this.legacyExchangeUrl(configData.URL);
273
273
  try {
274
274
  const response = await fetch(apiUrl, {
275
275
  method: 'POST',
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-callback.component.js","sourceRoot":"","sources":["../../../src/lib/oauth/oauth-callback.component.ts","../../../src/lib/oauth/oauth-callback.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview OAuth Callback Component\n *\n * Handles OAuth provider redirects in the frontend. When an OAuth provider\n * redirects back to the application after user authorization, this component:\n * 1. Waits for the user's session to be restored (authentication)\n * 2. Extracts the code and state from URL query parameters\n * 3. Calls the backend /oauth/exchange endpoint to complete the token exchange\n * 4. Redirects to the original page with success/error notification\n *\n * @module OAuth Callback\n */\n\nimport { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { Metadata } from '@memberjunction/core';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n/**\n * Response from the OAuth exchange endpoint\n */\ninterface OAuthExchangeResponse {\n success: boolean;\n connectionId?: string;\n errorCode?: string;\n errorMessage?: string;\n isRetryable?: boolean;\n}\n\n/** Maximum time to wait for provider initialization (30 seconds) */\nconst MAX_WAIT_TIME_MS = 30000;\n/** Polling interval for checking provider readiness (500ms) */\nconst POLL_INTERVAL_MS = 500;\n\n/**\n * OAuth Callback Component\n *\n * Handles the redirect from OAuth providers after user authorization.\n * This component is loaded at /oauth/callback and processes the\n * authorization code to complete the OAuth flow.\n *\n * The component waits for authentication to complete before attempting\n * the code exchange, since the user's session needs to be restored first.\n */\n@Component({\n standalone: false,\n selector: 'mj-oauth-callback',\n templateUrl: './oauth-callback.component.html',\n styleUrls: ['./oauth-callback.component.css']\n})\nexport class OAuthCallbackComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n /** Loading state while processing OAuth callback */\n public IsLoading = true;\n\n /** Error state */\n public HasError = false;\n\n /** Error message to display */\n public ErrorMessage = '';\n\n /** Error code from OAuth provider or exchange */\n public ErrorCode = '';\n\n /** Whether the error is retryable */\n public IsRetryable = false;\n\n /** Status message shown during processing */\n public StatusMessage = 'Restoring session...';\n\n /** Timer for polling provider readiness */\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n\n /** Flag to prevent double processing */\n private isProcessing = false;\n\n constructor(\n private route: ActivatedRoute,\n private router: Router,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n async ngOnInit(): Promise<void> {\n // Wait for the GraphQL provider to be ready, then process the callback\n await this.waitForProviderAndProcess();\n }\n\n ngOnDestroy(): void {\n // Clean up the polling timer\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n /**\n * Waits for the GraphQL provider to be initialized (indicating auth is complete)\n * then processes the OAuth callback.\n */\n private async waitForProviderAndProcess(): Promise<void> {\n const startTime = Date.now();\n\n // Check if provider is already ready\n if (this.isProviderReady()) {\n await this.safeProcessCallback();\n return;\n }\n\n // Poll for provider readiness\n this.StatusMessage = 'Waiting for authentication...';\n this.cdr.detectChanges();\n\n return new Promise<void>((resolve) => {\n this.pollTimer = setInterval(async () => {\n const elapsed = Date.now() - startTime;\n\n if (this.isProviderReady()) {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n await this.safeProcessCallback();\n resolve();\n return;\n }\n\n if (elapsed >= MAX_WAIT_TIME_MS) {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n this.showError(\n 'timeout',\n 'Timed out waiting for authentication. Please try logging in again.',\n true\n );\n resolve();\n return;\n }\n\n // Update status message with progress\n const secondsRemaining = Math.ceil((MAX_WAIT_TIME_MS - elapsed) / 1000);\n this.StatusMessage = `Waiting for authentication... (${secondsRemaining}s)`;\n this.cdr.detectChanges();\n }, POLL_INTERVAL_MS);\n });\n }\n\n /**\n * Checks if the GraphQL provider is initialized and has a valid token\n */\n private isProviderReady(): boolean {\n try {\n const provider = this.ProviderToUse as GraphQLDataProvider;\n if (!provider) {\n return false;\n }\n const configData = provider.ConfigData;\n if (!configData || !configData.Token || !configData.URL) {\n return false;\n }\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Safely processes the callback, preventing double execution\n */\n private async safeProcessCallback(): Promise<void> {\n if (this.isProcessing) {\n return;\n }\n this.isProcessing = true;\n\n try {\n await this.processOAuthCallback();\n } catch (error) {\n console.error('[OAuth Callback] Error in processOAuthCallback:', error);\n this.showError('component_error', error instanceof Error ? error.message : String(error), true);\n }\n }\n\n /**\n * Process the OAuth callback by extracting params and exchanging the code\n */\n private async processOAuthCallback(): Promise<void> {\n const params = this.route.snapshot.queryParams;\n\n // Check for error from OAuth provider\n if (params['error']) {\n this.showError(\n params['error'] as string,\n params['error_description'] as string || 'Authorization was denied or failed'\n );\n return;\n }\n\n const code = params['code'] as string;\n const state = params['state'] as string;\n\n // Validate required parameters\n if (!code) {\n this.showError('missing_code', 'No authorization code received from the OAuth provider');\n return;\n }\n\n if (!state) {\n this.showError('missing_state', 'No state parameter received from the OAuth provider');\n return;\n }\n\n // Exchange the code for tokens\n this.StatusMessage = 'Exchanging authorization code...';\n this.cdr.detectChanges();\n\n try {\n const result = await this.exchangeCode(code, state);\n\n if (result.success) {\n this.handleSuccess(result.connectionId);\n } else {\n this.showError(\n result.errorCode || 'exchange_failed',\n result.errorMessage || 'Failed to complete authorization',\n result.isRetryable\n );\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.showError('network_error', message, true);\n }\n }\n\n /**\n * Call the backend to exchange the authorization code for tokens\n */\n private async exchangeCode(code: string, state: string): Promise<OAuthExchangeResponse> {\n // Get the GraphQL provider - we know it's ready at this point\n const gqlProvider = this.ProviderToUse as GraphQLDataProvider;\n const configData = gqlProvider.ConfigData;\n\n // Build the exchange endpoint URL from the GraphQL URL\n // Handle both cases: URL with /graphql suffix and URL without\n let apiUrl = configData.URL;\n if (apiUrl.includes('/graphql')) {\n apiUrl = apiUrl.replace('/graphql', '/oauth/exchange');\n } else {\n // URL doesn't have /graphql, append /oauth/exchange\n apiUrl = apiUrl.replace(/\\/$/, '') + '/oauth/exchange';\n }\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${configData.Token}`\n },\n body: JSON.stringify({ code, state })\n });\n\n // Parse response regardless of status code\n const data = await response.json();\n return data as OAuthExchangeResponse;\n } catch (fetchError) {\n return {\n success: false,\n errorCode: 'fetch_error',\n errorMessage: fetchError instanceof Error ? fetchError.message : 'Network error during token exchange'\n };\n }\n }\n\n /**\n * Handle successful OAuth completion\n */\n private handleSuccess(connectionId?: string): void {\n this.IsLoading = false;\n this.StatusMessage = 'Authorization successful! Redirecting...';\n this.cdr.detectChanges();\n\n // Get the stored return URL - try both localStorage and sessionStorage\n const storedUrl = localStorage.getItem('oauth_return_url');\n const storedPath = localStorage.getItem('oauth_return_path');\n const sessionUrl = sessionStorage.getItem('oauth_return_url');\n const sessionPath = sessionStorage.getItem('oauth_return_path');\n\n let returnUrl = storedUrl || sessionUrl || storedPath || sessionPath;\n\n // Clean up all possible storage locations\n this.clearStoredReturnUrls();\n\n // Default to MCP dashboard if no return URL found\n const defaultPath = '/app/admin/MCP';\n if (!returnUrl || returnUrl.trim() === '' || returnUrl === '/') {\n returnUrl = defaultPath;\n }\n\n // Build the final navigation path\n const finalPath = this.buildFinalPath(returnUrl, connectionId, defaultPath);\n\n // Use window.location for reliable navigation after OAuth\n setTimeout(() => {\n window.location.href = finalPath;\n }, 500);\n }\n\n /**\n * Builds the final navigation path with success query params\n */\n private buildFinalPath(returnUrl: string, connectionId: string | undefined, defaultPath: string): string {\n try {\n let finalPath: string;\n\n // If it's a full URL, extract just the path and search\n if (returnUrl.startsWith('http://') || returnUrl.startsWith('https://')) {\n const url = new URL(returnUrl);\n finalPath = url.pathname + url.search;\n } else {\n finalPath = returnUrl;\n }\n\n // Ensure we have a valid path (not empty or just \"/\")\n if (!finalPath || finalPath.trim() === '' || finalPath === '/') {\n finalPath = defaultPath;\n }\n\n // Add success query params\n const separator = finalPath.includes('?') ? '&' : '?';\n finalPath = `${finalPath}${separator}oauth=success`;\n if (connectionId) {\n finalPath += `&connectionId=${connectionId}`;\n }\n\n return finalPath;\n } catch (e) {\n console.error('[OAuth Callback] Error parsing return URL:', e);\n return `${defaultPath}?oauth=success${connectionId ? `&connectionId=${connectionId}` : ''}`;\n }\n }\n\n /**\n * Clears all stored return URLs from storage\n */\n private clearStoredReturnUrls(): void {\n localStorage.removeItem('oauth_return_url');\n localStorage.removeItem('oauth_return_path');\n sessionStorage.removeItem('oauth_return_url');\n sessionStorage.removeItem('oauth_return_path');\n }\n\n /**\n * Show error state\n */\n private showError(errorCode: string, message: string, isRetryable = false): void {\n this.IsLoading = false;\n this.HasError = true;\n this.ErrorCode = errorCode;\n this.ErrorMessage = message;\n this.IsRetryable = isRetryable;\n this.cdr.detectChanges();\n }\n\n /**\n * Handle retry button click\n */\n public OnRetry(): void {\n // Get the stored return URL and redirect there to start fresh\n const returnUrl = localStorage.getItem('oauth_return_url') || '/app/admin/MCP';\n this.clearStoredReturnUrls();\n this.router.navigateByUrl(returnUrl);\n }\n\n /** @deprecated Use {@link OnRetry}. */\n public onRetry(): void {\n return this.OnRetry();\n }\n\n /**\n * Handle close button click (return to MCP dashboard)\n */\n public OnClose(): void {\n this.clearStoredReturnUrls();\n this.router.navigate(['/app/admin/MCP']);\n }\n\n /** @deprecated Use {@link OnClose}. */\n public onClose(): void {\n return this.OnClose();\n }\n}\n","<div class=\"oauth-callback-container\">\n <div class=\"oauth-callback-card\">\n <!-- Loading State -->\n @if (IsLoading) {\n <div class=\"oauth-status loading\">\n <mj-loading text=\"{{ StatusMessage }}\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (HasError) {\n <div class=\"oauth-status error\">\n <div class=\"icon-container error-icon\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <h2>Authorization Failed</h2>\n @if (ErrorCode) {\n <div class=\"error-code\">{{ ErrorCode }}</div>\n }\n <p class=\"error-message\">{{ ErrorMessage }}</p>\n <div class=\"button-group\">\n @if (IsRetryable) {\n <button mjButton variant=\"secondary\" (click)=\"onRetry()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n Try Again\n </button>\n }\n <button mjButton [variant]=\"IsRetryable ? 'outline' : 'secondary'\" (click)=\"onClose()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Return to Dashboard\n </button>\n </div>\n </div>\n }\n\n <!-- Success State (brief - redirects quickly) -->\n @if (!IsLoading && !HasError) {\n <div class=\"oauth-status success\">\n <div class=\"icon-container success-icon\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <h2>Authorization Successful</h2>\n <p>{{ StatusMessage }}</p>\n </div>\n }\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"oauth-callback.component.js","sourceRoot":"","sources":["../../../src/lib/oauth/oauth-callback.component.ts","../../../src/lib/oauth/oauth-callback.component.html"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAwC,MAAM,eAAe,CAAC;AAKhF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;;;;;ICdzD,8BAAkC;IAC9B,gCAAoD;IACxD,iBAAM;;;IADU,cAA0B;IAA1B,sBAAA,sCAA0B,CAAA;;;IAYlC,8BAAwB;IAAA,YAAe;IAAA,iBAAM;;;IAArB,cAAe;IAAf,sCAAe;;;;IAKnC,kCAAyD;IAApB,yMAAS,gBAAS,KAAC;IACpD,wBAAwC;IACxC,2BACJ;IAAA,iBAAS;;;;IAbjB,AADJ,8BAAgC,aACW;IACnC,uBAA8C;IAClD,iBAAM;IACN,0BAAI;IAAA,oCAAoB;IAAA,iBAAK;IAC7B,sGAAiB;IAGjB,4BAAyB;IAAA,YAAkB;IAAA,iBAAI;IAC/C,+BAA0B;IACtB,0GAAmB;IAMnB,mCAAuF;IAApB,2LAAS,gBAAS,KAAC;IAClF,yBAAsC;IACtC,sCACJ;IAER,AADI,AADI,iBAAS,EACP,EACJ;;;IAhBF,eAEC;IAFD,2CAEC;IACwB,eAAkB;IAAlB,yCAAkB;IAEvC,eAKC;IALD,6CAKC;IACgB,cAAiD;IAAjD,sEAAiD;;;IAWtE,AADJ,8BAAkC,cACW;IACrC,wBAAwC;IAC5C,iBAAM;IACN,0BAAI;IAAA,wCAAwB;IAAA,iBAAK;IACjC,yBAAG;IAAA,YAAmB;IAC1B,AAD0B,iBAAI,EACxB;;;IADC,eAAmB;IAAnB,0CAAmB;;ADZtC,oEAAoE;AACpE,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,+DAA+D;AAC/D,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;;;;;;GASG;AAOH,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IA0BhD;IACA;IACA;IA3BZ,oDAAoD;IAC7C,SAAS,GAAG,IAAI,CAAC;IAExB,kBAAkB;IACX,QAAQ,GAAG,KAAK,CAAC;IAExB,+BAA+B;IACxB,YAAY,GAAG,EAAE,CAAC;IAEzB,iDAAiD;IAC1C,SAAS,GAAG,EAAE,CAAC;IAEtB,qCAAqC;IAC9B,WAAW,GAAG,KAAK,CAAC;IAE3B,6CAA6C;IACtC,aAAa,GAAG,sBAAsB,CAAC;IAE9C,2CAA2C;IACnC,SAAS,GAA0C,IAAI,CAAC;IAEhE,wCAAwC;IAChC,YAAY,GAAG,KAAK,CAAC;IAE7B,YACY,KAAqB,EACrB,MAAc,EACd,GAAsB;QAElC,KAAK,EAAE,CAAC;QAJI,UAAK,GAAL,KAAK,CAAgB;QACrB,WAAM,GAAN,MAAM,CAAQ;QACd,QAAG,GAAH,GAAG,CAAmB;IAE1B,CAAC;IAET,KAAK,CAAC,QAAQ;QACV,uEAAuE;QACvE,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAC;IAC3C,CAAC;IAED,WAAW;QACP,6BAA6B;QAC7B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,yBAAyB;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,qCAAqC;QACrC,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACjC,OAAO;QACX,CAAC;QAED,8BAA8B;QAC9B,IAAI,CAAC,aAAa,GAAG,+BAA+B,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACjC,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;gBACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBAEvC,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;oBACzB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;wBACjB,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;oBAC1B,CAAC;oBACD,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBACjC,OAAO,EAAE,CAAC;oBACV,OAAO;gBACX,CAAC;gBAED,IAAI,OAAO,IAAI,gBAAgB,EAAE,CAAC;oBAC9B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;wBACjB,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;oBAC1B,CAAC;oBACD,IAAI,CAAC,SAAS,CACV,SAAS,EACT,oEAAoE,EACpE,IAAI,CACP,CAAC;oBACF,OAAO,EAAE,CAAC;oBACV,OAAO;gBACX,CAAC;gBAED,sCAAsC;gBACtC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,gBAAgB,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;gBACxE,IAAI,CAAC,aAAa,GAAG,kCAAkC,gBAAgB,IAAI,CAAC;gBAC5E,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YAC7B,CAAC,EAAE,gBAAgB,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,eAAe;QACnB,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAoC,CAAC;YAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACZ,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;YACvC,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;gBACtD,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB;QAC7B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,OAAO;QACX,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAEzB,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;YACxE,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACpG,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;QAE/C,sCAAsC;QACtC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC,SAAS,CACV,MAAM,CAAC,OAAO,CAAW,EACzB,MAAM,CAAC,mBAAmB,CAAW,IAAI,oCAAoC,CAChF,CAAC;YACF,OAAO;QACX,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAW,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAW,CAAC;QAExC,+BAA+B;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,wDAAwD,CAAC,CAAC;YACzF,OAAO;QACX,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,qDAAqD,CAAC,CAAC;YACvF,OAAO;QACX,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,aAAa,GAAG,kCAAkC,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAEpD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,SAAS,CACV,MAAM,CAAC,SAAS,IAAI,iBAAiB,EACrC,MAAM,CAAC,YAAY,IAAI,kCAAkC,EACzD,MAAM,CAAC,WAAW,CACrB,CAAC;YACN,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;YACxF,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;IACL,CAAC;IAED,yGAAyG;IACjG,iBAAiB,CAAC,UAAkB;QACxC,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,OAAO,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,iBAAiB,CAAC;IAC7D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,IAAY,EAAE,KAAa;QAClD,8DAA8D;QAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,aAAoC,CAAC;QAC9D,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAE1C,+FAA+F;QAC/F,sDAAsD;QACtD,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAEtH,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;gBACjC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACL,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,UAAU,CAAC,KAAK,EAAE;iBAChD;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;aACxC,CAAC,CAAC;YAEH,2CAA2C;YAC3C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,IAA6B,CAAC;QACzC,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YAClB,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,aAAa;gBACxB,YAAY,EAAE,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,qCAAqC;aACzG,CAAC;QACN,CAAC;IACL,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,YAAqB;QACvC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,0CAA0C,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,uEAAuE;QACvE,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAEhE,IAAI,SAAS,GAAG,SAAS,IAAI,UAAU,IAAI,UAAU,IAAI,WAAW,CAAC;QAErE,0CAA0C;QAC1C,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAE7B,kDAAkD;QAClD,MAAM,WAAW,GAAG,gBAAgB,CAAC;QACrC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YAC7D,SAAS,GAAG,WAAW,CAAC;QAC5B,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QAE5E,0DAA0D;QAC1D,UAAU,CAAC,GAAG,EAAE;YACZ,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC;QACrC,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,SAAiB,EAAE,YAAgC,EAAE,WAAmB;QAC3F,IAAI,CAAC;YACD,IAAI,SAAiB,CAAC;YAEtB,uDAAuD;YACvD,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACtE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC/B,SAAS,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACJ,SAAS,GAAG,SAAS,CAAC;YAC1B,CAAC;YAED,sDAAsD;YACtD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;gBAC7D,SAAS,GAAG,WAAW,CAAC;YAC5B,CAAC;YAED,2BAA2B;YAC3B,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACtD,SAAS,GAAG,GAAG,SAAS,GAAG,SAAS,eAAe,CAAC;YACpD,IAAI,YAAY,EAAE,CAAC;gBACf,SAAS,IAAI,iBAAiB,YAAY,EAAE,CAAC;YACjD,CAAC;YAED,OAAO,SAAS,CAAC;QACrB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,CAAC,CAAC,CAAC;YAC/D,OAAO,GAAG,WAAW,iBAAiB,YAAY,CAAC,CAAC,CAAC,iBAAiB,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAChG,CAAC;IACL,CAAC;IAED;;OAEG;IACK,qBAAqB;QACzB,YAAY,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;QAC5C,YAAY,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;QAC7C,cAAc,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;QAC9C,cAAc,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,SAAiB,EAAE,OAAe,EAAE,WAAW,GAAG,KAAK;QACrE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,OAAO;QACV,8DAA8D;QAC9D,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,gBAAgB,CAAC;QAC/E,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAED,uCAAuC;IAChC,OAAO;QACZ,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACI,OAAO;QACV,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,uCAAuC;IAChC,OAAO;QACZ,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;gHAvVQ,sBAAsB;6DAAtB,sBAAsB;YClD/B,AADJ,8BAAsC,aACD;YAE7B,wFAAiB;YAOjB,yFAAgB;YA0BhB,wFAA+B;YAUvC,AADI,iBAAM,EACJ;;YA3CE,eAIC;YAJD,wCAIC;YAGD,cAuBC;YAvBD,uCAuBC;YAGD,cAQC;YARD,0DAQC;;;iFDOI,sBAAsB;cANlC,SAAS;6BACI,KAAK,YACL,mBAAmB;;kFAIpB,sBAAsB","sourcesContent":["/**\n * @fileoverview OAuth Callback Component\n *\n * Handles OAuth provider redirects in the frontend. When an OAuth provider\n * redirects back to the application after user authorization, this component:\n * 1. Waits for the user's session to be restored (authentication)\n * 2. Extracts the code and state from URL query parameters\n * 3. Calls the backend /oauth/exchange endpoint to complete the token exchange\n * 4. Redirects to the original page with success/error notification\n *\n * @module OAuth Callback\n */\n\nimport { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { Metadata } from '@memberjunction/core';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n/**\n * Response from the OAuth exchange endpoint\n */\ninterface OAuthExchangeResponse {\n success: boolean;\n connectionId?: string;\n errorCode?: string;\n errorMessage?: string;\n isRetryable?: boolean;\n}\n\n/** Maximum time to wait for provider initialization (30 seconds) */\nconst MAX_WAIT_TIME_MS = 30000;\n/** Polling interval for checking provider readiness (500ms) */\nconst POLL_INTERVAL_MS = 500;\n\n/**\n * OAuth Callback Component\n *\n * Handles the redirect from OAuth providers after user authorization.\n * This component is loaded at /oauth/callback and processes the\n * authorization code to complete the OAuth flow.\n *\n * The component waits for authentication to complete before attempting\n * the code exchange, since the user's session needs to be restored first.\n */\n@Component({\n standalone: false,\n selector: 'mj-oauth-callback',\n templateUrl: './oauth-callback.component.html',\n styleUrls: ['./oauth-callback.component.css']\n})\nexport class OAuthCallbackComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n /** Loading state while processing OAuth callback */\n public IsLoading = true;\n\n /** Error state */\n public HasError = false;\n\n /** Error message to display */\n public ErrorMessage = '';\n\n /** Error code from OAuth provider or exchange */\n public ErrorCode = '';\n\n /** Whether the error is retryable */\n public IsRetryable = false;\n\n /** Status message shown during processing */\n public StatusMessage = 'Restoring session...';\n\n /** Timer for polling provider readiness */\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n\n /** Flag to prevent double processing */\n private isProcessing = false;\n\n constructor(\n private route: ActivatedRoute,\n private router: Router,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n async ngOnInit(): Promise<void> {\n // Wait for the GraphQL provider to be ready, then process the callback\n await this.waitForProviderAndProcess();\n }\n\n ngOnDestroy(): void {\n // Clean up the polling timer\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n }\n\n /**\n * Waits for the GraphQL provider to be initialized (indicating auth is complete)\n * then processes the OAuth callback.\n */\n private async waitForProviderAndProcess(): Promise<void> {\n const startTime = Date.now();\n\n // Check if provider is already ready\n if (this.isProviderReady()) {\n await this.safeProcessCallback();\n return;\n }\n\n // Poll for provider readiness\n this.StatusMessage = 'Waiting for authentication...';\n this.cdr.detectChanges();\n\n return new Promise<void>((resolve) => {\n this.pollTimer = setInterval(async () => {\n const elapsed = Date.now() - startTime;\n\n if (this.isProviderReady()) {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n await this.safeProcessCallback();\n resolve();\n return;\n }\n\n if (elapsed >= MAX_WAIT_TIME_MS) {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n this.showError(\n 'timeout',\n 'Timed out waiting for authentication. Please try logging in again.',\n true\n );\n resolve();\n return;\n }\n\n // Update status message with progress\n const secondsRemaining = Math.ceil((MAX_WAIT_TIME_MS - elapsed) / 1000);\n this.StatusMessage = `Waiting for authentication... (${secondsRemaining}s)`;\n this.cdr.detectChanges();\n }, POLL_INTERVAL_MS);\n });\n }\n\n /**\n * Checks if the GraphQL provider is initialized and has a valid token\n */\n private isProviderReady(): boolean {\n try {\n const provider = this.ProviderToUse as GraphQLDataProvider;\n if (!provider) {\n return false;\n }\n const configData = provider.ConfigData;\n if (!configData || !configData.Token || !configData.URL) {\n return false;\n }\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Safely processes the callback, preventing double execution\n */\n private async safeProcessCallback(): Promise<void> {\n if (this.isProcessing) {\n return;\n }\n this.isProcessing = true;\n\n try {\n await this.processOAuthCallback();\n } catch (error) {\n console.error('[OAuth Callback] Error in processOAuthCallback:', error);\n this.showError('component_error', error instanceof Error ? error.message : String(error), true);\n }\n }\n\n /**\n * Process the OAuth callback by extracting params and exchanging the code\n */\n private async processOAuthCallback(): Promise<void> {\n const params = this.route.snapshot.queryParams;\n\n // Check for error from OAuth provider\n if (params['error']) {\n this.showError(\n params['error'] as string,\n params['error_description'] as string || 'Authorization was denied or failed'\n );\n return;\n }\n\n const code = params['code'] as string;\n const state = params['state'] as string;\n\n // Validate required parameters\n if (!code) {\n this.showError('missing_code', 'No authorization code received from the OAuth provider');\n return;\n }\n\n if (!state) {\n this.showError('missing_state', 'No state parameter received from the OAuth provider');\n return;\n }\n\n // Exchange the code for tokens\n this.StatusMessage = 'Exchanging authorization code...';\n this.cdr.detectChanges();\n\n try {\n const result = await this.exchangeCode(code, state);\n\n if (result.success) {\n this.handleSuccess(result.connectionId);\n } else {\n this.showError(\n result.errorCode || 'exchange_failed',\n result.errorMessage || 'Failed to complete authorization',\n result.isRetryable\n );\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'An unexpected error occurred';\n this.showError('network_error', message, true);\n }\n }\n\n /** Pre-#5674 exchange URL for hosts that have not configured MJAPI_URI: derived from the GraphQL URL. */\n private legacyExchangeUrl(graphqlUrl: string): string {\n if (graphqlUrl.includes('/graphql')) {\n return graphqlUrl.replace('/graphql', '/oauth/exchange');\n }\n return graphqlUrl.replace(/\\/$/, '') + '/oauth/exchange';\n }\n\n /**\n * Call the backend to exchange the authorization code for tokens\n */\n private async exchangeCode(code: string, state: string): Promise<OAuthExchangeResponse> {\n // Get the GraphQL provider - we know it's ready at this point\n const gqlProvider = this.ProviderToUse as GraphQLDataProvider;\n const configData = gqlProvider.ConfigData;\n\n // The exchange endpoint hangs off the configured MJAPI URL (MJAPI_URI, MJ #5674). Without one,\n // keep the pre-#5674 derivation from the GraphQL URL.\n const apiUrl = configData.MJAPIURL ? `${configData.MJAPIURL}/oauth/exchange` : this.legacyExchangeUrl(configData.URL);\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${configData.Token}`\n },\n body: JSON.stringify({ code, state })\n });\n\n // Parse response regardless of status code\n const data = await response.json();\n return data as OAuthExchangeResponse;\n } catch (fetchError) {\n return {\n success: false,\n errorCode: 'fetch_error',\n errorMessage: fetchError instanceof Error ? fetchError.message : 'Network error during token exchange'\n };\n }\n }\n\n /**\n * Handle successful OAuth completion\n */\n private handleSuccess(connectionId?: string): void {\n this.IsLoading = false;\n this.StatusMessage = 'Authorization successful! Redirecting...';\n this.cdr.detectChanges();\n\n // Get the stored return URL - try both localStorage and sessionStorage\n const storedUrl = localStorage.getItem('oauth_return_url');\n const storedPath = localStorage.getItem('oauth_return_path');\n const sessionUrl = sessionStorage.getItem('oauth_return_url');\n const sessionPath = sessionStorage.getItem('oauth_return_path');\n\n let returnUrl = storedUrl || sessionUrl || storedPath || sessionPath;\n\n // Clean up all possible storage locations\n this.clearStoredReturnUrls();\n\n // Default to MCP dashboard if no return URL found\n const defaultPath = '/app/admin/MCP';\n if (!returnUrl || returnUrl.trim() === '' || returnUrl === '/') {\n returnUrl = defaultPath;\n }\n\n // Build the final navigation path\n const finalPath = this.buildFinalPath(returnUrl, connectionId, defaultPath);\n\n // Use window.location for reliable navigation after OAuth\n setTimeout(() => {\n window.location.href = finalPath;\n }, 500);\n }\n\n /**\n * Builds the final navigation path with success query params\n */\n private buildFinalPath(returnUrl: string, connectionId: string | undefined, defaultPath: string): string {\n try {\n let finalPath: string;\n\n // If it's a full URL, extract just the path and search\n if (returnUrl.startsWith('http://') || returnUrl.startsWith('https://')) {\n const url = new URL(returnUrl);\n finalPath = url.pathname + url.search;\n } else {\n finalPath = returnUrl;\n }\n\n // Ensure we have a valid path (not empty or just \"/\")\n if (!finalPath || finalPath.trim() === '' || finalPath === '/') {\n finalPath = defaultPath;\n }\n\n // Add success query params\n const separator = finalPath.includes('?') ? '&' : '?';\n finalPath = `${finalPath}${separator}oauth=success`;\n if (connectionId) {\n finalPath += `&connectionId=${connectionId}`;\n }\n\n return finalPath;\n } catch (e) {\n console.error('[OAuth Callback] Error parsing return URL:', e);\n return `${defaultPath}?oauth=success${connectionId ? `&connectionId=${connectionId}` : ''}`;\n }\n }\n\n /**\n * Clears all stored return URLs from storage\n */\n private clearStoredReturnUrls(): void {\n localStorage.removeItem('oauth_return_url');\n localStorage.removeItem('oauth_return_path');\n sessionStorage.removeItem('oauth_return_url');\n sessionStorage.removeItem('oauth_return_path');\n }\n\n /**\n * Show error state\n */\n private showError(errorCode: string, message: string, isRetryable = false): void {\n this.IsLoading = false;\n this.HasError = true;\n this.ErrorCode = errorCode;\n this.ErrorMessage = message;\n this.IsRetryable = isRetryable;\n this.cdr.detectChanges();\n }\n\n /**\n * Handle retry button click\n */\n public OnRetry(): void {\n // Get the stored return URL and redirect there to start fresh\n const returnUrl = localStorage.getItem('oauth_return_url') || '/app/admin/MCP';\n this.clearStoredReturnUrls();\n this.router.navigateByUrl(returnUrl);\n }\n\n /** @deprecated Use {@link OnRetry}. */\n public onRetry(): void {\n return this.OnRetry();\n }\n\n /**\n * Handle close button click (return to MCP dashboard)\n */\n public OnClose(): void {\n this.clearStoredReturnUrls();\n this.router.navigate(['/app/admin/MCP']);\n }\n\n /** @deprecated Use {@link OnClose}. */\n public onClose(): void {\n return this.OnClose();\n }\n}\n","<div class=\"oauth-callback-container\">\n <div class=\"oauth-callback-card\">\n <!-- Loading State -->\n @if (IsLoading) {\n <div class=\"oauth-status loading\">\n <mj-loading text=\"{{ StatusMessage }}\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (HasError) {\n <div class=\"oauth-status error\">\n <div class=\"icon-container error-icon\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <h2>Authorization Failed</h2>\n @if (ErrorCode) {\n <div class=\"error-code\">{{ ErrorCode }}</div>\n }\n <p class=\"error-message\">{{ ErrorMessage }}</p>\n <div class=\"button-group\">\n @if (IsRetryable) {\n <button mjButton variant=\"secondary\" (click)=\"onRetry()\">\n <i class=\"fa-solid fa-rotate-right\"></i>\n Try Again\n </button>\n }\n <button mjButton [variant]=\"IsRetryable ? 'outline' : 'secondary'\" (click)=\"onClose()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Return to Dashboard\n </button>\n </div>\n </div>\n }\n\n <!-- Success State (brief - redirects quickly) -->\n @if (!IsLoading && !HasError) {\n <div class=\"oauth-status success\">\n <div class=\"icon-container success-icon\">\n <i class=\"fa-solid fa-circle-check\"></i>\n </div>\n <h2>Authorization Successful</h2>\n <p>{{ StatusMessage }}</p>\n </div>\n }\n </div>\n</div>\n"]}
@@ -0,0 +1,34 @@
1
+ import type { MJDashboardEntity } from '@memberjunction/core-entities';
2
+ /** The dashboard fields the palette matches on and shows. */
3
+ export interface DashboardMatchLike {
4
+ ID: string;
5
+ Name: string;
6
+ Description: string | null;
7
+ Category: string | null;
8
+ User: string;
9
+ }
10
+ /**
11
+ * True when the dashboard tab can render the dashboard: a Config dashboard, or a Code
12
+ * dashboard that names its driver class. 'Dynamic Code' dashboards have no renderer.
13
+ */
14
+ export declare function CanOpenInDashboardTab(dashboard: Pick<MJDashboardEntity, 'Type' | 'DriverClass'>): boolean;
15
+ /**
16
+ * Dashboards whose name, description or category contains the query, case-insensitively.
17
+ * An exact name ranks first, then a name that starts with the query, then a name that
18
+ * contains it, then a description or category hit. Ties keep the input order.
19
+ * Returns at most `max` dashboards.
20
+ */
21
+ export declare function MatchDashboards<T extends DashboardMatchLike>(dashboards: ReadonlyArray<T>, query: string, max: number): T[];
22
+ /** Dashboard matches split by what matched the query. */
23
+ export interface DashboardMatchSplit<T> {
24
+ /** Exact, prefix and contains name matches, best first. */
25
+ NameMatches: T[];
26
+ /** Dashboards whose description or category matches but whose name does not, in input order. */
27
+ DescriptionOrCategoryMatches: T[];
28
+ }
29
+ /**
30
+ * The dashboards of {@link MatchDashboards}, split into name matches and matches on the
31
+ * description or category only. The two lists share the `max` cap, and name matches fill it first.
32
+ */
33
+ export declare function SplitDashboardMatches<T extends DashboardMatchLike>(dashboards: ReadonlyArray<T>, query: string, max: number): DashboardMatchSplit<T>;
34
+ //# sourceMappingURL=omnibar-dashboard-matches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"omnibar-dashboard-matches.d.ts","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-dashboard-matches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,OAAO,CASzG;AAWD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,kBAAkB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,CAW3H;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB,CAAC,CAAC;IAClC,2DAA2D;IAC3D,WAAW,EAAE,CAAC,EAAE,CAAC;IACjB,gGAAgG;IAChG,4BAA4B,EAAE,CAAC,EAAE,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,kBAAkB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAQpJ"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * True when the dashboard tab can render the dashboard: a Config dashboard, or a Code
3
+ * dashboard that names its driver class. 'Dynamic Code' dashboards have no renderer.
4
+ */
5
+ export function CanOpenInDashboardTab(dashboard) {
6
+ switch (dashboard.Type) {
7
+ case 'Config':
8
+ return true;
9
+ case 'Code':
10
+ return !!dashboard.DriverClass;
11
+ default:
12
+ return false;
13
+ }
14
+ }
15
+ /** How well a dashboard matches the query. A higher rank lists first. */
16
+ const MatchRank = {
17
+ ExactName: 4,
18
+ NamePrefix: 3,
19
+ NameContains: 2,
20
+ DescriptionOrCategory: 1,
21
+ None: 0,
22
+ };
23
+ /**
24
+ * Dashboards whose name, description or category contains the query, case-insensitively.
25
+ * An exact name ranks first, then a name that starts with the query, then a name that
26
+ * contains it, then a description or category hit. Ties keep the input order.
27
+ * Returns at most `max` dashboards.
28
+ */
29
+ export function MatchDashboards(dashboards, query, max) {
30
+ const q = query.trim().toLowerCase();
31
+ if (!q) {
32
+ return [];
33
+ }
34
+ return dashboards
35
+ .map((d, i) => ({ d, rank: matchRank(d, q), i }))
36
+ .filter((x) => x.rank > MatchRank.None)
37
+ .sort((a, b) => b.rank - a.rank || a.i - b.i)
38
+ .slice(0, max)
39
+ .map((x) => x.d);
40
+ }
41
+ /**
42
+ * The dashboards of {@link MatchDashboards}, split into name matches and matches on the
43
+ * description or category only. The two lists share the `max` cap, and name matches fill it first.
44
+ */
45
+ export function SplitDashboardMatches(dashboards, query, max) {
46
+ const q = query.trim().toLowerCase();
47
+ const isNameMatch = (dashboard) => matchRank(dashboard, q) > MatchRank.DescriptionOrCategory;
48
+ const matches = MatchDashboards(dashboards, query, max);
49
+ return {
50
+ NameMatches: matches.filter(isNameMatch),
51
+ DescriptionOrCategoryMatches: matches.filter((dashboard) => !isNameMatch(dashboard)),
52
+ };
53
+ }
54
+ /** The rank of one dashboard for a trimmed, lower-case query. */
55
+ function matchRank(dashboard, q) {
56
+ const name = dashboard.Name.trim().toLowerCase();
57
+ if (name === q) {
58
+ return MatchRank.ExactName;
59
+ }
60
+ if (name.startsWith(q)) {
61
+ return MatchRank.NamePrefix;
62
+ }
63
+ if (name.includes(q)) {
64
+ return MatchRank.NameContains;
65
+ }
66
+ const description = (dashboard.Description || '').toLowerCase();
67
+ const category = (dashboard.Category || '').toLowerCase();
68
+ return description.includes(q) || category.includes(q) ? MatchRank.DescriptionOrCategory : MatchRank.None;
69
+ }
70
+ //# sourceMappingURL=omnibar-dashboard-matches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"omnibar-dashboard-matches.js","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-dashboard-matches.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MJDashboardEntity } from '@memberjunction/core-entities';\n\n/** The dashboard fields the palette matches on and shows. */\nexport interface DashboardMatchLike {\n ID: string;\n Name: string;\n Description: string | null;\n Category: string | null;\n User: string;\n}\n\n/**\n * True when the dashboard tab can render the dashboard: a Config dashboard, or a Code\n * dashboard that names its driver class. 'Dynamic Code' dashboards have no renderer.\n */\nexport function CanOpenInDashboardTab(dashboard: Pick<MJDashboardEntity, 'Type' | 'DriverClass'>): boolean {\n switch (dashboard.Type) {\n case 'Config':\n return true;\n case 'Code':\n return !!dashboard.DriverClass;\n default:\n return false;\n }\n}\n\n/** How well a dashboard matches the query. A higher rank lists first. */\nconst MatchRank = {\n ExactName: 4,\n NamePrefix: 3,\n NameContains: 2,\n DescriptionOrCategory: 1,\n None: 0,\n} as const;\n\n/**\n * Dashboards whose name, description or category contains the query, case-insensitively.\n * An exact name ranks first, then a name that starts with the query, then a name that\n * contains it, then a description or category hit. Ties keep the input order.\n * Returns at most `max` dashboards.\n */\nexport function MatchDashboards<T extends DashboardMatchLike>(dashboards: ReadonlyArray<T>, query: string, max: number): T[] {\n const q = query.trim().toLowerCase();\n if (!q) {\n return [];\n }\n return dashboards\n .map((d, i) => ({ d, rank: matchRank(d, q), i }))\n .filter((x) => x.rank > MatchRank.None)\n .sort((a, b) => b.rank - a.rank || a.i - b.i)\n .slice(0, max)\n .map((x) => x.d);\n}\n\n/** Dashboard matches split by what matched the query. */\nexport interface DashboardMatchSplit<T> {\n /** Exact, prefix and contains name matches, best first. */\n NameMatches: T[];\n /** Dashboards whose description or category matches but whose name does not, in input order. */\n DescriptionOrCategoryMatches: T[];\n}\n\n/**\n * The dashboards of {@link MatchDashboards}, split into name matches and matches on the\n * description or category only. The two lists share the `max` cap, and name matches fill it first.\n */\nexport function SplitDashboardMatches<T extends DashboardMatchLike>(dashboards: ReadonlyArray<T>, query: string, max: number): DashboardMatchSplit<T> {\n const q = query.trim().toLowerCase();\n const isNameMatch = (dashboard: T): boolean => matchRank(dashboard, q) > MatchRank.DescriptionOrCategory;\n const matches = MatchDashboards(dashboards, query, max);\n return {\n NameMatches: matches.filter(isNameMatch),\n DescriptionOrCategoryMatches: matches.filter((dashboard) => !isNameMatch(dashboard)),\n };\n}\n\n/** The rank of one dashboard for a trimmed, lower-case query. */\nfunction matchRank(dashboard: DashboardMatchLike, q: string): number {\n const name = dashboard.Name.trim().toLowerCase();\n if (name === q) {\n return MatchRank.ExactName;\n }\n if (name.startsWith(q)) {\n return MatchRank.NamePrefix;\n }\n if (name.includes(q)) {\n return MatchRank.NameContains;\n }\n const description = (dashboard.Description || '').toLowerCase();\n const category = (dashboard.Category || '').toLowerCase();\n return description.includes(q) || category.includes(q) ? MatchRank.DescriptionOrCategory : MatchRank.None;\n}\n"]}
@@ -5,7 +5,11 @@ import * as i0 from "@angular/core";
5
5
  /** One rendered result row: the suggestion + presentation extras. */
6
6
  interface OmnibarRow {
7
7
  Suggestion: MentionSuggestion;
8
- /** Set only on the FIRST row of each group — drives the section header. */
8
+ /**
9
+ * Section header before this row, set where the group changes: the group name, '' for the
10
+ * empty spacer before an ungrouped row that follows a group (the "see all" row), or null
11
+ * for no header. A group that comes back after another group gets its header again.
12
+ */
9
13
  GroupLabel: string | null;
10
14
  /** 0-100 relevance bar (search mode only). */
11
15
  ScorePercent: number | null;
@@ -47,6 +51,8 @@ export declare class OmnibarPaletteComponent implements OnDestroy {
47
51
  private defaultProvider;
48
52
  private byTrigger;
49
53
  private queryGeneration;
54
+ /** Trigger char of the provider that produced the current {@link Rows}. */
55
+ private renderedTriggerChar;
50
56
  private debounceHandle;
51
57
  /** Element focused before the palette opened — restored on close (a11y). */
52
58
  private previousFocus;
@@ -69,7 +75,20 @@ export declare class OmnibarPaletteComponent implements OnDestroy {
69
75
  /** RecentRows render after the hint bar; selection indexes continue into them. */
70
76
  get RecentBaseIndex(): number;
71
77
  private get activeProvider();
78
+ /**
79
+ * Rows that keyboard selection may target: only rendered rows. {@link RecentRows}
80
+ * render only in the empty-query state, so they are selectable only then.
81
+ */
72
82
  private get selectableRows();
83
+ /**
84
+ * Whether <kbd>Enter</kbd> on a palette with no rows may open the full Search Results
85
+ * workspace for the typed text. Drives both the key handler and the empty-state wording.
86
+ *
87
+ * Default mode always allows it, because full search is that mode's own action. A trigger
88
+ * mode allows it only after its fetch settles, because there full search is a different
89
+ * action from what the rows offer (switch app, open record).
90
+ */
91
+ get CanEscapeToFullSearch(): boolean;
73
92
  /**
74
93
  * ARIA combobox wiring: the input keeps DOM focus while this points at the
75
94
  * virtually-highlighted option row, so screen readers announce selection moves.
@@ -108,7 +127,13 @@ export declare class OmnibarPaletteComponent implements OnDestroy {
108
127
  IsScopeSelected(id: string): boolean;
109
128
  ToggleScope(id: string): void;
110
129
  ClearScopes(): void;
111
- /** Executes a suggestion: navigate per its payload, or re-seed for entity drill-in. */
130
+ /**
131
+ * Executes a suggestion: navigate per its payload, or re-seed for entity drill-in.
132
+ *
133
+ * Not blocked while a fetch is pending: every activation path targets a rendered row,
134
+ * because {@link selectableRows} offers only rendered rows and a mode change clears
135
+ * {@link Rows}.
136
+ */
112
137
  Execute(suggestion: MentionSuggestion): void;
113
138
  private openFullSearch;
114
139
  /** '@' selection: switch to the Chat app pre-addressed to the agent. */
@@ -1 +1 @@
1
- {"version":3,"file":"omnibar-palette.component.d.ts","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-palette.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"omnibar-palette.component.d.ts","sourceRoot":"","sources":["../../../src/lib/omnibar/omnibar-palette.component.ts"],"names":[],"mappings":"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"}