@burdenoff/microfe-channel 2026.519.1 → 2026.520.1
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.
- package/dist/channel/ChannelRoot.d.ts.map +1 -1
- package/dist/channel/ChannelRoot.js +23 -29
- package/dist/channel/ChannelRoot.js.map +1 -1
- package/dist/channel/components/AdapterCredentialsForm.js +7 -7
- package/dist/channel/components/AdapterCredentialsForm.js.map +1 -1
- package/dist/channel/components/FeatureNotEnabled.d.ts +3 -0
- package/dist/channel/components/FeatureNotEnabled.d.ts.map +1 -1
- package/dist/channel/components/FeatureNotEnabled.js +31 -13
- package/dist/channel/components/FeatureNotEnabled.js.map +1 -1
- package/dist/channel/hooks/useChannels.d.ts +17 -3
- package/dist/channel/hooks/useChannels.d.ts.map +1 -1
- package/dist/channel/hooks/useChannels.js +64 -18
- package/dist/channel/hooks/useChannels.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js +307 -274
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.js +31 -31
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js +22 -22
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js +193 -137
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelsListPage.js +320 -248
- package/dist/channel/modules/channels/pages/ChannelsListPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js +5 -5
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionsListPage.js +160 -112
- package/dist/channel/modules/channels/pages/ConnectionsListPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/CreateChannelPage.js +4 -4
- package/dist/channel/modules/channels/pages/CreateChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js +221 -157
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/EditChannelPage.js +9 -9
- package/dist/channel/modules/channels/pages/EditChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.js +89 -89
- package/dist/channel/modules/channels/pages/SendMessagePage.js.map +1 -1
- package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/WebhookEventsPage.js +188 -126
- package/dist/channel/modules/channels/pages/WebhookEventsPage.js.map +1 -1
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -1
- package/dist/generated/global-operations.js +2 -0
- package/dist/generated/global-operations.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,290 +7,318 @@ import { CHANNEL_PERMISSIONS as o } from "../../../constants/permissions.js";
|
|
|
7
7
|
import { useExportWebhookEvents as s } from "../hooks/useExport.js";
|
|
8
8
|
import { useCallback as c, useEffect as l, useState as u } from "react";
|
|
9
9
|
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
10
|
-
import { AlertCircle as f, ArrowLeft as p, CheckCircle2 as m,
|
|
11
|
-
import { useNavigate as
|
|
12
|
-
import { Fragment as
|
|
10
|
+
import { AlertCircle as f, ArrowLeft as p, CheckCircle2 as m, ChevronLeft as h, ChevronRight as g, Clock as _, Download as v, Eye as y, EyeOff as b, Loader2 as x, RefreshCw as S, XCircle as C } from "lucide-react";
|
|
11
|
+
import { useNavigate as w, useParams as T } from "react-router-dom";
|
|
12
|
+
import { Fragment as E, jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
13
13
|
//#region src/channel/modules/channels/pages/WebhookEventsPage.tsx
|
|
14
|
-
var
|
|
14
|
+
var k = {
|
|
15
15
|
PENDING: {
|
|
16
16
|
label: "Pending",
|
|
17
17
|
color: "text-muted-foreground bg-muted",
|
|
18
|
-
icon:
|
|
18
|
+
icon: _
|
|
19
19
|
},
|
|
20
20
|
PROCESSING: {
|
|
21
21
|
label: "Processing",
|
|
22
22
|
color: "text-accent-primary bg-accent-primary/10",
|
|
23
|
-
icon:
|
|
23
|
+
icon: S
|
|
24
24
|
},
|
|
25
25
|
COMPLETED: {
|
|
26
26
|
label: "Completed",
|
|
27
|
-
color: "text-success-
|
|
27
|
+
color: "text-status-success-text bg-status-success-bg-subtle",
|
|
28
28
|
icon: m
|
|
29
29
|
},
|
|
30
30
|
FAILED: {
|
|
31
31
|
label: "Failed",
|
|
32
|
-
color: "text-error-
|
|
33
|
-
icon:
|
|
32
|
+
color: "text-status-error-text bg-status-error-bg-subtle",
|
|
33
|
+
icon: C
|
|
34
34
|
},
|
|
35
35
|
IGNORED: {
|
|
36
36
|
label: "Ignored",
|
|
37
|
-
color: "text-warning-
|
|
38
|
-
icon:
|
|
37
|
+
color: "text-status-warning-text bg-status-warning-bg-subtle",
|
|
38
|
+
icon: b
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
function
|
|
42
|
-
let { channelId: m } =
|
|
43
|
-
let n =
|
|
41
|
+
function A() {
|
|
42
|
+
let { channelId: m } = T(), _ = w(), { t: C } = d(), A = (e, t) => {
|
|
43
|
+
let n = C(e);
|
|
44
44
|
return n === e ? t : n;
|
|
45
|
-
}, { organizationId:
|
|
45
|
+
}, { organizationId: j } = e(), { triggerExport: M, isExporting: N, exportError: P } = s(j ?? void 0, m), [F, I] = u(!0), [L, R] = u([]), [z, B] = u(null), [V, H] = u(25), [U, W] = u(0), [G, K] = u([void 0]), [q, J] = u(0), { channel: Y, isLoading: X, error: Z, fetchWebhookEvents: Q } = i(m), $ = c(async (e) => {
|
|
46
46
|
if (m) {
|
|
47
|
-
|
|
47
|
+
I(!0);
|
|
48
48
|
try {
|
|
49
|
-
|
|
49
|
+
let t = await Q(V, e);
|
|
50
|
+
return R(t.items), W(t.total), t.nextCursor;
|
|
50
51
|
} finally {
|
|
51
|
-
|
|
52
|
+
I(!1);
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
}, [
|
|
55
56
|
m,
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
Q,
|
|
58
|
+
V
|
|
58
59
|
]);
|
|
59
60
|
l(() => {
|
|
60
|
-
Promise.resolve().then(() =>
|
|
61
|
-
|
|
61
|
+
Promise.resolve().then(() => {
|
|
62
|
+
K([void 0]), J(0), $(void 0);
|
|
63
|
+
});
|
|
64
|
+
}, [V]), l(() => {
|
|
65
|
+
Promise.resolve().then(() => $(G[q]));
|
|
66
|
+
}, [q]), l(() => {
|
|
67
|
+
Promise.resolve().then(() => $(void 0));
|
|
68
|
+
}, []);
|
|
69
|
+
let ee = c(async () => {
|
|
70
|
+
let e = await $(G[q]);
|
|
71
|
+
e && K((t) => {
|
|
72
|
+
let n = [...t];
|
|
73
|
+
return n[q + 1] || (n[q + 1] = e), n;
|
|
74
|
+
}), J((e) => e + 1);
|
|
75
|
+
}, [
|
|
76
|
+
G,
|
|
77
|
+
q,
|
|
78
|
+
$
|
|
79
|
+
]), te = c(() => {
|
|
80
|
+
let e = q - 1;
|
|
81
|
+
J(e), $(G[e]);
|
|
82
|
+
}, [
|
|
83
|
+
G,
|
|
84
|
+
q,
|
|
85
|
+
$
|
|
86
|
+
]), ne = L.length === V, re = q > 0;
|
|
87
|
+
r({
|
|
62
88
|
query: n,
|
|
63
89
|
variables: { channelId: m },
|
|
64
90
|
operationName: "WebhookReceived",
|
|
65
91
|
enabled: !!m,
|
|
66
92
|
onData: () => {
|
|
67
|
-
t("webhook.received", { channelId: m }), G
|
|
93
|
+
t("webhook.received", { channelId: m }), $(G[q]);
|
|
94
|
+
},
|
|
95
|
+
pollFn: () => {
|
|
96
|
+
$(G[q]);
|
|
68
97
|
},
|
|
69
|
-
pollFn: G,
|
|
70
98
|
pollIntervalMs: 6e4
|
|
71
99
|
});
|
|
72
|
-
let
|
|
73
|
-
return
|
|
100
|
+
let ie = (e) => k[e] || k.PENDING;
|
|
101
|
+
return X ? /* @__PURE__ */ D("div", {
|
|
74
102
|
className: "flex items-center justify-center min-h-screen",
|
|
75
|
-
children: /* @__PURE__ */
|
|
103
|
+
children: /* @__PURE__ */ D(x, {
|
|
76
104
|
size: 32,
|
|
77
105
|
className: "animate-spin text-accent-primary"
|
|
78
106
|
})
|
|
79
|
-
}) :
|
|
107
|
+
}) : Z || !Y ? /* @__PURE__ */ D("div", {
|
|
80
108
|
className: "p-6",
|
|
81
|
-
children: /* @__PURE__ */
|
|
82
|
-
className: "flex items-center gap-3 p-4 bg-error-
|
|
109
|
+
children: /* @__PURE__ */ O("div", {
|
|
110
|
+
className: "flex items-center gap-3 p-4 bg-status-error-bg-subtle border border-status-error-border rounded-lg",
|
|
83
111
|
children: [
|
|
84
|
-
/* @__PURE__ */
|
|
112
|
+
/* @__PURE__ */ D(f, {
|
|
85
113
|
size: 20,
|
|
86
|
-
className: "text-error-
|
|
114
|
+
className: "text-status-error-text"
|
|
87
115
|
}),
|
|
88
|
-
/* @__PURE__ */
|
|
89
|
-
className: "text-sm font-medium text-error-
|
|
90
|
-
children:
|
|
116
|
+
/* @__PURE__ */ D("div", { children: /* @__PURE__ */ D("p", {
|
|
117
|
+
className: "text-sm font-medium text-status-error-text",
|
|
118
|
+
children: Z || "Channel not found"
|
|
91
119
|
}) }),
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
onClick: () =>
|
|
94
|
-
className: "ml-auto px-3 py-1 text-sm text-error-
|
|
120
|
+
/* @__PURE__ */ D("button", {
|
|
121
|
+
onClick: () => _(`/channels/${m}`),
|
|
122
|
+
className: "ml-auto px-3 py-1 text-sm text-status-error-text hover:bg-status-error-bg-subtle rounded transition-colors",
|
|
95
123
|
children: "Go Back"
|
|
96
124
|
})
|
|
97
125
|
]
|
|
98
126
|
})
|
|
99
|
-
}) : /* @__PURE__ */
|
|
127
|
+
}) : /* @__PURE__ */ D(a, {
|
|
100
128
|
permission: o.CHANNEL_WEBHOOK_READ,
|
|
101
|
-
children: /* @__PURE__ */
|
|
129
|
+
children: /* @__PURE__ */ O("div", {
|
|
102
130
|
className: "space-y-6 p-3 sm:p-6",
|
|
103
131
|
children: [
|
|
104
|
-
/* @__PURE__ */
|
|
132
|
+
/* @__PURE__ */ O("div", {
|
|
105
133
|
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
106
|
-
children: [/* @__PURE__ */
|
|
134
|
+
children: [/* @__PURE__ */ O("div", {
|
|
107
135
|
className: "flex items-center gap-3",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
109
|
-
onClick: () =>
|
|
110
|
-
"aria-label":
|
|
136
|
+
children: [/* @__PURE__ */ D("button", {
|
|
137
|
+
onClick: () => _(`/channels/${m}`),
|
|
138
|
+
"aria-label": A("channel.backToChannel", "Back to channel"),
|
|
111
139
|
className: "p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors",
|
|
112
|
-
children: /* @__PURE__ */
|
|
140
|
+
children: /* @__PURE__ */ D(p, {
|
|
113
141
|
size: 20,
|
|
114
142
|
"aria-hidden": "true"
|
|
115
143
|
})
|
|
116
|
-
}), /* @__PURE__ */
|
|
144
|
+
}), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("h1", {
|
|
117
145
|
className: "text-xl sm:text-2xl font-bold text-foreground",
|
|
118
|
-
children:
|
|
119
|
-
}), /* @__PURE__ */
|
|
146
|
+
children: A("channel.webhookEvents", "Webhook Events")
|
|
147
|
+
}), /* @__PURE__ */ O("p", {
|
|
120
148
|
className: "text-sm text-muted-foreground mt-1",
|
|
121
|
-
children: [
|
|
149
|
+
children: [Y.name, " - Event history"]
|
|
122
150
|
})] })]
|
|
123
|
-
}), /* @__PURE__ */
|
|
151
|
+
}), /* @__PURE__ */ O("div", {
|
|
124
152
|
className: "flex items-center gap-3",
|
|
125
153
|
children: [
|
|
126
|
-
/* @__PURE__ */
|
|
127
|
-
value:
|
|
128
|
-
onChange: (e) =>
|
|
154
|
+
/* @__PURE__ */ O("select", {
|
|
155
|
+
value: V,
|
|
156
|
+
onChange: (e) => H(Number(e.target.value)),
|
|
129
157
|
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",
|
|
130
158
|
children: [
|
|
131
|
-
/* @__PURE__ */
|
|
159
|
+
/* @__PURE__ */ D("option", {
|
|
132
160
|
value: 10,
|
|
133
161
|
children: "10 results"
|
|
134
162
|
}),
|
|
135
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ D("option", {
|
|
136
164
|
value: 25,
|
|
137
165
|
children: "25 results"
|
|
138
166
|
}),
|
|
139
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ D("option", {
|
|
140
168
|
value: 50,
|
|
141
169
|
children: "50 results"
|
|
142
170
|
}),
|
|
143
|
-
/* @__PURE__ */
|
|
171
|
+
/* @__PURE__ */ D("option", {
|
|
144
172
|
value: 100,
|
|
145
173
|
children: "100 results"
|
|
146
174
|
})
|
|
147
175
|
]
|
|
148
176
|
}),
|
|
149
|
-
/* @__PURE__ */
|
|
150
|
-
onClick: G,
|
|
151
|
-
disabled:
|
|
177
|
+
/* @__PURE__ */ O("button", {
|
|
178
|
+
onClick: () => void $(G[q]),
|
|
179
|
+
disabled: F,
|
|
152
180
|
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",
|
|
153
|
-
children: [/* @__PURE__ */
|
|
181
|
+
children: [/* @__PURE__ */ D(S, {
|
|
154
182
|
size: 16,
|
|
155
|
-
className:
|
|
156
|
-
}),
|
|
183
|
+
className: F ? "animate-spin" : ""
|
|
184
|
+
}), A("channel.refresh", "Refresh")]
|
|
157
185
|
}),
|
|
158
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ D(a, {
|
|
159
187
|
permission: o.CHANNEL_ADMIN,
|
|
160
|
-
children: /* @__PURE__ */
|
|
161
|
-
onClick: () => void
|
|
162
|
-
disabled:
|
|
188
|
+
children: /* @__PURE__ */ O("button", {
|
|
189
|
+
onClick: () => void M(),
|
|
190
|
+
disabled: N,
|
|
163
191
|
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",
|
|
164
|
-
title:
|
|
165
|
-
children: [
|
|
192
|
+
title: A("channel.exportCSV", "Export to CSV"),
|
|
193
|
+
children: [N ? /* @__PURE__ */ D(x, {
|
|
166
194
|
size: 16,
|
|
167
195
|
className: "animate-spin"
|
|
168
|
-
}) : /* @__PURE__ */
|
|
196
|
+
}) : /* @__PURE__ */ D(v, { size: 16 }), A("channel.export", "Export")]
|
|
169
197
|
})
|
|
170
198
|
})
|
|
171
199
|
]
|
|
172
200
|
})]
|
|
173
201
|
}),
|
|
174
|
-
|
|
175
|
-
className: "p-4 bg-error-
|
|
176
|
-
children: [/* @__PURE__ */
|
|
202
|
+
P && /* @__PURE__ */ O("div", {
|
|
203
|
+
className: "p-4 bg-status-error-bg-subtle border border-status-error-border rounded-lg flex items-center gap-3",
|
|
204
|
+
children: [/* @__PURE__ */ D(f, {
|
|
177
205
|
size: 20,
|
|
178
|
-
className: "text-error-
|
|
179
|
-
}), /* @__PURE__ */
|
|
180
|
-
className: "text-sm text-error-
|
|
181
|
-
children:
|
|
206
|
+
className: "text-status-error-text"
|
|
207
|
+
}), /* @__PURE__ */ D("p", {
|
|
208
|
+
className: "text-sm text-status-error-text flex-1",
|
|
209
|
+
children: P
|
|
182
210
|
})]
|
|
183
211
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ D("div", {
|
|
185
213
|
className: "p-4 bg-surface border border-border rounded-lg",
|
|
186
|
-
children: /* @__PURE__ */
|
|
214
|
+
children: /* @__PURE__ */ D("p", {
|
|
187
215
|
className: "text-sm text-muted-foreground",
|
|
188
216
|
children: "Webhook events show all incoming webhooks received by this channel. Data is retained for 7 days."
|
|
189
217
|
})
|
|
190
218
|
}),
|
|
191
|
-
/* @__PURE__ */
|
|
219
|
+
/* @__PURE__ */ D("div", {
|
|
192
220
|
className: "bg-surface border border-border rounded-lg overflow-hidden",
|
|
193
|
-
children: /* @__PURE__ */
|
|
221
|
+
children: /* @__PURE__ */ D("div", {
|
|
194
222
|
className: "overflow-x-auto min-w-full",
|
|
195
|
-
children: /* @__PURE__ */
|
|
223
|
+
children: /* @__PURE__ */ O("table", {
|
|
196
224
|
className: "w-full min-w-[600px]",
|
|
197
|
-
children: [/* @__PURE__ */
|
|
225
|
+
children: [/* @__PURE__ */ D("thead", {
|
|
198
226
|
className: "bg-muted/50 border-b border-border",
|
|
199
|
-
children: /* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
227
|
+
children: /* @__PURE__ */ O("tr", { children: [
|
|
228
|
+
/* @__PURE__ */ D("th", {
|
|
201
229
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
202
|
-
children:
|
|
230
|
+
children: A("channel.status", "Status")
|
|
203
231
|
}),
|
|
204
|
-
/* @__PURE__ */
|
|
232
|
+
/* @__PURE__ */ D("th", {
|
|
205
233
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
206
|
-
children:
|
|
234
|
+
children: A("channel.eventType", "Event Type")
|
|
207
235
|
}),
|
|
208
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ D("th", {
|
|
209
237
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
210
|
-
children:
|
|
238
|
+
children: A("channel.duplicate", "Duplicate")
|
|
211
239
|
}),
|
|
212
|
-
/* @__PURE__ */
|
|
240
|
+
/* @__PURE__ */ D("th", {
|
|
213
241
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
214
|
-
children:
|
|
242
|
+
children: A("channel.processedAt", "Processed At")
|
|
215
243
|
}),
|
|
216
|
-
/* @__PURE__ */
|
|
244
|
+
/* @__PURE__ */ D("th", {
|
|
217
245
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
218
|
-
children:
|
|
246
|
+
children: A("channel.error", "Error")
|
|
219
247
|
}),
|
|
220
|
-
/* @__PURE__ */
|
|
248
|
+
/* @__PURE__ */ D("th", {
|
|
221
249
|
className: "px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider",
|
|
222
|
-
children:
|
|
250
|
+
children: A("channel.actions", "Actions")
|
|
223
251
|
})
|
|
224
252
|
] })
|
|
225
|
-
}), /* @__PURE__ */
|
|
253
|
+
}), /* @__PURE__ */ D("tbody", {
|
|
226
254
|
className: "divide-y divide-border",
|
|
227
|
-
children:
|
|
255
|
+
children: L.length === 0 ? /* @__PURE__ */ D("tr", { children: /* @__PURE__ */ D("td", {
|
|
228
256
|
colSpan: 6,
|
|
229
257
|
className: "px-4 py-8 text-center text-muted-foreground",
|
|
230
|
-
children:
|
|
231
|
-
}) }) :
|
|
232
|
-
let t =
|
|
233
|
-
return /* @__PURE__ */ E
|
|
258
|
+
children: A("channel.noWebhookEventsFound", "No webhook events found")
|
|
259
|
+
}) }) : L.map((e) => {
|
|
260
|
+
let t = ie(e.status), n = t.icon, r = z === e.id;
|
|
261
|
+
return /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ O("tr", {
|
|
234
262
|
className: "hover:bg-muted/30 transition-colors",
|
|
235
263
|
children: [
|
|
236
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ D("td", {
|
|
237
265
|
className: "px-4 py-3",
|
|
238
|
-
children: /* @__PURE__ */
|
|
266
|
+
children: /* @__PURE__ */ O("div", {
|
|
239
267
|
className: "flex items-center gap-2",
|
|
240
|
-
children: [/* @__PURE__ */
|
|
268
|
+
children: [/* @__PURE__ */ D(n, {
|
|
241
269
|
size: 14,
|
|
242
270
|
className: t.color.split(" ")[0]
|
|
243
|
-
}), /* @__PURE__ */
|
|
271
|
+
}), /* @__PURE__ */ D("span", {
|
|
244
272
|
className: `text-sm font-medium ${t.color}`,
|
|
245
273
|
children: t.label
|
|
246
274
|
})]
|
|
247
275
|
})
|
|
248
276
|
}),
|
|
249
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ D("td", {
|
|
250
278
|
className: "px-4 py-3 text-sm font-mono text-foreground",
|
|
251
279
|
children: e.eventType
|
|
252
280
|
}),
|
|
253
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ D("td", {
|
|
254
282
|
className: "px-4 py-3",
|
|
255
|
-
children: e.isDuplicate ? /* @__PURE__ */
|
|
256
|
-
className: "text-xs text-warning-
|
|
283
|
+
children: e.isDuplicate ? /* @__PURE__ */ D("span", {
|
|
284
|
+
className: "text-xs text-status-warning-text bg-status-warning-bg-subtle px-2 py-1 rounded",
|
|
257
285
|
children: "Duplicate"
|
|
258
|
-
}) : /* @__PURE__ */
|
|
286
|
+
}) : /* @__PURE__ */ D("span", {
|
|
259
287
|
className: "text-xs text-muted-foreground",
|
|
260
288
|
children: "No"
|
|
261
289
|
})
|
|
262
290
|
}),
|
|
263
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ D("td", {
|
|
264
292
|
className: "px-4 py-3 text-sm text-muted-foreground",
|
|
265
293
|
children: e.processedAt ? new Date(e.processedAt).toLocaleString() : "-"
|
|
266
294
|
}),
|
|
267
|
-
/* @__PURE__ */
|
|
268
|
-
className: "px-4 py-3 text-sm text-error-
|
|
295
|
+
/* @__PURE__ */ D("td", {
|
|
296
|
+
className: "px-4 py-3 text-sm text-status-error-text max-w-xs truncate",
|
|
269
297
|
children: e.errorMessage || "-"
|
|
270
298
|
}),
|
|
271
|
-
/* @__PURE__ */
|
|
299
|
+
/* @__PURE__ */ D("td", {
|
|
272
300
|
className: "px-4 py-3",
|
|
273
|
-
children: /* @__PURE__ */
|
|
274
|
-
onClick: () =>
|
|
275
|
-
"aria-label": r ?
|
|
301
|
+
children: /* @__PURE__ */ D("button", {
|
|
302
|
+
onClick: () => B(r ? null : e.id),
|
|
303
|
+
"aria-label": r ? A("channel.hidePayload", "Hide payload") : A("channel.viewPayload", "View payload"),
|
|
276
304
|
"aria-expanded": r,
|
|
277
305
|
className: "p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors",
|
|
278
|
-
children:
|
|
306
|
+
children: D(r ? b : y, {
|
|
279
307
|
size: 16,
|
|
280
308
|
"aria-hidden": "true"
|
|
281
309
|
})
|
|
282
310
|
})
|
|
283
311
|
})
|
|
284
312
|
]
|
|
285
|
-
}, e.id), r && /* @__PURE__ */
|
|
313
|
+
}, e.id), r && /* @__PURE__ */ D("tr", { children: /* @__PURE__ */ D("td", {
|
|
286
314
|
colSpan: 6,
|
|
287
315
|
className: "px-4 py-3 bg-muted/30",
|
|
288
|
-
children: /* @__PURE__ */
|
|
316
|
+
children: /* @__PURE__ */ O("div", {
|
|
289
317
|
className: "text-xs",
|
|
290
|
-
children: [/* @__PURE__ */
|
|
318
|
+
children: [/* @__PURE__ */ O("p", {
|
|
291
319
|
className: "text-muted-foreground mb-1",
|
|
292
|
-
children: [
|
|
293
|
-
}), /* @__PURE__ */
|
|
320
|
+
children: [A("channel.payload", "Payload"), ":"]
|
|
321
|
+
}), /* @__PURE__ */ D("pre", {
|
|
294
322
|
className: "bg-surface p-2 rounded border border-border overflow-auto",
|
|
295
323
|
children: JSON.stringify(e.payload, null, 2)
|
|
296
324
|
})]
|
|
@@ -300,12 +328,46 @@ function O() {
|
|
|
300
328
|
})]
|
|
301
329
|
})
|
|
302
330
|
})
|
|
331
|
+
}),
|
|
332
|
+
/* @__PURE__ */ O("div", {
|
|
333
|
+
className: "flex items-center justify-between",
|
|
334
|
+
children: [/* @__PURE__ */ D("p", {
|
|
335
|
+
className: "text-sm text-muted-foreground",
|
|
336
|
+
children: U > 0 && /* @__PURE__ */ O(E, { children: [
|
|
337
|
+
A("channel.page", "Page"),
|
|
338
|
+
" ",
|
|
339
|
+
/* @__PURE__ */ D("span", {
|
|
340
|
+
className: "font-medium",
|
|
341
|
+
children: q + 1
|
|
342
|
+
}),
|
|
343
|
+
" · ",
|
|
344
|
+
A("channel.totalRecords", "Total"),
|
|
345
|
+
": ",
|
|
346
|
+
/* @__PURE__ */ D("span", {
|
|
347
|
+
className: "font-medium",
|
|
348
|
+
children: U
|
|
349
|
+
})
|
|
350
|
+
] })
|
|
351
|
+
}), /* @__PURE__ */ O("div", {
|
|
352
|
+
className: "flex items-center gap-2",
|
|
353
|
+
children: [/* @__PURE__ */ O("button", {
|
|
354
|
+
onClick: te,
|
|
355
|
+
disabled: !re || F,
|
|
356
|
+
className: "flex items-center gap-1 px-3 py-1.5 text-sm border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
|
|
357
|
+
children: [/* @__PURE__ */ D(h, { size: 16 }), A("channel.previous", "Previous")]
|
|
358
|
+
}), /* @__PURE__ */ O("button", {
|
|
359
|
+
onClick: () => void ee(),
|
|
360
|
+
disabled: !ne || F,
|
|
361
|
+
className: "flex items-center gap-1 px-3 py-1.5 text-sm border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
|
|
362
|
+
children: [A("channel.next", "Next"), /* @__PURE__ */ D(g, { size: 16 })]
|
|
363
|
+
})]
|
|
364
|
+
})]
|
|
303
365
|
})
|
|
304
366
|
]
|
|
305
367
|
})
|
|
306
368
|
});
|
|
307
369
|
}
|
|
308
370
|
//#endregion
|
|
309
|
-
export {
|
|
371
|
+
export { A as WebhookEventsPage };
|
|
310
372
|
|
|
311
373
|
//# sourceMappingURL=WebhookEventsPage.js.map
|
|
@@ -1 +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 aria-label={tr('channel.backToChannel', 'Back to channel')}\n className=\"p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\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 aria-label={\n isExpanded\n ? tr('channel.hidePayload', 'Hide payload')\n : tr('channel.viewPayload', 'View payload')\n }\n aria-expanded={isExpanded}\n className=\"p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors\"\n >\n {isExpanded ? (\n <EyeOff size={16} aria-hidden=\"true\" />\n ) : (\n <Eye size={16} aria-hidden=\"true\" />\n )}\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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"}
|
|
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 ChevronLeft,\n ChevronRight,\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: {\n label: 'Completed',\n color: 'text-status-success-text bg-status-success-bg-subtle',\n icon: CheckCircle2,\n },\n FAILED: {\n label: 'Failed',\n color: 'text-status-error-text bg-status-error-bg-subtle',\n icon: XCircle,\n },\n IGNORED: {\n label: 'Ignored',\n color: 'text-status-warning-text bg-status-warning-bg-subtle',\n icon: EyeOff,\n },\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 const [total, setTotal] = useState(0);\n const [cursorStack, setCursorStack] = useState<(string | undefined)[]>([undefined]);\n const [currentPageIdx, setCurrentPageIdx] = useState(0);\n\n const { channel, isLoading, error, fetchWebhookEvents } = useChannel(channelId);\n\n const loadEvents = useCallback(\n async (cursor?: string) => {\n if (!channelId) return;\n setIsLoadingEvents(true);\n try {\n const result = await fetchWebhookEvents(limit, cursor);\n setEvents(result.items);\n setTotal(result.total);\n return result.nextCursor;\n } finally {\n setIsLoadingEvents(false);\n }\n },\n [channelId, fetchWebhookEvents, limit]\n );\n\n useEffect(() => {\n void Promise.resolve().then(() => {\n setCursorStack([undefined]);\n setCurrentPageIdx(0);\n void loadEvents(undefined);\n });\n }, [limit]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n void Promise.resolve().then(() => loadEvents(cursorStack[currentPageIdx]));\n }, [currentPageIdx]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Initial load\n useEffect(() => {\n void Promise.resolve().then(() => loadEvents(undefined));\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleNextPage = useCallback(async () => {\n const nextCursor = await loadEvents(cursorStack[currentPageIdx]);\n if (nextCursor) {\n setCursorStack((prev) => {\n const next = [...prev];\n if (!next[currentPageIdx + 1]) {\n next[currentPageIdx + 1] = nextCursor;\n }\n return next;\n });\n }\n setCurrentPageIdx((p) => p + 1);\n }, [cursorStack, currentPageIdx, loadEvents]);\n\n const handlePrevPage = useCallback(() => {\n const prevIdx = currentPageIdx - 1;\n setCurrentPageIdx(prevIdx);\n void loadEvents(cursorStack[prevIdx]);\n }, [cursorStack, currentPageIdx, loadEvents]);\n\n const hasNextPage = events.length === limit;\n const hasPrevPage = currentPageIdx > 0;\n\n // Real-time webhook stream. Subscribes when the gateway exposes\n // `webhookReceived`; otherwise polls every 60s as a graceful fallback.\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(cursorStack[currentPageIdx]);\n },\n pollFn: () => {\n void loadEvents(cursorStack[currentPageIdx]);\n },\n pollIntervalMs: 60_000,\n });\n\n const getStatusConfig = (status: WebhookProcessingStatus) => {\n return STATUS_CONFIG[status] || STATUS_CONFIG.PENDING;\n };\n\n // Loading state (only show full-screen for initial channel load)\n if (isLoading) {\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-status-error-bg-subtle border border-status-error-border rounded-lg\">\n <AlertCircle size={20} className=\"text-status-error-text\" />\n <div>\n <p className=\"text-sm font-medium text-status-error-text\">\n {error || 'Channel not found'}\n </p>\n </div>\n <button\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"ml-auto px-3 py-1 text-sm text-status-error-text hover:bg-status-error-bg-subtle 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 aria-label={tr('channel.backToChannel', 'Back to channel')}\n className=\"p-2 text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\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={() => void loadEvents(cursorStack[currentPageIdx])}\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-status-error-bg-subtle border border-status-error-border rounded-lg flex items-center gap-3\">\n <AlertCircle size={20} className=\"text-status-error-text\" />\n <p className=\"text-sm text-status-error-text 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-status-warning-text bg-status-warning-bg-subtle 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-status-error-text 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 aria-label={\n isExpanded\n ? tr('channel.hidePayload', 'Hide payload')\n : tr('channel.viewPayload', 'View payload')\n }\n aria-expanded={isExpanded}\n className=\"p-1 text-muted-foreground hover:text-foreground hover:bg-muted rounded transition-colors\"\n >\n {isExpanded ? (\n <EyeOff size={16} aria-hidden=\"true\" />\n ) : (\n <Eye size={16} aria-hidden=\"true\" />\n )}\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\n {/* Pagination footer */}\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-muted-foreground\">\n {total > 0 && (\n <>\n {tr('channel.page', 'Page')}{' '}\n <span className=\"font-medium\">{currentPageIdx + 1}</span>\n {' · '}\n {tr('channel.totalRecords', 'Total')}: <span className=\"font-medium\">{total}</span>\n </>\n )}\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handlePrevPage}\n disabled={!hasPrevPage || isLoadingEvents}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n <ChevronLeft size={16} />\n {tr('channel.previous', 'Previous')}\n </button>\n <button\n onClick={() => void handleNextPage()}\n disabled={!hasNextPage || isLoadingEvents}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n {tr('channel.next', 'Next')}\n <ChevronRight size={16} />\n </button>\n </div>\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
|
|
@@ -817,6 +817,8 @@ export type SendNotificationMutation = {
|
|
|
817
817
|
sentAt?: string | null;
|
|
818
818
|
title: string;
|
|
819
819
|
message: string;
|
|
820
|
+
errorMessage?: string | null;
|
|
821
|
+
errorCode?: string | null;
|
|
820
822
|
};
|
|
821
823
|
};
|
|
822
824
|
export declare const ChannelFieldsFragmentDoc: Apollo.DocumentNode;
|