@burdenoff/microfe-devportal 2026.830.1 → 2026.830.2

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 (104) hide show
  1. package/dist/devportal/AdminDevportalRoot.d.ts.map +1 -1
  2. package/dist/devportal/AdminDevportalRoot.js +16 -19
  3. package/dist/devportal/AdminDevportalRoot.js.map +1 -1
  4. package/dist/devportal/DevportalRoot.d.ts.map +1 -1
  5. package/dist/devportal/DevportalRoot.js +36 -39
  6. package/dist/devportal/DevportalRoot.js.map +1 -1
  7. package/dist/devportal/components/AppCard.js +41 -41
  8. package/dist/devportal/components/ConfirmDialog.d.ts.map +1 -1
  9. package/dist/devportal/components/ConfirmDialog.js +19 -22
  10. package/dist/devportal/components/ConfirmDialog.js.map +1 -1
  11. package/dist/devportal/components/DataTable.d.ts.map +1 -1
  12. package/dist/devportal/components/DataTable.js +31 -34
  13. package/dist/devportal/components/DataTable.js.map +1 -1
  14. package/dist/devportal/components/FeatureFlaggedRoute.js +8 -8
  15. package/dist/devportal/components/FormField.d.ts.map +1 -1
  16. package/dist/devportal/components/FormField.js +26 -32
  17. package/dist/devportal/components/FormField.js.map +1 -1
  18. package/dist/devportal/components/GrantDelegationModal.js +64 -64
  19. package/dist/devportal/components/GrantDelegationModal.js.map +1 -1
  20. package/dist/devportal/components/LoadingState.d.ts.map +1 -1
  21. package/dist/devportal/components/LoadingState.js +5 -8
  22. package/dist/devportal/components/LoadingState.js.map +1 -1
  23. package/dist/devportal/components/PageLayout.d.ts.map +1 -1
  24. package/dist/devportal/components/PageLayout.js +10 -13
  25. package/dist/devportal/components/PageLayout.js.map +1 -1
  26. package/dist/devportal/components/PermissionGuard.d.ts.map +1 -1
  27. package/dist/devportal/components/PermissionGuard.js +11 -14
  28. package/dist/devportal/components/PermissionGuard.js.map +1 -1
  29. package/dist/devportal/components/SecretDisplay.d.ts.map +1 -1
  30. package/dist/devportal/components/SecretDisplay.js +24 -30
  31. package/dist/devportal/components/SecretDisplay.js.map +1 -1
  32. package/dist/devportal/components/SectionNav.d.ts.map +1 -1
  33. package/dist/devportal/components/SectionNav.js +24 -27
  34. package/dist/devportal/components/SectionNav.js.map +1 -1
  35. package/dist/devportal/components/StatusBadge.d.ts.map +1 -1
  36. package/dist/devportal/components/StatusBadge.js +24 -33
  37. package/dist/devportal/components/StatusBadge.js.map +1 -1
  38. package/dist/devportal/index.d.ts +1 -0
  39. package/dist/devportal/index.d.ts.map +1 -1
  40. package/dist/devportal/index.js +1 -0
  41. package/dist/devportal/pages/AdminReviewPage.js +172 -172
  42. package/dist/devportal/pages/AnalyticsDashboardPage.js +43 -43
  43. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  44. package/dist/devportal/pages/ApiKeysPage.js +119 -119
  45. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  46. package/dist/devportal/pages/AppLogsPage.js +45 -45
  47. package/dist/devportal/pages/ApplicationDetailPage.js +607 -607
  48. package/dist/devportal/pages/ApplicationVersionsPage.js +13 -13
  49. package/dist/devportal/pages/ApplicationsPage.d.ts.map +1 -1
  50. package/dist/devportal/pages/ApplicationsPage.js +104 -101
  51. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  52. package/dist/devportal/pages/CreateApiKeyPage.js +45 -45
  53. package/dist/devportal/pages/CreateApplicationPage.js +38 -38
  54. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  55. package/dist/devportal/pages/CreateOAuthClientPage.js +52 -52
  56. package/dist/devportal/pages/CreateOrganizationPage.js +26 -26
  57. package/dist/devportal/pages/CreateWebhookPage.d.ts.map +1 -1
  58. package/dist/devportal/pages/CreateWebhookPage.js +48 -48
  59. package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
  60. package/dist/devportal/pages/DashboardPage.d.ts.map +1 -1
  61. package/dist/devportal/pages/DashboardPage.js +66 -72
  62. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  63. package/dist/devportal/pages/DelegationsPage.js +174 -174
  64. package/dist/devportal/pages/DocumentationPage.js +93 -93
  65. package/dist/devportal/pages/EditApplicationPage.js +14 -14
  66. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  67. package/dist/devportal/pages/ListingPreviewPage.js +76 -76
  68. package/dist/devportal/pages/OAuthClientDetailPage.js +75 -75
  69. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  70. package/dist/devportal/pages/OAuthClientsPage.js +64 -64
  71. package/dist/devportal/pages/OrganizationDetailPage.js +189 -189
  72. package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
  73. package/dist/devportal/pages/OrganizationMembersPage.js +10 -10
  74. package/dist/devportal/pages/OrganizationsPage.d.ts.map +1 -1
  75. package/dist/devportal/pages/OrganizationsPage.js +163 -154
  76. package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
  77. package/dist/devportal/pages/PublishPage.js +104 -104
  78. package/dist/devportal/pages/PublishPage.js.map +1 -1
  79. package/dist/devportal/pages/PublisherProfilePage.js +55 -55
  80. package/dist/devportal/pages/ResourcesPage.js +60 -60
  81. package/dist/devportal/pages/RevenueDashboardPage.js +60 -60
  82. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
  83. package/dist/devportal/pages/SellerDashboardPage.js +83 -83
  84. package/dist/devportal/pages/SellerItemsPage.js +163 -163
  85. package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
  86. package/dist/devportal/pages/SellerOrdersPage.js +63 -63
  87. package/dist/devportal/pages/SettingsPage.js +21 -21
  88. package/dist/devportal/pages/SetupPage.js +183 -183
  89. package/dist/devportal/pages/SetupPage.js.map +1 -1
  90. package/dist/devportal/pages/StoreSubmissionPage.js +5 -5
  91. package/dist/devportal/pages/WebhookDetailPage.js +123 -123
  92. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  93. package/dist/devportal/pages/WebhooksPage.js +118 -118
  94. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  95. package/dist/devportal/utils/i18n.d.ts +9 -2
  96. package/dist/devportal/utils/i18n.d.ts.map +1 -1
  97. package/dist/devportal/utils/i18n.js +13 -10
  98. package/dist/devportal/utils/i18n.js.map +1 -1
  99. package/dist/index.js +2 -1
  100. package/dist/translations/en.d.ts +1251 -0
  101. package/dist/translations/en.d.ts.map +1 -0
  102. package/dist/translations/en.js +1235 -0
  103. package/dist/translations/en.js.map +1 -0
  104. package/package.json +1 -1
@@ -1,73 +1,73 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
2
  import { EmptyState as t } from "../components/EmptyState.js";
3
- import { useDeleteWebhookMutation as n, useGetApplicationQuery as r, useGetWebhookDetailQuery as i, useTestWebhookMutation as ee, useUpdateWebhookMutation as a } from "../../generated/global-operations.js";
4
- import { getErrorMessage as o } from "../hooks/useGraphQL.js";
3
+ import { useDeleteWebhookMutation as n, useGetApplicationQuery as r, useGetWebhookDetailQuery as i, useTestWebhookMutation as a, useUpdateWebhookMutation as o } from "../../generated/global-operations.js";
4
+ import { getErrorMessage as ee } from "../hooks/useGraphQL.js";
5
5
  import { PageLayout as s, PageSection as c } from "../components/PageLayout.js";
6
6
  import { StatusBadge as l } from "../components/StatusBadge.js";
7
- import { StatCard as u, StatCardGrid as te } from "../components/StatCard.js";
8
- import { nativeImpact as ne, nativeNotify as d } from "../../utils/nativeBridge.js";
9
- import { SecretDisplay as re } from "../components/SecretDisplay.js";
10
- import { DataTable as ie, DetailList as ae } from "../components/DataTable.js";
11
- import { Alert as oe, ConfirmDialog as f } from "../components/ConfirmDialog.js";
12
- import { useDevportalPermission as p } from "../hooks/usePermission.js";
7
+ import { StatCard as u, StatCardGrid as d } from "../components/StatCard.js";
8
+ import { nativeImpact as f, nativeNotify as p } from "../../utils/nativeBridge.js";
9
+ import { SecretDisplay as te } from "../components/SecretDisplay.js";
10
+ import { DataTable as ne, DetailList as re } from "../components/DataTable.js";
11
+ import { Alert as ie, ConfirmDialog as m } from "../components/ConfirmDialog.js";
12
+ import { useDevportalPermission as h } from "../hooks/usePermission.js";
13
13
  import "../hooks/index.js";
14
- import { DEVPORTAL_PERMISSIONS as m } from "../constants/permissions.js";
15
- import h from "../../node_modules/date-fns/format.js";
16
- import { useEffect as g, useMemo as _, useState as v } from "react";
17
- import { useI18n as se } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
18
- import { AlertCircle as ce, CheckCircle as y, Clock as b, ExternalLink as x, Loader2 as le, Pause as S, Play as C, Send as w, Trash2 as ue, Webhook as de, XCircle as fe } from "lucide-react";
19
- import { useParams as pe } from "react-router";
14
+ import { DEVPORTAL_PERMISSIONS as g } from "../constants/permissions.js";
15
+ import _ from "../../node_modules/date-fns/format.js";
16
+ import { useEffect as v, useMemo as y, useState as b } from "react";
17
+ import { AlertCircle as ae, CheckCircle as x, Clock as oe, ExternalLink as se, Loader2 as ce, Pause as S, Play as C, Send as w, Trash2 as le, Webhook as ue, XCircle as de } from "lucide-react";
18
+ import { useParams as fe } from "react-router";
20
19
  import { jsx as T, jsxs as E } from "react/jsx-runtime";
21
- import { CTAOverflowMenu as D, EmphasisPanel as O, NextSteps as k } from "@burdenoff/fe-libs/ui";
20
+ import { useI18n as D } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
21
+ import { CTAOverflowMenu as O, EmphasisPanel as k, NextSteps as A } from "@burdenoff/fe-libs/ui";
22
22
  //#region src/devportal/pages/WebhookDetailPage.tsx
23
- var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
24
- let { appId: j, webhookId: M } = pe(), { navigate: N, basePath: P } = e(), { t: F } = se(), I = (e, t) => {
25
- let n = F(e);
23
+ var j = (e) => e ? _(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
24
+ let { appId: M, webhookId: N } = fe(), { navigate: P, basePath: F } = e(), { t: I } = D(), L = (e, t) => {
25
+ let n = I(e);
26
26
  return n === e ? t : n;
27
- }, { allowed: L } = p(m.WEBHOOK_UPDATE), { allowed: R } = p(m.WEBHOOK_DELETE), [z, B] = v(!1), [me, V] = v(!1), [H, U] = v(null), [he, W] = v(!1), { data: G } = r({
28
- variables: { id: j ?? "" },
29
- skip: !j,
27
+ }, { allowed: R } = h(g.WEBHOOK_UPDATE), { allowed: z } = h(g.WEBHOOK_DELETE), [B, V] = b(!1), [pe, H] = b(!1), [U, W] = b(null), [me, G] = b(!1), { data: K } = r({
28
+ variables: { id: M ?? "" },
29
+ skip: !M,
30
30
  fetchPolicy: "cache-first"
31
31
  });
32
- g(() => {
33
- let e = G?.application?.name;
34
- if (!j || !e) return;
32
+ v(() => {
33
+ let e = K?.application?.name;
34
+ if (!M || !e) return;
35
35
  let t = window.__breadcrumbRegistry;
36
- return t?.register(j, e), () => t?.unregister(j);
37
- }, [j, G?.application?.name]);
38
- let { data: K, loading: ge, error: q, refetch: J } = i({
36
+ return t?.register(M, e), () => t?.unregister(M);
37
+ }, [M, K?.application?.name]);
38
+ let { data: q, loading: he, error: J, refetch: Y } = i({
39
39
  variables: {
40
- id: M || "",
40
+ id: N || "",
41
41
  limit: 20,
42
42
  offset: 0
43
43
  },
44
- skip: !M,
44
+ skip: !N,
45
45
  fetchPolicy: "cache-and-network"
46
- }), [_e, { loading: Y }] = a(), [ve, { loading: ye }] = n(), [be, { loading: xe }] = ee(), X = K?.webhook;
47
- g(() => {
46
+ }), [ge, { loading: _e }] = o(), [ve, { loading: ye }] = n(), [be, { loading: xe }] = a(), X = q?.webhook;
47
+ v(() => {
48
48
  let e = X?.name;
49
- if (!M || !e) return;
49
+ if (!N || !e) return;
50
50
  let t = window.__breadcrumbRegistry;
51
- return t?.register(M, e), () => t?.unregister(M);
52
- }, [M, X?.name]);
53
- let Z = K?.webhookDeliveries?.edges?.map((e) => e.node) ?? [], Q = j || X?.applicationId, Se = _(() => {
51
+ return t?.register(N, e), () => t?.unregister(N);
52
+ }, [N, X?.name]);
53
+ let Z = q?.webhookDeliveries?.edges?.map((e) => e.node) ?? [], Q = M || X?.applicationId, Se = y(() => {
54
54
  if (!X) return 0;
55
55
  let e = (X.successCount ?? 0) + (X.failureCount ?? 0);
56
56
  return e === 0 ? 100 : Math.round((X.successCount ?? 0) / e * 100);
57
57
  }, [X]), Ce = (e) => {
58
- N?.(`${P}${e}`);
58
+ P?.(`${F}${e}`);
59
59
  }, $ = async () => {
60
- X && (await _e({ variables: {
60
+ X && (await ge({ variables: {
61
61
  id: X.id,
62
62
  input: { isActive: !X.isActive }
63
- } }), await J());
63
+ } }), await Y());
64
64
  }, we = async () => {
65
65
  if (X) {
66
- ne("medium");
66
+ f("medium");
67
67
  try {
68
- await ve({ variables: { id: X.id } }), d("success"), Ce(`/apps/${X.applicationId}/webhooks`);
68
+ await ve({ variables: { id: X.id } }), p("success"), Ce(`/apps/${X.applicationId}/webhooks`);
69
69
  } catch {
70
- d("error");
70
+ p("error");
71
71
  }
72
72
  }
73
73
  }, Te = async () => {
@@ -77,116 +77,116 @@ var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
77
77
  eventType: X.events[0] || "application.updated"
78
78
  } })).data?.testWebhook;
79
79
  if (!e) {
80
- W(!1), U("Test request did not return a response.");
80
+ G(!1), W("Test request did not return a response.");
81
81
  return;
82
82
  }
83
- W(e.success), U(e.success ? `Test delivery succeeded with HTTP ${e.statusCode ?? 200}.` : e.error || "Webhook test failed."), await J();
83
+ G(e.success), W(e.success ? `Test delivery succeeded with HTTP ${e.statusCode ?? 200}.` : e.error || "Webhook test failed."), await Y();
84
84
  };
85
- return ge && !X ? /* @__PURE__ */ T(s, {
86
- title: I("devportal.webhook", "Webhook"),
87
- description: I("devportal.loadingWebhookDetails", "Loading webhook details"),
85
+ return he && !X ? /* @__PURE__ */ T(s, {
86
+ title: L("devportal.webhook", "Webhook"),
87
+ description: L("devportal.loadingWebhookDetails", "Loading webhook details"),
88
88
  backLink: Q ? `/apps/${Q}/webhooks` : "/webhooks",
89
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
89
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
90
90
  children: /* @__PURE__ */ T("div", {
91
91
  className: "flex items-center justify-center py-16 text-text-secondary",
92
- children: /* @__PURE__ */ T(le, { className: "h-8 w-8 animate-spin" })
92
+ children: /* @__PURE__ */ T(ce, { className: "h-8 w-8 animate-spin" })
93
93
  })
94
- }) : q || !X ? /* @__PURE__ */ T(s, {
95
- title: I("devportal.webhook", "Webhook"),
96
- description: I("devportal.webhookDetails", "Webhook details"),
94
+ }) : J || !X ? /* @__PURE__ */ T(s, {
95
+ title: L("devportal.webhook", "Webhook"),
96
+ description: L("devportal.webhookDetails", "Webhook details"),
97
97
  backLink: Q ? `/apps/${Q}/webhooks` : "/webhooks",
98
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
98
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
99
99
  children: /* @__PURE__ */ T(t, {
100
- icon: /* @__PURE__ */ T(ce, {
100
+ icon: /* @__PURE__ */ T(ae, {
101
101
  size: 32,
102
102
  className: "text-status-error-text"
103
103
  }),
104
- title: I("devportal.unableToLoadWebhook", "Unable to load webhook"),
105
- description: q ? o(q) : I("devportal.webhookNotFound", "Webhook not found")
104
+ title: L("devportal.unableToLoadWebhook", "Unable to load webhook"),
105
+ description: J ? ee(J) : L("devportal.webhookNotFound", "Webhook not found")
106
106
  })
107
107
  }) : /* @__PURE__ */ E(s, {
108
108
  title: X.name,
109
109
  description: X.description || "Webhook configuration and delivery history",
110
- purpose: I("devportal.webhookDetailPurpose", "This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures."),
110
+ purpose: L("devportal.webhookDetailPurpose", "This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures."),
111
111
  backLink: `/apps/${Q}/webhooks`,
112
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
113
- actions: /* @__PURE__ */ T(D, {
112
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
113
+ actions: /* @__PURE__ */ T(O, {
114
114
  primary: {
115
- label: I("devportal.test", "Test"),
115
+ label: L("devportal.test", "Test"),
116
116
  icon: /* @__PURE__ */ T(w, { size: 16 }),
117
117
  onSelect: () => {
118
- U(null), V(!0);
118
+ W(null), H(!0);
119
119
  }
120
120
  },
121
121
  actions: [{
122
- label: X.isActive ? I("devportal.pauseWebhook", "Pause") : I("devportal.resumeWebhook", "Resume"),
122
+ label: X.isActive ? L("devportal.pauseWebhook", "Pause") : L("devportal.resumeWebhook", "Resume"),
123
123
  icon: X.isActive ? /* @__PURE__ */ T(S, { size: 16 }) : /* @__PURE__ */ T(C, { size: 16 }),
124
- disabled: Y || !L,
124
+ disabled: _e || !R,
125
125
  onSelect: () => void $()
126
126
  }, {
127
- label: I("devportal.deleteWebhook", "Delete"),
128
- icon: /* @__PURE__ */ T(ue, { size: 16 }),
127
+ label: L("devportal.deleteWebhook", "Delete"),
128
+ icon: /* @__PURE__ */ T(le, { size: 16 }),
129
129
  intent: "destructive",
130
- disabled: !R,
131
- onSelect: () => B(!0)
130
+ disabled: !z,
131
+ onSelect: () => V(!0)
132
132
  }]
133
133
  }),
134
134
  children: [
135
- /* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(te, {
135
+ /* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(d, {
136
136
  columns: 4,
137
137
  children: [
138
138
  /* @__PURE__ */ T(u, {
139
- title: I("devportal.successRate", "Success Rate"),
139
+ title: L("devportal.successRate", "Success Rate"),
140
140
  value: `${Se}%`,
141
- icon: /* @__PURE__ */ T(y, { size: 20 })
141
+ icon: /* @__PURE__ */ T(x, { size: 20 })
142
142
  }),
143
143
  /* @__PURE__ */ T(u, {
144
- title: I("devportal.successfulDeliveries", "Successful Deliveries"),
144
+ title: L("devportal.successfulDeliveries", "Successful Deliveries"),
145
145
  value: (X.successCount ?? 0).toLocaleString(),
146
- icon: /* @__PURE__ */ T(y, { size: 20 })
146
+ icon: /* @__PURE__ */ T(x, { size: 20 })
147
147
  }),
148
148
  /* @__PURE__ */ T(u, {
149
- title: I("devportal.failedDeliveries", "Failed Deliveries"),
149
+ title: L("devportal.failedDeliveries", "Failed Deliveries"),
150
150
  value: (X.failureCount ?? 0).toLocaleString(),
151
- icon: /* @__PURE__ */ T(fe, { size: 20 })
151
+ icon: /* @__PURE__ */ T(de, { size: 20 })
152
152
  }),
153
153
  /* @__PURE__ */ T(u, {
154
- title: I("devportal.lastTriggered", "Last Triggered"),
155
- value: X.lastTriggeredAt ? h(new Date(X.lastTriggeredAt), "MMM d, HH:mm") : I("devportal.never", "Never"),
156
- icon: /* @__PURE__ */ T(b, { size: 20 })
154
+ title: L("devportal.lastTriggered", "Last Triggered"),
155
+ value: X.lastTriggeredAt ? _(new Date(X.lastTriggeredAt), "MMM d, HH:mm") : L("devportal.never", "Never"),
156
+ icon: /* @__PURE__ */ T(oe, { size: 20 })
157
157
  })
158
158
  ]
159
159
  }) }),
160
- /* @__PURE__ */ T(k, {
160
+ /* @__PURE__ */ T(A, {
161
161
  storageKey: `devportal-webhook-${X.id}`,
162
162
  steps: [{
163
163
  id: "test",
164
- label: I("devportal.sendTestEvent", "Send a test event"),
165
- description: I("devportal.webhookStepTest", "Confirm your endpoint receives and verifies the payload"),
164
+ label: L("devportal.sendTestEvent", "Send a test event"),
165
+ description: L("devportal.webhookStepTest", "Confirm your endpoint receives and verifies the payload"),
166
166
  icon: /* @__PURE__ */ T(w, { size: 16 }),
167
167
  onClick: () => {
168
- U(null), V(!0);
168
+ W(null), H(!0);
169
169
  }
170
170
  }, {
171
171
  id: "toggle",
172
- label: X.isActive ? I("devportal.pauseWebhook", "Pause deliveries") : I("devportal.resumeWebhook", "Resume deliveries"),
173
- description: I("devportal.webhookStepToggle", "Pause while your endpoint is down to avoid lost retries"),
172
+ label: X.isActive ? L("devportal.pauseWebhook", "Pause deliveries") : L("devportal.resumeWebhook", "Resume deliveries"),
173
+ description: L("devportal.webhookStepToggle", "Pause while your endpoint is down to avoid lost retries"),
174
174
  icon: X.isActive ? /* @__PURE__ */ T(S, { size: 16 }) : /* @__PURE__ */ T(C, { size: 16 }),
175
175
  onClick: () => void $()
176
176
  }]
177
177
  }),
178
178
  /* @__PURE__ */ T(c, {
179
- title: I("devportal.configuration", "Configuration"),
180
- children: /* @__PURE__ */ T(ae, { items: [
179
+ title: L("devportal.configuration", "Configuration"),
180
+ children: /* @__PURE__ */ T(re, { items: [
181
181
  {
182
- label: I("devportal.status", "Status"),
182
+ label: L("devportal.status", "Status"),
183
183
  value: /* @__PURE__ */ T(l, {
184
184
  status: X.status,
185
185
  type: "webhook"
186
186
  })
187
187
  },
188
188
  {
189
- label: I("devportal.endpointUrl", "Endpoint URL"),
189
+ label: L("devportal.endpointUrl", "Endpoint URL"),
190
190
  value: /* @__PURE__ */ E("span", {
191
191
  className: "flex flex-wrap items-center gap-2 font-mono text-sm",
192
192
  children: [/* @__PURE__ */ T("span", {
@@ -197,19 +197,19 @@ var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
197
197
  target: "_blank",
198
198
  rel: "noopener noreferrer",
199
199
  className: "text-primary",
200
- children: /* @__PURE__ */ T(x, { size: 14 })
200
+ children: /* @__PURE__ */ T(se, { size: 14 })
201
201
  })]
202
202
  })
203
203
  },
204
204
  {
205
- label: I("devportal.signingSecret", "Signing Secret"),
206
- value: /* @__PURE__ */ T(re, {
205
+ label: L("devportal.signingSecret", "Signing Secret"),
206
+ value: /* @__PURE__ */ T(te, {
207
207
  value: X.secret || "******",
208
208
  label: ""
209
209
  })
210
210
  },
211
211
  {
212
- label: I("devportal.subscribedEvents", "Subscribed Events"),
212
+ label: L("devportal.subscribedEvents", "Subscribed Events"),
213
213
  value: /* @__PURE__ */ T("div", {
214
214
  className: "flex flex-wrap gap-1",
215
215
  children: X.events.map((e) => /* @__PURE__ */ T("code", {
@@ -219,28 +219,28 @@ var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
219
219
  })
220
220
  },
221
221
  {
222
- label: I("devportal.retryPolicy", "Retry Policy"),
223
- value: X.retryEnabled ? I("devportal.retryPolicyEnabled", `Up to ${X.maxRetries ?? 0} retries`) : I("devportal.retriesDisabled", "Retries disabled")
222
+ label: L("devportal.retryPolicy", "Retry Policy"),
223
+ value: X.retryEnabled ? L("devportal.retryPolicyEnabled", `Up to ${X.maxRetries ?? 0} retries`) : L("devportal.retriesDisabled", "Retries disabled")
224
224
  },
225
225
  {
226
- label: I("devportal.created", "Created"),
227
- value: A(X.createdAt)
226
+ label: L("devportal.created", "Created"),
227
+ value: j(X.createdAt)
228
228
  },
229
229
  {
230
- label: I("devportal.updated", "Updated"),
231
- value: A(X.updatedAt)
230
+ label: L("devportal.updated", "Updated"),
231
+ value: j(X.updatedAt)
232
232
  }
233
233
  ] })
234
234
  }),
235
235
  /* @__PURE__ */ T(c, {
236
- title: I("devportal.recentDeliveries", "Recent Deliveries"),
237
- children: Z.length > 0 ? /* @__PURE__ */ T(ie, {
236
+ title: L("devportal.recentDeliveries", "Recent Deliveries"),
237
+ children: Z.length > 0 ? /* @__PURE__ */ T(ne, {
238
238
  data: Z,
239
239
  keyField: "id",
240
240
  columns: [
241
241
  {
242
242
  key: "status",
243
- header: I("devportal.status", "Status"),
243
+ header: L("devportal.status", "Status"),
244
244
  render: (e) => /* @__PURE__ */ T("div", {
245
245
  className: "flex items-center gap-2",
246
246
  children: /* @__PURE__ */ T(l, {
@@ -251,7 +251,7 @@ var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
251
251
  },
252
252
  {
253
253
  key: "eventType",
254
- header: I("devportal.event", "Event"),
254
+ header: L("devportal.event", "Event"),
255
255
  render: (e) => /* @__PURE__ */ T("code", {
256
256
  className: "text-xs",
257
257
  children: e.eventType
@@ -259,56 +259,56 @@ var A = (e) => e ? h(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
259
259
  },
260
260
  {
261
261
  key: "responseStatus",
262
- header: I("devportal.response", "Response"),
262
+ header: L("devportal.response", "Response"),
263
263
  render: (e) => e.responseStatus ?? "-"
264
264
  },
265
265
  {
266
266
  key: "attemptNumber",
267
- header: I("devportal.attempts", "Attempts"),
267
+ header: L("devportal.attempts", "Attempts"),
268
268
  render: (e) => e.attemptNumber
269
269
  },
270
270
  {
271
271
  key: "createdAt",
272
- header: I("devportal.created", "Created"),
273
- render: (e) => A(e.createdAt)
272
+ header: L("devportal.created", "Created"),
273
+ render: (e) => j(e.createdAt)
274
274
  }
275
275
  ]
276
276
  }) : /* @__PURE__ */ T(t, {
277
277
  illustration: "empty-notifications",
278
- icon: /* @__PURE__ */ T(de, { size: 24 }),
279
- title: I("devportal.noDeliveriesYet", "No deliveries yet"),
280
- description: I("devportal.noDeliveriesYetDescription", "Deliveries will appear here after the first matching event is sent to this endpoint.")
278
+ icon: /* @__PURE__ */ T(ue, { size: 24 }),
279
+ title: L("devportal.noDeliveriesYet", "No deliveries yet"),
280
+ description: L("devportal.noDeliveriesYetDescription", "Deliveries will appear here after the first matching event is sent to this endpoint.")
281
281
  })
282
282
  }),
283
- /* @__PURE__ */ T(f, {
284
- open: z,
285
- onOpenChange: B,
283
+ /* @__PURE__ */ T(m, {
284
+ open: B,
285
+ onOpenChange: V,
286
286
  onConfirm: () => void we(),
287
287
  loading: ye,
288
- title: I("devportal.deleteWebhookTitle", "Delete webhook"),
289
- description: I("devportal.deleteWebhookDescription", "Deleting this webhook stops all future deliveries for this endpoint."),
290
- confirmLabel: I("devportal.deleteWebhookConfirm", "Delete webhook"),
288
+ title: L("devportal.deleteWebhookTitle", "Delete webhook"),
289
+ description: L("devportal.deleteWebhookDescription", "Deleting this webhook stops all future deliveries for this endpoint."),
290
+ confirmLabel: L("devportal.deleteWebhookConfirm", "Delete webhook"),
291
291
  variant: "danger"
292
292
  }),
293
- /* @__PURE__ */ T(f, {
294
- open: me,
293
+ /* @__PURE__ */ T(m, {
294
+ open: pe,
295
295
  onOpenChange: (e) => {
296
- V(e), e || U(null);
296
+ H(e), e || W(null);
297
297
  },
298
298
  onConfirm: () => void Te(),
299
299
  loading: xe,
300
- title: I("devportal.sendTestDelivery", "Send test delivery"),
301
- description: I("devportal.sendTestDeliveryDescription", "A signed test event will be sent to the configured endpoint through the public gateway."),
302
- confirmLabel: I("devportal.sendTestEvent", "Send test event"),
303
- children: H && /* @__PURE__ */ T(oe, {
304
- variant: he ? "success" : "error",
305
- children: H
300
+ title: L("devportal.sendTestDelivery", "Send test delivery"),
301
+ description: L("devportal.sendTestDeliveryDescription", "A signed test event will be sent to the configured endpoint through the public gateway."),
302
+ confirmLabel: L("devportal.sendTestEvent", "Send test event"),
303
+ children: U && /* @__PURE__ */ T(ie, {
304
+ variant: me ? "success" : "error",
305
+ children: U
306
306
  })
307
307
  })
308
308
  ]
309
309
  });
310
310
  };
311
311
  //#endregion
312
- export { j as WebhookDetailPage };
312
+ export { M as WebhookDetailPage };
313
313
 
314
314
  //# sourceMappingURL=WebhookDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookDetailPage.js","names":[],"sources":["../../../src/devportal/pages/WebhookDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n Clock,\n ExternalLink,\n Loader2,\n Pause,\n Play,\n Send,\n Trash2,\n Webhook,\n XCircle,\n AlertCircle,\n} from \"lucide-react\";\nimport { format } from \"date-fns\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n NextSteps,\n} from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { ConfirmDialog, Alert } from \"../components/ConfirmDialog\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { SecretDisplay } from \"../components/SecretDisplay\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\nimport {\n type GetWebhookDetailQuery,\n getErrorMessage,\n useDeleteWebhookMutation,\n useGetApplicationQuery,\n useGetWebhookDetailQuery,\n useTestWebhookMutation,\n useUpdateWebhookMutation,\n} from \"../hooks\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\n\nconst formatTimestamp = (value?: string | null) => {\n if (!value) return \"Never\";\n return format(new Date(value), \"MMM d, yyyy HH:mm:ss\");\n};\n\ntype WebhookDeliveryEntry =\n GetWebhookDetailQuery[\"webhookDeliveries\"][\"edges\"][number][\"node\"];\n\nexport const WebhookDetailPage: FC = () => {\n const { appId, webhookId } = useParams<{\n appId: string;\n webhookId: string;\n }>();\n const { navigate, basePath } = useDevportal();\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 { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.WEBHOOK_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.WEBHOOK_DELETE,\n );\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showTestDialog, setShowTestDialog] = useState(false);\n const [testMessage, setTestMessage] = useState<string | null>(null);\n const [testSuccess, setTestSuccess] = useState(false);\n\n const { data: appData } = useGetApplicationQuery({\n variables: { id: appId ?? \"\" },\n skip: !appId,\n fetchPolicy: \"cache-first\",\n });\n\n useEffect(() => {\n const name = appData?.application?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, appData?.application?.name]);\n\n const { data, loading, error, refetch } = useGetWebhookDetailQuery({\n variables: {\n id: webhookId || \"\",\n limit: 20,\n offset: 0,\n },\n skip: !webhookId,\n fetchPolicy: \"cache-and-network\",\n });\n const [updateWebhook, { loading: updateLoading }] =\n useUpdateWebhookMutation();\n const [deleteWebhook, { loading: deleteLoading }] =\n useDeleteWebhookMutation();\n const [testWebhook, { loading: testLoading }] = useTestWebhookMutation();\n\n const webhook = data?.webhook;\n\n useEffect(() => {\n const name = webhook?.name;\n if (!webhookId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(webhookId, name);\n return () => reg?.unregister(webhookId);\n }, [webhookId, webhook?.name]);\n\n const deliveries: WebhookDeliveryEntry[] =\n data?.webhookDeliveries?.edges?.map(\n (edge: GetWebhookDetailQuery[\"webhookDeliveries\"][\"edges\"][number]) =>\n edge.node,\n ) ?? [];\n const backAppId = appId || webhook?.applicationId;\n const successRate = useMemo(() => {\n if (!webhook) return 0;\n const total = (webhook.successCount ?? 0) + (webhook.failureCount ?? 0);\n if (total === 0) return 100;\n return Math.round(((webhook.successCount ?? 0) / total) * 100);\n }, [webhook]);\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleToggleActive = async () => {\n if (!webhook) return;\n\n await updateWebhook({\n variables: {\n id: webhook.id,\n input: {\n isActive: !webhook.isActive,\n },\n },\n });\n\n await refetch();\n };\n\n const handleDelete = async () => {\n if (!webhook) return;\n void nativeImpact(\"medium\");\n\n try {\n await deleteWebhook({\n variables: {\n id: webhook.id,\n },\n });\n void nativeNotify(\"success\");\n handleNavigate(`/apps/${webhook.applicationId}/webhooks`);\n } catch {\n void nativeNotify(\"error\");\n }\n };\n\n const handleTest = async () => {\n if (!webhook) return;\n\n const result = await testWebhook({\n variables: {\n id: webhook.id,\n eventType: webhook.events[0] || \"application.updated\",\n },\n });\n\n const response = result.data?.testWebhook;\n if (!response) {\n setTestSuccess(false);\n setTestMessage(\"Test request did not return a response.\");\n return;\n }\n\n setTestSuccess(response.success);\n setTestMessage(\n response.success\n ? `Test delivery succeeded with HTTP ${response.statusCode ?? 200}.`\n : response.error || \"Webhook test failed.\",\n );\n\n await refetch();\n };\n\n if (loading && !webhook) {\n return (\n <PageLayout\n title={tr(\"devportal.webhook\", \"Webhook\")}\n description={tr(\n \"devportal.loadingWebhookDetails\",\n \"Loading webhook details\",\n )}\n backLink={backAppId ? `/apps/${backAppId}/webhooks` : \"/webhooks\"}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !webhook) {\n return (\n <PageLayout\n title={tr(\"devportal.webhook\", \"Webhook\")}\n description={tr(\"devportal.webhookDetails\", \"Webhook details\")}\n backLink={backAppId ? `/apps/${backAppId}/webhooks` : \"/webhooks\"}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.unableToLoadWebhook\", \"Unable to load webhook\")}\n description={\n error\n ? getErrorMessage(error)\n : tr(\"devportal.webhookNotFound\", \"Webhook not found\")\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={webhook.name}\n description={\n webhook.description || \"Webhook configuration and delivery history\"\n }\n purpose={tr(\n \"devportal.webhookDetailPurpose\",\n \"This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures.\",\n )}\n backLink={`/apps/${backAppId}/webhooks`}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n actions={\n <CTAOverflowMenu\n primary={{\n label: tr(\"devportal.test\", \"Test\"),\n icon: <Send size={16} />,\n onSelect: () => {\n setTestMessage(null);\n setShowTestDialog(true);\n },\n }}\n actions={[\n {\n label: webhook.isActive\n ? tr(\"devportal.pauseWebhook\", \"Pause\")\n : tr(\"devportal.resumeWebhook\", \"Resume\"),\n icon: webhook.isActive ? <Pause size={16} /> : <Play size={16} />,\n disabled: updateLoading || !canUpdate,\n onSelect: () => void handleToggleActive(),\n },\n {\n label: tr(\"devportal.deleteWebhook\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n disabled: !canDelete,\n onSelect: () => setShowDeleteDialog(true),\n },\n ]}\n />\n }\n >\n <EmphasisPanel>\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.successRate\", \"Success Rate\")}\n value={`${successRate}%`}\n icon={<CheckCircle size={20} />}\n />\n <StatCard\n title={tr(\n \"devportal.successfulDeliveries\",\n \"Successful Deliveries\",\n )}\n value={(webhook.successCount ?? 0).toLocaleString()}\n icon={<CheckCircle size={20} />}\n />\n <StatCard\n title={tr(\"devportal.failedDeliveries\", \"Failed Deliveries\")}\n value={(webhook.failureCount ?? 0).toLocaleString()}\n icon={<XCircle size={20} />}\n />\n <StatCard\n title={tr(\"devportal.lastTriggered\", \"Last Triggered\")}\n value={\n webhook.lastTriggeredAt\n ? format(new Date(webhook.lastTriggeredAt), \"MMM d, HH:mm\")\n : tr(\"devportal.never\", \"Never\")\n }\n icon={<Clock size={20} />}\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n {/* Guided next steps (dismissable) */}\n <NextSteps\n storageKey={`devportal-webhook-${webhook.id}`}\n steps={[\n {\n id: \"test\",\n label: tr(\"devportal.sendTestEvent\", \"Send a test event\"),\n description: tr(\n \"devportal.webhookStepTest\",\n \"Confirm your endpoint receives and verifies the payload\",\n ),\n icon: <Send size={16} />,\n onClick: () => {\n setTestMessage(null);\n setShowTestDialog(true);\n },\n },\n {\n id: \"toggle\",\n label: webhook.isActive\n ? tr(\"devportal.pauseWebhook\", \"Pause deliveries\")\n : tr(\"devportal.resumeWebhook\", \"Resume deliveries\"),\n description: tr(\n \"devportal.webhookStepToggle\",\n \"Pause while your endpoint is down to avoid lost retries\",\n ),\n icon: webhook.isActive ? <Pause size={16} /> : <Play size={16} />,\n onClick: () => void handleToggleActive(),\n },\n ]}\n />\n\n <PageSection title={tr(\"devportal.configuration\", \"Configuration\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.status\", \"Status\"),\n value: <StatusBadge status={webhook.status} type=\"webhook\" />,\n },\n {\n label: tr(\"devportal.endpointUrl\", \"Endpoint URL\"),\n value: (\n <span className=\"flex flex-wrap items-center gap-2 font-mono text-sm\">\n <span className=\"break-all\">{webhook.url}</span>\n <a\n href={webhook.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary\"\n >\n <ExternalLink size={14} />\n </a>\n </span>\n ),\n },\n {\n label: tr(\"devportal.signingSecret\", \"Signing Secret\"),\n value: (\n <SecretDisplay value={webhook.secret || \"******\"} label=\"\" />\n ),\n },\n {\n label: tr(\"devportal.subscribedEvents\", \"Subscribed Events\"),\n value: (\n <div className=\"flex flex-wrap gap-1\">\n {webhook.events.map((eventName: string) => (\n <code\n key={eventName}\n className=\"rounded bg-bg-sunken px-1.5 py-0.5 text-xs\"\n >\n {eventName}\n </code>\n ))}\n </div>\n ),\n },\n {\n label: tr(\"devportal.retryPolicy\", \"Retry Policy\"),\n value: webhook.retryEnabled\n ? tr(\n \"devportal.retryPolicyEnabled\",\n `Up to ${webhook.maxRetries ?? 0} retries`,\n )\n : tr(\"devportal.retriesDisabled\", \"Retries disabled\"),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: formatTimestamp(webhook.createdAt),\n },\n {\n label: tr(\"devportal.updated\", \"Updated\"),\n value: formatTimestamp(webhook.updatedAt),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.recentDeliveries\", \"Recent Deliveries\")}\n >\n {deliveries.length > 0 ? (\n <DataTable\n data={deliveries}\n keyField=\"id\"\n columns={[\n {\n key: \"status\",\n header: tr(\"devportal.status\", \"Status\"),\n render: (delivery) => (\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={delivery.status} type=\"delivery\" />\n </div>\n ),\n },\n {\n key: \"eventType\",\n header: tr(\"devportal.event\", \"Event\"),\n render: (delivery) => (\n <code className=\"text-xs\">{delivery.eventType}</code>\n ),\n },\n {\n key: \"responseStatus\",\n header: tr(\"devportal.response\", \"Response\"),\n render: (delivery) => delivery.responseStatus ?? \"-\",\n },\n {\n key: \"attemptNumber\",\n header: tr(\"devportal.attempts\", \"Attempts\"),\n render: (delivery) => delivery.attemptNumber,\n },\n {\n key: \"createdAt\",\n header: tr(\"devportal.created\", \"Created\"),\n render: (delivery) => formatTimestamp(delivery.createdAt),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Webhook size={24} />}\n title={tr(\"devportal.noDeliveriesYet\", \"No deliveries yet\")}\n description={tr(\n \"devportal.noDeliveriesYetDescription\",\n \"Deliveries will appear here after the first matching event is sent to this endpoint.\",\n )}\n />\n )}\n </PageSection>\n\n <ConfirmDialog\n open={showDeleteDialog}\n onOpenChange={setShowDeleteDialog}\n onConfirm={() => void handleDelete()}\n loading={deleteLoading}\n title={tr(\"devportal.deleteWebhookTitle\", \"Delete webhook\")}\n description={tr(\n \"devportal.deleteWebhookDescription\",\n \"Deleting this webhook stops all future deliveries for this endpoint.\",\n )}\n confirmLabel={tr(\"devportal.deleteWebhookConfirm\", \"Delete webhook\")}\n variant=\"danger\"\n />\n\n <ConfirmDialog\n open={showTestDialog}\n onOpenChange={(open) => {\n setShowTestDialog(open);\n if (!open) {\n setTestMessage(null);\n }\n }}\n onConfirm={() => void handleTest()}\n loading={testLoading}\n title={tr(\"devportal.sendTestDelivery\", \"Send test delivery\")}\n description={tr(\n \"devportal.sendTestDeliveryDescription\",\n \"A signed test event will be sent to the configured endpoint through the public gateway.\",\n )}\n confirmLabel={tr(\"devportal.sendTestEvent\", \"Send test event\")}\n >\n {testMessage && (\n <Alert variant={testSuccess ? \"success\" : \"error\"}>\n {testMessage}\n </Alert>\n )}\n </ConfirmDialog>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"WebhookDetailPage.js","names":[],"sources":["../../../src/devportal/pages/WebhookDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n Clock,\n ExternalLink,\n Loader2,\n Pause,\n Play,\n Send,\n Trash2,\n Webhook,\n XCircle,\n AlertCircle,\n} from \"lucide-react\";\nimport { format } from \"date-fns\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n NextSteps,\n} from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { ConfirmDialog, Alert } from \"../components/ConfirmDialog\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { SecretDisplay } from \"../components/SecretDisplay\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\nimport {\n type GetWebhookDetailQuery,\n getErrorMessage,\n useDeleteWebhookMutation,\n useGetApplicationQuery,\n useGetWebhookDetailQuery,\n useTestWebhookMutation,\n useUpdateWebhookMutation,\n} from \"../hooks\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\n\nconst formatTimestamp = (value?: string | null) => {\n if (!value) return \"Never\";\n return format(new Date(value), \"MMM d, yyyy HH:mm:ss\");\n};\n\ntype WebhookDeliveryEntry =\n GetWebhookDetailQuery[\"webhookDeliveries\"][\"edges\"][number][\"node\"];\n\nexport const WebhookDetailPage: FC = () => {\n const { appId, webhookId } = useParams<{\n appId: string;\n webhookId: string;\n }>();\n const { navigate, basePath } = useDevportal();\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 { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.WEBHOOK_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.WEBHOOK_DELETE,\n );\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showTestDialog, setShowTestDialog] = useState(false);\n const [testMessage, setTestMessage] = useState<string | null>(null);\n const [testSuccess, setTestSuccess] = useState(false);\n\n const { data: appData } = useGetApplicationQuery({\n variables: { id: appId ?? \"\" },\n skip: !appId,\n fetchPolicy: \"cache-first\",\n });\n\n useEffect(() => {\n const name = appData?.application?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, appData?.application?.name]);\n\n const { data, loading, error, refetch } = useGetWebhookDetailQuery({\n variables: {\n id: webhookId || \"\",\n limit: 20,\n offset: 0,\n },\n skip: !webhookId,\n fetchPolicy: \"cache-and-network\",\n });\n const [updateWebhook, { loading: updateLoading }] =\n useUpdateWebhookMutation();\n const [deleteWebhook, { loading: deleteLoading }] =\n useDeleteWebhookMutation();\n const [testWebhook, { loading: testLoading }] = useTestWebhookMutation();\n\n const webhook = data?.webhook;\n\n useEffect(() => {\n const name = webhook?.name;\n if (!webhookId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(webhookId, name);\n return () => reg?.unregister(webhookId);\n }, [webhookId, webhook?.name]);\n\n const deliveries: WebhookDeliveryEntry[] =\n data?.webhookDeliveries?.edges?.map(\n (edge: GetWebhookDetailQuery[\"webhookDeliveries\"][\"edges\"][number]) =>\n edge.node,\n ) ?? [];\n const backAppId = appId || webhook?.applicationId;\n const successRate = useMemo(() => {\n if (!webhook) return 0;\n const total = (webhook.successCount ?? 0) + (webhook.failureCount ?? 0);\n if (total === 0) return 100;\n return Math.round(((webhook.successCount ?? 0) / total) * 100);\n }, [webhook]);\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleToggleActive = async () => {\n if (!webhook) return;\n\n await updateWebhook({\n variables: {\n id: webhook.id,\n input: {\n isActive: !webhook.isActive,\n },\n },\n });\n\n await refetch();\n };\n\n const handleDelete = async () => {\n if (!webhook) return;\n void nativeImpact(\"medium\");\n\n try {\n await deleteWebhook({\n variables: {\n id: webhook.id,\n },\n });\n void nativeNotify(\"success\");\n handleNavigate(`/apps/${webhook.applicationId}/webhooks`);\n } catch {\n void nativeNotify(\"error\");\n }\n };\n\n const handleTest = async () => {\n if (!webhook) return;\n\n const result = await testWebhook({\n variables: {\n id: webhook.id,\n eventType: webhook.events[0] || \"application.updated\",\n },\n });\n\n const response = result.data?.testWebhook;\n if (!response) {\n setTestSuccess(false);\n setTestMessage(\"Test request did not return a response.\");\n return;\n }\n\n setTestSuccess(response.success);\n setTestMessage(\n response.success\n ? `Test delivery succeeded with HTTP ${response.statusCode ?? 200}.`\n : response.error || \"Webhook test failed.\",\n );\n\n await refetch();\n };\n\n if (loading && !webhook) {\n return (\n <PageLayout\n title={tr(\"devportal.webhook\", \"Webhook\")}\n description={tr(\n \"devportal.loadingWebhookDetails\",\n \"Loading webhook details\",\n )}\n backLink={backAppId ? `/apps/${backAppId}/webhooks` : \"/webhooks\"}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error || !webhook) {\n return (\n <PageLayout\n title={tr(\"devportal.webhook\", \"Webhook\")}\n description={tr(\"devportal.webhookDetails\", \"Webhook details\")}\n backLink={backAppId ? `/apps/${backAppId}/webhooks` : \"/webhooks\"}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.unableToLoadWebhook\", \"Unable to load webhook\")}\n description={\n error\n ? getErrorMessage(error)\n : tr(\"devportal.webhookNotFound\", \"Webhook not found\")\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={webhook.name}\n description={\n webhook.description || \"Webhook configuration and delivery history\"\n }\n purpose={tr(\n \"devportal.webhookDetailPurpose\",\n \"This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures.\",\n )}\n backLink={`/apps/${backAppId}/webhooks`}\n backLabel={tr(\"devportal.backToWebhooks\", \"Back to Webhooks\")}\n actions={\n <CTAOverflowMenu\n primary={{\n label: tr(\"devportal.test\", \"Test\"),\n icon: <Send size={16} />,\n onSelect: () => {\n setTestMessage(null);\n setShowTestDialog(true);\n },\n }}\n actions={[\n {\n label: webhook.isActive\n ? tr(\"devportal.pauseWebhook\", \"Pause\")\n : tr(\"devportal.resumeWebhook\", \"Resume\"),\n icon: webhook.isActive ? <Pause size={16} /> : <Play size={16} />,\n disabled: updateLoading || !canUpdate,\n onSelect: () => void handleToggleActive(),\n },\n {\n label: tr(\"devportal.deleteWebhook\", \"Delete\"),\n icon: <Trash2 size={16} />,\n intent: \"destructive\",\n disabled: !canDelete,\n onSelect: () => setShowDeleteDialog(true),\n },\n ]}\n />\n }\n >\n <EmphasisPanel>\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.successRate\", \"Success Rate\")}\n value={`${successRate}%`}\n icon={<CheckCircle size={20} />}\n />\n <StatCard\n title={tr(\n \"devportal.successfulDeliveries\",\n \"Successful Deliveries\",\n )}\n value={(webhook.successCount ?? 0).toLocaleString()}\n icon={<CheckCircle size={20} />}\n />\n <StatCard\n title={tr(\"devportal.failedDeliveries\", \"Failed Deliveries\")}\n value={(webhook.failureCount ?? 0).toLocaleString()}\n icon={<XCircle size={20} />}\n />\n <StatCard\n title={tr(\"devportal.lastTriggered\", \"Last Triggered\")}\n value={\n webhook.lastTriggeredAt\n ? format(new Date(webhook.lastTriggeredAt), \"MMM d, HH:mm\")\n : tr(\"devportal.never\", \"Never\")\n }\n icon={<Clock size={20} />}\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n {/* Guided next steps (dismissable) */}\n <NextSteps\n storageKey={`devportal-webhook-${webhook.id}`}\n steps={[\n {\n id: \"test\",\n label: tr(\"devportal.sendTestEvent\", \"Send a test event\"),\n description: tr(\n \"devportal.webhookStepTest\",\n \"Confirm your endpoint receives and verifies the payload\",\n ),\n icon: <Send size={16} />,\n onClick: () => {\n setTestMessage(null);\n setShowTestDialog(true);\n },\n },\n {\n id: \"toggle\",\n label: webhook.isActive\n ? tr(\"devportal.pauseWebhook\", \"Pause deliveries\")\n : tr(\"devportal.resumeWebhook\", \"Resume deliveries\"),\n description: tr(\n \"devportal.webhookStepToggle\",\n \"Pause while your endpoint is down to avoid lost retries\",\n ),\n icon: webhook.isActive ? <Pause size={16} /> : <Play size={16} />,\n onClick: () => void handleToggleActive(),\n },\n ]}\n />\n\n <PageSection title={tr(\"devportal.configuration\", \"Configuration\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.status\", \"Status\"),\n value: <StatusBadge status={webhook.status} type=\"webhook\" />,\n },\n {\n label: tr(\"devportal.endpointUrl\", \"Endpoint URL\"),\n value: (\n <span className=\"flex flex-wrap items-center gap-2 font-mono text-sm\">\n <span className=\"break-all\">{webhook.url}</span>\n <a\n href={webhook.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary\"\n >\n <ExternalLink size={14} />\n </a>\n </span>\n ),\n },\n {\n label: tr(\"devportal.signingSecret\", \"Signing Secret\"),\n value: (\n <SecretDisplay value={webhook.secret || \"******\"} label=\"\" />\n ),\n },\n {\n label: tr(\"devportal.subscribedEvents\", \"Subscribed Events\"),\n value: (\n <div className=\"flex flex-wrap gap-1\">\n {webhook.events.map((eventName: string) => (\n <code\n key={eventName}\n className=\"rounded bg-bg-sunken px-1.5 py-0.5 text-xs\"\n >\n {eventName}\n </code>\n ))}\n </div>\n ),\n },\n {\n label: tr(\"devportal.retryPolicy\", \"Retry Policy\"),\n value: webhook.retryEnabled\n ? tr(\n \"devportal.retryPolicyEnabled\",\n `Up to ${webhook.maxRetries ?? 0} retries`,\n )\n : tr(\"devportal.retriesDisabled\", \"Retries disabled\"),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: formatTimestamp(webhook.createdAt),\n },\n {\n label: tr(\"devportal.updated\", \"Updated\"),\n value: formatTimestamp(webhook.updatedAt),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.recentDeliveries\", \"Recent Deliveries\")}\n >\n {deliveries.length > 0 ? (\n <DataTable\n data={deliveries}\n keyField=\"id\"\n columns={[\n {\n key: \"status\",\n header: tr(\"devportal.status\", \"Status\"),\n render: (delivery) => (\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={delivery.status} type=\"delivery\" />\n </div>\n ),\n },\n {\n key: \"eventType\",\n header: tr(\"devportal.event\", \"Event\"),\n render: (delivery) => (\n <code className=\"text-xs\">{delivery.eventType}</code>\n ),\n },\n {\n key: \"responseStatus\",\n header: tr(\"devportal.response\", \"Response\"),\n render: (delivery) => delivery.responseStatus ?? \"-\",\n },\n {\n key: \"attemptNumber\",\n header: tr(\"devportal.attempts\", \"Attempts\"),\n render: (delivery) => delivery.attemptNumber,\n },\n {\n key: \"createdAt\",\n header: tr(\"devportal.created\", \"Created\"),\n render: (delivery) => formatTimestamp(delivery.createdAt),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Webhook size={24} />}\n title={tr(\"devportal.noDeliveriesYet\", \"No deliveries yet\")}\n description={tr(\n \"devportal.noDeliveriesYetDescription\",\n \"Deliveries will appear here after the first matching event is sent to this endpoint.\",\n )}\n />\n )}\n </PageSection>\n\n <ConfirmDialog\n open={showDeleteDialog}\n onOpenChange={setShowDeleteDialog}\n onConfirm={() => void handleDelete()}\n loading={deleteLoading}\n title={tr(\"devportal.deleteWebhookTitle\", \"Delete webhook\")}\n description={tr(\n \"devportal.deleteWebhookDescription\",\n \"Deleting this webhook stops all future deliveries for this endpoint.\",\n )}\n confirmLabel={tr(\"devportal.deleteWebhookConfirm\", \"Delete webhook\")}\n variant=\"danger\"\n />\n\n <ConfirmDialog\n open={showTestDialog}\n onOpenChange={(open) => {\n setShowTestDialog(open);\n if (!open) {\n setTestMessage(null);\n }\n }}\n onConfirm={() => void handleTest()}\n loading={testLoading}\n title={tr(\"devportal.sendTestDelivery\", \"Send test delivery\")}\n description={tr(\n \"devportal.sendTestDeliveryDescription\",\n \"A signed test event will be sent to the configured endpoint through the public gateway.\",\n )}\n confirmLabel={tr(\"devportal.sendTestEvent\", \"Send test event\")}\n >\n {testMessage && (\n <Alert variant={testSuccess ? \"success\" : \"error\"}>\n {testMessage}\n </Alert>\n )}\n </ConfirmDialog>\n </PageLayout>\n );\n};\n"],"mappings":"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"}