@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,219 @@
1
+ import { useChannel as e } from "../../../providers/ChannelProvider.js";
2
+ import { useChannel as t, useChannels as n } from "../../../hooks/useChannels.js";
3
+ import { PermissionGuard as r } from "../../../components/PermissionGuard.js";
4
+ import { CHANNEL_PERMISSIONS as i } from "../../../constants/permissions.js";
5
+ import { useMemo as a, useState as o } from "react";
6
+ import { useI18n as s } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
+ import { AlertCircle as c, ArrowLeft as l, Loader2 as u, Save as d, Shield as f } from "lucide-react";
8
+ import { useNavigate as p, useSearchParams as m } from "react-router-dom";
9
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
10
+ //#region src/channel/modules/channels/pages/CreateConnectionPage.tsx
11
+ var v = [
12
+ {
13
+ value: "OAUTH2",
14
+ label: "OAuth 2.0",
15
+ help: "Authorization code flow"
16
+ },
17
+ {
18
+ value: "API_KEY",
19
+ label: "API Key",
20
+ help: "Static API key"
21
+ },
22
+ {
23
+ value: "BOT_TOKEN",
24
+ label: "Bot Token",
25
+ help: "Slack/Discord/Teams bot token"
26
+ },
27
+ {
28
+ value: "WEBHOOK",
29
+ label: "Webhook",
30
+ help: "Shared secret for HMAC verification"
31
+ },
32
+ {
33
+ value: "SMTP_IMAP",
34
+ label: "SMTP / IMAP",
35
+ help: "Mail server credentials"
36
+ }
37
+ ];
38
+ function y() {
39
+ let y = p(), [b] = m(), { organizationId: x } = e(), { channels: S, isLoading: C } = n(), { t: w } = s(), T = (e, t) => {
40
+ let n = w(e);
41
+ return n === e ? t : n;
42
+ }, [E, D] = o(b.get("channelId") ?? ""), { createConnection: O } = t(E), [k, A] = o("OAUTH2"), [j, M] = o(""), [N, P] = o(""), [F, I] = o(""), [L, R] = o(""), [z, B] = o(!1), [V, H] = o(null), U = a(() => S.find((e) => e.id === E) ?? null, [S, E]);
43
+ return /* @__PURE__ */ g(r, {
44
+ permission: i.CHANNEL_CONNECTION_CREATE,
45
+ children: /* @__PURE__ */ _("div", {
46
+ className: "container mx-auto p-6 max-w-2xl",
47
+ children: [
48
+ /* @__PURE__ */ _("button", {
49
+ onClick: () => y(-1),
50
+ className: "flex items-center gap-2 text-fg-muted hover:text-fg mb-6",
51
+ children: [/* @__PURE__ */ g(l, { className: "w-4 h-4" }), T("common.back", "Back")]
52
+ }),
53
+ /* @__PURE__ */ _("div", {
54
+ className: "flex items-center gap-3 mb-6",
55
+ children: [/* @__PURE__ */ g(f, { className: "w-7 h-7 text-accent-blue" }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h1", {
56
+ className: "text-2xl font-bold text-fg",
57
+ children: T("connection.create.title", "Create Connection")
58
+ }), /* @__PURE__ */ g("p", {
59
+ className: "text-sm text-fg-muted",
60
+ children: T("connection.create.subtitle", "Authenticate a channel against its platform provider.")
61
+ })] })]
62
+ }),
63
+ V && /* @__PURE__ */ _("div", {
64
+ className: "bg-status-error-bg-subtle border border-status-error-bg-subtle rounded-lg p-4 mb-6 flex gap-3",
65
+ children: [/* @__PURE__ */ g(c, { className: "w-5 h-5 text-status-error-text shrink-0" }), /* @__PURE__ */ g("p", {
66
+ className: "text-sm text-status-error-text",
67
+ children: V
68
+ })]
69
+ }),
70
+ /* @__PURE__ */ _("form", {
71
+ onSubmit: async (e) => {
72
+ if (e.preventDefault(), H(null), !E) {
73
+ H(T("connection.validation.channelRequired", "Pick a channel to connect"));
74
+ return;
75
+ }
76
+ if (!x) {
77
+ H(T("connection.validation.organizationRequired", "Organization context missing"));
78
+ return;
79
+ }
80
+ let t;
81
+ if (L.trim()) try {
82
+ t = JSON.parse(L);
83
+ } catch {
84
+ H(T("connection.validation.credentialsJson", "Credentials must be valid JSON"));
85
+ return;
86
+ }
87
+ B(!0);
88
+ try {
89
+ let e = await O({
90
+ authType: k,
91
+ authCode: j.trim() || void 0,
92
+ apiKey: N.trim() || void 0,
93
+ redirectUri: F.trim() || void 0,
94
+ credentials: t
95
+ });
96
+ e ? y(`../${e.id}`) : H(T("connection.createFailed", "Failed to create connection"));
97
+ } catch (e) {
98
+ H(e instanceof Error ? e.message : T("connection.createFailed", "Failed to create connection"));
99
+ } finally {
100
+ B(!1);
101
+ }
102
+ },
103
+ className: "space-y-6 bg-bg-elevated rounded-lg p-6 border border-border",
104
+ children: [
105
+ /* @__PURE__ */ _("div", { children: [
106
+ /* @__PURE__ */ _("label", {
107
+ className: "block text-sm font-medium text-fg mb-2",
108
+ children: [T("connection.field.channel", "Channel"), " *"]
109
+ }),
110
+ /* @__PURE__ */ _("select", {
111
+ value: E,
112
+ onChange: (e) => D(e.target.value),
113
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md text-fg",
114
+ required: !0,
115
+ disabled: C,
116
+ children: [/* @__PURE__ */ g("option", {
117
+ value: "",
118
+ children: C ? T("common.loading", "Loading...") : T("connection.field.channelPlaceholder", "Select a channel")
119
+ }), S.map((e) => /* @__PURE__ */ _("option", {
120
+ value: e.id,
121
+ children: [
122
+ e.name,
123
+ " (",
124
+ e.platform,
125
+ ")"
126
+ ]
127
+ }, e.id))]
128
+ }),
129
+ U && /* @__PURE__ */ _("p", {
130
+ className: "mt-1 text-xs text-fg-muted",
131
+ children: [T("connection.field.channelHint", "Adapter: "), U.adapterType ?? "—"]
132
+ })
133
+ ] }),
134
+ /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("label", {
135
+ className: "block text-sm font-medium text-fg mb-2",
136
+ children: [T("connection.field.authType", "Authentication Type"), " *"]
137
+ }), /* @__PURE__ */ g("select", {
138
+ value: k,
139
+ onChange: (e) => A(e.target.value),
140
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md text-fg",
141
+ required: !0,
142
+ children: v.map((e) => /* @__PURE__ */ _("option", {
143
+ value: e.value,
144
+ children: [
145
+ e.label,
146
+ " — ",
147
+ e.help
148
+ ]
149
+ }, e.value))
150
+ })] }),
151
+ k === "OAUTH2" && /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
152
+ className: "block text-sm font-medium text-fg mb-2",
153
+ children: T("connection.field.authCode", "OAuth Authorization Code")
154
+ }), /* @__PURE__ */ g("input", {
155
+ type: "text",
156
+ value: j,
157
+ onChange: (e) => M(e.target.value),
158
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md text-fg",
159
+ autoComplete: "off"
160
+ })] }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
161
+ className: "block text-sm font-medium text-fg mb-2",
162
+ children: T("connection.field.redirectUri", "Redirect URI")
163
+ }), /* @__PURE__ */ g("input", {
164
+ type: "url",
165
+ value: F,
166
+ onChange: (e) => I(e.target.value),
167
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md text-fg"
168
+ })] })] }),
169
+ (k === "API_KEY" || k === "BOT_TOKEN") && /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
170
+ className: "block text-sm font-medium text-fg mb-2",
171
+ children: T("connection.field.apiKey", "API Key / Token")
172
+ }), /* @__PURE__ */ g("input", {
173
+ type: "password",
174
+ value: N,
175
+ onChange: (e) => P(e.target.value),
176
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md text-fg",
177
+ autoComplete: "new-password"
178
+ })] }),
179
+ /* @__PURE__ */ _("div", { children: [
180
+ /* @__PURE__ */ g("label", {
181
+ className: "block text-sm font-medium text-fg mb-2",
182
+ children: T("connection.field.credentials", "Additional Credentials (JSON)")
183
+ }),
184
+ /* @__PURE__ */ g("textarea", {
185
+ value: L,
186
+ onChange: (e) => R(e.target.value),
187
+ rows: 6,
188
+ className: "w-full px-3 py-2 bg-bg border border-border rounded-md font-mono text-sm text-fg",
189
+ placeholder: "{\"smtpHost\": \"smtp.example.com\"}"
190
+ }),
191
+ /* @__PURE__ */ g("p", {
192
+ className: "mt-1 text-xs text-fg-muted",
193
+ children: T("connection.field.credentialsHint", "Encrypted at rest with AES-256-GCM. Never logged in plaintext.")
194
+ })
195
+ ] }),
196
+ /* @__PURE__ */ _("div", {
197
+ className: "flex gap-3 pt-2",
198
+ children: [/* @__PURE__ */ _("button", {
199
+ type: "submit",
200
+ disabled: z || !E,
201
+ className: "flex items-center gap-2 px-4 py-2 bg-accent-blue text-fg-on-accent rounded-md disabled:opacity-50",
202
+ children: [z ? /* @__PURE__ */ g(u, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ g(d, { className: "w-4 h-4" }), T("connection.create.submit", "Create Connection")]
203
+ }), /* @__PURE__ */ g("button", {
204
+ type: "button",
205
+ onClick: () => y(-1),
206
+ className: "px-4 py-2 text-fg border border-border rounded-md",
207
+ children: T("common.cancel", "Cancel")
208
+ })]
209
+ })
210
+ ]
211
+ })
212
+ ]
213
+ })
214
+ });
215
+ }
216
+ //#endregion
217
+ export { y as CreateConnectionPage };
218
+
219
+ //# sourceMappingURL=CreateConnectionPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateConnectionPage.js","names":[],"sources":["../../../../../src/channel/modules/channels/pages/CreateConnectionPage.tsx"],"sourcesContent":["/**\n * Create Connection Page\n *\n * Standalone page mounted at /channels/connections/create.\n * User picks a target channel, then provides auth details.\n *\n * Form fields match CreateConnectionInput exactly (less channelId which is\n * resolved from the selector).\n */\n\nimport { useMemo, useState } from 'react';\nimport { useNavigate, useSearchParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Loader2, AlertCircle, Save, Shield } from 'lucide-react';\nimport { useChannel as useChannelContext } from '../../../providers/ChannelProvider';\nimport { useChannel, useChannels, type ChannelAuthType } from '../../../hooks/useChannels';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\n\nconst AUTH_TYPES: { value: ChannelAuthType; label: string; help: string }[] = [\n { value: 'OAUTH2', label: 'OAuth 2.0', help: 'Authorization code flow' },\n { value: 'API_KEY', label: 'API Key', help: 'Static API key' },\n { value: 'BOT_TOKEN', label: 'Bot Token', help: 'Slack/Discord/Teams bot token' },\n { value: 'WEBHOOK', label: 'Webhook', help: 'Shared secret for HMAC verification' },\n { value: 'SMTP_IMAP', label: 'SMTP / IMAP', help: 'Mail server credentials' },\n];\n\nexport function CreateConnectionPage() {\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const { organizationId } = useChannelContext();\n const { channels, isLoading: channelsLoading } = useChannels();\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 const initialChannelId = searchParams.get('channelId') ?? '';\n const [selectedChannelId, setSelectedChannelId] = useState<string>(initialChannelId);\n const { createConnection } = useChannel(selectedChannelId);\n\n const [authType, setAuthType] = useState<ChannelAuthType>('OAUTH2');\n const [authCode, setAuthCode] = useState('');\n const [apiKey, setApiKey] = useState('');\n const [redirectUri, setRedirectUri] = useState('');\n const [credentials, setCredentials] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const selectedChannel = useMemo(\n () => channels.find((c) => c.id === selectedChannelId) ?? null,\n [channels, selectedChannelId]\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n if (!selectedChannelId) {\n setError(tr('connection.validation.channelRequired', 'Pick a channel to connect'));\n return;\n }\n if (!organizationId) {\n setError(tr('connection.validation.organizationRequired', 'Organization context missing'));\n return;\n }\n\n let parsedCredentials: Record<string, unknown> | undefined;\n if (credentials.trim()) {\n try {\n parsedCredentials = JSON.parse(credentials);\n } catch {\n setError(tr('connection.validation.credentialsJson', 'Credentials must be valid JSON'));\n return;\n }\n }\n\n setIsSubmitting(true);\n try {\n const result = await createConnection({\n authType,\n authCode: authCode.trim() || undefined,\n apiKey: apiKey.trim() || undefined,\n redirectUri: redirectUri.trim() || undefined,\n credentials: parsedCredentials,\n });\n if (result) {\n navigate(`../${result.id}`);\n } else {\n setError(tr('connection.createFailed', 'Failed to create connection'));\n }\n } catch (err: unknown) {\n setError(\n err instanceof Error\n ? err.message\n : tr('connection.createFailed', 'Failed to create connection')\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_CONNECTION_CREATE}>\n <div className=\"container mx-auto p-6 max-w-2xl\">\n <button\n onClick={() => navigate(-1)}\n className=\"flex items-center gap-2 text-fg-muted hover:text-fg mb-6\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {tr('common.back', 'Back')}\n </button>\n\n <div className=\"flex items-center gap-3 mb-6\">\n <Shield className=\"w-7 h-7 text-accent-blue\" />\n <div>\n <h1 className=\"text-2xl font-bold text-fg\">\n {tr('connection.create.title', 'Create Connection')}\n </h1>\n <p className=\"text-sm text-fg-muted\">\n {tr(\n 'connection.create.subtitle',\n 'Authenticate a channel against its platform provider.'\n )}\n </p>\n </div>\n </div>\n\n {error && (\n <div className=\"bg-status-error-bg-subtle border border-status-error-bg-subtle rounded-lg p-4 mb-6 flex gap-3\">\n <AlertCircle className=\"w-5 h-5 text-status-error-text shrink-0\" />\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n\n <form\n onSubmit={handleSubmit}\n className=\"space-y-6 bg-bg-elevated rounded-lg p-6 border border-border\"\n >\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.channel', 'Channel')} *\n </label>\n <select\n value={selectedChannelId}\n onChange={(e) => setSelectedChannelId(e.target.value)}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md text-fg\"\n required\n disabled={channelsLoading}\n >\n <option value=\"\">\n {channelsLoading\n ? tr('common.loading', 'Loading...')\n : tr('connection.field.channelPlaceholder', 'Select a channel')}\n </option>\n {channels.map((c) => (\n <option key={c.id} value={c.id}>\n {c.name} ({c.platform})\n </option>\n ))}\n </select>\n {selectedChannel && (\n <p className=\"mt-1 text-xs text-fg-muted\">\n {tr('connection.field.channelHint', 'Adapter: ')}\n {selectedChannel.adapterType ?? '—'}\n </p>\n )}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.authType', 'Authentication Type')} *\n </label>\n <select\n value={authType}\n onChange={(e) => setAuthType(e.target.value as ChannelAuthType)}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md text-fg\"\n required\n >\n {AUTH_TYPES.map((a) => (\n <option key={a.value} value={a.value}>\n {a.label} — {a.help}\n </option>\n ))}\n </select>\n </div>\n\n {authType === 'OAUTH2' && (\n <>\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.authCode', 'OAuth Authorization Code')}\n </label>\n <input\n type=\"text\"\n value={authCode}\n onChange={(e) => setAuthCode(e.target.value)}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md text-fg\"\n autoComplete=\"off\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.redirectUri', 'Redirect URI')}\n </label>\n <input\n type=\"url\"\n value={redirectUri}\n onChange={(e) => setRedirectUri(e.target.value)}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md text-fg\"\n />\n </div>\n </>\n )}\n\n {(authType === 'API_KEY' || authType === 'BOT_TOKEN') && (\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.apiKey', 'API Key / Token')}\n </label>\n <input\n type=\"password\"\n value={apiKey}\n onChange={(e) => setApiKey(e.target.value)}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md text-fg\"\n autoComplete=\"new-password\"\n />\n </div>\n )}\n\n <div>\n <label className=\"block text-sm font-medium text-fg mb-2\">\n {tr('connection.field.credentials', 'Additional Credentials (JSON)')}\n </label>\n <textarea\n value={credentials}\n onChange={(e) => setCredentials(e.target.value)}\n rows={6}\n className=\"w-full px-3 py-2 bg-bg border border-border rounded-md font-mono text-sm text-fg\"\n placeholder='{\"smtpHost\": \"smtp.example.com\"}'\n />\n <p className=\"mt-1 text-xs text-fg-muted\">\n {tr(\n 'connection.field.credentialsHint',\n 'Encrypted at rest with AES-256-GCM. Never logged in plaintext.'\n )}\n </p>\n </div>\n\n <div className=\"flex gap-3 pt-2\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !selectedChannelId}\n className=\"flex items-center gap-2 px-4 py-2 bg-accent-blue text-fg-on-accent rounded-md disabled:opacity-50\"\n >\n {isSubmitting ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Save className=\"w-4 h-4\" />\n )}\n {tr('connection.create.submit', 'Create Connection')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n className=\"px-4 py-2 text-fg border border-border rounded-md\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Delivery History Page
3
+ *
4
+ * Displays message delivery attempts for a specific channel with retry capability
5
+ */
6
+ export declare function DeliveryHistoryPage(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=DeliveryHistoryPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeliveryHistoryPage.d.ts","sourceRoot":"","sources":["../../../../../src/channel/modules/channels/pages/DeliveryHistoryPage.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAiDH,wBAAgB,mBAAmB,4CA6SlC"}
@@ -0,0 +1,375 @@
1
+ import { useChannel as e } from "../../../providers/ChannelProvider.js";
2
+ import { DELIVERY_UPDATED_SUBSCRIPTION as t, useChannelSubscription as n } from "../../../hooks/useChannelSubscription.js";
3
+ import { useChannel as r } from "../../../hooks/useChannels.js";
4
+ import { PermissionGuard as i } from "../../../components/PermissionGuard.js";
5
+ import { CHANNEL_PERMISSIONS as a } from "../../../constants/permissions.js";
6
+ import { useExportDeliveryAttempts as o } from "../hooks/useExport.js";
7
+ import { useCallback as s, useEffect as c, useState as l } from "react";
8
+ import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
+ import { AlertCircle as d, ArrowLeft as f, CheckCircle2 as p, Clock as m, Download as h, Loader2 as g, RefreshCw as _, RotateCcw as v, Send as y, XCircle as b } from "lucide-react";
10
+ import { useNavigate as x, useParams as S } from "react-router-dom";
11
+ import { jsx as C, jsxs as w } from "react/jsx-runtime";
12
+ //#region src/channel/modules/channels/pages/DeliveryHistoryPage.tsx
13
+ var T = {
14
+ PENDING: {
15
+ label: "Pending",
16
+ color: "text-muted-foreground bg-muted",
17
+ icon: m
18
+ },
19
+ QUEUED: {
20
+ label: "Queued",
21
+ color: "text-info-500 bg-info-100",
22
+ icon: m
23
+ },
24
+ SENDING: {
25
+ label: "Sending",
26
+ color: "text-accent-primary bg-accent-primary/10",
27
+ icon: y
28
+ },
29
+ SENT: {
30
+ label: "Sent",
31
+ color: "text-success-500 bg-success-100",
32
+ icon: p
33
+ },
34
+ DELIVERED: {
35
+ label: "Delivered",
36
+ color: "text-success-500 bg-success-100",
37
+ icon: p
38
+ },
39
+ FAILED: {
40
+ label: "Failed",
41
+ color: "text-error-500 bg-error-100",
42
+ icon: b
43
+ },
44
+ BOUNCED: {
45
+ label: "Bounced",
46
+ color: "text-warning-500 bg-warning-100",
47
+ icon: d
48
+ },
49
+ REJECTED: {
50
+ label: "Rejected",
51
+ color: "text-error-500 bg-error-100",
52
+ icon: b
53
+ },
54
+ RATE_LIMITED: {
55
+ label: "Rate Limited",
56
+ color: "text-warning-500 bg-warning-100",
57
+ icon: m
58
+ },
59
+ RETRYING: {
60
+ label: "Retrying",
61
+ color: "text-accent-primary bg-accent-primary/10",
62
+ icon: _
63
+ },
64
+ OPENED: {
65
+ label: "Opened",
66
+ color: "text-success-500 bg-success-100",
67
+ icon: p
68
+ },
69
+ CLICKED: {
70
+ label: "Clicked",
71
+ color: "text-success-500 bg-success-100",
72
+ icon: p
73
+ }
74
+ };
75
+ function E() {
76
+ let { channelId: p } = S(), m = x(), { t: b } = u(), E = (e, t) => {
77
+ let n = b(e);
78
+ return n === e ? t : n;
79
+ }, { organizationId: D } = e(), { triggerExport: O, isExporting: k, exportError: A } = o(D ?? void 0, p), [j, M] = l(!0), [N, P] = l([]), [F, I] = l(null), [L, R] = l(null), [z, B] = l(25), { channel: V, isLoading: H, error: U, fetchDeliveryAttempts: W, retryDelivery: G } = r(p), K = s(async () => {
80
+ if (p) {
81
+ M(!0), R(null);
82
+ try {
83
+ P(await W(z));
84
+ } finally {
85
+ M(!1);
86
+ }
87
+ }
88
+ }, [
89
+ p,
90
+ W,
91
+ z
92
+ ]);
93
+ c(() => {
94
+ Promise.resolve().then(() => K());
95
+ }, [K]), n({
96
+ query: t,
97
+ variables: { channelId: p },
98
+ operationName: "DeliveryUpdated",
99
+ enabled: !!p,
100
+ onData: () => void K(),
101
+ pollFn: K,
102
+ pollIntervalMs: 6e4
103
+ });
104
+ let q = async (e) => {
105
+ I(e), R(null);
106
+ try {
107
+ let t = await G(e);
108
+ t.success || R(t.error || "Retry failed");
109
+ } finally {
110
+ I(null);
111
+ }
112
+ }, J = (e) => T[e] || T.PENDING;
113
+ return H ? /* @__PURE__ */ C("div", {
114
+ className: "flex items-center justify-center min-h-screen",
115
+ children: /* @__PURE__ */ C(g, {
116
+ size: 32,
117
+ className: "animate-spin text-accent-primary"
118
+ })
119
+ }) : U || !V ? /* @__PURE__ */ C("div", {
120
+ className: "p-6",
121
+ children: /* @__PURE__ */ w("div", {
122
+ className: "flex items-center gap-3 p-4 bg-error-100 border border-error-500 rounded-lg",
123
+ children: [
124
+ /* @__PURE__ */ C(d, {
125
+ size: 20,
126
+ className: "text-error-500"
127
+ }),
128
+ /* @__PURE__ */ C("div", { children: /* @__PURE__ */ C("p", {
129
+ className: "text-sm font-medium text-error-700",
130
+ children: U || "Channel not found"
131
+ }) }),
132
+ /* @__PURE__ */ C("button", {
133
+ onClick: () => m(`/channels/${p}`),
134
+ className: "ml-auto px-3 py-1 text-sm text-error-700 hover:bg-error-200 rounded transition-colors",
135
+ children: "Go Back"
136
+ })
137
+ ]
138
+ })
139
+ }) : /* @__PURE__ */ C(i, {
140
+ permission: a.CHANNEL_DELIVERY_READ,
141
+ children: /* @__PURE__ */ w("div", {
142
+ className: "space-y-6 p-3 sm:p-6",
143
+ children: [
144
+ /* @__PURE__ */ w("div", {
145
+ className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
146
+ children: [/* @__PURE__ */ w("div", {
147
+ className: "flex items-center gap-3",
148
+ children: [/* @__PURE__ */ C("button", {
149
+ onClick: () => m(`/channels/${p}`),
150
+ className: "p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors",
151
+ children: /* @__PURE__ */ C(f, { size: 20 })
152
+ }), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("h1", {
153
+ className: "text-xl sm:text-2xl font-bold text-foreground",
154
+ children: E("channel.deliveryHistory", "Delivery History")
155
+ }), /* @__PURE__ */ w("p", {
156
+ className: "text-sm text-muted-foreground mt-1",
157
+ children: [V.name, " - Message deliveries"]
158
+ })] })]
159
+ }), /* @__PURE__ */ w("div", {
160
+ className: "flex items-center gap-3",
161
+ children: [
162
+ /* @__PURE__ */ w("select", {
163
+ value: z,
164
+ onChange: (e) => B(Number(e.target.value)),
165
+ 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",
166
+ children: [
167
+ /* @__PURE__ */ C("option", {
168
+ value: 10,
169
+ children: "10 results"
170
+ }),
171
+ /* @__PURE__ */ C("option", {
172
+ value: 25,
173
+ children: "25 results"
174
+ }),
175
+ /* @__PURE__ */ C("option", {
176
+ value: 50,
177
+ children: "50 results"
178
+ }),
179
+ /* @__PURE__ */ C("option", {
180
+ value: 100,
181
+ children: "100 results"
182
+ })
183
+ ]
184
+ }),
185
+ /* @__PURE__ */ w("button", {
186
+ onClick: K,
187
+ disabled: j,
188
+ 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",
189
+ children: [/* @__PURE__ */ C(_, {
190
+ size: 16,
191
+ className: j ? "animate-spin" : ""
192
+ }), E("channel.refresh", "Refresh")]
193
+ }),
194
+ /* @__PURE__ */ C(i, {
195
+ permission: a.CHANNEL_ADMIN,
196
+ children: /* @__PURE__ */ w("button", {
197
+ onClick: () => void O(),
198
+ disabled: k,
199
+ 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",
200
+ title: E("channel.exportCSV", "Export to CSV"),
201
+ children: [k ? /* @__PURE__ */ C(g, {
202
+ size: 16,
203
+ className: "animate-spin"
204
+ }) : /* @__PURE__ */ C(h, { size: 16 }), E("channel.export", "Export")]
205
+ })
206
+ })
207
+ ]
208
+ })]
209
+ }),
210
+ A && /* @__PURE__ */ w("div", {
211
+ className: "p-4 bg-error-100 border border-error-500 rounded-lg flex items-center gap-3",
212
+ children: [/* @__PURE__ */ C(d, {
213
+ size: 20,
214
+ className: "text-error-500"
215
+ }), /* @__PURE__ */ C("p", {
216
+ className: "text-sm text-error-700 flex-1",
217
+ children: A
218
+ })]
219
+ }),
220
+ L && /* @__PURE__ */ w("div", {
221
+ className: "p-4 bg-error-100 border border-error-500 rounded-lg flex items-center gap-3",
222
+ children: [
223
+ /* @__PURE__ */ C(d, {
224
+ size: 20,
225
+ className: "text-error-500"
226
+ }),
227
+ /* @__PURE__ */ C("p", {
228
+ className: "text-sm text-error-700 flex-1",
229
+ children: L
230
+ }),
231
+ /* @__PURE__ */ C("button", {
232
+ onClick: () => R(null),
233
+ className: "text-error-500 hover:text-error-700",
234
+ children: E("channel.dismiss", "Dismiss")
235
+ })
236
+ ]
237
+ }),
238
+ /* @__PURE__ */ C("div", {
239
+ className: "p-4 bg-surface border border-border rounded-lg",
240
+ children: /* @__PURE__ */ C("p", {
241
+ className: "text-sm text-muted-foreground",
242
+ children: "Delivery history shows all message attempts sent through this channel. Data is retained for 7 days. Click retry on a failed delivery to attempt sending again."
243
+ })
244
+ }),
245
+ /* @__PURE__ */ C("div", {
246
+ className: "bg-surface border border-border rounded-lg overflow-hidden",
247
+ children: /* @__PURE__ */ C("div", {
248
+ className: "overflow-x-auto min-w-full",
249
+ children: /* @__PURE__ */ w("table", {
250
+ className: "w-full min-w-[700px]",
251
+ children: [/* @__PURE__ */ C("thead", {
252
+ className: "bg-muted/50 border-b border-border",
253
+ children: /* @__PURE__ */ w("tr", { children: [
254
+ /* @__PURE__ */ C("th", {
255
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
256
+ children: E("channel.status", "Status")
257
+ }),
258
+ /* @__PURE__ */ C("th", {
259
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
260
+ children: E("channel.content", "Content")
261
+ }),
262
+ /* @__PURE__ */ C("th", {
263
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
264
+ children: E("channel.sentAt", "Sent At")
265
+ }),
266
+ /* @__PURE__ */ C("th", {
267
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
268
+ children: E("channel.retries", "Retries")
269
+ }),
270
+ /* @__PURE__ */ C("th", {
271
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
272
+ children: E("channel.error", "Error")
273
+ }),
274
+ /* @__PURE__ */ C("th", {
275
+ className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
276
+ children: E("channel.actions", "Actions")
277
+ })
278
+ ] })
279
+ }), /* @__PURE__ */ C("tbody", {
280
+ className: "divide-y divide-border",
281
+ children: j ? /* @__PURE__ */ C("tr", { children: /* @__PURE__ */ w("td", {
282
+ colSpan: 6,
283
+ className: "px-4 py-12 text-center",
284
+ children: [/* @__PURE__ */ C(g, {
285
+ size: 24,
286
+ className: "animate-spin text-accent-primary mx-auto"
287
+ }), /* @__PURE__ */ C("p", {
288
+ className: "text-sm text-muted-foreground mt-2",
289
+ children: "Loading delivery attempts..."
290
+ })]
291
+ }) }) : N.length === 0 ? /* @__PURE__ */ C("tr", { children: /* @__PURE__ */ C("td", {
292
+ colSpan: 6,
293
+ className: "px-4 py-12 text-center",
294
+ children: /* @__PURE__ */ w("div", {
295
+ className: "flex flex-col items-center gap-2",
296
+ children: [
297
+ /* @__PURE__ */ C(y, {
298
+ size: 32,
299
+ className: "text-muted-foreground"
300
+ }),
301
+ /* @__PURE__ */ C("p", {
302
+ className: "text-sm font-medium text-foreground",
303
+ children: E("channel.noDeliveryAttempts", "No delivery attempts yet")
304
+ }),
305
+ /* @__PURE__ */ C("p", {
306
+ className: "text-xs text-muted-foreground",
307
+ children: E("channel.sendMessageToSeeHistory", "Send a message through this channel to see delivery history")
308
+ })
309
+ ]
310
+ })
311
+ }) }) : N.map((e) => {
312
+ let t = J(e.status), n = t.icon, r = e.status === "FAILED" || e.status === "BOUNCED" || e.status === "REJECTED";
313
+ return /* @__PURE__ */ w("tr", {
314
+ className: "hover:bg-muted/30 transition-colors",
315
+ children: [
316
+ /* @__PURE__ */ C("td", {
317
+ className: "px-4 py-3",
318
+ children: /* @__PURE__ */ w("div", {
319
+ className: "flex items-center gap-2",
320
+ children: [/* @__PURE__ */ C(n, {
321
+ size: 14,
322
+ className: t.color.split(" ")[0]
323
+ }), /* @__PURE__ */ C("span", {
324
+ className: `text-sm font-medium ${t.color}`,
325
+ children: t.label
326
+ })]
327
+ })
328
+ }),
329
+ /* @__PURE__ */ C("td", {
330
+ className: "px-4 py-3 text-sm text-foreground truncate max-w-xs",
331
+ children: e.content
332
+ }),
333
+ /* @__PURE__ */ C("td", {
334
+ className: "px-4 py-3 text-sm text-muted-foreground",
335
+ children: e.sentAt ? new Date(e.sentAt).toLocaleString() : "-"
336
+ }),
337
+ /* @__PURE__ */ C("td", {
338
+ className: "px-4 py-3 text-sm text-muted-foreground",
339
+ children: e.retryCount
340
+ }),
341
+ /* @__PURE__ */ C("td", {
342
+ className: "px-4 py-3 text-sm text-error-500 max-w-xs truncate",
343
+ children: e.errorMessage || "-"
344
+ }),
345
+ /* @__PURE__ */ C("td", {
346
+ className: "px-4 py-3",
347
+ children: r && /* @__PURE__ */ C(i, {
348
+ permission: a.CHANNEL_DELIVERY_EXECUTE,
349
+ children: /* @__PURE__ */ w("button", {
350
+ onClick: () => q(e.id),
351
+ disabled: F === e.id,
352
+ className: "flex items-center gap-1 px-2 py-1 text-xs font-medium text-accent-primary hover:bg-accent-primary/10 rounded transition-colors disabled:opacity-50",
353
+ title: E("channel.retryDelivery", "Retry this delivery"),
354
+ children: [/* @__PURE__ */ C(v, {
355
+ size: 12,
356
+ className: F === e.id ? "animate-spin" : ""
357
+ }), F === e.id ? E("channel.retrying", "Retrying...") : E("channel.retry", "Retry")]
358
+ })
359
+ })
360
+ })
361
+ ]
362
+ }, e.id);
363
+ })
364
+ })]
365
+ })
366
+ })
367
+ })
368
+ ]
369
+ })
370
+ });
371
+ }
372
+ //#endregion
373
+ export { E as DeliveryHistoryPage };
374
+
375
+ //# sourceMappingURL=DeliveryHistoryPage.js.map