@burdenoff/microfe-channel 2026.510.112

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 (156) hide show
  1. package/README.md +147 -0
  2. package/dist/channel/ChannelRoot.d.ts +32 -0
  3. package/dist/channel/ChannelRoot.d.ts.map +1 -0
  4. package/dist/channel/ChannelRoot.js +81 -0
  5. package/dist/channel/ChannelRoot.js.map +1 -0
  6. package/dist/channel/ChannelRoutes.d.ts +10 -0
  7. package/dist/channel/ChannelRoutes.d.ts.map +1 -0
  8. package/dist/channel/ChannelRoutes.js +104 -0
  9. package/dist/channel/ChannelRoutes.js.map +1 -0
  10. package/dist/channel/components/AdapterCredentialsForm.d.ts +20 -0
  11. package/dist/channel/components/AdapterCredentialsForm.d.ts.map +1 -0
  12. package/dist/channel/components/AdapterCredentialsForm.js +230 -0
  13. package/dist/channel/components/AdapterCredentialsForm.js.map +1 -0
  14. package/dist/channel/components/FeatureNotEnabled.d.ts +10 -0
  15. package/dist/channel/components/FeatureNotEnabled.d.ts.map +1 -0
  16. package/dist/channel/components/FeatureNotEnabled.js +32 -0
  17. package/dist/channel/components/FeatureNotEnabled.js.map +1 -0
  18. package/dist/channel/components/PermissionGuard.d.ts +15 -0
  19. package/dist/channel/components/PermissionGuard.d.ts.map +1 -0
  20. package/dist/channel/components/PermissionGuard.js +23 -0
  21. package/dist/channel/components/PermissionGuard.js.map +1 -0
  22. package/dist/channel/config/adapterCredentials.d.ts +44 -0
  23. package/dist/channel/config/adapterCredentials.d.ts.map +1 -0
  24. package/dist/channel/config/adapterCredentials.js +946 -0
  25. package/dist/channel/config/adapterCredentials.js.map +1 -0
  26. package/dist/channel/constants/permissions.d.ts +32 -0
  27. package/dist/channel/constants/permissions.d.ts.map +1 -0
  28. package/dist/channel/constants/permissions.js +30 -0
  29. package/dist/channel/constants/permissions.js.map +1 -0
  30. package/dist/channel/graphql/global-client.d.ts +11 -0
  31. package/dist/channel/graphql/global-client.d.ts.map +1 -0
  32. package/dist/channel/graphql/global-client.js +56 -0
  33. package/dist/channel/graphql/global-client.js.map +1 -0
  34. package/dist/channel/hooks/useChannelOrgSettings.d.ts +22 -0
  35. package/dist/channel/hooks/useChannelOrgSettings.d.ts.map +1 -0
  36. package/dist/channel/hooks/useChannelOrgSettings.js +61 -0
  37. package/dist/channel/hooks/useChannelOrgSettings.js.map +1 -0
  38. package/dist/channel/hooks/useChannelSubscription.d.ts +36 -0
  39. package/dist/channel/hooks/useChannelSubscription.d.ts.map +1 -0
  40. package/dist/channel/hooks/useChannelSubscription.js +111 -0
  41. package/dist/channel/hooks/useChannelSubscription.js.map +1 -0
  42. package/dist/channel/hooks/useChannels.d.ts +214 -0
  43. package/dist/channel/hooks/useChannels.d.ts.map +1 -0
  44. package/dist/channel/hooks/useChannels.js +416 -0
  45. package/dist/channel/hooks/useChannels.js.map +1 -0
  46. package/dist/channel/index.d.ts +12 -0
  47. package/dist/channel/index.d.ts.map +1 -0
  48. package/dist/channel/index.js +2 -0
  49. package/dist/channel/modules/channels/hooks/useExport.d.ts +45 -0
  50. package/dist/channel/modules/channels/hooks/useExport.d.ts.map +1 -0
  51. package/dist/channel/modules/channels/hooks/useExport.js +195 -0
  52. package/dist/channel/modules/channels/hooks/useExport.js.map +1 -0
  53. package/dist/channel/modules/channels/i18n.d.ts +14 -0
  54. package/dist/channel/modules/channels/i18n.d.ts.map +1 -0
  55. package/dist/channel/modules/channels/i18n.js +110 -0
  56. package/dist/channel/modules/channels/i18n.js.map +1 -0
  57. package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts +14 -0
  58. package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts.map +1 -0
  59. package/dist/channel/modules/channels/pages/ChannelDashboardPage.js +680 -0
  60. package/dist/channel/modules/channels/pages/ChannelDashboardPage.js.map +1 -0
  61. package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts +7 -0
  62. package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts.map +1 -0
  63. package/dist/channel/modules/channels/pages/ChannelDetailsPage.js +949 -0
  64. package/dist/channel/modules/channels/pages/ChannelDetailsPage.js.map +1 -0
  65. package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts +7 -0
  66. package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts.map +1 -0
  67. package/dist/channel/modules/channels/pages/ChannelSettingsPage.js +404 -0
  68. package/dist/channel/modules/channels/pages/ChannelSettingsPage.js.map +1 -0
  69. package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts +7 -0
  70. package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts.map +1 -0
  71. package/dist/channel/modules/channels/pages/ChannelUsersPage.js +315 -0
  72. package/dist/channel/modules/channels/pages/ChannelUsersPage.js.map +1 -0
  73. package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts +7 -0
  74. package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts.map +1 -0
  75. package/dist/channel/modules/channels/pages/ChannelsListPage.js +604 -0
  76. package/dist/channel/modules/channels/pages/ChannelsListPage.js.map +1 -0
  77. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts +7 -0
  78. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts.map +1 -0
  79. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js +323 -0
  80. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js.map +1 -0
  81. package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts +7 -0
  82. package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts.map +1 -0
  83. package/dist/channel/modules/channels/pages/ConnectionsListPage.js +276 -0
  84. package/dist/channel/modules/channels/pages/ConnectionsListPage.js.map +1 -0
  85. package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts +12 -0
  86. package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts.map +1 -0
  87. package/dist/channel/modules/channels/pages/CreateChannelPage.js +456 -0
  88. package/dist/channel/modules/channels/pages/CreateChannelPage.js.map +1 -0
  89. package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts +11 -0
  90. package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts.map +1 -0
  91. package/dist/channel/modules/channels/pages/CreateConnectionPage.js +219 -0
  92. package/dist/channel/modules/channels/pages/CreateConnectionPage.js.map +1 -0
  93. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts +7 -0
  94. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts.map +1 -0
  95. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js +375 -0
  96. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js.map +1 -0
  97. package/dist/channel/modules/channels/pages/EditChannelPage.d.ts +8 -0
  98. package/dist/channel/modules/channels/pages/EditChannelPage.d.ts.map +1 -0
  99. package/dist/channel/modules/channels/pages/EditChannelPage.js +459 -0
  100. package/dist/channel/modules/channels/pages/EditChannelPage.js.map +1 -0
  101. package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts +10 -0
  102. package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts.map +1 -0
  103. package/dist/channel/modules/channels/pages/EditConnectionPage.js +199 -0
  104. package/dist/channel/modules/channels/pages/EditConnectionPage.js.map +1 -0
  105. package/dist/channel/modules/channels/pages/SendMessagePage.d.ts +8 -0
  106. package/dist/channel/modules/channels/pages/SendMessagePage.d.ts.map +1 -0
  107. package/dist/channel/modules/channels/pages/SendMessagePage.js +403 -0
  108. package/dist/channel/modules/channels/pages/SendMessagePage.js.map +1 -0
  109. package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts +7 -0
  110. package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts.map +1 -0
  111. package/dist/channel/modules/channels/pages/WebhookEventsPage.js +303 -0
  112. package/dist/channel/modules/channels/pages/WebhookEventsPage.js.map +1 -0
  113. package/dist/channel/modules/channels/pages/index.d.ts +18 -0
  114. package/dist/channel/modules/channels/pages/index.d.ts.map +1 -0
  115. package/dist/channel/modules/channels/pages/index.js +14 -0
  116. package/dist/channel/pages/ChannelLandingPage.d.ts +9 -0
  117. package/dist/channel/pages/ChannelLandingPage.d.ts.map +1 -0
  118. package/dist/channel/pages/ChannelLandingPage.js +72 -0
  119. package/dist/channel/pages/ChannelLandingPage.js.map +1 -0
  120. package/dist/channel/providers/ChannelProvider.d.ts +16 -0
  121. package/dist/channel/providers/ChannelProvider.d.ts.map +1 -0
  122. package/dist/channel/providers/ChannelProvider.js +35 -0
  123. package/dist/channel/providers/ChannelProvider.js.map +1 -0
  124. package/dist/channel/types/index.d.ts +89 -0
  125. package/dist/channel/types/index.d.ts.map +1 -0
  126. package/dist/channel/utils/shellBridge.d.ts +59 -0
  127. package/dist/channel/utils/shellBridge.d.ts.map +1 -0
  128. package/dist/channel/utils/shellBridge.js +36 -0
  129. package/dist/channel/utils/shellBridge.js.map +1 -0
  130. package/dist/dev/App.d.ts +6 -0
  131. package/dist/dev/App.d.ts.map +1 -0
  132. package/dist/dev/main.d.ts +2 -0
  133. package/dist/dev/main.d.ts.map +1 -0
  134. package/dist/generated/global-operations.d.ts +1547 -0
  135. package/dist/generated/global-operations.d.ts.map +1 -0
  136. package/dist/generated/global-operations.js +466 -0
  137. package/dist/generated/global-operations.js.map +1 -0
  138. package/dist/generated/global-types.d.ts +21289 -0
  139. package/dist/generated/global-types.d.ts.map +1 -0
  140. package/dist/generated/global-types.js +14 -0
  141. package/dist/generated/global-types.js.map +1 -0
  142. package/dist/generated/wspace-operations.d.ts +2 -0
  143. package/dist/generated/wspace-operations.d.ts.map +1 -0
  144. package/dist/generated/wspace-types.d.ts +55214 -0
  145. package/dist/generated/wspace-types.d.ts.map +1 -0
  146. package/dist/index.d.ts +5 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +4 -0
  149. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js +24 -0
  150. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -0
  151. package/dist/node_modules/@apollo/client/errors/utils.js +16 -0
  152. package/dist/node_modules/@apollo/client/errors/utils.js.map +1 -0
  153. package/dist/utils/nativeBridge.d.ts +3 -0
  154. package/dist/utils/nativeBridge.d.ts.map +1 -0
  155. package/dist/utils/nativeBridge.js +2 -0
  156. package/package.json +116 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendMessagePage.js","names":[],"sources":["../../../../../src/channel/modules/channels/pages/SendMessagePage.tsx"],"sourcesContent":["/**\n * Send Message Page\n *\n * UI for sending notifications/messages through channels.\n * Supports single and bulk delivery with recipient management.\n */\n\nimport { useState, useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ArrowLeft,\n Send,\n Loader2,\n AlertCircle,\n CheckCircle2,\n XCircle,\n Plus,\n X,\n Mail,\n Smartphone,\n Bell,\n MessageSquare,\n Hash,\n Users,\n MessageCircle,\n} from 'lucide-react';\nimport { useChannel as useChannelContext } from '../../../providers/ChannelProvider';\nimport { useChannels } from '../../../hooks/useChannels';\nimport { getGlobalChannelClient } from '../../../graphql/global-client';\nimport { useSendNotificationMutation } from '../../../../generated/global-operations';\nimport {\n ChannelPlatform,\n NotificationChannel,\n NotificationPriority,\n RecipientInput,\n TriggerNotificationInput,\n} from '../../../../generated/global-types';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface Recipient {\n id: string;\n address: string;\n name?: string;\n}\n\ninterface DeliveryResult {\n recipientId: string;\n success: boolean;\n messageId?: string;\n error?: string;\n}\n\n// ============================================================================\n// PLATFORM CONFIG\n// ============================================================================\n\nconst PLATFORM_ICONS: Record<string, typeof Mail> = {\n EMAIL: Mail,\n SMS: Smartphone,\n PUSH: Bell,\n WHATSAPP: MessageSquare,\n SLACK: Hash,\n TEAMS: Users,\n DISCORD: MessageCircle,\n INAPP: Bell,\n WEBCHAT: MessageSquare,\n WEBHOOK: Send,\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function SendMessagePage() {\n const navigate = useNavigate();\n const { channels } = useChannels();\n const { organizationId, authToken, apiGatewayUrl } = useChannelContext();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n // Get Apollo client for notification mutations\n const client = getGlobalChannelClient(apiGatewayUrl, authToken, organizationId);\n\n // Send notification via notification-svc (which calls channel-svc with service actor)\n const [sendNotification, { loading: isSending }] = useSendNotificationMutation({ client });\n\n // Channel selection\n const [selectedChannelId, setSelectedChannelId] = useState('');\n const [platform, setPlatform] = useState<ChannelPlatform>('EMAIL' as ChannelPlatform);\n\n // Recipients\n const [recipients, setRecipients] = useState<Recipient[]>([]);\n const [newAddress, setNewAddress] = useState('');\n const [newName, setNewName] = useState('');\n\n // Message content\n const [subject, setSubject] = useState('');\n const [body, setBody] = useState('');\n const [priority, setPriority] = useState<NotificationPriority>(NotificationPriority.Medium);\n\n // UI state\n const [results, setResults] = useState<DeliveryResult[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Filter channels by platform\n const filteredChannels = channels.filter((ch) => ch.platform === platform);\n\n // Add recipient\n const addRecipient = useCallback(() => {\n if (!newAddress.trim()) return;\n\n const recipient: Recipient = {\n id: `temp-${Date.now()}`,\n address: newAddress.trim(),\n name: newName.trim() || undefined,\n };\n\n setRecipients((prev) => [...prev, recipient]);\n setNewAddress('');\n setNewName('');\n }, [newAddress, newName]);\n\n // Remove recipient\n const removeRecipient = useCallback((id: string) => {\n setRecipients((prev) => prev.filter((r) => r.id !== id));\n }, []);\n\n // Clear results and reset\n const handleReset = useCallback(() => {\n setResults(null);\n setError(null);\n setSubject('');\n setBody('');\n setRecipients([]);\n }, []);\n\n // Send message via notification-svc (which handles service actor auth to channel-svc)\n const handleSend = async () => {\n if (!selectedChannelId) {\n setError(tr('channel.validation.selectChannel', 'Please select a channel'));\n return;\n }\n\n if (recipients.length === 0) {\n setError(tr('channel.validation.addRecipient', 'Please add at least one recipient'));\n return;\n }\n\n if (!body.trim()) {\n setError(tr('channel.validation.enterMessage', 'Please enter a message'));\n return;\n }\n\n setError(null);\n setResults(null);\n\n try {\n // Find the selected channel to get platform and connection info\n const selectedChannel = channels.find((ch) => ch.id === selectedChannelId);\n if (!selectedChannel) {\n setError(tr('channel.error.channelNotFound', 'Selected channel not found'));\n return;\n }\n\n // Map ChannelPlatform to NotificationChannel\n // Most platforms have the same name (EMAIL, SMS, PUSH, etc.)\n // ChannelPlatform uses 'INAPP' but there's no INAPP in ChannelPlatform enum\n // (only in PLATFORM_ICONS). We check using string literal.\n const platformStr = platform as string;\n const notificationChannel =\n platformStr === 'INAPP'\n ? NotificationChannel.InApp\n : (platform as unknown as NotificationChannel);\n\n // Send to each recipient in parallel via notification-svc\n const deliveryResults: DeliveryResult[] = await Promise.all(\n recipients.map(async (recipient): Promise<DeliveryResult> => {\n // Build recipient input for notification-svc\n const recipientInput: RecipientInput = {};\n switch (platform) {\n case 'EMAIL':\n recipientInput.email = recipient.address;\n break;\n case 'SMS':\n case 'WHATSAPP':\n recipientInput.phoneNumber = recipient.address;\n break;\n case 'PUSH':\n recipientInput.pushToken = recipient.address;\n break;\n case 'SLACK':\n recipientInput.slackUserId = recipient.address;\n break;\n case 'TEAMS':\n recipientInput.teamsUserId = recipient.address;\n break;\n case 'WEBHOOK':\n recipientInput.webhookUrl = recipient.address;\n break;\n default:\n recipientInput.email = recipient.address;\n }\n\n // Build TriggerNotificationInput - creates notification AND triggers delivery\n const triggerInput: TriggerNotificationInput = {\n channelId: selectedChannel.id,\n platform: notificationChannel,\n notification: {\n body: body,\n channel: notificationChannel,\n recipient: recipientInput,\n subject: platform === 'EMAIL' ? subject : undefined,\n priority: priority,\n },\n };\n\n try {\n const result = await sendNotification({ variables: { input: triggerInput } });\n\n if (result.data?.triggerNotification) {\n const notification = result.data.triggerNotification;\n // deliveryStatus is null at trigger time (async delivery hasn't completed yet).\n // Use triggerStatus + status to determine immediate send success.\n const failed =\n notification.status === 'FAILED' || notification.triggerStatus === 'FAILED';\n return {\n recipientId: recipient.id,\n success: !failed,\n messageId: notification.id,\n error: failed ? 'Delivery failed' : undefined,\n };\n }\n return {\n recipientId: recipient.id,\n success: false,\n error: result.error?.message || 'Failed to send notification',\n };\n } catch (err: unknown) {\n return {\n recipientId: recipient.id,\n success: false,\n error: err instanceof Error ? err.message : 'Failed to send notification',\n };\n }\n })\n );\n\n setResults(deliveryResults);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : 'Failed to send message';\n setError(message);\n }\n };\n\n const successCount = results?.filter((r) => r.success).length ?? 0;\n const failCount = results?.filter((r) => !r.success).length ?? 0;\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_DELIVERY_SEND}>\n <div className=\"min-h-screen bg-background\">\n {/* Header */}\n <div className=\"border-b bg-card\">\n <div className=\"container mx-auto px-6 py-4\">\n <div className=\"flex items-center gap-4\">\n <button\n onClick={() => navigate('/channels/list')}\n className=\"p-2 hover:bg-muted rounded-lg transition-colors\"\n >\n <ArrowLeft className=\"w-5 h-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold\">{tr('channel.sendMessage', 'Send Message')}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n 'channel.sendMessageSubtitle',\n 'Send notifications through configured channels'\n )}\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"container mx-auto px-6 py-8 max-w-3xl\">\n {results === null ? (\n <div className=\"space-y-6\">\n {/* Error Alert */}\n {error && (\n <div className=\"p-4 rounded-lg bg-destructive/10 border border-destructive/20 flex items-center gap-3\">\n <AlertCircle className=\"w-5 h-5 text-destructive shrink-0\" />\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n )}\n\n {/* Platform Selection */}\n <div className=\"space-y-3\">\n <label className=\"text-sm font-medium\">{tr('channel.platform', 'Platform')}</label>\n <div className=\"flex flex-wrap gap-2\">\n {(\n [\n 'EMAIL',\n 'SMS',\n 'PUSH',\n 'WHATSAPP',\n 'SLACK',\n 'TEAMS',\n 'WEBHOOK',\n ] as ChannelPlatform[]\n ).map((p) => {\n const Icon = PLATFORM_ICONS[p] || Send;\n const isSelected = platform === p;\n return (\n <button\n key={p}\n onClick={() => {\n setPlatform(p);\n setSelectedChannelId('');\n }}\n className={`px-4 py-2 rounded-lg border flex items-center gap-2 transition-all ${\n isSelected\n ? 'bg-primary text-primary-foreground border-primary'\n : 'bg-card hover:bg-muted border-border'\n }`}\n >\n <Icon className=\"w-4 h-4\" />\n <span className=\"text-sm\">{p}</span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Channel Selection */}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">{tr('channel.channel', 'Channel')} *</label>\n {filteredChannels.length === 0 ? (\n <div className=\"p-4 rounded-lg border border-dashed text-center\">\n <p className=\"text-sm text-muted-foreground\">\n No {platform} channels configured.\n <button\n onClick={() => navigate('./create')}\n className=\"text-primary hover:underline ml-1\"\n >\n Create one\n </button>\n </p>\n </div>\n ) : (\n <select\n value={selectedChannelId}\n onChange={(e) => setSelectedChannelId(e.target.value)}\n className=\"w-full px-4 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"\">{tr('channel.selectChannel', 'Select a channel...')}</option>\n {filteredChannels.map((ch) => (\n <option key={ch.id} value={ch.id}>\n {ch.name} ({ch.adapterType})\n </option>\n ))}\n </select>\n )}\n </div>\n\n {/* Recipients */}\n <div className=\"space-y-3\">\n <label className=\"text-sm font-medium\">\n {tr('channel.recipients', 'Recipients')}\n </label>\n\n {/* Add recipient form */}\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={newAddress}\n onChange={(e) => setNewAddress(e.target.value)}\n placeholder={platform === 'EMAIL' ? 'email@example.com' : '+1234567890'}\n className=\"flex-1 px-4 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder={tr('channel.nameOptional', 'Name (optional)')}\n className=\"w-48 px-4 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n <button\n onClick={addRecipient}\n disabled={!newAddress.trim()}\n className=\"px-4 py-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 flex items-center gap-2\"\n >\n <Plus className=\"w-4 h-4\" />\n {tr('channel.add', 'Add')}\n </button>\n </div>\n\n {/* recipient list */}\n {recipients.length > 0 ? (\n <div className=\"border rounded-lg divide-y\">\n {recipients.map((r) => (\n <div key={r.id} className=\"p-3 flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium\">{r.address}</p>\n {r.name && <p className=\"text-xs text-muted-foreground\">{r.name}</p>}\n </div>\n <button\n onClick={() => removeRecipient(r.id)}\n className=\"p-1 hover:bg-muted rounded transition-colors\"\n >\n <X className=\"w-4 h-4 text-muted-foreground\" />\n </button>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n {tr('channel.noRecipientsYet', 'No recipients added yet')}\n </p>\n )}\n </div>\n\n {/* Message Content */}\n <div className=\"space-y-3\">\n <label className=\"text-sm font-medium\">\n {tr('channel.messageContent', 'Message Content')} *\n </label>\n\n {platform === 'EMAIL' && (\n <input\n type=\"text\"\n value={subject}\n onChange={(e) => setSubject(e.target.value)}\n placeholder=\"Subject\"\n className=\"w-full px-4 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n )}\n\n <textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder=\"Enter your message...\"\n rows={6}\n className=\"w-full px-4 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary resize-none\"\n />\n </div>\n\n {/* Priority */}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">{tr('channel.priority', 'Priority')}</label>\n <div className=\"flex gap-2\">\n {(\n [\n NotificationPriority.Low,\n NotificationPriority.Medium,\n NotificationPriority.High,\n NotificationPriority.Urgent,\n ] as const\n ).map((p) => (\n <button\n key={p}\n onClick={() => setPriority(p)}\n className={`px-4 py-2 rounded-lg border text-sm transition-all ${\n priority === p\n ? 'bg-primary text-primary-foreground border-primary'\n : 'bg-card hover:bg-muted border-border'\n }`}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n\n {/* Send Button */}\n <div className=\"flex justify-end pt-4\">\n <button\n onClick={handleSend}\n disabled={\n isSending || !selectedChannelId || recipients.length === 0 || !body.trim()\n }\n className=\"px-6 py-3 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 flex items-center gap-2\"\n >\n {isSending ? (\n <>\n <Loader2 className=\"w-5 h-5 animate-spin\" />\n {tr('channel.sending', 'Sending...')}\n </>\n ) : (\n <>\n <Send className=\"w-5 h-5\" />\n {tr('channel.sendTo', 'Send to')} {recipients.length}{' '}\n {recipients.length !== 1\n ? tr('channel.recipients', 'recipients')\n : tr('channel.recipient', 'recipient')}\n </>\n )}\n </button>\n </div>\n </div>\n ) : (\n /* Results View */\n <div className=\"space-y-6\">\n {/* Summary */}\n <div className=\"p-4 rounded-lg border flex items-center justify-between\">\n <div className=\"flex items-center gap-4\">\n {failCount === 0 ? (\n <CheckCircle2 className=\"w-8 h-8 text-green-500\" />\n ) : (\n <AlertCircle className=\"w-8 h-8 text-yellow-500\" />\n )}\n <div>\n <h2 className=\"text-lg font-semibold\">\n {failCount === 0\n ? tr('channel.allMessagesSent', 'All messages sent!')\n : `${successCount} of ${recipients.length} sent`}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {successCount} {tr('channel.successful', 'successful')}, {failCount}{' '}\n {tr('channel.failed', 'failed')}\n </p>\n </div>\n </div>\n <button\n onClick={handleReset}\n className=\"px-4 py-2 rounded-lg border hover:bg-muted transition-colors\"\n >\n {tr('channel.sendAnother', 'Send Another')}\n </button>\n </div>\n\n {/* Results List */}\n <div className=\"border rounded-lg divide-y\">\n {results.map((result) => {\n const recipient = recipients.find((r) => r.id === result.recipientId);\n return (\n <div key={result.recipientId} className=\"p-4 flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium\">{recipient?.address}</p>\n {recipient?.name && (\n <p className=\"text-xs text-muted-foreground\">{recipient.name}</p>\n )}\n {result.messageId && (\n <p className=\"text-xs text-muted-foreground font-mono\">\n {result.messageId}\n </p>\n )}\n {result.error && <p className=\"text-xs text-destructive\">{result.error}</p>}\n </div>\n {result.success ? (\n <CheckCircle2 className=\"w-5 h-5 text-green-500\" />\n ) : (\n <XCircle className=\"w-5 h-5 text-destructive\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Webhook Events Page
3
+ *
4
+ * Displays webhook event history for a specific channel
5
+ */
6
+ export declare function WebhookEventsPage(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=WebhookEventsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebhookEventsPage.d.ts","sourceRoot":"","sources":["../../../../../src/channel/modules/channels/pages/WebhookEventsPage.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA4CH,wBAAgB,iBAAiB,4CAwQhC"}
@@ -0,0 +1,303 @@
1
+ import { useChannel as e } from "../../../providers/ChannelProvider.js";
2
+ import { emitShellEvent as t } from "../../../utils/shellBridge.js";
3
+ import { WEBHOOK_RECEIVED_SUBSCRIPTION as n, useChannelSubscription as r } from "../../../hooks/useChannelSubscription.js";
4
+ import { useChannel as i } from "../../../hooks/useChannels.js";
5
+ import { PermissionGuard as a } from "../../../components/PermissionGuard.js";
6
+ import { CHANNEL_PERMISSIONS as o } from "../../../constants/permissions.js";
7
+ import { useExportWebhookEvents as s } from "../hooks/useExport.js";
8
+ import { useCallback as c, useEffect as l, useState as u } from "react";
9
+ import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
+ import { AlertCircle as f, ArrowLeft as p, CheckCircle2 as m, Clock as h, Download as g, Eye as _, EyeOff as v, Loader2 as y, RefreshCw as b, XCircle as x } from "lucide-react";
11
+ import { useNavigate as S, useParams as C } from "react-router-dom";
12
+ import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
13
+ //#region src/channel/modules/channels/pages/WebhookEventsPage.tsx
14
+ var D = {
15
+ PENDING: {
16
+ label: "Pending",
17
+ color: "text-muted-foreground bg-muted",
18
+ icon: h
19
+ },
20
+ PROCESSING: {
21
+ label: "Processing",
22
+ color: "text-accent-primary bg-accent-primary/10",
23
+ icon: b
24
+ },
25
+ COMPLETED: {
26
+ label: "Completed",
27
+ color: "text-success-500 bg-success-100",
28
+ icon: m
29
+ },
30
+ FAILED: {
31
+ label: "Failed",
32
+ color: "text-error-500 bg-error-100",
33
+ icon: x
34
+ },
35
+ IGNORED: {
36
+ label: "Ignored",
37
+ color: "text-warning-500 bg-warning-100",
38
+ icon: v
39
+ }
40
+ };
41
+ function O() {
42
+ let { channelId: m } = C(), h = S(), { t: x } = d(), O = (e, t) => {
43
+ let n = x(e);
44
+ return n === e ? t : n;
45
+ }, { organizationId: k } = e(), { triggerExport: A, isExporting: j, exportError: M } = s(k ?? void 0, m), [N, P] = u(!0), [F, I] = u([]), [L, R] = u(null), [z, B] = u(25), { channel: V, isLoading: H, error: U, fetchWebhookEvents: W } = i(m), G = c(async () => {
46
+ if (m) {
47
+ P(!0);
48
+ try {
49
+ I(await W(z));
50
+ } finally {
51
+ P(!1);
52
+ }
53
+ }
54
+ }, [
55
+ m,
56
+ W,
57
+ z
58
+ ]);
59
+ l(() => {
60
+ Promise.resolve().then(() => G());
61
+ }, [G]), r({
62
+ query: n,
63
+ variables: { channelId: m },
64
+ operationName: "WebhookReceived",
65
+ enabled: !!m,
66
+ onData: () => {
67
+ t("webhook.received", { channelId: m }), G();
68
+ },
69
+ pollFn: G,
70
+ pollIntervalMs: 6e4
71
+ });
72
+ let K = (e) => D[e] || D.PENDING;
73
+ return H || N ? /* @__PURE__ */ T("div", {
74
+ className: "flex items-center justify-center min-h-screen",
75
+ children: /* @__PURE__ */ T(y, {
76
+ size: 32,
77
+ className: "animate-spin text-accent-primary"
78
+ })
79
+ }) : U || !V ? /* @__PURE__ */ T("div", {
80
+ className: "p-6",
81
+ children: /* @__PURE__ */ E("div", {
82
+ className: "flex items-center gap-3 p-4 bg-error-100 border border-error-500 rounded-lg",
83
+ children: [
84
+ /* @__PURE__ */ T(f, {
85
+ size: 20,
86
+ className: "text-error-500"
87
+ }),
88
+ /* @__PURE__ */ T("div", { children: /* @__PURE__ */ T("p", {
89
+ className: "text-sm font-medium text-error-700",
90
+ children: U || "Channel not found"
91
+ }) }),
92
+ /* @__PURE__ */ T("button", {
93
+ onClick: () => h(`/channels/${m}`),
94
+ className: "ml-auto px-3 py-1 text-sm text-error-700 hover:bg-error-200 rounded transition-colors",
95
+ children: "Go Back"
96
+ })
97
+ ]
98
+ })
99
+ }) : /* @__PURE__ */ T(a, {
100
+ permission: o.CHANNEL_WEBHOOK_READ,
101
+ children: /* @__PURE__ */ E("div", {
102
+ className: "space-y-6 p-3 sm:p-6",
103
+ children: [
104
+ /* @__PURE__ */ E("div", {
105
+ className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
106
+ children: [/* @__PURE__ */ E("div", {
107
+ className: "flex items-center gap-3",
108
+ children: [/* @__PURE__ */ T("button", {
109
+ onClick: () => h(`/channels/${m}`),
110
+ className: "p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors",
111
+ children: /* @__PURE__ */ T(p, { size: 20 })
112
+ }), /* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("h1", {
113
+ className: "text-xl sm:text-2xl font-bold text-foreground",
114
+ children: O("channel.webhookEvents", "Webhook Events")
115
+ }), /* @__PURE__ */ E("p", {
116
+ className: "text-sm text-muted-foreground mt-1",
117
+ children: [V.name, " - Event history"]
118
+ })] })]
119
+ }), /* @__PURE__ */ E("div", {
120
+ className: "flex items-center gap-3",
121
+ children: [
122
+ /* @__PURE__ */ E("select", {
123
+ value: z,
124
+ onChange: (e) => B(Number(e.target.value)),
125
+ className: "px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground",
126
+ children: [
127
+ /* @__PURE__ */ T("option", {
128
+ value: 10,
129
+ children: "10 results"
130
+ }),
131
+ /* @__PURE__ */ T("option", {
132
+ value: 25,
133
+ children: "25 results"
134
+ }),
135
+ /* @__PURE__ */ T("option", {
136
+ value: 50,
137
+ children: "50 results"
138
+ }),
139
+ /* @__PURE__ */ T("option", {
140
+ value: 100,
141
+ children: "100 results"
142
+ })
143
+ ]
144
+ }),
145
+ /* @__PURE__ */ E("button", {
146
+ onClick: G,
147
+ disabled: N,
148
+ className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors disabled:opacity-50",
149
+ children: [/* @__PURE__ */ T(b, {
150
+ size: 16,
151
+ className: N ? "animate-spin" : ""
152
+ }), O("channel.refresh", "Refresh")]
153
+ }),
154
+ /* @__PURE__ */ T(a, {
155
+ permission: o.CHANNEL_ADMIN,
156
+ children: /* @__PURE__ */ E("button", {
157
+ onClick: () => void A(),
158
+ disabled: j,
159
+ className: "flex items-center gap-2 px-4 py-2 text-sm font-medium text-fg border border-border hover:bg-bg-elevated rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
160
+ title: O("channel.exportCSV", "Export to CSV"),
161
+ children: [j ? /* @__PURE__ */ T(y, {
162
+ size: 16,
163
+ className: "animate-spin"
164
+ }) : /* @__PURE__ */ T(g, { size: 16 }), O("channel.export", "Export")]
165
+ })
166
+ })
167
+ ]
168
+ })]
169
+ }),
170
+ M && /* @__PURE__ */ E("div", {
171
+ className: "p-4 bg-error-100 border border-error-500 rounded-lg flex items-center gap-3",
172
+ children: [/* @__PURE__ */ T(f, {
173
+ size: 20,
174
+ className: "text-error-500"
175
+ }), /* @__PURE__ */ T("p", {
176
+ className: "text-sm text-error-700 flex-1",
177
+ children: M
178
+ })]
179
+ }),
180
+ /* @__PURE__ */ T("div", {
181
+ className: "p-4 bg-surface border border-border rounded-lg",
182
+ children: /* @__PURE__ */ T("p", {
183
+ className: "text-sm text-muted-foreground",
184
+ children: "Webhook events show all incoming webhooks received by this channel. Data is retained for 7 days."
185
+ })
186
+ }),
187
+ /* @__PURE__ */ T("div", {
188
+ className: "bg-surface border border-border rounded-lg overflow-hidden",
189
+ children: /* @__PURE__ */ T("div", {
190
+ className: "overflow-x-auto min-w-full",
191
+ children: /* @__PURE__ */ E("table", {
192
+ className: "w-full min-w-[600px]",
193
+ children: [/* @__PURE__ */ T("thead", {
194
+ className: "bg-muted/50 border-b border-border",
195
+ children: /* @__PURE__ */ E("tr", { children: [
196
+ /* @__PURE__ */ T("th", {
197
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
198
+ children: O("channel.status", "Status")
199
+ }),
200
+ /* @__PURE__ */ T("th", {
201
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
202
+ children: O("channel.eventType", "Event Type")
203
+ }),
204
+ /* @__PURE__ */ T("th", {
205
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
206
+ children: O("channel.duplicate", "Duplicate")
207
+ }),
208
+ /* @__PURE__ */ T("th", {
209
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
210
+ children: O("channel.processedAt", "Processed At")
211
+ }),
212
+ /* @__PURE__ */ T("th", {
213
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
214
+ children: O("channel.error", "Error")
215
+ }),
216
+ /* @__PURE__ */ T("th", {
217
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
218
+ children: O("channel.actions", "Actions")
219
+ })
220
+ ] })
221
+ }), /* @__PURE__ */ T("tbody", {
222
+ className: "divide-y divide-border",
223
+ children: F.length === 0 ? /* @__PURE__ */ T("tr", { children: /* @__PURE__ */ T("td", {
224
+ colSpan: 6,
225
+ className: "px-4 py-8 text-center text-muted-foreground",
226
+ children: O("channel.noWebhookEventsFound", "No webhook events found")
227
+ }) }) : F.map((e) => {
228
+ let t = K(e.status), n = t.icon, r = L === e.id;
229
+ return /* @__PURE__ */ E(w, { children: [/* @__PURE__ */ E("tr", {
230
+ className: "hover:bg-muted/30 transition-colors",
231
+ children: [
232
+ /* @__PURE__ */ T("td", {
233
+ className: "px-4 py-3",
234
+ children: /* @__PURE__ */ E("div", {
235
+ className: "flex items-center gap-2",
236
+ children: [/* @__PURE__ */ T(n, {
237
+ size: 14,
238
+ className: t.color.split(" ")[0]
239
+ }), /* @__PURE__ */ T("span", {
240
+ className: `text-sm font-medium ${t.color}`,
241
+ children: t.label
242
+ })]
243
+ })
244
+ }),
245
+ /* @__PURE__ */ T("td", {
246
+ className: "px-4 py-3 text-sm font-mono text-foreground",
247
+ children: e.eventType
248
+ }),
249
+ /* @__PURE__ */ T("td", {
250
+ className: "px-4 py-3",
251
+ children: e.isDuplicate ? /* @__PURE__ */ T("span", {
252
+ className: "text-xs text-warning-500 bg-warning-100 px-2 py-1 rounded",
253
+ children: "Duplicate"
254
+ }) : /* @__PURE__ */ T("span", {
255
+ className: "text-xs text-muted-foreground",
256
+ children: "No"
257
+ })
258
+ }),
259
+ /* @__PURE__ */ T("td", {
260
+ className: "px-4 py-3 text-sm text-muted-foreground",
261
+ children: e.processedAt ? new Date(e.processedAt).toLocaleString() : "-"
262
+ }),
263
+ /* @__PURE__ */ T("td", {
264
+ className: "px-4 py-3 text-sm text-error-500 max-w-xs truncate",
265
+ children: e.errorMessage || "-"
266
+ }),
267
+ /* @__PURE__ */ T("td", {
268
+ className: "px-4 py-3",
269
+ children: /* @__PURE__ */ T("button", {
270
+ onClick: () => R(r ? null : e.id),
271
+ className: "p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors",
272
+ title: r ? O("channel.hidePayload", "Hide payload") : O("channel.viewPayload", "View payload"),
273
+ children: T(r ? v : _, { size: 16 })
274
+ })
275
+ })
276
+ ]
277
+ }, e.id), r && /* @__PURE__ */ T("tr", { children: /* @__PURE__ */ T("td", {
278
+ colSpan: 6,
279
+ className: "px-4 py-3 bg-muted/30",
280
+ children: /* @__PURE__ */ E("div", {
281
+ className: "text-xs",
282
+ children: [/* @__PURE__ */ E("p", {
283
+ className: "text-muted-foreground mb-1",
284
+ children: [O("channel.payload", "Payload"), ":"]
285
+ }), /* @__PURE__ */ T("pre", {
286
+ className: "bg-surface p-2 rounded border border-border overflow-auto",
287
+ children: JSON.stringify(e.payload, null, 2)
288
+ })]
289
+ })
290
+ }) }, `${e.id}-payload`)] });
291
+ })
292
+ })]
293
+ })
294
+ })
295
+ })
296
+ ]
297
+ })
298
+ });
299
+ }
300
+ //#endregion
301
+ export { O as WebhookEventsPage };
302
+
303
+ //# sourceMappingURL=WebhookEventsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebhookEventsPage.js","names":[],"sources":["../../../../../src/channel/modules/channels/pages/WebhookEventsPage.tsx"],"sourcesContent":["/**\n * Webhook Events Page\n *\n * Displays webhook event history for a specific channel\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ArrowLeft,\n Loader2,\n AlertCircle,\n CheckCircle2,\n XCircle,\n Clock,\n RefreshCw,\n Eye,\n EyeOff,\n Download,\n} from 'lucide-react';\nimport { useChannel, type WebhookEvent as WebhookEventType } from '../../../hooks/useChannels';\nimport type { WebhookProcessingStatus } from '../../../hooks/useChannels';\nimport { useChannel as useChannelContext } from '../../../providers/ChannelProvider';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\nimport { emitShellEvent } from '../../../utils/shellBridge';\nimport {\n WEBHOOK_RECEIVED_SUBSCRIPTION,\n useChannelSubscription,\n} from '../../../hooks/useChannelSubscription';\nimport { useExportWebhookEvents } from '../hooks/useExport';\n\nconst STATUS_CONFIG: Record<\n WebhookProcessingStatus,\n { label: string; color: string; icon: typeof CheckCircle2 }\n> = {\n PENDING: { label: 'Pending', color: 'text-muted-foreground bg-muted', icon: Clock },\n PROCESSING: {\n label: 'Processing',\n color: 'text-accent-primary bg-accent-primary/10',\n icon: RefreshCw,\n },\n COMPLETED: { label: 'Completed', color: 'text-success-500 bg-success-100', icon: CheckCircle2 },\n FAILED: { label: 'Failed', color: 'text-error-500 bg-error-100', icon: XCircle },\n IGNORED: { label: 'Ignored', color: 'text-warning-500 bg-warning-100', icon: EyeOff },\n};\n\nexport function WebhookEventsPage() {\n const { channelId } = useParams<{ channelId: string }>();\n const navigate = useNavigate();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const { organizationId } = useChannelContext();\n const {\n triggerExport: exportWebhooks,\n isExporting: isExportingWebhooks,\n exportError: exportWebhooksError,\n } = useExportWebhookEvents(organizationId ?? undefined, channelId);\n const [isLoadingEvents, setIsLoadingEvents] = useState(true);\n const [events, setEvents] = useState<WebhookEventType[]>([]);\n const [expandedEvent, setExpandedEvent] = useState<string | null>(null);\n const [limit, setLimit] = useState(25);\n\n const { channel, isLoading, error, fetchWebhookEvents } = useChannel(channelId);\n\n const loadEvents = useCallback(async () => {\n if (!channelId) return;\n setIsLoadingEvents(true);\n try {\n const data = await fetchWebhookEvents(limit);\n setEvents(data);\n } finally {\n setIsLoadingEvents(false);\n }\n }, [channelId, fetchWebhookEvents, limit]);\n\n useEffect(() => {\n void Promise.resolve().then(() => loadEvents());\n }, [loadEvents]);\n\n // Real-time webhook stream. Subscribes when the gateway exposes\n // `webhookReceived`; otherwise polls every 60s as a graceful fallback.\n // Conservative fallback keeps gateway/svc cost low when subs are\n // unavailable; live updates flow through the subscription path.\n useChannelSubscription({\n query: WEBHOOK_RECEIVED_SUBSCRIPTION,\n variables: { channelId },\n operationName: 'WebhookReceived',\n enabled: Boolean(channelId),\n onData: () => {\n emitShellEvent('webhook.received', { channelId });\n void loadEvents();\n },\n pollFn: loadEvents,\n pollIntervalMs: 60_000,\n });\n\n const getStatusConfig = (status: WebhookProcessingStatus) => {\n return STATUS_CONFIG[status] || STATUS_CONFIG.PENDING;\n };\n\n // Loading state\n if (isLoading || isLoadingEvents) {\n return (\n <div className=\"flex items-center justify-center min-h-screen\">\n <Loader2 size={32} className=\"animate-spin text-accent-primary\" />\n </div>\n );\n }\n\n // Error state\n if (error || !channel) {\n return (\n <div className=\"p-6\">\n <div className=\"flex items-center gap-3 p-4 bg-error-100 border border-error-500 rounded-lg\">\n <AlertCircle size={20} className=\"text-error-500\" />\n <div>\n <p className=\"text-sm font-medium text-error-700\">{error || 'Channel not found'}</p>\n </div>\n <button\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"ml-auto px-3 py-1 text-sm text-error-700 hover:bg-error-200 rounded transition-colors\"\n >\n Go Back\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_WEBHOOK_READ}>\n <div className=\"space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors\"\n >\n <ArrowLeft size={20} />\n </button>\n <div>\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">\n {tr('channel.webhookEvents', 'Webhook Events')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-1\">{channel.name} - Event history</p>\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <select\n value={limit}\n onChange={(e) => setLimit(Number(e.target.value))}\n className=\"px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground\"\n >\n <option value={10}>10 results</option>\n <option value={25}>25 results</option>\n <option value={50}>50 results</option>\n <option value={100}>100 results</option>\n </select>\n <button\n onClick={loadEvents}\n disabled={isLoadingEvents}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors disabled:opacity-50\"\n >\n <RefreshCw size={16} className={isLoadingEvents ? 'animate-spin' : ''} />\n {tr('channel.refresh', 'Refresh')}\n </button>\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_ADMIN}>\n <button\n onClick={() => void exportWebhooks()}\n disabled={isExportingWebhooks}\n className=\"flex items-center gap-2 px-4 py-2 text-sm font-medium text-fg border border-border hover:bg-bg-elevated rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tr('channel.exportCSV', 'Export to CSV')}\n >\n {isExportingWebhooks ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <Download size={16} />\n )}\n {tr('channel.export', 'Export')}\n </button>\n </PermissionGuard>\n </div>\n </div>\n\n {/* Export Error Banner */}\n {exportWebhooksError && (\n <div className=\"p-4 bg-error-100 border border-error-500 rounded-lg flex items-center gap-3\">\n <AlertCircle size={20} className=\"text-error-500\" />\n <p className=\"text-sm text-error-700 flex-1\">{exportWebhooksError}</p>\n </div>\n )}\n\n {/* Info Banner */}\n <div className=\"p-4 bg-surface border border-border rounded-lg\">\n <p className=\"text-sm text-muted-foreground\">\n Webhook events show all incoming webhooks received by this channel. Data is retained for\n 7 days.\n </p>\n </div>\n\n {/* Events List */}\n <div className=\"bg-surface border border-border rounded-lg overflow-hidden\">\n <div className=\"overflow-x-auto min-w-full\">\n <table className=\"w-full min-w-[600px]\">\n <thead className=\"bg-muted/50 border-b border-border\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.status', 'Status')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.eventType', 'Event Type')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.duplicate', 'Duplicate')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.processedAt', 'Processed At')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.error', 'Error')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\">\n {tr('channel.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {events.length === 0 ? (\n <tr>\n <td colSpan={6} className=\"px-4 py-8 text-center text-muted-foreground\">\n {tr('channel.noWebhookEventsFound', 'No webhook events found')}\n </td>\n </tr>\n ) : (\n events.map((event) => {\n const statusConfig = getStatusConfig(event.status as WebhookProcessingStatus);\n const StatusIcon = statusConfig.icon;\n const isExpanded = expandedEvent === event.id;\n return (\n <>\n <tr key={event.id} className=\"hover:bg-muted/30 transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2\">\n <StatusIcon size={14} className={statusConfig.color.split(' ')[0]} />\n <span className={`text-sm font-medium ${statusConfig.color}`}>\n {statusConfig.label}\n </span>\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm font-mono text-foreground\">\n {event.eventType}\n </td>\n <td className=\"px-4 py-3\">\n {event.isDuplicate ? (\n <span className=\"text-xs text-warning-500 bg-warning-100 px-2 py-1 rounded\">\n Duplicate\n </span>\n ) : (\n <span className=\"text-xs text-muted-foreground\">No</span>\n )}\n </td>\n <td className=\"px-4 py-3 text-sm text-muted-foreground\">\n {event.processedAt ? new Date(event.processedAt).toLocaleString() : '-'}\n </td>\n <td className=\"px-4 py-3 text-sm text-error-500 max-w-xs truncate\">\n {event.errorMessage || '-'}\n </td>\n <td className=\"px-4 py-3\">\n <button\n onClick={() => setExpandedEvent(isExpanded ? null : event.id)}\n className=\"p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors\"\n title={\n isExpanded\n ? tr('channel.hidePayload', 'Hide payload')\n : tr('channel.viewPayload', 'View payload')\n }\n >\n {isExpanded ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </td>\n </tr>\n {isExpanded && (\n <tr key={`${event.id}-payload`}>\n <td colSpan={6} className=\"px-4 py-3 bg-muted/30\">\n <div className=\"text-xs\">\n <p className=\"text-muted-foreground mb-1\">\n {tr('channel.payload', 'Payload')}:\n </p>\n <pre className=\"bg-surface p-2 rounded border border-border overflow-auto\">\n {JSON.stringify(event.payload, null, 2)}\n </pre>\n </div>\n </td>\n </tr>\n )}\n </>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Channel Pages
3
+ */
4
+ export { ChannelDashboardPage } from './ChannelDashboardPage';
5
+ export { ChannelsListPage } from './ChannelsListPage';
6
+ export { ChannelDetailsPage } from './ChannelDetailsPage';
7
+ export { CreateChannelPage } from './CreateChannelPage';
8
+ export { EditChannelPage } from './EditChannelPage';
9
+ export { SendMessagePage } from './SendMessagePage';
10
+ export { ConnectionsListPage } from './ConnectionsListPage';
11
+ export { ConnectionDetailsPage } from './ConnectionDetailsPage';
12
+ export { CreateConnectionPage } from './CreateConnectionPage';
13
+ export { EditConnectionPage } from './EditConnectionPage';
14
+ export { ChannelSettingsPage } from './ChannelSettingsPage';
15
+ export { DeliveryHistoryPage } from './DeliveryHistoryPage';
16
+ export { WebhookEventsPage } from './WebhookEventsPage';
17
+ export { ChannelUsersPage } from './ChannelUsersPage';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/channel/modules/channels/pages/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import "./ChannelDashboardPage.js";
2
+ import "./ChannelsListPage.js";
3
+ import "./ChannelDetailsPage.js";
4
+ import "./CreateChannelPage.js";
5
+ import "./EditChannelPage.js";
6
+ import "./SendMessagePage.js";
7
+ import "./ConnectionsListPage.js";
8
+ import "./ConnectionDetailsPage.js";
9
+ import "./CreateConnectionPage.js";
10
+ import "./EditConnectionPage.js";
11
+ import "./ChannelSettingsPage.js";
12
+ import "./DeliveryHistoryPage.js";
13
+ import "./WebhookEventsPage.js";
14
+ import "./ChannelUsersPage.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tabbed landing page for the Channel microfrontend.
3
+ *
4
+ * The first tab ("dashboard") uses a clean URL with no `tab` query param.
5
+ * Detail routes (e.g. /:channelId, /:channelId/edit) remain registered in
6
+ * ChannelRoutes so existing deep links continue to work.
7
+ */
8
+ export declare function ChannelLandingPage(): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=ChannelLandingPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelLandingPage.d.ts","sourceRoot":"","sources":["../../../src/channel/pages/ChannelLandingPage.tsx"],"names":[],"mappings":"AAeA;;;;;;GAMG;AACH,wBAAgB,kBAAkB,4CAuDjC"}
@@ -0,0 +1,72 @@
1
+ import { PermissionGuard as e } from "../components/PermissionGuard.js";
2
+ import { CHANNEL_PERMISSIONS as t } from "../constants/permissions.js";
3
+ import { ChannelDashboardPage as n } from "../modules/channels/pages/ChannelDashboardPage.js";
4
+ import { ChannelsListPage as r } from "../modules/channels/pages/ChannelsListPage.js";
5
+ import { SendMessagePage as i } from "../modules/channels/pages/SendMessagePage.js";
6
+ import { ConnectionsListPage as a } from "../modules/channels/pages/ConnectionsListPage.js";
7
+ import { ChannelSettingsPage as o } from "../modules/channels/pages/ChannelSettingsPage.js";
8
+ import "../modules/channels/pages/index.js";
9
+ import { useCallback as s, useMemo as c } from "react";
10
+ import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
+ import { useSearchParams as u } from "react-router-dom";
12
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
13
+ import { Tabs as p } from "@burdenoff/fe-libs/chrome";
14
+ //#region src/channel/pages/ChannelLandingPage.tsx
15
+ function m() {
16
+ let [m, h] = u(), { t: g } = l(), _ = s((e, t) => {
17
+ let n = g(e);
18
+ return n === e ? t : n;
19
+ }, [g]), v = c(() => [
20
+ {
21
+ id: "dashboard",
22
+ label: _("channel.dashboard", "Dashboard")
23
+ },
24
+ {
25
+ id: "all",
26
+ label: _("channel.allChannels", "All Channels")
27
+ },
28
+ {
29
+ id: "connections",
30
+ label: _("channel.connections", "Connections")
31
+ },
32
+ {
33
+ id: "send",
34
+ label: _("channel.sendMessage", "Send Message")
35
+ },
36
+ {
37
+ id: "settings",
38
+ label: _("channel.settings", "Settings")
39
+ }
40
+ ], [_]), y = m.get("tab") ?? v[0].id;
41
+ return /* @__PURE__ */ d(e, {
42
+ permission: t.CHANNEL_READ,
43
+ children: /* @__PURE__ */ f("div", {
44
+ className: "flex flex-col h-full",
45
+ children: [/* @__PURE__ */ d("div", {
46
+ className: "border-b border-border-subtle px-4 pt-3",
47
+ children: /* @__PURE__ */ d(p, {
48
+ items: v,
49
+ activeTabId: y,
50
+ onTabChange: (e) => {
51
+ let t = new URLSearchParams(m);
52
+ e === v[0].id ? t.delete("tab") : t.set("tab", e), h(t, { replace: !0 });
53
+ },
54
+ variant: "underline"
55
+ })
56
+ }), /* @__PURE__ */ f("div", {
57
+ className: "flex-1 min-h-0 overflow-auto",
58
+ children: [
59
+ y === "dashboard" && /* @__PURE__ */ d(n, {}),
60
+ y === "all" && /* @__PURE__ */ d(r, {}),
61
+ y === "connections" && /* @__PURE__ */ d(a, {}),
62
+ y === "send" && /* @__PURE__ */ d(i, {}),
63
+ y === "settings" && /* @__PURE__ */ d(o, {})
64
+ ]
65
+ })]
66
+ })
67
+ });
68
+ }
69
+ //#endregion
70
+ export { m as ChannelLandingPage };
71
+
72
+ //# sourceMappingURL=ChannelLandingPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelLandingPage.js","names":[],"sources":["../../../src/channel/pages/ChannelLandingPage.tsx"],"sourcesContent":["import { useMemo, useCallback } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Tabs, type TabItem } from '@burdenoff/fe-libs/chrome';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport {\n ChannelDashboardPage,\n ChannelsListPage,\n ConnectionsListPage,\n SendMessagePage,\n ChannelSettingsPage,\n} from '../modules/channels/pages';\nimport { PermissionGuard } from '../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../constants/permissions';\n\n/**\n * Tabbed landing page for the Channel microfrontend.\n *\n * The first tab (\"dashboard\") uses a clean URL with no `tab` query param.\n * Detail routes (e.g. /:channelId, /:channelId/edit) remain registered in\n * ChannelRoutes so existing deep links continue to work.\n */\nexport function ChannelLandingPage() {\n const [params, setParams] = useSearchParams();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const tabs: TabItem[] = useMemo(\n () => [\n { id: 'dashboard', label: tr('channel.dashboard', 'Dashboard') },\n { id: 'all', label: tr('channel.allChannels', 'All Channels') },\n { id: 'connections', label: tr('channel.connections', 'Connections') },\n { id: 'send', label: tr('channel.sendMessage', 'Send Message') },\n { id: 'settings', label: tr('channel.settings', 'Settings') },\n ],\n [tr]\n );\n\n const activeId = params.get('tab') ?? tabs[0].id;\n\n const handleTabChange = (id: string) => {\n const next = new URLSearchParams(params);\n if (id === tabs[0].id) {\n next.delete('tab');\n } else {\n next.set('tab', id);\n }\n setParams(next, { replace: true });\n };\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_READ}>\n <div className=\"flex flex-col h-full\">\n <div className=\"border-b border-border-subtle px-4 pt-3\">\n <Tabs\n items={tabs}\n activeTabId={activeId}\n onTabChange={handleTabChange}\n variant=\"underline\"\n />\n </div>\n <div className=\"flex-1 min-h-0 overflow-auto\">\n {activeId === 'dashboard' && <ChannelDashboardPage />}\n {activeId === 'all' && <ChannelsListPage />}\n {activeId === 'connections' && <ConnectionsListPage />}\n {activeId === 'send' && <SendMessagePage />}\n {activeId === 'settings' && <ChannelSettingsPage />}\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAsBA,SAAgB,IAAqB;CACnC,IAAM,CAAC,GAAQ,KAAa,GAAiB,EACvC,EAAE,SAAM,GAAS,EACjB,IAAK,GACR,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAEpC,CAAC,EAAE,CACJ,EAEK,IAAkB,QAChB;EACJ;GAAE,IAAI;GAAa,OAAO,EAAG,qBAAqB,YAAY;GAAE;EAChE;GAAE,IAAI;GAAO,OAAO,EAAG,uBAAuB,eAAe;GAAE;EAC/D;GAAE,IAAI;GAAe,OAAO,EAAG,uBAAuB,cAAc;GAAE;EACtE;GAAE,IAAI;GAAQ,OAAO,EAAG,uBAAuB,eAAe;GAAE;EAChE;GAAE,IAAI;GAAY,OAAO,EAAG,oBAAoB,WAAW;GAAE;EAC9D,EACD,CAAC,EAAG,CACL,EAEK,IAAW,EAAO,IAAI,MAAM,IAAI,EAAK,GAAG;AAY9C,QACE,kBAAC,GAAD;EAAiB,YAAY,EAAoB;YAC/C,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,OAAO;KACP,aAAa;KACb,cAjBe,MAAe;MACtC,IAAM,IAAO,IAAI,gBAAgB,EAAO;AAMxC,MALI,MAAO,EAAK,GAAG,KACjB,EAAK,OAAO,MAAM,GAElB,EAAK,IAAI,OAAO,EAAG,EAErB,EAAU,GAAM,EAAE,SAAS,IAAM,CAAC;;KAW1B,SAAQ;KACR,CAAA;IACE,CAAA,EACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,MAAa,eAAe,kBAAC,GAAD,EAAwB,CAAA;KACpD,MAAa,SAAS,kBAAC,GAAD,EAAoB,CAAA;KAC1C,MAAa,iBAAiB,kBAAC,GAAD,EAAuB,CAAA;KACrD,MAAa,UAAU,kBAAC,GAAD,EAAmB,CAAA;KAC1C,MAAa,cAAc,kBAAC,GAAD,EAAuB,CAAA;KAC/C;MACF;;EACU,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { FC, PropsWithChildren } from 'react';
2
+ import { ChannelRootProps } from '../types';
3
+
4
+ /**
5
+ * Hook to access Channel context
6
+ */
7
+ export declare const useChannel: () => ChannelRootProps;
8
+ /**
9
+ * Provider component for Channel microfrontend
10
+ * Sets up routing and context
11
+ *
12
+ * When integrated into a shell (basePath provided), the shell already has a router
13
+ * so we don't create another one. When standalone (no basePath), use MemoryRouter.
14
+ */
15
+ export declare const ChannelProvider: FC<PropsWithChildren<ChannelRootProps>>;
16
+ //# sourceMappingURL=ChannelProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChannelProvider.d.ts","sourceRoot":"","sources":["../../../src/channel/providers/ChannelProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAInD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AASjD;;GAEG;AACH,eAAO,MAAM,UAAU,wBAMtB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAkDnE,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { createContext as e, useContext as t } from "react";
2
+ import { MemoryRouter as n } from "react-router-dom";
3
+ import { PermissionProvider as r } from "@burdenoff/fe-libs/shared/providers/shell";
4
+ import { jsx as i } from "react/jsx-runtime";
5
+ //#region src/channel/providers/ChannelProvider.tsx
6
+ var a = e(null), o = () => {
7
+ let e = t(a);
8
+ if (!e) throw Error("useChannel must be used within ChannelProvider");
9
+ return e;
10
+ }, s = ({ children: e, basePath: t, navigate: o, currentUser: s, workspaceId: c, organizationId: l, tenantId: u, apiGatewayUrl: d, authToken: f, registerNavItems: p, registerFooterItems: m }) => {
11
+ let h = {
12
+ basePath: t,
13
+ navigate: o,
14
+ currentUser: s,
15
+ workspaceId: c,
16
+ organizationId: l,
17
+ tenantId: u,
18
+ apiGatewayUrl: d,
19
+ authToken: f,
20
+ registerNavItems: p,
21
+ registerFooterItems: m
22
+ }, g = !!t, _ = /* @__PURE__ */ i(a.Provider, {
23
+ value: h,
24
+ children: g ? /* @__PURE__ */ i(r, {
25
+ scopeId: l ?? null,
26
+ gateway: "global",
27
+ children: e
28
+ }) : e
29
+ });
30
+ return g ? _ : /* @__PURE__ */ i(n, { children: _ });
31
+ };
32
+ //#endregion
33
+ export { s as ChannelProvider, o as useChannel };
34
+
35
+ //# sourceMappingURL=ChannelProvider.js.map